一、前言:为什么同样是相似度搜索,分数却不一样?
在开发 RAG 知识库系统时,我们经常会看到类似代码:
docs = vectorstore.similarity_search_with_score( query )或者:
docs = vectorstore.similarity_search_with_relevance_scores( query )两者名字非常接近:
- similarity_search
- score
- relevance_scores
很多刚接触 LangChain 的开发者会认为:
“它们返回的不都是相似度分数吗?为什么还要设计两个方法?”
实际上:
两者最大的区别就在于:分数是否经过标准化处理。
二、similarity_search_with_score() 是什么?
1. 基本作用
similarity_search_with_score():
根据用户输入的 query,在向量数据库中搜索最相似的文档,并返回原始距离或者原始相似度分数。
示例:
results = vectorstore.similarity_search_with_score( "什么是 RAG", k=3 ) for doc, score in results: print(score) print(doc.page_content)返回:
0.23 RAG 是一种结合搜索和大语言模型的方法 0.45 向量数据库用于存储 Embedding 0.78 机器学习基础知识三、similarity_search_with_score() 的分数有什么特点?
重点来了:
分数没有统一标准。
原因:
不同向量数据库:
- FAISS
- Chroma
- Milvus
- Pinecone
- Weaviate
使用的距离算法可能不同。
例如:
1. 欧氏距离(L2 Distance)
公式:
距离越小,越相似结果可能:
0.12 0.35 0.89这里:
0.12 比 0.89 更相关。
2. 余弦距离(Cosine Distance)
可能:
0.01 0.20 0.60通常:
越接近 0:
代表越相似。
3. 内积(Inner Product)
可能:
0.95 0.82 0.61可能:
越大越相似。
所以:
similarity_search_with_score()返回的 score:
可能:
0-1也可能:
0-100甚至:
负数都属于正常情况。
四、为什么不同数据库分数不同?
因为向量搜索本质上是在计算:
两个向量之间的距离。
例如:
用户问题:
什么是人工智能?Embedding:
[ 0.21, 0.34, 0.56, ... ]数据库中的文档:
[ 0.22, 0.35, 0.55, ... ]然后计算:
query vector | | ↓ distance calculation | | ↓ score但是:
距离怎么算?
由数据库和算法决定。
五、similarity_search_with_relevance_scores() 是什么?
这个方法解决了一个问题:
不同数据库返回的 score 没有统一标准。
所以 LangChain 对结果进行了:
相关性归一化处理。
使用:
similarity_search_with_relevance_scores()示例:
results = vectorstore.similarity_search_with_relevance_scores( "什么是RAG", k=3 ) for doc, score in results: print(score)返回:
0.92 0.81 0.63六、relevance score 有什么特点?
它经过统一处理:
范围:
0 <= score <= 1含义:
| 分数 | 含义 |
|---|---|
| 0.9-1.0 | 高度相关 |
| 0.7-0.9 | 比较相关 |
| 0.5-0.7 | 一般相关 |
| <0.5 | 相关性较低 |
并且:
分数越大,表示文档越相关。
七、两者核心区别总结
| 对比 | similarity_search_with_score | similarity_search_with_relevance_scores |
|---|---|---|
| 返回内容 | 文档 + 原始score | 文档 + 归一化score |
| 是否标准化 | ❌ 否 | ✅ 是 |
| 范围 | 不固定 | 0~1 |
| 是否依赖数据库 | 强依赖 | 弱依赖 |
| 适合场景 | 底层调试 | 业务判断 |
| 跨数据库比较 | 困难 | 方便 |
八、代码对比
方法一:原始score
docs = vectorstore.similarity_search_with_score( query, k=5 ) for doc, score in docs: print( f"score:{score}" )可能输出:
score:0.231 score:0.452 score:0.891问题:
不同数据库:
可能变成:
score:15.2 score:8.6 score:3.1代码无法统一判断。
方法二:relevance score
docs = vectorstore.similarity_search_with_relevance_scores( query, k=5 ) for doc, score in docs: print( f"score:{score}" )输出:
score:0.96 score:0.82 score:0.71可以直接:
if score > 0.8: print("保留")九、RAG 项目中应该使用哪个?
这是很多开发者关心的问题。
场景一:调试向量搜索
推荐:
similarity_search_with_score()原因:
可以看到底层真实距离。
例如:
检查:
- Embedding 是否正常
- 向量是否生成正确
- 数据是否入库
场景二:知识库问答系统
推荐:
similarity_search_with_relevance_scores()例如:
RAG:
用户问题 ↓ 向量检索 ↓ 相关性过滤 ↓ LLM生成答案可以:
docs = [ doc for doc, score in results if score > 0.75 ]过滤低质量文档。
十、实际开发中的一个坑
很多新人会这样写:
docs = vectorstore.similarity_search_with_score( query ) if score > 0.8: use_document()问题:
如果当前数据库:
score 是距离:
例如:
0.2代表高度相关。
那么:
0.2 > 0.8结果:
直接过滤掉。
导致:
明明相关的文档,却没有被召回。
正确方式:
如果不知道底层算法:
使用:
similarity_search_with_relevance_scores()十一、底层原理简单理解
可以这样理解:
similarity_search_with_score
类似:
数据库: A文档 距离 = 0.15 B文档 距离 = 0.42 C文档 距离 = 0.89这是:
原始测量值。
similarity_search_with_relevance_scores
类似:
经过加工:
A文档 相关度 = 0.95 B文档 相关度 = 0.75 C文档 相关度 = 0.30变成:
业务更容易理解的数据。
十二、总结
今天我们学习了 LangChain 中两个重要方法:
similarity_search_with_score()和:
similarity_search_with_relevance_scores()核心区别:
一句话总结:
similarity_search_with_score 返回的是向量数据库原始评分,不同算法和数据库结果可能不同;similarity_search_with_relevance_scores 会对评分进行归一化,将结果转换为 0~1 的相关性分数,更适合业务判断。
在实际 RAG 项目中:
- 调试检索效果 → 使用
similarity_search_with_score - 判断文档相关性 → 使用
similarity_search_with_relevance_scores - 做阈值过滤 → 优先使用
relevance_scores
掌握这两个方法的区别,是理解 LangChain 向量检索机制的重要一步,也是优化 RAG 系统准确率的基础。