LangChain RAG

一、简介

RAG(Retrieval-Augmented Generation,检索增强生成)让 AI 能够基于你的私有文档回答问题,不需要微调模型,只需将文档向量化存储,Agent 就能检索相关内容来回答。

RAG 的核心思想是:让 LLM 在回答问题时,先从外部知识库中检索相关内容,再基于检索结果生成回答,而不是仅依赖模型训练时记住的知识。
这解决了 LLM 的两个核心痛点:知识截止日期(模型不知道训练后发生的事)和幻觉问题(模型在不确定时会编造答案)。

二、Embedding 模型初始化

from langchain_ollama import OllamaEmbeddings

# OpenAI 的文本嵌入模型
# 将文本转换为向量(一组浮点数)
embeddings = OllamaEmbeddings(
    # model="quentinz/bge-large-zh-v1.5",  # 换成 bge-small-zh 中文更好
    model="bge-m3",  # 换成 bge-small-zh 中文更好
    base_url="http://localhost:11434"  # ollama默认地址
)

# 测试:将一段文本转为向量
text = "菜鸟教程 RUNOOB 是一个编程学习平台"
vector = embeddings.embed_query(text)

print(f"文本: {text}")
print(f"向量维度: {len(vector)}")  # text-embedding-3-small 是 1536 维
print(f"向量前 5 个值: {vector[:5]}")

三、创建向量存储

# *_*coding:utf-8

from langchain_ollama import OllamaEmbeddings
from langchain_chroma import Chroma

# OpenAI 的文本嵌入模型
# 将文本转换为向量(一组浮点数)
embeddings = OllamaEmbeddings(
    # model="quentinz/bge-large-zh-v1.5",  # 换成 bge-small-zh 中文更好
    model="bge-m3",  # 换成 bge-small-zh 中文更好
    base_url="http://localhost:11434"  # ollama默认地址
)

# 创建 Chroma 向量存储(数据保存在本地目录)
vector_store = Chroma(
    collection_name="runoob_docs",
    embedding_function=embeddings,
    persist_directory="./file/chroma_test_db",  # 持久化目录
)

# 添加文档(最简单的形式:文本列表)
texts = [
    "菜鸟教程(RUNOOB)是一个免费的编程学习网站,提供 HTML、CSS、JavaScript、Python 等教程。",
    "Python3 基础教程共 30 章,适合零基础入门,包含环境搭建、语法基础、面向对象等内容。",
    "HTML 基础教程共 25 章,覆盖 HTML 标签、表单、多媒体等基础知识。",
]

# add_texts 自动将文本转为向量并存储 ,注 add_texts 是会进行重复累加
vector_store.add_texts(texts)

print(f"已添加 {len(texts)} 个文档到向量存储")


# 真正统计库里有多少条
count = vector_store._collection.count()
print(f"库中实际文档数: {count}")

四、语义检索

# 语义搜索——不依赖关键词匹配,而是语义相似度
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}")

五、加载数据

# *_*coding:utf-8

from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_chroma import Chroma
from langchain_ollama import OllamaEmbeddings


# 流程 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 = embeddings = OllamaEmbeddings(
    # model="quentinz/bge-large-zh-v1.5",  # 换成 bge-small-zh 中文更好
    model="bge-m3",  # 换成 bge-small-zh 中文更好
    base_url="http://localhost:11434"  # ollama默认地址
)

# 删除已有的数据库
vector_store = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./file/chroma_test2_db",
)
vector_store.delete_collection()

# 再进行重建
vector_store = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./file/chroma_test2_db",
)

print(f"已建立索引:{len(chunks)} 个文档块")

# 真正统计库里有多少条
count = vector_store._collection.count()
print(f"库中实际文档数: {count}")

六、加载已有的向量数据

# *_*coding:utf-8
import os

from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_chroma import Chroma
from langchain_ollama import OllamaEmbeddings


# 流程 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 = OllamaEmbeddings(
    # model="quentinz/bge-large-zh-v1.5",  # 换成 bge-small-zh 中文更好
    model="bge-m3",  # 换成 bge-small-zh 中文更好
    base_url="http://localhost:11434"  # ollama默认地址
)

PERSIST_DIR = "./file/chroma_test4_db"


# 直接加载已有的向量数据库;若不存在则新建并入库
if os.path.exists(PERSIST_DIR) and os.listdir(PERSIST_DIR):
    # 库已存在:直接加载,不重复写入
    vector_store = Chroma(
        collection_name="test_docs",
        embedding_function=embeddings,
        persist_directory=PERSIST_DIR,
    )
    print("已加载已有向量数据库")
else:
    # 库不存在:首次构建并持久化
    vector_store = Chroma.from_documents(
        collection_name="test_docs",
        documents=chunks,
        embedding=embeddings,
        persist_directory=PERSIST_DIR,
    )
    print(f"已建立索引:{len(chunks)} 个文档块")

# 真正统计库里有多少条
count = vector_store._collection.count()
print(f"库中实际文档数: {count}")

# 流程 4:检索
results = vector_store.similarity_search("Python 教程有多少章?", k=2)
for doc in results:
    print(f"检索结果: {doc.page_content}")

七、增加新的向量数据

# add_texts 是插入,不是替换。重复执行会不断累加
new_texts = [
    "这是一条新增的文档内容。",
    "这是另一条新增内容。",
]
vector_store.add_texts(new_texts)
print("新增后库内条数:", vector_store._collection.count())

八、各自文档的加载方式

from langchain_community.document_loaders import (
    TextLoader,
    PyPDFLoader,
    WebBaseLoader,
    CSVLoader,
    UnstructuredMarkdownLoader,
)


# 流程 加载(支持多种文档来源,按需要切换 DATA_SOURCE)
# 需要安装:
#   pip install langchain-community pypdf beautifulsoup4 unstructured
DATA_SOURCE = "sample"  # 可选: sample / txt / pdf / url / csv / markdown

if DATA_SOURCE == "txt":
    # .txt 文本文件
    loader = TextLoader("./file/example.txt", encoding="utf-8")
    docs = loader.load()
elif DATA_SOURCE == "pdf":
    # PDF 文件(依赖 pypdf)
    loader = PyPDFLoader("./file/example.pdf")
    docs = loader.load()
elif DATA_SOURCE == "url":
    # 网页 URL(依赖 beautifulsoup4)
    loader = WebBaseLoader("https://www.runoob.com/python3/python3-tutorial.html")
    docs = loader.load()
elif DATA_SOURCE == "csv":
    # CSV 文件
    loader = CSVLoader("./file/example.csv")
    docs = loader.load()
elif DATA_SOURCE == "markdown":
    # Markdown 文件(依赖 unstructured)
    loader = UnstructuredMarkdownLoader("./file/example.md")
    docs = loader.load()
else:
    # 默认:示例文本
    docs = [
        "菜鸟教程(RUNOOB)是一个免费的编程学习网站。",
        "网站提供 Python、Java、HTML 等多种编程语言的教程。",
        "Python3 基础教程共 30 章,适合零基础入门学习。",
        "HTML 基础教程共 25 章,包含表单、多媒体等内容。",
        "菜鸟教程的所有基础教程都是免费的。",
    ]

print(f"已加载文档数: {len(docs)}")

# 流程 2:切分
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=100,
    chunk_overlap=20,
)
chunks = text_splitter.create_documents(docs)

九、教程

https://www.runoob.com/ai-agent/retrieval-augmented-generation.html


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。

文章标题:LangChain RAG

本文作者:伟生

发布时间:2026-09-13, 21:45:00

最后更新:2026-09-13, 21:49:21

原始链接:http://yoursite.com/2026/09/13/ai_05_RAG_02/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏