手把手教你用DeepSeek+LangGraph搭建企业级RAG知识库

开发者实战教程DeepSeekLangGraphRAG向量数据库检索增强企业知识库开发者教程2026-10-04

手把手教你用DeepSeek+LangGraph搭建企业级RAG知识库

1. 环境准备与模型选型对比

先跑通最小链路,再替换组件。需要这些:

  • Python 3.11+
  • DeepSeek API Key(开放平台创建,模型名 deepseek-chat、deepseek-reasoner)
  • LangGraph + LangChain
  • 一个向量库,本地开发用 Qdrant 或 Chroma,生产用 Milvus/pgvector
  • Embedding 模型,中文场景常用 BGE-M3 或 bge-large-zh-v1.5
  • Docker(部署阶段)
安装:

pip install -U langgraph langchain langchain-openai langchain-community
pip install -U qdrant-client sentence-transformers

DeepSeek 兼容 OpenAI 接口,用 ChatOpenAI 指向 https://api.deepseek.com 即可。

import os
from langchain_openai import ChatOpenAI

llm = ChatOpenAI( model='deepseek-chat', api_key=os.environ['DEEPSEEK_API_KEY'], base_url='https://api.deepseek.com', temperature=0, )

模型选型对比:

模型/服务主要用途延迟成本倾向注意
DeepSeek deepseek-chat生成答案、查询改写、引用校验低-中按 token 计费默认选它,适合 RAG 生成
DeepSeek deepseek-reasoner复杂多跳推理、难查询规划高高于 chat不是所有请求都值得用
BGE-M3多语言 Embedding,支持长文本取决于硬件自托管无 API 费需要 GPU/CPU 资源
bge-large-zh-v1.5中文短文本检索低自托管中文效果好,长文本要切
云端 Embedding API快速上线低按量计费评估数据出境与合规
选型建议:RAG 的瓶颈通常在检索,不在生成。先用 `deepseek-chat` 做生成,把预算花在切分、Embedding 和重排序上。`deepseek-reasoner` 只在查询改写或复杂对比题上开,避免全量走高延迟链路。

LangGraph 最小状态图:

from typing import TypedDict, List
from langgraph.graph import StateGraph, END

class RAGState(TypedDict): question: str docs: List[dict] answer: str

def retrieve(state: RAGState): # 调向量库,返回 docs return {'docs': []}

def generate(state: RAGState): # 拼上下文,调 DeepSeek return {'answer': ''}

graph = StateGraph(RAGState) graph.add_node('retrieve', retrieve) graph.add_node('generate', generate) graph.set_entry_point('retrieve') graph.add_edge('retrieve', 'generate') graph.add_edge('generate', END) app = graph.compile()

这段先不求跑通,后面把 retrieve 和 generate 填实。

2. 文档切分、Embedding与向量库选型

切分决定检索上限。企业文档常见 PDF、Word、Confluence、飞书导出。先做解析,再切。

切分策略:

  • 按标题层级切:#、##、### 作为边界,保留章节路径。
  • 段落太长再递归切:chunk 500–1000 tokens,overlap 100–200。
  • 表格、代码、FAQ 单独处理,不要按字符硬切。
  • 每个 chunk 带元数据:source、page、section、version、access_level。
from langchain_text_splitters import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter( chunk_size=800, chunk_overlap=150, separators=['## ', '### ', '\n\n', '\n', '。', ' '], ) chunks = splitter.split_text(raw_text)

Embedding 选型:

方案维度最大长度适合不适合
BGE-M310248192多语言、混合检索无 GPU 时慢
bge-large-zh-v1.51024512中文短段长文档、多语言
text-embedding-3-large30728191英文、云端快速成本与数据合规
向量库选型:
向量库部署规模过滤混合检索适用
Qdrant单机/Docker/K8s中-大强原生稀疏+密集快速开发到生产
MilvusK8s/集群大强支持大规模企业
pgvectorPostgreSQL 扩展中SQL 过滤需自己拼 BM25已有 PG 的团队
Chroma本地/单机小一般弱Demo、原型
如果已有 PostgreSQL,pgvector 最省运维;如果要 10 亿级向量和独立扩缩容,Milvus;要开发快、过滤灵活,Qdrant 折中。不要一开始上集群,先用 Qdrant 单机跑通。

入库代码示意:

from qdrant_client import QdrantClient
from sentence_transformers import SentenceTransformer

client = QdrantClient(path='./qdrant_data') model = SentenceTransformer('BAAI/bge-m3')

def embed(texts): return model.encode(texts, normalize_embeddings=True).tolist()

client.recreate_collection( collection_name='kb', vectors_config={'size': 1024, 'distance': 'Cosine'}, )

3. 检索增强与重排序策略

单路向量检索会漏关键词。企业文档里型号、错误码、合同条款,必须用混合检索。

流程:

flowchart LR Q[用户问题] --> QW[查询改写] QW --> V[向量检索] QW --> B[BM25/稀疏检索] V --> RRF[RRF 融合] B --> RRF RRF --> RR[重排序] RR --> CC[上下文压缩] CC --> G[DeepSeek 生成] G --> C[引用校验]

查询改写用 deepseek-chat,输出 3–5 个变体。多跳问题拆子查询。改写不是为了好看,是为了覆盖不同表述。

混合检索:向量 top 20 + BM25 top 20,用 RRF 融合。RRF 公式简单:

def rrf(rank_lists, k=60):
    scores = {}
    for ranks in rank_lists:
        for i, doc_id in enumerate(ranks):
            scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + i + 1)
    return sorted(scores, key=scores.get, reverse=True)

重排序:取融合后 top 20,送交叉编码器。常用 BAAI/bge-reranker-v2-m3,云端可用 Cohere Rerank、Jina Reranker。重排后取 top 5–8 给模型。重排能明显减少“检索到了但排后面”的问题,代价是延迟。

from sentence_transformers import CrossEncoder

reranker = CrossEncoder('BAAI/bge-reranker-v2-m3')

def rerank(question, docs, top_k=6): pairs = [(question, d['text']) for d in docs] scores = reranker.predict(pairs) ranked = sorted(zip(docs, scores), key=lambda x: x[1], reverse=True) return [d for d, _ in ranked[:top_k]]

LangGraph 节点拆法:

  • rewrite_query:改写问题,保留原问题。
  • retrieve:并行走向量和 BM25。
  • fuse:RRF。
  • rerank:交叉编码器。
  • compress:只留与问题相关的句子,减少 token。
  • generate:DeepSeek 生成,要求带引用编号。
  • verify:检查每个引用是否支持对应句子。
上下文压缩用 LLM 或小模型都行。长上下文会推高成本,也会让模型分心。把 20 段压到 6 段,比换更贵的生成模型更有效。

4. 幻觉抑制与评测指标

幻觉抑制靠流程,不靠一句“不要编造”。

系统提示模板:

你是企业知识库助手。只允许根据 <context> 回答。
每条结论后标注来源编号,如 [1]。
如果 <context> 没有答案,直接说“当前知识库没有找到依据”,不要推测。
如果用户问题涉及权限,先检查 access_level。

生成后做引用校验。用 deepseek-chat 判断:答案中的每个事实句是否能被对应引用支持。不支持的句子删掉或标“未验证”。

verify_prompt = '''
上下文:
{context}

答案: {answer}

逐句检查答案是否被上下文支持。输出 JSON: {"supported": true/false, "unsupported_sentences": []} '''

评测分两层:检索和生成。

层级指标含义怎么测
检索Hit Rate@ktop k 是否含正确文档人工标 100 条问答
检索MRR正确文档排名倒数均值同上
检索NDCG@k排序质量有分级相关性时
生成Faithfulness答案是否忠于上下文RAGAS
生成Answer Relevance答案是否切题RAGAS
生成Context Precision上下文里有多少相关RAGAS
生成Context Recall应召回的上下文是否召回RAGAS
RAGAS 跑法:
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy, context_precision

result = evaluate( dataset, metrics=[faithfulness, answer_relevancy, context_precision], ) print(result)

没有黄金集就先标 50 条。覆盖三类:单文档事实、跨文档对比、无答案拒答。每次改切分、Embedding、重排、提示词,都跑同一套集。只看几个问答的体感,会把回归漏掉。

拒答也是指标。无答案集上的正确拒答率要单独统计。企业场景里,编造一条错误政策比答不出更贵。

5. 部署上线与成本优化

上线架构:

flowchart TB U[用户] --> API[FastAPI] API --> LG[LangGraph 服务] LG --> VDB[向量库] LG --> RR[重排服务] LG --> DS[DeepSeek API] LG --> PG[(Postgres Checkpointer)] API --> OBS[日志/监控]

FastAPI 暴露 /chat,请求体带 user_id、question、tenant_id。权限过滤必须在检索阶段做,不能只在生成阶段藏答案。

from fastapi import FastAPI
from pydantic import BaseModel

class ChatReq(BaseModel): question: str user_id: str tenant_id: str

app = FastAPI()

@app.post('/chat') def chat(req: ChatReq): state = {'question': req.question, 'docs': [], 'answer': ''} result = app_graph.invoke(state) return {'answer': result['answer'], 'sources': result['docs']}

LangGraph 的持久化用 Postgres 或 Redis 做 checkpointer。多轮对话、人工审核、失败重试都需要状态。别把状态放进程内存,扩副本会丢。

成本控制清单:

  • Embedding 缓存:文档不变就不重复算。
  • 查询缓存:相同问题走缓存,设 TTL。
  • 批处理:离线入库用 batch,不要一条一条调。
  • 分层检索:先用小模型/BM25 粗筛,再向量精排。
  • 上下文压缩:只留相关句,减少输入 token。
  • 模型分流:简单问答走 deepseek-chat,复杂推理才用 deepseek-reasoner。
  • 输出限制:max_tokens 按业务设上限。
  • 监控 token:按租户、接口、模型记录消耗。
  • 缓存命中:DeepSeek 提供上下文缓存,命中后输入价格更低,具体折扣看官方定价页。
  • 冷热分离:热数据留向量库,冷数据归档。
安全与合规:
  • 多租户隔离:collection 或 filter 必须带 tenant_id。
  • PII 脱敏:入库前识别手机号、身份证、银行卡。
  • 审计日志:记录谁在何时问了什么、命中了哪些文档。
  • 权限同步:文档权限变更后,向量库元数据要跟着更新。
部署顺序建议:先单机 Docker Compose 跑 API + Qdrant + Postgres,压测 50 并发;再上 K8s,把重排服务独立扩缩容。DeepSeek API 是外部依赖,要设超时、重试和降级:重排挂了就退回向量 top 5,生成挂了就返回检索结果。

可操作下一步:拿你手头 50 份文档,按本文切分入库,标 30 条问答,记录 Hit Rate@5 和 Faithfulness。如果 Hit Rate 低于预期,先查切分和 Embedding;如果 Faithfulness 低,先查重排和引用校验提示词。

推荐视频:B 站搜索“LangGraph RAG 教程”“DeepSeek API 实战”,腾讯视频、优酷、抖音也有相关开发者分享。视频内容随版本变化,请以 LangChain、LangGraph、DeepSeek 官方文档为准。本文不绑定具体视频链接,避免失效后误导。免责声明:视频为第三方内容,不代表本文验证其准确性。

PREMIUM

需要完整版教程?

包含详细步骤、视频演示、提示词模板和可下载资料包。微信支付即时获取。

购买完整版 ¥29.90