# Coding Copilot 代码补全技术方案

---

## 1. 方案概览

### 1.1 背景

早期，代码补全主要基于 OpenAI，部分场景是自研模型，主要用户内测产品验证场景，为了满足公测的需要，我们想将代码补全基于自研模型重新实现并优化，并尽可能保留 OpenAI 已有的能力。由于自研模型并不支持 FIM（Fill in the middle），所以我们将会在应用层使用另一种方案来完成近似 FIM 的功能，同时也会与模型层团队一起深入优化细节。

### 1.2 目标

抽象并实现代码补全相关逻辑，支持不同模型之间的适配与无法切换，同时确保补全性能和 LLM API 节流。

### 1.3 分析

1. LLM 模型层计算是很耗 GPU 资源的，在应用层上，我们需要尽可能减少不必要的代码补全请求，例如相似的代码补全项能否从缓存中取、只在接近行尾的位置进行代码补全等等。

1. 不同 LLM、不同的代码语言、以及不同的光标位置的语法特性等情况，对代码补全请求参数的要求是不一样的。我们需要一种机制将这类场景抽象统一起来。（其中不同 LLM API 的统一，已经基于 langchain 实现了，不再分析与设计）

1. 对补全返回结果的处理方式也十分复杂多样，同样也需要一种机制进行统一抽象。

1. 为了获取更多光标所在位置的语法特性，我们需要用到 web-tree-sitter 库进行抽象语法树分析。


### 1.4 设计与实现

主要实现涉及的代码目录为 `frontend/extensions/extensions/coding-wise/src/completion/inline`。

目录结构与说明：

```shell
.
├── filter                                           # 代码补全过滤器所在目录
│   ├── boundary-symbol-request-filter.ts            # 代码补全触发边界过滤器
│   ├── feature-request-filter.ts                    # 代码补全功能开关过滤器
│   ├── index.ts
│   └── text-length-request-filter.ts                # 代码文本长度约束过滤器
├── index.ts
├── inline-completion-cache-service.ts               # 代码补全结果缓存服务类
├── inline-completion-provider.ts                    # VSCode 内联代码补全 API 接入
├── inline-completion-service.ts                     # 代码补全服务类，主要是组件与 VSCode 插件 API 之间的胶水层代码
├── inline-protocol.ts                               # 代码补全相关的所有抽象接口
├── processor                                        # 代码补全后置处理器所在目录
│   ├── compensation-result-post-processor.ts        # 补偿性的结果后置处理器
│   ├── default-result-post-processor.ts             # 默认的结果后置处理器（兜底用）
│   ├── index.ts
│   ├── prefix-result-post-processor.ts              # 代码补全结果前缀相关后置处理器
│   ├── reverse-stop-result-post-processor.ts        # 代码补全结果逆序停止符后置处理器
│   ├── suffix-result-post-processor.ts              # 代码补全结果后缀相关后置处理器
│   └── telemetry-result-post-processor.ts           # 代码补全结果上报后置处理器
└── resolver                                         # 代码补全请求参数解释器所在目录
    ├── big-document-request-resolver.ts             # 大文档代码补全请求参数解释器
    ├── default-request-resolver.ts                  # 默认代码补全请求参数解释器（兜底）
    ├── empty-text-after-cursor-request-resolver.ts  # 光标之后代码为空情况的代码补全请求参数解析器
    ├── generic-ast-request-resolver.ts              # 通用抽象语法树代码补全请求参数解释器
    ├── index.ts
    ├── javascript-ast-request-resolver.ts           # JavaScript 语言抽象语法树增强补全请求参数解释器
    └── python-ast-request-resolver.ts               # Python 语言抽象语法树增强补全请求参数解释器
```

代码补全关键接口与类型：

1. `InlineCompletionRequest`: 代码补全请求。主要包含获取代码补全结果可能需要用到的信息。
1. `InlineCompletionResult`: 代码补全结果。主要用于存放代码补全返回的结果或者错误信息。
1. `InlineCompletionService`: 代码补全服务。 主要负责与 VSCode 插件 API 胶水层相关的代码。
1. `InlineCompletionRequestFilter`: 代码补全请求过滤器。
1. `InlineCompletionRequestResolver`: 代码补全请求参数解释器。根据不同情况构造解析不同的代码补全请求参数（InlineCompletionRequest）。
1. `InlineCompletionRequestPostFilter`: 代码补全请求参数后置过滤器。基于代码补全请求参数进一步过滤。
1. `InlineCompletionRequestPostProcessor`: 代码补全请求参数后置处理器。基于代码补全请求参数进行后置处理。
1. `InlineCompletionResultPostProcessor`: 代码补全结果后置处理器。基于代码补全结果进行后置处理。
1. `InlineCompletionCacheService`: 代码补全缓存服务。负责缓存代码补全结果。


代码补全完整流程：
1. 根据文档与光标位置过滤掉不需要补全的请求，具体细节可以参考代码目录：`src/completion/inline/filter`；
1. 根据文档、光标位置、补全上下文构造解析代码补全请求参数对象，具体细节可以参考代码目录：`src/completion/inline/resolver`；
1. 如果需要，则根据补全请求参数首先从缓存服务中匹配合适的结果，具体细节可以参考代码：`src/completion/inline/inline-completion-provider.ts` 和 `src/completion/inline/inline-completion-cache-service.ts`；
1. 缓存未命中，则继续调用 LLM API 获取补全结果, 具体细节可以参考代码：`src/completion/inline/inline-completion-provider.ts`；
1. 根据补全请求参数以及结果，对结果进一步加工（边界、相似性等）处理，具体细节可以参考代码目路：`src/completion/inline/processor`。
