Compare commits

...
Author SHA1 Message Date
Garry TanandClaude Fable 5 7517a11300 fix(ai): migrate DeepSeek recipe to v4 model names (#1255)
DeepSeek retired `deepseek-chat` and `deepseek-reasoner` on 2026-07-24;
both map to `deepseek-v4-flash` (non-thinking / thinking mode). Recipe
model lists, context window (1M), providers-test example, and canonical
pricing updated; legacy `deepseek:deepseek-chat` pricing row kept so
historical usage/audit rows still price.

Reported by @W4RW1CK in #1255.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 16:06:43 -07:00
5 changed files with 29 additions and 10 deletions
+1 -1
View File
@@ -134,7 +134,7 @@ EXAMPLES
gbrain providers list
gbrain providers test --model openai:text-embedding-3-large
gbrain providers test --touchpoint chat --model anthropic:claude-haiku-4-5
gbrain providers test --touchpoint chat --model deepseek:deepseek-chat
gbrain providers test --touchpoint chat --model deepseek:deepseek-v4-flash
gbrain providers env ollama
gbrain providers explain --json
`);
+15 -9
View File
@@ -1,9 +1,10 @@
import type { Recipe } from '../types.ts';
/**
* `deepseek-reasoner` returns its answer in a separate `reasoning_content`
* field and leaves `content` empty/whitespace when the whole response was
* reasoning. The AI SDK's openai-compatible adapter reads only `content`, so
* DeepSeek's thinking mode (default on `deepseek-v4-flash`/`deepseek-v4-pro`;
* formerly the `deepseek-reasoner` model, retired 2026-07-24) returns its
* answer in a separate `reasoning_content` field and leaves `content`
* empty/whitespace when the whole response was reasoning. The AI SDK's openai-compatible adapter reads only `content`, so
* the model appears to answer with nothing. This transport shim promotes
* `reasoning_content` into `content` when `content` is empty, before the
* adapter parses the body. Fail-open: any error returns the original response.
@@ -80,20 +81,25 @@ export const deepseek: Recipe = {
// gateway's expansion path is a plain languageModel call). Without this
// declaration an explicit `expansion_model: deepseek:...` silently
// yields no expansion (#1135).
// `deepseek-chat` / `deepseek-reasoner` were retired by DeepSeek on
// 2026-07-24 (#1255); both map to `deepseek-v4-flash` (non-thinking /
// thinking mode). Do not re-add the old names — the API 404s them.
// openai-compat tier means user-configured legacy names still pass
// validation locally; the provider rejects them at call time.
expansion: {
models: ['deepseek-chat'],
models: ['deepseek-v4-flash'],
cost_per_1m_tokens_usd: 0.14,
price_last_verified: '2026-04-20',
price_last_verified: '2026-07-27',
},
chat: {
models: ['deepseek-chat', 'deepseek-reasoner'],
models: ['deepseek-v4-flash', 'deepseek-v4-pro'],
supports_tools: true,
supports_subagent_loop: true,
supports_prompt_cache: false,
max_context_tokens: 128000,
cost_per_1m_input_usd: 0.14, // deepseek-chat off-peak baseline
max_context_tokens: 1_000_000,
cost_per_1m_input_usd: 0.14, // deepseek-v4-flash cache-miss baseline
cost_per_1m_output_usd: 0.28,
price_last_verified: '2026-04-20',
price_last_verified: '2026-07-27',
},
},
setup_hint: 'Get an API key at https://platform.deepseek.com/api_keys, then `export DEEPSEEK_API_KEY=...`',
+5
View File
@@ -93,7 +93,12 @@ export const CANONICAL_PRICING: Record<string, ModelPricing> = {
// ── Together / DeepSeek (cross-modal-eval panel) ───────────────────────
'together:meta-llama/Llama-3.3-70B-Instruct-Turbo': { input: 0.88, output: 0.88 },
// `deepseek-chat` was retired by DeepSeek 2026-07-24 (#1255); kept so
// historical usage/audit rows still price. New calls use the v4 names.
'deepseek:deepseek-chat': { input: 0.14, output: 0.28 },
// DeepSeek v4 (verified 2026-07-27 at api-docs.deepseek.com): cache-miss rates.
'deepseek:deepseek-v4-flash': { input: 0.14, output: 0.28 },
'deepseek:deepseek-v4-pro': { input: 0.435, output: 0.87 },
};
/**
@@ -121,4 +121,9 @@ describe('applyOpenAICompatConfig — compat.fetch wiring (gateway seam)', () =>
test('recipe wires the shim via compat.fetch', () => {
expect(deepseek.compat?.fetch).toBe(deepseekReasoningContentCompatFetch);
});
test('recipe lists only v4 model names — deepseek-chat/deepseek-reasoner retired 2026-07-24 (#1255)', () => {
expect(deepseek.touchpoints.chat?.models).toEqual(['deepseek-v4-flash', 'deepseek-v4-pro']);
expect(deepseek.touchpoints.expansion?.models).toEqual(['deepseek-v4-flash']);
});
});
+3
View File
@@ -110,6 +110,9 @@ describe('chat touchpoint — model resolver + aliases (Codex F-OV-5)', () => {
expect(() => assertTouchpoint(getRecipe('anthropic')!, 'chat', 'claude-opus-4-7')).not.toThrow();
expect(() => assertTouchpoint(getRecipe('openai')!, 'chat', 'gpt-5.2')).not.toThrow();
expect(() => assertTouchpoint(getRecipe('google')!, 'chat', 'gemini-2.0-flash')).not.toThrow();
expect(() => assertTouchpoint(getRecipe('deepseek')!, 'chat', 'deepseek-v4-flash')).not.toThrow();
// Legacy id retired by DeepSeek 2026-07-24 (#1255): still passes local
// validation (openai-compat tier), rejection surfaces at the provider.
expect(() => assertTouchpoint(getRecipe('deepseek')!, 'chat', 'deepseek-chat')).not.toThrow();
});