专题一:《RAG技术全景解析:从原理到架构设计》
📚 企业级 RAG 智能问答系统全栈实施指南
第一部分:基础认知与架构设计
第 1 章 RAG 技术全景解析
1.1 什么是 RAG?
RAG(Retrieval-Augmented Generation,检索增强生成)是一种将信息检索与文本生成相结合的人工智能技术架构。它通过从外部知识库检索相关信息,并将其作为上下文提供给大语言模型,从而生成更准确、更有依据的回答。
📌 核心概念简介
| 术语 | 英文全称 | 简单解释 |
|---|---|---|
| RAG | Retrieval-Augmented Generation | 先检索相关知识,再让 AI 生成答案 |
| Embedding | 嵌入向量 | 把文字变成数字向量,让计算机理解语义 |
| Vector Store | 向量存储 | 专门存储向量的数据库,能快速找到相似内容 |
| LLM | Large Language Model | 大语言模型,如 Qwen、GPT 等 |
| Token | 词元 | AI 处理文本的基本单位,中文约 1.5 字符=1 token |
1.2 RAG 系统核心流转
用户提问 → 向量化检索 → 上下文组装 → LLM 生成回答
(Milvus) (Spring) (Ollama)
四大核心组件
| 组件 | 角色 | 技术实现 | 详细说明 |
|---|---|---|---|
| 📝 翻译官 | 将非结构化文档转化为高维向量 | Embedding 模型 (bge-m3/bge-small-zh) | 负责把文字"翻译"成向量,让计算机能理解语义相似度 |
| 🗄 记忆库 | 负责海量向量的存储、索引及相似度检索 | Milvus 向量数据库 | 存储所有向量,能在毫秒级找到最相似的内容 |
| 🧠 决策大脑 | 结合检索出的上下文背景生成精准回答 | LLM 大模型 (Qwen/Ollama) | 根据检索到的政策片段,生成准确的答案 |
| 🖥 展示层 | 流式文字输出,展示引用来源 | Vue3+ SSE | 实时显示答案,让用户不用等待完整生成 |
1.3 为什么需要向量数据库?
传统 SQL 数据库的局限
| 能力 | SQL 数据库 | 说明 |
|---|---|---|
| ✅ 精确匹配 | 擅长 | 能准确查找"等于"、"大于"等条件 |
| ✅ 结构化数据 | 擅长 | 适合存储表格形式的规整数据 |
| ❌ 语义理解 | 无法 | 无法理解"猫"和"小猫"的语义关系 |
| ❌ 模糊搜索 | 困难 | LIKE 查询效率低,无法理解语义相似度 |
向量数据库的优势
| 能力 | 向量数据库 | 说明 |
|---|---|---|
| ✅ 语义相似度 | 专精 | 能理解"人工智能"和"AI"是相似概念 |
| ✅ 模糊匹配 | 擅长 | 即使措辞不同,也能找到相关内容 |
| ✅ 海量数据 | 支持 | 专为千万级、亿级甚至万亿级向量数据集设计 |
| ✅ 毫秒检索 | 支持 | 使用 HNSW 等索引算法,实现毫秒级检索 |
1.4 典型应用场景
| 场景 | 描述 | 技术要点 |
|---|---|---|
| 🤖 企业知识库问答 | 构建政务/企业政策问答系统,用户提问→检索相关切片→注入 LLM 上下文→生成准确回答 | 需要准确的引用来源追溯 |
| 🖼 多模态搜索 | 在数亿商品或图片库中,实现毫秒级的视觉相似度检索 | 需要 CLIP 等多模态 Embedding 模型 |
| 🛍 个性化推荐 | 将用户行为和商品特征向量化,实时推荐感兴趣的内容 | 需要实时更新用户向量 |
| 🛡 异常检测/风控 | 通过对比行为轨迹的向量距离,快速识别欺诈或系统故障 | 需要设定相似度阈值告警 |
第 2 章 系统架构与运行逻辑
2.1 完整架构设计
本项目采用典型的 RAG(检索增强生成)架构,将政务文档(PDF/Word)转化为可检索的知识库,结合大模型进行精准回答。
展示层 (Presentation)
Vue3 前端 + SSE 流式输出 + 引用来源展示
↑↓
生成层 (Generation)
Ollama 运行的 Qwen-7B/Qwen2.5-1.5B 模型
↑↓
检索层 (Retrieval)
用户问题向量化 → Milvus 检索最相关政策片段 (Top K)
↑↓
数据层 (ETL)
Spring Boot 读取文档 → bge-small-zh/bge-m3 模型向量化 →存入 Milvus
2.2 技术底座
| 技术组件 | 版本 | 说明 | 选择理由 |
|---|---|---|---|
| Spring Boot | 3.4.3(稳定版) | 后端框架 | 生态完善,与 Spring AI 深度集成 |
| Spring AI | 1.0.0-M6(里程碑版) | AI 集成框架 | 简化 AI 应用开发,统一 API 接口 |
| Milvus | v2.4.0+ | 向量数据库 | 开源、高性能、支持海量数据 |
| Ollama | 最新版 | 本地大模型运行平台 | 本地部署、模型管理方便 |
| Vue3 | 最新版 | 前端框架 | 响应式、组件化、生态丰富 |
| JDK | 21 LTS | Java 运行环境 | 长期支持版本,性能优化 |
2.3 一个完整请求的流转过程
-
解析阶段:Spring Boot 通过 Apache Tika 解析上传的 PDF/Word 政策文件
Tika 自动识别文件类型,提取纯文本内容
-
向量化:调用 bge-small-zh/bge-m3 模型将文字转为向量
每 500 token 切分为一个片段,重叠 100 token 保持语义连贯
-
检索阶段:在 Milvus 中进行相似度搜索,提取最相关的政策原文
使用余弦相似度,返回 Top 3 最相关片段
-
Prompt 组装:将"用户问题"+"政策片段"组装成一段"限定范围"的提示词
告知 LLM 仅基于提供的上下文回答,减少幻觉
-
推理与流式响应:
- Ollama 使用选定模型生成答案
- 后端通过 SSE(Server-Sent Events)协议将字符流实时推送到 Vue3 前端
- 用户在 500ms-2s 内看到首字和完整逻辑
第 3 章 硬件选型与路线规划
3.1 两条实施路线选择
| 特性对比 | 🌟 Path A:标准企业级方案 | 💻 Path B:低配/个人实验方案 |
|---|---|---|
| 适用场景 | 生产环境、演示汇报、高性能要求 | 个人学习、阿里云低配 ECS、无显卡环境 |
| 硬件底线 | 至少 16GB 内存,建议配备 NVIDIA 显卡 | 2 核 4G/4 核 8G,纯 CPU 运算 |
| 对话模型 | qwen:7b(4-bit 量化,逻辑严密) | qwen2.5:1.5b(极致轻量,速度极快) |
| 向量模型 | bge-m3(多语言优异,维度 1024) | bge-small-zh(极小巧,维度 512) |
| 预期性能 | 首字延迟<1s,推理顺滑 | 首字延迟<2s,勉强流畅 |
| 保命手段 | 模型常驻内存、GPU 加速 | 开启 Swap 虚拟内存、模型降级、限制 JVM |
3.2 阿里云服务器选型建议(Path A)
| 组件 | 推荐配置 | 理由 | 预估成本 |
|---|---|---|---|
| 实例规格 | 阿里云 GPU 实例 (gn7i 或 gn6i) | 必须配备 NVIDIA GPU,否则 7B 模型推理将极其缓慢(>10s) | 约 8-15 元/小时 |
| GPU | NVIDIA A10(24GB) 或 T4(16GB) | Qwen-7B 约占 5-8GB 显存,A10 可确保首字极速响应 | 包含在实例中 |
| CPU/内存 | 8 核 32GB | Milvus 检索和 Spring Boot 文档解析非常消耗内存 | 包含在实例中 |
| 系统盘 | 100GB ESSD | 确保模型加载和日志写入的高吞吐 | 约 50 元/月 |
🚨避坑提醒:普通 ECS 实例(无 GPU)只能以 CPU 模式运行 Ollama,体验极差,仅适合测试 1.5B 以下的超轻量模型。
3.3 硬件与业务逻辑分工
| 硬件 | 职责 | 说明 | 性能影响 |
|---|---|---|---|
| CPU | 负责逻辑处理(Spring 业务、PDF 解析)和 AI 推理(Ollama 的数学计算) | 核心数决定并发量 | 核心越多,并发处理能力越强 |
| 内存 (RAM) | 系统的命门 | Java(JVM)、Milvus 索引、Ollama 模型都需要驻留内存。内存不足会导致系统直接崩溃 (OOM) | 内存不足是低配服务器最大瓶颈 |
| GPU | AI 的加速器 | 没有它,AI 也能跑,但速度会变慢 10 倍以上 | GPU 可使推理速度提升 10-50 倍 |
| 硬盘 (SSD) | 决定向量数据库检索速度和模型加载速度 | ESSD 优于普通云盘 | SSD 可使数据加载速度提升 5-10 倍 |
3.4 内存资产负债表(4GB 内存分配参考)
⚠️ 在 4G 内存中运行 Milvus+ Ollama+ Spring Boot,必须执行"资源精细化管理",严防 OOM(内存溢出)导致系统假死
| 组件 | 内存分配上限 | 调优核心手段 | 监控命令 |
|---|---|---|---|
| Milvus 数据库 | 1.0 GB | Docker deploy.resources.limits 硬限制 + 内部缓存限额 | docker stats |
| Ollama (LLM+Embed) | 2.2 GB | 设置 KEEP_ALIVE 动态释放 + 限制并发线程 | ollama ps |
| Spring Boot(JVM) | 0.6 GB | 参数-Xmx600m-XX:MaxMetaspaceSize=256m | j stat-gc |
| OS 预留 | 0.2 GB | 卸载冗余插件,维持基础响应 | free-h |
3.5 为什么 2GB 内存必崩无疑?
🚨 在 2GB 内存下,系统处于"小马拉大车"的超载状态
内存赤字账本
| 组件 | 内存需求 | 是否可优化 |
|---|---|---|
| BGE-M3(Embed) | ~1.2GB | 可降级为 bge-small-zh(~400MB) |
| Qwen-1.5B(LLM) | ~1.0GB | 可降级为 qwen2.5:0.5b(~400MB) |
| Milvus(DB) | ~1.0GB | 可限制为 512MB(影响性能) |
| Spring Boot | ~0.5GB | 可限制为 256MB(可能 OOM) |
| 总计需求 | 约 3.7GB(远超物理内存) | 最低可压至 2.2GB |
连锁反应
物理内存溢出
↓
系统疯狂调用 Swap(虚拟内存)
↓
硬盘读写速度比内存慢数百倍
↓
CPU 长期处于 iowait 状态
↓
程序表现为连接超时 [request_sent] 或直接卡死
第 4 章 核心名词与概念详解
4.1 向量 (Vector) 与 Embedding
向量是一组有序的数字序列,用于表示数据的数学特征。在 AI 中,文本、图片、音频等非结构化数据通过 Embedding 模型转换为向量。
Embedding 模型工作原理
原始文本:"人工智能是未来技术"
↓(通过 BGE-M3 模型处理)
向量:[0.123,-0.456, 0.789,..., 0.321](1024 维数字序列)
关键参数详解
| 参数 | 含义 | 典型值 | 影响说明 |
|---|---|---|---|
| 维度 (Dimension) | 向量的长度,决定表达能力 | 512/768/1024/1536 | 维度越高,表达能力越强,但内存占用越大 |
| 量化 (Quantization) | 压缩模型精度以减少内存占用 | Q4_K_M/Q5_K_M/Q8_0 | Q4 占用最小但精度损失约 3%,Q8 精度损失<1% |
| 上下文窗口 (Context) | 模型一次能处理的最大 token 数 | 512/2048/4096 | 越大能处理的文本越长,但内存占用越高 |
4.2 相似度度量算法
| 算法 | 公式 | 适用场景 | 值域范围 |
|---|---|---|---|
| 余弦相似度 (Cosine) | cos(θ)= A·B/(‖A‖‖B‖) | 文本语义检索,最常用 | [-1, 1],越接近 1 越相似 |
| 欧式距离 (L2) | √(Σ(ai-bi)²) | 图像、物理空间距离 | [0, ∞),越小越相似 |
| 内积 (IP) | Σ(ai×bi) | 推荐系统、排序 | 无固定范围,越大越相似 |
💡 Milvus 默认使用余弦相似度,值域 [-1, 1],越接近 1 表示越相似。一般阈值设为 0.6-0.8。
4.3 HNSW 索引详解
HNSW(Hierarchical Navigable Small World) 是一种基于图的近似最近邻搜索算法,是当前工业界综合性能最强的向量索引算法。
核心参数
| 参数 | 含义 | 推荐值 | 影响 | 内存影响 |
|---|---|---|---|---|
| M | 每个节点的最大连接数 | 16 | 越大检索越准,内存占用越高 | M 每增加 8,内存增加约 10% |
| efConstruction | 构建索引时的搜索深度 | 128 | 越大索引质量越好,构建越慢 | 仅影响构建时,不影响运行时 |
| efSearch | 检索时的搜索深度 | 64 | 越大检索越准,速度越慢 | 影响检索时内存和速度 |
索引构建示例
yaml
spring:
ai:
vectorstore:
milvus:
index-type: HNSW
index-params:
M: 16
efConstruction: 128
4.4 SSE(Server-Sent Events) 协议
SSE 是一种服务器向客户端推送实时数据的技术,基于 HTTP 长连接。
与 WebSocket 对比
| 特性 | SSE | WebSocket | 选择建议 |
|---|---|---|---|
| 通信方向 | 单向(服务器→客户端) | 双向 | RAG 问答只需单向,SSE 更简单 |
| 协议 | HTTP/HTTPS | WebSocket(ws/wss) | SSE 无需额外协议支持 |
| 重连机制 | 自动 | 需手动实现 | SSE 断线自动重连 |
| 适用场景 | 流式文本、新闻推送 | 聊天、游戏、实时协作 | RAG 推荐 SSE |
SSE 数据格式
data:第
data:一
data:个
data:字
data:[DONE]
4.5 Token 与文本切片
Token 是 NLP 中的基本处理单位,中文约 1.5 字符=1 token,英文约 0.75 单词=1 token。
切片策略详解
| 策略 | 描述 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 固定长度切片 | 按固定 token 数切割 | 实现简单,可预测 | 可能切断语义 | 通用场景 |
| 语义切片 | 按段落/句子边界切割 | 语义完整 | 实现复杂 | 文档结构清晰时 |
| 重叠切片 | 相邻切片保留部分重叠 | 防止语义截断 | 数据冗余 | 推荐默认使用 |
推荐配置
java
//每片 500 token,重叠 100 token,保证语义连贯
TextSplitter splitter = new TokenTextSplitter(500, 100, 10, 10000, true);
4.6 OOM(Out Of Memory) 详解
OOM 是内存溢出错误,在 RAG 系统中常见原因:
| 原因 | 症状 | 解决方案 | 预防措施 |
|---|---|---|---|
| JVM 堆内存不足 | Java 进程被 kill | 限制-Xmx 参数 | 设置-Xmx600m |
| 容器内存无限制 | 容器占用全部物理内存 | 设置 deploy.resources.limits | Docker Compose 中限制 |
| Swap 未开启 | 系统直接崩溃 | 创建 8G Swap 分区 | 部署前必做 |
| 模型并发加载 | 多个模型同时驻留内存 | 设置 OLLAMA_KEEP_ALIVE | 设置 5 分钟自动释放 |
4.7 Docker 网络模式详解
| 模式 | 描述 | 适用场景 | 优缺点 |
|---|---|---|---|
| bridge(默认) | 容器通过虚拟网桥通信 | 大多数场景 | ✅隔离性好 ❌轻微性能损耗 |
| host | 容器直接使用宿主机网络 | 性能要求高 | ✅性能最优 ❌端口易冲突 |
| none | 无网络 | 安全隔离 | ✅最安全 ❌无法联网 |
| container | 共享其他容器网络 | 特殊架构 | ✅灵活 ❌配置复杂 |
💡 RAG 系统推荐:使用默认 bridge 模式,通过服务名通信。
第 5 章 Spring AI 版本演进说明
5.1 Spring AI 1.0 GA 正式发布(2025 年 5 月 20 日)
📢 重要更新:本书编写时使用的是 Spring AI 1.0.0-M6 里程碑版,但 Spring AI 1.0 GA 已于 2025 年 5 月 20 日正式发布。
| 版本 | 发布时间 | 状态 | 建议 | 主要变化 |
|---|---|---|---|---|
| 1.0.0-M1~M8 | 2024-2025 | 里程碑版 | 仅用于学习测试 | API 不稳定,可能有 breaking changes |
| 1.0.0 GA | 2025-05-20 | 正式生产版 | 生产环境推荐使用 | API 稳定,生产就绪 |
| 1.1 GA | 2025-11 | 正式版 | 新功能尝鲜 | 引入 Agents 框架 |
| 1.0.2 | 2026-01 | 最新稳定版 | 最佳选择 | Bug 修复,性能优化 |
5.2 GA 版本核心改进
xml
<!--推荐使用最新稳定版本-->
<properties>
<spring-ai.version>1.0.2</spring-ai.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
GA 版本主要改进
- ChatClient API 稳定化:提供可移植且易于使用的标准接口
- RAG 功能增强:改进检索增强生成的全流程支持
- 会话记忆机制:支持 ChatMemory 持久化到数据库
- 工具调用(Function Calling):支持智能体(Agent)模式
- 评估框架(Bench):内置 RAG 系统质量评估工具
5.3 M6 到 GA 版本迁移指南
| 变更项 | M6 版本 | GA 版本 | 迁移操作 | 影响程度 |
|---|---|---|---|---|
| 包路径 | spring.ai.* | org.springframework.ai.* | 更新 import 语句 | 🔴 高 |
| ChatClient | ChatClient.builder() | ChatClient.create() | API 简化 | 🟡 中 |
| VectorStore | 自动配置不稳定 | 自动配置稳定 | 可移除手动配置 | 🟢 低 |
| 依赖仓库 | 需要 milestone 仓库 | 仅需 central 仓库 | 移除 milestone 配置 | 🟢 低 |
⚠️ 重要提醒:本书代码基于 M6 版本编写,若升级至 GA 版本,请参考官方迁移文档进行调整。
第 6 章 Embedding 模型选型指南(2026 版)
6.1 MMTEB 评估基准最新排名(ICLR 2025)
🎯 震惊发现:参数量仅 560M 的模型击败了 7B 大模型!
| 排名 | 模型 | 参数量 | 维度 | 中文 MTEB 得分 | 内存占用 | 推荐指数 | 适用场景 |
|---|---|---|---|---|---|---|---|
| 🥇 | bge-m3 | 567M | 1024 | 64.8 | ~1.2GB | ⭐⭐⭐⭐⭐ | 生产环境首选 |
| 🥈 | bge-large-zh-v1.5 | 335M | 1024 | 63.2 | ~800MB | ⭐⭐⭐⭐ | 中文场景 |
| 🥉 | text-embedding-3-large | - | 3072 | 62.5 | API 调用 | ⭐⭐⭐⭐ | 云端 API |
| 4 | bge-small-zh-v1.5 | 118M | 512 | 61.8 | ~400MB | ⭐⭐⭐⭐⭐(低配) | 低配服务器 |
| 5 | m3e-base | 220M | 768 | 60.5 | ~600MB | ⭐⭐⭐ | 平衡方案 |
📊 数据来源:MMTEB(Massive Multilingual Text Embedding Benchmark) 覆盖 250+ 语言、500+ 任务
6.2 模型选型决策树
是否需要中文支持?
是 → 是否需要多语言?
是 → bge-m3(推荐)
否 → bge-large-zh-v1.5
否 → 是否内存受限?
是 → bge-small-zh-v1.5(512 维)
否 → text-embedding-3-large(3072 维)
6.3 维度与性能权衡
| 维度 | 检索精度 | 内存占用 | 检索速度 | 适用场景 | 推荐配置 |
|---|---|---|---|---|---|
| 512 | 85% | 低 | 最快 | 低配服务器、快速原型 | 2C4G 环境 |
| 768 | 92% | 中 | 快 | 平衡方案 | 4C8G 环境 |
| 1024 | 96% | 高 | 中 | 生产环境推荐 | 8C16G+ 环境 |
| 3072 | 98% | 极高 | 慢 | 高精度要求场景 | GPU 环境 |
⚠️ 重要提醒:更换 Embedding 模型后,必须删除并重建 Milvus Collection!维度不匹配会导致检索崩溃。
6.4 Ollama 中的 Embedding 模型管理
bash
#查看已安装的 Embedding 模型
ollama list | grep -E "embed|bge"
#拉取推荐模型
ollama pull bge-m3
#测试 Embedding 效果
curl http://localhost:11434/api/embeddings -d '{
"model": "bge-m3",
"prompt": "什么是 RAG 技术?"
}'
#查看模型详细信息
ollama show bge-m3
第 7 章 文档分块策略进阶
7.1 传统分块 vs 新兴分块策略
| 策略 | 原理 | 优点 | 缺点 | 适用场景 | 实现难度 |
|---|---|---|---|---|---|
| 固定长度分块 | 按固定 token 数切割 | 实现简单,可预测 | 可能切断语义 | 通用场景 | ⭐ |
| 重叠分块 | 相邻切片保留重叠 | 保持语义连贯 | 数据冗余 | 推荐默认使用 | ⭐⭐ |
| 语义分块 | 按段落/句子边界切割 | 语义完整 | 实现复杂 | 文档结构清晰 | ⭐⭐⭐ |
| Late Chunking | 先 Embedding 再分块 | 检索精度提升 15% | 计算成本高 | 高精度要求 | ⭐⭐⭐⭐ |
| Max-Min 语义分块 | 动态相似度决策 | 自适应文档结构 | 需要调参 | 混合文档类型 | ⭐⭐⭐⭐⭐ |
7.2 Late Chunking 实现原理
传统流程
文档 → 分块 → Embedding → 向量数据库
Late Chunking 流程
文档 → 句子 Embedding → 语义相似度计算 → 动态分块 → 向量数据库
💡 优势:利用句子级向量计算语义相似度,确保分块边界在语义断裂处,检索精度提升 15%+。
7.3 Spring AI 中的分块配置
java
//推荐配置:重叠分块(平衡性能与精度)
TokenTextSplitter splitter = new TokenTextSplitter(
500, //每片 token 数
100, //重叠 token 数(20% 重叠率)
10, //最小片大小
10000, //最大片大小
true //保持段落完整
);
//低配服务器配置(减少内存占用)
TokenTextSplitter lowMemSplitter = new TokenTextSplitter(
300, //减少每片大小
50, //减少重叠
10,
5000,
true
);
7.4 分块策略性能对比测试
| 分块大小 | 重叠率 | 检索精度 | 索引大小 | 检索延迟 | 推荐场景 |
|---|---|---|---|---|---|
| 200 token | 10% | 82% | 小 | 20ms | 低配服务器 |
| 500 token | 20% | 91% | 中 | 35ms | 生产环境推荐 |
| 800 token | 25% | 93% | 大 | 50ms | 高精度要求 |
| 500 token | 0% | 78% | 最小 | 15ms | 不推荐(语义断裂) |
💡 最佳实践:500 token + 20% 重叠率是精度与性能的最佳平衡点。
本专题完
📌 核心要点总结:
- RAG 本质是"先检索相关知识,再让 AI 生成答案"
- 向量数据库是 RAG 系统的核心基础设施
- 硬件选型决定系统性能上限,4GB 内存是最低生存线
- Embedding 模型选型参考 MMTEB 排名,bge-m3 是生产环境首选
- 文档分块 500 token + 20% 重叠率是最佳平衡点
📖 下专题预告:《Milvus 向量数据库:从零开始搭建 RAG 系统的核心组件》------ 详解 Docker 部署、Milvus 架构、2.6 新特性