LangChain RAG 入门:从文档加载、切分到向量检索
大模型再强,也只「知道」训练数据里有的东西。你公司内部的文档、你的个人笔记,它一概不知。RAG(Retrieval-Augmented Generation,检索增强生成) 就是为此而生——不微调模型,把文档向量化,让 Agent 检索相关内容来回答。
这一篇讲的是 RAG 的**离线建库(索引)**这一半:怎么用 Document Loader 加载文档、用 Text Splitter 切分、用 Embedding 向量化、存进向量库并检索。这是所有 RAG 应用的地基。
一、先厘清:RAG 到底解决什么
1.1 普通模型的两段式不足
普通大模型只能回答训练数据里有的内容。私有文档它「不知道」,因为那些内容从没进过训练集。
1.2 RAG 的两阶段
- 离线阶段(索引):文档 → 切分小块 → Embedding 转向量 → 存入向量数据库
- 在线阶段(检索):用户提问 → 转向量 → 搜索最相似内容 → 作为上下文发给模型 → 模型回答
┌──────────────────────────────────────────────────────┐
│ 离线阶段(索引) │
│ 文档 → DocumentLoader → TextSplitter → Embedding │
│ ↓ │
│ VectorStore │
└──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
│ 在线阶段(检索) │
│ 用户提问 → Embedding → 相似度搜索 → 检索结果 │
│ ↓ │
│ 检索结果 + 用户问题 → 模型 → 回答 │
└──────────────────────────────────────────────────────┘
✅ 一句话总结:RAG 就是把「检索」和「生成」拼起来——先从私有文档里捞出相关内容,再让模型基于它回答。
二、环境准备
安装 RAG 相关依赖:
$ pip install langchain-deepseek langchain-chroma chromadb
| langchain-deepseek | 提供 OpenAI Embedding 模型 |
| langchain-chroma | Chroma 向量数据库的 LangChain 集成 |
| chromadb | Chroma 向量数据库(轻量级,适合入门) |
三、Document Loader——加载各类文档
实际项目里,文档可能是 PDF、网页、Markdown 文件等。LangChain 提供数十种加载器覆盖常见格式:
| TextLoader | .txt 文件 | langchain(内置) |
| PyPDFLoader | PDF 文件 | langchain-community + pypdf |
| WebBaseLoader | 网页 URL | langchain-community + beautifulsoup4 |
| CSVLoader | CSV 文件 | langchain-community |
| UnstructuredMarkdownLoader | Markdown 文件 | langchain-community + unstructured |
# 加载文本文件(内置,无需额外安装)
from langchain_community.document_loaders import TextLoader
loader = TextLoader("knowledge.txt", encoding="utf-8")
docs = loader.load()
print(f"加载了 {len(docs)} 个文档")
print(f"内容预览: {docs[0].page_content[:150]}…")
# 加载网页
# pip install langchain-community beautifulsoup4
from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader("https://www.runoob.com/python/python-tutorial.html")
docs = loader.load()
print(f"\\n网页内容: {docs[0].page_content[:150]}…")
四、Text Splitter——把文档切分
文档太长,如果不切分直接向量化,一个 chunk 会包含大量无关信息,检索时「宁大勿准」。切分策略直接决定 RAG 效果。
4.1 用 RecursiveCharacterTextSplitter
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 创建切分器
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每块最多 500 个字符
chunk_overlap=50, # 块之间重叠 50 个字符
separators=["\\n\\n", "\\n", "。", "!", "?", ";", ",", " ", ""],
# 优先按段落分割,然后是句子,最后是字符
)
# 示例文档
long_text = """菜鸟教程(RUNOOB)是一个免费的编程学习平台。
平台提供了丰富的编程语言教程,包括但不限于:
– Python 教程:从基础语法到数据分析
– Java 教程:面向对象编程到 Spring 框架
– 前端教程:HTML、CSS、JavaScript 及其框架
所有教程都配有详细的代码示例和在线运行环境。
学习者可以通过边学边练的方式快速掌握编程技能。"""
# 切分文档
chunks = text_splitter.split_text(long_text)
print(f"原文长度: {len(long_text)} 字")
print(f"切分后: {len(chunks)} 块\\n")
for i, chunk in enumerate(chunks):
print(f"— 块 {i+1} ({len(chunk)} 字) —")
print(chunk)
print()
运行结果:
原文长度: 153 字
切分后: 3 块
— 块 1 (54 字) —
菜鸟教程(RUNOOB)是一个免费的编程学习平台。
平台提供了丰富的编程语言教程,包括但不限于:
— 块 2 (49 字) —
– Python 教程:从基础语法到数据分析
– Java 教程:面向对象编程到 Spring 框架
— 块 3 (50 字) —
– 前端教程:HTML、CSS、JavaScript 及其框架
所有教程都配有详细的代码示例和在线运行环境。
4.2 chunk_overlap 有多重要
⚠️ 避坑:chunk_overlap 很重要。如果块之间没有重叠,一个完整的句子可能被切成两半,导致检索时遗漏关键信息。50-100 字符的重叠是常见设置。
4.3 切分参数设置指南
| FAQ 问答 | 200~500 | 20~50 | 问答对较短,小块即可 |
| 技术文档 | 500~1000 | 50~100 | 技术内容需要更多上下文 |
| 长文章/论文 | 1000~2000 | 100~200 | 需要保留段落完整性 |
| 代码库 | 500~1500 | 0~50 | 函数/类作为自然边界 |
五、Embedding 模型——把文本变成向量
5.1 什么是 Embedding
Embedding 模型把一段文本(句子、段落)转换成一个固定长度的数值向量,其中每个数字都捕获文本的语义含义。语义相近的文本,向量在空间里离得近——这样就能按「意思」而不是「字面用词」来比较和搜索。
text-embedding-3-small 输出 1536 维向量。
5.2 用 OpenAIEmbeddings
from dotenv import load_dotenv
load_dotenv()
from langchain_openai import OpenAIEmbeddings
# OpenAI 的文本嵌入模型
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# 测试:将一段文本转为向量
text = "菜鸟教程 RUNOOB 是一个编程学习平台"
vector = embeddings.embed_query(text)
print(f"文本: {text}")
print(f"向量维度: {len(vector)}") # text-embedding-3-small 是 1536 维
print(f"向量前 5 个值: {vector[:5]}")
运行结果:
文本: 菜鸟教程 RUNOOB 是一个编程学习平台
向量维度: 1536
向量前 5 个值: [0.0123, -0.0045, 0.0234, -0.0012, 0.0089]
5.3 用阿里云百炼 Embedding(无 OpenAI key)
没有 OpenAI key 可以改用阿里云百炼(DashScope)的通义千问 Embedding,接口兼容 OpenAI,直接指 base_url 即可。
import os
from dotenv import load_dotenv
load_dotenv()
from langchain_openai import OpenAIEmbeddings
# 使用阿里云百炼(DashScope)的通义千问 Embedding 服务
# 百炼接口兼容 OpenAI 规范,直接用 OpenAIEmbeddings + base_url 即可
# text-embedding-v4 当前推荐通用向量模型,默认输出 1024 维
embeddings = OpenAIEmbeddings(
model="text-embedding-v4",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
check_embedding_ctx_length=False, # 关键参数,见下方避坑
chunk_size=10, # 关键参数,见下方避坑
)
text = "菜鸟教程 RUNOOB 是一个编程学习平台"
vector = embeddings.embed_query(text)
print(f"向量维度: {len(vector)}")
⚠️ 两个关键参数不能省:
- check_embedding_ctx_length=False:OpenAIEmbeddings 默认用 tiktoken 把文本先编码成 token id 再发(OpenAI 官方接口认这个格式),但百炼兼容接口只接受原始字符串,不关掉会报 "contents is neither str nor list of str" 错误。
- chunk_size=10:百炼 Embedding 单次请求最多接受 10 条文本,OpenAIEmbeddings 默认一次打包 1000 条,知识库稍大就会超限报错。
.env 里加一行:
DASHSCOPE_API_KEY="sk-xxx"
六、向量数据库——存起来并检索
6.1 创建 Chroma 向量存储
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
# 初始化 Embedding 模型
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# 创建 Chroma 向量存储(数据保存在本地目录)
vector_store = Chroma(
collection_name="runoob_docs",
embedding_function=embeddings,
persist_directory="./chroma_db", # 持久化目录
)
# 添加文档(最简单的形式:文本列表)
texts = [
"菜鸟教程(RUNOOB)是一个免费的编程学习网站,提供 HTML、CSS、JavaScript、Python 等教程。",
"Python3 基础教程共 30 章,适合零基础入门,包含环境搭建、语法基础、面向对象等内容。",
"HTML 基础教程共 25 章,覆盖 HTML 标签、表单、多媒体等基础知识。",
]
# add_texts 自动将文本转为向量并存储
vector_store.add_texts(texts)
print(f"已添加 {len(texts)} 个文档到向量存储")
6.2 语义检索
similarity_search 按语义相似度排序,不依赖关键词精确匹配——这是向量检索的核心优势。
# 语义搜索——不依赖关键词匹配,而是语义相似度
results = vector_store.similarity_search(
"我想学 Python,有什么教程推荐?",
k=2, # 返回最相似的 2 个结果
)
print("搜索结果:")
for i, doc in enumerate(results):
print(f"\\n结果 {i+1}:")
print(f" 内容: {doc.page_content}")
print(f" 元数据: {doc.metadata}")
运行结果:
搜索结果:
结果 1:
内容: Python3 基础教程共 30 章,适合零基础入门…
元数据: {}
结果 2:
内容: 菜鸟教程(RUNOOB)是一个免费的编程学习网站…
元数据: {}
🔴 重点:第一个结果比第二个更相关——虽然它不含「Python 教程推荐」这些词,但按语义相似度排到了最前,这正是向量检索强于关键词检索的地方。
6.3 创建 Retriever 检索器
Retriever 是 Vector Store 的标准化接口,让向量库能作为 Agent 的工具使用。
# 从 vector_store 创建 retriever
retriever = vector_store.as_retriever(
search_type="similarity", # 相似度搜索
search_kwargs={"k": 3}, # 返回前 3 个结果
)
# 使用 retriever
docs = retriever.invoke("Python 学习路线")
for doc in docs:
print(f"- {doc.page_content[:60]}…")
七、完整流程:加载 → 切分 → 向量化 → 检索
把前面几节串成一个端到端的最小可用 RAG:
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
# 流程 1:加载
# loader = TextLoader("runoob_knowledge.txt", encoding="utf-8")
# docs = loader.load()
# 为演示直接使用示例文本
docs = [
"菜鸟教程(RUNOOB)是一个免费的编程学习网站。",
"网站提供 Python、Java、HTML 等多种编程语言的教程。",
"Python3 基础教程共 30 章,适合零基础入门学习。",
"HTML 基础教程共 25 章,包含表单、多媒体等内容。",
"菜鸟教程的所有基础教程都是免费的。",
]
# 流程 2:切分
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=100,
chunk_overlap=20,
)
chunks = text_splitter.create_documents(docs)
# 流程 3:向量化存储
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vector_store = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./runoob_db",
)
print(f"已建立索引:{len(chunks)} 个文档块")
# 流程 4:检索
results = vector_store.similarity_search("Python 教程有多少章?", k=2)
for doc in results:
print(f"检索结果: {doc.page_content}")
运行结果:
已建立索引:5 个文档块
检索结果: Python3 基础教程共 30 章,适合零基础入门学习。
检索结果: 菜鸟教程(RUNOOB)是一个免费的编程学习网站。
八、向量库与嵌入模型选型参考
LangChain 对向量库和嵌入模型提供了统一接口,可以按需切换。以下是常见的嵌入模型和向量库:
常见嵌入模型:OpenAI text-embedding-3-large、Azure text-embedding-ada-002、Google text-embedding-004、Mistral mistral-embed、Cohere embed-english-v3.0 等。
常见向量库:内存 MemoryVectorStore、PineconeStore、MongoDBAtlasVectorSearch、RedisVectorStore、QdrantVectorStore、WeaviateStore 等。
选型建议:入门用 Chroma(轻量本地),上规模换 Pinecone / Qdrant / MongoDB Atlas(托管、可扩展),已用 PostgreSQL 的可以加 pgvector。
相似度度量
向量相似度通常用这三种:余弦相似度(夹角)、欧氏距离(直线距离)、点积(投影)。高效检索常借助 HNSW 等索引结构,具体取决于向量库实现。
九、总结:你真正需要记住的这几件事
验证清单
- 能用 TextLoader / WebBaseLoader 加载文档
- RecursiveCharacterTextSplitter 切分且 chunk_overlap 生效
- Embedding 输出向量维度正确(1536 / 1024)
- similarity_search 按语义而非关键词排序
- as_retriever() 能生成可供 Agent 使用的检索器
- 跑通「加载→切分→向量化→检索」完整链路
参考资源
- LangChain 官方 · Vector store integrations: https://docs.langchain.com/oss/python/integrations/vectorstores
- LangChain 官方 · Embedding model integrations: https://docs.langchain.com/oss/python/integrations/embeddings
- 菜鸟教程 · LangChain 文档加载与切分: https://www.runoob.com/langchain/langchain-document-loaders.html
- 菜鸟教程 · RAG 概述: https://www.runoob.com/langchain/langchain-rag-overview.html
说明:文中模型名与 API 以官方文档和菜鸟教程为准,具体版本细节请以你安装的 LangChain 为准。


