首页 > 编程问答 >如何增强LangChain和FAISS多查询检索的相关性

如何增强LangChain和FAISS多查询检索的相关性

时间:2024-08-03 15:50:37浏览次数:14  
标签:python langchain llama ollama faiss

我正在为一个专注于冥想和灵性的项目开发一个使用 LangChain 和 FAISS 的多查询检索系统。我当前的设置涉及生成用户查询的变体以改进文档检索。

但是,我遇到一个问题,即检索到的文档通常与查询主题无关。

对于嵌入,我使用“经济嵌入文本”模型。我已将 335 本 PDF 书籍嵌入到矢量数据库中。

这是我用于生成查询变体和检索文档的代码:

from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.llms import Ollama
from langchain.retrievers import MultiQueryRetriever
from langchain.schema import StrOutputParser

# Load the FAISS database
new_db = FAISS.load_local("bookdb", embedder, allow_dangerous_deserialization=True)

# Define the prompt template for generating question variations
QUERY_PROMPT = PromptTemplate(
    input_variables=["question"],
    template="""You are an AI language model assistant. Generate five variations of the following question, maintaining the core meaning but using different phrasings or perspectives. Ensure all variations remain highly relevant to the topic of meditation.
    Original question: {question}"""
)

# Initialize the Ollama model
ollama = Ollama(model="llama3.1")

# Define the chain for generating question variations
question_variation_chain = LLMChain(
    llm=ollama,
    prompt=QUERY_PROMPT,
    output_parser=StrOutputParser(key="lines")
)

# Define the retriever
retriever = MultiQueryRetriever(
    retriever=new_db.as_retriever(),
    llm_chain=question_variation_chain
)

# Example query
question = "How to start a meditation?"

# Run the retriever
results = retriever.invoke(question)
print("Number of unique documents found:", len(results))

# Process the results to ensure uniqueness and sort by score
unique_results = {r.page_content: r for r in results}.values()
sorted_results = sorted(unique_results, key=lambda x: x.metadata.get('score', 0), reverse=True)

print(f"Number of unique documents found: {len(sorted_results)}")

for i, result in enumerate(sorted_results, 1):
    print(f"\nResult {i}:")
    print(f"Content: {result.page_content[:200]}...")  # Print first 200 characters
    print(f"Metadata: {result.metadata}")

生成的查询变体是相关的,但检索到的文档似乎与主题不匹配好吧。

例如,通过查询“如何开始冥想?”,即使我所有的书都是关于冥想和灵性的,我也会得到不相关的文档。


根据提供的信息,我发现有几个方面可以改进的LangChain和FAISS多查询检索系统的相关性:

1. 嵌入模型:

  • “经济嵌入文本”模型可能不是最佳选择: 虽然它速度快且资源效率高,但对于语义相似性,可能存在更强大的嵌入模型。
  • 考虑使用专门针对语义搜索的模型: 例如:
    • SentenceTransformers: 提供各种预训练模型,专门用于语义文本相似性,例如 all-mpnet-base-v2 multi-qa-mpnet-base-dot-v1
    • OpenAI 的 Embeddings API: 提供强大的嵌入模型 (例如 text-embedding-ada-002 ),在语义搜索方面表现出色。

2. 数据预处理:

  • 清理和规范化文本数据: 确保从 PDF 中提取的文本干净且格式一致。 这包括:
    • 移除页眉、页脚、页码和其他无关信息。
    • 处理特殊字符、空格和换行符。
    • 将文本转换为小写,以便在嵌入过程中保持一致性。
  • 分割长文本: 将书籍分割成更小的文本块,例如段落或句子。 这可以提高嵌入的质量,并允许更精确地检索相关信息。

3. 查询扩展:

  • 使用更强大的查询扩展技术:
    • 同义词和相关词: 使用 WordNet 或 ConceptNet 等知识库来识别查询的同义词和相关词,并将其包含在检索过程中。
    • 基于上下文的扩展: 使用预训练的语言模型(例如 GPT-3)根据查询的上下文生成其他相关词或短语。
  • 调整查询变体的数量: 五种变体可能不足以捕获查询的全部范围。 尝试增加变体的数量,或使用不同的提示来生成更广泛的变体。

4. 评分和排序:

  • 探索不同的评分指标: FAISS 默认使用余弦相似度,但这可能不是最佳选择。 尝试其他指标,例如点积或欧几里德距离。
  • 重新排序结果: 使用机器学习模型(例如,基于 BERT 的排序模型)根据查询相关性重新排序检索到的结果。

5. 代码改进:

  • 结果多样性: 的代码目前会删除重复的结果,这可能会导致相关文档丢失。 考虑修改代码以保留多样性,并在必要时对重复项进行分组或排名。

建议的代码改进 (使用 SentenceTransformers):

from sentence_transformers import SentenceTransformer, util
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.llms import Ollama
from langchain.retrievers import MultiQueryRetriever
from langchain.schema import StrOutputParser

# Load the SentenceTransformer model
embedder = SentenceTransformer('all-mpnet-base-v2')

# ... (加载 FAISS 数据库的代码)

# ... (定义 QUERY_PROMPT 和初始化 Ollama 模型的代码)

# Define the retriever
retriever = MultiQueryRetriever.from_llm(
    retriever=new_db.as_retriever(search_type="mmr", search_kwargs={"k": 10}),  # 使用 MMR 并增加返回结果的数量
    llm=ollama,
    prompt=QUERY_PROMPT
)

# ... (查询和打印结果的代码)

调试建议:

  • 检查嵌入: 使用降维技术(例如 PCA 或 t-SNE)可视化查询和文档嵌入。 这可以帮助识别潜在的问题,例如不相关的嵌入或数据集中存在偏差。
  • 分析检索到的文档: 手动检查检索到的文档,了解它们与查询的相关性。 这可以帮助识别查询扩展或评分方面的潜在问题。
  • 迭代改进: 逐步实施这些改进,并评估它们对检索性能的影响。

通过实施这些改进,应该能够增强 LangChain 和 FAISS 多查询检索系统的相关性,并获得与用户查询更相关的结果。

标签:python,langchain,llama,ollama,faiss
From: 78828141

相关文章

  • 如何使用 BeautifulSoup python 查找选择标签的选定选项值
    我正在尝试从python中的htmlselect标签获取选定的值。好吧,当选项属性设置为selected="selected"时,它是成功的,但我试图废弃的网站具有不同的选项属性,例如:-html="""<select><optionvalue="">Pleaseselectavlalue</option><o......
  • 12:Python元组属性
    #元组tuple,元素不可被修改,不能被增加或则删除tu=(111,'alex',(11,22),[(33,44)],True,33,44,)#一般写元组的时候,最后可以加个逗号不报错print(tu)tu=(111,'alex',(11,22),[(33,44)],True,33,44,)v=tu[0]#元组索引print(v)tu=(111,'alex',(11,2......
  • 如何在venv python中安装requirements.txt
    我是Python虚拟环境的初学者,在安装requirements.txt文件时遇到问题。问题是,当我运行命令来安装requirements.txt文件时,没有安装任何内容。平台:WindowsVS代码镜像如何解决这个问题?没有正确激活虚拟环境。请按照以下步骤操作:1.激活虚拟环境:在VSC......
  • 【代码随想录】图论复习(Python版)
    深度优先搜索1.搜索过程一个方向搜,不到黄河不回头,直到遇到绝境了,搜不下去了,再换方向(换方向的过程就涉及到了回溯)2.代码框架回溯法的代码框架:defbacktracking(参数):if终止条件:存放结果returnfor选择本层集合中的元素(树中节点孩子的数量......
  • 开源模型应用落地-LangChain实用小技巧-ChatPromptTemplate的各种花样(三)
    一、前言  在当今的自然语言处理领域,LangChain框架因其强大的功能和灵活性而备受关注。掌握一些实用的小技巧,能够让您在使用LangChain框架时更加得心应手,从而更高效地开发出优质的自然语言处理应用。二、术语2.1.LangChain  是一个全方位的、基于大语言模型这......
  • 【Python】数据类型之字符串
    本篇文章将继续讲解字符串其他功能:1、求字符串长度功能:len(str)  ,该功能是求字符串str的长度。代码演示:2、通过索引获取字符串的字符。功能:str[a]  str为字符串,a为整型。该功能是获取字符串str索引为a处的字符。注意:字符串的索引是从0开始的。代码演示:注意......
  • 【Python】python基础
    本篇文章将讲解以下知识点:(1)循环语句(2)字符串格式化(3)运算符一:循环语句循环语句有两种:while   for本篇文章只讲解while循环格式:while 条件:  代码(只有条件为真的时候,此代码才会被执行,此处的代码可以是多行代码)(1)循环语句基本使用示例1:此处代码执行过程:1<3......
  • python 爬虫入门实战——爬取维基百科“百科全书”词条页面内链
    1.简述本次爬取维基百科“百科全书”词条页面内链,仅发送一次请求,获取一个html页面,同时不包含应对反爬虫的知识,仅包含最基础的网页爬取、数据清洗、存储为csv文件。爬取网址url为“https://zh.wikipedia.org/wiki/百科全书”,爬取内容为该页面所有内链及内链标识(下图蓝......
  • Python:match()和search()的区别
    在Python中,match()和search()函数通常与正则表达式(regularexpressions)一起使用,特别是在re模块中。尽管它们都用于搜索字符串中的模式,但它们在搜索行为上有关键的区别。re.match()re.match()函数尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()......
  • Python:range()函数的用法
    range()函数是Python中一个内置函数,用于生成一个数字序列。这个函数通常用于在for循环中迭代一个指定的次数。range()函数可以接收一到三个参数,分别是起始值(start)、结束值(stop)和步长(step),但步长是可选的,默认值为1。基本用法两个参数:range(start,stop)生成一个从star......