pgvector

pgvector 是 PostgreSQL 扩展:在已有库里加 vector 列,用 SQL 做相似度查询。不必再运维一套独立向量数据库。扩展仓库:pgvector/pgvector。Postgres 本身(安装、SQL、索引)见本站 PostgreSQL 教程

适合「用户表、文章表已经在 PG」的团队。纯本地试 RAG,先走 Chroma


启用扩展

发行版需带 pgvector(Debian 包、Postgres.app、或 pgvector/pgvector Docker 镜像)。连上之后:

CREATE EXTENSION IF NOT EXISTS vector;

没有这条命令,后面的类型和 <=> 都不会存在。权限不够时找管理员在目标数据库执行一次。


最小表与余弦查询

维度必须和嵌入模型一致:text-embedding-3-small 默认 1536bge-m3 常见 1024。建表后不要改维,否则整列重嵌。

CREATE TABLE docs (
  id        bigserial PRIMARY KEY,
  content   text NOT NULL,
  source    text,
  embedding vector(1536) NOT NULL
);

CREATE INDEX ON docs USING hnsw (embedding vector_cosine_ops);

-- 余弦距离越小越相似;1 - distance 得到相似度
SELECT id, content,
       1 - (embedding <=> '[0.01, 0.02]'::vector) AS similarity
FROM docs
ORDER BY embedding <=> '[0.01, 0.02]'::vector
LIMIT 5;

真实查询会传入 1536 维,上面的两维只是语法示意。常用算子:

算子含义索引 opclass
<=>余弦距离vector_cosine_ops
<->L2vector_l2_ops
<#>负内积vector_ip_ops

文本嵌入一般用余弦。数据量小可以先不建 HNSW,顺序扫描也能教;上万行再加索引。


Python:psycopg + pgvector

pip install "psycopg[binary]" pgvector
pip install "psycopg[binary]" pgvector
import psycopg
from pgvector.psycopg import register_vector

DSN = "postgresql://postgres:secret@localhost:5432/rag"
conn = psycopg.connect(DSN)
register_vector(conn)
conn.execute("CREATE EXTENSION IF NOT EXISTS vector")

conn.execute(
    """
    CREATE TABLE IF NOT EXISTS docs (
      id bigserial PRIMARY KEY,
      content text NOT NULL,
      source text,
      embedding vector(1536) NOT NULL
    )
    """
)

vec = [0.0] * 1536  # 换成 embeddings 章的 embed_openai / embed_ollama
vec[0] = 0.1
conn.execute(
    "INSERT INTO docs (content, source, embedding) VALUES (%s, %s, %s)",
    ("退款须在到货 7 日内申请。", "refund.md", vec),
)
conn.commit()

q = vec  # 查询同样要 embed
rows = conn.execute(
    """
    SELECT content, 1 - (embedding <=> %s) AS similarity
    FROM docs
    ORDER BY embedding <=> %s
    LIMIT 5
    """,
    (q, q),
).fetchall()
print(rows)

register_vector(conn) 让 Python list / NumPy 数组能写入 vector 列。忘记注册时,插入会报类型错误。

已有业务表时不要另起炉灶,直接加列:

ALTER TABLE articles ADD COLUMN embedding vector(1536);
-- 回填后再:
-- CREATE INDEX ON articles USING hnsw (embedding vector_cosine_ops);

回填脚本:SELECT id, body FROM articles WHERE embedding IS NULL,逐批 embed 再 UPDATE。完整例子见 实战案例 案例 2。


和 RAG 的关系

SQL 里可以同时写 WHERE org_id = 42 AND published ORDER BY embedding <=> :q。这是 pgvector 相对纯向量库的优势:权限、租户、时间过滤跟相似度在同一条语句里。提示词侧仍然要写「只根据 content 回答」。


下一步

评论