F FisherHub Docs

RAG 应用开发

RAG 的基本原理

RAG(Retrieval-Augmented Generation)是目前解决 LLM 知识更新和幻觉问题的主流方案。其核心思路是:在模型生成答案前,先从外部知识库中检索相关内容,将检索结果作为上下文注入提示词

为什么需要 RAG

问题纯 LLM 方案RAG 方案
知识截止日期训练数据截止后无法更新实时检索最新信息
幻觉模型可能编造事实答案有检索结果支撑
领域知识通用模型不擅长垂直领域可接入企业知识库
成本微调成本高无需重新训练

标准 RAG 流程

用户问题 → 向量化 → 向量检索 → 文档重排序 → LLM 生成 → 返回回答

                    向量数据库(存储 Embedding)

1. 文档预处理

from langchain.text_splitter import RecursiveCharacterTextSplitter

def prepare_documents(docs):
    splitter = RecursiveCharacterTextSplitter(
        chunk_size=500,
        chunk_overlap=50,
        separators=["\n\n", "\n", "。", "!", "?", ".", "!", "?", " "]
    )
    chunks = splitter.split_documents(docs)
    return chunks

选择合适的 chunk 大小是关键。太小的 chunk 会丢失上下文,太大会引入噪声。中文场景建议使用分句符号作为分隔符。

2. Embedding 模型选择

Embedding 模型将文本转换为向量。选择时需考虑:

  • 维度:高维度保留更多信息但存储和检索成本高
  • 语言支持:中文场景需要中英双语或多语言模型
  • 最大输入长度:决定单次编码的文本上限

常用 Embedding 模型:

模型维度最大长度特点
text-embedding-3-small15368192OpenAI,性价比高
BGE-large-zh1024512中文优化,开源免费
m3e-base768512轻量中文模型
jina-embeddings-v27688192支持长文本
from langchain.embeddings import OpenAIEmbeddings

embeddings = OpenAIEmbeddings(
    model="text-embedding-3-small",
    dimensions=512  # 通过 API 参数压缩维度
)

3. 向量数据库

向量数据库负责存储 Embedding 并支持高效的近似最近邻(ANN)搜索。

# 使用 Chroma(本地开发推荐)
from langchain.vectorstores import Chroma

vector_store = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./chroma_db"
)

# 检索
results = vector_store.similarity_search_with_score(
    query="什么是 RAG?",
    k=4  # 返回 top-4
)

生产环境推荐使用 Qdrant、Milvus 或 Pinecone,它们支持分布式部署和更复杂的过滤逻辑。

4. 重排序(Re-ranking)

初次检索结果可能包含不相关的内容。使用重排序模型对结果重新打分,可以显著提升最终质量。

from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import CohereRerank

compressor = CohereRerank(model="rerank-multilingual-v2.0")
compression_retriever = ContextualCompressionRetriever(
    base_compressor=compressor,
    base_retriever=vector_store.as_retriever(search_kwargs={"k": 10})
)

compressed_docs = compression_retriever.get_relevant_documents(query)

5. 生成增强回答

from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI

qa_chain = RetrievalQA.from_chain_type(
    llm=ChatOpenAI(model="gpt-4o-mini", temperature=0),
    chain_type="stuff",  # 将检索结果全部塞入上下文
    retriever=vector_store.as_retriever(search_kwargs={"k": 4}),
    return_source_documents=True
)

result = qa_chain.invoke("为什么 RAG 能减少幻觉?")
print(result["result"])
print("来源:", [doc.metadata["source"] for doc in result["source_documents"]])

进阶优化

HyDE(假设性文档检索)

先用 LLM 生成一个假设性答案,再用这个答案去检索相似文档。当用户问题简短或措辞模糊时效果显著。

多路召回

同时从向量数据库、全文搜索引擎(如 Elasticsearch)和知识图谱中检索,合并结果后重排序。

查询改写

用户的原始问题可能不适合直接检索。先用 LLM 将其改写成更适合搜索的形式。

def rewrite_query(original_query, history):
    prompt = f"""
    历史对话:{history}
    用户原始问题:{original_query}
    任务:将用户问题改写成更适合检索的形式,保持原意。
    改写结果:
    """
    return llm.invoke(prompt)

评估 RAG 系统

指标测量内容优化方向
Recall@k检索结果是否覆盖正确答案chunk 大小、检索算法
MRR正确答案在结果中的排位重排序模型
忠实度生成内容是否基于检索结果提示词设计
答案相关性回答是否匹配问题生成模型选择