RAG 实现与 LangChain 实战详解(附豆包seed2.0模型实现)

4 阅读7分钟

image.png

这张图,正是标准 RAG(检索增强生成)的核心流程

  • 下方是离线知识库构建阶段:企业文档→解析→分块→向量化→存入知识库
  • 上方是在线问答阶段:用户提问→检索相关 chunk→组装 prompt→大模型生成答案下面我会结合豆包 Seed 2.0 的 RAG 技术特点,对比LangChain 框架,拆解全流程技术细节。

可以解析为下面2个图: 知识库构建 image.png 在线问答处理 image.png 流程图把 RAG 拆成了两大阶段,和行业通用范式完全一致:

阶段核心动作关键细节
离线知识库构建企业知识(txt/doc/html 等)→解析为 txt 文本→分块(split)→存入知识库解决 “如何把非结构化文档变成可检索的结构化数据”
在线问答用户 query→检索知识库中相关 chunk→组装 prompt(instruction+{chunk}+query)→调用大模型生成回复解决 “如何让大模型基于私有知识回答问题”

豆包 Seed 2.0 的 RAG 架构,在标准流程基础上做了深度优化,核心特点如下:

1. 离线知识库构建阶段(和流程图下方对应)

(1)多模态文档解析

  • 支持 txt/doc/html/pdf/ 表格 / 图片等企业级文档,内置 OCR、表格结构化、PDF 版式解析能力,自动提取文本内容并还原格式。
  • 针对复杂文档(如带图片的手册、多列排版的报告),会先做布局分析,按语义段落而非单纯按字符切分,避免上下文断裂。

(2)智能分块(Chunking)优化

  • 不是固定长度切割,而是语义感知分块:优先按段落、章节、句子边界拆分,同时支持滑动窗口重叠(overlap),避免关键信息被切断。
  • 支持动态块大小:根据文本密度自动调整(比如密集的代码块分块更大,松散的说明文字分块更小),同时适配 Seed 2.0 的 256K 超长上下文窗口。

(3)向量化与向量库存储

  • 使用字节自研的 Embedding 模型(适配中文和企业场景),将每个 chunk 转换为高维向量,同时保留 chunk 的元数据(来源文档、页码、章节等)。
  • 向量库采用 HNSW 索引,支持亿级向量的毫秒级检索,同时内置混合检索(向量语义检索 + 关键词检索),解决纯向量检索的语义漂移问题。

2. 在线问答阶段(和流程图上方对应)

(1)用户 Query 理解与改写

  • 首先对用户 query 做意图理解:判断是否需要检索知识库,是否需要历史对话上下文(多轮对话场景)。
  • 支持query 改写 / 扩展:比如用户问 “这个政策什么时候实施?”,模型会结合历史对话,补全为 “XX 公司 2025 年 XX 政策的实施时间是什么时候?”,提升检索准确率。

(2)多策略检索与重排序

  • 基础检索:Top-K 向量召回(默认召回 5-10 个 chunk),结合元数据过滤(比如按文档类型、时间范围筛选)。
  • 进阶优化:内置 RRF(Reciprocal Rank Fusion)融合检索结果,再通过交叉编码器(Cross-Encoder) 对召回的 chunk 做相关性重排序,只保留最相关的 3-5 个 chunk。
  • 针对复杂问题,支持多轮检索 / 迭代检索:先根据问题主题检索,再根据第一次检索结果的补充信息,二次检索更精准的 chunk。

(3)Prompt 组装与安全控制

  • 采用结构化 prompt 模板,和图中的结构完全对应:

    text

    instruction: 请根据以下内容回答用户问题,回答要准确、简洁,只使用给定的信息,如果信息不足请说明。
    content: {chunk1}\n{chunk2}\n{chunk3}
    input: {user_query}
    
  • 内置上下文压缩:自动过滤检索结果中与问题无关的冗余内容,避免 prompt 过长超过模型上下文限制。

  • 同时做内容安全校验:过滤检索结果中的敏感信息,避免生成违规内容。

(4)生成与溯源

  • 调用 Seed 2.0 大模型生成回答时,会在 prompt 中强制模型引用来源 chunk 的标识,生成回答后自动附带引用来源(比如 “根据《员工手册》第 3 章第 2 节”),解决 RAG 常见的 “幻觉” 问题。
  • 支持答案可验证:用户点击引用链接,可直接跳转到知识库中的原始文档位置。

LangChain 如何实现和豆包同款 RAG?(附核心代码)

正在学习的 LangChain,提供了一套标准化的 RAG 实现框架,完全可以复现上述流程,以下是核心步骤和代码示例:

1. 环境准备

bash

运行

pip install langchain langchain-community langchain-openai faiss-cpu python-docx PyPDF2

2. 离线知识库构建(对应流程图下方)

python

运行

from langchain.document_loaders import PyPDFLoader, Docx2txtLoader, TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings  # 也可以用字节/其他Embedding模型
from langchain.vectorstores import FAISS
import os

# 1. 加载多格式文档(对应“企业知识→txt”步骤)
def load_documents(file_dir):
    documents = []
    for file in os.listdir(file_dir):
        file_path = os.path.join(file_dir, file)
        if file.endswith('.pdf'):
            loader = PyPDFLoader(file_path)
        elif file.endswith('.docx'):
            loader = Docx2txtLoader(file_path)
        elif file.endswith('.txt'):
            loader = TextLoader(file_path, encoding='utf-8')
        else:
            continue
        documents.extend(loader.load())
    return documents

# 2. 分块(对应“split chunk”步骤)
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=800,  # 块大小,可根据场景调整
    chunk_overlap=150,  # 重叠部分,避免上下文断裂
    separators=["\n\n", "\n", "。", ",", " ", ""]  # 按语义边界拆分
)
documents = load_documents("./enterprise_docs")
texts = text_splitter.split_documents(documents)

# 3. 向量化并存入向量库(对应“知识库”步骤)
embeddings = OpenAIEmbeddings(api_key="你的API_KEY")
vectorstore = FAISS.from_documents(texts, embeddings)
# 持久化存储
vectorstore.save_local("enterprise_knowledge_base")

3. 在线问答阶段(对应流程图上方)

python

运行

from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate

# 1. 加载向量库和模型
vectorstore = FAISS.load_local("enterprise_knowledge_base", embeddings)
retriever = vectorstore.as_retriever(
    search_kwargs={"k": 5}  # 召回Top5个chunk
)
llm = ChatOpenAI(
    model_name="doubao-seed-2.0",  # 对接豆包Seed 2.0模型
    temperature=0.1  # 低温度,保证回答的准确性
)

# 2. 自定义prompt模板(和图中的结构完全一致)
prompt_template = """
请你作为企业知识库助手,根据以下给定的参考信息回答用户问题。
如果参考信息中没有相关内容,请直接回答“抱歉,我没有找到相关信息”,不要编造内容。

参考信息:
{context}

用户问题:{question}

回答:
"""
QA_PROMPT = PromptTemplate(
    template=prompt_template,
    input_variables=["context", "question"]
)

# 3. 构建RAG问答链
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",  # 把所有chunk直接拼接进prompt
    retriever=retriever,
    return_source_documents=True,  # 返回来源文档,方便溯源
    chain_type_kwargs={"prompt": QA_PROMPT}
)

# 4. 调用问答
user_query = "公司的年假政策是什么?"
result = qa_chain.invoke(user_query)
print("回答:", result["result"])
print("来源文档:", [doc.metadata["source"] for doc in result["source_documents"]])

豆包 Seed 2.0 RAG vs 原生 LangChain:关键差异

能力维度豆包 Seed 2.0 RAG原生 LangChain
文档解析内置多模态解析、OCR、表格结构化需要依赖第三方库(如 PyPDF2、pytesseract),复杂文档解析能力弱
分块策略语义感知分块 + 动态块大小,适配超长上下文依赖固定规则的文本分割器,对复杂文本分块效果一般
检索优化混合检索 + 交叉编码器重排序 + 迭代检索基础向量检索,需额外集成 RRF、重排序组件
对话支持原生支持多轮对话上下文理解与 query 改写需额外维护对话历史,手动实现 query 扩展
安全与溯源内置敏感信息过滤、自动引用溯源需自定义 prompt 和后处理逻辑实现

给 LangChain 学习者的进阶建议

  1. 从基础到进阶:先跑通上述基础代码,再逐步加入这些优化:

    • 集成混合检索:结合 BM25 关键词检索和向量检索
    • 加入重排序模型(如 BGE-reranker)提升召回精度
    • 实现对话式 RAG:用ConversationRetrievalChain维护多轮上下文
  2. 和豆包 Seed 2.0 对齐:可以用火山引擎提供的豆包 API,替换代码中的 OpenAI 模型,实现和官方一致的模型能力。

  3. 调优核心参数:重点调整 chunk 大小、重叠度、召回 Top-K 数量,这些参数直接影响 RAG 效果。