English | 한국어
Korean public-procurement notice classification from titles alone, deployed as an INT8 ONNX CPU batch API.
New notices had to be routed as soon as they arrived. The service needed to decide whether a notice was eligible for bidding and which team should handle it without opening and analyzing the full document. Fine-grained labels for domains such as river engineering, fire protection, and telecommunications were limited, and the production server had no inference GPU.
A RoBERTa-large model fine-tuned with LoRA first learned bid eligibility and domain-specific language. Historical notice titles from each team were then clustered with UMAP and HDBSCAN to construct a domain ontology. The binary teacher's domain representation was combined with SBERT-RoBERTa weak labeling to create training labels for a multiclass student. Both classifiers were exported to static INT8 ONNX and served through a FastAPI batch path on CPU.
| Task | Result |
|---|---|
| Bid-eligibility classification | Macro-F1 0.9639, Accuracy 96.4% |
| Detailed-domain classification | F1 0.90 |
| CPU inference | About 50 ms per notice |
| INT8 ONNX model | About 330 MB |
Notice titles
-> RoBERTa-large + LoRA bid-eligibility teacher
-> UMAP/HDBSCAN domain ontology
-> SBERT + RoBERTa weak labeling
-> Multiclass student
-> Static INT8 ONNX
-> FastAPI batch serving on CPU
01_preprocess.py # Build the balanced binary dataset
02_train_binary.py # Train RoBERTa-large + LoRA
03_vector_db.py # Build an optional SBERT/FAISS index
04_cluster.py # Cluster domain representations with UMAP/HDBSCAN
05_ontology.py # Extract representative terms per cluster
06_weak_label.py # Produce hybrid SBERT/RoBERTa weak labels
06_weak_label_llm.py # Optional LLM-assisted review
07_optimization_compare.py # Compare optimization and quantization paths
08_train_multiclass.py # Train the detailed-domain classifier
09_quantize.py # Export and statically quantize ONNX models
10_serve.py # Serve /classify_batch with FastAPI
pip install -r requirements.txt
# Train bid eligibility
python 02_train_binary.py
# Build the domain ontology and weak labels
python 04_cluster.py
python 05_ontology.py
python 06_weak_label.py
# Train the detailed-domain model
python 08_train_multiclass.py
# Quantize and serve
python 09_quantize.py
python 10_serve.pyUltimateTrainercombines focal loss, R-Drop, and FGM with LoRA fine-tuning.- Weak labeling uses per-label maximum similarity from a general Korean SBERT model and a procurement-domain RoBERTa teacher, with deterministic overrides for frequent categories.
- Static INT8 quantization exports ONNX models and calibrates them on 200 samples for AVX512-VNNI CPU inference.
This repository contains the training, weak-labeling, quantization, and serving code. Procurement data and trained weights are not included because they contain domain-specific labels and operational data.
MIT.