DeepSeek + 本地知识库:30 分钟给团队搭一个智能问答机器人(附完整源码)
·
【摘要】本文用 DeepSeek + LangChain + Chroma 从零搭建一个能回答"自己公司/团队内部资料"的智能问答机器人。核心就三步:文档切片 → 向量化 → 检索生成。附带完整可运行代码和中文分块的 5 个避坑要点。
一、为什么要用 RAG?
很多刚接触的同学会问:大模型这么强,为什么还要搞 RAG(Retrieval-Augmented Generation,检索增强生成)?
因为大模型有两个硬伤:
- 知识陈旧:训练数据有截止时间,公司上个月新改的制度它根本不知道。
- 容易幻觉:遇到不懂的内容会一本正经地"编"。
RAG 的思路很朴素:先把你自己的资料切块存进向量库,提问时先检索最相关的片段,再连同问题一起喂给大模型,让它"照着资料回答"。资料是真实的,答案自然靠谱,幻觉也少很多。
这也是 2025 年 RAG 相关内容同比增长 300%、成为最大技术黑马的原因。
二、整体架构
原始文档 (MD/TXT/PDF)
│ ① 切块 (Split)
▼
文本片段 (Chunks)
│ ② Embedding 向量化
▼
向量数据库 (Chroma) ◄───────┐
│ ③ 相似度检索(提问时)
用户提问 ────────────────────┘
│ ④ 组装 Prompt
▼
DeepSeek 大模型 ──► 基于资料的答案
三、环境准备
pip install langchain langchain-community chromadb sentence-transformers openai
DeepSeek 提供 OpenAI 兼容接口,直接用
openai库即可,无需额外安装专用包。
四、完整源码
1. 接入 DeepSeek
import os
from langchain_openai import ChatOpenAI
os.environ["DEEPSEEK_API_KEY"] = "sk-你的key" # 在 https://platform.deepseek.com 申请
llm = ChatOpenAI(
model="deepseek-chat",
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com/v1",
temperature=0.1, # 问答场景温度调低,避免自由发挥
)
2. 加载文档并切块
from langchain_community.document_loaders import DirectoryLoader, TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 加载 ./docs 目录下所有 md 文档
loader = DirectoryLoader("./docs", glob="*.md", loader_cls=TextLoader)
documents = loader.load()
# 切块:中文建议 chunk_size 略大、overlap 略高
splitter = RecursiveCharacterTextSplitter(
chunk_size=512, # 每块约 512 字
chunk_overlap=80, # 相邻块重叠 80 字,防止关键信息被切裂
separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""], # 按中文标点优先切
)
chunks = splitter.split_documents(documents)
print(f"共切出 {len(chunks)} 个文本块")
3. 向量化并存入 Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import Chroma
# 本地中文 embedding 模型,免费、无需联网
embeddings = HuggingFaceEmbeddings(model_name="shibing624/text2vec-base-chinese")
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db",
)
4. 组装检索问答链
from langchain.chains import RetrievalQA
retriever = vectorstore.as_retriever(search_kwargs={"k": 4}) # 取最相关的 4 块
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=retriever,
return_source_documents=True, # 返回来源,便于核对
)
question = "报销流程是什么?"
result = qa_chain.invoke({"query": question})
print("回答:", result["result"])
print("\n--- 依据的来源片段 ---")
for i, doc in enumerate(result["source_documents"][:3]):
print(f"[{i+1}] {doc.page_content[:120]}...")
运行效果示例:
回答: 按公司制度,报销需填写报销单并附发票,直属主管审批后,财务在
3 个工作日内复核打款;单笔超过 5000 元需 CTO 二次审批。
--- 依据的来源片段 ---
[1] 报销管理制度:……5000 元以上需 CTO 审批……
[2] 财务指引:……报销单需在当月月底前提交……
五、中文 RAG 最常见的 5 个坑
| # | 坑 | 现象 | 解法 |
|---|---|---|---|
| 1 | 分块漏信息 | 一句话被切成两半,检索不到 | chunk_overlap 调到 60~100 字 |
| 2 | 按英文标点切 | 中文长句被粗暴切断 | separators 加上 。!?;, |
| 3 | 默认 embedding 不适配中文 | 检索结果文不对题 | 换 text2vec / bge 等中文模型 |
| 4 | 温度太高 | 答案开始"自由发挥" | 问答场景 temperature=0.1 以下 |
| 5 | 不返回来源 | 出错时无法排查 | 打开 return_source_documents=True |
六、进阶方向
- 多轮对话:换
ConversationalRetrievalChain保留历史 - PDF 文档:加载器换
PyMuPDFLoader - 数据量大:把 Chroma 换成 Faiss / Milvus
- 对外服务:用 FastAPI 包一层 HTTP 接口
结语
RAG 不复杂,核心就是"切好块 + 中文向量化 + 检索生成"三步。难点不在大模型,而在中文分块和检索质量。把上面 5 个坑避开,你就能交付一个真正能用的内部问答机器人。
如果你在搭建过程中遇到问题,欢迎在评论区留言交流。
本文代码在 Python 3.11 + LangChain 0.2 环境验证。API Key 请使用自己的,切勿泄露到公开仓库。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)