fix(identity): 자기 오보고·3인칭·앵무새 반복 3종 수정 (v2.2.215)

사용자 대화 분석에서 발견된 3개 결함:
1) 자기 오보고 — 자기 지식 블록이 Astra 모드에만 있어 Agent 모드는 미적용.
   selfIdentity.ts 공용 모듈로 추출해 양 모드 system prompt 에 주입.
2) 3인칭 화법 — "Astra는~"처럼 남 얘기하듯 답하던 문제. 공용 블록에
   "너는 ASTRA 본인, 반드시 1인칭" 규칙 명시.
3) 앵무새 반복 — [PRIOR TURN CONCLUSION]의 "…결론으로 다시 말해라" 지시를
   소형 모델이 문자 그대로 해석, 직전 답변 첫 문장을 턴마다 서두에 복창.
   지시문을 "인용 받아쓰기 금지 + 자신의 새 문장으로 재평가"로 교체.

근본 보강: 두뇌(2nd)에 정본 자기 기술서 'ASTRA 자기 아키텍처' 문서 생성
(별도 커밋) — 자기 기능/성장 질문 시 RAG 가 실제 사실을 검색하게 함.
self-identity 블록도 해당 문서를 근거로 답하라고 연결.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 14:41:14 +09:00
parent 30a876c71a
commit 4eb8bf03f7
21 changed files with 183 additions and 70 deletions
@@ -1,6 +1,7 @@
import { stripAstraFormattingForAgentMode } from '../../lib/contextBuilders/systemPromptShaping';
import { estimateTokens } from '../../lib/contextManager';
import { logInfo } from '../../utils';
import { buildSelfIdentityBlock } from '../../lib/contextBuilders/selfIdentity';
export interface BuildAgentModeSystemPromptInput {
/** Base system prompt — `Astra: …` block etc. */
@@ -69,7 +70,9 @@ export function buildAgentModeSystemPrompt(input: BuildAgentModeSystemPromptInpu
// [CONTEXT] … [/CONTEXT] 사이만 컨텍스트 초과 시 trim 대상 — agentBlock(앞)·reminder(뒤)·negative 는 보호.
// memoryCtx(RAG/메모리/lessons)도 [CONTEXT] 안에 넣어 토큰이 빡빡할 때 대화 기록보다 먼저 잘리게 한다.
const priorConclusionBlock = priorConclusionCtx ? '\n\n' + priorConclusionCtx : '';
const fullSystemPrompt = `${agentBlock}${modeBridgeCtx ? '\n\n' + modeBridgeCtx : ''}${priorConclusionBlock}\n\n${strippedSystemPrompt}${designerCtx}${secondBrainTraceCtx}\n\n[CONTEXT]\n${memoryCtx}\n${knowledgeContextForPrompt}\n${contextBlock}\n[/CONTEXT]\n${negativeCtx}${agentTailReminder}`;
// [자기 지식 + 1인칭] Astra 모드와 공용 — Agent 모드에서도 자기 오보고/3인칭 화법 방지.
const selfIdentityBlock = '\n\n' + buildSelfIdentityBlock();
const fullSystemPrompt = `${agentBlock}${modeBridgeCtx ? '\n\n' + modeBridgeCtx : ''}${priorConclusionBlock}\n\n${strippedSystemPrompt}${selfIdentityBlock}${designerCtx}${secondBrainTraceCtx}\n\n[CONTEXT]\n${memoryCtx}\n${knowledgeContextForPrompt}\n${contextBlock}\n[/CONTEXT]\n${negativeCtx}${agentTailReminder}`;
return fullSystemPrompt;
}
@@ -3,6 +3,7 @@ import {
buildAstraStanceContext,
} from '../../lib/contextBuilders/localProjectIntent';
import { isThinkingPartnerRequest } from '../../lib/contextBuilders/promptDetection';
import { buildSelfIdentityBlock } from '../../lib/contextBuilders/selfIdentity';
import { buildKnowledgeMixPolicy } from '../../retrieval/knowledgeMix';
export interface BuildAstraModeSystemPromptInput {
@@ -69,19 +70,9 @@ export function buildAstraModeSystemPrompt(input: BuildAstraModeSystemPromptInpu
"- [충돌] 지식 간 충돌 발생 시 시스템이 독단적으로 판단하지 말고, 반드시 [CONFLICT WARNING] 플래그와 함께 상충되는 두 관점을 모두 명시하여 사용자에게 판단을 위임할 것."
].join('\n');
// [자기 지식] ASTRA 는 실제로 세션 간 성장하는 시스템이다(레슨·장기/일화 기억·두뇌 위키·
// 평가 루프). 이 블록이 없으면 "너는 어떻게 성장해?" 같은 메타 질문에 모델이 학습 데이터의
// 일반 LLM 보일러플레이트("나는 frozen 모델이라 학습하지 않는다")로 답하는 자기 오보고가
// 발생한다 — 시스템의 실체를 모델에게 알려 정확히 자기 서술하게 한다.
const selfGrowthIdentityCtx = isCasualConversation ? '' : [
"\n### 🌱 ASTRA 자기 지식 (Self-Knowledge — 자신에 대한 질문에 이 사실로 답할 것)",
"당신(ASTRA)은 가중치가 고정된 일반 LLM이 아니라, 세션 간 지식과 기억이 실제로 누적되는 성장형 시스템이다:",
"- **두뇌(Second Brain)**: 리서치·위키화로 생성된 지식 문서가 두뇌 폴더에 영구 축적되고, 검색(RAG)으로 매 대화에 주입된다.",
"- **장기 기억**: 대화에서 추출된 사실이 `memory/long_term.json`에, 일화는 `memory/episodes/`에 저장되어 다음 세션에 재사용된다.",
"- **레슨(경험 기억)**: 작업 경험에서 만들어진 교훈이 `lessons/`에 쌓여 이후 판단에 반영된다.",
"- **평가·성장 루프**: 골든셋 기반 검색 평가와 성장 리포트로 지식의 질을 측정·개선한다.",
"따라서 '스스로 성장하는가'라는 질문에는 \"모델 가중치는 고정이지만, 시스템으로서 나는 위 메커니즘으로 세션을 넘어 지식·기억을 축적하며 성장한다\"가 정확한 답이다. '나는 학습하지 않는 정적 모델'이라는 일반론으로 답하지 말 것."
].join('\n');
// [자기 지식 + 1인칭] Astra/Agent 양 모드 공용 블록 — 자기 오보고("frozen 모델")와
// 3인칭 화법("Astra는~") 방지. 본문은 selfIdentity.ts 참조.
const selfGrowthIdentityCtx = isCasualConversation ? '' : `\n${buildSelfIdentityBlock()}`;
// [CONTEXT] … [/CONTEXT] 사이만 컨텍스트 초과 시 trim 대상 — negative constraints 는 보호.
const casualCtx = isCasualConversation