fix(phase6b): DeepSeek V4 disable thinking by default + parse text block (not first content)

- thinking={type:disabled} skips reasoning trace → output_tokens drop 10x
- find first content block of type='text' (V4 may emit thinking before text)
- DEEPSEEK_THINKING=true env to re-enable if needed for hard problems

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Semih
2026-05-13 23:11:09 +00:00
parent 95c7e8e321
commit 0295b88981

View File

@@ -64,13 +64,15 @@ export async function callDeepSeek(opts: {
const model = modelForTier(opts.tier);
const url = `${BASE}/v1/messages`;
const body = {
const enableThinking = (process.env.DEEPSEEK_THINKING ?? "false") === "true";
const body: Record<string, unknown> = {
model,
max_tokens: opts.maxOutputTokens,
temperature: opts.temperature ?? 0.3,
system: opts.systemPrompt,
messages: [{ role: "user" as const, content: opts.userPrompt }],
};
if (!enableThinking) body.thinking = { type: "disabled" };
const start = Date.now();
let res: Response;
@@ -97,9 +99,13 @@ export async function callDeepSeek(opts: {
} catch {
throw new DeepSeekError(res.status, `non-json: ${text.slice(0, 200)}`);
}
const content = parsed?.content?.[0]?.text;
// V4 models may emit a "thinking" block before the final "text" block.
// Find the first text block; thinking blocks are not billed as output_tokens.
const blocks = Array.isArray(parsed?.content) ? parsed.content : [];
const textBlock = blocks.find((b: any) => b && b.type === "text" && typeof b.text === "string");
const content = textBlock?.text;
if (typeof content !== "string") {
throw new DeepSeekError(res.status, `no content text: ${text.slice(0, 200)}`);
throw new DeepSeekError(res.status, `no text block (got types: ${blocks.map((b: any) => b?.type).join(",")})`);
}
const usage = parsed.usage ?? {};