跳到主要内容

Tabby — 这是什么·全景·阅读地图

30 秒导读: Tabby 是一个可以装在自己机器上的 AI 编码助手——把 GitHub Copilot 那套「边写边补全 + 聊代码 + 问答」搬进你自己的服务器,代码和上下文都不出门。它是一整个纯 Rust 工程,跑起来只要一条 tabby serve 命令,不需要外接数据库、也不依赖任何云服务,一块消费级显卡就能带动。

本章是这组文档的总入口。它只做两件事:让你零基础也能说清「Tabby 是什么」,再给你一张全景图和一份阅读地图,告诉你后面每一章讲什么、该按什么顺序读。任何子系统的实现细节都留给后续章节,本章不深入代码。


1. 这是什么(零基础也能懂)

一句话定义: Tabby 是一个自托管、开源的 AI 编码助手,是 GitHub Copilot 的私有化替代品

它的三个卖点,README 开门见山写得很清楚(README.md:18-21):

  • 自包含——不需要外部 DBMS,也不需要任何云服务,程序自己就是全部。
  • OpenAPI 接口——对外是标准 HTTP API,容易接进你已有的基础设施(比如云端 IDE)。
  • 支持消费级 GPU——不用数据中心显卡,家用卡也能跑。

解决谁的什么问题? 假设你在一家对代码保密很在意的公司,既想要 Copilot 那种「边打字边冒出补全」的体验,又不能把源码发给外部服务。Tabby 就是为这种场景生的:模型、索引、数据全部在你自己的机器上,自己起一个服务,IDE 插件连过去即可。

它能做什么(功能)? 主要是三类对外能力:

  • 代码补全——在编辑器里根据光标上下文实时补全(/v1/completions),而且会检索你仓库里的相关代码片段一起喂给模型(RAG,检索增强生成)。
  • 代码对话——像 ChatGPT 一样和模型聊代码、让它改代码(/v1/chat/completions)。
  • 答案引擎(Answer Engine)——企业版能力:把团队内部的代码库、文档、issue 索引起来,做成一个「问工程问题就给带引用答案」的内部知识引擎。

用起来什么样? 最小启动就是一条 Docker 命令(README.md:85-90),指定一个补全模型和一个对话模型:

docker run -it \
--gpus all -p 8080:8080 -v $HOME/.tabby:/data \
tabbyml/tabby \
serve --model StarCoder-1B --device cuda --chat-model Qwen2-1.5B-Instruct

跑起来后,8080 端口就是一个带 Swagger UI 的 HTTP 服务;VSCode / IntelliJ / Vim 等插件填上这个地址就能用。

一句话直觉/类比: 把 Tabby 想成**「一台你自己的、开源的 Copilot 服务器」**——它把「一个 HTTP API 服务器」和「一个会读你代码库的补全大脑」打包成了单个 Rust 二进制。


2. 顶层全景(它大概怎么转)

2.1 怎么读这张图

从上到下是「用户请求 → 进程入口 → HTTP 服务器 → 三大能力 → 底层支撑」。左边是补全/对话主链路,右边灰色框是企业版(EE)才启用的部分。底层的「检索」和「推理后端」是所有能力共享的两根柱子。

IDE 插件 / 浏览器 (clients/vscode, intellij, vim, ...)
│ HTTP (OpenAPI)

┌──────────────────────────────────────────────────────────────────┐
│ CLI 入口 crates/tabby —— tabby serve / tabby download │
│ 解析参数 → 加载 config → 下载模型 → 装配 axum Router │
└──────────────────────────────────────────────────────────────────┘


┌──────────────────────────────────────────────────────────────────┐
│ axum HTTP Server (带 Swagger UI / openapi.json) │
└───────┬───────────────────┬───────────────────┬──────────────────┘
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌────────────────────────┐
│ /v1/ │ │ /v1/chat/ │ │ EE Answer Engine │
│ completions │ │ completions │ │ (GraphQL / 后台索引) │
│ 代码补全 │ │ 代码对话 │ │ ee/tabby-webserver ░░░ │
└──────┬────────┘ └──────┬────────┘ └───────────┬────────────┘
│ │ │
▼ │ ▼
┌───────────────┐ │ ┌────────────────────────┐
│ 检索增强 │ │ │ ee/tabby-db (SQLite) │
│ 拼 FIM 提示 │ │ │ 用户/线程/集成 ░░░ │
└──────┬────────┘ │ └────────────────────────┘
│ │
▼ ▼
┌────────────────────┐ ┌──────────────────────────────────────────┐
│ 底层检索 │ │ 可插拔推理后端 tabby-inference (抽象接口) │
│ tabby-index │ │ ├─ 本地: llama-cpp-server (跑 GGUF) │
│ Tantivy 索引 + │ │ └─ 远程: http-api-bindings (OpenAI 兼容) │
│ embedding/BM25 混合 │ └──────────────────────────────────────────┘
└────────────────────┘
(░░░ = 企业版 EE feature 才启用)

2.2 主线走一遍(高层,不进代码)

跟着一次代码补全请求从进程启动到吐出文本,看看它经过哪些部件。装配顺序取自 crates/tabby/src/serve.rsmain(serve.rs:117-233)与 api_router(serve.rs:251-360):

  1. 进程启动。 tabby serve 走到 serve::main;先 load_model 按需下载本地模型(serve.rs:235-249),再决定要不要启用嵌入服务和企业版 Webserver。
  2. 装配依赖。 依次建好:事件日志器 logger、Tantivy 索引读取器 IndexReaderProvider、代码检索 create_code_search、补全+对话服务 create_completion_service_and_chat(serve.rs:147-184)。
  3. 搭路由。 api_router 把每个能力挂到一条 HTTP 路由上——/v1/completions/v1/chat/completions/v1/health 等,合并成一个 axum Router,再叠上 Swagger UI(serve.rs:271-359)。
  4. 收到补全请求。 /v1/completions 落到补全服务的 generate(services/completion.rs:358);它先 build_snippets 从索引里检索相关代码片段,再 prompt_builder.build 拼成 FIM(填空)提示(completion.rs:390-402)。
  5. 喂给推理后端。 self.engine.generate(&prompt, options) 把提示交给推理抽象层(completion.rs:407-408);后端可能是本地 llama-cpp-server,也可能是远程 OpenAI 兼容 API,取决于配置(services/model/mod.rs:38-73)。
  6. 返回并记账。 生成的文本经 logger.log 记录后,包成 CompletionResponse 返回给编辑器(completion.rs:410-438)。

一句话: 一次补全 = 「HTTP 路由 → 检索拼提示 → 推理后端生成 → 返回」,而检索和推理后端这两根柱子被所有能力复用。


3. 部件职责表(crate | 干什么)

Tabby 是一个 Cargo workspace,由多个 crate 组成;下面这张表按「对外能力 → 核心库 → 底层 → 企业版」的层次列出主要成员,数据取自 Cargo.toml:3-24members 和各 crate 的 lib.rs 头部说明。

crate / 目录层次干什么
crates/tabby入口CLI(serve / download 两个子命令)+ axum 服务器装配 + 补全/对话服务编排(main.rs:26-33)
crates/tabby-common基础跨子项目共享的类型与工具:config、api、index schema、路径、注册表(tabby-common/src/lib.rs:1-12)
crates/tabby-inference底层引擎文本生成模型的抽象定义:补全流、对话流、嵌入、解码停止逻辑(tabby-inference/src/lib.rs:1-11)
crates/tabby-index检索后台索引调度:同步仓库、切片、写 Tantivy 索引(tabby-index/src/lib.rs:1-2)
crates/http-api-bindings后端(远程)把远程 OpenAI 兼容 API 适配成推理抽象:补全/对话/嵌入(http-api-bindings/src/lib.rs:1-8)
crates/llama-cpp-server后端(本地)拉起并托管本地 llama.cpp 进程,跑 GGUF 模型(llama-cpp-server/src/lib.rs:1-17)
crates/tabby-download / aim-downloader支撑从模型注册表下载权重文件
crates/tabby-git / tabby-crawler支撑Git 仓库读取 / 文档抓取,为索引供料
ee/tabby-webserver企业版企业功能主体:Answer Engine、GraphQL、鉴权、后台任务(tabby-webserver/src/lib.rs:1)
ee/tabby-db企业版SQLite 数据访问层:用户、线程、集成等(tabby-db/src/lib.rs)
ee/tabby-schema企业版GraphQL schema 与 DAO 定义(tabby-schema/src/lib.rs:1)
clients/*客户端IDE / 编辑器插件与共享库:vscodeintellijvimeclipsetabby-agent 等(clients/ 九个目录)

一个反常识点: 企业版(ee/)不是一个独立部署的服务,而是通过 Cargo feature = "ee" 编进同一个二进制;serve.rs 里到处是 #[cfg(feature = "ee")],启用后 ws.attach 把 GraphQL、鉴权、答案引擎等路由挂到同一个 axum Router 上(serve.rs:209-225)。


4. 阅读地图(后续各章、建议顺序、面向读者)

这组文档由浅入深、从骨架到底层排列。建议按顺序读;如果只关心某一块,可按「面向读者」跳读。

顺序章节讲什么面向读者
0index.md(本章)这是什么 · 全景 · 阅读地图所有人,先读我
101-serving-and-request-flow.md服务骨架:从 CLI 两个子命令到 axum 路由装配,一次请求怎么被路由想理解整体控制流的人
202-code-completion.md核心价值:检索增强的代码补全,FIM 提示怎么拼、片段怎么选关心补全质量/prompt 工程的人
303-retrieval-and-indexing.md仓库上下文:tree-sitter 切片、Tantivy 索引、embedding + BM25 的 RRF 混合检索关心 RAG / 检索排序的人
404-inference-backends.md底层引擎:推理抽象接口、解码停止条件、本地 llama.cpp 与远程后端如何可插拔关心模型接入 / 推理的人
505-enterprise-webserver.md企业面:Answer Engine、GraphQL、后台索引任务、Git/GitLab 集成关心企业版/团队功能的人

推荐路线:

  • 只想看懂整体架构 → 本章 + 第 1 章即可。
  • 想吃透「为什么 Tabby 补全更聪明」 → 第 2 章 → 第 3 章(补全依赖检索,先看补全再看检索的来源)。
  • 想接自己的模型 / 做推理优化 → 第 4 章。
  • 要部署企业版、做团队知识库 → 第 5 章。

5. 巧妙之处速览(指向后续章)

这里只点一句妙在哪 + 指到哪一章看细节,不展开。它们是读完全套文档你该带走的「精华索引」。

  • 推理后端是一层薄抽象,本地/远程随便换。 tabby-inference 只定义 CompletionStream / ChatCompletionStream 等接口(tabby-inference/src/lib.rs:8-11),配置是 Local 就走 llama-cpp-server,是 Http 就走 http-api-bindings(services/model/mod.rs:38-73)。→ 第 4 章

  • 检索用 RRF 融合两种召回,而不是只信向量。 代码检索把 embedding 和 BM25 的结果用 Reciprocal Rank Fusion(倒数排名融合)合并、再按 rrf 分排序过滤(services/code.rs:95-138)。→ 第 3 章

  • 补全提示是「检索片段 + FIM 填空」拼出来的,不是裸提示。 generatebuild_snippets 检索、再 prompt_builder.build 组装,还处理了 CRLF 换行差异(services/completion.rs:382-408)。→ 第 2 章

  • 企业版靠 feature flag「挂载」进同一个服务器。 ws.attach 把企业路由并进主 Router,一个二进制两种形态(serve.rs:209-225)。→ 第 5 章

  • 本地模型按需自动下载。 启动时 load_model 检查配置,缺哪个(补全/对话/嵌入)就下载哪个(serve.rs:235-249)。→ 第 1 章


6. 代码地图(导航索引)

一张跳转表:想直接进源码,从这些符号名下手(符号名比行号抗上游漂移,可直接 grep)。

主题文件路径符号名
CLI 子命令定义crates/tabby/src/main.rsCommands(Serve / Download)
本地模型配置构造crates/tabby/src/main.rsto_local_config
服务器主装配crates/tabby/src/serve.rsmain
HTTP 路由拼装crates/tabby/src/serve.rsapi_router
OpenAPI 文档定义crates/tabby/src/serve.rsApiDocServeArgs
补全服务入口crates/tabby/src/services/completion.rsCompletionService::generate
补全+对话服务构造crates/tabby/src/services/completion.rscreate_completion_service_and_chat
推理后端选择(本地/远程)crates/tabby/src/services/model/mod.rsload_code_generation_and_chat
代码检索 + RRF 融合crates/tabby/src/services/code.rsCodeSearchImplcreate_code_search
推理抽象接口crates/tabby-inference/src/lib.rsCompletionStreamChatCompletionStream
后台索引调度crates/tabby-index/src/lib.rspublic(索引/GC 入口)
workspace 成员清单Cargo.tomlmembers