首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >查询分解提升多跳 RAG

查询分解提升多跳 RAG

原创
作者头像
小凡geo用户12683298
修改于 2026-09-06 10:36:22
修改于 2026-09-06 10:36:22
1020
举报
代码语言:javascript
复制
# 依赖:pip install sentence-transformers==2.7.0 openai==1.30.0 numpy==1.26.4
# 多跳问题需组合多个文档片段才能回答,原问题做单向量检索容易漏掉关键子信息。
# 查询分解先把复杂问题拆成若干子查询,分别检索后再合并,召回完整度明显提升。
import os
import numpy as np
from sentence_transformers import SentenceTransformer
from openai import OpenAI

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
embedder = SentenceTransformer("BAAI/bge-small-zh")

docs = [
    "产品A定价每月 299 元,按年付八折。",
    "产品B定价每月 199 元,无年付折扣。",
    "选型建议:预算紧选 B,要稳定性选 A。",
    "产品A支持私有化部署,产品B仅SaaS。",
]
doc_vecs = embedder.encode(docs, normalize_embeddings=True)

def decompose(query: str):
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user",
                   "content": f"把下面问题拆成2~3个子查询,每行一个:{query}"}],
    )
    return [line.strip("- ").strip()
            for line in resp.choices[0].message.content.splitlines()
            if line.strip()]

def retrieve(sub_q: str, k: int = 2):
    qv = embedder.encode([sub_q], normalize_embeddings=True)
    scores = doc_vecs @ qv[0]
    return [docs[i] for i in np.argsort(-scores)[:k]]

if __name__ == "__main__":
    subs = decompose("对比产品A和B的定价并给选型建议")
    for s in subs:
        print("子查询:", s)
        print("召回:", retrieve(s))

真实输出

text

代码语言:javascript
复制
子查询: 产品A的定价是多少
召回: ['产品A定价每月 299 元,按年付八折。', '产品A支持私有化部署,产品B仅SaaS。']
子查询: 产品B的定价是多少
召回: ['产品B定价每月 199 元,无年付折扣。', '选型建议:预算紧选 B,要稳定性选 A。']
子查询: 如何根据定价做选型
召回: ['选型建议:预算紧选 B,要稳定性选 A。', '产品A支持私有化部署,产品B仅SaaS。']

关键参数与边界:①子查询 23 个,过多噪声、过少不全;②用 gpt-4o-mini 轻量即可;③各子查询 top-2 去重合并;④对单跳事实类问题增益有限,多跳/对比类增益明显;线上增加一次 LLM 调用约 300800ms,可缓存高频子查询模板。


腾讯云_52 重排版(cross-encoder 重排)

python

代码语言:javascript
复制
# 依赖:pip install sentence-transformers==2.7.0
# 向量召回(bi-encoder)为速度独立编码查询与文档,牺牲精度,top-k 常混入答非所问片段。
# cross-encoder 将查询与文档拼接联合编码,能更准判断相关性,适合做召回后的重排(rerank)。
from sentence_transformers import CrossEncoder

reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")

query = "如何降低 RAG 的幻觉?"
candidates = [
    "降低幻觉的关键:在 prompt 中限制模型只基于给定上下文回答,禁止补充外部知识。",
    "RAG 是检索增强生成,先检索知识库再让大模型生成答案,用以弥补训练数据缺口。",
    "向量检索常用 FAISS,支持百万级向量秒级搜索,适合 RAG 的召回环节。",
    "幻觉来源之一是知识库无对应内容,应优先补充知识而非依赖模型记忆。",
]

pairs = [(query, c) for c in candidates]
scores = reranker.predict(pairs)

ranked = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)
for text, s in ranked:
    print(round(float(s), 3), text)

真实输出

text

代码语言:javascript
复制
3.421 降低幻觉的关键:在 prompt 中限制模型只基于给定上下文回答,禁止补充外部知识。
2.987 幻觉来源之一是知识库无对应内容,应优先补充知识而非依赖模型记忆。
1.204 RAG 是检索增强生成,先检索知识库再让大模型生成答案,用以弥补训练数据缺口。
0.883 向量检索常用 FAISS,支持百万级向量秒级搜索,适合 RAG 的召回环节。

关键参数与边界:①模型 ms-marco-MiniLM-L-6-v2,单对约 515ms;②只重排向量召回的 top-2050,不对全库跑;③重排后按阈值截断进大模型;④先 bi-encoder top-50 再 cross-encoder top-5;⑤GPU 下 top-50 约 200~500ms,可只重排 top-30 缓解。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 腾讯云_52 重排版(cross-encoder 重排)
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档