postgres-word2vec
在PostgreSQL数据库内直接运行word2vec语义搜索的扩展,无需数据迁移
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
在PostgreSQL数据库内直接运行word2vec语义搜索的扩展,无需数据迁移
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
想象这样的场景:你在一家媒体公司负责内容推荐系统,数据库里存着几十万篇新闻标题,需要快速找到与「科幻电影」语义最接近的其他文章标题。传统的 SQL LIKE '%科幻%' 只能匹配字面,无法理解「科幻」与「science fiction」、「太空歌剧」的语义关联——这就是 word2vec 在数据库应用中的价值所在。FREDDY(Fast Word Embeddings in Database Systems)正是为解决这一痛点而生的 PostgreSQL 扩展。它由德国慕尼黑大学的研究者 Michael Günther 于 2017 年开发,2018 年在 ACM SIGMOD 国际数据库会议上正式发表。与其将向量数据导出到 Python 或专门的向量数据库中做相似度计算,FREDDY 直接在数据库内部完成全部操作,避免了数据迁移的性能损耗。FREDDY 的核心是一套精心设计的 PostgreSQL 用户定义函数(UDF),通过这些函数开发者可以在 SQL 查询中直接调用词向量操作。例如 cosine_similarity(float[], float[]) 函数接受两个浮点数组作为输入,计算它们之间的余弦相似度,从而在 SQL 语句中实现语义搜索。一个典型的查询可能是:找出与「喜剧」(comedy)语义最接近的电影标题,并按相似度排序——这在传统数据库中几乎无法实现,而 FREDDY 让它变得像普通 SQL 查询一样简单。然而,简单查询在大规模向量数据上会遇到性能瓶颈——全表扫描的时间复杂度为 O(n),百万级向量的相似度计算可能耗时数秒。为此 FREDDY 实现了两种高级索引结构来解决这一问题。第一种是基于 Product Quantization(PQ,乘积量化)的近似最近邻搜索,将高维向量压缩为短编码,通过查表快速估算距离,实验中在 0.35 精度下将响应时间从 8.79 秒压缩到 1.06 秒。第二种是 IVFADC(Inverted File with Asymmetric Distance Calculation)索引,采用倒排文件结构对向量空间进行聚类分区,实现非穷举搜索,在同等精度下进一步将时间降至 0.03 秒。值得注意的是,FREDDY 的 PQ 和 IVFADC 实现参考了 Facebook Research 的 faiss 库。除了基础的相似度查询,FREDDY 还支持更复杂的语义操作。类比查询(Analogy Queries)可以回答「A 之于 B,相当于 C 之于谁?」类型的问题——例如给定「弗朗西斯·福特·科波拉」对应「教父」,询问与「克里斯托弗·诺兰」最对应的电影,往往能得到正确的答案。K 最近邻(kNN)查询允许指定返回多少个最相似结果,而 kNN-Join 操作则能在两组文本数据之间做交叉相似度计算,比如将电影标题与影评文本按语义匹配。分组操作(Groups)则支持对语义相近的文本进行聚类分析。
图1:Post Verification 效果 Post Verification(后验)机制是 FREDDY 精度提升的关键。当 PQ 或 IVFADC 返回初步结果后,系统再用精确的余弦相似度重新排序,从而在牺牲少量速度的前提下大幅提升精度。从图中可以看出,开启后验后 IVFADC 的精度从 0.35 提升到 0.65,PQ 则从 0.38 提升到 0.87,响应时间从 0.03 秒略微上升到 0.26 秒,仍然远快于精确搜索的 8.79 秒。这种设计体现了向量数据库中经典的「先快后准」(Approximate then Refine)策略。
图2:kNN-Join 性能评估 kNN-Join 操作的精度与执行时间呈现典型的帕累托权衡: selectivity 参数(alpha)越高,精度越高但耗时越长。图中每种颜色代表不同的 alpha 值,不同符号代表不同的距离计算方法。在 post verification 因子(pvf)=50 的条件下,batch 模式(蓝色圆圈)能够在保持较高精度的同时将时间控制在 1 秒以内。
图3:批处理查询性能对比
从代码架构来看,FREDDY 分为三个核心部分。C 语言编写的 PostgreSQL 扩展(freddy_extension/)负责底层的向量计算与数据库集成,其中 core_functions.c 实现了余弦相似度等基础函数,ivpq_search_in.c 实现了 IVFADC 索引搜索逻辑,index_utils.c 提供了索引操作的通用工具,所有函数遵循 PostgreSQL 的 PG_FUNCTION_INFO_V1 宏规范,符合官方扩展开发标准。Python 脚本(index_creation/)则负责向量数据的导入与索引构建,transform_vecs.py 将 Google News word2vec 二进制模型转换为文本格式,vec2database.py 负责数据入库,pq_index.py 和 ivfadc.py 分别创建对应的索引结构。整个系统在 PostgreSQL 12 上编译运行,使用 faiss 作为量化计算的后端依赖。