欢迎光临
我们一直在努力

【LangChain进阶04:RAG】—— LangChain RAG 入门:从文档加载、切分到向量检索

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 提供数十种加载器覆盖常见格式:

Loader来源安装包
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 切分参数设置指南

场景chunk_sizechunk_overlap原因
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 等索引结构,具体取决于向量库实现。


九、总结:你真正需要记住的这几件事

  • RAG = 检索 + 生成:离线把文档向量化入库,在线检索相关内容喂给模型。
  • 加载用 Document Loader:按文档格式选 TextLoader / PyPDFLoader / WebBaseLoader 等。
  • 切分是 RAG 效果的关键:chunk_size + chunk_overlap 要按场景调,重叠别忘记。
  • Embedding 把文本变语义向量:能按「意思」而非「字面」搜索。
  • 向量库管存储 + 检索:similarity_search 按语义相似度排,Retriever 是标准化接口。
  • 入门 Chroma,上规模换托管库。
  • 验证清单

    • 能用 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 为准。

    赞(0)
    未经允许不得转载:171主机测评 » 【LangChain进阶04:RAG】—— LangChain RAG 入门:从文档加载、切分到向量检索
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址