RAG技术栈全景:从向量数据库到LLM

RAG技术栈全景:从向量数据库到LLM

上篇我们聊了RAG是什么,这篇我们直接上硬菜:把RAG技术栈的每一个组件拆开看清楚。不夸张地说,90%的人做RAG卡住,都是因为组件选型没想清楚就开干。看完这篇,你至少能画出自己系统的架构图。

大家好,我是黒漂技术佬。


一、一张图看清RAG全貌

先把全景图甩出来。一个企业级RAG系统包含6个核心层:

复制代码
┌─────────────────────────────────────────────────┐
│                【应用层】                          │
│  问答对话  │  文档搜索  │  数据助手  │  标注平台    │
├─────────────────────────────────────────────────┤
│                【生成层】                          │
│  Prompt模板  │  上下文组装  │  流式输出  │  引用追溯  │
│                     │                            │
│              LLM(大语言模型)                      │
│    GPT-4  │  DeepSeek  │  Qwen  │  私有部署模型    │
├─────────────────────────────────────────────────┤
│                【检索层】                          │
│  混合检索  │  Query改写  │  重排序  │  结果过滤     │
├─────────────────────────────────────────────────┤
│                【向量层】                          │
│  Embedding模型  │  向量数据库  │  索引管理         │
├─────────────────────────────────────────────────┤
│                【数据层】                          │
│  文档解析  │  文本分块  │  元数据提取  │  数据清洗   │
├─────────────────────────────────────────────────┤
│                【基础设施层】                       │
│  Python/FastAPI  │  Docker  │  Redis  │  MinIO    │
└─────────────────────────────────────────────────┘

看起来层很多?别慌,我们一层层拆。


二、数据层:垃圾进,垃圾出

RAG系统有一条铁律:知识库的质量上限 = 你喂进去的文档质量

LLM再强,检索算法再精妙,如果文档本身就是一坨------表格乱码、图片丢失、层级全乱------那最终答案能好才见鬼了。

文档解析引擎

不同格式需要不同的解析器:

文档格式 推荐工具 难点
PDF(文字型) PyMuPDF / pdfplumber 表格提取、双栏布局
PDF(扫描型) Tesseract OCR + pdf2image 手写体、印章遮盖
Word (.docx) python-docx 嵌入图片、复杂表格
Markdown 直接读文本
HTML BeautifulSoup 导航栏、广告等噪音
飞书/语雀 各自API + HTML解析 富文本嵌套
微信群聊记录 正则解析 大量表情、无关消息

实操建议

  • 优先用 pdfplumber,它比 PyMuPDF 更擅长处理中文表格
  • 扫描件必须过OCR,但别期望太高------扫描质量差的文档 OCR 准确率不到 80%
  • 能用Markdown就别用Word------未来你的知识库一定是日积月累的,让员工从源头上用结构化的格式

文本分块(Chunking)

解析出纯文本后,不能整篇喂给Embedding模型------那就像把一本书扔进搜索框。需要切块

常用的分块策略:

复制代码
策略1:固定长度分块(naive,不推荐)
  按 500 字切一块,遇到句号才断。
  问题:可能在「第3章......第4章」中间一刀砍断。

策略2:语义分块(推荐)
  按标题层级切:一二级标题作为独立块,正文段落聚合到对应标题下。
  工具:LangChain 的 RecursiveCharacterTextSplitter + MarkdownHeaderTextSplitter

策略3:滑窗重叠(折中方案)
  每块 500 字,相邻两块重叠 100 字。
  好处:不会因为切在句子中间而丢掉语义。

我的实战经验

  • 中文文档,块大小 300~500 字比较合适(太短缺少上下文,太长稀释语义)
  • 每个块必须带元数据:来源文件名、页码、章节标题、更新时间
  • 元数据在检索时会派上大用场------比如「只搜 2024 年后的技术文档」

三、向量层:RAG的发动机

上一篇文章讲了,Embedding是把文字变成数字数组。这层有两个关键选型。

Embedding 模型怎么选?

截至 2026 年,中文 Embedding 模型已经卷得不成样了。选型核心看三点:语义质量、推理速度、向量维度

模型 维度 中文效果 特点
text-embedding-3-small (OpenAI) 1536 ⭐⭐⭐ 云端调用,付费,效果好但数据要流出
bge-large-zh-v1.5 (BAAI) 1024 ⭐⭐⭐⭐ 开源,中文顶流,本地部署
m3e-large (moka-ai) 1024 ⭐⭐⭐⭐ 开源,中英双语,社区活跃
stella-large-zh (infgrad) 1024 ⭐⭐⭐⭐ 开源,速度快
jina-embeddings-v3 1024 ⭐⭐⭐⭐ 支持 8192 token 长文本
GTE-Qwen2-7B-instruct 3584 ⭐⭐⭐⭐⭐ 大模型做Embedding,效果最好但资源吃紧

我的选择 :公司内部用 bge-large-zh-v1.5,效果和速度都OK;如果预算充足且对数据安全没那么敏感,text-embedding-3-small 的 API 调用是零运维成本的选择。

详细评测(同一份测试集、同一检索任务下的 mAP@10 对比)留到第 5 篇再展开。

向量数据库怎么选?

向量数据库是RAG的"记忆仓库"。市面上的选择大致分三类:

类型 代表产品 适用场景
轻量级向量库 Chroma 开发测试、Demo、单机小规模
专用向量数据库 Milvus / Qdrant / Weaviate 百万级以上向量、需要分布式
全文+向量融合 Elasticsearch 8.x 已有ES基础设施、需要混合检索

具体选哪个,我们放到第 6 篇详细对比。这里只给结论:Demo 阶段用 Chroma 最快跑通,生产环境优先看 Milvus 或带向量能力的 ES 8.x。


四、检索层:让系统真正懂你

检索层是RAG的"大脑",也是调优空间最大的环节。几个核心技术:

1. 混合检索(Hybrid Search)

单独用向量检索有一个经典问题:你问"张三的报销单",向量可能匹配到一堆讲报销流程的文档,但就是找不到张三那份具体的报销单。

原因在于:向量擅长语义类比,但不擅长精确匹配人名、工号、金额这类实体。

所以企业级RAG几乎都用「混合检索」:

复制代码
用户问题 
    │
    ├──→ 向量检索(语义召回)  → Top 20
    │
    └──→ 关键词检索(BM25/ES)→ Top 20
           │
           └──→ RRF(倒数排名融合)/ 加权融合 → Top 10
                    │
                    └──→ 重排序(Reranker)→ Top 5 → 送给LLM

2. Query 改写

用户不会写完美的搜索查询。他们可能会问:"上次那个关于代码评审的,就是那个谁来着,你说要加的那个检查项......"

这种问题直接向量化,几乎搜不到任何东西。所以需要Query改写------在检索之前,用一个小型的LLM把用户的模糊问题重写为检索友好的形式:

原文:"上次那个关于代码评审的检查项"

改写后:"代码评审(Code Review)检查项清单 规范"

3. 重排序(Reranker)

向量检索返回的 Top-K 只是"大概相关",还需要一个更强的模型重新打分排序。推荐用 bge-reranker-large,它在 MTEB 中文排行榜上长期霸榜。

流程:向量检索出 20 条 → Reranker 精排后取前 5 条 → 送给 LLM。


五、生成层:把材料变成答案

生成层看似最简单------把文档片段拼进Prompt就行。但实际上,Prompt写得好不好,答案质量差一个档次。

一份好的RAG Prompt 至少包含:

复制代码
【角色设定】你是一个企业知识库助手,服务于XX公司内部员工。
【核心规则】
  1. 只根据提供的文档内容回答,文档中没有的信息明确说"不知道"
  2. 回答末尾必须标注引用的文档名称和页码
  3. 如果文档中有矛盾信息,如实指出并说明分别来自哪份文档
【相关文档】(由检索系统自动填充)
  ...
【用户问题】(用户的原话)

LLM 选型

模型 适用场景 成本
GPT-4o 最高质量,复杂推理 $$
DeepSeek-V3 性价比极高,中文友好 $
Qwen2.5-72B 私有化部署首选 自建GPU
GLM-4 中文效果好 $

实操建议:内部问答场景用 DeepSeek 完全够用,成本只有 GPT-4o 的十分之一不到;如果数据安全要求高,部署一个 Qwen2.5-32B 本地跑也不是不行。


六、企业级架构全景(附带一张真实部署图)

讲完所有组件,来看一张我实际部署的企业级RAG架构:

复制代码
                   ┌─────────────┐
                   │   Nginx     │  负载均衡 + SSL
                   └──────┬──────┘
                          │
              ┌───────────┴───────────┐
              │                       │
       ┌──────▼──────┐        ┌──────▼──────┐
       │  FastAPI    │        │  FastAPI    │  API服务(多副本)
       │  (问答API)  │        │  (管理API)  │
       └──────┬──────┘        └──────┬──────┘
              │                       │
    ┌─────────┼───────────────┬───────┼─────────┐
    │         │               │       │         │
    ▼         ▼               ▼       ▼         ▼
┌──────┐ ┌──────┐       ┌──────┐ ┌──────┐  ┌──────┐
│Milvus│ │Redis │       │  LLM │ │Embed│  │MinIO │
│向量库│ │ 缓存 │       │ 服务 │ │ ding│  │文件存│
└──────┘ └──────┘       └──────┘ └──────┘  └──────┘
                                        文档源 (PDF/Word/MD)

关键设计点:

  • 向量库独立部署:Milvus 跑在独立服务器上,不跟 API 服务耦合
  • Redis 做两层缓存:问题→答案缓存(完全相同的提问秒回)+ Embedding 结果缓存(节省反复调 Embedding 服务的开销)
  • MinIO 存原始文件:文档的原始 PDF/Word 存在对象存储里,方便追溯原文
  • 异步文档处理:上传文档后走消息队列(Redis Stream / RabbitMQ),解析→分块→向量化→入库,全部异步,上传秒回

七、这里选型,最容易踩的3个坑

坑1:上来就搞微服务

Demo 阶段一个 FastAPI + Chroma + SQLite 完全够用。不要一上来就拆微服务、搞 K8s、配服务网格------你连用户到底怎么用都还没搞清楚。

先跑通一个单机的端到端流程,再考虑架构拆分。

坑2:Embedding 模型随便选

选了英文优化的模型贴到中文场景上,语义检索基本等于随机猜。中文必须选中英双语或纯中文优化的模型。

坑3:文档不处理就直接扔

"我试了试,把 200 页的 PDF 直接 Embedding,效果不好。"------那是当然的。文档必须经过解析→清洗→分块的流水线。跳过这一步,就是在给后续所有环节埋雷。


💬 你的技术栈选好了吗?Embedding 模型和向量数据库准备用哪个?评论区分享一下,我帮你参谋参谋!