什么是 RAG 重排?
重排 = 从“初步检索的一堆候选文档”里,再挑出最相关的那几个
重排在干嘛?
它会做一件更“聪明”的事:
让模型直接判断:这个文档能不能回答这个问题?
而不是只看向量距离。
—-say by gpt老师
这里讲一种最经典的重排方法吧
1 Cross-Encoder(最经典🔥)
1.1 首先安装库
1
| !pip install sentence-transformers
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| # 模拟数据
documents = [
{"id": 1, "text": "RAG 是一种结合检索和生成的技术"},
{"id": 2, "text": "Embedding 用于文本向量化"},
{"id": 3, "text": "RAG 中重排可以提升检索结果的相关性"},
{"id": 4, "text": "搜索引擎的发展历史"},
]
#模拟问题
query = "embedding的作用"
|
1.2 召回
当然重排是在召回的后面的,我们要先召回,对得到的list[documet]重排,召回的步骤就很熟悉了吧,这边省略的文本切割还是挺快的
ps;我这里vector_store.similarity_search_with_score用的是这种检索方法,所以呢就是我得到的不是list[documet],而是list[(document,score ) ]这种二维元组列表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| # ===== 步骤1:向量检索(粗排)=====
print("=" * 50) print("步骤1: 向量检索 (Top-4)") print("=" * 50)
#注意哦检索完返回的是list[(document,score)] 一个元组数列
initial_results = vector_store.similarity_search_with_score(query, k=4) print(len(initial_results))
#查看检索结束的数组里面是不是有重复的
for doc,score in initial_results: print(1 / (1 + score)) print(doc.page_content + "\n")
for i, (doc, distance) in enumerate(initial_results, 1): similarity = 1 / (1 + distance) print(f"{i}. 相似度: {similarity:.4f} | {doc.page_content[:30]}...")
|
1.3 配对
这个我感觉有点弱智的地方,向量检索器接收的是一个str,但是词匹配用的检索器,接收的是一个元组(问题,chunk)或者这种元组列表,
所以呢我们需要准备一个配对好的列表给这个检索器排序
1 2
| #配对,像对比配偶一样,是个二维数组,这个我们需要继续用第一轮召回得到数据嘛 pairs = [[query, doc.page_content] for doc, _ in initial_results]
|
配对后就是排序了
1.4 排序
zip的作用是把两个列表变成一个
list_a = [a1, a2, a3]
list_b = [b1, b2, b3]
zip(list_a, list_b) # → [(a1,b1), (a2,b2), (a3,b3)]
1 2 3 4 5 6 7 8 9
|
reranked = sorted(
zip(initial_results, rerank_scores), key=lambda x: x[1], reverse=True )
|