一、前言
带阈值的相似性搜索是一种非常实用的信息检索方法。它允许用户设定一个具体的相似度标准,从而提升搜索结果的相关性和准确性。在面对大规模数据时,传统的相似性搜索往往难以满足用户的需求,因为返回的结果可能包含很多不相干的信息。而通过设定相似度阈值,系统只会返回那些在特定程度上和用户查询对象相似的结果。这种方法不仅提高了搜索效率,还有助于用户更集中地获取与他们需求匹配的信息。
二、术语
2.1.相似性搜索
是一种信息检索技术,旨在找到与给定查询对象相似的其他对象。这种技术在多个领域都有广泛的应用,尤其是在文本处理、图像处理、推荐系统和数据挖掘等领域。
相似性搜索的关键点包括:
1. 相似性度量:为了比较对象之间的相似性,通常需要定义一个相似性度量或距离度量(如欧几里得距离、余弦相似度、曼哈顿距离等)。不同的度量适用于不同类型的数据。
2. 特征表示:对象通常需要通过某种方式进行特征提取,将其表示为向量或其他形式,以便于计算相似性。
3. 高效检索:对于大规模数据库,传统的线性搜索可能效率低下,因此常常采用高效的数据结构(如KD树、球树、LSH等)来加速搜索过程。
4. 应用场景:相似性搜索广泛应用于推荐系统(如电影或商品推荐)、图像搜索(如查找相似图片)、文本相似性检测(如抄袭检测)等。
2.2.带阈值的相似性搜索
是一种相似性搜索方法,其中用户设置一个阈值,以限制返回的结果是足够相似的对象。这种搜索方式不仅寻找与查询对象相似的其他对象,而且还确保这些对象的相似度超过用户设定的阈值。
带阈值的相似性搜索的关键要素包括:
1. 阈值设定:用户可以指定一个具体的阈值,这个值代表了对象之间需要达到的最小相似度。例如,如果使用余弦相似度,阈值可能被设定为0.8,表示只返回与查询对象相似度大于或等于0.8的对象。
2. 相似性度量:需要选择适合的数据相似性度量方法(如余弦相似度、Jaccard相似度、欧几里得距离等),以便有效地计算对象之间的相似度。
3. 过滤结果:在检索过程中,只有那些满足阈值条件的对象会被纳入最终结果。这有助于用户更快速地找到最相关的信息,并减少无关信息的干扰。
三、前提条件
3.1. 基础环境
- 操作系统:不限
3.2. 安装虚拟环境
conda create --name langchain python=3.10
conda activate langchain
pip install langchain langchain-openai langchain-community
# CPU版本安装
pip install faiss-cpu# GPU版本安装
pip install faiss-gpu
四、技术实现
4.1.传统的相似性检索
#!/usr/bin/env python
import osfrom langchain_community.vectorstores import FAISS
from langchain_core.documents import Document
from langchain_openai import OpenAIEmbeddingsos.environ["OPENAI_API_KEY"] = 'sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' # 你的Open AI Keyembedding = OpenAIEmbeddings(model="text-embedding-3-small")documents = [Document(page_content="在月光下,城市的喧嚣渐渐沉寂,只听见一只唱歌的猫咪,仿佛在讲述夜晚的秘密。", metadata={"page": 1}),Document(page_content="每当黄昏降临,时光咖啡馆的门口,总会出现一位会唱歌的叫小猫的少年,他的歌声像风铃般清脆,吸引着过路的行人。", metadata={"page": 2}),Document(page_content="长久以来,水晶球中的小镇有个传说,只有在下雪的日子里,许下的愿望才会变成现实。", metadata={"page": 3}),Document(page_content="一个人在沙滩上捡到一颗奇特的贝壳,听说它能听懂海浪的低语,带着他探索海底的神秘世界。", metadata={"page": 4}),Document(page_content="春天的第一场雨下过之后,花瓣上竟然映出了天空的彩虹,仿佛大自然在为人间铺设一条美丽的桥梁。", metadata={"page": 5}),Document(page_content="公园里,一只迷路的小狗不小心走进了时光隧道,突然变成了一个会说话的小精灵,开始了它的冒险旅程。", metadata={"page": 6}),Document(page_content="在遥远的山谷中,隐藏着一座会唱歌的瀑布,只有真正的勇者才敢去迎接这水的旋律。", metadata={"page": 7}),Document(page_content="一本无字书,翻开时却能让人看到自己未来的每一个选择,书页间飘散着淡淡的香气,令人心旷神怡。", metadata={"page": 8}),Document(page_content="有个城市的天空,每到午夜,会洒下星星的雨滴,居民们在梦中收集这些星星,实现心底的愿望。", metadata={"page": 9}),Document(page_content="星期五的晚上,神秘的镜子里会出现一位来自异界的旅行者,他带着五彩斑斓的故事,邀你一起进入奇幻的冒险。", metadata={"page": 10}),
]
db = FAISS.from_documents(documents, embedding)if __name__ == '__main__':print(db.similarity_search("我看见一只会唱歌的猫", k=2))
调用结果:
说明:
- k: 设置返回的结果数量,默认值是4
4.2.带阈值的相似性搜索
#!/usr/bin/env python
import osfrom langchain_community.vectorstores import FAISS
from langchain_core.documents import Document
from langchain_openai import OpenAIEmbeddingsos.environ["OPENAI_API_KEY"] = 'sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' # 你的Open AI Keyembedding = OpenAIEmbeddings(model="text-embedding-3-small")documents = [Document(page_content="在月光下,城市的喧嚣渐渐沉寂,只听见一只唱歌的猫咪,仿佛在讲述夜晚的秘密。", metadata={"page": 1}),Document(page_content="每当黄昏降临,时光咖啡馆的门口,总会出现一位会唱歌的叫小猫的少年,他的歌声像风铃般清脆,吸引着过路的行人。", metadata={"page": 2}),Document(page_content="长久以来,水晶球中的小镇有个传说,只有在下雪的日子里,许下的愿望才会变成现实。", metadata={"page": 3}),Document(page_content="一个人在沙滩上捡到一颗奇特的贝壳,听说它能听懂海浪的低语,带着他探索海底的神秘世界。", metadata={"page": 4}),Document(page_content="春天的第一场雨下过之后,花瓣上竟然映出了天空的彩虹,仿佛大自然在为人间铺设一条美丽的桥梁。", metadata={"page": 5}),Document(page_content="公园里,一只迷路的小狗不小心走进了时光隧道,突然变成了一个会说话的小精灵,开始了它的冒险旅程。", metadata={"page": 6}),Document(page_content="在遥远的山谷中,隐藏着一座会唱歌的瀑布,只有真正的勇者才敢去迎接这水的旋律。", metadata={"page": 7}),Document(page_content="一本无字书,翻开时却能让人看到自己未来的每一个选择,书页间飘散着淡淡的香气,令人心旷神怡。", metadata={"page": 8}),Document(page_content="有个城市的天空,每到午夜,会洒下星星的雨滴,居民们在梦中收集这些星星,实现心底的愿望。", metadata={"page": 9}),Document(page_content="星期五的晚上,神秘的镜子里会出现一位来自异界的旅行者,他带着五彩斑斓的故事,邀你一起进入奇幻的冒险。", metadata={"page": 10}),
]
db = FAISS.from_documents(documents, embedding)if __name__ == '__main__':print(db.similarity_search_with_relevance_scores("我看见一只会唱歌的猫", k=2, score_threshold=0.44))
调用结果:
说明:
- k: 设置返回的结果数量,默认值是4
- score_threshold:设置用于过滤检索到的文档的结果集,值在0~1之间。
相较于传统的相似性检索的结果,低于阈值的记录将会被过滤,仅返回大于阈值0.44的记录!