电商 RAG 知识库切片与重排质量调优

日期:2026-07-15

一、项目背景

我们为 XpShop 智能客服搭建初版 RAG 问答时,遇到最棘手的不是模型能力,而是知识库本身的组织质量。客服坐席每天面对海量商品手册、售后政策与订单 FAQ,文档来源杂乱:有运营手工维护的 Excel,有产品部导出的 PDF 手册,还有散落在 Wiki 里的临时公告。初版直接把整篇文档按固定 500 字窗口切片、丢进向量库检索,结果答非所问频繁出现。一个典型负例:用户问"七天无理由退货的运费谁承担",模型却从相邻段落拼出"质量问题由商家承担"并信誓旦旦编成政策。更糟的是,遇到知识库没有的内容,模型会凭空生成看似合理的退货规则,导致一线频繁被投诉,甚至引发过一次客诉升级。这个项目里,我们决定把精力从"换更大模型"转向"把检索与重排做扎实",因为复盘发现约八成的幻觉来自检索阶段喂错了上下文,模型背了不该背的锅。底座侧也配合我们,把 RAG 知识库层从"能跑通"升级为"可调优",把切片、向量化、重排做成可配置流水线。

二、落地场景

落地的核心场景围绕三类高咨询量文档展开。第一是商品手册,包含规格参数、适用人群与禁忌说明,长尾问题多;第二是售后政策,覆盖退换货、质保、运费规则,条款之间容易交叉引用;第三是订单 FAQ,处理物流、开票、改地址等高频问题,用户表述口语化严重。客服会话时,我们采用的 AI 私有化部署底座中的 RAG 知识库层会先对问题做意图识别与改写,再实时检索相关政策片段,拼接进提示词交给大模型生成回复,同时把命中来源一并回传给坐席,方便核验。整套链路跑在我们采用的技术平台之上,数据不出内网,满足客户对隐私与合规的硬性要求。上线后覆盖约 12 个客服小组,日均检索调用约 8 万次。知识库文档总量约 30 万条切片,更新频率最高的售后政策做到小时级同步。

三、关键技术挑战与解决思路

语义切片防截断。 固定长度切片最大的问题是把"运费规则"这一句和"质保期限"那一句强行拼在一个 chunk 里,检索时噪声极大,模型容易被相邻段落带偏。我们改用基于语义边界的递归切片,先按 Markdown/标题层级切,再在段落内用句向量相似度判断是否该继续合并。关键配置如下:

chunk_strategy:
  method: semantic_recursive
  max_tokens: 320
  overlap: 48
  split_by: [heading, paragraph, sentence]
  embed_model: bge-large-zh-v1.5
  merge_threshold: 0.62   # 句向量余弦低于此值则断开

实践中我们发现 overlap 设太小会切断跨句指代,设太大又引入重复噪声,最终 48 token 是召回与精度的平衡点。同时我们为每条政策标注了结构化元数据(类目、生效时间、适用区域),检索时不只算文本相似,还做元数据过滤,把"区域不适用"的文档直接排除,这一步单独把误召降了约 6 个百分点。

向量+BM25 混合检索与重排。 纯向量检索对精确关键词(如订单号格式、SKU 编码、特定活动编号)不敏感,而 BM25 恰好补强。我们采用双路召回再融合:

# 双路召回,RRF 融合
vec_hits = vector_db.search(query_emb, top_k=20)
bm25_hits = bm25_index.search(query, top_k=20)
fused = rrf_merge(vec_hits, bm25_hits, k=60)
reranked = cross_encoder.predict(fused[:30], query)  # bge-reranker-large
top3 = reranked[:3]

重排模型用 bge-reranker-large,把融合后的 30 条送进去打分,取前 3 条进上下文。重排配置片段:

reranker:
  model: bge-reranker-large
  candidate_pool: 30
  final_k: 3
  batch_size: 8

重排阶段是质量分水岭:融合召回的 30 条里常混着标题相关但正文无关的文档,Reranker 能把它压到后排,显著减少"看起来像答案其实不是"的干扰。

无出处拒答防幻觉。 我们给生成环节加了一道硬约束:只有当检索返回的 top-k 中存在与问题语义相关度超过阈值的片段时,才允许模型作答;否则直接走"未能在知识库中找到确切依据,建议转人工"分支。提示词里明确写入"只能引用提供的来源,禁止推断政策条款"。

if max(top3_scores) < 0.35:
    return route_to_human(query)   # 无出处,强制转人工

阈值 0.35 是我们用约 500 条边界样本标出的最优切点:再低会放进来幻觉,再高会误伤可答问题。这条规则上线后,政策类幻觉投诉基本归零。

四、效果数据

改造前后核心指标对比如下(脱敏示意值):

指标改造前改造后说明
检索命中率约 71%约 92%top-3 命中正确政策片段
转人工率约 38%约 19%含无出处拒答分支
回答准确率约 76%约 94%抽样 2000 条人工评测
平均处理时长约 95 秒约 52 秒含检索+生成+人工核验

案例片段(已脱敏):重排前后 top-k 召回质量对比。同一问题"退货的运费由谁出",初版纯向量检索 top-5 中仅 2 条相关(命中率 40%);引入 BM25 融合+Reranker 后,top-5 相关条数升至 5 条(命中率 100%),相关片段排名由第 3、5 位升至第 1、2 位,模型据此生成"非质量问题运费由买家承担"的准确结论,误答归零。

五、可复用经验总结

第一,切片粒度决定 RAG 效果的上限。我们后来复盘,语义切片相对固定切片把命中率直接拉高约 20 个百分点,这比换模型更划算,也更易迁移。第二,没有出处就不生成,这是防幻觉最朴素也最有效的准则,宁可多转人工,也不能让模型编政策,这一点要写进提示词和代码两道闸门。第三,混合检索不是简单堆叠,向量负责语义、BM25 负责关键词,二者靠 Reranker 收敛,工程上要控制候选池规模避免重排耗时拖累延迟。第四,元数据过滤常被忽视,但它能把"区域/时间不适用"的干扰项在检索前就拦掉,是性价比极高的优化。第五,阈值类参数要用边界样本标切点,别拍脑袋。这套链路我们已沉淀为底座的标准 RAG 流水线,后续接新客户文档基本可复用,新项目接入周期从两周压缩到两三天。