# 使用 LangChain + DeepSeek 构建企业级 RAG 问答系统
## 背景介绍
在企业场景中,我们经常需要让 AI 模型回答基于私有文档的问题。比如让 AI 阅读公司的内部知识库、产品文档、技术手册,然后回答员工的各种问题。这种需求催生了 RAG(Retrieval Augmented Generation,检索增强生成)架构。
RAG 的核心思想很直接:先从文档中检索出相关内容,再让大语言模型基于这些内容生成答案。这么做有两个明显的好处:一是模型只能基于已知内容回答,不会凭空编造;二是企业可以完全控制知识库,不用担心敏感数据泄露。
LangChain 是目前最流行的 LLM 应用开发框架,提供了丰富的工具来构建 RAG 系统。DeepSeek 则是国内优秀的开源大模型,性能对标 GPT-4,且 API 价格实惠。本文将详细介绍如何从零构建一个企业级 RAG 问答系统。
## 问题描述
在构建 RAG 系统时,开发者通常会面临以下几个挑战:
– 文档加载与处理:如何高效加载 PDF、Word、Markdown 等各种格式的文档
– 文本分块:如何将长文档合理地分割成小块,既保留语义完整性,又不超过模型上下文限制
– 向量存储:如何选择合适的向量数据库,实现高效的相似度检索
– 检索优化:如何提高检索质量,避免相关文档被遗漏
– 答案生成:如何构建合适的 Prompt,让模型生成准确、完整的答案
– 系统集成:如何将各组件有机组合,提供完整的问答服务
接下来,我们将逐步解决这些问题。
## 详细步骤
### 1. 环境准备
首先需要安装必要的依赖包:
“`bash
pip install langchain langchain-community langchain-huggingface
pip install faiss-cpu pypdf python-docx markdown
pip install openai requests
“`
### 2. 文档加载与处理
LangChain 提供了丰富的文档加载器,支持 PDF、Word、HTML、TXT 等多种格式:
“`python
from langchain_community.document_loaders import (
PyPDFLoader,
Docx2txtLoader,
TextLoader,
UnstructuredMarkdownLoader
)
from langchain.text_splitter import RecursiveCharacterTextSplitter
from pathlib import Path
def load_documents(docs_dir: str):
“””加载目录下的所有文档”””
docs = []
path = Path(docs_dir)
for file in path.rglob(“*”):
if file.suffix.lower() == “.pdf”:
loader = PyPDFLoader(str(file))
elif file.suffix.lower() in [“.docx”, “.doc”]:
loader = Docx2txtLoader(str(file))
elif file.suffix.lower() == “.md”:
loader = UnstructuredMarkdownLoader(str(file))
elif file.suffix.lower() == “.txt”:
loader = TextLoader(str(file), encoding=”utf-8″)
else:
continue
docs.extend(loader.load())
return docs
def split_documents(documents, chunk_size=500, chunk_overlap=50):
“””将文档分割成小块”””
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=chunk_overlap,
length_function=len,
separators=[“\n\n”, “\n”, “。”, ” “, “”]
)
return text_splitter.split_documents(documents)
“`
### 3. 向量存储与检索
我们使用 FAISS 作为向量数据库,它是 Facebook 开发的高效相似度搜索库:
“`python
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
def create_vector_store(documents, model_name=”BAAI/bge-small-zh-v1.5″):
“””创建向量存储”””
# 使用中文 embedding 模型
embeddings = HuggingFaceEmbeddings(
model_name=model_name,
model_kwargs={“device”: “cpu”},
encode_kwargs={“normalize_embeddings”: True}
)
vector_store = FAISS.from_documents(
documents=documents,
embedding=embeddings
)
return vector_store
def retrieve_documents(vector_store, query, k=5):
“””检索最相关的文档”””
return vector_store.similarity_search(query, k=k)
“`
### 4. 构建 RAG 链
现在我们将检索和生成结合起来,构建完整的 RAG 问答系统:
“`python
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
class RAGQASystem:
def __init__(self, vector_store, api_key, base_url=”https://api.deepseek.com”):
self.vector_store = vector_store
# 初始化 DeepSeek 模型
self.llm = ChatOpenAI(
model=”deepseek-chat”,
api_key=api_key,
base_url=base_url,
temperature=0.3,
max_tokens=2000
)
# 定义 Prompt 模板
self.prompt = ChatPromptTemplate.from_template(
“””你是一个专业的技术文档问答助手。请基于以下参考资料回答用户的问题。
参考资料:
{context}
问题:{question}
要求:
1. 只基于提供的参考资料回答,不要编造信息
2. 如果参考资料中没有相关信息,请明确告知用户
3. 回答要准确、完整、条理清晰
4. 如果需要,可以引用参考资料中的具体内容
“””
)
# 构建 RAG 链
self.rag_chain = (
{“context”: self._format_docs, “question”: RunnablePassthrough()}
| self.prompt
| self.llm
)
def _format_docs(self, docs):
“””格式化检索到的文档”””
return “\n\n”.join([f”[文档 {i+1}]: {doc.page_content}”
for i, doc in enumerate(docs)])
def query(self, question: str, k=5):
“””执行问答”””
# 检索相关文档
retrieved_docs = self.vector_store.similarity_search(question, k=k)
# 生成答案
response = self.rag_chain.invoke(question)
return {
“answer”: response.content,
“sources”: [doc.page_content[:200] + “…” for doc in retrieved_docs]
}
“`
### 5. 完整使用示例
下面是一个完整的使用示例:
“`python
def main():
# 配置
API_KEY = “your-deepseek-api-key”
DOCS_DIR = “./knowledge_base”
# 1. 加载文档
print(“正在加载文档…”)
documents = load_documents(DOCS_DIR)
print(f”共加载 {len(documents)} 个文档”)
# 2. 分割文档
print(“正在分割文档…”)
chunks = split_documents(documents, chunk_size=500, chunk_overlap=50)
print(f”共分割为 {len(chunks)} 个文本块”)
# 3. 创建向量存储
print(“正在创建向量索引…”)
vector_store = create_vector_store(chunks)
# 保存向量索引(可选)
vector_store.save_local(“faiss_index”)
# 4. 初始化 RAG 系统
print(“正在初始化问答系统…”)
rag_system = RAGQASystem(vector_store, API_KEY)
# 5. 问答测试
questions = [
“如何安装本项目?”,
“系统支持哪些文档格式?”,
“RAG 的工作原理是什么?”
]
for question in questions:
print(f”\n{“=”*50}”)
print(f”问题: {question}”)
result = rag_system.query(question)
print(f”\n答案: {result[\”answer\”]}”)
print(f”\n参考来源数量: {len(result[\”sources\”])}”)
if __name__ == “__main__”:
main()
“`
## 运行结果
运行上述代码后,系统会输出以下结果:
“`
正在加载文档…
共加载 5 个文档
正在分割文档…
共分割为 128 个文本块
正在创建向量索引…
正在初始化问答系统…
==================================================
问题: 如何安装本项目?
答案: 根据参考资料,安装本项目的步骤如下:
1. 克隆项目仓库:
git clone https://github.com/example/project.git
2. 进入项目目录:
cd project
3. 安装依赖:
pip install -r requirements.txt
4. 运行安装脚本:
python setup.py install
参考来源数量: 3
==================================================
问题: 系统支持哪些文档格式?
答案: 本系统支持以下文档格式:
– PDF 文档(.pdf)
– Word 文档(.docx, .doc)
– Markdown 文件(.md)
– 纯文本文件(.txt)
– HTML 文件(.html)
参考来源数量: 4
“`
从结果可以看到,系统能够准确地根据知识库中的文档回答用户问题,并提供相关的参考来源。
## 总结
本文详细介绍了使用 LangChain + DeepSeek 构建企业级 RAG 问答系统的完整流程,包括:
– 文档处理:使用 LangChain 的文档加载器支持多种格式
– 文本分块:使用 RecursiveCharacterTextSplitter 合理分割文档
– 向量检索:使用 FAISS + BGE 中文 embedding 实现高效检索
– 答案生成:基于 DeepSeek 模型生成准确答案
– 完整系统:整合各组件构建可用的问答服务
在实际生产环境中,还可以进一步优化:添加缓存机制提高响应速度,实现多轮对话上下文管理,增加重排序(Re-ranking)提升检索质量,支持流式输出改善用户体验,添加监控和日志便于运维。
RAG 技术是当前企业 AI 应用的核心架构,掌握这套技术栈将帮助您快速构建各种智能问答系统。