ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

oh-my-pi 的 In-Band 工具调用提示词模板:用纯文本协议统一 11 种模型方言

oh-my-pi 的 In-Band 工具调用提示词模板:用纯文本协议统一 11 种模型方言 oh-my-pi 的 In-Band 工具调用提示词模板用纯文本协议统一 11 种模型方言【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi本文以 prompt-template.md 为骨架剖析 oh-my-pi一个IDE 接线的 Coding Agent如何把各家大模型的工具调用function calling降级为纯文本 in-band 协议提示词模板负责声明工具以文本形式发射{{TOOLS}}负责注入一行一条 JSON 的工具目录{{DIALECT}}负责注入当前模型对应的格式指南。读完本文你将掌握这套模板的占位符语义、目录渲染实现、11 种方言的书写规范以及驱动它的源码与测试验证路径。模板是什么系统提示词中的工具调用接线层packages/ai/src/dialect/prompt-template.md全文只有寥寥十余行却是整个 in-band 工具调用机制的对外契约。其完整内容如下# Tools You may call one or more functions to assist with the user query. Tool calls are emitted as text using the exact syntax below, not as native provider tool messages. Available functions are listed inside tools/tools as one JSON object per line: tools {{TOOLS}} /tools {{DIALECT}}它传递了三个关键事实调用形式是文本而非原生消息模板明确要求模型使用下述精确语法以文本形式发射工具调用而不是 provider 原生的 tool messages。这是 in-band 协议的出发点——不依赖各家 API 的tool_calls结构把工具调用当作普通文本流从而在流式扫描端用统一的方式解析。工具目录以tools围栏注入可用函数被列举在tools/tools之间且每行一个 JSON 对象。方言指南随后注入{{DIALECT}}占位符承载当前所选模型专属的格式指南Format guide Rules。从源码结构看这份模板不是孤立的静态文件而是被 catalog.ts 以文本资源形式直接导入并做模板替换的渲染单元。占位符的运行时替换renderInbandToolPrompt 的实现模板中的两个占位符由 catalog.ts 完成替换。其核心实现如下const TOOLS_TOKEN {{TOOLS}}; const DIALECT_PROMPT_TOKEN {{DIALECT}}; export function renderToolCatalog(tools: readonly InbandTool[]): string { return tools .map(tool JSON.stringify({ type: function, function: { name: tool.name, description: tool.description ?? , parameters: toolWireSchema(tool), }, }), ) .join(\n); } export function renderInbandToolPrompt(tools: readonly InbandTool[], dialect: Dialect): string { const prompt getDialectDefinition(dialect).prompt.trim(); return promptTemplate .replace(TOOLS_TOKEN, () renderToolCatalog(tools)) .replace(DIALECT_PROMPT_TOKEN, () prompt); }这里可以看到三层结构{{TOOLS}}→renderToolCatalog(tools)对每个工具生成{type:function,function:{name:...,description:...,parameters:...}}的 JSON 对象用JSON.stringify序列化后以换行符连接正好对应模板中每行一个 JSON 对象的要求。description为空时兜底为空字符串parameters通过导入自../utils/schema的toolWireSchema(tool)生成线上传输用 JSON Schema。{{DIALECT}}→getDialectDefinition(dialect).prompt.trim()从方言注册表中取出当前Dialect的prompt即各方言.md格式指南的文本trim()后注入模板末尾。替换采用函数形式.replace(TOOLS_TOKEN, () ...)避免了$等替换串特殊字符对 JSON 内容的干扰属于对模板注入的防御性实现细节。方言注册表DIALECT 占位符的 11 种取值{{DIALECT}}能注入什么取决于 factory.ts 中注册的方言定义。该注册表完整覆盖了当前 11 种方言const DIALECT_DEFINITIONS: RecordDialect, DialectDefinition { glm: glmDefinition, hermes: hermesDefinition, kimi: kimiDefinition, xml: xmlDefinition, anthropic: anthropicDefinition, deepseek: deepseekDefinition, minimax: minimaxDefinition, harmony: harmonyDefinition, qwen3: qwen3Definition, gemini: geminiDefinition, gemma: gemmaDefinition, };每种方言对应三个要素定义于 types.ts 的DialectDefinition接口prompt: string——即注入模板的格式指南文本{{DIALECT}}的内容createScanner(options)——流式扫描器工厂负责从模型输出的文本流中解析出工具调用事件InbandScanEvent包含toolStart、toolArgDelta、toolEnd等事件类型一组渲染函数——renderToolCall、renderAssistantToolCalls、renderToolResults、renderThinking、renderTranscript用于把内部ToolCall结构反向渲染成对应方言的文本以及把多轮对话转录为方言要求的消息格式。也就是说提示词模板是发射端的契约扫描器与渲染函数则是接收端的镜像实现——二者必须严格对称模型按指南写出来的文本才能被createScanner无歧义地解析回结构化工具调用。11 种方言的书写规范速览各方言的完整格式指南分别存放于 dialect 目录 下同名.md文件如 anthropic.md、xml.md、kimi.md、deepseek.md 等以下是核心语法的横向对照Anthropic / XML / MiniMax 系XML 风格anthropic.md 规定调用必须包在function_calls块中内含一个或多个invokefunction_calls invoke nametool_nameparameter namearg_namearg value/parameter/invoke /function_calls结果以function_results块返回成功用result/stdout失败用error/stderrfunction_results result tool_nametool_name/tool_name stdoutverbatim tool result/stdout /result /function_resultsxml.md 更精简单个invoke即一次调用可自愿用tool_calls…/tool_calls包裹多个连续invoke结果一律进tool_response。从 xml.ts 的实现看XML 方言的扫描器是按xmlTagset选项在 Anthropic 扫描器与 DeepSeekDSML扫描器之间二选一而stringfalse属性用于强制把 schema 中声明为字符串的参数按 JSON 解析。minimax.md 与 Anthropic 几乎同构唯一差异是外层块名为minimax:tool_call并明确禁止使用function_calls写法。Kimi 与 DeepSeek特殊 token 系kimi.md 要求同一轮的所有调用放进一个 section每个调用由固定格式 idfunctions.NAME:INDEX加一个 JSON 参数对象组成|tool_calls_section_begin||tool_call_begin|functions.NAME:INDEX|tool_call_argument_begin|{arg:value}|tool_call_end||tool_calls_section_end|结果以## Return of functions.NAME:INDEX标题引导的 system 轮次返回。deepseek.md 使用 Unicode 全角竖线UFF5C与下划线一▁U2581构成的 DSML tokentool▁calls▁begintool▁call▁begintool_nametool▁sep{arg:value}tool▁call▁endtool▁calls▁end多个调用之间不允许任何分隔符、空格或换行必须直接串联。Harmony多 channel 系harmony.md 的模型把工具调用建模为assistant 向函数发消息调用是发往functions.function_name的commentarychannel 消息私有推理放在analysischannel工具结果则是函数回发给 assistant 的消息|start|assistant|channel|commentary tofunctions.function_name|message|{arg:value}|call|Qwen3 / HermesJSON-in-block 系qwen3.md 与 hermes.md 都要求tool_call块内包裹单行JSON 对象且arguments必须是对象而非字符串化 JSONtool_call {name:function_name,arguments:{arg:value}} /tool_callGeminiPython 字面量系gemini.md 要求调用写成tool_code围栏内的 Python函数作为default_api的方法调用参数为关键字形式支持 Python 字面量True/False/None、列表、字典并行调用写成列表tool_code default_api.function_name(argvalue, count2)对应地[rendering.ts](https://link.gitcode.com/i/ab42d979caaa3961125f255edfc89b38) 中的 pyCall/pyValue 实现了内部 ToolCall 到 Python 字面量的反向渲染——多行字符串参数用三引号 … 原样包裹避免 \n 转义污染载荷内容。 ### Gemma|| 字符串围栏系 [gemma.md](https://link.gitcode.com/i/f9462ae39c8c062062b1f090dd5c1c13) 的语法最特殊|tool_call 块内是 call:NAME{key:value,...} 形式**每个字符串值都必须用 || token 包裹**裸文本、无转义非字符串值数字、true/false、null、列表、嵌套对象则直接裸写 text |tool_callcall:function_name{path:||src/a.ts||,count:2}tool_call|注意闭合标签是tool_call|竖线在右不是/tool_call。GLMarg_key/arg_value键值对系glm.md 要求函数名紧跟tool_call起始标签同行每个参数是一对arg_key/arg_valuetool_callget_weather arg_keylocation/arg_key arg_valueBeijing/arg_value arg_keydays/arg_key arg_value3/arg_value /tool_call所有方言共通的硬性规则尽管语法各异各格式指南的 Rules 部分存在一组贯穿始终的约束它们构成了 in-band 协议的宪法name必须精确匹配目录中列出的函数MUST match a listed function。绝不 HTML 转义参数值所有正文均由正则分隔符匹配而非真实 XML 解析器读取多处文档原文read by regex (delimiter matching), NOT a real XML parser因此必须原样写出a b、、唯一保留字符是正文自身的闭合标签如/parameter、/arg_value。JSON 类方言只允许标准 JSON 字符串转义\、\\、\n。绝不自行发射结果块NEVER emit function_results/tool_response/tool_outputs yourself——结果永远由系统返回模型只读不写。先写完整调用再停所有方言都强调只有在完整写出调用块之后才发射停止序列严禁出现先说Lets run cargo clippy然后停住的残缺输出。私有推理与工具调用分离凡支持思考的方言如 Kimi、DeepSeek、Qwen3、Gemma、GLM、Harmony都要求推理放进think/thinking/analysis等专用区域绝不允许把工具调用放进推理块。测试如何验证模板与扫描器的对称性这套机制的对称性由测试用例直接守护。inband-tools.test.ts 中renders a tool prompt for every dialectL153-L161遍历全部 11 种方言调用renderInbandToolPrompt断言生成的提示词必然包含tools//tools围栏、包含name:read的工具目录项且包含各方言getDialectDefinition(dialect).prompt的首行即方言指南确实被注入。each dialect renders calls that its scanner parses backL163-L178以{ path: src/a.ts, count: 2 }为例对每个方言先用渲染函数把内部ToolCall转成文本再喂给该方言的扫描器解析回事件断言name与arguments完全一致——即发射语法与解析语法互为逆运算。此外测试中的流式分块用例如XML_PARAMETER_STREAMS模拟了标签被中途截断的真实流式场景a.ts/para后再补meter验证扫描器具备跨 chunk 增量解析能力这正是InbandScanner.feed设计为增量接口的原因。模板在系统中的落点从源码结构看renderInbandToolPrompt产出的成品提示词会被进一步接入系统提示词的完整装配流程{{TOOLS}}目录还会与仓库中标注的verbose system-prompt inventory联动渲染相关说明见 inventory.ts 的注释。整个链路可以概括为Agent 框架收集本次会话可用的工具列表InbandTool[]renderToolCatalog将每个工具序列化为一行 JSON 目录从 factory.ts 按当前模型取出对应方言的格式指南二者分别填充 prompt-template.md 的{{TOOLS}}与{{DIALECT}}形成最终系统提示词模型按指南以纯文本发射调用流式响应由同方言的createScanner增量解析回结构化ToolCall执行结果再经渲染函数转回方言格式形成闭环。这套设计使得 oh-my-pi 可以在不依赖各家 API 原生 tool-call 结构的前提下以一份统一模板加 11 份方言指南覆盖从 Anthropic 风格 XML 到 Gemma 特殊 token 的广阔模型生态任何新模型的接入本质上就是新增一份.md指南与对应的扫描器/渲染器实现。【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表