ChatGLM2+SentenceTransformer 向量检索任务上不太灵敏,哪里出错了?

我的代码是这样,五个毫不相关的领域文本转成向量,查询问题也转成向量做向量积,按照向量积倒序排序文本:

from sentence_transformers import SentenceTransformer
import faiss
import numpy as np

model = SentenceTransformer('D:\\\\src\\chatglm2-6b-int4')
lines = [
    "国际高等教育研究机构QS Quacquarelli Symonds于2023年6月28日正式发布第20版世界大学排名,首次将就业能力和可持续发展指标纳入排名体系,成为全球唯一一个同时包含这两项指标的排名。",
    "瑞典皇家科学院2022年10月10日在斯德哥尔摩宣布,将2022年诺贝尔经济学奖授予经济学家本·伯南克(Ben Bernanke)、道格拉斯·戴蒙德(Douglas Diamond)和菲利普·迪布维格(Philip Dybvig),以表彰他们在银行与金融危机研究领域的突出贡献。",
    "2022年11月10日,《福布斯》发布2022中国内地富豪榜。本次上榜者的财富总额从去年的1.48万亿美元下降至9,071亿美元,跌幅达到39%,并创下了《福布斯》调查中国内地富豪20多年以来的最大跌幅。",
    "新能源是指传统能源之外的各种能源形式。它的各种形式都是直接或者间接地来自于太阳或地球内部所产生的热能。包括太阳能、风能、生物质能、地热能、水能和海洋能以及由可再生能源衍生出来的生物燃料和氢所产生的能量。也可以说,新能源包括各种可再生能源和核能。相对于传统能源,新能源普遍具有污染少、储量大的特点,对于解决当今世界严重的环境污染问题和资源(特别是化石能源)枯竭问题具有重要意义。",
    "费曼学习法可以简化为四个单词:Concept (概念)、Teach (教给别人)、Review (评价)、Simplify (简化)。  费曼学习法的灵感源于诺贝尔物理奖获得者理查德•费曼(Richard Feynman),运用费曼技巧,你只需花上20分钟就能深入理解知识点,而且记忆深刻,难以遗忘。知识有两种类型,我们绝大多数人关注的都是错误的那类。第一类知识注重了解某个事物的名称。第二类知识注重了解某件事物。这可不是一回事儿。著名的诺贝尔物理学家理查德·费曼(Richard Feynman)能够理解这二者间的差别,这也是他成功最重要的原因之一。事实上,他创造了一种学习方法,确保他会比别人对事物了解的更透彻。",
]
vecs = np.asarray(model.encode(lines))
faiss.normalize_L2(vecs)
print(vecs.shape) # (5, 65024)
vecdb = faiss.IndexFlatIP(vecs.shape[1])
vecdb.add(vecs)
query = '费曼学习法是什么?'
qvec = np.asarray([model.encode(query)])
faiss.normalize_L2(qvec)
sims, idcs = vecdb.search(qvec, vecdb.ntotal)
for i, (sim, idx) in enumerate(zip(sims[0], idcs[0])):
    print(f'结果#{i+1},相似度:{sim:.03f}\n{lines[idx]}')
    print('-' * 30)

结果是这样:

结果#1,相似度:0.975
2022年11月10日,《福布斯》发布2022中国内地富豪榜。本次上榜者的财富总额从去年的1.48万亿美元下降至9,071亿美元,跌幅达到39%,并创下了《福布斯》调查中国内地富豪20多年以来的最大跌幅。
------------------------------
结果#2,相似度:0.973
新能源是指传统能源之外的各种能源形式。它的各种形式都是直接或者间接地来自于太阳或地球内部所产生的热能。包括太阳能、风能、生物质能、地热能、水能和海洋能以及由可再生能源衍生出来的生物燃料和氢所产生的能量。也可以说,新能源包括各种可再生能源和核能。相对于传统能源,新能源普遍具有污染少、储量大的特点,对于解决当今世界严重的环境污染问题和资源(特别是化石能源)枯竭问题具有重要意义。
------------------------------
结果#3,相似度:0.970
费曼学习法可以简化为四个单词:Concept (概念)、Teach (教给别人)、Review (评价)、Simplify (简化)。  费曼学习法的灵感源于诺贝尔物理奖获得者理查德•费曼(Richard Feynman),运用费曼技巧,你只需花上20分钟就能深入理解知识点,而且记忆深刻, 难以遗忘。知识有两种类型,我们绝大多数人关注的都是错误的那类。第一类知识注重了解某个事物的名称。第二类知识注重了解某件事物。这可不是一回事儿。著名的诺贝尔物理学家理查德·费曼(Richard Feynman)能够理解这二者间的差别,这也是他成功最重要的原 因之一。事实上,他创造了一种学习方法,确保他会比别人对事物了解的更透彻。
------------------------------
结果#4,相似度:0.966
国际高等教育研究机构QS Quacquarelli Symonds于2023年6月28日正式发布第20版世界大学排名,首次将就业能力和可持续发展指标纳入排名体系,成为全球唯一一个同时包含这两项指标的排名。
------------------------------
结果#5,相似度:0.943
瑞典皇家科学院2022年10月10日在斯德哥尔摩宣布,将2022年诺贝尔经济学奖授予经济学家本·伯南克(Ben Bernanke)、道格拉斯·戴蒙德(Douglas Diamond)和菲利普·迪布维格(Philip Dybvig),以表彰他们在银行与金融危机研究领域的突出贡献。
------------------------------

显然这个结果是不对的,最匹配的结果#3应该排在最前面。我这个代码哪里错了,有什么改进方法?

补充:我以为是 Faiss 的问题,然后我用 NumPy 重写了一遍,还是这样:

def l2_norm(arr, axis=-1):
    return (arr ** 2).sum(axis=axis, keepdims=True) ** 0.5

vecs = np.asarray(model.encode(lines))
vecs /= l2_norm(vecs)
print(vecs.shape) # (5, 65024)
query = '费曼学习法是什么?'
qvec = np.asarray([model.encode(query)])
qvec /= l2_norm(qvec)
sim_mat = qvec @ vecs.T
sims = np.sort(sim_mat, axis=-1)[:, ::-1]
idcs = np.argsort(sim_mat, axis=-1)[:, ::-1]
for i, (sim, idx) in enumerate(zip(sims[0], idcs[0])):
    print(f'结果#{i+1},相似度:{sim:.03f}\n{lines[idx]}')
    print('-' * 30)
阅读 1k
1 个回答
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np

model = SentenceTransformer('D:\\\\src\\chatglm2-6b-int4')
lines = [
    # ...
]
vecs = np.asarray(model.encode(lines))
faiss.normalize_L2(vecs)  # 对数据库向量进行归一化
print(vecs.shape) # (5, 65024)
vecdb = faiss.IndexFlatIP(vecs.shape[1])
vecdb.add(vecs)  # 添加归一化后的向量到索引
query = '费曼学习法是什么?'
qvec = np.asarray([model.encode(query)])
faiss.normalize_L2(qvec)  # 对查询向量进行归一化
sims, idcs = vecdb.search(qvec, vecdb.ntotal)
for i, (sim, idx) in enumerate(zip(sims[0], idcs[0])):
    print(f'结果#{i+1},相似度:{sim:.03f}\n{lines[idx]}')
    print('-' * 30)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进