Skip to content

Commit 7da1e80

Browse files
committed
feat: adaptive num_ctx for Ollama — auto-size context window based on input length
Ollama defaults to 2048 context which silently truncates long prompts. Now estimates input tokens (CJK-aware) and sets num_ctx = input + output + buffer, so small inputs stay fast and large inputs don't get cut off.
1 parent 8f38b4c commit 7da1e80

1 file changed

Lines changed: 23 additions & 1 deletion

File tree

src/connectors/ollama.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ export class OllamaConnector implements LLMConnector {
1212
}
1313

1414
async chat(systemPrompt: string, userMessage: string, config: LLMConfig): Promise<LLMResult> {
15+
const numPredict = config.max_tokens || 8192;
16+
const numCtx = estimateNumCtx(systemPrompt, userMessage, numPredict);
17+
1518
let response: Response;
1619
try {
1720
response = await fetch(`${this.baseUrl}/api/chat`, {
@@ -25,7 +28,8 @@ export class OllamaConnector implements LLMConnector {
2528
],
2629
stream: false,
2730
options: {
28-
num_predict: config.max_tokens || 8192,
31+
num_predict: numPredict,
32+
num_ctx: numCtx,
2933
},
3034
}),
3135
});
@@ -60,3 +64,21 @@ export class OllamaConnector implements LLMConnector {
6064
};
6165
}
6266
}
67+
68+
/**
69+
* 根据实际输入长度自适应计算 num_ctx,避免 Ollama 默认 2048 截断,
70+
* 同时小输入不分配多余显存,提升推理速度。
71+
*/
72+
function estimateNumCtx(systemPrompt: string, userMessage: string, numPredict: number): number {
73+
const text = systemPrompt + userMessage;
74+
// CJK 字符约 1.5-2 token/字,ASCII 约 0.25 token/字,按实际比例加权
75+
let tokens = 0;
76+
for (let i = 0; i < text.length; i++) {
77+
tokens += text.charCodeAt(i) > 0x7F ? 1.5 : 0.3;
78+
}
79+
const estimatedInputTokens = Math.ceil(tokens);
80+
const buffer = 512;
81+
const computed = estimatedInputTokens + numPredict + buffer;
82+
// 下限 4096(部分模型低于此值行为异常),上限 131072(主流模型极限)
83+
return Math.min(Math.max(computed, 4096), 131072);
84+
}

0 commit comments

Comments
 (0)