最近在给团队的 AI 辅助开发流程做优化时,我一直在折腾一个叫context-mode的配置项。这个名字听起来像个启动参数,但真正落地之后我才意识到,它决定了整个 AI 编程工作流的成败。说白了,context-mode就是给编程助手选择“该看什么代码”的上文模式——每次让模型生成代码或回答问题之前,决定把项目里的哪些信息放进它的工作记忆里。我见过太多项目抱怨“AI 补全越来越离谱”,最后排查下来根本不是模型不行,而是上下文喂错了。这个问题在几万行甚至几十万行的代码仓库里尤其明显:让 AI 看全部代码会犯选择困难,什么关键内容都不给又会让它凭空臆造。如果你也在用 AI 辅助写代码,或者正在给团队搭类似的开发环境,这篇文章应该能帮你少走不少弯路。1. 为什么需要“上下文模式”:它到底解决了什么问题1.1 AI 的“工作记忆”是有限的,别指望它记住整个仓库模型工作的时候,真正被读进计算流程的是一段 token 序列,也就是“它此刻能看到的东西”。这和人类的短期记忆非常像,一次性能处理的信息量是有上限的。一个几十万行的仓库,不可能全部塞进对话里,即使强行塞进去,效果也未必好。我实测过一种极端做法:把仓库索引后的所有匹配文件一股脑打包进提问里。结果模型确实“看”到了所有文件,但回答却开始四平八稳,甚至出现自相矛盾的结论。原因是无关代码占据了大量工作记忆,模型对关键位置的注意力被稀释了。打个比方,这就像让一个人在满屏小字里找某个电话号码,你给他看整本通讯录,他反而容易看错行。context-mode的第一个价值,就是给有限的“工作记忆”做减法。它要解决的核心问题,不是“让 AI 看到更多”,而是“让 AI 在合适的时机看到合适的部分”。这两者的区别,就是你问一个同事“这个函数怎么改”时,是直接把整个项目甩给他,还是先把相关文件和调用关系整理好再开口。1.2 两个极端都不能走:全塞进去 vs 什么都不给很多初用 AI 编程助手的人,会走两个极端。第一个极端是“全自动检索打包”:把代码库里所有与关键词相关的文件都丢给模型。这种做法看似稳妥,但带来的问题很实际——首轮响应变慢,token 消耗成倍上涨,而且检索出来的文件之间可能包含大量互相矛盾的旧逻辑。模型需要在垃圾信息里找金子,生成质量自然不稳定。第二个极端是“只给当前打开的文件”:为了省事,只让 AI 看正在编辑的这个文件。这个方案对小脚本没问题,但一遇到跨文件改动就立刻露馅。比如你改了一个被二十个地方引用的工具函数,只给它看当前文件,它大概率会对着函数内部“硬补”,完全意识不到调用方也需要同步调整。真实项目里最常踩的坑,恰恰是这两种极端之间的模糊地带。context-mode的意义,就是在“检索-筛选-注入-生成”这条链路上,给开发者在关键节点留出人工干预的位置。不是让 AI 自己拍板看什么,而是由你决定当前任务适合哪种上下文策略。1.3 模式的本质:给上下文做分级调控我最终把context-mode拆成了四种基础模式:compact、balanced、deep、custom。名字很直白,但真正设计的时候需要考虑很多细节。compact模式只注入当前文件、最近编辑的片段和少量全局规则,适合修一个明显的小 bug、调样式、补注释。balanced模式会额外纳入同目录文件、直接被引用的模块和近期对话摘要,适合日常开发。deep模式则会把仓库索引、跨模块调用链、架构文档都纳入考虑,适合重构、审计、排查疑难问题。custom模式允许你手写文件选择器,精确控制哪些路径参与上下文。这几种模式本质上是同一个能力的“分级调控”:决定上下文广度、检索深度和 token 预算的配比。用备菜的类比来解释——有人做快手菜只需要两三样配料,有人办宴席要把整个厨房的调料都摆出来。context-mode就是让 AI 知道,你今天到底是来“炒个饭”,还是来“做一桌年夜饭”。2. 核心细节解析:context-mode内部到底调了什么2.1 上下文的来源与优先级理解了为什么需要模式之后,更关键的问题是:模式内部到底在调什么?我拆开看,发现context-mode主要管理五个信息源,它们各自有更新频率和优先级。信息源更新频率优先级典型用途当前文件与选区每次编辑时更新最高代码补全、局部修改、解释报错同目录与直接引用文件依赖分析后更新高跨文件小改动、函数签名调整仓库级索引(RAG)索引更新时重建中全局检索、定位实现、架构问答项目规则文件配置变更时生效高但常被忽略风格约束、命名规范、禁用项对话历史随会话增长中低多轮澄清、连续需求优先级设计里有个容易出错的地方:对话历史的优先级不能太高。很多模型会被“最近几轮说过的话”带偏,即使当前文件已经改了,它还是顺着旧对话往下编。我见过最典型的翻车现场是——开发者改完接口参数后忘了开新会话,AI 连续三次按旧签名生成调用代码,报错之后还一脸无辜。所以模式切换时,一定要连带调整对话历史的使用策略。compact模式下历史只保留最近一轮,deep模式反而可以适当保留完整多轮讨论,因为复杂重构需要保持思路连贯。2.2 三个关键参数:token 预算、检索数量、chunk 大小真正细看配置项,有三个参数决定了模式的实际表现:max_context_tokens、retrieval_top_k、chunk_size。max_context_tokens是给模型“工作记忆”画的预算线。预算越大,AI 能看到的内容越多,但响应速度会变慢,费用也会上涨。我自己的经验值仅供参考:compact模式设在 4k 到 8k,balanced模式在 8k 到 16k,deep模式在 32k 以上。这里的核心不是数字本身,而是让你意识到:上下文不是免费午餐,每 token 都有成本。retrieval_top_k控制的是检索阶段召回多少个相关片段。这个值太大,会引入噪声;太小,则找不到关键文件。实测下来,5 到 10 是个比较舒服的范围。如果你发现模型每次都抓错文件,先别急着怪索引,看一眼是不是top_k设置太低,或者命中的文件被忽略规则误伤了。chunk_size则决定仓库索引时把代码切成多大块。切得太大,一个块里混着多个函数,检索命中后噪声很高;切得太小,语义又被切碎,模型难以理解完整逻辑。我倾向于把块大小控制在 256 到 512 token 之间,并且尽量按函数边界切割,而不是机械地按字符数切。2.3 排除规则和忽略文件:模式也是“不看什么”的艺术很多人在配置context-mode时只关注“看什么”,却忽略了“不看什么”。这部分恰恰是最容易提升检索质量的地方。我把node_modules、dist、构建产物、二进制资源、测试 fixture、密钥文件都加入了默认忽略名单。这些文件有几个共同特点:体量大、语义信息少、经常变动,而且一旦被检索命中,往往会霸占大量上下文额度。更麻烦的是,某些工具会递归扫描,导致一次检索返回几十个匹配项,其中大部分是无关的生成代码。忽略规则的重要性在于,它可以显著提升检索命中率。索引里少了一万个垃圾文件,真正有用的文件被召回的概率自然会变大。同时,这也是隐私底线——我绝不允许 AI 工具把密钥或线上配置读进上下文,这不是信任问题,而是边界问题。另外一个小细节:忽略规则不是越严格越好。我见过有人把tests目录整个忽略,结果重构时 AI 完全不理解测试对旧接口的依赖,生成了一堆破坏既有测试的代码。合理的策略是按模式区分——调试单个功能时可以忽略测试目录,做全局重构时必须保留。3. 实操过程:搭一套可以用起来的context-mode3.1 最小可落地的配置示例理论说再多,不如直接给配置。下面这份是我在某团队内部实验项目里实际跑过的context-mode.yaml,你可以直接抄作业再按需调整。project: demo-workspace modes: compact: description: "小改动、快速修复" max_context_tokens: 8192 retrieval_top_k: 3 include_files: - "src/**/*.{ts,js}" include_recent_edits: true history_turns: 1 balanced: description: "日常开发、新增功能" max_context_tokens: 16384 retrieval_top_k: 6 include_files: - "src/**/*.{ts,js}" - "tests/**/*.{ts,js}" include_recent_edits: true history_turns: 3 deep: description: "跨模块重构、架构排查" max_context_tokens: 32768 retrieval_top_k: 10 include_files: - "src/**/*" - "tests/**/*" - "docs/**/*.md" - "README.md" use_repository_index: true history_turns: 8 excludes: - "node_modules/**" - "dist/**" - "build/**" - "**/*.lock" - "**/.env" - "**/.git/**" - "**/*.png" - "**/*.jpg" rules: - "所有新增函数必须包含单元测试" - "禁止修改公共 API 的签名而不更新调用方" - "错误处理使用统一的日志组件"注意几个容易被忽视的地方。第一,include_files用的是 glob 通配,不是正则。第二,excludes优先于include_files,也就是说即使某个文件被 include 规则命中,只要在 excludes 里,依然会被忽略。第三,rules是全局规则,会注入所有模式,所以别写太多,否则会挤占上下文额度。我一开始把规则写了一百多条,结果 AI 在多数请求里都在“背规则”,真正写代码反而草草了事。后来精简到十条以内,质量立刻上来了。3.2 把“选模式”变成肌肉记忆的工作流配置文件只是第一步,真正让context-mode发挥价值的是工作流。我的做法是建一张简易决策表,贴在项目文档里,让每位开发者遇到任务时先过一遍。任务类型推荐模式说明修一个明确的小 bugcompact文件少,范围小,响应最快新增一个独立功能页balanced需要理解部分现有代码结构跨模块重构deep必须看到调用链和架构约束Code Review/审计deep + 只读规则需要全局理解且不产生修改写单元测试balanced既要看被测代码,也要看测试风格除了模式选择,我还给常用操作绑了快捷指令。输入/ctx compact会立即把当前会话切到紧凑模式,输入/ctx reset会清空对话历史并重建上下文。这个小动作非常重要,因为模式切换只是改了“未来该看什么”,如果历史里还堆着旧内容,模型依然会被带偏。在多人协作时,我还会把模式声明写进任务卡片描述。谁负责这个需求、建议用什么模式、涉及哪些模块,一目了然。这样 AI 在工作流里就不是一个“神秘的黑盒”,而是一个行为可预期的协作者。3.3 用一个轻量脚本按 diff 自动切模式配置靠手工选,偶尔会忘。为了减少记忆负担,我写了一个非常轻量的 Python 脚本,根据当前的git diff自动推荐模式。思路很简单:统计变更文件数和总行数,再判断是否有跨目录变动。import subprocess import sys def get_diff_stats(): diff = subprocess.run( ["git", "diff", "--stat"], capture_output=True, text=True, ).stdout lines = diff.strip().splitlines() file_count = len([l for l in lines if l.endswith("|")]) added = 0 for line in lines: if "|" not in line: continue try: head = line.split("|")[0] added = max(added, line.count("+")) except Exception: pass return file_count, added def suggest_mode(): count, added = get_diff_stats() if count <= 2 and added <= 30: return "compact" if count <= 8 and added <= 200: return "balanced" return "deep" if __name__ == "__main__": print(suggest_mode())脚本本身很简陋,但够用。它会在git提交前跑一次,给出建议模式,开发者确认后手动执行/ctx 对应模式。这种做法比完全自动化可靠——机器推荐,人拍板,AI 执行,每一步都有明确责任人。顺带一提,diff 统计里的“跨目录”判断最简单的方式是看文件路径的顶层目录数量。如果一次改动同时动了src、tests、docs,几乎一定是大改动,直接用deep不会错。4. 常见问题与排查技巧实录4.1 五个高频问题和抢救方案速查表context-mode用多了之后,我攒了一张问题排查表。每次 AI 表现不对,先对号入座。现象可能原因处理办法模式切了但还是按旧行为输出对话历史未清空执行/ctx reset后再切模式deep模式响应很慢仓库索引太旧重建索引,或调整为按需实时检索compact模式回答太泛检索召回太少,关键文件没进上下文加大retrieval_top_k,检查忽略规则检索结果频繁命中无关文件chunk 太大或忽略配置遗漏按函数边界切 chunk,补充忽略项索引初始化占用过高全量索引范围太广仅索引src和关键文档目录这里面最容易被忽视的是第一行:很多人以为切换模式就是改个参数,但实际上模型在同一个会话里会继承大量历史状态。我踩过一次很深的坑,在balanced模式下讨论了半天旧架构,然后直接切换到deep做重构设计,结果 AI 依然沿用刚才讨论里的错误假设。从那以后,“先 reset 再切模式”就成了铁律。4.2 “上下文过期”是最大杀手:改完代码,AI 还在读旧版本上下文管理有个很隐蔽的问题,我称它为“上下文过期”。具体表现是:你刚改了某个模块的接口,AI 下次回答时还在用旧签名推断逻辑,甚至信誓旦旦地指出“这个函数不存在”。原因在于,仓库索引和对话历史并不会因为你的编辑器保存而实时更新。索引有自己的重建周期,对话历史则是快照式的。要解决这个问题,有几个处理姿势。第一,改动关键公共接口后,手动触发一次索引刷新,确认更新完成再提问。第二,如果项目支持,可以在提问时强制注入“最近修改文件列表”,让 AI 优先关注当前变更。第三,也是我自己的习惯:每个任务开始时新建会话,而不是在旧会话里继续追加。上下文一旦过期,与其反复纠正,不如直接归零。4.3 我从坑里爬出来的三条心得最后分享几条从实际操作中沉淀下来的经验,都属于常规文档里不会写的内容。第一条,全局规则不要贪多。我见过团队在规则文件里写了大量“应该怎么做”的指导,结果 AI 每次都要先处理规则,生成代码反而越来越保守。规则应当是硬约束,比如“禁止删除公共 API”“所有请求必须加超时”,而不是软建议。第二条,模式要和任务绑定,不要设置一个全局默认就完事。如果默认设成deep,每个小请求都会变慢变贵;如果默认设成compact,遇到复杂需求时就容易答非所问。最佳实践是把默认设成balanced,遇到具体任务再往两侧切换。第三条,切换任务时必须重置上下文。这个操作看似多余,但它能省下无数“AI 怎么还在纠结上一个问题”的时间。重置之后,模式才能真正发挥作用。最后再分享一个小技巧这个技巧是我在实际使用中摸索出来的:在项目里留一个AI_CONTEXT.md文件,每次任务开始前,把当前任务的目标、约束、涉及模块写进去。这样不管切到什么模式,AI 至少有一个稳定的“锚点”可以参考。你在配置context-mode时,不妨也把这个文件纳入include_files的固定清单,实测下来,这个文件的投入产出比是所有配置项里最高的。
最近在给团队的 AI 辅助开发流程做优化时,我一直在折腾一个叫context-mode的配置项。这个名字听起来像个启动参数,但真正落地之后我才意识到,它决定了整个 AI 编程工作流的成败。说白了,context-mode就是给编程助手选择“该看什么代码”的上文模式——每次让模型生成代码或回答问题之前,决定把项目里的哪些信息放进它的工作记忆里。我见过太多项目抱怨“AI 补全越来越离谱”,最后排查下来根本不是模型不行,而是上下文喂错了。这个问题在几万行甚至几十万行的代码仓库里尤其明显:让 AI 看全部代码会犯选择困难,什么关键内容都不给又会让它凭空臆造。如果你也在用 AI 辅助写代码,或者正在给团队搭类似的开发环境,这篇文章应该能帮你少走不少弯路。1. 为什么需要“上下文模式”:它到底解决了什么问题1.1 AI 的“工作记忆”是有限的,别指望它记住整个仓库模型工作的时候,真正被读进计算流程的是一段 token 序列,也就是“它此刻能看到的东西”。这和人类的短期记忆非常像,一次性能处理的信息量是有上限的。一个几十万行的仓库,不可能全部塞进对话里,即使强行塞进去,效果也未必好。我实测过一种极端做法:把仓库索引后的所有匹配文件一股脑打包进提问里。结果模型确实“看”到了所有文件,但回答却开始四平八稳,甚至出现自相矛盾的结论。原因是无关代码占据了大量工作记忆,模型对关键位置的注意力被稀释了。打个比方,这就像让一个人在满屏小字里找某个电话号码,你给他看整本通讯录,他反而容易看错行。context-mode的第一个价值,就是给有限的“工作记忆”做减法。它要解决的核心问题,不是“让 AI 看到更多”,而是“让 AI 在合适的时机看到合适的部分”。这两者的区别,就是你问一个同事“这个函数怎么改”时,是直接把整个项目甩给他,还是先把相关文件和调用关系整理好再开口。1.2 两个极端都不能走:全塞进去 vs 什么都不给很多初用 AI 编程助手的人,会走两个极端。第一个极端是“全自动检索打包”:把代码库里所有与关键词相关的文件都丢给模型。这种做法看似稳妥,但带来的问题很实际——首轮响应变慢,token 消耗成倍上涨,而且检索出来的文件之间可能包含大量互相矛盾的旧逻辑。模型需要在垃圾信息里找金子,生成质量自然不稳定。第二个极端是“只给当前打开的文件”:为了省事,只让 AI 看正在编辑的这个文件。这个方案对小脚本没问题,但一遇到跨文件改动就立刻露馅。比如你改了一个被二十个地方引用的工具函数,只给它看当前文件,它大概率会对着函数内部“硬补”,完全意识不到调用方也需要同步调整。真实项目里最常踩的坑,恰恰是这两种极端之间的模糊地带。context-mode的意义,就是在“检索-筛选-注入-生成”这条链路上,给开发者在关键节点留出人工干预的位置。不是让 AI 自己拍板看什么,而是由你决定当前任务适合哪种上下文策略。1.3 模式的本质:给上下文做分级调控我最终把context-mode拆成了四种基础模式:compact、balanced、deep、custom。名字很直白,但真正设计的时候需要考虑很多细节。compact模式只注入当前文件、最近编辑的片段和少量全局规则,适合修一个明显的小 bug、调样式、补注释。balanced模式会额外纳入同目录文件、直接被引用的模块和近期对话摘要,适合日常开发。deep模式则会把仓库索引、跨模块调用链、架构文档都纳入考虑,适合重构、审计、排查疑难问题。custom模式允许你手写文件选择器,精确控制哪些路径参与上下文。这几种模式本质上是同一个能力的“分级调控”:决定上下文广度、检索深度和 token 预算的配比。用备菜的类比来解释——有人做快手菜只需要两三样配料,有人办宴席要把整个厨房的调料都摆出来。context-mode就是让 AI 知道,你今天到底是来“炒个饭”,还是来“做一桌年夜饭”。2. 核心细节解析:context-mode内部到底调了什么2.1 上下文的来源与优先级理解了为什么需要模式之后,更关键的问题是:模式内部到底在调什么?我拆开看,发现context-mode主要管理五个信息源,它们各自有更新频率和优先级。信息源更新频率优先级典型用途当前文件与选区每次编辑时更新最高代码补全、局部修改、解释报错同目录与直接引用文件依赖分析后更新高跨文件小改动、函数签名调整仓库级索引(RAG)索引更新时重建中全局检索、定位实现、架构问答项目规则文件配置变更时生效高但常被忽略风格约束、命名规范、禁用项对话历史随会话增长中低多轮澄清、连续需求优先级设计里有个容易出错的地方:对话历史的优先级不能太高。很多模型会被“最近几轮说过的话”带偏,即使当前文件已经改了,它还是顺着旧对话往下编。我见过最典型的翻车现场是——开发者改完接口参数后忘了开新会话,AI 连续三次按旧签名生成调用代码,报错之后还一脸无辜。所以模式切换时,一定要连带调整对话历史的使用策略。compact模式下历史只保留最近一轮,deep模式反而可以适当保留完整多轮讨论,因为复杂重构需要保持思路连贯。2.2 三个关键参数:token 预算、检索数量、chunk 大小真正细看配置项,有三个参数决定了模式的实际表现:max_context_tokens、retrieval_top_k、chunk_size。max_context_tokens是给模型“工作记忆”画的预算线。预算越大,AI 能看到的内容越多,但响应速度会变慢,费用也会上涨。我自己的经验值仅供参考:compact模式设在 4k 到 8k,balanced模式在 8k 到 16k,deep模式在 32k 以上。这里的核心不是数字本身,而是让你意识到:上下文不是免费午餐,每 token 都有成本。retrieval_top_k控制的是检索阶段召回多少个相关片段。这个值太大,会引入噪声;太小,则找不到关键文件。实测下来,5 到 10 是个比较舒服的范围。如果你发现模型每次都抓错文件,先别急着怪索引,看一眼是不是top_k设置太低,或者命中的文件被忽略规则误伤了。chunk_size则决定仓库索引时把代码切成多大块。切得太大,一个块里混着多个函数,检索命中后噪声很高;切得太小,语义又被切碎,模型难以理解完整逻辑。我倾向于把块大小控制在 256 到 512 token 之间,并且尽量按函数边界切割,而不是机械地按字符数切。2.3 排除规则和忽略文件:模式也是“不看什么”的艺术很多人在配置context-mode时只关注“看什么”,却忽略了“不看什么”。这部分恰恰是最容易提升检索质量的地方。我把node_modules、dist、构建产物、二进制资源、测试 fixture、密钥文件都加入了默认忽略名单。这些文件有几个共同特点:体量大、语义信息少、经常变动,而且一旦被检索命中,往往会霸占大量上下文额度。更麻烦的是,某些工具会递归扫描,导致一次检索返回几十个匹配项,其中大部分是无关的生成代码。忽略规则的重要性在于,它可以显著提升检索命中率。索引里少了一万个垃圾文件,真正有用的文件被召回的概率自然会变大。同时,这也是隐私底线——我绝不允许 AI 工具把密钥或线上配置读进上下文,这不是信任问题,而是边界问题。另外一个小细节:忽略规则不是越严格越好。我见过有人把tests目录整个忽略,结果重构时 AI 完全不理解测试对旧接口的依赖,生成了一堆破坏既有测试的代码。合理的策略是按模式区分——调试单个功能时可以忽略测试目录,做全局重构时必须保留。3. 实操过程:搭一套可以用起来的context-mode3.1 最小可落地的配置示例理论说再多,不如直接给配置。下面这份是我在某团队内部实验项目里实际跑过的context-mode.yaml,你可以直接抄作业再按需调整。project: demo-workspace modes: compact: description: "小改动、快速修复" max_context_tokens: 8192 retrieval_top_k: 3 include_files: - "src/**/*.{ts,js}" include_recent_edits: true history_turns: 1 balanced: description: "日常开发、新增功能" max_context_tokens: 16384 retrieval_top_k: 6 include_files: - "src/**/*.{ts,js}" - "tests/**/*.{ts,js}" include_recent_edits: true history_turns: 3 deep: description: "跨模块重构、架构排查" max_context_tokens: 32768 retrieval_top_k: 10 include_files: - "src/**/*" - "tests/**/*" - "docs/**/*.md" - "README.md" use_repository_index: true history_turns: 8 excludes: - "node_modules/**" - "dist/**" - "build/**" - "**/*.lock" - "**/.env" - "**/.git/**" - "**/*.png" - "**/*.jpg" rules: - "所有新增函数必须包含单元测试" - "禁止修改公共 API 的签名而不更新调用方" - "错误处理使用统一的日志组件"注意几个容易被忽视的地方。第一,include_files用的是 glob 通配,不是正则。第二,excludes优先于include_files,也就是说即使某个文件被 include 规则命中,只要在 excludes 里,依然会被忽略。第三,rules是全局规则,会注入所有模式,所以别写太多,否则会挤占上下文额度。我一开始把规则写了一百多条,结果 AI 在多数请求里都在“背规则”,真正写代码反而草草了事。后来精简到十条以内,质量立刻上来了。3.2 把“选模式”变成肌肉记忆的工作流配置文件只是第一步,真正让context-mode发挥价值的是工作流。我的做法是建一张简易决策表,贴在项目文档里,让每位开发者遇到任务时先过一遍。任务类型推荐模式说明修一个明确的小 bugcompact文件少,范围小,响应最快新增一个独立功能页balanced需要理解部分现有代码结构跨模块重构deep必须看到调用链和架构约束Code Review/审计deep + 只读规则需要全局理解且不产生修改写单元测试balanced既要看被测代码,也要看测试风格除了模式选择,我还给常用操作绑了快捷指令。输入/ctx compact会立即把当前会话切到紧凑模式,输入/ctx reset会清空对话历史并重建上下文。这个小动作非常重要,因为模式切换只是改了“未来该看什么”,如果历史里还堆着旧内容,模型依然会被带偏。在多人协作时,我还会把模式声明写进任务卡片描述。谁负责这个需求、建议用什么模式、涉及哪些模块,一目了然。这样 AI 在工作流里就不是一个“神秘的黑盒”,而是一个行为可预期的协作者。3.3 用一个轻量脚本按 diff 自动切模式配置靠手工选,偶尔会忘。为了减少记忆负担,我写了一个非常轻量的 Python 脚本,根据当前的git diff自动推荐模式。思路很简单:统计变更文件数和总行数,再判断是否有跨目录变动。import subprocess import sys def get_diff_stats(): diff = subprocess.run( ["git", "diff", "--stat"], capture_output=True, text=True, ).stdout lines = diff.strip().splitlines() file_count = len([l for l in lines if l.endswith("|")]) added = 0 for line in lines: if "|" not in line: continue try: head = line.split("|")[0] added = max(added, line.count("+")) except Exception: pass return file_count, added def suggest_mode(): count, added = get_diff_stats() if count <= 2 and added <= 30: return "compact" if count <= 8 and added <= 200: return "balanced" return "deep" if __name__ == "__main__": print(suggest_mode())脚本本身很简陋,但够用。它会在git提交前跑一次,给出建议模式,开发者确认后手动执行/ctx 对应模式。这种做法比完全自动化可靠——机器推荐,人拍板,AI 执行,每一步都有明确责任人。顺带一提,diff 统计里的“跨目录”判断最简单的方式是看文件路径的顶层目录数量。如果一次改动同时动了src、tests、docs,几乎一定是大改动,直接用deep不会错。4. 常见问题与排查技巧实录4.1 五个高频问题和抢救方案速查表context-mode用多了之后,我攒了一张问题排查表。每次 AI 表现不对,先对号入座。现象可能原因处理办法模式切了但还是按旧行为输出对话历史未清空执行/ctx reset后再切模式deep模式响应很慢仓库索引太旧重建索引,或调整为按需实时检索compact模式回答太泛检索召回太少,关键文件没进上下文加大retrieval_top_k,检查忽略规则检索结果频繁命中无关文件chunk 太大或忽略配置遗漏按函数边界切 chunk,补充忽略项索引初始化占用过高全量索引范围太广仅索引src和关键文档目录这里面最容易被忽视的是第一行:很多人以为切换模式就是改个参数,但实际上模型在同一个会话里会继承大量历史状态。我踩过一次很深的坑,在balanced模式下讨论了半天旧架构,然后直接切换到deep做重构设计,结果 AI 依然沿用刚才讨论里的错误假设。从那以后,“先 reset 再切模式”就成了铁律。4.2 “上下文过期”是最大杀手:改完代码,AI 还在读旧版本上下文管理有个很隐蔽的问题,我称它为“上下文过期”。具体表现是:你刚改了某个模块的接口,AI 下次回答时还在用旧签名推断逻辑,甚至信誓旦旦地指出“这个函数不存在”。原因在于,仓库索引和对话历史并不会因为你的编辑器保存而实时更新。索引有自己的重建周期,对话历史则是快照式的。要解决这个问题,有几个处理姿势。第一,改动关键公共接口后,手动触发一次索引刷新,确认更新完成再提问。第二,如果项目支持,可以在提问时强制注入“最近修改文件列表”,让 AI 优先关注当前变更。第三,也是我自己的习惯:每个任务开始时新建会话,而不是在旧会话里继续追加。上下文一旦过期,与其反复纠正,不如直接归零。4.3 我从坑里爬出来的三条心得最后分享几条从实际操作中沉淀下来的经验,都属于常规文档里不会写的内容。第一条,全局规则不要贪多。我见过团队在规则文件里写了大量“应该怎么做”的指导,结果 AI 每次都要先处理规则,生成代码反而越来越保守。规则应当是硬约束,比如“禁止删除公共 API”“所有请求必须加超时”,而不是软建议。第二条,模式要和任务绑定,不要设置一个全局默认就完事。如果默认设成deep,每个小请求都会变慢变贵;如果默认设成compact,遇到复杂需求时就容易答非所问。最佳实践是把默认设成balanced,遇到具体任务再往两侧切换。第三条,切换任务时必须重置上下文。这个操作看似多余,但它能省下无数“AI 怎么还在纠结上一个问题”的时间。重置之后,模式才能真正发挥作用。最后再分享一个小技巧这个技巧是我在实际使用中摸索出来的:在项目里留一个AI_CONTEXT.md文件,每次任务开始前,把当前任务的目标、约束、涉及模块写进去。这样不管切到什么模式,AI 至少有一个稳定的“锚点”可以参考。你在配置context-mode时,不妨也把这个文件纳入include_files的固定清单,实测下来,这个文件的投入产出比是所有配置项里最高的。