/ RAG  LangChain  向量数据库  知识库  大模型  检索增强生成  Milvus  AI应用 

企业级 RAG 知识库实战:从文档入库到混合检索全链路优化


封面

什么是 RAG?为什么企业需要它

大语言模型(LLM)虽然强大,但存在两大天然局限:知识截止日期无法访问私有数据。当你问 ChatGPT 关于公司内部产品文档、最新的行业报告或私有数据库时,它要么一无所知,要么"幻觉"出一个听起来合理但完全错误的答案。

RAG(Retrieval-Augmented Generation,检索增强生成)正是为解决这一问题而生。它的核心思路是:先检索、后生成——在调用 LLM 之前,先从知识库中检索出与问题最相关的文档片段,将其作为上下文一并喂给模型,从而让模型基于真实、最新的私有数据来回答问题。

  • 解决 LLM 知识时效性问题,无需频繁微调模型

  • 保护企业私有数据,文档不离开本地/私有云

  • 回答可溯源,每条答案都能关联到原始文档片段

  • 成本远低于全量微调,适合快速迭代

RAG 架构全景:从文档入库到问答响应

一个完整的 RAG 系统分为两个阶段:离线索引阶段在线查询阶段

离线索引阶段(文档入库):

  1. 文档加载(PDF、Word、网页、数据库等)

  2. 文本清洗与预处理(去除噪声、格式标准化)

  3. 文档切片(Chunking)

  4. 向量化(Embedding)

  5. 存入向量数据库

在线查询阶段(问答响应):

  1. 用户提问 → Query 向量化

  2. 向量相似度检索(召回 Top-K 文档片段)

  3. (可选)精排/重排序

  4. 拼装 Prompt(系统指令 + 检索结果 + 用户问题)

  5. 调用 LLM 生成最终答案

文档切片策略:决定 RAG 质量的关键

切片(Chunking)是 RAG 中最容易被忽视但影响最大的环节。切得太大,单个 chunk 包含过多无关信息,噪声大;切得太小,语义不完整,检索效果差。

常见切片策略对比:

  • 固定长度切片:简单粗暴,按字符数或 token 数切分,适合均匀文本

  • 递归字符切片:LangChain 默认策略,按段落→句子→词语层级递归,效果较好

  • 语义切片:基于句子 embedding 相似度,在语义断点处切分,质量最高但耗时

  • 父子切片(Parent-Child):小 chunk 用于检索,大 chunk 用于生成,兼顾精准和完整

from langchain.text_splitter import RecursiveCharacterTextSplitter

# 推荐配置:chunk_size=512,overlap=64
splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,
    chunk_overlap=64,
    separators=["\n\n", "\n", "。", "!", "?", " ", ""]
)

docs = splitter.split_documents(raw_docs)
print(f"切片数量: {len(docs)}")
print(f"示例片段: {docs[0].page_content[:200]}")

向量数据库选型:2025 年主流方案横评

向量数据库是 RAG 的"记忆中枢",直接影响检索速度和精度。以下是当前主流选项的对比:

  • Chroma:轻量级,纯 Python,本地开发首选,不适合生产大规模场景

  • Milvus:开源旗舰,支持十亿级向量,生产环境主流选择,支持混合检索

  • Weaviate:自带 BM25+向量混合检索,GraphQL API,适合复杂查询场景

  • Qdrant:Rust 编写,高性能低内存,支持 payload 过滤,云原生友好

  • pgvector:PostgreSQL 扩展,已有 PG 基础设施的团队零迁移成本

from langchain_community.vectorstores import Milvus
from langchain_openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

# 连接 Milvus 并建立索引
vectorstore = Milvus.from_documents(
    documents=docs,
    embedding=embeddings,
    collection_name="company_knowledge_base",
    connection_args={"host": "localhost", "port": "19530"},
)

# 相似度检索
retriever = vectorstore.as_retriever(
    search_type="mmr",          # 最大边际相关,减少重复
    search_kwargs={"k": 6, "fetch_k": 20}
)

混合检索与重排序:进阶优化让召回率提升30%

纯向量检索在关键词精确匹配场景(如产品型号、人名、专有名词)表现欠佳。混合检索结合 BM25(稀疏检索)和向量检索(稠密检索),能显著提升召回全面性。

from langchain.retrievers import EnsembleRetriever, BM25Retriever

# BM25 稀疏检索
bm25_retriever = BM25Retriever.from_documents(docs)
bm25_retriever.k = 4

# 向量稠密检索
dense_retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

# 混合检索:加权融合
hybrid_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, dense_retriever],
    weights=[0.3, 0.7]   # 向量检索权重更高
)

在混合检索之后,还可以加入重排序(Reranking)模型(如 Cohere Rerank、BGE-Reranker),对召回的候选文档再次精排,进一步提升最终 Top-K 的质量。实测在企业 FAQ 场景中,加入重排序后 MRR@5 提升约 28%。

以下是完整的 RAG Chain 组装示例:

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)

prompt = ChatPromptTemplate.from_template("""
你是一个专业的企业知识库助手。请严格基于以下参考文档回答用户问题。
如果文档中没有相关信息,请明确说明"我在知识库中未找到相关信息",不要凭空编造。

参考文档:
{context}

用户问题:{question}

请用中文回答:
""")

def format_docs(docs):
    return "\n\n---\n\n".join(
        f"【来源: {doc.metadata.get('source', '未知')}】\n{doc.page_content}"
        for doc in docs
    )

rag_chain = (
    {"context": hybrid_retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

# 使用
answer = rag_chain.invoke("公司差旅报销的上限是多少?")
print(answer)

至此,一个具备混合检索、可溯源、低幻觉的企业级 RAG 知识库问答系统就搭建完成了。根据实际业务场景,还可以继续扩展:引入 HyDE(假设性文档嵌入)提升 query 质量、使用 RAPTOR 做层次化索引处理长文档、以及接入 LangSmith 做 RAG 全链路评估与监控。

发布评论

热门评论区: