11.1 RAG 概念
RAG 的全称是 Retrieval-Augmented Generation(检索增强生成)。RAG(检索增强生成)是一项为大语言模型安装“外接大脑”的技术,使其能够生成更准确、更及时的回答。它的价值在于巧妙地结合了信息检索的准确性和大语言模型的强大生成能力。
RAG核心思想是让大模型在回答问题前,先从您提供的外部知识库(如文档、数据库)中检索相关信息,再基于这些信息生成答案,从而显著提升回答的准确性和可靠性。其核心流程可以清晰地划分为两个主要阶段:数据预处理(构建知识库)和实时问答。
RAG技术主要为了解决大语言模型固有的几个核心痛点:
知识过时与幻觉:大模型的训练数据有截止日期,对于新事件无能为力,并且在不确定时可能“自信地”编造答案。RAG通过提供实时、准确的外部知识,有效对抗了模型的“幻觉”问题。专业领域知识不足:通用大模型在面对医疗、法律、金融等高度专业领域的问题时,可能缺乏深度。RAG可以为其接入专业的领域知识库,提供权威答案。成本与透明度:相比为了学习新知识而重新训练模型,更新RAG外部知识库的成本要低得多。同时,RAG系统可以提供答案的来源依据,增强了答案的可验证性和可信度。上下文有限:无法一次性加载所有的语料库信息,然后投喂给大模型,因为大模型有上下文窗口限制。
11.2.场景案例
本场景将以文本型PDF作为素材,对文本型PDF进行加载、解析、文本分隔、向量化与存储、文档时的快速检索并结合大模型,生成合适的结果。
11.2.1. 依赖包安装
当前的场景需要安装pdf读取器pypdf、文本向量化ollama模型nomic-embed-text、模型向量数据库Chroma依赖:
pip install pypdf
pip install langchain-chroma
ollama pull nomic-embed-text
说明:
是一个纯 Python 编写的 PDF 处理库,专注于 PDF 的基础操作和简单文本提取,无法胜任对复杂布局(如多栏排版、表格)的文本提取。nomic-embed-text:
pypdf
nomic-embed-text是一个高效且功能强大的文本嵌入模型,它的核心作用是将文本(如单词、句子或文档)转换成一组数值向量(即嵌入向量)。这个过程就像是给文本内容制作了一个独特的“数字指纹”,计算机通过分析和比较这些“指纹”,能够理解文本的语义信息。非常适合:
🔍 语义搜索与智能检索:与传统基于关键词匹配的搜索不同,语义搜索能够理解用户的查询意图。例如,搜索“省电的手机”,系统也能找到提到“超长续航”的文档。这在构建企业知识库、智能问答系统中非常关键。📊文本分类与聚类分析:该模型可以用于对大量文本进行自动归类(如新闻分类、情感分析)或发现文本集合中的自然分组(如从用户反馈中自动归纳出主要话题),帮助高效地分析和组织信息。🤖 增强RAG系统:RAG(检索增强生成)是当前大模型应用的热点技术。可以作为RAG系统的“检索器”核心,先从海量知识库中精准找到与问题最相关的信息,再提供给大语言模型来生成准确、有依据的答案,有效缓解模型的“幻觉”问题。📄 多格式文档处理:结合相应的工具库,它可以处理PDF、Word、HTML等多种格式的文档,将其中的文本内容提取出来并向量化,从而实现对非结构化文档的智能化管理。
nomic-embed-text
langchain-chroma:LangChain 框架的强大能力与轻量级向量数据库 Chroma 的高效性结合了起来。其核心应用场景是任何需要让大语言模型(LLM)能够“理解”并处理您自有知识库的任务。
11.2.2 代码实现
代码实现将分为2个部分:数据预处理与实时问答
11.2.2.1.数据预处理
脚本文件名称:pdf_indexing.py

数据预处理脚本见下:
"""
本脚本实现对pdf的读取,然后向量化存储。将按照以下步骤执行:
1. 读取PDF,获取文本文档;
2. 分隔文本;
3. 文本向量化;
4. 文本向量存储;
"""
# 第一步:读取PDF
"""
langchain的加载器有很多,都是在langchain-community包中,都是在langchain_community.document_loaders这个路径下
"""
from langchain_community.document_loaders import PyPDFLoader
#示例化pdfloader
loader = PyPDFLoader("httpclient-tutorial.pdf")
#加载pdf
docs = loader.load()
# 第二步:分隔文本
"""
文本分隔,将采用langchain中的RecursiveCharacterTextSplitter分割器。
RecursiveCharacterTextSplitter是 LangChain 中一个非常核心且常用的文本分割工具,
它的主要作用是将长文档智能地分割成大小合适的文本块,以便后续处理,比如输入给大语言模型或存入向量数据库。
"""
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, #每个文本块的最大长度
chunk_overlap=200,#文本块之间的重叠长度,能够保证语义的连续性
)
split_docs = text_splitter.split_documents(docs)
print(f"分割后的文本块数量:{len(split_docs)}")
# 第三步:文本向量化
"""
文本向量化将采用本地ollama nomic-embed-text向量模型
embeddings = OllamaEmbeddings(model="nomic-embed-text")
embeddings核心有2个方法:
1.embed_query: 用于处理单个查询文本(如用户提问)。
2.embed_documents: 用于批量处理多个文档文本。
"""
from langchain_ollama import OllamaEmbeddings
embeddings = OllamaEmbeddings(model="nomic-embed-text")
split_page_docs = [doc.page_content for doc in split_docs]
# vectors = embeddings.embed_documents(split_page_docs)
# 第四步:文本向量存储
"""
将第三步处理好的文本向量化的结果存储到Chroma中。
在Chroma内部会执行embeddings.embed_documents(split_page_docs),所以第三步中的vectors = embeddings.embed_documents(split_page_docs)不需要写
"""
from langchain_chroma import Chroma
vector_store = Chroma.from_texts(
texts= split_page_docs,
embedding=embeddings,
collection_name="ai_httpclient_tutorial",
persist_directory="./chroma_langchain_db" # 持久化到本地目录
)
print("向量存储完成")
11.2.2.2.实时问答
创建实时问答脚本semantic-query.py,脚本内容见下:
"""
根据已向量化数据,进行问答查询
"""
from langchain.agents import create_agent
from langchain.tools import tool
#第一步构建向量化模型
from langchain_ollama import OllamaEmbeddings
embeddings = OllamaEmbeddings(model="nomic-embed-text")
#第二步构建向量数据库
from langchain_chroma import Chroma
vector_store = Chroma(
collection_name="ai_httpclient_tutorial",
embedding_function=embeddings,
persist_directory="./chroma_langchain_db" # 持久化到本地目录
)
#第三步构建大模型
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
load_dotenv()
model = init_chat_model(
"deepseek:deepseek-chat",
temperature=0.1,
max_retries=2,
timeout=None
)
# 第四步构建向量检索工具
@tool(response_format="content_and_artifact")
def query_vector_store(query: str) -> str:
"""
使用向量数据库进行查询
"""
result_docs = vector_store.similarity_search( query, k=3)
content = "
".join([f"{doc.page_content}" for doc in result_docs])
return content,result_docs
# 第五步构建Agent
system_prompt = """
你是一个知识问答助手,请根据提供的内容回答问题。
"""
agent = create_agent(model, [query_vector_store],system_prompt= system_prompt)
# 第六步进行问答
query = "httpClient是什么?"
result = agent.invoke({
"messages":[
{"role": "user", "content": query}
]
})
print(result)
finalMessage = result["messages"][-1]
print(finalMessage.content)
说明:
自该脚本中向量嵌入模型还是与知识向量化存储保持一致,采用什么样的嵌入模型进行数据向量化进行存储,在数据查询的时候也需要采用同一个嵌入模型进行数据的向量匹配查询。构建向量库对象,所采用的配置需要与写入时的配置保持一致,不然无法读取相关知识信息。RAG的核心思想是先检索本地知识,后通过大模型生成,所以选择采用RetrievalQA组件。在RetrievalQA对象构建中,需要传递检索器(retriever)。检索器是构建 RAG 系统的核心引擎,负责从知识库中快速准确地找到与问题最相关的信息。其实现方式多样,核心目标是平衡检索精度、召回率、速度与资源消耗。目前检索器的类型有:向量检索器、BM25检索器、多向量检索器、上下文压缩检索器等等,在该案例中基于向量数据库采用向量检索器。向量检索器的创建可以通过向量数据库对象的方法创建。
.as_retriever()
执行效果:

11.3. 知识补充
11.3.1. 向量数据库
向量数据库作为管理和检索高维向量数据的专用数据库,已成为支撑语义搜索、推荐系统和大模型应用的关键基础设施。向量数据库有很多种,下面将通过表格的方式列举常见的向量数据库。
| 数据库名称 | 类型/模式 | 核心特点 | 理想应用场景 |
|---|---|---|---|
| Milvus | 开源分布式 | 处理超大规模数据(十亿级以上),扩展性极强,支持多种索引算法和GPU加速 | 企业级大规模图像/视频检索、高并发推荐系统、需要处理海量向量的NLP应用 |
| Pinecone | 全托管云服务 | 开箱即用,无需管理基础设施,自动扩缩容,低延迟 | 快速原型验证、生产环境实时推荐系统、语义搜索,适合追求开发效率和稳定服务的团队 |
| Chroma | 开源嵌入式 | 轻量级,API简单易用,与AI框架(如LangChain)集成度高,适合本地开发和实验 | RAG系统、聊天机器人、文档问答等中小规模项目或快速原型开发 |
| Qdrant | 开源/云服务 | Rust编写,性能优异,支持丰富的数据类型和过滤查询,兼顾性能与功能 | 对性能和过滤查询有较高要求的实时搜索、边缘部署场景 |
| Weaviate | 开源/云服务 | 支持混合搜索(向量+关键字),内置模块化设计,集成知识图谱功能 | 需要结合语义和关键字搜索的应用、知识图谱构建、复杂数据集成 |
| PgVector | PostgreSQL扩展 | 作为PostgreSQL插件,可直接在熟悉的关系型数据库中使用SQL进行向量操作 | 项目已用PostgreSQL,需快速增加向量搜索功能;处理混合(关系型+向量)数据查询 |
| FAISS | 开源库(非数据库) | Meta开源的高效相似性搜索库,专注索引和搜索算法,性能卓越 | 学术研究、嵌入到应用程序或服务中处理大规模向量相似性计算,通常需自行构建服务层 |
针对上面列举的向量数据库,下面将表格的形式展示各自的优缺点:
| 数据库 | 优点 | 缺点 |
|---|---|---|
| Milvus | – 开源免费,可自行部署控制成本 – 强大的分布式架构,支持水平扩展,可处理海量数据 – 活跃的开源社区和丰富的文档 | – 自托管环境下,分布式架构的部署和运维非常复杂,对团队技术要求高 – 学习曲线相对陡峭 |
| Pinecone | – 全托管服务,极大简化运维,开发者可专注于业务 – 高性能,优化良好,低延迟 – 高可用性 | – 作为商业托管服务,费用通常高于自托管方案,尤其在高并发场景下 – 无法在本地或私有化环境中部署,依赖云服务 |
| Chroma | – 极其易于上手,提供简单的Python/JS API,适合快速入门 – 轻量级,可作为嵌入式数据库使用 – 与LangChain等AI框架集成度高 | – 主要适用于中小规模数据,在大规模生产环境下性能可能受限 – 功能相对单一,缺乏高级数据库管理特性 |
| Qdrant | – Rust实现,性能出色,资源利用率高 – 在API一致性、查询灵活性和易用性间有良好平衡 – 支持云服务和本地部署 | – 相比Milvus等,其生态系统和社区规模仍在成长中 |
| Weaviate | – 混合搜索能力突出,结合向量与关键字检索 – 模块化设计,易于与不同AI模型集成 – 提供GraphQL接口,查询灵活 | – 在超大规模数据集上,纯向量搜索性能可能略逊于专用数据库 – 模块化设计可能增加初学者的配置复杂度 |
| PgVector | – 与PostgreSQL无缝集成,无需引入新数据库系统 – 可利用现有SQL技能和生态工具,学习成本低 – 支持复杂SQL查询,兼容ACID特性 | – 在处理十亿级以上向量的超大规模数据时,性能与专用向量数据库有差距 – 索引类型相对有限 |
| FAISS | – 专注于相似性搜索算法,在此领域性能卓越 – 支持GPU加速,计算速度快 | – 是一个算法库而非完整数据库,不提供服务器端功能、元数据过滤或持久化管理 – 使用门槛较高,需自行处理许多底层细节 |
11.3.2.检索器
在 LangChain 中,**检索器(Retriever)**是一个核心组件,它充当着智能信息桥梁的角色,专门负责从外部知识库(如文档集合、数据库)中,为用户的查询快速查找并召回最相关的信息片段。

为了让你快速建立整体认知,下表概括了 LangChain 中主要检索器的类型及其核心特点。
| 检索器类型 | 核心原理 | 适用场景 |
|---|---|---|
| 向量检索器 | 基于语义相似度进行检索,将查询和文档转换为向量后计算相似度。 | 最常用,适用于开放领域问答、语义搜索等需要理解语义的场景。 |
| 关键字检索器(如BM25) | 基于关键词匹配(如词频)进行检索,不依赖语义理解。 | 资源受限、强调关键词精确匹配或快速轻量级搜索的场景。 |
| 多查询检索器 | 利用大语言模型为原始查询生成多个相关问题变体,从不同角度检索以提升召回率。 | 用户查询表述模糊或需要多角度理解的复杂问题。 |
| 自查询检索器 | 自动从自然语言问题中解析出元数据过滤条件(如日期、作者),实现更精准的过滤检索。 | 需要根据来源、时间等属性对结果进行筛选的查询。 |
| 上下文压缩检索器 | 先进行初步检索,然后使用模型对结果进行精炼和去冗余,只保留最相关的核心信息。 | 当初步检索结果冗长,需要为生成模型提供更精炼、高质量上下文的场景。 |
| 集成检索器 | 混合多种检索算法(如向量检索 + BM25),综合不同策略的优势,通过加权融合结果。 | 需要高召回率的复杂场景,结合语义和关键词匹配的优点。 |
11.3.2.1 向量检索器
向量检索器也叫基本的检索器,本案例将以FAISS进行向量化存储。
依赖安装
pip install faiss-cpu #这个是基于CPU进行计算存储,如果有GPU,可以下载安装faiss-gpu
案例文件名称:embeding-retriever.py
代码如下:
"""
检索器练习:
向量检索器(采用FAISS向量数据库)
操作步骤:
1.加载文本;
2.文本分隔
3.文本向量化后存储
4.基本检索器查询
"""
# 第一步:加载文本
from langchain_community.document_loaders import TextLoader
loader = TextLoader("embeding_source.txt")
docs = loader.load()
print(docs)
print(docs[0].page_content)
# 第二步:文本分隔
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
)
split_docs = text_splitter.split_documents(docs)
# 第三步:向量化文本
from langchain_ollama import OllamaEmbeddings
from langchain_community.vectorstores import FAISS
embeddings = OllamaEmbeddings(model="nomic-embed-text")
vector_store = FAISS.from_documents(split_docs, embeddings)
vector_store.save_local("./faiss_langchain_db")
print("向量存储完成")
# 第四步:查询向量数据库
# 创建向量检索器
faiss_retriever = vector_store.as_retriever(
search_kwargs={"k": 3} # 检索出相似度比较高的top 3的文档
)
query = "什么是DeepSeek?"
result = faiss_retriever.invoke( query)
print(f"答案:{result}")
效果如下:

11.3.2.2. 关键词BM25检索器
bm25检索器是根据关键词进行检索,如果匹配不到关键词,则会将不符合条件的文档检索出来。单纯的关键词检索在处理语义模糊或需要深层理解的查询时存在局限。
依赖安装
pip install rank_bm25
案例文件名称:bm25-retriever.py
代码如下:
"""
BM25检索器案例
需要安装依赖:pip install rank_bm25
bm25检索器是根据关键词进行检索,如果匹配不到关键词,则会将不符合条件的文档检索出来。
单纯的关键词检索在处理语义模糊或需要深层理解的查询时存在局限。
"""
from langchain_community.retrievers import BM25Retriever
from langchain_core.documents import Document
# 准备文档数据
documents = [
Document(page_content="LangChain 是一个用于构建 LLM 应用的框架。"),
Document(page_content="RAG 技术结合了检索与生成。"),
Document(page_content="BM25 是一种用于信息检索的经典算法。"),
Document(page_content="向量数据库可以高效进行相似性搜索。"),
Document(page_content="大型语言模型通常基于Transformer架构。"),
Document(page_content="深度学习是机器学习的一个子领域。"),
Document(page_content="Hugging Face 提供了丰富的预训练模型。")
]
retriever = BM25Retriever.from_documents(documents)
retriever.k = 2
# 执行查询
query = "LangChain"
results = retriever.invoke(query)
# 查看结果
for doc in results:
print(doc.page_content)
执行效果如下:














暂无评论内容