feat: v2.2.83 → v2.2.91 — info prompt 강화 + 사용자 노출 설정 + 답변 포맷 정리
[v2.2.83] /youtube info 프롬프트 강화 - 비유 방향 보존 룰 (Hugging Face=자료실 같은 짝 뒤집기 방지) - 신뢰도 라벨 4종 ([근거 명시] / [화자 주장] / [가정] / [정리자 추론]) - 타임스탬프 fail 룰 (인용·구간 요약 모두 mm:ss 필수) - "정리자 노트" 별도 섹션으로 추론 격리 [v2.2.85] polishPersona self-check 5가지 - 정리·리뷰·요약 답변 출력 직전 머릿속 체크: (1) 사실 오류 (2) 없는 내용 추가 (3) 뉘앙스 유지 (4) 중요도 비례 (5) 중복 제거 [v2.2.86] chunkedSwitchTokens 절대 임계값 게이트 - 입력 < 50k 토큰이면 키워드·길이 트리거 무시하고 단일 호출 - 큰 컨텍스트 모델(131k+)에서 chunked 과잉 발동 방지 [v2.2.87] MAX_SECTIONS 5→3 cap - 총 호출 7회 → 5회 (outline + 3 section + polish) - 사용자 피드백 "6+회는 과하다" [v2.2.88] 이모지 사용 금지 룰 - polishPersona / directPersona / sectionPersona 모두 적용 - 사용자 피드백 "이모지는 시각 노이즈" [v2.2.89] 사용자 노출 설정 두 항목 - chunkedMaxSections config 신규 (default 3, 1~10 clamp) - MAX_SECTIONS_HARD_CEILING (10) 으로 안전망 격상 - Astra Settings 패널 "고급" 섹션에 두 슬라이더 노출 [v2.2.90] 가이드 문구 단순화 - "작은 모델은 낮추라" 문구 빼고 일관되게 50000 권장으로 [v2.2.91] 답변 포맷 가독성 fix - persona 의 "TL;DR" 표현 전부 "한 줄 요약" 으로 단일화 - stripMarkdownFormatting 에 헤더 후 빈 줄 강제 삽입 (marked.parse 가 라벨·본문을 별도 단락으로 인식 → 시각 분리) [테스트] 400/400 통과 (resilience_stress + chunked flow + MAX_SECTIONS cap 등) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+28
-6
@@ -456,8 +456,14 @@ export class CacheManager {
|
||||
* - Error Recovery Matrix 기반의 Transient/Permanent 오류 자동 분류 및 복구
|
||||
*/
|
||||
export class AgentEngine {
|
||||
/** Outline LLM이 제안한 N을 강제로 1..MAX_SECTIONS 로 clamp 한다. */
|
||||
static readonly MAX_SECTIONS = 5;
|
||||
/**
|
||||
* Hard ceiling — *사용자 config 가 어떤 값이든 절대 넘을 수 없다*. 안전망.
|
||||
* 실제 사용 상한은 `getConfig().chunkedMaxSections` (default 3). 사용자가
|
||||
* Astra Settings 에서 1~10 사이 조정.
|
||||
*
|
||||
* factory.ts ChunkedWriter.MAX_SECTIONS_HARD_CEILING 와 일치.
|
||||
*/
|
||||
static readonly MAX_SECTIONS_HARD_CEILING = 10;
|
||||
|
||||
/**
|
||||
* 단일 writer agent — 같은 모델이 outline / section / polish 역할을 번갈아
|
||||
@@ -526,18 +532,28 @@ export class AgentEngine {
|
||||
|
||||
// --- Phase 1: Outline ---
|
||||
// 1번의 LLM 호출로 답변을 몇 개 섹션으로 쪼갤지 결정. JSON 배열 반환.
|
||||
// 사용자 config 의 chunkedMaxSections 를 outline persona 에 전달 — outline
|
||||
// LLM 이 그 상한을 지키도록 prompt 에 박힘. parseOutline 의 cap 도 같은
|
||||
// 값 사용해서 LLM 이 룰 어겨도 강제로 자름.
|
||||
const cfgMaxSections = (() => {
|
||||
try {
|
||||
const { getConfig } = require('../config') as typeof import('../config');
|
||||
const v = getConfig().chunkedMaxSections;
|
||||
return Math.max(1, Math.min(AgentEngine.MAX_SECTIONS_HARD_CEILING, v ?? 3));
|
||||
} catch { return 3; } // 안전 fallback
|
||||
})();
|
||||
const outlineRaw = await this.executeStep(
|
||||
state, 'outline', '답변 구조 잡는 중...',
|
||||
() => this.resilientExecute(state, this.writer, 'Outline', prompt, brainContext, signal, onProgress, {
|
||||
...options,
|
||||
context: brainContext,
|
||||
signal,
|
||||
config: { ...options?.config, role: 'outline' },
|
||||
config: { ...options?.config, role: 'outline', maxSections: cfgMaxSections },
|
||||
}),
|
||||
`outline::${prompt}`, brainContext, signal, onProgress
|
||||
);
|
||||
|
||||
const outline = this.parseOutline(outlineRaw);
|
||||
const outline = this.parseOutline(outlineRaw, cfgMaxSections);
|
||||
const sections = outline.sections;
|
||||
|
||||
// outline 이 빈 배열(`reason === 'empty'`)을 반환했다면 LLM 이
|
||||
@@ -920,10 +936,16 @@ export class AgentEngine {
|
||||
* (옛 버전엔 길이로만 구분이 안 돼서 empty 와 fallback 이 혼동돼
|
||||
* parse 실패가 우발적 single-pass 전환을 일으켰음).
|
||||
*/
|
||||
private parseOutline(raw: string): {
|
||||
private parseOutline(raw: string, cap?: number): {
|
||||
sections: Array<{ heading: string; scope: string }>;
|
||||
reason: 'ok' | 'empty' | 'fallback';
|
||||
} {
|
||||
// cap 미지정 시 hard ceiling 으로 안전 보호. 정상 호출 경로에선 호출자가 사용자
|
||||
// config 값 (chunkedMaxSections) 을 전달함.
|
||||
const effectiveCap = Math.max(1, Math.min(
|
||||
AgentEngine.MAX_SECTIONS_HARD_CEILING,
|
||||
cap ?? AgentEngine.MAX_SECTIONS_HARD_CEILING,
|
||||
));
|
||||
const fallbackSections = [{ heading: '본문', scope: '사용자 요청 전체를 다루는 단일 섹션' }];
|
||||
if (!raw || !raw.trim()) {
|
||||
return { sections: fallbackSections, reason: 'fallback' };
|
||||
@@ -949,7 +971,7 @@ export class AgentEngine {
|
||||
}))
|
||||
.filter((o) => o.heading.length > 0);
|
||||
if (cleaned.length === 0) return null;
|
||||
return { kind: 'sections', list: cleaned.slice(0, AgentEngine.MAX_SECTIONS) };
|
||||
return { kind: 'sections', list: cleaned.slice(0, effectiveCap) };
|
||||
} catch { return null; }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user