feat(llm-deepseek): configure max token defaults
This commit is contained in:
@@ -124,6 +124,7 @@ describe('DeepSeekAdapter against a mock server', () => {
|
||||
// The wire request carried the auth header contents we configured.
|
||||
expect(server.requests[0]).toMatchObject({
|
||||
model: 'deepseek-v4-flash',
|
||||
max_tokens: 256_000,
|
||||
reasoning_effort: 'high',
|
||||
stream: true,
|
||||
stream_options: { include_usage: true },
|
||||
@@ -232,6 +233,20 @@ describe('DeepSeekAdapter against a mock server', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('uses the configured maxTokens default and preserves an explicit request cap', async () => {
|
||||
const server = await mockServer([
|
||||
{ kind: 'sse', events: textEvents },
|
||||
{ kind: 'sse', events: textEvents },
|
||||
])
|
||||
const ctx = await harness(server.url, { maxTokens: 32_000 })
|
||||
|
||||
await assemble(ctx, { model: 'deepseek-v4-flash', messages: [] })
|
||||
await assemble(ctx, { model: 'deepseek-v4-flash', messages: [], maxTokens: 8_192 })
|
||||
|
||||
expect(server.requests[0]).toMatchObject({ max_tokens: 32_000 })
|
||||
expect(server.requests[1]).toMatchObject({ max_tokens: 8_192 })
|
||||
})
|
||||
|
||||
it('publishes only off and omits the wire effort when thinking is disabled', async () => {
|
||||
const server = await mockServer([{ kind: 'sse', events: textEvents }])
|
||||
const ctx = await harness(server.url, { thinking: 'disabled' })
|
||||
@@ -666,7 +681,8 @@ describe('plugin registration and config', () => {
|
||||
provider: 'deepseek',
|
||||
id: 'deepseek-v4-flash',
|
||||
name: 'DeepSeek-V4-Flash',
|
||||
context: { contextWindow: 256_000 },
|
||||
context: { contextWindow: 1_000_000 },
|
||||
defaultMaxTokens: 256_000,
|
||||
reasoning: {
|
||||
efforts: [
|
||||
{ id: ReasoningEffortId('off'), name: 'Off' },
|
||||
@@ -795,7 +811,10 @@ describe('plugin registration and config', () => {
|
||||
description: 'Higher reasoning budget',
|
||||
})
|
||||
await expect(ctx.llm.resolveModelInfo('deepseek', 'arbitrary-unlisted'))
|
||||
.resolves.not.toHaveProperty('context')
|
||||
.resolves.toMatchObject({
|
||||
context: { contextWindow: 1_000_000 },
|
||||
defaultMaxTokens: 256_000,
|
||||
})
|
||||
})
|
||||
|
||||
it('uses exact model capacity before the adapter-wide default', async () => {
|
||||
@@ -880,6 +899,26 @@ describe('plugin registration and config', () => {
|
||||
},
|
||||
)
|
||||
|
||||
it.each([0, 1.5, Number.MAX_SAFE_INTEGER + 1])(
|
||||
'rejects invalid adapter-wide maxTokens %s',
|
||||
async (maxTokens) => {
|
||||
expect(() => new DeepSeekAdapter({
|
||||
apiKey: 'k',
|
||||
baseURL: 'http://127.0.0.1:1',
|
||||
maxTokens,
|
||||
})).toThrow(/maxTokens must be a positive safe integer/)
|
||||
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(LlmService)
|
||||
await expect(ctx.plugin(LlmDeepSeek, {
|
||||
apiKey: 'k',
|
||||
baseURL: 'http://127.0.0.1:1',
|
||||
maxTokens,
|
||||
})).rejects.toThrow(/maxTokens/)
|
||||
expect(ctx.llm.listProviders()).toEqual([])
|
||||
},
|
||||
)
|
||||
|
||||
it('falls back to DEEPSEEK_API_KEY and DEEPSEEK_BASE_URL env vars', async () => {
|
||||
vi.stubEnv('DEEPSEEK_API_KEY', 'env-key')
|
||||
vi.stubEnv('DEEPSEEK_BASE_URL', 'http://127.0.0.1:1')
|
||||
|
||||
@@ -170,6 +170,13 @@ describe('serializeRequest', () => {
|
||||
expect(wire.stop).toEqual(['END'])
|
||||
})
|
||||
|
||||
it('uses the adapter maxTokens default only when the request omits a cap', () => {
|
||||
expect(serializeRequest(request({ messages: history }), {}, 256_000).max_tokens)
|
||||
.toBe(256_000)
|
||||
expect(serializeRequest(request({ messages: history, maxTokens: 8_192 }), {}, 256_000).max_tokens)
|
||||
.toBe(8_192)
|
||||
})
|
||||
|
||||
it('maps tools to the wire function shape', () => {
|
||||
const wire = serializeRequest(request({
|
||||
messages: history,
|
||||
|
||||
Reference in New Issue
Block a user