dsh-ollama-no-tools
v0.1.1
Published
DeepSeek Harness 插件:当所选 Ollama 模型不支持工具/函数调用时,从发给模型的请求中剥离工具定义,让模型退化为纯聊天模式
Maintainers
Readme
dsh-ollama-no-tools
DeepSeek Harness 插件:当所选 Ollama 模型不支持工具/函数调用时,从发给模型的请求中剥离工具定义,让模型退化为纯聊天模式。
安装
安装分两步,缺一不可:
plugin add只把包装进 profile 的依赖(package.json),不会自动写入挂载行——挂载行必须手动加到 profile 的cordis.patch.yml(见第 2 步)。
cd /Users/tristanliu/Project/deepseek-harness # 你的 harness 仓库目录
# 第 1 步:安装依赖(发布到 npm 后用包名;发布前用本地路径)
pnpm dsh plugin --profile web add dsh-ollama-no-tools
# 发布前本地开发版:pnpm dsh plugin --profile web add /Users/tristanliu/Project/dsh-ollama-no-tools第 2 步:编辑 ~/.dsh/profiles/web/cordis.patch.yml,追加挂载行(配置按需填写):
- insert:
- id: dsh-ollama-no-tools
name: 'dsh-ollama-no-tools'
config:
noToolsModels:
- gemma3-27b # 改为你那些不支持工具的模型 id
- qwen2.5
- deepseek-r1-32b
ollamaBaseURL: http://127.0.0.1:11434 # 改为你的 Ollama 地址第 3 步:重启服务:
pnpm dsh web验证:配置了 ollamaBaseURL 且探测成功时,启动日志会打印
dsh-ollama-no-tools: 已从 <url> 探测到 N 个不支持工具的模型;命中模型的对话不再报 400。
卸载时同样两步:
pnpm dsh plugin --profile web remove dsh-ollama-no-tools(删依赖)并删除上面加的挂载行(否则插件继续生效)。
解决的问题
DeepSeek Harness 是 agent 框架:每一轮模型请求都会携带工具定义(bash、fs、subagent……)。Ollama 对模板未声明工具能力的模型会整体拒绝请求(HTTP 400)——典型如 GGUF 导入的 gemma3-27b(capabilities 不含 tools)。通用路由无法预知这一点,于是用户得到的是硬失败,而不是一个可用的纯聊天模型。
写
noToolsModels时请用完整的模型短名(含后缀),例如实际模型叫gemma3-27b-abl就要写gemma3-27b-abl而非gemma3-27b——归一化只消除 registry 前缀与:tag的形态差异,不把gemma3-27b模糊匹配到gemma3-27b-abl(两个不同模型)。最省心的做法是配好ollamaBaseURL让启动探测自动并入。
工作原理
agent 循环通过 system-prompt/assemble 瀑布装配每一轮的模型输入,PromptAssembly.tools 正是后续流入请求的工具 schema 列表。本插件监听该瀑布:当会话模型命中「不支持工具」集合时,返回 tools 被清空的装配副本——请求体里不出现任何工具定义。
模型判定(均基于 Agent 的公开结构成员):
agent.options.model—— agent 的声明路由,即「本 agent 请求使用的模型」,也是权威依据;session.requestHeader().config.model—— 上一轮实际使用的模型,仅在它与声明路由一致时复用。
两者不一致(如会话中把模型从 deepseek 切到 gemma)时,说明 header 还滞后在上一轮的旧模型上
(request/header 在装配之后才写入 session 日志)——此时以声明路由为准。否则切换后的
首轮请求仍会带着工具定义发给 gemma,正是那个 400 的来源。
模型 id 匹配做了归一化,不要求逐字符一致:
- 大小写不敏感;
- 自动剥离
registry.ollama.ai/library/之类的仓库前缀与:latest之类的 tag; - 因此配置里写短名
gemma3-27b-abl、请求侧用完整 idregistry.ollama.ai/library/gemma3-27b-abl:latest也能互相命中;/api/tags探测到的形态差异同理。
配置 ollamaBaseURL 后,启动(或设置变更)时探测 GET /api/tags,自动把 capabilities 不含
tools 的模型并入命中集(best-effort,失败退回配置列表)。
注意:
noToolsModels只接受字符串数组(schemastery 校验),不再接受裸字符串。
安装(harness 通用插件方式)
cd /Users/tristanliu/Project/deepseek-harness
# 发布前用本地路径安装;发布后:pnpm dsh plugin --profile web add dsh-ollama-no-tools
pnpm dsh plugin --profile web add /Users/tristanliu/Project/dsh-ollama-no-tools然后在 profile 用户层挂载(~/.dsh/profiles/web/cordis.patch.yml):
- insert:
- id: dsh-ollama-no-tools
name: 'dsh-ollama-no-tools'
config:
noToolsModels:
- gemma3-27b
ollamaBaseURL: http://127.0.0.1:11435重启服务:pnpm dsh web。
配置
| 配置项 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
| noToolsModels | string[] | 否 | [] | 永不接收工具定义的模型 id 列表;大小写不敏感,逗号/空格分隔,支持短名或完整 id(自动剥离 registry 前缀与 :tag) |
| ollamaBaseURL | string | 否 | '' | Ollama 地址;配置后启动时自动探测无 tools 能力的模型 |
运行时修改(settings 命名空间)
插件注册 dsh-ollama-no-tools settings 命名空间(~/.dsh/settings.yaml 的 dsh-ollama-no-tools: 分节)——运行时可改,无需编辑 patch 文件:
- 组合配置(patch 层)是 base,settings 用户层覆盖它;
- settings 服务挂载时(web profile 默认有),修改即时生效,
ollamaBaseURL变更自动重新探测; - 当前通过设置 API(
settings.describe/settings.update)修改;图形化设置卡片是待落地项(见下)。
# ~/.dsh/settings.yaml
dsh-ollama-no-tools:
noToolsModels:
- gemma3-27b
ollamaBaseURL: http://127.0.0.1:11435依赖姿态(独立 npm 包)
对 harness 零类型依赖:不 import 任何 @deepseek-ai/dsh-* 类型,只依赖稳定契约(事件名 system-prompt/assemble、Agent 公开结构、settings 服务结构)。唯一运行时依赖 @deepseek-ai/schemastery(npm 上与 harness vendored 同版本 3.18.1,保证 schema 契约一致)。
UI 设置卡片(待落地)
服务端 settings 命名空间已就绪(数据层)。图形化卡片需要:独立包提供 ./client 入口(React 组件,绑定 settings.plugin.item keyed slot)→ harness 的 web-app bundle 依赖本包并挂载 client 行。依赖 npm 上 client 生态(@deepseek-ai/dsh-client-*,当前 rc.1 版本)契约对齐,属后续版本。
开发
npm install
npm run build # tsc -> lib/
npm test # vitest 行为套件
npm publish # 发布到 npm(需先登录)