V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
pmpmp
V2EX  ›  程序员

你真的了解上下文工程么?

  •  
  •   pmpmp · 9 天前 · 1138 次点击

    全文逐字手打,多年不写长文了,累..

    如果你关注人工智能技术,尤其是 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”的,有很多信息得它自己动态的挖掘和探索的,这就需要工具(我在这里先挖个坑吧,一提到工具,可能马上就能想到 MCP ,MCP 也是大家津津乐道的话题,但是什么是 MCP ,跟 llm 的关系我估计真正能讲清楚的人也不多,所以用起来更是云里雾里,下回我说说这个)。
    • llm 的其他的参数叫不叫上下文?我觉得也应该叫上下文,因为这也是对 llm 的输入,我举个简单的例子,假设对话的气氛活跃起来了,发现用户脑回路清奇的时候,你是不是得让 llm 回答的时候跳跃一些多给些情绪价值?不然用户会觉得这个机器人不解风情啊,这时候 temperature 是不是也应该作为一种“上下文信息”让模型感知到?

    收一收吧

    简单点说,所谓的上下文工程,就是在任何一轮的对话中,你都能用一种适合你业务的、巧妙的、无需人为干预的、通用的办法,告诉 llm 这个对话的重点信息、来龙去脉 、背景知识、可用的工具等等“关键信息”,从而达到让 llm 的输出更可靠的一种手段,毕竟,llm 只是一个推理引擎,它又不是神仙,你不给它优质的信息,它就无法给你优质的答案

    而之所谓称之为“工程”,就是因为这件事情是非常麻烦的,它甚至都没有任何“标准解决方案”(至少到今天为止是没有的),顶多只有一些“最佳实践”,而且它可以用的手段非常多,组合起来更是无边无际。

    简单的事情叫做“工作”,麻烦的事情才能称之为“工程”,一旦麻烦的事情被搞定了,就离“工业”不远了。

    OK ,到这里为止,我们已经知道了,什么是上下文,什么是上下文工程了,它不是一个枯燥晦涩的定义,就这么一个朴素的东西。

    好,那么下一个问题:怎么做到呢?

    别急,升级打怪到了这里,我先把下一关的怪物给你展示出来,它们是:RAG 、知识库、graph 、短期记忆、长期记忆、剪枝、摘要、向量数据库、嵌入、召回、reranking 、chunk 、MCP 等等,以及与之相关的各种你可能都不知道怎么发音的奇怪工具和论文。

    慌不慌?别慌,给你再吃颗定心丸:我在下面的故事里面,会把他们全都给你串起来,这些“怪物”虽然很烦,但是他们的目的都是一样的,就是为了吓死你,哦不,都是围绕“怎么才能喂给 llm 准确的信息”这个问题的一系列解决方案,他们没有谁好谁坏的问题,只有合不合适的问题,要客观看待,不要被营销号带节奏,也不要被某些大佬的只言片语带到沟里去,搞技术嘛,要客观全面的看待问题。

    下面我们开始由浅入深的聊聊

    在做 chatbot 或者 agent 的时候,里面的一个核心任务就是周而复始的和 llm 对话,而对话一旦多了,马上遇到的第一个问题就是:超出了上下文窗口大小

    怎么办?

    还能怎么办?缩短它呗。怎么缩短?其实有这么几种办法:

    • 硬截断:前面的消息不要了,只保留最新鲜的,这种简单粗暴的方式,肯定不是什么好主意,但也未必是个坏主意,具体看业务,有些业务前面的信息确实就什么用了,你搞那么花里胡哨的方法还不如这样的 ROI 高
    • 弹性的总结和摘要:当消息快满了时候或者话题转变的时候,可以总结一下前面的消息,得出一个富含精华信息的摘要,用这个摘要替代前面的冗长信息,这种方法就稍微智能了一点,既能保证窗口"永远"不会被充满,又节省 token ,但是他也是有明显的局限性的,比如会丢失细节,但是你又不知道会丢失哪些细节,可能某些细节会直接决定后续对话的质量
    • 总结摘要+遗忘:有些信息随着对话的轮次就不重要了,比如话题已经转向了,那这些过时的信息就应该被剔除掉,为其他的重要信息腾出空间来,但是缺点也很明显:你怎么知道后面的对话中用户不会话锋一转又回来了呢?
    • 其他:比如分层记忆(这个层怎么分就看你的需求了,可以按照时间来分,也可以按照重要性来分,都可以);甚至比如用 deepseek-ocr 来做一层前置都可以;

    这些手段可以灵活组合,千奇百怪,脑洞大开,但是本质上都是在解决“上下文窗口大小”的问题,也只是从“短期记忆”的角度来解决问题(所谓的的短期记忆其实就是你的 agent 在运行的过程中,在内存中存储的、用于随时可以和 llm 交互的那些数据)

    当你发现好不容易这些问题都解决了之后,新的问题又出现了:llm 的回答并不准确

    为什么呢?这是众所周知的,llm 其实就是一个“八音盒”,出厂的时候有哪些数据就有,没有的就是没有,数据都没有,你怎么指望它回答准确呢?那它只能给你胡编乱造了(就是幻觉)。

    怎么办呢?有几种办法:

    • 重新训练模型:如果你只是需要 llm 具备一些额外的、相对静态的知识,你可以重新训练一个 llm 出来,这个不在我们今天的讨论范围内,而且,这种事情是一个深坑,轻易不要尝试
    • RAG:Retrieval Augmented Generation ,RAG 这个话题很大,这里不展开,但是我想说的是所谓的检索增强其实也是一个很广义的概念,检索什么呢?知识库、搜索引擎、数据库、记忆系统(本质其实就是数据库)等等,都算,而且 RAG 可不是一个什么过时的技术,那都是卖记忆系统的那帮人渲染出来的营销话术,混淆视听,无商不奸,搞技术的要客观看待。RAG 包含的技术也很多,以后有机会专门写一篇吧,前面提到的,分块、嵌入、查询召回、reranking (重排)、向量数据库、甚至传统的基于关键词的搜索技术其实都算是 RAG 的领域。RAG 从技术层面叫做“检索增强”,从功能层面讲,如果是检索的是知识库,其实你也可以叫它长期记忆(至少他是长期记忆的手段之一),所以 RAG 是多面的,你能武断的说他过时了么?

    当你用了这些技术之后(当然你得用好,用的不好只会适得其反),你会发现,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

    以上,全文完,感谢阅读。

    4 条回复    2025-11-15 21:43:06 +08:00
    Scarb
        1
    Scarb  
       9 天前
    写了很多,但是不知道我的理解对不对,实际只有一个功能:自动化上下文压缩(包括总结和 LRU )。其他的 LangChain 也都能做到。
    但是自动化上下文压缩感觉是一个伪需求,各个 Agent 使用场景大不相同,每个都应该有自定义的压缩方式。自动化压缩很容易把 Agent 需要的内容丢掉。
    pmpmp
        2
    pmpmp  
    OP
       9 天前
    @Scarb 感谢阅读

    是这样的,不能说是个伪需求,我觉得应该这样看:

    1. 是不是用得到,有些场景可能是短平快的,通常不需要压缩模型表现也会很好,压缩了反而会丢细节
    2. 如果用得到(多数情况下其实无法人为判断是否会用到),就要看具体的对话性质,需要保留哪些需要使用什么样的策略,只有业务方最清楚,不过 chak 提供了几种通用的、开箱即用的方式,不过也是支持自定义的,继承个基类自己实现就行了
    3. 即使用了,也是不够的,压缩摘要只是前置的一种手段,孤立的手段并不能构成绝对有效的结果


    作为一个框架,其实这些都是基操,我搞这 chak 也是因为 langchain 其实对于我搞过的很多场景来说还是太重了,一个简单的 mvp 结果要搞半天,但是 langchain 或者 langgraph 的 node 里面如果使用 chak ,还是非常方便的,否则我就得自己在 graph 里面反复的造轮子,管理上下文、管理工具调用

    langchain 和 langgraph 很强大,有时候杀鸡不需要用牛刀,语法太复杂学习曲线太高了,没有必要,就像 urllib 能搞定所有的 http 请求,但是太麻烦了,requests 就满足了绝大多数的需求了,接口简单易用凭直觉就能快速用起来


    一切看场景吧,定位不一样哈,chak 显然是搞不定也不会搞复杂的编排的,这不是 goal
    zzhirong
        3
    zzhirong  
       8 天前   ❤️ 1
    话说最近刚好看了一篇相关论文[Context Engineering 2.0: The Context of Context Engineering]( https://arxiv.org/abs/2510.26493), 里面总结了当前 LLM 面临的一些挑战(有限的窗口, 如何过滤有用的上下文)以及目前应对措施(收集, 处理, 存储, 使用等).

    我之前有种 LLM 类似编译器, 而自然语言扮演编译器角色的错觉. 仔细想又发现没这么简单, LLM 作为编译器最大的问题就是它很多时候都是一个黑盒, 相同的输入, 不同的输出, 你可以去接近控制它, 但是你没办法精确控制它, 编程语言可以精确描述你需要的库以及你想做什么(精确的上下文), 而 prompt 更像是一种许愿(类似于声明式编程).
    zololiu
        4
    zololiu  
       7 天前   ❤️ 1
    希望 V2EX 上这类高质量的分享文章多一点哇!
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   2460 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 18ms · UTC 06:13 · PVG 14:13 · LAX 22:13 · JFK 01:13
    ♥ Do have faith in what you're doing.