混合搜索:将BM25和语义搜索与Langchain结合起来以获得更好的结果

2023年12月14日 由 alex 发表 1978 0

了解BM25:


BM25是信息检索系统中使用的排名算法,用于估计文档与给定搜索查询的相关性。


  • 它的作用:它会检查你的搜索词在文档中出现的频率,并考虑文档的长度以提供最相关的结果。
  • 为什么它有用:它非常适合对巨大的文档集合进行排序,比如数字图书馆,不会偏向较长的文档或过度使用的词汇。


BM25的关键元素:


  • 词频(TF):这个统计了你的搜索词在文档中出现的次数。
  • 逆文档频率(IDF):这个给予稀有词更多的重要性,确保常见词不会占主导地位。
  • 文档长度规范化:这确保较长的文档不会不公平地统治结果。
  • 查询词饱和度:这阻止过分重复的词汇扭曲结果。


score(d, q) = ∑(tf(i, d) * idf(i) * (k1 + 1)) / (tf(i, d) + k1 * (1 - b + b * (dl / avgdl)))


BM25/关键词搜索何时理想?


  • 大型文档集合:非常适合需要处理大量信息的大型数据库。
  • 防止偏见:很适合平衡词频和文档长度。
  • 一般信息检索:在各种搜索场景中都有用,提供了简单与有效性的混合。


实际应用:构建混合搜索系统


想象你正在为一个大型数字图书馆打造搜索系统。你不仅希望它能找到带有特定关键字的文档,也希望它能把握每个查询背后的上下文和语义。方法如下:


  • 步骤1:BM25快速获取带有搜索关键词的文档。
  • 步骤2:VectorDB更深入地寻找与上下文有关的文档。
  • 步骤3:集合检索器(Ensemble Retriever)运行两个系统,结合它们的发现,并重新排序结果,向用户展示一个细致全面的文档集。


什么是混合搜索?


混合搜索可以被想象成一个放大镜,它不仅仅看表面,而且会深入探究。它是一种两管齐下的方法:


  • 关键词搜索:这是我们最熟悉的老方法。输入一个词或短语,这种搜索会专注于数据库或文档集合中那些确切的术语或紧密相关的词语。
  • 向量搜索:与其对应项不同,向量搜索对仅仅是单词并不满足。它使用语义意义工作,旨在洞察查询的潜在上下文或意义。这确保了即使你的词语与文档不完全相符,如果意义相关,它也将被获取。


7


我们来看看代码片段。在这里,我们将使用带有LanceDB向量存储的langchain。


# example of using bm25 & lancedb -hybrid serch
from langchain.vectorstores import LanceDB
import lancedb
from langchain.retrievers import BM25Retriever, EnsembleRetriever
from langchain.schema import Document
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.document_loaders import PyPDFLoader
# Initialize embeddings
embedding = OpenAIEmbeddings()


并加载一个单独的PDF文件。


# load single pdf
loader = PyPDFLoader("/content/Food_and_Nutrition.pdf")
pages = loader.load_and_split()


创建BM25稀疏关键词匹配检索器


# Initialize the BM25 retriever
bm25_retriever = BM25Retriever.from_documents(pages)
bm25_retriever.k =  2  # Retrieve top 2 results


创建lancedb向量存储以进行密集型语义搜索/检索。


db = lancedb.connect('/tmp/lancedb')
table = db.create_table("pandas_docs", data=[
    {"vector": embedding.embed_query("Hello World"), "text": "Hello World", "id": "1"}
], mode="overwrite")

# Initialize LanceDB retriever
docsearch = LanceDB.from_documents(pages, embedding, connection=table)
retriever_lancedb = docsearch.as_retriever(search_kwargs={"k": 2})


现在将两个检索器组装起来,在这里你可以为它分配权重。


# Initialize the ensemble retriever
ensemble_retriever = EnsembleRetriever(retrievers=[bm25_retriever, retriever_lancedb],
                                       weights=[0.4, 0.6])
# Example customer query
query = "which food needed for building strong bones and teeth ?
 which Vitamin & minerals importat for this?"

# Retrieve relevant documents/products
docs = ensemble_retriever.get_relevant_documents(query)


利用集成检索器,它尝试在文档中搜索每个词语,例如“强健的骨骼和牙齿”,同时它还通过使用lancedb进行搜索,这将基于相似性找到最相似的文档。


from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(openai_api_key="sk-yourapikey")
#if you want to use opensource models such as lama,mistral check this 
# https://github.com/lancedb/vectordb-recipes/blob/main/tutorials/chatbot_using_Llama2_&_lanceDB
qa = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=ensemble_retriever)
query = "what nutrition needed for pregnant women  "
qa.run(query)


在数据库中使用BM25算法搜索关键词——“孕妇营养”,并返回最佳匹配结果。同时,我们也在使用LanceDB来进行这项工作。这展示了它在提取文本时更强大的能力。


8


以下是回答。


9



文章来源:https://medium.com/etoai/hybrid-search-combining-bm25-and-semantic-search-for-better-results-with-lan-1358038fe7e6
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
写评论取消
回复取消