新闻详情

新闻详情

首页 / 资讯中心 / 详情

GSD:目标驱动的Agent上下文清洗实践

发布时间:2026/10/2 5:09:56来源:尧图网络
GSD:目标驱动的Agent上下文清洗实践
最近在带Agent开发时我踩了一个大坑Agent从代码库里扒了一段废弃代码当参考然后照着那个过时API写了一大堆实现跑起来全是编译错误。我连续调了三小时才反应过来问题不在模型而在上下文——我给了它一个“脏”上下文。这个坑让我总结了一套方法我管它叫GSDGoal-driven Context Sanitization也就是目标驱动的上下文清洗。核心就一句话别让Agent在脏上下文里写代码。这篇文章不聊高深理论主要聊聊我在实际项目里怎么治理Agent的上下文包括什么是脏上下文、它为什么会破坏输出、以及一套已经验证可行的实操方法。如果你在用Cursor、Codex、Claude Code这类工具或者自己在搭Agent框架这篇文章应该能帮你少走不少弯路。1. 什么是“脏上下文”它到底怎么污染Agent的输出1.1 一个真实场景Agent把坏代码当成了金科玉律前两周我负责维护一个内部工具需要Agent帮我把一个老模块从Python 2迁移到Python 3。我图省事直接把整个仓库目录丢给Agent让它自己找。结果Agent在仓库里找到一份好几年前的旧模块里面充斥着xrange、iteritems这类早已消失的语法更离谱的是它还把那份旧代码当成“标准实现”用同样的风格开写新代码。最终生成的东西不仅不能运行还把我们的代码风格带偏了。事后复盘根子就在我给Agent的上下文里塞满了“历史垃圾”。当时的目录里既有新旧版本共存的代码又有几百行废弃的helper函数还有一堆带# TODO: remove标记的测试函数。Agent的注意力机制不具备“这是废代码不要看”的先验判断它只会觉得所有出现在上下文里的代码都是同等重要的参考材料。1.2 脏上下文的三大来源代码库噪点、对话历史累积、工具返回失控我总结下来脏上下文主要来自三个地方基本每个项目踩坑都是这三个源头在作怪。第一个是代码库噪点。这是最常见的坑包括各种旧版本文件、被注释掉的代码块、临时调试代码、第三方库示例里夹带的非标准写法甚至还有藏在node_modules或venv里的一些示例文件。很多人喜欢把整个仓库打包给Agent这和给一个刚入职的实习生扔一整个硬盘让他自己找资料没区别——他能找到但大概率会找到一堆过期文档。第二个是对话历史累积。在同一个会话里持续修改代码时前面几轮的错误代码、失败日志、反复尝试过的方案都会留在上下文里。如果你中途不清理这些历史“伤疤”会持续干扰模型判断。比如你让Agent先改A函数改错了接着让它改B函数结果Agent可能还惦记着A函数的那套失败实现把A的错误模式也带进B里。第三个是工具返回失控。Agent通过工具调用拿到的返回内容往往比我们想象的要大得多。比如一个grep -r可能返回几百个文件路径一个cat file.js可能把几千行代码一次性扔进来而实际需要修改的可能只有其中10行。如果不对工具返回做限制这些无关内容就成了“噪音”把真正重要的信号给淹没了。这三类脏东西叠加起来相当于你让Agent在一个堆满旧图纸的办公室里画新图纸——不是它能力不行是你给的材料有毒。2. 为什么Agent如此脆弱从原理上理解上下文的重要性2.1 注意力机制一视同仁模型不会自动过滤“垃圾”如果你理解Transformer的注意力机制就能明白为什么上下文质量如此关键。Attention的计算本质上是对所有输入token进行加权求和模型在训练过程中学会了关注哪些token之间有关系但它并没有一个“这条信息是不是历史遗留”的标签。在你喂给它的文本里一份2020年的废弃代码和一份当前规范代码在注意力计算时是被同等对待的。换句话说模型缺乏“垃圾回收机制”。自动过滤噪点这种能力目前还得靠人来完成。既然模型不会过滤那我们就得在上游帮它把脏东西摘干净。这正是GSD想解决的问题与其指望模型变聪明不如先把输入变干净。2.2 上下文窗口是稀缺资源垃圾多了干货就没位置了现在大家都在追大上下文128K、200K听着很唬人。但仔细想想窗口再大也是物理上限。你往里面塞了50K的日志和无关代码剩下给有效代码的空间就只剩一丁点。即使有128K一个大项目的核心业务代码可能也有几十万行你根本塞不完更别说模型对中间部分的注意力还会衰减。我经常看到有人把一份几千行的文件直接cat给Agent然后说“帮我改一下中间那个函数”。Agent确实看到了文件内容但它要在这几千行里找到你指定的函数还得记住前面的实现逻辑再结合任务思考修改方案。有效的上下文被大量无关代码稀释输出质量自然下降。我自己的经验是在同等模型下只给Agent一段20行的函数定义加调用处的30行上下文要比给它整个800行文件的效果好得多。少即是多在Agent上下文这里体现得淋漓尽致。2.3 指令遵循的“最后指令效应”上下文污染会造成指令矛盾还有一个隐蔽问题模型对后面出现的信息往往有更强的“服从倾向”也就是所谓的近因偏好。当你把一坨字面意思矛盾的内容塞进上下文时Agent很可能会优先采纳最后看到的那份“过时技术”或“错误纠偏”导致行为混乱。比如你在一开始明确说“不要使用旧API”但上下文里某段历史代码使用了旧API而这段代码恰恰紧邻任务描述部分模型就会照葫芦画瓢。我遇到过Agent在我提供的示例里看到pkg_resources就跟着用哪怕系统指令里明确写了“优先使用importlib.metadata”。因为它看到的实例代码离任务更近权重更高。上下文不干净连指令都变得不再可靠。理解这几点后你就会明白治理上下文不是“锦上添花”而是Agent代码质量的生死线。3. GSD的核心方法论给Agent一个干净的可执行上下文3.1 什么是GSD目标驱动的上下文清洗而不是简单的删除GSD的全称是Goal-driven Context Sanitization目标驱动的上下文清洗。它的核心思想不是把所有信息减少到最简而是围绕当前任务目标把与目标相关的有效信息组织成高度可用的结构。就好比不是给实习生一台装满了全公司文件的电脑而是把“本期任务”相关的三份文件放到桌面上并把过期版本移走。GSD和“简单压缩上下文”的区别在于压缩是为了省token而GSD是为了提升信噪比和指令一致性。省token只是副产品真正的收益是模型能更准确地聚焦任务、更少被无关内容干扰。3.2 步骤一用任务描述替代模糊需求让Agent知道该干什么脏上下文往往始于一个模糊的任务描述。你如果只写“帮我改一下这个函数”Agent就必须自己猜测你的目标而猜测的依据就是上下文里那些乱七八糟的东西。所以GSD的第一步就是先写出清晰的任务描述。一个合格的任务描述应该包含目标、输入、期望输出、约束条件和验收标准。举个例子。目标在 src/utils/dateFormat.js 中实现一个 formatDate 函数。 输入Date 对象。 期望输出格式化字符串 YYYY-MM-DD HH:mm:ss。 约束不要修改其他文件不要引入第三方库使用纯 JavaScript 实现。 验收运行 npm test -- date-format 通过所有用例。我在实际操作中会把这段描述放在对话的最前面作为整个上下文的锚点。这样即使后面穿插了代码片段模型也知道一切内容都是为了服务这个目标。3.3 步骤二用代码检索代替“喂整个仓库”只捞相关片段很多人给Agent上下文的第一反应是“把整个项目目录拖进去”。这非常不推荐。正确的做法是先定位相关代码再只喂相关片段。我常用的方式是ripgrep。比如要修改某个模块我会先搜索rg -n formatDate|parseDate|dateFormat src --type js然后根据搜索结果只把符合的文件路径和行号抽出来再通过查看代码片段决定带哪些部分。如果你在用Cursor或类似的Agent工具直接在对话框里#引用文件也是可以的但建议只引用和任务相关的文件别把整个目录扔进去。在Agent框架里这个动作可以抽象成“限制检索范围”。比如在AutoGen或LangGraph里给Agent的检索工具只开放src目录的权限排除tests、examples、legacy这类容易混入噪声的路径。3.4 步骤三对检索到的内容做“去噪归一化”去除伪相关这段代码真的需要全部放进上下文吗不一定。在检索结果里经常会有大段注释、被注释掉的旧实现、模板生成的无意义占位代码。这些都属于“伪相关”——看起来相关实际只会增加干扰。我在实际操作中会给检索结果做一遍轻量清洗去掉注释块除非注释里有关键信息去掉console.log/print调试语句去掉明显废弃的代码分支统一缩进和引号风格。这些操作可以用简单的脚本完成。# 提取 src/utils/dateFormat.js 中第1-80行并去除注释 sed -n 1,80p src/utils/dateFormat.js | sed /^\s*\/\/\s*/d去噪之后我会把代码片段放进上下文的“代码参考区”并在前面标注来源路径和版本状态比如[参考代码] 文件src/utils/dateFormat.js (当前工作版本第1-80行)这个标注很重要它告诉Agent这段代码是“当前要工作的代码”而不是“历史参考”。3.5 步骤四用结构化上下文模板把信息打包给Agent与其让Agent从一串连续的文本中去“领悟”哪些是任务、哪些是参考、哪些是约束不如把信息结构化。我会用Markdown模板组织上下文保持一致的格式这样每次Agent都能快速定位信息。我常用的一套上下文模板如下## 任务 [一句话描述当前任务] ## 输入 [输入参数或文件内容的关键部分] ## 依赖代码 [与本次任务直接相关的函数、类或文件片段标注来源] ## 约束条件 [禁止的行为、必须遵守的代码规范、不允许修改的文件] ## 验收标准 [如何判断结果正确] ## 示例 [如果可能提供一个正确的输入输出示例]这个模板的好处有两点。第一它能让模型快速建立“任务-代码-约束”的映射关系减少歧义。第二它把“参考代码”的位置固定下来避免模型把参考代码误认为是任务本身。在实际项目中我会为每个Agent任务生成一个这样的Markdown文件然后让Agent读取这个文件作为主要上下文。3.6 步骤五控制对话历史长度适时开启新会话并摘要上下文一个会话里如果已经进行了很多轮对话脏东西会越积越多。即使每一步你都小心翼翼前面的失败尝试、报错信息依然会残留在上下文里。我的习惯是每完成一个子任务就开一个新会话把上一个会话的结论浓缩成一个摘要然后把摘要粘贴到新会话中作为上下文的一部分。摘要模板也不复杂就写三个内容做了什么、最终结果是什么、还有哪些遗留问题。例如[会话摘要] 已完成formatDate的实现测试通过3个用例。遗留问题handleInvalidInput分支未覆盖下一步需要补上。当前工作文件 src/utils/dateFormat.js。这样做能有效避免对话历史里的旧错误污染新任务。4. 实操在Cursor/VSCode/Codex中践行GSD的几个具体配置4.1 在System Prompt里写清Agent行为和红线System Prompt是你控制Agent行为的第一个抓手。我建议在System Prompt里明确写出与上下文治理相关的规则尤其是“不要做什么”。我给自己的Agent设置了一套“红线提示词”你们可以按需取用。[System] 你是一名资深软件工程师。在开始任务前请先阅读上下文中的所有代码片段确认它们与任务目标相关。 规则 1. 只使用上下文中明确标注为“当前版本”的代码不要使用历史或废弃代码。 2. 如果上下文中的API信息不够确定不要盲目调用先搜索或询问。 3. 不要修改与当前任务无关的文件。 4. 输出代码时请附带简短的修改说明和影响范围。 5. 如果上下文已经超过1000行请提示用户精简而不是继续基于大段上下文操作。这条System Prompt解决了很多我的痛点特别是第1条和第5条。它可以强制Agent在做决定前意识到“这个代码可能是过期的”也提醒上下文已经膨胀时需要精简。4.2 用受控检索代替“全选粘贴”以VSCode为例很多人在VSCode里让Agent写代码时习惯性地会把整个文件内容复制粘贴到对话窗口里。其实VSCode的搜索功能远比你想的好用。比如你要让Agent修改某个函数的实现可以先用CtrlShiftF搜索函数名找到函数定义的位置和所有调用点。然后只复制相关行而不是整页代码。如果你用的是Cursor这类支持“引用文件”的编辑器也可以直接在对话中file引用但要注意引用的文件数量。我通常限制在5个以内。超过5个文件基本可以判断你的子任务划分得太大需要拆分。或者在给Agent的上下文中只保留这5个文件中与你改动相关的函数定义其余部分用注释省略。4.3 让Codex/Claude只读必要文件而不是整个工作区在使用Codex CLI或Claude Code这类工具时默认行为往往是把整个工作区的文件索引都加载进来。虽然它们有层次的代码感知但依然可能把你仓库根目录下的README.md里的示例代码也当成参考导致风格跑偏。我通常在工具的配置里指定一个allowlist限制Agent只能访问src目录排除掉legacy、examples、generated等目录。在Claude Code里可以像这样配置{ permissions: { allow: [Read(src/**)], deny: [Read(legacy/**), Read(generated/**), Read(node_modules/**)] } }在Codex CLI里则可以在会话开始时显式告诉它“本次任务只关注src/utils下的文件其他目录不需要读取”。这一步虽然简单但能非常有效地把脏上下文的入口堵住。4.4 用项目摘要文件PROJECT_CONTEXT.md作为最外层上下文如果你的项目有一定的复杂度光靠临时检索还不够。我会在项目根目录放一个PROJECT_CONTEXT.md文件专门给Agent和未来的自己看。这个文件不是代码而是对整个项目架构、技术栈、核心约定、废弃代码位置的描述。每次让Agent做任务前先让它读这个文件。# PROJECT_CONTEXT.md ## 项目架构 - src/源码 - legacy/旧版本不可修改仅作参考 - generated/自动生成代码禁止手改 ## 技术栈 - Node.js 18TypeScript - 使用importlib 规范不支持CommonJS ## 约定 - API文档见 src/api/README.md过期的API在docs/obsolete.md中标记 - 日期格式化使用 ISO-8601不使用 Date.toLocaleString() ## 废弃代码位置 - legacy/legacyDateParser.js旧的日期解析器不要去读也不要去借鉴有了这个文件Agent就能在进入具体代码前先建立“什么可以看、什么不能看”的框架。我个人觉得这是性价比最高的上下文治理手段它相当于给Agent画了一张地图避免它在地雷区乱逛。5. 常见问题排查当Agent还是在脏上下文里乱写怎么办即使有了GSD还是会遇到一些意外。这里我整理了几个高频问题和对应的排查思路。5.1 Agent引用了不存在的API或函数现象生成的代码调用了某个函数但在项目里根本没有定义。根因Agent在上下文里看到了一个过时的调用示例以为该API仍然存在。这最常见于legacy代码或第三方库的旧版本文档被塞进上下文的情况。解决先检查你的上下文参考区是否混入了过期代码。用GSD模板重新组织上下文并且加入一条System Prompt“如果调用某个API前不确定它是否存在于当前项目中请先搜索项目代码确认不要盲写。”如果项目有类型定义把类型定义文件如.d.ts也放进去。5.2 修复一个Bug却引入两个新Bug现象Agent在修复某个问题时改动范围超出了任务边界结果出现了新的错误。根因对话历史里包含了之前的错误状态Agent试图“修正”错误时把不该动的代码也改了。或者上下文里的参考代码太多Agent分不清哪些是依赖哪些是它可以修改的区域。解决立刻开新会话只保留当前错误信息和最少的上下文。新会话的任务描述改为“修复getUser函数中的空指针错误只允许修改getUser函数体其他函数只能读取”。这个限制能让Agent把注意力集中在目标区域。5.3 Agent在VSCode写C代码没有代码提示现象Agent生成C代码时在VSCode里没有任何智能提示看起来像“瞎写”。根因VSCode的C/C提示依赖compile_commands.json或c_cpp_properties.jsonAgent生成的上下文缺少头文件路径和宏定义导致IDE无法解析符号。本质上也是上下文不完整——你给了它代码却没给它“编译配置上下文”。解决在给Agent的任务描述中附加上编译配置的关键信息。比如“项目使用CMake根目录包含compile_commands.json头文件在include/目录下”。对于Agent生成的C代码要求它确保#include路径正确。我在实际中还会让Agent先读取一遍compile_commands.json再让它写代码。5.4 Agent开始问无关问题或者跑偏现象你让它改一个函数它突然开始研究项目里的其他模块甚至问你要不要重构整个目录结构。根因工具的检索结果里包含了大量无关内容Agent把“无关内容”当成了“潜在任务线索”。解决缩小工具返回范围。比如给搜索工具加上输出限制只返回文件名行号相关代码片段不返回全文。在Agent框架中如果使用grep工具可以约定返回值每行不超过200字符并且只匹配与关键词出现的行。5.5 常见问题速查表问题现象根因GSD解法引用不存在的API上下文含过期代码限制检索范围加入“先搜索后调用”规则修复A引入B新bug对话历史污染新会话隔离任务边界C代码无提示缺少编译配置上下文带入compile_commands.json/头文件路径偏离任务问无关问题工具返回过多无关内容控制返回行数限定只返回相关片段生成风格与项目不符参考了legacy代码在PROJECT_CONTEXT.md中明确风格规范大段上下文导致漏改有效信息被稀释使用结构化模板减少参考片段数量6. 踩坑心得与进一步思考6.1 别追求大上下文小而精才是王道我一开始也迷信“上下文越大Agent记得越清楚”后来发现完全不是这么回事。当上下文窗口塞满几万行代码后模型往往会在代码的海洋里迷路。我做过一个对比实验同一个任务是修复一个日期解析函数方案A给Agent 6000行的整个工具模块方案B只给Agent 40行的函数定义加20行测试代码。结果方案B不仅在更短时间内生成正确代码而且改动范围非常精准。方案A则花了很长时间在无关的日志解析代码上纠缠。这件事让我坚定了一个原则上下文的大小应该以任务所需的必要信息为上限。能10行解决绝不放100行。6.2 上下文清洗要自动化否则很难坚持一开始我觉得手工清洗上下文太麻烦每次都要先搜索、再筛选、再写模板。但用了几次之后我发现这些步骤完全可以脚本化。我写了一个小脚本传入一个需求描述自动从代码库检索相关片段、剥离注释、生成GSD格式的Markdown文件。这样我只用把文件路径和任务描述写清楚剩下的清洗工作交给脚本。如果你在用Agent框架你还可以让“上下文清洗Agent”去做这件事——先让一个Agent负责检索和清洗再把干净上下文传给你真正写业务代码的Agent。6.3 参考吴恩达的Agent教程把任务分解每个子任务用独立上下文吴恩达在Agent课程里反复强调过“任务分解”的价值。我后来把GSD和任务分解结合起来效果非常明显。原来我让一个Agent一口气完成“重构整个模块”它总是越改越乱。现在我会拆成几个子任务先让Agent在干净上下文中梳理模块接口再让它在第二个干净上下文中实现核心算法最后让它在第三个上下文中补测试。每个子任务都是一个小而干净的上下文互不污染。这样做的额外好处是你可以并行处理多个子任务。因为上下文隔离每个Agent都是独立工作不会互相干扰。6.4 最后一点把Agent当实习生你提供的资料质量决定它的产出经历了这么多我最大的感触就是Agent在当前阶段更像一个能力很强但经验不足的实习生。你给它一份整洁的任务说明书和几段相关代码它就能交出像样的活如果你给它一坨千头万绪的仓库转储再指望它自己“提炼重点”那你大概率会失望。脏上下文不是Agent的错是我们没有尽到“管理上下文”的责任。我自己在实际项目中把GSD当成日常流程后Agent的产出质量提升非常明显。以前我总在改Agent烂代码和Agent反复横跳之间消耗精力现在基本可以做到“给什么上下文得到什么结果”。如果你最近也被Agent的“脑洞代码”折磨得头疼建议从下一个任务开始先清一清上下文再让它动手。你会发现很值得。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Grok 4.7升级实战:API开发者零改造提稳指南 2026/10/2 5:51:15

Grok 4.7升级实战:API开发者零改造提稳指南

1. Grok 4.7 不是“又一个新模型”,而是API开发者手里的扳手升级了Grok 4.7 正式上线——这个标题里藏着一个被多数人忽略的关键定语:“同价同速”。它不是一次常规的模型迭代,更不是靠堆参数刷榜的营销动作。对API开发者而言,这是…

阅读更多 →
DroidCam USB直连手机摄像头实战指南 2026/10/2 5:51:15

DroidCam USB直连手机摄像头实战指南

1. 项目概述:为什么非得用数据线连手机摄像头? DroidCam 是我过去三年里在直播、远程教学、轻量级视频采集场景中反复验证过的一套方案——它不是最炫的,但胜在稳定、低延迟、跨平台兼容性好。而标题里说的“通过数据线调用手机摄像头”&…

阅读更多 →
从传统机箱到openrig:铝型材开放式机架搭建实战指南 2026/10/2 5:51:15

从传统机箱到openrig:铝型材开放式机架搭建实战指南

玩硬件这些年,让我最省心的一台机器,不是哪款旗舰机箱装的,而是这套自己搭的开放机架。先说清楚,openrig 是我给自己这套“开放式硬件承载平台”起的名字,核心就一句话:用标准铝型材搭一个没有侧板的骨架&a…

阅读更多 →
Android SeekBar 自定义样式完全指南:从 XML 到 Compose 2026/10/2 5:51:15

Android SeekBar 自定义样式完全指南:从 XML 到 Compose

1. 为什么原生 SeekBar 总是“看起来很丑”——从设计缺陷到定制刚需SeekBar 是 Android 开发中出现频率极高的基础控件,但凡涉及音视频播放、参数调节、时间选择等场景,它几乎无处不在。可几乎所有做过 UI 适配的开发者都踩过同一个坑:原生 …

阅读更多 →
Java工程师的Cursor提示规则实战指南:构建语境感知的IDE协作者 2026/10/2 5:51:15

Java工程师的Cursor提示规则实战指南:构建语境感知的IDE协作者

1. 这不是“AI提示词”,而是Java工程师的实时协作者养成指南你有没有过这样的体验:在Cursor里敲下Service,光标停住,等三秒,弹出的补全是Service("userService")——可你真正想写的是Service public class U…

阅读更多 →
从零搭建AI工程能力:评测、模型接入与服务化落地实践 2026/10/2 5:51:08

从零搭建AI工程能力:评测、模型接入与服务化落地实践

1. 从零搭建AI工程能力,为什么大多数人卡在“会调包但不会落地”“ai-engineering-from-scratch”这个标题,第一次看到的时候我就觉得它戳中了一个很真实的痛点。现在网上讲AI的教程铺天盖地,但绝大多数要么停留在“调个API、跑个demo”的层面…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉