- 人工智能
- 大模型
- 推理引擎
- 本地部署
- 模型推理服务
【免费下载链接】ds4
DeepSeek 4 Flash and PRO local inference engine for Metal, CUDA and ROCm
本篇文章基于仓库设计文档 misc/ANTHROPIC_LIVE_CONTINUATION.md,剖析 DS4 本地推理引擎在 Anthropic Messages 协议(/v1/messages)下如何用tool_use_id实现工具循环的"实时续接":不重放 JSON、不做检查点规范化,而是直接以采样态 KV 为前缀,只追加工具结果后缀。读完你将掌握快路径的完整判定条件、四级回退路径、"不要做"清单,以及 ds4_server.c 中对应的源码级实现与 QA 验证记录。
背景:本地工具循环为何需要"续接"而不是"重放"
Anthropic 工具循环的标准形态是:模型在一轮 assistant 输出中给出带tool_use.id的调用块,客户端执行工具后在下一轮 user 消息里以tool_result.tool_use_id回填结果。对 DS4 这类本地服务器而言,最大的工程问题是KV 缓存的一致性:
- 模型实际采样出的提示词是 DSML(DeepSeek 标记语言)形式的 token 序列,包含隐藏思考(hidden thinking)等客户端不可见内容;
- 客户端回传的可见 JSON(assistant
tool_use块 + usertool_result块)只是对采样结果的"描述",逐字节重放这一段并不一定能与采样 DSML 完全对齐; - 若每次工具回合都重新做一次前缀匹配甚至冷启动 prefill,本地多轮 Agent 循环的成本会急剧上升。
DS4 的解法是:利用协议自带的 ID 作为"实时续接句柄",只要 ID 集合与当前采样 frontier 匹配,就直接从采样 KV 上追加极小后缀,跳过一切重放与规范化。
设计原则:采样态是最高保真状态
文档开篇从两份内部设计笔记提炼出三条可复用原则(misc/ANTHROPIC_LIVE_CONTINUATION.md第 3–26 行):
- 采样出的 KV 状态是 DS4 拥有的最忠实状态。模型实际生成并缓存进 KV 的 token 序列,比任何客户端可见文本都更接近"事实"。
- 客户端可见的协议对象应当"选择"该采样状态,而非强迫 DS4 重写它。只有当既没有 live 匹配也没有持久化匹配时,才允许重写/重建。
- 工具调用正是这条规则的天然实例:
tool_use_id -> 精确的采样 DSML/KV frontier,一个 ID 就是一把打开采样态的钥匙。
从misc/RESPONSE_API.md(文档第 16–25 行引用)补充的推论同样关键:
- 协议 ID 存在的意义就是避免再次证明"已知前缀会被同样地 tokenize"——这是已证明过的事实,不需要每轮重做;
- 绑定到 live 调用 ID 的工具结果请求,只应在 live KV 上追加工具结果后缀;
- 前缀匹配与磁盘检查点始终作为重启、无状态重放、编辑、客户端/会话切换时的回退手段;
- 如果请求没有重放足够的历史,未知 ID 无法被静默修复。
Anthropic 契约与五步快路径
契约:tool_use.id↔tool_result.tool_use_id
Anthropic 协议在 assistant 输出中使用tool_use.id(形如toolu_...),在随后的 user 回合使用tool_result.tool_use_id。对只有一个 live KV 会话的本地服务器来说,只要 live 会话仍停留在记忆中的 token 位置,这个 ID 就足以证明"下一个请求正是从刚采样的 assistant 工具调用 frontier 继续的"。
快路径流程(文档第 35–51 行)
- 模型采样出一个 Anthropic 工具调用;
- DS4 分配/记住
toolu_...ID,并将 live KV 原样保留为采样态(包括隐藏思考与原始 DSML); - 下一个
/v1/messages请求携带带这些 ID 的tool_result块; - DS4 校验 live token 位置与 ID 集合是否匹配;
- DS4只 tokenize 如下后缀并追加到 live 采样前缀上:
<|end▁of▁sentence|><|User|><tool_result>...<|Assistant|><think-or-/think>这一步同时达成两个目标:
- 避免工具调用后的检查点规范化(canonicalization)——不再需要把采样态"压平"成客户端可见形态再缓存;
- 避免依赖重放的 JSON 工具块与采样 DSML 逐字节一致——这是传统重放方案最容易踩坑的地方(BPE 合并、隐藏思考缺失等)。
回退路径(Fallbacks)
当 live Anthropic ID 绑定丢失时(文档第 53–66 行),DS4 按以下顺序回退到普通重放:
- 精确 token 前缀匹配;
- live 渲染文本前缀 + 后缀重新 tokenize;
- 磁盘字符串前缀 KV 检查点;
- 冷 prefill。
回退成立的先决条件是:请求在tool_result之前重放了 assistant 的tool_use块。此时"精确 DSML 工具记忆(tool memory)"可以从工具 ID 恢复采样到的工具调用字节。反过来,如果请求只含某个未知 live ID 的tool_result、且没有重放先前的 assistant 调用,DS4 应返回明确的 400,要求客户端重放完整历史——因为没有任何安全的前缀可以重建。
三条"不要做"的边界
文档第 68–76 行明确划定了实现红线,理解这些边界比理解快路径本身更重要:
- 不要为了掩盖 live 续接失配而新增 RAM 快照缓存(rewind checkpoint)。Anthropic 场景的真正问题不是缺少回退检查点,而是协议本身已通过工具 ID 标识了 live frontier——加缓存是治错方向;
- 不要为了匹配客户端 JSON 而对 live 工具调用检查点做规范化。只要 DS4 持有原始采样 DSML 且 live ID 匹配,live 状态应当胜出;
- 不要在字符串边界上复用整份渲染请求中已 tokenize 的后缀 token。缓存/续接决策之后,后缀必须重新 tokenize——整段请求的 BPE 可能跨过该字节边界完成合并,直接复用会导致前后缀错位。
源码实现级解析
以下对照 ds4_server.c 的关键路径,说明快路径在代码里如何落地。
请求校验:anthropic_validate_tool_results
位于 ds4_server.c。它对 messages 建立call_id -> 先前 assistant 消息的 O(1) 映射(rax 树),逐个检查每条tool_result尾消息中的 ID:
- ID 要么命中某个 slot 的
anthropic_live实时态(anthropic_live_has_call_id,ds4_server.c); - 要么能在请求自身重放的先前 assistant
tool_use块中找到(走精确 DSML 重放路线); - 两者皆无则直接报错:
Anthropic continuation state is not available for tool_use_id %s; retry by replaying the full messages history,并把requires_live_tool_state置位。
实时态记忆与匹配
anthropic_live_remember(ds4_server.c):模型采样出工具调用后,记录 ID 集合与当前ds4_session_pos(token 位置);anthropic_live_matches_request(ds4_server.c):要求valid、live_tokens == live_tokens、ID 数量与集合完全一致——注意是"全量匹配",部分 ID 集合不会通过;anthropic_prepare_live_continuation(ds4_server.c):从请求尾部剥离出tool_result尾消息,收集全部ID(chat_msg_collect_tool_call_ids,ds4_server.c,会遍历tool_call_ids_len全部 ID 而非只看第一个/最后一个),并渲染出只含工具结果尾部的后缀文本。
后缀渲染与拼接:anthropic_live_continuation_prompt
位于 ds4_server.c。前置条件齐全(API_ANTHROPIC、有 live 后缀文本、ID 非空、anthropic_live_matches_request通过、live token 长度与live_pos一致)后,调用build_live_prompt_suffix(ds4_server.c)完成采样态保留 + 后缀追加。该函数明确注释了核心原则:live 图是权威的,保留其采样 tokenization,只 tokenize 请求中位于其后的字节;复用整段请求已 tokenize 的 token 是错的,因为完整 prompt 的 BPE 可能已跨字节边界合并。
主流程调度、日志与失效清理
在 prefill 主流程(ds4_server.c)中,续接优先级为 Responses live → Anthropic live → thinking live → 常规 token/text/disk 匹配。命中 Anthropic live 时cache_source置为anthropic-tool-output,并输出文档记录的日志(ds4_server.c):
ds4-server: anthropic live continuation match=tool-output-ids ids=%d cached=%d prompt=%d其中cached即 live token 计数。若requires_live_tool_state为真却未命中任何缓存,则返回 409/400 级错误要求重放完整历史(ds4_server.c)。请求处理结束后,若本请求没有续接成功,旧 live 绑定会被清理(anthropic_live_clear,ds4_server.c),避免陈旧绑定污染后续请求。多槽位场景下,job_required_slot_locked(ds4_server.c)会优先把请求钉在持有匹配 live ID 的槽位上,对应的槽位绑定测试见 tests/ds4_test.c。
QA 清单与实测记录
单元/集成测试覆盖
文档第 78–88 行的 QA 清单要求(与实现一一对应):
- 单元:
tool_result.tool_use_id被解析并收集——由chat_msg_collect_tool_call_ids与请求解析器覆盖; - 单元:Anthropic live 后缀只渲染 EOS、工具结果与 assistant 前缀,不包含先前的 assistant 工具调用——由
anthropic_prepare_live_continuation的尾部裁剪逻辑保证; - 集成:匹配的 live ID 构建出的 effective prompt 其缓存前缀长度等于 live token 数——
anthropic_live_continuation_prompt返回live_tokens->len作为 cached 长度; - 单元:仅含未知 ID 的
tool_result请求被拒绝——anthropic_validate_tool_results的报错分支; - 集成:Claude Code 可在不做工具后检查点规范化、不做多余 prefill 的前提下跑通多轮工具会话;
- 回归:Responses 协议的 live 续接不受影响。
ds4_test.c 中有对应的工具结果续接测试:先发送带工具调用的请求,tool_memory_remember记录调用后,用test_tool_result_request_json构造第二轮回合请求并断言续接成功。
实测日志与负向检查(文档第 108–129 行 QA Log)
make ds4_test: pass ./ds4_test --server: pass make ds4-server: pass Claude Code through ~/bin/claude-ds4 against /v1/messages: pass - Prompt forced two Bash tool calls in one assistant turn. - Server logged: anthropic live continuation match=tool-output-ids ids=2 cached=24002 prompt=24041 chat ctx=24002..24041:39 TOOLS prompt done 0.873s - The trace contained no post-tool `tool checkpoint canonicalization` event.注意ids=2表示一次 assistant 回合内有两个 Bash 工具调用被同时续接,且cached=24002与prompt=24041的差正好是追加的 39 token 后缀;整个续接 prefill 耗时 0.873s,全程无规范化事件。负向检查(未知tool_use_id且未重放先前 assistant 调用)则返回:
HTTP/1.1 400 Bad Request unknown Anthropic tool_result tool_use_id toolu_unknown; replay full messages当前实现状态小结
文档第 90–107 行记录的实现要点,与 ds4_server.c 现状一致:
- speculative RAM KV 重启缓存已被移除——它在为错误的问题打补丁:Anthropic 协议本身已通过
tool_use_id给出精确的 live 续接键; chat_msg现在保留一条消息中全部工具结果 ID(而非仅首个/末个),因为 Anthropic 允许一个 user 消息携带多个tool_result块,部分 ID 集合会让续接不安全;- Anthropic live 状态只保存采样 token frontier 与生成的工具调用 ID;Responses 协议因为存在可见前缀续接模式,还会额外保存可见重放文本;
tool_result请求只在两种情况下被接受:ID 匹配当前 live Anthropic 工具调用 frontier;或请求重放了先前的 assistanttool_use块(走精确 DSML 重放 + 前缀匹配);- 既无 live 状态又未重放先前工具调用的
tool_result请求返回 HTTP 400,并要求回传完整 messages。
这套设计的核心价值可以浓缩为一句话:把协议 ID 当作采样态的指针,而不是把客户端 JSON 当作事实来源。它让本地工具循环从"每轮重放 + 规范化"降级为"ID 校验 + 极小后缀追加",在保证 KV 缓存命中的同时,也守住了隐藏思考等采样态内容的忠实性。
- 人工智能
- 大模型
- 推理引擎
- 本地部署
- 模型推理服务
【免费下载链接】ds4
DeepSeek 4 Flash and PRO local inference engine for Metal, CUDA and ROCm
相关推荐
ArcKit /arckit:ai-playbook实战:一条命令跑完UK政府AI Playbook负责任AI评估
ArcKit /arckit:ai playbook实战:一条命令跑完UK政府AI Playbook负责任AI评估 ArcKit(企业架构治理框架)的 /arc
人工智能大模型推理引擎本地部署模型推理服务XPipe服务器连接管理工具深度解析
XPipe服务器连接管理工具深度解析 项目概述 XPipe是一款革命性的shell连接中心和远程文件管理器,让您能够从本地机器轻松访问整个服务器基础设施。它基于
桌面应用开发工具运维Flutter ShadcnUI:终极Flutter UI组件库完全指南
Flutter ShadcnUI:终极Flutter UI组件库完全指南 Flutter ShadcnUI是一个功能强大的Flutter UI组件库,它将流行的
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考