纲要
- RAG核心概念
- 检索增强生成的原理与价值
- 解决大模型数据时效性与领域知识缺失的关键技术
- 数据预处理全流程
Document Loader:从多种数据源加载原始文档Text Splitter:将大文档切分为语义连贯的片段Embedding Model:将文本片段转换为向量Vector Store:持久化存储向量并支持相似性检索
- LangChain实现组件
TextLoader、RecursiveCharacterTextSplitterFakeEmbeddings与Chroma向量数据库
- 完整可运行代码:从文本到向量存储的端到端示例
引言
大语言模型虽然具备广泛的通用知识,但普遍存在两个固有局限:一是知识截止日期(Knowledge Cutoff Date)问题,模型无法获知训练数据截止时间之后的最新信息;二是领域知识盲区,对于企业内部文档、专业法规等非公开或垂直领域知识,模型难以给出准确回答。检索增强生成通过将外部知识库与模型生成能力相结合,在回答用户问题前先从知识库中检索相关文档片段,并将其作为上下文注入提示词,从而显著提升答案的准确性、时效性与可追溯性。
本文聚焦RAG流水线的第一环——数据预处理,介绍如何利用LangChain将原始文档转化为可供语义搜索的向量存储,并提供可直接运行的代码示例。
RAG基本原理
RAG的核心理念可概括为“先检索,后生成”。当用户提出问题时,系统执行以下步骤:
- 向量化用户问题:使用与知识库相同的嵌入模型将问题转换为向量。
- 向量相似性搜索:在向量数据库中检索与问题向量最接近的若干文档片段。
- 构建增强提示词:将检索到的文档片段与原始问题拼接为最终的模型输入。
- 调用大模型生成:模型基于提供的上下文生成可靠答案。
上述流程顺畅运转的前提是知识库的数据预处理——将原始文档加工成适合向量检索的格式,这也是本文的核心内容。
数据预处理四步骤
一个典型的RAG数据预处理流水线包含四个关键环节:加载 → 切片 → 嵌入 → 存储。
文档加载
LangChain提供了多种内置加载器,支持TXT、PDF、Markdown、CSV、HTML、Notion等主流格式。所有加载器的输出统一为Document对象,包含page_content(文本内容)和metadata(元数据)两个字段。TextLoader是最基础的文本文件加载器,默认将整个文件作为一个Document返回。
文本切片
大语言模型的上下文窗口有限,过长的文档无法直接输入模型,也不利于精确检索——过大的文本块会降低检索的语义粒度。切片器负责将长文本分割为较小的语义块。RecursiveCharacterTextSplitter是LangChain官方推荐的最常用的文本分割器。它通过递归地尝试多个分隔符(段落、句子、词等边界)来切分文本,尽量保持语义单元的完整性。
向量化(嵌入)
嵌入模型将文本片段映射为高维空间中的稠密向量,语义相近的文本在向量空间中距离更近。LangChain支持OpenAI、HuggingFace以及各类国产嵌入模型。为便于本地测试和流程验证,LangChain提供了FakeEmbeddings类,可生成随机向量模拟嵌入过程,无需任何外部API密钥。生产环境需替换为真实的嵌入模型。
向量存储
将向量与对应的文本片段存入向量数据库,并提供快速的相似性搜索接口。Chroma是一个轻量级的开源向量数据库,专为LLM应用设计,非常适合本地开发和原型验证。Chroma支持内存模式和持久化模式。
LangChain数据预处理实战
以下代码演示从原始文本出发,完成加载、切片、嵌入和存储的完整流程。使用FakeEmbeddings模拟嵌入,无需任何外部API即可运行。
环境准备
安装所需依赖包:
pip install langchain langchain-core langchain-community langchain-text-splitters chromadb
注意:LangChain 0.2.0及以上版本对模块结构进行了重构,文档加载器需从
langchain_community导入,文本分割器需从langchain_text_splitters导入。Chroma的导入可通过langchain_community.vectorstores或独立的langchain_chroma包。
完整代码
from langchain_community.document_loaders import TextLoader
from langchain_community.embeddings import FakeEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_core.documents import Document
from langchain_text_splitters import RecursiveCharacterTextSplitter
# ---------- 1. 准备原始文本 ----------
# 模拟一段产品手册
raw_text = """
产品名称:智能温控水杯 X-200
功能描述:
1. 实时显示水温,精确到 ±0.5°C。
2. 支持手机 App 远程设置目标温度。
3. 内置 5000mAh 电池,可续航 48 小时。
4. 采用 316 不锈钢内胆,安全健康。
5. 具有过热保护功能,超过 99°C 自动断电。
使用说明:
- 首次使用前请用清水冲洗内胆。
- 长按电源键 3 秒开机,蓝牙自动配对。
- 可通过 App 调节温度范围:40°C~100°C。
注意事项:
- 请勿将杯体浸入水中清洗。
- 充电时请使用 5V/2A 适配器。
"""
# ---------- 2. 文档加载 ----------
# 从字符串直接构造 Document 列表(实际使用中可从文件加载)
docs = [Document(page_content=raw_text.strip(), metadata={"source": "产品手册"})]
print(f"加载文档数: {len(docs)}")
print(f"文档长度: {len(docs[0].page_content)} 字符")
# ---------- 3. 文本切片 ----------
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=100, # 每个块的最大字符数
chunk_overlap=20, # 相邻块之间的重叠字符数,保证语义连贯
separators=["\n\n", "\n", "。", ",", " ", ""] # 优先按段落、换行、标点切分
)
split_docs = text_splitter.split_documents(docs)
print(f"切片数量: {len(split_docs)}")
for i, doc in enumerate(split_docs):
print(f"切片 {i+1}: {doc.page_content[:50]}... (长度 {len(doc.page_content)})")
# ---------- 4. 向量化与存储 ----------
# 使用 FakeEmbeddings 模拟嵌入,维度设为 128
embeddings = FakeEmbeddings(size=128)
# 初始化 Chroma 向量库(默认存储于内存)
vectorstore = Chroma.from_documents(
documents=split_docs,
embedding=embeddings,
collection_name="product_manual"
)
print(f"向量库中文档数量: {vectorstore._collection.count()}")
# ---------- 5. 相似性检索测试 ----------
query = "如何给水杯充电?"
print(f"\n查询: {query}")
# 将查询向量化并搜索最相似的 2 个文档
results = vectorstore.similarity_search(query, k=2)
for idx, doc in enumerate(results):
print(f"检索结果 {idx+1}: {doc.page_content}")
运行结果解析
- 加载阶段:原始文本被封装为一个
Document对象,包含文本内容和元数据。 - 切片阶段:根据
chunk_size=100和chunk_overlap=20,文本被分割为多个语义块,每个块尽可能保持语义完整。 - 嵌入与存储阶段:
FakeEmbeddings生成随机向量(维度128)并存入Chroma向量库。实际应用中应替换为OpenAIEmbeddings或HuggingFaceEmbeddings。 - 检索测试阶段:对于“如何给水杯充电?”这一查询,向量搜索返回了包含充电相关信息的文档片段,验证了语义匹配的基本能力。
注意事项与最佳实践
- 切片大小选择:
chunk_size需根据嵌入模型的上下文窗口和业务需求调整。通用场景下500~1000字符通常效果较好,过小会丢失上下文,过大会降低检索精度。 - 重叠尺寸设置:保留
chunk_overlap可避免关键信息在切片边界被截断,一般设为chunk_size的10%~20%。 - 嵌入模型选型:中文场景推荐使用OpenAI的
text-embedding-ada-002或HuggingFace的bge-large-zh-v1.5,两者均具备良好的中文语义理解能力。 - 向量数据库选型:原型开发阶段可使用Chroma(内存模式)或FAISS;生产环境可考虑Pinecone、Weaviate或Milvus等具备分布式能力的方案。
- 导入路径注意事项:LangChain 0.2.0及以上版本中,
TextLoader应从langchain_community.document_loaders导入,RecursiveCharacterTextSplitter应从langchain_text_splitters导入,Chroma可从langchain_community.vectorstores或langchain_chroma导入。
总结
数据预处理是构建高质量RAG应用的基石。通过LangChain的文档加载器、文本分割器、嵌入模型和向量数据库四件套,开发者可以快速将海量非结构化文本转化为可供语义搜索的知识库。
本文的完整代码使用FakeEmbeddings模拟嵌入,无需任何外部API密钥,便于初学者在本地即刻体验RAG预处理全流程。
掌握这些基础后,下一步可将检索结果接入大模型,构建完整的智能问答系统。
397



被折叠的 条评论
为什么被折叠?



