0%

一、为什么 SDD 突然火了?

2025 年下半年,GitHub 上突然冒出两个”爆款”项目:

项目 Stars 出品方 创建时间
spec-kit 87,549 GitHub 官方 2025-08
OpenSpec 39,543 Fission AI 2025-08

两个项目都主打同一个概念——SDD(Specification-Driven Development,规格驱动开发)

有意思的是,SDD 这个概念早在 2010 年左右就有人提过,但一直不温不火。为什么到了 2025 年突然”爆了”?

答案很简单:AI 编码助手成熟了

以前写规格是为了”人理解需求”,现在写规格是为了”AI 理解需求并生成代码”。这个转变,让 SDD 从”锦上添花”变成了”必备技能”。


二、SDD 的起源与发展

2.1 方法论的演进脉络

软件开发方法论一直在”左移”——把质量保障的关口往前推:

1
2
3
4
5
6
7
8
9
10
11
传统开发:需求 → 编码 → 测试 → 部署
↑______________| 问题发现太晚

TDD(2003):测试 → 编码 → 重构
↑_____| 先写测试,确保可测试

BDD(2006):行为描述 → 测试 → 编码
↑__________| 用自然语言描述行为

SDD(2025):规格 → AI生成代码 → 审查验证
↑______________| 先写清楚"要什么",AI 再生成"怎么做"

用一个生活类比:

方法论 类比
传统开发 厨师边做菜边尝,最后才发现盐放多了
TDD 先准备好品尝标准,做菜过程中不断对照
BDD 先写好”菜谱描述”(这道菜应该有什么味道),再让厨师做
SDD 先写好”完整菜单规格”(食材、步骤、口味),让 AI 厨师按规格来做

2.2 为什么以前 SDD 不火?

SDD 的核心思想是”先写规格再写代码”,听起来很合理。但以前有三大障碍:

  1. 人写代码比写规格快:资深程序员脑子里有模板,写代码比写文档快多了
  2. 规格容易过时:代码改了,规格忘了同步,最后变成”摆设”
  3. 没有工具支撑:规格只是 Markdown 文档,没法”执行”,也没法验证代码是否符合规格

2.3 为什么现在突然火了?

2024-2025 年,三个关键条件同时成熟:

条件 变化
AI 编码工具成熟 Claude Code、Cursor、Copilot 能真正写出可用代码
开发者角色转变 从”代码编写者”变成”规格设计者 + 代码审查者”
工具链完善 spec-kit、OpenSpec 提供了规格的”执行框架”

一个数据:预计到 2026 年,80% 的开发者将常态化使用 AI 编码工具。开发者花在规格设计和架构上的时间将超过写代码的时间。


三、SDD 的核心能力

3.1 一句话定义

SDD = 先用结构化规格精确描述”要做什么”,再让 AI 照着规格生成代码,最后验证代码是否符合规格。

3.2 核心能力拆解

能力 说明
协作澄清 开发者可能不清楚怎么做,AI 协助完成问题定义和方案探索——这是 SDD 最被低估的能力
规格即契约 规格不是”参考文档”,而是人机之间的”契约”——AI 必须按规格实现
迭代友好 规格可以随时更新,AI 会同步更新代码(不是”写完就扔”)
验证闭环 有工具验证代码是否符合规格,偏离时自动提醒
追溯性强 每一行代码都能追溯到对应的规格条款

3.3 协作澄清:SDD 最被低估的能力

很多人以为 SDD 是”开发者先写清楚规格,再让 AI 照着做”。但现实是:开发者往往也不清楚自己要什么

这时候,SDD 的”澄清模式”就派上用场了:

1
2
传统模式:开发者想清楚 → 写规格 → AI 实现
澄清模式:开发者有个模糊想法 → AI 协助澄清 → 共同定义问题 → 探索方案 → 写规格 → AI 实现

用一个类比:

场景 类比
传统 SDD 你拿着完整菜单去餐厅,厨师照着做
澄清模式 你说”我想吃点清淡的”,厨师和你讨论:是汤?是蒸菜?有什么忌口?最后一起定菜单

这就是 /speckit.clarify/opsx:explore 模式的价值——AI 不是被动执行者,而是主动的”需求澄清伙伴”

3.4 规格包含什么?

一个完整的 SDD 规格通常包含四个部分:

1
2
3
4
5
6
7
openspec/changes/add-dark-mode/
├── proposal.md # 为什么做这个改动?影响范围?
├── specs/ # 详细需求规格
│ ├── requirements.md # 功能需求
│ └── scenarios.md # 使用场景
├── design.md # 技术方案:怎么实现?
└── tasks.md # 任务清单:分几步完成?

3.5 与 TDD/BDD 的关系

SDD 不是替代 TDD/BDD,而是它们的”前置层”:

1
2
3
4
5
6
7
8
9
10
11
12
13
┌─────────────────────────────────────────────────────┐
│ SDD │
│ 规格 → 定义"要做什么" │
├─────────────────────────────────────────────────────┤
│ BDD │
│ 行为描述 → 定义"应该有什么行为" │
├─────────────────────────────────────────────────────┤
│ TDD │
│ 测试 → 定义"怎么验证正确性" │
├─────────────────────────────────────────────────────┤
│ 实现 │
│ 代码 → AI 按上述三层约束生成 │
└─────────────────────────────────────────────────────┘

四、如何与 Code Agent 配合使用

4.1 工作流程对比

没有 SDD 时的工作流

1
2
3
4
5
6
7
8
9
10
你:帮我加个深色模式
AI:(直接开始写代码)好的,我创建 ThemeContext...
你:等等,我想要的是 localStorage 持久化
AI:那我改一下...
你:还要支持系统主题自动切换
AI:再改一下...
你:切换按钮放在导航栏右侧
AI:...

问题:需求在"聊天中不断补充",AI 来回改,效率低

有 SDD 时的工作流

1
2
3
4
5
6
7
8
你:/opsx:propose "添加深色模式"
AI:生成完整规格 → proposal + specs + design + tasks
你:(审查规格)嗯,规格里漏了 localStorage 持久化,补一下
AI:(更新规格)
你:(确认无误)/opsx:apply
AI:按规格一次性实现,不用来回改

优势:先对齐"要做什么",再一次性实现

4.2 支持的 Code Agent

Code Agent spec-kit 支持 OpenSpec 支持
Claude Code --ai claude /opsx:* 命令
Cursor ✅ slash commands ✅ slash commands
GitHub Copilot CLI ✅ 原生支持 ✅ skills 模式
Codex CLI ✅ skills 模式 ✅ skills 模式
Windsurf

五、问题澄清模式:当你不知道怎么做时

前面讲的流程都有一个前提:开发者知道”要做什么”。但现实往往是:

“我想给博客加个评论功能,但不知道怎么设计…”
“用户反馈搜索太慢,但我不清楚具体慢在哪里…”
“产品说要提升用户体验,但这个需求太模糊了…”

这时候,澄清模式(Clarify/Explore) 就派上用场了。

5.1 澄清模式的价值

澄清前 澄清后
“我想加评论功能”(模糊) “评论功能需要:登录才能评论、支持楼中楼、可编辑删除、有审核机制”(清晰)
“搜索太慢”(笼统) “问题定位:首页搜索接口响应 3s+,原因是全文检索没走索引,需要优化 SQL 并加缓存”(具体)
“提升用户体验”(抽象) “具体方案:页面加载加骨架屏、关键操作加确认弹窗、表单加实时校验提示”(可落地)

澄清过程本身就是在”定义问题”——很多 Bug 的根因不是代码写错了,而是需求本身就没想清楚。

5.2 spec-kit 的澄清流程

使用 /speckit.clarify 命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
你:/speckit.clarify "我想给博客加个评论功能"

AI:让我帮你澄清一下这个需求...
Q1: 评论需要登录才能发吗?
你:是的,必须登录

Q2: 评论支持回复别人的评论吗?(楼中楼)
你:支持,最多嵌套 3 层

Q3: 评论发出去能编辑或删除吗?
你:发出去 5 分钟内可以编辑,用户自己发的可以删除

Q4: 评论需要审核吗?还是直接显示?
你:需要审核,管理员后台审核后才显示

AI:好的,我来整理一下澄清后的需求...

[生成 clarification.md]
✓ 问题边界已明确
✓ 关键决策已记录
✓ 可以进入规格编写阶段

你:/speckit.spec blog-comment-system

5.3 OpenSpec 的探索流程

使用 /opsx:explore 命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
你:/opsx:explore "用户反馈搜索太慢,想优化一下"

AI:让我先帮你分析问题...

1. 定位问题范围:
- 是首页搜索慢?还是后台管理搜索?
- 是所有搜索都慢?还是特定关键词?
- "慢"的标准是什么?2s?5s?

你:首页的全站搜索,大概 3-4 秒才出结果,用户说体验很差

2. 排查可能原因:
- 检查当前实现:全文检索 LIKE '%keyword%'
- 数据量:posts 表 10万+,没走索引
- 缓存策略:无缓存,每次查库

3. 方案探索:
方案A:加全文索引(MySQL FULLTEXT)
方案B:引入 Elasticsearch
方案C:加 Redis 缓存热点关键词

各方案对比:
| 方案 | 成本 | 效果 | 维护难度 |
|------|------|------|----------|
| A | 低 | 中(大数据量仍慢) | 低 |
| B | 高 | 高 | 高(新增组件) |
| C | 低 | 中(命中率依赖) | 低 |

建议组合方案:A + C,先加索引打底,再加缓存加速热点

你:就用 A + C 组合方案

AI:好的,我来生成探索记录...

[生成 openspec/explorations/search-optimization/]
✓ exploration.md — 问题分析 + 方案对比
✓ decision.md — 最终选择的方案 + 原因
✓ 可以进入 /opsx:propose 阶段

5.4 澄清模式的核心价值

用一个公式总结:

1
需求质量 = 澄清深度 × 规格精度 × 验证闭环

澄清是起点。如果一开始需求就模糊,后面写再详细的规格、做再严格的验证,都是”在错误的方向上努力”。

很多项目的返工、延期,根因都在这里:

返工原因 根因
“这不是我想要的” 澄清不够,理解偏差
“需求又变了” 边界没定清楚,后面不断加范围
“实现方案不对” 没探索充分,选错了技术路线

SDD 的澄清模式,就是帮你把这些问题”前置解决”——在写代码之前,先把问题聊清楚。


六、与 Claude Code 配合的安装步骤

6.1 spec-kit 安装

1
2
3
4
5
6
7
8
# 方式一:推荐安装稳定版本(v0.6.1)
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git@v0.6.1

# 方式二:安装最新版本
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git

# 验证安装
specify check

初始化项目:

1
2
3
4
5
# 创建新项目
specify init my-project --ai claude

# 或在现有项目中初始化
specify init . --ai claude

6.2 OpenSpec 安装

1
2
3
4
5
6
7
8
9
# 需要 Node.js 20.19.0+
npm install -g @fission-ai/openspec@latest

# 验证安装
openspec --version

# 初始化项目
cd your-project
openspec init

七、实战示例:同一个需求,两种工具

需求:为博客网站添加深色模式

7.1 spec-kit 使用流程

步骤 1:定义项目原则

1
2
cd my-project
claude

在 Claude Code 中执行:

1
2
3
4
> /speckit.constitution 创建项目核心原则:
- 代码风格遵循 ESLint 规范
- 所有 UI 组件需要单元测试
- 新功能需要配套文档

AI 会生成 .speckit/constitution.md 文件。

步骤 2:创建功能规格

1
2
3
4
5
6
7
> /speckit.spec add-dark-mode 创建深色模式功能规格

需求要点:
- 支持亮色/深色/跟随系统三种模式
- 用户偏好存储在 localStorage
- 导航栏右侧放置切换按钮
- 切换时平滑过渡动画

AI 会生成 .speckit/features/add-dark-mode/spec.md

步骤 3:生成实施计划

1
> /speckit.plan add-dark-mode

AI 生成 .speckit/features/add-dark-mode/plan.md,包含:

  • 技术方案(用 React Context 还是 CSS 变量?)
  • 文件改动清单
  • 实施步骤

步骤 4:分解任务

1
> /speckit.tasks add-dark-mode

生成 .speckit/features/add-dark-mode/tasks.md

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
## Tasks

### 1. 基础设施
- [ ] 1.1 创建 ThemeContext
- [ ] 1.2 定义 CSS 变量体系
- [ ] 1.3 创建 useTheme hook

### 2. UI 组件
- [ ] 2.1 创建 ThemeToggle 组件
- [ ] 2.2 添加过渡动画样式
- [ ] 2.3 集成到导航栏

### 3. 持久化
- [ ] 3.1 localStorage 存取逻辑
- [ ] 3.2 系统主题监听

### 4. 测试
- [ ] 4.1 ThemeContext 单元测试
- [ ] 4.2 ThemeToggle 组件测试

步骤 5:执行实施

1
> /speckit.implement add-dark-mode

AI 按任务清单逐项实现代码。

步骤 6:验证审查

1
> /speckit.verify add-dark-mode

AI 检查:

  • 每个任务是否完成
  • 代码是否符合规格
  • 测试是否通过

7.2 OpenSpec 使用流程

步骤 1:一键生成完整规格

1
2
cd my-project
claude

在 Claude Code 中执行:

1
2
> /opsx:propose "添加深色模式,支持亮色/深色/跟随系统三种模式,
用户偏好存储在 localStorage,导航栏右侧放置切换按钮"

AI 一次性生成完整规格目录:

1
2
3
4
5
6
7
openspec/changes/add-dark-mode/
├── proposal.md # ✅ 为什么做?影响哪些页面?
├── specs/
│ ├── requirements.md # ✅ 功能需求详情
│ └── scenarios.md # ✅ 用户使用场景
├── design.md # ✅ 技术方案:React Context + CSS 变量
└── tasks.md # ✅ 实施任务清单

步骤 2:审查并调整规格

1
2
> 打开 specs/requirements.md,补充一个需求:
切换按钮需要显示当前模式图标(太阳/月亮/电脑)

AI 更新规格文件。

步骤 3:执行实施

1
> /opsx:apply

输出:

1
2
3
4
5
6
7
8
9
10
11
12
AI: Implementing tasks...
✓ 1.1 Create ThemeContext provider
✓ 1.2 Define CSS variable system
✓ 1.3 Create useTheme hook
✓ 2.1 Create ThemeToggle component
✓ 2.2 Add transition animation
✓ 2.3 Integrate to navbar
✓ 3.1 localStorage logic
✓ 3.2 System theme listener
✓ 4.1 Unit tests
✓ 4.2 Component tests
All tasks complete!

步骤 4:归档

1
> /opsx:archive

AI 将完成的变更归档:

1
2
Archived to openspec/changes/archive/2026-04-13-add-dark-mode/
Specs updated. Ready for the next feature.

八、spec-kit vs OpenSpec:如何选择?

维度 spec-kit OpenSpec
出品方 GitHub 官方 Fission AI(创业公司)
风格 工程化、严谨 灵活、快速
安装 Python + uv Node.js + npm
流程 分步执行(6 个命令) 一键生成 + 一键应用
扩展性 40+ 官方扩展 配置化定制
适合场景 大型项目、团队协作 个人项目、快速迭代
学习曲线 较陡(概念多) 较平(上手快)

选择建议

1
2
3
4
5
6
如果你是...
├─ 大型团队,需要严格控制 → 选 spec-kit
├─ 个人开发者,追求效率 → 选 OpenSpec
├─ Python 项目 → spec-kit(工具链一致)
├─ TypeScript/JS 项目 → OpenSpec(工具链一致)
└─ 想快速体验 SDD → 先试 OpenSpec,再学 spec-kit

九、总结:SDD 是 AI 编码时代的”必修课”

回顾一下:

  1. SDD 不是新概念,但 AI 编码工具让它变得至关重要
  2. 核心能力:协作澄清、规格即契约、迭代友好、验证闭环、追溯性强
  3. 澄清模式:当你不知道怎么做时,AI 协助你把需求聊清楚——这是最被低估的能力
  4. 与 Code Agent 配合:先对齐”要做什么”,再让 AI 一次性实现
  5. 两个主流工具:spec-kit(GitHub 官方)、OpenSpec(灵活高效)

一句话总结:

以前写代码靠”手艺”,现在写代码靠”规格”。写得越清楚,AI 生成得越精准。

如果你自己都不清楚要什么,先用澄清模式把需求聊明白——这才是 SDD 的起点。


参考资料

如果你是一个人做项目,你不需要成为产品经理、架构师、营销专家——只需要知道何时调用哪个「虚拟专家」。Agency-Agents 这个开源项目,就是把 200 多个专业角色打包成了可以直接导入 Claude Code 的 Agent 文件。本文会介绍这个工具是什么、怎么用,以及如何用它协作开发一个完整项目。

阅读全文 »

用 Claude Code 写代码的时候,你有没有过这种焦虑:不知道当前用的什么模型、context 还剩多少、这一轮对话花了多少钱?这三个指标直接影响代码质量和你的钱包,但 Claude Code 默认不显示。好在有个 statusLine 功能,可以自定义一个「仪表盘」实时监控这些数据。

阅读全文 »

画架构图、流程图、时序图,传统方式是打开 draw.io 手动拖拽。Next AI Draw.io 提供了另一种方式:你用自然语言描述,AI 帮你画。更棒的是,它支持 MCP 协议,可以在 Claude Code 中直接调用——写代码时让 AI 顺手把图也画了。

阅读全文 »

写在前面

如果你刚读完《AI 概念指南》,对 LLM、Agent 这些基础概念有了初步了解,但在实际使用 AI 时,可能又遇到了新的困惑:

  • “Claude Code 和 Claude 是什么关系?用 Claude Code 必须用 Claude 吗?”
  • “Claude Code 里可以切换模型,那它和 Kimi、GLM 是什么关系?”
  • “我想用国产模型,该选工具还是选模型?”

这些问题非常普遍。AI 领域有两层东西叠在一起:一层是”大脑”(模型),一层是”应用”(工具)。很多小白搞混,就是因为分不清哪层是哪层。

这篇文章的目标:让你彻底搞清楚模型和工具的关系,看完之后不再迷糊


一、核心概念:两层架构

把 AI 世界想象成一个餐厅:

1
2
3
4
5
6
7
8
9
10
11
┌─────────────────────────────────────────────────────────┐
│ 餐厅(AI 生态) │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 厨师(模型) │◄──────│ 服务员(工具) │ │
│ │ │ │ │ │
│ │ 负责做菜 │ │ 负责端菜、接待 │ │
│ │ 提供"智能能力" │ │ 提供"交互界面" │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘

第一层:AI 模型(厨师)—— 提供”智能”

模型是 AI 的核心,负责思考、理解、生成内容。它就像餐厅里的厨师,决定菜品的”味道”(智能水平)。

模型的核心特点:

  • 不直接面向用户,而是通过 API 被”工具”调用
  • 是智能的”发动机”,所有的推理、理解、生成都在这里完成
  • 一次训练成本极高(数亿到数十亿美元),但边际使用成本低

第二层:AI 工具(服务员)—— 提供”交互”

工具是用户实际接触的产品,负责界面交互、功能整合。它就像餐厅里的服务员,把厨师做的菜端到顾客面前。

工具的核心特点:

  • 直接面向用户,提供聊天界面、编程环境、文档处理等功能
  • 调用一个或多个模型的 API,把模型能力”包装”成用户友好的产品
  • 本身不产生智能,只是”智能的搬运工”

二、主流模型一览(第一层)

先认识一下市面上的”厨师们”:

国内模型

模型 出品公司 特点 适用场景
Kimi 月之暗面 超长上下文(200万字),中文优化 长文档阅读、论文分析
GLM 智谱AI 开源+闭源双轨,学术背景强 技术研究、企业部署
Qwen(通义千问) 阿里巴巴 中文能力强,开源生态好 中文场景、企业应用
DeepSeek 深度求索 开源、性价比极高、数学推理强 代码、数学、技术研究
Doubao(豆包) 字节跳动 中文理解好,性价比高,多场景适配 日常对话、办公助手
MiniMax MiniMax 多模态、语音交互强 语音场景、多模态应用

国外模型

模型 出品公司 特点 适用场景
Claude Anthropic 推理严谨、代码能力强、上下文长 编程、长文档分析、安全场景
GPT(ChatGPT 底层) OpenAI 生态最完善、插件最多 通用场景、创意写作
Gemini Google 多模态原生、谷歌生态集成 多媒体处理、谷歌用户
Llama Meta 完全开源、可本地部署 私有部署、技术研究

一个关键认知

模型本身不是产品。你无法”直接使用”模型,必须通过某个工具(如 ChatGPT、Claude 网页版、API 接口等)来访问模型的能力。

1
2
3
4
5
6
7
8
┌─────────────────────────────────────────────────────────┐
│ 模型不能直接访问 │
│ │
│ ❌ "我要用 GPT-4" —— 这是无法直接做到的 │
│ ✅ "我要用 ChatGPT" —— 这才是正确说法 │
│ │
│ 因为 ChatGPT 是工具,GPT-4 是它背后的模型 │
└─────────────────────────────────────────────────────────┘

三、主流工具一览(第二层)

再认识一下”服务员们”:

AI 对话工具(网页版/APP)

这些工具提供对话界面,让你能和模型”聊天”:

工具 主要模型 是否支持切换模型
ChatGPT GPT 系列 ❌ 仅 OpenAI 模型
Claude 网页版 Claude 系列 ❌ 仅 Anthropic 模型
Kimi 网页版/APP Kimi ❌ 仅月之暗面模型
豆包 Doubao ❌ 仅字节跳动模型
Poe 多模型 ✅ 支持 Claude、GPT、Llama 等
Cherry Studio 多模型 ✅ 支持配置多种模型 API
Chatbox 多模型 ✅ 支持配置多种模型 API

AI 编程工具(IDE/编辑器插件)

这些工具专注于编程场景,能读写代码、理解项目:

工具 类型 支持的模型 特点
Claude Code CLI/IDE插件 Claude、Kimi、GLM、MiniMax、Doubao 等多模型 官方出品,代码理解最强,支持多模型切换
Cursor AI IDE Claude、GPT、DeepSeek、Gemini 等 可切换模型,IDE 集成体验好
GitHub Copilot IDE 插件 GPT 系列 微软出品,与 GitHub 深度集成
Trae AI IDE Kimi、GLM、Doubao 等(国内模型为主) 字节出品,中文优化
Qoder AI 编程工具 多模型 支持多种国产模型
OpenCode 开源 AI 编程工具 多模型 开源免费,可自定义配置

重要说明:Claude Code 是 Anthropic 官方出品的编程工具,但它支持多种模型,包括国内的 Kimi、GLM、MiniMax、Doubao 等。对于没有海外信用卡的中国用户,可以配置国产模型 API 来使用 Claude Code。

工具的本质

工具做的事情就是把你的输入(问题、代码、文档)发送给模型,然后把模型的回答展示给你:

1
2
3
4
5
6
7
8
9
┌─────────────────────────────────────────────────────────────────┐
│ 工具的工作流程 │
│ │
│ 用户输入 ──► 工具处理 ──► 调用模型 API ──► 获取模型回答 ──► 展示给用户
│ │ │ │
│ "帮我写个函数" 发送请求 返回代码
│ 到模型服务器 给用户
│ │
└─────────────────────────────────────────────────────────────────┘

四、模型与工具的关系图

关系示意图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
                              工具层(用户直接接触)
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Claude Code │ │ Cursor │ │ Trae │ │
│ │ (多模型) │ │ (多模型) │ │ (国内模型) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 多模型 API │ │ 多模型 API │ │ Kimi/GLM API │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────┬───────────────────────────────┘


模型层(智能来源)
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ Claude │ │ GPT │ │ Gemini │ │ Kimi │ │ DeepSeek│ │
│ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ GLM │ │ Doubao │ │MiniMax │ │ Qwen │ │ ... │ │
│ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

两种关系模式

模式一:官方绑定型

1
2
3
4
5
6
7
8
9
10
11
┌─────────────┐           ┌─────────────┐
│ ChatGPT │ ────────► │ GPT │
│ (工具) │ 官方绑定 │ (模型) │
└─────────────┘ └─────────────┘

┌─────────────┐ ┌─────────────┐
│ Claude 网页版│ ────────► │ Claude │
│ (工具) │ 官方绑定 │ (模型) │
└─────────────┘ └─────────────┘

特点:一个工具只能用自家模型的 API,不能切换其他模型

模式二:多模型支持型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌─────────────┐           ┌─────────────┐
│ Claude Code │ ────────► │ Claude │
│ (工具) │ │ (模型) │
│ │ ────────► ├─────────────┤
│ │ │ Kimi │
│ │ ────────► ├─────────────┤
│ │ │ GLM │
│ │ ────────► ├─────────────┤
│ │ │ MiniMax │
│ │ ────────► ├─────────────┤
│ │ │ Doubao │
└─────────────┘ └─────────────┘

特点:一个工具可以切换多个模型,用户自己选择

注意:Claude Code 虽然是 Anthropic 官方出品,但它支持配置多种模型的 API。对于中国用户来说,这意味着你可以用 Kimi、GLM、MiniMax、Doubao 等国产模型来驱动 Claude Code,而不必依赖海外支付渠道。


五、常见困惑解答

Q1:Claude Code 就是 Claude 吗?

不是。

  • Claude 是模型,是 Anthropic 开发的 AI “大脑”
  • Claude Code 是工具,是 Anthropic 官方出品的编程助手

Claude Code 调用模型来帮你写代码,但它不只是调用 Claude,还支持 Kimi、GLM、MiniMax、Doubao 等多种模型。你可以理解为:

1
Claude Code = 编程专用界面 + 代码操作能力 + 多模型 API 支持

Q2:为什么 Claude Code 可以选择 Claude、Kimi、GLM、MiniMax?

因为 Claude Code 是”多模型工具”,它支持配置多个模型厂商的 API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌─────────────────────────────────────────────────────────┐
│ Claude Code 架构 │
│ │
│ 用户界面 ◄──► Claude Code 核心 ◄──► 模型配置 │
│ │ │
│ ┌──────────────────┼────────────┐ │
│ ▼ ▼ ▼ │
│ Claude API Kimi API GLM API │
│ (Anthropic) (月之暗面) (智谱AI) │
│ │
│ ▼ ▼ ▼ │
│ MiniMax API Doubao API 其他 API │
│ (MiniMax) (字节跳动) (可扩展) │
└─────────────────────────────────────────────────────────┘

Claude Code 做的是”整合商”的工作,让你在一个工具里能用多个模型。

对于中国用户特别友好:如果你没有海外信用卡,无法购买 Claude API,完全可以配置国产模型(如 Kimi、GLM、MiniMax、Doubao)的 API 来使用 Claude Code。这些国产模型通常支持国内支付方式,获取 API 更方便。

Q3:我想用国产模型,该怎么选?

方案一:直接用模型官方工具

  • Kimi → Kimi 网页版/APP
  • GLM → 智谱清言
  • Doubao → 豆包 APP
  • Qwen → 通义千问
  • DeepSeek → DeepSeek 网页版

方案二:用支持国产模型的编程工具

这是很多程序员的选择,既能用国产模型,又能享受专业编程工具的体验:

  • Claude Code(推荐)—— 支持 Kimi、GLM、MiniMax、Doubao 等多种国产模型,代码能力最强
  • Trae(字节出品)—— 默认 Kimi/GLM/Doubao,中文优化
  • Qoder —— 支持多种国产模型
  • Cursor —— 支持 DeepSeek

Q4:模型和工具哪个更重要?

都重要,但影响点不同:

维度 模型决定 工具决定
智能水平 ✓ 回答质量、推理能力
使用体验 ✓ 界面设计、操作流畅度
功能丰富度 ✓ 代码高亮、文件管理、历史记录
模型选择 ✓ 是否支持切换模型
价格 ✓ API 调用成本 ✓ 订阅费用
隐私合规 ✓ 数据处理方式 ✓ 本地存储、日志记录

一句话总结:模型决定”上限”,工具决定”体验”。


六、选型指南

按需求选

你的需求 推荐模型 推荐工具
日常聊天问答 GPT-4o、Claude、Doubao ChatGPT、Claude 网页版、豆包
读长文档/论文 Kimi、Claude Kimi 网页版、Claude
写代码/重构 Claude、DeepSeek、GLM Claude Code、Cursor
数学/逻辑推理 DeepSeek-R1、Claude DeepSeek 网页版、Claude Code
国产模型+编程 Kimi、GLM、Doubao、MiniMax Claude Code(配置国产模型 API)
企业私有部署 GLM、Qwen、DeepSeek OpenCode、自建平台

按用户类型选

用户类型 推荐组合 理由
完全小白 ChatGPT 或 Kimi/豆包 网页版 开箱即用,无需配置
办公族 Kimi/豆包 + Claude 网页版 长文档 + 通用问答
程序员(有海外支付) Claude Code + Claude API 官方模型,体验最佳
程序员(国内用户) Claude Code + Kimi/GLM/Doubao API 国产模型,支付方便
技术极客 Cherry Studio + 多模型 API 灵活配置,自由切换
企业用户 私有部署 + 定制工具 数据安全,合规可控

七、避坑指南

常见误区

误区 正确理解
“我买了 Cursor,是不是就能用 Claude?” Cursor 是工具,Claude API 需要单独付费或配置
“Claude Code 只能用 Claude 吗?” 错误! Claude Code 支持多种模型,包括 Kimi、GLM、MiniMax、Doubao 等
“Kimi 和 DeepSeek 哪个好?” 没有绝对好坏,看场景:Kimi 长文档强,DeepSeek 代码数学强
“Claude Code 是官方出品,肯定只支持自家模型” 官方出品不代表只支持自家模型,Claude Code 是开放的多模型工具
“国产模型不如国外模型” 各有优势,国产模型中文理解更好,国外模型生态更完善

省钱技巧

  1. 简单任务用小模型:日常对话用更便宜的模型(如 GPT-4o-mini、Claude Haiku)
  2. 复杂任务用大模型:代码、推理用更强的模型(如 Claude Sonnet、DeepSeek-V3)
  3. 对比后再订阅:先用免费额度测试,再决定是否付费
  4. 注意 API 调用成本:工具可能免费,但模型 API 调用要收费
  5. 国产模型性价比高:Kimi、GLM、Doubao 等国产模型通常价格更友好,支付更方便

八、总结

用一个比喻来总结模型和工具的关系:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 模型 = 发动机(提供动力) │
│ 工具 = 汽车(提供驾驶体验) │
│ │
│ Claude Code = 一辆可以换不同发动机的改装车 │
│ 可以装 Claude、Kimi、GLM、MiniMax、Doubao 等 │
│ │
│ ChatGPT = 装了 GPT 发动机的官方轿车(不能换发动机) │
│ Claude 网页版 = 装了 Claude 发动机的官方轿车(不能换发动机) │
│ │
│ 你可以: │
│ - 买不能换发动机的官方车(ChatGPT、Claude 网页版) │
│ - 买可换发动机的车(Claude Code、Cursor、Poe) │
│ - 自己组装(Cherry Studio + API) │
│ │
│ 核心原则:先想好你要什么体验,再选车和发动机 │
│ │
└─────────────────────────────────────────────────────────────────┘

记住三个要点

  1. 模型是智能来源,工具是交互入口 —— 搞清楚你在用哪层
  2. 一个工具可能支持多个模型,一个模型可以被多个工具调用 —— 它们是多对多的关系
  3. Claude Code 支持多模型 —— 对于中国用户,可以配置国产模型 API 来使用

附录:术语对照表

模型术语 所属公司 常见混淆
Claude Anthropic Claude Code 是工具,Claude 是模型;但 Claude Code 支持多模型
GPT-4、GPT-4o OpenAI ChatGPT 是工具,GPT 是模型
Kimi 月之暗面 同名,但要注意区分工具和模型
DeepSeek 深度求索 同名,网页版是工具,API 是模型
GLM 智谱AI 智谱清言是工具,GLM 是模型
Doubao(豆包) 字节跳动 豆包 APP 是工具,Doubao 是模型
Qwen 阿里巴巴 通义千问是工具,Qwen 是模型
Gemini Google Gemini 网页版是工具,Gemini 是模型

参考资料

背景

很多刚开始接触大模型的朋友,经常会看到”消耗了 XXX tokens”、”超出 token 限制”这样的提示。但到底什么是 Token?为什么大模型要用 Token 而不是直接理解整段话?本文将深入浅出地解答这些问题。


一、Token 是什么?

Token 是大模型处理文本的最小单位。可以把它理解为文本世界的”乐高积木块”——模型不是逐字逐句读取,而是先把文本拆成一块块 Token,再逐块处理。

1.1 通俗理解

想象你在读一本书:

阅读方式 特点
字符级别 一个字母一个字母读 → 太慢,无法理解语义
单词级别 一个单词一个单词读 → 更合理,但词汇量太大
Token 级别 介于两者之间,灵活切分 → 效率与能力的平衡点

1.2 具体例子

英文句子 I love artificial intelligence

1
2
3
按字符:20 个字符(含空格)
按单词:4 个单词
按 Token:约 5-6 个 Token(取决于分词器)

中文句子 我爱人工智能

1
2
按字符:6 个汉字
按 Token:约 6-10 个 Token(每个汉字可能单独成 Token)

二、为什么使用 Token 而不是”理解整段话”?

这个问题触及了大模型的核心原理。答案很简单:计算机只能处理数字,不能直接理解文字

2.1 大模型的工作流程

1
文字 → Token → 数字(向量)→ 计算 → 预测 → Token → 文字

每一步都必须是有限、可枚举的。

2.2 如果是”整段话处理”

假设模型要直接处理”整段话”,会遇到以下问题:

问题 说明
无限组合 一段话可能有任意长度、任意组合,无法穷举
无法对齐 “我爱AI”和”我 爱 AI”算同一段话吗?
无法计算 神经网络本质是矩阵乘法,需要固定维度的输入
存储爆炸 要存储所有可能的句子组合,内存直接撑爆

2.3 Token 方案的优势

优势 说明
有限词汇表 常用 Token 约 5-10 万个,可以穷举并编号
可数学化 每个 Token 对应一个向量(如 4096 维),可以计算
灵活组合 像乐高一样,有限积木块能拼出无限造型
长短皆可 Token 序列可以处理任意长度的文本

2.4 语言的组合性原理

语言有一个核心特点:有限符号,无限组合

1
2
3
英语:26 个字母 → 无数句子
中文:几千常用字 → 无数句子
Token:几万个 Token → 无数句子

大模型的设计正是利用了这个特性:

如果 Token 只有 5 万个,但能组合出无限句子,那么模型只需要学会这 5 万个 Token 的”表示”和”关系”,就能理解所有可能的句子。

这比试图记忆所有可能的句子要高效得多。


三、Token 的产生背景与历史

3.1 为什么不按”单词”处理?

早期自然语言处理确实尝试过按单词处理,但遇到两个问题:

问题一:词汇量爆炸

英语有超过 100 万个单词,而且每天都在增加新词。要让模型记住所有单词,词汇表会无限膨胀。

问题二:罕见词无法处理

遇到没见过的单词(如 unprecedented),模型直接”不认识”。

3.2 子词分词的诞生

研究者提出子词分词的概念:

1
2
常见词 → 整体作为一个 Token
罕见词 → 拆成多个子词 Token

例如:

单词类型 处理方式 例子
常见词 整体作为一个 Token the, is, hello, love
罕见词 拆成多个 Token unprecedentedun + pre + ced + ented
新词 用已知 Token 组合表示 chatgptchat + g + pt

3.3 主流分词算法

目前主流的分词算法有三类:

算法 全称 特点 代表模型
BPE Byte Pair Encoding 合并频率最高的相邻符号 GPT 系列
WordPiece WordPiece 基于概率的分词,用 ## 标记子词 BERT 系列
Unigram Unigram Language Model 基于统计概率,选择最优分词 T5、XLNet

3.4 BPE 分词示例

BPE 的核心思路是迭代合并

1
2
3
4
5
6
7
8
9
10
11
初始状态:每个字符都是一个 Token
["u", "n", "p", "r", "e", "c", "e", "d", "e", "n", "t", "e", "d"]

迭代 1:合并频率最高的字符组合 "e" + "d" → "ed"
["u", "n", "p", "r", "e", "c", "ed", "e", "n", "t", "ed"]

迭代 2:合并 "un"
["un", "p", "r", "e", "c", "ed", "e", "n", "t", "ed"]

迭代 N:最终得到
["un", "pre", "ced", "ented"]

通过这种方式,模型既能高效处理常见词,又能”认识”从未见过的罕见词。


四、Token 计量规则

4.1 不同语言的 Token 效率

这是很多中文用户最容易困惑的地方:

语言 Token 效率 估算公式
英文 1 Token ≈ 0.75 个单词 ≈ 4 个字符 Token 数 ≈ 单词数 × 1.3
中文 1 Token ≈ 0.6-0.8 个汉字 Token 数 ≈ 字数 × 1.5-2
代码 1 Token ≈ 4 个字符 Token 数 ≈ 字符数 ÷ 4

4.2 为什么中文 Token 数更多?

原因在于分词器的训练数据。主流分词器(如 GPT 系列)主要基于英文语料训练:

  • 英文artificial 可能是 1 个 Token(常见词)
  • 中文:每个汉字 可能各自成为 1 个 Token

这导致同样内容,中文 Token 数通常是英文的 1.5-2 倍

4.3 实例对比

同样的内容用不同语言表达:

内容 语言 Token 数估算
The future of artificial intelligence is bright 英文 约 7-8 个
人工智能的未来很光明 中文 约 10-12 个

这就是为什么用中文对话可能更快消耗 Token 配额。

4.4 不同模型的 Token 效率对比

模型系列 中文 Token 效率 特点
GPT-4 较低(约 2 字/Token) 英文优化,中文拆字多
Claude 中等(约 1.5 字/Token) 多语言平衡
DeepSeek 较高(约 1 字/Token) 中文专项优化
Qwen 较高(约 1 字/Token) 中文原生模型

五、Token 在大模型中的作用方式

5.1 完整处理流程

以句子 "人工智能很强大" 为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
步骤 1: 分词
"人工智能很强大" → ["人工", "智能", "很", "强大"]

步骤 2: 编号(在词汇表中查找)
["人工", "智能", "很", "强大"] → [3821, 567, 89, 4521]

步骤 3: 向量化(每个编号对应一个向量)
3821 → [0.12, -0.34, 0.56, 0.78, ...](4096 维向量)
567 → [0.23, 0.45, -0.11, 0.89, ...]
89 → [0.67, -0.23, 0.34, 0.12, ...]
4521 → [0.45, 0.67, 0.23, -0.45, ...]

步骤 4: 神经网络计算
向量输入 Transformer 模型,计算"下一个 Token 是什么"
- 注意力机制:计算 Token 之间的关联关系
- 前馈网络:提取和变换语义信息

步骤 5: 预测输出
模型输出概率分布 → "的"(概率最高)

步骤 6: Token 转文字
["的"] → "的"

完整输出:"人工智能很强大" + "的" → "人工智能很强大的..."

5.2 向量化是什么?

每个 Token 都有一个向量表示——可以理解为这个 Token 的”数学身份证”。

1
2
3
4
5
Token "人工智能" 的向量(简化示例):
[0.12, -0.34, 0.56, 0.78, 0.23, 0.45, -0.11, 0.89, ...]

这个向量有 4096 个数值(或更多)
每个数值代表这个 Token 在某个语义维度上的"坐标"

向量的神奇之处:语义相似的 Token,向量也相似。

1
2
3
4
5
6
7
Token "狗" 的向量:[0.8, 0.2, 0.1, ...]
Token "猫" 的向量:[0.7, 0.3, 0.2, ...]
Token "汽车" 的向量:[0.1, 0.9, 0.5, ...]

计算相似度:
"狗" vs "猫" → 高相似度(都是动物)
"狗" vs "汽车" → 低相似度(语义差异大)

5.3 为什么是 5 万个 Token 而不是 5 万个单词?

关键区别在于覆盖能力

1
2
3
4
5
6
7
8
单词方案:
- 词汇表:5 万个单词
- 遇到新词:直接"不认识"

Token 方案:
- 词汇表:5 万个 Token(子词)
- 遇到新词:用已知 Token 组合表示
- 例:新词 "deepseek" → ["deep", "seek"](都是已知 Token)

这就是 Token 方案的核心优势:有限词汇表 + 无限组合能力


六、Token 量化方法

6.1 方法一:在线可视化工具

最直观的方式是使用官方提供的 Tokenizer 工具:

工具 链接 特点
OpenAI Tokenizer https://platform.openai.com/tokenizer GPT 模型分词可视化
Anthropic Console https://console.anthropic.com Claude 模型分词查看

这些工具可以让你直观看到文本是怎么被拆成 Token 的。

6.2 方法二:代码计算

使用 Python 进行精确计算:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 方案 1:使用 tiktoken(OpenAI 官方库)
import tiktoken

enc = tiktoken.encoding_for_model("gpt-4")
text = "我爱人工智能"
tokens = enc.encode(text)
print(f"Token 数量: {len(tokens)}")
print(f"Token 列表: {tokens}")
print(f"Token 文本: {[enc.decode([t]) for t in tokens]}")

# 方案 2:使用 transformers(通用方案)
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("gpt2")
text = "我爱人工智能"
tokens = tokenizer.encode(text)
print(f"Token 数量: {len(tokens)}")

6.3 方法三:API 返回值

调用大模型 API 时,返回结果通常包含 Token 使用量:

1
2
3
4
5
6
7
8
9
10
11
12
13
from openai import OpenAI

client = OpenAI(api_key="your-key")

response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "介绍一下人工智能"}]
)

# Token 使用量
print(f"输入 Token: {response.usage.prompt_tokens}")
print(f"输出 Token: {response.usage.completion_tokens}")
print(f"总 Token: {response.usage.total_tokens}")

6.4 方法四:经验估算(快速估算)

当你没有工具时,可以用经验公式:

语言 估算公式 示例
英文 Token ≈ 单词数 × 1.3 100 单词 ≈ 130 Token
中文 Token ≈ 字数 × 1.5-2 100 字 ≈ 150-200 Token
代码 Token ≈ 字符数 ÷ 4 400 字符 ≈ 100 Token
混合 各部分分别估算再相加 英文 + 中文 + 代码

七、Token 限制与成本

7.1 各模型的 Token 限制

模型 上下文窗口 最大输出
GPT-4o 128K Token 16K Token
GPT-4 Turbo 128K Token 4K Token
Claude 3.5 Sonnet 200K Token 8K Token
Claude Opus 4.6 200K Token 32K Token
DeepSeek V3 200K Token 8K Token

7.2 Token 与 API 成本

API 费用通常按 Token 计算:

1
2
3
4
5
6
7
8
成本 = 输入 Token × 输入单价 + 输出 Token × 输出单价

例:GPT-4o
- 输入:$2.5 / 1M Token
- 输出:$10 / 1M Token

对话消耗 1000 输入 Token + 500 输出 Token
成本 = 1000 × $2.5/1M + 500 × $10/1M = $0.0075

7.3 超出 Token 限制会怎样?

1
2
3
4
5
6
7
情况 1:输入超出上下文窗口
→ API 报错:context_length_exceeded
→ 解决:截断历史消息或分段处理

情况 2:输出超出最大输出限制
→ 输出被截断,不完整
→ 解决:设置合理的 max_tokens 或分段生成

八、实用技巧:如何节省 Token

8.1 语言选择

同样的内容,用英文表达 Token 数更少:

内容 中文 Token 英文 Token
请帮我写一篇关于人工智能的文章 约 15-20 约 8-10

技巧:如果不需要输出中文,可以用英文提问和回答。

8.2 Prompt 精简

1
2
3
4
5
❌ 冗长版本(约 50 Token):
"请帮我写一篇非常详细的、包含多个方面的、内容丰富的关于人工智能发展历史的文章,要涵盖从早期研究到现在的发展历程"

✅ 精简版本(约 15 Token):
"写一篇 AI 发展史,涵盖早期到现在的关键节点"

8.3 避免重复上下文

每次对话都会带上历史消息,Token 消耗会累积:

1
2
3
4
第 1 轮:100 Token 输入
第 2 轮:100 + 50(历史)= 150 Token 输入
第 3 轮:100 + 50 + 50 = 200 Token 输入
第 N 轮:线性增长...

技巧

  • 定期开启新对话,清除历史
  • 只保留必要的历史消息
  • 使用 System Prompt 存储固定指令

8.4 System Prompt 的妙用

System Prompt 只计算一次,不会重复:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 每条消息都重复指令(浪费 Token)
messages = [
{"role": "user", "content": "请用简洁的语言回答:什么是 AI?"},
{"role": "assistant", "content": "AI 是..."},
{"role": "user", "content": "请用简洁的语言回答:什么是机器学习?"}, # 重复了指令
]

# 使用 System Prompt(高效)
messages = [
{"role": "system", "content": "请用简洁的语言回答所有问题"}, # 只算一次
{"role": "user", "content": "什么是 AI?"},
{"role": "assistant", "content": "AI 是..."},
{"role": "user", "content": "什么是机器学习?"},
]

8.5 图片的 Token 消耗

图片也会消耗 Token,计算方式较复杂:

1
2
3
4
图片 Token ≈ (图片宽度 ÷ 512) × (图片高度 ÷ 512) × 基础 Token 数

例:1024×1024 图片
Token ≈ 2 × 2 × 85 = 340 Token(大致估算)

技巧

  • 压缩图片尺寸
  • 只传必要的图片
  • 使用低分辨率版本

九、Token 与上下文窗口的关系

9.1 上下文窗口是什么?

上下文窗口是模型能”记住”的最大 Token 数:

1
2
3
4
5
模型上下文窗口 = 128K Token

意味着:
- 输入 + 历史对话 + 输出 的总 Token 数不能超过 128K
- 超过部分会被截断或报错

9.2 为什么需要长上下文?

场景 Token 需求
简单问答 100-500 Token
代码分析 5K-20K Token
长文档总结 50K-100K Token
复杂 Agent 任务 100K-1M Token

9.3 长上下文的代价

1
2
3
4
上下文越长:
- 计算成本越高(Transformer 是 O(n²) 复杂度)
- 响应速度越慢
- API 费用越高

十、总结

10.1 Token 的核心概念

概念 说明
Token 大模型处理文本的最小单位,类似”积木块”
分词器 把文本拆成 Token 的工具,不同模型分词方式不同
词汇表 所有已知 Token 的集合,通常 5-10 万个
向量 每个 Token 的”数学身份证”,用于计算

10.2 为什么选择 Token

原因 说明
计算机只认识数字 文字必须转换成数字才能计算
有限词汇表 5 万个 Token 可以穷举和编号
无限组合能力 有限积木块拼出无限造型
处理新词 用已知 Token 组合表示未见过的词

10.3 Token 计量要点

语言 估算公式
英文 Token ≈ 单词数 × 1.3
中文 Token ≈ 字数 × 1.5-2
代码 Token ≈ 字符数 ÷ 4

10.4 实用建议

  • 用英文对话可以节省 Token
  • 精简 Prompt,避免冗长描述
  • 使用 System Prompt 存储固定指令
  • 定期清理历史对话,避免累积
  • 压缩图片尺寸减少 Token 消耗

附录:Token 可视化体验

想直观感受 Token 是怎么”切”文本的?试试这些工具:

  1. OpenAI Tokenizerhttps://platform.openai.com/tokenizer

    • 输入中英文混排的内容
    • 看看模型是怎么”切”的
    • 每个 Token 用不同颜色高亮显示
  2. Anthropic Consolehttps://console.anthropic.com

    • Claude 模型的 Token 计数
    • 支持实时估算
  3. 本地体验

    1
    2
    3
    4
    5
    import tiktoken
    enc = tiktoken.encoding_for_model("gpt-4")
    text = "你的测试文本"
    print(enc.encode(text))
    print([enc.decode([t]) for t in enc.encode(text)])

参考资源

CloudCLI UI(又名 Claude Code UI)是一款基于 Node.js + React 的 Web 应用,为 Claude Code、Cursor CLI、Codex 和 Gemini CLI 提供统一的图形化界面。与桌面应用不同,它可以通过浏览器访问,支持移动端使用,并提供云端托管选项。本文将详细介绍其功能特性、安装配置和使用方法。

阅读全文 »

Claude Code 是 Anthropic 官方的命令行 AI 编程助手,强大的功能让它成为开发者的新宠。但命令行界面对于复杂任务管理仍有局限。opcode 作为一款基于 Tauri 2 的桌面应用,为 Claude Code 提供了可视化界面,支持自定义 Agent、会话管理、成本追踪等功能,让 AI 辅助编程更加直观高效。

阅读全文 »

写在前面

说实话,2024 到 2025 这一年,AI 领域的名词简直像爆米花一样噼里啪啦往外蹦。ChatGPT、Claude、DeepSeek、Agent、MCP、Vibe Coding……身边的朋友经常一脸懵地问我:”这些到底都是啥?我该学哪个?”

这篇文章的目标很简单:帮你建立一套清晰的认知坐标系。读完之后,你不会再被各种新名词唬住,能准确判断某个新概念在整个版图里的位置,也知道该用什么工具解决自己的问题。


一、三个核心概念:LLM、Agent、Skills

理解 AI 生态,其实就抓三个东西:LLM(大脑)、Agent(行动者)、Skills(工具箱)。这三者的关系搞明白了,其他的都是在这个基础上的变体。

1. LLM——AI 的大脑,但它不是魔法

一句话理解:LLM(大语言模型)就是 AI 的”大脑”,它读了互联网上能读到的海量文本,学会了人类的语言模式和知识,能听懂你说的话,也能生成像人写的文字。

不过这里有几个坑,不得不说很多新手都会踩:

  • LLM 不是搜索引擎。搜索引擎是去库里找现成的答案,LLM 是”脑补”出最可能的回答。这意味着它可能会一本正经地胡说八道——也就是所谓的”幻觉”。
  • LLM 不联网(除非你特别配置)。它的知识有个截止日期,比如 GPT-4 的知识就到 2024 年初,问它之后的事,它是真不知道。
  • LLM 并不”理解”。它本质上是概率预测——根据前面的词,猜下一个最可能出现的词是什么。它不像人一样有真正的理解,只是模式匹配玩得溜。

模型 vs 产品的区分

这里有个很多人混淆的概念:模型产品是两回事。

  • 模型(如 GPT-4、Claude 3.5)是底层的”大脑”,提供智能能力
  • 产品(如 ChatGPT、Claude 网页版)是包装好的应用,包含界面、功能和安全限制

同一个模型可以驱动多个产品。比如 GPT-4 既驱动 ChatGPT,也驱动 Microsoft Copilot。所以别问”GPT-4 和 ChatGPT 哪个好”,这就像是问”发动机和小轿车哪个好”——根本不是一个层面的东西。

主流 LLM 怎么选

如果你现在就想试试,这几款是市面上的主力:

模型 出品方 特点 适合场景
GPT-4/GPT-4o OpenAI 通用能力强,生态完善 创意写作、通用问答
Claude 3.5/4 Anthropic 上下文长(20万token),推理严谨 长文档分析、代码审查
DeepSeek-V3/R1 深度求索 开源、性价比高、数学强 技术研究、预算敏感场景
Gemini 1.5/2.0 Google 多模态原生,谷歌生态 多媒体处理
Qwen2.5 阿里巴巴 中文优化,开源友好 中文场景

我的建议:普通用户从 ChatGPT 或 Claude 开始,想省钱或玩技术的试试 DeepSeek,中文场景多的选 Kimi 或 Qwen。

2. Agent——不只会聊天,还能动手干活

如果你只用过 ChatGPT 网页版,那你接触的还是”纯对话”模式。但 Agent 不一样,它是能自主规划、使用工具、完成任务的 AI 系统。

打个比方

  • LLM 是”会聊天的百科全书”——你问它答,但它不动手
  • Agent 是”能动手解决问题的智能助手”——你说”帮我订一张明天去上海的机票”,它能自己去查航班、比价、填信息、完成预订

Agent 和纯对话 LLM 的核心区别:

能力 纯对话 LLM Agent 系统
交互方式 一问一答 自主多轮执行
工具使用 依赖产品是否开放 原生设计为调用外部工具
任务完成 给建议、生成内容 实际执行操作并交付结果
记忆能力 单轮或有限轮对话 长期记忆、状态跟踪、跨会话

Agent 是怎么干活的

Agent 的工作流程通常叫 ReAct 范式(Reasoning + Acting):

1
2
3
观察环境 → 理解目标 → 推理思考 → 选择工具 → 执行操作 → 观察结果 → 迭代直到完成
▲ │
└──────────────────────────────────────────────────────────────────┘

它会循环执行这个过程,直到任务完成或达到终止条件。比如你要 Agent”分析一下这份财报并生成图表”,它可能会:

  1. 读取文件(调用文件操作 Skill)
  2. 分析数据(调用代码执行 Skill 跑 Python)
  3. 生成图表(调用可视化工具)
  4. 检查输出,如果不对就调整重试

Agent 产品有哪些

产品 类型 核心能力
Claude Code 编程 Agent 直接操作代码库,批量重构、调试
Manus 通用 Agent 端到端任务自动化,可操作用户界面
AutoGPT 实验性 Agent 自主分解任务、循环执行

注意:Cursor 和 GitHub Copilot 很多人以为是 Agent,其实它们更像是”增强型编辑器”——主要帮你写代码,而不是自主执行任务。真正的 Agent 像 Claude Code,能独立规划和执行多步骤任务。

3. Skills——Agent 的手和脚

Skills 是 Agent 能调用的具体能力,没有 Skills,Agent 就是”光说不练”。

常见的 Skills 包括:

  • 📁 文件操作(读/写/搜索本地文件)
  • 🔍 网络搜索(获取实时信息)
  • 💻 代码执行(运行 Python、Bash 等)
  • 🗄️ 数据库查询(SQL 操作)
  • 📧 消息发送(邮件、IM 通知)

二、市面上的 AI 产品怎么分类

现在你已经搞懂了 LLM、Agent、Skills 三层架构,接下来看看市面上的产品都落在哪个象限。

1. 对话产品(包装好的 LLM)

这些产品本质上是”给 LLM 套了个壳”,主要提供对话界面:

产品 底层模型 核心特点
ChatGPT GPT-4o/o3 最知名,生态丰富,插件多
Claude Claude 3.5/4 上下文长(20万token),推理严谨
Kimi Moonshot 自研 超长上下文(200万字),适合读长文档
DeepSeek DeepSeek-V3/R1 开源透明,数学推理强,价格低

上下文的坑:很多人不知道”上下文长度”是什么意思。简单说,就是 AI 能”记住”多少内容。Kimi 的 200 万字 ≈ 几十本书,Claude 的 20 万 token ≈ 30 万汉字。如果你要读一篇很长的论文或合同,必须选支持大上下文的模型,否则它读到后面就忘了前面说什么。

2. AI 编程助手(程序员的武器库)

产品 定位 适合场景
Cursor AI IDE 日常开发,代码生成、解释、重构
GitHub Copilot 代码补全 实时代码建议,提升编码效率
Claude Code 编程 Agent 复杂任务,批量重构,多文件操作

选型建议:日常写代码用 Cursor 或 Copilot 就够了;要做大规模代码重构、理解整个项目架构,Claude Code 更猛。

3. 内容生成工具(特定领域的 AI)

产品 类型 特点
Midjourney 图像生成 艺术风格最强,需 Discord 使用
DALL·E 3 图像生成 与 ChatGPT 集成,使用方便
Sora 视频生成 OpenAI 出品,目前仅对特定用户开放
Nano Banana 图文处理 Gemini 生态,支持图文混合任务

注意:Nano Banana 是 Google 实验性工具,功能可能迭代更新。


三、MCP 和 Vibe Coding:两个值得关注的趋势

1. MCP——AI 的 USB-C 接口

MCP(Model Context Protocol)是 Anthropic 在 2024 年 11 月推出的开放协议,旨在标准化 AI 与外部数据源的连接方式。

一句话理解:MCP 是 AI 世界的”USB-C 标准”。以前每个 AI 连数据库都要单独开发适配器,现在只要实现一次 MCP,所有支持 MCP 的 AI 都能用。

MCP 的三层架构:

  • MCP 主机 (Host):运行 AI 的程序(如 Claude Code)
  • MCP 客户端 (Client):维持与服务器连接的组件
  • MCP 服务器 (Server):提供具体能力的服务(如文件系统、GitHub、数据库)
1
2
3
4
5
6
7
8
9
10
11
12
┌─────────────────────────────────────────────────────────┐
│ MCP 架构示意 │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌──────────┐ ┌───────────┐ │
│ │ MCP Host │──────► MCP Client │────► MCP Server │ │
│ │ (Claude Code)│ │(连接管理)│ │ (文件系统) │ │
│ └─────────────┘ └──────────┘ └───────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ [LLM] 标准化协议 具体工具 │
└─────────────────────────────────────────────────────────┘

为什么说它重要:MCP 让 AI 能方便地”伸手”到你的文件、数据库、GitHub、Slack 等各种数据源,是 Agent 能力的核心基础设施。目前已有文件系统、GitHub、PostgreSQL 等官方 MCP Server。

2. Vibe Coding——自然语言编程的新范式

Vibe Coding 是由前特斯拉 AI 总监 Andrej Karpathy 在 2025 年初提出的概念,指用自然语言描述需求,由 AI 自动生成代码的开发方式。

核心理念的转变

  • 从”写代码”转向”描述需求”
  • 从”语法细节”转向”意图表达”
  • 从”手工实现”转向”审查和迭代”

实际场景:你说”帮我做一个待办事项网页,可以添加任务、标记完成、删除,要简洁美观”,AI 直接生成完整的 HTML/CSS/JavaScript 代码,你只需要审查和微调。

但不得不说,它也有局限

  • 适合原型开发、简单应用、脚本任务
  • 复杂系统架构仍需专业开发者把控
  • 对”描述清楚需求”的能力要求反而更高——说不明白,AI 也猜不透

四、概念关系全景图

把上面的内容串起来,整个 AI 生态的层次是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
                    ┌─────────────────────────────────────┐
│ AI 生态全景 │
└─────────────────────────────────────┘

┌─────────────────────────┼─────────────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ LLM │ │ Agent │ │ Skills │
│ (大脑) │◄────────►│ (行动者) │◄────────►│ (工具) │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ MCP 协议层 │ │
│ │ (标准化连接) │ │
│ └────────┬─────────┘ │
│ │ │
┌───────┴───────┐ ┌────────┴────────┐ ┌────────┴────────┐
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│GPT-4 │ │Claude│ │Claude│ │OpenCl│ │文件系│ │搜索 │
│系列 │ │系列 │ │ Code │ │aw │ │统 │ │引擎 │
└──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│ChatGPT │ │Claude │ │Cursor │ │本地任务│ │代码执行│ │联网搜索│
│网页版 │ │网页版 │ │IDE插件 │ │自动化 │ │文件读写│ │API调用 │
└────────┘ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘

记住这个核心逻辑:LLM 提供智能基础 → Agent 赋予行动能力 → Skills 提供工具支持 → MCP 标准化连接方式。


五、选型指南——我该用什么?

按使用场景选

你的需求 推荐工具 原因
日常问答、灵感收集 ChatGPT / Claude 通用性强,易用
读论文/长文档/法律文件 Kimi / Claude Kimi 200万字上下文,Claude 20万token
写代码、审查代码 Claude Code / Cursor 代码理解和操作能力强
画插画、设计图 Midjourney / DALL·E 3 Midjourney 艺术风格佳,DALL·E 集成方便
做视频内容 Runway / Pika / Sora(开放后) Sora 暂未全面开放
处理敏感数据 本地模型 + OpenClaw 数据不出本机,隐私可控
数学/逻辑推理 DeepSeek-R1 / Claude / o3 DeepSeek-R1 开源且推理强
自动化办公任务 Manus / AutoGPT 端到端任务自动化

按技术接受度选

用户类型 推荐起点 进阶方向
完全小白 ChatGPT 网页版 Claude、Kimi
办公族 Kimi 读文档 + ChatGPT 写作 学习 Prompt 工程
创作者 Midjourney + Claude 学习 AI 工作流
程序员 Cursor / Claude Code MCP + Agent 开发
极客玩家 本地模型 + OpenClaw 自建 AI 工作流

六、避坑指南——这些误区你得知道

常见误区

误区 真相
AI 什么都知道 LLM 有知识截止日期,不联网时无法获取新信息
AI 不会犯错 会产生”幻觉”,一本正经地生成错误信息
AI 有真正的理解 基于概率的模式匹配,不是真正的”理解”
越贵的模型越好 简单任务用小模型更快更便宜(如 GPT-4o-mini)
AI 要取代人类了 当前是”增强人类”阶段,替代的是重复性工作
提示词越复杂越好 关键是清晰表达需求,不是堆砌辞藻

使用建议

  1. 交叉验证:重要信息用多个 AI 或搜索引擎验证,别盲信单一来源
  2. 提供上下文:给 AI 足够的背景信息,结果更准确(Garbage In, Garbage Out)
  3. 迭代优化:第一次不满意?继续追问、细化需求
  4. 了解边界:创意、整理、初稿适合 AI;关键决策、医疗法律建议不适合
  5. 保存记录:AI 输出可能变化,重要内容要保存

附录:术语速查表

术语 定义
Token LLM 处理文本的基本单位,1 token ≈ 0.75 个英文单词
上下文长度 AI 能”记住”的文本范围
微调 (Fine-tuning) 在基础模型上用特定数据进一步训练
RAG 检索增强生成,让 AI 基于知识库回答问题
Prompt 给 AI 的输入指令
多模态 能同时处理文本、图像、音频、视频
幻觉 AI 生成看似合理但实际错误的内容
推理模型 专门优化推理的模型(如 o1、o3、DeepSeek-R1)
Function Calling LLM 调用外部函数/API 的能力

总结

说了这么多,核心观点就三个:

  1. 没有”最好”的 AI,只有”最适合”的 AI。选工具要看场景,不是越贵越好。
  2. 模型是大脑,产品是包装,Agent 是系统。搞清楚这三层,新名词来了你也能归类。
  3. AI 是增强人类的工具,不是替代人类的魔法。它会犯错,有边界,需要人的判断。

如果你看完还是不知道从何下手,不妨这样:先花 30 分钟注册个 ChatGPT 或 Kimi 账号,实际提几个问题,比看十篇文章都有用。用着用着,你就知道自己需要什么了。


参考资料

写在前面

向量数据库的核心问题只有一个:给定一个查询向量,如何快速找出数据库中最相似的 K 个向量?

这个问题看似简单,实则涉及数学、算法、工程三个层面。数学层面是相似度度量,算法层面是近似最近邻搜索(ANN),工程层面是索引结构与存储优化。

这篇文章从研究角度切入,深入剖析相似度计算的数学原理和核心算法,不谈产品选型,只谈技术本质。


一、相似度度量:三种主流方法

1. 余弦相似度(Cosine Similarity)

定义:两个向量夹角的余弦值。

特点

  • 值域 [-1, 1],1 表示方向完全相同,-1 表示方向相反
  • 只关注方向,忽略向量长度(magnitude)
  • 对向量长度不敏感,适合文本语义相似度

为什么文本向量用余弦:Embedding 模型输出的向量长度(norm)本身就蕴含信息,但语义相似度主要看方向。两篇文章讨论同一话题,即使篇幅不同(向量长度不同),方向应该相近。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np

def cosine_similarity(a, b):
"""余弦相似度计算"""
dot_product = np.dot(a, b)
norm_a = np.linalg.norm(a)
norm_b = np.linalg.norm(b)
return dot_product / (norm_a * norm_b)

# 示例
a = np.array([1, 2, 3])
b = np.array([2, 4, 6]) # b = 2a,方向完全相同

print(cosine_similarity(a, b)) # 输出 1.0

计算复杂度:O(d),d 为向量维度。

2. 欧氏距离(Euclidean Distance)

定义:两个向量在欧氏空间中的直线距离。

特点

  • 值域 [0, ∞),越小越相似
  • 同时考虑方向和长度
  • 适合图像特征、物理坐标等绝对距离有意义的场景

与余弦的关系:对归一化向量,欧氏距离和余弦相似度有单调关系:

证明:设 $\vec{A}$ 和 $\vec{B}$ 均归一化($|\vec{A}| = |\vec{B}| = 1$),则:

结论:如果向量已归一化,用 L2 或余弦结果一致。

1
2
3
4
5
6
7
8
9
10
11
12
def euclidean_distance(a, b):
"""欧氏距离计算"""
return np.sqrt(np.sum((a - b) ** 2))

# 归一化后与余弦的关系
a_norm = a / np.linalg.norm(a)
b_norm = b / np.linalg.norm(b)

d = euclidean_distance(a_norm, b_norm)
cos = cosine_similarity(a_norm, b_norm)

print(np.sqrt(2 * (1 - cos))) # 与 d 相等

3. 内积(Inner Product / Dot Product)

定义:两个向量对应分量乘积之和。

特点

  • 值域取决于向量,无固定范围
  • 计算最快,无需计算 norm
  • 要求向量归一化,否则结果不可比

为什么内积最快:省去了 norm 计算(两遍向量遍历),只需一遍遍历。在大规模检索中,这个差异很显著。

1
2
3
4
5
6
7
8
9
def dot_product(a, b):
"""内积计算"""
return np.dot(a, b)

# 归一化向量:内积 = 余弦相似度
a_norm = a / np.linalg.norm(a)
b_norm = b / np.linalg.norm(b)

print(dot_product(a_norm, b_norm)) # 与 cosine_similarity 相等

4. 三种度量对比

度量方法 公式复杂度 值域 计算速度 适用场景
余弦相似度 O(d) + norm [-1, 1] 中等 文本语义、方向敏感
欧氏距离 O(d) [0, ∞) 中等 图像特征、物理位置
内积 O(d) 不固定 最快 归一化向量、追求速度

工程选择

  • 文本向量默认归一化 → 内积或余弦,推荐内积(快)
  • 未归一化向量 → 余弦或 L2
  • 物理坐标、图像特征 → L2

二、精确搜索 vs 近似搜索

1. 暴力搜索(FLAT)

遍历所有向量,逐一计算相似度,排序取 Top-K。

1
2
3
4
5
6
7
def brute_force_search(query, database, k=10):
"""暴力搜索"""
# 计算所有相似度
similarities = [cosine_similarity(query, vec) for vec in database]
# 排序取 Top-K
indices = np.argsort(similarities)[-k:]
return indices, [similarities[i] for i in indices]

复杂度分析

  • 时间:O(N × d),N 为向量数,d 为维度
  • 空间:O(1),无需额外索引

问题:N 达到百万级时,单次查询耗时秒级,无法满足实时需求。

2. 维度灾难(Curse of Dimensionality)

高维空间的几何特性与低维截然不同:

维度 特性
2D/3D 距离有意义,近邻真的”近”
高维(>100) 所有向量距离趋于均匀,近邻与远邻差距缩小

定量分析:在 d 维超立方体中,随机两点距离的方差:

随着 d 增加,距离分布趋于集中,”最近”和”最远”的区分度下降。

结论:高维空间中,精确找到最近邻代价极高,但”足够近”的近似最近邻(ANN)足够好——这是 ANN 算法的理论基础。


三、ANN 算法:核心思想与分类

ANN(Approximate Nearest Neighbor)牺牲少量精度换取大幅提升的速度。核心思想:构建索引结构,搜索时只考察部分候选,而非全量遍历

算法分类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ANN 算法家族
├── 基于树(Tree-based)
│ ├── KD-Tree:低维有效,高维失效
│ ├── Ball Tree:球形划分,中等维度
│ └── Annoy(Spotify):多棵随机投影树

├── 基于图(Graph-based)
│ ├── NSW:可导航小世界图
│ ├── HNSW:分层 NSW,当前最优
│ └── NGT/ONNG:日本 Yahoo 开源

├── 基于量化(Quantization-based)
│ ├── PQ:乘积量化,压缩向量
│ ├── OPQ:优化乘积量化
│ └── ScaNN:Google 开源,量化+重排

├── 基于哈希(Hash-based)
│ ├── LSH:局部敏感哈希
│ └── Multi-probe LSH:改进版

└── 基于聚类(Clustering-based)
├── IVF:倒排文件索引
└── IVF-PQ:倒排+量化组合

四、HNSW:当前最优的图索引算法

1. 核心思想

HNSW(Hierarchical Navigable Small World)由 Malkov 等人在 2016 年提出,是当前最主流的 ANN 算法。

灵感来源:跳表(Skip List)。跳表通过多层索引实现 O(log N) 查找,HNSW 将这个思想移植到图结构。

结构设计

  • 多层图,上层稀疏,下层密集
  • 搜索从顶层开始,逐层向下逼近
  • 每层内节点通过边连接,边代表”邻居关系”
1
2
3
4
5
6
7
8
9
10
11
层级结构示意:

Layer 2 (最高层,概率 p²): ●───────●
│ │
Layer 1 (概率 p¹): ●───●───●───●
│ │ │ │
Layer 0 (全量节点): ●─●─●─●─●─●─●─●─●─●─●
(每个节点都在 Layer 0)

节点进入高层概率:p^l = 1 / (ln(M) × M^(level))
高层节点数 ≈ N / (ln M × M^level)

2. 构建算法

1
2
3
4
5
6
7
8
9
10
算法:INSERT(element, hnsw)
输入:新元素 q,HNSW 图
输出:更新后的 HNSW 图

1. 确定插入层数 l = floor(-ln(uniform(0,1)) × mL)
2. 从顶层 entry point 开始,贪心搜索到 l 层的入口
3. 从 l 层向下到 0 层,每层:
a. 在当前层搜索 efConstruction 个最近邻候选
b. 从候选中选择 M 个最近邻连接
c. 处理连接边:保持每节点最大 M 条边

关键参数

  • M:每节点最大连接数(默认 16)
  • efConstruction:构建时搜索宽度(默认 200)
  • mL:层数乘数,通常取 $1/\ln M$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# HNSW 构建伪代码
def insert(q, hnsw, M=16, ef_construction=200, mL=1/np.log(16)):
# 1. 确定插入层数
level = int(-np.log(np.random.random()) * mL)

# 2. 从顶层搜索到 level 层的入口
entry = hnsw.entry_point
for l in range(hnsw.max_level, level + 1):
entry = greedy_search(q, entry, ef=1, layer=l)

# 3. 从 level 层向下插入
for l in range(level, -1, -1):
candidates = search_layer(q, entry, ef_construction, l)
neighbors = select_neighbors(q, candidates, M)
connect(q, neighbors, l)

3. 搜索算法

1
2
3
4
5
6
7
8
9
算法:SEARCH(query, hnsw, ef, K)
输入:查询向量 q,HNSW 图,搜索宽度 ef,返回数量 K
输出:K 个最近邻

1. 从顶层 entry point 开始
2. 逐层向下贪心搜索:
- 在当前层找最近的节点作为下一层入口
3. 到达 Layer 0 后,搜索 ef 个候选
4. 从候选中取 Top-K 返回
1
2
3
4
5
6
7
8
9
10
11
12
def search(q, hnsw, ef=50, k=10):
entry = hnsw.entry_point

# 从顶层贪心向下
for l in range(hnsw.max_level, 0):
entry = greedy_search_layer(q, entry, ef=1, layer=l)

# Layer 0:扩展搜索
candidates = search_layer(q, entry, ef, layer=0)

# 返回 Top-K
return sorted(candidates, key=lambda x: x.distance)[:k]

4. 参数调优指南

参数 影响 调优建议
M ↑ 精度↑,内存↑,构建时间↑ 16-32 是平衡点
efConstruction ↑ 构建质量↑,构建时间↑ 200-400 足够
ef ↑ 召回率↑,查询延迟↑ 动态调整:在线查询用 50-100

召回率与延迟权衡

1
2
3
4
5
6
ef 值      召回率      延迟
─────────────────────────────
10 70% 1ms
50 95% 5ms
100 98% 10ms
200 99.5% 20ms

五、IVF:倒排文件索引

1. 核心思想

聚类 + 倒排:将向量空间划分为多个区域(cluster),每个区域维护一个倒排列表。

搜索流程

  1. 找出查询向量最近的几个聚类中心
  2. 只在这些聚类内搜索,而非全量遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
IVF 结构示意:

向量空间划分:
┌──────────────────────────────┐
│ ┌─────┐ ┌─────┐ │
│ │ C1 │ │ C2 │ ┌───┐ │
│ │ ●●● │ │ ●● │ │C3 │ │
│ │ ●● │ │ ● │ │ ● │ │
│ └─────┘ └─────┘ └───┘ │
└──────────────────────────────┘

倒排列表:
C1 → [vec1, vec5, vec8, vec12, ...]
C2 → [vec3, vec7, vec11, ...]
C3 → [vec2, vec4, vec6, ...]

2. 算法流程

1
2
3
4
5
6
7
8
9
构建阶段:
1. 对全量向量做 K-means 聚类,得到 nlist 个聚类中心
2. 每个向量分配到最近的聚类中心
3. 每个聚类维护一个倒排列表

搜索阶段:
1. 找出查询向量最近的 nprobe 个聚类中心
2. 只在这些聚类内做 FLAT 搜索
3. 合并结果,返回 Top-K

关键参数

  • nlist:聚类数量(通常取 $\sqrt{N}$)
  • nprobe:搜索时探查的聚类数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# IVF 构建伪代码
def build_ivf(vectors, nlist=1024):
# K-means 聚类
centroids = kmeans(vectors, nlist)

# 分配向量到聚类
clusters = {i: [] for i in range(nlist)}
for vec in vectors:
nearest = argmin(distance(vec, centroids))
clusters[nearest].append(vec)

return centroids, clusters

# IVF 搜索伪代码
def search_ivf(query, centroids, clusters, nprobe=10, k=10):
# 找最近的 nprobe 个聚类
nearest_clusters = argsort(distance(query, centroids))[:nprobe]

# 在这些聚类内搜索
candidates = []
for c in nearest_clusters:
for vec in clusters[c]:
candidates.append((vec, distance(query, vec)))

# 返回 Top-K
return sorted(candidates, key=lambda x: x[1])[:k]

3. 性能分析

参数 影响
nlist ↑ 聚类更精细,单聚类内向量更少,搜索更快
nprobe ↑ 搜索更多聚类,召回率↑,延迟↑

召回率与 nprobe 关系

1
2
3
4
5
6
nprobe/nlist    召回率
────────────────────────
1% 60-70%
5% 85-90%
10% 92-96%
20% 95-98%

六、PQ:乘积量化压缩

1. 问题背景

高维向量存储和计算成本高。1536 维向量,100万个需要 6GB 内存。如何压缩?

2. 核心思想

将高维向量切分成多个低维子向量,每个子空间独立量化。

1
2
3
4
5
6
7
8
9
10
11
PQ 量化过程:

原始向量:[v1, v2, v3, v4, v5, v6, v7, v8] (8维)
↓ 切分为 4 个子向量(每个2维)
子向量: [v1,v2] [v3,v4] [v5,v6] [v7,v8]
↓ 每个子空间独立聚类量化
量化码: [P1=3] [P2=7] [P3=1] [P4=5]
↓ 存储为码本索引
存储: [3, 7, 1, 5] (4字节,压缩率 50%)

码本:每个子空间 256 个中心点(8bit索引)

数学表示

设向量 $\vec{x} \in \mathbb{R}^d$,切分为 $m$ 个子向量:

每个子空间有 $K^$ 个中心点(通常 $K^ = 256$),量化函数:

压缩后向量表示为 $[q^1, q^2, …, q^m]$,共 $m$ 字节。

3. 距离计算:ADC(Asymmetric Distance Computation)

关键洞察:查询向量不压缩,只压缩数据库向量。预先计算查询向量与码本中心的距离表。

1
2
3
4
5
6
7
8
9
10
11
12
def pq_distance(query, pq_code, codebooks, m=8):
"""PQ 距离计算"""
# 1. 预计算距离表
# distance_table[i][k] = distance(query的第i段, 第i个码本的第k个中心)
distance_table = precompute_distance_table(query, codebooks, m)

# 2. 查表累加
d = 0
for i in range(m):
d += distance_table[i][pq_code[i]]

return d

复杂度分析

  • 距离表构建:$O(m \times K^ \times d/m) = O(d \times K^)$
  • 单向量距离查表:$O(m)$

相比原始距离计算 $O(d)$,PQ 距离查表 $O(m)$ 快得多($m \ll d$)。

4. 压缩率计算

1
2
3
4
5
6
7
8
原始存储:d × 4 字节(float32)
PQ 存储:m 字节(m 个 uint8 码)

压缩率:d × 4 / m = 4d/m

示例:d=1536, m=48
压缩率 = 1536 × 4 / 48 = 128 倍
100万向量:6GB → 48MB

七、IVF-PQ:组合优化

将 IVF 和 PQ 组合,兼顾速度和内存:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
IVF-PQ 结构:

┌────────────────────────────────────────────┐
│ IVF 聚类层 │
│ C1 C2 C3 C4 ... Cnlist │
├────────────────────────────────────────────┤
│ PQ 量化层 │
│ 每个聚类内向量用 PQ 压缩存储 │
│ C1 → [pq_code1, pq_code2, ...] │
└────────────────────────────────────────────┘

搜索流程:
1. 找最近的 nprobe 个聚类中心(FLAT)
2. 在这些聚类内用 PQ 查表计算距离
3. 可选:重排(rerank)Top-K 用原始向量精确计算

重排策略:PQ 计算的是近似距离,对 Top-K 候选用原始向量重新计算精确距离。

1
2
3
4
5
6
7
8
9
10
11
12
def search_ivf_pq(query, nprobe=10, k=10, rerank=True):
# 1. 找聚类
nearest_clusters = find_nearest_clusters(query, nprobe)

# 2. PQ 查表搜索
candidates = pq_search(query, nearest_clusters, k * rerank_factor)

# 3. 重排(可选)
if rerank:
candidates = rerank_with_original_vectors(query, candidates, k)

return candidates[:k]

八、算法性能对比

1. 理论复杂度

算法 构建复杂度 搜索复杂度 空间复杂度
FLAT O(1) O(Nd) O(Nd)
IVF O(Ndnlist) O(nprobe × Nd/nlist) O(Nd)
HNSW O(Nd × efConstruction × logN) O(d × ef × logN) O(Nd × M)
PQ O(Nd × K^*) O(dK^* + Nm) O(Nm)
IVF-PQ O(Nd × nlist × K^*) O(nprobe × (dK^* + N/nlist × m)) O(Nm)

2. 实测性能(SIFT-1M 数据集)

算法 召回率@10 QPS 内存
FLAT 100% 200 512MB
IVF (nlist=1024, nprobe=64) 95% 8000 512MB
HNSW (M=16, ef=64) 96% 15000 700MB
PQ (m=8) 85% 30000 16MB
IVF-PQ (nlist=1024, m=8) 90% 20000 16MB

九、研究前沿与新算法

1. ScaNN(Google,2020)

创新点:量化 + 内积优化 + 重排

  • 量化时考虑内积最大化的方向
  • 用 SIMD 加速距离表计算
  • 比 HNSW 在内积度量上更快

2. DiskANN(Microsoft,2019)

创新点:磁盘索引 + SSD 优化

  • 向量和索引存储在 SSD,内存只放聚类中心
  • 利用 SSD 高并发读取特性
  • 支持 10 亿级向量,内存需求 < 16GB

3. Faiss(Facebook,2017)

工业界最成熟的开源库:

  • GPU 加速(10倍提速)
  • 支持 IVF、PQ、HNSW 等多种索引
  • 灵活的组合索引(IVF-PQ, IVF-HNSW)

十、工程实践要点

1. 索引选择决策

1
2
3
4
5
6
7
8
数据规模 < 10万:FLAT(精确搜索)
数据规模 10万-100万:
- 内存充足 → HNSW(最快)
- 内存紧张 → IVF-PQ(压缩)
数据规模 > 100万:
- 内存充足 → HNSW
- 内存紧张 → IVF-PQ
- 超大规模 → DiskANN

2. 参数调优经验

目标 参数调整
提高召回率 HNSW: ef↑ / IVF: nprobe↑
降低延迟 HNSW: M↓, ef↓ / IVF: nlist↑, nprobe↓
降低内存 使用 PQ 压缩
加速构建 HNSW: efConstruction↓

3. 常见陷阱

问题 解决方案
召回率不够 ef/nprobe 调高;检查向量质量
延迟太高 减少候选数量;检查是否做了不必要的重排
内存爆炸 使用 PQ 压缩;检查索引参数 M
构建太慢 efConstruction 适度降低;分批构建

总结

向量相似度计算的核心要点:

  1. 度量选择:归一化向量用内积(最快),文本用余弦,物理坐标用 L2
  2. 算法选择:小数据 FLAT,大数据 HNSW 或 IVF-PQ
  3. 参数调优:ef/nprobe 控制召回率,M/nlist 控制内存
  4. 压缩策略:PQ 压缩率可达 100 倍,代价是精度下降 5-10%

数学是本质,算法是手段,工程是落地。理解原理,才能在选型和调优时做出正确决策。