Skip to content

Latest commit

 

History

History
296 lines (222 loc) · 16 KB

File metadata and controls

296 lines (222 loc) · 16 KB

Continue 补全(Autocomplete)算法架构调研

本文基于本仓库 /Users/llm/Desktop/Code/ttab/continue 的代码,梳理 Continue 的「Tab Autocomplete」补全算法流程、所用方法与关键模块位置(具体文件路径)。

1) 入口与请求路径(IDE → Core)

VS Code 插件层入口

  • 入口:extensions/vscode/src/autocomplete/completionProvider.tsContinueCompletionProvider.provideInlineCompletionItems(...)
  • 作用:
    • 处理 VS Code Inline Completion 的触发(按键、移动、Tab 等)。
    • 校验是否启用 Tab Autocomplete、是否多光标、是否 SCM/Notebook 等特殊场景。
    • 决定走「Autocomplete」还是「Next Edit」路径(this.isNextEditActive)。
    • 把 VS Code 的上下文(光标、文件、选中 completion 等)整理为 AutocompleteInput

Core 侧协议入口

  • 入口:core/core.tson("autocomplete/complete") 处理器。
  • 作用:通过 CompletionProvider.provideInlineCompletionItems(...) 执行核心补全流程,然后返回文本结果给 IDE。

2) 输入结构与配置合并

输入结构(AutocompleteInput)

  • 定义:core/autocomplete/util/types.ts
  • 关键字段:
    • filepath, pos, completionId:定位补全发生位置。
    • recentlyVisitedRanges, recentlyEditedRanges:供上下文拼装使用。
    • manuallyPassFileContents / manuallyPassPrefix:Notebook 或 commit 输入框特例。
    • selectedCompletionInfo:用户已有 IntelliSense 选中项,用于精细渲染。

配置合并策略(TabAutocompleteOptions)

  • 默认值:core/util/parameters.tsDEFAULT_AUTOCOMPLETE_OPTS
  • 合并顺序:core/autocomplete/CompletionProvider.ts_getAutocompleteOptions(...)
    • DEFAULT_AUTOCOMPLETE_OPTS
    • config.tabAutocompleteOptions
    • llm.autocompleteOptions
  • 关键配置项:
    • maxPromptTokens, prefixPercentage, maxSuffixPercentage
    • debounceDelay, modelTimeout, multilineCompletions
    • useCache, useRecentlyEdited, useRecentlyOpened, useImports
    • experimental_* 开关(剪贴板、静态上下文等)

3) 前置过滤(Prefilter)

  • 入口:core/autocomplete/prefiltering/index.tsshouldPrefilter(...)
  • 主要策略:
    • options.disable 直接关闭。
    • 禁止在 Continue 配置文件中补全(getConfigJsonPath)。
    • disableInFiles + .continueignore 规则(getGlobalContinueIgArray / getWorkspaceContinueIgArray)。
    • Untitled 空文件不补全。

此外还会先做安全判断:core/autocomplete/CompletionProvider.tsisSecurityConcern(...)

4) HelperVars:统一上下文变量构造

  • 入口:core/autocomplete/util/HelperVars.ts
  • 核心职责:
    • 读取文件内容、分行 (readFile)。
    • 计算完整前缀/后缀:core/autocomplete/templating/constructPrefixSuffix.ts
    • 按 token 预算裁剪前缀/后缀(pruneLinesFromTop / pruneLinesFromBottom)。
    • 通过 Tree-sitter 建 AST,获取 treePath(用于 root-path context)。

5) 上下文检索(Snippets)

上下文聚合总入口

  • 入口:core/autocomplete/snippets/getAllSnippets.tsgetAllSnippetsWithoutRace(...)
  • 产物:SnippetPayload,包含多类 snippets。

主要来源与方法

  1. Root Path Context(基于语法树路径)

    • core/autocomplete/context/root-path-context/RootPathContextService.ts
    • 通过 Tree-sitter 的 root-path 查询(extensions/vscode/tree-sitter/root-path-context-queries/*
    • 对 AST 路径节点做 gotoDefinition,抓取相关定义内容。
  2. Import Definitions

    • core/autocomplete/context/ImportDefinitionsService.ts
    • 用 Tree-sitter import queries(extensions/vscode/tree-sitter/import-queries/*
    • 对 import 符号做 gotoDefinition,并读取定义内容。
  3. Static Context(实验性)

    • core/autocomplete/context/static-context/StaticContextService.ts
    • 主要针对 TS/OCaml 等类型信息,输出“类型洞”相关上下文。
  4. Recently Edited / Visited Ranges

    • AutocompleteInput 传入(IDE 层维护)。
  5. Clipboard Snippets

    • getAllSnippets.tsgetClipboardSnippets(...),来自 IDE.getClipboardContent()
  6. Recently Opened Files

    • core/autocomplete/util/openedFilesLruCache + getAllSnippets.tsgetSnippetsFromRecentlyOpenedFiles(...)
  7. Diff Snippets

    • 目前在 getAllSnippets.ts 中被临时禁用(注释说明)

Snippet 排序与 Token 预算

  • 入口:core/autocomplete/templating/filtering.tsgetSnippets(...)
  • 策略:
    • 各类 snippet 按优先级(可配置)排序。
    • 根据 maxPromptTokens 预算逐个塞入。
    • 通过 countTokens 计算大小。
    • 处理 recentlyOpened 的定制裁剪逻辑(formatOpenedFilesContext(...))。

6) Prompt 构造与模板

模板选择

  • 入口:core/autocomplete/templating/AutocompleteTemplate.ts
  • 按模型选择不同 FIM 模板(Codestral / Qwen / StarCoder / Granite 等)。
  • 部分模板支持 compilePrefixSuffix(...),用于多文件拼接、file_sep 标记等。

Prompt 拼装

  • 入口:core/autocomplete/templating/index.ts
  • 流程:
    1. preparePromptContext(...) 选择模板 + 组合 snippets。
    2. buildPrompt(...) 将 snippets 拼进 prefix/suffix,再渲染模板。
    3. renderPromptWithTokenLimit(...) 检测 token 预算超限后裁剪 prefix/suffix。
    4. 生成 stop tokens(getStopTokens(...))。

7) 生成与流式输出(Generation)

生成入口

  • core/autocomplete/CompletionProvider.tsprovideInlineCompletionItems(...)
  • 关键步骤:
    • 选择 LLM:_prepareLlm()(处理 OpenAI legacy endpoint、温度、provider 特例)。
    • 使用 AutocompleteDebouncer 延迟防抖。
    • 调用 renderPromptWithTokenLimit 获取最终 prompt。

FIM vs 普通 Completion

  • core/autocomplete/generation/CompletionStreamer.ts
    • 如果模型支持 FIM(llm.supportsFim()),调用 llm.streamFim(prefix, suffix, ...)
    • 否则使用 llm.streamComplete(prompt, ...)

生成复用(减小延迟)

  • core/autocomplete/generation/GeneratorReuseManager.ts
    • 尝试复用上一次的 generator(如果新 prefix 是旧 prefix + 已生成内容)。
    • 支持“用户继续输入时复用已生成的 stream”。

8) 流式过滤链(Filtering)

流式处理入口

  • core/autocomplete/filtering/streamTransforms/StreamTransformPipeline.ts

主要过滤/截断策略

  • Stop TokensstopAtStopTokens(...)charStream.ts)。
  • Suffix 检测stopAtStartOf(...)charStream.ts),避免生成与已有后缀重复。
  • 行级处理lineStream.ts
    • stopAtLines / stopAtLinesExact / stopAtRepeatingLines / stopAtSimilarLine
    • avoidEmptyComments, avoidPathLine, noDoubleNewLine, skipPrefixes
    • showWhateverWeHaveAtXMs(超时展示已生成片段)
  • 语言级过滤AutocompleteLanguageInfo.ts 里的 charFilters / lineFilters
    • 例:JSON 使用 BracketMatchingService.stopOnUnmatchedClosingBracket(...)

单/多行判定

  • core/autocomplete/classification/shouldCompleteMultiline.ts
    • 依据 multilineCompletions 配置。
    • 根据语言与注释类型作额外判断。

9) 后处理(Postprocess)

  • 入口:core/autocomplete/postprocessing/index.ts
  • 主要规则:
    • 空白/重复内容过滤。
    • 针对模型的修正(Codestral、Qwen3、Granite、Mercury 等)。
    • 移除多余的 Markdown 代码块符号。

10) 缓存与日志

LRU + SQLite 缓存

  • core/autocomplete/util/AutocompleteLruCache.ts
  • 特性:
    • Prefix → Completion 的最长前缀匹配。
    • 内存 LRU + SQLite 持久化。
    • 命中缓存时直接返回剩余 completion。

Logging / Telemetry

  • core/autocomplete/util/AutocompleteLoggingService.ts
  • 记录:
    • completion 结果、是否接受、耗时、模型信息等。
    • 对 rejected completion 设置超时日志。

Bracket 处理(接受后)

  • core/autocomplete/filtering/BracketMatchingService.ts
    • 记录上一次 completion 的括号栈。
    • 在后续补全时避免闭合不匹配。

11) VS Code 渲染与展示策略

  • extensions/vscode/src/autocomplete/completionProvider.ts(渲染阶段)。
  • 关键逻辑:
    • 单行补全调用 processSingleLineCompletion(...)core/autocomplete/util/processSingleLineCompletion.ts)来决定替换范围。
    • 多行补全默认扩展到当前行末尾。
    • 生成 InlineCompletionItem 返回给 VS Code。

12) 与 Next Edit 的关系

  • 入口同一处:extensions/vscode/src/autocomplete/completionProvider.ts
  • isNextEditActive 决定走 CompletionProvider 还是 NextEditProvider
  • Next Edit 复用部分 autocomplete 组件(例如 snippets、templating、postprocess)。
    • core/nextEdit/NextEditProvider.ts
    • core/nextEdit/context/autocompleteContextFetching.ts

13) Next Edit 算法架构

入口与触发

  • VS Code 入口:extensions/vscode/src/autocomplete/completionProvider.ts,当 isNextEditActive 时走 NextEditProvider
  • Core 协议入口:core/core.tson("nextEdit/predict") 调用 NextEditProvider.provideInlineCompletionItems(...)

模型选择与能力校验

  • 模型准备:core/nextEdit/NextEditProvider.ts_prepareLlm(),与 autocomplete 类似的温度/endpoint处理。
  • 能力校验:modelSupportsNextEdit(...)core/llm/autodetect.ts)。
  • 模型适配:NextEditProviderFactory 根据模型名选择 Provider:
    • core/nextEdit/providers/InstinctNextEditProvider.ts
    • core/nextEdit/providers/MercuryCoderNextEditProvider.ts

上下文与历史

  • 基础上下文与 snippets:core/nextEdit/NextEditProvider.ts_generatePrompts(...) 通过 getAllSnippetsWithoutRace(...) 获取 SnippetPayload
  • 可编辑区域(editable region):由 model provider 计算:
    • BaseNextEditModelProvider.calculateEditableRegion(...)
  • diff 历史与 in-progress edits:
    • core/nextEdit/context/aggregateEdits.tsEditAggregator.getInProgressDiff(...)
    • core/nextEdit/context/diffFormatting.tscreateDiff(...)
    • core/nextEdit/DocumentHistoryTracker.ts 保存文档历史与 AST
  • autocomplete context 复用(用于 next edit prompt 中的“上下文片段”):
    • core/nextEdit/context/processNextEditData.ts
    • core/nextEdit/context/autocompleteContextFetching.ts

Prompt 构建与模板

  • Provider 负责具体 prompt 生成与模板渲染:
    • core/nextEdit/providers/BaseNextEditProvider.ts
    • core/nextEdit/templating/NextEditPromptEngine.ts
    • core/nextEdit/templating/instinct.ts
    • core/nextEdit/templating/mercuryCoderNextEdit.ts
  • Mercury 模型会注入 unique token(MercuryCoderNextEditProvider)。

生成与后处理

  • LLM 调用:NextEditProvider._handleCompletion(...) 使用 llm.chat(...)(当前非流式)。
  • completion 提取:由 provider 实现 extractCompletion(...)
  • 后处理:复用 core/autocomplete/postprocessing/index.ts

Diff 分解、链式跳转与预取

  • Full-file diff 路径:BaseNextEditModelProvider.handleFullFileDiff(...) 使用 myersDiff(...) 分组 diff(core/nextEdit/diff/diff.ts)。
  • Partial diff 路径:BaseNextEditModelProvider.handlePartialFileDiff(...)
  • 预取/链式队列:core/nextEdit/NextEditPrefetchQueue.ts + NextEditProvider.provideInlineCompletionItemsWithChain(...)
  • 维护 chain 状态:NextEditProvider.startChain(...) / deleteChain(...)

VS Code 展示与跳转

  • Jump(跳转提示/接受):extensions/vscode/src/activation/JumpManager.ts
  • Next Edit 窗口展示:extensions/vscode/src/activation/NextEditWindowManager.ts
  • FIM 判定:core/nextEdit/diff/diff.tscheckFim(...)(VS Code 渲染时使用)。

日志与遥测

  • core/nextEdit/NextEditLoggingService.ts 记录 accept/reject/abort 与 Telemetry。

14) 一句话总览

Continue 的 autocomplete 流程可以概括为:IDE 触发 → Pre-filter → 构造 HelperVars → 汇总 snippets → 拼装 prompt → 生成(FIM/普通)→ 流式过滤 → 后处理 → 缓存与日志 → VS Code 渲染展示。关键代码集中在 core/autocomplete/*extensions/vscode/src/autocomplete/*

入口与激活分层:Continue 的 extension.ts 只负责激活、遥测和异常处理,补全在其他文件里实现和注册。见 extension.ts (line 14),VsCodeExtension.ts (line 351);你的实现全部在 extension.ts (line 10)。 触发与门控逻辑:Continue 有状态栏开关、SCM 文件过滤、多光标禁用、selectedCompletionInfo 验证等,避免无效触发。见 completionProvider.ts (line 168);你的实现只有 apiKey 与取消判断。见 extension.ts (line 101)。 上下文收集更丰富:Continue 会处理 notebook、untitled 文件、手动触发、recently edited/visited ranges、LSP definitions 等上下文。见 completionProvider.ts (line 226);你的 prompt 只拼接全文前后缀。见 extension.ts (line 21)。 请求/模型管线更复杂:Continue 有模型角色选择、AbortController、Next Edit/chain/jump/prefetch、rerank 等机制。见 completionProvider.ts (line 91);你的请求是一次性 chat/completions。见 extension.ts (line 41)。 输出处理更细致:Continue 会对单行补全对齐、替换范围、selectedCompletionInfo 拼接、completeBracketPairs 等做处理。见 completionProvider.ts (line 521);你的输出只是剥离 code fence 后直接插入。见 extension.ts (line 121)。 Next Edit/差异呈现能力:Continue 支持 FIM 判断、ghost text 接受跟踪、diff 窗口展示。见 completionProvider.ts (line 610);你的实现不包含这些能力。 可靠性与诊断:Continue 有统一错误处理、日志/遥测链路。见 completionProvider.ts (line 43);你的输出仅写 OutputChannel。见 extension.ts (line 69)。

状态栏启用开关:只有当状态栏显示“Enabled”时才触发补全,避免在用户关闭时仍消耗请求。completionProvider.ts (line 168) 取消请求判断:若 token 已取消则直接返回,避免浪费计算和显示过期结果。completionProvider.ts (line 170) SCM 文档过滤:vscode-scm 是提交消息或 diff 视图,通常不需要补全。completionProvider.ts (line 174) 多光标过滤:多光标时补全会错位/冲突,直接禁用以保证正确性。completionProvider.ts (line 182) selectedCompletionInfo 校验:当原生补全列表有选中项时,Inline completion 必须“扩展”它;如果用户只输入了很短的前缀或选中的文本不匹配,就不显示。completionProvider.ts (line 187) completionId:为每次补全生成唯一 ID,用于日志、接受/拒绝追踪、链式 next edit。completionProvider.ts (line 213) AbortController:把 VS Code 的取消信号传给模型请求,避免返回过时结果。completionProvider.ts (line 210) notebook cell 合并:把 notebook 各 cell 合并成一个完整文本,保证模型能看到上下文;并调整光标行号。completionProvider.ts (line 232) untitled 文件全文传递:未保存文件没有路径/磁盘内容,需手动传全文给模型。completionProvider.ts (line 265) manuallyPassPrefix:预留的“手动补全前缀”入口,目前为空(为未来/特殊编辑器场景保留)。completionProvider.ts (line 270) 手动触发标记:区分用户显式触发 vs 自动触发,可用于调整策略/阈值。completionProvider.ts (line 273) filepath:提供模型/日志文件位置,支持路径相关规则与后续追踪。completionProvider.ts (line 278) recentlyVisitedRanges:近期访问的代码片段,帮助模型理解“注意力”所在区域。completionProvider.ts (line 279) recentlyEditedRanges:近期编辑范围,帮助模型聚焦当前改动上下文。completionProvider.ts (line 280) ctx 聚合:把上述字段统一打包传给 autocomplete/next edit 逻辑,减少参数散落。completionProvider.ts (line 283)