genmux API 现已全面开放。 查看文档 →
genmux API

博客

用一把 genmux 密钥在 OpenCode 里跑 DeepSeek V4

2 分钟阅读作者 genmux API Team


OpenCode 是一个终端里的编程智能体,能对接任何兼容 OpenAI 的后端;而 genmux 现在提供了智能体离不开的那一样东西:函数调用。从 v0.4.0 起,POST /v1/chat/completions 接受 tools、返回 tool_calls,并像 OpenAI 那样流式推送 delta.tool_calls——所以 OpenCode 通过 DeepSeek V4 读文件、改文件、跑测试的方式,和它对接任何托管模型时完全一样。本文讲配置、模型选择,以及一次会话诚实的成本估算。

配置块

把这段放进项目里的 opencode.json(想对所有项目生效就放 ~/.config/opencode/opencode.json):

json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "genmux": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "genmux",
      "options": { "baseURL": "https://api.genmux.tech/v1", "apiKey": "{env:GENMUX_API_KEY}" },
      "models": {
        "deepseek-v4-flash": { "name": "DeepSeek V4 Flash" },
        "deepseek-v4-pro": { "name": "DeepSeek V4 Pro" },
        "qwen3-max": { "name": "Qwen3-Max" }
      }
    }
  }
}

然后导出密钥并启动:

bash
export GENMUX_API_KEY=nb_live_...
opencode --model genmux/deepseek-v4-flash
# or one-shot, for scripts and CI:
opencode run --model genmux/deepseek-v4-flash "add a --json flag to cmd/report and update the README"

{env:GENMUX_API_KEY} 让密钥不落进文件里,如果 opencode.json 会被提交,这一点很重要。models 映射只影响 OpenCode 选择器里显示什么——列进去之后,七个支持工具调用的 id 都能以 genmux/<id> 的形式使用。

Flash 还是 Pro

两个 V4 模型都支持工具、都有 100 万 token 上下文,也都能思考(reasoning_effort 对应思维链的开关)。差别在价格和深度:

模型用在哪每 100 万 token 价格(输入 / 输出)
deepseek-v4-flash日常智能体循环:读代码、小改动、跑测试、写提交信息$0.198 / $0.594
deepseek-v4-pro硬核重构、跨文件改动、「这个测试为什么挂」的排查$0.594 / $1.782

一个实用做法:默认跑 Flash,当智能体开始原地打转时用 /model 切到 Pro。在我们的智能体风格工具评测中,Flash 得分 19/20,Pro 得分 20/20(细节见模拟函数调用那篇),所以选默认值并不是在可靠性上让步——让步的是模型在动手之前推理得有多深。上面配置块里放了 qwen3-max,是因为它多了视觉能力,当任务从一张截图开始时很有用。

从 OpenCode 这一侧看,工具调用是什么样

OpenCode 自带二十来个工具——read、write、edit、bash、glob、grep、list、webfetch、一个待办列表,还有几个——并在每次请求里把它们全部作为 JSON schema 放进 tools 数组。genmux 把这些定义渲染进 system prompt,把模型的回复流式送回,再把模型的调用块变成一个正规的 delta.tool_calls 分块,带上 finish_reason: "tool_calls"。OpenCode 完全看不出区别:它收到一次工具调用、在本地执行、把结果作为 role: tool 消息追加进去,然后再问一次。

线上的一个轮次,节选:

→ POST /v1/chat/completions  {"model":"deepseek-v4-flash","stream":true,"tools":[…20 tools…],"messages":[…]}
← data: {"choices":[{"delta":{"tool_calls":[{"index":0,"id":"call_7f…","type":"function","function":{"name":"read","arguments":"{\"filePath\":\"cmd/report/main.go\"}"}}]}}]}
← data: {"choices":[{"delta":{},"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":6814,"completion_tokens":31,"total_tokens":6845,"cost":0.109,"cost_source":"estimated"}}
← data: [DONE]
→ POST … messages now end with {"role":"tool","tool_call_id":"call_7f…","content":"package main\n…"}

有两个特性值得知道。模型通常每轮发一次调用,而不是并行一批;OpenCode 是循环的,所以改五个文件是五次短往返,而不是一次长往返。另外,模型在调用之前写的那句话(「我先读一下这个文件」)会作为普通内容流出来,所以终端界面在调用被拼装的同时仍在讲述进度。

一次会话要花多少钱

工具定义不是免费的:它们被渲染成文本,所以每次请求都算 prompt token——每个工具约 40 个 token 外加它的 schema,对 OpenCode 这一套来说每次请求大约 1.5K token。不过更大的开销来自对话历史:每次请求都会把目前为止读过的一切重新发一遍。

拿一次现实的会话来算——40 次请求,prompt 随着文件被读取从 3K 涨到 25K token(平均 12K),回复平均 400 token。也就是 48 万 prompt token 和 1.6 万 completion token:

模型Prompt(48 万)Completion(1.6 万)整场会话其中工具占(6 万)
deepseek-v4-flash$0.095$0.010≈ $0.105$0.012
deepseek-v4-pro$0.285$0.029≈ $0.314$0.036
qwen3-max$0.518$0.086≈ $0.605$0.065

按 Scale 套餐单价(每积分 $0.0125)折算成积分,就是 8.4 积分≈ $0.10Flash,40 次请求 对 25.1 积分≈ $0.31Pro,40 次请求。工具开销在 Flash 上大约落在一美分——真正占大头的是历史,这也是为什么 /compact(或者每个任务开一场新会话)比精简工具省下的钱多得多。

排查

400 tools_unsupported——模型 id 属于不支持工具的那三个之一(qwen3-6-flash、doubao-seed-2-lite、doubao-seed-2-mini)。函数调用是模拟实现的,只在评测通过的地方开启:两个 V4 模型、deepseek-v3、qwen3-7-max、qwen3-max、doubao-seed-2-pro 和 doubao-seed-2-code。GET /v1/models 里以 params_schema.tools 展示这个标志。

模型用自然语言作答,而没有调用工具。 tool_choice: required 和指定函数只是模型可以忽略的指令——小模型有时就会忽略。OpenCode 用的是 auto,所以实际表现是你多说一句「继续」,而不是循环坏掉。在我们那一轮里,Pro 20 次一次都没忽略。

max_tokens 相关的抱怨。 OpenCode 对每个模型都会发 32K 起步的 max_tokens。genmux 会把它收敛到该模型的 max_output_tokens,而不是拒绝请求,所以没什么要配置的。工具模型的默认回复预算是 8192 token,足够整文件重写。

一次调用以文本形式到达。 如果回复里出现了原始的 <function_call> 块而不是工具卡片,说明解析器没能解出来——请带上模型 id 和那段回复提个 issue;我们为每个模型跟踪一个 malformed 计数,模型出现漂移时就扩展解析器。

开始使用

从控制台拿一把密钥,粘贴上面那段配置,然后 opencode --model genmux/deepseek-v4-flash——整个迁移就这么多。Aider、Cline、Roo Code 和 Continue 的方式相同——Aider 有单独一篇,每个客户端的简版都在编程智能体页面。tools、tool_choice 和 response_format 的完整参数说明见文档。

关于作者

作者 genmux API Team — genmux API.

了解我们