这张图,正是标准 RAG(检索增强生成)的核心流程:
- 下方是离线知识库构建阶段:企业文档→解析→分块→向量化→存入知识库
- 上方是在线问答阶段:用户提问→检索相关 chunk→组装 prompt→大模型生成答案下面我会结合豆包 Seed 2.0 的 RAG 技术特点,对比LangChain 框架,拆解全流程技术细节。
可以解析为下面2个图:
知识库构建
在线问答处理
流程图把 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 学习者的进阶建议
-
从基础到进阶:先跑通上述基础代码,再逐步加入这些优化:
- 集成混合检索:结合 BM25 关键词检索和向量检索
- 加入重排序模型(如 BGE-reranker)提升召回精度
- 实现对话式 RAG:用
ConversationRetrievalChain维护多轮上下文
-
和豆包 Seed 2.0 对齐:可以用火山引擎提供的豆包 API,替换代码中的 OpenAI 模型,实现和官方一致的模型能力。
-
调优核心参数:重点调整 chunk 大小、重叠度、召回 Top-K 数量,这些参数直接影响 RAG 效果。