
DS2API Tool Calling 终极指南DSML 与 Canonical XML 工具块格式全解析【免费下载链接】ds2apiDeepSeek-Compatible Middleware Interface: A technical exploration project in Go, focusing on high-concurrency protocol adaptation. It serves as a reference implementation for converting diverse web protocols into standardized formats.项目地址: https://gitcode.com/GitHub_Trending/ds/ds2apiDS2API 是一个用 Go 编写的 DeepSeek 兼容中间件核心价值在于高并发协议适配它把 OpenAI Chat、Responses、Claude、Gemini 等 API 请求统一转换成标准化文本上下文再把模型返回的工具调用Tool Calling解析回各协议的原生结构。其中最受关注的机制就是本文要完整拆解的DSML / canonical XML 工具块格式——理解它你就能明白 DS2API 如何稳定、防泄漏地执行工具调用。1️⃣ 为什么用 XML 工具块而不是 JSON传统 OpenAI 式tools调用依赖模型输出严格的 JSONtool_calls字段但纯文本网页对话渠道没有结构化输出通道。DS2API 的解法是让模型直接输出约定格式的 XML 文本块由兼容层负责识别和解析。这样做有三个好处协议无关不管客户端用哪种 API 格式模型侧只有一套工具输出语法️防误触发代码块、行内代码里的示例 XML 会被明确忽略不会误执行强容错对模型常见的标签拼写漂移、全角符号、漏写开标签等失误做了窄修复语义细节的权威描述见项目文档 docs/toolcall-semantics.md它是 Go 与 Node 两套解析实现的统一行为说明。2️⃣ 两种可执行工具块格式推荐格式半角管道符 DSML 外壳这是 Prompt 中要求模型输出的首选格式|DSML|tool_calls |DSML|invoke nameread_file |DSML|parameter namepath![CDATA[README.MD]]/|DSML|parameter /|DSML|invoke /|DSML|tool_calls|DSML|tool_calls最外层 wrapper一次响应可包含多个工具调用|DSML|invoke name...每次工具调用工具名必须放在name属性|DSML|parameter name...参数节点字符串值统一用![CDATA[...]]包裹兼容格式旧式 canonical XML兼容层仍接受不带协议前缀的写法参考测试夹具 tests/compat/fixtures/toolcalls/canonical_tool_call.jsontool_calls invoke nameread_file parameter namepath![CDATA[README.MD]]/parameter /invoke /tool_calls⚠️ 注意DSML 只是外壳别名进入解析器前会归一化成本地标签名tool_calls/invoke/parameter内部始终按现有 XML 解析语义处理并不是原生 DSML 全链路实现。3️⃣ 工具块格式规则清单新手速查表规则说明必须有 wrapper外层\|DSML\|tool_calls或tool_calls缺一不可调用放 invoke 内每个调用必须在invoke标签内工具名放name属性参数用 parameter每个顶层参数一个parameter name...节点字符串用 CDATA代码、路径、prompt 等一律![CDATA[...]]包裹数字/布尔保持纯文本123、true、null直接写会自动还原为对应 JSON 类型数组用重复 itemitem.../item重复子节点会被还原为数组禁止混用标签同一工具块内不要 DSML 与旧式 XML 混搭不要空参数缺参数应询问用户而非输出空占位完整指令模板由 internal/toolcall/tool_prompt.go 中的BuildToolCallInstructions生成OpenAI / Claude / Gemini 三种适配器共用同一份规则、反例与正例。4️⃣ 流式防泄漏为什么工具块不会被泄漏到正文DS2API 对流式SSE场景做了专门的筛分器stream sieve设计源码见 internal/toolstream/Go与 internal/js/helpers/stream-tool-sieve/Node核心行为✅ 已识别成功的工具调用不会回流为普通文本客户端收到的delta.tool_calls是结构化增量✅ fenced 代码块与~~~、Markdown 行内代码中的 XML 示例始终按普通文本处理不会误执行✅ 支持嵌套围栏4 反引号嵌套 3 反引号与 CDATA 内围栏保护✅ 长文本参数如command/content内的 CDATA 即使包含/parameter这类片段也不会被误判为外层结束✅ 若 wrapper 完整但内部形态不合法如用了param整块作为普通文本释放——不吞、不半漏这一层设计直接解决了社区常见的工具调用输出成文本、没被执行的痛点。5️⃣ 容错修复模型写歪了怎么办解析链路internal/toolcall/toolcalls_parse.go内置了一组窄修复专门应对真实模型的失误漏写开标签只有 closing wrapper 存在且结构证据充分时才补回缺失的 opening wrapper符号漂移全角感叹号、顿号、、CJK 尖括号〈〉、弯引号、重复的、Unicode 空白等在固定标签名上会被折回 ASCII 语义尾部分隔符|DSML|tool_calls|这类标签后多出的非结构性分隔符会被归一化未闭合 CDATA流式阶段保守缓冲收尾阶段再做窄修复但修复是有边界的参数正文、普通聊天文本、非工具壳 XML不会被广义 Unicode 归一化tool_calls_extra这类相似但非固定标签名仍按普通文本透传。6️⃣ 解析结果与参数类型还原ParseToolCallsDetailed返回结构internal/toolcall/toolcalls_parse.gocalls解析出的工具调用列表nameinputsawToolCallSyntax检测到工具块语法或命中可修复形态时为true显式空字符串参数会保留是否拒绝由工具执行侧 / 客户端 schema 校验决定参数值还原规则参数写法还原结果parameter namen123/parameter数字123parameter namearr![CDATA[[1,2]]]/parameter数组[1,2]合法 JSON 字面量多个item子节点JSON 数组CDATA 内完整 XML 结构object / arraycontent/command等原文字段受保护单个行内标签如burgent/b保留原始字符串7️⃣ 常见问题排查清单工具调用输出成文本、未执行→ 先检查模型输出是否为推荐的 DSML 外壳或兼容的 canonical XML旧式 【免费下载链接】ds2apiDeepSeek-Compatible Middleware Interface: A technical exploration project in Go, focusing on high-concurrency protocol adaptation. It serves as a reference implementation for converting diverse web protocols into standardized formats.项目地址: https://gitcode.com/GitHub_Trending/ds/ds2api创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考