1. 先别急着骂AI“蠢”你可能一直在让它盲打1.1 “盲打”式提问的三张典型面孔我几乎每周都能碰到这样的场景有人打开AI编程助手敲下一句“帮我写一个用户登录功能”然后期望得到一个可以直接上线的模块。结果代码确实出来了但细看问题一大堆——没有考虑项目里现有的用户表结构把微信登录、邮箱登录的逻辑全部揉在一起异常处理只有一句print更不用说单元测试和边界条件。这不是运气问题而是一个非常普遍的“用法问题”。我管这种用法叫“盲打”你只给了AI一句话没有给它任何关于代码库、技术栈、约束条件、验收标准的上下文然后就期望它像一位在公司干了三年的老同事一样把活儿干得恰到好处。这本质上是把AI当成一个“读心术专家”而不是一个“开卷考试的考生”。第二张面孔是“碎片化喂料”。有人确实懂得要贴代码但做法是把整个文件复制粘贴进对话框也不解释这个文件在项目里的位置、和其他模块的关系然后问“帮我改改这里”。AI看到了一段没有来龙去脉的代码只能凭直觉猜你的意图改出来的结果经常和你的预期差着十万八千里。第三张面孔更隐蔽明明已经和AI聊了半个多小时把需求一步步补充进去了但AI还是会忘掉前面的关键约束到后面几轮回答里忽然引用一个早就推翻的方案。你以为它“记住了”实际上大模型的上下文窗口就像一个随时会倒掉的水杯旧信息会被新信息冲走而你没有对信息做任何“加固”和“复用”处理所以它只能越聊越偏。1.2 同一个模型为什么有人用成大神有人用成实习生我做过很多次对比测试用同一个底层大模型、同一个需求只改变输入方式产出质量能差出一整个等级。问题从来不是模型不行而是你把模型放进了什么样的“视野”里。打个比方你去一家新公司面试高级工程师人事把你带到工位不给你看需求文档不告诉你系统架构不给你任何历史代码然后说“来吧写个订单模块”。你能写出什么大概率是一套自洽的、教科书风格的代码但和公司现有的技术体系、领域模型、代码风格肯定有冲突。反过来如果给你架构图、数据字典、类似模块的源码、几条明确的验收标准你写出来的东西就完全不一样了。AI编程助手也是一样的道理。它不是一个有记忆的长期员工而是一个“上下文即视野”的工具。你给它多少相关背景它就看到多大的世界。把这句话作为前提接下来所有关于“上下文工程”的讨论才有意义。2. 上下文工程到底在解决什么问题给AI一副“看得见全局”的眼睛2.1 大模型的工作方式注定了“上下文即视野”大模型本身没有持久记忆它能“看到”的只有当前对话中被送入上下文窗口的内容。这个概念可以类比成一次开卷考试你可以把参考资料带进考场但如果带的资料乱七八糟、关键部分残缺哪怕参考资料堆得再高考试成绩也不会理想。很多人对上下文窗口有一个误解觉得窗口越大越好能塞进去的东西越多越强。实际上窗口只是容量上限你的目标不是“塞满它”而是“让足够高质量的信息占据它”。一位资深工程师进入一个陌生代码库时也不会把全部源码从头读到尾而是会先看目录结构、读README、找核心模块入口、翻历史提交记录形成一张“认知地图”。上下文工程做的事情就是为AI打造这样一张地图并且把当前任务最相关的“补给物资”精准投放到它面前。编程场景和闲聊场景最大的不同在于编程对信息准确性的要求极高一个函数名写错、一处接口语义理解偏差会导致整段代码无法落地。所以编程场景下的上下文工程不是简单的“多贴几段代码”而是要完成“筛选—压缩—结构化—表达”的全链路加工。2.2 编程场景下最值得放进上下文的四类关键信息结合自己的实操经验我认为一次高质量的任务输入至少应该覆盖以下四类信息缺一类都会明显影响产出。第一类是“目标与验收标准”。不要只说“实现登录”要说清楚“用户能够用手机号和验证码登录登录成功后跳转首页连续五次输错验证码时锁定十分钟同一账号同一时间只允许一个有效会话”。验收标准越明确AI生成的代码越有边界感不会东一榔头西一棒子。第二类是“项目结构与技术地图”。AI需要知道它正在给什么系统写代码是单体应用还是微服务前端和后端各自的目录在哪里项目里用的是哪套框架有没有统一的状态管理方案这些信息决定AI的代码风格、包引用方式和模块划分方式。第三类是“相关文件与现有实现”。如果新功能要复用某个已有的工具类、要参照某个旧的页面写法、要接某个已存在的接口最好在输入中把这些文件的路径、关键函数名、核心逻辑片段都放进去让AI直接站在“肩膀”上写代码而不是另起炉灶。第四类是“约束与历史决策”。比如团队规定禁止用某个依赖、数据库必须走某层封装、接口返回格式统一用某种结构、之前某人踩过某个坑所以大家约定XX方案。这些约束看起来琐碎却是绕过“看似合理但实际会翻车”方案的关键。2.3 信息密度比信息数量更重要我在早期的实践中犯过一个典型错误为了“省事”把一整个模块的所有源文件都丢给AI让它自己“挑重点”。结果AI被无关代码带偏甚至开始“顺手”改掉和当前需求无关的逻辑输出里混入了大量噪音。后来我意识到一个核心原则信息密度优先。宁可给AI一份三千字的精炼设计说明也不要丢给它三万字的新手能看懂的源码。原因有两个一是上下文窗口中的注意力是有限的再大的窗口也架不住无关信息抢占注意力二是大模型对“用户提示词”的重视程度通常高于对代码文件本身的理解如果你在提示词里明确写了“这些代码中只有A类和B类与本次任务相关其余仅供参考”效果会好很多。所以上下文工程的核心动作不是说“给得多”而是“给得准”。这个理念贯穿了后面所有可落地的操作。3. 实战把“盲打”改造成“有脑协作”的工作流3.1 先用一张“任务卡”替代一句话需求我之前习惯直接在对话框里输入需求后来改成先在编辑器里写好一张结构化任务卡再复制给AI。这张任务卡的模板如下你可以直接复制使用。# 任务目标 用两三句话说明要做什么希望达到什么效果 # 验收标准 - [ ] 标准1…… - [ ] 标准2…… - [ ] 标准3…… # 技术环境 - 语言/框架…… - 项目结构见项目地图随后粘贴 - 相关接口/数据表…… # 需要参考的现有实现 - 文件路径1关键函数说明 - 文件路径2关键函数说明 # 约束条件 - 必须使用项目已有的XX封装 - 禁止引入新的XX依赖 - 输出风格参考XX文件 # 请先输出 1. 你对任务的理解 2. 实现方案概览不超过300字 3. 需要我补充的信息如果没有则直接开始写代码我特意在最后加了一栏“请先输出”。别小看这一步它等于让AI先把问题复述一遍逼它在正式动手之前完成“解读任务”的过程。如果AI的理解有偏差你在它写代码之前就能发现并纠正而不是等它写出一大坨之后才发现方向错了。使用任务卡之后我最大的感受是AI生成的代码更像“标准答案”而不是“自由发挥”。原因是任务卡把模糊的题面变成了边界清晰的题目模型不需要去猜你的真实意图自然就不会产生那么多看似合理、实则跑偏的方案。3.2 用项目地图帮AI快速建立代码库认知给AI“喂”项目结构是上下文工程里性价比最高的一步。你不需要把整个项目压进上下文只需要让它看到目录骨架和关键入口文件的内容。我常用的一种做法是在每次请求之前用一条命令生成项目的物理结构再配合几个关键文件的路径一起放进对话tree -L 3 -I node_modules|target|build|dist|.git project_map.txt然后把project_map.txt的内容粘贴到任务卡的“项目地图”部分再额外注明后端入口文件在哪里数据库模型定义在哪个目录路由注册的方式是注解还是配置中心前端页面与API接口的对应关系在哪里维护。这样做的逻辑很简单AI有了“地图”之后就能在回答中对文件路径、模块名做出符合项目实际的引用。它给你的代码里写出的import路径、组件位置、接口地址往往是你项目里真实存在的而不是它臆想出来的标准结构。如果你嫌手动维护地图麻烦也可以写一个几十行的小脚本把最近一小时内被修改过的文件和它们的内容导出成一个上下文包。这套“时间窗口聚合”的方式在改bug场景里特别有用因为最近被改动的文件大概率就是问题所在的区域。3.3 用“相关文件聚合器”精准投喂代码片段地图解决的是“大局观”但真正要动手写代码时AI还需要看到和当前改动直接相关的局部细节。这时候就要做一轮“相关文件聚合”思路是从任务卡中的关键词出发定位调用链把与本次任务相关的类型、函数、数据结构抽取出来。最简单的做法是手动复制三个文件一是你要修改或参考的主文件二是它依赖的核心模型/接口文件三是同目录下风格最接近的“示例实现”文件。把这三个文件的代码片段粘贴到任务卡里并且明确告诉AI“第二个文件里的XX类型是本次改动的数据结构基础第三个文件的编码风格请尽量保持一致”。如果项目比较大我会用一个小工具脚本来自动抽取思路类似下面这版简化代码import os import re def find_related_files(root_dir, keywords, max_files5): hits [] for dirpath, _, filenames in os.walk(root_dir): if any(x in dirpath for x in [node_modules, target, .git]): continue for name in filenames: if not name.endswith((.py, .js, .ts, .java, .go, .vue)): continue path os.path.join(dirpath, name) try: text open(path, encodingutf-8, errorsignore).read() except Exception: continue if any(k in text for k in keywords): hits.append((path, len(text))) hits.sort(keylambda x: x[1]) return [p for p, _ in hits[:max_files]]这个脚本会根据关键词找出代码库里引用最集中的几个文件按体积从小到大排序避免一上来就把一个上万行的巨型文件丢给AI。实际使用中我会再人工确认一遍把明显不相关的文件剔除再把剩下的文件内容拼进任务卡。经过这三步一个请求从“一句话需求”变成了“任务卡项目地图关联代码”的完整输入包。你会发现AI输出质量有一个质的飞跃但这还没有结束——因为上下文工程不只是“输入一次”的事它还牵涉到复用它和维护它。4. 一次真实的对比实验同一需求两种喂法结果天差地别4.1 模拟项目的背景设定为了把话说得更直观我构造了一个非常常见的模拟项目某公司内部运营系统技术栈是Spring Boot加Vue已有“库存管理”模块现在需要在“入库单”上增加“状态流转”功能——入库单从“草稿”到“已提交”再到“入库完成”如果库存不符则进入“异常待处理”。我不去写具体业务代码而是从产出代码的形态上拆解两组输入的差异。这里的关键不是某个函数怎么写而是整个代码结构的设计思路会走多远。4.2 盲打组只给一句话需求的结果盲打组只输入了一句话“给入库单加一个状态流转功能草稿可以提交提交后可以入库完成库存不对就走异常。”AI的输出有几个非常典型的“盲打”特征第一它自己发明了一套状态枚举常量。项目里其实已经有InventoryStatus枚举类但它没有读这个类于是新生成了OrderStatus造成两套状态逻辑并存。第二它把校验逻辑直接写在了Controller里。项目里明明有Service层规范但它因为没有看到现有代码只能按“最通用的教科书写法”输出。第三它完全不处理并发。入库单提交和库存扣减之间有并发问题但盲打组AI根本没有感受到这个约束的存在也就无从设计乐观锁或数据库事务。这套代码如果跑在真实项目中至少需要大量重构。最麻烦的不是功能没实现而是它的实现风格与项目沉淀完全脱节等于制造了一个需要花时间消化的“异类”。4.3 上下文工程组给足信息的产出上下文工程组的输入包括项目地图、任务卡、InventoryStatus枚举的源码、现有StockService里的入库单查询方法、项目统一返回结果类以及一条明确的约束“所有校验逻辑必须放在Service层”。AI这次的表现就像换了一个人。它没有重新定义状态枚举而是直接复用InventoryStatus里已经存在的DRAFT、SUBMITTED、COMPLETED、EXCEPTION四个值它把状态校验写进了Service层Controller只是薄薄一层它还在事务方法上加了隔离级别和乐观锁的字段版本判断因为上下文里明确提到了“入库单由多人同时操作系统”。更重要的是它生成的方法签名、参数命名、返回类型都和项目现有代码高度一致。后续维护这个功能的人看到的几乎就是“老员工写的代码”几乎没有认知负担。4.4 对比结论不是模型变强了是问题定义清楚了我把两组结果的差异整理成一张表便于大家直接对照。维度盲打组上下文工程组对既有代码结构的感知无自造新枚举有复用已有枚举分层合理性校验逻辑在Controller内校验逻辑按规范放入Service层并发与事务处理完全缺失有版本字段与隔离级别命名风格一致性与项目风格脱节与现有代码保持一致后续可维护性需要重构可直接进入代码评审我更想强调的结论是底层模型没有变上下文工程没有“提高模型的智力”它只是把问题定义得足够清楚让模型把自己已有的能力充分释放出来。这个结论非常重要因为它意味着你不需要等到“更强的模型”才能享受更好的AI编程辅助你只需要在输入端多下一点功夫就可以让当前手上的工具发挥出接近它潜力上限的水平。5. 上下文工程中的“反模式”与避坑清单5.1 上下文过载喂太多反而更笨第一个坑是我见过最多人踩的既然上下文工程有用那我把整个代码库都喂给AI岂不是最强事实恰恰相反。我把这种模式叫“地毯式投喂”。曾经有一次我想让AI帮忙调整某个报表接口图省事把整个业务模块的十几个文件全部复制进去其中还包括三个跟报表毫无关系的配置文件。结果AI在回答里突然开始“关心”起日志组件的初始化顺序甚至建议我修改配置类差点把无关代码搞坏。这就是典型的上下文过载大模型会被高比例的无关信息带偏注意力是宝贵的你喂进去十句话其中三句是噪音它就可能把这三句当成隐含需求来处理。所以我在实践中给自己定了一条规矩上下文中的每一段代码、每一句说明都必须能回答“这段信息对完成当前任务有什么直接帮助”这个问题。回答不出来就删掉。5.2 只做一次性输入没有把上下文资产化第二个坑更隐蔽很多人会在单个任务上认真准备上下文但做完就丢下次遇到类似功能又开始从零准备。这种“一次性输入”的做法并没有真正吃到上下文工程的红利。正确的做法是把高频复用的上下文沉淀成团队资产。比如一个模块的架构说明、一份接口设计约定、一段“为什么要用这个方案而不是另一个方案”的历史决策记录这些都应该整理成独立的文档放进仓库的docs/context目录。之后无论是人类协作还是AI辅助都可以直接引用而不是每次都重新讲述一遍。我见过一些团队把“上下文资产目录”当成代码库的一部分来维护里面固定放三类文件MODULE_GUIDE.md模块导览、ARCHITECTURE_DECISIONS.md关键决策记录、CODING_STANDARD.md代码风格与约束。有了这三类资产不管是新人也罢、AI也罢都能在最短时间内建立起对项目的“认知基线”。5.3 AI生成的上下文也要人工复核第三个坑是有些开发者把上下文工程理解成“只要把AI自己生成的解释再塞回给AI”从而陷入一种“自产自销”的循环。我之前犯过一次这样的错误让AI写了一段关于某个功能模块的说明然后直接把这段说明作为上下文去驱动它写另一个功能。结果看起来逻辑自洽其实它在关键接口的调用方式上理解错了而我因为偷懒没有去核对真实源码导致生成代码上线前才暴露出问题。上下文工程虽然讲究“让AI多看”但最根本的信任基线还是真实的代码库和文档。AI生成的任何描述性内容都必须对照原始代码验证一遍才能作为上下文使用。否则你精心构造的输入包本质上只是一个看起来精致、实际可能跑偏的“幻觉放大器”。5.4 不要为了“精致”而牺牲效率最后一个提醒可能有点反直觉上下文工程也可能做得过重。有些朋友看到任务卡模板之后恨不得把每个字段都写成一篇论文光准备上下文就花两个小时最后写代码只要二十分钟。这是本末倒置。我认为一个合理的投入产出比是上下文的准备时间不超过编码时间的30%。如果需求本身只有“把列表页改成支持分页”这么简单那项目地图拿来即用相关文件只需筛一屏根本不需要长篇大论的验收标准清单。上下文工程讲究“刚刚好”而不是“越重越好”。判断标准只有一个AI产出一次通过的次数是不是明显变高了而不是你的提示词看起来有多专业。6. 六边形战斗力上下文工程如何补齐编程智能体的短板6.1 从盲打状态到六维能力的全面拉升标题里提到的“六边形战斗力”我把它拆成六个维度来看意图理解、全局视野、方案规划、代码生成、自我校验、迭代协作。上下文工程对每个维度都有直接的拉升作用而不是停留在“让代码更像样”这一个表层。意图理解靠的是任务卡里的目标描述和验收标准。当你明确写出“必须覆盖验证码输错五次锁定”时AI就不会只做一个裸登录框。全局视野靠的是项目地图和模块导览。AI一旦知道自己所处的系统长什么样就不容易写出和现有架构冲突的“天降代码”。方案规划靠的是约束条件与历史决策。知道“之前为什么不用消息队列”“为什么流量入口要统一走网关”以后AI提出的技术方案才会贴合现实而不是从教科书里摘一段最标准的抽象回答。代码生成、自我校验、迭代协作这三项本质上都是前三项的延伸。上下文喂到位生成代码自然命中率高命中率高自校验负担就小而当你把每个任务卡沉淀成资产后续所有迭代都能复用前一轮的上下文AI在协作中的表现会越来越像一位熟悉项目的资深同事。6.2 把上下文工程变成团队基础设施而不是个人技巧上下文工程最终应该升级为团队基础设施。个人水平再高如果每次都要靠某位核心开发者手动写任务卡、手动聚合文件那整套方法就无法规模化。一个可落地的做法是在仓库里建立context/目录维护三件套——任务卡模板、项目地图生成脚本、相关文件聚合脚本再定一条团队约定凡是要动用AI做较复杂功能先创建任务卡文件完成后再把AI最终采纳的方案要点写回ARCHITECTURE_DECISIONS.md。这样每一次与AI协作的产物都会积累成下一轮的上下文形成复利效应。我也见过更“重”一点的方案把上下文资产接入自动化流水线比如提交PR时自动把PR描述、改动文件diff、相关模块说明合并成一个上下文包推送给代码评审AI做预审。这条路完全可行但它依赖前面那些基础资产已经沉淀得足够干净否则自动化只会加速垃圾信息的传播。6.3 一点个人的实操体会说了这么多最后分享两个我在实战中反复验证过的小技巧。第一个技巧是“先写任务卡再打开AI”。以前我习惯打开对话框边聊边想结果上下文东补一块西补一块AI老是记不住前面说过的约束。现在我会在编辑器里先花几分钟把任务卡写出来哪怕只是几行要点然后一次性发给AI。这个小小的顺序调整让AI理解需求的准确率提升非常明显。第二个技巧是“学会让AI复述任务”。在任务卡末尾加一句“请先用不超过两百字复述你对任务的理解然后再开始写代码”几乎零成本却极其有效。它相当于给AI加了一道“理解校验”一旦理解偏了你能在最早期发现并立刻纠正而不是看着错误代码白白浪费五分钟。说到底上下文工程不是什么高深莫测的魔法它只是把“和人类协作时你会主动交代背景”的常识系统地延伸到和AI协作的场景里。你的AI大概率早就具备六边形潜力的底层引擎只是你一直让它在盲打。现在有了上下文工程这把钥匙剩下的就是多试几次、多攒几份资产慢慢把战斗力练满。