Z Talk 是真格分享认知的栏目。
在《》中,Manus 联合创始人、首席科学家 Peak(季逸超)提到,每当团队在讨论某个功能的技术实现时,他会习惯性地思考:这个功能,能不能在产品里形成网络效应?
作为一个通用 Agent,Manus 每增加一项能力,团队就希望它能和已有功能之间产生意想不到的耦合效应。比如在加入图像读取功能后,他们发现 Manus 能自行调试生成的数据可视化代码,甚至能神奇地修复其他模块的问题。这正是他们所看重的复合效应。
昨天,Manus 官网发布了一篇新文章,Peak 分享了他manus 教程们在搭建上下文工程过程中踩过的坑和总结出的经验。这是一篇真诚、深入、极具实战价值的记录。Peak 把团队在一次次试错中淬炼出的经验系统梳理,为正在构建 AI Agent 的开发者们提供了一套可借鉴的路径,也带我们重新走了一遍 Manus 从零到一的探索过程。
Manus 还在前行。正如 Peak 在文中所说:「如果模型进步是上涨的潮水,我们希望 Manus 是船,而不是钉在海床上的柱子。」
如果你也在打造自己的 Agent,希望这些总结能帮你更快找到方向。本文转自 Founder Park,基于 Kimi K2 翻译,以下为编译原文:
在 Manus 项目伊始,我和团队就面临一个关键抉择:是利用开源基础模型训练一个端到端的智能体,还是依托前沿模型的上下文学习能力,在其之上构建智能体?
在我投身 NLP 的第一个十年里,我们并没有这种奢侈的选择。遥想当年 BERT 问世(没错,那已是七年前),模型必须先经过微调——还要评估——才能迁移到新任务。每次迭代往往耗时数周,尽管那时的模型体积与今日的 LLMs 相比微不足道。对于快速迭代的应用,尤其是 PMF 之前的阶段,如此缓慢的反馈循环几乎是致命的。这是我上一家初创公司留下的惨痛教训:当时我从零开始训练模型,用于开放信息抽取和语义搜索。随后 GPT-3 与 Flan-T5 横空出世,我那些自研模型一夜之间便失去了意义。颇具讽刺意味的是,正是这些新模型开启了上下文学习的大门,也为我们指明了一条全新的道路。
这个来之不易的教训让选择变得清晰:Manus 将押注于上下文工程。这让我们能在几小时内发布改进,而非几周,同时也让我们的产品与底层模型保持正交:如果模型进步是上涨的潮水,我们希望 Manus 是船,而不是钉在海床上的柱子。
然而,上下文工程远非一帆风顺。它是一门实验科学。我们已经四次重构了智能体框架,每一次都是在发现更好的上下文塑造方式之后。我们亲切地把这个手动进行架构搜索、提示微调和经验猜测的过程称为「随机梯度下降」(Stochastic Graduate Descent)。它并不优雅,但确实有效。
这篇文章分享了我们通过自身「SGD」抵达的局部最优解。如果你正在构建自己的 AI 智能体,希望这些原则能帮助你更快收敛。
围绕 KV-Cache 进行设计
如果只能选一个指标,我会说 KV 缓存命中率是生产级 AI 智能体最重要的单一指标,它直接影响延迟和成本。要理解原因,我们先看一个典型智能体的工作流程:
收到用户输入后,智能体通过一连串工具调用来完成任务。每一次迭代,模型都会根据当前上下文从预定义的动作空间中选择一个动作,然后在环境(如 Manus 的虚拟机沙箱)里执行该动作并产生观察结果。动作和观察结果被追加到上下文中,成为下一次迭代的输入。这个循环持续进行,直到任务完成。
可以想象,上下文在每一步都会增长,而输出——通常是一个结构化的函数调用——相对较短。这使得智能体的预填充与解码比例相比聊天机器人严重失衡。以 Manus 为例,平均输入与输出 token 的比例约为 100:1。
幸运的是,具有相同前缀的上下文可以利用 KV 缓存,从而显著降低首 token 延迟(TTFT)和推理成本,无论你是使用自托管模型还是调用推理 API。这可不是小打小闹的节省:以 Claude Sonnet 为例,缓存的输入 token 价格为 0.30 美元/百万 token,而未缓存的则高达 3 美元/百万 token,相差 10 倍。

从上下文工程的角度来看,提高 KV 缓存命中率需要遵循几个关键实践:
1. 保持提示前缀稳定。由于 LLMs 的自回归特性,即使只有一个 token 的差异,也可能从该 token 开始使整个缓存失效。一个常见错误是在系统提示开头加入时间戳——尤其是精确到秒的那种。虽然这让模型能告诉你当前时间,但也会让你的缓存命中率归零。
2. 让上下文保持追加式。避免修改之前的动作或观察结果。确保序列化是确定性的。许多编程语言和库在序列化 JSON 对象时并不保证键的顺序稳定,这会在无声无息中破坏缓存。
3. 在需要时明确标记缓存断点。某些模型提供方或推理框架不支持自动增量前缀缓存,而是要求手动在上下文中插入缓存断点。设置这些断点时,要考虑潜在的缓存过期,并至少确保断点包含系统提示的结尾。
此外,如果你使用 vLLM 等框架自行托管模型,请确保启用了前缀/提示缓存,并使用会话 ID 等技术在分布式工作节点间一致地路由请求。
通过掩码而非移除的方式约束行为选择
随着你的智能体承担更多能力,其行动空间自然会变得更加复杂。直白地说,工具数量会爆炸式增长。最近 MCP 的流行更是火上浇油。如果你允许用户自行配置工具,相信我:一定会有人把上百个神秘工具插进你精心策划的行动空间。结果,模型更容易选错动作,或走上低效的路线。简而言之,全副武装的智能体反而变得更笨。
一种自然的想法是设计一个动态的动作空间——也许用类似 RAG 的方式按需加载工具。我们在 Manus 中也尝试过。但实验结果给出了一个明确的规则:除非绝对必要,否则避免在迭代过程中动态增删工具。主要原因有两点:
1. 在大多数 LLMs 中,工具定义在序列化后通常位于上下文的前部,一般在系统提示之前或之后。因此,任何变动都会使后续所有动作与观察的 KV-cache 失效。
2. 当之前的动作和观察仍引用当前上下文中已不存在的工具时,模型会陷入混乱。在没有约束解码的情况下,这往往导致模式违规或幻觉动作。
为了在提升动作选择的同时解决这一问题,Manus 使用了一个上下文感知的状态机来管理工具可用性。它并不真正移除工具,而是在解码阶段屏蔽相应 token 的 logits,从而根据当前上下文阻止(或强制)选择某些动作。

在实践中,大多数模型提供商和推理框架都支持某种形式的响应预填充,这让你无需修改工具定义即可约束动作空间。函数调用通常有三种模式(我们以 NousResearch 的 Hermes 格式为例):
- Auto – 模型可以选择是否调用函数。实现方式:仅预填充回复前缀:<|im_start|>assistant
- Required – 模型必须调用函数,但具体调用哪个函数不受限制。实现方式:预填充到工具调用标记:<|im_start|>assistant
- Specified – 模型必须从特定子集中调用函数。实现方式:预填充到函数名开头:<|im_start|>assistant
“>
发布者:Ai探索者,转载请注明出处:https://javaforall.net/244816.html原文链接:https://javaforall.net
