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:
+39
-8
@@ -49,7 +49,7 @@ export interface IAgent {
|
||||
/**
|
||||
* 파이프라인 단계 상태 정의
|
||||
*/
|
||||
export type PipelineStage = 'idle' | 'planner' | 'researcher' | 'writer' | 'completed' | 'error';
|
||||
export type PipelineStage = 'idle' | 'planner' | 'researcher' | 'reflector' | 'writer' | 'completed' | 'error';
|
||||
|
||||
/**
|
||||
* 감사(Audit) 이력에 기록되는 단일 상태 전환 엔트리.
|
||||
@@ -449,7 +449,9 @@ export class AgentEngine {
|
||||
constructor(
|
||||
private readonly planner: IAgent,
|
||||
private readonly researcher: IAgent,
|
||||
private readonly writer: IAgent
|
||||
private readonly writer: IAgent,
|
||||
// [Self-Reflection] Researcher와 Writer 사이에 주입되는 메타인지 노드. 미주입 시 기존 3단계 파이프라인을 그대로 유지.
|
||||
private readonly reflector?: IAgent
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -528,16 +530,45 @@ export class AgentEngine {
|
||||
// [Structural Fix] 점수가 낮을수록 더 상세한 근거를 요구(comprehensive)하도록 로직 역전
|
||||
const writerLevel: AbstractionLevel = researchScore < 65 ? 'comprehensive' : 'balanced';
|
||||
|
||||
// --- Phase 3.5: Reflector (Self-Reflection) ---
|
||||
// Reflector가 주입되어 있고 옵션에서 명시적으로 끄지 않은 경우에만 실행한다.
|
||||
// 실패해도 파이프라인을 막지 않는다(soft-fail): Reflector는 품질 보강이지 필수 게이트가 아님.
|
||||
let reflection = '';
|
||||
const reflectionDisabled = options?.config?.enableReflection === false;
|
||||
if (this.reflector && !reflectionDisabled) {
|
||||
try {
|
||||
reflection = await this.executeStep(
|
||||
state, 'reflector', '중간 산출물 자기검증 중...',
|
||||
() => this.resilientExecute(state, this.reflector!, 'Reflector', research, brainContext, signal, onProgress, {
|
||||
...options,
|
||||
context: brainContext,
|
||||
signal,
|
||||
config: { ...options?.config, role: 'reflector', isSamePrompt: true },
|
||||
priorResults: { plan, originalPrompt: prompt, ...options?.priorResults },
|
||||
abstractionLevel: 'balanced'
|
||||
}),
|
||||
// [Cache namespace] Writer와 동일한 (research, prompt) 페어를 쓰면 CacheManager가
|
||||
// Writer 호출 시 reflector 결과를 그대로 반환해버린다. 단계명을 prefix로 분리.
|
||||
`reflector::${research}`, prompt, signal, onProgress
|
||||
);
|
||||
} catch (reflErr: any) {
|
||||
// Reflector 실패는 치명적이지 않다. 감사 이력에만 남기고 빈 reflection으로 Writer를 진행시킨다.
|
||||
if (reflErr?.name === 'AbortError') throw reflErr;
|
||||
logError(`[AgentEngine] Reflector soft-fail — Writer 계속 진행: ${reflErr?.message || reflErr}`);
|
||||
reflection = '';
|
||||
}
|
||||
}
|
||||
|
||||
// --- Phase 4: Writer ---
|
||||
const finalReport = await this.executeStep(
|
||||
state, 'writer', '최종 리포트 작성 및 편집 중...',
|
||||
() => this.resilientExecute(state, this.writer, 'Writer', research, prompt, signal, onProgress, {
|
||||
() => this.resilientExecute(state, this.writer, 'Writer', research, prompt, signal, onProgress, {
|
||||
...options,
|
||||
context: brainContext,
|
||||
signal,
|
||||
config: { role: 'writer', allowFallback: true, isSamePrompt: true, ...options?.config },
|
||||
priorResults: { plan, writerPrep, previousValidData: state.getResult('finalReport'), ...options?.priorResults },
|
||||
abstractionLevel: writerLevel
|
||||
context: brainContext,
|
||||
signal,
|
||||
config: { role: 'writer', allowFallback: true, isSamePrompt: true, ...options?.config },
|
||||
priorResults: { plan, writerPrep, reflection, previousValidData: state.getResult('finalReport'), ...options?.priorResults },
|
||||
abstractionLevel: writerLevel
|
||||
}),
|
||||
research, prompt, signal, onProgress
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user