모델 평가 — 임베딩·LLM

2026-10-04 ~ 10-07 · 운영 기준 백엔드 v0.88.0 · RTX 5060 Ti 16GB 1장 · 외부 API 비교

서비스가 지금 쓰는 모델 세 개와 그 성적입니다. 리포트 해석·의도 관문·RAG 임베딩을 각각 고정된 평가셋과 블라인드 판정, 사람 검수로 확인해 골랐습니다. 위에는 운영 모델이 무엇을 달성했는지를, 아래에는 평가 방법과 경과, 시도했지만 채택하지 않은 후보와 한계를 차례로 적었습니다.

1. 한눈에 보기

01 / 리포트 해석

gemini-3.8-flash

운영 1차 · 일반 모드

2.6% 해석 핵심 오류 3/116 · 적용분 마지막 측정(12단계)

사람 검수에서 틀린 내용 0/20, 질문에 답함 11/12. 응답 p50 4.0초·p93 5.6초. Opus와 오류율 구간이 겹치면서 비용은 약 1/10. 폴백은 claude-opus-5-5 → gemma4:12b.

리포트 해석 결과 보기 →

02 / 의도 관문

gemini-3.8-flash

운영 · 일반 모드 (10/7 교체)

98.8% 지역·업종 동시 정답 · 지어내기 0/26

같은 날 2.5-flash(95.0%)가 놓친 랜드마크(광장시장·익선동·건대입구)를 행정동으로 맞게 옮겼습니다. 응답 p50 2.5초·p93 4.4초.

의도 관문 결과 보기 →

03 / RAG 임베딩

bge-m3@1024

운영 전환 완료

0.940 MRR · Hit@5 0.991

색인·질의를 모델 하나로 처리하고, CPU에서도 질의 p95 149ms에 GPU와 같은 벡터(코사인 0.99998).

임베딩 결과 보기 →
역할 운영 모델 실패 시 대표 성적 확인 방법
리포트 해석(맨 위 한 단락) gemini-3.8-flash 일반 모드(사전 추론 끔) claude-opus-5-5 → 로컬 gemma4:12b 해석 핵심 오류 3/116(2.6%), 폴백 Opus 2/116, p93 5.6초 116건 opus 블라인드 판정 + 사람 검수 4·5차
의도 관문(규칙이 못 푼 자유문) gemini-3.8-flash 일반 모드(사전 추론 끔) 규칙 결과로 응답 동시 정답 98.8%, 지어내기 0/26, p93 4.4초 사람이 검수한 정답 80건 × 3회
RAG 임베딩 bge-m3@1024 (Ollama) — MRR 0.940(벤치) · 0.930(운영 HNSW) 사람이 검수한 정답 233문항
  • 리포트의 6개 절(판정·이유·유사 사례·조건·대안·지원사업)과 질문별 직접 답은 코드가 씁니다(v0.68.0~·v0.69.0~). LLM은 맨 위 해석 한 단락만 쓰므로 판정과 본문 수치는 LLM이 바꿀 수 없고, LLM의 오류는 해석 단락 안에 머뭅니다. 그 단락의 오류를 “핵심 오류”로 잽니다.
  • 평가셋과 사실 묶음을 고정해 모델만 바꿔 비교했고, 판정자에게는 모델 이름을 가렸습니다. LLM 판정 결과는 사람 검수로 방향을 다시 확인했습니다.
  • 지금 리포트는 RAG 검색을 부르지 않습니다. 뉴스는 이용조건에 따라 원문 링크로만 쓰고(v0.83.0), RAG 색인에는 지원사업 공고만 남아 운영 점검과 검색 평가가 씁니다.

2. 리포트 해석 — gemini-3.8-flash

해석 모델이 쓰는 것은 리포트 맨 위 한 단락입니다. 품질은 그 단락이 본문과 다른 숫자·추세·신호 뜻이나 본문에 없는 사실을 쓰는지(핵심 오류)로 잽니다. 평가셋 150건 중 자료 부족으로 LLM을 부르지 않는 34건을 뺀 116건을 매번 같은 조건으로 돌리고, opus 판정자가 블라인드로 판정했습니다(기준표 v2).

성적

지표 gemini-3.8-flash 일반 근거
해석 핵심 오류 3/116 (2.6%, 95% 구간 0.9%~7.3%) 적용분 마지막 측정, 12단계(v0.86.0)
선택 당시 → 개선 후 8/116 (6.9%) → 3/116 (2.6%) 3단계 → 12단계(판정 묶음이 달라 ±3건 변동)
사람 검수 4차 틀린 내용 0/20, 질문에 답함 11/12 블라인드, 3.8 일반·Opus 비교
사람 검수 5차 기록한 2건 모두 3.8이 더 나은 해석, 틀린 내용 0 운영 v0.78.0판
숫자 금지 규칙 가드가 지운 문장 0건(Opus 4건, 2.5-flash 26건) 3단계
동 이름 표기 동 이름 한글 풀이(“답십리제두동” 등) 11 → 0건 7단계(v0.76.1)
응답 시간 p50 4.00초 · p93 5.61초 [5.04, 6.71] · 최대 12.4초 해석 단락 생성 시간, 13단계(v0.87.0) 116호출. p93은 바깥 표본 8개라 ‘참고’, p91 5.42초 [4.94, 6.09]까지 ‘신뢰’
비용 건당 약 $0.0022 (Opus $0.0217) 사용량 × 공시 단가(10/6 확인)
폴백 Opus 2/116 (1.7%) 12단계

13단계(v0.87.0)는 적용한 “판정 근거 약함”과 넣지 않은 조기 폐업 가드를 함께 시험해 3.8 5/116이 나왔습니다. 지금 운영판만 따로 잰 값은 아직 없습니다.

왜 gemini-3.8-flash인가

모델 핵심 오류 95% 구간 p95 건당 비용 추정
claude-opus-5-5 5/116 (4.3%) 1.9%~9.7% 8.6초 $0.0217
gemini-3.8-flash 일반 8/116 (6.9%) 3.5%~13.0% 5.5초 $0.0022
gemini-3.8-flash 추론 5/116 (4.3%) 1.9%~9.7% 12.0초 $0.0022 + 미기록 추론 토큰
gemini-2.5-flash 19/115 (16.5%) 10.8%~24.4% 4.5초 $0.0010

이 표는 3단계 모델 선택 비교입니다. 오류율 구간이 겹쳐 성능 동등성이 입증된 것은 아니지만, 비용이 약 1/10이고 더 빨라 3.8 일반을 선택했습니다(v0.75.0). 이후 사람 검수 4차(틀린 내용 두 모델 0/20)가 이 결정을 뒷받침했습니다. 비용은 당시 사용량·단가로 추정한 값이며 추론 모드는 하한입니다.

적용한 개선

해석을 바꿀 때마다 같은 116건을 다시 쟀습니다. 기본 모델(3.8)의 오류가 늘면 넣지 않는 것이 원칙이고, 예외는 이용조건상 필수인 11단계와 제품 결정인 13단계입니다. 판정자 변동은 약 ±3건입니다.

단계 적용한 변경 3.8 핵심 오류 확인된 효과
4 해석 말투 규칙(v0.76.0) — 중고등학생 눈높이, 전문 용어 풀어 쓰기 8 → 4 쉬운 말로 써도 사실 오류가 늘지 않음. 사람 검수 의견 반영
7 동 이름은 본문 표기 그대로(v0.76.1) 4 → 3 동 이름 한글 풀이(“답십리제두동” 등) 11 → 0
8 매출 중앙값 비교·시간대 매출 가드·판정 신호 구분(v0.78.0) 3 → 4 (판정 오차 안) 겨냥한 오류 3유형 0건, Opus 5 → 1
11 뉴스·상권 축소 신호를 해석 입력에서 제거(v0.83.0) 4 → 9 데이터 이용조건상 필수 변경
12 조건 절에 지역 사건 연결(v0.86.0) 9 → 3 (판정자 변동이 커 ‘늘지 않음’까지만) 사건을 언급한 해석 8건(3.8 3·Opus 5) 중 오류 0
13 판정 근거 약함 표시(v0.87.0) 함께 시험한 가드 포함 3 → 5 안정 신호 없는 7개 업종 비추천 방지(제품 결정)

효과가 난 방식은 코드가 쓰는 사실 문장의 등급 낱말과 코드 가드, 사람 검수로 확인한 말투·표기 변경이었습니다. 윤문 규칙·뜻풀이·사실 문장을 더하거나 입력을 빼는 시도(5·6·9·10단계)는 오류를 늘려 넣지 않았습니다(7-2).

사람 검수

LLM 판정만으로는 질문에 답했는지와 사실 오류를 충분히 구분하기 어려웠습니다. 사람이 읽은 결과가 직접 답 구조·위험 등급 표기·해석 말투를 바꾸는 근거가 됐습니다.

평가셋 정답 검수

날짜 대상 결과 반영
9/24 RAG 평가셋 1차 사람이 10건을 X로 뒤집음 → confirmed 30 질문만으로 해당 공고가 우선 정답이어야 O라는 기준으로 통일
9/25 RAG 평가셋 200건 confirmed 180 / rejected 20 정답 검수 종료
10/4 RAG 평가셋 260건 confirmed 233 / rejected 27 질문 22건 교체, 임베딩 평가에 사용
10/5 의도 관문 평가셋 81건 confirmed 80 / rejected 1 종로1.2.3.4가동 정답 정정, 관문 평가에 사용

리포트 해석 검수

차수 날짜 대상 결과 반영
1차 10/5 20건 × Gemini 2.5·12b 38칸 중 질문 응답 입력 10칸 모두 못 답함, 판단 어려움 26칸 해석 한 단락을 본문과 대조하도록 검수 범위 축소
2차 10/5 같은 20건 × 2모델 질문 있는 16건 중 답함 4건, Claude 판정은 모두 답함 질문 유형별 직접 답·근거를 코드가 작성, 판정 기준표 개정
3차 10/6 질문 있는 16건 × 2모델 답함 13/16 (81%), 통과선 75% 못 답함 3건의 백분위 오독을 위험 등급·풀어 쓴 순번으로 수정
4차 10/6 20건 × 3.8 일반·Opus, 블라인드 틀린 내용 두 모델 0/20, 질문 답함 둘 다 11/12. 더 나은 해석: 비슷함 14·3.8 2·Opus 1·미선택 3 3.8 일반 선택을 뒷받침, 친절한 말투 규칙 반영
5차 10/6 같은 20건 × 운영 v0.78.0의 두 모델 기록한 2건에서 틀린 내용 둘 다 0, 더 나은 해석 둘 다 3.8 직접 답·근거 상자만 펼치고 본문을 접은 검수 구성 유지

사람 검수에서 배운 것

  • 판정자와 사람은 다르게 본다. 2차에서 Claude 판정자는 질문 16건 모두 “답함”으로 봤지만 사람은 4건만 답했다고 봤습니다. LLM 판정 수치는 사람 검수로 방향을 확인한 뒤에만 믿습니다.
  • 사람에게는 바로 판단할 질문 하나만 묻는다. 1·2차에서 핵심 오류 칸이 거의 비어, 3차부터는 “질문에 답했나”만 묻고 오류율은 LLM 판정과 자동 검사로 잽니다.
  • 사람 메모가 제품 요구가 됐다. 질문 미응답 → 직접 답, 백분위 오독 → 위험 등급, “친절하지 않다” → 말투 규칙.
  • 검수 화면은 짧아야 끝까지 본다. 직접 답·근거 상자만 펼치고 본문을 접은 구성이 가장 보기 좋았습니다.

5차의 나머지 18건은 총평만 있어 20건 전체의 오류율로 계산하지 않습니다. 4차의 0/20도 작은 표본의 사람 검수 결과이며, 116건 LLM 판정의 오류가 사라졌다는 뜻은 아닙니다. 다음 검수는 분량을 줄여 끝까지 기록하도록 구성할 필요가 있습니다.

원자료는 구현 저장소의 docs/model-evaluation.md §11~12와 data/eval/results/claude-models-2026-10-06/에 있습니다. 날짜별 구현 기록은 개발 일지에서 확인할 수 있습니다.

3. 의도 관문 — gemini-3.8-flash 일반 모드

규칙이 동을 찾지 못한 자유문(“홍대 근처 미용실”, “광장시장 국밥집”)에서 동·업종·예산을 JSON으로 뽑습니다. 동 이름이 들어간 문장은 규칙이 먼저 처리하므로, LLM의 몫은 주로 랜드마크·상권 이름을 행정동으로 옮기는 일입니다. 평가셋은 사람이 검수한 80건이고, 그중 26건은 동이나 업종을 비워 둬야 정답인 문장(누락·범위 밖)입니다.

성적

지표 gemini-3.8-flash 일반 모드 뜻
지역·업종 동시 정답 98.8% (79/80) 동과 업종을 모두 맞힌 비율. 놓친 1건은 오답이 아니라 호출 실패
지역 / 업종 / 예산 98.8% / 98.8% / 98.8% 칸별 정답률(호출 실패 1건 포함)
지어내기 0/26 비워야 할 칸(서울 밖 지명·없는 업종·말하지 않은 값)에 값을 채운 경우
응답 시간 p50 2.47초 · p93 4.42초 [3.73, 5.01] 호출 한 번 기준, 240호출
호출 실패 1/240 약 9초 만에 끊김(10초 시간 제한 추정). 실패하면 규칙 결과로 응답

지어내기가 중요한 이유는 관문이 뽑은 동·업종으로 바로 판정 지도와 리포트를 열기 때문입니다. 모르면 비워 두고 되묻는 것이 안전합니다.

2.5-flash에서 바꾼 이유 — 같은 날 비교 (10/7)

리포트 해석을 3.8로 바꾼 뒤, 관문도 같은 날·같은 조건(80건 × 3회, 같은 지시문·JSON 스키마·온도 0)으로 2.5-flash와 3.8 두 설정을 나란히 쟀습니다.

모델 동시 정답(1회차) 놓친 문항 지어내기 p50 p93
gemini-3.8-flash 일반(운영, v0.88.0~) 98.8% 호출 실패 1 0/26 2.47초 4.42초
gemini-2.5-flash(10/7 이전 운영) 95.0% 익선동 한옥거리·광장시장·건대입구 맛의거리(랜드마크 → 행정동), “헬스장 차리면 망할까요?”(업종) 0/26 1.70초 2.37초
gemini-3.8-flash 사전 추론 기본 98.8% 호출 실패 1 0/26 3.28초 5.34초
  • 3.8이 LLM의 핵심 몫인 랜드마크 변환을 더 잘했습니다. 2.5는 “익선동”(행정동이 아님)·”종로5.6가동”(광장시장은 종로1.2.3.4가동)·”자양4동”(건대입구 맛의거리는 화양동)으로 옮겼고, 3회 내내 거의 같은 문항을 놓쳤습니다.
  • 동시 정답 차이(3.8 − 2.5)는 +3.7%p, 95% 구간 [−1.3%p, +10.0%p]입니다. 80건으로는 유의하다고 말할 수 없지만 차이는 3.8 쪽을 가리킵니다.
  • 대가는 응답 시간입니다. p93 기준 약 2초 느리고, 토큰 단가도 높습니다(100만 토큰당 3.8 입력 $0.75·출력 $3.75, 2.5 $0.30·$2.50).
  • 같은 2.5-flash가 10/5에는 98.8%(광장시장만 틀림)였습니다. 같은 설정·온도 0인데 날짜에 따라 결과가 달랐습니다(원인은 확인하지 못함).
  • 결정: 3.8 일반 모드로 교체(사용자 결정, v0.88.0). 사전 추론을 켠 설정은 정확도가 같고 더 느려 쓰지 않습니다.

응답 시간 분포와 신뢰도 — 모델마다 240호출. 95% 구간은 같은 문항 3회를 한 묶음으로 4,000번 다시 뽑아(bootstrap) 구했고, “바깥 표본”은 그 값보다 느린 호출을 실제로 센 개수입니다(세 모델 모두 240호출이라 같음). 판정은 구간 폭까지 봅니다. 고정 지연 기준은 두지 않고 구간별 신뢰도로 읽습니다.

  • 신뢰: 바깥 표본이 10개 이상이고 구간 폭이 1.5초 미만
  • 참고: 바깥 표본이 5개 이상
  • 불안정: 바깥 표본이 5개 미만
구간 바깥 표본 3.8 일반(운영) 95% 구간 판정 2.5-flash 95% 구간 판정 3.8 사전 추론 기본 95% 구간 판정
p50 120개 2.47초 2.42~2.57 신뢰 1.70초 1.65~1.74 신뢰 3.28초 3.14~3.40 신뢰
p60 96개 2.62초 2.52~2.77 신뢰 1.74초 1.70~1.80 신뢰 3.50초 3.37~3.65 신뢰
p70 72개 2.88초 2.72~3.04 신뢰 1.80초 1.75~1.90 신뢰 3.77초 3.62~3.91 신뢰
p80 48개 3.21초 3.00~3.38 신뢰 1.91초 1.82~2.12 신뢰 4.09초 3.86~4.42 신뢰
p90 24개 3.90초 3.43~4.44 신뢰 2.21초 1.99~2.51 신뢰 4.93초 4.47~5.73 신뢰
p91 22개 4.16초 3.48~4.72 신뢰 2.26초 2.04~2.59 신뢰 5.07초 4.54~5.82 신뢰
p92 20개 4.22초 3.59~4.88 신뢰 2.30초 2.09~2.68 신뢰 5.17초 4.63~5.99 신뢰
p93 17개 4.42초 3.73~5.01 신뢰 2.37초 2.12~2.78 신뢰 5.34초 4.73~6.23 신뢰
p94 15개 4.65초 4.07~5.57 신뢰 2.45초 2.16~3.02 신뢰 5.76초 5.00~7.07 참고
p95 12개 4.88초 4.19~6.34 참고 2.57초 2.21~3.24 신뢰 5.85초 5.12~7.24 참고
p96 10개 5.01초 4.39~6.53 참고 2.66초 2.26~3.29 신뢰 6.09초 5.23~7.79 참고
p97 8개 5.71초 4.54~6.60 참고 2.82초 2.31~3.40 참고 6.78초 5.73~8.83 참고
p98 5개 6.42초 4.94~8.67 참고 3.25초 2.47~3.45 참고 7.44초 5.88~8.95 참고
p99 3개 7.86초 5.53~8.93 불안정 3.42초 2.62~3.66 불안정 8.74초 6.18~9.22 불안정
최대 — 9.09초(실패)     3.77초     9.26초(실패)    
3초 초과 — 62/240     7/240     153/240    
5초 초과 — 11/240     0/240     24/240    
8초 초과 — 3/240     0/240     5/240    
  • 3.8 일반은 p50~p80이 2.5~3.2초로 단단하고, p94까지 ‘신뢰’입니다(p93 4.42초). p95부터는 구간 폭이 2초를 넘어 범위로 읽습니다.
  • 2.5-flash는 꼬리가 짧아 p96까지 ‘신뢰’이고, 가장 느린 호출도 3.77초였습니다.
  • p99는 세 모델 모두 바깥 표본이 3개뿐이라 판단 근거로 쓰지 않습니다. 9초대 최대값은 시간 제한에 걸린 실패 호출입니다.
  • 한 날·한 네트워크에서 잰 값이고, 3.8 두 설정은 동시에 돌렸습니다.

4. RAG 임베딩 — bge-m3@1024

품질 차이가 작아 자원과 운영 방식이 선택을 갈랐습니다. 로컬 3조합은 규칙상 동률이며, API 최고 MRR은 0.960이지만 기준선보다 유의하게 좋은 Gemini 조합은 없었습니다.

임베딩 9조합 · MRR은 높을수록 좋음

● 로컬 ◆ API 비교군 · MRR 축 0.90–1.00 확대 · 오른쪽은 질의 p95

bge-m3@1024로컬 · 채택 0.940p95 111ms
qwen3@1536로컬 · 기준선 0.935p95 89ms
qwen3@2560로컬 0.934p95 89ms
gemini-001@1024API 0.953p95 426ms
gemini-001@1536API 0.957p95 426ms
gemini-001@2560API 0.960p95 426ms
gemini-2@1024API 0.957p95 574ms
gemini-2@1536API 0.959p95 574ms
gemini-2@2560API 0.960p95 574ms
149msbge-m3 CPU 질의 p95
0.99998CPU·GPU 벡터 코사인 최소
약 45분CPU 전체 재색인 추정

벤치와 운영은 구분합니다. 위 MRR은 confirmed 233건·8,891청크·전수 검색 기준입니다. 운영 전환 후에는 8,905건을 재색인했고, HNSW 검색 MRR은 0.930입니다. CPU 동시 부하는 측정하지 않았습니다.

지금 RAG 색인은 지원사업 공고 2,265청크만 담습니다(뉴스는 이용조건에 따라 v0.83.0부터 색인하지 않음). 위 벤치는 뉴스를 포함한 당시 코퍼스 기준이라, 공고만으로 다시 재지는 않았습니다.

임베딩 상세: 평가셋·전체 결과·hard 유형·CPU·비용·전환 기록

후보 9조합

구분 모델 차원 구성
로컬 bge-m3 1024 Ollama F16, 색인·질의 같은 모델, instruction 없음
로컬 qwen3-embedding-4b 1536, 2560 당시 운영 그대로 — 색인 fp16 / 질의 Ollama Q4 + 질의 프롬프트
API gemini-embedding-001 1024, 1536, 2560 task_type RETRIEVAL_DOCUMENT / RETRIEVAL_QUERY
API gemini-embedding-2 1024, 1536, 2560 task_type을 받지 않아 프롬프트 프리픽스로 대체
  • 모델당 한 번만 최대 차원으로 임베딩하고, 앞부분을 잘라 L2 재정규화해 하위 차원을 만들었다(MRL).
  • 운영 DB를 건드리지 않고 오프라인 벡터 캐시 + numpy 전수 검색으로 쟀다. HNSW 근사 오차를 빼고 임베딩 품질만 보려는 것이다.
  • 로컬 게이트: gemma4:12b와 동시 상주 시 밀려나지 않을 것, 질의 p95 ≤ 500ms.

평가셋

  • 전체 260건을 2026-10-04에 다시 검수했다. confirmed 233건(base 179 + hard 54), rejected 27건.
  • 재검수에서 질문 22건을 바꿨다(기존 base 16건 + hard 6건: 204·215·227·233·236·249). 118번은 O→X, 258번은 X→O(커밋 18f48f9).
  • hard는 세 종류다. colloquial(n=20)은 공고명·핵심어를 피한 창업자 말투, sibling(n=16)은 유사 공고 쌍에서 정답에만 해당하는 조건으로 구별, news_event(n=18)는 헤드라인 단어를 피한 사건 질문이다.
  • hard 질문은 ANTHROPIC_API_KEY가 없어 Claude Code 서브에이전트가 쓰고 1차 판정했다. 최종 판정은 사람 검수다.
  • 판정 기준은 하나다. 질문만 보고 유사 공고보다 우선해 정답이면 O.
  • 기존 질문 16건이 바뀌어 9/24 evaluate_rag 수치와 직접 비교하지 않는다.

코퍼스

  • rag_chunk 전량 8891청크(sha256 757b1bbfee5b). 만료 공고를 포함했다.
  • 만료 공고는 운영 검색에서는 빠진다. 여기서는 모든 조합에 같은 방해 문서로 남겼다.

지표

  • top-1: 1순위 결과가 정답인 문항 비율.
  • Hit@5: 상위 5개 안에 정답이 있는 문항 비율.
  • MRR: 첫 정답 순위의 역수 평균. 상위 10 기준이다(기존 evaluate_rag는 상위 5). 주 지표.
  • nDCG@10: 상위 10개의 순위 가중 적중(이진 관련도). 보조 지표.
  • MRR(hard): hard 54건만의 MRR.
  • p50 / p95 ms: 질의 임베딩 지연의 중앙값·95백분위. 모델 단위로 쟀다(같은 모델의 차원별 지연은 같다고 본다).

전체 결과

조합 그룹 차원 top-1 Hit@5 MRR nDCG@10 MRR(hard) p50 ms p95 ms 동시상주
bge-m3@1024 local 1024 0.897 0.991 0.940 0.889 0.880 105 111 O
qwen3@1536 local 1536 0.888 0.996 0.935 0.887 0.878 84 89 O
qwen3@2560 local 2560 0.884 1.000 0.934 0.887 0.880 84 89 O
gemini-001@1024 api 1024 0.918 0.996 0.953 0.902 0.899 374 426 -
gemini-001@1536 api 1536 0.923 0.996 0.957 0.904 0.905 374 426 -
gemini-001@2560 api 2560 0.931 0.996 0.960 0.905 0.914 374 426 -
gemini-2@1024 api 1024 0.923 1.000 0.957 0.907 0.901 458 574 -
gemini-2@1536 api 1536 0.927 1.000 0.959 0.909 0.910 458 574 -
gemini-2@2560 api 2560 0.931 1.000 0.960 0.909 0.907 458 574 -
  • 측정 조건: effective 지연(max(p50, 60000/RPM))은 --rpm을 주지 않아 계산하지 않았다.
  • 로컬 VRAM 사용량(results.json vram_used_mib): bge-m3 8998 MiB, qwen3 13369 MiB.
  • 기준선 대조: 운영 evaluate_rag --provider ollama(MRR@5, HNSW, 만료 공고 제외)는 같은 233건에서 Hit@5 0.991 / MRR 0.930이었다. 벤치 qwen3@1536은 Hit@5 0.996 / MRR 0.935다. 검색 방식·코퍼스가 달라도 같은 범위다(Hit@5 +0.005, MRR +0.005).

hard 유형별 MRR

조합 colloquial (n=20) news_event (n=18) sibling (n=16)
bge-m3@1024 0.883 0.796 0.969
qwen3@1536 0.950 0.745 0.938
qwen3@2560 0.950 0.750 0.938
gemini-001@1024 0.975 0.798 0.919
gemini-001@1536 0.975 0.798 0.938
gemini-001@2560 0.975 0.826 0.938
gemini-2@1024 0.950 0.815 0.938
gemini-2@1536 0.950 0.843 0.938
gemini-2@2560 0.975 0.815 0.927
  • 로컬 둘은 유형별로 갈린다. 구어체는 qwen3, 유사 공고 구별은 bge-m3가 낫다. news_event는 bge-m3가 조금 높다.

CPU 실행

Ollama options.num_gpu=0으로 CPU에만 올렸다(ollama ps PROCESSOR 100% CPU 확인). 측정 시 load 0.4.

항목 bge-m3 CPU bge-m3 GPU qwen3-4b CPU
질의 지연 p50 / p95 (233건, bge는 ×3) 131 / 149ms 105 / 111ms 299 / 417ms
GPU 캐시 질의 벡터와 코사인 (최소 / 평균) 0.99998 / 1.00000 — 0.98703 / 0.99670
상주 메모리 (ollama ps) 1.2GB (RAM) 664MB (VRAM) 4.4GB (RAM)
콜드 로드 1.2초 — 1.7초
문서 색인 속도 (32건 배치) 3.3건/초 (512건 표본) — 0.4건/초 (128건 표본)
전체 8,891건 재색인 추정 약 45분 — 약 5.7시간
배치 처리량 (질의 32 / 128건 묶음) 28 / 29건/초 140 / 211건/초 —
  • bge-m3는 CPU에서도 벡터가 GPU와 사실상 같다. 검색 품질(MRR 0.940)이 그대로 유지된다고 본다. 질의 지연은 GPU보다 25~40ms 늘어난다.
  • qwen3-4b는 CPU에서 질의 p95 417ms, 재색인 6시간 가까이 걸린다. CPU 운영은 현실적이지 않다.
  • 같은 서버에서 백엔드·LLM이 CPU를 함께 쓰면 지연이 더 늘 수 있다. 동시 부하는 따로 본다.

비용 (API)

  • 색인 토큰: 모델당 전체 색인 1회 1,537,106토큰(count_tokens 실측). gemini-embedding-2의 프롬프트 프리픽스 토큰은 빠져 있다.
  • 429 재시도: gemini-001, gemini-2 모두 0회.
  • 가격 확인: 2026-10-04, https://ai.google.dev/gemini-api/docs/pricing
모델 무료 등급 유료 표준(100만 토큰당, 텍스트) 유료 배치 1회 전체 색인 비용(표준)
gemini-embedding-2 무료 $0.20 $0.10 약 $0.31 (배치 약 $0.15)
gemini-embedding-001 가격표에 없음 가격표에 없음 가격표에 없음 계산 불가
  • 계산: 1,537,106 / 1,000,000 × $0.20 = $0.3074. 질의(233건) 비용은 무시할 수준이라 넣지 않았다.

판정과 최종 결정

  • 로컬(규칙): qwen3@1536 현행 유지. 1위는 bge-m3@1024이고, bge-m3@1024·qwen3@1536·qwen3@2560이 동률이다. 기준선 대비 MRR 차 +0.005 [-0.018, +0.028].
  • API(규칙): gemini-001@1024. 6조합이 모두 동률이라 1024차원 둘 중 p95가 짧은 쪽(426 vs 574ms)을 골랐다.
    • gemini-001@1024와 API 최고 MRR(001@2560)의 차이는 -0.0068 [-0.0156, +0.0001]이다. 구간 상한이 0을 간신히 넘는 경계 동률이다. 이 동률이 없었다면 규칙은 gemini-2@1024를 골랐을 것이다.
    • gemini-embedding-001은 2028-05-14 단종 예정이고 가격표에도 없다(https://ai.google.dev/gemini-api/docs/deprecations, 2026-10-04 확인). gemini-2@1024는 001@1024와 동률(MRR 차 +0.0031 [-0.0141, +0.0195])이라, API 경로를 쓰게 되면 gemini-2@1024를 실무 대안으로 검토한다(재색인 1회 약 $0.31).
  • API 대 로컬: 기준선 qwen3@1536보다 유의하게 좋은 Gemini 조합은 없다. 001@1024 대비 +0.0187 [-0.0016, +0.0396], 2@1024 대비 +0.0218 [-0.0006, +0.0456]. 둘 다 구간이 0을 포함한다.
  • 최종(사용자): bge-m3@1024. 이유는 §5 ‘규칙 판정과 사용자 결정이 다른 경우’에 원문으로 옮겼다. 재색인은 GPU(Ollama)로 했다.

전환 결과 (v0.65.0, 개발 일지·버전 로그 기준)

  • 마이그레이션 c7a3f1e8d204 — HNSW 인덱스 drop → embedding vector(1024) → 기존 벡터 NULL → 인덱스 재생성. 차원이 달라 전량 재색인이 필수다.
  • 기존 테이블 백업(rag_chunk_qwen1536_20261004.dump) 뒤 GPU 전량 재색인 8,905건(funding 2,265 + news 6,640), 101초. 전부 embedded_by=bge-m3.
  • 운영 평가(confirmed 233) — Hit@5 0.983 / MRR 0.930. 전환 전 qwen3 운영은 0.991 / 0.930.
  • 재색인 건수(8,905)는 벤치 코퍼스 스냅샷(8,891)과 다르다. 원자료에 차이의 원인은 적혀 있지 않다.

5. 어떻게 평가했나

  1. 1. 게이트필수 기준을 통과한 로컬 후보만 남김
  2. 2. 품질역할별 주 지표와 95% 구간 비교
  3. 3. 자원규칙상 동률이면 차원·VRAM·지연 비교
임베딩 교체 규칙qwen3@1536 유지

기준선보다 유의하게 좋을 때만 교체. MRR 차이 +0.005의 95% 구간은 [−0.018, +0.028].

최종 사용자 결정bge-m3@1024 채택

자원 효율, 색인·질의 모델 통일, CPU 운영 가능성을 고려한 선택.

동률은 성능 동등성이 입증됐다는 뜻이 아닙니다. 유의한 차이를 관측하지 못했다는 선택 규칙입니다. API는 온라인 비교군으로 로컬 채택 판정에서 제외했습니다.

메모리 비교: bge-m3의 664MB는 VRAM, qwen3의 4.4GB는 RAM입니다. 같은 기준의 CPU 상주 메모리는 각각 1.2GB / 4.4GB이며, 664MB와 4.4GB를 GPU 메모리끼리 비교할 수 없습니다.

자원 제약·판정 규칙·사용자 결정 원문

평가 순서는 research.remakeday.com/experiments/model-selection 과 같습니다. 게이트 먼저, 그다음 품질, 품질이 동률이면 자원(VRAM·지연)이 작은 쪽입니다. 보안 요구가 있으면 온프레미스로만 돌려야 할 수 있습니다.

자원 제약

  • GPU는 RTX 5060 Ti 16GB 한 장이다. 임베딩·리포트 모델·관문 모델이 함께 올라가야 한다.
  • GPU가 없는 서버도 고려해 CPU 실행을 따로 쟀다(AMD Ryzen 5 9600X 6코어, RAM 29GB).
  • 로컬 모델은 토큰 단가가 없다. 전기료·카드 감가는 계산에 넣지 않았다.

외부 API를 쓰는 이유

로컬 후보 6개는 가드 후에도 엄격 게이트를 넘지 못했습니다. LLM이 해석 한 단락만 쓰는 코드 우선 구조로 바꾼 뒤에도 gemma4:12b의 핵심 오류는 35/116(30.2%, 7-2의 2단계 기준)였습니다. 숫자·추세·신호 뜻을 본문과 다르게 옮기는 오류라, 리포트 해석은 외부 API를 기본으로 쓰고 로컬은 폴백으로 둡니다.

RTX 5060 Ti 16GB 한 장에 임베딩과 리포트 모델이 함께 올라가야 합니다. gemma4:12b와 bge-m3의 동시 상주는 9,790 MiB이고, 관문 e4b까지 올리면 14,661 MiB입니다. 이번 평가 범위는 이 장비에서 함께 실행할 수 있는 후보로 한정했습니다. 더 큰 모델이나 미세조정·증류로 품질을 높이는 방법은 검증하지 않았습니다. 27~32B급은 4비트 양자화 파일만으로 16GB를 넘고(파일 크기 기준 추정), 학습은 추론보다 VRAM이 더 필요해 이 장비에서 시도할 수 없었습니다. 온프레미스가 꼭 필요해지면 GPU 증설이나 별도 추론 서버가 먼저입니다.

온프레미스 대 온라인

  • 온라인(Gemini API)은 같은 지표로 비교만 하고 판정 대상에서 뺐다. 대신 비용(토큰 × 공개 단가, 확인일·URL)과 지연을 적었다.
  • 온프레미스 후보는 판정 대상이다. “로컬만으로 운영할 수 있는가”가 이 평가의 핵심 질문이다.

판정 규칙

  1. 하드 게이트를 통과한 로컬 모델만 후보로 남긴다.
  2. 주 지표 1위를 고른다(임베딩 MRR, 리포트 품질 점수, 관문 동시 정답).
  3. 1위와 후보의 문항별 점수 차이를 paired bootstrap(n=10000, seed 0)으로 구한다. 95% 구간이 0을 포함하면 모델 선택 규칙상 동률로 처리한다. 이 문서의 ‘동률’은 유의한 차이를 관측하지 못했다는 뜻이며, 성능 동등성이 입증됐다는 뜻은 아니다.
  4. 동률이면 자원이 작은 쪽이다. 임베딩은 낮은 차원 → 짧은 질의 지연, LLM은 VRAM 작은 순 → p95 짧은 순.
  5. 현행 운영 모델에 우대는 없다. 단, 임베딩은 “기준선보다 유의하게 좋을 때만 교체”를 규칙에 넣었다.

규칙 판정과 사용자 결정이 다른 경우 (임베딩)

  • 규칙 판정은 qwen3@1536 현행 유지였다. 1위 bge-m3@1024가 기준선보다 유의하게 좋지 않았기 때문이다.
  • 사용자는 bge-m3@1024로 바꾸기로 했다. 원문 이유는 다음과 같다.
    • “qwen3@1536과 MRR 동률(+0.005 [−0.018, +0.028])이면서 GPU 메모리 664MB 대 4.4GB, 색인·질의를 모델 하나로 처리, CPU로도 운영 가능하다는 점에서 자원 대비 효율이 가장 높다.”
    • “위 판정 절의 ‘현행 유지’는 교체 비용을 고려한 규칙상 결과이고, 자원 제약·온프레미스를 기준으로 한 최종 선택은 bge-m3다.”
  • 위 인용문의 메모리 비교는 정정이 필요하다. bge-m3의 664MB는 GPU 상주 메모리(VRAM), qwen3-4b의 4.4GB는 CPU 상주 메모리(RAM)다. CPU 기준으로는 bge-m3 1.2GB와 qwen3-4b 4.4GB를 비교할 수 있다. 표에 qwen3의 GPU 상주값은 따로 없으므로, 664MB와 4.4GB를 GPU 메모리끼리 직접 비교할 수 없다.

6. 평가가 흘러간 과정

  1. 임베딩

    로컬 3·API 6조합을 같은 233문항으로 비교 → bge-m3@1024 채택(v0.65.0). 품질은 동률, 자원·운영 방식이 갈랐다

  2. 로컬 LLM

    "로컬만으로 운영할 수 있나"를 물었다. 당시 구조(LLM이 6개 절을 모두 씀)에서 리포트·관문 로컬 후보 6개 모두 게이트 탈락. gemini-2.5-flash는 비교군

  3. 가드·온도 0

    LLM이 틀리는 자리를 코드 가드로 막고 온도 0·seed를 고정(v0.67.0). 일관성은 올랐지만 로컬은 여전히 규칙 위반·지연으로 미달

  4. 구조 전환

    결론: LLM에 맡기는 범위를 줄인다. 판정·수치·근거는 코드가, LLM은 해석 한 단락만(v0.68.0). 이때부터 재는 대상이 "해석 한 단락의 핵심 오류"로 바뀌어 앞 수치와 직접 비교하지 않는다

  5. 사람 검수

    1~5차. 판정자와 사람의 차이를 확인하고, 직접 답·위험 등급·말투 규칙이 여기서 나왔다

  6. 외부 API 비교

    Claude 3종 → Opus 1차(v0.73.0) → 같은 116건에 Gemini 3.8 추가 → 3.8 일반 1차(v0.75.0)

  7. 반복 개선

    해석을 바꿀 때마다 116건을 다시 쟀다(4~13단계: 적용 5 · 일부 적용 1 · 미적용 4). 기본 모델 오류가 늘면 넣지 않는다

  8. 관문 3.8

    의도 관문을 같은 날 2.5-flash와 3.8 두 설정으로 나란히 쟀다. 3.8 일반 98.8% 대 2.5 95.0%(2.5가 랜드마크 변환을 놓침), 지어내기 둘 다 0/26 → 3.8 일반 모드로 교체(v0.88.0)

단계마다 무엇을 재는지가 달라졌습니다. 10/5 리포트 품질 점수(10점 만점, 6개 절 전체)와 10/6 이후 핵심 오류율(해석 한 단락)은 다른 검사입니다. 그래서 10/5 리포트 실험(품질·가드·온도 0)은 3.8로 다시 재지 않았습니다 — 그 구조가 운영에 없고, 3.8은 지금 구조에서 116건으로 쟀습니다.

7. 시도했지만 채택하지 않은 것

운영 모델을 고르기까지 여러 후보와 개선안을 같은 방식으로 쟀습니다. 채택하지 않은 것도 결정의 근거라 그대로 남깁니다. 7-1은 로컬 LLM, 7-2는 해석 개선 전체 기록, 7-3은 다른 후보 모델입니다.

7-1. 로컬 LLM 단독 운영 (2026-10-05)

질문은 “로컬만으로 운영할 수 있나”였습니다. 당시 리포트는 LLM이 사실 묶음을 받아 6개 절(판정·이유·유사 사례·조건·대안·지원사업)을 모두 쓰는 구조였고, 로컬 후보 6개와 비교군 gemini-2.5-flash를 같은 고정 사실 12건 × 3회로 쟀습니다. 기준선 → 코드 가드 → 온도 0 순서로 고쳐 가며 다시 쟀지만 로컬은 끝내 기준을 넘지 못했고, 이 결과가 코드 우선 구조로 바꾸는 근거가 됐습니다. 이 구조는 지금 운영에 없으므로 아래 수치는 결정의 경위로 읽습니다.

기준선 (가드 전)

리포트는 가드 전 로컬 6개 모두 탈락했습니다. 품질 점수는 gemini-2.5-flash 6.67 / gemma4:12b 6.00 / gemma4:e4b 5.42였지만, 점수만으로 채택할 수 없습니다. 가드 후 게이트별 결과는 아래 ‘코드 가드 적용 후’에 있습니다.

LLM 기준선 상세: 후보·채점·리포트·관문 전체 결과·자원·정정 이력
두 역할
역할 당시 운영 구성 호출 형태
창업 경고 리포트 작성 gemini-2.5-flash 주, 실패 시 gemma4:12b 사실 묶음(facts)을 첫 메시지에 넣고 6개 절(판정·이유·유사 사례·조건·대안·지원사업)을 스트리밍. 도구는 자금 계산·RAG 재검색에만
의도 관문 폴백 gemini-2.5-flash만 규칙이 못 푼 자유문에서 region_name(동 427개 중)·industry_id·budget_krw를 JSON 스키마로 1콜 추출
후보 모델
모델 VRAM(MiB, size_vram) 리포트 관문 라이선스 비고
gemma4:12b 8034 O O Gemma 이용 약관(상업 가능) 당시 로컬 폴백. 우대 없음
gemma4:e4b 3158 O O Gemma 이용 약관(상업 가능) 실제 점유는 보고값보다 크다(아래 동시 상주)
kanana1.5:8b-q4km 8780 O O Apache 2.0(모델 카드 확인) 한국어 특화
qwen3.5:9b 6424 O O Apache 2.0  
qwen3.5:4b 4074 O O Apache 2.0  
qwen3.5:2b-q4_K_M 1990 — O Apache 2.0 관문 전용
exaone3.5:7.8b 8697 O(도구 없이) — EXAONE AI Model License 1.1 NC(비상업) 참고 비교군. 채택 불가
gemini-2.5-flash - O O API 온라인 비교군. 판정 대상 아님
  • 통제: Ollama 기본 태그(Q4_K_M), thinking 끔(think: false), 입력 고정. 리포트는 num_ctx 32,768로 고정했다.
  • kanana는 ollama show --license가 아무것도 출력하지 않아 Hugging Face 모델 카드로만 확인했다.
  • 스펙 §2의 모델 크기(예: gemma4:e4b 9.6GB)는 설계 시점 표기다. 이 문서의 VRAM은 결과 보고서의 실측값(size_vram)을 따른다.
평가셋
  • 관문: 81건을 사람이 검수해 confirmed 80 / rejected 1(i008 정답을 종로1.2.3.4가동으로). 유형은 랜드마크·업종 구어체·예산 표현·누락(missing)·범위 밖(out_of_scope)·복합이다. 규칙 엔진을 거치지 않고 추출기를 직접 부른다. 모든 모델에 같은 지시문(동 427개 포함)과 같은 JSON 스키마.
  • 리포트: 12시나리오 × 3회. 판정 4종을 고루 넣고, 데이터 일부 없음·응답 규칙이 걸리는 질문·도구가 필요한 질문을 포함했다.
  • facts 고정: 12건의 사실 묶음을 한 번 수집해 data/eval/report_facts/<id>.json으로 저장하고 모든 모델에 같은 것을 넣었다. 데이터 갱신과 무관하게 모델만 비교한다.
채점 방식

자동 지표(전 회차)와 블라인드 LLM 판정자(품질·규칙 위반)를 함께 쓴다.

리포트 지표:

  • 품질: 판정자 점수 = 근거 충실도(1~5) + 자연스러움(1~5), 10점 만점. 주 지표.
  • 완주: 오류 없이 6개 절을 모두 쓴 비율.
  • 판정 모순 없음: facts와 다른 등급을 단정하지 않은 비율.
  • 판정 등급 생략: 판정 절에서 등급 말을 아예 쓰지 않은 회차 수. 생략은 위 지표를 통과하므로 따로 센다.
  • 지어내기: 근거에 없는 숫자가 하나라도 나온 리포트 비율.
  • 규칙: 판정자가 적은 응답 규칙 위반 건수.
  • 첫 글자 / 완료 p95: LLM 호출 시작부터 첫 글자·완료까지 시간의 95백분위(facts 수집 시간 제외).

관문 지표:

  • 동시 정답: 지역·업종이 모두 맞은 비율. 주 지표.
  • 지역 / 업종 / 예산: 각 필드 정답률. 예산은 보조.
  • 스키마: JSON 스키마 통과율.
  • 지어내기: missing·out_of_scope 26건에서 null이어야 할 칸에 값을 만든 비율.
  • 지어내기(null 칸 전체, 참고): 정답에 null 칸이 있는 모든 행(51건)을 분모로 센 값.

게이트:

역할 게이트
리포트 완주 ≥ 0.95 · 판정 일치 = 1.00 · 지어내기 ≤ 0.05 · 응답 규칙 위반 0건 · 첫 글자 p95 ≤ 5초 · 완료 p95 ≤ 60초
관문 스키마 ≥ 0.98 · 지어내기 ≤ 0.05 · p95 ≤ 3초
자원 조합 리포트 모델 + 관문 모델 + bge-m3를 함께 올려 밀려나지 않을 것(ollama ps + nvidia-smi)

판정자 기준표(data/eval/report_judge_rubric.md) 요약:

  • 판정자는 이름이 가려진 리포트(A, B, C…)를 글만 보고 채점한다. 판정 모델은 opus다.
  • faithfulness(1~5): 사실 묶음에 있는 사실만 쓰는가. 숫자·공고명·URL 지어내기, 예시값을 현재 사실처럼 쓰기, 판정 등급 바꿔 말하기는 크게 감점.
  • fluency(1~5): 한국어가 자연스럽고 섹션 계약(판정 1~2문장, 이유는 신호별 단락 등)을 지키는가.
  • violations: 차별·혐오 표현, 재난기(2020~2022) 폐업률 일반화, 금융 규제(특정 금융사·상품 추천, 대출 권유), 신뢰 등급 표기 규칙 위반.
  • 판정 묶음에는 facts 요약(앞 3,000자)만 들어가므로 전체 facts 파일도 함께 읽게 했다.
리포트 결과 (가드 전)
모델 VRAM(MiB) 품질 완주 판정 모순 없음 판정 등급 생략 지어내기 규칙 첫 글자 p95(ms) 완료 p95(ms) 게이트 비고
gemma4:12b 8034 6.00 0.92 1.00 7/36 0.39 12 8292 37056 X  
gemma4:e4b 3158 5.42 1.00 0.94 11/36 0.03 7 11858 21010 X  
kanana1.5:8b-q4km 8780 3.75 1.00 0.94 2/36 0.47 19 4277 31013 X  
qwen3.5:9b 6424 4.67 0.78 0.69 2/36 0.17 14 5417 17224 X  
qwen3.5:4b 4074 4.50 0.94 0.58 5/36 0.08 13 3671 10889 X  
exaone3.5:7.8b 8697 3.50 1.00 0.89 1/36 0.19 21 4541 31035 X 도구 없음(참고 비교군, 라이선스 NC)
gemini-2.5-flash - 6.67 1.00 1.00 18/36 0.03 11 1537 14244 X 온라인 비교군

게이트 탈락 사유:

모델 탈락 게이트
gemma4:12b completion, fabrication, rules, latency
gemma4:e4b verdict_match, rules, latency
kanana1.5:8b-q4km verdict_match, fabrication, rules
qwen3.5:9b completion, verdict_match, fabrication, rules, latency
qwen3.5:4b completion, verdict_match, fabrication, rules
exaone3.5:7.8b verdict_match, fabrication, rules
gemini-2.5-flash 온라인 비교군(판정 대상 아님). 규칙 게이트 미달
  • gemma4:12b의 지어내기 0.39는 36회 중 14회에서 기업마당 공고 번호·URL을 깨뜨려 옮긴 것이다(예: 200124107, 000000000124844).
  • Gemini도 규칙 게이트에서 떨어졌다. 판정자가 적은 위반 11건 중 8건이 신뢰 등급 표기 누락이다.
관문 결과
모델 VRAM(MiB) 동시 정답 지역 업종 예산 스키마 지어내기 지어내기(null 칸 전체, 참고) p95(ms) 게이트
gemma4:12b 8034 0.887 0.887 0.988 0.950 1.000 0.077 0.039 1300 X
gemma4:e4b 3158 0.762 0.787 0.975 0.762 1.000 0.308 0.157 754 X
kanana1.5:8b-q4km 8780 0.487 0.550 0.900 0.350 1.000 0.654 0.569 606 X
qwen3.5:9b 6424 0.625 0.675 0.875 0.675 1.000 0.192 0.098 957 X
qwen3.5:4b 4074 0.650 0.738 0.887 0.762 1.000 0.308 0.157 704 X
qwen3.5:2b-q4_K_M 1990 0.013 0.075 0.163 0.613 1.000 0.577 0.294 434 X
gemini-2.5-flash - 0.988 0.988 1.000 0.950 1.000 0.000 0.000 2637 O
  • 로컬 6개 모델 모두 지어내기 게이트 하나로 탈락했다.
  • gemma4:12b는 2/26 = 0.077이다. 지어낸 2건은 둘 다 서울 밖 지명을 서울 동으로 바꾼 경우다. “분당 정자동 치킨집”(i057)에서 region을 정자동으로, “하남 미사에서 꽃집”(i067)에서 region을 신장동으로 채웠다.
  • 예산 “3천”을 여러 로컬 모델이 3,000으로 읽었다.
  • 관문 동시 정답 로컬 최고는 gemma4:12b(0.887)다. 2위 e4b(0.762)와의 차이는 +0.125 [+0.05, +0.20]이라 동률이 아니다.
참고 순위와 bootstrap 구간 (채택 결정 아님)

엄격 게이트를 통과한 로컬 리포트 모델이 없어 참고용이다. 참고 1위(동률 시 VRAM 작은 쪽)는 gemma4:e4b, 동률 {gemma4:12b, gemma4:e4b}.

순위 모델 품질 1위 대비 차이 [95% 구간] VRAM(MiB) 게이트 탈락
1 gemma4:12b 6.00 - 8034 completion, fabrication, rules, latency
2 gemma4:e4b 5.42 +0.58 [-0.17, +1.25] 3158 verdict_match, rules, latency
3 qwen3.5:9b 4.67 +1.33 [+0.58, +2.08] 6424 completion, verdict_match, fabrication, rules, latency
4 qwen3.5:4b 4.50 +1.50 [+0.50, +2.42] 4074 completion, verdict_match, fabrication, rules
5 kanana1.5:8b-q4km 3.75 +2.25 [+1.50, +3.00] 8780 verdict_match, fabrication, rules
6 exaone3.5:7.8b 3.50 +2.50 [+1.83, +3.17] 8697 verdict_match, fabrication, rules
  • Gemini 품질은 6.67이다.
판정자 위반 유형 (가드 전)
모델 신뢰 등급 표기 금융 재난기 차별 기타
gemma4:12b 10 0 0 0 2
gemma4:e4b 6 0 0 0 1
kanana1.5:8b-q4km 12 4 1 0 2
qwen3.5:9b 11 0 0 0 3
qwen3.5:4b 9 2 0 0 2
exaone3.5:7.8b 11 6 0 0 4
gemini-2.5-flash 8 3 0 0 0
  • 표 합계로 보면 위반 97건 중 67건이 신뢰 등급 표기다(합계는 이 문서에서 더한 값). Gemini를 포함한 모든 모델이 이 규칙을 어긴다. 프롬프트·형식 문제로 보인다.
동시 상주

백엔드가 리포트 모델·관문 모델·bge-m3를 함께 올리는 경우의 GPU 사용량(nvidia-smi)이다. /api/ps의 size_vram이 size와 같을 때(CPU 오프로드 없음)만 통과로 셌다.

조합 합계(MiB) ok
gemma4:e4b(리포트) + gemma4:12b(관문) + bge-m3 14,661 O
gemma4:12b 단독(리포트·관문 겸용) + bge-m3 9,790 O
  • /api/ps 기준 e4b는 3,158 MiB지만 두 조합의 nvidia-smi 차이는 4,871 MiB다. 실제 점유가 보고값보다 크다. 16GB 카드에서 첫 조합의 여유는 약 1.6GB다.

로컬로 간다면 받아들여야 할 트레이드오프(notes 원문 요약):

구성 장점 대가
gemma4:12b로 리포트·관문 모두 모델 하나라 단순. bge-m3까지 9,790 MiB 리포트 지어내기 0.39(공고 번호·URL 훼손), 완주 0.92, 첫 글자 p95 8.3초(게이트 5초)
gemma4:e4b 리포트 + 12b 관문 e4b 리포트는 지어내기 0.03, 완주 1.00 판정 모순 2/36, 등급 생략 11/36. 실제 GPU 약 4.9GB 추가, 여유 약 1.6GB
Gemini 비용
  • 리포트 1건 평균 토큰(캐시 36건): 입력 14,085 / 출력 1,942.
  • 단가: 입력 $0.30 / 출력 $2.50(100만 토큰당, 확인 2026-10-05, https://ai.google.dev/gemini-api/docs/pricing).
  • 리포트 1건 약 $0.0091, 1,000건이면 약 $9.08.
  • 관문 호출은 캐시에 토큰을 남기지 않아 관문 비용은 계산하지 않았다.
  • 로컬 리포트 1건 평균 입력은 13,076~15,413 토큰, 출력은 524~1,387 토큰이다(여러 턴 합계).
채점 정정 이력
  • 판정 일치 → 판정 모순 없음. 처음에는 기대 등급 표현이 있어야 일치로 봤다. 정상 표현(‘주의’ 등급, insufficient, 빨간불, “판정을 내리지 않습니다”)을 놓쳐 Gemini가 0.22로 왜곡됐다. “다른 등급을 단정하지 않음”으로 다시 정의하고 동의어를 넓혔다. 생략 회차는 판정 등급 생략 열에 따로 적는다.
  • 지어내기 근거 확장. 대조 근거는 facts + 질문 + 도구 결과 + 시스템 프롬프트 + 도구 설명이다. 프롬프트가 준 숫자(“13개 입력” 등)를 지어낸 것으로 세지 않으려는 것이다. 시스템 프롬프트의 예시 값을 사실처럼 쓴 경우는 자동 대조로 못 거르므로 판정자에게 맡긴다.
  • 관문 지어내기 분모. 처음 결과는 null 칸이 있는 모든 행(51건)을 분모로 써서 스펙과 달랐고, 그 기준으로는 gemma4:12b가 0.039로 관문 승자였다. 스펙대로 missing·out_of_scope 26건으로 다시 세면 0.077이고 로컬 관문 승자는 없다. 두 값을 모두 표에 실었다.
발견 — 운영 폴백 컨텍스트 잘림
  • Ollama 0.31.2는 num_ctx를 지정하지 않으면 입력을 잘라 읽는다. 합성 입력(약 29,400자)을 qwen3.5:4b에 보내자 prompt_eval_count가 기본 컨텍스트에서 2,050, num_ctx 32,768에서 17,422였다. gemma4:12b도 기본 컨텍스트에서 2,051이었다.
  • 실제 리포트의 첫 턴 프롬프트는 num_ctx 32,768에서 13.1k~14.1k 토큰이다(도구 없이 최대 13,111, 도구 설명 포함 최대 14,143).
  • 운영 로컬 폴백(gemma4:12b)은 그동안 약 2k 토큰만 읽고 facts 대부분을 못 보고 있었다. v0.66.1에서 num_ctx=32768을 지정했고, 호스트·컨테이너 실측 입력이 2,051 → 19,228토큰이 됐다(개발 일지 기준).
  • 관문 프롬프트는 2,025~2,078 토큰이라 잘리지 않았다. num_ctx 8192를 줘도 같은 값이었다.
  • Ollama의 format은 Gemini 스키마의 nullable을 무시한다(문자열 “null”이 관측됨). Ollama용 스키마는 type 합집합([“string”,”null”])을 쓴다.

코드 가드 적용 후 (v0.67.0)

가드 후에도 로컬 리포트 단독 운영 기준을 만족하는 모델은 없었습니다. 12b는 지어내기가 줄었지만 규칙 위반·첫 글자 지연이 남았고, e4b는 지어내기도 기준을 넘었습니다.

가드 후 리포트 · ✓ 통과 / ✕ 미달 · 셀 안에 실측값 표시
모델완주
≥ 0.95
모순 없음
= 1.00
지어내기
≤ 0.05
규칙 위반
0건
첫 글자 p95
≤ 5초
완료 p95
≤ 60초
gemma4:12b✓ 통과1.00✓ 통과1.00✓ 통과0.00✕ 미달12건✕ 미달9.606초✓ 통과25.162초
gemma4:e4b✓ 통과1.00✓ 통과1.00✕ 미달0.06✕ 미달12건✕ 미달12.694초✓ 통과20.031초
kanana1.5:8b-q4km✕ 미달0.61✕ 미달0.47✕ 미달0.64✕ 미달27건✕ 미달7.446초✓ 통과28.639초
qwen3.5:9b✕ 미달0.69✕ 미달0.64✕ 미달0.11✕ 미달15건✕ 미달6.761초✓ 통과16.396초
qwen3.5:4b✕ 미달0.61✕ 미달0.53✕ 미달0.14✕ 미달19건✓ 통과4.465초✓ 통과12.503초
exaone3.5:7.8b비상업 라이선스 · 채택 불가✕ 미달0.78✕ 미달0.78✕ 미달0.11✕ 미달19건✕ 미달25.558초✓ 통과44.109초
gemini-2.5-flash온라인 비교군 · 판정 대상 제외✕ 미달0.94✓ 통과1.00✕ 미달0.06✕ 미달4건✓ 통과2.114초✓ 통과9.402초

gemini-2.5-flash는 온라인 비교군입니다. 위 표의 셀은 같은 기준과 비교한 값이며, 로컬 채택 판정 대상에는 포함하지 않습니다. 가드 후 gemini-2.5-flash도 완주·지어내기·규칙 위반 기준에 미달했습니다.

gemma4:12b · 가드·프롬프트 변경 전후

○ 가드 전 ● 가드 후 · 축 0–1

지어내기 · 낮을수록 좋음 0.39 → 0.00
완주 · 높을수록 좋음 0.92 → 1.00

해석: 지어내기 0.39 → 0.00은 프롬프트에서 링크를 빼자 모델이 링크를 쓰지 않은 결과입니다(링크 제거 개입 0회). 규칙 위반은 12건 → 12건으로 남았습니다.

비교 조건: 가드 후 첫 글자 지연은 판정 절 버퍼링을 포함하므로 가드 전과 직접 비교하지 않습니다. 전후 품질은 판정 세션이 달라 ±0.5 안쪽 차이를 판정자 잡음과 구분할 수 없습니다.

당시(옛 구조) 남은 문제는 대안 등급 바꿔 쓰기, 뉴스가 없을 때 문장 지어내기, 꺼진 신호 오독, 예시 금리 옮기기, 추측에도 붙는 기본 신뢰 태그였습니다. 이 가운데 대안 등급·신뢰 태그는 v0.68.0부터 코드가 쓰고, 예시 금리는 v0.67.0에서 지웠으며, 뉴스는 v0.83.0부터 해석 입력에서 빠졌습니다.

가드 상세: 4종 동작·전체 전후 수치·개입 횟수·남은 실패 유형

화면이 이미 카드로 보여 주는 값(판정 등급·지원사업 원문 링크)을 LLM이 글로 옮기다 틀리는 실패가 많았다. 이것을 코드로 막고 같은 조건(고정 facts 12건, 7개 모델 × 3회, 같은 기준표, 같은 판정 모델)으로 다시 쟀다. 관문은 다시 돌리지 않았다(기준선 캐시 그대로).

가드 4종
  1. 판정 모순 교체: 판정 절에 등급 이름을 쓰지 말라고 바꿨다. 명시적 등급 단정이 사실과 어긋나면 코드가 판정 절을 사실 문장으로 바꾼다. 판정 절은 끝까지 모았다가 한 번에 내보낸다.
  2. 링크·공고 번호 제거: 프롬프트에서 쓰지 말라고 하고, 출력 스트림에서도 URL·공고 번호를 지운다.
  3. 기본 신뢰 태그: 판정·이유·조건·대안·지원사업 절 본문이 태그 없이 시작하면 [확인된 사실]을 붙인다(유사 사례 절 제외).
  4. 지원사업 고지문: 절 끝에 “금리·한도는 예상치…원문 확인” 고지문을 붙인다.
전후 비교 (리포트, 화면 본문 기준)
모델 품질 전→후 완주 판정 모순 없음 지어내기 판정자 규칙 위반 첫 글자 p95(ms)*
gemini-2.5-flash 6.67 → 6.75 1.00 → 0.94 1.00 → 1.00 0.03 → 0.06 11 → 4 1,537 → 2,114
gemma4:12b 6.00 → 5.83 0.92 → 1.00 1.00 → 1.00 0.39 → 0.00 12 → 12 8,292 → 9,606
gemma4:e4b 5.42 → 5.58 1.00 → 1.00 0.94 → 1.00 0.03 → 0.06 7 → 12 11,858 → 12,694
qwen3.5:9b 4.67 → 4.92 0.78 → 0.69 0.69 → 0.64 0.17 → 0.11 14 → 15 5,417 → 6,761
qwen3.5:4b 4.50 → 3.92 0.94 → 0.61 0.58 → 0.53 0.08 → 0.14 13 → 19 3,671 → 4,465
kanana1.5:8b-q4km 3.75 → 3.25 1.00 → 0.61 0.94 → 0.47 0.47 → 0.64 19 → 27 4,277 → 7,446
exaone3.5:7.8b 3.50 → 3.67 1.00 → 0.78 0.89 → 0.78 0.19 → 0.11 21 → 19 4,541 → 25,558

* 가드 후 첫 글자는 판정 절 전체를 모으는 시간을 포함한다. 기준선과 의미가 다르다.

  • 가드 notes의 이 표는 kanana를 “kanana1.5:8b”로 적었다. 같은 모델(kanana1.5:8b-q4km)이다.
  • 품질은 판정 세션이 달라 ±0.5 안쪽 차이는 판정자 잡음과 구분되지 않는다(참고치).
  • qwen·kanana·exaone의 완주·판정 하락에는 가드가 잘못된 판정 절을 교체한 것(교체 = 실패로 집계)과 프롬프트 변경 영향이 섞여 있다.

가드 후 전체 표(나머지 열 포함):

모델 VRAM(MiB) 품질 완주 판정 모순 없음 판정 등급 생략 지어내기 규칙 첫 글자 p95(ms) 완료 p95(ms) 게이트 탈락 게이트
gemma4:12b 8034 5.83 1.00 1.00 36/36 0.00 12 9606 25162 X rules, latency
gemma4:e4b 3158 5.58 1.00 1.00 35/36 0.06 12 12694 20031 X fabrication, rules, latency
kanana1.5:8b-q4km 8780 3.25 0.61 0.47 2/36 0.64 27 7446 28639 X completion, verdict_match, fabrication, rules, latency
qwen3.5:9b 6424 4.92 0.69 0.64 6/36 0.11 15 6761 16396 X completion, verdict_match, fabrication, rules, latency
qwen3.5:4b 4074 3.92 0.61 0.53 6/36 0.14 19 4465 12503 X completion, verdict_match, fabrication, rules
exaone3.5:7.8b 8697 3.67 0.78 0.78 3/36 0.11 19 25558 44109 X completion, verdict_match, fabrication, rules, latency
gemini-2.5-flash - 6.75 0.94 1.00 27/36 0.06 4 2114 9402 X 온라인 비교군
가드 개입 횟수 (전 회차 합)
모델 판정 교체 링크 제거 태그 추가 고지문 원문 판정 모순 없음 원문 지어내기
gemma4:12b 0 0 180 36 1.00 0.00
gemma4:e4b 0 0 180 36 1.00 0.06
kanana1.5:8b-q4km 14 5 180 36 0.50 0.64
qwen3.5:9b 10 1 178 34 0.64 0.11
qwen3.5:4b 13 0 179 35 0.53 0.14
exaone3.5:7.8b 7 40 175 35 0.78 0.11
gemini-2.5-flash 0 0 174 36 1.00 0.06
  • “원문” 두 열은 가드 전 모델 출력 그대로의 지표다.
  • 12b의 지어내기 0.39 → 0.00은 프롬프트에서 링크를 빼자 12b가 링크를 아예 쓰지 않은 결과다(링크 제거 개입 0회).
  • 신뢰 태그는 모든 모델이 섹션 180개 중 174~180개를 빠뜨려 코드가 붙였다. 프롬프트로는 지켜지지 않는 규칙이었다.

판정자 위반 유형(가드 후):

모델 신뢰 등급 표기 금융 재난기 차별 기타
gemma4:12b 7 0 1 0 4
gemma4:e4b 6 0 0 0 6
kanana1.5:8b-q4km 9 0 0 0 18
qwen3.5:9b 1 0 0 0 14
qwen3.5:4b 1 0 4 0 14
exaone3.5:7.8b 7 1 0 0 11
gemini-2.5-flash 2 1 0 0 1

참고 순위(가드 후): 1위 gemma4:12b 5.83, 2위 gemma4:e4b 5.58, 차이 +0.25 [-0.17, +0.67]로 동률 → VRAM 우선으로 e4b. 3위 이하는 qwen3.5:9b 4.92(+0.92 [+0.25, +1.67]), qwen3.5:4b 3.92(+1.92 [+1.17, +2.75]), exaone3.5:7.8b 3.67(+2.17 [+1.25, +2.92]), kanana1.5:8b-q4km 3.25(+2.58 [+2.17, +3.00]).

Gemini 비용(가드 후): 리포트 1건 평균 입력 14,189 / 출력 1,308 토큰, 약 $0.0075.

남은 실패 유형

로컬 모델은 여전히 엄격 게이트를 통과하지 못한다. 12b·e4b의 남은 탈락 사유는 규칙 위반과 첫 글자 지연이다. 남은 위반은 가드가 다루지 않은 새 유형이다.

  1. 대안 절 등급 바꿔 쓰기 — 대안 동네·업종의 등급(clear 등)을 “판정 없음”·”조건부”로 옮겨 적는다. 12b 12건 중 5건(s03·s07·s08·s11·s12), e4b 2건.
  2. 뉴스 없을 때 [참고 신호] 지어내기 — 뉴스가 없는데 프롬프트 예시 문장(“대부분 논의·실험 단계라…”)을 그대로 옮긴다. 12b 4건, Gemini 2건(“기사 없음” 문장).
  3. 꺼진 신호를 켜진 신호로 읽기 — e4b 4건. 모델 능력 문제.
  4. Gemini의 “예상 대출 금리 연 4.05%” 1건 — 도구 명세의 예시값(loan_rate “예 0.0405”)이 원인. 온도 0 단계에서 예시값을 지웠다.
  5. 기본 태그의 위험 — 코드가 붙이는 [확인된 사실]은 문단에 뉴스·추측이 섞여도 붙는다. e4b가 판정·이유 문단에 “최근 뉴스에서는 … 긍정적인 신호”를 섞으면 확인된 사실처럼 보인다(비교 판정에서 4건 지적). 그래서 판정자의 신뢰 등급 표기 위반은 크게 줄지 않았다(e4b 6 → 6, 12b 10 → 7).

온도 0·seed 고정 (v0.67.0)

일관성은 높아졌고, 유의한 품질 차이는 관측되지 않았습니다. 고정 사실 12건을 모델별로 3회 반복해 비교했습니다.

결론 일치 · 높을수록 좋음

○ 벤치 기본 설정 ● 온도 0 · 축 0–1

gemini-2.5-flash 0.75 → 1.00
gemma4:12b 1.00 → 1.00
gemma4:e4b 0.83 → 1.00
문장 유사도 · 높을수록 반복 응답이 비슷함

○ 벤치 기본 설정 ● 온도 0 · 축 0–1

gemini-2.5-flash 0.39 → 0.74
gemma4:12b 0.58 → 0.86
gemma4:e4b 0.40 → 0.82

비교 조건: 이전 값은 로컬 온도 0.3 / Gemini 기본값입니다. 운영 로컬 기본 온도 대비 개선 폭은 측정하지 않았고, 같은 변경에 loan_rate 예시값 제거도 포함돼 온도만의 효과로 볼 수 없습니다.

결론 일치 1.00은 반복 회차의 (완주·판정 모순 없음·지어내기 여부)가 같다는 뜻입니다. 정답률이나 본문 전체의 동일성을 뜻하지 않으며, 온도 0도 글자까지 같은 응답을 보장하지 않습니다.

온도 0 상세: 설정·지표 정의·전체 수치·블라인드 품질 비교·해석
원인
  • 운영 리포트는 온도를 지정하지 않았다(Gemini 기본 약 1.0, 로컬 모델은 Ollama 기본값).
  • 벤치는 로컬만 0.3이었고, “운영과 같게”라는 주석은 틀렸다. LLM 평가 스펙에도 “리포트 0.3(현행과 같게)”로 적혀 있었는데 이 역시 사실과 달랐다.
  • v0.67.0에서 운영·벤치 모두 REPORT_TEMPERATURE=0.0, REPORT_SEED=42(apps/agent/domain/services/report_sampling.py) 단일 원천으로 바꿨다. 같은 커밋에서 도구 명세의 loan_rate 예시값(0.0405)을 지웠다.
  • 재측정은 후보 3개(gemini-2.5-flash, gemma4:12b, gemma4:e4b)만, 고정 사실 12건 × 3회.
일관성 지표

같은 모델·같은 시나리오의 3회 반복끼리 비교한다. 1.00이면 완전히 같다.

  • 결론 일치: 회차 간 (완주, 판정 모순 없음, 지어내기 여부)가 모두 같은 시나리오 비율.
  • 숫자 일치(Jaccard): 회차별 본문 숫자 집합의 겹침.
  • 문장 유사도: 화면 본문끼리의 문자열 유사도(SequenceMatcher).
  • 대안 등급 일치: 대안 절 등급별 항목 수까지 비교(다중집합). 두 회차 모두 대안 등급 줄이 없으면 일치로 세서 값이 조금 부풀 수 있다.
모델 결론 일치 숫자 일치(Jaccard) 문장 유사도 대안 등급 일치
gemini-2.5-flash 0.75 → 1.00 0.42 → 0.71 0.39 → 0.74 0.75 → 0.94
gemma4:12b 1.00 → 1.00 0.62 → 0.84 0.58 → 0.86 0.44 → 0.78
gemma4:e4b 0.83 → 1.00 0.34 → 0.79 0.40 → 0.82 0.22 → 0.72
  • 왼쪽은 가드 재평가(벤치 설정: 로컬 0.3 · Gemini 기본값), 오른쪽은 온도 0이다.
  • 운영 로컬 폴백은 그동안 Ollama 기본 온도로 돌았다. 운영 기준의 실제 개선 폭은 재지 않았다. 로컬 행은 0.3 대비라 운영 기준보다 작게 잡혔을 수 있다.
자동 지표
모델 완주 판정 모순 없음 지어내기 첫 글자 p50/p95(ms)
gemini-2.5-flash 0.94 → 1.00 1.00 → 1.00 0.056 → 0.00 1,679/2,114 → 1,664/8,679*
gemma4:12b 1.00 → 1.00 1.00 → 1.00 0.00 → 0.00 –/9,606 → –/9,489
gemma4:e4b 1.00 → 1.00 1.00 → 1.00 0.056 → 0.00 –/12,694 → –/7,099

* Gemini p95 상승은 2회차 4건의 API 지연(5.9~9.6초)이다. 중앙값은 같아 온도와 무관한 네트워크 변동으로 본다.

섞은 묶음 블라인드 품질 비교

기본 온도 회차와 온도 0 회차를 한 판정 묶음에 섞어 블라인드로 판정했다(시나리오당 6개 리포트, 같은 판정 세션). 판정 세션이 달라서 생기는 잡음을 없애려는 것이다.

모델 충실도 기본→0 차이 [95% 구간] 자연스러움 기본→0 차이 [95% 구간]
gemini-2.5-flash 3.50 → 3.25 −0.25 [−0.83, +0.42] 3.17 → 3.17 +0.00 [−0.42, +0.42]
gemma4:12b 2.25 → 2.33 +0.08 [−0.33, +0.50] 3.42 → 3.50 +0.08 [−0.25, +0.42]
gemma4:e4b 2.00 → 1.75 −0.25 [−0.58, +0.08] 2.83 → 2.83 +0.00 [−0.33, +0.33]
해석
  • 세 모델 모두 구간이 0을 포함한다. 유의한 품질 차이는 관측되지 않았다.
  • n=12라 작은 차이는 못 잡는다. e4b 충실도는 −0.25, 하한 −0.58로 경계에 가깝다.
  • 같은 회차에 loan_rate 예시값 제거가 함께 들어가 있어 온도만의 효과로 볼 수는 없다. 영향은 s11·s12 금리 문장에 한정된다.
  • 일관성은 크게 올랐다.
  • Gemini는 온도 0에서도 판정 절에 등급 이름을 36건 중 15건 썼다. 모순은 아니지만 프롬프트 준수가 부분적이다.
  • 온도 0이어도 완전히 같지는 않다(Ollama·Gemini 모두 결정적이지 않다). 대안 등급이 회차마다 다르게 적히는 경우가 12b 22%, e4b 28% 남았다.
  • 같은 질문에 글자까지 같은 답은 캐시(의도 관문 칸 + 사실 기준월 키)로만 보장된다.

이 단계의 결론

  • 가드로 gemma4:12b의 지어내기(0.39→0.00)와 e4b의 판정 모순은 줄었지만, 다른 로컬 모델은 오히려 나빠진 지표가 있었고 12b·e4b도 규칙 위반과 첫 글자 지연이 남았습니다. 프롬프트로 지켜지지 않는 규칙(신뢰 태그 174~180/180 누락)도 확인했습니다.
  • 그래서 LLM이 글로 옮기다 틀리는 값(판정·수치·근거)을 아예 코드가 쓰게 바꿨습니다(v0.68.0). 온도 0·seed 42는 지금도 Gemini·로컬 경로의 기본값입니다(Opus는 온도를 받지 않음).

의도 관문 로컬 후보

같은 80건에서 로컬 후보는 모두 비워야 할 칸을 채웠습니다(missing·out_of_scope 26건 기준).

관문 지어내기 비율 · 낮을수록 좋음

축 0–100% · 점선은 허용 상한 5% · 숫자는 지어내기 비율

gemma4:12b 7.7%✕ 기준 초과
gemma4:e4b 30.8%✕ 기준 초과
kanana1.5:8b-q4km 65.4%✕ 기준 초과
qwen3.5:9b 19.2%✕ 기준 초과
qwen3.5:4b 30.8%✕ 기준 초과
qwen3.5:2b-q4_K_M 57.7%✕ 기준 초과
gemini-2.5-flash 0.0%✓ 기준 충족

12b가 지어낸 2건은 모두 서울 밖 지명을 서울 동으로 바꾼 경우였습니다.

7-2. 해석 개선 전체 기록(넣지 않은 것 포함)

아래 수치는 각 단계의 해석 핵심 오류 건수입니다. 운영 두 모델을 같은 116건에서 다시 돌리고 opus 판정자가 블라인드로 판정했으며, 판정자 변동은 약 ±3건입니다. 기본 모델(3.8)의 오류가 늘면 미적용이 원칙입니다. 미적용 단계 다음은 직전 적용 단계를 기준선으로 다시 쟀습니다(9·10·11단계의 기준선은 8단계).

단계 변경 3.8 일반 Opus 결정
4 해석 말투 규칙 8 → 4 5 → 4 적용
5 한국어 윤문 규칙 4 → 10 (축소판 12) 4 → 2 (축소판 4) 미적용
6 시간대 매출 자료 없음을 사실 문장으로 명시 4 → 7 4 → 5 미적용
7 동 이름은 본문 표기 그대로 4 → 3 4 → 5 적용
8 매출 중앙값 비교·시간대 가드·판정 신호 구분 3 → 4 5 → 1 적용
9 상권변화지표 뜻풀이·시간대 낱말 가드 4 → 5 1 → 5 미적용
10 시간대 자료가 없으면 사람 흐름을 해석 입력에서 제거 4 → 6 1 → 6 미적용
11 뉴스·상권 축소 신호 제거 4 → 9 1 → 4 이용조건에 따라 적용
12 조건 절에 지역 사건 연결 9 → 3 4 → 2 적용
13 판정 근거 약함 표시 + 조기 폐업 오독 가드 3 → 5 2 → 4 근거 약함만 적용, 가드 미적용

13단계는 두 변경을 함께 시험한 결과입니다. 5/116·4/116을 가드를 제외한 최종 운영판의 오류율로 읽으면 안 됩니다. 적용분만으로 잰 마지막 값은 12단계(v0.86.0)의 3.8 3/116·Opus 2/116이며, 현재 운영판(v0.87.0, 판정 근거 약함만 적용)을 단독으로 잰 값은 없습니다. 7개 업종의 판정 근거 약함 표시는 제품 결정으로 적용했지만, 조기 폐업 가드는 올바른 근거 문장까지 지워 적용하지 않았습니다.

윤문 규칙·뜻풀이·사실 문장 추가(5·6·9단계)와 입력 빼기(10단계)에서는 3.8이 그 글을 재료로 추론을 덧붙여 오류가 늘었습니다. 지역 사건 줄(12단계)은 오류를 늘리지 않았습니다. 효과가 난 것은 코드가 쓰는 사실 문장의 등급 낱말과 코드 가드, 사람 검수로 확인한 말투·표기 변경이었습니다. 시간대 추정·신호 사이 인과·조기 폐업 오독은 남은 한계입니다.

1~13단계의 전체 비교 조건·오류 사례·결정

코드 우선 구조(v0.68.0~)에서 LLM은 리포트 맨 위 해석 한 단락만 쓴다. 외부 API 후보를 같은 150건 평가셋으로 비교했다. 코드는 v0.71.2(폐업률·점포 수 해마다), 판정은 opus 블라인드(기준표 data/eval/report_answer_rubric.md v2), 자료 부족 34건은 LLM을 부르지 않아 제외했다.

1단계 — 표본 20건으로 Claude 모델 고르기

모델 요청 설정 핵심 오류 건당 비용(추정) p50 / p95
claude-haiku-4-5 온도 0 10/20 $0.0045 3.4 / 4.4초
claude-sonnet-5-5 생각 끔(between_tools) 4/20 $0.0103 4.4 / 5.4초
claude-opus-5-5 effort low(생각을 끌 수 없다) 2/20 $0.0222 5.7 / 9.1초
gemini-2.5-flash 생각 끔·온도 0 2/19 $0.0010 4.0 / 4.3초

2단계 — 전체 116건, 같은 묶음에 세 해석

모델 핵심 오류 95% 구간 p50 / p95 건당 비용(추정)
claude-opus-5-5 2/116 (1.7%) 0.5%~6.1% 5.7 / 8.6초 $0.0217
gemini-2.5-flash 19/115 (16.5%) 10.8%~24.4% 4.0 / 4.5초 $0.0010
gemma4:12b(로컬) 35/116 (30.2%) 22.6%~39.1% 3.7 / 4.6초 —
  • 짝 비교(115건): Opus만 오류 2건, Gemini만 오류 19건. 결정: 운영 1차를 Opus로(v0.73.0, §9).
  • 비용은 usage × 공시 단가 추정(Opus $4/$20, Gemini 2.5 Flash $0.30/$2.50, 1M 토큰당). Opus는 Gemini의 약 22배다.

3단계 — Gemini 3.8 Flash 일반·추론 모드 (같은 116건, 한 묶음에 네 해석)

모델 핵심 오류 95% 구간 p50 / p95 건당 비용(추정)
claude-opus-5-5 5/116 (4.3%) 1.9%~9.7% 5.7 / 8.6초 $0.0217
gemini-3.8-flash 일반(사전 추론 끔) 8/116 (6.9%) 3.5%~13.0% 4.1 / 5.5초 $0.0022
gemini-3.8-flash 추론(사전 추론 켬) 5/116 (4.3%) 1.9%~9.7% 8.4 / 12.0초 $0.0022 + 추론 토큰(미기록)
gemini-2.5-flash 19/115 (16.5%) 10.8%~24.4% 4.0 / 4.5초 $0.0010
  • 짝 비교: 3.8 일반 vs 2.5 — 3.8만 오류 8, 2.5만 오류 19. 3.8 일반 vs 오퍼스 — 3.8만 8, 오퍼스만 5(구간 겹침). 3.8 추론 vs 오퍼스 — 5 대 5.
  • 숫자 가드가 지운 문장: 3.8 일반·추론 0 · 오퍼스 4 · 2.5 26 — 3.8은 숫자 금지 규칙을 지킨다.
  • 같은 오퍼스가 2단계(묶음당 3개)에선 2건, 여기(4개)선 5건 — 판정 묶음 구성에 따라 ±3건쯤 흔들린다.
  • 남은 오류 유형(세 모델 공통): 시간대 자료가 부족한데 업종 일반 특성으로 메움(e022·e028·e029·e075), 등급 낱말 한 단계 과장(“낮은 편”→”매우 낮은”, e013·e073).
  • 결정(사용자, v0.75.0): 1차 gemini-3.8-flash 일반 모드 → 폴백 claude-opus-5-5 → 로컬 gemma4:12b. 오류율의 95% 구간이 오퍼스와 겹치고, 당시 벤치 비용은 약 1/10이며 더 빠르다. 구간 겹침은 성능 동등성이 입증됐다는 뜻이 아니다. 추론 모드는 핵심 오류 5/116으로 오퍼스와 건수가 같지만 가장 느려(p95 12초) 쓰지 않는다.
  • 단가(확인 2026-10-06, https://ai.google.dev/gemini-api/docs/pricing): 3.8 Flash 입력 $0.75 · 출력 $3.75(추론 토큰 포함, 1M당). 벤치 사용량 기록에 추론 토큰이 빠져 있어 추론 모드 비용은 하한이다.

4단계 — 해석 말투 규칙(v0.76.0) 전후, 운영 두 모델

사람 검수 4차에서 “답변이 사용자에게 친절하지 않다”는 의견이 나와 [말투] 규칙(중고등학생 눈높이, 전문 용어 풀어 쓰기, 짧은 문장, 유치한 표현 금지)을 넣고 같은 116건을 다시 쟀다(태그 persona150, 묶음당 두 해석).

모델 핵심 오류 전 → 후 평균 길이 문장 평균 길이 p95
gemini-3.8-flash 일반 8 (6.9%) → 4 (3.4%) 301 → 255자 60 → 51자 5.5 → 5.9초
claude-opus-5-5 5 (4.3%) → 4 (3.4%) 382 → 315자 57 → 45자 8.6 → 7.4초
  • 짝 비교: 3.8은 전에만 오류 7 · 후에만 3, 오퍼스는 4 · 3. 쉽게 쓰라고 해도 사실 오류가 늘지 않았다.
  • 오퍼스는 “즉 ~라는 뜻입니다”로 풀어 쓴 해석이 8 → 93건, 3.8은 용어 앞에서 뜻을 먼저 풀고 용어를 붙이는 식(“문 닫는 곳이 훨씬 많은 순유출 상태”)이다.
  • 남은 오류: 시간대 자료 부족을 업종 일반론으로 메움(e066·e084·e114), 본문에 없는 평가(“안정적”, “매출 수준이 낮다”).

5단계 — 한국어 윤문 규칙(im-not-ai quick-rules 발췌) 시험, 미적용

[말투] 위에 [문장 다듬기] 규칙(번역투·AI 관용구·같은 완곡 표현 반복·문두 접속사·형식명사 끝맺음)을 더해 같은 116건을 쟀다(태그 polish150, 브랜치 feat/answer-polish v0.77.0, 미머지).

모델 핵심 오류 말투만 → +윤문 짝 비교(말투만에만 / +윤문에만) 문두 접속사
gemini-3.8-flash 일반(기본) 4 (3.4%) → 10 (8.6%) 4 / 10 72 → 41
claude-opus-5-5 4 (3.4%) → 2 (1.7%) 4 / 2 20 → 4
  • 문장은 깔끔해졌지만 기본 모델(3.8)의 사실 오류가 늘었다 — 새로 생긴 오류는 본문에 없는 평가·추정을 단정한 것(“점포 평균 매출 수준도 높지 않다”, “점심 장사에 어울립니다”, “카드 결제 외 매출이 많아”를 가능성 아닌 사실로). 완곡 표현·접속사를 줄이라는 규칙이 3.8을 단정 쪽으로 민 것으로 보인다.
  • 오퍼스는 오히려 줄었다(4 → 2). 같은 규칙이 모델에 따라 반대로 작용했다.
  • 단정 쪽으로 민다고 본 두 규칙(완곡 표현 반복·문두 접속사)을 빼고 번역투·AI 관용구·형식명사 끝맺음만 남겨 다시 쟀다(태그 polish2-150): 3.8 12/116 (10.3%)(짝 비교 말투만에만 3 · 줄인 윤문에만 11), 오퍼스 4/116(4 · 4). 줄여도 3.8 오류가 줄지 않았다 — 새 오류는 대부분 “시간대 매출 자료 부족인데 유동인구로 매출·장사 시간을 추정”과 “본문에 없는 평가(평균 매출이 높지 않다)”였다. 규칙 내용보다 지시문이 길어지는 것 자체가 3.8의 근거 지키기를 흐리게 하는 것으로 보인다.
  • 결정: 두 번 모두 기본 모델 오류가 늘어 운영에 넣지 않았다(말투 규칙 v0.76.0까지만 운영). 번역투·AI 관용구는 말투 규칙만으로도 이미 0건이다. 브랜치 feat/answer-polish는 기록으로 남기고 머지하지 않는다.
  • 모델별 지시문(Gemini는 말투만, 오퍼스는 말투+윤문)도 검토했으나 넣지 않았다(사용자 결정 2026-10-06) — 오퍼스는 폴백이라 실제로 쓰는 리포트가 1% 안팎(운영 기록 약 130건 중 폴백 1건)이고, 오퍼스 4 → 2건 개선은 판정 오차(±3건) 안이다. 오퍼스 사용이 늘거나 반복 측정으로 개선이 확인되면 다시 본다.

6단계 — 시간대 매출 자료 없음을 코드 문장으로 명시, 미적용

남은 오류 중 가장 많은 “시간대 매출 자료가 없는데 유동인구로 매출·장사 시간을 추정”을 지시문이 아니라 코드가 쓰는 사실 문장으로 막아 봤다(태그 hours150, 브랜치 feat/hour-gap-missing, 미머지). 시간대 자료 부족 줄 끝에 “이 업종이 어느 시간대에 매출을 내는지는 알 수 없습니다”, 사람 흐름 줄에 “(동 전체 유동인구, 업종 매출과 다름)”.

모델 핵심 오류 말투만(운영) → +시간대 명시 그중 시간대 관련 짝 비교(전에만 / 후에만)
gemini-3.8-flash 일반 4 → 7 3 → 2 4 / 7
claude-opus-5-5 4 → 5 2 → 4 3 / 4
  • 시간대 관련 오류가 줄지 않았다. 오퍼스는 “자료 없음”을 읽고도 “술집은 밤 장사”처럼 업종 상식으로 메웠다 — 사실 문장으로는 업종 일반론을 막지 못한다.
  • 결정: 오류가 늘어 운영에 넣지 않았다.
  • 부수 발견: 숫자 금지 규칙 때문에 동 이름 속 숫자를 한글로 풀어 쓴다(“이태원제일동”, “답십리제두동”) — 3.8은 매 회차 116건 중 약 11건. 대부분 뜻은 통하지만 “제두동”처럼 없는 지명이 되면 오류로 잡힌다. 숫자 가드는 이미 동 이름을 검사에서 빼므로(v0.68.0) 지시문에서 “동 이름은 본문 표기 그대로”를 허용하는 것이 다음 후보다.

7단계 — 동 이름은 본문 표기 그대로(v0.76.1, 적용)

6단계에서 찾은 “숫자 금지 때문에 동 이름을 한글로 풀어 씀”을 고쳤다 — 숫자 금지 규칙에 “동 이름은 본문에 적힌 그대로 쓴다(예: 역삼1동)” 예외 한 줄(태그 dong150).

모델 동 이름 한글 풀이 숫자 가드가 지운 문장 핵심 오류 말투만 → +예외 짝 비교(전에만 / 후에만)
gemini-3.8-flash 일반 11 → 0 0 → 0 4 → 3 3 / 2
claude-opus-5-5 4 → 0 6 → 4 4 → 5 4 / 5
  • 목표(없는 지명 방지)를 이뤘고 기본 모델 오류가 늘지 않아 운영에 넣었다(main 머지·8200 재빌드).
  • 남은 오류: 본문에 없는 평가(“평균 매출이 낮은 편”), 시간대 자료 부족을 동 흐름으로 메움, “경고 없음”을 자료 공백 탓으로 돌림.

8단계 — 남은 오류 3유형을 코드로 막기(v0.78.0)

7단계 뒤 남은 오류를 유형별로 지시문이 아니라 코드(사실 문장·가드)로 막았다(태그 fix150). 평가셋 facts 116건에는 매출 근거의 서울 중앙값만 다시 채웠다(freeze --augment, 다른 값 변화 없음).

유형 고친 방식
본문에 없는 매출 평가(“평균 매출이 낮은 편”) 매출 줄에 서울 같은 업종 동 중앙값과 견준 등급을 코드가 붙임
시간대 매출 자료가 없는데 사람 흐름으로 매출 시간 추정 자료가 없으면 시간대 낱말+매출·장사 문장을 지우는 가드(모른다고 밝힌 문장은 남김)
“경고 없음”을 자료 공백 탓으로 설명 판정 줄을 켜짐 / 계산했지만 기준 안 넘음(이름) / 자료 부족(이름)으로 나눔
모델 핵심 오류 7단계 → 8단계 짝 비교(전에만 / 후에만) 가드가 지운 문장
gemini-3.8-flash 일반 3 → 4 3 / 4 5
claude-opus-5-5 5 → 1 5 / 1 4
  • 7단계 3.8 오류 3건 중 매출 평가 2건(e064·e100)은 사라졌다. 8단계 3.8 오류 4건은 시간대 이름을 바꿔 옮김(e038, 매출 낱말이 없어 가드 밖), 상권변화지표 반대로 읽음, 없는 자료를 추정, 본문에 없는 판단 — 겨냥한 세 유형은 0건이다. +1은 판정 오차(±3) 안이다.
  • 해석 속 “경고 없음… 자료가 비어서” 인과 표현(키워드 집계): 3.8 3 → 1, 오퍼스 6 → 1.

9단계 — 상권변화지표 쉬운 뜻·본문에 없는 시간대 낱말 가드, 미적용

8단계 뒤 남은 오류 중 “상권확장을 침체로 읽음”(e082)과 “밤을 저녁·주말로 바꿔 옮김”(e038)을 코드로 막아 봤다(태그 fix2-150, 브랜치 feat/answer-fixes-2, 미머지). 상권변화지표 이름 뒤에 쉬운 뜻(예: “정체(영업 중·폐업 점포 모두 서울보다 오래 영업 — 오래된 가게 위주로 변화가 적은 쪽)”)을 붙이고, 해석에 본문에 없는 시간대 낱말(저녁·점심·퇴근 등)이 나오면 그 문장을 지웠다.

모델 핵심 오류 8단계 → 9단계 짝 비교(전에만 / 후에만)
gemini-3.8-flash 일반 4 → 5 4 / 5
claude-opus-5-5 1 → 5 1 / 5
  • 쉬운 뜻이 새 오류를 낳았다: “오래된 가게 위주”를 읽고 “상권이 굳어 새로 들어가기 어렵다”를 덧붙였다(3.8 e001·e016). 뜻풀이도 해석의 재료가 된다.
  • 오퍼스 오류 5건 중 4건은 시간대 매출 자료가 없는데 “저녁 손님이 많다”처럼 손님으로 매출 시간을 메운 것 — 본문에 있는 시간대(저녁) 낱말이라 새 가드 밖이고, 8단계 시간대 매출 가드는 “손님”을 넣으면 지나치게 지워 뺐다.
  • 결정: 오류가 늘어 운영에 넣지 않았다. 8단계 오퍼스 1건은 판정 오차 쪽으로 낮게 나온 값으로 본다.

10단계 — 시간대 매출을 모르면 해석 입력에서 사람 흐름 빼기, 미적용

9단계 뒤 가장 많이 남은 오류는 시간대 매출 자료가 없는데 본문의 “사람 흐름: 가장 많은 때 저녁”을 “저녁 손님이 많다”로 옮기는 것이었다. 원인을 없애려고, 시간대 매출 자료가 없을 때 모델에 주는 입력에서만 사람 흐름 구절을 뺐다(화면 본문은 그대로, 태그 flow150, 브랜치 feat/hour-flow-input, 미머지).

모델 핵심 오류 8단계 → 10단계 그중 시간대 관련 짝 비교(전에만 / 후에만)
gemini-3.8-flash 일반 4 → 6 1 → 4 2 / 4
claude-opus-5-5 1 → 6 1 → 4 0 / 5
  • 새 오류 유형이 생겼다: 입력에 사람 흐름이 없으니 “사람이 언제 많은지는 자료가 부족하다”고 썼는데, 화면 본문에는 사람 흐름이 있어 본문과 어긋난다(e038·e082·e104). 모델 입력과 화면이 다르면 그 차이가 오류가 된다.
  • 결정: 오류가 늘어 운영에 넣지 않았다.
  • 시간대 매출 오류에 대해 지금까지 시도한 세 방법 — 사실 문장 추가(6단계), 시간대 낱말 가드(9단계), 입력에서 빼기(10단계) — 모두 오류를 늘렸다. 8단계(v0.78.0)의 시간대 매출 가드(“시간대 낱말 + 매출·장사”)까지가 효과가 확인된 선이다. 남은 “저녁 손님” 유형은 판정 오차 수준(116건 중 1건 안팎)이라 더 손대지 않는다.

11단계 — 뉴스를 본문(해석 입력)에서 빼기·상권 축소 신호 제거(v0.83.0, 이용조건상 필수)

네이버 검색 API 특약(AI 입력 금지)에 따라 리포트 본문에서 뉴스 줄과 유사 사례의 뉴스 건수 문장을 빼고, 해석 지시문의 뉴스 규칙 한 줄도 뺐다. 같은 때 판정 신호 “상권 축소”가 빠져 왜 안 되나 절의 참고 신호 줄도 없어졌다(태그 news150, 브랜치 feat/news-compliance).

모델 핵심 오류 8단계(fix150) → 11단계 짝 비교(전에만 / 후에만)
gemini-3.8-flash 일반 4 → 9 4 / 9
claude-opus-5-5 1 → 4 1 / 4
  • 겹치는 오류 시나리오가 하나도 없다. 해석 글이 크게 바뀌었고(같은 시나리오끼리 유사도 0.4~0.8, 글자까지 같은 것 150건 중 34건 — 대부분 LLM을 안 부르는 자료 부족 시나리오) 판정자 기준도 흔들렸다.
  • 3.8의 9건 중 4건(e024·e045·e050·e111)과 오퍼스 1건(e141)이 “조기 폐업(문 닫은 점포의 영업 기간)을 새로 연 점포의 생존율로 풀이” 유형이다. 8단계 판정자는 같은 유형을 핵심 오류로 보지 않았다(e141 오퍼스 메모). 이 유형을 빼면 3.8 4 → 5, 오퍼스 1 → 3으로 판정 오차(±3) 안이다.
  • 나머지는 본문에 없는 인과(e046·e048 “많아서 조기 폐업”, e039 원인 설명)·시간대 옮김(e015·e077·e078)·자료 부족을 추정으로 메움(e058)이다.
  • 결정: 이용조건상 되돌릴 수 없는 변경이라 적용한다. 조기 폐업 오독은 다음 개선 후보(코드 가드나 본문 정의 문장).

12단계 — 지역 사건 줄을 조건 절에 넣기(v0.86.0, 적용)

조건 절에 “[확인된 사실] ○○동 지역 사건(최근 3년, 서울 열린데이터광장): 2025-08 … (출처: OA-xxxxx)” 줄을 넣었다(정비사업 이주·착공, 대규모점포 개설·폐업, 1,000세대 이상 입주 — 최대 5건, 날짜는 달까지). 평가 facts 150건에 한 번 채웠고 사건이 있는 시나리오는 40건(LLM 판정 대상 116건 중 34건). 태그 events150, 기준선은 11단계 news150.

모델 핵심 오류 11단계 → 12단계 사건 줄 있는 34건 안
gemini-3.8-flash 일반 9 → 3 5 → 3
claude-opus-5-5 4 → 2 1 → 2
  • 해석이 사건을 언급한 건 3.8 3건·오퍼스 5건(34건 중)뿐이고, 그중 오류는 없다. 남은 핵심 오류(e013·e028·e033·e114)는 모두 기존 유형(업종 시간대 자료 부족을 일반론으로 메움, 신호 사이 인과 지어냄, 순유출 기준 미달을 개폐업 수로 단정)이다.
  • 3.8 9 → 3은 판정자 변동이 크다(11단계 오류 시나리오와 겹침 거의 없음). 결론은 “늘지 않았다”까지만 — 기본 모델 오류가 늘지 않아 적용.

13단계 — 판정 근거 약함 표시(v0.87.0, 적용) · 조기 폐업 오독 가드(미적용)

두 가지를 함께 시험했다(태그 weak150b, 기준선 12단계 events150). ① 안정 신호 없는 7개 업종에 비추천을 내지 않고 판정 줄에 “판정 근거 약함” 문장(평가 facts 74건에 반영, 그중 비추천 12건 → 조건부). ② 해석에서 “조기 폐업”을 새로 연 점포의 생존으로 풀이한 문장을 지우는 가드 — 첫판(weak150)은 생존 절벽·조기 폐업을 한 문장에 바르게 푼 문장까지 25개를 지워 “조기 폐업” 앞뒤 구만 보도록 고친 뒤 다시 돌렸다(3.8 5문장·오퍼스 4문장 삭제).

모델 핵심 오류 12단계 → 13단계
gemini-3.8-flash 일반 3 → 5
claude-opus-5-5 2 → 4
  • 3.8의 늘어난 2건: e036은 “판정 근거 약함”을 빼고 위험을 확실하다고 단정(①), e050은 가드가 “저녁 매출이 하루 평균보다 높다”와 오독이 섞인 첫 문장을 통째로 지워 직접 답의 근거가 사라졌다(②). 나머지는 기존 유형(시간대 자료 부족 메움·신호 사이 인과·없는 사실 보탬).
  • 오퍼스 e041은 가드가 못 잡은 조기 폐업 오독이다.
  • 결정: ①은 사용자 제품 결정이라 적용. ②는 문장 단위 삭제가 맞는 근거까지 지우고 판정된 오류도 줄지 않아 미적용(기록 브랜치 exp/early-closure-guard). 조기 폐업 오독은 판정자마다 핵심 오류로 보는 기준이 흔들린다(11·12단계).

한계

  • 판정자도 Claude(opus)다. 같은 계열 해석을 후하게 볼 수 있어 사람 검수(4차)로 확인한다.
  • Gemini 2.5 오류율이 판정 회차마다 흔들린다(묶음당 2개 해석일 때 9.5%, 3개일 때 16.5%). 모델마다 1회 실행이다.
  • 폴백 Opus는 온도를 받지 않는다(effort low). 온도 0·seed 고정은 Gemini·로컬 경로에 해당한다.
  • 원자료: data/eval/results/claude-models-2026-10-06/(3단계는 g38-150/).

7-3. 채택하지 않은 후보 모델

후보 역할 결과 채택하지 않은 이유
claude-opus-5-5 리포트 해석 1차(v0.73.0 → v0.75.0) 2/116 · 5/116(판정 묶음에 따라) 3.8과 오류율 구간이 겹치고 비용 약 10배 → 폴백으로 유지
gemini-3.8-flash 추론 모드 리포트 해석 5/116 p95 12.0초로 가장 느림
claude-sonnet-5-5 · claude-haiku-4-5 리포트 해석(표본 20건) 4/20 · 10/20 Opus(2/20)보다 오류 많음
gemini-2.5-flash 리포트 해석 19/115 (16.5%) 3.8보다 오류 많음
gemini-2.5-flash 의도 관문(10/7까지 운영) 98.8%(10/5) · 95.0%(10/7) 같은 날 3.8 일반보다 랜드마크 변환을 놓침 → v0.88.0에 교체. 더 빠름(p93 2.4초)
gemini-3.8-flash 사전 추론 기본 의도 관문 98.8%, 지어내기 0/26 일반 모드와 정확도 같고 더 느림(p93 5.3초)
gemini-embedding-001·2 (6조합) RAG 임베딩 최고 MRR 0.960 기준선보다 유의하게 좋지 않고 외부 의존·비용 발생
qwen3-embedding-4b RAG 임베딩(당시 운영) MRR 0.935 bge-m3와 동률, CPU 재색인 약 5.7시간

8. 평가하지 못한 것과 한계

질문 결과 비고
로컬 모델만으로 운영할 수 있나 평가함 — 불가 리포트·관문 로컬 6개 모두 게이트 탈락(10/5), 코드 우선 구조에서도 gemma4:12b 해석 핵심 오류 35/116
외부 API 중 무엇을 1차로 평가함 — 3.8 일반 Opus와 구간 겹침, 비용 약 1/10. 동등성 입증은 아님
해석 개선이 실제로 효과가 있나 단계마다 평가함 116건 재평가 4~13단계, 판정자 변동 ±3건
의도 관문 모델 평가함 — 3.8 일반 모드로 교체 같은 날 비교에서 3.8 98.8% 대 2.5 95.0%. 다만 80건 한 묶음이라 차이 구간이 0을 포함함
지금 운영판(v0.87.0) 단독 오류율 재지 않음 13단계는 적용·미적용 변경을 함께 잼. 적용분 마지막 값은 12단계
10/5 리포트 품질·가드·온도 0을 3.8로 해당 없음 옛 구조(LLM이 6개 절 작성)는 폐기. 3.8은 현행 구조로 평가
더 큰 로컬 모델·미세조정·증류 할 수 없었음 16GB 한 장에 임베딩과 함께 올라가는 12b급이 상한. 27~32B급은 4비트로도 16GB 초과(추정), 학습은 VRAM이 더 필요
도구 호출 능력 측정 안 됨 10/5 252회 실행 전부 도구 호출 0건. 지금 구조는 도구를 쓰지 않음
CPU 동시 부하 측정 안 함 임베딩 CPU 단독 지연만 잼
판정자 편향 사람 검수로 방향만 확인 판정자가 Claude(opus)라 Opus 해석을 후하게 볼 수 있음

주요 한계: 해석 평가는 150건 중 LLM을 호출한 116건, 10/5 리포트 평가는 12시나리오입니다. 판정자도 LLM(Claude opus)이라 같은 계열인 Opus 해석을 후하게 볼 수 있고, 판정 묶음에 따라 오류 건수가 ±3건 흔들리며, 모델마다 1회 실행입니다. 지금 운영판(v0.87.0)만 따로 잰 오류율은 없습니다. CPU 동시 부하와 도구 호출 능력은 검증되지 않았습니다.

임베딩·LLM 평가의 전체 한계

임베딩:

  • 기존 base 179건은 qwen 운영 시절에 검수돼 qwen 쪽으로 기울었을 수 있다. 10/4 재검수에서 질문 16건을 바꿨지만 정답 판정의 출발점은 같다.
  • 만료 공고를 코퍼스에 남겼다(운영 검색은 뺀다). 모든 조합에 같은 방해 문서로 작용한다.
  • 지연은 모델 단위로 쟀다(같은 모델의 차원별 지연은 같다고 본다).
  • 정답이 여럿인 뉴스 행의 nDCG@10은 낮게 나온다. 같은 사건 기사를 하나로 접는데, 이상적 DCG는 관련 기사가 최대 10건 보인다고 가정하기 때문이다. 그래서 nDCG@10은 보조 지표다.
  • gemini-embedding-001은 가격표에 없어 색인 비용을 계산하지 못했다.
  • CPU 측정은 일회성 스크립트다. 백엔드·LLM과 CPU를 나눠 쓸 때의 동시 부하는 재지 않았다.

LLM:

  • 품질 판정자도 LLM이다. 모델명은 가렸지만 문체로 짐작할 수 있다.
  • 리포트 시나리오가 12건이라 표본이 작다. 참고 순위의 bootstrap 구간이 넓은 것도 그래서다.
  • 지어내기 비율은 하한이다. 대조를 관대하게 했다(프롬프트·도구 설명 숫자도 근거로 인정, 복합 금액 허용폭이 넓음 — 예: “1억 2천만”이 1.25억과도 맞음). 반대로 개월→년 환산 같은 오탐도 일부 있다.
  • 252회 실행(7개 모델 × 12 시나리오 × 3회) 전부에서 도구 호출이 0건이었다. s11·s12(규칙·도구 시나리오)도 도구를 쓰지 않았다. EXAONE의 도구 없음 불리함과 도구 결과 근거 대조는 시험되지 않았다.
  • 가드 전후 품질은 판정 세션이 달라 ±0.5 안쪽 차이를 판정자 잡음과 구분할 수 없다(참고치).
  • 가드 후 첫 글자 p95는 판정 절 버퍼링 시간을 포함해 기준선과 비교할 수 없다.
  • 온도 0 비교의 기준선은 운영 설정(기본 온도)이 아니라 벤치 설정(로컬 0.3)이다. 운영 기준 개선 폭은 재지 않았다.
  • 온도 0 회차에는 loan_rate 예시값 제거가 섞여 있어 온도 효과만 분리할 수 없다.
  • 대안 등급 일치는 두 회차 모두 대안 등급 줄이 없으면 일치로 세서 조금 부풀 수 있다.
  • e4b의 VRAM은 size_vram(3,158 MiB)보다 실제 점유(nvidia-smi 차이 4,871 MiB)가 크다.
  • kanana1.5 라이선스는 모델 카드로만 확인했다. 실제로 쓰기 전에 원문 LICENSE 파일을 확인해야 한다.

9. 운영 반영 이력

  1. v0.65.0

    운영 임베딩 qwen3@1536 → bge-m3@1024 전환, 8,905건 재색인 101초

  2. v0.65.1

    컨테이너가 127.0.0.1:11434로 자기 자신을 가리키던 문제 — OLLAMA_BASE_URL=http://host.docker.internal:11434로 호스트 Ollama 접속

  3. v0.66.1

    운영 로컬 폴백·운영 점검 프로브에 num_ctx 32,768 — 입력 2,051 → 19,228토큰

  4. v0.67.0

    리포트 코드 가드 4종, 온도 0·seed 42 단일 원천, loan_rate 예시값 제거

  5. v0.67.1

    컨테이너에 backend/.env 키 주입(env_file, required: false) — 8200 컨테이너가 Gemini 키 없이 로컬 12b 단독으로 쓰던 리포트 129초 → 8초

  6. v0.68.0~v0.71.2

    판정·수치·직접 답·근거는 코드가 쓰고, LLM은 해석 한 단락만 작성. 질문 유형별 직접 답과 위험 등급 표기 반영

  7. v0.73.0

    리포트 해석 1차를 claude-opus-5-5로 변경. 이후 같은 평가셋에 Gemini 3.8 Flash를 추가 비교

  8. v0.75.0

    1차 gemini-3.8-flash 일반 → 폴백 claude-opus-5-5 → gemma4:12b. 해석 가드 재시도는 Opus, 실패 시 로컬

  9. v0.76.0~v0.78.0

    해석 말투·동 이름 표기, 매출 중앙값 비교·시간대 매출 가드·판정 신호 구분 반영

  10. v0.83.0~v0.86.0

    이용조건에 따라 뉴스·상권 축소 신호를 해석 입력에서 제거하고, 지역 사건을 조건 절에 연결

  11. v0.87.0

    안정적인 경고 신호가 없는 7개 업종은 판정 근거 약함을 표시하고 최대 조건부. 함께 시험한 조기 폐업 오독 가드는 미적용

  12. v0.88.0

    의도 관문 LLM을 gemini-2.5-flash → gemini-3.8-flash 일반 모드(사전 추론 끔)로 교체

  • v0.67.1 이전 8200 컨테이너는 줄곧 로컬 gemma4:12b 단독으로 리포트를 썼다(1건 약 2분). 구글 로그인 버튼도 숨겨져 있었다.

10. 다음 단계

  • 남은 해석 오류 — 조기 폐업을 새 점포의 생존으로 풀이하는 오류, 시간대 자료 부족을 업종 일반론으로 메우는 오류, 경고 없음을 긍정으로 읽는 해석. 조기 폐업 문장 삭제 가드는 맞는 근거까지 지워 넣지 않았다.
  • 의도 관문 — 3.8 일반 모드로 바꿨지만(v0.88.0) 관문 평가는 80건 한 묶음이라 정확도 차이 4%p 안쪽은 가려내지 못한다 — 누락·범위 밖 문항을 늘리고, 실제 사용자 문장 중 LLM까지 간 비율과 결과를 기록하면 더 확실히 고를 수 있다. 관문 로컬 후보는 서울 밖 지명(분당 정자동·하남 미사)을 서울 동으로 바꾸는 문제를 고친 뒤 다시 잰다.
  • 사람 검수 분량 — 20건 × 2는 끝까지 기록되지 않았다(5차 2건). 10건 이하로 줄인다.
  • 온프레미스가 필요해지면 — GPU 증설(더 큰 VRAM)이나 별도 추론 서버가 먼저다. 그다음 캐시·증류를 검토한다.
  • API 임베딩 경로를 쓰게 되면 gemini-embedding-2@1024를 검토한다(001 단종 일정).

11. 원자료 위치

평가 결과·설계·코드·개정 이력 경로
내용 경로
임베딩 평가 결과 data/eval/results/embedding-benchmark-2026-10-04/ (report.md, results.json, corpus.jsonl.sha256)
LLM 평가 결과(가드 전) data/eval/results/llm-benchmark-2026-10-05/ (report.md, notes.md, results.json)
가드 후 재평가·온도 0 data/eval/results/llm-benchmark-2026-10-05-guards/ (report.md, notes.md, results.json, temp0/)
판정자 기준표 data/eval/report_judge_rubric.md
리포트 고정 facts data/eval/report_facts/<id>.json
평가셋 data/eval/rag_evalset.jsonl, data/eval/intent_evalset.jsonl, data/eval/report_scenarios.jsonl
임베딩 평가 설계 docs/superpowers/specs/2026-10-04-embedding-benchmark-design.md
LLM 평가 설계 docs/superpowers/specs/2026-10-04-llm-benchmark-design.md
코드 가드·샘플링 backend/apps/agent/domain/services/report_guards.py, backend/apps/agent/domain/services/report_sampling.py
개정 이력 backend/docs/backend_ver_log.md
외부 API 해석 비교·반복 개선 data/eval/results/claude-models-2026-10-06/ (3단계 g38-150/)
해석 판정 기준표 data/eval/report_answer_rubric.md (v2)
사람 검수 4·5차 data/eval/results/claude-models-2026-10-06/human_review_4.json, human_review_5.json
의도 관문 3.8 재측정 data/eval/results/intent-gemini38-2026-10-07/ (report.md, results.json)
정본 문서 구현 저장소 docs/model-evaluation.md (§1~§13)

팀 Beyond Facade — Metabole 창업 경고 서비스 개발 문서. 경고 없음은 성공·안전·추천을 보장하지 않습니다.

창업 경고의 근거와 구현 기록 전체 문서 검증 결과 최종 산출물