第 3 章 · 02 DeepSeek 预设与双模型协作


文档摘要

第 3 章 · 02 DeepSeek 预设与双模型协作 本节摘要:本节把上一节的 Provider 抽象落到 Reasonix 最核心的场景——DeepSeek。DeepSeek 在 Reasonix 里是一个"预设",本质是预配置好的 provider 实例,endpoint 指向 。本节先讲 DeepSeek 预设的每个字段含义、 与 等推理控制,再深讲 Reasonix 最独特的能力之一——双模型 executor + planner 协作:为什么必须开两个独立会话、为什么不能在共享会话里切模型、planner 的"轻量/完整/仅计划/待批准"四种深度档位、计划如何作为结构化文本交给 executor。

第 3 章 · 02 DeepSeek 预设与双模型协作

本节摘要:本节把上一节的 Provider 抽象落到 Reasonix 最核心的场景——DeepSeek。DeepSeek 在 Reasonix 里是一个"预设",本质是预配置好的 kind = "openai" provider 实例,endpoint 指向 https://api.deepseek.com。本节先讲 DeepSeek 预设的每个字段含义、reasoning_languageeffort 等推理控制,再深讲 Reasonix 最独特的能力之一——双模型 executor + planner 协作:为什么必须开两个独立会话、为什么不能在共享会话里切模型、planner 的"轻量/完整/仅计划/待批准"四种深度档位、计划如何作为结构化文本交给 executor。最后回到那句贯穿全书的论断——"任何 OpenAI 兼容端点只是配置项不是代码",这是"薄 harness"在 Provider 层的最佳兑现。

内容来源:原项目源码 docs/SPEC.md §3.4/§3.5/§5、reasonix.example.tomlinternal/provider/openai/openai.goREASONING_PROVIDERS.md/REASONING_LANGUAGE.md 文档。

⚠️ 注意:双模型协作不是"两个模型同时跑同一个会话",而是"两个独立会话各跑一个模型"。混淆这一点会误解整个设计意图——它的首要目标是保持各自的 prefix cache 稳定,其次才是分工。

学习目标

阅读完本节,你应当能够:

  1. 说出 DeepSeek 预设每个配置字段的含义。
  2. 解释 effortreasoning_language 如何控制推理行为。
  3. 默写双模型协作"两会话分离、各自 prepend-only"的核心约束。
  4. 区分 planner 的四种深度档位(轻量/完整/仅计划/待批准)。
  5. 解释"在共享会话切模型"为何会击穿 prefix cache。
  6. 用 SPEC §3.1 那句"config edit, not a code change"总结薄 harness。

一、DeepSeek 预设:kind = "openai" 的配置实例

第 2 章第 2 节已经看过 DeepSeek 预设的配置块,本节从 Provider 视角再读一遍(reasonix.example.toml:59-74):

[[providers]] name = "deepseek" kind = "openai" base_url = "https://api.deepseek.com" models = ["deepseek-v4-flash", "deepseek-v4-pro"] default = "deepseek-v4-flash" api_key_env = "DEEPSEEK_API_KEY" context_window = 1000000 effort = "high"

从 Provider 抽象看,这段配置做了三件事:

  1. 声明一个 provider 实例,实例名 "deepseek",注册表 kind "openai"reasonix setup 或运行时,internal/config 把它解析成 provider.Config{Name: "deepseek", BaseURL: "https://api.deepseek.com", APIKey: <从 .env 读出>, ...}
  2. 挂载多个 model:models = [...] 让一个 endpoint 暴露多个模型;default 指定列表的默认项。SPEC §3.1(docs/SPEC.md:97-99):

An entry declares either a single model = "..." or a models = ["...", "..."] list (with an optional default); the list form lets one vendor expose several models without re-declaring the endpoint/key.

  1. 声明 endpoint 元数据:context_window 是 provider 级上下文窗口(接近时触发压缩),api_key_env 命名密钥环境变量。

kind = "openai" 的运行时含义:internal/provider/openai.New(cfg) 被调用,返回一个实现了 Provider interface 的 openai 结构体。它负责:

  • Request 序列化成 OpenAI /chat/completions 请求体。
  • POST 到 base_url + "/chat/completions"
  • 解析 SSE 流,把 delta 累积成完整 ToolCall、规范化 Usage(DeepSeek 的 prompt_cache_hit_tokens 与 OpenAI 的 prompt_tokens_details.cached_tokens 都映射成 Usage.CacheHitTokens)。
  • DeepSeek 模型靠模型名识别(SPEC §5 注释:docs/SPEC.md:84-85),代理后的 DeepSeek 也靠模型名识别;reasoning_protocol = "none" 可禁用,"openai" 可强制普通 reasoning_effort

关键认知:DeepSeek 不是特殊 provider kind,它就是 kind = "openai" 的一个配置实例。Reasonix 没有任何 if provider == "deepseek" 的硬编码分支(那会违反 SPEC §1.1)。DeepSeek 的特殊性全在 endpoint 端——DeepSeek 服务器实现了 OpenAI 兼容协议 + 自动 prefix cache,客户端(provider/openai 实现)只需把 DeepSeek 特有的 usage 字段规范化。

二、effort 与 reasoning_language:推理控制

DeepSeek thinking 始终开启,effort 控制推理强度。example.toml 注释(reasonix.example.toml:73-74):

# DeepSeek thinking is always on; effort: high | max. Omit for auto (provider default). effort = "high"

/effort 命令在 TUI 里运行时切换强度。DeepSeek 模型支持 high/max;Anthropic 支持 low/medium/high/xhigh/max。自定义 [[providers]] 可通过 supported_effortsdefault_effort 暴露自定义档位(reasonix.example.toml:80-96)。

reasoning_language(reasonix.example.toml:36):

# reasoning_language = "auto" # visible reasoning text: auto|zh|en

控制可见推理文本的语言:auto(跟随 UI 语言)、zh(中文)、en(英文)。这是 Reasonix 作为中国开发者社区项目的本地化细节——让 DeepSeek 的思维链用中文输出,对中国用户更友好。相关文档见 REASONING_PROVIDERS.md(哪些 provider 支持推理)与 REASONING_LANGUAGE.md(推理语言控制)。

💡 契约要点:reasoning_language 只影响可见推理文本,不影响 Reasonix 内部决策或工具调用。它通过 provider 实现层的提示控制实现,不污染 prefix cache 稳定前缀(因为是放在 turn tail,不是 system prompt)。

三、双模型协作:Coordinator 与两会话分离

SPEC §3.5 是 Reasonix 最精巧的设计之一。开篇(docs/SPEC.md:200-204):

When agent.planner_model names a provider different from the executor, a Coordinator runs two models in separate sessions to keep each one's prompt prefix cache-stable.

机制:

  • executor(执行者):全功能 tool-using Agent,跑在自己的会话里,带着全部工具,执行 planner 给出的计划。
  • planner(规划者):低频,跑在另一个会话里,带相同的常驻记忆上下文 + 过滤后的只读研究工具集,产出简洁计划。
  • 两会话永不混合——任何一个模型的 prefix 都不被对方轮次干扰,各自 prepend-only 增长,各自 prefix cache 稳定。

Coordinator 满足 Runner interface(SPEC §3.4,docs/SPEC.md:195-197):

A Runner is anything with Run(ctx, input) error; both Agent and Coordinator satisfy it, so the CLI is agnostic to single- vs two-model mode.

RunnerRun(ctx, input) error 的任何东西,AgentCoordinator 都满足它,所以 CLI 不关心是单模型还是双模型模式——这是"核心只懂接口"的又一次兑现。

四、为什么不能在共享会话切模型

SPEC §3.5 最后一段点睛(docs/SPEC.md:237-240):

The sessions never mix, so neither model's prefix is disturbed by the other's turns; both grow prepend-only and stay cache-friendly. This reconciles "cache-first" with "two-model collaboration": switching models inside one shared conversation would break the prefix and tank cache hits, so we don't.

为什么"在同一个共享会话里切换模型"会击穿 prefix cache?

prefix cache 的工作原理是:provider 服务器缓存"请求前缀的 KV cache",下次请求前缀字节相同就复用。前缀包括 system prompt + tools schema + 历史消息。如果中途换模型:

  • 不同模型的 tokenizer/分词边界不同,前缀字节序列的"逻辑边界"变了。
  • 即使字节相同,服务器侧的 cache key 通常包含 model id,换模型 cache 直接 miss。
  • 更糟的是,不同模型对同一历史可能产生不同的内部状态,后续 prefix 全部失效。

所以 Reasonix 的解法是开两个会话:executor 会话只跟 executor 模型对话,planner 会话只跟 planner 模型对话,计划作为结构化文本在两会话间传递(不是共享消息历史)。这样两个会话各自 prepend-only 增长,各自 prefix cache 稳定——把"缓存优先"与"双模型协作"调和起来。

五、planner 的四种深度档位

planner 不是无脑"先规划再执行"。SPEC §3.5 描述了一个确定性 host 策略(docs/SPEC.md:206-215),根据原始用户文本 + 可信轮次元数据,选择五种路由:

  1. executor-only(仅执行者):简单任务,不走 planner。
  2. light planning(轻量规划):小预算研究轮次,产出紧凑目标 + 1-4 步 + 可能触点 + 主要验证。
  3. full planning(完整规划):更大有界预算,区分已验证/候选触点,带风险、验收标准、命令级验证、回滚。
  4. plan-for-approval(待批准规划):仅在用户显式要求"等确认"时使用,host 强制边界即使 planner 漏写标记。
  5. plan-only(仅计划):持久化计划并结束当前轮次,不执行。

关键设计:

  • 不调用分类器模型做路由决策——而是用确定性 host 策略,从原始用户文本 + 可信轮次元数据推断。这避免了一次额外 LLM 调用。
  • 不从 controller 编写的提示块推断 host 状态——防止提示注入污染路由决策。
  • 深度契约在一个稳定系统提示里——只有小的 host 编写的 <planner-turn> 块随用户轮次变化(docs/SPEC.md:219-221):

The depth contract stays in one stable system prompt; only a small host-authored <planner-turn> block changes per user turn.

这又是 prefix cache 友好——深度契约(系统提示)字节稳定,只有小的轮次块变。

  • planner 失败的回退(docs/SPEC.md:222-225):若 planner 在有界研究 + 宽限轮次后仍未定稿,plan-and-execute 回退到 executor 用原始任务;plan-only 与 plan-for-approval 保持 fail-closed(失败即停,不回退)。不完整的 planner 轮次被回滚,而非作为残缺的手动延续暴露。

六、计划作为结构化文本交给 executor

SPEC §3.5(docs/SPEC.md:234-236):

The plan is handed off as structured text to the executor — a full tool-using Agent in its own session — which validates candidate assumptions and carries it out.

计划以结构化文本形式交给 executor——不是函数调用、不是共享内存、不是消息历史拼接。executor 在自己的会话里收到这段文本,作为新的用户轮次,验证候选假设并执行。

这个设计有几个好处:

  • 两会话解耦:planner 与 executor 不共享任何状态,只通过文本"对话"。
  • prefix cache 友好:executor 会话的前缀(系统提示 + 工具 schema + 常驻记忆)字节稳定,计划只是新的用户轮次追加到 turn tail,不破坏前缀。
  • 可审计:计划是文本,人能读、能改、能拒绝(plan-for-approval 模式)。

七、薄 harness 的兑现:配置项不是代码

回到 SPEC §3.1 那句贯穿全书的话(docs/SPEC.md:91-93):

OpenAI-compatible vendors are config instances of kind = "openai", differing only in base_url / model / api_key_env. Adding another OpenAI-compatible model is a config edit, not a code change.

DeepSeek、Kimi、GLM、MiniMax、Qwen、Ollama Cloud……它们在 Reasonix 里都是 kind = "openai" 的配置实例。example.toml 第 50-58 行的注释列出了桌面"Settings -> Model -> Access -> Add provider"内置的推荐预设:Kimi CN/Global、Kimi Coding Plan、MiMo API、MiniMax CN/Global、GLM/Z.AI、Qwen/DashScope、Token Rhythm、StepFun、NovitaAI、GMI、Vercel AI Gateway、HuggingFace、NVIDIA、KiloCode、Ollama Cloud。

加一个新模型,改 config 即可,不写一行 Go 代码——这是"薄 harness"在 Provider 层的最佳兑现,也是 Reasonix 能用一套代码对接几十个模型的根本原因。

💡 契约要点:薄 harness 的力量在于"接口稳定 + 注册表扩展 + 配置声明"。Provider interface 两个方法不变,注册表机制不变,新模型通过 config 接入。开发者只需理解一个 interface,就能对接整个 OpenAI 兼容生态。

本节要点回顾

  1. DeepSeek 预设:kind = "openai" 的配置实例,endpoint 指向 https://api.deepseek.com;DeepSeek 不是特殊 kind,无硬编码 if provider == "deepseek"
  2. 推理控制:effort(high/max)控制强度;reasoning_language(auto/zh/en)控制可见推理文本语言;都放在 turn tail,不污染 prefix。
  3. 双模型协作:planner_model 开启 Coordinator,executor 与 planner 跑在两个独立会话,各自 prepend-only、各自 prefix cache 稳定。
  4. 不能共享会话切模型:换模型破坏 prefix 字节边界与 cache key,所以开两会话;计划作为结构化文本在两会话间传递。
  5. planner 四种深度:executor-only / light / full / plan-for-approval / plan-only;确定性 host 策略路由,不调分类器模型;深度契约在稳定系统提示,只有 <planner-turn> 块变。
  6. 薄 harness 兑现:加新 OpenAI 兼容模型 = 改 config,不是改代码;Reasonix 一套代码对接几十个模型。

下一章进入 Tool——SPEC §3.2 的 Tool interface 与 Registry,看 Reasonix 如何用与 Provider 同构的注册表模式管理内置工具与插件工具。


作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U