技术

Agent与软件开发 提升Agent能力——上下文工程 llm评测 rl微调 分布式Agent与A2A deepresearch梳理 mcp学习 SSE 和 WebSocket 是什么? AutoGen学习 Python ioc 从0到1构建一个db 上下文记忆 agentic rag 图数据库的一些考量 推理LLM梳理 Agent实践 LLM预训练 向量数据库的一些考量 fastapi+sqlalchemy进行项目开发 LLM微调实践 Python协程实现 Agent Functon Calling LLamaIndex入门 另一种微服务架构Multi-Agent Python虚拟机 LangGraph工作流编排 Python实践 增强型 LLM——Agent 激发LLM涌现——提示工程 LLM微调理论 大佬谈LLM LLM外挂知识库 LLMOps 多模态LLM Python一些比较有意思的库 Transformers源码学习 LangChain源码学习 通用分布式计算引擎Ray Python并发 go依赖注入 go collection gc的基本原理 golang性能分析及优化 数据湖 高性能计算与存储 Linux2.1.13网络源代码学习 《大数据经典论文解读》 三驾马车学习 Spark 内存管理及调优 Yarn学习 从Spark部署模式开始讲源码分析 容器狂占内存资源怎么办? 多角度理解一致性 golang io使用及优化模式 Flink学习 c++学习 学习ebpf go设计哲学 ceph学习 学习mesh kvm虚拟化 学习MQ go编译器以及defer实现 学习go 为什么要有堆栈 汇编语言 计算机组成原理 运行时和库 Prometheus client mysql 事务 mysql 事务的隔离级别 mysql 索引 坏味道 学习分布式 学习网络 学习Linux go堆内存分配 golang 系统调用与阻塞处理 Goroutine 调度过程 重新认识cpu mosn有的没的 负载均衡泛谈 单元测试的新解读 《Redis核心技术与实现》笔记 《Prometheus监控实战》笔记 Prometheus 告警学习 calico源码分析 对容器云平台的理解 Prometheus 源码分析 并发的成本 基础设施优化 hashicorp raft源码学习 docker 架构 mosn细节 与微服务框架整合 Java动态代理 编程范式 并发通信模型 《网络是怎样连接的》笔记 go channel codereview gc分析 jvm 线程实现 go打包机制 go interface及反射 如何学习Kubernetes 《编译原理之美》笔记——后端部分 《编译原理之美》笔记——前端部分 Pilot MCP协议分析 go gc 内存管理玩法汇总 软件机制 istio流量管理 Pilot源码分析 golang io 学习Spring mosn源码浅析 MOSN简介 《datacenter as a computer》笔记 学习JVM Tomcat源码分析 Linux可观测性 学习存储 学计算 Gotty源码分析 kubernetes operator kaggle泰坦尼克问题实践 kubernetes扩缩容 神经网络模型优化 直觉上理解深度学习 如何学习机器学习 TIDB源码分析 什么是云原生 Alibaba Java诊断工具Arthas TIDB存储——TIKV 《Apache Kafka源码分析》——简介 netty中的线程池 guava cache 源码分析 Springboot 启动过程分析 Spring 创建Bean的年代变迁 Linux内存管理 自定义CNI IPAM 共识算法 spring redis 源码分析 kafka实践 spring kafka 源码分析 Linux进程调度 让kafka支持优先级队列 Codis源码分析 Redis源码分析 C语言学习 《趣谈Linux操作系统》笔记 docker和k8s安全访问机制 jvm crash分析 Prometheus 学习 Kubernetes监控 Kubernetes 控制器模型 容器日志采集 容器狂占资源怎么办? Kubernetes资源调度——scheduler 时序性数据库介绍及对比 influxdb入门 maven的基本概念 《Apache Kafka源码分析》——server Kubernetes类型系统 源码分析体会 《数据结构与算法之美》——算法新解 Kubernetes源码分析——controller mananger Kubernetes源码分析——apiserver Kubernetes源码分析——kubelet Kubernetes介绍 ansible学习 Kubernetes源码分析——从kubectl开始 jib源码分析之Step实现 线程排队 jib源码分析之细节 跨主机容器通信 jib源码分析及应用 为容器选择一个合适的entrypoint kubernetes yaml配置 《持续交付36讲》笔记 mybatis学习 程序猿应该知道的 无锁数据结构和算法 CNI——容器网络是如何打通的 为什么很多业务程序猿觉得数据结构和算法没用? 串一串一致性协议 当我在说PaaS时,我在说什么 《数据结构与算法之美》——数据结构笔记 PouchContainer技术分享体会 harbor学习 用groovy 来动态化你的代码 精简代码的利器——lombok 学习 《深入剖析kubernetes》笔记 编程语言那些事儿 rxjava3——背压 rxjava2——线程切换 spring cloud 初识 《深入拆解java 虚拟机》笔记 《how tomcat works》笔记 hystrix 学习 rxjava1——概念 Redis 学习 TIDB 学习 如何分发计算 Storm 学习 AQS1——论文学习 Unsafe Spark Stream 学习 linux vfs轮廓 《自己动手写docker》笔记 java8 实践 中本聪比特币白皮书 细读 区块链泛谈 比特币 大杂烩 总纲——如何学习分布式系统 hbase 泛谈 forkjoin 泛谈 看不见摸不着的cdn是啥 《jdk8 in action》笔记 程序猿视角看网络 bgp初识 calico学习 AQS——粗略的代码分析 我们能用反射做什么 web 跨域问题 《clean code》笔记 《Elasticsearch权威指南》笔记 mockito简介及源码分析 2017软件开发小结—— 从做功能到做系统 《Apache Kafka源码分析》——clients dns隐藏的一个坑 《mysql技术内幕》笔记 log4j学习 为什么netty比较难懂? 递归、回溯、动态规划 apollo client源码分析及看待面向对象设计 学习并发 docker运行java项目的常见问题 OpenTSDB 入门 spring事务小结 分布式事务 javascript应用在哪里 《netty in action》读书笔记 netty对http2协议的解析 ssl证书是什么东西 http那些事 苹果APNs推送框架pushy apple 推送那些事儿 编写java框架的几大利器 java内存模型和jvm内存布局 java exception Linux IO学习 netty内存管理 测试环境docker化实践 netty在框架中的使用套路 Nginx简单使用 《Linux内核设计的艺术》小结 Go并发机制及语言层工具 Linux网络源代码学习——数据包的发送与接收 《docker源码分析》小结 docker namespace和cgroup zookeeper三重奏 数据库的一些知识 Spark 泛谈 链式处理的那些套路 netty回顾 Thrift基本原理与实践(二) Thrift基本原理与实践(一) 回调 异步执行抽象——Executor与Future Docker0.1.0源码分析 java gc Jedis源码分析 深度学习泛谈 Linux网络命令操作 JTA与TCC 换个角度看待设计模式 Scala初识 向Hadoop学习NIO的使用 以新的角度看数据结构 并发控制相关的硬件与内核支持 systemd 简介 quartz 源码分析 基于docker搭建测试环境(二) spring aop 实现原理简述 自己动手写spring(八) 支持AOP 自己动手写spring(七) 类结构设计调整 分析log日志 自己动手写spring(六) 支持FactoryBean 自己动手写spring(九) 总结 自己动手写spring(五) bean的生命周期管理 自己动手写spring(四) 整合xml与注解方式 自己动手写spring(三) 支持注解方式 自己动手写spring(二) 创建一个bean工厂 自己动手写spring(一) 使用digester varnish 简单使用 关于docker image的那点事儿 基于docker搭建测试环境 分布式配置系统 JVM执行 git maven/ant/gradle/make使用 再看tcp kv系统 java nio的多线程扩展 《Concurrency Models》笔记 回头看Spring IOC IntelliJ IDEA使用 Java泛型 vagrant 使用 Go常用的一些库 Python初学 Goroutine 调度模型 虚拟网络 《程序员的自我修养》小结 Kubernetes存储 访问Kubernetes上的Service Kubernetes副本管理 Kubernetes pod 组件 Go基础 JVM类加载 硬币和扑克牌问题 LRU实现 virtualbox 使用 ThreadLocal小结 docker快速入门

架构

大模型infra OpenTelemetry及生态 大模型可观测性 grpo演进 rlhf演进 agent框架 reward演进 大模型RLHF框架 rl框架 GPU与CUDA RL闲谈 MCTS与LLM rl从Policy Gradient(策略梯度)到PPO到GRPO 从Transformer到DeepSeek bert rerank微调 大模型推理tips RAG向量检索与微调 dddfirework源码分析 RAG与知识图谱 大模型推理服务框架vLLM 大模型推理服务框架 模型服务化(未完成) 大模型Post-Training 大模型训练 大模型推理 从Attention到Transformer k8s设备管理 ddd从理念到代码 如何应用LLM 小鼠如何驾驭大象(LLM)? 多类型负载协调员Koordinator controller-runtime细节分析 finops学习 kubevela多集群 kubevela中cue的应用 基于k8s的工作流 kubevela源码分析 容器和CPU那些事儿 数据集管理fluid 应用管理平台kubevela karmada支持crd 多集群管理 AutoML和AutoDL 特征平台 实时训练 分布式链路追踪 K8S YAML 资源清单管理方案 tensorflow原理——python层分析 如何学习tensorflow 数据并行——allreduce 数据并行——ps 推荐系统embedding原理及实践 机器学习中的python调用c 机器学习训练框架概述 tensornet源码分析 大模型训练和推理 X的生成——特征工程 tvm tensorflow原理——core层分析 模型演变 《深度学习推荐系统实战》笔记 keras 和 Estimator tensorflow分布式训练 分布式训练的一些问题 基于Volcano的弹性训练 图神经网络 pytorch弹性分布式训练 从混部到统一调度 从RNN到Attention pytorch分布式训练 CNN 《动手学深度学习》笔记 pytorch与线性回归 多活 volcano特性源码分析 推理服务 kubebuilder 学习 mpi 学习pytorch client-go学习 提高gpu 利用率 GPU与容器的结合 GPU入门 AI云平台梳理 tensorflow学习 tf-operator源码分析 k8s批处理调度/Job调度 喜马拉雅容器化实践 Kubernetes 实践 学习rpc BFF openkruise学习 可观察性和监控系统 基于Kubernetes选主及应用 《许式伟的架构课》笔记 Admission Controller 与 Admission Webhook 发布平台系统设计 k8s水平扩缩容 Scheduler如何给Node打分 Scheduler扩展 深入controller openkruise cloneset学习 controller-runtime源码分析 pv与pvc实现 csi学习 client-go informer源码分析 kubelet 组件分析 调度实践 Pod是如何被创建出来的? 《软件设计之美》笔记 mecha 架构学习 Kubernetes events学习及应用 CRI——kubelet与容器引擎之间的接口 资源调度泛谈 业务系统设计原则 grpc学习 元编程 以应用为中心 istio学习 下一代微服务Service Mesh 《实现领域驱动设计》笔记 概率论 serverless 泛谈 《架构整洁之道》笔记 处理复杂性 那些年追过的并发 服务器端编程 网络通信协议 架构大杂烩 如何学习架构 《反应式设计模式》笔记 项目的演化特点 反应式架构摸索 函数式编程的设计模式 服务化 ddd反模式——CRUD的败笔 研发效能平台 重新看面向对象设计 业务系统设计的一些体会 函数式编程 《左耳听风》笔记 业务程序猿眼中的微服务管理 DDD实践——CQRS 项目隔离——案例研究 《编程的本质》笔记 系统故障排查汇总及教训 平台支持类系统的几个点 代码腾挪的艺术 abtest 系统设计汇总 《从0开始学架构》笔记 初级权限系统设计 领域驱动理念 现有上传协议分析 移动网络下的文件上传要注意的几个问题 推送系统的几个基本问题 做配置中心要想好的几个基本问题 不同层面的异步 分层那些事儿 用户认证问题 资源的分配与回收——池 消息/任务队列

标签

k8s设备管理 多类型负载协调员Koordinator controller-runtime细节分析 finops学习 kubevela多集群 kubevela中cue的应用 基于k8s的工作流 kubevela源码分析 容器和CPU那些事儿 数据集管理fluid 应用管理平台kubevela karmada支持crd 多集群管理 K8S YAML 资源清单管理方案 从混部到统一调度 volcano特性源码分析 kubebuilder 学习 client-go学习 tf-operator源码分析 k8s批处理调度/Job调度 喜马拉雅容器化实践 Kubernetes 实践 openkruise学习 基于Kubernetes选主及应用 Admission Controller 与 Admission Webhook k8s水平扩缩容 Scheduler如何给Node打分 Scheduler扩展 深入controller openkruise cloneset学习 controller-runtime源码分析 pv与pvc实现 csi学习 client-go informer源码分析 kubelet 组件分析 调度实践 Pod是如何被创建出来的? Kubernetes events学习及应用 CRI——kubelet与容器引擎之间的接口 资源调度泛谈 如何学习Kubernetes 以应用为中心 kubernetes operator kubernetes扩缩容 serverless 泛谈 什么是云原生 自定义CNI IPAM docker和k8s安全访问机制 Kubernetes监控 Kubernetes 控制器模型 Kubernetes资源调度——scheduler Kubernetes类型系统 Kubernetes源码分析——controller mananger Kubernetes源码分析——apiserver Kubernetes源码分析——kubelet Kubernetes介绍 Kubernetes源码分析——从kubectl开始 kubernetes yaml配置 CNI——容器网络是如何打通的 当我在说PaaS时,我在说什么 《深入剖析kubernetes》笔记 Kubernetes存储 访问Kubernetes上的Service Kubernetes副本管理 Kubernetes pod 组件
Agent与软件开发 大模型infra 提升Agent能力——上下文工程 llm评测 大模型可观测性 rl微调 grpo演进 rlhf演进 agent框架 分布式Agent与A2A reward演进 deepresearch梳理 mcp学习 大模型RLHF框架 rl框架 GPU与CUDA RL闲谈 MCTS与LLM rl从Policy Gradient(策略梯度)到PPO到GRPO AutoGen学习 从Transformer到DeepSeek 上下文记忆 agentic rag bert rerank微调 大模型推理tips 推理LLM梳理 Agent实践 LLM预训练 RAG向量检索与微调 LLM微调实践 RAG与知识图谱 大模型推理服务框架vLLM Agent Functon Calling LLamaIndex入门 另一种微服务架构Multi-Agent LangGraph工作流编排 大模型推理服务框架 模型服务化(未完成) 大模型Post-Training 大模型训练 大模型推理 从Attention到Transformer 增强型 LLM——Agent 激发LLM涌现——提示工程 LLM微调理论 大佬谈LLM LLM外挂知识库 LLMOps 多模态LLM Transformers源码学习 LangChain源码学习 如何应用LLM 小鼠如何驾驭大象(LLM)? AutoML和AutoDL 特征平台 实时训练 tensorflow原理——python层分析 如何学习tensorflow 数据并行——allreduce 数据并行——ps 推荐系统embedding原理及实践 机器学习中的python调用c 机器学习训练框架概述 tensornet源码分析 大模型训练和推理 X的生成——特征工程 tvm tensorflow原理——core层分析 模型演变 《深度学习推荐系统实战》笔记 keras 和 Estimator tensorflow分布式训练 分布式训练的一些问题 基于Volcano的弹性训练 图神经网络 pytorch弹性分布式训练 从RNN到Attention pytorch分布式训练 CNN 《动手学深度学习》笔记 pytorch与线性回归 推理服务 mpi 学习pytorch 提高gpu 利用率 GPU与容器的结合 GPU入门 AI云平台梳理 tensorflow学习 kaggle泰坦尼克问题实践 神经网络模型优化 概率论 直觉上理解深度学习 如何学习机器学习 深度学习泛谈

提升Agent能力——上下文工程

2025年07月19日

简介(未完成)

未命名

从Prompt Engineering到Context Engineering跟AI开发相关的大部分工作,都是围绕着如何把上下文窗口填充正确来进行的。随着LLM性能的进步,人们不再需要为了想出一个像咒语一样的prompt而绞尽脑汁了。但是,随着agent系统的动态性、复杂性逐步增加,保持每一次都能把context组装正确和完整,已经不是一件简单的事情了。这就需要Context Engineering这样一个专业的词汇来指代一整套系统化的方案。Context Engineering包含了所有对组装正确的上下文起到关键作用的技术组件。为了从大量文档内容中选出跟当前任务更相关的数据,就需要retrieve技术(RAG);为了向模型传达长期记忆和短期记忆,就需要memory工程;为了更好地决策未来,就需要把当前状态以及历史信息传达给模型;另外,还需要一系列的错误处理、恢复、以及guardrails机制。所有这些,都属于Context Engineering的范畴。至少包括

  1. 静态的prompt及instruction。
  2. RAG返回的片段。
  3. web搜索返回的页面内容。
  4. 对于工具候选集合的描述。
  5. 工具调用的历史结果。
  6. 长期记忆及短期记忆。
  7. 程序运行的其他历史轨迹信息。
  8. 出错信息。
  9. 系统执行过程中通过human-in-the-loop获取到的用户反馈。 Context Engineering并不是某一种具体的技术,而更像是一种思想或观念。它也暗含了AI技术圈(尤其是深入一线的工程师们)对于未来技术趋势的一种判断。AI应用开发在本质上可以看成是,从海量信息中找到恰当的有效信息,最终适配到LLM的上下文窗口上。为了让这个漏斗工作得更高效,你需要检索、过滤、排序。你需要一套完整的Context Engineering工程架构。PS: 其实主要就是指令、记忆、知识。优化context(构建一个好用的单agent)也是从优化这几个方面着手:记忆召回+工具选择+知识检索

别再构建多智能体了来自全球首位AI程序员Devin,热门AI应用DeepWiki的开发团队,Cognition AI认为在2025年的技术水平下,追求让多个AI智能体并行协作的架构,是一种脆弱且极易失败的歧途。为什么?关键在于“上下文灾难”:

  1. 信息孤岛: 并行工作的子智能体无法看到彼此的进展和决策,就像蒙着眼睛的工匠,最终做出的“零件”风格迥异、无法组装。
  2. 决策冲突: 智能体的每一个行动都包含着“隐性决策”。当多个智能体独立决策时,这些决策极有可能相互冲突,导致整个项目走向混乱。

出路何在?拥抱“上下文工程(Context Engineering)”:Cognition AI 团队提出,构建可靠AI智能体的关键,不是增加智能体的数量,而是精细化地管理和传递信息。他们主张采用单线程线性架构,确保信息流的完整和连续,让每一步行动都基于完整的历史背景。对于超长任务,他们则提出用一个专门的模型来智能“压缩上下文”,而非粗暴地将任务分包。

HTML于1993年问世。2013年,Facebook向世界发布了React。如今已是2025年,React(及其衍生技术)主导了开发者构建网站和应用的方式。为什么?因为React不仅仅是一个编写代码的脚手架,它是一种哲学。通过使用React,你欣然接受了一种以响应式和模块化模式构建应用的方式——人们现在认为这是一种标准要求,但在早期Web开发者看来,这并非理所当然。在LLM和构建AI智能体的时代,感觉我们仍像是在玩弄原始的HTML和CSS,试图弄清楚如何将它们组合起来以创造良好的体验。除了某些最基础的概念外,还没有哪一种构建智能体的方法成为标准

在2025年,市面上的模型已经极其智能。但即使是最聪明的人,如果缺乏对任务上下文的理解,也无法有效地完成工作。“提示工程(Prompt engineering)”这个词被创造出来,指的是为LLM聊天机器人以理想格式编写任务所需的努力。而“上下文工程”则是它的下一个层次。它关乎在一个动态系统中自动完成这件事。这需要更精细的把握,并且实际上是构建AI智能体的工程师们的首要工作。以一种常见的智能体类型为例。这种智能体:

  1. 将工作分解成多个部分
  2. 启动子智能体来处理这些部分
  3. 最后(一个总结智能体)将结果合并 这是一个诱人的架构,特别是当你的任务领域包含多个并行组件时。然而,它非常脆弱。关键的失败点在于:假设你的任务是“构建一个Flappy Bird的克隆版”。它被分解为子任务1“构建一个带有绿色管道和碰撞区的移动游戏背景”和子任务2“构建一个可以上下移动的小鸟”。结果,子智能体1实际上误解了你的子任务,开始构建一个看起来像《超级马里奥》的背景。子智能体2为你构建了一只鸟,但它看起来不像游戏素材,其移动方式也与Flappy Bird中的完全不同。现在,最终的智能体只能面对一个棘手的任务:将这两个沟通失误的产物组合起来。

从Prompt Engineering到Context Engineering具备高度自主性的Agent,一般来说是由agent loop驱动的运行模式。在每一个循环迭代中,它借助LLM动态决策,自动调用适当的工具,存取恰当的记忆,向着任务目标不断前进,最终完成原始任务。然而,这种agent loop的运行模式,直接拿到企业生产环境中却很难长时间稳定运行。这种所谓的「tool calling loop」在连续运行10~20轮次之后一般就会进入非常混乱的状态,导致LLM再也无法从中恢复。Dex Horthy质疑道,即使你通过努力调试让你的Agent在90%的情况下都运行正确,这还是远远达不到“足以交付给客户使用”的标准。想象一下,应用程序在10%的情况下会崩溃掉,没有人能够接受这个。可以说,Agent无法长时间稳定运行的原因,大部分都能归结到系统送给LLM的上下文 (Context) 不够准确

  1. 所以说,Context Engineering产生的第一个背景就是,AI技术落地已经进入了一个非常专业化的时代。这就好比,对于流行歌曲,很多人都能哼上两句。你不管是自娱自乐,还是朋友聚会唱K,这当然没问题。但是,如果你真的要去参加“中国好声音”并拿个名次回来,那就不是一回事了。类似地,Context Engineering这一概念的提出,对于Agent开发的交付质量提升到了专业工程学的高度,它要求你的系统要尽最大可能确保LLM上下文准确无误。
  2. Context Engineering产生的第二个背景,来源于LLM的技术本质,它具有天然的不确定性。LLM的底层运行原理,基于概率统计的 predictnexttoken。概率是充满不确定性的,模型本身的行为就不能被精确控制。在模型训练完成之后的生产运行环境中,你只能通过精细地调整Context来「间接地」引导它的行为。在很多现实场景中,都采取了较为保守的做法,在现有的业务流程代码中,穿插着调用一两次LLM,对于这种简单的情形,只要在调用的局部把LLM所需的prompt提前设计好、调试好,系统就可以上生产环境了。但是,在更复杂、更高自主性的Agent系统中,对于prompt的管理就没有这么简单了。资深的AI从业者Nate Jones把Context Engineering大体分成两部分。
    1. 第一部分 (the smaller part),称为deterministic context。这部分指的是我们直接发送给LLM的上下文,包括指令、规则、上传的文档等等,总之它们是可以确定性地进行控制的 (deterministically control)。
    2. 第二部分 (the larger part) ,称为probabilistic context。这部分指的是,当LLM需要访问web以及外部工具的时候,会不可避免地将大量不确定的信息引入到LLM的上下文窗口。典型地,Deep Research就是属于这一类的技术。在这种情况下,我们能直接控制的上下文内容,只占整个上下文窗口的很小一部分(相反,来自web搜索和工具返回的内容,占据了上下文窗口的大部分)。因此,针对probabilistic context这一部分的上下文,你就很难像针对deterministic context那样,对prompt进行精细地微控制 (micro control) 。 总之,LLM本身的不确定性,加上访问web和外部工具带来的context的不确定性,与企业对于系统稳定运行的要求存在天然的矛盾。这样的难题解决起来,就需要更多、更系统的工程智慧。这成为Context Engineering产生的第二个背景。
  3. 至于Agent执行会失败的具体技术原因,更进一步拆解的话,可以归结为两个方面:
    1. 第一,模型本身不够好或者参数不够,即使有了正确的context还是生成了错误结果。
    2. 第二,模型没有被传递恰当的上下文。在实际中,占大多数。这第二个原因,又可以细分成两类:
      1. 上下文不充分,缺失必要的信息 (missing context) 。
      2. 上下文的格式不够好 (formatted poorly) 。类比人类,如果说话没有条例,颠三倒四,即使所有信息都提到了,仍然可能无法传达核心信息。
      3. 上下文污染,幻觉信息混入决策链
      4. 上下文混淆,冗余信息导致推理错误
      5. 上下文冲突,不同轮之间信息自相矛盾
      6. 上下文干扰,重点内容被淹没,性能下降

实践

Agent时代上下文工程的6大技巧

  1. KV-Cache 命中率,是直接决定Agent的延迟和成本的关键指标。先来看AI Agent的运行方式:用户输入 → 模型按当前上下文挑动作 → 动作在沙箱执行 → 结果写回上下文 → 进入下一次迭代重新按当前上下文挑动作 → … → 任务完成。可以看出,上下文在每一步都会增长,而输出的Function Call结果通常相对较短,以 Manus 为例,平均输入与输出 token 的比例约为 100:1。幸运的是,拥有相同前缀的上下文可以利用 KV 缓存(KV-cache)机制,极大降低首个 token 生成时间(TTFT)和推理成本。以 Claude Sonnet 为例,缓存的输入 token 价格为 0.30 美元/百万 token,而未缓存的则高达 3 美元/百万 token,相差 10 倍,很夸张的节省了。从上下文工程的角度看,提升 KV 缓存命中率的关键要点如下:
    1. 让 prompt 前缀绝对稳定。由于LLM的自回归属性,只要有一个 token 存在变动,就会让缓存从该 token 之后开始失效。一个常见的错误是在系统提示词的开始加入时间戳,尤其是精确到秒级,会直接让缓存命中率归0.
    2. 上下文只能追加。避免修改之前的动作以及观测结果,确保你的序列化过程是确定性的。很多编程语言和库在序列化 JSON 对象时并不保证键的顺序稳定,这会在悄无声息地破坏掉缓存。
    3. 需要时明确标记缓存断点。一些模型提供方或推理框架并不支持自动增量前缀缓存,需要手动在上下文中插入缓存断点。注意在设置断点时,要考虑潜缓存可能过期的时间,至少确保断点包含在系统提示词的结尾。 如果是使用vLLM等框架时,请记得打开 prefix caching,并用 session ID 把请求路由到同一worker。
  2. 利用Mask,而非删除。Agent系统中,能力越多,那么工具就需要越多。尤其是MCP大火,如果允许用户自定义配置工具,会有人塞上百个来历不明的工具到你构建的动作空间里。显而易见,模型会更容易选错行动,或者采取低效路径,就是工具越多的Agent,可能越笨。一般的做法就是动态加载/卸载工具,类似RAG一样,但Manus尝试过之后,都是血的教训
  3. 工具定义通常在上下文最前面,任何增删都会炸掉 KV-Cache。
  4. 在history里提到的工具一旦消失,模型会困惑甚至幻觉。 结论就是:除非绝对必要,否则避免在迭代中途动态增删工具。Manus 的解法就是,不动工具定义,利用上下文感知的状态机(state machine)来管理工具,在解码阶段用 logits mask 阻止或强制选择某些动作。在实践中,大多数模型提供商和推理框架都支持某种形式的响应预填充,以 NousResearch 的 Hermes 格式为例,
  5. Auto:模型可以选择是否调用函数,通过仅预填充回复前缀(<|im_start|>assistant)可实现。
  6. Required:模型必须调用函数,但具体调用哪个函数不受限制,通过预填充到工具调用标记(<|im_start|>assistant<tool_call>)可实现。
  7. 将文件系统作为上下文。即使大多数模型上下文长度以及支持到128K,但在真实的智能体场景中任然不够,甚至是一种负担:
  8. 观测结果可能极其庞大,当与网页、PDF 这类非结构化数据交互时,上下文长度限制很容易就爆表
  9. 即使模型支持很长上下文,但一般在超过一定长度之后模型性能会有一定的下降
  10. 长上下文输入即使有前缀缓存,依然很贵。 常见做法是截断或压缩,但不可逆压缩必丢信息,你永远不知道第 10 步会用到哪条观测值。Manus的做法,是把文件系统视为终极上下文,无限大、持久、可由模型直接操作读写,把文件系统不仅当作存储,更当作外部结构化的记忆。具体的压缩策略是保证内容可复原,例如,网页内容可暂时从上下文删掉,但保留原有的URL ;文档内容只要在沙盒中的路径可用于(查找?),那么内容可以也可以被省略。让Manus在不永久丢失信息的前提下,缩减上下文长度。甚至幻想:如果 State Space Model(SSM)能把长期状态外化到文件,而非留在上下文,它们可能成为下一代智能体。
  11. 通过复述操纵注意力。用过 Manus 的人会注意到它爱创建 todo.md,做完一条勾一条。这不是看起来可爱,而是精心设计的注意力操控机制。Manus中一个任务一般需要50次工具调用,在50步的长链中,LLM很容易出行跑题现象,偏离原有主题或忘记早期目标。通过不断重写待办清单,将任务目标不断复述到上下文末尾,相当于用自然语言把目标塞进最近注意力,避免中间遗忘(lost in the middle)。
  12. 保留错误内容在上下文中。智能体一定会犯错,LLM的幻觉、环境的报错、工具的抽风,这不是BUG,而是现实。在多步任务中,失败不是例外,而是循环的一部分。常见做法是隐藏这些错误:清理痕迹、重试动作,或者重置模型状态,然后把它交给神奇的“温度”。看起来似乎更安全、更可控。但这会抹掉证据,模型学不到教训。Manus发现:把错误留在上下文里,模型看到失败动作后,会隐式地更新其内部认知,降低重复犯错的概率。认为错误恢复能力是真正具备智能体行为的最明确的指标之一。但现在大多数学术研究和公开基准测试中,往往忽略了这一点,只关注了在理想条件下的任务成功率。
  13. 不要被few-shot误导。少样本提示(Few-shot Prompting)是提升LLM输出的常用手段,但在Agent系统中可能会适得其反。LLM是出色的模仿者,若上下文里都是大量相似的动作-观测对,模型会倾向遵循这种形式,哪怕者并不是最优解。例如,当使用 Manus 协助审阅20 份简历时,Agent往往会因为上下文里出现了类似操作,就不断重复,陷入一种循环,最终导致行为漂移、过度泛化,有时产生幻觉。Manus的做法:增加多样性。在动作和观察中引入少量结构化变化,例如采用不同序列化模板、措辞、在顺序或格式上加入噪音等,打破惯性。总之,上下文越单一,智能体越脆弱。

PS:这种表达方式很有意思,以context 视角来看很多工程化手段。