0%

一、前言:为什么需要这个工具?

你有没有遇到过这样的场景:

  • 想让 AI 帮你调试网页,但它只能”纸上谈兵”,给建议却不能动手
  • 需要自动化测试网页功能,写脚本太麻烦
  • 想分析网页性能瓶颈,但看不懂 DevTools 里的各种指标
  • 希望让 AI 帮你截取网页截图、提取页面内容

Chrome DevTools MCP 就是解决这些问题的神器。它让 AI 助手(如 Claude Code、Cursor、Copilot)能够直接操控浏览器,像一个真正的开发者一样干活。


二、核心概念:MCP 是什么?

2.1 MCP 协议简介

MCP(Model Context Protocol) 是 Anthropic 在 2024 年底提出的一个开放协议。简单理解,它是 AI 助手与外部工具之间的”通用插座”。

打个比方:

  • 没有 MCP 时,AI 像是”被困在盒子里的聪明人”——只能聊天,不能动手
    -有了 MCP,AI 像是”长了手脚的助手”——能连接数据库、操控浏览器、读写文件

2.2 MCP 的架构

1
2
3
4
5
6
7
8
9
10
┌─────────────┐     MCP 协议     ┌─────────────────┐
│ AI 助手 │◄──────────────►│ MCP Server │
│ (Claude等) │ │ (工具提供者) │
└─────────────┘ └─────────────────┘


┌─────────────────┐
│ 外部资源 │
│ (浏览器/数据库等)│
└─────────────────┘

MCP Server 是关键组件,它:

  1. 暴露工具(Tools)给 AI 调用
  2. 提供资源(Resources)供 AI 读取
  3. 发送提示(Prompts)引导 AI 使用

2.3 Chrome DevTools MCP 的定位

chrome-devtools-mcp 是官方提供的 MCP 服务器,它把 Chrome 浏览器的 DevTools 能力 暴露给 AI 助手。

这意味着 AI 可以:

  • 打开网页、点击按钮、填写表单
  • 查看控制台日志、网络请求
  • 截图、分析性能
  • 提取 DOM 元素、调试 JavaScript

三、核心功能一览

3.1 主要能力分类

类别 功能 典型用途
浏览器控制 打开页面、导航、刷新、关闭 自动化浏览
页面交互 点击、输入文本、滚动、等待 自动化测试
调试分析 控制台日志、网络请求、错误追踪 问题排查
性能分析 录制性能追踪、分析加载时间 性能优化
视觉捕获 截图、获取元素坐标 文档记录
DOM 操作 获取元素、查询选择器 内容提取

3.2 Slim 模式 vs 完整模式

Chrome DevTools MCP 提供两种运行模式:

模式 工具数量 适用场景 启动参数
Slim 模式 约 10 个 基础浏览任务 --slim --headless
完整模式 约 30+ 个 调试、性能分析 默认

新手建议先用完整模式,熟悉后再根据需求切换。


四、安装配置:Claude Code 实战

4.1 环境要求

在开始之前,请确保你有:

要求 版本 检查方法
Node.js v20.19+ node -v
npm 最新版 npm -v
Chrome 最新稳定版 浏览器设置查看
Claude Code 最新版 claude --version

4.2 方法一:CLI 快速安装(推荐)

打开终端,执行一行命令:

1
claude mcp add chrome-devtools --scope user npx chrome-devtools-mcp@latest

这会自动添加到你的用户级配置中。

4.3 方法二:手动配置

如果你想手动配置,找到 Claude Code 的配置文件:

Windows:

1
C:\Users\<你的用户名>\.claude\settings.json

Mac/Linux:

1
~/.claude/settings.json

mcpServers 部分添加:

1
2
3
4
5
6
7
8
{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": ["-y", "chrome-devtools-mcp@latest"]
}
}
}

4.4 配置参数详解

你可以通过参数定制行为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": [
"-y",
"chrome-devtools-mcp@latest",
"--headless", // 无头模式(不显示浏览器窗口)
"--slim", // 精简模式(减少工具数量)
"--no-performance-crux" // 禁用 CrUX 数据收集
]
}
}
}

常用参数说明:

参数 作用 建议场景
--headless 无界面运行 CI/CD、自动化脚本
--slim 只加载基础工具 简单浏览任务
--no-usage-statistics 禁用使用统计 隐私敏感场景
--browser-url=... 连接已有浏览器 调试特定实例

4.5 验证安装

重启 Claude Code 后,输入以下命令验证:

1
2
3
4
5
# 查看已安装的 MCP 服务器
claude mcp list

# 查看 MCP 服务器详情
claude mcp get chrome-devtools

如果看到 chrome-devtools 在列表中,说明安装成功!


五、使用实战:从零开始

5.1 基础操作示例

安装成功后,你可以直接在 Claude Code 中用自然语言操控浏览器。

示例 1:打开网页并截图

1
请打开 https://example.com,然后截取整个页面的截图

AI 会自动调用 MCP 工具:

  1. browser_navigate - 打开网页
  2. browser_screenshot - 截取屏幕

示例 2:提取页面内容

1
打开 https://news.ycombinator.com,获取首页所有新闻标题

AI 会:

  1. 打开 Hacker News
  2. 用 DOM 选择器提取标题元素
  3. 返回标题列表

示例 3:自动化表单填写

1
打开 https://example.com/login,填写用户名 "test@example.com",密码 "password123",然后点击登录按钮

5.2 调试实战

示例 4:检查控制台错误

1
打开我的项目 http://localhost:3000,检查是否有控制台错误

AI 会查看 console 日志,找出红色错误信息并分析原因。

示例 5:分析网络请求

1
打开 https://myapi.example.com,查看所有 API 请求的响应时间

AI 会:

  1. 捕获网络请求
  2. 分析每个请求的耗时
  3. 找出慢请求并给出优化建议

5.3 性能分析实战

示例 6:页面性能诊断

1
分析 https://mysite.com 的加载性能,找出瓶颈

AI 会:

  1. 录制性能追踪(Performance Trace)
  2. 分析关键指标(FCP、LCP、CLS)
  3. 给出具体优化建议

关键性能指标解释:

指标 全称 含义 理想值
FCP First Contentful Paint 首次内容绘制 < 1.8s
LCP Largest Contentful Paint 最大内容绘制 < 2.5s
CLS Cumulative Layout Shift 累积布局偏移 < 0.1
TTI Time to Interactive 可交互时间 < 3.8s

六、进阶技巧

6.1 连接已有的浏览器实例

如果你已经在调试某个页面,可以让 MCP 连接到现有浏览器:

步骤 1:以调试模式启动 Chrome

Windows:

1
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222

Mac:

1
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222

步骤 2:修改 MCP 配置

1
2
3
4
5
6
7
8
9
10
11
12
{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": [
"-y",
"chrome-devtools-mcp@latest",
"--browser-url=http://127.0.0.1:9222"
]
}
}
}

这样 MCP 会连接到你已有的浏览器,而不是启动新实例。

6.2 禁用数据收集(隐私考量)

Chrome DevTools MCP 默认会收集使用统计数据。如果你在意隐私:

1
"args": ["-y", "chrome-devtools-mcp@latest", "--no-usage-statistics"]

或设置环境变量:

1
export CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS=1

6.3 在 CI/CD 中使用

自动化测试场景建议配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": [
"-y",
"chrome-devtools-mcp@latest",
"--headless",
"--no-usage-statistics"
],
"env": {
"CI": "true"
}
}
}
}

七、常见问题排查

7.1 MCP 服务器启动失败

症状: Claude Code 提示 “Failed to start MCP server”

排查步骤:

  1. 检查 Node.js 版本:

    1
    node -v  # 需要 v20.19+
  2. 手动测试 MCP 服务器:

    1
    npx chrome-devtools-mcp@latest
  3. 检查网络连接(npx 需要下载包)

7.2 浏览器连接失败

症状: 提示 “Cannot connect to browser”

解决方案:

  1. 确保 Chrome 已安装且是最新版
  2. 如果使用 --browser-url,确保 Chrome 以调试模式启动
  3. 检查端口是否被占用:
    1
    2
    3
    4
    5
    # Windows
    netstat -ano | findstr 9222

    # Mac/Linux
    lsof -i :9222

7.3 工具调用超时

症状: 操作网页时长时间无响应

可能原因:

  • 页面加载缓慢
  • 网络问题
  • 复杂页面导致操作卡住

建议:

  • 使用 --headless 模式减少资源占用
  • 给 AI 明确的等待指令:”等待页面完全加载后再…”
  • 分步操作,不要一次性执行太多

7.4 Windows 特殊配置

Windows 用户可能遇到启动超时,建议添加环境变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"mcpServers": {
"chrome-devtools": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"chrome-devtools-mcp@latest"
],
"env": {
"SystemRoot": "C:\\Windows",
"PROGRAMFILES": "C:\\Program Files"
},
"startup_timeout_ms": 20000
}
}
}

八、最佳实践总结

8.1 使用建议

建议 说明
明确指令 告诉 AI 具体要做什么,不要模糊
分步执行 复杂任务拆成多个步骤
善用等待 让 AI 等待页面加载完成再操作
验证结果 让 AI 截图确认操作是否成功
保存日志 调试时让 AI 保存控制台日志供分析

8.2 安全注意事项

重要提醒: MCP 会将浏览器内容暴露给 AI 助手。

  • 不要在浏览器中打开敏感页面(银行、密码管理器等)
  • 不要填写真实密码或个人信息
  • CI/CD 环境建议禁用使用统计
  • 定期检查 MCP 配置,移除不需要的服务器

8.3 与其他工具对比

工具 类型 优点 适用场景
Chrome DevTools MCP AI+浏览器 AI自主操控、智能分析 调试、分析、自动化
Puppeteer Node.js库 精细控制、成熟稳定 自动化脚本
Selenium 自动化框架 跨浏览器、生态丰富 E2E测试
Playwright 自动化框架 现代、快速、多浏览器 现代Web测试

九、总结

Chrome DevTools MCP 打通了 AI 助手与浏览器之间的壁垒,让 AI 从”只能聊天”进化为”能动手干活”。

核心价值:

  1. 零代码自动化 - 用自然语言操控浏览器
  2. 智能调试 - AI 分析问题,给出解决方案
  3. 性能洞察 - 自动识别性能瓶颈
  4. 开发提效 - 减少手动重复操作

学习路径建议:

1
2
3
4
5
第1天:安装配置,尝试打开网页、截图
第2天:调试实战,检查控制台、网络请求
第3天:自动化测试,填写表单、点击按钮
第4天:性能分析,了解 Web Vitals 指标
第5天:进阶使用,连接已有浏览器、CI集成

参考资料


一、写在前面:为什么需要 Superpowers?

你有没有遇到过这样的场景:

  • 让 AI 帮你写代码,它一上来就开始”输出”,完全不考虑你的真实需求
  • AI 写的代码看似没问题,但测试一跑就崩,因为它根本没写测试
  • AI “自主工作”了半小时,结果偏离了原需求十万八千里
  • 多个功能并行开发,AI 把代码混在一起,最后连回滚都困难

Superpowers 就是解决这些问题的”流程管家”。它不是让 AI 更聪明,而是让 AI 更靠谱——先规划、再测试、再实现、再审查,像真正工程师一样工作。


二、Superpowers 是什么?

2.1 一句话定义

Superpowers 是由 Jesse Vincent(Perl 专家、Markdown 发明者之一)开发的软件开发工作流系统,通过一系列”技能(Skills)”让 AI 编码助手遵循严格的工程流程。

2.2 核心理念

打个比方:

没有 Superpowers 有 Superpowers
AI 像是个”热情但冲动的新手”——拿到任务就写代码,写完就交 AI 像是个”老练的资深工程师”——先问清楚需求,写测试,再实现,最后审查
容易偏离需求 强制按计划执行
测试是”事后补的” 测试是”先写的”(TDD)
一个分支干所有事 Git Worktree 隔离开发

2.3 支持的 AI 工具

工具 安装方式
Claude Code /plugin install superpowers@claude-plugins-official
Cursor /add-plugin superpowers
GitHub Copilot CLI copilot plugin install superpowers
Gemini CLI gemini extensions install
Codex CLI 手动配置(见后文)
OpenCode 手动配置

三、核心工作流程详解

3.1 七步流程

Superpowers 强制 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
31
32
33
34
35
36
37
38
┌──────────────────────────────────────────────────────────────────────┐
│ Superpowers 工作流程 │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ 1. brainstorming (头脑风暴) │
│ └─► AI 不直接写代码,先问你"到底想做什么" │
│ └─► 通过苏格拉底式提问,提炼出清晰的设计文档 │
│ │
│ 2. using-git-worktrees (创建隔离工作空间) │
│ └─► 自动创建新分支 + Git Worktree │
│ └─► 确保开发环境干净、可回滚 │
│ │
│ 3. writing-plans (编写计划) │
│ └─► 将设计拆成 2-5 分钟的小任务 │
│ └─► 每个任务包含:文件路径、代码、验证步骤 │
│ │
│ 4. subagent-driven-development (子代理执行) │
│ └─► 每个任务派发一个新的子代理 │
│ └─► 主代理审查子代理的工作 │
│ └─► 可连续自主工作数小时 │
│ │
│ 5. test-driven-development (强制 TDD) │
│ └─► RED: 先写失败的测试 │
│ └─► GREEN: 写最少代码让测试通过 │
│ └─► REFACTOR: 优化代码 │
│ └─► 如果代码先于测试写了,会被删除! │
│ │
│ 6. requesting-code-review (代码审查) │
│ └─► 每个任务完成后自动审查 │
│ └─► 两阶段审查:规格合规 + 代码质量 │
│ └─► 关键问题会阻塞进度 │
│ │
│ 7. finishing-a-development-branch (完成分支) │
│ └─► 验证所有测试通过 │
│ └─► 提供:合并 / PR / 保留 / 丢弃选项 │
│ └─► 清理 Worktree │
│ │
└──────────────────────────────────────────────────────────────────────┘

3.2 为什么这套流程有效?

问题 1:AI 容易”跑偏”

传统 AI 编码:

1
2
3
4
5
用户:帮我加个登录功能
AI:好的,开始写代码...
(30分钟后)
AI:登录功能写好了,还顺便加了注册、找回密码、OAuth...
用户:??我只想要个简单的登录啊

有 Superpowers:

1
2
3
4
5
6
7
8
9
用户:帮我加个登录功能
AI (brainstorming):让我先理解一下:
- 登录方式是什么?账号密码?OAuth?
- 需要记住登录状态吗?多久?
- 安全要求是什么?
用户:账号密码登录,记住 7 天,简单安全就行
AI:好的,我来写设计文档,你确认后再动手
(用户确认后)
AI:现在开始实现,每个任务都会按计划执行

问题 2:AI 不写测试

传统 AI 编码:

1
2
3
4
AI:功能写完了!
用户:测试呢?
AI:呃...我补一下
(补的测试可能根本测不到关键逻辑)

有 Superpowers(强制 TDD):

1
2
3
4
5
AI:现在要实现登录验证
AI:先写测试(RED)→ 测试失败 ✓
AI:再写代码(GREEN)→ 测试通过 ✓
AI:重构优化(REFACTOR)→ 测试仍通过 ✓
AI:继续下一个任务

问题 3:多功能开发混乱

传统方式:

1
2
3
4
5
main 分支上同时开发 3 个功能
功能 A 改了文件 X
功能 B 也改了文件 X
功能 C 又改了文件 X
→ 冲突灾难

有 Superpowers(Git Worktree):

1
2
3
4
功能 A → worktree/feature-a/ (独立目录)
功能 B → worktree/feature-b/ (独立目录)
功能 C → worktree/feature-c/ (独立目录)
→ 完全隔离,互不影响


四、安装配置实战

4.1 Claude Code 安装(推荐)

方式一:官方插件市场(最简单)

1
2
# 在 Claude Code 中执行
/plugin install superpowers@claude-plugins-official

方式二:第三方市场

1
2
3
4
5
# 先注册市场
/plugin marketplace add obra/superpowers-marketplace

# 再安装插件
/plugin install superpowers@superpowers-marketplace

验证安装:

1
2
3
4
# 查看已安装插件
/plugin list

# 应该看到 superpowers

4.2 Cursor 安装

在 Cursor Agent 聊天中:

1
/add-plugin superpowers

或者在插件市场搜索 “superpowers”。

4.3 GitHub Copilot CLI 安装

1
2
3
4
5
# 注册市场
copilot plugin marketplace add obra/superpowers-marketplace

# 安装插件
copilot plugin install superpowers@superpowers-marketplace

4.4 Codex CLI 手动安装

Codex 目前没有插件市场,需要手动配置:

步骤 1:获取技能文件

1
2
3
4
5
6
# 克隆仓库
git clone https://github.com/obra/superpowers.git

# 复制技能到 Codex 目录
mkdir -p ~/.codex/skills
cp -r superpowers/skills/* ~/.codex/skills/

步骤 2:配置 Codex

创建或编辑 ~/.codex/config.json

1
2
3
{
"skillsDirectory": "~/.codex/skills"
}

步骤 3:验证

启动 Codex 后,技能会自动加载。

4.5 Gemini CLI 安装

1
2
3
4
5
# 安装扩展
gemini extensions install https://github.com/obra/superpowers

# 更新
gemini extensions update superpowers

4.6 更新插件

1
2
3
4
5
6
7
8
# Claude Code
/plugin update superpowers

# Copilot CLI
copilot plugin update superpowers

# Gemini CLI
gemini extensions update superpowers

五、使用实战:从零开始

5.1 触发技能

Superpowers 的技能会自动触发。你不需要特殊命令,只需要用自然语言描述需求。

示例:启动一个新功能

1
我想给博客系统加一个评论功能,支持用户登录后评论

AI 会自动调用 brainstorming 技能:

1
2
3
4
5
6
7
8
AI:让我先理解你的需求...

问题 1:评论需要审核吗?还是直接发布?
问题 2:评论可以回复吗?支持嵌套?
问题 3:评论内容有什么限制?字数、格式?
问题 4:需要通知博主吗?邮件?站内?

请逐一回答,我会根据你的回答设计功能。

5.2 头脑风暴阶段

你的回答:

1
2
3
4
评论不需要审核,直接发布
支持回复,但不嵌套(最多一层)
评论最多 500 字,不能发链接
不需要通知

AI 会生成设计文档:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
## 评论功能设计文档

### 核心需求
- 用户登录后可评论
- 评论直接发布,无需审核
- 支持回复评论(一层)

### 技术方案
- 数据表:comments (id, user_id, post_id, content, parent_id, created_at)
- API:POST /comments, GET /comments/:post_id
- 前端:评论框 + 评论列表 + 回复按钮

### 验收标准
- 登录用户可发表评论
- 可回复他人评论
- 评论字数限制 500 字
- 不允许发送链接

你确认后,AI 进入下一阶段。

5.3 Git Worktree 阶段

AI 会自动:

1
2
3
4
5
6
7
8
9
10
11
12
# 创建新分支
git checkout -b feature/comments

# 创建 Worktree(独立工作目录)
git worktree add .claude/worktrees/feature-comments feature/comments

# 在 Worktree 中初始化环境
cd .claude/worktrees/feature-comments
npm install # 或其他项目初始化命令

# 验证测试基线
npm test # 确保当前测试都通过

Worktree 的好处:

1
2
3
4
5
6
你的主项目目录:     /projects/my-blog/
评论功能 Worktree: /projects/my-blog/.claude/worktrees/feature-comments/

两个目录完全独立!
你可以在主目录继续其他工作
AI 在 Worktree 专心开发评论功能

5.4 编写计划阶段

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
## 实现计划

### 任务 1:创建评论数据模型 (预计 3 分钟)
- 文件:`src/models/comment.js`
- 代码:定义 Comment schema
- 验证:模型可正确创建实例

### 任务 2:添加评论 API (预计 5 分钟)
- 文件:`src/routes/comments.js`
- 代码:POST /comments, GET /comments/:post_id
- 验证:API 测试通过

### 任务 3:评论前端组件 (预计 10 分钟)
- 文件:`src/components/CommentBox.jsx`, `src/components/CommentList.jsx`
- 代码:评论输入框、评论列表、回复按钮
- 验证:组件渲染正确,可交互

### 任务 4:字数限制和链接过滤 (预计 3 分钟)
- 文件:`src/utils/commentValidator.js`
- 代码:验证函数
- 验证:超过 500 字拒绝,包含链接拒绝

### 任务 5:集成测试 (预计 5 分钟)
- 文件:`tests/comment.test.js`
- 代码:完整流程测试
- 验证:测试通过

任务粒度原则:

  • 每个任务 2-5 分钟
  • 明确的文件路径
  • 验证步骤

5.5 子代理执行阶段

这是 Superpowers 的核心亮点:

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
┌─────────────────────────────────────────────────────────────┐
│ 子代理驱动开发 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 主代理 (你对话的 AI) │
│ │ │
│ ├──► 派发子代理 1 → 执行任务 1 (创建模型) │
│ │ │ │
│ │ └──► 完成后返回结果 │
│ │ │
│ ├──► 主代理审查:符合设计?代码质量? │
│ │ │
│ ├──► 派发子代理 2 → 执行任务 2 (添加 API) │
│ │ │ │
│ │ └──► 完成后返回结果 │
│ │ │
│ ├──► 主代理审查... │
│ │ │
│ └──► 继续执行... │
│ │
│ 优势: │
│ - 每个任务用"新鲜"的子代理,无上下文污染 │
│ - 主代理审查,确保质量 │
│ - 可连续自主工作数小时 │
│ │
└─────────────────────────────────────────────────────────────┘

你的体验:

1
2
3
4
5
6
7
8
AI:开始执行任务 1...
AI:任务 1 完成,审查中...
AI:审查通过 ✓,继续任务 2...
AI:任务 2 完成,审查中...
AI:发现一个小问题,已修复 ✓
AI:继续任务 3...
(你可以去喝咖啡了)
AI:所有任务完成!

5.6 TDD 阶段(强制)

Superpowers 的 TDD 是真正的 RED-GREEN-REFACTOR:

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
// 步骤 1:RED - 先写失败的测试
describe('CommentValidator', () => {
it('should reject comment longer than 500 chars', () => {
const longComment = 'a'.repeat(501);
expect(validateComment(longComment)).toBe(false);
});
});

// 运行测试 → 失败 ✓ (因为 validateComment 还不存在)

// 步骤 2:GREEN - 写最少代码让测试通过
function validateComment(content) {
if (content.length > 500) return false;
return true;
}

// 运行测试 → 通过 ✓

// 步骤 3:REFACTOR - 优化代码
function validateComment(content) {
const MAX_LENGTH = 500;
const LINK_PATTERN = /https?:\/\/\S+/;

if (content.length > MAX_LENGTH) return false;
if (LINK_PATTERN.test(content)) return false;
return true;
}

// 运行测试 → 仍通过 ✓

如果 AI 先写了代码再写测试?

1
2
AI 会删除代码,重新从测试开始写!
这是强制的,不是建议。

5.7 代码审查阶段

每个任务完成后,主代理会审查:

审查维度:

维度 检查内容
规格合规 是否符合设计文档?
代码质量 可读性、命名、结构
测试覆盖 测试是否充分?
安全性 有无安全漏洞?

审查结果:

1
2
3
4
5
6
7
8
审查报告:

✓ 规格合规:符合设计文档
⚠ 代码质量:变量命名可优化(comment → userComment)
✓ 测试覆盖:覆盖了主要场景
✓ 安全性:无明显问题

建议:优化变量命名后继续

关键问题会阻塞进度:

1
2
❌ 发现关键问题:API 缺少权限验证
→ 必须修复后才能继续

5.8 完成分支阶段

所有任务完成后:

1
2
3
4
5
6
7
8
9
10
AI:所有任务完成!验证测试...
AI:所有测试通过 ✓

请选择下一步:
[1] 合并到主分支
[2] 创建 Pull Request
[3] 保留分支(暂不合并)
[4] 丢弃所有更改

你的选择?

选择后,AI 会:

1
2
3
4
5
6
7
# 如果选择合并
git checkout main
git merge feature/comments
git worktree remove .claude/worktrees/feature-comments

# 如果选择创建 PR
gh pr create --title "Add comment feature" --body "..."

六、与 GitHub SpecKit 的对比

6.1 两者是什么关系?

SuperpowersGitHub SpecKit 都是”规范驱动开发”的工具,但理念和实现方式不同。

特性 Superpowers GitHub SpecKit
开发者 Jesse Vincent(独立开发者) GitHub 官方
形态 Skills 插件系统 CLI + Skills + Extensions 生态
核心理念 流程至上 - 强制 TDD、强制审查 规范至上 - spec 成为可执行文档
安装方式 /plugin install uv tool install specify-cli
项目宪法 /speckit.constitution 创建
产出文件 动态生成 固定:spec.md, plan.md, tasks.md
TDD 强制 RED-GREEN-REFACTOR 推荐但不强制
Git Worktree 自动创建 无内置
子代理执行 内置 subagent-driven 通过扩展实现
可视化 UI VS Code 扩展支持
外部集成 有限 Jira、Azure DevOps、Linear 等 40+ 扩展

6.2 核心哲学差异

Superpowers:流程至上

1
2
3
4
5
6
7
8
核心理念:"让 AI 不犯错误"

方式:强制工程流程
- 不写测试就不能写代码
- 不审查就不能继续
- 不隔离就不能开发

适合:个人开发者、追求代码质量

SpecKit:规范至上

1
2
3
4
5
6
7
8
核心理念:"让规范成为第一性原理"

方式:规范可执行
- spec.md 直接生成代码
- 规范是"活的",不是文档
- 专注于"做什么",而非"怎么做"

适合:团队协作、需要外部集成

6.3 工作流对比

Superpowers 流程:

1
2
3
需求 → 头脑风暴 → Worktree → 计划 → 子代理执行 → TDD → 审查 → 完成分支
↑ ↑ ↑ ↑ ↑ ↑
问清楚 隔离环境 拆任务 自动执行 强制 质量保证

SpecKit 流程:

1
2
3
宪法 → Specify → Plan → Tasks → Implement
↑ ↑ ↑ ↑ ↑
原则 需求 技术 任务 执行

6.4 SpecKit 的独特优势

1. 项目宪法

1
2
3
4
5
# 定义项目原则
/speckit.constitution Create principles focused on:
- Code quality: clean code, no duplication
- Testing: unit tests required for all logic
- Performance: response time < 200ms

这会生成一个”宪法文件”,指导所有后续开发。

2. 丰富的扩展生态

扩展 功能
spec-kit-jira 同步到 Jira
spec-kit-review 代码审查
spec-kit-qa QA 测试
spec-kit-ship 自动发布
superpowers-bridge 将 Superpowers 集成到 SpecKit!

3. 预设系统

可以自定义术语和模板:

1
2
3
4
5
6
7
8
{
"name": "pirate-speak",
"templates": {
"spec.md": "Voyage Manifest",
"plan.md": "Battle Plan",
"tasks.md": "Crew Assignments"
}
}

6.5 Superpowers 的独特优势

1. 强制 TDD

1
2
3
这是最大的区别。
SpecKit 推荐 TDD,但 Superpowers 强制 TDD。
如果你先写代码再写测试,代码会被删除。

2. Git Worktree 隔离

1
2
3
4
每个功能在独立目录开发:
- 不影响主项目
- 可以并行开发多个功能
- 回滚简单(删除 worktree 即可)

3. 子代理驱动

1
2
3
4
每个任务派发新的子代理:
- 无上下文污染
- 主代理审查质量
- 可连续自主工作数小时

6.6 可以一起用吗?

可以! 社区已经创建了 superpowers-bridge 扩展:

1
2
3
4
5
# 在 SpecKit 项目中安装
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git

# 安装 superpowers-bridge 扩展
# (详见扩展文档)

这样你可以:

  • 用 SpecKit 管理规范和外部集成
  • 用 Superpowers 的 TDD、Worktree、子代理执行

七、最佳实践与适用场景

7.1 适用场景建议

场景 推荐
个人开发者,追求代码质量 Superpowers
企业团队,需要外部集成 SpecKit
已有完善规范流程 SpecKit(可定制扩展)
需要长时间自主运行 Superpowers(子代理可工作数小时)
多功能并行开发 Superpowers(Git Worktree)
两者都需要 SpecKit + superpowers-bridge

7.2 使用 Superpowers 的建议

建议 1:让 AI 问清楚再开始

1
2
3
4
不要急着说"开始写代码"
等 AI 完成头脑风暴
仔细阅读设计文档
确认后再说"开始实现"

建议 2:任务粒度要小

1
2
3
4
5
6
7
好的任务:2-5 分钟,一个文件
不好的任务:"实现整个评论功能"

小任务的好处:
- 更容易审查
- 更容易回滚
- 更容易并行

建议 3:关注审查报告

1
2
3
不要忽略审查报告中的警告
即使是"建议优化"
让 AI 修复后再继续

建议 4:并行开发时用 Worktree

1
2
3
4
5
6
如果你要同时开发 3 个功能:
功能 A → 让 AI 创建 worktree/feature-a
功能 B → 让 AI 创建 worktree/feature-b
功能 C → 让 AI 创建 worktree/feature-c

完全隔离,不会冲突

7.3 使用 SpecKit 的建议

建议 1:先写宪法

1
/speckit.constitution Define project principles first

宪法会指导所有后续开发,相当于”项目宪法”。

建议 2:选择合适的扩展

1
2
3
需要 Jira 集成?→ spec-kit-jira
需要代码审查?→ spec-kit-review
需要自动发布?→ spec-kit-ship

建议 3:利用社区预设

1
2
3
4
不想自己配置?
用社区预设:
- Agent Teams Lite(多代理)
- Pirate Speak(有趣模板)

八、常见问题

Q1: Superpowers 和 SpecKit 可以同时用吗?

可以。 安装 superpowers-bridge 扩展即可。

Q2: Superpowers 会让我写代码变慢吗?

短期内可能变慢(因为要先规划、先写测试),但长期会更快(因为减少返工)。

Q3: 子代理执行安全吗?

安全。 子代理在隔离环境中执行,主代理审查结果。

Q4: Git Worktree 会占用很多磁盘空间吗?

会占用一些,但完成后会自动清理。 你也可以手动清理:

1
2
git worktree list
git worktree remove <path>

Q5: SpecKit 的扩展稳定吗?

社区扩展由独立开发者维护,GitHub 官方不审核。 使用前建议查看源代码。


九、总结

核心要点

  1. Superpowers 是流程管家:让 AI 遵循严格的工程流程
  2. 核心流程:头脑风暴 → Worktree → 计划 → 子代理 → TDD → 审查 → 完成
  3. 强制 TDD:不写测试就不能写代码
  4. Git Worktree:每个功能在独立目录开发
  5. 子代理执行:每个任务派发新的子代理,主代理审查

与 SpecKit 的核心区别

方面 Superpowers SpecKit
理念 流程至上 规范至上
TDD 强制 推荐
Worktree 自动 无内置
子代理 内置 通过扩展
生态 单一技能库 40+ 扩展

选择建议

1
2
3
追求代码质量、个人开发 → Superpowers
团队协作、外部集成 → SpecKit
两者都需要 → SpecKit + superpowers-bridge

学习路径

1
2
3
4
5
第 1 天:安装 Superpowers,体验头脑风暴
第 2 天:完整走一遍流程,感受 TDD
第 3 天:尝试并行开发(Worktree)
第 4 天:对比 SpecKit,选择适合你的
第 5 天:深入使用,定制你的工作流

参考资料



一、CrewAI 是什么?

官方定义

CrewAI 是一个精简、快速的 Python 框架,用于编排自主 AI 代理(Agent)。它让多个 AI Agent 可以协同工作,像一个团队一样完成复杂任务。

核心特点

特点 说明
独立框架 不依赖 LangChain 或其他框架,从零构建
高性能 比 LangGraph 快 5 倍以上
灵活定制 从高层工作流到底层提示词都可定制
两种模式 Crews(自主协作)+ Flows(精确控制)

与其他框架对比

框架 优点 缺点
CrewAI 简洁、快速、独立 社区相对较新
LangGraph 功能强大 样板代码多、与 LangChain 强耦合
Autogen 对话代理能力强 缺乏流程概念
ChatDev 有流程概念 定制能力有限

适用场景

  • 自动化工作流(报告生成、数据分析)
  • 多角色协作系统(一人公司、虚拟团队)
  • 复杂任务分解与执行
  • AI 驱动的应用开发

二、核心概念

2.1 Agent(代理)

Agent 是 CrewAI 的核心单元,代表一个”角色”。

1
2
3
4
5
6
7
8
9
10
11
from crewai import Agent

agent = Agent(
role="高级数据分析师", # 角色
goal="分析数据并提供洞察", # 目标
backstory="你是一位资深分析师...", # 背景故事
verbose=True, # 详细输出
allow_delegation=True, # 是否可以委派任务
tools=[], # 可用工具
llm=..., # 使用的大模型
)

关键参数

  • role:角色名称,定义 Agent 的身份
  • goal:目标,定义 Agent 想要达成什么
  • backstory:背景故事,决定 Agent 的性格和行为方式
  • tools:Agent 可以使用的工具列表
  • llm:Agent 使用的大模型

2.2 Task(任务)

Task 定义 Agent 需要完成的具体工作。

1
2
3
4
5
6
7
8
from crewai import Task

task = Task(
description="分析销售数据,找出增长趋势",
expected_output="包含 5 个关键发现的报告",
agent=agent, # 执行任务的 Agent
output_file="report.md", # 输出文件
)

2.3 Crew(团队)

Crew 是 Agent 的集合,定义它们如何协作。

1
2
3
4
5
6
7
8
from crewai import Crew, Process

crew = Crew(
agents=[agent1, agent2, agent3],
tasks=[task1, task2, task3],
process=Process.sequential, # 或 Process.hierarchical
verbose=True,
)

协作模式

模式 说明 适用场景
Process.sequential 顺序执行,一个任务完成后执行下一个 流程明确的任务
Process.hierarchical 层级模式,自动分配 Manager Agent 协调 需要动态决策的任务

2.4 Tools(工具)

Tools 扩展 Agent 的能力,让它可以搜索、读写文件、调用 API 等。

1
2
3
4
5
6
7
8
9
10
from crewai_tools import SerperDevTool, FileReadTool

search_tool = SerperDevTool() # 搜索工具
file_tool = FileReadTool() # 文件读取工具

agent = Agent(
role="研究员",
tools=[search_tool, file_tool],
...
)

2.5 整体工作流程

1
2
3
4
5
6
7
8
9
10
11
12
13
┌─────────────────────────────────────────────────────────────┐
│ Crew │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Agent 1 │ │ Agent 2 │ │ Agent 3 │ │
│ │ (分析师) │ │ (研究员) │ │ (撰稿人) │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Task 1 │ │ Task 2 │ │ Task 3 │ │
│ │ 分析数据 │→│ 研究背景 │→│ 撰写报告 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────────────────┘

三、安装与环境配置

3.1 环境要求

  • Python 3.10 - 3.13
  • 推荐使用 uv 作为包管理器

3.2 安装 CrewAI

方式一:使用 pip

1
2
3
4
5
# 基础安装
pip install crewai

# 安装额外工具
pip install 'crewai[tools]'

方式二:使用 uv(推荐)

1
2
3
4
5
6
# 安装 uv
pip install uv

# 安装 CrewAI
uv pip install crewai
uv pip install 'crewai[tools]'

3.3 创建项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 创建新项目
crewai create crew my_project

# 项目结构
my_project/
├── .env # 环境变量
├── pyproject.toml # 项目配置
└── src/my_project/
├── main.py # 入口文件
├── crew.py # Crew 定义
├── tools/ # 自定义工具
└── config/
├── agents.yaml # Agent 配置
└── tasks.yaml # Task 配置

3.4 常见安装问题

问题 1:ModuleNotFoundError: tiktoken

1
uv pip install 'crewai[embeddings]'

问题 2:Windows 上 Rust 编译错误

1
2
3
# 安装 Visual C++ Build Tools
# 或使用预编译包
uv pip install tiktoken --prefer-binary

四、大模型服务接入(重点)

这是大多数新手卡住的地方。CrewAI 默认使用 OpenAI,但你必须配置正确的 base_url 才能连接到你的大模型服务。

4.1 核心概念

为什么需要 base_url?

1
2
3
4
┌─────────────┐         ┌─────────────────────┐
│ CrewAI │ ────→ │ LLM 服务端点 │
│ (你的代码) │ HTTP │ (base_url) │
└─────────────┘ └─────────────────────┘
  • 默认情况下,CrewAI 会连接 https://api.openai.com/v1
  • 如果你用的是其他服务(阿里百炼、DeepSeek 等),必须指定 base_url
  • 否则会报错:Connection refusedInvalid API key

4.2 OpenAI 官方

1
2
3
4
5
6
7
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
model="gpt-4o",
api_key="sk-xxxxx",
# base_url 默认是 https://api.openai.com/v1,可以不填
)

环境变量方式

1
OPENAI_API_KEY=sk-xxxxx

4.3 Anthropic Claude

1
2
3
4
5
6
from langchain_anthropic import ChatAnthropic

llm = ChatAnthropic(
model="claude-sonnet-4-6",
api_key="sk-ant-xxxxx",
)

环境变量方式

1
ANTHROPIC_API_KEY=sk-ant-xxxxx

4.4 阿里百炼 Coding Plan(推荐)

阿里百炼 Coding Plan 提供两种兼容协议:

协议 Base URL 说明
OpenAI 兼容 https://coding.dashscope.aliyuncs.com/v1 使用 langchain-openai
Anthropic 兼容 https://coding.dashscope.aliyuncs.com/apps/anthropic 使用 langchain-anthropic

使用 OpenAI 兼容协议

1
2
3
4
5
6
7
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
model="qwen-max", # 通义千问模型
api_key="your_dashscope_key",
base_url="https://coding.dashscope.aliyuncs.com/v1", # 关键!
)

使用 Anthropic 兼容协议

1
2
3
4
5
6
7
from langchain_anthropic import ChatAnthropic

llm = ChatAnthropic(
model="qwen-max",
api_key="your_dashscope_key",
base_url="https://coding.dashscope.aliyuncs.com/apps/anthropic", # 关键!
)

环境变量方式

1
2
DASHSCOPE_API_KEY=your_dashscope_key
DASHSCOPE_BASE_URL=https://coding.dashscope.aliyuncs.com/v1

4.5 DeepSeek

1
2
3
4
5
6
7
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
model="deepseek-chat",
api_key="your_deepseek_key",
base_url="https://api.deepseek.com/v1", # 关键!
)

4.6 智谱 AI (GLM)

1
2
3
4
5
6
7
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
model="glm-4",
api_key="your_zhipu_key",
base_url="https://open.bigmodel.cn/api/paas/v4/", # 关键!
)

4.7 本地模型 (Ollama)

1
2
3
4
5
6
7
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
model="llama3",
api_key="ollama", # 任意值
base_url="http://localhost:11434/v1", # Ollama 默认端口
)

4.8 统一配置方案

在实际项目中,推荐使用配置文件统一管理:

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
# config/llm_config.py

import os
from langchain_openai import ChatOpenAI

def get_llm(provider: str = "dashscope"):
"""统一获取 LLM"""

configs = {
"openai": {
"model": "gpt-4o",
"api_key": os.getenv("OPENAI_API_KEY"),
"base_url": None,
},
"dashscope": {
"model": "qwen-max",
"api_key": os.getenv("DASHSCOPE_API_KEY"),
"base_url": "https://coding.dashscope.aliyuncs.com/v1",
},
"deepseek": {
"model": "deepseek-chat",
"api_key": os.getenv("DEEPSEEK_API_KEY"),
"base_url": "https://api.deepseek.com/v1",
},
}

config = configs.get(provider)
if not config or not config["api_key"]:
raise ValueError(f"请配置 {provider} 的 API Key")

return ChatOpenAI(
model=config["model"],
api_key=config["api_key"],
base_url=config["base_url"],
)

使用

1
2
3
4
5
# 默认使用阿里百炼
llm = get_llm()

# 切换到 OpenAI
llm = get_llm("openai")

4.9 Agent 中使用 LLM

1
2
3
4
5
6
7
8
9
from crewai import Agent
from config.llm_config import get_llm

agent = Agent(
role="分析师",
goal="分析数据",
backstory="你是一位资深分析师",
llm=get_llm("dashscope"), # 指定 LLM
)

五、项目结构详解

5.1 使用 CLI 创建项目

1
2
crewai create crew my_crew
cd my_crew

5.2 目录结构说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
my_crew/
├── .env # 环境变量(API Key 等)
├── pyproject.toml # Python 项目配置
├── README.md
└── src/my_crew/
├── __init__.py
├── main.py # 入口文件,运行 crew
├── crew.py # 定义 Crew、Agent、Task
├── tools/ # 自定义工具
│ ├── __init__.py
│ └── custom_tool.py
└── config/
├── agents.yaml # Agent 配置(角色、目标、背景)
└── tasks.yaml # Task 配置(描述、预期输出)

5.3 agents.yaml 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# config/agents.yaml

researcher:
role: >
{topic} 高级研究员
goal: >
深入研究 {topic} 领域的最新发展
backstory: >
你是一位经验丰富的研究员,擅长发现最前沿的技术趋势。
你以能够找到最相关信息并以清晰简洁的方式呈现而闻名。

analyst:
role: >
{topic} 数据分析师
goal: >
分析研究数据并生成洞察报告
backstory: >
你是一位严谨的分析师,擅长将复杂数据转化为可执行的洞察。

占位符说明

  • {topic} 会在运行时被替换为实际值

5.4 tasks.yaml 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# config/tasks.yaml

research_task:
description: >
{topic} 进行全面研究,找出最新、最相关的信息。
expected_output: >
包含 10 个关键发现的要点列表
agent: researcher # 执行此任务的 Agent

analysis_task:
description: >
分析研究结果,生成详细的分析报告。
expected_output: >
一份完整的 Markdown 格式报告
agent: analyst
output_file: report.md # 输出文件

5.5 crew.py 定义

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
39
40
41
42
43
44
# crew.py

from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task

@CrewBase
class MyCrew():
"""我的 Crew"""

@agent
def researcher(self) -> Agent:
return Agent(
config=self.agents_config['researcher'],
verbose=True,
)

@agent
def analyst(self) -> Agent:
return Agent(
config=self.agents_config['analyst'],
verbose=True,
)

@task
def research_task(self) -> Task:
return Task(
config=self.tasks_config['research_task'],
)

@task
def analysis_task(self) -> Task:
return Task(
config=self.tasks_config['analysis_task'],
output_file='report.md',
)

@crew
def crew(self) -> Crew:
return Crew(
agents=self.agents,
tasks=self.tasks,
process=Process.sequential,
verbose=True,
)

5.6 main.py 入口

1
2
3
4
5
6
7
8
9
10
11
12
13
# main.py

from my_crew.crew import MyCrew

def run():
"""运行 Crew"""
inputs = {
'topic': 'AI Agents'
}
MyCrew().crew().kickoff(inputs=inputs)

if __name__ == "__main__":
run()

5.7 运行项目

1
2
3
4
5
# 方式一:使用 CLI
crewai run

# 方式二:直接运行 Python
python src/my_crew/main.py

六、实战:构建一人公司 Agent 团队

6.1 场景描述

假设你要开发一个「人生规划器」App,但你只有一个人。你可以创建一个 Agent 团队来帮你:

  • CEO Agent:负责决策和协调
  • CTO Agent:负责技术架构
  • 产品经理 Agent:负责需求分析
  • 工程师 Agent:负责代码实现
  • 测试 Agent:负责质量保证

6.2 项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
life-planner-crew/
├── .env
├── requirements.txt
├── main.py
├── agents/
│ ├── ceo_agent.py
│ ├── cto_agent.py
│ ├── product_manager.py
│ ├── backend_engineer.py
│ ├── frontend_engineer.py
│ └── qa_agent.py
├── tasks/
│ ├── requirement_tasks.py
│ ├── development_tasks.py
│ └── test_tasks.py
├── crews/
│ └── development_crew.py
├── tools/
│ └── file_tools.py
└── config/
├── project_config.py
└── llm_config.py

6.3 LLM 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# config/llm_config.py

import os
from langchain_openai import ChatOpenAI

DASHSCOPE_API_KEY = os.getenv("DASHSCOPE_API_KEY")
DASHSCOPE_BASE_URL = "https://coding.dashscope.aliyuncs.com/v1"

def get_default_llm():
"""默认模型(用于决策类 Agent)"""
return ChatOpenAI(
model="qwen-max",
api_key=DASHSCOPE_API_KEY,
base_url=DASHSCOPE_BASE_URL,
)

def get_efficient_llm():
"""高效模型(用于执行类 Agent)"""
return ChatOpenAI(
model="qwen-turbo",
api_key=DASHSCOPE_API_KEY,
base_url=DASHSCOPE_BASE_URL,
)

6.4 Agent 定义

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
# agents/ceo_agent.py

from crewai import Agent
from config.llm_config import get_default_llm

def create_ceo_agent():
return Agent(
role="CEO - 公司首席执行官",
goal="""
负责:
1. 战略决策和目标设定
2. 团队协调和资源分配
3. 处理 Agent 团队分歧
4. 确保项目按时保质完成
""",
backstory="""
你是一位经验丰富的技术创业者。
决策果断但善于倾听,关注商业价值。
""",
verbose=True,
allow_delegation=True, # 可以委派任务
llm=get_default_llm(),
)

# agents/backend_engineer.py

def create_backend_engineer_agent():
return Agent(
role="后端工程师",
goal="实现 API 和数据库逻辑",
backstory="你专注于 Node.js 后端开发",
verbose=True,
allow_delegation=False,
llm=get_efficient_llm(), # 使用高效模型
)

6.5 Crew 配置

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
# crews/development_crew.py

from crewai import Crew, Process
from agents import (
create_ceo_agent,
create_cto_agent,
create_product_manager,
create_backend_engineer,
)

def create_development_crew():
# 创建 Agent
ceo = create_ceo_agent()
cto = create_cto_agent()
pm = create_product_manager()
backend = create_backend_engineer()

return Crew(
agents=[ceo, cto, pm, backend],
tasks=[], # 动态添加
process=Process.hierarchical, # 层级模式
manager_llm="qwen-max",
manager_agent=ceo, # CEO 作为管理者
verbose=True,
)

6.6 运行效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
python main.py

# 输出
╔═══════════════════════════════════════════════════════════════╗
║ 🎭 Life Planner Crew - 一人公司 Agent 团队 🎭 ║
╚═══════════════════════════════════════════════════════════════╝

📋 检查环境配置...
✓ DASHSCOPE_API_KEY 已配置
✓ 项目目录存在

🎯 请选择操作模式:
[1] 初始化项目
[2] 功能开发模式
[3] 决策讨论模式

七、常见问题与解决方案

Q1: 连接大模型失败

错误信息

1
ConnectionError: Failed to connect to api.openai.com

原因:没有配置正确的 base_url

解决

1
2
3
4
5
6
7
8
9
# 错误 ❌
llm = ChatOpenAI(model="qwen-max", api_key="xxx")

# 正确 ✅
llm = ChatOpenAI(
model="qwen-max",
api_key="xxx",
base_url="https://coding.dashscope.aliyuncs.com/v1",
)

Q2: API Key 格式错误

错误信息

1
AuthenticationError: Invalid API key

检查项

  1. API Key 是否正确复制(没有多余空格)
  2. 是否填对了环境变量名
  3. .env 文件是否被正确加载

解决

1
2
3
4
5
6
7
# 确保加载 .env
from dotenv import load_dotenv
load_dotenv()

# 验证 API Key
import os
print(os.getenv("DASHSCOPE_API_KEY"))

Q3: Agent 输出不符合预期

原因:角色定义不够清晰

解决:优化 backstory

1
2
3
4
5
6
7
8
9
10
11
# 不好 ❌
backstory="你是一个程序员"

# 更好 ✅
backstory="""
你是一位专注 Node.js 后端开发的工程师。
- 擅长 RESTful API 设计
- 遵循 Clean Code 原则
- 注重代码可维护性
- 使用 TypeScript 和 NestJS
"""

Q4: 依赖安装失败

Windows 上常见问题

1
2
3
4
# 安装 Visual C++ Build Tools
# 或使用预编译包
pip install tiktoken --prefer-binary
pip install 'crewai[embeddings]'

Q5: 如何调试 Agent

开启 verbose 模式

1
2
3
4
5
6
7
8
9
agent = Agent(
role="分析师",
verbose=True, # 输出详细过程
)

crew = Crew(
agents=[agent],
verbose=True, # 输出团队协作过程
)

八、总结

核心要点

  1. CrewAI 是什么:多 Agent 协作框架,让多个 AI 角色协同完成任务
  2. 核心概念:Agent(角色)、Task(任务)、Crew(团队)、Tools(工具)
  3. 关键配置:LLM 接入必须配置 base_url,这是大多数人踩坑的地方

大模型接入速查表

服务商 base_url 备注
OpenAI 默认 无需配置
阿里百炼 Coding Plan https://coding.dashscope.aliyuncs.com/v1 OpenAI 兼容
DeepSeek https://api.deepseek.com/v1 OpenAI 兼容
智谱 AI https://open.bigmodel.cn/api/paas/v4/ OpenAI 兼容
Ollama http://localhost:11434/v1 本地模型

学习资源

下一步

  1. 尝试创建你的第一个 Crew
  2. 接入你喜欢的大模型服务
  3. 设计适合你场景的 Agent 角色
  4. 组合 Crews 和 Flows 构建复杂工作流

作者:AI 技术探索者
日期:2026-03-31

本文基于 CrewAI v1.12+ 和阿里百炼 Coding Plan 服务编写

写在前面

如果你刚读完《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 是模型

参考资料

写在前面

说实话,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%

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

写在前面

做 RAG(检索增强生成)应用,向量数据库是绕不开的核心组件。市面上产品不少——Milvus、Qdrant、Weaviate、Chroma、Pinecone……每个都说自己最强。到底怎么选?

这篇文章不讲虚的,从底层原理实际选型,重点分析 Chroma 和 Milvus 两款代表产品,让你看完就能做决策。


一、向量数据库解决什么问题

传统数据库擅长精确匹配:WHERE name = '张三'。但语义搜索不一样——用户问”如何提高团队协作效率”,你得找出意思相近的文档,哪怕文档里压根没有这几个词。

向量数据库的核心价值:把文本、图像、音频等非结构化数据转换成向量(一串数字),然后用数学方法计算”相似度”,找出语义最接近的内容。

1
2
文本 → Embedding模型 → 向量 [0.12, -0.34, 0.56, ...] → 向量数据库
查询 → Embedding模型 → 向量 [0.15, -0.30, 0.52, ...] → 相似度计算 → Top-K结果

二、核心技术指标:怎么评判一个向量数据库

1. 索引算法决定性能上限

向量数据库的索引算法直接决定查询速度和召回率。主流索引类型:

索引类型 原理 查询速度 内存占用 适用场景
FLAT 暴力遍历,精确计算 最慢 最高 小数据量,要求100%召回
IVF-FLAT clustering + 倒排 中等 中等 百万级,平衡方案
IVF-PQ 聚类 + 乘积量化压缩 内存受限,牺牲精度
HNSW 分层可导航小世界图 最快 较高 高性能实时查询
DISKANN 磁盘索引 + SSD优化 较慢 极低 超大规模,成本敏感

HNSW 是当前主流选择,它的核心思想是构建一个多层图结构,搜索时从顶层快速跳转,逐层缩小范围,像”跳表”一样高效。

1
2
3
4
5
6
7
8
9
10
11
12
HNSW 结构示意:

Layer 2: ●────────────● (稀疏,快速跳转)
│ │
Layer 1: ●────●───────● (中等密度)
│ │ │
Layer 0: ●─●─●─●─●─●─●─●─● (全量节点,精确搜索)

关键参数:
- M: 每节点最大连接数(默认16),越大越精确但内存越高
- efConstruction: 构建时搜索宽度(默认200)
- efSearch: 查询时搜索宽度,动态调整召回率

2. 分布式架构决定扩展能力

架构类型 代表产品 特点
单机嵌入式 Chroma、Faiss 无部署成本,数据量受限
单机服务化 Qdrant 单机版 独立进程,支持持久化
分布式集群 Milvus、Qdrant 集群 水平扩展,高可用

3. 元数据过滤能力

实际业务中,向量搜索往往要结合条件过滤:找出”价格在100-500元之间且类别是电子产品”的相似商品。

数据库 过滤能力 实现方式
Qdrant 最强 原生支持复杂过滤,性能最优
Milvus 支持标量字段过滤
Chroma 基础 简单 where 条件
Pinecone 元数据命名空间

三、主流向量数据库横向对比

1. 开源产品对比

数据库 语言 架构 索引支持 过滤能力 社区活跃度
Milvus Go 分布式 HNSW/IVF/DISKANN 活跃(CNCF项目)
Qdrant Rust 单机/分布式 HNSW 最强 活跃
Weaviate Go 单机/分布式 HNSW 活跃
Chroma Python 嵌入式 HNSW 基础 活跃

2. 云服务对比

产品 定位 优势 劣势
Pinecone 全托管 Serverless 零运维,自动扩展 供应商锁定,成本不可控
Zilliz Cloud Milvus 托管版 企业级支持,兼容 Milvus API 价格较高
MongoDB Atlas Vector MongoDB 生态 复用现有基础设施 向量能力有限

3. 性能基准(百万级向量,HNSW索引)

数据库 QPS P99延迟 内存占用
Milvus ~15000 ~10ms
Qdrant ~12000 ~8ms
Weaviate ~8000 ~15ms
Chroma ~3000 ~30ms

四、Chroma:轻量级入门首选

1. 为什么选 Chroma

Chroma 的设计哲学是极简:Python 原生、嵌入式运行、API 设计友好。适合以下场景:

  • 原型验证:快速搭建 RAG Demo,几行代码就能跑
  • 小规模应用:文档量 < 10万,单机部署
  • 本地开发:数据不想出本机,隐私可控
  • 学习研究:理解向量数据库基本概念

2. Chroma 核心特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Chroma 的极简 API 设计
import chromadb

# 初始化:嵌入式,无需启动服务
client = chromadb.PersistentClient(path="./chroma_db")

# 创建集合
collection = client.create_collection(
name="documents",
metadata={"hnsw:space": "cosine"} # 支持 l2、ip、cosine
)

# 添加文档:自动调用 Embedding(内置默认模型)
collection.add(
documents=["文档内容1", "文档内容2"],
ids=["doc1", "doc2"]
)

# 查询:一步到位
results = collection.query(
query_texts=["查询内容"],
n_results=5
)

Chroma 内置 Embedding:默认使用 all-MiniLM-L6-v2 模型,也可以替换为 OpenAI、Cohere 等:

1
2
3
4
5
6
7
8
9
10
11
12
from chromadb.utils import embedding_functions

# 使用 OpenAI Embedding
openai_ef = embedding_functions.OpenAIEmbeddingFunction(
api_key="your-key",
model_name="text-embedding-3-small"
)

collection = client.create_collection(
name="docs",
embedding_function=openai_ef
)

3. Chroma 的元数据过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 添加带元数据的文档
collection.add(
documents=["技术文档", "产品文档"],
ids=["d1", "d2"],
metadatas=[
{"category": "tech", "author": "张三"},
{"category": "product", "author": "李四"}
]
)

# 查询时过滤
results = collection.query(
query_texts=["如何部署"],
n_results=5,
where={"category": "tech"} # 只在技术文档中搜索
)

4. Chroma 的局限性

限制 影响
单机架构 无法水平扩展,数据量上限约百万级
索引单一 仅支持 HNSW,无法根据场景切换
过滤简单 不支持复杂布尔组合,性能一般
无分布式 没有副本、分片机制,单点故障风险

一句话总结:Chroma 是向量数据库界的 SQLite——简单好用,但别指望它扛生产级大流量。


五、Milvus:生产级大规模首选

1. 为什么选 Milvus

Milvus 定位是云原生分布式向量数据库,CNCF 沙箱项目。适合以下场景:

  • 大规模生产应用:向量数 > 百万级,甚至亿级
  • 高并发实时检索:要求低延迟、高吞吐
  • 复杂过滤需求:需要结合标量字段过滤
  • 多云部署:支持 Kubernetes、Docker、云服务

2. Milvus 架构解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌─────────────────────────────────────────────────────────────┐
│ SDK Layer │
│ Python / Go / Java / Node.js / REST │
├─────────────────────────────────────────────────────────────┤
│ Proxy (接入层) │
│ 负责请求解析、路由、负载均衡 │
├───────────────┬───────────────┬─────────────────────────────┤
│ Query Coord │ Data Coord │ Index Coord │ Root Coord │
│ (查询协调) │ (数据协调) │ (索引协调) │ (总协调) │
├───────────────┴───────────────┴─────────────────────────────┤
│ Query Node Data Node Index Node │
│ (查询执行) (数据写入) (索引构建) │
├─────────────────────────────────────────────────────────────┤
│ etcd (元数据) + MinIO (存储) │
└─────────────────────────────────────────────────────────────┘

核心组件职责:
- Root Coord:全局协调者,处理 DDL(创建集合、索引等)
- Query Coord:查询节点调度,负载均衡
- Data Coord:数据节点调度,segment 管理
- Index Coord:索引构建任务调度

3. Milvus 索引选型实战

不同规模和场景,索引选择策略不同:

数据规模 内存预算 推荐索引 参数建议
< 100万 充足 FLAT 精确搜索,召回率100%
100万-1000万 充足 HNSW M=16, efConstruction=256
100万-1000万 紧张 IVF-FLAT nlist=1024
> 1000万 紧张 IVF-PQ nlist=1024, m=8, nbits=8
> 1亿 极紧张 DISKANN 磁盘索引,SSD必备
1
2
3
4
5
6
7
8
9
10
11
12
13
from pymilvus import MilvusClient, IndexType, MetricType

# 创建 HNSW 索引
index_params = MilvusClient.prepare_index_params()
index_params.add_index(
field_name="vector",
index_type=IndexType.HNSW,
metric_type=MetricType.COSINE,
params={"M": 16, "efConstruction": 256}
)

# 查询参数:动态调整 ef 提高召回率
search_params = {"params": {"ef": 64}} # ef越大,召回率越高,延迟越长

4. Milvus 集合设计最佳实践

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
from pymilvus import MilvusClient

client = MilvusClient("http://localhost:19530")

# 创建集合:向量字段 + 标量字段
client.create_collection(
collection_name="products",
dimension=1536, # OpenAI text-embedding-3-small 维度
metric_type="COSINE",
auto_id=False,
fields=[
{"name": "id", "dtype": "VARCHAR", "max_length": 64, "is_primary": True},
{"name": "vector", "dtype": "FLOAT_VECTOR", "dim": 1536},
{"name": "title", "dtype": "VARCHAR", "max_length": 256},
{"name": "category", "dtype": "VARCHAR", "max_length": 64},
{"name": "price", "dtype": "FLOAT"},
{"name": "created_at", "dtype": "INT64"} # 时间戳
]
)

# 创建标量字段索引(加速过滤)
client.create_index(
collection_name="products",
field_name="category",
index_type="Trie" # 字符串用 Trie,数值用 STL_SORT
)

5. Milvus 过滤查询实战

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 过滤表达式语法
results = client.search(
collection_name="products",
data=[[0.1, 0.2, ...]], # 查询向量
filter='category == "electronics" and price >= 100 and price <= 500',
limit=10,
output_fields=["title", "category", "price"]
)

# 复杂过滤:支持 AND、OR、NOT、IN、LIKE
filter_expr = '''
(category in ["electronics", "books"])
and price > 50
and created_at > 1700000000
'''

6. Milvus 部署方案

部署方式 适用场景 复杂度
Milvus Lite 开发测试,pip 安装 最低
Docker Compose 单机生产,快速部署
Docker + Kubernetes 集群部署,高可用
Zilliz Cloud 全托管,零运维
1
2
3
4
5
6
7
# Docker Compose 快速部署(适合单机生产)
wget https://github.com/milvus-io/milvus/releases/download/v2.4.0/milvus-compose.yml
docker-compose -f milvus-compose.yml up -d

# Milvus Lite 开发测试(Python 直接使用)
pip install milvus
# 自动启动嵌入式 Milvus,无需额外部署

六、选型决策树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
开始选型

├─ 数据规模多大?
│ ├─ < 10万向量 → Chroma 足够
│ ├─ 10万-100万 → Chroma 单机 / Milvus Lite
│ ├─ 100万-1000万 → Milvus 单机 / Qdrant
│ └─ > 1000万 → Milvus 集群 / Pinecone Serverless

├─ 是否需要强过滤?
│ ├─ 简单过滤 → Chroma / Milvus
│ └─ 复杂过滤 → Qdrant(性能最优)

├─ 是否接受云服务?
│ ├─ 必须本地 → Milvus / Qdrant / Chroma
│ └─ 可以云端 → Pinecone / Zilliz Cloud

├─ 团队技术栈?
│ ├─ Python 主导 → Chroma(最友好)
│ ├─ Go/Rust 主导 → Milvus / Qdrant
│ └─ 已有 MongoDB → Atlas Vector Search

└─ 运维能力?
├─ 无运维团队 → Chroma / Pinecone
├─ 有运维团队 → Milvus / Qdrant

七、实战建议

1. RAG 应用架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
用户查询


Embedding 模型(text-embedding-3-small / bge-large-zh)


向量数据库(Chroma / Milvus)
│ ┌──────────────────────────────────┐
│ │ Collection: documents │
│ │ ├─ vector: [1536 dimensions] │
│ │ ├─ content: 原始文本 │
│ │ ├─ metadata: {source, page, ...} │
│ │ └─ index: HNSW (M=16) │
│ └──────────────────────────────────┘


Top-K 相关文档(K=5~10)


LLM 生成回答(GPT-4 / Claude / DeepSeek)

2. 向量维度选择

Embedding 模型 维度 特点 推荐场景
text-embedding-3-small 1536 OpenAI,通用 英文为主
text-embedding-3-large 3072 OpenAI,更精准 高精度需求
bge-large-zh 1024 中文优化 中文场景
bge-m3 1024 多语言 跨语言场景

注意:维度越高,精度越高,但存储和计算成本也越高。1536维是性价比平衡点。

3. 内存估算

1
2
3
4
5
6
7
单向量存储开销 = 维度 × 4字节 + 元数据开销
索引额外开销 ≈ 基础存储 × 索引系数

示例:100万向量,1536维,HNSW索引
基础存储:1,000,000 × 1536 × 4 = 6.14 GB
索引开销:6.14 × 1.5 ≈ 9.2 GB
总内存需求:约 10 GB

总结

向量数据库选型的核心逻辑:

阶段 推荐方案
原型验证 Chroma,几行代码搞定
小规模生产 Chroma 单机 / Milvus Lite
大规模生产 Milvus 集群 / Qdrant
零运维需求 Pinecone / Zilliz Cloud

Chroma 是入门首选,简单好用,适合快速验证想法。
Milvus 是生产首选,架构成熟,生态完善,能扛大流量。


Oracle SQL*LoaderOracle 数据库管理系统中一个强大的工具,用于高效地将大量数据从外部文件加载到 Oracle 数据库中。它提供了一种快速、灵活的方式来导入数据,适用于各种数据格式和文件类型。本文将介绍 SQL*Loader 的基本概念、工作原理以及实际应用场景。

一、什么是 SQL*Loader?

SQL*Loader 是一个用于导入数据的实用程序,允许用户将普通文件、CSV 文件等外部数据源中的数据加载到 Oracle 数据库表中。它是 Oracle 数据库中的一个标准工具,可以轻松地处理大规模的数据加载任务。

二、SQL*Loader 的工作原理

SQL*Loader 的工作原理比较简单:

  • 控制文件定义:编写一个控制文件,其中指定了要加载的目标表、字段映射关系、数据格式等信息。控制文件是 SQL*Loader 的核心配置文件之一;

  • 准备外部数据文件:用户需要准备一个包含待加载数据的外部文件,可以是纯文本文件、CSV 文件等格式;

  • 运行 SQL*Loader:通过命令行或者其他界面工具运行 SQL*Loader,并指定控制文件和数据文件的位置。SQL*Loader 将根据控制文件加载到目标表中;

  • 数据加载SQL*Loader 按照控制文件中指定的规则,逐行解析外部数据文件,并将数据插入到目标表中;

三、SQL*Loader 控制文件

这是一个控制文件模板样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
LOAD DATA
INFILE 'data.csv' -- 指定外部数据文件的路径
INTO TABLE employees -- 指定目标表名
CHARACTERSET UTF8 -- 指定外部数据文件的字符集编码为 UTF-8
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' -- 指定字段分隔符和可选的字段包裹符
(
employee_id, -- 目标表的列名
first_name,
last_name,
email,
hire_date DATE 'YYYY-MM-DD' -- 数据格式化,确保日期格式正确
)
WHEN (hire_date >= '2022-02-01')
  • LOAD DATA 表示开始加载数据的声明;
  • INFILE 'data.csv' 指定了外部数据文件的路径。你需要将 data.csv 替换为实际的外部数据文件名,并确保文件路径正确;
  • INTO TABLE employees 指定了目标表名为 employees,即将数据加载到 employees 表中。你需要将 employees 替换为实际的目标表名;
  • CHARACTERSET UTF8 指定外部数据文件的字符集编码为 UTF-8
  • FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' 定义了字段的分隔符和可选的字段包裹符。在这个示例中,字段被逗号分隔,并且可能被双引号包裹。根据实际情况,你可能需要调整这些选项;
  • (employee_id, first_name, last_name, email, hire_date DATE 'YYYY-MM-DD') 定义了要加载的字段和它们的数据类型。确保与目标表的列名和数据类型匹配。在这个示例中,hire_date 被格式化为日期,并指定了日期的格式;
  • WHEN (hire_date >= '2022-01-01') 定义了加载数据的条件,只有满足条件的数据,才会被导入 Oracle 数据库;

四、SQL*Loader 的应用场景

SQL*Loader 在实际应用中有广泛的用途,例如:

  • 数据迁移和导入:当需要将外部数据源中的数据导入到 Oracle 数据库中时,SQL*Loader 是一个好的选择。它可以通过灵活的配置,处理大量的数据;
  • 数据集成和同步:在数据集成和同步的场景中,SQL*Loader 可以用于将不同系统或者数据源中的数据整合到同一数据库中,以便进行分析、报告等操作;
  • 日常数据加载:从外部系统中获取数据,并将其加载到 Oracle 数据库中进行进一步处理。SQL*Loader 可以自动化这一过程,提高数据处理的效率;

五、实际应用

以下是一个简单的示例,演示如何使用 SQL*LoaderCSV 文件加载到 Oracle 表中:

  • 创建一个控制文件 data.ctl,定义目标表和字段映射关系:
1
2
3
4
5
6
7
8
9
10
11
sqlCopy codeLOAD DATA
INFILE 'data.csv'
INTO TABLE employees
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
( employee_id,
first_name,
last_name,
email,
hire_date DATE 'YYYY-MM-DD'
)
WHEN (hire_date >= '2022-02-01')
  • 准备外部数据文件 data.csv,包含待加载的数据。
employee_id first_name last_name email hire_date
001 zhangsan@gmail.com 2023-02-01
002 lisi@gmail.com 2023-02-02
  • 在命令行中运行 SQL*Loader
1
2
bashCopy code
sqlldr username/password@database control=data.ctl

这样,SQL*Loader 就会将 data.csv 中的数据加载到名为 employees 的表中。

六、结论

Oracle SQL*Loader 是一个强大的数据加载工具,可用于高效地将外部数据加载到 Oracle 数据库中。通过简单的配置和命令,用户可以轻松地处理大量的数据加载任务,提高数据处理的效率和可靠性。


一、跨库分页查询

对于一定数量级的表,如订单表,通常采用分库分表的方式保存数据。根据指定字段,如果用户ID,散列数据到不同的库中。那么,如果需要按照下单时间分页查询订单信息,就涉及到跨库查询。

假设有45笔订单,存于三个库中,散列算法是 OrderID % 3,则数据分布为:

如果以每页五个订单,查询第二页的所有订单,则单库查询 sql 为:

1
select * from order_info order by id limit 5 offset 5;

但跨库查询就行不通了。下面,主要有三种方案可以用于跨库分页查询:

  • 全局查询法
  • 禁止跳页查询法
  • 二次查询法

二、全局查询法

全局查询法,需要在每个分库中执行查询语句,然后再程序中排序,再定位切割到指定的数据段。

如果需要查询第二页订单,需要查询每个库的前二页数据:

1
2
3
select * from order_info_1 order by id limit 10;
select * from order_info_2 order by id limit 10;
select * from order_info_3 order by id limit 10;

结果为:

将以上三个库的查询结果排序:

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

那么第二页的订单列表为:

6,7,8,9,10

小结:对于低页码查询,全局查询法是可以应付的,但是,当页码越来越大,查出来的数据也就越来越多,需要排序的数据也越来越多,查询效率也就会越来越慢。

三、禁止跳页查询法

全局查询法的一个显著缺陷,就是随着页码越来越大,查询的数据量也越来越大。那么,如果禁止跳页查询,且每次查询都以上次查询的最大ID为基点,就可以保证每次查询的数据量都是相同的。

查询第一页数据:

将以上三个库的查询结果排序:

1,2,3,4,5,6,7,8,9,10,11,12,13,14,15

那么第一页的订单列表为:

1,2,3,4,5

查询第二页数据:

第一页的订单ID最大值为5,因此第二页的订单ID起始值应大于5,查询得到:

将以上三个库的查询结果排序:

6,7,8,9,10,11,12,13,14,15,16,17,18,19,20

那么第二页的订单列表为:

6,7,8,9,10

小结:禁止跳页查询法,保证每次查询的数据量是相同的,避免了分页查询带来的性能衰减问题;但禁止跳页也是功能缺陷,没法一步定位到指定数据段。

四、二次查询法

二次查找法,既满足跳页查询,也能避免分页查询性能衰减。为了解释这一思想,我们以查询第三页订单数据为例。单库查询语句:

1
select * from order_info order by id limit 5 offset 10;

之所以叫二次查询法,当然需要查询两次。这两次查询有什么不同,希望通过以下四个步骤说清楚:

第一步:语句改写

select * from order_info order by id limit 5 offset 10 改写成 select * from order_info order by id limit 5 offset 3。偏移量10变成3,是基于10/3计算得出的。将语句在三个库分别执行,得到数据:

第二步:找最小值

  • 第一个库:最小数据为8
  • 第二个库:最小数据为11
  • 第三个库:最小数据为12

因此,从三个库中拿到的最小数据为8。

第三步:第二次语句改写

这次需要把 select * from order_info order by id limit 5 offset 3 改写成一个between语句,起点是最小的OrderID,终点是原来每个分库各自返回数据的最大值:

  • 第一个分库改写为: select * from order_info order by id where id between id_min and 22
  • 第二个分库改写为: select * from order_info order by id where id between id_min and 23
  • 第三个分库改写为: select * from order_info order by id where id between id_min and 24

查询结果如下:

第四步:找到id_min的全局偏移量

第一次查询的偏移量为3,那么每一个库的第一个目标数据的偏移量应该都是4。因此可知每个库的id_min的偏移量:

  • 第一个库:8就是id_min,偏移量为4;
  • 第二个库:11的偏移量为4,那么id_min的偏移量就是1;
  • 第三个库:12的偏移量为4,那么id_min的偏移量就是3;

因此id_min的全局偏移量为:4 + 1 + 3 = 8。

第五步:定位目标数据

  • 第一个库:8,13,14,19,22
  • 第二个库:9,10,11,16,17,18,23
  • 第三个库:12,15,20,21,24

经过排序,得到:

8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24

因为id_min的全局偏移量为8,最终结果需要 limit 5 offset 10,因此需要向后推移10 - 8 = 2 位,然后再取5位,得到:

11,12,13,14,15

小结:二次查找法,既避免了数据越处理越多,也支持跳转查询。但其也存在短板,需要查询两次,才能拿到目标数据。


一、零拷贝技术

零拷贝技术,是相对于传统 IO 的一种技术思想。传统 IO :读写数据是在用户空间和内核空间来回复制,而内核空间的数据是通过操作系统层面的 IO 接口从磁盘读取或写入的,中间也需要多次拷贝,因此效率较低。零拷贝技术,目的是尽可能地减少上下文切换和拷贝次数,提升操作性能。

二、传统 IO 实现原理

当应用服务接收客户端的请求时,传统 IO 通常需要两种系统调用:

1
2
3
4
// 读取
read(file, tmp_buf, len);
// 写入
write(socket, tmp_buf, len);

从细分图中可知,虽然只是简单的读写操作,但内部的流程还是比较复杂的。

一次读写将发生 4 次上下文切换:

  • 读取数据:从用户态切换到内核态;
  • 读取完毕:内核完成数据准备,从内核态切换到用户态;
  • 写入数据:从用户态切换到内核态;
  • 写入完毕:内核完成数据写入,从内核态切换到用户态;

一次读写将发生 4 次数据拷贝 (2 次 DMA 拷贝 + 2 次 CPU 拷贝):

  • 第一次拷贝 (DMA):把磁盘文件数据拷贝到内核缓冲区;
  • 第二次拷贝 (CPU):把内核缓冲区的数据拷贝到用户缓冲区,供应用程序使用;
  • 第三次拷贝 (CPU):把用户缓冲区的数据拷贝到内核 socket 缓冲区;
  • 第四次拷贝 (DMA):把内核 socket 缓冲区的数据拷贝到网卡缓冲区;

虽然一次上下文切换需耗时只有几微秒,但在高并发场景中,这种延迟容易被积累和放大,从而影响整体性能。此外,磁盘和网卡操作速度远远小于内存,而内存操作速度又远远小于 CPU,4 次拷贝将严重拖慢系统性能。因此,提高 IO 性能,需要从减少上下文切换次数和数据拷贝次数两方面入手。

三、零拷贝实现

基于以上的讨论,可知零拷贝技术的设计思路:尽可能地减少上下文切换次数和数据拷贝次数。

零拷贝的具体实现方式有:

  • mmap:将内核空间和用户空间的虚拟地址映射到同一物理地址;
  • sendfile:直接把内核缓冲区的数据拷贝到网卡缓冲区;
  • direct IO:在应用层与磁盘、网卡之间建立直接通道;
3.1 mmap 实现零拷贝

在介绍 mmap() 的作用机制之前,先介绍一个新概念:虚拟内存。虚拟内存是现代操作系统中普遍使用的内存结构,使用虚拟地址代替物理内存,有两点好处:一是多个虚拟地址可以指向同一个物理地址;二是虚拟内存空间远远大于物理内存空间。

在传统 IO 中,read() 调用会把内核缓冲区的数据拷贝到用户缓冲区,耗时又耗力。如果把内核空间和用户空间的虚拟地址映射到同一个物理地址,那么就不需要 CPU 来回复制了。

mmap() 正是利用了虚拟内存的这一特性,取代传统 IO 的 read() 操作,并将内核缓冲区和用户缓冲区地址映射到同一物理内存地址,省去一次 CPU 拷贝的过程,提升 IO 性能。具体过程如下:

  • 应用进程调用 mmap() 后,DMA 会把磁盘文件数据拷贝到内核缓冲区;
  • 应用进程跟操作系统内核共享这个缓冲区;

  • 应用进程再调用 write(),直接将内核缓冲区的数据拷贝到内核 socket 缓冲区;

  • DMA 把内核 socket 缓冲区的数据拷贝到网卡缓冲区;

从调用过程可知,与传统 IO 相比,mmap() + write 只减少了 1 次 CPU 拷贝,仍然要发生 4 次上下文切换和 3 次数据拷贝。

3.2 sendfile() 实现零拷贝

senfile() 是 Linux 提供的,专门用于发送文件的系统调用函数。sendfile() 可以替代传统 IO 的 read()、write() 函数,这意味着将省去 2 次上下文切换。此外,数据拷贝路径也有所优化,具体的优化方案与 Linux 内核版本有关,因为在 2.4 版本之后,Linux 提供了 SG-DMA 技术,它将提供比 DMA 技术更进一步的优化策略。

在 2.4 版本之前,CPU 可以直接把内核缓冲区的数据拷贝到内核 socket 缓冲区,省去拷贝到用户缓冲区这一步,因此还存在 2 次上下文切换和 3 次数据拷贝。

具体执行步骤:

  • DMA 把磁盘文件数据拷贝到内核缓冲区;
  • CPU 把内核缓冲区的数据拷贝到内核 socket 缓冲区;
  • DMA 把内核 socket 缓冲区的数据拷贝到网卡缓冲区;

在 2.4 版本之后,引入了 SG_DMA 技术,如果相应的网卡支持该技术,那么就可以把内核缓冲区的数据直接拷贝到网卡缓冲区,也就是说还存在 2 次上下文切换和 2 次数据拷贝。

具体执行步骤:

  • DMA 把磁盘文件数据拷贝到内核缓冲区;
  • 把内核缓冲区描述符和数据长度传到内核 socket 缓冲区;
  • SG-DMA 直接把内核缓冲区的数据拷贝到网卡缓冲区;

3.3 direct IO

直接 IO 是在用户缓冲区和磁盘、网卡之间建立直接通道的技术设计。直接 IO 在读写数据时,可以绕开内核,减少上下文切换和数据拷贝的次数,从而提高效率。

具体执行步骤:

  • DMA 把磁盘文件数据直接拷贝到用户缓冲区;
  • DMA 把用户缓冲区的数据直接拷贝到网卡缓冲区;

直接 IO 使用直接通道操作数据,由应用层完全管理数据,其优缺点也是很明显的。

优点:

  • 应用层与磁盘、网卡建立直接通道,减少了上下文切换和数据拷贝的次数,速度更快;
  • 数据直接缓存在应用层,应用可以更加灵活得操作数据;

缺点:

  • 在应用层引入直接 IO,需要应用层自主管理,给系统增添了额外的复杂度;
  • 若数据不在应用层缓冲区,那么将直接操作磁盘文件读写,将大大拖慢性能;