
【Notes】RAG
RAG 简介
什么是 RAG?
RAG(Retrieval-Augmented Generation)是一种 融合信息检索与文本生成 的技术范式。其核心逻辑是:在大型语言模型(LLM)生成文本前,先通过检索机制从外部知识库中动态获取相关信息,并将检索结果融入生成过程,从而提升输出的准确性和时效性。
- 关键组件:
- 索引(Indexing) 📑:将非结构化文档(PDF/Word 等)分割为片段,通过嵌入模型转换为向量数据。
- 检索(Retrieval) 🔍️:基于查询语义,从向量数据库召回最相关的文档片段(Context)。
- 生成(Generation) ✨:将检索结果作为上下文输入 LLM,生成自然语言响应。
为什么要使用 RAG?
为了解决 LLM 的核心局限:知识局限、幻觉问题等。
问题 | RAG 的解决方案 |
---|---|
静态知识局限 | 实时检索外部知识库,支持动态更新 |
幻觉(Hallucination) | 基于检索内容生成,错误率降低 |
领域专业性不足 | 引入领域特定知识库(如医疗/法律) |
数据隐私风险 | 本地化部署知识库,避免敏感数据泄露 |
如何上手 RAG?
基础工具链选择
开发框架
- LangChain:提供预置 RAG 链(如 rag_chain),支持快速集成 LLM 与向量库
- LlamaIndex:专为知识库索引优化,简化文档分块与嵌入流程
向量数据库
- Milvus:开源高性能向量数据库
- FAISS:轻量级向量搜索库
- Pinecone:云服务向量数据库
四步构建最小可行系统
- 数据准备
- 格式支持:PDF、Word、网页文本等
- 分块策略:按语义(如段落)或固定长度切分,避免信息碎片化
- 索引构建
- 嵌入模型:选取开源模型(如 text-embedding-ada-002)或微调领域专用模型
- 向量化:将文本分块转换为向量存入数据库
- 检索优化
- 混合检索:结合关键词(BM25)与语义搜索(向量相似度)提升召回率
- 重排序(Rerank):用小模型筛选 Top-K 相关片段(如 Cohere Reranker)
- 生成集成
- 提示工程:设计模板引导 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]" |
安装 Poppler
:https://github.com/oschwartz10612/poppler-windows/releases/,解压后将 /bin
加入到 PATH 中。
安装 Tesseract
:Index of /tesseract,安装完成后将安装路径加入到 PATH 中。
安装 nltk_data
:https://gitee.com/qwererer2/nltk_data/tree/gh-pages,下载 packages
文件夹,里面的所有文件夹放到 nltk_data
文件夹中(使用 print(nltk.find("."))
可以找到路径)
可能存在问题:File is not a zip file(应该是 zip 文件损坏了)
解决方法:NLTK Data 下载 punkt
和 punkt_tab
的 zip,覆盖 nltk_data\tokenizers
里面的,顺便解压这两 个 zip
使用:
from unstructured.partition.auto import partition |
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-models 的 EasyOcr
文件夹下载放进去。
使用:
from docling.document_converter import DocumentConverter, PdfFormatOption |
向量嵌入
向量嵌入(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 的语义搜索为核心。通用流程如下:
- 离线索引构建:将知识库内文档切分后,使用 Embedding 模型将每个文档块(Chunk)转换为向量,存入专门的向量数据库中。
- 在线查询检索:当用户提出问题时,使用 同一个 Embedding 模型 将用户的问题也转换为一个向量。
- 相似度计算:在向量数据库中,计算“问题向量”与所有“文档块向量”的相似度。
- 召回上下文:选取相似度最高的 Top-K 个文档块,作为补充的上下文信息,与原始问题一同送给大语言模型(LLM)生成最终答案。
多模态嵌入
待补充
向量数据库
当向量数量从几百个增长到数百万甚至数十亿时,一个核心问题随之而来:如何快速、准确地从海量向量中找到与用户查询最相似的那几个?
向量数据库的核心价值在于其 高效处理海量高维向量 的能力。其主要功能可以概括为以下几点:
- 高效的相似性搜索:这是向量数据库最重要的功能。它利用专门的索引技术(如 HNSW, IVF),能够在数十亿级别的向量中实现 毫秒级的近似最近邻(ANN)查询,快速找到与给定查询最相似的数据。
- 高维数据存储与管理:专门为存储高维向量(通常维度成百上千)而优化,支持对向量数据进行增、删、改、查等基本操作。
- 丰富的查询能力:除了基本的相似性搜索,还支持按标量字段过滤查询(例如,在搜索相似图片的同时,指定
年份 > 2023
)、范围查询和聚类分析等,满足复杂业务需求。 - 可扩展与高可用:现代向量数据库通常采用 分布式架构,具备良好的水平扩展能力和容错性,能够通过增加节点来应对数据量的增长,并确保服务的稳定可靠。
- 数据与模型生态集成:与主流的 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 的部署简单,适合快速原型开发。
选择建议:
- 新手入门/小型项目:从
ChromaDB
或FAISS
开始是最佳选择。它们与 LangChain/LlamaIndex 紧密集成,几行代码就能运行,且能满足基本的存储和检索需求。 - 生产环境/大规模应用:当数据量超过百万级,或需要高并发、实时更新、复杂元数据过滤时,应考虑更专业的解决方案,如
Milvus
、Weaviate
或云服务Pinecone
。
Weaviate 安装与使用
安装
安装(需要 Docker):
docker pull semitechnologies/weaviate:latest |
新建一个 docker-compose.yml
:
|
然后运行:
docker compose up -d |
访问 http://localhost:8080/v1/docs
验证是否正常运行。
然后安装客户端:
pip install -U weaviate-client |
测试连接:
import weaviate |
创建集合
def create_collection(client: weaviate.WeaviateClient, collection_name: str): |
插入数据
def save_documents(client: weaviate.WeaviateClient, collection_name: str, documents: list, embeddings: list): |
查询数据
def query_vector_collection(client: weaviate.WeaviateClient, collection_name: str, query: str, k: int) -> list: |
参考链接
All-in-RAG | 大模型应用开发实战:RAG 技术全栈指南
向量数据库 Weaviate 使用教程(安装+使用)-CSDN 博客
【RAG 落地利器】向量数据库 Weaviate 部署与使用教程-CSDN 博客
安装 nltk 库及 nltk_data 数据包_nltk data-CSDN 博客