一、RAG 是什么?为什么它如此重要?

在当前大模型(LLM)如日中天的背景下,检索增强生成(Retrieval-Augmented Generation, RAG)已成为最热门、最实用的 AI 应用架构之一。它的核心思想非常直观:不让大模型“凭空造答案”,而是先从你的私有知识库中检索相关信息,再基于这些信息生成回答

这种模式兼顾了大模型强大的语言能力与私有数据的准确性,尤其适合构建企业知识库问答、客服系统、智能文档助手等场景。本文将从原理出发,拆解 RAG 全链路,并手把手带你构建一个可运行的企业知识库问答系统。

二、RAG 架构全链路拆解

一个完整的 RAG 系统包含五个关键环节:

  1. 文档分块(Chunking):将原始文档(如 PDF、Word、网页等)切割成适合检索的小片段。
  2. 向量化(Embedding):通过嵌入模型(如 text-embedding-ada-002、bge 系列)将文本块转换为高维向量。
  3. 存储(Storage):将向量及其元数据存入向量数据库。
  4. 检索(Retrieval):用户提问时,将问题向量化,并在向量库中查找最相似的上下文。
  5. 生成(Generation):将检索到的上下文与用户问题拼接,输入大模型生成最终回答。

整个流程如下图所示:

三、向量数据库在 RAG 中的核心作用

向量数据库(如 Milvus、Qdrant、Weaviate、Pinecone)是 RAG 系统的“记忆中枢”。它的核心价值在于:

  • 高效存储高维向量:支持百万甚至十亿级向量的快速写入。
  • 近似最近邻检索(ANN):在毫秒级时间内从海量数据中召回语义最相近的文本块。
  • 支持元数据过滤:例如只检索“2024年发布”的文档,或“产品A”的FAQ。

没有向量数据库,RAG 就无法在大规模知识库上实时响应。传统数据库无法高效处理高维向量的相似性计算,而向量数据库专为此设计。

四、混合检索:关键词 + 语义,效果更佳

纯向量检索虽强,但在某些场景下仍有局限:例如用户使用专业术语或拼写错误时,语义相似度可能失效。因此,混合检索策略成为工业级 RAG 系统的标配。

常见混合方法包括:

  • RRF(Reciprocal Rank Fusion):分别对关键词检索(如 BM25)和向量检索的结果按排名加权融合,无需调整参数。
  • 加权融合:对两种检索结果的相关性分数加权(如 0.6 * 语义分数 + 0.4 * BM25 分数)。
  • 级联检索:先用关键词缩小范围,再在子集中做向量检索。

混合检索能显著提升召回率,尤其在长尾问题或术语密集场景中效果突出

五、如何评估 RAG 系统效果?

RAG 不是“能跑就行”,效果需量化评估。核心指标包括:

  1. 召回率(Recall@K):在 Top-K 检索结果中,是否包含真正相关的文档?这是衡量检索质量的关键。
  2. 答案相关性(Answer Relevance):生成的答案是否准确、有用?可通过人工评分或 LLM-as-a-Judge(如使用 GPT-4 打分)评估。
  3. 延迟(Latency):从用户提问到返回答案的总耗时。企业级系统通常要求 <2 秒。
  4. 上下文利用率:大模型是否真的使用了检索到的上下文?可通过消融实验对比“有无上下文”的回答差异。

建议构建自己的测试集:包含典型问题、边缘案例、错误输入等,避免依赖公开数据集脱离实际业务。

六、实战:构建企业知识库问答系统

下面是一个简化但可运行的 RAG 示例,使用 Python + Qdrant + OpenAI API(或开源 LLM)。

1. 环境准备

pip install qdrant-client openai langchain python-dotenv

2. 文档分块与向量化

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings

# 假设已有文本内容
text = "你的企业知识库内容..."
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50
)
chunks = text_splitter.split_text(text)

embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
vectors = embeddings.embed_documents(chunks)

3. 存入向量数据库(Qdrant)

from qdrant_client import QdrantClient
from qdrant_client.models import PointStruct, VectorParams

client = QdrantClient(":memory:")  # 可改为实际地址
client.create_collection(
    collection_name="kb_rag",
    vectors_config=VectorParams(size=1536, distance="Cosine")
)

points = [
    PointStruct(id=i, vector=vectors[i], payload={"text": chunks[i]})
    for i in range(len(chunks))
]
client.upsert(collection_name="kb_rag", points=points)

4. 检索 + 生成

from openai import OpenAI

def rag_query(question: str):
    # 向量化问题
    q_vec = embeddings.embed_query(question)
    
    # 检索 Top-3
    hits = client.search(
        collection_name="kb_rag",
        query_vector=q_vec,
        limit=3
    )
    
    context = "\n".join([hit.payload["text"] for hit in hits])
    
    # 构造 prompt
    prompt = f"""
    你是一个企业知识助手,请根据以下上下文回答问题。
    上下文:
    {context}
    
    问题:{question}
    回答:
    """
    
    client = OpenAI()
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[{"role": "user", "content": prompt}]
    )
    return response.choices[0].message.content

5. 部署建议

  • 生产环境:使用持久化 Qdrant 服务(Docker 或云托管)。
  • 模型选择:若数据敏感,可替换为开源嵌入模型(如 BAAI/bge-small-zh-v1.5)和本地 LLM(如 ChatGLM、Qwen)。
  • 缓存机制:对高频问题做缓存,降低延迟和成本。

七、总结与进阶方向

RAG 是连接大模型与企业私有知识的桥梁。掌握其全链路原理与实现细节,是构建实用 AI 应用的关键一步

未来可探索的方向包括:

  • 动态分块策略:根据文档结构智能切分(如基于标题、表格边界)。
  • 查询改写(Query Rewriting):用 LLM 对用户问题重写,提升检索精度。
  • RAG 与微调结合:对高频错误场景做针对性微调,形成闭环优化。

记住:RAG 的价值不在于技术炫酷,而在于解决真实业务问题。从一个可运行的小系统开始,逐步迭代,你就能打造出真正有用的企业级 AI 问答助手。

下期预告:《向量数据库出海必修课:安全、合规与企业级治理全解析》,敬请期待!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐