大模型实战:基于 DeepSeek 搭建企业知识库问答(RAG)应用案例
本文介绍了一个基于DeepSeek推理模型和本地向量检索的企业知识库问答系统实现方案。针对大模型应用中常见的无法回答内部知识和幻觉问题,采用RAG(检索增强生成)架构,通过本地向量检索找到相关文档片段,再结合DeepSeek生成答案。文章详细讲解了从知识库准备、向量索引构建到核心代码实现的完整流程,并提供了可运行的Python代码示例。重点分析了文档切分粒度、向量模型选择、降低幻觉等实战细节,同时
一、背景与目标
很多团队拿到大模型 API 之后,会遇到两个典型问题:
- 只能闲聊,无法回答公司内部知识(制度、产品、技术文档等)
- 幻觉严重:模型“一本正经胡说八道”,难以直接用于生产
业界主流的解决方案是 RAG(Retrieval-Augmented Generation,检索增强生成):
先用向量检索找到相关文档片段,再把这些文档作为上下文交给大模型生成答案。
本文用一个完整的实战案例,带你用 DeepSeek 推理模型 + 本地向量检索,从零实现一个可落地的 企业知识库问答系统:
- 支持用自然语言问“公司用的 DeepSeek 是什么版本?怎么调用?限流是多少?”
- 知识来源于你的 PDF/Word/内部 Wiki 导出的文本
- 支持本地向量检索,后端只调 DeepSeek 的 Chat Completion 接口
你可以直接改成自己公司的知识库,就能跑起来。
二、整体架构设计
我们要做的是一个典型的 RAG 应用,流程如下:
-
离线阶段(构建知识库)
- 收集公司文档(产品说明书、API 文档、SOP 等)
- 切分成段落
- 用本地向量模型生成 embeddings
- 建立向量索引(例如用
sklearn的NearestNeighbors)
-
在线阶段(回答用户问题)
- 用户输入问题
- 用同一个本地向量模型把问题转成向量
- 在向量索引中检索最相似的若干文档片段
- 把这些片段 + 问题 组合成 Prompt,发给 DeepSeek Chat 接口
- 返回结构化、可读的答案
架构示意:
用户问题 → 向量检索(本地) → 取出 Top-K 文档 → 构造 Prompt → 调用 DeepSeek → 返回答案
这套架构的好处:
- 数据可控:知识全在你本地,DeepSeek 只看到被选出来的内容
- 可解释:你可以把“引用的文档片段”一起展示给用户
- 成本可控:只有 DeepSeek 的调用需要付费,向量检索本地完成
三、环境准备
3.1 依赖安装
假设你已经有 Python 3.10+ 环境,安装依赖:
pip install openai sentence-transformers scikit-learn numpy
# 可选:Web UI
pip install streamlit
说明:
openai:用 OpenAI 兼容的 SDK 调 DeepSeek Chat APIsentence-transformers:本地向量模型,用来做文本嵌入scikit-learn:用NearestNeighbors做相似度检索streamlit:如果你想快速搭一个 Web Demo
3.2 DeepSeek API Key
- 去 DeepSeek 平台申请 API Key
- 在本地设置环境变量:
export DEEPSEEK_API_KEY="your_api_key_here"
四、准备一份简单的知识库
先准备一个最小可用的 JSON 知识库,放在 data/knowledge_base.json:
[
{
"title": "DeepSeek 模型简介",
"content": "DeepSeek 是由深度求索开发的一系列大语言模型,包括 Coder、Math、Reasoner 等。其中 DeepSeek-Reasoner 专注于多步推理和逻辑分析,适合构建问答和决策支持类应用。"
},
{
"title": "DeepSeek API 使用说明",
"content": "DeepSeek 提供兼容 OpenAI 风格的 API 接口,基础 URL 为 https://api.deepseek.com/v1,主要包含 chat.completions 和 embeddings 等。调用时需在 Header 中携带 Authorization: Bearer YOUR_API_KEY。"
},
{
"title": "RAG 技术架构简介",
"content": "RAG(检索增强生成)通过向量检索选出相关文档片段,再将其与用户问题一起输入大模型,从而生成更符合事实的回答。典型步骤包括:文档向量化、构建索引、查询检索、构造 Prompt 并调用 LLM。"
},
{
"title": "Python 实现 RAG 的常见做法",
"content": "在 Python 中实现 RAG 常用 sentence-transformers 来生成向量,使用 scikit-learn 或 FAISS 做近邻检索,再调用 OpenAI/DeepSeek 等模型进行生成。关键点在于分段粒度、向量模型选择和 Prompt 设计。"
}
]
真实项目里,你可以写个脚本把 PDF/Markdown 拆分成一段段文本后写成这个格式。
五、核心代码实现:RAG + DeepSeek
下面这份代码演示了一个从加载知识库 → 构建向量索引 → 调用 DeepSeek 回答问题的完整闭环,你可以保存为 rag_deepseek_demo.py。
5.1 完整代码
# -*- coding: utf-8 -*-
"""
大模型实战:基于 DeepSeek 的 RAG 知识库问答 Demo
"""
import os
import json
import logging
from typing import List, Dict, Any, Optional
from openai import OpenAI # 用 OpenAI SDK 调 DeepSeek
from sentence_transformers import SentenceTransformer
from sklearn.neighbors import NearestNeighbors
# ========= 日志配置 =========
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
# ========= DeepSeek 配置 =========
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY", "YOUR_API_KEY")
DEEPSEEK_BASE_URL = "https://api.deepseek.com/v1"
DEEPSEEK_MODEL = "deepseek-reasoner-671b" # 根据实际可用模型替换
# 初始化 DeepSeek 客户端(兼容 OpenAI 风格)
client = OpenAI(api_key=DEEPSEEK_API_KEY, base_url=DEEPSEEK_BASE_URL)
# ========= 向量检索相关 =========
EMBEDDING_MODEL = "all-MiniLM-L6-v2" # 通用中文/英文向量模型
def load_knowledge_base(path: str) -> List[Dict[str, str]]:
"""加载 JSON 格式的知识库"""
with open(path, "r", encoding="utf-8") as f:
docs = json.load(f)
if not isinstance(docs, list):
raise ValueError("知识库文件必须是 JSON 数组")
for d in docs:
if "content" not in d:
raise ValueError("每条记录必须包含 content 字段")
logger.info("成功加载 %d 条文档", len(docs))
return docs
class VectorDB:
"""简单的向量数据库封装"""
def __init__(self, docs: List[Dict[str, str]], model_name: str = EMBEDDING_MODEL):
self.docs = docs
self.model_name = model_name
self._embed_model: Optional[SentenceTransformer] = None
self.embeddings = None
self.nn = None
def _get_model(self) -> SentenceTransformer:
if self._embed_model is None:
logger.info("加载向量模型:%s", self.model_name)
self._embed_model = SentenceTransformer(self.model_name)
return self._embed_model
def build(self, n_neighbors: int = 5):
"""生成所有文档向量并构建近邻索引"""
model = self._get_model()
texts = [d["content"] for d in self.docs]
logger.info("开始生成 %d 条文档向量...", len(texts))
self.embeddings = model.encode(
texts,
convert_to_tensor=True,
show_progress_bar=True
)
# n_neighbors 不能超过样本数
n_neighbors = min(n_neighbors, len(self.docs))
self.nn = NearestNeighbors(
n_neighbors=n_neighbors,
metric="cosine"
)
self.nn.fit(self.embeddings)
logger.info("向量索引构建完成(n_neighbors=%d)", n_neighbors)
def search(self, query: str, top_k: int = 3) -> List[Dict[str, Any]]:
"""按语义相似度搜索最相关的文档"""
if self.nn is None or self.embeddings is None:
raise RuntimeError("请先调用 build() 构建索引")
model = self._get_model()
q_emb = model.encode([query], convert_to_tensor=True)
distances, indices = self.nn.kneighbors(q_emb)
results = []
for idx, dist in zip(indices[0], distances[0]):
doc = self.docs[int(idx)]
results.append({
"doc_id": int(idx),
"score": float(1 - dist), # 余弦距离转相似度
"title": doc.get("title", ""),
"content": doc["content"]
})
# 根据相似度排序并截断
results.sort(key=lambda x: x["score"], reverse=True)
return results[:top_k]
# ========= DeepSeek 调用封装 =========
def call_deepseek(prompt: str,
model: str = DEEPSEEK_MODEL,
temperature: float = 0.2,
max_tokens: int = 1024) -> str:
"""调用 DeepSeek Chat 接口"""
try:
resp = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
temperature=temperature,
max_tokens=max_tokens
)
return resp.choices[0].message.content.strip()
except Exception as e:
logger.error("调用 DeepSeek 失败:%s", e)
return f"调用 DeepSeek 失败:{e}"
class RAGWithDeepSeek:
"""RAG 主流程封装"""
def __init__(self, vector_db: VectorDB):
self.vector_db = vector_db
def build_prompt(self, question: str, docs: List[Dict[str, Any]]) -> str:
"""将检索到的文档 + 问题拼成 Prompt"""
context_blocks = []
for i, d in enumerate(docs, start=1):
title = d["title"] or f"文档{i}"
context_blocks.append(f"【{title}】\n{d['content']}")
context_text = "\n\n".join(context_blocks)
prompt = f"""你是一个专业的企业知识库问答助手,请严格依据给定的“上下文”回答用户问题,避免凭空编造。如果上下文中没有相关信息,请明确说明“从现有文档中无法找到答案”。
[上下文文档]
{context_text}
[用户问题]
{question}
请给出:
1. 直接可读的答案
2. 如有必要,简单说明你参考了哪些文档(用标题概述即可)
"""
return prompt
def answer(self, question: str, top_k: int = 3) -> Dict[str, Any]:
"""完整流程:检索 → 构造 Prompt → 调用 DeepSeek"""
retrieved = self.vector_db.search(question, top_k=top_k)
prompt = self.build_prompt(question, retrieved)
answer = call_deepseek(prompt)
return {
"question": question,
"answer": answer,
"retrieved_docs": retrieved
}
# ========= demo 入口 =========
def main():
# 1. 加载知识库
kb_path = "data/knowledge_base.json"
docs = load_knowledge_base(kb_path)
# 2. 构建向量索引
vdb = VectorDB(docs)
vdb.build(n_neighbors=4)
# 3. 初始化 RAG 系统
rag = RAGWithDeepSeek(vdb)
# 4. 测试几个典型问题
questions = [
"DeepSeek-Reasoner 适合做什么类型的应用?",
"我应该如何调用 DeepSeek 的 API?",
"什么是 RAG 架构?大概流程是怎样的?"
]
for q in questions:
print("=" * 60)
print("问题:", q)
result = rag.answer(q)
print("\n【答案】\n", result["answer"])
print("\n【命中的文档标题】")
for d in result["retrieved_docs"]:
print(f"- {d['title']} (score={d['score']:.3f})")
print("=" * 60, "\n")
if __name__ == "__main__":
main()
提示:把
YOUR_API_KEY换成真实 Key,把knowledge_base.json换成你自己的文档,就可以跑通一个最小可用的 DeepSeek RAG Demo。
六、运行与验证效果
6.1 运行
python rag_deepseek_demo.py
终端里你会看到类似输出(示意):
============================================================
问题: DeepSeek-Reasoner 适合做什么类型的应用?
【答案】
DeepSeek-Reasoner 是 DeepSeek 系列中专注多步推理和逻辑分析的模型,适合用于构建问答系统、
决策支持、知识库检索增强(RAG)等需要较强推理能力的场景……
【命中的文档标题】
- DeepSeek 模型简介 (score=0.89)
- RAG 技术架构简介 (score=0.75)
============================================================
可以看到:
- 模型的回答会明显参考你知识库中的描述;
- 同时你还能看到它参考了哪些文档,方便排查和解释。
七、落地实战中的关键细节与踩坑点
7.1 文档切分粒度
- 太长:一条记录 3000+ 字,向量会“稀释”语义,检索不到关键点
- 太短:一句话就一条记录,向量库膨胀、检索噪声增多
经验值:
- 中文文档:200~500 字为一段比较合适
- 代码/接口文档:按“一个接口/一个配置项说明”为粒度分段
7.2 向量模型选择
示例中用了 all-MiniLM-L6-v2,原因:
- 开源免费,推理快(CPU 就能用)
- 中英文都还可以,适合 Demo 和很多中小团队的场景
如果对中文语义检索要求更高,可以换成 中文优化的 sentence-transformers 模型,改一下:
python复制
EMBEDDING_MODEL = "your-chinese-embedding-model-name"
7.3 DeepSeek 模型选择与参数
- 场景:知识库问答 / 多步推理 → 推荐使用 Reasoner 系列
temperature:- 0.1~0.3:更稳、更少瞎编,适合知识问答
-
0.7:更有创造力,但幻觉多,一般不推荐给企业知识库
代码里的:
call_deepseek(prompt, temperature=0.2)
已经是偏稳的设置,可以根据实际情况微调。
7.4 降低“幻觉”的实战技巧
- Prompt 中明确要求“严格依据上下文”“没有就说不知道”
- 在业务侧加一个简单规则:
- 如果检索相似度都很低(比如 score < 0.4),直接告诉用户“目前知识库里没有相关内容”
- 可以把命中的文档标题 + 片段一并展示给用户,让用户自己判断可信度
八、如何扩展成真正的企业应用?
在上面的 Demo 基础上,你可以很自然地往下扩展:
-
接公司内部 SSO
对不同部门,只暴露不同子集的文档(权限控制)。 -
支持文档在线更新
定期从 Confluence/Wiki/Git 仓库同步文档,自动重新向量化和建索引。 -
加一个简单 Web 界面
用streamlit或Vue + FastAPI做一个提问界面和“引用文档展示”。 -
加反馈闭环
- 用户可以点“有用/没用”
- 记录问题/答案/点击行为
- 之后用这些数据微调提示词或精调检索模型
九、总结
我把DeepSeek 应用案例”完整走了一遍:
- 用本地向量模型 + DeepSeek 推理模型 搭建 RAG 应用
- 从 知识库 JSON 格式 → 向量索引 → Prompt 设计 → DeepSeek 调用 全流程给出了可运行代码
- 给出了在真实场景中需要注意的 切分粒度、向量模型选择、避免幻觉 等实践经验
可以直接做下面几件事,把 Demo 变成自己的应用:
- 把
knowledge_base.json换成你们自己的内部文档; - 把
DEEPSEEK_API_KEY换成真实的 Key,确认用的模型名称正确; - 在此基础上加一个简单 Web 界面,就可以给同事试用了。
更多推荐


所有评论(0)