feat(retrieval): 청크 검색 기본 켬(+62.5%p recall@1) + 확신도 전역화 (v2.2.218)

P1 — 섹션 청크 검색 기본 활성화:
- 골든셋 24질의 A/B 측정: 파일 단위 → 섹션 청크에서
  recall@1 12.5%→75.0% · recall@3 33.3%→83.3% · recall@5 37.5%→87.5%
  · MRR 0.217→0.802. 18질의 개선·악화 0건.
- Phase 1-가 구현은 완성돼 있었으나 chunkLevelRetrieval 기본값이 false 라
  실전 채팅이 열등한 파일 모드로 동작 — package.json·config 기본값 true 로.
- tests/retrievalEvalCompare.test.ts: 환경변수(ASTRA_EVAL_BRAIN) 게이트형
  A/B 회귀 측정 도구 (평소 skip — CI/패키징 무영향).

P2 — 확신도 전역화 (/meet 원칙을 모든 대화로):
- memoryContext 에 [GROUNDING] 블록 — 두뇌 근거 강도(강/보통/약)를 점수로
  평가해 답변 정책 주입: 약함 → "⚠️ 두뇌 근거 약함" 표기+단정 금지,
  강함 → 근거 문서 제목 인용, 보통 → 사실/추론 구분 서술.

P3 — 회의 용어집 자동화 + 출력 위생:
- /meet 실행마다 담당자 이름·사용자 메타데이터 용어를 .astra/meet_glossary.json
  에 누적, 다음 실행 때 자동 주입 (STT 보정 용어집 — 반복 회의 표기 일관성).
- selfIdentity 블록에 한·영 혼합 깨진 표기 금지 규칙 (전 대화, 무비용).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 18:13:11 +09:00
parent 92c92da090
commit c42c66a3fc
8 changed files with 174 additions and 7 deletions
+31 -1
View File
@@ -377,5 +377,35 @@ export async function buildMemoryContext(deps: MemoryContextDeps): Promise<strin
// 살아남게.
const lessonBlock = buildLessonChecklistBlock(lessonChunks.map((c) => ({ title: c.title, content: c.content })));
const memoryBlock = deps.retrievalOrchestrator.buildContextString(result);
return [lessonBlock, memoryBlock].filter(Boolean).join('\n\n');
// [확신도 전역화] 검색 근거 강도를 평가해 답변 정책을 함께 주입 — /meet 의
// "확신 없으면 단정 대신 표시" 원칙을 모든 대화로 확장. 근거가 약한데 단정적으로
// 답하는 '그럴듯한 오답'을 구조적으로 줄인다.
const groundingBlock = buildGroundingBlock(result);
return [groundingBlock, lessonBlock, memoryBlock].filter(Boolean).join('\n\n');
}
/**
* 검색 결과의 근거 강도 → 답변 정책 블록.
* - strong (top ≥ 0.5, 두뇌 청크 ≥ 2): 두뇌 근거 기반 — 사용한 문서 제목을 인용하라.
* - moderate: 부분 근거 — 두뇌 사실과 일반 지식 추론을 구분해 서술.
* - weak (top < 0.25 또는 두뇌 청크 0): 답변 첫 줄에 "⚠️ 두뇌 근거 약함" 표기 + 단정 금지.
* 점수는 normalize 된 0~1 — 임계값은 초기치이며 골든셋으로 추후 튜닝 가능.
*/
function buildGroundingBlock(result: { selectedChunks: Array<{ source: string; score: number }> }): string {
const brainChunks = result.selectedChunks.filter((c) => c.source === 'brain-trace' || c.source === 'brain-memory');
const top = brainChunks.length ? Math.max(...brainChunks.map((c) => c.score || 0)) : 0;
let level: 'strong' | 'moderate' | 'weak';
if (brainChunks.length === 0 || top < 0.25) level = 'weak';
else if (top >= 0.5 && brainChunks.length >= 2) level = 'strong';
else level = 'moderate';
const lines = [`[GROUNDING] 이번 질의의 두뇌 근거 강도: ${level === 'strong' ? '강함' : level === 'moderate' ? '보통' : '약함'} (두뇌 청크 ${brainChunks.length}개, 최고 점수 ${top.toFixed(2)})`];
if (level === 'weak') {
lines.push('→ 답변 첫 줄에 "⚠️ 두뇌 근거 약함 — 일반 지식 기반 추정입니다." 를 표기하고, 단정 대신 "가능성/추정" 표현을 사용하라. 확실하지 않은 세부 수치·고유명사는 만들지 말 것.');
} else if (level === 'strong') {
lines.push('→ 두뇌 근거를 우선 사용하고, 답변에서 근거로 삼은 문서 제목을 인용하라 (예: "…문서에 따르면").');
} else {
lines.push('→ 두뇌에서 가져온 사실과 일반 지식 추론을 문장 단위로 구분해 서술하라. 두뇌 근거가 없는 주장에는 단정 표현을 피하라.');
}
return lines.join('\n');
}
+1
View File
@@ -22,5 +22,6 @@ export function buildSelfIdentityBlock(): string {
'- **레슨(경험 기억)**: 작업 경험에서 만들어진 교훈이 `lessons/`에 쌓여 이후 판단에 반영된다.',
'- **평가·성장 루프(Self-Evolving OS)**: 골든셋 기반 검색/업무 평가, 성장 리포트, 학습 큐(Need Engine), 지식 노후 점검(Decay), 승인된 학습의 자동 실행(Research Agent)으로 지식의 질을 측정·개선한다.',
'따라서 "스스로 성장하는가"라는 질문에는 "모델 가중치는 고정이지만, 시스템으로서 저는 위 메커니즘으로 세션을 넘어 지식·기억을 축적하며 성장합니다"가 정확한 답이다. "나는 학습하지 않는 정적 모델"이라는 일반론으로 답하지 말 것. 자신의 기능·구조에 대한 상세 질문은 두뇌의 "ASTRA 자기 아키텍처" 문서를 근거로 답하라.',
'[출력 위생] 자연스러운 한국어로 쓰고, 한 단어 안에 한글과 영문 알파벳을 섞지 마라("응다", "텍록", "결ently" 같은 깨진 합성 표기 금지). 외래어·기술 용어는 완전한 한글 표기 또는 완전한 영문 단어 중 하나로 일관되게 쓴다.',
].join('\n');
}