当前位置:首页>php>纯 PHP 向量数据库 PHPVector

纯 PHP 向量数据库 PHPVector

  • 2026-09-08 10:04:23
纯 PHP 向量数据库 PHPVector

PHPVector

一个纯 PHP 向量数据库,实现了 HNSW(Hierarchical Navigable Small World)用于近似最近邻搜索,以及 BM25 用于全文检索。两种引擎可以组合成一个单一的 混合搜索(hybrid search) 管道。

要求

  • PHP 8.2+
  • 核心功能无需任何外部 PHP 扩展
  • ext-pcntl(可选)。启用异步文档写入,可显著降低插入延迟

安装

composer require ezimuel/phpvector

快速开始

1. 插入文档

Document 对象包含密集嵌入向量、可选的原始文本(用于 BM25)以及你希望随结果返回的任意元数据。id 字段可选——如果省略,将自动分配一个随机的 UUID v4。

usePHPVector\Document;use PHPVector\VectorDatabase;$db = new VectorDatabase();$db->addDocuments([new Document(        id: 1,        vector: [0.12, 0.85, 0.44, 0.67],        text: 'PHP vector database with HNSW index',        metadata: ['url' => 'https://example.com/1', 'lang' => 'en'],    ),new Document(        id: 2,        vector: [0.91, 0.23, 0.78, 0.05],        text: 'Approximate nearest neighbour search in PHP',        metadata: ['url' => 'https://example.com/2', 'lang' => 'en'],    ),new Document(        id: 3,        vector: [0.33, 0.61, 0.19, 0.88],        text: 'BM25 full-text ranking algorithm explained',        metadata: ['url' => 'https://example.com/3', 'lang' => 'en'],    ),// 未提供 id 时,会自动分配 UUID v4new Document(        vector: [0.55, 0.42, 0.71, 0.30],        text: 'Hybrid search with Reciprocal Rank Fusion',    ),]);

2. 向量搜索

使用 HNSW 查找与查询向量最相似的 k 个文档。

$queryVector = [0.10, 0.80, 0.50, 0.60];$results = $db->vectorSearch(vector: $queryVector, k: 2);foreach ($results as $result) {echo sprintf("[%d] score=%.4f  %s\n",        $result->rank,        $result->score,        $result->document->metadata['url'],    );}// 输出示例:// [1] score=0.9987  https://example.com/1// [2] score=0.8341  https://example.com/3

3. 全文搜索

使用 BM25 根据文本查询对文档进行相关性排序。

$results = $db->textSearch(query: 'nearest neighbour PHP', k: 2);foreach ($results as $result) {echo sprintf("[%d] score=%.4f  %s\n",        $result->rank,        $result->score,        $result->document->metadata['url'],    );}// 输出示例:// [1] score=1.2430  https://example.com/2// [2] score=0.8761  https://example.com/1

4. 混合搜索

将向量相似度分数和 BM25 分数融合成一个统一的排序列表。

推荐方式

RRF 基于排名且与分数尺度无关,无需调参。

usePHPVector\HybridMode;$results = $db->hybridSearch(    vector: $queryVector,    text:   'vector database PHP',    k:      3,    mode:   HybridMode::RRF,);foreach ($results as $result) {echo sprintf("[%d] score=%.4f  %s\n",        $result->rank,        $result->score,        $result->document->metadata['url'],    );}

加权组合

将两种分数都归一化到 [0, 1] 区间,然后应用显式权重。

$results = $db->hybridSearch(    vector:       $queryVector,    text:         'vector database PHP',    k:            3,    mode:         HybridMode::Weighted,    vectorWeight: 0.7,    textWeight:   0.3,);

配置

HNSW 和 BM25 引擎均可完全配置。将配置对象传递给 VectorDatabase 构造函数即可。

usePHPVector\BM25\ConfigasBM25Config;use PHPVector\BM25\SimpleTokenizer;use PHPVector\Distance;use PHPVector\HNSW\ConfigasHNSWConfig;use PHPVector\VectorDatabase;$db = new VectorDatabase(    hnswConfig: new HNSWConfig(        M:               16,    // 每层每个节点的最大连接数。越高 → 召回率越好,但内存占用增加。        efConstruction:  200,   // 构建索引时的束宽。越高 → 图质量越好,但插入变慢。        efSearch:        50,    // 查询时的束宽。越高 → 召回率越好,但查询变慢。        distance:        Distance::Cosine, // 支持:Cosine | Euclidean | DotProduct | Manhattan        useHeuristic:    true,  // 多样化邻居选择(推荐启用)。    ),    bm25Config: new BM25Config(        k1: 1.5,   // TF 饱和度。推荐范围 1.2–2.0。        b:  0.75,  // 长度归一化。0 = 不归一化,1 = 完全归一化。    ),    tokenizer: new SimpleTokenizer(        stopWords:      SimpleTokenizer::DEFAULT_STOP_WORDS,        minTokenLength: 2,    ),);

距离度量

度量
最适用场景
Distance::Cosine
文本嵌入、已归一化向量
Distance::Euclidean
原始未归一化向量
Distance::DotProduct
单位归一化向量(比 Cosine 更快)
Distance::Manhattan
稀疏向量,对异常值更鲁棒

HNSW 调优速查表

目标
调整参数
提高召回率
增大 efSearch 或 efConstruction
加快查询速度
减小 efSearch
减少内存占用
减小 M
处理聚类数据时获得更好图结构
保持 useHeuristic: true

持久化

PHPVector 采用基于文件夹的持久化模型。每个数据库对应一个独立目录,里面包含 HNSW 图、BM25 索引以及每个文档单独的文件。这种设计有两个主要优势:

  • 加载时内存占用低 —— 仅将 HNSW 图和 BM25 索引加载到内存。单个文档文件(docs/{n}.bin)采用懒加载,仅在搜索结果中出现时才读取。
  • 插入延迟低 —— 文档文件通过子进程异步写入磁盘(需要 ext-pcntl),因此 addDocument() 调用会立即返回。

文件夹结构

/var/data/mydb/  meta.json       — 距离度量、维度、文档 ID 映射  hnsw.bin        — HNSW 图(向量 + 连接关系)  bm25.bin        — BM25 倒排索引  docs/    0.bin         — 文档 0(id、文本、元数据)    1.bin         — 文档 1    …

保存

在构造函数中传入 path 参数即可启用持久化。每次 addDocument() 调用都会将文档文件写入 docs/ 目录(启用 ext-pcntl 时异步进行)。最后调用一次 save() 将 HNSW 图和 BM25 索引刷新到磁盘(会等待所有异步写入完成)。

usePHPVector\Document;usePHPVector\VectorDatabase;$db = new VectorDatabase(path: '/var/data/mydb');$db->addDocuments([new Document(id: 1, vector: [0.12, 0.85, 0.44], text: 'PHP vector search', metadata: ['source' => 'blog']),new Document(id: 2, vector: [0.91, 0.23, 0.78], text: 'Approximate nearest neighbour'),// ... 可以插入数千个文档]);// 将 HNSW 图和 BM25 索引刷盘(文档文件已异步写入)$db->save();

加载

使用 VectorDatabase::open() 加载已保存的数据库(文档加载部分此处原文被截断,实际使用时可参考源码或后续更新)。

最新文章

随机文章