Skip to content

Commit 2f94833

Browse files
committed
fix: respect user-configured context window for Ollama models
- Add ollamaContextWindow field to ProviderSettings schema - Update NativeOllamaHandler to use custom context window when provided - Add tests to verify context window configuration works correctly Fixes #7343
1 parent 8e4c0ae commit 2f94833

File tree

3 files changed

+102
-2
lines changed

3 files changed

+102
-2
lines changed

packages/types/src/provider-settings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ const openAiSchema = baseProviderSettingsSchema.extend({
184184
const ollamaSchema = baseProviderSettingsSchema.extend({
185185
ollamaModelId: z.string().optional(),
186186
ollamaBaseUrl: z.string().optional(),
187+
ollamaContextWindow: z.number().optional(),
187188
})
188189

189190
const vsCodeLmSchema = baseProviderSettingsSchema.extend({

src/api/providers/__tests__/native-ollama.spec.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,103 @@ describe("NativeOllamaHandler", () => {
100100
expect(results.some((r) => r.type === "reasoning")).toBe(true)
101101
expect(results.some((r) => r.type === "text")).toBe(true)
102102
})
103+
104+
describe("context window configuration", () => {
105+
it("should use custom context window when ollamaContextWindow is provided", async () => {
106+
const customContextWindow = 48000
107+
const optionsWithCustomContext: ApiHandlerOptions = {
108+
apiModelId: "llama2",
109+
ollamaModelId: "llama2",
110+
ollamaBaseUrl: "http://localhost:11434",
111+
ollamaContextWindow: customContextWindow,
112+
}
113+
handler = new NativeOllamaHandler(optionsWithCustomContext)
114+
115+
// Mock the chat response
116+
mockChat.mockImplementation(async function* () {
117+
yield {
118+
message: { content: "Test response" },
119+
eval_count: 10,
120+
prompt_eval_count: 5,
121+
}
122+
})
123+
124+
// Create a message to trigger the chat call
125+
const generator = handler.createMessage("System prompt", [{ role: "user", content: "Test message" }])
126+
127+
// Consume the generator
128+
const results = []
129+
for await (const chunk of generator) {
130+
results.push(chunk)
131+
}
132+
133+
// Verify that chat was called with the custom context window
134+
expect(mockChat).toHaveBeenCalledWith(
135+
expect.objectContaining({
136+
options: expect.objectContaining({
137+
num_ctx: customContextWindow,
138+
}),
139+
}),
140+
)
141+
})
142+
143+
it("should use model's default context window when ollamaContextWindow is not provided", async () => {
144+
// Mock the chat response
145+
mockChat.mockImplementation(async function* () {
146+
yield {
147+
message: { content: "Test response" },
148+
eval_count: 10,
149+
prompt_eval_count: 5,
150+
}
151+
})
152+
153+
// Create a message to trigger the chat call
154+
const generator = handler.createMessage("System prompt", [{ role: "user", content: "Test message" }])
155+
156+
// Consume the generator
157+
const results = []
158+
for await (const chunk of generator) {
159+
results.push(chunk)
160+
}
161+
162+
// Verify that chat was called with the model's default context window (4096)
163+
expect(mockChat).toHaveBeenCalledWith(
164+
expect.objectContaining({
165+
options: expect.objectContaining({
166+
num_ctx: 4096,
167+
}),
168+
}),
169+
)
170+
})
171+
172+
it("should use custom context window in completePrompt method", async () => {
173+
const customContextWindow = 48000
174+
const optionsWithCustomContext: ApiHandlerOptions = {
175+
apiModelId: "llama2",
176+
ollamaModelId: "llama2",
177+
ollamaBaseUrl: "http://localhost:11434",
178+
ollamaContextWindow: customContextWindow,
179+
}
180+
handler = new NativeOllamaHandler(optionsWithCustomContext)
181+
182+
// Mock the chat response
183+
mockChat.mockResolvedValue({
184+
message: { content: "Test response" },
185+
})
186+
187+
// Call completePrompt
188+
await handler.completePrompt("Test prompt")
189+
190+
// Verify that chat was called with the custom context window
191+
expect(mockChat).toHaveBeenCalledWith(
192+
expect.objectContaining({
193+
options: expect.objectContaining({
194+
num_ctx: customContextWindow,
195+
}),
196+
}),
197+
)
198+
})
199+
})
103200
})
104201

105202
describe("completePrompt", () => {
@@ -115,6 +212,7 @@ describe("NativeOllamaHandler", () => {
115212
messages: [{ role: "user", content: "Tell me a joke" }],
116213
stream: false,
117214
options: {
215+
num_ctx: 4096,
118216
temperature: 0,
119217
},
120218
})

src/api/providers/native-ollama.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ export class NativeOllamaHandler extends BaseProvider implements SingleCompletio
181181
messages: ollamaMessages,
182182
stream: true,
183183
options: {
184-
num_ctx: modelInfo.contextWindow,
184+
num_ctx: this.options.ollamaContextWindow || modelInfo.contextWindow,
185185
temperature: this.options.modelTemperature ?? (useR1Format ? DEEP_SEEK_DEFAULT_TEMPERATURE : 0),
186186
},
187187
})
@@ -262,14 +262,15 @@ export class NativeOllamaHandler extends BaseProvider implements SingleCompletio
262262
async completePrompt(prompt: string): Promise<string> {
263263
try {
264264
const client = this.ensureClient()
265-
const { id: modelId } = await this.fetchModel()
265+
const { id: modelId, info: modelInfo } = await this.fetchModel()
266266
const useR1Format = modelId.toLowerCase().includes("deepseek-r1")
267267

268268
const response = await client.chat({
269269
model: modelId,
270270
messages: [{ role: "user", content: prompt }],
271271
stream: false,
272272
options: {
273+
num_ctx: this.options.ollamaContextWindow || modelInfo.contextWindow,
273274
temperature: this.options.modelTemperature ?? (useR1Format ? DEEP_SEEK_DEFAULT_TEMPERATURE : 0),
274275
},
275276
})

0 commit comments

Comments
 (0)