RAG 简介

什么是 RAG?

RAG(Retrieval-Augmented Generation)是一种 融合信息检索与文本生成 的技术范式。其核心逻辑是:在大型语言模型(LLM)生成文本前,先通过检索机制从外部知识库中动态获取相关信息,并将检索结果融入生成过程,从而提升输出的准确性和时效性。

双阶段

  • 关键组件
    1. 索引(Indexing) 📑:将非结构化文档(PDF/Word 等)分割为片段,通过嵌入模型转换为向量数据。
    2. 检索(Retrieval) 🔍️:基于查询语义,从向量数据库召回最相关的文档片段(Context)。
    3. 生成(Generation) ✨:将检索结果作为上下文输入 LLM,生成自然语言响应。

为什么要使用 RAG?

为了解决 LLM 的核心局限:知识局限、幻觉问题等。

问题 RAG 的解决方案
静态知识局限 实时检索外部知识库,支持动态更新
幻觉(Hallucination) 基于检索内容生成,错误率降低
领域专业性不足 引入领域特定知识库(如医疗/法律)
数据隐私风险 本地化部署知识库,避免敏感数据泄露

如何上手 RAG?

基础工具链选择

开发框架

  • LangChain:提供预置 RAG 链(如 rag_chain),支持快速集成 LLM 与向量库
  • LlamaIndex:专为知识库索引优化,简化文档分块与嵌入流程

向量数据库

  • Milvus:开源高性能向量数据库
  • FAISS:轻量级向量搜索库
  • Pinecone:云服务向量数据库

四步构建最小可行系统

  1. 数据准备
    • 格式支持:PDF、Word、网页文本等
    • 分块策略:按语义(如段落)或固定长度切分,避免信息碎片化
  2. 索引构建
    • 嵌入模型:选取开源模型(如 text-embedding-ada-002)或微调领域专用模型
    • 向量化:将文本分块转换为向量存入数据库
  3. 检索优化
    • 混合检索:结合关键词(BM25)与语义搜索(向量相似度)提升召回率
    • 重排序(Rerank):用小模型筛选 Top-K 相关片段(如 Cohere Reranker)
  4. 生成集成
    • 提示工程:设计模板引导 LLM 融合检索内容
    • LLM 选型:GPT、Claude、Ollama、Qwen 等(按成本/性能权衡)

数据加载

在 RAG 系统中,数据加载 是整个流水线的第一步,也是至关重要的一步。数据加载的质量会直接影响后续的索引构建、检索效果和最终的生成质量。

文档加载器负责将各种格式的非结构化文档(如 PDF、Word、Markdown、HTML 等)转换为程序可以处理的结构化数据。

文档加载器主要功能:

  • 文档格式解析:将不同格式的文档(如 PDF、Word、Markdown 等)解析为文本内容。
  • 元数据提取:在解析文档内容的同时,提取相关的元数据信息,如文档来源、页码等。
  • 统一数据格式:将解析后的内容转换为统一的数据格式,便于后续处理。

主流文档加载器

工具名称 特点 适用场景 性能表现
PyMuPDF4LLM PDF→Markdown 转换,OCR+表格识别 科研文献、技术手册 开源免费,GPU 加速
TextLoader 基础文本文件加载 纯文本处理 轻量高效
DirectoryLoader 批量目录文件处理 混合格式文档库 支持多格式扩展
Unstructured 多格式文档解析 PDF、Word、HTML 等 统一接口,智能解析
FireCrawlLoader 网页内容抓取 在线文档、新闻 实时内容获取
LlamaParse 深度 PDF 结构解析 法律合同、学术论文 解析精度高,商业 API
Docling 模块化企业级解析 企业合同、报告,支持 PDF、DOCX、XLSX、HTML、图片等 IBM 生态兼容
Marker PDF→Markdown,GPU 加速 科研文献、书籍 专注 PDF 转换
MinerU 多模态集成解析 学术文献、财务报表 集成 LayoutLMv3+YOLOv8

Unstructured 简介

Unstructured 是一个专业的文档处理库,专门设计用于 RAG 和 AI 微调场景的非结构化数据预处理。提供了统一的接口来处理多种文档格式,是目前最受欢迎的文档加载解决方案之一。

核心优势

格式支持广泛

  • 支持多种文档格式:PDF、Word、Excel、HTML、Markdown 等
  • 统一的 API 接口,无需为不同格式编写不同代码

智能内容解析

  • 自动识别文档结构:标题、段落、表格、列表等
  • 保留文档元数据信息
支持的格式类型

Unstructured 能够识别和分类以下文档元素:

元素类型 描述
Title 文档标题
NarrativeText 由多个完整句子组成的正文文本,不包括标题、页眉、页脚和说明文字
ListItem 列表项,属于列表的正文文本元素
Table 表格
Image 图像元数据
Formula 公式
Address 物理地址
EmailAddress 邮箱地址
FigureCaption 图片标题/说明文字
Header 文档页眉
Footer 文档页脚
CodeSnippet 代码片段
PageBreak 页面分隔符
PageNumber 页码
UncategorizedText 未分类的自由文本
CompositeElement 分块处理时产生的复合元素(由一个或多个连续的文本元素组合而成。例如,多个列表项可能会被组合成一个单独的块。)
安装与使用

安装:

uv add "unstructured[all-docs]"

安装 Popplerhttps://github.com/oschwartz10612/poppler-windows/releases/,解压后将 /bin 加入到 PATH 中。

安装 TesseractIndex of /tesseract,安装完成后将安装路径加入到 PATH 中。

安装 nltk_datahttps://gitee.com/qwererer2/nltk_data/tree/gh-pages,下载 packages 文件夹,里面的所有文件夹放到 nltk_data 文件夹中(使用 print(nltk.find(".")) 可以找到路径)

可能存在问题:File is not a zip file(应该是 zip 文件损坏了)

解决方法:NLTK Data 下载 punktpunkt_tab 的 zip,覆盖 nltk_data\tokenizers 里面的,顺便解压这两 个 zip

使用:

from unstructured.partition.auto import partition

# PDF 文件路径
pdf_path = "../../data/C2/pdf/rag.pdf"

# 使用 Unstructured 加载并解析 PDF 文档
elements = partition(
filename=pdf_path,
content_type="application/pdf"
)

# 打印解析结果
print(f"解析完成: {len(elements)} 个元素, {sum(len(str(e)) for e in elements)} 字符")

# 统计元素类型
from collections import Counter
types = Counter(e.category for e in elements)
print(f"元素类型: {dict(types)}")

# 显示所有元素
print("\n所有元素:")
for i, element in enumerate(elements, 1):
print(f"Element {i} ({element.category}):")
print(element)
print("=" * 60)

partition 函数参数解析:

  • filename: 文档文件路径,支持本地文件路径
  • content_type: 可选参数,指定 MIME 类型(如 “application/pdf”),可绕过自动文件类型检测
  • file: 可选参数,文件对象,与 filename 二选一使用
  • url: 可选参数,远程文档 URL,支持直接处理网络文档
  • include_page_breaks: 布尔值,是否在输出中包含页面分隔符
  • strategy: 处理策略,可选 “auto”、”fast”、”hi_res” 等
  • encoding: 文本编码格式,默认自动检测

partition 函数使用自动文件类型检测,内部会根据文件类型路由到对应的专用函数(如 PDF 文件会调用 partition_pdf)。如果需要更专业的 PDF 处理,可以直接使用 from unstructured.partition.pdf import partition_pdf,它提供更多 PDF 特有的参数选项,如 OCR 语言设置、图像提取、表格结构推理等高级功能,同时性能更优。

Docling

安装与使用
uv add docling

另外还需自己下载模型,因为官方代码会自动下载 Docling 和 OCR 模型,但由于国内 HuggingFace 不能直接访问,因此下载会失败,无法执行代码。

找个地方 clone 一下:

git clone https://www.modelscope.cn/ms-agent/docling-models.git

然后把..\docling-models\model_artifacts\layout里面的内容剪切到docling-models下,以及把 MasonYyp/docling-modelsEasyOcr 文件夹下载放进去。

使用:

from docling.document_converter import DocumentConverter, PdfFormatOption
from docling.datamodel.pipeline_options import PdfPipelineOptions
from docling.datamodel.base_models import InputFormat

artifacts_path = "../../../docling-models"
pipeline_options = PdfPipelineOptions(artifacts_path=artifacts_path)

# 初始化文档转换器
converter = DocumentConverter(
format_options={
InputFormat.PDF: PdfFormatOption(pipeline_options=pipeline_options)
}
)

pdf_result_docling = converter.convert(pdf_path)

向量嵌入

向量嵌入(Embedding)是一种将真实世界中复杂、高维的数据对象(如文本、图像、音频、视频等)转换为数学上易于处理的、低维、稠密的连续数值向量的技术。

Embedding 过程示意图

嵌入是一个由浮点数组成的向量(列表)。两个向量之间的 距离 衡量它们的相关性。距离小表明相关性高,距离大表明相关性低。

向量空间的语义表示

Embedding 的真正威力在于,它产生的向量不是随机数值的堆砌,而是对数据 语义 的数学编码。

  • 核心原则:在 Embedding 构建的向量空间中,语义上相似的对象,其对应的向量在空间中的距离会更近;而语义上不相关的对象,它们的向量距离会更远。

  • 关键度量:我们通常使用以下数学方法来衡量向量间的“距离”或“相似度”:

    • **余弦相似度 (Cosine Similarity)**:计算两个向量夹角的余弦值。值越接近 1,代表方向越一致,语义越相似。这是最常用的度量方式。

    $$
    \text{cosine similarity} = \frac{\vec{A} \cdot \vec{B}}{||\vec{A}||\space ||\vec{B}||}
    $$

    • **点积 (Dot Product)**:计算两个向量的乘积和。在向量归一化后,点积等价于余弦相似度。
    • **欧氏距离 (Euclidean Distance)**:计算两个向量在空间中的直线距离。距离越小,语义越相似。

嵌入在 RAG 中的作用

RAG 的“检索”环节通常以基于 Embedding 的语义搜索为核心。通用流程如下:

  1. 离线索引构建:将知识库内文档切分后,使用 Embedding 模型将每个文档块(Chunk)转换为向量,存入专门的向量数据库中。
  2. 在线查询检索:当用户提出问题时,使用 同一个 Embedding 模型 将用户的问题也转换为一个向量。
  3. 相似度计算:在向量数据库中,计算“问题向量”与所有“文档块向量”的相似度。
  4. 召回上下文:选取相似度最高的 Top-K 个文档块,作为补充的上下文信息,与原始问题一同送给大语言模型(LLM)生成最终答案。

多模态嵌入

待补充

向量数据库

当向量数量从几百个增长到数百万甚至数十亿时,一个核心问题随之而来:如何快速、准确地从海量向量中找到与用户查询最相似的那几个?

向量数据库的核心价值在于其 高效处理海量高维向量 的能力。其主要功能可以概括为以下几点:

  1. 高效的相似性搜索:这是向量数据库最重要的功能。它利用专门的索引技术(如 HNSW, IVF),能够在数十亿级别的向量中实现 毫秒级的近似最近邻(ANN)查询,快速找到与给定查询最相似的数据。
  2. 高维数据存储与管理:专门为存储高维向量(通常维度成百上千)而优化,支持对向量数据进行增、删、改、查等基本操作。
  3. 丰富的查询能力:除了基本的相似性搜索,还支持按标量字段过滤查询(例如,在搜索相似图片的同时,指定 年份 > 2023)、范围查询和聚类分析等,满足复杂业务需求。
  4. 可扩展与高可用:现代向量数据库通常采用 分布式架构,具备良好的水平扩展能力和容错性,能够通过增加节点来应对数据量的增长,并确保服务的稳定可靠。
  5. 数据与模型生态集成:与主流的 AI 框架(如 LangChain, LlamaIndex)和机器学习工作流无缝集成,简化了从模型训练到向量检索的应用开发流程。

向量数据库 vs 传统数据库

传统的数据库(如 MySQL)擅长处理结构化数据的精确匹配查询(例如,WHERE age = 25),但它们并非为处理高维向量的相似性搜索而设计的。在庞大的向量集合中进行暴力、线性的相似度计算,其计算成本和时间延迟无法接受。向量数据库 (Vector Database) 很好的解决了这一问题,它是一种专门设计用于高效存储、管理和查询高维向量的数据库系统。在 RAG 流程中,它扮演着“知识库”的角色,是连接数据与大语言模型的关键桥梁。

维度 向量数据库 传统数据库 (RDBMS)
核心数据类型 高维向量 (Embeddings) 结构化数据 (文本、数字、日期)
查询方式 相似性搜索 (ANN) 精确匹配
索引机制 HNSW, IVF, LSH 等 ANN 索引 B-Tree, Hash Index
主要应用场景 AI 应用、RAG、推荐系统、图像/语音识别 业务系统 (ERP, CRM)、金融交易、数据报表
数据规模 轻松应对千亿级向量 通常在千万到亿级行数据,更大规模需复杂分库分表
性能特点 高维数据检索性能极高,计算密集型 结构化数据查询快,高维数据查询性能呈指数级下降
一致性 通常为最终一致性 强一致性 (ACID 事务)

主流向量数据库

向量数据库分类图

Pinecone 是一款完全托管的向量数据库服务,采用 Serverless 架构设计。它提供存储计算分离、自动扩展和负载均衡等企业级特性,并保证 99.95%的 SLA。Pinecone 支持多种语言 SDK,提供极高可用性和低延迟搜索(< 100ms),特别适合企业级生产环境、高并发场景和大规模部署。

Milvus 是一款开源的分布式向量数据库,采用分布式架构设计,支持 GPU 加速和多种索引算法。它能够处理亿级向量检索,提供高性能 GPU 加速和完善的生态系统。Milvus 特别适合大规模部署、高性能要求的场景,以及需要自定义开发的开源项目。

Qdrant 是一款高性能的开源向量数据库,采用 Rust 开发,支持二进制量化技术。它提供多种索引策略和向量混合搜索功能,能够实现极高的性能(RPS > 4000)和低延迟搜索。Qdrant 特别适合性能敏感应用、高并发场景以及中小规模部署。

Weaviate 是一款支持 GraphQL 的 AI 集成向量数据库,提供 20+AI 模块和多模态支持。它采用 GraphQL API 设计,支持 RAG 优化,特别适合 AI 开发、多模态处理和快速开发场景。Weaviate 具有活跃的社区支持和易于集成的特点。

Chroma 是一款轻量级的开源向量数据库,采用本地优先设计,无依赖。它提供零配置安装、本地运行和低资源消耗等特性,特别适合原型开发、教育培训和小规模应用。Chroma 的部署简单,适合快速原型开发。

选择建议

  • 新手入门/小型项目:从 ChromaDBFAISS 开始是最佳选择。它们与 LangChain/LlamaIndex 紧密集成,几行代码就能运行,且能满足基本的存储和检索需求。
  • 生产环境/大规模应用:当数据量超过百万级,或需要高并发、实时更新、复杂元数据过滤时,应考虑更专业的解决方案,如 MilvusWeaviate 或云服务 Pinecone

Weaviate 安装与使用

安装

安装(需要 Docker):

docker pull semitechnologies/weaviate:latest

新建一个 docker-compose.yml

---
services:
weaviate:
command:
- --host
- 0.0.0.0
- --port
- '8080'
- --scheme
- http
image: semitechnologies/weaviate:latest
container_name: weaviate
ports:
- 8080:8080
- 50051:50051
volumes:
- weaviate_data:/var/lib/weaviate
restart: on-failure:0
environment:
QUERY_DEFAULTS_LIMIT: 25
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true'
PERSISTENCE_DATA_PATH: '/var/lib/weaviate'
ENABLE_API_BASED_MODULES: 'true'
CLUSTER_HOSTNAME: 'node1'
volumes:
weaviate_data:
...

然后运行:

docker compose up -d

访问 http://localhost:8080/v1/docs 验证是否正常运行。

然后安装客户端:

pip install -U weaviate-client

测试连接:

import weaviate

client = weaviate.connect_to_local()
print(client.is_ready()) # Should print: `True`
client.close() # Free up resources
创建集合
def create_collection(client: weaviate.WeaviateClient, collection_name: str):
"""
创建集合
:param client: Weaviate 客户端
:param collection_name: 集合名称
"""
collection_obj = {
"class": collection_name,
"description": "A collection for product information",
"vectorizer": "none", # 假设你会上传自己的向量
"vectorIndexType": "hnsw",
"vectorIndexConfig": {
"distance": "cosine",
"efConstruction": 200,
"maxConnections": 64
},
"properties": [
{
"name": "text",
"description": "The text content",
"dataType": ["text"],
"tokenization": "word",
"indexFilterable": True,
"indexSearchable": True
}
]
}
try:
client.collections.create_from_dict(collection_obj)
print(f"创建集合 '{collection_name}' 成功.")
except weaviate.exceptions.UnexpectedStatusCodeException as e:
print(f"创建集合异常: {e}")
插入数据
def save_documents(client: weaviate.WeaviateClient, collection_name: str, documents: list, embeddings: list):
"""
向集合中插入数据
:param client: Weaviate 客户端
:param collection_name: 集合名称
:param documents: 文档列表
:param embeddings: 文档对应的向量列表
"""
collection = client.collections.get(collection_name)
for i in range(len(documents)):
content = documents[i]
vector = embeddings[i]
properties = {
"text": content
}
try:
uuid = collection.data.insert(properties=properties, vector=vector)
print(f"文档添加内容: {content[:30]}..., uuid: {uuid}")
except Exception as e:
print(f"添加文档异常: {e}")
查询数据
def query_vector_collection(client: weaviate.WeaviateClient, collection_name: str, query: str, k: int) -> list:
"""
从集合中查询数据
:param client: Weaviate 客户端
:param collection_name: 集合名称
:param query: 查询的【向量】
:param k: 返回的结果数量
:return: 查询结果列表
"""

collection = client.collections.get(collection_name)
response = collection.query.near_vector(
near_vector=query,
limit=k
)
documents = [res.properties['text'] for res in response.objects]
return documents

参考链接

All-in-RAG | 大模型应用开发实战:RAG 技术全栈指南

向量数据库 Weaviate 使用教程(安装+使用)-CSDN 博客

【RAG 落地利器】向量数据库 Weaviate 部署与使用教程-CSDN 博客

安装 nltk 库及 nltk_data 数据包_nltk data-CSDN 博客

https://github.com/langchain-ai/langchain/discussions/8212

安装和使用 docling-CSDN 博客

使用 - Docling 文档