# 给 DeepSeek Harness 加一个异步 B 模型:dsh-second-opinion 使用指南 大模型给出答案,并不代表这次决策已经经过独立检查。`dsh-second-opinion` 是一个面向 DeepSeek Harness 的独立插件:A 模型照常回答,B 模型在后台异步审阅每条已经提交的 assistant 消息,再把一致结论、风险点和替代建议交给人或自动复议流程。 项目地址:[GitHub](https://github.com/scwlkq/dsh-second-opinion);npm 包:[dsh-second-opinion](https://www.npmjs.com/package/dsh-second-opinion)。 ## 为什么采用异步审阅 审阅不应成为主回答的前置门槛。插件先让 A 模型完成并提交回答,再为这条消息创建 pending 记录并调用 B 模型,因此 B 模型超时、输出无效或网络失败都不会阻塞 A 模型。 首版按“完整 assistant 消息”审阅,而不是在 token 流式输出期间反复审阅半成品。这样可以避免重复计费、引用偏移变化和对未完成结论的误判。 调度规则也保持明确:同一 Session 中的审阅按消息顺序串行执行,不同 Session 的审阅可以并行。插件卸载时会停止接收新任务、取消进行中的 B 请求并等待队列收敛。 ## 你会看到什么 A 模型回答提交后,消息下方会出现第二意见入口。打开时如果 B 模型还没有完成,弹层显示“审阅中”。 ![B 模型异步审阅中](https://raw.githubusercontent.com/scwlkq/dsh-second-opinion/main/docs/assets/review-pending.png) B 模型完成后,弹层显示结论、引用原文、分析和建议。带引用的意见使用目标回答中的精确文本定位;无法匹配精确引用的意见仍会作为通用建议保留。 ![带原文引用的审阅意见](https://raw.githubusercontent.com/scwlkq/dsh-second-opinion/main/docs/assets/review-comments.png) 在 `auto` 模式中,`concern` 或 `disagree` 结论会自动要求 A 模型重新决策。原回答不会被覆盖,新的回答会追加到会话中,便于比较和追溯。 ![自动复议追加新决策](https://raw.githubusercontent.com/scwlkq/dsh-second-opinion/main/docs/assets/auto-reconsider.png) ## 环境要求 - DeepSeek Harness `0.1.2-rc.1`,这是当前已验证版本。 - Node.js `^22.19.0 || >=24.0.0`。 - `pnpm` 已加入 PATH,因为 `dsh plugin` 会把包管理操作转发给 `pnpm`。 - 已为 DSH 配置可用的模型凭证。 ## 安装插件 推荐从 npm 安装到 `web` profile: ```bash dsh plugin --profile web add dsh-second-opinion ``` 也可以直接安装 GitHub 当前源码: ```bash dsh plugin --profile web add github:scwlkq/dsh-second-opinion ``` 安装成功后重启 DSH Web: ```bash dsh --profile web ``` 插件包声明了 DSH bundle patch 和 Web browser contribution。安装命令会把包加入 profile,并让 Host 审阅服务和浏览器界面一起生效。 ## 默认的人工复议模式 默认模式是 `advisory`,不需要新增环境变量。 1. 在 DSH Web 中正常发送任务。 2. 等待 A 模型回答完成。 3. 点击回答下方的第二意见图标。 4. 查看 B 模型的结论和每条意见。 5. 选择“按此意见重新决策”或“按全部意见重新决策”。 人工操作会把已经持久化的审阅意见作为插件消息提交给当前 Agent。插件会再次确认目标 Session、目标消息和意见仍然有效,避免对已经失效的会话状态执行复议。 ## 指定独立的 B 模型 如果不配置 B 模型路由,插件会沿用生成目标回答时的 provider 和 model。若要让另一个模型独立审阅,必须同时设置 provider 和 model: ```bash export DSH_REVIEW_PROVIDER='' export DSH_REVIEW_MODEL='' dsh --profile web ``` 只设置其中一个会导致插件在加载时明确报错,不会静默退回其他模型。 ## 自动复议模式 设置以下变量后重启 DSH: ```bash export DSH_REVIEW_MODE=auto dsh --profile web ``` B 模型返回 `agree` 时不触发复议;返回 `concern` 或 `disagree` 时,插件会自动向当前 Agent 提交完整审阅意见。默认每个 turn 最多自动复议一次,而且插件建议产生的后续消息不会继续触发第二意见链,避免无限循环。 如果 B 模型返回时 Session 已经出现更新的消息,插件只保存旧审阅,不会把它自动注入后续任务。这个检查用于避免慢审阅干扰用户刚开始的新任务。 自动复议不是“悄悄替换答案”。原回答、审阅记录和新回答都保留,用户仍可以判断 B 模型的建议是否合理。 ## 全部配置项 组合包直接支持三个环境变量: | 环境变量 | 默认值 | 作用 | | --- | --- | --- | | `DSH_REVIEW_MODE` | `advisory` | 选择人工复议或自动复议。 | | `DSH_REVIEW_PROVIDER` | 未设置 | B 模型 provider ID,需和 model 一起设置。 | | `DSH_REVIEW_MODEL` | 未设置 | B 模型 model ID,需和 provider 一起设置。 | 需要控制上下文、token 或自动次数时,在 profile 的 `cordis.patch.yml` 中增加: ```yaml - id: second-opinion config: mode: advisory provider: '' model: '' reasoningEffort: high maxTokens: 900 maxContextMessages: 20 autoRevisionsPerTurn: 1 reviewToolCalls: true ``` | 配置项 | 默认值 | 说明 | | --- | --- | --- | | `mode` | `advisory` | `advisory` 只展示建议,`auto` 可自动复议。 | | `provider` | 目标消息路由 | B 模型 provider ID。 | | `model` | 目标消息路由 | B 模型 model ID。 | | `reasoningEffort` | 未设置 | 可选的 B 模型推理强度。 | | `maxTokens` | `900` | B 模型结构化输出 token 上限。 | | `maxContextMessages` | `20` | 发送给 B 模型的最近可见会话消息数量上限。 | | `autoRevisionsPerTurn` | `1` | 每个主模型 turn 的自动复议次数上限;设为 `0` 可禁止自动复议。 | | `reviewToolCalls` | `true` | 是否审阅仅含工具调用、没有非空文本的 assistant 消息。 | ## B 模型能看到什么 插件把目标回答和最多 `maxContextMessages` 条最近可见消息发送给 B provider。可见内容可能包括: - system、user 和 assistant 文本; - 工具调用名称及参数; - 工具结果存在标记; - 图片存在标记。 隐藏推理不会发送。即使如此,最近上下文仍可能包含业务信息、代码或用户输入,因此选择外部 B provider 前应先确认数据策略。 B 模型不会获得 A 模型的可执行工具。它只能调用一个非执行型的 `submit_review` 结构化响应工具,提交 `agree`、`concern` 或 `disagree` 结论及意见,不能直接修改文件、运行命令或调用业务工具。 ## 成本与延迟 每条被审阅的 assistant 消息会额外产生一次 B 模型请求。`auto` 模式遇到非 `agree` 结论后,还可能额外产生一次 A 模型请求。 可以通过以下方式控制成本: - 使用成本更低的专用 B 模型; - 调低 `maxTokens`; - 调低 `maxContextMessages`; - 将 `reviewToolCalls` 设为 `false`,跳过仅含工具调用的 assistant 消息; - 保持默认 `advisory`,只在人判断有必要时复议。 B 模型的延迟不会增加第一条 A 回答的等待时间,但会影响第二意见何时可见,以及 `auto` 模式何时出现新决策。 ## 失败与重试 下列情况会记录为审阅失败,而不是让 A 模型任务失败: - B provider 网络错误或超时; - B 模型没有调用 `submit_review`; - 结构化字段、枚举或长度不符合要求; - 插件卸载导致进行中的请求被取消。 Web 弹层会提供“重新审阅”。重复事件不会生成重复记录或重复调用;重试会复用同一目标消息的记录身份并更新状态。 ## 数据保存与界面限制 审阅数据保存在独立的 Storage Domain sidecar 中,不向 DSH Session 日志写入插件自定义事件。这样不会让不认识插件事件类型的运行时无法读取原会话。 当前 `0.1.0` 只在第二意见弹层中展示精确 quote,不会像编辑器批注一样直接装饰原 transcript DOM。插件也不会在 A 模型仍流式输出时进行增量审阅。 ## 卸载 ```bash dsh plugin --profile web remove dsh-second-opinion ``` 命令成功后重启 DSH Web 进程。 ## 本地自测 开发仓库提供单元测试、客户端测试、构建检查和真实 tarball 安装 smoke: ```bash pnpm install pnpm test pnpm run typecheck pnpm run lint pnpm run build DSH_SOURCE_ROOT=/path/to/deepseek-harness pnpm run smoke:install ``` `smoke:install` 会打包插件、安装到临时 DSH Web profile、检查 bundle 配置、加载 Host 入口,并确认浏览器模块完成注册。 ## 总结 `dsh-second-opinion` 把“让另一个模型再看一遍”变成 DSH 的独立插件能力:A 模型不被阻塞,B 模型没有工具副作用,审阅结果可持久化、可定位、可重试,并且可以由人或受限的自动策略决定是否复议。对于代码修改、上线判断、风险评估和长任务决策,这种异步第二意见可以在不牺牲首响应速度的前提下增加一道独立检查。