ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

智能体编程的上下文工程:从Mise en Place哲学到高效AI编码实践

智能体编程的上下文工程:从Mise en Place哲学到高效AI编码实践 1. 从厨房到代码为什么“备料”是智能体编程的第一性原理如果你在厨房里待过或者看过任何一档像样的烹饪节目一定会对一个词印象深刻Mise en Place。这是一个法语词直译过来是“各就各位”在烹饪界它指的是一种工作哲学——在真正开火烹饪之前把所有食材洗净、切配、称量好分门别类地放在小碗里工具也摆放就绪。厨师只需专注于烹饪本身而无需在油锅冒烟时手忙脚乱地去找一颗蒜。听起来很基础对吧但正是这个基础区分了专业厨房的井然有序和家庭厨房的兵荒马乱。现在让我们把这个概念平移到另一个看似毫不相干的领域智能体编程。当我们在谈论让AI智能体去编写、调试、重构代码时我们是否也陷入了“油锅冒烟才找蒜”的混乱答案是绝大多数时候是的。“Mise en Place for Agentic Coding”这个标题正是将这种厨房里的“备料”哲学提炼为一种严谨的上下文工程方法论。它不是在讲某个具体的AI模型或代码生成工具而是在讲一个更底层、更决定成败的环节我们如何为智能体准备“上下文”这就像是为一位顶级厨师准备一个完美的备料台。你给智能体的上下文就是它的“工作台”。台面是杂乱无章、堆满未处理的原始食材还是井井有条、分门别类、随时可取的半成品将直接决定它产出的“菜肴”即代码的质量、效率和可靠性。这篇文章就是写给那些已经尝过AI编码甜头但也饱受其“幻觉”、上下文溢出、指令漂移之苦的开发者、技术负责人和AI应用架构师的。我们将深入拆解为什么“有意识的准备”不是可选项而是智能体编码时代的必选项。我会结合大量一线实战中的踩坑经验告诉你如何系统性地构建你的“智能体备料台”把看似玄学的“提示工程”变成一套可重复、可评估、可优化的工程化流程。2. 智能体编码的“油锅困境”为什么上下文准备如此关键在深入方法论之前我们必须先理解我们面临的核心挑战。直接给智能体比如ChatGPT、Claude、Cursor等丢一个模糊的需求然后指望它吐出完美的代码这就像让一位厨师在堆满带泥土豆和整只鸡的台面上30分钟内做出一道法式炖鸡——结果要么是灾难要么厨师智能体会用自己的“想象力”幻觉来填补空白比如用番茄酱代替红酒因为你没告诉它需要红酒而它“觉得”番茄酱可能也行。2.1 智能体的“工作记忆”局限性当前的AI编码智能体无论其底层模型多么强大都有一个无法回避的物理限制上下文窗口。你可以把它想象成厨师工作台的面积。面积再大也是有限的。当你在对话中不断追加需求、发送文件、进行调试时这个“台面”很快就会被占满。更糟糕的是模型对于长上下文中不同位置信息的“注意力”是不均匀的。早期的、中间的关键信息可能会被“遗忘”或稀释。注意这里说的“遗忘”不是真的丢失而是指在模型生成下一个词时那些信息对决策的影响权重降低了。这会导致智能体前后行为不一致即“指令漂移”。我曾在一个微服务重构项目中让智能体基于一个复杂的领域模型接口生成实现类。一开始我提供了清晰的接口定义和业务规则。但在十几轮来回调试和优化后智能体突然开始生成与最初业务规则相悖的代码。回溯上下文发现最初的规则描述已经被淹没在大量调试日志和代码片段中智能体的“注意力”已经完全被最近的错误信息所吸引。2.2 “垃圾进垃圾出”的放大效应在传统编程中一个模糊的需求可能导致开发者产出有偏差的代码但开发者的人类常识和经验会起到一定的纠偏作用。然而智能体极度依赖你输入的上下文质量。你给的上下文如果模糊、矛盾、信息不全“垃圾进”那么智能体不仅会产出有问题的代码“垃圾出”还会以一种极其自信且逻辑自洽的方式呈现出来极具迷惑性。例如你只说“写一个用户登录函数。” 智能体可能会生成一个仅验证用户名密码的简单函数。但你的真实上下文可能包括需要集成OAuth 2.0、需要记录安全日志、需要防范暴力破解、需要返回特定的JWT令牌结构……这些缺失的“食材”智能体不会主动去“市场”采购它只会用台面上现有的东西一个模糊的“登录”概念来凑合。2.3 调试成本的非线性增长当智能体产出的代码基于一个糟糕的上下文时调试会变得异常痛苦。因为你不仅要调试代码本身的语法或逻辑错误更要先逆向工程出“智能体当时到底理解了什么”。这相当于你要先猜出厨师脑子里那个残缺的菜谱才能知道为什么他往炖鸡里加了草莓。这种双重调试的认知负荷常常比从头自己写代码还要高。因此“Mise en Place”的核心价值就在于通过前置的、系统性的上下文准备将智能体的“工作记忆”从存储和回忆原始、杂乱信息的负担中解放出来让它100%的“算力”都聚焦于“烹饪”即代码的推理、生成和组装这一核心创造性任务上。这本质上是一种认知卸载将人类擅长的规划、结构化、明确化工作与AI擅长的模式匹配、代码生成工作进行最优分工。3. 构建你的“智能体备料台”上下文工程的四大核心食材理解了“为什么”我们来看“怎么做”。一个专业的“智能体备料台”应该准备哪些“食材”我将其归纳为四大类它们共同构成了高质量上下文的基石。3.1 食材一清晰明确的任务规格说明书这是你的“主菜食谱”。它必须超越自然语言的模糊描述达到接近“机器可读”的精确度。输入/输出契约像写API文档一样明确。函数/模块的输入参数名称、类型、约束、示例、返回值类型、结构、可能的状态。例如不只是“处理用户数据”而是“输入UserRegistrationForm对象包含email, password, name字段其中email需符合RFC 5322标准输出ApiResponse对象成功时包含userId和jwtToken失败时包含errorCode和message。”验收条件与边界案例明确告诉智能体什么是“完成”。包括正常流主流程的成功场景。异常流各种错误处理网络超时、数据库连接失败、输入验证失败、权限不足等。边界案例空输入、极大/极小值、并发情况、数据一致性要求。非功能性需求性能指标如响应时间100ms、安全性要求如密码必须加盐哈希。“不要做什么”的负面清单这往往比“要做什么”更重要。明确禁止的模式、已弃用的库、特定的实现方式如“禁止使用eval()”“避免全局变量”“不要直接拼接SQL语句”。实操心得我习惯用一个结构化的注释块来承载这些信息直接作为给智能体的初始提示的一部分。这比在对话中零散描述要有效得多。## 任务创建用户积分扣除服务函数 **函数签名**: deductUserPoints(userId: string, points: number, reason: string): PromiseDeductionResult **输入**: - userId: 用户ID必须是存在的、状态为激活的用户。 - points: 扣除积分数必须为正整数且不大于用户当前可用积分。 - reason: 扣除原因枚举值[PURCHASE, REFUND, ADMIN_ADJUSTMENT, PENALTY]。 **输出**: - success: boolean。 - remainingPoints: number扣除后的积分余额。 - transactionId: string本次积分变动的唯一事务ID。 - error: string | null失败时的错误信息。 **业务规则**: 1. 必须是原子操作查询当前积分和扣除操作必须在同一个数据库事务中。 2. 需要记录完整的积分流水points_ledger表包含操作前余额、变动值、操作后余额、原因、时间戳。 3. 如果userId不存在或用户状态非激活立即失败错误码USER_INVALID。 4. 如果points超过可用积分立即失败错误码INSUFFICIENT_POINTS。 **禁止**: - 直接使用UPDATE ... SET points points - ?而不做前置查询校验。 - 在函数内进行任何形式的HTTP调用或IO阻塞操作日志除外。3.2 食材二精选的代码范例与风格指南这是你的“调味料和经典菜式样本”。智能体通过示例学习的速度和效果远超纯文本描述。架构与模式范例提供1-2个项目中类似模块的完整、简洁的代码文件。例如如果要生成一个GraphQL Resolver就提供一个现有的、设计良好的Resolver文件。这能传递项目整体的架构风格、分层逻辑、依赖注入方式等隐性知识。代码风格片段不是给一个通用的ESLint配置链接而是提供具体的代码片段对比。好的例子// 使用具名导出而非默认导出// 错误处理使用Result模式而非try-catch遍地开花。坏的例子// 避免嵌套超过三层的回调函数。领域特定语言如果你的项目有自己的一些术语、工具函数或设计模式提供它们的定义和用法。例如“我们使用Injectable()装饰器来自动处理依赖”“查询数据库统一使用queryBuilder()工具函数它内置了连接池管理和超时重试”。踩坑经验最初我只给智能体看“好”的代码后来发现它有时会模仿一些过时的模式。现在我会有意准备一个“模式进化说明”例如“本项目早期使用X模式处理错误但现在已全面迁移到Y模式。请参考service/authV2.ts而非service/auth.ts。”3.3 食材三精确的依赖与环境上下文这是你的“厨具和灶台状态”。智能体需要知道在哪个“厨房”里工作。技术栈清单精确到主版本号。Node.js 18 LTS,TypeScript 5.0,React 18,Prisma ORM 4.0。避免只说“用最新的”。关键依赖的API风格如果你用了某个特定的库说明你期望的用法。例如“我们使用axios进行HTTP请求并且已经配置了全局的请求拦截器添加JWT令牌所以直接使用axios.get(/api/endpoint)即可无需手动处理认证头。”项目结构导航用简短文字描述关键目录的作用。/src/models/存放Prisma生成的数据库模型和自定义的领域模型/src/services/存放核心业务逻辑每个文件对应一个领域服务/src/api/routes/存放Express路由定义它们只负责接收请求和返回响应逻辑委托给service层。运行时约束代码将运行在什么环境服务器less函数有冷启动时间限制Docker容器特定的Linux环境特定的云平台如AWS Lambda需要处理特定的环境变量3.4 食材四动态的会话状态与思维链锚点这是你在烹饪过程中的“火候控制和尝味记录”。对于复杂的、多轮的任务你需要管理对话本身。思维链显式化要求智能体在给出最终代码前先输出其思考过程。例如“请先分析需求列出实现步骤和可能遇到的坑然后再生成代码。” 这让你能中途纠正它的思路偏差而不是等到代码生成后才发现问题。关键决策记录在多轮对话中当你们共同做出一个重要技术决策时比如“决定采用策略模式来解耦不同的支付方式”用一句总结的话记录下来并在后续提示中简要提及作为“会话记忆锚点”。例如“【决策记录】支付处理器采用策略模式已定义PaymentStrategy接口。”问题-解决方案对在调试过程中将已识别的问题和已验证的解决方案明确记录下来避免智能体在后续步骤中重蹈覆辙或遗忘。这就像厨师在菜谱边上标注“上次盐放多了这次减半”。4. 实战演练一个用户注册API的“备料”到“出锅”全流程让我们通过一个具体的例子看看如何应用这套方法论。假设我们要为一个已有后端项目添加一个用户注册API。4.1 步骤一准备“备料台”编写上下文提示我不会直接打开AI对话窗口就开始打字。而是先创建一个临时的文档或注释系统性地组装上下文。# 智能体任务上下文添加用户注册API ## 1. 项目上下文 - **项目类型**: Node.js TypeScript后端服务采用分层架构。 - **核心框架**: Express.js, Prisma ORM, JWT for auth. - **代码风格**: Airbnb ESLint基础扩展规则见 .eslintrc.js。使用async/await错误处理统一使用try/catch包裹并在顶层中间件处理。 - **参考范例**: 请参考 src/api/routes/auth/login.ts 和 src/services/authService.ts 的现有模式。注意登录API的请求验证、错误响应格式。 ## 2. 任务规格说明书 **功能**: 实现用户注册端点。 **端点**: POST /api/v1/auth/register **请求体 (JSON)**: json { email: string, 必须符合邮箱格式且唯一, password: string, 最小长度8位必须包含字母和数字, username: string, 可选如未提供则使用邮箱前缀 }成功响应 (201 Created):{ success: true, data: { user: { id: uuid, email: string, username: string }, token: JWT字符串用于后续认证 } }错误响应 (400 Bad Request):邮箱格式无效:{ success: false, error: INVALID_EMAIL_FORMAT }邮箱已存在:{ success: false, error: EMAIL_ALREADY_EXISTS }密码强度不足:{ success: false, error: WEAK_PASSWORD }业务逻辑:验证请求体字段格式和强度。检查邮箱在User表中是否已存在。对密码进行加盐哈希使用bcrypt强度因子12。创建新用户记录写入数据库。生成JWT令牌payload包含userId和email有效期7天。返回用户基本信息不含密码哈希和JWT令牌。非功能需求:密码明文绝不可出现在日志中。邮箱唯一性检查需考虑数据库并发注册情况使用Prisma的create唯一约束或先findUnique后create在事务中处理。3. 给智能体的明确指令请按照以下步骤操作首先分析上述需求并列出你认为的实现计划1. 创建路由文件2. 创建或更新服务层函数3. 更新Prisma模型如果需要...。然后根据计划先生成src/api/routes/auth/register.ts文件。接着生成或修改src/services/userService.ts添加createUser函数。最后确保生成的代码遵循项目现有风格并处理所有提到的错误情况。 请分步骤进行在每个步骤后暂停等待我的确认或反馈。### 4.2 步骤二执行与交互“烹饪”过程 将上述精心准备的上下文提示复制到AI对话中。由于上下文清晰智能体通常能给出一个非常靠谱的实现计划。我会审阅这个计划确保它和我的架构理解一致。 然后让它按步骤生成代码。在每一步我都会重点检查 * **路由文件**是否正确地引入了依赖错误处理中间件是否使用正确响应格式是否符合规范 * **服务层函数**密码哈希的逻辑是否正确是否考虑了并发返回的数据结构是否匹配 * **代码风格**导入语句顺序、命名规范、异步处理方式是否与项目现有代码一致 如果在某一步发现偏差例如它可能用了一个旧的验证库而不是我们项目正在使用的Joi我会立即中断并纠正“停。我们项目使用 Joi 进行请求验证请参考 login.ts 中 validateLoginRequest 函数的写法重写注册请求的验证逻辑。” ### 4.3 步骤三验证与收尾“摆盘”与“尝味” 代码生成后我的工作并未结束。 1. **静态检查**将生成的代码放入IDE运行ESLint和TypeScript编译器检查是否有类型错误或风格问题。智能体有时会忽略一些边缘的类型定义。 2. **逻辑复查**人工通读代码特别是业务逻辑部分。检查密码哈希、唯一性约束处理、JWT生成等关键环节是否正确无误。 3. **集成测试**编写或运行一个简单的集成测试可以是手动调用也可以是简单的测试脚本验证API的完整流程。这是发现上下文理解偏差的最后一道防线。 4. **上下文归档**如果这个任务模式具有可复用性比如“添加一个标准的CRUD API”我会将这次成功的“上下文提示”作为一个模板保存下来下次类似任务只需做少量修改即可复用极大提升效率。 ## 5. 高级技巧应对复杂任务与避免常见陷阱 当任务从“炒个菜”升级为“筹办一场宴席”例如重构一个模块或实现一个包含多个交互组件的功能时简单的线性提示就不够了。 ### 5.1 分治与迭代不要试图一口吃成胖子 对于复杂任务绝对不要试图在一个提示里解决所有问题。采用“分治”策略。 * **第一步架构设计对话**。提示智能体“我们需要实现一个带实时通知的任务管理系统。请先给出一个高层次的技术架构设计包括主要模块、数据流和技术选型建议。” 基于它的建议进行讨论和修正形成共识。 * **第二步契约先行**。基于共识让智能体先定义核心的接口Interface、类型Type和数据传输对象DTO。例如“请根据上述设计先定义 Task, User, Notification 的TypeScript接口以及创建任务、更新任务状态的DTO类型。” * **第三步模块化实现**。然后按照模块逐个击破。“现在请先实现 TaskService 的核心方法包括 createTask, assignTask, updateTaskStatus。请确保它们符合你刚才定义的接口。” 每一轮都基于上一轮确定的、无歧义的“契约”进行确保上下文像搭积木一样稳步构建而不是推倒重来。 ### 5.2 幻觉检测与事实锚定 智能体的“幻觉”在复杂任务中尤为危险。对抗幻觉最有效的方法是“事实锚定”。 * **引用真实代码**当讨论现有代码时不要描述而是直接粘贴相关代码片段。例如不要说“我们的错误处理中间件是这么做的”而是说“请看现有的错误处理中间件代码[粘贴代码]请确保新的API使用相同的方式。” * **要求提供出处**当智能体给出一个建议或陈述一个关于你项目的事实时比如“Prisma模型里有一个createdAt字段”可以要求它“请指出这个信息是基于我提供的上下文还是你的通用知识如果是基于我的上下文请引用相关部分。” 这能迫使它检查自己的“记忆”减少信口开河。 * **交叉验证**对于关键逻辑可以让智能体从不同角度实现两次或者要求它解释代码的每一行在做什么。解释不通的地方往往就是幻觉或错误所在。 ### 5.3 上下文的版本管理与迭代 一个项目的“备料台”不是一成不变的。随着项目演进、技术栈升级、最佳实践变化你的上下文模板也需要迭代。 * **建立上下文库**为不同类型的任务CRUD API、数据迁移脚本、前端组件、配置部署文件建立标准化的上下文模板。 * **记录失败案例**当一次智能体交互因为糟糕的上下文而失败时事后分析原因并更新对应的上下文模板补充当时缺失的关键信息或纠正误导性描述。 * **团队共享**在团队中推广这种“备料”文化并共享优化后的上下文模板。这能极大统一团队内AI辅助编码的输出质量减少因个人提示风格差异导致的代码风格不一致问题。 ## 6. 工具化与未来展望将方法论沉淀为工作流 最高效的实践最终都会沉淀为工具或固化的工作流。 * **提示模板化**使用像Cursor IDE的.cursorrules文件或是将精心设计的提示保存为代码片段在需要时快速插入。 * **上下文文件化**为项目创建一个AGENT_CONTEXT.md文件存放项目的技术栈摘要、代码风格公约、常用范例链接、以及常见任务的提示模板。新成员或新的智能体会话都可以以此为基础。 * **与开发流程集成**在创建新的功能分支、或初始化一个新模块时将“编写智能体上下文提示”作为开发流程的第一步纳入代码审查的一部分。审查一个清晰的上下文提示往往能提前发现很多需求歧义和设计缺陷。 “Mise en Place for Agentic Coding”远不止是一个酷炫的类比。它代表了一种思维模式的转变从将AI智能体视为一个“许愿机”输入模糊愿望输出完美结果转变为将其视为一个拥有强大执行力的“专业协作者”。而作为人类开发者我们最核心、最不可替代的价值就在于成为那个**专业的“备料师”**——通过深思熟虑的上下文工程定义清晰的问题边界提供精准的约束和素材从而将智能体的能力引导向正确、高效、可靠的方向。 这个过程本身就是对问题更深层次的思考和解构它强迫你厘清需求、明确边界、审视架构。最终即使没有智能体经过这番“备料”思考后你自己去实现代码的思路也会清晰数倍。这或许就是人机协同编程带给我们的、超越工具本身的额外奖赏一种更严谨、更工程化的思维方式。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表