AI 专题学习手册

面向 Java 后端开发的 AI 应用开发学习指南——从基础概念到工程落地,结合 MindForge 考试指导 AI 平台项目代码,构建完整的 AI 工程能力体系。


前言:为什么学 AI 应用开发

2024-2026 年,AI 领域发生了根本性变化:大模型能力从"能用"到"好用",开发门槛从"需要 PhD + GPU 集群"降到"会调 API 就能搭应用"。对后端开发来说,这不是可选项——AI 应用开发正在成为和数据库、缓存、消息队列一样的基础技能

AI 应用开发的能力分层:

层次 描述 能力定位
用过 AI 工具 “我用 ChatGPT/Claude 写代码” 基础操作
系统化使用 AI “AI 辅助全流程:需求→设计→编码→审查” 有方法论
基于大模型开发应用 “我用 Agent + RAG 搭建了 AI 应用” 核心目标层
微调/训练模型 “用 LoRA 微调了领域模型” 算法工程师方向

本文档的目标是从第二层跨越到第三层——不是泛泛了解概念,而是能讲清楚代码实现、设计决策和工程权衡。

阅读建议

  • 如果你刚接触 AI 开发:从第一章顺序读到第七章,每章约 20-30 分钟
  • 如果你已有基础:跳读第四章(RAG)和第五章(Agent),重点看代码走读部分

第一章:AI 背景与基础概念

1.1 AI 是什么:从人工智能到大语言模型

人工智能(AI, Artificial Intelligence) 是一个宽泛的学科领域,目标是让机器表现出类似人类的智能行为——理解语言、识别图像、做出决策、解决问题。它不是单一技术,而是一组技术的统称。

理解 AI 的最佳方式是看它的层级包含关系

人工智能(AI)                       ← 最大的范畴:一切让机器"看起来智能"的技术
  └── 机器学习(ML)                  ← AI 的子集:不靠人写规则,靠从数据中学习规律
        └── 神经网络                  ← ML 的子集:模拟人脑神经元连接的计算模型
              └── 深度学习            ← 神经网络的子集:层数多、参数多、数据多
                    ├── CNN          ← 图像领域:卷积神经网络
                    ├── RNN/LSTM     ← 序列领域:循环神经网络
                    ├── Transformer  ← 2017年诞生,当前主流架构
                    │     └── GPT/Claude/DeepSeek/GLM...  ← 大语言模型
                    └── Diffusion    ← 图像生成:Stable Diffusion/Midjourney

每一层的核心区别:

层级 代表技术 输入 → 输出 人需要做什么 典型应用
AI(规则系统) 专家系统 事实 → 推理结论 人写全部规则 早期医疗诊断
机器学习 SVM/XGBoost 特征向量 → 分类/回归 人设计特征 垃圾邮件过滤、信用评分
深度学习 CNN/Transformer 原始数据 → 结果 人设计网络结构 人脸识别、机器翻译
大语言模型 GPT/Claude 自然语言 → 自然语言 人描述需求 代码生成、智能问答、Agent

关键跃迁:从 AI 到大语言模型,每一步都在减少"人的参与"——人写规则 → 人设计特征 → 人设计网络 → 人描述需求。大语言模型是当前 AI 领域中与应用开发关系最密切的子集,也是本书的核心关注对象。


1.2 大模型的构成:组件与协作原理

理解了"大模型在 AI 家族中的位置"之后,下一步是搞清楚它由哪些部件组成、各部件如何协作。可以把一个大语言模型比作一个"工厂":

┌────────────────────────────────────────────────────┐
│                    大语言模型"工厂"                     │
│                                                    │
│  ①训练数据          ②Tokenizer          ③Transformer │
│  ┌──────────┐     ┌──────────┐     ┌──────────────┐ │
│  │ 互联网文本  │ ──→ │ 文本→ID   │ ──→ │ 多层神经网络   │ │
│  │ 书籍/论文  │     │ (BPE分词) │     │ (注意力机制)    │ │
│  │ 代码仓库   │     └──────────┘     │ 逐层提取特征   │ │
│  │ ...       │           ↓          │ 预测下一个词   │ │
│  └──────────┘      ④词表映射         └──────┬───────┘ │
│                      (ID↔向量)              │         │
│                                            ↓         │
│  ⑥推理引擎 ◄──────────────────── ⑤模型参数            │
│  ┌──────────┐                  ┌──────────┐         │
│  │ 加载参数   │                  │ 权重矩阵   │         │
│  │ 运行计算   │                  │ ~几百亿个  │         │
│  │ 输出Token  │                  │ 浮点数    │         │
│  └──────────┘                  └──────────┘         │
└────────────────────────────────────────────────────┘

下面逐一拆解六个组件:

① 训练数据 —— 模型的"教科书"

大语言模型不是"学会推理"的,而是从海量文本中"统计出规律"的。训练数据的规模和多样性直接决定了模型的能力上限。

  • GPT-4 的训练数据约 13 万亿 token(相当于数千万本书)
  • DeepSeek-V3 约 14.8 万亿 token
  • 来源:互联网公开文本、书籍、论文、代码仓库、维基百科等

类比:训练数据就像工厂的"原材料"。原材料不够或质量差,工厂设备再先进也产不出好产品。

② Tokenizer(分词器)—— 把文本切成"最小处理单元"

模型不是逐字读文本的,而是先把文本切成 Token。Token 是模型处理的最小粒度。

输入文本:"大语言模型如何工作?"
    → Tokenizer 切分 → ["大", "语言", "模型", "如何", "工作", "?"]
    → 映射为 ID     → [12847, 9315, 5632, 2910, 1783, 62]
  • 1 个中文约 1-2 个 Token,1 个英文单词约 1-2 个 Token
  • Tokenizer 使用 BPE(Byte Pair Encoding)算法,自动发现高频词根
  • 同一个 Tokenizer 必须用于训练和推理——换 Tokenizer 等于换"语言"

类比:Tokenizer 是工厂的"分拣机"——把原材料切分成统一规格的零件,后续流水线才能处理。

③ Transformer —— 模型的核心"计算流水线"

Transformer 是 2017 年 Google 提出的神经网络架构,当前所有主流大语言模型都基于它或其变体。它的核心创新是自注意力机制(Self-Attention)

传统 RNN 处理序列:
  词1 → 词2 → 词3 → ...        ← 必须按顺序,不能并行,长文本会"遗忘"开头

Transformer 自注意力:
  输入所有词 → 每个词同时看所有其他词 → 计算关系权重 → 输出
  词1 ←→ 词2
    ↕    ↕                      ← 所有词两两计算关联度,完全并行
  词3 ←→ 词4

自注意力的直觉理解:

  • 输入:“她把苹果放进冰箱,然后坐下来吃了一个___”
  • 要预测横线上的词,模型需要关注前面的"吃"和"苹果"(不是"冰箱")
  • 自注意力机制自动为每对词计算"关联分数"——"苹果"和"吃"的分数高,"冰箱"和"吃"的分数低

Transformer 由多层(通常几十到上百层)堆叠而成,每层逐步提取更抽象的特征——底层识别词汇和语法,中层理解语义和逻辑,高层进行推理和生成。

类比:Transformer 是工厂的"核心流水线"——原材料经过几十道工序逐级加工,最终产出成品。

④ 词表(Vocabulary)—— 把数字还原为意义

词表是一个巨大的映射表,将 Token ID 映射为向量(一串浮点数):

  • Tokenizer 将文本转为 ID
  • 词表将 ID 转为向量(Embedding),例如 ID=12847 → [0.023, -0.154, 0.891, ...](几千维)
  • 这个向量承载了语义信息——语义相近的词,向量也接近

词表大小通常在 5 万到 20 万之间(即模型认识的"词"的数量)。Embedding 向量维度通常在 1024 到 8192 之间(每个词用多少维数字来表示其语义)。

类比:词表是工厂的"原材料编码手册"——每个零件编号对应一个规格参数表。

⑤ 模型参数 —— 模型学到的"知识"

参数是模型在训练过程中学习到的数以亿计的浮点数(权重)。它们存在于 Transformer 的每一层、每一个注意力头和每一个前馈网络中。

  • DeepSeek-V3:6710 亿总参数,每次推理激活约 370 亿(MoE 架构)
  • Qwen2.5-7B:70 亿参数,全激活
  • 参数量大致决定了模型的"知识容量",但不是线性关系——架构、数据质量同样重要

参数文件在磁盘上通常以数十到数百 GB 的形式存储(如 .safetensors.gguf),推理时加载到显存或内存中。

类比:参数是工厂的"工艺配方"——同样的流水线(架构),不同的配方(训练出来的参数),产出的产品完全不同。

⑥ 推理引擎 —— 运行模型的"发动机"

推理引擎是加载模型参数并实际执行计算的软件。常见的推理引擎:

引擎 特点 适合场景
Ollama 一键下载量化模型,CPU 友好 本地开发、测试
vLLM PagedAttention 显存优化,吞吐提升 10-20 倍 生产部署
llama.cpp C++ 实现,纯 CPU 可运行 嵌入式、边缘设备
云 API 厂商托管,无需自建 快速上线、个人项目

类比:推理引擎就像汽车的发动机——参数是图纸,推理引擎是引擎本体;同一个引擎可以搭配不同的参数(模型),同一个参数也可以在不同的引擎上运行。


六个组件如何协作:一次完整的问答流程

你输入:"什么是 AQS?"
    ↓
① Tokenizer 将文本切分为 Token → [688, 312, 9766, 5342, 62]
    ↓
② 词表将每个 Token ID 映射为向量 → 5 个向量,每个 1024 维
    ↓
③ Transformer(堆叠数十层)逐层计算:
    第 1-10 层:理解词义和语法结构
    第 11-30 层:捕捉语义关系和逻辑推理
    第 31-N 层:规划输出内容和顺序
    ↓
④ 输出层产生下一个 Token 的概率分布
    例如:Token "AQS" 后面最可能是 "是"(概率 0.73)、"全称"(概率 0.19)...
    ↓
⑤ 选择概率最高的 Token → 输出 "是" → 将 "是" 添加到输入末尾 → 重复步骤 ③-⑤
    逐 Token 生成,直到输出结束标记(EOS)
    ↓
⑥ 最终输出:"AQS 是 AbstractQueuedSynchronizer 的缩写,是 Java 并发包中..."

关键认知:模型不是一次性输出整段回答,而是逐 Token 预测下一个最可能是什么——这个过程重复成千上万次,直到输出终止标记。


1.3 从规则到大模型:AI 的四次范式转移

理解 AI 的发展脉络,有助于把握当前技术所处的位置和演进方向。

第一代:符号 AI(1950s-1980s)
  代表:专家系统
  思路:人写规则 → 机器执行
  问题:规则爆炸,无法覆盖开放场景
  例子:IF 发烧 AND 咳嗽 THEN 诊断=感冒

第二代:统计机器学习(1990s-2010s)
  代表:SVM、随机森林、XGBoost
  思路:人设计特征 → 机器学权重
  问题:特征工程依赖专家,泛化能力有限
  例子:垃圾邮件分类器(手工设计"免费""中奖"等特征)

第三代:深度学习(2012-2018)
  代表:CNN、RNN、Transformer
  思路:人设计网络结构 → 机器学特征+权重
  突破:不再需要手工特征,端到端学习
  例子:ResNet 图像识别、BERT 文本理解

第四代:大语言模型 / 基础模型(2018-至今)
  代表:GPT-4、Claude、DeepSeek、GLM
  思路:海量数据预训练 → 自然语言交互 → 涌现推理能力
  突破:单一模型处理数百种任务,不需要为每个任务训练专用模型
  关键转变:从"编程解决问题"到"对话解决问题"

AI 的发展本质上就是不断减少"人工"、增加"智能"的过程——从人写规则到人设计特征,再到人设计网络结构,现在是人描述需求。

1.4 大语言模型的训练与推理

上一节拆解了大模型的六个静态组件。本节从生命周期角度理解模型如何诞生和使用——一个模型的完整生命周期分为三个阶段:

第一阶段:预训练(Pre-training)——“学会语言”

在海量文本上做"完形填空":给前半句预测后半句。训练过程遍历数万亿 token 的文本,用数千张 GPU 运行数周到数月。这个阶段模型学到了语言模式、世界知识、推理能力。

第二阶段:对齐(Alignment)——“学会好好说话”

预训练后的模型"什么都懂但不会好好说话"——它可能拒绝回答、输出有害内容、格式混乱。对齐阶段用人类偏好数据教模型:什么是有用的回答、什么是安全的回答、什么该拒绝。主流对齐方法 DPO(Direct Preference Optimization)直接用好/坏回答对优化,替代了传统复杂的 RLHF(人类反馈强化学习)。

第三阶段:推理(Inference)——“回答问题”

即每一次调用模型的过程。关键认知:每次推理是独立的——模型不记忆和你的对话,对话记忆是应用层管理的(把历史消息重新发回去)。这也是 Token 消耗的核心——对话越长,每次推理越贵。

预训练决定了模型的 “知识天花板”,对齐决定了模型的 “表达方式”,推理则是应用开发者和模型交互的唯一接口。大部分 AI 应用开发工作集中在推理阶段——如何构造 Prompt、如何管理上下文、如何解析输出。

1.5 核心概念速查

以下为 AI 应用开发必须掌握的核心概念,按从基础到进阶排列:

概念 一句话 工程意义
LLM 在海量文本上预训练的大规模神经网络,通过预测下一个 token 来理解和生成文本 AI 应用的核心引擎。本质是概率模型,不可 100% 信赖,所有工程实践围绕"如何用好它、控制它、兜底它"展开
Token AI 处理文本的最小粒度,1 中文≈1-2 token,按 token 计费 决定了 API 调用的成本和上下文管理策略。DeepSeek 约 1 元/百万 token,GPT-5 约 70 元/百万 token
上下文窗口 模型一次能"看到"的最大文本量 决定了信息加载策略——不能无脑塞全量文档,需要分层管理:常驻上下文 + 按需加载 + 摘要压缩
Embedding 把文本映射成一串数字(向量),语义相近的文本向量距离近 RAG 的根基。不同 Embedding 模型产生的向量在不同语义空间中,跨模型不可混用——这是 MindForge 平台统一 Embedding 的根本原因
幻觉 AI 自信地编造不存在的事实、API、引用 AI 应用的第一大风险。应对策略:RAG 绑定来源、Context7 实时验证文档、结构化输出约束格式、关键逻辑人工审核
思维链(CoT) 让 AI 一步步推理而非直接给答案,复杂任务准确率大幅提升 复杂推理任务的标配。DeepSeek-R1、GPT-o1 内置推理,普通模型可在 Prompt 中添加"请逐步分析"手动触发
Agent AI 不只是回答,而是自主规划→调工具→观察结果→调整→完成任务 从"聊天机器人"到"能干活的系统"的关键跃升。核心三要素:规划能力 + 工具调用 + 反馈循环
RAG 先检索相关文档,再基于文档生成回答 解决 LLM 知识截止日期和幻觉问题的首选方案。核心链路:文档解析→切分→向量化→检索→增强 Prompt→生成
MCP Model Context Protocol,AI 与外部工具的统一连接协议 让 AI 工具从"N×M 次一对一集成"变成"N+M 次统一对接"。初期可用 Function Calling 快速落地,规模上来再改造
Function Calling Agent 调用工具的底层机制——模型输出结构化 JSON 指定调哪个函数+传什么参数 Agent 的"手"——没有它 AI 只能聊天。各厂商格式不同(OpenAI/Anthropic),MCP 是解决这一碎片化的开放标准

进阶概念(了解即可,拓展知识面):

概念 全称/含义 一句话 属于
MoE Mixture of Experts 总参数大但每次只激活一小部分,DeepSeek 的标志性架构 模型架构
LoRA Low-Rank Adaptation 不改原模型参数,在旁路训练极小参数包。全量微调=重写整本书,LoRA=贴便签纸 模型微调
QLoRA Quantized LoRA LoRA 的省钱版——先把模型压到 4-bit 再贴便签纸,7B 模型只需 4GB 显存 模型微调
DPO Direct Preference Optimization 直接用好/坏回答对优化模型,替代复杂的 RLHF。Llama3/Qwen2.5 的对齐方法 模型对齐
vLLM 开源推理引擎,PagedAttention 显存优化 + Continuous Batching 吞吐提升 10-20 倍 模型部署
量化 Quantization FP16→INT4,体积缩 4 倍、速度提 2-4 倍。Ollama 默认 Q4_K_M 模型部署
语义缓存 Semantic Cache 不是缓存 key-value,是缓存"语义相似的问题"——相似度>0.95 直接返回,不走 LLM 成本优化
结构化输出 JSON Schema 约束 LLM 按预定义 Schema 返回 JSON,确保下游代码可解析 输出控制
BYOK Bring Your Own Key 平台不提供模型额度,用户自带 API Key 架构模式

1.6 为什么 2024-2026 是 AI 应用开发的分水岭

三个趋势叠加:

  1. 模型能力突破临界点:GPT-4(2023.3)→ Claude Opus 4(2025)→ DeepSeek-V3/R1(2025),模型推理能力和代码能力达到了"可以作为工程组件信赖"的水平
  2. 成本断崖式下降:DeepSeek-V3 把 API 价格打到 GPT-4 的 1/70,个人开发者每月几十块就能搭建 AI 应用
  3. 工程生态成熟:LangChain/Spring AI/LlamaIndex 等框架把 LLM 调用从"手写 HTTP 请求"抽象为"声明式编排",Agent 和 RAG 的开发效率提升 10 倍

这意味着:AI 应用开发不再是大厂的专利,个人开发者也能做出有价值的产品。


第二章:AI 模型与工具生态

2.1 主流模型对比与选型

国外模型
模型 核心优势 短板 适合场景
Claude Opus/Sonnet Agent 能力最强,多文件理解+安全设计 国内访问不便 大型重构、项目级 Agent
GPT-5 / o1 推理深度最强 贵(70 元/百万 token)、国内访问不便 高难度算法、架构评审
Gemini 2.5 多模态最强(图+视频+代码) 中文弱 多模态场景、Google 生态
Llama 4(开源) 可本地部署,数据不出域 编码能力约闭源 70% 数据合规、二次训练、金融场景
国内模型
模型 核心优势 适合场景
DeepSeek V4-Pro / R1 性价比之王(约 GPT 1/70 价格),中文编程最优 日常编码首选
GLM-5.1(智谱) 国产合规首选,政务/金融信创认证 信创合规项目
Qwen3 / CodeQwen 阿里云生态集成好 阿里云技术栈
Kimi K2 200 万字上下文,长文档分析最强 需求评审、代码库理解
选型决策框架
日常编码 / SQL 优化 → DeepSeek V4-Pro(性价比+中文编程)
大型重构 / 多文件修改 → Claude Opus/Sonnet(Agent 能力最强)
复杂算法推理 → GPT o1 / DeepSeek R1(思维链深度)
长文档分析 → Kimi K2(200 万字上下文)
信创合规 → GLM-5.1 + 本地部署(国产化认证)

推荐组合:DeepSeek(日常)+ Claude(复杂)+ Kimi(长文档)

常见误区

  • 最强模型 ≠ 最适合(GPT-5 贵且延迟高,CRUD 用它浪费)
  • 开源模型 ≠ 免费(GPU 月租 5000+)
  • 没有一个模型在所有维度最好——组合策略是最优解

2.2 AI 编程助手

工具 定位 一句话评价
Claude Code Agent 级 CLI 项目级理解+多文件编辑+MCP 扩展,Agent 能力最强
GitHub Copilot IDE 行级补全 "猜下一行"最准,行级补全王者,任务规划弱
Cursor AI-native IDE IDE 深度集成 Agent,体验流畅
Cline VS Code 插件 开源 Agent,多模型支持,Token 消耗大
Aider CLI 开源 自动 git 提交,不如 Claude Code 灵活

选择原则:日常编码 Claude Code,快速补全 Copilot,前端调试 Cursor。没有银弹——根据任务切换工具。

大模型的"脚手架":MCP、Skills、Hooks

如果把大模型比作一台发动机,那么它要真正"驱动一辆车",还需要三样东西:

  • MCP:连接外部世界的"管道"——让 AI 能访问数据库、调用 API、操作文件
  • Skills:标准化的"操作手册"——把常见任务封装成可复用的工作流
  • Hooks:自动化的"安全护栏"——在关键节点自动检查和拦截

三者共同构成大模型的工程化脚手架。它们不是模型的一部分,但没有它们,
模型只能停留在"聊天界面"里,无法融入真实的软件工程流程。


2.3 MCP — 连接 AI 与工具的通用协议

概念:MCP 是什么

MCP(Model Context Protocol)是 Anthropic 于 2024 年 11 月发布的开放标准协议,
目标是成为"AI 应用的 USB 协议"——正如 USB 让任何外设都能接入任何电脑,
MCP 让任何工具都能被任何 AI 应用调用。

没有 MCP 时:每接入一个新工具(数据库、文件系统、搜索引擎、API),
开发者都要为每个 AI 应用单独写适配代码。N 个 AI 应用 × M 个工具 = N×M 次集成。
而且每个 AI 厂商的 Function Calling 格式不同(OpenAI 用 JSON Schema,
Anthropic 用 XML 嵌套),换模型等于重写工具层。

有 MCP 后:工具只需实现一次 MCP Server,所有支持 MCP 的 AI 应用自动可用。
N 个 AI 应用 + M 个工具 = N+M 次对接。新增工具不需要改 AI 应用代码,
启动新的 MCP Server 即可。

架构与原理

MCP 采用经典的 Client-Server 架构,基于 JSON-RPC 2.0 协议通信:

┌─────────────┐                    ┌──────────────────┐
│  MCP Host   │  ── JSON-RPC ──►  │   MCP Server     │
│  (Claude/   │  ◄── 双向通信 ──  │                  │
│   Cursor/   │                    │  实现三个原语:    │
│   自研 App)  │  tools/list        │  • Tools(工具)   │
│             │  tools/call        │  • Resources(资源)│
│             │  resources/read    │  • Prompts(模板)  │
│             │  prompts/get       │                  │
└─────────────┘                    └──────────────────┘

三个核心原语(MCP 暴露给 AI 的三类能力):

原语 用途 类比 例子
Tools 让 AI 执行操作 函数调用 查数据库、发邮件、创建 Issue
Resources 让 AI 读取数据 GET 请求 读文件内容、查配置、获取日志
Prompts 预定义的提示词模板 快捷指令 “代码审查清单”、“提交信息生成”

传输层——MCP 支持两种通信方式

方式 通信机制 适合场景 例子
stdio 标准输入/输出,进程间通信 本地工具、CLI 场景 文件系统 Server、Git Server
HTTP + SSE HTTP 请求 + Server-Sent Events 流式推送 远程服务、多客户端共享 数据库 Server、企业内部 API Server

MCP 的完整生命周期

1. 初始化(Handshake)
   Client → Server: initialize { clientInfo, capabilities }
   Server → Client: initializeResult { serverInfo, capabilities }
   双方交换版本号和能力列表,协商兼容的功能集

2. 能力发现(Discovery)
   Client → Server: tools/list     → Server 返回: [{name, description, inputSchema}, ...]
   Client → Server: resources/list → Server 返回: [{uri, name, mimeType}, ...]
   AI 模型通过这些描述自主决定"何时"调用"哪个"工具

3. 操作执行(Operation)
   Client → Server: tools/call { name: "query_db", arguments: { sql: "..." } }
   Server → Client: { content: [{ type: "text", text: "查询结果..." }] }
   支持流式返回——Server 可以逐步推送结果,不必等全部完成

4. 资源读取(Resource Access)
   Client → Server: resources/read { uri: "config://app/settings" }
   Server → Client: { contents: [{ uri: "...", mimeType: "application/json", text: "..." }] }

5. 断开(Shutdown)
   Client → Server: notifications/cancelled  (取消进行中的请求)
   Client → Server: disconnect                 (优雅断开连接)
用法:如何配置和使用 MCP

以 Claude Code 为例,在 settings.json 中配置 MCP Server:

{
  "mcpServers": {
    "context7": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@upstash/context7-mcp@latest"],
      "env": {}
    },
    "postgres": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@anthropic/mcp-server-postgres", "postgresql://localhost/mydb"]
    },
    "github": {
      "type": "http",
      "url": "https://mcp-server.example.com/github",
      "headers": { "Authorization": "Bearer ${GITHUB_TOKEN}" }
    }
  }
}

配置后,Claude Code 启动时自动连接这些 Server,AI 就能在对话中直接操作数据库、
查询文档、管理 GitHub——不需要在每次对话中重新解释上下文。

常用 MCP Server 分类
类别 推荐 Server 一句话功能
文档 Context7 实时查最新版本文档,消除幻觉 API
数据库 PostgreSQL / SQLite / Redis AI 直连数据库执行查询和 Schema 分析
浏览器 Puppeteer / Chrome DevTools 截图、填表、E2E 自动化测试
开发工具 GitHub / GitLab PR 审查、Issue 管理、代码搜索
容器 Docker / Kubernetes 容器管理、Pod 日志查询
搜索 Brave Search / Tavily / Exa 实时网络搜索
文件 Filesystem 读写文件、目录遍历
价值:MCP 改变了什么
  1. 标准化:工具开发者只需实现一次 MCP Server,所有 AI 应用(Claude、Cursor、
    Continue、自研 App)都能复用。对比 Function Calling——每个厂商有自己的格式,
    换模型就要改工具描述方式。

  2. 热插拔:新增工具不需要改 AI 应用代码、不需要重新部署。启动新的 MCP Server
    进程,AI 应用下次连接时自动发现。这对微服务架构尤其重要。

  3. 生态效应:社区已有 10000+ MCP Server,覆盖数据库、云服务、开发工具、
    办公软件等几乎所有品类。这意味着大部分外部系统大概率已有现成的 MCP Server,
    不需要从零写适配。

  4. 安全边界:MCP Server 运行在独立进程中,权限隔离。你可以给不同的 Server
    分配不同的系统权限(数据库 Server 给只读账号、文件 Server 限制目录范围),
    AI 的"手"伸不到你没授权的地方。

注意:MCP 的价值在于规模——如果你的应用只有 2-3 个固定工具且短期内不会扩展,
Function Calling 足够。当工具数量增长、需要跨应用复用时,MCP 的优势开始显现。
MindForge V1 用 FC 是合理的工程决策,V2 切 MCP 是规模驱动的自然演进。

2.4 Skills — 封装可复用的 AI 工作流

概念:Skill 是什么

每个人和 AI 协作时都会积累一些"固定套路"——比如"生成单元测试报告"这件事,
每次都一样:读取截图索引 → 解析模块列表 → 填充模板 → 生成报告文件。
如果你每次都要从头向 AI 解释这个流程,效率极低。

Skill 就是把这种"固定套路"封装成一个可复用的能力包——相当于给 AI 写了一份
“标准操作程序(SOP)”。激活 Skill 后,AI 自动获得完成该任务所需的全部上下文、
规则和步骤,不需要你每次重复解释。

类比:Skill 之于 AI,如同"制造工艺卡"之于工厂——不是机器本身的能力,
但规定了机器该按什么顺序、用什么参数、检验什么标准来完成特定产品。

原理:Skill 如何工作

加载机制

用户输入 /skill-name 或 AI 自动匹配
  → 系统读取 SKILL.md(Skill 的核心文件)
  → 内容注入到 System Prompt(优先级高于默认系统提示词)
  → AI 获得该 Skill 的专用知识、规则、工作流
  → 执行过程中严格遵循 Skill 中定义的步骤
  → Skill 执行完毕,专用上下文释放

Skill 的文件结构

.claude/skills/my-skill/
├── SKILL.md          ← 核心:Skill 的定义文件(必须)
│   ├── frontmatter   ← 元数据:名称、描述、触发条件
│   └── body          ← 具体指令:步骤、规则、示例
└── resources/        ← 可选:模板文件、参考数据

SKILL.md 的 frontmatter 示例

---
name: gen-unit-test-report
description: 从截图索引生成单元测试报告(.doc 格式)
trigger: 用户要求生成单元测试报告时
---

Skill 的三种来源

类型 位置 谁维护 范围
项目级 项目的 .claude/skills/ 项目团队 当前项目
个人级 用户的 ~/.claude/skills/ 个人 所有项目
插件级 通过插件管理器安装 社区/第三方 全局
用法:创建和使用 Skill

创建 Skill 的核心原则

  1. 一个 Skill 只做一件事——职责单一,组合使用而不是大而全
  2. 站在 AI 的视角写指令——不要写"你应该理解",而是"遇到 X 情况执行 Y 步骤"
  3. 包含具体示例——AI 从示例中比从规则中学习得更准确
  4. 写清楚失败处理——“如果文件不存在,提示用户检查路径,不要自行创建”

调用方式

  • /skill-name —— 显式调用
  • AI 自动匹配 —— 当检测到任务和 Skill 描述一致时自动激活
  • 编程调用 —— 在 Workflow 脚本中引用其他 Skill
价值:Skill 改变了什么
  1. 知识捕获:把"老员工脑子里的经验"变成"新人运行 /skill-name 就能执行的流程"。
    从"口口相传"变成"可执行的代码"。

  2. 效率跃升:我的 gen-unit-test-report Skill——130+ 份单元测试报告,
    从人工 65+ 小时降到 AI 自动几分钟完成。

  3. 质量一致:每次执行同一 Skill,产出物的格式、检查点、质量门禁完全一致。
    不会出现"这次写得好、下次忘了检查某个项"的情况。

  4. 团队杠杆:一人写好 Skill,全团队受益。新人不需要培训就能输出和老员工
    同等质量的工作成果——Skill 就是"写在纸上"的经验。

Skill 的核心价值不在于"让 AI 做某件事"(裸 Prompt 也能做到),而在于
让 AI 每次都按同一套标准做这件事——可重复、可审计、可改进。


2.5 Hooks — 事件驱动的自动化守卫

概念:Hook 是什么

AI 工作时有一些关键节点需要"自动检查"——比如每次改文件之前确认改的不是生产配置、
每次改完之后自动格式化、每次结束会话前检查测试是否通过。

如果这些全靠人来记住和执行,迟早会出疏漏。Hooks 就是这些关键节点上的
“自动哨兵”
——到达触发点时自动执行预设的检查脚本,不通过则拦截操作。

类比:Hooks 之于 AI 操作,如同 CI/CD Pipeline 的各个 Gate 之于代码提交——
lint 不过不能合入、测试不过不能部署、安全扫描不过不能上线。只不过 Hooks
管控的不是 CI 流程,而是 AI 的每一次工具调用和会话生命周期。

原理:Hook 的触发和执行

四种 Hook 类型

Hook 类型 触发时机 典型用途
PreToolUse 工具执行前 “即将执行 rm -rf,确认目标路径不在保护列表中”
PostToolUse 工具执行后 “写完文件了,自动运行 prettier 格式化”
Stop 会话结束前 “退出前检查:还有未提交的 TODO 吗?测试过了吗?”
SessionStart 会话启动时 “加载项目上下文,注入自定义规则”

Hook 的执行流

用户请求 AI 执行某个操作
  →
┌─ 匹配到 PreToolUse Hook? ──是──→ 执行 Hook 脚本 ──→ 返回结果
│                                    ├── allow:继续执行
│                                    ├── deny:拦截操作 + 返回原因
│                                    └── modify:修改参数后继续
└─ 未匹配 → 正常执行
  →
AI 操作执行完成
  →
┌─ 匹配到 PostToolUse Hook? ──是──→ 执行 Hook 脚本(格式化/记录/通知)
└─ 未匹配 → 流程结束

关键特性:Hook 是同步阻塞的——PreToolUse 返回 deny 时,操作不会发生;
Hook 执行超时(默认 60 秒)视为 deny。这是安全的底线设计。

Hook 的返回值协议(PreToolUse 示例):

{
  "decision": "allow",
  "reason": "拒绝或修改的原因说明",
  "modifiedInput": {}
}
用法:配置和使用 Hooks

在 Claude Code 的 settings.json 中配置:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "python",
        "args": [".claude/hooks/check_protected_files.py"],
        "timeout": 10000
      },
      {
        "matcher": "Bash",
        "command": "python",
        "args": [".claude/hooks/deny_dangerous_commands.py"]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash",
        "args": [".claude/hooks/auto_format_and_log.sh"]
      }
    ],
    "Stop": [
      {
        "command": "bash",
        "args": [".claude/hooks/check_todos_and_tests.sh"]
      }
    ]
  }
}

matcher 字段支持正则,精确控制哪些工具操作触发 Hook:

  • "Edit|Write":只拦截文件写入操作
  • "Bash":拦截所有 shell 命令
  • "*":拦截所有工具操作(慎用)
实战模式

模式 1:改文件前自动检查(PreToolUse)

触发条件:Edit / Write 工具
Hook 逻辑:
  1. 检查目标文件是否在 "受保护文件列表" 中(如 production.yml, .env)
  2. 若是 → 返回 deny:"此文件为生产配置,请先在测试环境验证"
  3. 若否 → 返回 allow

模式 2:改完后自动格式化 + 记录(PostToolUse)

触发条件:Edit / Write 工具执行成功
Hook 逻辑:
  1. 获取修改的文件路径
  2. 运行 prettier / clang-format 自动格式化
  3. 将变更记录追加到 .claude/CHANGELOG.md

模式 3:会话结束前质量检查(Stop)

触发条件:会话即将退出
Hook 逻辑:
  1. git diff --stat 检查是否有未提交变更
  2. grep "TODO\|FIXME" 检查是否有遗留的待办标记
  3. 运行单元测试确认全部通过
  4. 有未通过项 → 返回 deny + 清单,阻止退出
价值:Hooks 改变了什么
  1. 安全兜底:PreToolUse 是第一道防线——在你看到确认弹窗前,
    自动脚本已经拦截了明显危险的操作(删除系统文件、修改生产配置)。
    它不依赖"人注意到危险",而是靠预设规则自动判断。

  2. 质量自动化:格式化、Lint、测试检查变成默认行为而不是"记得就做"。
    PostToolUse + Stop 组合覆盖了代码修改的完整生命周期。

  3. 流程强制:团队规范从"README 里的一句话"变成"Hook 里的硬约束"。
    不通过 Hook 就走不下去——比 Code Review Checklist 的约束力强得多。

  4. 可组合:Hooks 和 Skills 联动——Skill 定义怎么做事,
    Hooks 保证做事过程中不出错。两者配合形成完整的 AI 工程化闭环。

Skill vs Hook 的区别:Skill 是 AI 的"操作手册"(告诉它能做什么、怎么做),
Hook 是 AI 的"交通规则"(告诉它什么不能做、做完要检查什么)。Skill 是增强能力,
Hook 是约束行为——两者缺一不可。


第三章:Prompt Engineering — 从写提示词到管资产

3.1 Prompt 六要素

个人使用 Prompt 和工程化 Prompt 的区别,就像个人写脚本和团队开发系统——前者能跑就行,后者需要可维护、可测试、可追溯。

六要素模板

① 角色:"你是 5 年 Spring Boot 开发,熟悉金融系统规范"
② 任务:一个 Prompt 只聚焦一个任务
③ 上下文:@引用相关代码 + 业务规则说明
④ 约束:"保持现有方法签名不变"、"不要引入新第三方依赖"
⑤ 输出格式:指定结构(正常3个 + 边界2个 + 异常2个)
⑥ 示例:@ExistingTest.java "新测试风格保持一致"

对比

  • ❌ “帮我优化这段代码”
  • ✅ “这段代码在 Oracle→OceanBase 迁移中性能下降 50%。分析执行计划,找出瓶颈,给 2-3 种改写方案,保持语义等价。@SlowQuery.sql”

实用技巧

  • “一步一步思考” → 触发思维链
  • “先给方案,确认后再写代码” → 避免方向错误
  • “不对,XXX 应该是 YYY” → AI 根据反馈即时调整

3.2 思维链(CoT)与推理模型

思维链(Chain of Thought)的本质是让模型把隐式的推理过程显式化。研究表明,对于数学推理、逻辑分析等复杂任务,CoT 能将准确率从 30% 提升到 80% 以上。

两种触发方式

  • 手动触发:Prompt 中加"请一步一步思考"或"先分析再给出结论"
  • 模型内置:DeepSeek-R1、GPT-o1 在训练时就学习了推理模式,调用时自动进行

何时需要 CoT

  • 多步骤推理(逻辑题、数学题、复杂 SQL 分析)
  • 多条件权衡(架构选型、方案对比)
  • 不需要 CoT 时不要硬加——会增加 Token 消耗和延迟

3.3 结构化输出 + 流式响应

这是 AI 应用输出的两个维度,不是二选一,而是标配:

结构化输出(JSON Schema)——控制"输出什么格式":

  • 出题:{"type":"选择","stem":"...","options":[...],"answer":"A"}
  • 评分:{"score":85,"correctness":4,"weakness":["CAS"]}
  • 意图分类:{"intent":"解题","subject":"AQS","difficulty":"中等"}
  • 没有结构化输出 → 用正则从自由文本里抠数据 → 脆弱不可靠

流式响应(SSE)——控制"输出怎么呈现":

  • LLM 逐 token 返回,用户看到文字一个个出现
  • 没有流式 → 用户等 10 秒看空白页 → 体验不可接受

两者配合:LLM 流式输出 JSON 字符串 → 前端一边接收 chunks 一边展示 → 收到完整 JSON 后做最终解析和校验。这是当前主流做法。

3.4 Prompt 工程化管理

当你的 AI 应用有 5+ 种场景,每种场景又对应不同备考方向时,Prompt 就不是"写一段话存备忘录"了——它是一套需要版本管理的代码资产

MindForge 的 Prompt 管理实践完整展示了这套体系:

模板分类:出题 / 评估 / 追问 / 简历 / 意图 —— 5 种场景各有独立模板
方向绑定:会计出题提示词 ≠ Java 出题提示词,每个方向可配置专属模板变量占位符:{{备考方向名称}} {{检索关键词}} {{题型列表}} {{难度}}
版本管理:tb_prompt_template + tb_prompt_version 两张表,每次修改留历史,支持 Git-revert 式回滚
升级门禁:模板升级前跑离线评估集,Faithfulness 低于阈值不发布
删除保护:被备考方向引用的模板不可直接删除
默认回退:未配置专属模板的方向,使用系统默认模板

工程化带来的好处

  1. 改 prompt 不用发版——管理员后台编辑即可
  2. prompt 质量可追溯——版本对比知道"改了哪句话导致质量变化"
  3. 知识可复用——"Java 出题提示词 v1.3"可被多个 Java 相关方向共享

第四章:RAG — 检索增强生成

RAG 是 AI 应用开发中最重要的技术范式之一。本章从原理讲到评估,从基础实现讲到高级优化,最后以 MindForge 代码为例走读完整链路。

4.1 RAG 解决了什么问题

LLM 有两大先天缺陷:① 知识截止日期(训练数据有终点)② 幻觉(对训练数据外的问题可能编造答案)。RAG 通过"检索+生成"的方式,让 LLM 能使用训练数据之外的知识。

有 RAG 和没有 RAG 的区别

没有 RAG(纯 LLM):
  用户:"OceanBase 迁移后性能为什么断崖下跌?"
  LLM:编造一段听起来合理但可能完全错误的分析

有 RAG:
  用户:"OceanBase 迁移后性能为什么断崖下跌?"
  → 向量检索找到相关技术文档中的"PL/SQL 函数逐行求值"段落
  → 作为上下文传给 LLM
  → LLM:"根据文档记录,根因是 OceanBase 对 WHERE 条件中的 PL/SQL 函数逐行求值...
          解决方案有 4 种:参数绑定、标量子查询包装..."
  → 回答正确,且有据可查

RAG 数据流

文档上传 → 解析(PDF/Word/Markdown)→ 文本切分 → 向量化 → 入库(向量数据库)
                                                                      ↓
用户提问 → 问题向量化 → 相似度检索 Top-K → 拼接 Prompt → LLM 生成 → 带引用来源的回答

4.2 文档切分策略

这是 RAG 最容易出问题的环节。切分不对,后面全白费。

三种策略

策略 方式 适合 不适合
固定大小 每 N 个 token 一刀切,相邻块重叠 10-20% FAQ、规章制度(条目独立性强) 连贯性强的技术文档
语义切分 按段落/章节边界切,保持语义完整 技术文档、业务手册 无结构文本
递归切分 先按一级标题→二级标题→段落逐级切 合同协议、法规(层级清晰) 扁平结构文档

关键参数

  • Chunk Size:256-512 token(中文约 200-400 字)。太小丢失上下文,太大检索精度下降
  • Overlap:10-20%。防止关键信息恰好落在分块边界上
  • 核心原则:每个 Chunk 自包含——单独拿出来看,不需要翻前一段也知道在说什么

Chunk Enrichment(块增强)——一个成本极低但效果显著的优化:

原文:"根据第3条,订单取消需提前通知..."
增强后:"[《代客交易系统接口规范》/ 第三章 订单接口 / 2025-06 更新]
         根据第3条,订单取消需提前通知..."

检索时 AI 就知道这段内容的来源和时效性,输出的引用也更准确。

4.3 Embedding 与向量数据库

Embedding 模型选择

模型 维度 语言 费用 适合
BGE-large-zh-v1.5 1024 中文最优 免费(本地) 中文知识库首选
text-embedding-3-small 1536 多语言 OpenAI 计费 多语言、快速验证
Jina embeddings-v3 1024 多语言 有免费额度 长文本(支持 8192 token 输入)

MindForge 的 Embedding 设计决策:平台统一使用 BGE 模型,而不是用用户自己的 API Key 调 Embedding API。为什么?公共知识库需要跨用户检索一致性——如果用户 A 用 GLM 的 Embedding 模型写向量,用户 B 用通义千问的模型去检索,两个向量在不同的语义空间中,检索结果完全不可用。平台统一 Embedding 保证了跨用户的向量空间兼容。

向量数据库选型

方案 规模 部署 延迟 MindForge 状态
Chroma < 10 万条 pip install 零部署 < 10ms 本地开发/原型
内存暴力搜索 < 1 万条 无依赖 O(n) 遍历 ✅ MindForge V1 使用
Milvus 百万~十亿 Docker/K8s 部署 < 5ms(HNSW) V2 升级方向

MindForge V1 选择了最轻量的内存暴力搜索方案(见 VectorIndexService.java)——启动时全量加载向量到 ConcurrentHashMap,查询时遍历计算余弦相似度,用小顶堆维护 Top-K。设计注释写得很诚实:

“当单方向文档量 >5000 或搜索 P99 >200ms 时,可替换为 Lucene HNSW 实现。”

这就是工程上"先跑通再优化"的典型决策——V1 阶段文档量少,暴力搜索完全够用,不引入 Milvus 的运维复杂度。

余弦相似度计算VectorIndexService.java:196-206):

// MindForge 实际代码
private double cosineSimilarity(float[] a, float[] b) {
    if (a.length != b.length) return 0.0;
    double dot = 0.0, normA = 0.0, normB = 0.0;
    for (int i = 0; i < a.length; i++) {
        dot += (double) a[i] * b[i];
        normA += (double) a[i] * a[i];
        normB += (double) b[i] * b[i];
    }
    if (normA == 0.0 || normB == 0.0) return 0.0;
    return dot / (Math.sqrt(normA) * Math.sqrt(normB));
}

4.4 混合检索

纯向量检索的盲区:擅长语义匹配(“数据库"↔"DB”),但可能漏掉精确的关键词(“PGET_SYSCURRDATE”)。混合检索 = 向量语义相似度 + BM25 关键词精确匹配,加权融合后重排序。

混合检索流程:
用户问题
  ├── 向量检索(语义匹配)   → Top-K₁ 结果 ──┐
  └── BM25 检索(关键词匹配) → Top-K₂ 结果 ──┼── RRF 融合(k=60)→ 最终排序 → 传给 LLM

MindForge 设计文档中采用了 RRF(Reciprocal Rank Fusion, k=60)进行融合。BM25 权重 0.3 + 向量权重 0.7——向量为主、关键词为辅,适合中文技术文档场景。

4.5 RAG 评估:你怎么知道你的 RAG 好不好用

三层评估体系:

第一层:检索评估 → 检索回来的文档是否相关?排序是否正确?
  指标:Hit Rate(Top-K 命中率)、MRR(首个相关文档的排名倒数)、NDCG(排序加权)

第二层:生成评估 → 答案是否忠实于检索文档?有没有编造?
  框架:RAGAS(业界最常用)
  指标:Faithfulness(忠实度)、Answer Relevancy(答案相关性)、
        Context Precision(上下文精度)、Context Recall(上下文召回)

第三层:端到端评估 → 用户满意度
  指标:点赞率、点踩率、回答可用率、考试通过率

LLM-as-Judge(当前性价比最高的自动评估方式):
用强模型评估弱模型输出——输入问题+检索文档+待评估答案,输出 1-5 分的 faithfulness/correctness/completeness + 解释。每 100 条对话抽样 5 条自动打分。

MindForge 的评估策略

  • 离线:建 50 条标准问答对,每次改 prompt 或检索策略跑一遍,对比 MRR 和 Faithfulness
  • 在线:用户点赞/点踩 + LLM-as-Judge 自动抽样
  • 监控:检索命中率、平均相似度、AI 搜索触发频率(反映知识库覆盖不足)
  • 门禁:prompt 模板升级前先跑离线评估集,低于阈值不发布

4.6 高级 RAG 技术

基础 RAG 有三个常见问题,各有对应方案:

问题 现象 方案 原理
检索不相关 问"AQS 原理"返回"美国质量标准 AQS" Self-RAG / CRAG LLM 生成前先自评检索文档相关性,低分丢弃+触发 Web 搜索
跨文档多跳推理 “synchronized 锁升级后对 GC 有什么影响” GraphRAG 用知识图谱替代向量检索,沿图谱路径做多跳遍历
短问题精度低 "怎么优化慢查询"口语化太短 HyDE 先让 LLM 生成"假设性答案",用答案的向量去检索——答案和文档在向量空间更接近

MindForge 的 RAG 升级路线

阶段 技术 解决的问题
V1(已实现) 基础 RAG + 内存向量索引 基本问答、来源标注
V1.5 + Self-RAG(检索结果自评) 减少不相关文档干扰
V2 + Milvus HNSW + HyDE 检索性能 + 短问题精度
V3(按需) + GraphRAG 跨文档多跳推理

MindForge 三级出题源降级(本质是简化版 CRAG):

出题时获取知识:
  Layer 1:知识库 RAG 检索  → 有结果 → 使用
                              → 无结果/相关性低 ↓
  Layer 2:LLM 训练数据      → 模型自身知识兜底
                              → 知识不可靠 ↓
  Layer 3:AI 搜索(可选)    → DuckDuckGo 等外部搜索补充

4.7 RAG vs 微调:选型决策框架

RAG vs 微调的本质区别:

维度 RAG 微调(Fine-tuning)
改什么 不改模型参数,只优化检索+prompt 改模型权重参数
知识更新 实时(更新向量库即可) 需重新训练
成本 低(Embedding + 检索开销) 高(GPU 训练 + 数据标注)
幻觉控制 有来源可追溯 来源不可追溯
适合 知识密集型、频繁变动 风格/格式固定、领域术语注入

决策框架

知识是否频繁变动?
  ├── 是 → RAG(考纲每年更新、法规变化)
  └── 否 → 需要特定输出格式/风格?
            ├── 是 → 微调(客服话术、代码风格)
            └── 否 → RAG 或 Prompt 工程即可

资源有多少?
  ├── 有 GPU + 标注数据 → 可考虑微调
  └── 只有 API Key → RAG

MindForge 为什么选 RAG

  1. 考纲每年可能变化,微调跟不上,RAG 更新文档即可
  2. Java/会计/架构师三套完全不同的知识域,微调一个模型全覆盖极难
  3. 考试答案必须标注来源,RAG 天然支持,微调做不到
  4. 个人项目无 GPU,API 调用是唯一可行方案
  5. 公共知识库跨用户共享,RAG 天然支持,微调无法做到

进阶——不是二选一:RAFT(训练时注入检索文档,让模型学会忽略不相关文档)、GraphRAG(知识图谱替代向量检索)、RAG + LoRA 微调混合。业界趋势是组合使用。

4.8 实战:MindForge RAG 全链路代码走读

MindForge 的 RAG 全链路涉及三个核心组件:

链路全景

用户上传文档(PDF/Word/Markdown)
  → DocumentParser(解析为纯文本)
  → TextSplitter(语义切分,512 token/chunk,64 token overlap)
  → EmbeddingService.embedBatchAndStore()(BGE 向量化 + 磁盘持久化)
  → DocumentChunkRepository(MySQL 存元数据:chunkId/documentId/content/vectorId)
  → VectorIndexService.loadAll()(启动时 ConcurretHashMap 全量加载)
  → RagSearchTool(Agent 工具——LLM 自主决定何时调用)
  → VectorIndexService.search()(余弦相似度 + 小顶堆 Top-K)
  → 结果拼入 System Prompt → LLM 生成 → SSE 流式返回

EmbeddingServicemindforge-rag/.../EmbeddingService.java):

  • 支持 GLM(embedding-2)和通义千问(text-embedding-v3)两种 Embedding API
  • 向量以 JSON 数组格式存到 data/vectors/{uuid}.json
  • 30 秒超时,调用失败抛 RuntimeException(由 Agent Tool 层 catch)

VectorIndexServicemindforge-rag/.../VectorIndexService.java):

  • @PostConstruct loadAll() 启动时全量加载到 ConcurrentHashMap
  • directionIndex(Map<Long, List>)实现按备考方向隔离检索
  • 查询用 PriorityQueue 小顶堆维护 Top-K,时间复杂度 O(n log k)
  • 设计注释标注了升级路径:“>5000 条或 P99>200ms 时换 Lucene HNSW”

RagSearchToolmindforge-agent/.../tools/RagSearchTool.java):

  • 实现 AgentTool 接口,注册到 AgentToolRegistry
  • 参数 query + topK(上限 10),由 LLM 自主决定何时调用
  • 返回 JSON 格式的检索结果列表(含 chunkId/documentId/content/score)
  • 通过 _provider_apiKey_directionId 等系统注入参数获取运行时上下文

第五章:Agent — 让 AI 从"聊天"到"干活"

5.1 Agent 的本质

三种 AI 能力的递进:

纯 LLM RAG Agent
能力 仅靠训练数据回答 LLM + 检索外部知识 LLM + 调用工具 + 多步推理
能做什么 回答问题 基于文档回答 执行任务(查数据库、调 API、操作文件)
例子 “什么是 MVCC” “根据面试笔记回答锁升级过程” “查表找出交易量最大的客户,生成 Excel 报表”

Agent 的三个核心能力:

  • 规划:把复杂任务拆成可执行的步骤
  • 工具调用:自主决定何时调用什么工具
  • 反馈循环:观察工具结果 → 调整下一步计划 → 继续执行

5.2 ReAct 模式深入

ReAct(Reasoning + Acting)是当前最主流的 Agent 推理范式:

循环结构(Thought → Action → Observation → 回到 Thought):

用户:"出 5 道 Java 多线程的单选题,难度中等"

→ Thought: 需要先从知识库检索多线程相关内容
→ Action: call rag_search(query="Java 多线程 知识点")
→ Observation: 返回 12 个文本片段(synchronized/ReentrantLock/线程池/volatile/AQS...)

→ Thought: 有足够的知识点,可以出题了。结合 LLM 知识出 5 道中等难度单选题。
→ Action: call exam_generation(
    topics=["synchronized","ReentrantLock","线程池","volatile","AQS"],
    questionType="单选", count=5, difficulty="中等"
  )
→ Observation: 生成了 5 道题目

→ Thought: 题目生成完成,检查一下是否覆盖了要求的 5 个主题
→ Final Answer: (输出 5 道题目,标注每题来源)

和传统编程的本质区别

  • 传统:人思考 → 人写代码 → 人检查
  • Agent:AI 思考 → AI 调工具 → AI 看结果 → AI 调整 → AI 输出

ReAct 的进化版

  • Plan-and-Execute:先一次性规划出完整步骤(Plan),再逐步执行(Execute),执行中发现问题就调整 Plan。适合复杂多步骤任务
  • Reflexion:执行失败后不只重试,而是先反思"为什么失败"→ 把反思记入上下文,下次自动避免同类错误

5.3 Function Calling vs MCP

两者的关系不是对立,而是演进:

维度 Function Calling MCP
定义者 各厂商各自定义(OpenAI/Anthropic 格式不同) Anthropic 提出的开放标准,社区共建
工具描述 写在每次 API 请求的 tools 参数里 Server 启动时通过 tools/list 动态提供
工具发现 应用代码硬编码工具列表 连接到 Server 时自动发现可用工具
新增工具 改代码 + 重新部署 启动新 MCP Server 即可(热插拔)
生态 厂商锁定 社区共建,已有 10000+ Server

MindForge 为什么 V1 用 Function Calling

  • 工具集固定(RAG 检索/AI 搜索/题库查询/代码沙箱),不会频繁变动
  • Spring AI 的 ToolCallback 机制开发效率高,AgentTool 接口注册到 AgentToolRegistry 后自动适配
  • 个人项目单机部署,MCP 每个 Server 独立进程增加运维负担

V2 改造方向

当前(FC):Agent → @Tool 注解的 Java 方法 → 直接调用

V2(MCP):Agent → MCP Client → MCP Server(RAG检索) → 向量库
                               → MCP Server(题库)     → MySQL
                               → MCP Server(沙箱)     → Docker

改造后的价值:

  • 工具热插拔:新增"简历评估服务"作为独立 MCP Server,不停机上线
  • 工具复用:RAG 检索 MCP Server 可被其他应用直接复用
  • 协议演进意义:“V1 用 FC 快速落地,V2 改造 MCP 开放生态”

Function Calling vs MCP = 各厂商的私有充电口 vs USB-C。前者够用但换手机得换线,后者一次适配到处能用。关键是知道什么时候用什么——初期 FC 快速验证,规模上来切 MCP。

5.4 多 Agent 协作模式

单 Agent 能解决大部分问题,但当任务规模超过单一上下文的承载能力时,需要多 Agent 协作。

四种经典模式

模式 结构 适合场景 例子
顺序流水线 A→B→C 串行 步骤有明确依赖关系 需求→设计→编码→测试→审查
辩论模式 多 Agent 独立分析→互相质疑→收敛 高风险决策 技术方案评审、安全审查
投票/集成 多 Agent 独立输出→汇总比较 有多个可行解的开放问题 Bug 根因分析、SQL 优化方案
分层委派 主 Agent 拆任务→N 个子 Agent→汇总 大型跨模块任务 项目框架升级

关键原则:人永远是总指挥——任务的拆解边界、验收标准、最终决策权在人手上。AI 是执行者,不是决策者。

5.5 语义缓存与降级策略

两个容易被忽视但实际价值极大的工程手段。

语义缓存

  • 不是缓存 key-value 字符串,是缓存"语义相似的问题"
  • “synchronized 原理” = “Java 内置锁的工作机制” → 语义相同 → 缓存命中
  • 相似度阈值 ≥ 0.95 直接返回,不走 LLM
  • BYOK 模式下,每省一次 LLM 调用 = 帮用户省钱

降级策略(MindForge 的三级降级):

RAG 检索
  ├── 返回结果充足 → 基于知识库生成,标注来源
  ├── 返回结果不足 → 降级到 LLM 训练数据 + 提示"以下答案基于通用知识,非您的资料"
  └── RAG 不可用(异常)
      ├── LLM 训练数据 → 降级兜底
      ├── 两者均不可用 → 提示用户"服务暂不可用,请稍后重试"
      └── 绝不让用户看到 500 / 空白页

5.6 实战:MindForge Agent + ReAct 代码走读

MindForge 的 Agent 实现是全文最核心的代码,完整展示了如何用 Spring AI 构建 ReAct 循环。

架构设计

mindforge-agent 模块(独立 Maven 模块,不依赖 mindforge-service)

AgentTool (接口)
  ├── getName()       → "rag_search"
  ├── getDescription() → "从用户知识库中检索..."(LLM 决策依据)
  ├── getParametersSchema() → JSON Schema(LLM 理解参数格式)
  └── execute(Map params)  → ToolResult(实际执行逻辑)

AgentToolRegistry (注册中心)
  ├── Spring 自动注入所有 AgentTool Bean
  ├── buildToolsDescription() → 生成工具列表文本,注入 System Prompt
  └── get(String name) → 按名查找工具

ReActLoop (循环调度器)
  ├── buildInitialMessages() → System Prompt + 对话历史 + 用户查询
  ├── buildToolCallbacks()  → AgentTool → Spring AI ToolCallback 适配
  └── execute() → ChatClient.prompt().tools(...).call().chatResponse()

关键设计:AgentTool → ToolCallback 适配ReActLoop.java:142-193):

// 将 AgentTool 适配为 Spring AI 2.0 ToolCallback
// 核心是三个动作:
// 1. 提供 ToolDefinition(名/描述/参数Schema)—— LLM 用来决定是否调用
// 2. 实现 call(String input) —— Spring AI 自动解析 LLM 的工具调用请求
// 3. 合并系统注入参数(_provider, _apiKey, _directionId)—— 这些是 LLM 不知道的
ToolCallback callback = new ToolCallback() {
    @Override
    public ToolDefinition getToolDefinition() {
        return DefaultToolDefinition.builder()
                .name(tool.getName())
                .description(tool.getDescription())
                .inputSchema(tool.getParametersSchema())
                .build();
    }

    @Override
    public String call(String input) {
        Map<String, Object> params = new HashMap<>(JSON.parseObject(input, Map.class));
        // 合并系统注入的额外参数
        if (context.getExtraToolParams() != null) {
            params.putAll(context.getExtraToolParams());
        }
        // 发送 SSE thinking 事件 → 前端展示"正在检索知识库..."
        emitThinking(context, 0, tool.getName(), "started", null);
        ToolResult result = tool.execute(params);
        emitThinking(context, 0, tool.getName(),
                result.isSuccess() ? "completed" : "failed", buildSummary(result));
        return result.isSuccess() ? result.getData() : "ERROR: " + result.getErrorMessage();
    }
};

ReActContextReActContext.java):

// 封装一次 Agent 调用所需的全部参数
ChatModel chatModel;                        // 由调用方通过 LlmChatRouter 获取
String systemPrompt;                        // 含工具列表 + 角色定义 + 行为规则
String userQuery;                           // 用户输入的原始问题
List<Message> history;                      // 对话历史(多轮对话)
Map<String, Object> extraToolParams;        // 系统注入参数(_provider, _apiKey 等)
Consumer<ThinkingEvent> thinkingCallback;   // SSE 事件回调
int maxIterations = 10;                     // 兜底:单次最多 10 步
int toolTimeoutSeconds = 30;                // 单次工具调用 30 秒超时

工具列表(已实现的 3 个 + 设计中的 3 个):

工具 功能
rag_search RagSearchTool 知识库语义检索
ai_search AiSearchTool 外部网络搜索(DuckDuckGo 免费兜底,按 Provider 路由)
question_bank_query QuestionBankQueryTool 历史题库查询
exam_generation (设计中) 根据检索结果生成考题
answer_evaluation (设计中) 评估用户答案,输出评分+建议
follow_up_decision (设计中) 从四维度判断是否继续追问

上下文窗口管理ContextWindowManager.java):

  • 会话超过 20 轮时,自动摘要前 10 轮
  • 摘要注入为 SystemMessage,后续轮次基于摘要继续
  • 摘要 LLM 调用失败时降级为简单截断(保留最近 10 轮)

第六章:AI 工程化实践

6.1 内容安全纵深防御

AI 应用的内容安全不只是 Prompt Injection 防护,而是输入→模型→输出的三层纵深防御。

第一层:输入安全(用户给 LLM 的内容)

  • 敏感词过滤:本地部署敏感词库,用户输入命中则拦截(< 5ms 延迟)
  • 文件内容扫描:上传的 PDF/Word 先过文本审核再入知识库
  • 频率限制:单用户每分钟最多 N 次请求,防滥用

第二层:Prompt 约束(模型的行为边界)

  • 系统提示词中写入内容边界:“你只能回答考试相关内容,拒绝政治/违法/色情/暴力问题”
  • 注意:Prompt 约束定义的是正当行为底线,不是防注入的手段(注入会覆盖系统指令)

第三层:输出安全(LLM 给用户的内容)

  • 规则校验:正则 + 关键词黑名单检测输出
  • 可疑标记:触发规则 → 标记"仅个人可见" + 后台记录待审查
  • 人工审核:AI 自动生成的题库题目需管理员审核后方可进入公共题库

MindForge 安全架构

用户输入 → 敏感词过滤 → 合规 → Agent 处理
                       → 不合规 → "输入包含不当内容,请修改后重试"

LLM 输出 → 规则校验 → 合规 → 返回用户
                    → 可疑 → 标记+仅个人可见+后台待审查

Prompt Injection 四道防线(金融系统特别重要):

  1. 输入校验:用户输入只作为"数据"处理,用参数化方式拼接,绝不让用户输入成为"指令"
  2. 角色隔离:System Prompt(不可变)和 User Message(标签化)物理隔离
  3. 输出过滤:AI 回复在返回前二次检查——正则匹配敏感词、长度异常检测
  4. 最小权限:AI 数据库连接用只读账号、代码沙箱 --network none --read-only

6.2 成本控制策略

MindForge 采用 BYOK(用户自带 Key)模式,平台不承担模型成本。但用户体验的核心是"帮我省钱"。

成本控制层次

第一层:模型选型(最大省钱点)
  DeepSeek(¥1/百万 token) vs GPT-5(¥70/百万 token)= 70 倍差距
  日常 CRUD → DeepSeek,复杂推理 → Claude

第二层:语义缓存
  高频问题相似度 > 0.95 → 直接返回缓存 → 不走 LLM
  考试场景下,"synchronized 原理"类问题重复率很高

第三层:上下文控制
  对话超过 20 轮自动摘要压缩 → 减少每次请求的 token 数
  不是把所有历史消息重新发一次

第四层:限制兜底
  ReAct 最多 10 步、追问最多 5 层、上下文最多 8000 Token
  防止 Agent 无限循环消耗 Token

6.3 AI 应用可观测性

AI 应用的可观测性和传统后端不同——不是 CPU/内存/QPS,而是 AI 特有的指标:

指标类别 具体指标 为什么重要
成本 Token 消耗(输入/输出/总计),按用户+方向汇总 用户自带的 Key,要知道钱花在哪了
延迟 首 Token 延迟(用户感知最强)、工具调用耗时 等 2 秒 vs 等 10 秒出第一个字的体验天差地别
质量 检索命中率、平均相似度、AI 搜索触发频率 命中率持续下降 = 知识库需要更新
可用性 LLM API 错误率、Embedding 失败率、沙箱执行失败率 降级策略触发频率过高 → 需要扩容或优化
用户反馈 点赞率、点踩率、追问接受率 点踩率突增 → prompt 或检索策略可能出问题了

MindForge 的 Token 追踪设计:90 天明细保留(tb_token_usage_log),按日汇总归档(tb_token_daily_summary)。这样可以做趋势分析——“这周的 Token 消耗为什么比上周多了 30%?”

6.4 模型部署与量化

本地 vs 生产,技术栈完全不同

本地开发(Ollama):
  ollama pull deepseek-r1:7b  → 一行命令搞定
  自动下载 Q4_K_M 量化版本,CPU 友好
  适合:验证、测试、数据不出域的场景

生产部署(vLLM / TensorRT-LLM):
  vLLM:PagedAttention 显存优化 + Continuous Batching 吞吐提升 10-20 倍
  一条命令启动 OpenAI 兼容 API:vllm serve Qwen/Qwen2.5-7B-Instruct
  适合:上线服务、高并发

量化——把模型从 CD 压成 MP3

  • FP16 → INT4,体积缩 4 倍,速度提 2-4 倍,效果几乎无损
  • 三种格式:GGUF(CPU 推理/Ollama)、GPTQ(GPU/需校准数据)、AWQ(GPU/精度优于 GPTQ)
  • Q4_K_M:4-bit,质量与速度的最佳平衡点(Ollama 默认)

6.5 微调入门

虽然大部分场景 RAG 就够了,但了解微调有助于理解模型能力边界和 AI 应用的全技术栈。

三种方式,成本从高到低

方式 成本 原理 适用
全量微调 最高(7B 需 56GB+) 更新全部参数 大公司专属模型
LoRA 中(7B 需 8GB) 在旁路训练小参数包 当前主流
QLoRA 低(7B 需 4GB) 先量化再 LoRA 消费级显卡可跑

DPO(直接偏好优化)——当前开源模型的标准对齐方法:

  • 传统 RLHF 需要三步:训奖励模型→评分→PPO 强化学习(复杂+不稳定)
  • DPO 直接用好/坏回答对优化,数学上等价 RLHF 但简单得多
  • Llama 3、Qwen 2.5 等主流开源模型都用 DPO 做对齐

微调数据准备——最容易被忽视的环节:

  • 数据格式:{"instruction":"任务","input":"用户输入","output":"期望输出"}
  • LoRA 几百到几千条高质量样本就有效果
  • 数据质量 >> 数据数量:100 条精心标注 > 1000 条自动生成
  • 多样性:覆盖正常/边界/异常场景

选型判断:RAG 优先验证价值 → 确实需要固化输出风格/格式 → LoRA/QLoRA 微调。大部分场景 RAG + Prompt 工程已经够用,微调是最后的优化手段。


第七章:实战全景 — MindForge 考试指导 AI 平台

本章将前面六章的知识点串联到一个完整的项目中,展示它们在实际代码中是如何组合在一起的。

7.1 项目架构全景

业务定位:AI 驱动的多方向考试/面试辅导平台。用户自带 API Key(DeepSeek/GLM/通义千问),选择备考方向(Java 求职/会计中级/架构师),平台通过 Agent + RAG 提供智能问答、模拟考试和简历评估。

技术栈

技术 备注
后端框架 Spring Boot 4.1.0 + Spring MVC Java 17
AI 框架 Spring AI 2.0(ChatClient + ToolCallback) 而非 LangChain4j(需求文档写的是后者,实际选了前者)
数据库 MySQL 8.0(业务) + 内存 ConcurrentHashMap(向量) V1 无外部向量数据库
前端 Vue 3 + TypeScript + Element Plus + Vite 6 Composition API
安全 JWT + AES-256-CBC(API Key 加密) 每次加密随机 16 字节 IV
实时通信 SSE(LLM 流式) + WebSocket(代码沙箱输出)

Maven 模块结构

mindforge (parent POM)
├── mindforge-common/      共享 DTO/枚举/常量/异常
├── mindforge-repository/  JPA Entity + Repository(MySQL)
├── mindforge-security/    JWT + AES 加密 + Spring Security 配置
├── mindforge-rag/         Embedding 向量化 + 内存向量索引
├── mindforge-agent/       AgentTool 接口 + ReActLoop + 工具实现
├── mindforge-service/     业务逻辑编排(调用 Agent + RAG)
├── mindforge-web/         REST Controller + Spring Boot 入口
└── mindforge-frontend/    Vue 3 前端(Vite)

依赖方向:web → service → {repository, agent, security} → common

7.2 关键设计决策复盘

以下是 MindForge 开发过程中的关键设计决策,体现了 AI 应用开发中的典型工程权衡:

决策 1:Spring AI 2.0 而非 LangChain4j

需求文档最初写的是 LangChain4j,实际选的是 Spring AI。原因:

  • Spring AI 2.0 的 ChatClient API 与 Spring Boot 生态深度集成(依赖注入、自动配置、属性绑定)
  • ToolCallback 机制比 LangChain4j 的 @Tool 注解更直接地映射 Agent 工具
  • MindForge 作为 Spring Boot 项目,减少跨生态依赖降低维护成本

决策 2:内存向量索引而非 Milvus

V1 选择了最简单的方案——ConcurrentHashMap + 启动时全量加载。这是刻意的工程决策:

  • V1 阶段文档量少(每个备考方向几百条 chunk),暴力搜索 O(n) 完全够用
  • 避免引入外部依赖(Milvus 需要 Docker 部署,增加运维复杂度)
  • 代码中明确标注了升级条件(>5000 条或 P99 > 200ms)和升级路径(Lucene HNSW)
  • 体现工程判断力——知道什么时候该简单、什么时候该复杂

决策 3:平台统一 Embedding 而非用户自带

这是实际开发中发现的关键问题:

  • 公共知识库需要跨用户检索,如果各用各的 Embedding 模型 → 向量在不同语义空间 → 检索完全不可用
  • 解决:平台统一使用 BGE 中文模型,不绑定用户的 API Key 提供商
  • 技术价值:展示对"跨用户数据一致性"这一分布式系统经典问题的延伸思考

决策 4:Agent 模块独立,不反向依赖 Service

注意 mindforge-agent 模块的依赖方向——它不依赖 mindforge-service

  • ReActContext 通过 extraToolParams 从外部接收运行时参数(_provider_apiKey_directionId
  • ChatModel 由调用方通过 LlmChatRouter 获取后传入,Agent 层不管路由逻辑
  • 这是一个经典的依赖倒置——Agent 层定义接口,Service 层注入实现

决策 5:BYOK 模式的前提和代价

  • 前提:用户有自己的 API Key(国内 LLM 注册即可获取)
  • 好处:平台零模型成本、用户可选择便宜的模型
  • 代价:Key 安全存储(AES-256-CBC 加密+UI 脱敏)、过期验证、多 Key 管理、Embedding 策略必须独立于用户 Key

7.3 代码核心链路走读

链路 1:智能问答完整流程

用户在前端输入问题 → Vue 发起 SSE 连接(fetch + ReadableStream)

Controller 层(ExamController / ChatController):
  → 验证 JWT Token → 获取 userId
  → 获取当前备考方向 directionId
  → 获取用户 API Key → AesEncryptionService.decrypt()
  → 构造 ReActContext → 调用 ReActLoop.execute()

Agent 层(ReActLoop):
  → buildInitialMessages(): System Prompt(含工具列表)+ 历史 + 用户问题
  → buildToolCallbacks(): 6 个 AgentTool → 6 个 ToolCallback
  → ChatClient.prompt().messages().tools().call().chatResponse()
  → Spring AI 自动处理 LLM 的工具调用决策(多轮)
  → LLM 返回最终答案

SSE 推送:
  → ThinkingEvent 通过 thinkingCallback → SseEmitter.send()
  → 前端展示 "正在检索知识库..." / "正在搜索外部资料..."
  → 最终答案逐 token 流式返回

链路 2:API Key 加密存储

// AesEncryptionService.java — AES-256-CBC,每次加密随机 16 字节 IV
public String encrypt(String plaintext) {
    byte[] iv = new byte[16];
    new SecureRandom().nextBytes(iv);         // 每次随机 IV
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv));
    byte[] ciphertext = cipher.doFinal(plaintext.getBytes(UTF_8));
    // 存储格式: Base64(IV + ciphertext)
    byte[] combined = new byte[16 + ciphertext.length];
    System.arraycopy(iv, 0, combined, 0, 16);
    System.arraycopy(ciphertext, 0, combined, 16, ciphertext.length);
    return Base64.getEncoder().encodeToString(combined);
}

链路 3:AI 搜索的 Provider 路由

// AiSearchTool.java — 按 _provider 选择搜索适配器
// 当前默认 DuckDuckGo(免费,无需 Key)
// 后续扩展:provider=GLM → GLM 内置搜索, provider=QWEN → 千问内置搜索
private SearchAdapter selectAdapter(String provider) {
    if (provider != null) {
        // 后续扩展:按 LLM 提供商选择对应的搜索能力
    }
    return adapters.getOrDefault("duckduckgo",
        adapters.values().stream().findFirst().orElse(null));
}

7.4 从需求到代码:一个 AI 应用的完整工程链路

MindForge 不只是"一个 CRUD 项目加了 LLM 调用"——它涉及了 AI 应用开发的完整工程链路:

需求分析(6 个功能模块 + 5 个非功能需求)
  → 数据库设计(16 张表 + 50 个索引 + ER 图)
  → 接口设计(74 个 REST API + 14 种 SSE 事件类型 + WebSocket)
  → 前端设计(Vue 3 + 状态机驱动的考试流程 + 5 个 Pinia Store)
  → 部署设计(Nginx + systemd + Docker 沙箱 + .env 密钥管理)
  → 编码实现(7 个 Maven 模块 + Spring AI + Vue 3 + Element Plus)
  → AI 特有的工程关注:Prompt 模板管理、语义缓存、降级策略、Token 追踪、内容安全

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐