一、為什么要重排序?

       重新排序是檢索過程中的一個步驟,根據某些標準對最初檢索到的結果進行進一步排序、細化或重新排序,以提高其相關性或準確性。

       這里有一個例子:想象一下,你正在搜索有關企鵝的信息。當你輸入搜索查詢時,系統會很快彈出幾篇關于不同類型企鵝的文章。這些結果是基于通用相關性檢索獲得的。

       現在,假設前幾篇文章是關于“南極企鵝”的,但你真正想要的是關于“動物園棲息地的企鵝”的信息,那么就需要對這幾篇文章進行重新排序了,比如使用用戶行為、特定關鍵字或更復雜的算法來進行該操作。這可能會使有關動物園棲息地的文章在列表中排名更高,降低有關南極洲的文章的排名。這一步驟確保最相關或最有用的信息出現在頂部,使您更容易找到您要查找的內容。

       本質上,重新排序微調了最初檢索到的結果,基于特定標準或用戶偏好提供了一組更具針對性和相關性的文檔或信息。

二、基于嵌入的檢索有什么問題?

使用基于嵌入的檢索有許多優點:

  1. 使用向量點積快速計算,并且在查詢推理期間不需要調用任何模型
  2. 嵌入可以對文檔和查詢進行語義編碼,并可以根據查詢檢索出高度相關的文檔。

? ? ? ?然而,盡管有這些優點,基于嵌入的檢索有時準確性不高,并返回與查詢相關的無關上下文,這會大大降低RAG系統的整體質量。

? ? ? ?針對上述問題,可以借鑒推薦系統召回和排序兩個階段來解決。第一階段基于嵌入召回出相關性最高的top-k個文檔,該階段注重召回而非準確性。第二階段是對召回的top-k個文檔進行重新排序。

三、代碼實現

模型zephyr-7b-alpha

嵌入模型:hkunlp/instructor-large

3.1 加載數據

? ? ? ?LlamaIndex通過數據連接器Reader來加載數據,數據連接器可以加載不同數據源的數據,并將數據格式化為Document對象,Document對象會存儲文本和對應的元數據(未來會存儲圖像和音頻)。

PDFReader = download_loader("PDFReader")
loader = PDFReader()
docs = loader.load_data(file=Path("QLoRa.pdf"))

3.2 分塊

? ? ?我們將文本分割成512大小的分塊來創建節點Node。Node是LlamaIndex中的原子數據單元,表示源文檔的“塊”。節點包含元數據以及與其他節點的關系信息。

node_parser = SimpleNodeParser.from_defaults(chunk_size=512)
nodes = node_parser.get_nodes_from_documents(docs)

3.3 開源LLM和嵌入

       我們將使用開源大模型zephyr-7b-alpha,并對其進行量化,量化后的模型可以運行在Colab免費的T4 GPU上。

? ? ? ?在本例中,我們將使用hkunlp/instructor-large指令微調的文本嵌入模型,它可以通過簡單地提供任務指令來生成針對任何任務(例如,分類、檢索、聚類、文本評估等)定制的文本嵌入,而無需任何微調。在MTEB排行榜(https://huggingface.co/spaces/mteb/leaderboard)上排名第14!

from google.colab import userdata

# huggingface and cohere api token
hf_token = userdata.get('hf_token')

quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
)

def messages_to_prompt(messages):
prompt = ""
for message in messages:
if message.role == 'system':
prompt += f"<|system|>\n{message.content}</s>\n"
elif message.role == 'user':
prompt += f"<|user|>\n{message.content}</s>\n"
elif message.role == 'assistant':
prompt += f"<|assistant|>\n{message.content}</s>\n"

# ensure we start with a system prompt, insert blank if needed
if not prompt.startswith("<|system|>\n"):
prompt = "<|system|>\n</s>\n" + prompt

# add final assistant prompt
prompt = prompt + "<|assistant|>\n"

return prompt

# LLM
llm = HuggingFaceLLM(
model_name="HuggingFaceH4/zephyr-7b-alpha",
tokenizer_name="HuggingFaceH4/zephyr-7b-alpha",
query_wrapper_prompt=PromptTemplate("<|system|>\n</s>\n<|user|>\n{query_str}</s>\n<|assistant|>\n"),
context_window=3900,
max_new_tokens=256,
model_kwargs={"quantization_config": quantization_config},
# tokenizer_kwargs={},
generate_kwargs={"temperature": 0.7, "top_k": 50, "top_p": 0.95},
messages_to_prompt=messages_to_prompt,
device_map="auto",
)

# Embedding
embed_model = HuggingFaceInstructEmbeddings(
model_name="hkunlp/instructor-large", model_kwargs={"device": DEVICE}
)

3.4 配置索引和檢索器

      首先,我們將設置ServiceContext對象,并使用它來構造索引和查詢。

索引是一種由Document對象組成的數據結構,大模型可以使用該索引進行查詢相關上下文。

? ? ? ?VectorStoreIndex是最常見和最易于使用的索引,支持在大規模數據語料庫上進行檢索,包括獲取“top-k”個最相似的節點,并將它們傳遞到“響應合成”模塊。

# ServiceContext
service_context = ServiceContext.from_defaults(llm=llm,
embed_model=embed_model
)

# index
vector_index = VectorStoreIndex(
nodes, service_context=service_context
)

# configure retriever
retriever = VectorIndexRetriever(
index=vector_index,
similarity_top_k=10,
service_context=service_context)

3.5 初始化重排序器

我們會評估以下3個重新排序器的性能:

# Define all embeddings and rerankers
RERANKERS = {
"WithoutReranker": "None",
"CohereRerank": CohereRerank(api_key=cohere_api_key, top_n=5),
"bge-reranker-base": SentenceTransformerRerank(model="BAAI/bge-reranker-base", top_n=5),
"bge-reranker-large": SentenceTransformerRerank(model="BAAI/bge-reranker-large", top_n=5)
}

3.6 檢索比較

       檢索器定義了在給定查詢時如何有效地從索引中檢索相關上下文。

       節點后處理器:節點后處理器接收一組檢索到的節點,并對它們進行轉換、過濾或重新排序操作。節點后處理器通常在節點檢索步驟之后和響應之前應用于查詢引擎中。

? ? ? ?讓我們創建一些助手函數來執行我們的任務:

# helper functions

def get_retrieved_nodes(
query_str, reranker
):
query_bundle = QueryBundle(query_str)

retrieved_nodes = retriever.retrieve(query_bundle)

if reranker != "None":
retrieved_nodes = reranker.postprocess_nodes(retrieved_nodes, query_bundle)
else:
retrieved_nodes

return retrieved_nodes

def pretty_print(df):
return display(HTML(df.to_html().replace("\\n", "<br>")))

def visualize_retrieved_nodes(nodes) -> None:
result_dicts = []
for node in nodes:
node = deepcopy(node)
node.node.metadata = None
node_text = node.node.get_text()
node_text = node_text.replace("\n", " ")

result_dict = {"Score": node.score, "Text": node_text}
result_dicts.append(result_dict)

pretty_print(pd.DataFrame(result_dicts))

讓我們可視化查詢的結果:

query_str = "What are the top features of QLoRA?"

# Loop over rerankers
for rerank_name, reranker in RERANKERS.items():
print(f"Running Evaluation for Reranker: {rerank_name}")

query_bundle = QueryBundle(query_str)

retrieved_nodes = retriever.retrieve(query_bundle)

if reranker != "None":
retrieved_nodes = reranker.postprocess_nodes(retrieved_nodes, query_bundle)
else:
retrieved_nodes

print(f"Visualize Retrieved Nodes for Reranker: {rerank_name}")
visualize_retrieved_nodes(retrieved_nodes)

沒有重新排序–頂部節點的相似性得分為0.87,這是baseline分數。

CohereRebank——頂部節點的相似性得分為0.988。

bge reranker base——頂部節點的相似性得分為0.72。

四、性能評價

       現在,我們將使用RetrieverEvaluator來評估我們的Retriever的質量。

       我們定義了各種評估指標,如命中率hit-rateMRR,這些指標根據每個特定問題的ground-truth文本來評估檢索結果的質量。為了簡化評估數據集的構造,我們采用了合成數據生成方法。

       MRR( Mean Reciprocal Rank)表示平均倒數排名,是一個國際上通用的對搜索算法進行評價的機制,并且只評估排名前10個的排名感知相關性得分。第一個結果匹配,分數為1,第二個匹配分數為0.5,第n個匹配分數為1/n,如果沒有匹配的句子分數為0。最終的分數為所有得分之和。

        hit-rate衡量檢索到的結果中至少包含一個與基本事實相關的項目的查詢的比例或百分比。例如,想象一個搜索引擎返回一個文檔列表來響應用戶的查詢。這里的基本事實是指該查詢的已知相關文檔,通常由人類判斷或標記數據確定。hit-rate計算搜索結果至少包含一個相關文檔的頻率。

4.1 構建(查詢、上下文)對的評估數據集

      我們可以手動構建問題+Node id的檢索評估數據集。Llamaindex通過generate_question_context_pairs函數在現有文本語料庫上提供合成數據集生成。使用大模型根據每個上下文塊自動生成問題,可以參閱:https://docs.llamaindex.ai/en/stable/module_guides/evaluating/usage_pattern_retrieval.html

? ? ? ?這里,我們使用Zephr-7B在現有的文本語料庫上構建一個簡單的評估數據集,返回的結果是一個EmbeddingQAFinetuneDataset對象(包含queries、relevant_docs和corpus)。

# Prompt to generate questions
qa_generate_prompt_tmpl = """\
Context information is below.

---------------------
{context_str}
---------------------

Given the context information and not prior knowledge.
generate only questions based on the below query.

You are a Professor. Your task is to setup \
{num_questions_per_chunk} questions for an upcoming \
quiz/examination. The questions should be diverse in nature \
across the document. The questions should not contain options, not start with Q1/ Q2. \
Restrict the questions to the context information provided.\
"""

# Evaluator

qa_dataset = generate_question_context_pairs(
nodes, llm=llm, num_questions_per_chunk=2, qa_generate_prompt_tmpl=qa_generate_prompt_tmpl
)
# helper function for displaying results
def display_results(reranker_name, eval_results):
"""Display results from evaluate."""

metric_dicts = []
for eval_result in eval_results:
metric_dict = eval_result.metric_vals_dict
metric_dicts.append(metric_dict)

full_df = pd.DataFrame(metric_dicts)

hit_rate = full_df["hit_rate"].mean()
mrr = full_df["mrr"].mean()

metric_df = pd.DataFrame({"Reranker": [reranker_name], "hit_rate": [hit_rate], "mrr": [mrr]})

return metric_df

?Llamaindex提供了一個函數,用于在批處理模式下對數據集運行RetrieverEvaluator

query_str = "What are the top features of QLoRA?"

results_df = pd.DataFrame()
# Loop over rerankers
for rerank_name, reranker in RERANKERS.items():
print(f"Running Evaluation for Reranker: {rerank_name}")

query_bundle = QueryBundle(query_str)

retrieved_nodes = retriever.retrieve(query_bundle)

if reranker != "None":
retrieved_nodes = reranker.postprocess_nodes(retrieved_nodes, query_bundle)
else:
retrieved_nodes

retriever_evaluator = RetrieverEvaluator.from_metric_names(
["mrr", "hit_rate"], retriever=retriever
)

eval_results = await retriever_evaluator.aevaluate_dataset(qa_dataset)

current_df = display_results(rerank_name, eval_results)
results_df = pd.concat([results_df, current_df], ignore_index=True)

4.2 結果

WithoutReranker:為每個嵌入提供了baseline;

CohereRerank:是SOTA結果;

bge-reranker-base:結果比CohereRerank差,也許是因為該模型對這種重新排序無效;

bge-reranker-large:結果比bge-reranker-base差,也許是因為該模型對這種重新排序無效。

     結果表明重新排序在優化檢索過程中的重要性,尤其是CohereRebank模型。

五、結論

      為搜索選擇適當的嵌入至關重要;即使是最有效的重新排序也無法彌補較差的基本搜索結果(比如bge-rerankers)。

? ? ? 最大限度地提高檢索器的性能取決于發現嵌入和重新排序的最佳組合。這仍然是一個活躍的研究領域,來確定最有效的組合。

本文章轉載微信公眾號@ArronAI

熱門推薦
一個賬號試用1000+ API
助力AI無縫鏈接物理世界 · 無需多次注冊
3000+提示詞助力AI大模型
和專業工程師共享工作效率翻倍的秘密
返回頂部
上一篇
開源| 伯克利AI分布式框架Ray,兼容TensorFlow、PyTorch與MXNet
下一篇
Open-R1 技術解密:HuggingFace 如何完整復現 DeepSeek 推理模型
国内精品久久久久影院日本,日本中文字幕视频,99久久精品99999久久,又粗又大又黄又硬又爽毛片
国产三级三级三级精品8ⅰ区| 精品久久久久久久久久久院品网| 色综合天天综合色综合av| 日韩三级av在线播放| 91精选在线观看| 蜜桃视频一区二区三区| 日韩精品影音先锋| 激情文学综合丁香| 精品处破学生在线二十三| 麻豆精品视频在线观看免费| 精品国产凹凸成av人网站| 国产精品白丝av| 一区二区中文视频| 欧美丰满少妇xxxxx高潮对白| 午夜久久久久久久久| 日韩一本二本av| 成人av影视在线观看| 一区二区三区av电影 | 国产精一区二区三区| 国产日韩v精品一区二区| 99热在这里有精品免费| 一区二区高清在线| 日韩视频免费观看高清完整版| 国产在线精品免费| 亚洲综合男人的天堂| 精品久久久三级丝袜| 色综合久久88色综合天天免费| 一个色在线综合| 欧美国产综合一区二区| 555夜色666亚洲国产免| www.色综合.com| 男男视频亚洲欧美| 亚洲综合色婷婷| 国产精品久久久久影院亚瑟 | 国产欧美一区二区在线| 欧美精品丝袜久久久中文字幕| 风流少妇一区二区| 六月婷婷色综合| 亚洲大片在线观看| 综合久久一区二区三区| 久久久蜜臀国产一区二区| 欧美日韩一区二区三区四区五区| 不卡av免费在线观看| 国产在线精品视频| 久久成人免费网站| 蜜桃视频一区二区| 美腿丝袜亚洲综合| 久久国内精品自在自线400部| 亚洲午夜羞羞片| 亚洲另类一区二区| 亚洲欧美日韩在线| 亚洲欧美日韩在线播放| 日韩伦理av电影| 亚洲精品写真福利| 亚洲最快最全在线视频| 亚洲精品自拍动漫在线| 一区二区高清在线| 亚洲一区二区三区自拍| 依依成人精品视频| 亚洲国产精品久久艾草纯爱| 亚洲午夜精品网| 日韩精品欧美成人高清一区二区| 亚洲一区二区三区中文字幕在线| 亚洲综合成人在线视频| 日韩激情中文字幕| 国产一区二区三区免费在线观看| 国产精品免费看片| 一区二区在线观看免费 | 国产亚洲欧美日韩日本| 成人欧美一区二区三区白人| 一区二区三区产品免费精品久久75| 亚洲一区二区三区自拍| 另类小说视频一区二区| 99久久精品国产一区二区三区| 色狠狠综合天天综合综合| 91精品久久久久久蜜臀| 欧美国产日本视频| 日韩在线观看一区二区| 国产99久久久国产精品免费看| 91蝌蚪porny| 久久精品人人做人人综合 | 国产视频一区二区在线观看| 一区二区三区四区视频精品免费 | 国产一区二区久久| 在线亚洲高清视频| 久久嫩草精品久久久精品| 国产麻豆视频精品| 欧美视频在线播放| 久久人人97超碰com| 亚洲最快最全在线视频| 欧美日韩aaa| 亚洲激情自拍视频| 国产精品白丝jk黑袜喷水| 色婷婷综合久久久久中文一区二区| 欧美色网一区二区| 中文幕一区二区三区久久蜜桃| 亚洲国产综合人成综合网站| 国产成人精品影院| 欧美高清激情brazzers| 国产色产综合色产在线视频| 亚洲不卡av一区二区三区| 国产精品99久久久久久久女警| 色域天天综合网| 久久精品一级爱片| 国产视频在线观看一区二区三区| 天堂va蜜桃一区二区三区漫画版| 成人免费观看视频| 欧美变态tickle挠乳网站| 亚洲精品视频自拍| 成人综合激情网| 久久久国产精品麻豆| 国产精品视频你懂的| 亚洲天堂成人在线观看| jvid福利写真一区二区三区| 日韩高清在线电影| 欧美r级在线观看| 亚洲视频在线观看一区| 欧美人与性动xxxx| 91免费视频网| 国产欧美日韩精品一区| 国产精品一区三区| 中文字幕亚洲在| 国产98色在线|日韩| 日韩一级免费观看| 日韩国产一二三区| 51久久夜色精品国产麻豆| 亚洲电影一区二区| 色婷婷一区二区| 欧美一级二级在线观看| 韩国精品久久久| 国产校园另类小说区| 成人精品国产福利| 亚洲视频一区在线观看| 欧美性大战久久| 日韩高清电影一区| 中文字幕第一区综合| 在线观看日韩高清av| 日本成人在线电影网| 欧美精品一区二区精品网| 成人免费黄色大片| 国产精品私人自拍| 欧美一区二区三区在线观看视频| 国产一区二区h| 亚洲综合成人网| 日韩片之四级片| 不卡免费追剧大全电视剧网站| 悠悠色在线精品| 欧美不卡在线视频| av在线一区二区| 国产精品一二三四区| 樱桃视频在线观看一区| 精品处破学生在线二十三| 99精品国产热久久91蜜凸| 国产精品久久久久久福利一牛影视 | 国产精品乱码人人做人人爱 | 日韩欧美你懂的| 色综合天天天天做夜夜夜夜做| 激情图片小说一区| 天堂资源在线中文精品| 亚洲综合免费观看高清完整版| 精品久久久久久亚洲综合网 | 国产精品伊人色| 国产主播一区二区三区| 日韩不卡一区二区三区| 午夜精品免费在线| 亚洲欧洲日韩av| 中文字幕在线一区二区三区| 精品国产精品一区二区夜夜嗨| 欧美成人猛片aaaaaaa| 欧美日韩国产美| 欧美日高清视频| 在线亚洲一区观看| 欧美久久久一区| 在线精品观看国产| 欧美视频在线播放| 欧美性色欧美a在线播放| 欧美日韩黄色一区二区| av亚洲精华国产精华精华| 国产福利视频一区二区三区| 轻轻草成人在线| 亚洲成人www| 激情五月激情综合网| 亚洲婷婷综合色高清在线| 亚洲丝袜另类动漫二区| 国产午夜精品福利| 久久这里只有精品6| aaa亚洲精品| 国产精品影视天天线| 亚洲国产精品成人久久综合一区| 欧美日韩精品系列| 国产日韩欧美综合在线| 久久99热狠狠色一区二区| 偷拍一区二区三区四区| 亚洲va欧美va人人爽午夜| 日韩av电影免费观看高清完整版 | 91精品国产福利在线观看 | 亚洲成人精品影院| 国精产品一区一区三区mba桃花 | 91精品麻豆日日躁夜夜躁| 91蜜桃视频在线|