← 返回文章列表
AI

如何用 RAG 搭建私有知识库问答系统

大语言模型(LLM)虽然强大,却有两个明显短板:知识截止日期幻觉问题。当你问它公司的内部流程或最新的产品参数时,它要么回答"我不知道",要么一本正经地胡说。RAG(Retrieval-Augmented Generation,检索增强生成)正是解决这个问题的钥匙——它在 LLM 生成答案之前,先从你的私有知识库中检索相关文档,让模型基于真实资料作答。

本文将带你从零搭建一个 RAG 知识库问答系统,覆盖完整的技术链路。

RAG 的核心架构

RAG 的工作流程可以概括为三个阶段:

  1. 索引(Indexing):将你的文档切分、向量化并存入向量数据库
  2. 检索(Retrieval):根据用户问题,从向量数据库中召回最相关的文档片段
  3. 生成(Generation):将检索到的片段和用户问题一起发给 LLM,生成最终答案

这套架构的优势在于:知识是动态更新的(更新文档即可,无需重新训练模型),答案可溯源(每个回答都能追溯到原文),且幻觉大幅减少

第一步:文档处理与切分

原始文档(PDF、Markdown、网页等)不能直接使用。需要先提取纯文本,然后切分成合适大小的 chunk:

from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,        # 每个 chunk 约 500 字符
    chunk_overlap=50,      # 相邻 chunk 重叠 50 字符,保持上下文连贯
    separators=["\n\n", "\n", "。", ".", " ", ""]
)

chunks = text_splitter.split_documents(documents)
chunk_size 是关键参数:太大则检索精度下降、超出 LLM 上下文窗口;太小则丢失上下文。中文内容建议 300-800 字符,英文 500-1000 字符。务必保留 overlap 避免关键信息被截断。

第二步:向量化(Embedding)

将文本 chunk 转换成高维向量,语义相近的文本在向量空间中距离也近:

from openai import OpenAI

client = OpenAI()
def get_embedding(text: str) -> list[float]:
    response = client.embeddings.create(
        model="text-embedding-3-small",
        input=text
    )
    return response.data[0].embedding

2026 年主流的 Embedding 模型包括 OpenAI text-embedding-3-large(3072 维)、Google text-embedding-004,以及开源方案如 bge-large-zh-v1.5(中文效果好)。

第三步:向量数据库选型与写入

向量数据库负责高效存储和检索海量向量。常见选择:

import chromadb

client = chromadb.PersistentClient(path="./knowledge_db")
collection = client.get_or_create_collection("company_docs")

for i, chunk in enumerate(chunks):
    collection.add(
        ids=[f"doc_{i}"],
        embeddings=[get_embedding(chunk.page_content)],
        documents=[chunk.page_content],
        metadatas=[{"source": chunk.metadata.get("source", "")}]
    )

第四步:检索 Pipeline

用户提问后,将问题向量化,在数据库中做相似度搜索:

def retrieve(query: str, top_k: int = 5):
    query_embedding = get_embedding(query)
    results = collection.query(
        query_embeddings=[query_embedding],
        n_results=top_k
    )
    return results["documents"][0]

进阶技巧:使用 HyDE(假设文档嵌入)先让 LLM 生成一个假设答案,再拿假设答案去检索——对短查询效果提升明显。还可以引入 重排序(Re-ranking),用 Cross-Encoder 对召回结果二次打分。

第五步:LLM 生成答案

def generate_answer(query: str, contexts: list[str]) -> str:
    prompt = f"""你是一个专业的企业知识助手。请严格基于以下资料回答问题。
如果资料中找不到答案,请明确说"根据现有资料无法回答",不要编造。

【参考资料】
{"\n\n".join(contexts)}

【用户问题】
{query}

【回答】"""
    
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.2
    )
    return response.choices[0].message.content

关键设计:明确限制 LLM 不要编造提供引用来源让用户自行核实,以及低 temperature 保证回答稳定。

实践中的常见坑

总结

RAG 是 2026 年 AI 应用开发中最实用的模式之一。完整的落地路径是:文档处理 → 向量化 → 存储 → 检索 → 生成 → 界面。对于快速验证,LangChain + ChromaDB + Streamlit 三天就能跑通 MVP;对于生产级部署,建议将检索和生成解耦为独立微服务,方便独立扩展和监控。

掌握了 RAG,你就可以为律所搭建案件检索助手、为电商搭建产品问答机器人、为企业搭建内部 wiki 助手——可能性无穷。