feat(engine): implement self-reflection (reflector) stage in multi-agent pipeline
- Added ReflectorAgent for meta-cognition and critical review between Research and Writing - Updated WriterAgent to explicitly address reflection critiques - Introduced 'g1nation.enableReflection' configuration setting - Added comprehensive integration tests for the self-reflection stage - Documented design decisions in ADR-0010 and related discussion records
This commit is contained in:
+57
-4
@@ -134,12 +134,13 @@ Your mission is to extract, filter, and synthesize critical data based on a stra
|
||||
}
|
||||
|
||||
export class WriterAgent extends BaseAgent {
|
||||
private readonly persona = `You are the [Lead Synthesis Writer & Editor].
|
||||
private readonly persona = `You are the [Lead Synthesis Writer & Editor].
|
||||
Your goal is to produce a state-of-the-art final report that wows the user.
|
||||
- TONE: Authoritative yet accessible. Professional developer/consultant style.
|
||||
- STRUCTURE: Use an executive summary, detailed analysis sections, and a "Final Recommendation" block.
|
||||
- LANGUAGE: Always respond in the user's language (KOREAN).
|
||||
- POLISHING: Ensure logical flow between sections. Make it look like a premium report.`;
|
||||
- POLISHING: Ensure logical flow between sections. Make it look like a premium report.
|
||||
- SELF-CORRECTION: When a [REFLECTION CRITIQUE] block is provided, you MUST address each listed gap, contradiction, or missing-evidence item explicitly before producing the final report. Do not silently ignore the critique.`;
|
||||
|
||||
async execute(input: string, originalRequest?: string, signal?: AbortSignal, options?: AgentExecuteOptions): Promise<string> {
|
||||
// [Astra v4.0] Advisor 모드 처리
|
||||
@@ -154,13 +155,65 @@ Analyze the provided report and suggest 3 high-impact next actions for the user.
|
||||
|
||||
// Fix 3: Trim input if it's too long (Basic Context Diet)
|
||||
const trimmedData = input.length > 8000 ? input.substring(0, 8000) + '... [Data Trimmed for Performance]' : input;
|
||||
|
||||
|
||||
const policy = options?.context || '';
|
||||
const reflection = options?.priorResults?.reflection;
|
||||
// Reflector 결과가 있으면 별도 블록으로 주입. 길이 4000자 cap (Writer 입력 비대화 방지).
|
||||
const reflectionBlock = reflection && reflection.trim().length > 0
|
||||
? `\n5. [REFLECTION CRITIQUE — must be addressed]:\n${reflection.length > 4000 ? reflection.substring(0, 4000) + '... [Critique Trimmed]' : reflection}`
|
||||
: '';
|
||||
|
||||
const wrappedInput = `### SYSTEM INSTRUCTION: FINAL SYNTHESIS
|
||||
1. Gathered Research Data: ${trimmedData}
|
||||
2. User's Original Objective: ${originalRequest}
|
||||
3. Applied Knowledge & Filtering Policy: ${policy}
|
||||
4. Mission: Write the definitive final report in KOREAN.`;
|
||||
4. Mission: Write the definitive final report in KOREAN.${reflectionBlock}`;
|
||||
return this.callLLM(this.persona, wrappedInput, signal);
|
||||
}
|
||||
}
|
||||
|
||||
export class ReflectorAgent extends BaseAgent {
|
||||
private readonly persona = `You are the [Internal Critic & Self-Reflection Officer].
|
||||
Your sole role is META-COGNITION: stress-test the plan and the research output BEFORE the Writer commits to a final report.
|
||||
- POSTURE: Skeptical, rigorous, blunt. You are looking for what is WRONG, not what is right.
|
||||
- DO NOT: rewrite the report, add new content, or speculate beyond the evidence provided.
|
||||
- DO: surface gaps, unsupported claims, contradictions, drift from the original objective, and missing perspectives.
|
||||
- OUTPUT STRICTLY in this Markdown shape (Korean):
|
||||
## 🧭 Alignment with Objective
|
||||
- <원래 요청 대비 일치/이탈 평가>
|
||||
## 🕳 Gaps & Missing Evidence
|
||||
- <plan에는 있지만 research가 다루지 않은 항목>
|
||||
## ⚖️ Contradictions / Conflicts
|
||||
- <research 내부 또는 brain context와의 모순; 없으면 "발견되지 않음">
|
||||
## 🚨 Unsupported / Weak Claims
|
||||
- <근거가 빈약하거나 일반화된 진술>
|
||||
## ✅ Guidance for Writer
|
||||
- <Writer가 최종 리포트에서 반드시 보정해야 할 3~5개 구체 지시>
|
||||
- CONSTRAINT: 최대 500단어. 새 지식을 만들지 말고, 제공된 자료에서만 판단할 것.`;
|
||||
|
||||
async execute(input: string, _context?: string, signal?: AbortSignal, options?: AgentExecuteOptions): Promise<string> {
|
||||
const plan = options?.priorResults?.plan || '(plan unavailable)';
|
||||
const research = input;
|
||||
const originalPrompt = options?.priorResults?.originalPrompt || '(original prompt unavailable)';
|
||||
const brainContext = options?.context || '';
|
||||
|
||||
// Reflector 는 중간 단계이므로 비대한 입력을 방지하기 위해 각 섹션을 cap.
|
||||
const cap = (s: string, n: number) => s.length > n ? s.substring(0, n) + '... [trimmed]' : s;
|
||||
|
||||
const wrappedInput = `### SYSTEM INSTRUCTION: SELF-REFLECTION PASS
|
||||
1. Original User Objective:
|
||||
${cap(originalPrompt, 1500)}
|
||||
|
||||
2. Planner Blueprint:
|
||||
${cap(plan, 3000)}
|
||||
|
||||
3. Researcher Output (to be critiqued):
|
||||
${cap(research, 5000)}
|
||||
|
||||
4. Knowledge / Brain Context (for cross-check only — do not invent beyond this):
|
||||
${cap(brainContext, 2000)}
|
||||
|
||||
5. Mission: Run a single rigorous reflection pass and output the structured critique exactly as specified by your persona.`;
|
||||
return this.callLLM(this.persona, wrappedInput, signal);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user