现场是这样的。一部分文档入库时做了 L2 归一化,另一部分没有,用内积检索时分数出现 1.4 这种值,按 0.7 设的阈值完全失效。

中间走过弯路,把「归一化写在应用层,绕开应用的导入没做」当成主因,改完现象没变。

原因不止一个,得分开看。内积在未归一化时没有上界,与余弦不可比;两条入库路径的预处理不一致,补数据的脚本漏了;索引的度量类型与查询时的假设不一致。

先抽查库里向量的模长

python -c "import numpy as np;print(round(float(np.linalg.norm([0.6,0.8])),3))"

接着统一在入库前做 L2 归一化

python -c "import numpy as np;print((np.array([3,4])/np.linalg.norm([3,4])).round(3))"

然后把度量改成余弦,减少对归一化的依赖

curl -X PATCH http://127.0.0.1:6333/collections/kb -H "Content-Type: application/json" -d '{"vectors":{"distance":"Cosine"}}'

全量重算后统计模长分布

python -c "import numpy as np;print(np.linalg.norm(np.random.rand(5,8),axis=1).round(2))"

这类改动我都写进变更记录,过两周再出问题时能对上号。

怎么算真的好了,看的是同一批现象。全部向量模长落在 0.999 到 1.001 之间,检索分数不超过 1,阈值 0.7 的判断结果稳定。

余弦在部分引擎内部就是归一化后的内积,混用两种度量比混用归一化更隐蔽。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189