django PostgreSQL上的语义搜索

k7fdbhmy  于 2023-06-07  发布在  Go
关注(0)|答案(1)|浏览(132)

我知道PostgreSQL有trigram trigram相似性搜索,甚至索引优化(CREATE INDEX trgm_idx ON table USING gist (column gist_trgm_ops);),可以直接从Django(Web框架)使用:

Model.objects.filter(attribute__trigram_similar=query_string)

但是,如果我想对数据库对象执行语义相似性查询,而不是表面相似性查询,该怎么办呢?(这显然与经典的三元组相似性有很大不同)。
一个很好的例子是Google的universal sentence encoder,我将所有字符串转换为512维嵌入向量(使用库),并通过计算归一化点积(余弦相似度)来执行查询,并产生具有最高相似度的对象(或者可能是具有相似度>=0.50的n个对象)。
最简单的方法是在数据库对象上迭代(在框架级别),但这是非常低效的(特别是如果数据库很大),因此我宁愿找到一种方法,我可以在数据库级别上执行查询(也许如果可能的话,为语义搜索设置最佳索引?)).
在预矢量化对象的数据库上执行此自定义相似性搜索的最佳方式是什么?
如果我手动获得预矢量化数据库中所有对象的点积会怎么样?
谢谢你!

h4cxqtbf

h4cxqtbf1#

下面是PostgreSQL的查询。
您可以将ARRAY[1,2,3]替换为您可以搜索的文本的嵌入。长度必须与documents.embeddings字段相同。例如,如果您使用OpenAI ada模型来计算嵌入,则必须将其用于搜索查询。

CREATE OR REPLACE FUNCTION cosine_similarity(a float[], b float[]) RETURNS float AS $$
  DECLARE
      dot_product float = 0;
      norm_a float = 0;
      norm_b float = 0;
  BEGIN
      FOR i IN 1 .. array_length(a, 1)
      LOOP
          dot_product = dot_product + a[i] * b[i];
          norm_a = norm_a + a[i] * a[i];
          norm_b = norm_b + b[i] * b[i];
      END LOOP;
      RETURN dot_product / (sqrt(norm_a) * sqrt(norm_b));
  END;
  $$ LANGUAGE plpgsql;

  SELECT *, cosine_similarity(documents.embeddings, ARRAY[1,2,3]) as cosine_similarity
   FROM documents
  ORDER BY cosine_similarity DESC

相关问题