前言¶
在 DSH(DeepSeek Harness)上寫 Agent 時,常見的做法是讓一個模型串行地把活幹完。遇到答案可能不穩定、需要第二個意見,或者需要交叉驗證的場景,就得自己在外層寫編排邏輯:發多次請求、合併結果、處理部分失敗。delltig/dsh-multi-model-collab 把這個動作收進了一個插件:它向當前 Profile 註冊一個 multi_model_run 工具,主 Agent 調用時,插件內部通過 ctx.llm 服務並行(或按主/副角色)發起多次模型調用,再按配置的策略聚合,返回「每個模型的獨立結果 + 聚合摘要」。下面介紹它做了什麼、怎麼裝、怎麼配。
插件定位¶
這是一個 DeepSeek Harness(dsh)插件,倉庫爲 delltig/dsh-multi-model-collab,package.json 裏 author 字段爲 applestore,版本 0.1.0,MIT 許可證。README 的自我定位很明確:不修改 dsh 源碼,是純 Cordis 插件掛載,靠 ctx.tools.register + ctx.llm 兩個接口工作。
它解決的是「一個任務讓 N 個模型各答一遍」這件事,而不是帶工具、帶會話、多步的子 Agent 委派。插件明確寫了它不硬編碼任何 API Key、端點或模型清單,模型一律用 ctx.llm.listProviders() 報告的 <provider>/<model> 路由;單個模型失敗不會讓整個工具調用失敗,只有全部模型失敗時 execute 才拋異常;調用方取消時,仍在進行的模型調用一併取消。
核心功能¶
主要能力是註冊 multi_model_run 工具。主 Agent 調用它時,插件內部按配置發起多次模型調用,再按策略聚合,把每個模型的獨立結果和聚合摘要返回給主 Agent。
執行模式有兩種:
parallel——每個模型獨立回答同一個任務,全部並行。適合要第二意見、要跨供應商一致性、答案可能有分歧的場合。primary_secondary——主模型先答;其餘模型拿到「原始任務 + 主模型草稿 +secondaryInstruction」,做審閱、糾錯與補全。適合需要一個”審稿人”、單點判斷風險高的場合。主模型失敗時自動降級爲各副模型獨立作答,而不是整體失敗。
聚合策略有三種:
all——原樣返回全部結果,不做選擇(answer爲空串)。這是默認值,理由是分歧本身往往是主 Agent 需要的信息。vote——先把文本歸一化(大小寫、標點、空白、Markdown 符號)再分組;嚴格多數則取該組代表,無嚴格多數則回退到最長答案,並在summary裏說明實際票數與回退原因。longest——取最長的成功答案作爲answer。
render() 把這些渲染成一段 Markdown(每個模型一節 + ## aggregate 摘要 + 可選 ## selected answer),主 Agent 讀到的就是這段文本。
安裝與啓用¶
方式 A:安裝到 Profile(長期生效)。在插件包目錄內(即本倉庫根目錄)執行:
dsh plugin --profile desktop add .
該命令把本包裝進 ~/.dsh/profiles/<profile>/node_modules,package.json 的 dsh.bundle.patch 指向的 cordis.patch.yml 會作爲 bundle patch 層生效。也可以用 dsh 的插件管理器,在 dsh 會話內調用:
plugin_manager(action="install_bundle", target="<本目錄絕對路徑>")
方式 B:--patch 覆蓋層,不安裝直接試。cordis.patch.yml 裏插入行的 name 是相對路徑(./lib/index.js),Loader 會把它錨定在該 patch 文件旁邊,所以無需安裝即可掛載:
dsh web --patch ./cordis.patch.yml
# 若用 pnpm 管理 dsh:
pnpm dsh web --patch ./cordis.patch.yml
# 不搶端口、不自動開瀏覽器:
dsh web --patch ./cordis.patch.yml --no-open --port 0
也可以一次性 headless 驗證:
dsh --profile <headless-profile> --patch ./cordis.patch.yml "用 multi_model_run 跑一個任務"
這裏有一個坑:headless 模板默認把 credentials 行設爲 disabled: true;如果 Profile 沒有其它層重新啓用它,API Key 會查找失敗(MISSING_CREDENTIAL)。Web / Desktop Profile 本來就啓用了該行,無需處理。
改源碼後重新構建:
npm install
npm run build # tsc -> lib/,並 node --check 校驗產物
npm test # 離線行爲測試(假 ctx.llm,不髮網絡請求)
配置¶
所有配置都在 Loader 行(cordis.yml / cordis.patch.yml)的 config: 下,改值不需要改代碼。字段與默認值如下,與 src/index.ts 的 Config 一致。
| 字段 | 類型 | 默認值 | 說明 |
|---|---|---|---|
models |
string[] |
["deepseek-official/deepseek-flash", "deepseek-official/deepseek-v4-pro"] |
默認模型組合,格式 <provider>/<model>。primary_secondary 模式下第一個是主模型。 |
mode |
parallel / primary_secondary |
parallel |
執行模式。 |
aggregate |
all / vote / longest |
all |
聚合策略。 |
defaultProvider |
string |
"" |
模型標識不帶 provider 前綴時使用哪個 provider;空則按各 provider 的目錄自動匹配。 |
system |
string |
"" |
發給每個模型的 system prompt;空則不發。 |
temperature |
number |
-1 |
採樣溫度;負數表示不發該字段(用適配器默認)。 |
maxTokens |
number |
0 |
單次調用的輸出 token 上限;0 表示不限制(用適配器默認)。 |
perModelTimeoutMs |
number |
180000 |
單個模型調用的取消預算。 |
toolTimeoutMs |
number |
900000 |
整個工具調用的協作預算;0 表示交給註冊表默認。 |
maxConcurrency |
number |
4 |
同時在飛的模型調用數上限。 |
clipChars |
number |
12000 |
每個模型返回文本的截斷長度;0 表示不截斷。未截斷長度仍記錄在 chars。 |
includeUsage |
boolean |
true |
是否上報每個模型的 token 用量(適配器提供時)。 |
secondaryInstruction |
string |
審閱指令(中英雙語) | primary_secondary 模式下要求副模型做什麼。 |
models 的默認值是示例組合,實際跑什麼模型取決於當前 Profile 裏 listProviders() 報告了哪些路由,所以默認值未必都能解析。
工具用法¶
工具名 multi_model_run。入參如下。
| 參數 | 必填 | 說明 |
|---|---|---|
task |
是 | 要執行的任務/問題。每個模型只看到這段文本,看不到當前會話,必須自帶上下文。 |
models |
否 | 本次使用的模型列表,覆蓋配置的 models。 |
mode |
否 | 本次執行模式,覆蓋配置。 |
aggregate |
否 | 本次聚合策略,覆蓋配置。 |
system |
否 | 本次 system prompt,覆蓋配置。 |
task 是唯一必填項,這意味着調用前要在 task 裏把上下文寫全。返回結構如下(節選):
{
"task": "…",
"mode": "parallel",
"aggregate": "all",
"models": ["deepseek-official/deepseek-flash", "deepseek-official/deepseek-v4-pro"],
"succeeded": 2,
"failed": 0,
"results": [
{
"provider": "deepseek-official",
"model": "deepseek-flash",
"id": "deepseek-official/deepseek-flash",
"role": "peer",
"status": "ok",
"text": "…",
"clipped": false,
"chars": 12,
"durationMs": 1840,
"error": null,
"usage": { "inputTokens": 10, "outputTokens": 5, "totalTokens": 15 }
}
],
"answer": "",
"summary": "mode=parallel aggregate=all models=2 ok=2 failed=0 elapsed=2140ms\n- OK …"
}
失敗與取消的邊界:
- 單個模型失敗(適配器報錯、拋異常、無終止 chunk、超時)→ 該條
status: "failed"+error.code,其餘模型繼續;工具整體仍然成功。 - 全部模型失敗 →
execute拋錯,錯誤信息裏帶每個模型的code: message,並帶code: "ALL_MODELS_FAILED"。 exec.signal觸發 → 已發出的模型調用被取消;若一個都沒成功則拋ABORTED。- 模型引用無法解析(例如只寫了
deepseek-flash但目錄裏匹配不到、又沒配defaultProvider)→ 拋錯並列出當前所有可用的provider/model路由。
驗證¶
離線行爲測試不髮網絡請求,共 21 個用例:
npm test
覆蓋插件契約、defineTool 參數/輸出 schema 編譯、並行執行、失敗隔離、全失敗拋錯、vote/longest 聚合、primary_secondary 的審閱 prompt 與主模型失敗降級、模型引用解析(含目錄查找與報錯文案)、文本截斷、取消、缺終止 chunk。
端到端測試(真實模型,需要已配置的供應商):
npm run e2e # 4 個真實場景,約 2 分鐘,會消耗真實 token
它會自建/複用臨時 headless profile(默認 mmcollab),掛 ./cordis.patch.yml 讓真實 Agent 調用 multi_model_run,並斷言四件事:並行雙模型都返回、單模型失敗被隔離、primary_secondary 的副模型真的審閱了草稿、全部失敗時工具調用本身報錯。
手工單跑的等價命令(需要先造臨時 headless profile):
node "<dsh>/lib/bin.js" --profile mmcollab --from-default-profile headless --dump-config
node "<dsh>/lib/bin.js" --profile mmcollab \
--patch ./verify/patch-forms/enable-credentials.yml \
--patch ./cordis.patch.yml --json \
"Call the multi_model_run tool exactly once with task='Reply with exactly the single word PONG and nothing else.' and omit every other argument. Then print the tool result verbatim."
這裏有個容易漏的點:只看退出碼不夠。Loader 對沒能激活的插件行只打印一條 stderr 警告,進程照樣 exit 0。驗收必須斷言 --json 輸出裏出現 tool_call / tool_result。
適用場景與注意¶
適合的場景:需要第二意見、需要跨供應商對同一個問題的答案做對比,或者想讓一個模型產出草稿、另一個模型審校的場合。它不承擔帶工具、多步的委派任務——那應該用子 Agent 機制。README 在設計說明裏明確寫了,這個插件走 ctx.llm.stream() 而不是複用子 Agent,因爲前者的每條調用只有一個模型請求,沒有會話、工具集和上下文;後者的每個子 Agent 有自己的 loop 和上下文,適合需要模型自己查資料再回答的任務。
使用前要注意幾點:
- 插件以當前 dsh 進程的權限運行,安裝前應檢查源碼與許可證(MIT)。
- 這些調用不是完整 Agent 回合,不會寫入 session,也不會被按會話計量的插件(如 cost-meter)統計,因爲
GenerateOptions.sessionId沒有設置。每個模型的實際用量看返回裏的usage字段(includeUsage: true時)。 - 沒有工具循環,模型只能拿到
task文本,不能自己檢索或執行命令。 vote是文本歸一化後的嚴格多數,不是語義投票。開放式答案很少逐字一致,通常會回退到最長答案,並在summary裏寫明。- 默認每個模型最多 12000 字符乘以模型數,模型多或答案長時調小
clipChars。 - README 寫明實測於 dsh
0.2.1(CLI rc.2 / 桌面打包運行時 rc.3),package.json聲明兼容性爲>=0.2.0-rc.1 <0.3.0-0。 - GitHub 上存在一個同名但無關的項目
zanapeng/dsh-multi-model-collab(2026-08 創建),它把固定的四段流水線寫死;本插件不是流水線,而是一個通用工具,選型時別裝錯。
結尾¶
這個插件的價值在於把”一個任務問多個模型”從一個需要自己搭的編排動作,收斂成 Profile 裏一個配置項加一次工具調用,同時把部分失敗、取消、聚合策略這些邊界情況處理掉了。如果你已經在 DSH 上做模型對比或交叉驗證,可以先按方式 B 掛 --patch 試一次,再決定要不要裝到 Profile。
目錄頁:https://www.skillhub.cn/plugins/delltig/dsh-multi-model-collab
GitHub:https://github.com/delltig/dsh-multi-model-collab