AI 读书笔记
AI 编程助手 Quest 1.0:把执行交给 AI,把选择留给人类
核心理念:人类“品味”是人机协作的终极壁垒
- “品味” ≠ 审美,而是决策力:在众多可行方案中判断“哪个是对的选择”,尤其体现为“选择不做”(如舍弃文件树导航,拒绝向下兼容)。
- AI 擅长执行与优化,但缺乏责任意识与经验直觉;人类凭借踩坑记忆、业务理解与后果承担能力,守住质量、边界与必要性底线。
- “品味”是未来人类区别于 AI 的核心差异,也是 AI Coding 中 human-in-the-loop 不可替代的价值。
Quest 1.0 的关键升级:为 SOTA 而生,专注"自主编程"
- 架构定位:专为当前最优(SOTA)大模型(如 Claude Opus/Codex/Gemini)深度优化,不兼容旧模型、不提供模型切换选项,追求 Token 效率与产物质量极致。
- 交互范式革新:
- ✅ 舍弃代码导航 → 转向“阅读意图”(Spec/测试/结果),代码降级为“中间产物”;
- ✅ 对话窗口为主视图 → 降低非专业开发者门槛,同时打破研发者技术栈认知边界(如后端工程师无需懂前端即可驱动前端开发)。
模式对比:Quest(自主编程) vs Editor(协同编程)
更高级的模式是视角更上移的模式。人的注意力是有限的,更关注结果,结果更大-总成本和产出更大;更关注细节,则质量更好。
| 维度 | Quest 模式 | Editor 模式 |
|---|---|---|
| 角色定位 | 架构师(关注 Spec、交付、问题抽象) | 导师(提需求、审代码、微调) |
| 介入程度 | 少干预、AI 自主完成端到端任务 | 高频人机协同、逐步确认与修正 |
| 适用场景 | 新项目、AI 原生技术栈、高效率交付 | 存量生产项目、小范围确定性改动 |
实践突破:Skill 驱动的 DevOps 自动化闭环
以某内部压测项目为例,展示自主编程模式如何超越“写代码”:
- ✅ 自然语言驱动全链路:Spec → 编码 → Docker 构建 → Helm 部署 → K8s 任务下发 → 压测执行 → 报告生成;
- ✅ Skill 是关键使能器:通过预置 k8s-benchmark skill,让 AI 编程助手感知集群、操作资源、读取日志、自动回滚,实现“无人干预的任务闭环”;
- ✅ 本质是构建反馈回路:AI 写代码 → 自动部署 → 运行验证 → 结果驱动修正,人类仅在“结果不符预期”时介入——从“手工匠人”升级为“流水线设计师”
深层反思:AI 时代的“认知债务”与开发者进化
- 警惕“AI 代劳导致的能力退化”:不手写 SQL → 不懂索引;不写并发 → 不解死锁;
- 提出务实建议:定期关闭 AI,手写关键代码,保持对底层机制的敏感度与接管能力;
- 最终回归初心:AI 编程助手的自主编程模式不是取代开发者,而是放大人类独有的"品味"——在 AI 的无限可能性中,坚定划出那条"值得做"的边界。
从 Rostow 五阶段模型看技术与组织的演进曲线
1960 年,经济学家 Walt Rostow 在《经济增长阶段论》(The Stages of Economic Growth)中提出了经典的五阶段发展模型。这一模型不仅适用于国家经济,同样可以映射到技术团队、产品乃至 AI 能力的演进路径:
| 阶段 | 经济学定义 | 技术/AI 类比 | 特征 |
|---|---|---|---|
| 1. 传统社会 | 农业主导、技术有限、社会结构僵化 | 手工作坊式开发 | 无标准化流程,依赖个人经验,知识不沉淀 |
| 2. 起飞前准备 | 基础设施投资、教育普及、创业萌芽 | 工程化建设期 | 引入 CI/CD、代码规范、文档体系,积累技术资产 |
| 3. 起飞阶段 | 快速工业化、关键产业驱动、投资超过临界值 | AI 辅助开发爆发期 | AI 工具普及,生产力跃升,新范式确立(如 Quest 模式) |
| 4. 迈向成熟 | 经济多元化、技术广泛应用、高储蓄与投资 | 人机协作深化期 | AI 成为基础设施,人类聚焦决策与品味,组织能力全面升级 |
| 5. 大众消费时代 | 消费导向、高生活水平、服务业驱动 | 创新消费与价值创造期 | 技术红利普惠,关注点从"怎么做"转向"做什么"与"为什么做" |
第六阶段的警示:停滞与衰退
近年来,有学者提出 Rostow 模型缺失的第六阶段——“膨胀式衰退”(Bloated Decline):
- 去工业化:制造业流失,过度依赖金融与服务
- 过度消费:投资不足,资本追逐短期回报
- 生产力停滞:创新乏力,组织僵化
- 政治俘获:既得利益集团阻碍变革
映射到技术组织:
当 AI 带来的效率红利被挥霍于"更快的平庸"而非"更高的价值",当开发者习惯于 AI 代劳而丧失底层理解,当组织不再追求技术突破而沉溺于存量博弈——第六阶段便悄然而至。
给 AI 时代开发者的启示
- 没有永恒的巅峰:Rostow 模型的核心缺陷是假设"第五阶段是终点"。实际上,经济增长没有终点,技术演进也没有终点——爬上一座山峰,只是为了继续攀登下一座。
- 警惕"到达顶峰"的心态:当团队认为"我们已经很先进了",恰恰是衰退的开始。中国的目标不是与美国一起"欣赏风景",而是持续向上攀登。
- 两条路径的抉择:第五阶段之后,要么走向衰退,要么走向重塑——通过自动化与前沿技术开启新一轮增长。选择权在人类手中。
Claude 智能体生态系统:技能、提示词、项目、MCP 与子代理的协同之道
核心理念:五个组件,一个目标
Claude 的智能体生态系统由 技能 (Skills)、提示词 (Prompts)、项目 (Projects)、子代理 (Sub-agents)、MCP 五个组件构成。它们各有定位,但目标一致:让 AI 在正确的时间做正确的事,让人类专注于不可替代的决策。
五元对比:何时选用什么?
| 组件 | 本质 | 核心作用 | 持久性 | 典型场景 |
|---|---|---|---|---|
| 技能 | 专业知识手册 | 教 Claude “怎么做” | 跨对话复用 | 品牌规范、代码审查标准、数据分析方法 |
| 提示词 | 即时指令 | 告诉 Claude “做什么” | 单次对话有效 | “总结一下”“优化这段文字”“检查安全问题” |
| 项目 | 独立工作空间 | 提供背景知识库 | 项目内始终可用 | Q4 产品发布、竞品研究、长期追踪的任务 |
| 子代理 | 专门 AI 助手 | 独立处理特定任务 | 跨会话存在 | 代码审查、安全审计、市场研究(带工具限制) |
| MCP | 通用连接器 | 打通外部数据/工具 | 持续连接 | Google Drive、GitHub、数据库、Slack |
关键决策原则
✅ 使用技能时
需要可复用的专业知识——当同一个指令在多个对话中重复出现,就该固化为技能。
例如:“按 OWASP 标准审查安全漏洞”“使用我们的品牌色和排版规则”
✅ 使用提示词时
一次性、对话式、即时性的需求——快速响应,无需沉淀。
例如:“让语气更专业”“格式化为表格”
✅ 使用项目时
需要持久上下文的长期工作——上传文档、设置自定义指令,成为该主题的知识基座。
例如:上传竞品资料、市场报告,每次对话自动继承
✅ 使用子代理时
需要独立执行+权限隔离——让专门的"数字员工"处理敏感或专注的任务。
例如:只读权限的代码审查代理、并行处理的技术分析代理
✅ 使用 MCP 时
需要连接外部系统——打破 AI 的信息孤岛,接入实时数据源。
例如:读取公司 Drive 的最新文档、查询生产数据库、操作 GitHub
组合威力:研究智能体的完整工作流
1 | |
人类的角色:设定研究方向、审视最终结论、在结果偏离预期时纠偏。
常见误区澄清
| 误区 | 正解 |
|---|---|
| ❌ 技能 vs 子代理二选一 | ✅ 互补关系——子代理可以加载技能获得专业知识 |
| ❌ 项目 vs 技能重复建设 | ✅ 分工明确——项目说"你需要知道这些",技能说"你要这样做" |
| ❌ MCP 替代技能 | ✅ 前后衔接——MCP 负责"连得上",技能负责"做得好" |
| ❌ 所有场景都用人机协同 | ✅ 模式分层——Quest 模式交给 AI 端到端,Editor 模式高频确认 |
深层启示:构建个人 AI 工位的方法论
- 从提示词开始,向技能沉淀——重复三次以上的指令,立即技能化
- 项目作为知识中枢——按主题组织,避免每次对话重新投喂上下文
- 子代理实现权责分离——危险操作限定只读,复杂任务拆分到专职代理
- MCP 打通数据闭环——减少人工搬运,让 AI 直接操作一手信息源
- 保留"无 AI 时间"——定期手写核心代码,防止认知债务累积
最终洞察:AI 生态的成熟标志,不是单个组件的强大,而是组合的优雅——像搭积木一样,根据任务复杂度灵活组装,让人类的"品味"始终处于决策中心。
RAG 架构全景:从分块到生成的完整流程
为什么 RAG 需要 Chunking?
在理解 RAG 架构之前,我们必须先回答一个核心问题:为什么不能直接把整个文档喂给 LLM?
Chunking 解决的三大根本问题
1. 上下文窗口限制
- 问题:即使是最先进的 LLM(如 GPT-4 的 128K tokens),也无法处理企业级知识库(数百万文档)
- 解决:将文档切分成小块,只检索最相关的几个块(通常 3-10 个),控制在 LLM 的上下文窗口内
2. 检索精度问题
- 问题:整篇文档的嵌入向量会"平均化"所有主题,导致语义模糊
- 例如:一篇同时讨论"数据库索引"和"Web 缓存"的文章,其向量既不精确匹配"索引优化"也不精确匹配"缓存策略"
- 解决:小块的嵌入向量语义更聚焦,能精确匹配用户查询的具体主题
3. 成本与延迟优化
- 问题:处理长文本的 Token 成本高昂,且推理速度慢
- 解决:只传递必要的上下文块,降低 API 调用成本并提升响应速度
Chunking 在 RAG 架构中的位置
Chunking 位于 Indexing(索引)阶段,是整个 RAG 流程的起点和基础:
1 | |
为什么必须在最前面?
- 决定检索粒度:块的大小直接影响后续检索的精度和召回率
- 影响嵌入质量:块的语义完整性决定了向量表示的准确性
- 不可逆操作:一旦索引完成,重新分块需要重建整个向量库
RAG 基础流程:三阶段架构
flowchart LR
subgraph Indexing["🟤 索引阶段(离线)"]
D[Documents] -->|Chunking| C[Chunks]
C -->|Embedding| VS[(Vectorstore)]
VS -.->|HNSW 索引| VS
end
subgraph Retrieval["🟠 检索阶段(在线)"]
Q[Question] -->|Embedding| QV[Query Vector]
QV -->|相似度搜索| VS
VS -->|Top-K| RD[Relevant Chunks]
end
subgraph Generation["🟢 生成阶段(在线)"]
RD --> CTX{Context}
Q --> CTX
CTX -->|PromptTemplate| PV[PromptValue]
PV --> LLM[LLM]
LLM --> CM[ChatMessage]
CM --> P[Parser]
P --> A[Answer]
end
style Indexing fill:#d7ccc8
style Retrieval fill:#ffe0b2
style Generation fill:#c8e6c9
三阶段的核心逻辑
| 阶段 | 时机 | 核心任务 | Chunking 的作用 |
|---|---|---|---|
| 🟤 Indexing | 离线预处理 | 文档 → 块 → 向量 → 存储 | 决定检索的基本单元 |
| 🟠 Retrieval | 用户提问时 | 查询向量化 → 相似度搜索 → 返回 Top-K 块 | 块的质量决定检索准确性 |
| 🟢 Generation | 检索后 | 块 + 问题 → Prompt → LLM → 答案 | 块的完整性决定生成质量 |
RAG 全景架构:七大模块的协同优化
flowchart TD
Q([Question]) --> QT_NODE[ ]
QT_NODE --> ROUTING_NODE[ ]
ROUTING_NODE --> QC_NODE[ ]
QC_NODE --> GDB[(Graph DB)]
QC_NODE --> RDB[(Relational DB)]
QC_NODE --> VS[("{} Vectorstore")]
GDB --> DOCS[Documents]
RDB --> DOCS
VS --> DOCS
DOCS --> FILTER{Filter}
FILTER --> LLM[🧠 LLM]
LLM --> ANS([Answer])
subgraph QT["🔴 Query Translation"]
direction LR
QD["Query Decomposition\nMulti-query / Step-back / RAG-Fusion\n分解或改写输入问题"]
HyDE["Pseudo-documents / HyDE\n生成假设性文档"]
end
subgraph RT["🟠 Routing"]
direction LR
LR_NODE["Logical routing\n让 LLM 根据问题选择数据库"]
SR_NODE["Semantic routing\nEmbed 问题并按相似度选 Prompt"]
end
subgraph QC["🟡 Query Construction"]
direction LR
SQL["Text-to-SQL\n(Relational DBs)"]
CYPHER["Text-to-Cypher\n(GraphDBs)"]
SELFQ["Self-query retriever\n(VectorDBs)"]
end
subgraph RTV["🟢 Retrieval"]
direction TB
RANK["Ranking\nRe-Rank / RankGPT / RAG-Fusion\n按相关性排序/过滤/压缩文档"]
REFINE["Refinement\nCRAG\n精炼结果"]
ACTIVE_R["Active retrieval\nCRAG\n若文档不相关则重新检索或从新数据源检索"]
RANK --> REFINE
end
subgraph IDX["🔵 Indexing"]
direction LR
CHUNK["Chunk Optimization\nSemantic Splitter\n优化 embedding 的 chunk 大小"]
MULTI["Multi-representation indexing\nParent Document / Dense X\n将文档转为紧凑检索单元(如摘要)"]
SPEC["Specialized Embeddings\nFine-tuning / ColBERT\n领域专属或高级 embedding 模型"]
HIER["Hierarchical Indexing\nRAPTOR\n多抽象层次的文档摘要树"]
end
subgraph GEN["🟣 Generation"]
direction LR
SELF_RAG["Active retrieval\nSelf-RAG / RRR\n用生成质量指导问题改写或重新检索"]
end
QT -.-> QT_NODE
RT -.-> ROUTING_NODE
QC -.-> QC_NODE
RTV -.-> FILTER
IDX -.-> VS
GEN -.-> LLM
flowchart TB
Q[Question] --> QT
Q --> R
Q --> QC
subgraph QT["🔴 Query Translation<br/>查询翻译"]
QT1["Multi-query / RAG-Fusion<br/>多查询扩展"]
QT2["Decomposition / Step-back<br/>问题分解与回退"]
QT3["HyDE<br/>假设文档嵌入"]
QT1 --- QT2 --- QT3
end
subgraph R["🟠 Routing<br/>路由"]
R1["Logical Routing<br/>LLM 根据问题选择数据源"]
R2["Semantic Routing<br/>Embed 后按相似度选 Prompt"]
R1 --- R2
end
subgraph QC["🟡 Query Construction<br/>查询构造"]
QC1["Text-to-SQL<br/>关系型数据库"]
QC2["Text-to-Cypher<br/>图数据库"]
QC3["Self-query Retriever<br/>向量库元数据过滤"]
QC1 --- QC2 --- QC3
end
QT --> DS
R --> DS
QC --> DS
subgraph DS["数据源"]
DS1[(Graph DB)]
DS2[(Relational DB)]
DS3[(Vectorstore)]
end
subgraph IDX["🟤 Indexing<br/>索引(Chunking 在此)"]
IDX1["Chunk Optimization<br/>五层级分块策略"]
IDX2["Multi-representation<br/>Parent Document / Dense X"]
IDX3["Specialized Embeddings<br/>Fine-tuning / ColBERT"]
IDX4["Hierarchical Indexing<br/>RAPTOR 树状摘要"]
IDX1 --- IDX2 --- IDX3 --- IDX4
end
IDX -.->|离线构建| DS
DS --> DOCS[Documents/Chunks]
subgraph RET["🟢 Retrieval<br/>检索后处理"]
RET1["Ranking<br/>Re-Rank / RankGPT / RAG-Fusion"]
RET2["Refinement<br/>CRAG 压缩过滤"]
RET3["Active Retrieval<br/>检索不相关时重新检索"]
RET1 --- RET2 --- RET3
end
DOCS --> RET
RET --> GEN_LLM[LLM]
GEN_LLM --> ANS[Answer]
subgraph GEN["🟣 Generation<br/>生成优化"]
GEN1["Active Retrieval<br/>Self-RAG / RRR"]
GEN2["根据生成质量<br/>决定是否重写问题或重新检索"]
GEN1 --- GEN2
end
ANS -.->|质量不佳时回退| GEN
GEN -.->|重写/重检索| QT
style QT fill:#ffcdd2
style R fill:#ffe0b2
style QC fill:#fff9c4
style IDX fill:#d7ccc8
style DS fill:#f5f5f5
style RET fill:#c8e6c9
style GEN fill:#e1bee7
七大模块的协同关系
| 模块 | 核心思想 | 与 Chunking 的关系 | 代表技术 |
|---|---|---|---|
| 🔴 Query Translation | 将用户问题改写为更适合检索的形式 | 查询优化后才能匹配到正确的块 | Multi-query、RAG-Fusion、HyDE |
| 🟠 Routing | 根据问题特征选择最佳数据源 | 决定去哪个向量库检索块 | Logical/Semantic Routing |
| 🟡 Query Construction | 将自然语言转为结构化查询 | 结构化查询可过滤块的元数据 | Text-to-SQL、Self-query |
| 🟤 Indexing | 优化文档的切分、表示与索引 | Chunking 的核心战场 | 五层级分块策略(见下文) |
| 🟢 Retrieval | 对检索结果进行排序、过滤、补充 | 对检索到的块进行二次优化 | Re-Rank、CRAG、Active Retrieval |
| 🟣 Generation | 根据生成质量决定是否回退重试 | 生成失败时可能需要重新检索块 | Self-RAG、RRR |
| ⚪ 主流程 | Question → 数据源 → Chunks → LLM → Answer | 块是检索和生成的桥梁 | 端到端 RAG Pipeline |
Chunking 的五个层级:从机械到智能的演进
核心理念:分块策略决定 RAG 系统的上限
在 RAG 的 Indexing 阶段,Chunking 是第一步,也是最关键的一步。不同的分块策略直接影响:
- 检索精度:块的边界是否在语义转换点?
- 上下文完整性:块内的信息是否自洽?
- 嵌入质量:块的语义是否聚焦?
从简单的固定大小切分到智能的 LLM 驱动分块,五个层级代表了从机械切割到认知理解的演进。
Level 1: Fixed-Size Chunking(固定大小分块)
原理
按照预设的字符数或 Token 数量,机械地将文本切分成等长片段。
特点
- ✅ 实现简单:无需复杂逻辑,直接按长度切割
- ✅ 性能高效:计算开销极低
- ❌ 语义割裂:可能在句子中间切断,破坏上下文
- ❌ 信息分散:关键信息可能跨越多个块
适用场景
- 对语义完整性要求不高的场景
- 需要快速原型验证的初期阶段
- 文本结构简单且均匀的内容
示例代码
1 | |
Level 2: Recursive Chunking(递归分块)
原理
先按自然分隔符(如段落、句子)切分,若某块超过阈值,则递归地进一步细分。
特点
- ✅ 尊重文本结构:优先保留段落和句子的完整性
- ✅ 灵活可控:通过多级分隔符(
\n\n→.→,)逐步细化 - ⚠️ 边界依赖:依赖明确的分隔符,对非结构化文本效果有限
适用场景
- 结构化文档(如技术文档、学术论文)
- 需要平衡语义完整性和块大小的场景
示例代码
1 | |
Level 3: Document Structure-Based Chunking(文档结构分块)
原理
利用文档的内在结构(标题、章节、列表)作为分块边界,保持逻辑单元的完整性。
特点
- ✅ 语义对齐:块与文档的逻辑结构天然对应
- ✅ 可解释性强:每个块对应明确的章节或主题
- ❌ 结构依赖:要求文档有清晰的层级结构(Markdown、HTML 等)
- ❌ 块大小不均:某些章节可能过长或过短
适用场景
- Markdown、HTML、PDF 等结构化文档
- 需要保留文档层级关系的知识库
示例代码
1 | |
Level 4: Semantic Chunking(语义分块)
原理
通过嵌入模型计算相邻句子的语义相似度,当相似度显著下降时创建新块。
特点
- ✅ 语义连贯:块内的句子主题一致,跨块时主题切换
- ✅ 自适应边界:无需预设分隔符,自动识别主题转换点
- ❌ 计算密集:需要为每个句子生成嵌入并计算相似度
- ⚠️ 阈值敏感:相似度阈值的选择影响块的粒度
适用场景
- 主题多变的长文本(如新闻、博客)
- 对语义完整性要求极高的场景
示例代码
1 | |
深入理解:Embedding 与相似度计算的本质
问题 1:RAG 中的双重 Embedding
是的,嵌入模型在 RAG 流程中会对文档和问题都进行 embedding。
flowchart TB
subgraph Offline["🟤 离线索引阶段"]
DOC[原始文档] -->|1. Chunking| CHUNKS[文档块]
CHUNKS -->|2. Embedding Model| DOC_VEC[文档向量]
DOC_VEC -->|3. 存储| VS[(向量数据库)]
end
subgraph Online["🟠 在线检索阶段"]
Q[用户问题] -->|4. 同一个 Embedding Model| Q_VEC[问题向量]
Q_VEC -->|5. 相似度计算| VS
VS -->|6. Top-K 最相似| RESULT[检索结果]
end
style Offline fill:#d7ccc8
style Online fill:#ffe0b2
NOTE1[关键:必须使用同一个模型<br/>才能保证向量空间一致]
NOTE1 -.->|约束| DOC_VEC
NOTE1 -.->|约束| Q_VEC
核心原理:
- 离线阶段:文档被切分成块后,每个块通过 embedding 模型转换为向量并存储
- 在线阶段:用户问题也通过同一个 embedding 模型转换为向量
- 相似度匹配:在同一向量空间中,计算问题向量与所有文档块向量的相似度
- 返回结果:相似度最高的 Top-K 个文档块被召回
为什么必须是同一个模型?
- 不同的 embedding 模型会产生不同维度、不同语义空间的向量
- 只有在同一向量空间中,相似度计算才有意义
- 例如:
all-MiniLM-L6-v2产生 384 维向量,text-embedding-ada-002产生 1536 维向量,两者无法直接比较
问题 2:Embedding 的本质——文本的数值化表示
是的,embedding 可以理解为对任何输入内容进行数值化的过程,但它不仅仅是简单的数值化。
flowchart LR
subgraph Traditional["传统数值化(One-Hot/TF-IDF)"]
T1[文本] -->|词频统计| V1[稀疏向量]
V1 -->|维度 = 词汇表大小| V1_EX["[0,0,1,0,0,...,0,1,0]<br/>维度:10000+"]
end
subgraph Modern["现代 Embedding(深度学习)"]
T2[文本] -->|神经网络| V2[密集向量]
V2 -->|维度 = 模型设定| V2_EX["[0.23, -0.45, 0.78, ...]<br/>维度:384/768/1536"]
V2 -->|语义编码| SEM[语义空间]
end
style Traditional fill:#ffcdd2
style Modern fill:#c8e6c9
NOTE["关键区别:<br/>1. 密集 vs 稀疏<br/>2. 语义 vs 词频<br/>3. 低维 vs 高维"]
NOTE -.-> V1
NOTE -.-> V2
Embedding 的三个层次理解:
层次 1:数值化(Numeralization)
将文本转换为计算机可处理的数字形式
- 传统方法:One-Hot 编码、TF-IDF
- 问题:无法捕捉语义,"国王"和"女王"的向量完全不相关
层次 2:向量化(Vectorization)
将文本映射到高维空间中的一个点
- 现代方法:Word2Vec、GloVe、BERT
- 优势:相似语义的词在向量空间中距离更近
层次 3:语义编码(Semantic Encoding)
将文本的含义压缩到固定维度的向量中
- 核心思想:相似含义 → 相似向量
- 实现方式:通过大规模语料训练神经网络,学习语义表示
示例对比:
| 方法 | “国王” 的表示 | “女王” 的表示 | 相似度 |
|---|---|---|---|
| One-Hot | [1,0,0,...,0] |
[0,0,1,...,0] |
0(完全不相关) |
| Word2Vec | [0.2, 0.5, -0.3, ...] |
[0.18, 0.52, -0.28, ...] |
0.85(高度相关) |
| Sentence-BERT | [0.23, -0.45, 0.78, ...] |
[0.21, -0.43, 0.76, ...] |
0.92(考虑上下文) |
关键洞察:
- Embedding 不是简单的"文本 → 数字",而是"文本 → 语义向量"
- 向量的每个维度不对应具体的词,而是抽象的语义特征
- 通过训练,模型学会将"语义相近"映射为"向量相近"
问题 3:余弦相似度——向量相似度的黄金标准
是的,这里的余弦相似度和 Elasticsearch 中的余弦相似度是同一个数学概念,它是比较两个向量(文档)相似程度的标准方法之一。
余弦相似度的数学原理
graph TB
subgraph Concept["核心概念"]
V1["向量 A<br/>[a₁, a₂, ..., aₙ]"]
V2["向量 B<br/>[b₁, b₂, ..., bₙ]"]
ANGLE["夹角 θ"]
V1 -.->|夹角| ANGLE
V2 -.->|夹角| ANGLE
end
subgraph Formula["计算公式"]
COS["cos(θ) = (A·B) / (||A|| × ||B||)"]
DOT["点积:A·B = Σ(aᵢ × bᵢ)"]
NORM["模长:||A|| = √(Σaᵢ²)"]
COS --> DOT
COS --> NORM
end
subgraph Range["取值范围"]
R1["-1:完全相反"]
R2["0:正交(无关)"]
R3["1:完全相同"]
R1 --> R2 --> R3
end
subgraph Visual["几何直观"]
direction LR
A["向量 A"] -->|θ=0°| B1["向量 B<br/>cos=1"]
A -->|θ=90°| B2["向量 B<br/>cos=0"]
A -->|θ=180°| B3["向量 B<br/>cos=-1"]
end
Concept --> Formula
Formula --> Range
Range --> Visual
为什么使用余弦相似度而非欧氏距离?
对比三种相似度度量:
| 度量方法 | 公式 | 特点 | 适用场景 |
|---|---|---|---|
| 余弦相似度 | cos(θ) = (A·B) / (‖A‖×‖B‖) |
只关注方向,不关注长度 | 文本相似度(长度不重要) |
| 欧氏距离 | d = √Σ(aᵢ-bᵢ)² |
关注绝对位置差异 | 图像、坐标(长度重要) |
| 点积 | A·B = Σ(aᵢ×bᵢ) |
同时考虑方向和长度 | 推荐系统(热度+相关性) |
余弦相似度的优势:
1 | |
核心洞察:
- 文本的语义由向量的方向决定,而非长度
- 重复的内容不应改变语义相似度
- 余弦相似度天然归一化到
[-1, 1],便于设置阈值
余弦相似度的计算流程可视化
flowchart TB
subgraph Input["输入"]
S1["句子 1:机器学习很有趣"]
S2["句子 2:深度学习很强大"]
end
subgraph Embedding["向量化"]
S1 -->|Embedding Model| V1["v1 = [0.2, 0.5, 0.3, -0.1]"]
S2 -->|Embedding Model| V2["v2 = [0.18, 0.52, 0.25, -0.08]"]
end
subgraph Calculation["计算步骤"]
V1 --> DOT["1. 点积<br/>A·B = 0.2×0.18 + 0.5×0.52 + 0.3×0.25 + (-0.1)×(-0.08)<br/>= 0.036 + 0.26 + 0.075 + 0.008 = 0.379"]
V2 --> DOT
V1 --> NORM1["2. 模长<br/>||A|| = √(0.2² + 0.5² + 0.3² + 0.1²) = 0.616"]
V2 --> NORM2["||B|| = √(0.18² + 0.52² + 0.25² + 0.08²) = 0.604"]
DOT --> COS["3. 余弦相似度<br/>cos(θ) = 0.379 / (0.616 × 0.604) = 0.379 / 0.372 = 1.02 ≈ 1.0"]
NORM1 --> COS
NORM2 --> COS
end
subgraph Result["结果解释"]
COS --> INTER["相似度 ≈ 1.0<br/>→ 两句话语义高度相关<br/>(都在讨论 AI 技术)"]
end
style Input fill:#e3f2fd
style Embedding fill:#fff9c4
style Calculation fill:#f3e5f5
style Result fill:#c8e6c9
与 Elasticsearch 的关系
Elasticsearch 中的余弦相似度:
ES 的 dense_vector 字段支持余弦相似度,查询示例如下:
1 | |
关键点:
- ES 的
cosineSimilarity函数返回[-1, 1] - 为了转换为分数,通常加 1.0 变为
[0, 2] - 底层数学原理与 Python 的
sklearn.metrics.pairwise.cosine_similarity完全相同
标准化程度:
- 余弦相似度是线性代数中的标准概念
- 在信息检索、推荐系统、NLP 领域广泛使用
- 几乎所有向量数据库(Pinecone、Weaviate、Milvus)都支持
问题 4:RAG 检索配置的深度解析
配置 1:分段召回 vs 全文召回
flowchart TB
subgraph Chunk["分段召回(主流)"]
DOC1[长文档] -->|Chunking| C1[块1]
DOC1 -->|Chunking| C2[块2]
DOC1 -->|Chunking| C3[块3]
Q1[问题] -->|匹配| C2
C2 -->|返回| R1[仅块2]
NOTE1["优势:精确匹配<br/>劣势:可能丢失上下文"]
end
subgraph Full["全文召回(少见)"]
DOC2[长文档] -->|整体 Embedding| V[文档向量]
Q2[问题] -->|匹配| V
V -->|返回| R2[整个文档]
NOTE2["优势:上下文完整<br/>劣势:噪声多、Token 消耗大"]
end
style Chunk fill:#c8e6c9
style Full fill:#ffcdd2
为什么主流选择分段召回?
| 维度 | 分段召回 | 全文召回 |
|---|---|---|
| 精确度 | ✅ 高(只返回相关段落) | ❌ 低(包含大量无关内容) |
| Token 消耗 | ✅ 低(每块 200-500 tokens) | ❌ 高(整篇文档可能上万 tokens) |
| 检索速度 | ✅ 快(向量库中块数量多但单个小) | ⚠️ 慢(文档向量维度高) |
| 上下文完整性 | ⚠️ 可能割裂 | ✅ 完整 |
混合策略:
- Parent Document Retriever:检索时返回小块,生成时提供大块或整篇文档
- Hierarchical Indexing:先检索章节,再检索段落
配置 2:向量召回 vs 关键词召回
flowchart TB
subgraph Vector["向量召回(语义搜索)"]
Q1["问题:如何提升模型性能?"] -->|Embedding| QV1[问题向量]
QV1 -->|余弦相似度| DB1[(向量库)]
DB1 -->|Top-K| R1["召回:<br/>1. 调参技巧<br/>2. 数据增强<br/>3. 模型蒸馏"]
NOTE1["优势:理解同义词、语义<br/>劣势:计算成本高"]
end
subgraph Keyword["关键词召回(BM25)"]
Q2["问题:如何提升模型性能?"] -->|分词| KW["关键词:提升、模型、性能"]
KW -->|TF-IDF/BM25| DB2[(倒排索引)]
DB2 -->|匹配| R2["召回:<br/>1. 模型性能优化指南<br/>2. 性能提升的10个技巧"]
NOTE2["优势:精确匹配、速度快<br/>劣势:无法理解同义词"]
end
subgraph Hybrid["混合召回(最佳实践)"]
Q3[问题] --> V3[向量召回]
Q3 --> K3[关键词召回]
V3 --> M[结果合并<br/>Reciprocal Rank Fusion]
K3 --> M
M --> R3[最终结果]
NOTE3["结合两者优势<br/>Elasticsearch 的 kNN + BM25"]
end
style Vector fill:#e1bee7
style Keyword fill:#fff9c4
style Hybrid fill:#c8e6c9
对比分析:
| 特性 | 向量召回 | 关键词召回 | 混合召回 |
|---|---|---|---|
| 同义词处理 | ✅ “汽车"能匹配"车辆” | ❌ 必须精确匹配 | ✅ 两者互补 |
| 专有名词 | ⚠️ 可能混淆相似名词 | ✅ 精确匹配 | ✅ 关键词兜底 |
| 语义理解 | ✅ 理解"如何"=“怎样” | ❌ 不理解语义 | ✅ 向量主导 |
| 计算成本 | 高(向量计算) | 低(倒排索引) | 中(并行计算) |
| 冷启动 | ⚠️ 需要训练 embedding | ✅ 无需训练 | ✅ 关键词兜底 |
实际应用建议:
- 纯向量召回:适合语义理解要求高的场景(客服、问答)
- 纯关键词召回:适合精确匹配场景(法律、医疗术语)
- 混合召回:适合大多数生产环境(70% 向量 + 30% 关键词)
配置 3:相似度阈值的深度解析
你的困惑来源于对"相似度"和"阈值"关系的误解。让我们彻底澄清:
误区纠正:相似度的正确理解
flowchart TB
subgraph Correct["✅ 正确理解"]
SIM1["相似度越高 = 越相似<br/>1.0 = 完全相同<br/>0.0 = 完全无关<br/>-1.0 = 完全相反"]
THR1["阈值越高 = 要求越严格<br/>阈值 0.9:只召回极相似的<br/>阈值 0.5:召回中等相似的<br/>阈值 0.1:召回几乎所有的"]
SIM1 --> THR1
end
subgraph Wrong["❌ 错误理解"]
SIM2["差异越大,相似度越接近1?<br/>(这是错误的!)"]
THR2["阈值越高,召回越多?<br/>(这是错误的!)"]
SIM2 -.->|实际相反| THR2
end
style Correct fill:#c8e6c9
style Wrong fill:#ffcdd2
阈值对召回行为的影响
核心规则:
- 阈值调高 → 要求更严格 → 召回数量减少(但精确度提高)
- 阈值调低 → 要求更宽松 → 召回数量增加(但噪声增多)
可视化示例:
flowchart TB
subgraph Example["实际案例"]
Q["问题:机器学习算法"]
D1["文档1:机器学习入门<br/>相似度:0.95"]
D2["文档2:深度学习原理<br/>相似度:0.82"]
D3["文档3:数据挖掘技术<br/>相似度:0.65"]
D4["文档4:Python 编程<br/>相似度:0.45"]
D5["文档5:前端开发<br/>相似度:0.12"]
Q --> D1
Q --> D2
Q --> D3
Q --> D4
Q --> D5
end
subgraph Threshold["不同阈值的召回结果"]
T1["阈值 = 0.9<br/>召回:文档1<br/>数量:1"]
T2["阈值 = 0.7<br/>召回:文档1、2<br/>数量:2"]
T3["阈值 = 0.5<br/>召回:文档1、2、3<br/>数量:3"]
T4["阈值 = 0.3<br/>召回:文档1、2、3、4<br/>数量:4"]
T1 -->|降低阈值| T2
T2 -->|降低阈值| T3
T3 -->|降低阈值| T4
end
style T1 fill:#ffcdd2
style T2 fill:#fff9c4
style T3 fill:#c8e6c9
style T4 fill:#e1bee7
阈值调优的实战策略
调优决策树:
1 | |
不同场景的推荐阈值:
| 场景 | 推荐阈值 | 理由 |
|---|---|---|
| 客服问答 | 0.75-0.85 | 需要高精确度,避免答非所问 |
| 文档检索 | 0.60-0.75 | 平衡召回率和精确度 |
| 推荐系统 | 0.50-0.65 | 需要多样性,宁可多召回 |
| 法律合规 | 0.85-0.95 | 必须精确匹配,不能有误 |
向量阈值 vs 关键词阈值
为什么两者的阈值语义不同?
1 | |
关键区别:
| 维度 | 向量阈值 | 关键词阈值 |
|---|---|---|
| 数学基础 | 余弦相似度(归一化) | BM25 分数(非归一化) |
| 取值范围 | [-1, 1] 或 [0, 1] |
[0, +∞),无上限 |
| 语义 | 几何夹角 | 词频权重 |
| 可比性 | 跨查询可比 | 跨查询不可比 |
| 调优难度 | 容易(固定范围) | 困难(需要根据语料调整) |
混合召回时的阈值策略:
1 | |
阈值调优的 A/B 测试方法
实验设计:
flowchart TB
subgraph Baseline["基线(阈值 0.7)"]
B1[100 个查询] --> B2[召回率:60%]
B2 --> B3[精确率:80%]
B3 --> B4[F1-Score:0.69]
end
subgraph Variant["变体(阈值 0.6)"]
V1[100 个查询] --> V2[召回率:75%]
V2 --> V3[精确率:70%]
V3 --> V4[F1-Score:0.72]
end
subgraph Decision["决策"]
B4 --> CMP{对比}
V4 --> CMP
CMP -->|F1提升| WIN["采用阈值 0.6"]
end
style Baseline fill:#e3f2fd
style Variant fill:#fff9c4
style Decision fill:#c8e6c9
评估指标:
- 召回率(Recall):相关文档中被召回的比例
- 精确率(Precision):召回文档中真正相关的比例
- F1-Score:召回率和精确率的调和平均数
Level 5: Agentic Chunking(智能体分块)
原理
利用大语言模型(LLM)理解文本的深层语义和逻辑关系,动态决定分块边界。LLM 可以识别:
- 主题转换点
- 因果关系链
- 论证结构
- 隐含的逻辑分段
特点
- ✅ 最高语义准确性:理解上下文、隐喻、复杂逻辑
- ✅ 极致灵活性:适应任何文本类型和风格
- ❌ 成本高昂:每次分块需调用 LLM API
- ❌ 速度慢:受 LLM 推理速度限制
- ⚠️ 上下文窗口限制:超长文档需分段处理
适用场景
- 高价值文档的精细处理(如法律合同、研究报告)
- 需要理解复杂逻辑关系的场景
- 对成本和延迟不敏感的应用
示例代码
1 | |
五个层级的对比总结
| 层级 | 核心机制 | 语义完整性 | 计算成本 | 适用场景 |
|---|---|---|---|---|
| Level 1: Fixed-Size | 固定长度切割 | ⭐ | 极低 | 快速原型、简单文本 |
| Level 2: Recursive | 多级分隔符递归 | ⭐⭐⭐ | 低 | 结构化文档 |
| Level 3: Structure-Based | 文档结构对齐 | ⭐⭐⭐⭐ | 低 | Markdown/HTML 文档 |
| Level 4: Semantic | 嵌入相似度计算 | ⭐⭐⭐⭐⭐ | 中 | 主题多变的长文本 |
| Level 5: Agentic | LLM 深度理解 | ⭐⭐⭐⭐⭐ | 高 | 高价值复杂文档 |
实践建议:如何选择分块策略?
决策树
1 | |
混合策略
在实际应用中,可以组合多种策略:
- 先结构后语义:用 Level 3 按章节粗分,再用 Level 4 细化长章节
- 分层索引:用 Level 2 创建粗粒度索引,用 Level 4 创建细粒度索引
- 动态降级:优先尝试 Level 5,失败时回退到 Level 4 或 Level 3
深层洞察:分块的本质是信息边界的划定
- Level 1-2 关注物理边界(长度、分隔符)
- Level 3 关注结构边界(文档层级)
- Level 4 关注语义边界(主题转换)
- Level 5 关注认知边界(逻辑完整性)
随着层级提升,分块从"机械切割"演进为"智能理解",但成本和复杂度也随之上升。最佳策略不是最高级的,而是最适配业务场景的。
Chunking 在 RAG 架构中的战略地位
为什么 Chunking 必须在 Indexing 阶段?
1 | |
三个不可逆的影响:
-
检索粒度锁定
- 一旦分块完成,检索的最小单元就被固定
- 块太大 → 检索不精确(噪声多)
- 块太小 → 上下文不完整(信息碎片化)
-
嵌入质量固化
- 向量库中存储的是块的嵌入向量
- 块的语义质量直接决定向量表示的准确性
- 重新分块 = 重建整个向量库(成本高昂)
-
成本结构确定
- 块的数量决定向量库的规模
- 块的大小影响检索和生成的 Token 消耗
- 前期优化 Chunking 可节省后续 90% 的成本
Chunking 与其他模块的协同关系
| 模块 | 依赖 Chunking 的方式 | 反向影响 |
|---|---|---|
| Query Translation | 查询改写后需要匹配到正确的块 | 查询模式可指导分块策略(如:FAQ 场景用问答对分块) |
| Routing | 路由到不同向量库时,每个库的分块策略可能不同 | 多数据源场景需要统一分块标准 |
| Retrieval | 检索的对象就是块,块的质量决定召回率 | Re-Rank 可弥补分块不佳导致的排序问题 |
| Generation | LLM 的输入上下文由块组成 | 生成失败时可能需要调整块的大小或数量 |
最佳实践:Chunking 的三阶段优化
1 | |
关键决策点:
- 初期:用 Fixed-Size 或 Recursive 快速搭建 MVP
- 优化期:根据检索日志分析,升级到 Semantic Chunking
- 成熟期:对高价值文档(合同、研报)使用 Agentic Chunking
从 RAG 到 Context:2025-2026 的架构演进
RAG 的角色转变:从"知识库"到"Context Engine"
2025 年的实践证明,RAG 的价值远不止于简单的"检索增强生成"。随着 AI Agent 的兴起,RAG 正在演变为更基础的 Context Engine(上下文引擎),成为所有 LLM 应用的数据基础设施。
flowchart TB
subgraph Traditional["传统 RAG(2024)"]
Q[用户问题] --> RAG[RAG 系统]
RAG --> ANS[答案]
RAG -.->|知识库| KB[(静态文档)]
end
subgraph Modern["Context Engine(2025-2026)"]
Q2[用户问题] --> AGENT[AI Agent]
AGENT --> CTX[Context Engine]
CTX --> RAG1[RAG: 领域知识]
CTX --> MEM[Memory: 对话历史]
CTX --> TOOLS[Tool Retrieval: 工具选择]
RAG1 --> AGENT
MEM --> AGENT
TOOLS --> AGENT
AGENT --> ANS2[复杂任务执行]
end
style Traditional fill:#ffcdd2
style Modern fill:#c8e6c9
核心变化:
- 数据范围扩展:从"文档知识"到"知识 + 记忆 + 工具"
- 服务对象升级:从"问答系统"到"AI Agent 的统一数据层"
- 架构定位提升:从"功能模块"到"企业级数据基础"
Context Engineering:上下文的智能组装
Context Engineering 是 2025 年兴起的全新领域,其核心是:如何为 LLM 动态组装最有效的上下文。
三大上下文来源
flowchart TB
subgraph Sources["上下文三大来源"]
KNO[领域知识<br/>RAG 系统]
MEM[对话记忆<br/>Memory 系统]
TOOL[工具描述<br/>Tool Retrieval]
end
subgraph Assembly["智能组装"]
KNO --> INTENT[意图理解]
MEM --> INTENT
TOOL --> INTENT
INTENT --> FILTER[语义过滤]
FILTER --> RANK[相关性排序]
RANK --> STITCH[动态拼接]
STITCH --> CTX[最终上下文]
end
CTX --> LLM[LLM 推理]
style Sources fill:#fff9c4
style Assembly fill:#c8e6c9
style CTX fill:#e1bee7
| 上下文类型 | 数据来源 | 检索特点 | 典型技术 |
|---|---|---|---|
| 领域知识 | 企业文档、知识库 | 静态、离线索引 | TreeRAG、GraphRAG、混合检索 |
| 对话记忆 | 用户历史交互 | 动态、流式写入 | 向量检索、时间衰减、语义总结 |
| 工具描述 | MCP 封装的服务 | 结构化、元数据丰富 | BM25、向量检索、参数匹配 |
Tool Retrieval:解决"工具选择瘫痪"
当企业通过 MCP 封装了成百上千个工具时,将所有工具描述塞入上下文会导致:
- Token 浪费:大量无关描述占用上下文窗口
- 选择困难:LLM 面对过多选项容易"幻觉"或错误调用
- 性能下降:上下文过长影响推理速度和质量
Tool Retrieval 的解决方案:
1 | |
Tool Retrieval 的技术路径:
- 工具描述向量化:为每个工具的名称、描述生成 embedding
- 元数据索引:建立工具类别、权限、参数的倒排索引
- Playbook 检索:检索"如何正确使用工具"的最佳实践指南
- 动态过滤:根据用户权限、上下文实时过滤可用工具
Memory 系统:对话记忆的智能管理
Memory 系统本质上是一个特殊的 RAG 系统,专门处理动态生成的对话数据。
Memory 的分层架构
flowchart TB
subgraph Memory["Memory 分层架构"]
WM[Working Memory<br/>当前会话上下文]
EM[Episodic Memory<br/>历史对话片段]
SM[Semantic Memory<br/>提取的知识和模式]
MM[Meta Memory<br/>用户偏好和反馈]
end
subgraph Flow["记忆流程"]
NEW[新对话] --> PARSE[解析和提取]
PARSE --> CLASSIFY{分类}
CLASSIFY -->|临时信息| WM
CLASSIFY -->|完整事件| EM
CLASSIFY -->|可复用知识| SM
CLASSIFY -->|用户反馈| MM
WM --> RETRIEVE[检索]
EM --> RETRIEVE
SM --> RETRIEVE
MM --> RETRIEVE
RETRIEVE --> CTX[上下文组装]
end
style Memory fill:#e1bee7
style Flow fill:#c8e6c9
| 记忆类型 | 存储内容 | 检索策略 | 典型应用 |
|---|---|---|---|
| Working Memory | 当前会话的临时信息 | 直接访问 | 保持对话连贯性 |
| Episodic Memory | 历史对话片段 | 语义 + 时间检索 | 跨会话上下文 |
| Semantic Memory | 从对话中提取的知识 | 向量检索 | 知识积累和复用 |
| Meta Memory | 用户偏好、反馈 | 精确匹配 | 个性化体验 |
Memory 与 RAG 的技术同源性:
- 相同的核心:都是基于检索的信息访问系统
- 不同的数据:RAG 处理静态文档,Memory 处理动态对话
- 互补的关系:RAG 提供领域知识,Memory 提供个性化上下文
RAG vs MCP:互补而非替代
核心差异:解决不同的问题
2024 年底,Anthropic 推出了 Model Context Protocol (MCP),引发了业界关于"MCP 是否会取代 RAG"的讨论。但 2025 年的实践证明:RAG 和 MCP 是互补关系,各自解决不同的问题。
flowchart TB
subgraph RAG["RAG:知识检索"]
D1[非结构化数据]
D2[静态知识]
D3[语义理解]
D1 --> RAG_SYS[RAG 系统]
D2 --> RAG_SYS
D3 --> RAG_SYS
RAG_SYS --> CTX1[上下文增强]
end
subgraph MCP["MCP:工具调用"]
S1[结构化数据]
S2[实时系统]
S3[动作执行]
S1 --> MCP_SYS[MCP Server]
S2 --> MCP_SYS
S3 --> MCP_SYS
MCP_SYS --> ACT[工具调用]
end
subgraph Integration["协同工作"]
CTX1 --> LLM[LLM 推理]
ACT --> LLM
LLM --> RESULT[最终结果]
end
style RAG fill:#c8e6c9
style MCP fill:#e1bee7
style Integration fill:#fff9c4
详细对比表
| 维度 | RAG | MCP |
|---|---|---|
| 核心目的 | 检索知识增强生成 | 标准化工具调用接口 |
| 数据类型 | 非结构化(文档、文本) | 结构化(API、数据库、文件系统) |
| 数据时效性 | 相对静态(离线索引) | 实时(在线查询) |
| 主要能力 | 只读检索 | 读 + 写 + 执行 |
| 典型场景 | 知识库问答、文档分析 | 操作 CRM、调用 API、文件操作 |
| 技术基础 | 向量检索、语义搜索 | 标准化协议、API 封装 |
| 成本结构 | 离线索引成本 + 在线检索成本 | 在线调用成本(无离线成本) |
| 数据合规 | 需处理 PII、敏感信息 | 依赖权限控制、OAuth |
RAG 的独特价值(MCP 无法替代)
-
语义理解能力
- RAG 通过嵌入模型理解"同义不同词"(如"汽车"和"车辆")
- MCP 依赖精确匹配,无法处理语义变体
-
大规模知识检索
- RAG 可处理百万级文档的高效检索
- MCP 的工具选择问题(Tool Retrieval)本质上仍需 RAG 技术
-
跨文档推理
- RAG 的 GraphRAG、TreeRAG 可发现跨文档的隐含关联
- MCP 只能逐个调用工具,缺乏全局视角
-
成本效益
- RAG 的离线索引摊薄了在线检索成本
- MCP 每次调用都产生实时成本
MCP 的独特价值(RAG 无法替代)
-
实时数据访问
- MCP 可连接实时数据库、API、文件系统
- RAG 的索引更新有延迟,不适合高频变化的数据
-
动作执行能力
- MCP 可执行创建、更新、删除等操作
- RAG 是只读的,无法修改外部系统
-
标准化协议
- MCP 提供统一的工具调用标准,降低集成成本
- RAG 每个系统都需要定制化的检索逻辑
-
权限和安全
- MCP 内置 OAuth、权限控制、审计日志
- RAG 的数据合规需要额外处理(PII 识别、脱敏)
最佳实践:RAG + MCP 协同架构
flowchart TB
Q[用户问题] --> INTENT[意图理解]
INTENT --> ROUTE{路由决策}
ROUTE -->|知识查询| RAG[RAG 系统]
ROUTE -->|实时数据| MCP[MCP Server]
ROUTE -->|混合任务| HYBRID[协同模式]
RAG --> CTX1[知识上下文]
MCP --> CTX2[实时数据]
HYBRID --> RAG
HYBRID --> MCP
CTX1 --> LLM[LLM 推理]
CTX2 --> LLM
LLM --> ANS[答案]
MCP --> ACTION[执行动作]
style RAG fill:#c8e6c9
style MCP fill:#e1bee7
style HYBRID fill:#fff9c4
协同模式示例:
1 | |
企业级最佳实践:构建统一的数据基础
从"孤岛"到"平台"的架构演进
2025 年的企业实践表明,最成功的 AI 应用架构是:以 Context Engine 为核心的统一数据基础。
flowchart TB
subgraph DataSources["数据源"]
DOC[文档库<br/>PDF/Word/Markdown]
DB[数据库<br/>关系型/NoSQL]
API[外部服务<br/>REST/GraphQL]
FS[文件系统<br/>本地/云存储]
end
subgraph Ingestion["Ingestion Pipeline<br/>数据摄取管道"]
PARSER[解析器<br/>多格式支持]
ENHANCE[语义增强<br/>LLM 驱动]
INDEX[索引构建<br/>向量/关键词/图]
PARSER --> ENHANCE
ENHANCE --> INDEX
end
subgraph ContextEngine["Context Engine<br/>上下文引擎"]
RAG_SER[RAG 服务<br/>领域知识]
MEM_SER[Memory 服务<br/>对话记忆]
TOOL_SER[Tool Retrieval<br/>工具选择]
RAG_SER --> ASSEMBLY[上下文组装]
MEM_SER --> ASSEMBLY
TOOL_SER --> ASSEMBLY
end
subgraph Applications["应用层"]
QA[问答系统]
AGENT[AI Agent]
CODING[代码助手]
ANALYSIS[数据分析]
end
DataSources --> Ingestion
Ingestion --> ContextEngine
ContextEngine --> Applications
style DataSources fill:#e3f2fd
style Ingestion fill:#fff9c4
style ContextEngine fill:#c8e6c9
style Applications fill:#e1bee7
Ingestion Pipeline:企业级数据摄取
Ingestion Pipeline 是 RAG 系统的"ETL",负责将原始非结构化数据转化为可检索的索引。
三阶段流程
flowchart LR
subgraph Extract["Extract / Parse<br/>解析阶段"]
RAW[原始数据] --> P1[格式解析<br/>PDF/Word/OCR]
P1 --> P2[结构提取<br/>标题/表格/列表]
P2 --> P3[元数据提取<br/>作者/日期/标签]
end
subgraph Transform["Transform / Enhance<br/>增强阶段"]
P3 --> T1[文本分块<br/>多层级策略]
T1 --> T2[语义增强<br/>摘要/实体/关系]
T2 --> T3[结构构建<br/>树/图/元数据]
end
subgraph Load["Load / Index<br/>索引阶段"]
T3 --> L1[向量索引<br/>语义检索]
L1 --> L2[关键词索引<br/>BM25]
L2 --> L3[图索引<br/>关联查询]
L3 --> L4[元数据索引<br/>过滤/排序]
end
style Extract fill:#ffcdd2
style Transform fill:#fff9c4
style Load fill:#c8e6c9
| 阶段 | 核心任务 | 关键技术 | 输出产物 |
|---|---|---|---|
| Extract | 格式解析、结构提取 | PDF 解析器、OCR、VLM | 纯文本、结构化数据、元数据 |
| Transform | 语义理解、结构构建 | LLM、实体抽取、关系抽取 | 文本块、摘要、知识图谱 |
| Load | 索引构建、存储 | 向量数据库、图数据库 | 多模态索引 |
语义增强:LLM 驱动的智能处理
现代 RAG 系统的核心创新在于:利用 LLM 在数据摄取阶段进行深度语义理解。
1 | |
语义增强的五大维度:
- 摘要生成:为每个块生成简短摘要,提升检索效率
- 实体识别:提取人名、地名、组织名等实体
- 关系抽取:识别实体之间的关系
- 关键词提取:生成代表性关键词
- 问题生成:预生成该块可能回答的问题
TreeRAG:树状结构索引
flowchart TB
DOC[原始文档] --> L1[章节级别摘要]
L1 --> L2[子章节级别摘要]
L2 --> L3[段落级别摘要]
L3 --> CHUNKS[原始文本块]
Q[用户问题] --> SEARCH1[细粒度检索]
SEARCH1 --> CHUNKS
CHUNKS --> NAV[树状导航]
NAV --> EXPAND[上下文扩展]
EXPAND --> CTX[完整上下文]
style DOC fill:#e3f2fd
style L1 fill:#fff9c4
style L2 fill:#fff9c4
style L3 fill:#fff9c4
style CHUNKS fill:#c8e6c9
style CTX fill:#e1bee7
TreeRAG 的优势:
- 精确定位:细粒度块提供高精度检索
- 完整上下文:树状结构自动扩展相关上下文
- 避免割裂:保持文档的逻辑完整性
GraphRAG:知识图谱增强
graph TB
E1[实体:机器学习]
E2[实体:深度学习]
E3[实体:神经网络]
E4[实体:TensorFlow]
R1[关系:是子领域]
R2[关系:基于]
R3[关系:实现工具]
E1 -->|R1| E2
E2 -->|R2| E3
E3 -->|R3| E4
Q[问题:TensorFlow 和机器学习的关系?] --> GRAPH[图遍历]
GRAPH --> PATH[路径:E4 → E3 → E2 → E1]
PATH --> CTX[跨文档上下文]
style E1 fill:#e3f2fd
style E2 fill:#e3f2fd
style E3 fill:#e3f2fd
style E4 fill:#e3f2fd
style CTX fill:#c8e6c9
GraphRAG 的优势:
- 跨文档关联:发现物理分离但语义相关的信息
- 隐含关系:通过图遍历发现非直接关联
- 多跳推理:支持复杂的多跳查询
Context Engine:智能上下文组装
Context Engine 是 RAG 的进化形态,其核心是:根据任务需求,动态组装最有效的上下文。
上下文组装的决策树
1 | |
上下文组装的优化策略
-
Token 预算管理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22def assemble_context(query, token_budget=4000):
# 分配 Token 预算
rag_budget = token_budget * 0.5 # 50% 给知识
memory_budget = token_budget * 0.3 # 30% 给记忆
tool_budget = token_budget * 0.2 # 20% 给工具
# 按预算检索
rag_context = rag_retrieve(query, max_tokens=rag_budget)
memory_context = memory_retrieve(query, max_tokens=memory_budget)
tool_context = tool_retrieve(query, max_tokens=tool_budget)
# 动态调整
if len(rag_context) < rag_budget * 0.5:
# RAG 结果不足,增加 Memory 和 Tool 预算
memory_budget += (rag_budget - len(rag_context)) * 0.5
tool_budget += (rag_budget - len(rag_context)) * 0.5
return {
"knowledge": rag_context,
"memory": memory_context,
"tools": tool_context
} -
相关性去重
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17def deduplicate_context(contexts):
# 计算所有上下文片段的相似度
embeddings = [encode(ctx) for ctx in contexts]
similarity_matrix = cosine_similarity(embeddings)
# 去除高度相似的片段
unique_contexts = []
for i, ctx in enumerate(contexts):
is_duplicate = False
for j in unique_contexts:
if similarity_matrix[i][j] > 0.9:
is_duplicate = True
break
if not is_duplicate:
unique_contexts.append(i)
return [contexts[i] for i in unique_contexts] -
质量评分和重排
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22def rerank_context(query, contexts):
# 多维度评分
scores = []
for ctx in contexts:
score = {
"semantic": semantic_similarity(query, ctx),
"freshness": freshness_score(ctx),
"authority": authority_score(ctx),
"diversity": diversity_score(ctx, contexts)
}
# 加权总分
total = (
score["semantic"] * 0.4 +
score["freshness"] * 0.2 +
score["authority"] * 0.3 +
score["diversity"] * 0.1
)
scores.append(total)
# 按分数重排
ranked = [ctx for _, ctx in sorted(zip(scores, contexts), reverse=True)]
return ranked
2026 展望:Context Platform 的崛起
从 Context Engineering 到 Context Platform
2025 年的实践证明,手动构建和管理上下文是不可持续的。2026 年的趋势是:Context Platform(上下文平台)——将上下文创建、管理和交付产品化、自动化。
flowchart TB
subgraph Manual["2025:手动工程"]
DEV[开发者] --> PROMPT[手写 Prompt]
PROMPT --> LOGIC[硬编码逻辑]
LOGIC --> CTX[上下文组装]
end
subgraph Platform["2026:平台化"]
USER[业务用户] --> CONFIG[可视化配置]
CONFIG --> AUTO[自动化组装]
AUTO --> CTX2[上下文交付]
subgraph AI["AI 驱动"]
AUTO --> OPTIMIZE[自动优化]
OPTIMIZE --> MONITOR[监控和反馈]
MONITOR --> AUTO
end
end
style Manual fill:#ffcdd2
style Platform fill:#c8e6c9
Context Platform 的核心能力:
-
声明式配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# context-config.yaml
sources:
- type: rag
name: product_docs
priority: high
max_tokens: 2000
- type: memory
name: user_history
priority: medium
max_tokens: 1000
- type: tool
name: crm_tools
priority: low
max_tokens: 500
assembly:
strategy: dynamic
token_budget: 4000
deduplication: true
reranking: true -
自动化优化
- 基于用户反馈自动调整检索策略
- A/B 测试不同的上下文组装方案
- 自动发现和添加新的数据源
-
监控和治理
- 上下文质量监控(相关性、完整性、时效性)
- 数据血缘追踪(上下文来源可追溯)
- 访问控制和审计日志
多模态 Context:超越文本
2026 年,Context Platform 将支持真正的多模态上下文:
flowchart TB
subgraph Multimodal["多模态上下文"]
TXT[文本]
IMG[图像]
AUDIO[音频]
VIDEO[视频]
CODE[代码]
end
subgraph Unified["统一表示"]
TXT --> EMB[多模态 Embedding]
IMG --> EMB
AUDIO --> EMB
VIDEO --> EMB
CODE --> EMB
end
subgraph Retrieval["统一检索"]
EMB --> SEARCH[跨模态检索]
SEARCH --> CTX[多模态上下文]
end
CTX --> LLM[多模态 LLM]
style Multimodal fill:#e3f2fd
style Unified fill:#fff9c4
style Retrieval fill:#c8e6c9
多模态 RAG 的技术路径:
-
模态转换:将图像、音频转换为文本描述
- 优势:兼容现有文本 RAG 架构
- 劣势:丢失原始模态的细微特征
-
原生多模态:直接处理多模态向量
- 优势:保留完整的模态信息
- 劣势:计算和存储成本高
-
混合方案:关键信息用原生多模态,辅助信息用文本
- 优势:平衡质量和成本
- 劣势:架构复杂度高
总结:复杂数据处理的最佳实践
基于 2025-2026 年的业界实践,设计和组织模型处理复杂数据的最佳实践可以总结为:
核心原则
-
Context First,Model Second
- 上下文质量比模型能力更重要
- 投资于数据基础设施,而非单纯追求更大的模型
-
RAG + MCP 协同,而非替代
- RAG 负责知识检索和语义理解
- MCP 负责实时数据访问和动作执行
- 两者结合构建完整的 AI 能力
-
从手动工程到平台化
- 早期:手动构建 RAG Pipeline
- 中期:抽象为 Context Engine
- 成熟期:演进为 Context Platform
架构蓝图
flowchart TB
subgraph Foundation["数据基础层"]
INGESTION[Ingestion Pipeline<br/>数据摄取]
RAG_IDX[RAG Index<br/>知识索引]
MEM_IDX[Memory Index<br/>记忆索引]
TOOL_IDX[Tool Index<br/>工具索引]
end
subgraph Engine["Context Engine 层"]
CTX_ASSEMBLY[上下文组装]
CTX_OPTIMIZE[上下文优化]
CTX_DELIVERY[上下文交付]
end
subgraph Protocol["协议层"]
MCP[MCP Servers<br/>工具调用]
API[REST API<br/>标准接口]
SDK[Client SDK<br/>开发工具]
end
subgraph Applications["应用层"]
AGENT[AI Agents]
QA[问答系统]
CODING[代码助手]
ANALYSIS[数据分析]
end
Foundation --> Engine
Engine --> Protocol
Protocol --> Applications
style Foundation fill:#e3f2fd
style Engine fill:#c8e6c9
style Protocol fill:#fff9c4
style Applications fill:#e1bee7
实施路线图
1 | |
关键技术选型
| 能力 | 推荐技术 | 备注 |
|---|---|---|
| 向量数据库 | Milvus / Weaviate / Qdrant | 开源、高性能、可扩展 |
| 图数据库 | Neo4j / NebulaGraph | 支持 GraphRAG |
| Embedding 模型 | text-embedding-3 / bge-m3 | 多语言、多模态支持 |
| Rerank 模型 | BGE-Reranker / Cohere Rerank | 提升检索精度 |
| LLM | Claude 3.5 / GPT-4o / DeepSeek | 根据场景选择 |
| MCP 框架 | FastMCP (Python) / MCP SDK (TS) | 快速构建 MCP 服务器 |
| 监控 | Prometheus / Grafana | 系统监控 |
| 追踪 | LangSmith / Arize | 上下文追踪 |
最终洞察:RAG 不会消失,MCP 也不会取代 RAG。它们正在共同演进为更强大的 Context Platform,成为 AI 时代的数据基础设施。企业的核心竞争力将从"拥有最好的模型"转向"拥有最好的上下文"。
NLP 的演进之路:从统计模型到大模型
自然语言处理(NLP)是计算机科学与人工智能的交叉领域,目标是让计算机能够理解、解释和生成自然语言,从而实现人与机器之间的顺畅交流。纵观其发展历程,NLP 经历了统计模型 → 深度学习模型 → 预训练模型 → 大模型四个阶段,任务解决能力随之从"辅助特定任务"跃升为"通用任务求解器"。
1 | |
统计模型阶段(1990s):Specific Task Helper
代表模型:n-gram 语言模型
n-gram 模型(参见论文《Class-Based n-gram Models of Natural Language》)通过统计文本中连续 n 个词的出现频率,来预测下一个词或生成文本,从而捕捉语言的局部上下文特征。其核心方法是概率估计(Probability Estimation)和统计方法(Statistical Methods)。
这一阶段的 NLP 模型只能作为辅助工具,解决特定的局部任务,任务解决能力有限。
深度学习模型阶段(~2013):Task-Agnostic Feature Learner
代表模型:Word2vec、神经语言模型(NPLM)
这一阶段经历了从前馈神经网络到循环神经网络的演进:
- 前馈神经网络:被广泛应用于语言建模,但无法有效捕捉序列信息,逐渐被 RNN 取代。
- RNN(循环神经网络)(参见《A Critical Review of Recurrent Neural Networks for Sequence Learning》):能处理序列数据,但面对过长序列时存在梯度消失和梯度爆炸问题,导致长期依赖信息遗忘。
- LSTM(长短期记忆网络)(参见《Long Short-term Memory RNN》):通过引入门控机制,有效捕捉和保持长时间依赖信息,克服了传统 RNN 的梯度消失问题,大幅提升了上下文理解能力。
- Word2vec(2013)(参见《Efficient Estimation of Word Representations in Vector Space》):词嵌入方法的里程碑。通过将词语映射到低维向量空间,使相似词的向量在空间中彼此靠近,让自然语言第一次变得可以进行数学计算,推动了语义理解的进展。
这一阶段的模型具备了静态词表示(Static Word Representations)和神经上下文建模(Neural Context Modeling)能力,能够解决典型的 NLP 任务(Solve typical NLP tasks)。
预训练模型阶段(~2018):Transferable NLP Task Solver
代表模型:ELMo、BERT、GPT-1/2
这一阶段的突破点是 Google 提出的 Transformer 架构(参见《Attention Is All You Need》)。Transformer 替代了传统 RNN 结构,凭借自注意力机制大幅提升了模型的并行处理能力和上下文理解能力,成为现代 NLP 的基础架构——BERT 和 GPT 均基于此构建。
- ELMo(参见《Deep Contextualized Word Representations》):引入了上下文感知的词表示(Context-aware Representations),同一个词在不同语境下拥有不同的向量表示。
- BERT(参见《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》):利用大规模语料进行双向预训练,大幅提升了多项 NLP 任务的表现。在大模型出现之前,文本分类、实体识别、情感分析等任务都可以借助 BERT 完成,其巅峰时期是十几个 NLP 任务的最佳模型(SOTA,State of the Art)。
这一阶段的核心范式是预训练 + 微调(Pre-training + Fine-tuning),模型能力实现了跨任务迁移,可以解决各类 NLP 任务(Solve various NLP tasks)。
大模型阶段(~2020 至今):General-Purpose Task Solver
代表模型:GPT-3/4、ChatGPT、Claude、Llama、Qwen 等
基于 Transformer-Decoder 架构的 GPT(参见《Language Models are Unsupervised Multitask Learners》)与 BERT 是孪生关系——BERT 采用编码器(Encoder),GPT 采用解码器(Decoder)。大模型通过规模扩展(Scaling Language Models)和基于提示的补全(Prompt Based Completion),实现了通过对话解决大部分 NLP 领域问题的能力,甚至结合多模态能力后,也能处理大部分计算机视觉(CV)领域的问题。
值得注意的是,大模型并非万能的替代者。其他小模型仍可独立应对特定细分任务,并作为大模型的辅助工具:
- n-gram 可用于大模型语料的去重
- Word2vec 和 BERT 可用于大模型语料的质量筛选
从学习到推理:算法模型的训练本质
算法模型的学习过程与人类学习高度相似,可以用下图来类比:
1 | |
模型需要从数据中学习到能力,只有当这种能力足够强,才能实现良好的泛化能力——即在未见过的数据上也能有效表现。
数据是决定模型效果的关键中的关键。高质量且多样化的数据,输入经过调优的模型,通常能实现最佳的算法表现。OpenAI 在数据上做了大量工作,但这部分工作并未开源。Meta 通过 Llama 的早期版本证明:仅用现有开源语料,就可以训练出与 ChatGPT 效果相近的模型,由此开启了开源大模型的繁荣时代。
主流大模型技术报告索引
大模型开发者通常会将训练细节整理为技术报告公开发布,以下是主流大模型的参考文献:
| 模型 | 技术报告 |
|---|---|
| Llama | 《Llama 2: Open Foundation and Fine-Tuned Chat Models》《The Llama 3 Herd of Models》 |
| Qwen | 《Qwen Technical Report》《QWEN2 TECHNICAL REPORT》《Qwen2.5-Coder Technical Report》 |
| GPT-4 | 《GPT-4 Technical Report》 |
| Baichuan | 《Baichuan 2: Open Large-scale Language Models》 |
| DeepSeek | 《DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model》 |
| MiniCPM | 《MiniCPM-V: A GPT-4V Level MLLM on Your Phone》《MiniCPM: Unveiling the Potential of Small Language Models with Scalable Training Strategies》 |
| Yi | 《Yi: Open Foundation Models by 01.AI》 |
| GLM | 《GLM-130B: An Open Bilingual Pre-trained Model》 |
| Gemini | 《Gemini 1.5: Unlocking Multimodal Understanding Across Millions of Tokens of Context》《Gemini: A Family of Highly Capable Multimodal Models》 |
其中,Llama 的技术报告内容最为翔实,后续将主要参考 Llama 3.1 的工作,介绍大模型的详细训练过程。
大模型的训练(学习)过程
理解大模型是怎么"炼"出来的,有助于我们更好地选择和使用模型。训练过程本质上是一个从"吃数据"到"对齐人类"的系统工程。
训练一般经过三个阶段:
| 阶段 | 数据类型 | 产出 |
|---|---|---|
| Pre-Training(预训练) | 大规模无标注通用数据 | 基座大模型(Base Model) |
| Continue Pre-Training(继续预训练) | 无标注领域相关数据 | 领域垂直模型 |
| Post-Training(后训练) | 标注数据 + 人类偏好数据 | 指令对齐微调模型(Chat/Instruct) |
flowchart LR
RAW[海量原始数据] --> PT[Pre-Training\n预训练]
PT --> BASE[基座大模型]
BASE --> CPT[Continue Pre-Training\n继续预训练]
CPT --> DOMAIN[领域垂直模型]
DOMAIN --> POSTT[Post-Training\n后训练 SFT+DPO]
POSTT --> CHAT[指令对齐模型\n-chat / -instruct]
style BASE fill:#e3f2fd
style DOMAIN fill:#fff9c4
style CHAT fill:#c8e6c9
Pre-Training:预训练
语言模型的预训练包括四个核心环节:
- 训练语料的整理和过滤:决定模型"吃什么"
- 规模缩放法则(Scaling Law):确定合适的模型大小
- 模型结构设计:Transformer 架构的具体参数配置
- 制定训练方案并开始训练
数据配比:模型学什么,决定模型会什么
不同的模型开发者对模型所需学习的知识有各自的理解,这实质上是一个实验过程。下图来源于《A Survey of Large Language Models》,展示了主流大模型的预训练数据构成:
1 | |
数据配比(所学内容的类型和比例)将直接决定预训练模型的最终效果。
以 Llama 为例,预训练极其耗时耗钱——Llama 405B 预训练用了 54 天,中间还会遇到各种系统崩溃。为了避免浪费,Llama 团队先用小尺寸模型并行训练确定了最佳数据配比:
- 50% 一般知识
- 25% 数学和推理
- 17% 代码
- 8% 多语言
(这也解释了为什么 Llama 直接用起来中文体验差点意思——它学的中文太少了,会回复英文甚至中英文混输。不过社区有大量开源的中文魔改版本。)
数据预处理流水线
收集到海量文本后,数据预处理至关重要——要让模型"吃好的",而不是吃垃圾。整个流程如下图所示(Raw Corpus → 过滤 → 去重 → 隐私处理 → 分词 → 准备训练):
1 | |
具体来说,预处理包含以下几个关键步骤:
① 质量过滤
去除低质量数据,使用基于模型的质量分类器(FastText 和 RoBERTa)筛选高质量 token:
- FastText:Word2Vec 的扩展改进,训练快速分类器,识别文本是否可能被维基百科引用
- RoBERTa:BERT 的变种(用更多数据训练),为每个文档生成算法质量分
② 内容提取
- 网页数据:从 HTML 中提取正文内容
- Markdown 数据:去掉特殊标记,只保留有效文本
③ 去重
重复数据会降低模型多样性,影响训练稳定性。需要在三个层级进行去重:
1 | |
以零一万物(Yi)的数据处理流程为例,原始语料经过多轮过滤后,最终只保留约 31.68% 的数据作为训练语料:
1 | |
④ 隐私去除和安全过滤
- 删除可识别个人信息(PII):姓名、地址、电话号码等
- 过滤成人内容:大网站直接黑名单,小网站通过脏词统计分析过滤
⑤ 数据关系构建(In-context Pretraining)
来自 LLaMA 实践论文《In-context Pretraining: Language Modeling Beyond Document Boundaries》:
模型学习知识的过程应该由易到难,类似于我们先学小学再学初中。具体做法是:
1 | |
多个语义相关的文档被串联成连续序列,划分为固定大小的输入上下文(如 8k),让模型在相关知识之间建立更好的关联。
⑥ 分词(Tokenization)
分词是数据预处理的最后关键步骤,将原始文本分割成 tokens,作为大模型的实际输入。
不同模型的数据清洗流程各有细节设计。以 Baichuan 2 为例,其流程包含:语言过滤 → 文本指标过滤 → 重复文档删除 → 规则修正 → 困惑度过滤 → 文档质量过滤 → 段落去重 → MinHash 去重 → 精确去重 → 语义过滤 → 主题过滤 → 安全过滤。
Transformer 模型结构
预训练的核心是 Transformer 架构。模型的工作原理如下图所示:
1 | |
这就是自回归解码(Autoregressive Decoding):每次预测一个 token,然后把这个 token 加入输入,继续预测下一个,如此循环直到生成完整回答。
Continue Pre-Training:继续预训练
参考论文:《Continual Pre-Training of Large Language Models: How to (re)warm your model?》
继续预训练是在完成初步预训练之后,针对特定领域数据集对模型进行进一步训练的过程。目的是帮助模型更好地适应特定任务或领域,学习相关知识和术语。
上下文长度扩展
你可能注意到,主流大模型的上下文长度在某段时间突然集体变长了(从 4K 到 128K)。这个能力就是在继续预训练阶段实现的。
以 Llama 3 405B 为例,分六个阶段逐步增加上下文长度,使用约 800B tokens,从最初的 8K 上下文窗口逐步扩展到最终的 128K:
1 | |
模型通过逐步适应更长的上下文,最终具备处理超长输入的能力。
训练算法原理
预训练和继续预训练的算法原理相对简单:
1 | |
反向传播(Backpropagation)由深度学习之父 Geoffrey Hinton 在 1986 年论文《Learning representations by back-propagating errors》中提出,他也因此获得了图灵奖和诺贝尔奖。
训练完成后,模型参数被保存为离线快照文件。最终的参数数量由模型设计之初的结构决定,例如 7B(70亿)、13B(130亿)、72B(720亿)参数。
为了提升训练效率,通常会使用 DeepSpeed 等分布式训练优化工具,实现更高效的资源管理。
Post-Training:后训练
后训练的本质是对齐人类表达,让模型看起来更像一个智能的人类助手。
Llama 的后训练是迭代式的,包含多轮相同方法的训练,每轮包含三个核心模型:奖励模型(RM)、监督微调模型(SFT)、直接偏好优化模型(DPO)。
整体流程如下图所示:
1 | |
奖励建模(Reward Modeling,RM)
- 目的:构建能评估模型生成内容质量的奖励模型
- 做法:使用人类标注的偏好数据训练奖励模型,衡量生成回应的优劣
奖励模型的职责是筛选高质量样本用于下一步微调——相当于训练了一个"懂人类表达习惯的评审",替代人工来筛选高质量的微调样本。
在**拒绝采样(Rejection Sampling)**过程中:
- 对每个 Prompt,生成模型(DPO 模型)生成 K 个不同答案
- 奖励模型对 K 个样本打分,选出最优答案
- 为提升采样效率,Llama 采用了 PagedAttention(通过动态键值缓存分配增强内存效率)
监督微调(Supervised Fine-Tuning,SFT)
- 目的:提高模型在特定任务上的表现
- 做法:利用拒绝采样获得的数据及其他数据,使用标准交叉熵损失对预训练模型进行微调
Llama 微调数据构成(来自论文数据):
| 数据集类型 | 占比 | 平均轮次 | 平均 tokens |
|---|---|---|---|
| General English(通用英语) | 52.66% | 6.3 | 974.0 |
| Reasoning and tools(推理与工具) | 21.19% | 3.1 | 661.6 |
| Code(代码) | 14.89% | 2.7 | 753.3 |
| Exam-like(考试类) | 8.14% | 2.3 | 297.8 |
| Multilingual(多语言) | 3.01% | 2.7 | 520.5 |
| Long context(长上下文) | 0.11% | 6.7 | 38,135.6 |
直接偏好优化(Direct Preference Optimization,DPO)
参考论文:《Direct Preference Optimization: Your Language Model is Secretly a Reward Model》
- 目的:增强模型对人类偏好的对齐,进一步提升模型表现
- 做法:DPO 是 RLHF 的简化版,跳过了复杂的奖励模型训练过程
RLHF 与 DPO 的对比:
1 | |
正反馈循环
上述 Post-Training 流程会反复迭代 6 次,形成正反馈循环:
1 | |
工具调用能力的来源
模型的工具使用能力(Function Calling)主要是在 Post-Training 阶段通过人类注释和偏好数据训练得到的。这也是为什么最新开源大模型的 -chat / -instruct 版本都自带工具调用能力——它们是在 base 模型上经过了 SFT 和 DPO 的。
案例:Qwen2.5-Coder 训练步骤
以 Qwen2.5-Coder 为例,训练思路与上述一致:
1 | |
Benchmark 测评
经过几个阶段的训练之后,模型效果需要从多个维度进行评测:
| 能力维度 | 代表性 Benchmark |
|---|---|
| 通用能力 | MMLU、MMLU-Pro、IFEval |
| 代码能力 | HumanEval、MBPP EvalPlus |
| 数学能力 | GSM8K、MATH |
| 推理能力 | ARC Challenge、GPQA |
| 工具使用 | BFCL、Nexus |
| 长上下文 | ZeroSCROLLS、InfiniteBench |
| 多语言 | MGSM |
以 Llama 3 系列为例(部分 Benchmark 数据):
| Benchmark | Llama 3 8B | Llama 3 70B | Llama 3 405B | GPT-4o | Claude 3.5 Sonnet |
|---|---|---|---|---|---|
| MMLU (5-shot) | 69.4 | 83.6 | 87.3 | 89.1 | 89.9 |
| HumanEval | 72.6 | 80.5 | 89.0 | 90.2 | 92.0 |
| GSM8K | 84.5 | 95.1 | 96.8 | 96.1 | 96.4 |
| ARC Challenge | 83.4 | 94.8 | 96.9 | 96.7 | 96.7 |
| BFCL(工具使用) | 76.1 | 84.8 | 88.5 | 80.3 | 90.2 |
一般来说,参数量大的模型表现明显优于参数量小的模型,但它们之间的性能关系有一定规律,这就是 Scaling Law。
Scaling Law:规模缩放法则
参考论文:《Scaling Laws for Neural Language Models》(OpenAI,2020)
Scaling Law 描述了模型性能如何随数据量、模型规模和计算资源的变化而变化的经验法则。
核心公式
如图所示,单一指标的增加会带来模型损失(Loss)的幂律下降:
1 | |
三者的关系满足:C ≈ 6ND(计算量 ≈ 6 × 参数量 × Token 数)
实际应用:如何用 Scaling Law 规划训练
假设有固定的计算资源预算,可以这样规划:
示例:
- 计算资源预算 C = 1×10¹² FLOPs
- 选定模型规模 N = 2×10⁹(2B 参数)
- 则所需数据规模:D ≈ C / (6×N) = 1×10¹² / (6×2×10⁹) ≈ 83,300 tokens
Scaling Law 的局限与突破
Llama 实验发现,虽然 Scaling Law 可以设定"最优"的 token 数,但继续增加 tokens,模型性能仍在缓慢提升。
这催生了新的实验思路:在更大规模的数据上训练相对更小的模型,充分挖掘模型潜力。
Llama 3 的推导过程:
- 硬件资源:16,000 张 H100
- 推导出最佳规模:402B 参数 + 16.55T tokens(16.55 万亿)
- 最终决定:15.6T tokens 训练数据 + 405B 参数作为 Llama 3.1 旗舰模型
边际收益递减
随着参数量持续增加,模型能力的增长会逐渐放缓,体现出边际收益递减的趋势。并不是模型设计得越大就越好。
以 LLaMA 不同尺寸模型在多个 Benchmark 上随 Token 数增加的准确率变化为例:
1 | |
这也是为什么马斯克的 Grok(xAI 用 10 万张 H100 训练的 314B 模型)并不一定比更小但训练更充分的模型表现更好——堆参数不是万能的。
从随机性到确定性:AI 使用的实践指南
大语言模型生成内容本质上是一种概率过程,但我们可以通过多种手段在随机性与确定性之间找到平衡。
问题背景
很多朋友常问:“为啥我的提示词有时候效果还行,有时候效果不好呢?”、“怎样才能获取一致性的输出?”
随着 DeepSeek-R1(“思考模型”)和 Manus(通用 AI Agent)的出现,这个问题变得更加明显。模型能力越强,执行任务越自动化,如果一开始不能给 AI 足够清晰的约束,它就会自作主张,最终结果往往和我们想要的相差甚远。
其实,人说话也是随机性的——同样内容,同一个人在不同场合、不同时间说,表达可能不同。我们之所以能够有"确定性",是因为我们认知相对固定,知道自己"想要说什么"。但 AI 不够了解我们,不知道我们怎么想的。
核心建议:从一开始就尽量把"确定性"交给 AI,避免反复对话,也防止 AI 过度自动化后偏离预期。
解决之道
1. 提示词设计层面
提示词过于简单,模型就会进行很多猜测。将任务描述得越准确、上下文越充足、要求越具体,模型回答质量越高。但存在一个最佳平衡点——"最小充足准确"表述,即充足又准确但不啰嗦。
注意:DeepSeek-R1 等推理模型通常不需要在提示词中加入思维链,过多示例反而可能导致效果下降。
实践要点:
- 将"确定性"(你想要的"好"内容的定义)放入提示词中
- 明确输出格式要求,每个部分给出详细阐述
- 控制确定性的粒度,而非追求完全相同的输出
示例:想要稳定生成小红书标题,需要先定义"我想要的标题"是什么类型(痛点预警型、认知碾压型、解决方案型等),并将这些定义放入提示词。
2. 模型调用参数层面
使用 Cherry Studio、Chatbox 等 AI 客户端时,参数决定输出的确定性程度:
| 参数 | 作用 | 建议 |
|---|---|---|
| Temperature | 温度越高随机性越大,越低越确定 | DeepSeek-R1 建议设为 0.6 |
| Top_k | 限制模型选择的词汇范围 | 仅考虑概率最高的 K 个词 |
| Frequency Penalty | 降低模型重复相同内容的可能性 | 值域 [-2.0, 2.0] |
| Presence Penalty | 增加模型谈论新主题的可能性 | 值域 [-2.0, 2.0] |
不同场景的温度建议(DeepSeek 官方):
| 场景 | 温度 |
|---|---|
| 代码生成/数学解题 | 0.0 |
| 数据抽取/分析 | 1.0 |
| 通用对话 | 1.3 |
| 翻译 | 1.3 |
| 创意类写作/诗歌创作 | 1.5 |
3. 智能体设计层面
根据 Anthropic 的研究,智能体系统架构分为两类:
| 类型 | 特点 | 代表产品 |
|---|---|---|
| 工作流(Workflows) | 流程相对固定 | Coze、Dify |
| 智能体(Agents) | 更加自主化 | Manus、Flowith |
工作流控制:通过工作流编排实现确定性,把编排当做更粗粒度的"提示词"。每个环节的提示词精心打磨,保证整个流程的效果。
智能体控制:采用 Human-in-the-loop 机制,人类仅在必要时进行干预。Agent 在中间环节需要人类补充信息或进行关键决策时暂停确认,避免"一顿操作猛如虎"后结果不符合预期。
4. 工程化层面
类似 Kiro 的 Agent Hook、Spring 的生命周期回调,通过工程化手段插入回调节点,实现更多确定性,而非完全依赖 Agent 自主决策。
5. 产品设计层面
将完成功能所需的关键信息,通过选项或自动生成的方式提供给用户,降低使用复杂度,提高首次对话的确定性。
总结
随着 AI 越来越自动化,最初提示词的条件限定至关重要:
- 首次提问时给与充足准确的信息和明确的要求
- 避免 Agent 自动执行后输出不符合预期的结果,浪费大量 Token
- 减少不必要的二次对话和中间的人类参与
DeepSeek-R1 和 Manus 的问世,看似解放了人类,实则对人类的要求更高了:
- 提问的成本更高(自动化的代价是 Tokens 消耗)
- 提问的质量对结果影响更大
- AI 发展趋势是减少人类参与,无法给出准确信息,结果必将南辕北辙
本文从提示词工程、模型参数、智能体设计、工程化和产品设计五个层面,讲述了如何在随机性与确定性之间寻找平衡,希望对大家未来的 AI 使用有所帮助。
参考资料:
五、如何写好提示词:从祛魅到实战的完整方法论
本章融合全文讨论的核心洞察,以及 Claude 4 时代的最新实践,给出一套完整的提示词写作与迭代方法论。
5.0 提示词优化的前世今生:从"手把手教"到"说清楚要什么"
在深入具体技巧之前,我们需要先建立一个宏观认知:提示词工程不是静态的技巧集合,而是随着模型能力进化不断演变的动态实践。理解这个演变过程,才能知道"为什么现在可以这么写"。
5.0.1 提示词的本质结构:目标 + 上下文
无论提示词的形式如何变化,其本质始终可以拆解为两个核心部分:
目标(Goal):你想让模型完成什么任务——这是提示词的"北极星",必须在第一句话就说清楚。
上下文(Context):模型完成任务所需的背景信息——这是提示词的"地图",告诉模型在什么范围内、按什么规则行动。
但上下文本身是复杂的。为了让模型不用概率分布的直觉"乱思考、乱执行",我们需要把上下文进一步拆分为四个结构化要素:
| 上下文要素 | 作用 | 示例 |
|---|---|---|
| 角色定义 | 设定模型的工作身份和大方向 | “你是一位资深代码审查专家” |
| 执行流程 | 约束模型的思考和行动路径 | “先分析问题 → 再给出方案 → 最后提供代码” |
| 输出格式 | 规定输出的结构和样式 | “以 Markdown 表格形式输出,包含三列” |
| 样例示范 | 通过示例展示期望的输入输出模式 | Few-shot 示例 |
这四个要素构成了提示词的"四梁八柱",缺一不可——但需要写到什么程度,取决于模型的能力阶段。
5.0.2 提示词工程的三个时代
时代一:手把手教(GPT-3/3.5 时代,2020-2022)
模型能力较弱,相当于刚毕业的实习生。这个阶段的提示词需要:
- 完整的目标 + 全部四个上下文要素,缺一不可
- 详细的执行流程:每一步都要写清楚,否则模型会跳步或跑偏
- 大量的 Few-shot 示例:通过示例"教会"模型你期望的行为模式
- 严格的输出格式约束:模型很难自主遵循格式,需要显式规定
典型特征:提示词很长,动辄几百上千字;需要反复调试才能稳定输出;不同模型的提示词往往不通用。
时代二:结构化引导(GPT-4/Claude 2-3 时代,2023-2024)
模型能力显著提升,相当于有 3-5 年经验的专业人士。这个阶段出现了大量提示词技术:
- CoT(Chain-of-Thought):让模型"一步步思考",提升推理质量
- ToT(Tree-of-Thought):让模型探索多条推理路径,选择最优解
- GoT(Graph-of-Thought):让模型在思维图上进行非线性推理
- ReAct:让模型交替进行推理(Reasoning)和行动(Acting)
这些技术的本质,都是通过提示词显式地约束模型的思维过程。但在这个阶段,提示词仍然需要写得比较详细——角色、流程、格式、示例仍然重要,只是可以适当精简。
典型特征:提示词工程成为一门"手艺",出现了各种模板和最佳实践;Lisp 风格、XML 标签、结构化 Markdown 等格式流行;同一个提示词在不同模型上效果差异明显。
时代三:说清楚要什么(Claude 4/DeepSeek-R1/GPT-4.5 时代,2025-)
模型能力达到或超越资深专家水平。这个阶段的核心变化是:
| 变化维度 | 以前 | 现在 |
|---|---|---|
| 角色定义 | 必须写,否则模型不知道自己是谁 | 仍然建议写,但主要是设定大方向,不必过度细化 |
| 执行流程 | 必须写详细步骤,否则模型会跑偏 | 默认不需要写——模型已内化 CoT/ToT/ReAct 等能力,除非你的思维流程比模型更强 |
| 输出格式 | 必须写,否则输出不可控 | 有格式要求时才写,模型可以自主推断常见格式 |
| Few-shot 示例 | 需要多个示例"教会"模型 | 越来越不需要——模型能力越强,越不需要例子 |
核心洞察:模型能力越强,提示词越简洁;提示词的复杂度,本质上是用来"补完"模型能力的锯齿性缺陷。当模型能力足够强时,我们只需要准确描述目标 + 提供必要的上下文,剩下的交给模型自主规划。
典型特征:提示词大幅缩短;自然语言描述即可,不需要特殊格式;同一个提示词在多个模型上效果趋于一致;提示词工程从"技术"变成"沟通"。
5.0.3 当前的最佳实践:一个决策框架
基于以上认知,我们可以给出一个简洁的决策框架,帮助你判断"这个提示词需要写到什么程度":
1 | |
一句话总结:从无到有,从少到多。先试试最简单的提示词,效果不好再加内容——而不是一开始就写一个"完美"的长提示词。
5.0.4 未来展望:提示词工程的"消亡"
随着模型能力继续提升,我们可以期待:
- 提示词越来越短:最终可能只需要一句话描述目标
- 格式越来越自然:不需要 Lisp、XML 等特殊格式,自然语言即可
- 跨模型一致性:同一个提示词在所有主流模型上效果相近
- 提示词工程成为"沟通技能":不再是技术专家的专利,而是人人都能掌握的基本能力
但这并不意味着"提示词工程"会完全消失。在以下场景,我们仍然需要精心设计提示词:
- 复杂的多步骤任务:需要显式拆解和流程控制
- 高度定制化的输出:需要精确控制输出格式和风格
- 特定领域的专业知识:需要注入领域上下文
- Agent 系统:需要定义工具调用规则和决策逻辑
最终结论:提示词工程不会消失,但会从"技术密集型"转变为"沟通密集型"。核心能力不再是"怎么写提示词",而是"怎么准确表达需求"。
5.1 先理解:Lisp 提示词为什么"看起来更好"
在学会写好提示词之前,必须先搞清楚一个长期困扰很多人的问题:为什么 Lisp 风格的嵌套结构提示词,在 Claude 上的效果往往优于线性的自然语言描述?
答案不在于 Lisp 语言本身,而在于它碰巧实现了三个对 LLM 有效的结构特性。
① 训练数据偏差激活了代码理解路径
Claude 系列模型在训练时大量接触了 Lisp/Scheme/Emacs Lisp 代码。当你用 Lisp 风格写提示词时,模型会把它"识别"为一段有明确语义的程序,激活代码理解路径而非自然语言理解路径。代码理解路径的特点是:精确执行、不随意发挥、严格按结构输出。这在需要精确执行步骤的任务(如生成 SVG 卡片)上往往更稳定。
这也是为什么李继刚的提示词标注"模型: Claude 3.7 Sonnet"——换成 DeepSeek 或 Qwen,Lisp 风格的优势会大打折扣,因为这些模型对 Lisp 语法的"亲和力"不如 Claude。
② 括号结构强制消除语义歧义
Lisp 的括号把每个概念都"封装"起来:
1 | |
这等价于一个强类型的键值对声明。模型不需要猜测"敏锐"是修饰性格还是技能,括号已经把归属关系固定了。相比之下,线性描述"性格敏锐谨慎,技能洞察推理"在 attention 机制下,"敏锐"和"洞察"之间的关联权重可能被错误地拉近。
③ 管道操作符天然表达执行顺序
1 | |
这个 -> 管道操作符明确告诉模型:按顺序执行,前一步的输出是后一步的输入。这比"请先做A,然后做B,最后做C"的线性叙述更不容易被模型跳步,因为模型会把它识别为函数调用链,而不是建议性的自然语言。
结论:Lisp 的本质是"用代码语法强制结构化"。 任何能消除歧义、明确执行顺序、强制分组的结构都能达到类似效果——这正是我们用 Markdown 金字塔结构复刻成功的根本原因。
5.2 核心原则:三句话的提示词哲学
不需要记忆复杂的框架,只需要记住三句话:
- 准确描述任务 —— 开篇明义,第一句话就说清楚"你要做什么"
- 给充足而准确的上下文 —— 提供足够的背景、规范、约束,让模型不需要猜
- 提出明确的要求 —— 明确输出格式、长度、风格等约束条件
这三句话说来简单,但真正写提示词时,很多人还是容易违背。以前模型能力较弱,相当于刚毕业的实习生,我们需要手把手告诉他每一步怎么做;现在 Claude 4 时代的模型能力极强,甚至比我们还"资深",我们更需要做的是如何准确高效地表达自己的诉求,而不是手把手教它思维链。
5.3 结构选择:金字塔原则 vs Lisp 结构
金字塔原则(Pyramid Principle) 是麦肯锡顾问芭芭拉·明托提出的写作框架,核心是:结论先行 → MECE 分组 → 逻辑递进。这个结构和 Lisp 的嵌套结构同构,但对人类可读,对所有模型友好。
| 维度 | Lisp 结构 | 金字塔结构(Markdown) |
|---|---|---|
| 顶层声明 | (defun main ...) |
# 任务名:一句话目标 |
| 分组封装 | (list (A . ...) (B . ...)) |
## A 模块 / ## B 模块 |
| 执行顺序 | (-> step1 step2 step3) |
1. step1 2. step2 3. step3 |
| 约束边界 | ;;; Attention: 运行规则! |
## 约束规则 |
| 可读性 | 低(需懂 Lisp) | 高(人人能改) |
| 跨模型兼容 | 低(Claude 友好) | 高(所有模型) |
李继刚式提示词的四层金字塔结构:
1 | |
这四层天然构成金字塔,从最高层的"身份"到最底层的"边界",层层递进,MECE 不重叠。
5.4 通用模板:金字塔提示词标准格式
1 | |
四条写作原则:
- 结论先行:第一行就说清楚做什么,不要让模型从细节里猜
- MECE 分组:每个
##对应一个独立关注点,不重叠、不遗漏 - 编号列表表达顺序:执行步骤用
1. 2. 3.而非"先…然后…最后…",编号列表对模型的约束力远强于自然语言叙述 - 约束放最后用否定句:
不输出 xml 开头比只输出 SVG更精确,放在最后相当于"最后提醒"
5.4.1 ICEF 框架:上下文四要素的经典记忆口诀
在金字塔模板的基础上,有一个更简洁的记忆框架可以帮助你快速检查提示词是否完整——ICEF 四要素:
| 要素 | 英文 | 对应金字塔层 | 说明 |
|---|---|---|---|
| I | Identity | 角色定义 | 设定模型的工作身份,如"你是一位资深代码审查专家" |
| C | Context | 执行流程 + 约束 | 提供任务背景、规范和边界条件 |
| E | Examples | 可选 | Few-shot 示例,在模型能力不足时补充 |
| F | Format | 输出规范 | 明确输出格式、长度、结构要求 |
ICEF 和金字塔结构是同一件事的两种表达:金字塔是写作时的组织框架,ICEF 是检查时的记忆口诀。写完之后用 ICEF 对照检查,是一个高效的工作流。
写完提示词后,用这份清单做最终检查:
- [ ] 身份明确吗? 模型知道它是什么角色、工作在什么方向上吗?
- [ ] 上下文完整吗? 模型有足够的背景信息,不需要猜测吗?
- [ ] 格式清晰吗? 明确说明了想要的输出格式、长度、结构吗?
- [ ] 表达直接吗? 避免了模糊、反问、隐含情绪的表达方式吗?
- [ ] 正向引导吗? 告诉模型"要做什么"而非"不要做什么"吗?
- [ ] 示例必要吗? 如果效果不好,是否需要补充 1-2 个 Few-shot 示例?
最后一条值得单独强调:正向引导是一个容易被忽视但效果显著的原则。
1 | |
否定式约束要求模型先理解"什么是不好的"再规避,而正向描述直接给出目标状态,认知负担更低,执行更精确。
5.5 迭代流程:如何反复打磨出好提示词
写好提示词不是一次性的事,而是一个观察 → 分析 → 修改 → 验证的迭代循环。
第一步:从优秀案例出发,不要从零开始
找到一个效果好的提示词(如李继刚的"言外之意"),先理解它的核心逻辑,再用金字塔结构转写。转写时可以直接让大模型帮你完成格式转换:
下面是使用 Lisp 伪代码生成 SVG 卡片的原始提示词,请不要使用伪代码,直接使用 Markdown 格式帮我重新整理出新的提示词
第二步:分析转换后的提示词,找出问题
大模型自动转换的结果通常存在以下问题,需要逐一排查:
- 角色和任务关联度差:角色定义和实际任务脱节
- 示例和真实输入"串掉":few-shot 示例中的"用户输入"被模型误认为是真实输入
- 尺寸/参数错误:如长宽比反了,大模型有时会自动纠正,有时不会
- 描述过于简略:颜色、字体、间距等关键参数没有明确指定
- 缺少输出约束:没有限制输出格式,导致模型添加多余的解释文字
第三步:针对目标模型做定向优化
不同模型有不同的"怪癖",需要针对性处理:
| 模型 | 常见问题 | 对应优化 |
|---|---|---|
| DeepSeek-R1 | 喜欢以 ```xml 开头输出,影响 SVG 渲染 | 明确要求"输出必须以 <svg 开头" |
|
| DeepSeek-R1 | 纠结长宽比导致画面不协调 | 明确指定画布尺寸,避免让模型自行判断 |
| DeepSeek-R1 | 解析结果区内容过多导致布局混乱 | 明确限制条数,如"通常是 3 到 4 条" |
| Claude | 能力强,可以灵活纠正错误参数 | 可以给相对宽松的规范,让模型发挥 |
| Qwen | 对中文语义理解好,但对精确格式控制稍弱 | 输出约束要更明确 |
第四步:简化提示词,去掉不必要的内容
Claude 4 时代的模型能力极强,很多以前需要手动写的内容现在可以省略:
- 不需要写思维链:除非你强制要求模型按特定步骤执行,否则不需要在提示词中提供 CoT
- 不需要写 few-shot:遵循"从无到有,从少到多"的原则,先试试没有示例的效果
- 不需要写角色扮演的"启动仪式":如 Lisp 版的
(defun start () ...)这类初始化函数,Markdown 版完全不需要
第五步:跨模型验证,确认效果稳定性
一个好的提示词应该在多个模型上都能获得可接受的效果。验证顺序建议:
1 | |
如果某个模型效果明显差,针对该模型的"怪癖"做定向修复,而不是把整个提示词推倒重来。
5.6 进阶:从复刻到创新
复刻是学习,创新才是目的。掌握了金字塔结构之后,可以按以下路径进行创新:
创新路径:
1 | |
创新示例:"阿尔戈斯之眼"的诞生
观察到 DeepSeek-R1 在思考时会自动分析显性需求、隐性需求和根本需求,于是把这个能力显式化,设计了一个专门分析三层需求的智能体。命名时借助 AI 寻找希腊神话中最贴合"全方位洞察力"的人物,得到"阿尔戈斯之眼"(百眼巨人,可以同时观察各个方向)。
这个创新过程本身也是一个提示词工程的实践:
- 任务描述:寻找最贴合的神话人物
- 结构约束:标题结构为"人物 + 器官或物品"
- 明确要求:给出 2 个候选并说明推荐理由
从"言外之意"到"阿尔戈斯之眼",改动的只是三处:
- 角色名和任务描述(伽达默尔 → 阿尔戈斯之眼)
- 执行流程(5 步语言分析 → 3 层需求分析)
- 卡片结构(解析结果区 → 三标签圆角矩形区)
这说明一个好的提示词模板,改动成本极低,可以快速衍生出新的应用场景。
5.7 一句话总结
提示词的价值在于准确传达需求,而非展示技术复杂性。Lisp 的本质是"用代码语法强制结构化",金字塔的本质是"用文档层级强制结构化",两者同构。在 Claude 4 时代,用金字塔结构写提示词,更通用、更易改、跨模型兼容,是让提示词真正"走向寻常百姓家"的正确路径。
参考资料:
- DeepSeek-R1 官方文档
- Manus 产品介绍
- Prompting best practices - Claude API Docs
- Building effective agents - Anthropic
六、训练和推理:算力需求的本质差异
6.0 大模型核心概念:参数、权重、Token与网络结构
在深入训练和推理的差异之前,我们需要先理解大模型的几个核心概念及其关系。这些概念是理解后续内容的基础。
6.0.1 参数 vs 权重
参数(Parameters) 是模型所有可学习变量的统称,包括:
- 权重(Weights):神经元之间的连接强度,决定信号传递的强弱
- 偏置(Biases):神经元的激活阈值,决定神经元是否被激活
关系公式:
1 | |
实际案例:
- GPT-3: 175B 参数 = 1750 亿个权重+偏置
- LLaMA-7B: 7B 参数 = 70 亿个权重+偏置
- GPT-4: 参数量未公开,估计在 1.8T(1.8万亿)级别
为什么参数量重要?
- 参数量决定模型的"记忆容量"和"表达能力"
- 参数越多,模型能学习的模式越复杂,但训练成本也越高
- 参数量与显存需求成正比:FP32 精度下,1B 参数 ≈ 4GB 显存
术语说明:业界习惯用"权重"(weights)统称所有模型参数,包括权重矩阵、偏置向量、LayerNorm 参数等。因此"开源模型权重"实际指开源所有训练好的参数。
6.0.1.1 模型开源的真正价值
理解了参数的定义后,一个自然的问题是:模型"开源"到底开了什么?
模型开源 ≠ 软件开源
传统软件开源和模型开源有本质区别:
| 维度 | 传统软件开源 | 模型开源 |
|---|---|---|
| 开源内容 | 源代码(人类可读的逻辑) | 模型权重(参数文件) |
| 可修改性 | 可直接修改代码逻辑 | 只能通过训练调整参数 |
| 可复现性 | 可重新编译、构建、运行 | 无法复现训练过程 |
| 核心价值 | 逻辑透明 | 能力共享 |
模型训练的完整要素
一个模型的诞生涉及多个要素,它们的开放程度各不相同:
| 要素 | 说明 | 是否开源 | 原因 |
|---|---|---|---|
| 模型架构 | 网络结构设计(Transformer层数、注意力头数等) | ✅ 通常开源 | 纯代码,学术价值高 |
| 训练代码 | 数据处理、训练循环、优化器等 | ⚠️ 部分开源 | 涉及工程细节和优化技巧 |
| 训练数据 | 海量文本、图像等原始数据 | ❌ 几乎不开源 | 版权问题、数据量巨大、商业机密 |
| 训练权重 | 训练完成后得到的参数值 | ✅ 通常开源 | 是模型的核心"知识" |
| 训练配置 | 超参数(学习率、batch size等) | ⚠️ 部分开源 | 影响复现效果 |
为什么"开源权重"无法复现模型?
即使开源了权重、架构、代码,仍然无法完全复现训练过程,核心原因:
🔴 关键缺失:训练数据
1 | |
数据是模型"知识"的来源,没有数据就无法:
- 从零训练出相同能力的模型
- 理解模型为何学到某些知识
- 改进模型的数据处理流程
权重文件无法反向还原训练数据! 这就像:
- 你无法从"煮熟的菜"还原出"原始食材和烹饪步骤"
- 你无法从"编译后的二进制"还原出"源代码"
- 权重是数据的"压缩摘要",而非数据的"可逆编码"
厂商基于开源模型的开发路径
基于开源模型开发,通常有三种路径:
| 路径 | 数据需求 | 计算成本 | 时间 | 适用场景 |
|---|---|---|---|---|
| 直接使用 | 0 | 极低 | 分钟级 | 通用任务 |
| 微调 | 1K-100K 条 | 低-中 | 小时级 | 定制化需求 |
| 继续预训练 | 1B-10B tokens | 中-高 | 天级 | 垂直领域 |
| 从零训练 | 1T+ tokens | 极高 | 月级 | 基础模型研发 |
计算成本对比(以 7B 模型为例):
| 阶段 | 从零预训练 | 基于开源微调 | 节省比例 |
|---|---|---|---|
| 数据准备 | 数月 + 数百万美元 | 数周 + 数万美元 | 99%+ |
| 预训练 | 2000+ GPU 天 | 0(已省略) | 100% |
| 微调/对齐 | 数十 GPU 天 | 数十 GPU 天 | 0% |
| 总计 | 数百万美元 | 数千美元 | 99%+ |
开源权重的真正价值
开源权重 = 免费的"大学毕业生"
1 | |
你不需要知道他小学学了什么、中学怎么过的,只需要教他"我们公司的工作方式"。
开源权重的价值是"站在巨人的肩膀上":
- 跳过最昂贵的预训练阶段:LLaMA-2 的预训练成本估计在 200-500 万美元
- 获得"通用能力基座":模型已经学会了语言理解、推理、知识等
- 降低数据门槛:从零训练需要万亿级 tokens,微调只需要千/万级高质量数据
厂商的真正竞争力
即使开源了权重,原厂仍然有优势:
| 能力 | 开源权重提供 | 原厂优势 |
|---|---|---|
| 数据质量 | ❌ | ✅ 高质量数据管道 |
| 训练技巧 | ❌ | ✅ 超参数、架构优化经验 |
| 规模效应 | ❌ | ✅ 大规模集群、成本优势 |
| 持续迭代 | ❌ | ✅ 可以训练下一代模型 |
| 生态建设 | 部分 | ✅ 社区贡献反哺 |
一句话总结:
开源权重给你的是"结果",不是"配方"。你可以基于这个结果继续开发,但想做出同样好的"原版",还需要自己掌握配方。
6.0.1.2 大模型的"大"意味着什么?参数、压缩与知识的本质
理解了参数的定义之后,一个更深刻的问题浮现出来:大模型学到的东西,到底是什么?
大模型的"大"就是参数多
“大模型”(Large Language Model)的"大",确实主要指参数量大——即权重(Weights)和偏置(Biases)的数量极多。参数量是衡量模型规模最直接的指标,也是决定模型能力上限的核心因素之一。
但参数多只是手段,真正的问题是:这些参数里存储了什么?
训练数据被"压缩"进了参数
一个直觉上正确的理解是:训练数据通过梯度下降被"压缩"进了模型参数。但这种压缩与我们熟悉的工程压缩(如布隆过滤器、gzip)有本质区别:
| 维度 | 布隆过滤器 | 大模型参数 |
|---|---|---|
| 压缩目标 | 元素存在性(是/否) | 语义关系和概率分布 |
| 数据类型 | 二值位 | 连续浮点数 |
| 查询方式 | 精确成员检测 | 概率性生成/推理 |
| 可泛化性 | ❌ 只能回答"见过没" | ✅ 能处理未见过的输入 |
布隆过滤器存储的是离散的、原子化的存在性标记;而大模型参数存储的是连续的、关系化的语义空间——后者能理解"国王 - 男人 + 女人 ≈ 女王"这种抽象关系,这是布隆过滤器永远做不到的。
正因为参数存储的是规律而非副本,模型才具备泛化能力:它能处理训练时从未见过的输入,因为新输入可以被映射到已学习的语义空间中。
语言存储了人类的知识吗?
这引出了一个更宏观的命题:人类的语言存储了人类的知识和智能,因此大模型通过学习语言,获得了某种程度的"智能涌现"。
这个观点部分正确,但需要谨慎区分:
- ✅ 正确的部分:语言确实是人类知识的重要载体。逻辑、常识、推理模式、世界知识都以某种形式编码在语言中。大模型通过学习这些语言模式,确实获得了令人惊叹的能力。
- ⚠️ 需要补充的部分:语言 ≠ 知识的全部。很多知识是隐性的、具身的(如骑自行车、游泳),无法被语言完整表达。更准确的说法是:语言是人类知识和智能的一种投影,大模型学习这个投影,获得了"智能模拟",但这不等同于拥有真正的智能。
大模型学到的"隐式东西"到底是什么?
大模型参数中存储的内容,可以分解为以下几个层次:
| 层次 | 内容 | 本质 |
|---|---|---|
| 第一层 | 词法-句法模式 | 词序、语法、搭配习惯 |
| 第二层 | 语义关联 | 向量空间中词与词的关系 |
| 第三层 | 知识片段 | 事实性知识的统计编码 |
| 第四层 | 推理模式 | 逻辑推理的模式匹配 |
| 第五层 | 世界知识 | 物理世界的统计规律(非物理定律) |
这些内容之所以是"隐式"的,是因为知识被"压扁"进参数中,无法分离成模块化的结构。不同于人类大脑中相对独立的知识模块,大模型的 1750 亿个参数共同、混合地编码了所有知识,没有明确的边界,也没有统一的"真理检查"机制——这就是为什么模型可能同时"相信"两个矛盾的事实。
为什么 LeCun 认为大模型没有学到"真正的知识"?
尽管大模型的泛化能力令人印象深刻,以 Yann LeCun 为代表的学者仍然认为,大模型并未学到真正的知识。其核心论点是:
统计拟合 ≠ 因果理解
大模型学到的是统计相关性,而非因果机制。用 Judea Pearl 的因果阶梯来描述:
1 | |
大模型停留在第一层:它能观察到"公鸡叫后日出"的统计规律,但不理解"日出导致公鸡叫"的因果方向。更深层的问题是,大模型没有构建对世界的独立、结构化的内部模型——知识被"压扁"进参数,无法分离,无法进行真正的规划和推理。
1 | |
LeCun 的批评不是否定大模型的实用价值,而是指出:泛化 ≠ 理解。模型的泛化能力来自统计规律的迁移,但这不等同于对底层机制的真正理解。就像一个学生可以通过刷题掌握解题模式,却不真正理解数学原理——遇到稍微变形的题目就会失败。
这也是为什么大模型会产生"幻觉"(Hallucination):当统计模式无法覆盖某个问题时,模型会生成"看起来合理"但实际错误的内容,因为它没有一个可以校验的"真实世界模型"。
6.0.2 神经网络结构:节点与层次
基本组成单元:
| 概念 | 说明 | 示例 |
|---|---|---|
| 节点(神经元) | 神经网络的基本计算单元,接收输入、产生输出 | 每层可能有数千个节点 |
| 层 | 节点的集合,负责特定类型的计算 | Transformer 模型通常有 32-96 层 |
| 权重矩阵 | 连接相邻层节点的参数 | 决定信号如何从一层传递到下一层 |
Transformer 模型的层次结构:
1 | |
参数量计算(以 Transformer 为例):
1 | |
6.0.3 Token:文本的最小处理单位
Token 的定义:
- Token 是模型处理文本的最小单位
- 一个 Token 可能是一个词、一个字,或者一个子词(subword)
- 不同模型的分词方式不同,Token 的定义也不同
Token 化过程示例:
1 | |
Token 与参数的关系:
| 关系维度 | 说明 |
|---|---|
| 输入处理 | 每个输入 Token 都会通过神经网络的所有层 |
| 上下文长度 | 参数量影响模型能处理的最大 Token 数(如 4K → 32K → 128K) |
| 计算量 | 生成 1 个 Token 需要所有参数参与计算一次前向传播 |
| 显存占用 | KV Cache 存储与 Token 数成正比 |
Token 计算的实际意义:
1 | |
6.0.4 核心关系图:从文本到输出的完整流程
1 | |
6.0.5 关键指标对照表
| 模型 | 参数量 | 层数 | 隐藏层维度 | 最大 Token 数 | 推理速度 |
|---|---|---|---|---|---|
| GPT-2 Small | 117M | 12 | 768 | 1024 | 快 |
| GPT-2 Large | 1.5B | 36 | 1600 | 1024 | 中 |
| GPT-3 | 175B | 96 | 12288 | 2048 | 慢 |
| LLaMA-7B | 7B | 32 | 4096 | 2048 | 中 |
| LLaMA-70B | 70B | 80 | 8192 | 4096 | 慢 |
| GPT-4 | ~1.8T | 未公开 | 未公开 | 128K | 很慢 |
核心规律:
- 参数量 ↑ → 表达能力 ↑,但训练/推理成本 ↑
- 层数 ↑ → 模型深度 ↑,能学习更复杂的模式
- 隐藏层维度 ↑ → 单层容量 ↑,参数量呈平方级增长
- 最大 Token 数 ↑ → 上下文长度 ↑,显存占用 ↑
6.0.6 上下文窗口:输入输出共用的容量池
核心问题:上下文窗口是仅限输入,还是输入输出共用?
答案:上下文窗口是输入输出共用的总限制,不是仅指输入。
具体来说:
- 总容量固定:上下文窗口是一个固定的 token 容量池(如 GPT-4 的 128K)
- 动态分配:输入(用户消息 + 历史对话 + 系统提示)和输出(模型生成的内容)共享这个池
- 实际计算:
1
实际可用输出 = 上下文窗口总容量 - 输入 token 数 - 示例:如果模型有 8K 上下文窗口,你的输入占用了 6K,那么模型最多只能输出 2K 的内容
为什么这很重要?
| 场景 | 问题 | 解决方案 |
|---|---|---|
| 长文档分析 | 输入占用大量窗口,输出空间不足 | 分段处理或使用更大窗口的模型 |
| 多轮对话 | 历史消息累积,窗口逐渐耗尽 | 定期总结历史或限制对话轮次 |
| 代码生成 | 需要长输出但输入也长 | 精简输入,优先保留关键上下文 |
一句话总结:
上下文窗口是一个"共享池",输入多了输出就少。这也是为什么当你发送很长的文档给模型时,它的回复会变短——因为输出空间被压缩了。
6.0.7 为什么输入输出 Token 定价不同?
核心问题:为什么模型厂商对输入 token 和输出 token 的定价不一致?
定价不一致主要基于以下几个因素:
1. 技术成本差异
| 维度 | 输入 Token | 输出 Token |
|---|---|---|
| 计算复杂度 | 相对简单,主要是 embedding 和 attention 计算 | 更复杂,需要逐个 token 自回归生成 |
| 推理时间 | 可并行处理 | 必须串行生成,无法并行 |
| 显存占用 | 主要存储 KV Cache | 需要持续维护和更新生成状态 |
2. 生成过程的本质区别
- 输入处理:模型可以一次性对所有输入 token 做 attention 计算,相对高效
- 输出生成:每生成一个 token 都需要:
- 重新计算整个序列的 attention
- 进行采样决策
- 更新 KV Cache
- 这个过程必须串行,无法加速
3. 商业策略考量
- 用户行为差异:大部分场景下输入量 >> 输出量,差异化定价可以优化整体收入结构
- 引导使用方式:鼓励用户精简输入,提高系统吞吐效率
- 成本回收:输出阶段的计算资源消耗确实更高(通常 2-3 倍)
4. 实际定价示例(以 GPT-4 Turbo 为例)
1 | |
这个 3 倍左右的定价差异在业界比较常见,基本反映了输出阶段额外计算成本的量级。
一句话总结:
输出 token 更贵,因为生成比处理更"费力"——输入可以并行处理,输出必须逐字串行生成,每生成一个字都要重新计算整个序列。
6.0.8 自回归:LLM 生成的核心机制
在深入理解训练和推理之前,必须先理解 LLM 生成的核心机制——自回归(Autoregression)。
什么是自回归?
自回归是指:每次生成一个 token,都基于之前生成的所有 token 作为上下文。这个过程可以形式化为:
1 | |
即:整个序列的概率等于每个 token 条件概率的乘积。
生成过程示例:
1 | |
自回归的本质:概率预测,而非逻辑推理
这里有一个关键问题:自回归模型是否具有"数学计算能力"?
答案是:自回归模型本身不具备传统意义上的数学计算能力。它表现出的"计算能力"来自训练数据中的统计规律,而非真正的逻辑推理。
| 维度 | 自回归模型 | 传统计算器 |
|---|---|---|
| 计算方式 | 概率预测 | 算术运算 |
| 本质 | “看到 A,预测 B 可能出现” | “执行 A + B 的运算” |
| 精确性 | 依赖训练数据覆盖度 | 100% 精确 |
| 泛化能力 | 对训练数据外的计算容易出错 | 对所有输入都精确 |
具体例子:
- "2 + 2 = ?" → 模型预测 “4”,因为训练数据中这个模式出现过无数次
- "12345 × 67890 = ?" → 模型很可能出错,因为:
- 训练数据中很少出现这种大数乘法
- 模型没有真正的乘法运算能力
- 它只能"猜"一个看起来像答案的数字
为什么 LLM 需要工具调用?
正是因为自回归模型没有真正的计算能力,现代 LLM 引入了**工具调用(Tool Calling)**机制:
1 | |
这就是为什么 GPT-4、Claude 等模型都支持调用 Python 解释器、搜索引擎等外部工具——用真正的计算能力弥补概率预测的不足。
自回归与推理的关系:
理解了自回归,就能理解为什么推理是"单次前向传播":
- 每生成一个 token,都需要一次完整的神经网络前向传播
- 生成 100 个 token,就需要 100 次前向传播
- 这也是为什么 LLM 推理比传统软件慢得多——它不是"执行代码",而是"逐字预测"
一句话总结自回归:
自回归是"猜下一个字"的数学形式化。每一步都是概率计算,不存在"思考"或"推理",只有"预测"。模型表现出的"智能"来自训练数据中的统计规律,而非真正的逻辑能力。
6.0.9 Inference vs Reasoning:两个容易混淆的概念
在讨论 LLM 时,“inference” 和 “reasoning” 这两个词经常被混用,但它们实际上是两个完全不同的概念。
核心定义
| 概念 | 英文原意 | 在 AI 语境下的含义 |
|---|---|---|
| Inference | 推断、推论 | 模型的前向传播计算过程,即从输入生成输出的物理计算 |
| Reasoning | 推理、思考 | 模型进行逻辑推导、分析、综合的认知能力 |
关键区别
1 | |
这个关系可以理解为:
-
一切 reasoning 都是 inference
Reasoning 能力必须通过 inference 过程才能展现。没有 inference 这个"载体",reasoning 无从谈起。 -
能够 inference 的模型不一定具备 reasoning 能力
早期的小模型(如简单的 RNN、小型 Transformer)可以 inference,但几乎没有 reasoning 能力。它们只是"模式匹配",而非真正的逻辑推导。
一个形象的类比
| 概念 | 类比 | 说明 |
|---|---|---|
| Inference | 汽车引擎运转 | 物理过程,引擎能转就能跑 |
| Reasoning | 智能驾驶能力 | 认知能力,能跑不等于会自动驾驶 |
- 所有智能驾驶都依赖引擎运转(reasoning ⊂ inference)
- 但引擎能运转 ≠ 具备智能驾驶能力(inference ≠ reasoning)
模型演进视角
| 模型类型 | Inference 能力 | Reasoning 能力 |
|---|---|---|
| 简单 RNN/LSTM | ✅ 能运行 | ❌ 几乎没有 |
| 小型 Transformer | ✅ 能运行 | ⚠️ 非常有限 |
| GPT-3 | ✅ 能运行 | ✅ 初步具备 |
| GPT-4 / Claude | ✅ 能运行 | ✅ 强大的 CoT reasoning |
| o1 / DeepSeek-R1 | ✅ 能运行 | ✅ 专门的 reasoning 模型 |
Reasoning 模式的出现
现代大模型(如 o1、Claude)确实有显式的 reasoning 模式:
- Chain-of-Thought(思维链):逐步展示推理过程
- Step-by-step reasoning:分步骤解决问题
- Self-reflection(自我反思):检查和修正自己的推理
这些是训练/推理时专门强化的能力,不是所有模型都具备。这也是为什么 o1 等模型被称为"reasoning model"——它们在 inference 过程中会先进行大量的"思考"(生成 hidden tokens),然后再输出最终答案。
一句话总结
Inference 是"能跑",Reasoning 是"会想"。能跑不一定会想,但会想必须先能跑。Inference 是计算过程,Reasoning 是在这个过程中展现的认知能力。
6.0.10 分阶段训练的本质:时序覆写而非梯度混合
理解了参数和权重之后,一个自然的问题浮现:为什么大模型要分成预训练、持续预训练、后训练等多个阶段,而不是把所有数据混在一起一次训练完?
混合训练 vs 分阶段训练
混合训练(危险):
1 | |
分阶段训练(可控):
1 | |
分阶段训练的本质是 last-write-wins(时序覆写):每个阶段只有一种梯度信号,方向一致,收敛稳定;后训练在已经"懂语言"的基础上调整"行为偏好",不需要同时学语言。
覆写 ≠ 擦除:两种知识为何能共存?
这里有一个看似矛盾的地方:如果后训练覆写了预训练,为什么通用知识没有被擦除?两种知识同时存在,这不还是"混合"吗?
答案是:这确实是一种混合,但是"结果层面的混合",而非"梯度层面的混合"。
| 层次 | 混合训练 | 分阶段训练 |
|---|---|---|
| 梯度层次 | 两种梯度同时更新同一参数,互相抵消 ❌ | 每阶段只有一种梯度,方向一致 ✅ |
| 参数层次 | 参数同时被两种目标拉扯,无法收敛 ❌ | 参数被顺序修改,后者在前者基础上调整 ✅ |
| 知识层次 | 两种知识最终都存在 ✅ | 两种知识最终都存在 ✅ |
通用知识之所以不被擦除,是因为后训练的数据量远小于预训练,只能修改参数空间的一个小子集。LoRA 等技术更是显式限制了修改的参数范围(通常只改动全部参数的 0.1%)。如果后训练数据量和预训练一样大,通用知识就真的会被覆盖——这就是灾难性遗忘(Catastrophic Forgetting)。
更直观的比喻:
- 梯度混合:两个人同时拉着你的手往不同方向走,你哪里也去不了
- 分阶段覆写:先跟 A 学走路,再跟 B 学跳舞。最终你既会走路又会跳舞,但学习过程是有序的
Fine-tuning 是填 Gap 的工具,不是独立阶段
在这个框架下,Fine-tuning 不是一个独立的训练阶段,而是一把可以在不同阶段使用的手术刀:
| 你想解决的 Gap | 正确的工具 |
|---|---|
| 模型不懂领域词汇/知识 | 持续预训练(领域 Fine-tuning) |
| 模型不会听指令/对话 | SFT(监督微调,这本身就是 Fine-tuning) |
| 模型价值观不对齐 | RLHF / DPO |
| 模型在特定任务表现差 | 任务特化 Fine-tuning |
1 | |
一句话总结:分阶段训练是工程上的妥协,不是数学上的完美隔离。最终参数里的知识确实是"混合"的,但这个混合是有序叠加的结果,而非梯度级别的相互干扰。
6.1 核心问题:为什么训练和推理是两回事?
很多人有一个直觉误区:既然训练和推理都是"计算",为什么不能用同一套硬件?为什么训练完的模型不能直接在 CPU 上跑,非要上推理卡?
答案在于:训练和推理虽然都涉及矩阵运算,但它们的计算模式、内存访问模式、精度要求和延迟容忍度完全不同。这就像"建造工厂"和"工厂生产"的区别——前者需要重型机械和大量原材料,后者只需要流水线和工人。
6.2 计算模式的本质差异
6.2.1 训练:海量数据的并行"反向传播"
训练的核心是反向传播(Backpropagation),即根据损失函数的梯度,逐层更新数十亿甚至数万亿个参数。这个过程有三个关键特征:
| 特征 | 训练 | 推理 |
|---|---|---|
| 计算量 | 每个样本都要计算前向+反向两次,计算量是推理的 2-3 倍 | 只计算前向传播一次 |
| 内存访问 | 需要存储所有中间激活值(用于反向传播),内存占用是推理的 10-100 倍 | 只需要存储当前层的激活值 |
| 精度要求 | 必须用 FP32 或 BF16,否则梯度消失/爆炸 | 可以用 FP16 甚至 INT8 量化,精度损失可接受 |
具体来说:
- 前向传播:输入数据逐层通过神经网络,每层的输出(激活值)都需要保存下来,因为反向传播时要用。
- 反向传播:根据损失函数计算梯度,逐层反向传递。这个过程需要:
- 读取之前保存的所有激活值
- 计算梯度(涉及大量矩阵乘法和转置)
- 更新参数(写入内存)
这意味着训练时的内存访问量是推理的数十倍甚至上百倍。一个 175B 参数的模型,训练时需要数百 GB 的显存来存储中间激活值,而推理时只需要几十 GB。
6.2.2 推理:单次前向传播的"快闪计算"
推理只需要一次前向传播:
1 | |
每层的计算完成后,中间结果就可以丢弃,不需要保存。这使得推理的内存访问模式非常"干净":
- 顺序访问:一层一层往下算,内存访问模式可预测
- 一次性使用:中间结果用完即弃,不需要反复读写
- 低精度可行:不需要梯度计算,可以用 INT8 量化,速度提升 2-4 倍
6.3 为什么训练集群不能直接用于推理?
6.3.1 硬件架构的根本差异
训练集群的特点:
- 高带宽互联:多 GPU 之间需要频繁交换梯度数据,依赖 NVLink/InfiniBand 等高速互联
- 大容量显存:需要存储海量中间激活值,H100 80GB 是标配
- 高算力密度:需要大量矩阵运算单元(Tensor Core)
推理集群的特点:
- 低延迟优先:用户关注的是响应时间,而不是吞吐量
- 内存和带宽敏感:模型参数和中间结果需要快速加载与访问
- 批量处理能力弱:通常为单个或小批量请求服务,无需大规模并行
- 成本敏感:推理场景下,设备功耗和部署成本更为重要
例如,一张 H100 卡功耗可达 700W,散热要求高;而在推理端,更倾向于选择低功耗、低成本的方案如 A10 或 T4。
因此,在实际应用中,训练和推理对硬件的需求存在显著差异,不能简单地将训练集群用于推理任务。
6.3.2 实际案例:为什么不能混用?
假设你有一个 8 卡 H100 训练集群(总成本约 200 万人民币):
用于训练:
- 可以训练 70B 参数模型
- 吞吐量:每秒处理数万 token
- 性价比:高(硬件利用率 80%+)
用于推理:
- 单个请求延迟:可能比专用推理卡还慢(因为通信开销)
- 吞吐量:浪费了 90% 的算力(因为批量小)
- 性价比:极低(硬件利用率 <10%)
结论:用训练集群做推理,相当于开法拉利送外卖——能送,但成本是外卖费的几十倍。
6.4 为什么不能用 CPU 直接推理?
6.4.1 CPU 和 GPU 的架构差异
| 维度 | CPU | GPU |
|---|---|---|
| 核心数 | 少(几十个) | 多(数千个) |
| 单核性能 | 强(高主频、复杂指令集) | 弱(低主频、简单指令集) |
| 并行能力 | 弱(适合串行任务) | 强(适合大规模并行) |
| 内存带宽 | 低(~100 GB/s) | 高(~3000 GB/s) |
| 专用加速 | 无(或少量 AVX 指令) | 有(Tensor Core、矩阵加速器) |
神经网络的计算特点:
- 海量矩阵乘法:一个 7B 模型的单次推理,涉及数十亿次浮点乘加运算
- 高度并行:矩阵乘法可以拆分成数千个独立的小任务并行执行
- 内存带宽瓶颈:模型参数要从内存加载到计算单元,带宽决定速度
6.4.2 实际性能差距
以 7B 模型为例(参数量 70 亿,模型文件约 14GB):
| 硬件 | 推理速度 | 延迟 | 成本 |
|---|---|---|---|
| CPU(Intel i9) | ~1 token/s | 分钟级 | 低(硬件成本低) |
| 消费级 GPU(RTX 4090) | ~50 token/s | 秒级 | 中(1.5 万人民币) |
| 推理卡(A10) | ~80 token/s | 亚秒级 | 中高(2-3 万人民币) |
| 高端训练卡(H100) | ~150 token/s | 亚秒级 | 极高(25 万人民币) |
CPU 推理的实际问题:
- 速度太慢:生成 100 个 token 需要 1-2 分钟,用户体验极差
- 内存带宽瓶颈:CPU 的内存带宽只有 GPU 的 1/30,参数加载成为瓶颈
- 没有专用加速:CPU 没有 Tensor Core,矩阵乘法效率低
6.4.3 什么时候可以用 CPU 推理?
CPU 推理并非完全不可用,在以下场景可以考虑:
- 小模型(<1B 参数):如 BERT-base、DistilBERT
- 低频调用:每天只有几十次请求,延迟不敏感
- 边缘设备:手机、IoT 设备,无法部署 GPU
- 成本优先:初创公司验证产品,不想投入硬件成本
优化方案:
- 模型量化:将 FP32 量化为 INT8,速度提升 2-4 倍
- 模型剪枝:删除不重要的神经元,减少计算量
- 专用指令集:使用 AVX-512、ARM NEON 等加速指令
6.5 推理卡的价值:为推理而生的硬件
6.5.1 推理卡的设计哲学
推理卡(如 NVIDIA A10、T4、L40S)是专门为推理场景设计的,其设计哲学是:
- 低延迟优先:优化单次推理的响应时间
- 高内存带宽:快速加载模型参数
- 低功耗:单卡功耗 70W-300W(训练卡是 350W-700W)
- 高性价比:用更低的成本实现可接受的性能
6.5.2 推理卡 vs 训练卡:关键差异
| 维度 | 训练卡(H100) | 推理卡(A10) |
|---|---|---|
| 显存 | 80GB HBM3 | 24GB GDDR6 |
| 内存带宽 | 3352 GB/s | 600 GB/s |
| 算力(FP16) | 1979 TFLOPS | 125 TFLOPS |
| 功耗 | 700W | 150W |
| 价格 | ~25 万人民币 | ~2.5 万人民币 |
| 性价比(推理) | 低 | 高 |
关键洞察:推理卡的算力只有训练卡的 1/16,但价格只有 1/10,功耗只有 1/5。对于推理场景,推理卡的性价比远高于训练卡。
6.5.3 推理卡的实际应用
典型部署方案:
-
云端推理:
- 使用 A10/T4 等推理卡
- 支持多模型并行部署
- 动态扩缩容,按需付费
-
边缘推理:
- 使用 Jetson 系列嵌入式 GPU
- 模型量化为 INT8
- 功耗 <15W,适合边缘设备
-
混合部署:
- 小模型用 CPU
- 中型模型用推理卡
- 大模型用高端训练卡(但成本高)
6.6 技术趋势:训练和推理的边界在模糊
6.6.1 统一架构的出现
NVIDIA 的 H100 同时支持训练和推理,AMD 的 MI300 系列也采用统一架构。这意味着:
- 同一硬件可以做两件事:但性价比仍不如专用硬件
- 灵活调度:训练任务结束后,可以快速切换为推理服务
- 成本优化:对于中小公司,可以减少硬件采购种类
6.6.2 推理优化技术的进步
- Flash Attention:优化注意力计算的内存访问,推理速度提升 2-3 倍
- KV Cache 优化:减少重复计算,加速生成式推理
- 模型量化:INT8/INT4 量化技术成熟,精度损失可控
- 投机解码:用小模型"猜测"大模型的输出,加速推理
这些技术让推理卡的性能不断提升,甚至在某些场景下超越训练卡。
6.6.3 专用推理芯片的崛起
除了 GPU,越来越多的专用推理芯片出现:
- Google TPU:专为 TensorFlow 推理设计
- Groq LPU:语言处理专用芯片,推理速度极快
- 华为昇腾 310:边缘推理专用,功耗仅 8W
- 寒武纪思元:国产 AI 推理芯片
这些芯片放弃了训练能力,专注于推理场景,性价比往往优于通用 GPU。
6.7 一句话总结
训练是"建工厂",推理是"工厂生产"。训练需要海量算力和显存来反向传播更新参数,推理只需要低延迟的前向传播。用训练集群做推理,就像用超算跑单线程程序——能跑,但成本是正常方案的几十倍。推理卡的价值在于:用更低的成本、更低的功耗,实现可接受的推理性能。
OpenClaw:一个 AI Agent 框架的分层解剖
核心理念:分层隔离,职责单一
一个生产级的 AI Agent 框架,本质上是一套关注点分离的工程实践。用户看到的是"和 AI 对话",框架内部却在协调五个截然不同的层次:接入层、控制层、智能层、能力层、执行层。每一层只做自己该做的事,层与层之间通过标准接口通信。
这种分层思想并不新鲜——它和经典的 OSI 网络模型、MVC 架构一脉相承。新鲜的是:当 LLM 成为核心决策单元后,如何在它的上下游构建可靠的工程脚手架。
OpenClaw 五层架构全景
flowchart LR
subgraph ChatChannels["💬 ChatChannels\n接入层"]
WhatsApp["WhatsApp"]
Telegram["Telegram"]
end
subgraph ControlPlane["🔀 OpenClawGateway\nControlPlane 控制层"]
SessionRouter["SessionRouter"]
Config["Config\n(openclaw.json)"]
WSServer["WSServer\n(18789)"]
end
subgraph AgentLayer["🧠 AgentLayer\n智能层"]
PIAgentRuntime["PIAgentRuntime"]
Sessions["Sessions\n(main/group)"]
SkillsRegistry["SkillsRegistry\n(ClawHub+Workspace)"]
end
subgraph LLMProviders["☁️ LLMProviders\nLLM 提供商"]
AnthropicClaude["AnthropicClaude"]
OpenAI["OpenAI"]
CNModels["CNModels\n(DeepSeek/Qwen/etc.)"]
end
subgraph ToolsLayer["🔧 ToolsLayer\n工具层"]
BrowserTool["BrowserTool\n(Chromium)"]
SystemRun["SystemRun\n(Shell/FS)"]
CronJobs["CronJobs"]
Webhooks["Webhooks"]
end
subgraph DeviceNodes["📱 DeviceNodes\n设备节点"]
macOSNode["macOSNode"]
IOSNode["IOSNode"]
AndroidNode["AndroidNode"]
end
ChatChannels --> ControlPlane
ControlPlane --> AgentLayer
AgentLayer --> LLMProviders
AgentLayer --> ToolsLayer
ToolsLayer --> DeviceNodes
style ChatChannels fill:#fff9c4
style ControlPlane fill:#fff9c4
style AgentLayer fill:#fff9c4
style LLMProviders fill:#fff9c4
style ToolsLayer fill:#fff9c4
style DeviceNodes fill:#fff9c4
五层职责对比
| 层次 | 核心职责 | 关键组件 | 设计要点 |
|---|---|---|---|
| 💬 ChatChannels | 多渠道消息接入 | WhatsApp、Telegram | 屏蔽渠道差异,统一消息格式 |
| 🔀 ControlPlane | 会话路由与配置管理 | SessionRouter、WSServer(18789) | 单一入口,配置驱动(openclaw.json) |
| 🧠 AgentLayer | 智能决策核心 | PIAgentRuntime、SkillsRegistry | 技能注册表连接 ClawHub 与本地 Workspace |
| ☁️ LLMProviders | 模型调用抽象 | Claude、OpenAI、国产模型 | 多模型适配,避免厂商锁定 |
| 🔧 ToolsLayer | 真实世界能力执行 | Browser、Shell/FS、CronJobs | Agent 的"手脚",工具调用的落地层 |
| 📱 DeviceNodes | 跨平台设备执行 | macOS、iOS、Android | 工具层的物理延伸,实现跨设备操作 |
关键设计决策解读
为什么 ControlPlane 独立于 AgentLayer?
ControlPlane 处理的是会话管理(谁在说话、说到哪了),AgentLayer 处理的是智能决策(该怎么回答)。两者的变化频率和扩展方向完全不同:前者随渠道增加而扩展,后者随模型能力提升而演进。强行耦合会导致"换个 LLM 要改路由逻辑"的荒谬局面。
为什么 ToolsLayer 和 DeviceNodes 分离?
工具的定义(BrowserTool 能做什么)和工具的执行环境(在哪台设备上跑)是两个正交维度。分离后,同一个 CronJob 工具可以在 macOS 节点或 Android 节点上执行,无需为每个设备重写工具逻辑。
Agentic Loop:AI Agent 的心跳
核心理念:循环是智能的本质
如果说五层架构是 Agent 的骨架,那么 Agentic Loop 就是它的心跳。
一个 LLM 的单次调用是无状态的——它接收输入、产生输出、然后结束。但真实世界的任务需要多步推理、工具调用、结果验证、再次推理。Agentic Loop 正是将这个"单次调用"变成"持续循环"的工程机制:只要 LLM 还想调用工具,循环就不停止;直到 LLM 决定输出最终文本,循环才结束。
这个设计的深刻之处在于:决策权在 LLM,而非框架。框架只负责忠实地执行 LLM 的意图,不预设任务步骤数。
完整消息流:从用户输入到最终回复
flowchart TD
User(["👤 用户\n(Telegram/Discord 等)"])
ChannelAdapter1["渠道适配器\n(标准化消息,提取附件)"]
GatewayServer["Gateway Server\n网关服务器(协调器)\n将消息路由到正确的会话"]
SessionRouter["会话路由器"]
LaneQueue["Lane 队列\n(会话控制层)"]
subgraph AgentRunner["🧠 Agent Runner 智能体运行器"]
ModelParser["模型解析器"]
SystemPromptBuilder["System Prompt 构建器\n(tools, skills, memory)"]
SessionHistoryLoader["Session 历史加载器"]
ContextWindowGuard["Context Window Guard\n上下文窗口守卫(必要时压缩)"]
ModelParser --- SystemPromptBuilder --- SessionHistoryLoader
ModelParser --> ContextWindowGuard
SystemPromptBuilder --> ContextWindowGuard
SessionHistoryLoader --> ContextWindowGuard
end
LLMAPI["LLM API"]
subgraph AgenticLoop["🔄 Agentic Loop 智能体循环"]
LLMResponse["LLM 响应"]
ToolCallCheck{"tool call?"}
Execute["执行工具"]
FinalText["Final Text 最终文本"]
ToolA["Tool A"]
ToolB["Tool B"]
ToolC["Tool C"]
ToolD["Tool D"]
LLMResponse --> ToolCallCheck
ToolCallCheck -->|"是"| Execute
ToolCallCheck -->|"否"| FinalText
Execute --> ToolA & ToolB & ToolC & ToolD
Execute -->|"结果回注"| LLMResponse
end
subgraph ResponsePath["📤 Response Path 回复路径"]
StreamChunker["流式分块"]
ChannelAdapter2["渠道适配器"]
StreamChunker --> ChannelAdapter2
end
User -->|"消息"| ChannelAdapter1
ChannelAdapter1 --> GatewayServer
GatewayServer --> SessionRouter
SessionRouter --> LaneQueue
LaneQueue --> AgentRunner
AgentRunner --> LLMAPI
LLMAPI --> AgenticLoop
AgenticLoop -->|"Final Text"| ResponsePath
ResponsePath --> User
AgentRunner <-->|"上下文压缩/重建"| ContextWindowGuard
style AgentRunner fill:#1a1a2e,color:#ffffff
style AgenticLoop fill:#1a1a2e,color:#ffffff
style ResponsePath fill:#1a1a2e,color:#ffffff
style GatewayServer fill:#2d2d2d,color:#ffffff
六个核心模块的职责拆解
1. 渠道适配器(Channel Adapter)
入口处的标准化层。无论用户通过 Telegram 发来图片、Discord 发来 Markdown、还是 Slack 发来 @mention,渠道适配器都将其转换为框架内部统一的消息格式。
这是**防腐层(Anti-Corruption Layer)**的经典应用:外部世界的混乱不应该污染内部系统的整洁。
2. Gateway Server(网关服务器)
会话的交通指挥官。核心职责是"将消息路由到正确的会话"——听起来简单,实则复杂:
- 同一个用户可能有多个并发会话(主会话 + 群组会话)
- 消息需要按会话隔离,不能串台
- Lane 队列提供背压控制,防止消息洪峰压垮 Agent Runner
3. Agent Runner(智能体运行器)
上下文的组装工厂,也是整个架构中最复杂的模块。每次调用 LLM 之前,它需要:
| 子组件 | 职责 | 类比 |
|---|---|---|
| 模型解析器 | 根据任务选择合适的 LLM | 派单系统 |
| System Prompt 构建器 | 组装工具列表、技能说明、记忆摘要 | 给员工发工作手册 |
| Session 历史加载器 | 加载本次会话的对话历史 | 翻看会议记录 |
| Context Window Guard | 监控 Token 用量,必要时压缩历史 | 会议室容量管理员 |
Context Window Guard 是最容易被忽视却最关键的组件。LLM 的上下文窗口是有限资源,长对话必然触顶。Guard 的策略通常是:保留最近 N 轮对话 + 对早期历史做摘要压缩,在"记得住"和"放得下"之间找平衡。
4. Agentic Loop(智能体循环)
框架的心跳,也是"智能"真正发生的地方:
1 | |
这个循环的优雅之处在于:工具执行结果会作为新的上下文回注给 LLM,LLM 基于新信息做出下一步决策。这正是 ReAct(Reasoning + Acting)范式的工程实现。
多个工具(Tool A/B/C/D)可以并行执行——当 LLM 在一次响应中请求多个独立工具调用时,框架无需串行等待,可以并发执行后统一回注结果,显著降低延迟。
5. Response Path(回复路径)
出口处的用户体验层。Final Text 不是直接发给用户的,而是经过:
- 流式分块(Stream Chunker):将完整响应切成小块,实现"打字机效果",降低用户感知延迟
- 渠道适配器:将内部格式转换回目标渠道的消息格式(Telegram Markdown、Discord Embed 等)
注意这里的渠道适配器和入口处是同一个组件的两个方向——这是双向适配器模式,入口标准化、出口还原化。
两张图的本质关联
第一张图(OpenClaw 五层架构)回答的是:系统由哪些部分组成?
第二张图(Agentic Loop 消息流)回答的是:一条消息是如何在系统中流动的?
两者的关系是静态结构与动态行为的互补:
1 | |
AgentLayer 在静态视角中是一个方框,在动态视角中展开为 Agent Runner + Agentic Loop 的完整机制。架构图告诉你有什么,时序图告诉你发生了什么——两种视角缺一不可。
深层反思:为什么 Agentic Loop 是不可绕过的设计
✅ 它解决了 LLM 的根本局限
LLM 本身是无状态的函数:f(context) → response。它不能主动发起网络请求,不能记住上次对话,不能执行代码。Agentic Loop 通过外部状态管理 + 工具执行 + 历史注入,将无状态函数变成了有状态的智能体。
✅ 它保持了 LLM 的决策主权
框架不预设"这个任务需要几步"。LLM 自己决定何时调用工具、调用哪个工具、何时停止。这意味着同一个框架可以处理"查一下天气"(1次工具调用)和"帮我写一个完整的 Web 应用并部署"(数十次工具调用)——复杂度由任务决定,而非框架硬编码。
⚠️ 它也带来了新的工程挑战
| 挑战 | 根因 | 应对策略 |
|---|---|---|
| 无限循环风险 | LLM 可能陷入"调用工具 → 结果不满意 → 再调用"的死循环 | 设置最大迭代次数上限 |
| 上下文爆炸 | 每次工具调用都会增加历史长度,最终超出窗口 | Context Window Guard 压缩策略 |
| 工具调用失败 | 外部工具不可靠,网络超时、权限不足等 | 重试机制 + 错误信息回注给 LLM |
| 成本失控 | 多轮调用 = 多倍 Token 消耗 | 预算上限 + 轻量模型处理简单步骤 |
最终洞察
Agentic Loop 的本质是一个反馈控制系统:LLM 是控制器,工具是执行器,工具结果是传感器反馈,最终文本是系统稳定后的输出。这和工业控制系统的 PID 控制器、生物体的神经反射弧,在结构上惊人地相似。
AI Agent 框架的成熟标志,不是支持多少种工具,而是在 Loop 失控时能否优雅降级——这才是工程可靠性的真正考验。





