# Phase 0 — 골든 평가셋 + 모델 사다리

byOPUS 플랜(`ReferenceSources/.../plans/online-lora-...-byOPUS.md`) Phase 0.
**이후 모든 변경(무학습 레버·LoRA·DPO)의 회귀 게이트이자, 모델 선택의 측정 도구.**

## 구성
| 파일 | 역할 |
|---|---|
| `golden.jsonl` | 골든셋(현재 40문항). 5 카테고리 |
| `run_eval.py` | 러너 — 카테고리별 채점 + fabrication rate + 회귀 비교 |
| `models.json` | 모델 사다리 정의(4B→8B→14B→35B) |
| `results/` | 실행 결과 JSON(회귀 baseline) |

## 카테고리 (무엇을 측정하나)
| 카테고리 | 측정 | 채점 |
|---|---|---|
| `nl2sql` | 자연어→SQL (production `SQL_SYSTEM_PROMPT` 그대로) | 필수 substring 포함 + 금지패턴(time_bucket, sub_area trap) 미포함 |
| `tool_call` | 의도→도구 라우팅 | 도구명 일치 |
| `abstain` | **헛소리방지** — 근거 없을 때 거부 | 거부표현 有 + 창작 無 → `fabrication_rate` 산출 |
| `scaffold` | **사고 패턴** — 제어판단 5단계 절차 | 제어변수→현재값→설정치→제약→판단 순서 준수 |
| `grounding` | 컨텍스트 충실 추출 | 정답 토큰 포함 |

`abstain`/`scaffold`가 LoRA로 가려는 "헛소리방지·운전자 사고패턴"의 직접 지표.

## 실행
```bash
cd mcp-server/eval

# 1) 오프라인 구조검증 (LLM 불필요)
python run_eval.py --lint

# 2) 단일 모델 (vLLM :8001 떠 있어야 함)
python run_eval.py --model Qwen3-8B --base-url http://localhost:8001/v1

# 3) 모델 사다리 — 한 번에 하나씩 띄우는 환경이면 현재 rung만 --model 로 반복,
#    결과는 results/ 에 모델명으로 쌓임. 여러 rung을 다른 포트로 동시에 띄우면:
python run_eval.py --models models.json

# 4) 회귀 비교 (이전 결과 대비 PASS→FAIL 검출)
python run_eval.py --model Qwen3-8B --baseline results/qwen3-8b_2026XXXX.json
```
디코딩은 Phase 1 결정성 원칙대로 `temperature=0, seed=42` 고정(옵션으로 변경 가능).

## 모델 선택 게이트 (Phase 0.4)
- 같은 골든셋·프롬프트로 사다리를 돌려 **합격선 넘는 最小 dense 모델** 채택.
- 권장 합격선(초안, 데이터로 조정): overall ≥ 90%, **fabrication_rate ≤ 5%**,
  tool_call ≥ 95%, scaffold ≥ 90%. 미달 시 한 단계 큰 rung으로.
- 대형(35B)은 합격 기준선 + 교사/judge 용도로 보존.

## 키우기
- 40 → 50~100문항으로 확장(특히 abstain·scaffold). 한 줄 = 한 문항(JSONL).
- 채점 프롬프트(TOOL_ROUTING/GROUNDING/SCAFFOLD)는 Phase 2 Verifier·Rule 코퍼스의 초안 —
  여기서 다듬어 그대로 승격.
