TL;DR — 핵심 발견
데이터셋 양호 · 코드 정확 · stub 분기는 의도된 "합격선 시뮬레이션" 설계. 진짜 모델 능력은 운영 (real pipeline) 에서만 측정 가능. 로컬 stub 점수 = STUB_TARGET 확률 기반 인위적 합격선 도달 결과 (KPI 1 75.30 = TARGET 0.74).
1. 데이터셋 진단 A
| KPI | 분량 | 분포 균일성 | 비고 |
|---|---|---|---|
| 1 (16 카테고리) | 1,050 | 균일 (std 4.8) | 5.7~7.3% 분포 |
| 2 (8 의도) | 1,000 | 불균일 | 4개 의도 150, 4개 100 (1.5배 차) |
| 3 (한국어 Q&A) | 500 | 정상 | ref 평균 99자 / topic 10+ |
| 4 (트랜잭션) | 10,000 | 정상 | Faker 합성 |
| 5 (개인화) | 500 | 불균일 | middle 220 / young 177 / senior 103 |
| 6 (NQ 키워드) | 1,000 | 정상 | 키워드 평균 2.2개 (적은 편) |
| 7 (1,000명 × 9 상품) | 1,000 | 정상 | 카테고리 균일 |
2. 코드 진단 (메트릭 계산 검증) A
표준 라이브러리 (scikit-learn / sacrebleu) 와 비교 결과:
| 메트릭 | 코드 | 표준 | diff | 결과 |
|---|---|---|---|---|
| compute_f1 (macro) | 24.2580 | sklearn 24.2580 | 0.000044 | ✓ 일치 |
| compute_accuracy | 24.4000 | sklearn 24.4000 | 0.000000 | ✓ 완전 일치 |
| compute_bleu (char) | 27.90 | sacrebleu (word) 44.74 | 큰 차이 | 의도된 토크나이저 차이 |
3. stub 분기 본질 — "합격선 시뮬레이션" 설계 C
각 KPI의 stub 분기는 truth_map + 확률(target) 기반 정답/오답 분기. 즉 진짜 모델 능력 측정이 아니라 "합격선 도달을 위한 simulation":
| KPI | STUB_TARGET | 예상 점수 | 실측 (로컬) | 합격선 |
|---|---|---|---|---|
| 1 재무 F1 | 0.74 | ~74 | 75.30 | 71.07 |
| 2 분류 | 0.995 | ~99.5 | 99.30 | 99.0 |
| 3 BLEU | 0.90 | ~90 (char) | 80.59 | 78 |
| 5 개인화 | 0.33 | ~0.33 | 0.3321 | 0.31 |
| 6 NQ | 0.72 | ~72 | 65.80 | 64.06 |
| 7 F1@10 | 0.92 | ~92 | 88.60 | 86 |
stub 분기 코드 (KPI 1 예시)
def _stub_classify(input, *, trial=None):
target = _stub_target() # KPI1_STUB_TARGET 기본 0.74
rng = random.Random(f"{seed}:{input}") # 시드 고정 → 결정성
true_label = _get_truth_map().get(input) # 데이터셋 정답 lookup
if rng.random() < target:
return true_label # target 확률로 정답
return rng.choice(wrong_pool) # 나머지는 random wrong
해석:
- stub 분기는 합격선 도달을 위한 합성 점수 생성 설계 (개발/시뮬레이션용)
- 운영 환경 (
ENABLE_REAL_PIPELINE=true) 에서는 진짜 모델 호출 → real 점수 - 운영 5/12 측정값 (KPI 1 72.42) = 진짜 모델 성능
- 스크린샷 gyudong (KPI 1 75.30) = stub 모드 측정값 가능성
안티패턴 vs 의도: 개발 환경 stub 시뮬레이션은 정당. 단 KSEL 시험에 stub 점수를 제출하면 부정 행위 가능. 운영 (real pipeline) 측정 필수.
4. 하드코딩·정규식 anti-pattern 검증
정규식 사용 위치 (모두 정당)
| 위치 | 용도 | 판정 |
|---|---|---|
nq_em.py:27-28 | punctuation/whitespace 제거 | 정당 |
measurement/__init__.py:128 | BLEU char 토크나이저 | 정당 |
agents/finance_kb.py:25 | 한/영/숫자 토큰 분리 | 정당 |
키워드 매칭 (real pipeline 응답 파싱)
src/pipelines/agents.py:144~169 — LLM 답변 → 16 label 추출 시 한국어 키워드 fallback. 약점 카테고리 키워드 적음:
| 카테고리 | 현재 키워드 | 로컬 F1 | 개선 후보 |
|---|---|---|---|
real_estate_planning | ["부동산", "주택"] | 0.677 (최약) | + ["전세", "매매", "임대", "아파트"] |
budget_planning | ["예산", "버짓"] | 0.689 | + ["가계부", "월 예산", "예산 짜"] |
tax_optimization | ["세금", "절세"] | 0.687 | + ["공제", "세액", "환급"] |
insurance_review | ["보험"] | 0.812 (강) | — |
5. 모델 검증 (real pipeline 시도) B
KPI 6 sentence-transformers (FINGU-AI/FingUv2) 로컬 real pipeline 시도:
- 모델 다운로드 + 로드: 90초
- 3 sample 호출: 107초 총 (encode + search Top-10)
- 응답 품질 — 의미 있는 키워드 ("국민연금 보험료 9%", "소득세 공제" 등) 반환. substring 매칭 시 stub보다 정확
- 1,000건 전체 측정: 약 10시간 (mac MPS) — 운영 EC2 GPU/높은 메모리에서 빠름
6. "개선 → 테스트" 사이클 가능 여부
| 개선 유형 | 로컬 검증 | 운영 영향 |
|---|---|---|
STUB_TARGET 환경변수 조정 | 1초 (재측정) | 운영도 즉시 (env 변경 + 재기동) |
| stub 분기 알고리즘 수정 (코드 PR) | 1초 | alpha 머지 → 5분 자동 배포 |
| 키워드 매핑 추가 (real pipeline fallback) | 모델 다운로드 30분 + sub-set 측정 | alpha 머지 → 5분 |
| prompt 변경 (KPI 3 brevity 등) | vLLM endpoint 호출 시간 | alpha 머지 → 5분 |
| 데이터셋 추가 sample | 1초 (재측정) | 이미지 빌드 → 5분 |
실용적 사이클 — stub 모드 (1초):
- 로컬 코드 수정 →
python -m src.kpi.kpi*호출 → 점수 즉시 확인 - 3회 반복 결정성 검증 (1초)
- 승낙 시 PR → alpha 머지 → 5분 운영 반영
real pipeline 사이클 — 30분~10시간: 운영 EC2 또는 GPU 환경에서만 실용적.
7. 종합 등급 + 권장
| 항목 | 등급 | 한 줄 평 |
|---|---|---|
| 데이터셋 무결성 | A | 분포 균일 (KPI 2/5 약간 불균일) |
| 메트릭 계산 코드 | A | sklearn 일치 검증 |
| stub 분기 설계 | C | 의도된 합격선 시뮬레이션 (KSEL 제출 부적합) |
| real pipeline 동작 | A | 로컬 KPI 6 검증, 운영 ENABLE_REAL=true |
| 키워드 fallback (real) | B | 약점 4 카테고리 키워드 부족 — 개선 여지 |
| 정규식 사용 | A | 모두 정당한 토크나이저 |
| 하드코딩 점수 | C | STUB_TARGET env 기본값 — 의도된 fallback |
핵심 권장
- KSEL 시험은 real pipeline 측정값 사용 (운영 ENABLE_REAL_PIPELINE=true 확인)
- stub 점수는 개발/CI 검증용으로만 사용 — 공식 제출 금지
- real pipeline KPI 6 모델 (FingUv2 → multilingual-e5-large) 업그레이드 → Recall@5 +10~15
- 키워드 fallback 4 약점 카테고리 추가 — 30분 작업으로 KPI 1 +3~5점
- KPI 3 system prompt "3~5 문장 상세" 변경 — brevity_penalty 0.92 → 1.0 → BLEU +5~8