kimseunguk/converge-slot-extractor
converge-slot-extractor
한국어 현장 집결 조율 문장에서 슬롯 정보를 추출해 JSON으로 출력하는 GGUF 모델 3종이다. 도메인은 함정 정비(ship_maintenance)와 SI 배포(si_deploy) 두 가지다. Colab T4에서 QLoRA로 학습한 뒤 llama.cpp로 Q4KM 양자화했다.
파일
실행에는 각 GGUF와 짝인 .prompt.json(프롬프트 앞뒤 문자열)과 grammar.gbnf(출력 JSON 문법)가 함께 필요하다. 두 파일은 학습 저장소의 Drive 경로(runs/<모델>/gguf/, finetune/export/grammar.gbnf)에 있다.
하는 일
입력 문장 예: "오후 2시 마곡 고객사 미팅. 대리님이 차 있어서 부천 지하철역 앞에서 나 태우고 감. 장비 있어서 대리님 성북구, 나 부천. 각자 언제 나가?"
출력 예 (학습 데이터 실제 정답):
{"preset": "si_deploy", "datetime": "화요일 14:00", "purpose": "고객사 미팅", "destination": "마곡 고객사", "participants": [{"name": "대리님", "origin": "성북구", "transport": "car", "pickup": null, "pickup_at": null, "unfamiliar": false, "role": "colleague"}, {"name": "나", "origin": "부천", "transport": "car", "pickup": "대리님", "pickup_at": "부천 지하철역 앞", "unfamiliar": false, "role": "site"}], "rendezvous": null, "access": {"required": true, "applied": null, "lead_min": null}, "schedule_confirmed": true, "constraints": ["luggage"], "missing": [], "out_of_scope": false}출력 스키마
최상위 키 11개: preset, datetime, purpose, destination, participants, rendezvous, access, schedule_confirmed, constraints, missing, out_of_scope.
preset:ship_maintenance또는si_deploy. 범위 밖 요청(out_of_scopetrue)은 nullparticipants각 항목 키 7개:name,origin,transport,pickup,pickup_at,unfamiliar,roletransport:car,transit,walk또는 nullpickup: 태워주는 운전자 name, 없으면 nullpickup_at: 태우는 지점 (예: "부천 지하철역 앞"). 전원이 모이는 집결지가 아니라 개별 픽업 장소다. 없으면 nullrole:site,vendor,colleague,clientrendezvous: 전원이 모이는 집결지{"name", "transport_after"}또는 nullaccess:{"required", "applied", "lead_min"}또는 nullconstraints: 문자열 목록 (없으면[]). 장비 있는 날은luggage가 들어간다missing: 알 수 없는 값의 위치 목록 (없으면[])
학습 데이터
합성 데이터 591건을 템플릿과 어휘 사전 조합으로 생성했다 (gen_dataset.py, LLM 생성 아님). 입력 문장 중복 없이 train 551건 / valid 40건으로 나눴다.
원본 591건 카테고리 분포:
학습 설정
- 방식: QLoRA 4bit (nf4, double quant, 계산 fp16), gradient checkpointing
- LoRA: rank 16, alpha 32, dropout 0.05, 대상 q/k/v/o/gate/up/down_proj
- epoch 3, lr 2.0e-4, warmup 3%, linear 스케줄러, 유효 배치 16, maxseqlength 1152, 시드 42
- 환경: Colab T4 GPU, torch 2.11.0+cu128, transformers 5.16.1
- 베이스 revision 고정: Qwen3-0.6B
c1899de2, kanana-1.5-2.1b-instruct-25057df4bc35, Qwen3-1.7B70d244cc
결과 (valid 40건, 2026-09-18 측정)
latency는 T4 GPU fp16 generate 기준 건당 생성 시간이다. GGUF CPU 속도가 아니다.
슬롯별 lora F1 (pickup_at 포함):
GGUF CPU 스모크 테스트 (스레드 2)
위 시간은 Colab CPU 1건 측정값이다. 실제 서빙 환경에서는 반드시 재측정해야 한다.
베이스 모델 라이선스
- Qwen3-0.6B, Qwen3-1.7B: Apache 2.0 (
Qwen/Qwen3-0.6B,Qwen/Qwen3-1.7B) - Kanana-1.5-2.1B-Instruct: Apache 2.0 (
kakaocorp/kanana-1.5-2.1b-instruct-2505)
사용 예시
import json
from llama_cpp import Llama, LlamaGrammar
llm = Llama(model_path="kanana_2.1b-Q4_K_M.gguf", n_ctx=2048)
pf = json.load(open("kanana_2.1b-Q4_K_M.prompt.json", encoding="utf-8"))
prompt = pf["prefix"] + "오후 2시 마곡 고객사 미팅. 대리님이 차 있어서 부천 지하철역 앞에서 나 태우고 감. 장비 있어서 대리님 성북구, 나 부천. 각자 언제 나가?" + pf["suffix"]
tokens = llm.tokenize(prompt.encode("utf-8"), add_bos=pf["add_bos"], special=True)
grammar = LlamaGrammar.from_file("grammar.gbnf", verbose=False)
out = llm.create_completion(
prompt=tokens,
max_tokens=pf["max_new_tokens"],
temperature=pf["temperature"],
grammar=grammar,
stop=pf["stop"],
)
print(out["choices"][0]["text"])