用途
postgres-semantic-search 用于在 PostgreSQL 上构建和调优检索系统,面向搜索与 RAG 实现。它不只提供 SQL 片段,还给出决策依据、实测发现和静默失败模式。资料明确说明:官方文档已覆盖良好的语法留给官方文档,这里收录的是那些不报错却会出错的内容。
主要能力
- 向量检索:基于 pgvector,涵盖列类型按维度选择、HNSW 与 IVFFlat 取舍、迭代扫描、过滤与阈值、连接池下的 SET 行为、操作符语义等。
- 关键词检索:tsquery 解析、重音与语言配置、前缀匹配、pg_trgm 三元组、ParadeDB BM25。
- 混合检索:使用 RRF 融合向量与关键词两路结果,并给出混合相对单路的实测对比。
- 重排序:交叉编码器重排候选短名单,讨论深度、硬件、相关性提问措辞与采纳规则。
- 评估:建议在调优前建立长问题与短词两套评估集,并说明偏差、噪声与四种误导性测量。
- 脚本:scripts/ 目录提供可参考的 SQL 构建块。
使用方式
资料给出的构建顺序是:先观察用户实际输入(标识符与代码、一到三词短语、完整问题、语言),据此决定需要哪些检索路径;从最适合这些查询的最简检索开始(精确/关键词查找或向量检索),近似向量检索要保留精确向量检索作为召回基线;在调优前建立两套评估集;只在能改善基线时才增加另一路并用 RRF 融合;最后在良好短名单的头部加重排序。每次只改一项,预先定义验收规则,默认要求增益超过实测的逐次波动,且另一评估集无实质损失,并检查逐查询的胜负与延迟、成本预算。
脚本使用:新样例数据库先用 setup.sql,再用 indexes.sql 和选定的函数文件;已有数据库需作为迁移审阅/改写,脚本假设 documents(id, title, content, metadata, embedding vector(1536)) 与 chunks(id, document_id, chunk_index, content, embedding),改名与维度需在所有文件中同步修改。部分函数文件会删除旧签名,应用前需检查依赖对象。这些是构建块,不是完整生产迁移或授权策略;脚本均不设置 hnsw.ef_search,由调用方设置。
调用示例(资料原文):
Supabase .rpc() 按名称绑定参数,拼错键会在调用时报错:
const { data, error } = await supabase.rpc('hybrid_search_fts', {
query_embedding: embedding, // number[]
query_text: userQuery,
match_count: 10,
fts_language: 'simple',
});
// Drizzle or node-postgres: send the vector as text and cast it
await db.execute(sql`SELECT * FROM match_documents(${JSON.stringify(embedding)}::vector, NULL, 10)`);
脚本文件与函数(真实参数名):
- semantic_search.sql:match_documents(query_embedding, match_threshold, match_count)、match_documents_filtered(query_embedding, filter_metadata, match_threshold, match_count)、match_chunks(query_embedding, match_threshold, match_count);match_threshold 为 NULL 表示普通 top-k。
- hybrid_search_fts.sql:hybrid_search_fts(query_embedding, query_text, match_count, rrf_k, fts_language, vector_weight, keyword_weight);任一输入可为 NULL。
- hybrid_search_bm25.sql:hybrid_search_bm25(...)、hybrid_search_chunks_bm25(...),参数相同但无 fts_language;需要 pg_search。
- fuzzy_search.sql:fuzzy_search_trigram(query_text, similarity_threshold, max_results)、autocomplete_search(search_prefix, max_results)、hybrid_search_fuzzy_semantic(query_text, query_embedding, max_results, rrf_k)。
- prefix_tsquery.sql:prefix_tsquery(config, text [, join])。
- setup.sql、indexes.sql:扩展、示例表、索引。
适用场景
- 用户同时输入完整问题与短词的混合检索。
- 多语言与非英语文本检索,包括芬兰语、瑞典语、德语、土耳其语等屈折语。
- 转录文本/字幕检索,需要在匹配片段内做细粒度二次搜索定位时刻。
- 需要评估驱动、逐步调优的搜索或 RAG 实现。
限制与注意事项
- 资料中的数值发现是特定语料的观察,不是通用性能保证。
- BM25 并非处处可用:托管主机存在差异(Neon 移除了 pg_search)。
- 静默失败需重点防范:HNSW 结果受 hnsw.ef_search(默认 40)限制,更大的 LIMIT 或选择性 WHERE 会静默返回更少行;默认 ef_search 可能无警告地损失召回;距离阈值应放在 MATERIALIZED CTE 之外;SET 是按连接的,事务池器后需用 SET LOCAL 或函数级 SET;相似度截断值因模型而异,1 - (a <#> b) 不是余弦相似度;客户端会破坏 JS 数组,需发送 JSON.stringify(embedding) 并 ::vector 转换。
- 关键词侧:plainto_tsquery 与未加引号的 websearch_to_tsquery 输入会用 AND 连接裸词,长问题可能匹配不到;unaccent 会合并某些语言的不同词;零宽导出残留会阻碍词干化;ORM 迁移可能让生成的 tsvector 列静默变成普通 NULL 列;% 比较整串,前缀与短查询对长文本应使用 <% 。
- 非英语与分块:需按所选嵌入模型的分词器与输入上限限制块大小,比例因模型与文本而异;跨语言查询可能使词法路径失效并损失约 12 分,翻译成句子而非关键词列表,可考虑两遍融合。
- 重排序:交叉编码器评的是“提到 X”而非“关于 X”,会提升短词的顺带提及;资料建议先只重排约 30 个候选的头部(前 5),仅在短词集成立时再加深;相关性提问措辞可能比模型更重要;需按可运行位置与文本是否可离开网络选择模型,并在目标硬件上测 p95;重排序无法找回第一阶段漏掉的内容。
- 版本(资料标注检查于 2026-09):pgvector 用 SELECT extversion FROM pg_extension WHERE extname = 'vector' 查看已安装版本,迭代扫描需 0.8.0+;0.8.2 修复并行 HNSW 构建的缓冲区溢出,0.8.3 与 0.8.4 修复 HNSW vacuum 损坏与错误;升级前阅读当前索引修复与升级说明;发布仅以 git 标签形式提供,应读 CHANGELOG 而非空的 Releases 标签页。pg_search 0.25+ 依赖 pgvector,需先安装 pgvector;ParadeDB 的 API 变动较快。
相关技能
- 通用 Postgres schema、索引、RLS、连接池:supabase-postgres-best-practices
- 聊天机器人编排、会话、工具调用:nextjs-chatbot
- 通过 AI SDK 调用嵌入:ai-sdk