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 时代开发者的启示

  1. 没有永恒的巅峰:Rostow 模型的核心缺陷是假设"第五阶段是终点"。实际上,经济增长没有终点,技术演进也没有终点——爬上一座山峰,只是为了继续攀登下一座
  2. 警惕"到达顶峰"的心态:当团队认为"我们已经很先进了",恰恰是衰退的开始。中国的目标不是与美国一起"欣赏风景",而是持续向上攀登。
  3. 两条路径的抉择:第五阶段之后,要么走向衰退,要么走向重塑——通过自动化与前沿技术开启新一轮增长。选择权在人类手中

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
2
3
4
5
6
7
8
9
10
11
用户提问

项目加载背景知识(历史研报、竞品文档)

MCP 激活外部连接(Drive + GitHub + 搜索)

技能启动分析框架(竞争分析方法论)

子代理并行执行(市场研究代理 + 技术分析代理)

综合洞察输出(人类仅需审视结论)

人类的角色:设定研究方向、审视最终结论、在结果偏离预期时纠偏。


常见误区澄清

误区 正解
❌ 技能 vs 子代理二选一 互补关系——子代理可以加载技能获得专业知识
❌ 项目 vs 技能重复建设 分工明确——项目说"你需要知道这些",技能说"你要这样做"
❌ MCP 替代技能 前后衔接——MCP 负责"连得上",技能负责"做得好"
❌ 所有场景都用人机协同 模式分层——Quest 模式交给 AI 端到端,Editor 模式高频确认

深层启示:构建个人 AI 工位的方法论

  1. 从提示词开始,向技能沉淀——重复三次以上的指令,立即技能化
  2. 项目作为知识中枢——按主题组织,避免每次对话重新投喂上下文
  3. 子代理实现权责分离——危险操作限定只读,复杂任务拆分到专职代理
  4. MCP 打通数据闭环——减少人工搬运,让 AI 直接操作一手信息源
  5. 保留"无 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
2
3
4
5
这个图整个就是 Indexing

原始文档 → [Chunking] → 文档块 → [Embedding] → 向量库

架构的基石

为什么必须在最前面?

  1. 决定检索粒度:块的大小直接影响后续检索的精度和召回率
  2. 影响嵌入质量:块的语义完整性决定了向量表示的准确性
  3. 不可逆操作:一旦索引完成,重新分块需要重建整个向量库

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
2
3
4
def fixed_size_chunking(text, chunk_size=200):
return [text[i:i+chunk_size] for i in range(0, len(text), chunk_size)]

# 输出示例:每块固定 200 字符,可能在单词中间截断

Level 2: Recursive Chunking(递归分块)

原理

先按自然分隔符(如段落、句子)切分,若某块超过阈值,则递归地进一步细分。

特点

  • 尊重文本结构:优先保留段落和句子的完整性
  • 灵活可控:通过多级分隔符(\n\n.,)逐步细化
  • ⚠️ 边界依赖:依赖明确的分隔符,对非结构化文本效果有限

适用场景

  • 结构化文档(如技术文档、学术论文)
  • 需要平衡语义完整性和块大小的场景

示例代码

1
2
3
4
5
6
7
8
9
10
def recursive_chunking(text, max_size=500, separators=['\n\n', '. ', ', ']):
chunks = text.split(separators[0])
result = []
for chunk in chunks:
if len(chunk) <= max_size:
result.append(chunk)
else:
# 递归使用下一级分隔符
result.extend(recursive_chunking(chunk, max_size, separators[1:]))
return result

Level 3: Document Structure-Based Chunking(文档结构分块)

原理

利用文档的内在结构(标题、章节、列表)作为分块边界,保持逻辑单元的完整性。

特点

  • 语义对齐:块与文档的逻辑结构天然对应
  • 可解释性强:每个块对应明确的章节或主题
  • 结构依赖:要求文档有清晰的层级结构(Markdown、HTML 等)
  • 块大小不均:某些章节可能过长或过短

适用场景

  • Markdown、HTML、PDF 等结构化文档
  • 需要保留文档层级关系的知识库

示例代码

1
2
3
4
5
6
7
8
import re

def structure_based_chunking(markdown_text):
# 按 Markdown 标题切分
chunks = re.split(r'^(#{1,6}\s+.+)$', markdown_text, flags=re.MULTILINE)
return [chunk.strip() for chunk in chunks if chunk.strip()]

# 输出示例:每个块对应一个标题及其内容

Level 4: Semantic Chunking(语义分块)

原理

通过嵌入模型计算相邻句子的语义相似度,当相似度显著下降时创建新块。

特点

  • 语义连贯:块内的句子主题一致,跨块时主题切换
  • 自适应边界:无需预设分隔符,自动识别主题转换点
  • 计算密集:需要为每个句子生成嵌入并计算相似度
  • ⚠️ 阈值敏感:相似度阈值的选择影响块的粒度

适用场景

  • 主题多变的长文本(如新闻、博客)
  • 对语义完整性要求极高的场景

示例代码

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
45
46
47
48
49
50
51
52
53
54
55
56
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity

def semantic_chunking(text, similarity_threshold=0.7):
"""
基于语义相似度的文本分块函数

该函数使用嵌入模型将文本按语义相关性分割成多个块(chunks),
相邻句子如果语义相似度高于阈值则归为同一块,否则开始新块。

Args:
text: 待分块的原始文本
similarity_threshold: 余弦相似度阈值,默认0.7。
值越大要求相邻句子越相似才能归为同一块,
导致分块更细;值越小则分块更粗。

Returns:
chunks: 分块后的文本列表
"""
# 1. 加载预训练的句子嵌入模型(Sentence Transformer)
# 该模型会将文本转换为固定维度的向量表示(embedding)
model = SentenceTransformer('all-MiniLM-L6-v2')

# 2. 将文本按句号分割成句子列表
sentences = text.split('. ')

# 3. 对所有句子进行向量化(embedding)
# 这是一个批量操作,将每个句子转换为一个数值向量
# 语义相近的句子会得到相近的向量表示
embeddings = model.encode(sentences)

# 4. 初始化分块结果列表和当前块
chunks = []
current_chunk = [sentences[0]] # 第一个句子作为第一个块的起始

# 5. 遍历后续句子,基于语义相似度决定是否归入当前块
for i in range(1, len(sentences)):
# 计算当前句子与前一句子的余弦相似度
# cosine_similarity 返回相似度矩阵,[0][0]提取标量值
# 余弦相似度范围:[-1, 1],值越接近1表示越相似
similarity = cosine_similarity(
[embeddings[i-1]], [embeddings[i]]
)[0][0]

# 6. 根据相似度阈值决定分块策略
if similarity >= similarity_threshold:
# 相似度高于阈值:语义连贯,归入当前块
current_chunk.append(sentences[i])
else:
# 相似度低于阈值:语义转折,结束当前块并开始新块
chunks.append('. '.join(current_chunk))
current_chunk = [sentences[i]]

# 7. 将最后一个块加入结果
chunks.append('. '.join(current_chunk))
return chunks

深入理解: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

核心原理

  1. 离线阶段:文档被切分成块后,每个块通过 embedding 模型转换为向量并存储
  2. 在线阶段:用户问题也通过同一个 embedding 模型转换为向量
  3. 相似度匹配:在同一向量空间中,计算问题向量与所有文档块向量的相似度
  4. 返回结果:相似度最高的 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
2
3
4
5
6
7
8
9
10
11
12
13
# 示例:为什么余弦相似度更适合文本?

# 文档 A:"机器学习很有趣"
vec_A = [0.2, 0.5, 0.3] # embedding 向量

# 文档 B:"机器学习很有趣很有趣很有趣"(重复3次)
vec_B = [0.6, 1.5, 0.9] # 向量长度是 A 的 3 倍

# 欧氏距离:认为 A 和 B 差异很大
euclidean_distance = sqrt((0.2-0.6)² + (0.5-1.5)² + (0.3-0.9)²) = 1.73

# 余弦相似度:认为 A 和 B 完全相同(方向一致)
cosine_similarity = (0.2×0.6 + 0.5×1.5 + 0.3×0.9) / (sqrt(0.38) × sqrt(3.42)) = 1.0

核心洞察

  • 文本的语义由向量的方向决定,而非长度
  • 重复的内容不应改变语义相似度
  • 余弦相似度天然归一化到 [-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
2
3
4
5
6
7
8
9
10
11
{
"query": {
"script_score": {
"query": {"match_all": {}},
"script": {
"source": "cosineSimilarity(params.query_vector, 'embedding') + 1.0",
"params": {"query_vector": [0.2, 0.5, 0.3]}
}
}
}
}

关键点

  • 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
2
3
4
5
6
7
召回结果太少(< 3 个)?
├─ 是 → 降低阈值(0.7 → 0.5)
└─ 否 → 召回结果太多(> 10 个)?
├─ 是 → 提高阈值(0.5 → 0.7)
└─ 否 → 召回质量差(无关文档多)?
├─ 是 → 提高阈值 + 优化 Chunking
└─ 否 → 当前阈值合适

不同场景的推荐阈值

场景 推荐阈值 理由
客服问答 0.75-0.85 需要高精确度,避免答非所问
文档检索 0.60-0.75 平衡召回率和精确度
推荐系统 0.50-0.65 需要多样性,宁可多召回
法律合规 0.85-0.95 必须精确匹配,不能有误
向量阈值 vs 关键词阈值

为什么两者的阈值语义不同?

1
2
3
4
5
6
7
8
9
# 向量相似度阈值(余弦相似度)
vector_threshold = 0.7 # 范围:[-1, 1],通常用 [0, 1]
# 含义:向量夹角的余弦值
# 0.7 表示:夹角约 45°,语义中等相关

# 关键词匹配阈值(BM25 分数)
keyword_threshold = 5.0 # 范围:[0, +∞),无上限
# 含义:TF-IDF 加权分数
# 5.0 表示:词频和逆文档频率的综合得分

关键区别

维度 向量阈值 关键词阈值
数学基础 余弦相似度(归一化) BM25 分数(非归一化)
取值范围 [-1, 1][0, 1] [0, +∞),无上限
语义 几何夹角 词频权重
可比性 跨查询可比 跨查询不可比
调优难度 容易(固定范围) 困难(需要根据语料调整)

混合召回时的阈值策略

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
# 示例:Elasticsearch 的混合查询
{
"query": {
"bool": {
"should": [
{
"script_score": {
"query": {"match_all": {}},
"script": {
"source": "cosineSimilarity(params.query_vector, 'embedding') + 1.0"
},
"min_score": 1.7 # 向量阈值:0.7(加1后变1.7)
}
},
{
"match": {
"content": {
"query": "机器学习",
"minimum_should_match": "75%" # 关键词阈值:75%匹配度
}
}
}
]
}
}
}
阈值调优的 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from openai import OpenAI

def agentic_chunking(text, max_chunk_size=500):
client = OpenAI()

prompt = f"""
将以下文本分成语义连贯的块,每块不超过 {max_chunk_size} 字符。
在主题转换、逻辑断点处分块。返回 JSON 格式的块列表。

文本:
{text}
"""

response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}]
)

# 解析 LLM 返回的 JSON 块列表
return eval(response.choices[0].message.content)

五个层级的对比总结

层级 核心机制 语义完整性 计算成本 适用场景
Level 1: Fixed-Size 固定长度切割 极低 快速原型、简单文本
Level 2: Recursive 多级分隔符递归 ⭐⭐⭐ 结构化文档
Level 3: Structure-Based 文档结构对齐 ⭐⭐⭐⭐ Markdown/HTML 文档
Level 4: Semantic 嵌入相似度计算 ⭐⭐⭐⭐⭐ 主题多变的长文本
Level 5: Agentic LLM 深度理解 ⭐⭐⭐⭐⭐ 高价值复杂文档

实践建议:如何选择分块策略?

决策树

1
2
3
4
5
6
7
8
9
是否有明确的文档结构(标题/章节)?
├─ 是 → Level 3: Structure-Based
└─ 否 → 是否需要极高的语义准确性?
├─ 是 → 预算充足?
│ ├─ 是 → Level 5: Agentic
│ └─ 否 → Level 4: Semantic
└─ 否 → 文本是否有自然分隔符(段落/句子)?
├─ 是 → Level 2: Recursive
└─ 否 → Level 1: Fixed-Size

混合策略

在实际应用中,可以组合多种策略:

  1. 先结构后语义:用 Level 3 按章节粗分,再用 Level 4 细化长章节
  2. 分层索引:用 Level 2 创建粗粒度索引,用 Level 4 创建细粒度索引
  3. 动态降级:优先尝试 Level 5,失败时回退到 Level 4 或 Level 3

深层洞察:分块的本质是信息边界的划定

  • Level 1-2 关注物理边界(长度、分隔符)
  • Level 3 关注结构边界(文档层级)
  • Level 4 关注语义边界(主题转换)
  • Level 5 关注认知边界(逻辑完整性)

随着层级提升,分块从"机械切割"演进为"智能理解",但成本和复杂度也随之上升。最佳策略不是最高级的,而是最适配业务场景的


Chunking 在 RAG 架构中的战略地位

为什么 Chunking 必须在 Indexing 阶段?

1
2
3
4
5
时间线:离线阶段 → 在线阶段
↓ ↓
[Chunking][Retrieval][Generation]

决定后续所有环节的质量上限

三个不可逆的影响

  1. 检索粒度锁定

    • 一旦分块完成,检索的最小单元就被固定
    • 块太大 → 检索不精确(噪声多)
    • 块太小 → 上下文不完整(信息碎片化)
  2. 嵌入质量固化

    • 向量库中存储的是块的嵌入向量
    • 块的语义质量直接决定向量表示的准确性
    • 重新分块 = 重建整个向量库(成本高昂)
  3. 成本结构确定

    • 块的数量决定向量库的规模
    • 块的大小影响检索和生成的 Token 消耗
    • 前期优化 Chunking 可节省后续 90% 的成本

Chunking 与其他模块的协同关系

模块 依赖 Chunking 的方式 反向影响
Query Translation 查询改写后需要匹配到正确的块 查询模式可指导分块策略(如:FAQ 场景用问答对分块)
Routing 路由到不同向量库时,每个库的分块策略可能不同 多数据源场景需要统一分块标准
Retrieval 检索的对象就是块,块的质量决定召回率 Re-Rank 可弥补分块不佳导致的排序问题
Generation LLM 的输入上下文由块组成 生成失败时可能需要调整块的大小或数量

最佳实践:Chunking 的三阶段优化

1
2
3
4
5
6
阶段 1:快速验证(Level 1-2
↓ 验证 RAG 可行性
阶段 2:语义优化(Level 3-4
↓ 提升检索精度
阶段 3:智能升级(Level 5
↓ 处理复杂文档

关键决策点

  • 初期:用 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 传统方式:所有工具描述塞入上下文
prompt = f"""
你有以下工具可用:
{所有100个工具的描述} # 消耗 5000+ tokens

用户问题:{question}
请选择合适的工具...
"""

# Tool Retrieval 方式:动态检索相关工具
relevant_tools = tool_retrieval.search(question, top_k=3) # 只消耗 150 tokens
prompt = f"""
你有以下工具可用:
{relevant_tools} # 仅 3 个最相关的工具

用户问题:{question}
请选择合适的工具...
"""

Tool Retrieval 的技术路径

  1. 工具描述向量化:为每个工具的名称、描述生成 embedding
  2. 元数据索引:建立工具类别、权限、参数的倒排索引
  3. Playbook 检索:检索"如何正确使用工具"的最佳实践指南
  4. 动态过滤:根据用户权限、上下文实时过滤可用工具

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 无法替代)

  1. 语义理解能力

    • RAG 通过嵌入模型理解"同义不同词"(如"汽车"和"车辆")
    • MCP 依赖精确匹配,无法处理语义变体
  2. 大规模知识检索

    • RAG 可处理百万级文档的高效检索
    • MCP 的工具选择问题(Tool Retrieval)本质上仍需 RAG 技术
  3. 跨文档推理

    • RAG 的 GraphRAG、TreeRAG 可发现跨文档的隐含关联
    • MCP 只能逐个调用工具,缺乏全局视角
  4. 成本效益

    • RAG 的离线索引摊薄了在线检索成本
    • MCP 每次调用都产生实时成本

MCP 的独特价值(RAG 无法替代)

  1. 实时数据访问

    • MCP 可连接实时数据库、API、文件系统
    • RAG 的索引更新有延迟,不适合高频变化的数据
  2. 动作执行能力

    • MCP 可执行创建、更新、删除等操作
    • RAG 是只读的,无法修改外部系统
  3. 标准化协议

    • MCP 提供统一的工具调用标准,降低集成成本
    • RAG 每个系统都需要定制化的检索逻辑
  4. 权限和安全

    • 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
用户:"帮我分析上周的销售报告,然后给表现最好的客户发感谢邮件"

1. RAG 检索:
- 检索公司销售分析模板和方法论
- 检索邮件写作规范和客户关系政策

2. MCP 调用:
- 调用 CRM API 获取上周销售数据
- 调用邮件服务发送感谢邮件

3. LLM 推理:
- 结合 RAG 提供的知识和 MCP 提供的数据
- 生成分析报告和邮件内容

4. 执行动作:
- 通过 MCP 发送邮件

企业级最佳实践:构建统一的数据基础

从"孤岛"到"平台"的架构演进

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 传统 RAG:仅分块
chunks = split_into_chunks(document)

# 现代 RAG:语义增强
enhanced_chunks = []
for chunk in chunks:
# 使用 LLM 进行多层次语义增强
enhanced = llm.enhance(chunk, operations=[
"summary", # 生成摘要
"entities", # 提取实体
"relationships", # 提取关系
"keywords", # 提取关键词
"questions", # 生成潜在问题
"metadata" # 生成元数据
])
enhanced_chunks.append(enhanced)

语义增强的五大维度

  1. 摘要生成:为每个块生成简短摘要,提升检索效率
  2. 实体识别:提取人名、地名、组织名等实体
  3. 关系抽取:识别实体之间的关系
  4. 关键词提取:生成代表性关键词
  5. 问题生成:预生成该块可能回答的问题

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
用户问题分析

意图分类:知识查询 / 工具调用 / 混合任务

知识查询?
├─ 是 → RAG 检索
│ ├─ 检索类型:语义 / 关键词 / 混合
│ ├─ 检索粒度:细粒度 / 粗粒度 / 层级
│ └─ 上下文扩展:树状 / 图状 /
└─ 否 → 工具调用?
├─ 是 → Tool Retrieval
│ ├─ 检索工具描述
│ ├─ 检索使用指南
│ └─ 检索历史模式
└─ 否 → 混合任务?
├─ 是 → 并行检索 RAG + Tool
└─ 否 → Memory 检索

上下文组装的优化策略

  1. Token 预算管理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    def 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
    }
  2. 相关性去重

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    def 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]
  3. 质量评分和重排

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    def 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. 声明式配置

    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
  2. 自动化优化

    • 基于用户反馈自动调整检索策略
    • A/B 测试不同的上下文组装方案
    • 自动发现和添加新的数据源
  3. 监控和治理

    • 上下文质量监控(相关性、完整性、时效性)
    • 数据血缘追踪(上下文来源可追溯)
    • 访问控制和审计日志

多模态 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 的技术路径

  1. 模态转换:将图像、音频转换为文本描述

    • 优势:兼容现有文本 RAG 架构
    • 劣势:丢失原始模态的细微特征
  2. 原生多模态:直接处理多模态向量

    • 优势:保留完整的模态信息
    • 劣势:计算和存储成本高
  3. 混合方案:关键信息用原生多模态,辅助信息用文本

    • 优势:平衡质量和成本
    • 劣势:架构复杂度高

总结:复杂数据处理的最佳实践

基于 2025-2026 年的业界实践,设计和组织模型处理复杂数据的最佳实践可以总结为:

核心原则

  1. Context First,Model Second

    • 上下文质量比模型能力更重要
    • 投资于数据基础设施,而非单纯追求更大的模型
  2. RAG + MCP 协同,而非替代

    • RAG 负责知识检索和语义理解
    • MCP 负责实时数据访问和动作执行
    • 两者结合构建完整的 AI 能力
  3. 从手动工程到平台化

    • 早期:手动构建 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
阶段 1:基础建设(1-3 个月)
├─ 搭建基础 RAG 系统
├─ 接入核心数据源
└─ 验证可行性

阶段 2:能力增强(3-6 个月)
├─ 升级到 TreeRAG / GraphRAG
├─ 集成 MCP 服务器
├─ 构建 Memory 系统
└─ 实现 Tool Retrieval

阶段 3:平台化(6-12 个月)
├─ 抽象 Context Engine
├─ 实现声明式配置
├─ 建立监控和治理
└─ 优化成本和性能

阶段 4:智能化(12+ 个月)
├─ 自动化上下文优化
├─ 多模态支持
└─ AI 驱动的自我进化

关键技术选型

能力 推荐技术 备注
向量数据库 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
任务解决能力(Task Solving Capacity)

│ ┌─────────────────────────┐
│ │ General-purpose task
│ │ solver │
│ ┌───────────┐ │ GPT-3/4、ChatGPT、Claude│
│ │Transferable│ │ Scaling language models│
│ │NLP task │ │ Prompt based completion│
│ ┌────────┐ │ solver │ └─────────────────────────┘
│ │Task- │ │ELMO、BERT │ LLM ──────────►
│ ┌────────┐ │agnostic│ │GPT-1/2 │ Pre-trained LM
│ │Specific│ │feature │ │Pre-train +│
│ │ task │ │learner │ │fine-tuning│
│ │ helper │ │Word2vec│ └───────────┘
│ │n-gram │ │NPLM │ Neural LM
│ │models │ └────────┘
│ Statistical LM
└──────────────────────────────────────────────────────────────────►
1990s 2013 2018 2020

统计模型阶段(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
2
3
4
5
6
7
人类学习流程:
收集资料 ──► 学习计划 ──► 反复学习 ──► 测评
(预读/选择资料/资料分类)(学霸计划/自我定制)(章节学习/反复记忆/自我测评/错题调整)(考试分数)
↕ ↕ ↕ ↕
机器学习流程:
数据准备 ──► 模型定义 ──► 模型训练 ──► 评价
(清洗数据/样本选择/特征工程)(模型选择/模型开发)(批次学习/epoch/损失函数/优化算法)(性能评价)

模型需要从数据中学习到能力,只有当这种能力足够强,才能实现良好的泛化能力——即在未见过的数据上也能有效表现。

数据是决定模型效果的关键中的关键。高质量且多样化的数据,输入经过调优的模型,通常能实现最佳的算法表现。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:预训练

语言模型的预训练包括四个核心环节:

  1. 训练语料的整理和过滤:决定模型"吃什么"
  2. 规模缩放法则(Scaling Law):确定合适的模型大小
  3. 模型结构设计:Transformer 架构的具体参数配置
  4. 制定训练方案并开始训练

数据配比:模型学什么,决定模型会什么

不同的模型开发者对模型所需学习的知识有各自的理解,这实质上是一个实验过程。下图来源于《A Survey of Large Language Models》,展示了主流大模型的预训练数据构成:

1
2
3
4
5
6
7
8
9
10
各主流大模型预训练数据配比(来源:A Survey of Large Language Models)

T5 (11B) ████████████████████ 100% 网页
Falcon (40B) ████████████████████ 100% 网页
LLaMA (65B) ████████████████░░░░ 87% 网页 + 少量代码/书籍/维基
GPT-3 (175B) ████████████████░░░░ 84% 网页 + 16% 书籍
Yi (34B) ████████████████░░░░ 83% 网页 + 9%代码 + 5%书籍
PaLM (540B) ██████████░░░░░░░░░░ 50% 网页 + 31%书籍 + 14%代码
CodeGen (16B) ████████░░░░░░░░░░░░ 39%代码 + 25%网页 + 10%书籍
StarCoder2(15B)████████████████████ 92% 代码(代码专用模型)

数据配比(所学内容的类型和比例)将直接决定预训练模型的最终效果。

以 Llama 为例,预训练极其耗时耗钱——Llama 405B 预训练用了 54 天,中间还会遇到各种系统崩溃。为了避免浪费,Llama 团队先用小尺寸模型并行训练确定了最佳数据配比:

  • 50% 一般知识
  • 25% 数学和推理
  • 17% 代码
  • 8% 多语言

(这也解释了为什么 Llama 直接用起来中文体验差点意思——它学的中文太少了,会回复英文甚至中英文混输。不过社区有大量开源的中文魔改版本。)


数据预处理流水线

收集到海量文本后,数据预处理至关重要——要让模型"吃好的",而不是吃垃圾。整个流程如下图所示(Raw Corpus → 过滤 → 去重 → 隐私处理 → 分词 → 准备训练):

1
2
3
4
5
6
7
原始语料 → [过滤与筛选][去重][隐私处理][分词] → 准备预训练!

过滤与筛选: 去重: 隐私处理: 分词:
• 语言过滤 • 句子级去重 • 检测 PII • 复用已有分词器
• 指标过滤 • 文档级去重 • 删除个人信息 • SentencePiece
• 统计过滤 • 数据集级去重 • Byte-level BPE
• 关键词过滤

具体来说,预处理包含以下几个关键步骤:

① 质量过滤

去除低质量数据,使用基于模型的质量分类器(FastText 和 RoBERTa)筛选高质量 token:

  • FastText:Word2Vec 的扩展改进,训练快速分类器,识别文本是否可能被维基百科引用
  • RoBERTa:BERT 的变种(用更多数据训练),为每个文档生成算法质量分

② 内容提取

  • 网页数据:从 HTML 中提取正文内容
  • Markdown 数据:去掉特殊标记,只保留有效文本

③ 去重

重复数据会降低模型多样性,影响训练稳定性。需要在三个层级进行去重:

1
句子级去重 → 文档级去重 → 数据集级去重(防止测试集污染)

以零一万物(Yi)的数据处理流程为例,原始语料经过多轮过滤后,最终只保留约 31.68% 的数据作为训练语料:

1
2
3
4
5
6
原始语料 100%
→ 精确去重后:70.11%(去掉 29.89%)
→ 启发式过滤后:68.34%(去掉 1.77%)
→ 句子级质量过滤后:65.28%(去掉 3.06%)
→ 句子+段落级去重后:50.81%(去掉 14.47%)
→ 文档级去重后:最终训练语料 31.68%(去掉 19.13%)

④ 隐私去除和安全过滤

  • 删除可识别个人信息(PII):姓名、地址、电话号码等
  • 过滤成人内容:大网站直接黑名单,小网站通过脏词统计分析过滤

⑤ 数据关系构建(In-context Pretraining)

来自 LLaMA 实践论文《In-context Pretraining: Language Modeling Beyond Document Boundaries》:

模型学习知识的过程应该由易到难,类似于我们先学小学再学初中。具体做法是:

1
2
3
4
5
6
7
Step 1:找相关文档 → 构建文档图(Doc Graph)
Doc 0 ──0.8── Doc 9 ──0.0── Doc 1 ──0.7── Doc 3 ──0.6── Doc 5 ──0.9── Doc 7

Step 2:遍历文档图 → 构建预训练输入上下文(8192 context window)
[Doc 0 | Doc 9 | Doc 1]
[Doc 1 | Doc 3 ]
[Doc 3 | Doc 5 | Doc 7]

多个语义相关的文档被串联成连续序列,划分为固定大小的输入上下文(如 8k),让模型在相关知识之间建立更好的关联。

⑥ 分词(Tokenization)

分词是数据预处理的最后关键步骤,将原始文本分割成 tokens,作为大模型的实际输入。

不同模型的数据清洗流程各有细节设计。以 Baichuan 2 为例,其流程包含:语言过滤 → 文本指标过滤 → 重复文档删除 → 规则修正 → 困惑度过滤 → 文档质量过滤 → 段落去重 → MinHash 去重 → 精确去重 → 语义过滤 → 主题过滤 → 安全过滤。


Transformer 模型结构

预训练的核心是 Transformer 架构。模型的工作原理如下图所示:

1
2
3
4
5
6
7
8
输入文本 tokens

Token Embeddings(词向量化)

[Self-Attention + Feedforward Network] × N

输出下一个 Text Token
↑_______(自回归解码,循环预测)_________|

这就是自回归解码(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
2
3
4
5
6
阶段 1: 8K tokens
阶段 2: 16K tokens
阶段 3: 32K tokens
阶段 4: 64K tokens
阶段 5: 96K tokens
阶段 6: 128K tokens ← 最终目标

模型通过逐步适应更长的上下文,最终具备处理超长输入的能力。

训练算法原理

预训练和继续预训练的算法原理相对简单:

1
输入语料 → 预测下一个 token → 计算损失(Loss)→ 反向传播 → 更新参数

反向传播(Backpropagation)由深度学习之父 Geoffrey Hinton 在 1986 年论文《Learning representations by back-propagating errors》中提出,他也因此获得了图灵奖和诺贝尔奖。

训练完成后,模型参数被保存为离线快照文件。最终的参数数量由模型设计之初的结构决定,例如 7B(70亿)、13B(130亿)、72B(720亿)参数。

为了提升训练效率,通常会使用 DeepSpeed 等分布式训练优化工具,实现更高效的资源管理。


Post-Training:后训练

后训练的本质是对齐人类表达,让模型看起来更像一个智能的人类助手。

Llama 的后训练是迭代式的,包含多轮相同方法的训练,每轮包含三个核心模型:奖励模型(RM)、监督微调模型(SFT)、直接偏好优化模型(DPO)。

整体流程如下图所示:

1
2
3
4
5
6
7
8
9
10
11
收集 Prompts

每个 Prompt 生成 K 个答案(由上一轮最佳 DPO 模型生成)

奖励模型(Reward Model)打分 → 拒绝采样(Rejection Sampling)→ 筛出最优答案

SFT 数据(拒绝采样结果 + 专项数据)→ 训练 SFT 模型

DPO 训练(偏好数据对)→ 产出多个 DPO 模型(不同超参)

选出最佳 DPO 模型 → 用于下一轮生成答案 ↑(循环 6 次)

奖励建模(Reward Modeling,RM)

  • 目的:构建能评估模型生成内容质量的奖励模型
  • 做法:使用人类标注的偏好数据训练奖励模型,衡量生成回应的优劣

奖励模型的职责是筛选高质量样本用于下一步微调——相当于训练了一个"懂人类表达习惯的评审",替代人工来筛选高质量的微调样本。

在**拒绝采样(Rejection Sampling)**过程中:

  1. 对每个 Prompt,生成模型(DPO 模型)生成 K 个不同答案
  2. 奖励模型对 K 个样本打分,选出最优答案
  3. 为提升采样效率,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
2
3
4
5
6
7
RLHF(强化学习从人类反馈):
偏好数据 → 训练奖励模型 → 奖励模型打分 → 强化学习更新 LM policy → 循环迭代
(复杂、计算量大)

DPO(直接偏好优化):
偏好数据 → 直接最大似然优化 → 最终 LM
(简洁、高效)

正反馈循环

上述 Post-Training 流程会反复迭代 6 次,形成正反馈循环:

1
2
3
4
DPO 模型越来越好
→ 拒绝采样能选出的最佳答案质量越来越高
→ SFT 模型越来越好
→ 下一轮 DPO 模型越来越好(循环)

工具调用能力的来源

模型的工具使用能力(Function Calling)主要是在 Post-Training 阶段通过人类注释和偏好数据训练得到的。这也是为什么最新开源大模型的 -chat / -instruct 版本都自带工具调用能力——它们是在 base 模型上经过了 SFT 和 DPO 的。

案例:Qwen2.5-Coder 训练步骤

以 Qwen2.5-Coder 为例,训练思路与上述一致:

1
2
3
4
5
6
Qwen2.5(基座)
↓ ① File-Level Pretrain5.2T Tokens
↓ ② Repo-Level Pretrain300B Tokens
Qwen2.5-Coder(代码基座模型)
↓ ③ AlignmentSFT & DPO
Qwen2.5-Code-Instruct(指令对齐代码模型)

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
2
3
计算量 CL = (C_min / 2.3×10)^(-0.050)
数据规模 DL = (D / 5.4×10¹³)^(-0.095)
参数规模 NL = (N / 8.8×10¹³)^(-0.076)

三者的关系满足: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
2
3
4
在 TriviaQA、HellaSwag、NaturalQuestions 等 Benchmark 上:
LLaMA 65B(红线)始终领先
• 但随着 Token 数增加,各尺寸模型的差距逐渐缩小
• 小模型用更多数据训练,可以接近甚至超过大模型的 Chinchilla 最优点(紫色虚线)

这也是为什么马斯克的 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
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
┌─────────────────────────────────────────────────────────────┐
│ 提示词复杂度决策框架 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 目标是否清晰? │
│ ├─ 否 → 先把目标写清楚,这是必须的 │
│ └─ 是 → 继续 │
│ │
│ 2. 任务是否需要特定角色视角? │
│ ├─ 是 → 写角色定义(1-2 句话即可) │
│ └─ 否 → 跳过 │
│ │
│ 3. 模型的默认思考路径是否符合你的预期? │
│ ├─ 不确定 → 先试试不写,看模型怎么思考 │
│ ├─ 不符合 → 显式写出你期望的执行流程 │
│ └─ 符合 → 跳过,让模型自主规划 │
│ │
│ 4. 输出是否有特定格式要求? │
│ ├─ 是 → 写输出规范 │
│ └─ 否 → 跳过 │
│ │
│ 5. 尝试后效果如何? │
│ ├─ 效果好 → 结束 │
│ ├─ 效果差 → 添加 1-2 个 Few-shot 示例 │
│ └─ 仍差 → 考虑换模型或拆解任务 │
│ │
└─────────────────────────────────────────────────────────────┘

一句话总结:从无到有,从少到多。先试试最简单的提示词,效果不好再加内容——而不是一开始就写一个"完美"的长提示词。

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
2
(list (性格 . (敏锐 谨慎 通达 澄明))
(技能 . (洞察 推理 融会 逆思)))

这等价于一个强类型的键值对声明。模型不需要猜测"敏锐"是修饰性格还是技能,括号已经把归属关系固定了。相比之下,线性描述"性格敏锐谨慎,技能洞察推理"在 attention 机制下,"敏锐"和"洞察"之间的关联权重可能被错误地拉近。

③ 管道操作符天然表达执行顺序

1
(-> 用户输入 核心命题 正向推理 反向逆思 视域融合 通俗俚语)

这个 -> 管道操作符明确告诉模型:按顺序执行,前一步的输出是后一步的输入。这比"请先做A,然后做B,最后做C"的线性叙述更不容易被模型跳步,因为模型会把它识别为函数调用链,而不是建议性的自然语言。

结论:Lisp 的本质是"用代码语法强制结构化"。 任何能消除歧义、明确执行顺序、强制分组的结构都能达到类似效果——这正是我们用 Markdown 金字塔结构复刻成功的根本原因。


5.2 核心原则:三句话的提示词哲学

不需要记忆复杂的框架,只需要记住三句话:

  1. 准确描述任务 —— 开篇明义,第一句话就说清楚"你要做什么"
  2. 给充足而准确的上下文 —— 提供足够的背景、规范、约束,让模型不需要猜
  3. 提出明确的要求 —— 明确输出格式、长度、风格等约束条件

这三句话说来简单,但真正写提示词时,很多人还是容易违背。以前模型能力较弱,相当于刚毕业的实习生,我们需要手把手告诉他每一步怎么做;现在 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
2
3
4
第一层(顶):角色定义 —— 我是谁,我有什么特质
第二层:执行流程 —— 按顺序做什么
第三层:输出规范 —— 做成什么样
第四层(底):约束规则 —— 不能做什么

这四层天然构成金字塔,从最高层的"身份"到最底层的"边界",层层递进,MECE 不重叠。


5.4 通用模板:金字塔提示词标准格式

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
# [智能体名称]:[一句话任务描述]

## 角色定义
你是 [角色名],[核心能力一句话]。

特质:
- 性格:[特质1]、[特质2]、[特质3]
- 技能:[技能1]、[技能2]、[技能3]
- 表达:[风格1]、[风格2]、[风格3]

## 执行流程
接收用户输入后,**严格按以下顺序**处理:

1. **[步骤1名称]**:[做什么,产出什么]
2. **[步骤2名称]**:基于步骤1,[做什么]
3. **[步骤3名称]**:基于步骤2,[做什么]
4. **[步骤4名称]**:整合以上,产出最终结果

## 输出规范
[详细描述输出格式、尺寸、颜色、结构等]

## 约束规则
- 不 [禁止行为1]
- 不 [禁止行为2]
- 必须 [强制要求]

四条写作原则:

  1. 结论先行:第一行就说清楚做什么,不要让模型从细节里猜
  2. MECE 分组:每个 ## 对应一个独立关注点,不重叠、不遗漏
  3. 编号列表表达顺序:执行步骤用 1. 2. 3. 而非"先…然后…最后…",编号列表对模型的约束力远强于自然语言叙述
  4. 约束放最后用否定句不输出 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
2
3
4
5
"不要写太长的回答"
"回答控制在 200 字以内"

"不要用专业术语"
"用初中生能理解的语言表达"

否定式约束要求模型先理解"什么是不好的"再规避,而正向描述直接给出目标状态,认知负担更低,执行更精确。


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
Claude 3.7/4(基准验证)→ DeepSeek-R1(开源模型验证)→ Qwen-max(中文场景验证)

如果某个模型效果明显差,针对该模型的"怪癖"做定向修复,而不是把整个提示词推倒重来。


5.6 进阶:从复刻到创新

复刻是学习,创新才是目的。掌握了金字塔结构之后,可以按以下路径进行创新:

创新路径:

1
观察优秀案例 → 理解核心原理 → 简化表达方式 → 适配多模型 → 创新应用场景

创新示例:"阿尔戈斯之眼"的诞生

观察到 DeepSeek-R1 在思考时会自动分析显性需求、隐性需求和根本需求,于是把这个能力显式化,设计了一个专门分析三层需求的智能体。命名时借助 AI 寻找希腊神话中最贴合"全方位洞察力"的人物,得到"阿尔戈斯之眼"(百眼巨人,可以同时观察各个方向)。

这个创新过程本身也是一个提示词工程的实践:

  • 任务描述:寻找最贴合的神话人物
  • 结构约束:标题结构为"人物 + 器官或物品"
  • 明确要求:给出 2 个候选并说明推荐理由

从"言外之意"到"阿尔戈斯之眼",改动的只是三处:

  1. 角色名和任务描述(伽达默尔 → 阿尔戈斯之眼)
  2. 执行流程(5 步语言分析 → 3 层需求分析)
  3. 卡片结构(解析结果区 → 三标签圆角矩形区)

这说明一个好的提示词模板,改动成本极低,可以快速衍生出新的应用场景。


5.7 一句话总结

提示词的价值在于准确传达需求,而非展示技术复杂性。Lisp 的本质是"用代码语法强制结构化",金字塔的本质是"用文档层级强制结构化",两者同构。在 Claude 4 时代,用金字塔结构写提示词,更通用、更易改、跨模型兼容,是让提示词真正"走向寻常百姓家"的正确路径。


参考资料


六、训练和推理:算力需求的本质差异

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
2
GPT-3 训练数据 ≈ 45TB 文本
LLaMA-2 训练数据 ≈ 2万亿 tokens

数据是模型"知识"的来源,没有数据就无法:

  • 从零训练出相同能力的模型
  • 理解模型为何学到某些知识
  • 改进模型的数据处理流程

权重文件无法反向还原训练数据! 这就像:

  • 你无法从"煮熟的菜"还原出"原始食材和烹饪步骤"
  • 你无法从"编译后的二进制"还原出"源代码"
  • 权重是数据的"压缩摘要",而非数据的"可逆编码"
厂商基于开源模型的开发路径

基于开源模型开发,通常有三种路径:

路径 数据需求 计算成本 时间 适用场景
直接使用 0 极低 分钟级 通用任务
微调 1K-100K 条 低-中 小时级 定制化需求
继续预训练 1B-10B tokens 中-高 天级 垂直领域
从零训练 1T+ tokens 极高 月级 基础模型研发

计算成本对比(以 7B 模型为例)

阶段 从零预训练 基于开源微调 节省比例
数据准备 数月 + 数百万美元 数周 + 数万美元 99%+
预训练 2000+ GPU 天 0(已省略) 100%
微调/对齐 数十 GPU 天 数十 GPU 天 0%
总计 数百万美元 数千美元 99%+
开源权重的真正价值

开源权重 = 免费的"大学毕业生"

1
2
3
4
5
6
7
从零训练 = 自己养育一个孩子 22 年直到大学毕业

成本:数百万 + 22

开源微调 = 招聘一个大学毕业生,培训 3 个月上岗

成本:数千元 + 3 个月

你不需要知道他小学学了什么、中学怎么过的,只需要教他"我们公司的工作方式"。

开源权重的价值是"站在巨人的肩膀上"

  1. 跳过最昂贵的预训练阶段:LLaMA-2 的预训练成本估计在 200-500 万美元
  2. 获得"通用能力基座":模型已经学会了语言理解、推理、知识等
  3. 降低数据门槛:从零训练需要万亿级 tokens,微调只需要千/万级高质量数据
厂商的真正竞争力

即使开源了权重,原厂仍然有优势:

能力 开源权重提供 原厂优势
数据质量 ✅ 高质量数据管道
训练技巧 ✅ 超参数、架构优化经验
规模效应 ✅ 大规模集群、成本优势
持续迭代 ✅ 可以训练下一代模型
生态建设 部分 ✅ 社区贡献反哺

一句话总结

开源权重给你的是"结果",不是"配方"。你可以基于这个结果继续开发,但想做出同样好的"原版",还需要自己掌握配方。

6.0.1.2 大模型的"大"意味着什么?参数、压缩与知识的本质

理解了参数的定义之后,一个更深刻的问题浮现出来:大模型学到的东西,到底是什么?

大模型的"大"就是参数多

“大模型”(Large Language Model)的"大",确实主要指参数量大——即权重(Weights)和偏置(Biases)的数量极多。参数量是衡量模型规模最直接的指标,也是决定模型能力上限的核心因素之一。

但参数多只是手段,真正的问题是:这些参数里存储了什么?

训练数据被"压缩"进了参数

一个直觉上正确的理解是:训练数据通过梯度下降被"压缩"进了模型参数。但这种压缩与我们熟悉的工程压缩(如布隆过滤器、gzip)有本质区别:

维度 布隆过滤器 大模型参数
压缩目标 元素存在性(是/否) 语义关系和概率分布
数据类型 二值位 连续浮点数
查询方式 精确成员检测 概率性生成/推理
可泛化性 ❌ 只能回答"见过没" ✅ 能处理未见过的输入

布隆过滤器存储的是离散的、原子化的存在性标记;而大模型参数存储的是连续的、关系化的语义空间——后者能理解"国王 - 男人 + 女人 ≈ 女王"这种抽象关系,这是布隆过滤器永远做不到的。

正因为参数存储的是规律而非副本,模型才具备泛化能力:它能处理训练时从未见过的输入,因为新输入可以被映射到已学习的语义空间中。

语言存储了人类的知识吗?

这引出了一个更宏观的命题:人类的语言存储了人类的知识和智能,因此大模型通过学习语言,获得了某种程度的"智能涌现"。

这个观点部分正确,但需要谨慎区分:

  • 正确的部分:语言确实是人类知识的重要载体。逻辑、常识、推理模式、世界知识都以某种形式编码在语言中。大模型通过学习这些语言模式,确实获得了令人惊叹的能力。
  • ⚠️ 需要补充的部分:语言 ≠ 知识的全部。很多知识是隐性的、具身的(如骑自行车、游泳),无法被语言完整表达。更准确的说法是:语言是人类知识和智能的一种投影,大模型学习这个投影,获得了"智能模拟",但这不等同于拥有真正的智能。
大模型学到的"隐式东西"到底是什么?

大模型参数中存储的内容,可以分解为以下几个层次:

层次 内容 本质
第一层 词法-句法模式 词序、语法、搭配习惯
第二层 语义关联 向量空间中词与词的关系
第三层 知识片段 事实性知识的统计编码
第四层 推理模式 逻辑推理的模式匹配
第五层 世界知识 物理世界的统计规律(非物理定律)

这些内容之所以是"隐式"的,是因为知识被"压扁"进参数中,无法分离成模块化的结构。不同于人类大脑中相对独立的知识模块,大模型的 1750 亿个参数共同、混合地编码了所有知识,没有明确的边界,也没有统一的"真理检查"机制——这就是为什么模型可能同时"相信"两个矛盾的事实。

为什么 LeCun 认为大模型没有学到"真正的知识"?

尽管大模型的泛化能力令人印象深刻,以 Yann LeCun 为代表的学者仍然认为,大模型并未学到真正的知识。其核心论点是:

统计拟合 ≠ 因果理解

大模型学到的是统计相关性,而非因果机制。用 Judea Pearl 的因果阶梯来描述:

1
2
3
Level 3: 反事实推理  "如果当时没有做X,会发生什么?"  ← 人类能做到
Level 2: 干预推理 "如果我做X,会发生什么?" ← 人类能做到
Level 1: 关联推理 "观察到X时,Y的概率是多少?" ← 大模型停留在这里

大模型停留在第一层:它能观察到"公鸡叫后日出"的统计规律,但不理解"日出导致公鸡叫"的因果方向。更深层的问题是,大模型没有构建对世界的独立、结构化的内部模型——知识被"压扁"进参数,无法分离,无法进行真正的规划和推理。

1
2
3
4
5
人类/真正AGI的认知架构:
感知 → 世界模型(显式、结构化、因果) → 规划 → 行动

当前大模型的认知架构:
输入 → 统计映射(隐式、分布式、相关性) → 输出

LeCun 的批评不是否定大模型的实用价值,而是指出:泛化 ≠ 理解。模型的泛化能力来自统计规律的迁移,但这不等同于对底层机制的真正理解。就像一个学生可以通过刷题掌握解题模式,却不真正理解数学原理——遇到稍微变形的题目就会失败。

这也是为什么大模型会产生"幻觉"(Hallucination):当统计模式无法覆盖某个问题时,模型会生成"看起来合理"但实际错误的内容,因为它没有一个可以校验的"真实世界模型"。

6.0.2 神经网络结构:节点与层次

基本组成单元

概念 说明 示例
节点(神经元) 神经网络的基本计算单元,接收输入、产生输出 每层可能有数千个节点
节点的集合,负责特定类型的计算 Transformer 模型通常有 32-96 层
权重矩阵 连接相邻层节点的参数 决定信号如何从一层传递到下一层

Transformer 模型的层次结构

1
2
3
4
5
6
7
8
输入层(Embedding Layer

隐藏层(Transformer Blocks × N
├─ 多头自注意力机制(Multi-Head Attention
├─ 前馈神经网络(Feed-Forward Network
└─ 层归一化(Layer Normalization

输出层(Output Layer

参数量计算(以 Transformer 为例)

1
2
3
4
5
6
7
8
9
10
11
12
13
单层参数 ≈ 
注意力权重 (4 × hidden_size × hidden_size) +
前馈网络权重 (2 × hidden_size × intermediate_size) +
偏置项

总参数 ≈ 层数 × 单层参数 + 嵌入层参数

示例(GPT-3 175B):
- 层数:96 层
- 隐藏层维度:12288
- 前馈网络维度:49152
- 单层参数 ≈ 1.8B
- 总参数 ≈ 96 × 1.8B ≈ 175B

6.0.3 Token:文本的最小处理单位

Token 的定义

  • Token 是模型处理文本的最小单位
  • 一个 Token 可能是一个词、一个字,或者一个子词(subword)
  • 不同模型的分词方式不同,Token 的定义也不同

Token 化过程示例

1
2
3
4
5
6
7
原始文本:"你好,世界!"

分词器(Tokenizer)

Token 序列:[101, 2769, 3456, 8024, 3844, 8013, 102]

嵌入向量:每个 Token 对应一个高维向量(如 768 维)

Token 与参数的关系

关系维度 说明
输入处理 每个输入 Token 都会通过神经网络的所有层
上下文长度 参数量影响模型能处理的最大 Token 数(如 4K → 32K → 128K)
计算量 生成 1 个 Token 需要所有参数参与计算一次前向传播
显存占用 KV Cache 存储与 Token 数成正比

Token 计算的实际意义

1
2
3
4
生成 100 个 Token 的计算量:
= 100 × 参数量 × 单次前向传播的计算强度
= 100 × 7B × 2 FLOPs/参数
= 1.4 TFLOPs(万亿次浮点运算)

6.0.4 核心关系图:从文本到输出的完整流程

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
┌─────────────────────────────────────────────────────────┐
│ 文本输入:"今天天气不错"
│ ↓ │
Token 化(分词器) │
│ ↓ │
Token 序列:[今天, 天气, 不错] │
│ ↓ │
│ 嵌入层(Embedding) │
│ ↓ │
│ 神经网络处理(多层 Transformer) │
│ ├─ Layer 1: 注意力 + 前馈网络 │
│ ├─ Layer 2: 注意力 + 前馈网络 │
│ ├─ ... │
│ └─ Layer N: 注意力 + 前馈网络 │
│ ↓ │
│ 输出层:预测下一个 Token
│ ↓ │
Token 输出:"适合"
│ ↓ │
│ 文本输出:"适合出门"
└─────────────────────────────────────────────────────────┘

参数 = 所有权重 + 所有偏置
参数量 ∝ 层数 × 隐藏层维度²
计算量 ∝ Token 数 × 参数量

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 都需要:
    1. 重新计算整个序列的 attention
    2. 进行采样决策
    3. 更新 KV Cache
    4. 这个过程必须串行,无法加速

3. 商业策略考量

  • 用户行为差异:大部分场景下输入量 >> 输出量,差异化定价可以优化整体收入结构
  • 引导使用方式:鼓励用户精简输入,提高系统吞吐效率
  • 成本回收:输出阶段的计算资源消耗确实更高(通常 2-3 倍)

4. 实际定价示例(以 GPT-4 Turbo 为例)

1
2
输入:$10 / 1M tokens
输出:$30 / 1M tokens(3 倍差异)

这个 3 倍左右的定价差异在业界比较常见,基本反映了输出阶段额外计算成本的量级。

一句话总结

输出 token 更贵,因为生成比处理更"费力"——输入可以并行处理,输出必须逐字串行生成,每生成一个字都要重新计算整个序列。


6.0.8 自回归:LLM 生成的核心机制

在深入理解训练和推理之前,必须先理解 LLM 生成的核心机制——自回归(Autoregression)

什么是自回归?

自回归是指:每次生成一个 token,都基于之前生成的所有 token 作为上下文。这个过程可以形式化为:

1
P(x₁, x₂, ..., xₙ) = P(x₁) × P(x₂|x₁) × P(x₃|x₁,x₂) × ... × P(xₙ|x₁,...,xₙ₋₁)

即:整个序列的概率等于每个 token 条件概率的乘积。

生成过程示例

1
2
3
4
5
6
7
8
9
输入:"今天天气"

模型预测下一个 token 的概率分布

采样得到 token"不错"

拼接为新输入:"今天天气不错"

重复上述过程,直到生成结束符

自回归的本质:概率预测,而非逻辑推理

这里有一个关键问题:自回归模型是否具有"数学计算能力"?

答案是:自回归模型本身不具备传统意义上的数学计算能力。它表现出的"计算能力"来自训练数据中的统计规律,而非真正的逻辑推理。

维度 自回归模型 传统计算器
计算方式 概率预测 算术运算
本质 “看到 A,预测 B 可能出现” “执行 A + B 的运算”
精确性 依赖训练数据覆盖度 100% 精确
泛化能力 对训练数据外的计算容易出错 对所有输入都精确

具体例子

  • "2 + 2 = ?" → 模型预测 “4”,因为训练数据中这个模式出现过无数次
  • "12345 × 67890 = ?" → 模型很可能出错,因为:
    • 训练数据中很少出现这种大数乘法
    • 模型没有真正的乘法运算能力
    • 它只能"猜"一个看起来像答案的数字

为什么 LLM 需要工具调用?

正是因为自回归模型没有真正的计算能力,现代 LLM 引入了**工具调用(Tool Calling)**机制:

1
2
3
4
5
6
7
8
9
用户:"12345 × 67890 = ?"

LLM 识别这是一个计算任务

LLM 调用 Python 解释器:eval("12345 * 67890")

解释器返回精确结果:838102050

LLM 将结果返回给用户

这就是为什么 GPT-4、Claude 等模型都支持调用 Python 解释器、搜索引擎等外部工具——用真正的计算能力弥补概率预测的不足

自回归与推理的关系

理解了自回归,就能理解为什么推理是"单次前向传播":

  • 每生成一个 token,都需要一次完整的神经网络前向传播
  • 生成 100 个 token,就需要 100 次前向传播
  • 这也是为什么 LLM 推理比传统软件慢得多——它不是"执行代码",而是"逐字预测"

一句话总结自回归

自回归是"猜下一个字"的数学形式化。每一步都是概率计算,不存在"思考"或"推理",只有"预测"。模型表现出的"智能"来自训练数据中的统计规律,而非真正的逻辑能力。


6.0.9 Inference vs Reasoning:两个容易混淆的概念

在讨论 LLM 时,“inference” 和 “reasoning” 这两个词经常被混用,但它们实际上是两个完全不同的概念。

核心定义

概念 英文原意 在 AI 语境下的含义
Inference 推断、推论 模型的前向传播计算过程,即从输入生成输出的物理计算
Reasoning 推理、思考 模型进行逻辑推导、分析、综合的认知能力

关键区别

1
Reasoning ⊂ Inference

这个关系可以理解为:

  1. 一切 reasoning 都是 inference
    Reasoning 能力必须通过 inference 过程才能展现。没有 inference 这个"载体",reasoning 无从谈起。

  2. 能够 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
2
3
4
5
6
同一个 batch 里同时有:
- 通用文本:"我无法回答这个问题"(预训练目标:这句话合理)
- 指令数据:"你必须拒绝有害请求"(后训练目标:主动拒绝)

梯度方向:← 和 → 同时拉扯,参数不知道往哪走
结果:两个目标都学不好,互相干扰

分阶段训练(可控)

1
2
3
4
第一阶段:只优化 P(text),参数收敛到 θ₁
第二阶段:在 θ₁ 基础上优化 P(response|instruction),参数移动到 θ₂

θ₂ 覆写了 θ₁ 的部分方向,但这是"有意为之的覆写"

分阶段训练的本质是 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
2
3
4
5
6
7
8
9
基础模型(预训练)

├─→ 持续预训练(领域知识不够)→ 领域基础模型
│ │
│ └─→ SFT → 领域对话模型

└─→ SFT(直接教指令跟随)

└─→ RLHF → 最终产品模型

一句话总结:分阶段训练是工程上的妥协,不是数学上的完美隔离。最终参数里的知识确实是"混合"的,但这个混合是有序叠加的结果,而非梯度级别的相互干扰。


6.1 核心问题:为什么训练和推理是两回事?

很多人有一个直觉误区:既然训练和推理都是"计算",为什么不能用同一套硬件?为什么训练完的模型不能直接在 CPU 上跑,非要上推理卡?

答案在于:训练和推理虽然都涉及矩阵运算,但它们的计算模式、内存访问模式、精度要求和延迟容忍度完全不同。这就像"建造工厂"和"工厂生产"的区别——前者需要重型机械和大量原材料,后者只需要流水线和工人。


6.2 计算模式的本质差异

6.2.1 训练:海量数据的并行"反向传播"

训练的核心是反向传播(Backpropagation),即根据损失函数的梯度,逐层更新数十亿甚至数万亿个参数。这个过程有三个关键特征:

特征 训练 推理
计算量 每个样本都要计算前向+反向两次,计算量是推理的 2-3 倍 只计算前向传播一次
内存访问 需要存储所有中间激活值(用于反向传播),内存占用是推理的 10-100 倍 只需要存储当前层的激活值
精度要求 必须用 FP32 或 BF16,否则梯度消失/爆炸 可以用 FP16 甚至 INT8 量化,精度损失可接受

具体来说:

  1. 前向传播:输入数据逐层通过神经网络,每层的输出(激活值)都需要保存下来,因为反向传播时要用。
  2. 反向传播:根据损失函数计算梯度,逐层反向传递。这个过程需要:
    • 读取之前保存的所有激活值
    • 计算梯度(涉及大量矩阵乘法和转置)
    • 更新参数(写入内存)

这意味着训练时的内存访问量是推理的数十倍甚至上百倍。一个 175B 参数的模型,训练时需要数百 GB 的显存来存储中间激活值,而推理时只需要几十 GB。

6.2.2 推理:单次前向传播的"快闪计算"

推理只需要一次前向传播:

1
输入 → [Layer 1][Layer 2] → ... → [Layer N] → 输出

每层的计算完成后,中间结果就可以丢弃,不需要保存。这使得推理的内存访问模式非常"干净":

  • 顺序访问:一层一层往下算,内存访问模式可预测
  • 一次性使用:中间结果用完即弃,不需要反复读写
  • 低精度可行:不需要梯度计算,可以用 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 推理的实际问题

  1. 速度太慢:生成 100 个 token 需要 1-2 分钟,用户体验极差
  2. 内存带宽瓶颈:CPU 的内存带宽只有 GPU 的 1/30,参数加载成为瓶颈
  3. 没有专用加速: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 推理卡的实际应用

典型部署方案

  1. 云端推理

    • 使用 A10/T4 等推理卡
    • 支持多模型并行部署
    • 动态扩缩容,按需付费
  2. 边缘推理

    • 使用 Jetson 系列嵌入式 GPU
    • 模型量化为 INT8
    • 功耗 <15W,适合边缘设备
  3. 混合部署

    • 小模型用 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
2
3
4
5
LLM 响应

是否包含 tool_call?
├── 是 → 执行对应工具 → 将结果追加到消息历史 → 再次调用 LLM
└── 否 → 输出 Final Text → 退出循环

这个循环的优雅之处在于:工具执行结果会作为新的上下文回注给 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
2
3
4
5
静态视角(OpenClaw 架构)
ChatChannels → ControlPlane → AgentLayer → LLMProviders/ToolsLayer → DeviceNodes

动态视角(Agentic Loop 消息流)
用户 → 渠道适配器 → Gateway → Agent Runner → LLM API → Agentic Loop → Response Path → 用户

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 失控时能否优雅降级——这才是工程可靠性的真正考验。