你有没有见过这种场景让人工智能帮你实现一个功能模块它噼里啪啦生成了一大段代码看起来头头是道但你把它贴进工程里瞬间报错——引用的方法根本不存在接口参数对不上调用的函数和你项目里另外一套封装完全不是一回事。你皱着眉头追问它“为什么不按我的项目规范写”它只会支支吾吾地道个歉然后重来一遍结果还是不对。我把这种状态叫“盲打”——AI编程助手在没有代码库上下文的情况下凭着训练时记得的“通用套路”瞎猜你的项目。它根本不了解你的工程结构、依赖关系、编码规范、现有模块边界那它怎么可能写出贴合实际需求的代码问题不在模型本身真正的关键在上下文工程。这个概念懂的人已经把它用成编程智能体的“六边形战斗力”了准确性、一致性、效率、可维护性、协作体验、扩展能力六项全能。这文章我就从实战角度拆一拆为什么上下文工程决定了你的AI助手是“玩具”还是“生产力”以及到底怎么把上下文喂到位。1. 为什么提示词工程不够用了AI编程正在从“单次问答”走向“智能体协作”1.1 “盲打”的病根模型根本不知道你的项目长什么样先说个很常见又很典型的小例子。最近的模拟项目X里同事A想让AI帮他给一个已有的类加一个异步方法。他写了一大段提示词描述得非常详细“请给FooService增加一个async loadBar()方法要包含超时控制和重试机制……”AI倒是很努力把市面上常见异步框架的标准写法都搬过来了读配置文件、构建重试策略、设置超时时间、抛出异常、甚至打印了一堆带颜色的日志。问题来了这个项目根本没有用那套异步框架。项目里统一封装的异步调用基类是另一套超时参数要从配置中心的某个特定key读取而同事A非常详细地描述了自己想要的逻辑——但是完全没说“项目里已经存在一个BaseAsyncService所有异步服务都要继承它”。AI只能按“最普遍的行业实践”来猜猜出来的结果自然和行为不符。这个场景就是典型的“盲打”。AI没有感知代码库的能力它对你项目的理解全靠这次对话里你给的那点文字。这背后其实是个很简单的道理大语言模型在训练时见过海量代码它知道“一个通用异步方法通常怎么写”但它不知道“你的项目是怎么组织的”。这两种知识之间存在巨大的鸿沟。提示词工程试图用“把这个需求写得更具体”来填补鸿沟但效果有限——因为你不可能在一次提示里把整个项目的架构、约定、边界条件都描述清楚。就算你写一万字的提示词模型依然可能踩到它没看见的坑。1.2 从“对话框里的助手”到“工作区里的队友”上下文是唯一桥梁这两年编程助手的形态变化很大。以前是“你问一句它答一段”你复制代码自己粘贴。现在的主流编码智能体已经进化成另一种协作方式它能直接读取工作区文件、搜索整个代码库、打开相关文件、运行测试、然后根据报错修改代码。你可以把它理解成新入职的同事。真人新同事上手快不快核心取决于你给了他什么资料——有没有项目文档有没有架构图有没有代码规范有没有人能回答他的问题。你什么都给他第一周就能改代码你丢一堆代码仓库链接让他自己看他大概率要折腾很久才能产出合格代码。编程智能体也一样而且它比真人更“较真”你给它看什么它就用什么你不给它看它就只能靠想象力补全。这也是为什么我说“上下文工程才是六边形战斗力”。上下文工程不是简单写几个提示词而是要系统性地解决这个问题如何在整个协作流程里把“项目真实情况”和“任务当前状态”持续地注入给模型让它的每一步决策都有据可依。你可以把它拆成四个维度静态上下文项目结构、开发规范、依赖清单、动态上下文当前打开的文件、最近的改动、报错信息、演进上下文对话历史、决策记录、交接摘要和联动上下文外部API文档、配置中心、设计文档。1.3 “六边形”到底指什么上下文好坏的六个可测量维度为什么用“六边形战斗力”这个说法因为我观察下来上下文工程做到位之后编程智能体在六个维度上会同时变强缺一个都会明显拖后腿准确性写出来的代码符合实际项目架构引用的方法真实存在接口签名正确编译一次通过率大幅上升。一致性生成的代码风格、命名规范、错误处理方式与现有代码维持一个统一的调性你不会看得出来“这段是AI写的那段是人写的”。效率不需要反复追问“你的项目用什么框架”“这个函数在哪定义”一次对话能连续完成多步任务来回沟通成本显著降低。可维护性AI生成的代码不是孤立的一坨而是跟着项目的分层结构落在合适的位置后续人改起来顺。协作体验AI能“主动”去查上下文而不是等着你喂你知道它为什么这么写改起来放心。扩展性同一个上下文管理思路可以复制到不同的任务、不同的项目、不同的智能体工具上模板化之后团队其他人也能用。如果你发现某个AI编程助手在你的项目上表现很差先别急着怪模型笨。多数情况下是上下文工程没做好。模型还是那个模型输入的上下文质量不同输出的上限和下限完全不同。2. 上下文工程的核心到底该给AI喂什么信息2.1 静态上下文让AI先“读懂”你的项目再动手静态上下文指那些在较长一段时间内不发生变化的项目基础信息。这类信息应该一次性构建好然后反复使用。我自己的习惯是在项目根目录维护一份精简的工程情报文件作为静态上下文的主入口内容覆盖面大概是这样先把项目是干什么的写清楚——业务领域是什么核心功能模块有哪些主要的用户角色和技术边界。这块不写详细业务需求只写“这个系统是个扫码点餐后端”或“这是内部爬虫调度平台的控制面”让AI对全局有个定位。接下来写技术栈清单这部分极其重要而且比很多人想象得更细不仅仅是“Python”或“Java”这种语言级别还要包括框架的特定版本、ORM方案、接口风格、依赖注入方式、打包构建工具、代码生成器的约定。真项目里一个大坑就是同一种语言的不同框架写法差异巨大AI按通用印象写很容易写出和当前项目完全不同的代码组织方式。然后写代码结构地图也就是目录结构加一段说明哪些目录放接口层哪些放服务层哪些放领域模型哪些是基础设施代码。这一步的意义在于当AI要在你的项目里定位某个类、某个方法时它有一个导航图而不是在庞大的文件树里瞎翻。再写上重点约定比如“所有对外接口统一返回Result 包装”“事务只能写在应用服务层不允许出现在仓储层”这种规则。这类“隐性知识点”往往是团队积累下来的血泪教训也是AI最容易违反的东西。还有一个容易被忽略但很有用的字段对应的编码禁忌表写明不准怎么做防止AI往坑里走。你可能会想这些内容写下来不就等于是让AI看一遍文档吗它真能理解吗问题在于你得把它放在AI能看到的地方。多数编程智能体工具支持配置自定义说明、项目记忆或者自定义指令文件把这份工程情报挂进去每次对话都自动加载那AI的初始智力就完全不一样了。你可以这样理解一份好的静态上下文相当于在新同事入职第一天不花五分钟把团队这套“潜规则”讲透。2.2 动态上下文每次对话时告诉AI“现在到底在干吗”静态上下文解决了“项目是什么样”但每次任务都是一个独立事件你还需要动态上下文告诉AI“这次我们要解决什么、当前处在什么状态”。动态上下文的第一层是目标声明。不要只说“帮我写一个用户注册接口”而要说“在用户模块下新增一个注册接口入口是POST /api/v1/users/register已经有一个UserDomainService负责用户唯一性校验需要先调用它再落库最后发一条MQ消息通知欢迎任务”。你会发现这个提示里故意包含了很多“路标词”这些路标的作用是引导AI如果去读代码找到正确的切入口。第二层是相关代码片段。光说“参考UserDomainService”还不够AI在不少工具里可以主动去查看文件但为了减少搜索成本你最好把关键代码文件或符号贴给它或使用工具的“添加文件到上下文”功能把UserDomainService、UserRepository接口、注册接口的现用Controller直接挂到上下文中。第三层是排错上下文。如果AI运行了测试、出现了报错请把报错堆栈完整给它。如果你只给一个“测试失败”的结论它只能盲猜但你把堆栈给了它它就能沿着报错信息一路定位到代码行再结合静态上下文里的模块设计修复速度会快得多。这三层之间还有一层重要的关系动态上下文是不断变化的。随着任务推进AI产生了新的代码发现了新的问题你应当把新增的代码和新的结论也回填到上下文里去形成一个闭环。我个人的经验是与其反复开新对话把之前解决过的问题再说一遍不如让它在当前对话里带着“这段代码是我上一步写的”这种记忆往下走一致性强很多。2.3 静态与动态的权重平衡信息不是越多越好这里我想特别提一个反直觉的点上下文不是越全越好。给AI塞一个完整的仓库、几百个文件、上百万行代码效果反而会变差。原因主要有两个一个是技术层面的模型对上下文的注意力资源有限。现代大模型虽然支持很长的上下文窗口但输入越长它对每个细节的关注度会被稀释。两个是不相关的文件被混进上下文之后AI经常会被里面的噪音干扰做出南辕北辙的判断。这就像让一个真人同时看二十份资料再写总结他大概率也只能记住最重要的几份。所以上下文工程真正的功夫在于裁剪。静态上下文要精炼只放那些“团队约定中最关键、最容易违反”的部分动态上下文要精准只放和当前任务强相关的代码。中间的判断标准是这条信息是否直接影响了本次代码生成的正确性如果影响放进去如果只是背景砍掉。你可以在上下文里加一个简单的筛选逻辑先看任务描述涉及哪个模块 - 再看这个模块有哪些关键文件 - 从中选择“定义、入口、边界条件”类文件加入上下文。3. 手把手实操从零搭一套高品质的AI编码上下文工作流3.1 第一步建立项目情报文件作为上下文的“总入口”这个文件我习惯命名为PROJECT_CONTEXT.md放在项目根目录。内容不需要长篇大论控制在150行以内最好。太长了AI每次加载成本高人也懒得维护最后就过期了。核心部分按上面说的五块来写就行。给你看一个简化的模板片段这是一个内部工具类项目的示例# PROJECT_CONTEXT ## 这是什么 一个内部任务调度系统的后端服务负责接收上万个异步任务的创建、分发、状态回写。 ## 技术栈 - 语言: Python 3.11 - Web框架: FastAPI不使用Django - ORM: SQLAlchemy 2.0 Alembic迁移 - 队列: 本地Redis Stream 自定义消费组封装不要直接用redis-py的xreadgroup裸调 - 任务定义: 用内部库taskkit统一装饰器声明任务 ## 目录结构 - app/api/ - 路由入口层只做参数校验和响应封装 - app/service/ - 业务编排层事务和业务规则都在这层 - app/repository/ - 数据访问层只放SQL/ORM查询 - app/domain/ - 领域模型含枚举、常量、数据类 - app/infra/ - 基础设施如Redis、ES、HTTP client封装 ## 关键约定 - 所有HTTP接口返回统一JSON格式: {code, message, data} - service层方法名用动词短语如create_task、cancel_task禁止直接写成task_save - 数据库更新时间字段统一由ORM的onupdate维护禁止手动set - 新增一个任务类型时必须在taskkit注册表中登记 ## 编码禁忌 - 不要创建app/utils.py这种“什么都能塞”的公共工具文件 - 不要在repository层抛业务异常异常统一在service层转成业务码 - 不要直接操作asyncio.create_task要用内部封装的TaskManager.submit你可能会疑惑“AI真的会遵守吗”实测下来这份文件一旦被加载进上下文AI对很多问题的回答会明显更“懂规矩”。它会优先引用PROJECT_CONTEXT里的约定来回答而不是拿通用最佳实践来糊弄你。3.2 第二步把项目情报挂进你的编程智能体这一步取决于你用的是哪款工具但逻辑是相通的。大多数编码智能体都支持某种形式的项目级配置或者自定义指令。你把PROJECT_CONTEXT.md的核心要点提炼成一个精简版的“项目预设”指令配置到智能体里。还有些工具支持直接读取当前工作区的某个固定文件作为附加上下文那更省事直接让它把PROJECT_CONTEXT.md的内容一并带入。我自己的经验是不要直接甩一个巨大的文档路径给它让它自己读那样不可靠有时候它不知道要去读。你要么把内容复制到配置区要么明确指示“首先阅读根目录的PROJECT_CONTEXT.md”。把它变成每次对话自动加载的上下文比让AI“自觉”去翻靠谱得多。还有一个值得注意的点配置区的字符串长度有限如果PROJECT_CONTEXT太长你要压缩出一版“核心约束版”只保留技术栈、目录导航、关键约定和禁忌把业务描述压缩成一句话。这样既节省token信息密度也更高。3.3 第三步为每个任务写好“任务开头信息包”有了总入口每次新任务你还要额外喂一份短小精悍的开头信息包。它和全局的PROJECT_CONTEXT配合使用一个管“全局”一个管“本次”。我自己总结了一个信息包公式四个部分目标objective、切入口entry、边界boundary、验收acceptance。举个例子你要让AI改一个订单超时关闭功能一份合格的开头信息包大概是这样的目标实现订单创建后30分钟未支付自动关闭任务。 切入口参考app/service/order_service.py中的create_order方法在事务提交后调用TaskManager.submit发布一个延时任务延时任务的消费逻辑写在app/service/order_close.py下的close_timeout_orders()。 边界本次不涉及支付回调关闭订单只改订单状态为CLOSED_TIMEOUT不操作库存。 验收单元测试覆盖“创建订单后触发延时任务”和“执行延时任务时订单状态正确变化”两个场景测试数据不要用真实生产数据。这个信息包的作用是给AI规划出一个“工作区间”它在这个区间内自由发挥很可能会写出让人满意的代码。你会发现“边界”这一项特别有效能拦住大量无用发挥。没有它AI经常会顺手帮你把库存扣了、把退款流程给设计了顺带还引入了一堆新依赖最后你还得删。3.4 第四步善用对话内的“状态回填”编程智能体在跑任务时并不是一次性生成全部代码它会先分析、再改文件、再跑测试、再修bug。这个过程里上下文状态是流动的。很多人失败的原因是在AI完成一次代码修改之后不把“这次修改的结果”告诉它就直接进了下一轮问题然后AI就忘了自己刚刚写了什么。所以请养成一个习惯每完成一个动作就给它回填一句话的“状态更新”。比如“刚才新增的close_timeout_orders方法在order_close.py中已完成方法内部用了TaskManager.submit接下来请为它补充单元测试测试文件建在tests/service/test_order_close.py”。这本身就是一种上下文工程而且不费什么力气只要你稍微有点意识地去做效果提升立竿见影。进阶一点的玩法是利用工具的“读取并总结”能力。每一轮工作结束后让AI自己总结当前进度把总结粘贴回上下文里再继续。“已完成register接口已添加UserService注入已改完待做给异常分支补日志风险支付回调的幂等逻辑未覆盖。”这种滚动式的上下文交接能让长任务的完成质量显著高于一次性写一大段提示词让AI从头做到尾。3.5 第五步模板化封装形成团队级别的“上下文资产”当你自己摸索出一套好用的上下文格式下一步就不要藏着掖着了。把PROJECT_CONTEXT.md的模板、开头信息包的公式、常用任务类型的上下文样例都沉淀到一个团队共享目录里。这样新同事用AI编程助手时不用从零摸索直接套模板就能上手。我在实际项目中见过这样一个变化团队统一了上下文模板之后AI生成代码的“返工率”肉眼可见地降低了。之前那种“AI一改动就破坏旁边模块”的情况少了很多。原因很简单——之前每个人喂给AI的信息参差不齐有的给得多有的给得少现在模板把“关键信息的最小集”固定下来了。4. 常见问题与排查技巧实录4.1 上下文越写越长AI反而“变笨了”怎么办症状你给AI喂了很多文档、很多代码文件它反而开始答非所问甚至忘记了你最开始的任务要求。排查思路这大概率是上下文超载。你塞进去的噪音太多了。编码智能体的注意力是有限的不是给得越多越聪明。解决方法是做减法把和本次任务无关的文件从上下文里移除。只保留两类信息直接要被修改/参考的文件、定义了关键接口或模式的文件。把PROJECT_CONTEXT.md这类静态信息压缩成“速查卡”格式让AI只看到结论不要看到长篇的说明。另外我还发现一个细节把大段代码折叠成“文件路径 关键符号名 核心逻辑摘要”的组合比直接粘贴整段代码更省上下文同时信息量并不会减少太多。比如“util/http_client.py中有个request_json()方法接收url、params、headers、timeout四个参数返回解析后的dict内部已经处理了重试和日志”这种描述足够AI使用了。需要精细修改时再让它打开对应文件。4.2 AI引用了一个项目里根本不存在的依赖或方法怎么回事症状AI生成代码里出现了一个你从来没导入过的库或者调了一个压根不存在的内部方法。排查思路这多半是因为上下文里没有项目依赖清单也没有代码索引。AI在训练时见过很多流行库的用法如果它感知不到你的项目实际用的依赖版本就很容易随手写一个“万金油”方案。解决办法是确保静态上下文里有明确的依赖清单标注好“禁止引入新依赖”的区块。如果项目里已经封装了HTTP客户端那上下文里一定要写清楚“所有HTTP请求走app/infra/http_client.py的request_json禁止直接用requests库”。有了这条约束AI就不会干出“自己手搓一个requests.get”这类事了。4.3 AI生成的代码风格和现有代码明显不一致怎么让它“入乡随俗”症状明明上下文里写了项目规范和目录结构AI还是生成了一段与现有风格格格不入的代码比如旧的代码都用dataclass定义模型AI上来给写了个pydantic的BaseModel。排查思路先确认那条规则真的被AI“看”到了而不是只存在于你的想象中。我在实践里发现把规范写在文档里但如果不在任务开始时明确要求“严格参照PROJECT_CONTEXT.md中的目录结构和命名规范”AI有时就漏了。你要在信息包里显式引用规范条目比如“请参考order_service.py中现有方法的参数风格保持一致”效果比“按项目风格”这种模糊指示好得多。也可以用“正反例”的方法给它一小段现有的好的代码示例说“模仿这个写法”它往往能学得更快。这和教真人新同事其实是同一个道理——给抽象规范不如给具体范例。4.4 AI改A模块时把B模块的逻辑也动坏了怎么防止症状你只让AI改一个接口的入参校验回头发现它顺手把另一个服务的查询逻辑也“优化”了测试挂了一堆。排查思路这是典型的上下文缺失导致的“过度扩散”。AI在上下文里看到了很多文件它以为你希望它把所有看到的代码都改进一遍。解决方案是给你的任务信息包写一个高优先级的“改动范围”提示明确告诉它只准改这几个文件其他文件一行都不要动。如果它自己过度修改了你可以立刻在下一轮回填里纠正它“刚刚对billing_service.py的改动全部撤销恢复成上一版。后续不要修改此文件。”好消息是多数现代编程智能体工具在“撤销文件改动”这一点上做得比较顺手你也可以利用版本控制面板来快速回滚再让AI基于回滚后的状态重新操作。我把这四类问题和对应的排查思路整理成了一张速查表方便你遇到问题时对照处理现象根本原因上下文修复动作AI答非所问、忽略主线任务上下文过载噪音太多移除无关文件压缩静态文档只保留与任务强相关的信息引用不存在的依赖或方法上下文里缺依赖清单和现有封装目录加入依赖清单、禁止新增依赖声明、标注内部封装入口代码风格与现有项目不一致规范未能被AI感知到在信息包中显式引用规范给出参考文件或正反例修改越界波及无关模块缺少改动范围约束声明“只改某文件”AI越界时及时回填纠正指令4.5 长任务做到一半AI开始忘记前文约定怎么办症状一个任务延续了很久开了新对话AI突然不知道你已经让它改过哪些文件了之前的约定全部作废。排查思路在编程智能体工具中跨对话记忆往往不如我们想象的那么可靠。散落的上下文会丢失。我要么建议你尽量在一个对话内把任务做完里程碑式地让AI总结进度要么就在新对话里粘贴一份“交接摘要”内容是之前任务的起点、过程、结论和待办。这份摘要可以很短但必须包含三个要素项目根目录的上下文文件仍然有效、哪些任务已完成、哪些待完成且下一步要做什么。这和我之前说的“状态回填”一致——本质上就是给不同对话之间搭建一座信息桥。有人会嫌麻烦但我实测下来多花三十秒写个交接摘要能让后续所有AI的操作少踩一半的坑。提示写交接摘要时切忌把一整段对话记录全贴进去。那个信息量太大噪音很多。你要的是“结论摘要”不是“过程回放”。精简到十句话以内信息密度反而最高。4.6 AI生成速度越来越慢是不是上下文太多导致的症状你发现AI响应开始变慢尤其是加了PROJECT_CONTEXT和多轮代码后每轮对话都像在加载一座大山。排查思路响应速度和输入token数量直接相关。编程智能体工具需要在每次生成前处理你提供的所有上下文喂给它的token越多首字响应时间就越长。这不是玄学是计算资源成本问题。解决方案是分级管理上下文全局静态信息用精简版任务信息包用局部版长文件不要整段粘贴而用“路径关键行号摘要”引入。如果工具支持“自动选取相关文件”的功能可以手动在任务信息包里指定检索范围缩小搜索目标。还有一个小技巧把过时的大段代码片段从对话里清理掉只保留最新的版本避免AI一直盯着旧代码分析。5. 更进一步把上下文工程沉淀成团队协作的“接口契约”讲到这里你会发现上下文工程已经不只是“怎么和AI对话”的问题了它本质上是把项目知识显性化的过程。那些原本只存在于老程序员脑中的“潜规则”——为什么这个模块要这样设计、为什么不能直接调用某个底层服务、为什么异常处理要集中做——一旦被写进PROJECT_CONTEXT并加载给AI它们就从隐性知识变成了可传播的团队资产。我见过团队把上下文工程玩到下一个高度把常见模板做成了“任务提示词模板库”。比如“新增一个CRUD接口”“修复一个线上Bug”“重构一个服务方法”“为模块补充单元测试”每种任务类型都提前写好一套标准化的信息包框架开发人员只需要往里填具体内容。这样一来无论谁来驱动AI产出的质量下限都被拉高了。甚至在不少场景下AI生成的代码风格趋于统一代码评审的争论都少了因为上下文里已经把“为什么要这么写”的原因讲清楚了。这个思路你也可以带到非编码场景写文档、做数据分析、整理会议纪要本质上都是在“给一个智能体提供高质量上下文”。你给它的材料越精准它输出的结果就越接近你脑子里想要的东西。反过来如果你只是简单问一句“帮我总结一下”它是很难凭空猜出你所认为重要的重点的。这是一项可以重复利用的核心方法在任何用到生成式AI的环节都成立。从“盲打”到“六边形战斗力”真正发生变化的不只是AI而是我们自己的工作方式。当你养成了给AI整理高质量上下文的习惯之后你会发现自己对项目结构的理解反而更清晰了——因为你需要不断提炼“什么是最重要的约定”这个过程本身就在倒逼你把项目知识体系化。这可能才是上下文工程带给开发者最意外的收获它不但让AI变得更好用也让使用AI的人变成了更好的工程师。我个人的体会是不要指望一款编程智能体装上就立刻变强它更像一块需要不断调校的仪表。你给它的上下文质量决定了它的表盘数值。把上下文工程这门功夫练好比换任何新模型都管用。真要说有什么捷径那就是从今天开始先给项目写一份PROJECT_CONTEXT.md再把你下一次交给AI的任务按“目标—切入口—边界—验收”四段式整理出来试一次你会立刻感受到差别。
阅读完成 · 觉得有帮助?