我正在为一个专注于冥想和灵性的项目开发一个使用 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
),在语义搜索方面表现出色。
-
SentenceTransformers:
提供各种预训练模型,专门用于语义文本相似性,例如
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