RAG检索增强生成系统部署实践:从分块策略到推理加速的全链路优化

RAG系统架构概述

检索增强生成(RAG)通过将外部知识库与大语言模型结合,缓解模型幻觉问题,提升回答的事实准确性。其核心流程分为三个阶段:文档预处理与向量化、语义检索、生成回答。企业部署RAG系统时,性能瓶颈集中在检索质量和推理延迟两个维度。

文档分块策略对检索质量的影响

分块(Chunking)是RAG系统的第一步,直接决定检索召回率。固定长度分块实现简单,但容易截断语义完整的段落。基于句号或段落标记的分块能保留语义完整性,适用于结构化文档。

对于技术文档,推荐使用重叠分块(Overlapping Chunks),相邻块之间保留10%-20%的重叠内容,避免关键信息被切断。以下是一个基于LangChain的分块实现:

from langchain_text_splitters import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,
    chunk_overlap=64,
    separators=["\n\n", "\n", "。", "!", "?", ";", " ", ""],
    length_function=len
)

chunks = text_splitter.split_text(document_text)
print(f"分块数量: {len(chunks)}")

chunk_size设为512 tokens是经验值,在大多数embedding模型上表现稳定。中文文档需要特别注意分隔符设置,中文标点符号应纳入separators列表。

Embedding模型选型与向量化

向量化阶段选择Embedding模型,直接影响语义检索的精度。开源模型中,BGE-M3和m3e-base在中文场景表现优于多数商用API。BGE-M3支持稠密检索、稀疏检索和多向量检索三种模式,覆盖多语言场景。

向量化时需注意维度对齐。以BGE-M3为例,输出维度为1024,存入向量数据库时需确保collection的维度配置一致:

from FlagEmbedding import BGEM3FlagModel

model = BGEM3FlagModel('BAAI/bge-m3', use_fp16=True)

embeddings = model.encode(
    chunks,
    batch_size=12,
    max_length=8192,
    return_dense=True,
    return_sparse=False,
    return_colbert_vecs=False
)

dense_embeddings = embeddings['dense_vecs']  # shape: (n, 1024)

向量数据库选型与索引优化

Milvus和Qdrant是目前主流的开源向量数据库。Milvus 2.4+版本支持GPU加速的IVF_FLAT和HNSW索引。HNSW(分层可导航小世界图)在召回率和查询速度之间取得了较好的平衡,适合大多数RAG场景。

HNSW索引的关键参数:

# Milvus HNSW索引参数
index_params = {
    "index_type": "HNSW",
    "metric_type": "COSINE",
    "params": {
        "M": 16,          # 每层最大连接数,影响内存占用和召回率
        "efConstruction": 200  # 建图时的搜索宽度,影响索引质量
    }
}

M值设为16在百万级向量量级下内存可控,efConstruction=200能保证建图质量。查询时通过ef参数控制搜索宽度,ef=64在多数场景下召回率可达95%以上。

混合检索提升召回率

纯向量检索存在语义漂移问题——语义相近但事实不符的文档也会被检索到。引入BM25关键词检索与向量检索融合,可显著提升召回精度。这套方案称为混合检索(Hybrid Search)。

实现思路是同时执行BM25和向量检索,再通过倒数排名融合(RRF)合并结果:

import numpy as np
fromRank_bm25 import BM25Okapi

def hybrid_search(query, vector_db, bm25_corpus, top_k=10, alpha=0.5):
    # 向量检索
    vec_results = vector_db.search(query_embedding, top_k=top_k * 2)
    
    # BM25检索
    tokenized_query = query.split()
    bm25 = BM25Okapi(bm25_corpus)
    bm25_scores = bm25.get_scores(tokenized_query)
    bm25_top = np.argsort(bm25_scores)[-top_k * 2:][::-1]
    
    # RRF融合
    rrf_scores = {}
    for rank, doc_id in enumerate(vec_results):
        rrf_scores[doc_id] = rrf_scores.get(doc_id, 0) + 1 / (50 + rank)
    for rank, doc_id in enumerate(bm25_top):
        rrf_scores[doc_id] = rrf_scores.get(doc_id, 0) + alpha / (50 + rank)
    
    return sorted(rrf_scores.items(), key=lambda x: x[1], reverse=True)[:top_k]

重排序模型进一步过滤噪声

检索阶段返回的候选集存在一定比例的噪声文档。重排序模型(Reranker)对query-doc对进行精细化的相关性打分,能将Top-k的准确率提升10%-20%。

BGE-Reranker-v2-m3是目前中文场景表现突出的开源重排序模型,推理速度相对可控:

from FlagEmbedding import FlagReranker

reranker = FlagReranker('BAAI/bge-reranker-v2-m3', use_fp16=True)

pairs = [[query, doc] for doc in candidate_docs]
scores = reranker.compute_score(pairs, normalize=True)

# 按分数排序,取Top-5
ranked = sorted(zip(candidate_docs, scores), key=lambda x: x[1], reverse=True)[:5]

上下文窗口管理与Prompt构建

检索到相关文档后,需要构建Prompt送入LLM生成回答。上下文窗口管理的关键在于Token预算分配。假设LLM支持8K tokens,推理回答预留1500 tokens,系统提示和对话历史预留1000 tokens,则检索文档可用预算约5500 tokens。

def build_prompt(query, retrieved_docs, max_context_tokens=5500):
    context = ""
    current_tokens = 0
    
    for i, doc in enumerate(retrieved_docs):
        doc_tokens = count_tokens(doc)  # 使用tokenizer精确计算
        if current_tokens + doc_tokens > max_context_tokens:
            break
        context += f"\n[文档{i+1}]\n{doc}\n"
        current_tokens += doc_tokens
    
    prompt = f"""你是一个技术问答助手。根据以下检索到的文档回答问题。如果文档中没有相关信息,请明确说明无法回答。

参考文档:
{context}

问题:{query}

回答:"""
    return prompt

推理延迟优化方案

RAG系统的端到端延迟由检索延迟和推理延迟两部分组成。检索阶段在HNSW索引下,百万级向量查询时间可控制在50ms以内。瓶颈在于LLM推理。vLLM和TensorRT-LLM是两种主流的推理加速方案。

vLLM通过PagedAttention机制优化KV Cache管理,吞吐量相比HuggingFace Transformers提升10-20倍。部署时推荐使用AWQ或GPTQ量化模型,在精度损失可控的前提下将显存占用降低至原来的1/4:

# vLLM部署量化模型
from vllm import LLM, SamplingParams

llm = LLM(
    model="Qwen/Qwen2.5-14B-Instruct-AWQ",
    quantization="awq",
    tensor_parallel_size=2,      # 2卡并行
    gpu_memory_utilization=0.9,
    max_model_len=8192
)

sampling_params = SamplingParams(temperature=0.7, max_tokens=1500)
outputs = llm.generate(prompts, sampling_params)

评估指标与持续优化

RAG系统上线后需要建立量化评估体系。核心指标包括检索阶段的Recall@k(召回率)和MRR(平均倒数排名),生成阶段的答案准确率和忠实度。RAGAS框架提供了自动化评估方案:

from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy, context_precision

result = evaluate(
    dataset={
        "question": questions,
        "answer": answers,
        "contexts": retrieved_contexts,
        "ground_truth": ground_truths
    },
    metrics=[faithfulness, answer_relevancy, context_precision]
)
print(result)

faithfulness衡量回答是否忠实于检索文档,answer_relevancy衡量回答与问题的相关性,context_precision衡量检索文档的精确率。三项指标均高于0.8时,系统达到可用标准。定期用bad case驱动分块策略和检索参数调整,能实现持续优化。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/rag-jian-suo-zeng-qiang-sheng-cheng-xi-tong-bu-shu-shi-jian/

(0)
小编小编
上一篇 1天前
下一篇 1天前

相关推荐