
在使用向量数据库进行相似度搜索时,我们通常期望查询与库中完全相同的文本能得到最高的相似度分数。然而,实际操作中,即使查询字符串与向量库中的文档内容完全一致,相似度分数也可能未达到理论上的最大值(例如,余弦相似度中的1.0)。这引发了一个常见疑问:为什么会出现这种“不完美”的匹配分数?
这背后的原因复杂多样,涉及嵌入模型的特性、向量数据库的距离计算方式以及LangChain框架的封装逻辑。理解这些核心概念对于优化搜索结果至关重要。
LangChain的similarity_search_with_score()方法在与FAISS等向量库交互时,会根据底层向量库的配置和嵌入模型的特性来返回相似度分数。关键在于理解FAISS可能使用的距离度量以及这些度量如何转换为最终的“相似度得分”。
FAISS支持多种距离度量,其中最常见的是:
当使用HuggingFaceBgeEmbeddings并设置encode_kwargs={'normalize_embeddings': True}时,这明确指示模型输出归一化的嵌入向量。归一化后的向量,其点积(dot product)即为余弦相似度。因此,在这种配置下,similarity_search_with_score()返回的得分通常代表余弦相似度,理论上,完全相同的文本应该得到1.0的余弦相似度。
然而,用户观察到对于精确匹配的查询'无纸化发送失败?',返回的得分却是0.9069208,而非预期的1.0。这暗示了以下几种可能性:
为什么BGE模型在精确匹配时未能达到1.0的余弦相似度?这可能由以下因素导致:
为了验证是否是BGE模型本身的问题,可以尝试直接计算相同字符串的嵌入向量的余弦相似度:
from transformers import AutoModel, AutoTokenizer
from sklearn.metrics.pairwise import cosine_similarity
import torch
model_name = "BAAI/bge-large-zh-v1.5"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)
model.eval() # Set model to evaluation mode
def get_bge_embedding(text):
inputs = tokenizer(text, return_tensors='pt', padding=True, truncation=True)
with torch.no_grad():
outputs = model(**inputs)
# Get the last hidden state and apply pooling (BGE uses CLS token embedding)
embeddings = outputs.last_hidden_state[:, 0]
# Normalize embeddings
embeddings = torch.nn.functional.normalize(embeddings, p=2, dim=1)
return embeddings.cpu().numpy()
query_text = '无纸化发送失败?'
embedding1 = get_bge_embedding(query_text)
embedding2 = get_bge_embedding(query_text) # Embed the exact same text again
# Calculate cosine similarity directly
direct_similarity = cosine_similarity(embedding1, embedding2)[0][0]
print(f"Direct cosine similarity for identical texts: {direct_similarity}")如果上述代码输出的direct_similarity接近1.0(例如0.9999999),那么问题可能更多在于LangChain/FAISS的集成或浮点数误差。如果它也略低于1.0,则说明这是BGE模型本身的特性。
不同的嵌入模型和LangChain的集成方式可能导致相似度得分的含义和表现有所不同。例如,OpenAI的嵌入模型在LangChain中通常表现出不同的得分特性。
考虑以下使用OpenAI嵌入模型和FAISS的例子:
from langchain.document_loaders import TextLoader
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import FAISS
import os
# 假设您已设置OPENAI_API_KEY环境变量
# 或者直接传入 model_name, openai_api_key 等参数
# embeddings = OpenAIEmbeddings(model_name="text-embedding-ada-002", openai_api_key="YOUR_API_KEY")
embeddings = OpenAIEmbeddings() # 默认使用 text-embedding-ada-002
# 创建一个临时文本文件
with open("./text.txt", "w", encoding="utf-8") as f:
f.write("无纸化发送失败?\n")
f.write("凭证打包失败?\n")
f.write("edi发送不了?\n")
loader = TextLoader("./text.txt", encoding="utf-8")
documents = loader.load()
# 注意:这里直接从文档创建FAISS,而不是加载本地文件
# 这样可以确保嵌入过程是在当前环境下进行的
db = FAISS.from_documents(documents, embeddings)
query = '无纸化发送失败?'
res = db.similarity_search_with_score(query, k=3)
print("OpenAI Embeddings Results (L2 Distance, lower is better):")
print(res)
query2 = '纸化发送失败?' # 略有差异的查询
res2 = db.similarity_search_with_score(query2, k=3)
print("OpenAI Embeddings Results for slightly different query:")
print(res2)示例输出(OpenAI):
OpenAI Embeddings Results (L2 Distance, lower is better):
[(Document(page_content='无纸化发送失败?', metadata={'source': './text.txt'}), 0.0)]
OpenAI Embeddings Results for slightly different query:
[(Document(page_content='无纸化发送失败?', metadata={'source': './text.txt'}), 0.08518691)]从OpenAI的输出可以看出,对于精确匹配的查询,其得分是0.0。这表明OpenAIEmbeddings(或其在LangChain中的集成)可能默认使用欧氏距离(L2距离),并且对于完全相同的输入,它能够产生完全相同的嵌入向量,从而导致L2距离为0。
核心区别总结:
因此,用户遇到的0.9分数对于余弦相似度而言,已经是非常高的相似度,可以认为是“几乎完美匹配”。问题不在于分数“低”,而在于它没有达到理论上的1.0。
理解相似度分数的含义:
数据预处理一致性:确保在构建向量索引时和执行查询时,文本的预处理(如大小写转换、标点符号处理、分词等)保持一致。任何不一致都可能导致嵌入向量的差异。
模型选择与调优:
调试策略:
LangChain结合FAISS与BGE嵌入模型进行相似度搜索时,精确匹配的查询得到0.9左右的余弦相似度分数是正常现象。这通常不是一个“问题”,而是嵌入模型特性、浮点精度以及距离计算方式共同作用的结果。重要的是理解这个分数的含义:对于余弦相似度,0.9已经代表了极高的相似性。如果追求0.0(L2距离)或1.0(余弦相似度)的“完美”分数,需要深入理解所选嵌入模型和向量库的内部机制,并可能需要尝试不同的模型或调整配置。在实际应用中,关注模型的整体性能和召回率,而不是过于纠结于精确匹配的微小分数差异,通常更为重要。
以上就是LangChain FAISS与BGE嵌入模型相似度得分优化指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号