news 2026/9/8 22:03:39

goose Ollama Tool Shim 实战:让不支持函数调用的本地模型也能执行工具

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
goose Ollama Tool Shim 实战:让不支持函数调用的本地模型也能执行工具

goose Ollama Tool Shim 实战:让不支持函数调用的本地模型也能执行工具

【免费下载链接】goosean open source, extensible AI agent that goes beyond code suggestions - install, execute, edit, and test with any LLM项目地址: https://gitcode.com/GitHub_Trending/goose3/goose

本文聚焦 goose 的实验特性 Ollama Tool Shim:它解决"本地模型不支持原生工具调用、或偶发以纯文本形式输出工具请求"的问题。读完本篇,你将掌握完整的启用步骤与全部环境变量配置,并理解 goose 源码中"直接解析 → 内联 JSON 解析 → 解释器模型兜底"的三段式工具调用恢复管线,以及 Ollama 与内置 llama.cpp 两种解释器后端的实现差异。

需要预先说明:Tool Shim 是一个实验性功能,文档明确提示其行为与配置项可能在未来版本中变化(见 experimental/ollama.md)。

什么是 Ollama Tool Shim,何时需要启用

goose 的工具(shell、文件读写等 MCP 工具)默认依赖模型原生的 function calling 能力:模型通过 API 的结构化字段返回工具调用。但很多本地模型(尤其是经由 Ollama、llama.cpp 运行的模型)并不支持这种机制,或者行为不稳定,典型症状包括:

  • 会话中途工具突然失效——模型"调用了"工具但 goose 没有执行;
  • 模型输出的是纯文本工具格式,例如functions.shell:0 <|tool_call_argument_begin|> {...}这样的标记串,而不是 API 结构化的 tool call;
  • 推理模型把思考标签(think标记)和工具调用混在一起输出,导致解析失败。

启用 Tool Shim 后,shim 会拦截模型响应,把上述文本形式的工具请求转换成 goose 可执行的结构化工具调用。核心机制是引入一个解释器模型(interpreter model):它独立于你主对话使用的任何 provider(可以是 Ollama、llama.cpp 内置推理),专门负责从文本中"读懂"工具调用意图。完整的使用与排查指南见 guides/tool-shim.md。

快速开始

官方文档给出的最小路径只有三步:

  1. 安装并启动 Ollama;
  2. 拉取默认解释器模型mistral-nemo
ollama pull mistral-nemo
  1. 启用 shim 启动 goose:
GOOSE_TOOLSHIM=true goose session

其中mistral-nemo是源码中写死的默认解释器模型,定义于 toolshim.rs:

/// Default model to use for tool interpretation pub const DEFAULT_INTERPRETER_MODEL_OLLAMA: &str = "mistral-nemo";

工作原理:工具调用的三段式恢复管线

从源码 augment_message_with_tool_calls 的实现看,每条助手消息进入 shim 后,按以下优先级逐级处理,只有前两级都没命中时才调用解释器模型:

第一段:tokenized 标记直接解析。很多模型的文本工具输出带有固定的特殊标记,shim 用一组常量识别它们(toolshim.rs):

const TOOL_CALLS_SECTION_BEGIN: &str = "<|tool_calls_section_begin|>"; const TOOL_CALLS_SECTION_END: &str = "<|tool_calls_section_end|>"; const TOOL_CALL_BEGIN: &str = "<|tool_call_begin|>"; const TOOL_CALL_ARGUMENT_BEGIN: &str = "<|tool_call_argument_begin|>"; // ...

解析器支持两种写法:标准的name <|tool_call_argument_begin|> {json}以及省略参数标记的name {json}。工具名解析还做了大量容错——去掉:0序号、functions.前缀,把.映射成 goose 工具命名约定的__,并在多个候选名中匹配真实工具列表(见 resolve_tool_name)。

第二段:内联 JSON 解析。有些模型直接输出形如{"name": "shell", "arguments": {...}}的 JSON 指令(常伴随Using tool:前缀)。shim 用括号配对扫描提取第一个 JSON 对象并做同样容错解析(parse_inline_json_tool_calls),解析成功后会清理掉文本中残留的 JSON 工具指令,避免泄漏到最终回复。

第三段:解释器模型兜底。前两段都未命中时,消息文本连同当前可用工具列表一起发给解释器模型,由后者按固定 JSON Schema 输出{"tool_calls": [{"name", "arguments"}]};若模型判断"没有工具调用",则返回名为noop的空调用,shim 会过滤掉noop。解析完成后,无论是否成功,消息都会经过sanitize_residual_markers清洗,保证原始标记(<|tool_call_begin|>等)不会出现在用户可见的最终输出里。

单元测试 crates/goose/src/providers/toolshim.rs 中的 tests 模块 覆盖了这些路径:tokenized 标记解析、内联 JSON 解析、Windows 反斜杠路径参数的 JSON 容错、以及"直接解析优先于解释器"的优先级验证。

安全细节:execute 别名只允许"确定"的 shell 转换

部分模型会用execute/execute_code这类泛化工具名包裹Developer.shell({ command: "..." })形式的 TypeScript 代码。shim 会用 tree-sitter 对这段代码做真实语法解析,仅在唯一且明确匹配Developer.shell单参命令时才转换为 goose 的 shell 工具调用(maybe_convert_execute_to_shell_tool_call)。一旦出现多个 shell 调用、动态参数、额外参数、字符串/注释/正则里的"诱饵"文本,解析直接拒绝并把整条消息内容清空(rejected_execute),宁可放弃执行也不猜测。相关拒绝用例集中在augment_does_not_interpret_rejected_execute_marker测试中,值得作为该设计意图的证据参考。

环境变量与配置参考

变量说明默认值
GOOSE_TOOLSHIM启用 tool shim(true1false
GOOSE_TOOLSHIM_BACKEND解释器后端:ollamalocalllama.cppollama
GOOSE_TOOLSHIM_OLLAMA_MODELOllama 解释器模型mistral-nemo
GOOSE_TOOLSHIM_MODEL本地解释器后端的模型名(使用local后端且未设置LOCAL_LLM_MODEL配置时必填)

几个源码中可确认的细节,可以帮你排配置问题:

  • 布尔值解析很宽容:global_toolshim() 读取GOOSE_TOOLSHIM,parse_bool_config 接受1 / true / yes / on(小写不敏感)为真值,0 / false / no / off为假值,其余取值直接报错。
  • backend 取值同样容错:parse_toolshim_backend 除文档列出的ollama/local/llama.cpp外,还接受llama_cpp和空串(视为 ollama)。
  • 本地后端模型名有明确的优先级:resolve_local_interpreter_model 先取环境变量GOOSE_TOOLSHIM_MODEL,再回退到全局配置键LOCAL_LLM_MODEL,两者都为空时启动即报Local toolshim backend requires GOOSE_TOOLSHIM_MODEL or LOCAL_LLM_MODEL to be set
  • Ollama 地址来自统一配置:解释器请求的 base URL 由OLLAMA_HOST配置决定,默认localhost:11434(ollama.rs),解析逻辑见 get_ollama_base_url——未带协议会补http://,未带端口会补 11434。
  • 诊断入口goose doctor也会检查该开关(doctor.rs)。

三种典型使用组合

Ollama 作为主 provider

GOOSE_TOOLSHIM=true goose session

主对话与解释器都走本地 Ollama,解释器默认mistral-nemo,需要时可用GOOSE_TOOLSHIM_OLLAMA_MODEL覆盖。

自定义 OpenAI 兼容 provider

GOOSE_TOOLSHIM=true \ GOOSE_TOOLSHIM_OLLAMA_MODEL=llama3.2 \ goose session

主 provider 可以是任意 OpenAI 兼容服务(Bedrock、自建路由等)。shim 的解释器始终在本地 Ollama 上运行,与主对话使用什么 provider 无关——这正是"解释器模型独立于主 provider"设计要带来的灵活性。

内置本地推理后端(llama.cpp)

如果你本来就在用 goose 的内置本地推理,可以直接把它当解释器,无需再起一个 Ollama 实例。注意此时必须指定模型名,否则启动报错:

GOOSE_TOOLSHIM=true \ GOOSE_TOOLSHIM_BACKEND=local \ GOOSE_TOOLSHIM_MODEL=my-model-name \ goose session

对应实现 LocalInterpreter 会创建一个localprovider 并显式.with_toolshim(false),避免解释器自身再进入 shim 管线造成递归。

解释器后端实现细节

Ollama 后端使用 Ollama 的结构化输出能力:post_structured 以非流式方式调用/api/chat,并在请求体中注入固定 JSON Schema(payload["format"]),约束输出必须形如:

{ "tool_calls": [ { "name": "tool_name", "arguments": { "param1": "value1" } } ] }

系统提示词明确要求:检测到 JSON 格式的工具请求就转写为上述格式,否则返回{"tool_calls": [{"name": "noop", "arguments": {}}]}(interpret_to_tool_calls)。

为什么主模型收不到 tools 定义?在 shim 模式下 goose 向模型传空的工具列表,把工具说明改以文本形式写进系统提示词——modify_system_prompt_for_tool_json 会追加每个工具的Tool Name / Schema / Description与"一次只调一个工具、按 JSON 格式告知要调用的工具"的指令;历史消息中的工具请求/响应也会由 convert_tool_messages_to_text 降级为纯文本,因为部分 provider(如 Bedrock)会校验 tool_use/tool_result 块只能与工具定义共存。

故障排查

继承官方指南的四个高频问题:

1. 会话中途工具突然不工作。模型可能已从原生工具调用切换到文本格式。设置GOOSE_TOOLSHIM=true并重启会话。

2. shim 已启用但工具仍不执行。检查解释器后端可达性:

  • Ollama:运行ollama list确认服务在跑、解释器模型已拉取;
  • Local:确认本地推理已配置且模型名已设置(环境变量或LOCAL_LLM_MODEL)。

3. 解释器调用太慢。换一个更小更快的解释器模型:

export GOOSE_TOOLSHIM_OLLAMA_MODEL=qwen2.5:3b

4. 模型在工具调用前输出推理标签(think标记)导致解析失败。shim 会自动处理:启用后推理内容会从最终消息中剥离。

延伸阅读

  • 实验特性入口文档:documentation/docs/experimental/ollama.md
  • 完整 Tool Shim 指南:documentation/docs/guides/tool-shim.md
  • 核心实现:crates/goose/src/providers/toolshim.rs
  • 配置解析:crates/goose/src/model_config.rs
  • Ollama 默认地址常量:crates/goose-providers/src/ollama.rs

【免费下载链接】goosean open source, extensible AI agent that goes beyond code suggestions - install, execute, edit, and test with any LLM项目地址: https://gitcode.com/GitHub_Trending/goose3/goose

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 22:00:19

Claude Code生产环境必备9款插件,精准提效

讲真&#xff0c;我就是那个看到 Claude Code 插件生态就走不动道的人。2026 年还没过半&#xff0c;我已经把能试的插件基本试了一遍&#xff0c;有些装上不到半小时就卸了&#xff0c;有些让我在项目里开了“后悔药”&#xff0c;直到它们帮我解决掉大批重复劳动&#xff0c;…

作者头像 李华
网站建设 2026/9/8 21:59:24

AI与硬件结合的结构设计:从边缘算力到模型部署的工程实践

去年接项目的时候&#xff0c;有个客户提了个需求&#xff1a;用AI识别现场设备的状态&#xff0c;摄像头拍仪表盘&#xff0c;把读数自动录进系统。我第一反应是调云端的OCR接口&#xff0c;结果到现场一测彻底傻眼了——车间里网络不稳&#xff0c;一张图传上去要两三秒才能返…

作者头像 李华
网站建设 2026/9/8 21:58:05

Windows 更新后 ExplorerPatcher 失效?5 分钟修复完整指南

Windows 更新后 ExplorerPatcher 失效&#xff1f;5 分钟修复完整指南 【免费下载链接】ExplorerPatcher This project aims to enhance the working environment on Windows 项目地址: https://gitcode.com/GitHub_Trending/ex/ExplorerPatcher 刚做完 Windows 更新&am…

作者头像 李华
网站建设 2026/9/8 21:56:17

低内存MCU上的SM2国密算法实现:STM32优化实践

简介&#xff1a;这份源码将sm2国密算法完整移植到低内存stm32单片机环境&#xff0c;面向嵌入式安全开发与国密改造场景&#xff0c;适合需要在资源受限设备上集成国产密码算法、实现通信加密与数据签名的软硬件工程师。压缩包共421个文件、约6.88MB&#xff0c;以c源码、h头文…

作者头像 李华