fix: revert bad ctx trimming add n_keep>n_ctx GPU error detection

This commit is contained in:
2026-05-07 14:03:17 +09:00
parent 99ddf6a3cf
commit 47e35ab62c
7 changed files with 45 additions and 38 deletions
+31 -24
View File
@@ -526,7 +526,28 @@ export class AgentExecutor {
logInfo('Generation aborted by user.');
} else {
logError('Stream reading error.', { engine, apiUrl, error: err?.message || String(err) });
this.webview?.postMessage({ type: 'error', value: `Connection lost: ${err.message}` });
// LM Studio llama.cpp n_keep > n_ctx 에러 감지
const errMsg = String(err?.message || err || '');
const nCtxMatch = errMsg.match(/n_keep\s*:\s*(\d+)\s*>=?\s*n_ctx\s*:\s*(\d+)/);
if (nCtxMatch) {
const nKeep = nCtxMatch[1];
const nCtx = nCtxMatch[2];
this.webview?.postMessage({
type: 'error',
value: [
`Connection lost: AI Engine Error (LM Studio)`,
`시스템 프롬프트 토큰(${nKeep})이 실제 KV 캐시(${nCtx})보다 큽니다.`,
'',
'**원인:** LM Studio가 GPU 메모리 부족으로 컨텍스트 창을 축소했습니다.',
'**해결 방법 (LM Studio 재설정):**',
`1. LM Studio → 모델 설정 → GPU Offload 레이어를 줄여보세요 (현재 설정보다 낮게)`,
`2. 모델을 언로드 후 재로드하세요`,
`3. 다른 앱이 GPU 메모리를 점유하고 있다면 종료 후 재시도`,
].join('\n')
});
} else {
this.webview?.postMessage({ type: 'error', value: `Connection lost: ${err.message}` });
}
}
}
@@ -2020,40 +2041,26 @@ export class AgentExecutor {
for (const candidateModel of modelCandidates) {
for (const variant of messageVariants) {
// LM Studio: context_length를 명시적으로 제한하여 컨텍스트 초과 방지
// 총 메시지 토큰 추정: 문자 수 / 4 (rough estimate)
const totalChars = variant.messages.reduce((acc, m) => acc + String(m.content || '').length, 0);
const estimatedTokens = Math.ceil(totalChars / 4);
// LM Studio 소형 모델(4B~8B)은 4096~8192 context 제한
// 컨텍스트 초과 시 max_tokens을 줄여서 모델이 응답할 공간 확보
const lmStudioMaxTokens = Math.max(512, Math.min(4096, 8192 - estimatedTokens));
const streamBody = {
model: candidateModel,
messages: variant.messages,
stream: true,
...(engine === 'lmstudio'
? {
max_tokens: lmStudioMaxTokens,
temperature,
// LM Studio: context_length로 컨텍스트 창 명시 설정
context_length: 8192
}
? { max_tokens: 4096, temperature }
: { options: { num_ctx: 32768, num_predict: 4096, temperature } }),
};
if (engine === 'lmstudio' && estimatedTokens > 6000) {
logError('LM Studio context may be too large for small models.', { estimatedTokens, lmStudioMaxTokens, model: candidateModel });
}
logInfo('AI streaming request started.', {
engine, apiUrl, model: candidateModel,
variant: variant.name,
messageCount: variant.messages.length,
estimatedTokens,
roles: variant.messages.map(message => message.role),
firstUserPreview: summarizeText(String(variant.messages.find(message => message.role === 'user')?.content || ''), 300)
});
try {
logInfo('AI streaming request started.', {
engine,
apiUrl,
model: candidateModel,
variant: variant.name,
messageCount: variant.messages.length,
roles: variant.messages.map(message => message.role),
firstUserPreview: summarizeText(String(variant.messages.find(message => message.role === 'user')?.content || ''), 300)
});
const response = await fetch(apiUrl, {
method: 'POST',
headers: {