47b3b9f93a
- v2.2.299 아키텍처 수렴: coreChat 통일(엔진 휴리스틱 3벌 제거), 기업 모드 검색 오케스트레이터 승격, lib/execUtil(실행 래퍼 6곳·Python 탐지 3벌 단일화), lib/kstSchedule(워처 4개 nowInKst 통합), estimateTokens 통합, 설정 접근 규칙 명문화 - v2.2.300 채팅 화면 정리: LiveReasoningFilter(스트리밍 중 <think>/Harmony 추론 토큰 단위 차단), 확신도·검토요청 footer 기본 숨김(계산·Reflection 은 유지) - v2.2.301 문맥·의도 이해: [답변 전 이해 원칙] 상시 주입, 워크플로우 의도 브리핑, Report QA 루프(규칙 레지스트리+실측치+회귀 게이트, 블로그_v3 개념 이식) - v2.2.302 /benchmark 비즈니스 렌즈(가격·수익·운영)+빌드 프롬프트 모드+QA 연계 - v2.2.303 handoff 모드(측정치 무손실 인수인계 문서)+/claude(Claude Code 터미널 위임) - v2.2.304 이식성: 지식 경로 두뇌-상대 규약(pickWikiDir 상대 해석), 이사 체크리스트 - v2.2.305 Claude 구독 엔진: claude: 프로바이더(CLI 위임, 모델 드롭다운 자동 노출, coreChat 지원 — 워크플로우·QA도 구독 모델 가능) - v2.2.306 Tone Guard: AI 상투어 금지 레지스트리(상담사 화법 실사례 8종+대조 예시) - v2.2.307 /benchmark 레이아웃 골격(sectionRoles 결정론 분석, 롤링 배너 즉답), 파트별 실패 격리, 합성 타임아웃 120→300초 검증: tsc 무오류 + jest 888 통과 + esbuild 정상 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
104 lines
5.5 KiB
TypeScript
104 lines
5.5 KiB
TypeScript
import { getConfig } from '../../config';
|
|
import { estimateTokens, estimateModelParamsB } from '../contextManager';
|
|
import { isCasualConversationPrompt } from './promptDetection';
|
|
import { isAstraModeArchitectureQuestion } from './astraModeArchitecture';
|
|
import { shouldPreflightLocalProjectPath } from './localProjectIntent';
|
|
|
|
/**
|
|
* 단일-LLM vs Multi-Agent (5단계 파이프라인) 라우팅 결정. 사용자가 명시 토글을
|
|
* 켰거나 (configEnabled), 작은 모델인데 prompt 가 크거나, 복합 작업 키워드가
|
|
* 매치되면 multi-agent 활성화. 잡담/짧은 prompt 는 무조건 단일 LLM.
|
|
*
|
|
* Priority (위→아래로 evaluated, 먼저 매치되면 그 결정 사용):
|
|
* 1) Astra-mode meta question / local-path preflight → 단일 (false)
|
|
* 2) mode='off' 인 사용자 — legacy 키워드+길이 휴리스틱만 사용
|
|
* 3) casual prompt / 너무 짧음 (<12자) → 단일
|
|
* 4) mode='always' → 무조건 multi (위 가드 통과 시)
|
|
* 5) mode='auto' — 작은 모델 / context fraction / 키워드 / 길이 중 하나라도
|
|
* 매치되면 multi. 단 prompt tokens 가 `chunkedSwitchTokens` 미만이면 *모든*
|
|
* 트리거 무시하고 단일 (큰 context 모델에서 키워드만으로 chunked 강제 발동
|
|
* 되는 회귀 차단 — 사용자 명시 요청).
|
|
*
|
|
* Stateless — agent.ts 의 private 메서드를 그대로 추출. 의존: config / token
|
|
* 추정기 / 다른 detection 함수 (모두 이미 stateless).
|
|
*/
|
|
export function shouldUseMultiAgentWorkflow(prompt: string, configEnabled: boolean): boolean {
|
|
if (!prompt || isAstraModeArchitectureQuestion(prompt)) {
|
|
return false;
|
|
}
|
|
|
|
if (shouldPreflightLocalProjectPath(prompt)) {
|
|
return false;
|
|
}
|
|
|
|
const cfg = getConfig();
|
|
const mode = cfg.workflowMultiAgentMode || 'auto';
|
|
|
|
// 'off' → 기존 키워드/길이 휴리스틱만 사용 (legacy multiAgentEnabled 토글 존중).
|
|
if (mode === 'off') {
|
|
const legacyComplex = prompt.length > 180 || /(보고서|심층|종합\s*분석|리서치|조사|전략\s*수립|기획안|제안서|roadmap|research|report|deep\s*analysis|strategy|proposal)/i.test(prompt);
|
|
if (!legacyComplex) return false;
|
|
return configEnabled || /(보고서|심층|종합\s*분석|리서치|조사|전략\s*수립|기획안|제안서|research|report|deep\s*analysis|strategy|proposal)/i.test(prompt);
|
|
}
|
|
|
|
// 인사·잡담은 5단계 파이프라인 낭비. 짧은 casual prompt 는 제외.
|
|
if (isCasualConversationPrompt(prompt)) {
|
|
return false;
|
|
}
|
|
if (prompt.trim().length < 12) {
|
|
return false;
|
|
}
|
|
|
|
// 'always' → 위 가드만 통과하면 무조건 발동.
|
|
if (mode === 'always') return true;
|
|
|
|
// 'auto' → 다음 중 하나라도 만족하면 발동:
|
|
// (1) 사용자가 multiAgentEnabled 를 명시적으로 켰다,
|
|
// (2) 작은 모델 (≤4B params) 이라 한 번에 처리하기 위험,
|
|
// (3) prompt 토큰이 효과적 context window 의 임계 이상을 차지한다,
|
|
// (4) "보고서/리뷰/심층 분석" 같은 명백한 복합 작업 키워드 매치,
|
|
// (5) prompt 길이 자체가 큼 (>240 chars).
|
|
if (configEnabled) return true;
|
|
|
|
const paramB = estimateModelParamsB(cfg.defaultModel);
|
|
if (paramB !== null && paramB <= 4) return true;
|
|
|
|
// ── 절대 임계값 게이트 (사용자 명시 요청) ────────────────────────────
|
|
// 입력 prompt 가 `chunkedSwitchTokens` 미만이면 *키워드·길이 트리거 모두 무시*
|
|
// 하고 단일 LLM 호출. 큰 컨텍스트 모델(131k 등)에서 "요약/리뷰" 같은 키워드만
|
|
// 써도 chunked 가 강제 발동해 답변이 느려지던 문제 해결.
|
|
//
|
|
// 이 게이트는 fraction 안전 체크보다 *먼저* 평가됨 — 사용자가 절대 임계값을
|
|
// 명시한 의도(50k 미만은 한 번에 처리)를 fraction 이 뒤집지 못하게. 작은
|
|
// 컨텍스트 모델 사용자는 config 에서 이 값을 모델 윈도우의 ~30% 로 낮춰야 함.
|
|
// [v2.2.301] 명시적 조사·보고서 요청은 절대 임계값 게이트보다 우선 발동 —
|
|
// 짧은 "X 조사해줘"도 Report QA 파이프라인(의도 브리핑→채점→회귀 게이트)을
|
|
// 타야 하기 때문. '요약/리뷰' 류 일반 키워드는 기존 결정대로 게이트 아래 유지.
|
|
if (/(조사|리서치|보고서|레포트)/.test(prompt) || /\b(research|report)\b/i.test(prompt)) {
|
|
return true;
|
|
}
|
|
|
|
try {
|
|
const promptTokensForGate = estimateTokens(prompt);
|
|
if (promptTokensForGate < cfg.chunkedSwitchTokens) {
|
|
return false;
|
|
}
|
|
} catch { /* fall through — 안전 측 fraction/keyword 체크가 처리 */ }
|
|
|
|
try {
|
|
const effectiveCtx = cfg.smallModelContextCap > 0 && paramB !== null && paramB <= 4
|
|
? cfg.smallModelContextCap
|
|
: cfg.contextLength;
|
|
const promptTokens = estimateTokens(prompt);
|
|
const threshold = Math.floor(effectiveCtx * cfg.workflowAutoCtxFractionThreshold);
|
|
if (promptTokens >= threshold) return true;
|
|
} catch { /* 안전한 폴백: 키워드/길이 체크로 진행 */ }
|
|
|
|
if (/(보고서|심층|종합\s*분석|리서치|조사|전략\s*수립|기획안|제안서|코드\s*리뷰|리뷰|아키텍처|architecture|research|report|deep\s*analysis|strategy|proposal|review)/i.test(prompt)) {
|
|
return true;
|
|
}
|
|
if (prompt.length > 240) return true;
|
|
|
|
return false;
|
|
}
|