
全文逐字手打,多年不写长文了,累..
如果你关注人工智能技术,尤其是 agent 技术,上下文工程( context engineering )可能是你在这半年听到的最多的词之一了吧?各种营销派、技术流从各种角度的解释和解读估计已经把你彻底搞麻了,甚至你都开始自我怀疑了:是我太笨了么?为啥我怎么也搞不清楚这玩意?
其实,只是因为信息太杂乱了,我希望通过这篇文章,给你讲清楚到底什么是上下文工程,文章有点长,需要点耐心,读完大概需要 30 分钟,如果你没有时间,你可以先关注这个 github 的项目 https://github.com/zhixiangxue/chak-ai ,这篇文章里面谈到的所有话题我都把他浓缩在这里面了(很好用,不信你去试试,是不是打中了你的痛点,hhh ),我会定期维护更新这个项目,前几天 V2EX 的评论区提到的需求,刚刚发布了,嗯,真维护,hhh 。如果对你有帮助,请给个 star 哦~
先给你吃一颗定心丸:上下文工程不是什么神奇的技术,来来回回就那么几件事情(这几件事情的技术栈确实是很深的),但是其本质其实很简单,我们抓住事物的本质就不怕乱了,乱七八糟的东西都是都是围绕这个本质转的。
搞清楚了下面这几个问题,我们大概就能搞懂上下文工程了:为什么会有上下文工程?什么叫上下文?为什么叫工程?怎么做?效果是什么?没有它会怎么样?
开始吧
首先我们先问自己一个问题:为什么会有上下文工程?
如果你只做过简单的 llm chatbot ,你可能是无法理解为什么会出现这玩意的,但是如果你做过稍微复杂一点的 llm chatbot 或者是 agent ,你就很能理解了,因为多数时候你都会对着电脑破口大骂:这什么垃圾模型,跟个傻 X 似的。
为什么会这样呢?
不是因为模型太傻,而是你没有给模型精准的上下文,它就很难按照你的想法/意图输出东西。模型的上下文空间是一个稀缺资源,模型的注意力和能力固然有先天缺陷(这不在我们的讨论范围内),但是现状就是这样,想让模型干活,就必须给它精准的上下文。太多了不行,它无法集中注意力,太少了也不行,它无法知晓细节,这其实跟人是一样的。
这件事情发生在一轮对话中可能还好,因为对模型的输入是你人为可以控制的,精心的设计提示词就行了(这就是所谓的提示词工程),但是,如果是多轮呢?粗暴一点想,假设 1000 轮对话,中途你怎么干预这个上下文的窗口中的信息呢?麻烦了吧?
所以就有了上下文工程这个说法:所谓的上下文工程,其实就是在每一轮的对话中,用一些巧妙的办法,给 llm 注入恰当的、准确的上下文信息,让它能更准确的进行推理(回复)。
那么问题来了,上下文是什么?你说上下文不就是 messages 么? NONONO ,上下文是一个广义的概念,千万不要把他理解成只是来来回回对话的 Message ,它还可能包含工具和参数,因为:
收一收吧
简单点说,所谓的上下文工程,就是在任何一轮的对话中,你都能用一种适合你业务的、巧妙的、无需人为干预的、通用的办法,告诉 llm 这个对话的重点信息、来龙去脉 、背景知识、可用的工具等等“关键信息”,从而达到让 llm 的输出更可靠的一种手段,毕竟,llm 只是一个推理引擎,它又不是神仙,你不给它优质的信息,它就无法给你优质的答案。
而之所谓称之为“工程”,就是因为这件事情是非常麻烦的,它甚至都没有任何“标准解决方案”(至少到今天为止是没有的),顶多只有一些“最佳实践”,而且它可以用的手段非常多,组合起来更是无边无际。
简单的事情叫做“工作”,麻烦的事情才能称之为“工程”,一旦麻烦的事情被搞定了,就离“工业”不远了。
OK ,到这里为止,我们已经知道了,什么是上下文,什么是上下文工程了,它不是一个枯燥晦涩的定义,就这么一个朴素的东西。
好,那么下一个问题:怎么做到呢?
别急,升级打怪到了这里,我先把下一关的怪物给你展示出来,它们是:RAG 、知识库、graph 、短期记忆、长期记忆、剪枝、摘要、向量数据库、嵌入、召回、reranking 、chunk 、MCP 等等,以及与之相关的各种你可能都不知道怎么发音的奇怪工具和论文。
慌不慌?别慌,给你再吃颗定心丸:我在下面的故事里面,会把他们全都给你串起来,这些“怪物”虽然很烦,但是他们的目的都是一样的,就是为了吓死你,哦不,都是围绕“怎么才能喂给 llm 准确的信息”这个问题的一系列解决方案,他们没有谁好谁坏的问题,只有合不合适的问题,要客观看待,不要被营销号带节奏,也不要被某些大佬的只言片语带到沟里去,搞技术嘛,要客观全面的看待问题。
下面我们开始由浅入深的聊聊
在做 chatbot 或者 agent 的时候,里面的一个核心任务就是周而复始的和 llm 对话,而对话一旦多了,马上遇到的第一个问题就是:超出了上下文窗口大小
怎么办?
还能怎么办?缩短它呗。怎么缩短?其实有这么几种办法:
这些手段可以灵活组合,千奇百怪,脑洞大开,但是本质上都是在解决“上下文窗口大小”的问题,也只是从“短期记忆”的角度来解决问题(所谓的的短期记忆其实就是你的 agent 在运行的过程中,在内存中存储的、用于随时可以和 llm 交互的那些数据)
当你发现好不容易这些问题都解决了之后,新的问题又出现了:llm 的回答并不准确
为什么呢?这是众所周知的,llm 其实就是一个“八音盒”,出厂的时候有哪些数据就有,没有的就是没有,数据都没有,你怎么指望它回答准确呢?那它只能给你胡编乱造了(就是幻觉)。
怎么办呢?有几种办法:
当你用了这些技术之后(当然你得用好,用的不好只会适得其反),你会发现,llm 的回答的质量明显的提升了,可是还没等你高兴多久呢,新的问题又出现了:llm 无法处理真实的业务
经过你的一通折腾,你的 chatbot 变成了一个挺有意思的“陪聊玩具”,但是真实业务的上下文是非常复杂的,为什么呢?因为这些信息被分割到了各个地方,一个经典的例子就是客服,当网线那头的客户火冒三丈的跟你拍桌子反应问题的时候,你的 bot 如何知道怎么处理?我举一个常见的场景吧,这个场景对人类来说很简单,但是对 AI 来说就要死了。
客户 A:[一张烂果的图片]
你看,日常的真实情况就是这么朴实无华,AI 就是 CPU 干烧了也没用,为什么呢?因为根本没有任何的上下文,前面提到的那些“奇技淫巧”瞬间失灵了,怎么办?没有上下文,就要自己创造上下文。
怎么创造?调用工具。
客服 AI 的祖传技能之一就是搜集情报的能力,一个客诉过来了,要能准确的从 N 个系统中找出和这个客诉一切可能的背景信息,把这些准确的背景信息作为上下文传给 llm 在进行一步步的问题解决。
那么,如何让 llm 知道要调用工具、以及调用什么工具呢?这个问题稍微有点复杂,因为前面埋过一个坑了,到时候我们聊 MCP 的时候,会把这个事情从头到尾一五一十的扒清楚,这里按下不表。
好,到此为止,你的 AI 又 get 了一个新技能:使用工具。你可能觉得你的 AI 已经快无敌了,可是现实总是很残酷 你的 AI 兜兜转转可能又回到了问题的原点,上下文窗口被各种信息挤满了,有效的信号越来越弱,它,又变成一个笨蛋了,而且还是一个很慢的笨蛋...
为什么呢?因为llm 记住的信息质量不高。你要知道,无论是从消息列表、外部知识/数据、工具结果来的数据,它们未必真的是因为质量不好,只是他们对于 llm 来说不够友好。
这话什么意思呢,上海交通大学和 GAIR 实验室发表了个很有意思的论文 《上下文工程 2.0:上下文工程的上下文》,它里面用了一个精辟的方式来解释这个现象:熵(所谓熵,其实就是无序混乱的程度)。
人类的沟通是高熵的,也就是很混乱、很跳跃,比如一句话里面有很多隐藏信息(例如指代),但是这些对人类都不是问题,因为人的大脑可以快速处理这些乱七八糟的背景信息,甚至是隐含在表情、肢体动作、语速、语气里面的隐形信息。
但是,LLM 是低熵的,它无法接受乱七八糟的上下文,只能理解明确的、毫不含糊的指令。
高熵和低熵的对话,无异于鸡同鸭讲,即使你上了很多的手段,你依然发现这些问题还是存在,这就回到了我们前面说到的一个问题 如何让数据对 llm 友好呢?这就涉及到另一个宏大的话题 记忆。
你要为你的 llm 构造一个对它友好的记忆系统,让信息经过过滤提纯之后,成为对 llm 友好的数据,也就是把高熵的信息转为低熵的信息。
写累了,我们总结一下,上下文工程怎么做呢?本质上就是想办法组织和构造对 llm 友好的、精准的信息和工具,才能让 llm 发挥它的特长,手段有很多,这些手段组合起来才可能达到一个更好的效果,但是怎么组合并没有标准答案。
所以,大神 Karpathy 才精辟的总结到:上下文工程是一门微妙的艺术与科学,旨在填入恰到好处的信息,为下一步推理做准备。
玄之又玄,众妙之门。
那么,有了上下文工程之后的效果是什么呢?其实很难量化定义(因为如何评估效果又是一个大话题),但是从用户体验上来说,就会产生或多或少的“啊哈时刻”,你会觉得你面对的这个“对话框”有时候真的很聪明。反过来,如果没有它,你会很明显的感觉到你面对的这个“对话框”很机械很傻很笨很蠢很烂很垃圾...
最后
当我们要构建一个智能系统来解决业务问题的时候,我们要清醒的认知到:模型决定了这个系统的下限,而上下文工程能力决定了这个系统的上限。作为 AI 应用的开发者,应该尽快放弃幻想准备战斗,上下文工程是必修课,因为...没有其他选项。
虽然上下文工程非常复杂,但是我们能不能做一些事情让它变的稍微简单一些呢?是可以的,这就是我开发并开源 Chak 的初衷
Chak 是一个极简的多模型 LLM 客户端,内置了上下文管理和工具调用,极简,开箱即用。
chak 不是另一个 liteLLM 、one-api 或 OpenRouter ,而是一个为你主动管理对话上下文(短期记忆)和工具调用的 LLM 客户端库。你只需专注于对话,让 chak 帮你处理一部分上下文工程。
地址: https://github.com/zhixiangxue/chak-ai
如果觉得好用的话,给个 star 吧,欢迎提 issue ,欢迎贡献
我始终认为,先让和 llm 的对话变得智能轻松简单起来,才能谈 agent
以上,全文完,感谢阅读。
1 Scarb 1 天前 写了很多,但是不知道我的理解对不对,实际只有一个功能:自动化上下文压缩(包括总结和 LRU )。其他的 LangChain 也都能做到。 但是自动化上下文压缩感觉是一个伪需求,各个 Agent 使用场景大不相同,每个都应该有自定义的压缩方式。自动化压缩很容易把 Agent 需要的内容丢掉。 |
2 pmpmp OP @Scarb 感谢阅读 是这样的,不能说是个伪需求,我觉得应该这样看: 1. 是不是用得到,有些场景可能是短平快的,通常不需要压缩模型表现也会很好,压缩了反而会丢细节 2. 如果用得到(多数情况下其实无法人为判断是否会用到),就要看具体的对话性质,需要保留哪些需要使用什么样的策略,只有业务方最清楚,不过 chak 提供了几种通用的、开箱即用的方式,不过也是支持自定义的,继承个基类自己实现就行了 3. 即使用了,也是不够的,压缩摘要只是前置的一种手段,孤立的手段并不能构成绝对有效的结果 作为一个框架,其实这些都是基操,我搞这 chak 也是因为 langchain 其实对于我搞过的很多场景来说还是太重了,一个简单的 mvp 结果要搞半天,但是 langchain 或者 langgraph 的 node 里面如果使用 chak ,还是非常方便的,否则我就得自己在 graph 里面反复的造轮子,管理上下文、管理工具调用 langchain 和 langgraph 很强大,有时候杀鸡不需要用牛刀,语法太复杂学习曲线太高了,没有必要,就像 urllib 能搞定所有的 http 请求,但是太麻烦了,requests 就满足了绝大多数的需求了,接口简单易用凭直觉就能快速用起来 一切看场景吧,定位不一样哈,chak 显然是搞不定也不会搞复杂的编排的,这不是 goal |
3 zzhirong 1 天前 话说最近刚好看了一篇相关论文[Context Engineering 2.0: The Context of Context Engineering]( https://arxiv.org/abs/2510.26493), 里面总结了当前 LLM 面临的一些挑战(有限的窗口, 如何过滤有用的上下文)以及目前应对措施(收集, 处理, 存储, 使用等). 我之前有种 LLM 类似编译器, 而自然语言扮演编译器角色的错觉. 仔细想又发现没这么简单, LLM 作为编译器最大的问题就是它很多时候都是一个黑盒, 相同的输入, 不同的输出, 你可以去接近控制它, 但是你没办法精确控制它, 编程语言可以精确描述你需要的库以及你想做什么(精确的上下文), 而 prompt 更像是一种许愿(类似于声明式编程). |
4 zololiu 2 小时 2 分钟前 希望 V2EX 上这类高质量的分享文章多一点哇! |