You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL中DOT_PRODUCT函数未识别报错的解决求助

问题:pgvector中使用点积函数报错UndefinedFunction

背景

在基于PostgreSQL+pgvector的RAG场景中,需要计算查询嵌入向量与数据库中存储的段落嵌入向量的点积,替换原查询中使用<=>(L2距离)的逻辑,但调用DOT_PRODUCT()函数时触发如下错误:

UndefinedFunction: function dot_product(vector, vector) does not exist
LINE 4: ORDER BY DOT_PRODUCT(embedding, embedding)

^

HINT: no function matches the given name and argument types. You might need to add explicit type casts.

原查询逻辑是通过<=>排序取最相似的topN,现在需要改为按点积排序(点积越大,向量相似度越高)。

解决思路与可执行方案

1. 使用pgvector官方支持的点积语法

pgvector并未提供DOT_PRODUCT()函数,正确的点积计算方式有两种:

  • 操作符方式:使用<#>操作符计算点积,注意需要按降序排序(因为点积越大相似度越高,与<=>的升序逻辑相反)
    SELECT content, document, page, line, link
    FROM documents
    ORDER BY embedding <#> %(embedding)s DESC
    LIMIT %(n)s
    
  • 函数方式:使用官方提供的vec_dot()函数,同样需要降序排序
    SELECT content, document, page, line, link
    FROM documents
    ORDER BY vec_dot(embedding, %(embedding)s) DESC
    LIMIT %(n)s
    

2. 修正向量参数的传递方式

原代码中将向量转换为字符串数组的方式容易引发类型问题,由于插入数据时已经调用了register_vector(conn)让psycopg支持向量类型,查询时可以直接传递numpy数组,无需手动转换:

# 移除字符串转换代码:embedding_pgarray = "[" + ",".join(map(str, embedding)) + "]"
# 直接传入model.encode生成的embedding向量
neighbors = conn.execute(query, {'embedding': embedding, 'n':n}).fetchall()

同时,查询连接时必须调用register_vector(conn),否则psycopg无法正确识别向量类型:

conn = psycopg.connect(dbname='rag', user='rag', password='rag', autocommit=True)
conn.execute('CREATE EXTENSION IF NOT EXISTS vector')
register_vector(conn)  # 必须添加该行,开启psycopg的向量类型支持

3. 确保向量类型一致性

如果仍然存在类型不匹配问题,可以在SQL中显式指定向量维度,强制类型转换:

ORDER BY vec_dot(embedding::vector(384), %(embedding)s::vector(384)) DESC

注:这里的384对应all-MiniLM-L6-v2模型的输出向量维度,需与表定义中的embedding vector(384)一致。

4. 验证pgvector扩展状态

执行以下SQL确认扩展已正确安装:

SELECT * FROM pg_extension WHERE extname = 'vector';

如果无返回结果,需重新执行CREATE EXTENSION IF NOT EXISTS vector;,确保扩展安装成功。

修正后的完整代码片段

string = query

# 初始化嵌入模型
model = SentenceTransformer('all-MiniLM-L6-v2')
# 生成查询向量
embedding = model.encode(string)

# 建立数据库连接并启用向量支持
conn = psycopg.connect(dbname='rag', user='rag', password='rag', autocommit=True)
conn.execute('CREATE EXTENSION IF NOT EXISTS vector')
register_vector(conn)  # 关键:注册向量类型支持

# 修正后的查询语句(使用vec_dot函数)
query =  """ 
    SELECT content, document, page, line, link
    FROM documents
    ORDER BY vec_dot(embedding, %(embedding)s) DESC
    LIMIT %(n)s
"""

# 直接传入numpy向量,无需字符串转换
neighbors = conn.execute(query, {'embedding': embedding, 'n':n}).fetchall()

# 结果整理为DataFrame
df = pd.DataFrame(neighbors, columns=['Content', 'Document', 'Page', 'Line', 'Link'])
df['Content'] = df['Content'].str.strip()
df = df.reset_index(drop=True)
return df

内容的提问来源于stack exchange,提问作者Sean Last

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 02:23:17