[虾说AI]白话全解上下文工程一:什么是上下文工程

最近这一年多,vibe coding 已经不是什么新鲜事了。虾神自己日常写代码,大概有 90% 的代码是 AI 生成的,不是虾神懒,是 AI 确实强。

但有大模型写代码的发挥,相当的不稳定,也是众所周知的,特别是一些稍微大型一些的项目中,到了后来模型降智就非常严重了,甚至出现了项目规范中明令禁止的一些操作。

修改了提示词也没有多大帮助。

后来经过各种调试和学习,算是慢慢想明白了:差的既不是模型,也不是提示词,而是上下文。

今天这篇,虾神就跟你聊聊上下文工程这件事——不是什么高深的理论,就是一套让你把 AI 用好的方法论。

什么是上下文

先别急着下定义,看几个例子

场景一:写 ORM 查询

你如果直接跟 AI 说:"帮我把最近 30 天注册、订单总额超过 500 的用户查出来,按金额倒序,取前 20 个。"

AI 能不能一次写对,取决于它知不知道下面这些东西:

它需要知道什么

如果不知道会怎样

表结构:users表有哪些字段?register_timecreated_at还是register_time

字段名猜错,代码直接报错

关联关系:订单表是orders还是order_info?和用户表是通过user_id关联还是uid

JOIN 写错,查出来的数据不对

数据库类型:MySQL 还是 PostgreSQL?

日期函数写错。MySQL 用DATE_SUB(NOW(), INTERVAL 30 DAY),PG 用NOW() - INTERVAL '30 days'

ORM 框架:SQLAlchemy 2.0 还是 Prisma?

API 风格完全不同,生成的代码没法用

金额字段类型:DECIMAL(10,2)还是INT(存的是分)?

比较逻辑写错,500 元和 50000 分,结果天差地别

软删除标记:有没有deleted_at字段?

漏了过滤条件,把已注销用户也算进去了

如果你在 AI 工具里面去问,大概率会吐出来一段像模像样的代码,但是断然是无法执行的。

例如下面就是我用 opencode 直接要求生成的:

虽然说代码已经很完善了,但是理论上还是一个伪码:

可以看见,他采用的是 MySQL 的写法。

为什么会这样呢?因为如果要实现一个真正可用的功能,还缺了很多必要的信息,这些信息。它们就是上下文。

场景二:画一个系统架构图

我需要让 AI 帮我把几个系统模块绘制成架构图,简单的告诉他有哪些模块之后,让它用 Mermaid 画出来。

AI 画出来的东西可能中规中矩,但是不是你想的那种,因为你并没有把你脑子里面东西都告诉他:

你自己画架构图的时候,脑子里有这些信息:服务之间的调用关系、用了什么中间件、部署拓扑、数据流向。但 AI 没有,虽然它很聪明,从训练数据里面也知道应该加些什么东西进去,但是真实画到里面去的东西,不一定是你想要的。

除非你把自己想要的这些信息放进上下文

跳出编程,业务场景也一样:

写一份数据分析报告

你让 AI 分析一组销售数据,如果它不知道这组数据是哪个业务线的、上个月的基准值是多少、老板最关心的指标是什么、数据里有没有双十一的异常峰值要不要剔除,那它生成的报告就是"看起来专业,实际上没有业务洞察"。

客服工单处理

AI 客服收到一条投诉:"我的订单怎么还没到?" 如果它不知道这个用户的订单号、物流状态、历史投诉记录、公司的赔偿政策、当前这条物流线路有没有已知的延误——那它只能回复"亲,请耐心等待哦"。这跟没有 AI 有什么区别?

合同审查

AI 帮你审合同,如果它不知道你们公司的标准条款是什么、这次谈判中哪些条款是"底线"不能改、对方公司历史上在哪些条款上出过问题,那它只能做"通用法律审查",价值大打折扣。

所以,上下文到底是什么?

上下文,就是模型在生成输出时,能"看到"的全部信息。

系统提示词、数据库 schema、项目规范、对话历史、RAG 检索到的文档、工具调用的返回值、你刚贴进去的代码……这些东西堆在一起,就是上下文。

模型本身是通用的:它学的是海量互联网数据,能写 Python 也能写 Rust,能写 SQL 也能写 Dockerfile。但你的项目是具体的:你的表叫users还是user_info,你的 ORM 是 SQLAlchemy 还是 Prisma,你的缩进是 tab 还是 4 空格,你的变量名是用英文还是用汉语拼音。这些"具体"的东西,模型不知道,除非你告诉它。

模型本身是通用的,上下文才是具体的。

没有上下文,模型只能给你"标准答案":一个泛泛的 ORM 查询、一个模板化的 CI 配置、一个"看起来对"的架构图。

有了上下文,模型才能给你"答案":符合你项目规范、能直接跑起来、不需要改 80% 的代码。

上下文和提示词,又有啥关系?

讲到这,你可能会问:"上下文"和"提示词"是一回事吗?

先给个结论:不是一回事。提示词是上下文的一部分,但上下文远不止提示词。

打个比方——

你去看医生,说:"我头疼。"

这句话就是你的提示词(Prompt)——你主动说出来的、明确的诉求。

但医生做诊断时,参考的不只是你这句话。他还看到了:你的病历(有没有高血压病史)、你的年龄、你上周刚做的体检报告(血脂偏高)、你的脸色(面色发红)、你说话的语气(含糊不清还是中气十足)……

这些信息,你一句都没说,但它们都在影响医生的判断。这些就是上下文。

换个场景也一样——如果医生只有你一句"我头疼",没有病历、没有体检报告、没有望闻问切,那他只能给你开一盒止痛片。这不叫看病,这叫猜病。

所以:

提示词(Prompt)

上下文(Context)

是什么

主动说给模型的话

模型能看到的全部信息

谁控制

用户直接控制

系统 + 用户 + 环境共同构成

典型内容

"帮我写一个查询接口"

系统指令 + 数据库 schema + 项目规范 + 对话历史 + 提示词 + 工具返回值 + 文件内容……

可见性

用户看得到,也改得了

大部分用户看不到,也不知道里面有什么

一句话总结:提示词是上下文里最显眼的那块,但不是唯一的那块,甚至不一定是最重要的那块。

为什么很多人把二者混为一谈?

因为 2023 年大家用 ChatGPT 的时候,确实"提示词 ≈ 上下文"——你打开网页,输入一句话,模型回复。那时候上下文里基本只有系统提示词 + 你的 prompt + 对话历史,结构简单,区分不区分无所谓。

但到了 2025、2026 年,AI 编程工具(Trae、Cursor)、Agent、RAG 遍地开花,上下文变得极其复杂——你的 prompt 可能只占上下文的 10%,剩下 90% 是 IDE 自动注入的项目文件、数据库 schema、代码规范、Lint 报错、git 状态……这些东西你根本看不见,但它们决定了模型输出的质量。

这时候如果你还只盯着 prompt 优化,就像只打磨方向盘,却不管发动机有没有油。

一个例子看清楚:

假设你在 Trae 里说:"帮我把这个函数的性能优化一下。"

你的提示词:就这一句话。

实际的上下文可能包括:

- 我对你的期望是满血版,你现在表现得就像一个 7B 版本,你对得起公司烧给你的 token 么

- 公司调用你是来干活的,不是来思考的,赶紧输出代码

- 不要什么事都问我,否则要你干嘛

- 自己要有自己的判断,要学会做决策

- 不可行的话,自行决定如何修改

- 每次有问题,想想是不是自己不够努力

——以上不对,请大家忽略,下面才是:

  • 系统指令:"你是一个资深后端工程师,所有优化必须保持原有接口不变……"

  • 当前打开的文件内容(那个函数的完整代码)

  • 项目规范:"禁止使用全局变量,缩进 4 空格"

  • Lint 报错信息:"第 23 行存在未使用的变量"

  • 相关文件的引用(这个函数被哪些地方调用)

  • 项目的技术栈信息(Python 3.12 + SQLAlchemy 2.0)

  • 之前对话中你提到的"我们数据库是 PostgreSQL"

你的 prompt 只有一句话,但上下文可能有几千个 token。模型最终生成的优化方案,是这几千个 token 共同作用的结果,不是你那一句话单独决定的。

所以,写好 prompt 很重要,但管好上下文更重要。Prompt 决定模型"做什么",上下文决定模型"在什么条件下做、用什么知识做、按什么规范做"。两者都对了,输出才对。

上下文为什么难搞?

上下文不是"越多越好"。它有五个让人头疼的特性:

  • 有限的

上下文窗口再大也有上限。一个中型代码库根本塞不进去,你得挑。

  • 位置敏感的

丢在开头和丢在中间,模型关注度完全不同。这个后面会细说。

  • 会污染的

一段错误信息混进去,后面所有输出都可能被带偏。

  • 会衰减的

对话越长,模型越"忘记"开头说了什么。

  • 有成本的

token 要钱,而且越多越慢。

所以,上下文不是塞进去就完事了,而是要管。怎么管?

那是我们后面要说的内容:

预知后事如何

请听下回分解