fix(output): 한·영 깨진 토큰("덩ey") 결정론 감지 + 1회 수리 패스 (v2.2.230)
소형 로컬 모델이 한국어 단어 중간에 영문 토큰을 섞는 디코딩 사고
("덩어리"→"덩ey", "결과적으로"→"결ently"). 프롬프트 출력 위생 규칙으로는
못 막음 — 지시 불이행이 아니라 토큰 붕괴라서. 사후 보정으로 해결:
- hangulHygiene.ts: 고정밀 감지 패턴(한글 음절+영문 소문자 2+ 연속) —
"API를"/"Code의"(영문+조사)·"플랜B"(한글+대문자)는 정상 표기로 미감지,
코드 블록 제외. 감지 시 LLM 수리 1회 (깨진 토큰만 복원, 내용 변경 금지).
- 수리 검증 게이트: 길이 ±35% 이내 + 깨진 토큰 감소 — 미통과 시 원문 유지
(수리가 더 망치는 것 방지). 실패 전 과정 로그 (관측성 원칙).
- 적용 경로: 채팅 답변(스트림 후·확정 전) + /wikify 산출물(영구 자산이라
더 중요 — "🩹 표기 오류 N건 교정" 표시).
테스트 11건 (감지 정밀도·검증 게이트·실패 안전).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1092,6 +1092,35 @@ export class AgentExecutor {
|
||||
continuationCount = _cont.continuationCount;
|
||||
if (this.isStaleRun(runId)) return;
|
||||
}
|
||||
// (c2) 한·영 깨진 토큰 수리 — "덩어리"→"덩ey" 류 토큰 붕괴를 결정론 감지
|
||||
// 후 1회 수리 패스로 복원. 검증 미통과 시 원문 유지 (악화 방지).
|
||||
if (loopDepth === 0 && cleaned.visible && !this.abortController?.signal.aborted) {
|
||||
try {
|
||||
const { findBrokenHangulTokens, repairBrokenHangul } = await import('./agent/hangulHygiene');
|
||||
const broken = findBrokenHangulTokens(cleaned.visible);
|
||||
if (broken.length > 0) {
|
||||
this.webview.postMessage({ type: 'autoContinue', value: '표기 오류 교정 중…' });
|
||||
const repaired = await repairBrokenHangul(cleaned.visible, broken, async (system, user, maxTokens) => {
|
||||
const r = await this.callNonStreaming({
|
||||
baseUrl: ollamaUrl, modelName: actualModel, engine,
|
||||
messages: [{ role: 'system', content: system }, { role: 'user', content: user }],
|
||||
temperature: 0.1, maxTokens, contextLength: ctxLimits.contextLength,
|
||||
signal: this.abortController?.signal,
|
||||
});
|
||||
return r.text;
|
||||
});
|
||||
if (repaired) {
|
||||
logInfo('한·영 깨진 토큰 수리 완료.', { broken: broken.slice(0, 5), before: cleaned.visible.length, after: repaired.length });
|
||||
cleaned = { ...cleaned, visible: repaired };
|
||||
} else {
|
||||
logInfo('한·영 깨진 토큰 감지 — 수리 검증 미통과, 원문 유지.', { broken: broken.slice(0, 5) });
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
logError('한글 위생 수리 실패 (원문 유지).', { error: e?.message ?? String(e) });
|
||||
}
|
||||
}
|
||||
|
||||
// 답변 sanitize / policy enforcement → src/agent/handlePrompt/processFinalAnswer.ts
|
||||
const _finalProc = processFinalAnswer({
|
||||
visibleAnswer: cleaned.visible,
|
||||
|
||||
Reference in New Issue
Block a user