news 2026/10/8 11:57:37

AI编程助手上下文控制:context-mode插件如何精准投喂代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI编程助手上下文控制:context-mode插件如何精准投喂代码

如果你跟我一样把 AI 编程助手当成日常搭档,大概也经历过这样的崩溃瞬间:让 AI 改一个函数,它把整个仓库的无关代码全读进去,然后一本正经地给你一个根本跑不起来的方案;反过来,只给它当前文件的三十行,它又会漏掉关键的依赖定义,直接答非所问。这个“喂多少上下文才算刚好”的度,真的很难把握。我折腾了几个月,最后做了个取名 context-mode 的 IDE 插件,核心思路很简单:上下文不应该是一个固定的窗口大小,而应该是按模式切换的——窗口模式、符号模式、调用栈模式、仓库检索模式。这篇文章我把整个设计思路、实现要点和踩过的坑原原本本写出来,希望对正在做类似工具的人有点参考价值。

1. 为什么会有 context-mode:AI 编码助手的上下文控制问题

先说结论:AI 编码助手的能力上限,很大程度上取决于你给它看了什么。模型本身的能力当然重要,但“上下文”才是日常使用中最容易翻车的地方。这里的上下文不是聊天记录里那几条来回消息,而是“代码世界中,当前这次修改到底涉及哪些文件、哪些函数、哪些定义”。

1.1 上下文不是越大越好,而是越准越好

很多人的第一反应是:那就把所有相关的代码都喂给 AI 呗。我自己最初也这么干过,把整个模块的代码拼成一个大文本塞给模型,结果分两种情况:

  • 模型确实能读到相关信息,但注意力被大量无关代码稀释,经常抓错重点,改出来的代码风格混乱、逻辑绕弯。
  • 上下文太长之后,模型的“等效注意力”急剧下降,尤其当无关代码里有相似命名的函数时,它甚至会把 A 模块的实现套到 B 模块的需求上。

还有一个更现实的问题:成本。现在很多 AI 编码助手按 token 收费,或者有上下文长度上限。你把整个仓库塞进去,一次可能就好几千个 token,改十个文件就得重新传十次,时间和钱都烧不起。

所以 context-mode 的第一步,就是把“上下文”从一个大水池,拆成几个可以按需切换的水龙头。每个模式产出不同粒度的代码片段,AI 拿到的永远是一份经过筛选的材料,而不是一个未经整理的仓库。

1.2 设计前的三个约束

在动手写代码之前,我给自己定了三个约束,这三个约束后来帮了大忙:

第一,上下文提取必须基于语法结构,不能靠正则。正则匹配“找函数名”在简单的例子里看着没问题,但遇到嵌套函数、类方法、装饰器、多行签名就全崩了。必须用能容错的语法解析器,因为用户代码不一定是语法完整的。

第二,提取速度必须足够快,不能阻塞编辑器。用户只是把光标移到了另一个函数上,你如果花两秒才生成上下文,那这个插件就是负收益。所以要用增量解析,并且要设计缓存。

第三,模式之间要能自动切换。不是让用户手动去点一个“上下文模式”按钮,那样太反人类。理想状态是:用户打开一个 diff、把一个错误面板的条目点开、或者把光标移进某个函数体,context-mode 自动根据当前情境选择合适的模式。

这三个约束直接决定了后面所有的技术选型。Tree-sitter 解决了第一个,增量解析和缓存解决第二个,事件驱动架构解决第三个。

1.3 context-mode 的定位:不是替代 AI 助手,而是给所有 AI 助手提供素材

我一开始想把这个插件绑定到某一款具体的 AI 工具上,后来发现路走窄了。因为市面上的 AI 编码助手五花八门,有的有自己的 Agent 模式,有的只做自动补全,还有的是通用对话界面。它们的共同需求其实是:一份“你现在需要了解的代码上下文”。

所以 context-mode 干脆做成了一个通用层:它负责把当前编辑状态转换成结构化上下文,然后通过一个简单的接口暴露出去。无论你把它接到 Cline、Continue,还是自己写脚本调大模型 API,都能用。这个设计后面证明非常正确,因为不同 AI 工具的上手成本完全不同,但“如何获取上下文”这件事是共通的。

2. 核心模式拆解:window / symbol / stack / repo 各自管什么

context-mode 总共有四种模式,名字都很直白。下面逐个讲清楚它们各自解决什么问题,以及我为什么要设计成这样。

2.1 window 模式:当前文件的可视窗口,最简单但最常用

window 模式的输出很简单:把光标附近的代码块原样提取出来。默认行为是“当前光标所在函数 + 上下各 N 行注释”,N 默认是 10。

这个模式适合什么场景呢?最常见的是让 AI 补全一个局部逻辑,比如“在这个 for 循环里加一个去重逻辑”,这时候你根本不需要知道函数外面的世界,只需要让 AI 看到循环结构本身、相关的局部变量、以及循环体前后的上下文。

它的实现难度最低,但却是所有模式里用得最多的。因为大部分编码动作都是局部修改。而且这个模式对 latency 极度敏感,用户敲完提示词的瞬间就希望上下文已经准备好了,所以 window 模式必须做到“零感知”。

我后来在 window 模式里加了一个很有意思的小功能:把光标所在行的缩进层级也提取进去。因为模型经常在输出代码时把缩进搞乱,给它看当前缩进级别,能大幅减少“对不齐”的翻车。

2.2 symbol 模式:只要函数签名和当前实现,不要无关代码

symbol 模式是 context-mode 真正区别于“把整个文件塞进去”的第一个模式。它做的事情是:解析当前文件的 AST,找出光标所处的那一个具名函数/类/方法,然后只提取这个符号的签名、文档注释、主要实现体,以及它直接引用到的本文件内其他符号的定义。

举个例子:你在handleUserLogin这个函数里,这个函数内部调用了validatePassword和createSession。symbol 模式不会把整个auth.ts文件给你,它只给你handleUserLogin的完整实现,外加validatePassword和createSession这两个直接依赖的定义。如果这两个依赖函数又引用了别的东西,默认不再递归展开,除非用户手动要求。

这个设计来自一个很痛的教训:早期我天真地把整个文件都发给 AI,结果文件里有一个叫currentUser的全局变量不断地被各处修改,AI 读完整个文件之后,反而搞不清currentUser在handleUserLogin这个语境里到底是什么值。只有把“当前函数 + 直接引用符号”这个小集合交给它,它才能真正聚焦。

2.3 stack 模式:沿着调用链往上回溯,把相关函数打包

stack 模式解决的是“跨函数、跨文件”的追踪问题。它和 symbol 模式最大的区别是:symbol 只看“当前函数直接引用了谁”,而 stack 模式会沿着调用关系向上回溯——也就是反向查找“谁调用了当前函数”,再递归找出“谁调用了那谁”。

举个具体场景:你在修userService里的一个方法,这个方法报了一个 “null pointer” 错误。问题往往不在方法本身,而在调用方的使用方式。比如某个 controller 在调用这个方法之前没有做空值校验。如果你只给 AI 看userService里的方法实现,它可能根本不知道为什么会有空值传进来。

stack 模式默认向上回溯两层。它会用 LSP 的textDocument/references或者本地索引找到当前函数的所有调用点,然后把调用点的上下文也一起打包。注意这里不需要全量调用点,只需要一两个有代表性的调用点,否则上下文又会爆炸。

我在实现的时候发现一个非常实用的技巧:优先选择“在 git diff 中出现过的调用点”。因为如果调用点最近被改过,那这个 bug 大概率就是这次改动引起的。把 diff 信息叠加在 stack 上下文上,AI 的诊断准确率会高很多。

2.4 repo 模式:仓库级检索,但绝不整仓投喂

最后一个模式是 repo 模式。它对应的是“这个 bug 可能在任何地方”的场景,比如一个只有在运行时才会暴露的错误信息。这时候光看当前文件和调用链都不管用,得做仓库级检索。

很多 AI 工具在这个场景下的做法是:直接把仓库发给 AI,让 AI 自己翻。我的看法是:这是最糟糕的做法。一个中等仓库轻松几百个文件,让 AI 从头读到尾,不仅 token 爆炸,而且很多机器生成的代码(lock 文件、编译产物、前端脚手架)纯属噪音。

repo 模式的做法是:先对仓库做一个轻量级索引,包括文件路径、文件大小、最近修改时间、每个文件里的符号列表。当用户问一个跨仓库的问题时,先用关键词或错误信息进行检索,筛选出最相关的 5-10 个文件,再用 symbol 模式提取这些文件中的相关部分。

实际实现我用了一个很朴素但效果很好的方案:把仓库里的所有符号名、文件名、git 提交信息加入一个简单的倒排索引,用户输入关键词时按相关性排序。这个方案比训练一个 RAG 模型轻得多,而且对于一个代码仓库来说,符号名通常已经包含了足够强的语义信息。

模式上下文大小典型场景单次 token 成本
window极低补全循环、局部逻辑调整500-1500
symbol低修改函数实现、添加方法1000-4000
stack中追踪 bug、排查调用链问题3000-8000
repo高跨仓库定位问题源头5000-15000

这张表是我自己长期使用后粗略统计的,不同项目差异很大,但能看出一个趋势:不是所有问题都需要消耗大量 token。mode 选得对,AI 看得准,钱包也不受罪。

3. 实现细节:用 Tree-sitter 把代码切片成“可投喂”的上下文

这一节是 context-mode 的核心技术部分。前面说的那些模式听起来很美好,真正实现起来却有不少门道,尤其是“如何把一段代码准确地切出来”。

3.1 为什么选 Tree-sitter,而不是正则或 LSP 的符号信息

很多插件在“找到当前函数”这件事上会选择直接调 LSP 的textDocument/documentSymbol,它确实能返回文档结构,但它有几个问题:第一,LSP 返回的符号位置有时是模糊的,比如大多数实现对方法内的匿名函数、嵌套闭包支持不好;第二,你不能从 LSP 拿到底层源码文本,还得自己根据 range 再截取;第三,LSP 需要语言服务启动、连接,对这个插件来说太重了。正则更不用说,根本处理不了嵌套结构。

所以我选了 Tree-sitter。它有几个无可替代的优势:

  • 增量解析:编辑器里每个字符的修改,它都能在 O(修改大小) 时间范围内更新语法树,而不是整个文件重新解析。这对 5000 行以上的文件尤其重要。
  • 容错解析:用户正在打字的时候,代码可能处于不完整状态,Tree-sitter 依然能够给出一个部分正确的 AST,只是把错误节点标记出来。这意味着光标移动时上下文也能稳定提供。
  • 多语言支持:tree-sitter 的语言库覆盖很广,JavaScript、TypeScript、Python、Go、Rust、C/C++、Java、Ruby 都有现成的实现。我在插件里只需要按文件类型加载对应的 grammar。

代价就是编译成本和提高接入复杂度。但相比收益,这个代价完全值得。

3.2 AST 节点反查:从光标位置定位到“最内层函数”

实现 mode 的第一步是把光标位置映射到 AST 节点。Tree-sitter 提供了一个namedDescendantForPosition接口,可以直接拿到光标所在的具名节点。

import Parser from 'web-tree-sitter'; const parser = new Parser(); const lang = await Parser.Language.load( '/path/to/tree-sitter-typescript.wasm' ); parser.setLanguage(lang); const tree = parser.parse(sourceCode); const root = tree.rootNode; const node = root.namedDescendantForPosition({ row: cursor.line, column: cursor.character, });

拿到最内层节点之后,再往上遍历它的祖先节点,找到第一个类型是“函数声明/箭头函数/方法声明”的节点。这里有一个重要的细节:不能只找最内层的函数节点。因为在嵌套闭包的场景下,光标可能在回调函数里,但用户实际想改的是外层业务函数。我后来的策略是:找到从光标到根节点路径上的所有函数节点,组成一个“函数链”。默认取最内层函数,但如果最内层函数是类似.map((item) => ...)这种匿名回调,就退回到外层具名函数。

查找函数链的伪代码如下:

function findFunctionChain(node): FunctionNode[] { const chain = []; let current = node; while (current) { if (isFunctionNode(current)) { chain.unshift(current); } current = current.parent; } return chain; }

把函数链里的第一个具名函数作为主符号,后面的内部函数作为辅助上下文,这样在闭包场景下 AI 既能看清整体逻辑,也能看到细节实现。

3.3 用 Tree-sitter query 提取“符号 + 直接依赖”

定位到函数节点之后,下一步是提取函数签名和具体内容。这个可以用 Tree-sitter 的 query 语法,也可以在节点上直接遍历子节点提取。我推荐用 query,因为它的表达能力更强,而且很多语言的手册里都有现成示例。

这是 TypeScript 里提取函数声明和参数列表的 query 示例:

(function_declaration name: (identifier) @name parameters: (parameters) @params body: (statement_block) @body) (method_definition name: (property_identifier) @name parameters: (formal_parameters) @params body: (statement_block) @body)

拿到的@name、@params、@body就是三个具体的 AST 子节点,然后取它们的文本就得到了完整函数。注意@body可能非常长,比如一个 500 行的函数体。我实际提取时做了个截断:函数体默认最多保留 200 行,超出部分在上下文里用注释注明“剩余 X 行已省略”,防止把 token 浪费在一个函数内部。

接下来是“直接依赖”。这一步的做法是:遍历主函数体里的所有identifier和call_expression,提取出函数内引用的其他名称。这一步不用做到完美,只需要收集所有可能的引用名,然后去当前文件的符号列表里匹配同名函数。匹配到的就是直接依赖。

class SymbolIndex { symbolsByFile = new Map<string, SymbolInfo[]>(); findDirectDependencies(functionNode, filePath): SymbolInfo[] { const referencedNames = collectIdentifiers(functionNode); const fileSymbols = this.symbolsByFile.get(filePath) ?? []; return fileSymbols.filter((s) => referencedNames.has(s.name)); } }

这就是 symbol 模式的核心逻辑。简单、快、可靠。

3.4 增量解析和缓存:让“取上下文”这件事快到感知不到

Tree-sitter 本身支持增量解析,但插件要配合编辑器的编辑事件才能发挥这个优势。具体做法是:在文件每次编辑时,记录编辑的前后文本和偏移,调用tree.edit()方法,把编辑应用到现有的语法树中,而不是整体重新 parse。tree.edit()需要你提供一个Edit对象,包含起始位置、旧文本长度、新文本长度和新插入文本的前几个字符。

tree.edit({ startIndex: change.rangeOffset, oldEndIndex: change.rangeOffset + change.text.length, newEndIndex: change.rangeOffset + change.rangeLength, startPosition: change.range.start, oldEndPosition: { row: ..., column: ... }, newEndPosition: { row: ..., column: ... }, }); // 增量解析 const newTree = parser.parse(updatedSource, tree);

细心的读者会发现,parser.parse传了第二个参数tree,这就是 Tree-sitter 的增量解析入口:它会把旧的语法树作为起点,而不是从零开始。实测下来,对于 2000 行的文件,整体解析可能耗 5-10ms,增量解析只要 0.5-1ms。这个差异在快速敲代码时体感很明显。

缓存方面,我做了两层:

  • 全局符号索引缓存:文件未变更时,直接从缓存拿符号列表。
  • 模式输出缓存:模式、文件路径、光标位置组合起来作为 key,同一 key 且文件未变更时直接返回上次生成的上下文。

缓存失效事件就是文件保存或者大段编辑。小编辑不影响光标所在函数的结构时,也可以不失效,只更新位置映射。

4. 与 LSP 和 Git Diff 联动:自动发现“应该被注意”的代码

Tree-sitter 解决了“如何从当前文件切上下文”的问题,但真实编码场景里,问题往往分布在多个文件、多个历史版本之间。context-mode 的下一层,是把 LSP 的诊断信息和 Git Diff 融入上下文,让 AI 看到“刚才改了什么”“哪里报错了”。

4.1 从 Git Diff 提取“本次改动涉及的符号”

在 stack 模式和 symbol 模式下,我都加入了“diff-aware 增强”。具体逻辑是:读取当前文件相对 HEAD 的 diff,解析每个 hunk 头里的行号范围,然后把这些行号映射回 Tree-sitter 的节点上。

git diff的 hunk 头长这样:

@@ -10,6 +10,7 @@ function foo() {
  • -10,6表示旧文件从第 10 行开始,连续 6 行。
  • +10,7表示新文件从第 10 行开始,连续 7 行。

把新旧行号拿到之后,用这些行号去 AST 里反向查找对应的函数节点。如果一个函数体的起始行号落在 diff 的 hunk 范围内,就认为这个函数“被本次改动影响”。然后把这些函数的名字和 diff 片段单独收集起来。

这个功能有什么用呢?最典型的场景是:

你刚改完parseConfig这个函数,然后在loadConfig里报了个错误。你问 AI “为什么这里会报错”,如果 AI 没有 diff 信息,它只知道loadConfig的实现,不知道你刚把parseConfig的返回结构改了。有了 diff-aware 增强,context-mode 就会自动把这两个函数一起打包,AI 一眼就能看出新结构不兼容。

这个功能在多人协作的仓库里尤其好用。因为还有另一种情况:你什么都没改,但报错出现了。那多半是同事刚改了某个公共函数。此时把“最近 5 次提交涉及的文件和符号”提取出来,跟当前报错位置做交叉匹配,AI 的诊断效率会有质的提升。

4.2 用 LSP 诊断信息让 AI 看到“编辑器底部的红色波浪线”

错误列表里的信息,AI 通常是看不到的。所以我把 LSP 的诊断信息做成了合法上下文。

实现方式也简单:订阅 LSP 的textDocument/publishDiagnostics通知,收集当前文件或整个 workspace 的 error、warning 和 info 信息。注意只需要收集 error 和 warning,info 一般是风格提示,塞给 AI 反而干扰判断。每条诊断包含位置、严重级别和消息。

这些诊断信息怎么用呢?最好的方式是跟 window 模式结合。比如光标在某个函数里,函数体内两行有编译错误,context-mode 会在上下文的开头插入一段这样的文字:

当前文件 diagnostics: - [error] src/userService.ts:42:7 Cannot find name 'authToken' - [error] src/userService.ts:58:3 Type 'undefined' is not assignable to parameter of type 'Config'

然后紧接着是函数定义。AI 读的时候先看到错误,再看代码,就会非常清楚“改这个函数要解决哪两个问题”。我实测下来,这个功能对 TypeScript 这种编译错误频繁的语言特别有效。

4.3 事件驱动的模式选择:什么时候自动切到哪种模式

现在四种模式和两个数据源(Tree-sitter、LSP、Git diff)都有了,最后一步是设计“模式选择”的规则。我最初的设想是给用户四个按钮,后来发现没人会去点。于是改成了一套基于上下文的自动选择逻辑:

  • 如果当前文件有未保存的编辑,默认用 window 模式,因为这个时候 AST 都不稳定,没必要做复杂的跨文件提取。
  • 如果用户打开了 git diff 面板并选中了一个 hunk,context-mode 自动切到 diff-aware symbol 模式,提取该 hunk 涉及的所有新旧函数。
  • 如果用户点击 LSP 错误面板里的某条错误,context-mode 自动定位到对应函数,切换到 stack 模式,因为这个错误本身可能来自调用链更上层。
  • 如果用户输入的查询里包含错误信息文本或者跨文件关键词,就触发 repo 模式。

这套规则的实现不复杂,核心是给每个来源(diff、diagnostics、光标)都附带上“模式建议”,然后在事件合并时取优先级最高的建议。我用了一个简单的优先级表:diagnostics > diff > cursor。因为用户点开错误面板时,通常意图最明确。

4.4 与外部工具的接口:一个请求,一段上下文

最后,context-mode 要暴露一个统一的取上下文接口,无论是哪个 AI 工具都能调用。我定义了一个简单的协议:

{ "mode": "stack", "filePath": "src/userService.ts", "cursorLine": 42, "includeDiagnostics": true, "includeDiff": true, "maxContextSize": 12000 }

返回的结构也尽量简单,就是一个带标题的 Markdown 文本,标题上标明[Context-Window]、[Context-Symbol]、[Context-Stack]这样的标记。这样 AI 工具拿到之后不用再做二次解析,直接拼在系统提示词里就行。

5. 实测效果与翻车记录:context-mode 的真实边界

这一节是对前面所有设计的检验。我用 context-mode 实际跑了自己的几个项目,也做了一些对照实验。结果有惊喜,也有翻车。我会把翻车的地方重点写出来,因为这些才是没法靠自己脑补获得的经验。

5.1 三个真实场景:从局部修改到跨文件定位

第一个场景是局部逻辑修改。我在一个 open-source 项目里让 AI 给某个工具函数加一个“超时重试”逻辑。旧方式是把整个 800 行的工具文件发给 AI,AI 给出的代码总是试图复用文件里某个不相关的重试工具,导致逻辑混乱。换成 context-mode 的 window 模式后,AI 只看到目标函数本身和它引用的类型定义,给出的方案干净了很多,而且不用再反复粘贴修改。

第二个场景是跨文件问题追踪。我在项目里发现一个诡异的现象:createOrder这个接口偶尔会返回 500。报错信息在日志里,但代码里找不到直接抛错的地方。旧方式是我把一个 service 文件整个丢给 AI,AI 翻了半天没找到。换成 stack 模式后,context-mode 自动把createOrder的调用方、以及调用方最近改动过的几个函数一起打包,AI 立刻定位到是 controller 层在await之前提前释放了数据库事务。这个结果让我自己都很意外,因为如果没有调用链信息,人类排查这个 bug 至少要花小半天。

第三个场景是仓库级检索。我让 AI 回答“我们这个仓库里所有用到legacySession的地方有哪些,能不能统一迁移掉”。repo 模式用它自建的符号索引,把 30 多个引用点分门别类列出,AI 基于这些入口文件生成的迁移方案非常完整。旧方式是让 AI 自己搜,结果它漏了一半,因为有些引用是通过const legacy = legacySession这种别名方式引入的,普通的关键词搜索抓不到,但符号索引能抓到。

5.2 翻车记录:闭包、模板语言和缓存失效

有好就有坏,下面列出我实际踩过且修复了的坑。

第一个坑是嵌套闭包。Tree-sitter 在 TSX 文件里,光标落在 JSX 回调内部时,最内层节点往往是一个jsx_expression或者箭头函数。我之前直接从最内层开始提取,结果上下文里只有一个 3 行的 map 回调,AI 完全不知道外层在干嘛。修复方案就是前面提到的“函数链”——永远把从最内层到根节点的所有函数一起作为上下文,最内层函数放后面,外层函数放前面。

第二个坑是模板语言和预处理。我在一个 HTML 模板文件里测试时,Tree-sitter 的 HTML grammar 不支持模板内部的函数表达式,导致 symbol 模式提取为空。同样的问题也出现在 C/C++ 的宏定义上。tree-sitter-c 的 AST 里预处理器指令是独立节点,宏展开后的实际调用关系无能为力。最后的做法是给 context-mode 加了一个 fallback:当 AST 提取不到函数时,回退到 LSP 的documentSymbol和definition,虽然慢一点,但结果可靠。

第三个坑是缓存失效。最初我对“小编辑”做了缓存不过期的优化,结果用户在函数体内插入一个变量声明时,因为函数体的行号范围变了,但我的缓存还持有旧行号,导致上下文里的函数定义和实际代码对不上。这个问题非常隐蔽,AI 会基于错误的代码进行修改,改完一跑就挂。最后的修复方案简单粗暴:只要当前编辑使得 syntax tree 中某个函数的 start/end 位置发生变化,就立即把这个函数相关的所有缓存清掉。宁可牺牲一点速度,也不能给 AI 错代码。

5.3 实际配置建议与参数参考

如果你也想复制这套方案,下面是我的默认配置,可以作为起点:

[context-mode] default_mode = "symbol" [context-mode.window] around_lines = 10 include_indent = true [context-mode.symbol] max_body_lines = 200 max_direct_dependencies = 5 include_doc_comment = true [context-mode.stack] max_depth = 2 prefer_recent_diff = true max_caller_files = 3 [context-mode.repo] index_file_count = 50 use_diff_incremental = true [context-mode.cache] context_ttl_ms = 5000 invalidate_on_symbol_change = true

几个参数的取舍说明一下:

  • max_body_lines = 200不是越大越好。AI 在超长函数面前会失去对关键路径的判断力,宁可截断函数体,只留头部注释和签名,也要把“函数意图”讲清楚。
  • stack.max_depth = 2是实际使用后的平衡点。深度超过 3 层,调用链的上下文会呈指数膨胀,而且很多上层调用跟当前问题无关。
  • prefer_recent_diff = true非常关键。把这个开关打开之后,stack 模式会优先把 diff 中出现的调用点排在前面,上下文更相关。实测这个选项对诊断准确率的影响最大。

5.4 一个还没解决但仍值得做的方向:上下文之间的“关联度评分”

现在的 context-mode 还是基于规则的模式切换,没法做到真正的“个性化”。比如有人写的代码风格极简,函数都很短,symbol 模式默认给的 200 行上限就永远用不到;而有些人一个函数就 500 行,200 行截断又导致 AI 丢失重要信息。

我后续想做的改进是给每个候选上下文片段计算一个“关联度评分”,综合考量四个因素:行号距离、AST 父子关系、diff 同时出现频率、以及历史对话中用户对这个上下文的采纳率。评分高的上下文排在前面,不需要预先划分固定模式。这个方向本质上是把“上下文工程”从手工规则变成量化模型,我认为这是所有 AI 编码工具在工程化上的下一步。

从实际体验看,context-mode 现在给我的最大收获不是“AI 回答更准了”,而是我作为人类开发者,开始有意识地思考“这个改动真正依赖哪些代码”。这种思考习惯一旦建立,你写代码时也会更克制,不会为了省事把所有东西都堆在一个文件里。如果你也想在项目里试这套方案,建议从一个模式开始:先把 symbol 模式做好,让 AI 每次只看到当前函数和直接依赖,你很快就会感受到模型在有边界输入下的表现提升。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 11:56:34

Java+MooseFS网盘后端源码包解析:分布式文件系统落地实践

简介&#xff1a;这是基于Java与Moosefs的分布式文件系统设计与实现完整项目&#xff0c;面向高校计算机专业毕业设计、课程设计或分布式系统入门学习者。资源将服务端源码、客户端逻辑与项目文档整合为一体&#xff0c;可帮助读者理解分布式文件存储架构、元数据管理及Java多模…

作者头像 李华
网站建设 2026/10/8 11:54:45

Claude记忆系统实战:从短期上下文到长期检索的工程化落地

1. 从“记忆”这个痛点说起&#xff1a;claude-mem 到底想解决什么如果你用 Claude 这类大模型做过稍微长一点的对话&#xff0c;一定遇到过这种尴尬&#xff1a;前面聊了半小时&#xff0c;把项目背景、代码风格、命名规范、甚至几个关键决策都交代清楚了&#xff0c;结果聊到…

作者头像 李华
网站建设 2026/10/8 11:54:38

ponytail skill与插件全解析:轻量工具的使用哲学

1. 从“ponytail”这个热词说起&#xff1a;它到底指什么 第一次看到“ponytail”被当成一个技术词条来搜&#xff0c;我其实愣了一下。字面意思就是马尾辫&#xff0c;一个再日常不过的发型词&#xff0c;怎么会跟“skill”“插件”“如何使用”这些词绑在一起冲上热搜&#x…

作者头像 李华
网站建设 2026/10/8 11:54:08

Claude Code营销技能库marketingskills实战:SEO审计与关键词研究

1. 从“marketingskills”说起&#xff1a;一个被低估的AI营销技能库 第一次看到“marketingskills”这个词&#xff0c;是在一个做独立站的朋友群里。有人甩了个链接&#xff0c;说“这玩意儿把SEO、CRO、数据分析全塞进Claude Code里了&#xff0c;跑一遍顶我干三天”。我当时…

作者头像 李华
网站建设 2026/10/8 11:53:31

视频Agent系统设计:从OpenMontage概念到可运行架构

1. OpenMontage 是什么&#xff1a;一个被严重误读的开源视频生产代理系统OpenMontage 这个名字一出现&#xff0c;很多人第一反应是“又一个AI视频生成工具”&#xff0c;或者联想到Adobe Premiere的开源替代品。但实际翻遍GitHub、Hugging Face、主流技术社区和近期会议论文&…

作者头像 李华
网站建设 2026/10/8 11:52:56

Context Mode上下文模式:让编辑器在长文件中固定代码层级

你有没有过这样的体验&#xff1a;一个函数写了三百行&#xff0c;光标一路滚到屏幕最下方&#xff0c;盯着某个分支逻辑看了半天&#xff0c;突然发现自己忘了目前到底在哪个函数里、这个缩进级别对应的是什么层级。这种东西在DevTools、长配置文件、甚至三四百行的CSS里都特别…

作者头像 李华