PHP项目怎么实现向量检索?

wen java案例 1

本文目录导读:

PHP项目怎么实现向量检索?

  1. 使用专用向量数据库(最推荐)
  2. PostgreSQL + pgvector 扩展(性价比最高)
  3. Elasticsearch + 向量插件(适合已有ES的场景)
  4. 纯PHP实现(仅适用于小数据量)
  5. 推荐选择建议
  6. 向量生成注意事项

在PHP项目中实现向量检索,通常有以下几种方案,按推荐程度排序:

使用专用向量数据库(最推荐)

Milvus + PHP 客户端

// 安装: composer require milvus-php/milvus-php
use Milvus\Client;
use Milvus\Collection;
$client = new Client(['host' => 'localhost', 'port' => 19530]);
// 创建集合
$collection = new Collection($client, 'documents');
$collection->create([
    'fields' => [
        ['name' => 'id', 'type' => 'int64', 'primary_key' => true],
        ['name' => 'vector', 'type' => 'float_vector', 'params' => ['dim' => 768]],
        ['name' => 'text', 'type' => 'varchar', 'max_length' => 1000],
    ]
]);
// 插入向量数据
$vectors = [[0.1, 0.2, ...], [0.3, 0.4, ...]]; // 768维向量
$collection->insert([
    ['id' => 1, 'vector' => $vectors[0], 'text' => '文档1'],
    ['id' => 2, 'vector' => $vectors[1], 'text' => '文档2'],
]);
// 向量检索
$results = $collection->search([
    'vector' => [0.15, 0.25, ...],
    'anns_field' => 'vector',
    'limit' => 10,
    'metric_type' => 'COSINE'
]);

Qdrant + PHP 客户端

// 安装: composer require qdrant/php-client
use Qdrant\Client;
$client = new Client('http://localhost:6333');
// 创建集合
$client->collections()->create('documents', [
    'vectors' => [
        'size' => 768,
        'distance' => 'Cosine'
    ]
]);
// 插入点
$client->points()->upsert('documents', [
    'points' => [
        ['id' => 1, 'vector' => [0.1, 0.2, ...], 'payload' => ['text' => '文档1']],
        ['id' => 2, 'vector' => [0.3, 0.4, ...], 'payload' => ['text' => '文档2']],
    ]
]);
// 搜索
$results = $client->points()->search('documents', [
    'vector' => [0.15, 0.25, ...],
    'limit' => 10
]);

Weaviate + PHP

// 安装: composer require flow-php/weaviate-schema-manager
use Weaviate\Client;
$client = Client::withApiKey('your-api-key', 'https://your-instance.weaviate.io');
// 创建Schema
$client->schema()->createClass([
    'class' => 'Document',
    'vectorizer' => 'none', // 使用自定义向量
    'properties' => [
        ['name' => 'text', 'dataType' => ['text']],
    ]
]);
// 插入数据
$client->data()->create([
    'class' => 'Document',
    'properties' => ['text' => '文档内容'],
    'vector' => [0.1, 0.2, ...]
]);
// 向量搜索
$results = $client->graphql()->raw('
    {
        Get {
            Document(nearVector: {vector: [0.15, 0.25, ...]}, limit: 10) {
                text
                _additional { distance }
            }
        }
    }
');

PostgreSQL + pgvector 扩展(性价比最高)

// 需要PostgreSQL + pgvector扩展
// 安装: composer require doctrine/dbal
$conn = new PDO('pgsql:host=localhost;dbname=test', 'user', 'password');
// 创建表和索引(需在数据库中执行)
$conn->exec("
    CREATE TABLE documents (
        id SERIAL PRIMARY KEY,
        text TEXT,
        vector vector(768)
    );
    CREATE INDEX ON documents USING ivfflat (vector vector_cosine_ops);
");
// 插入数据
$stmt = $conn->prepare("INSERT INTO documents (text, vector) VALUES (?, ?)");
$stmt->execute(['文档1', json_encode([0.1, 0.2, ...])]);
// 向量检索
$queryVector = json_encode([0.15, 0.25, ...]);
$stmt = $conn->prepare("
    SELECT text, vector <=> ?::vector AS distance
    FROM documents
    ORDER BY vector <=> ?::vector
    LIMIT 10
");
$stmt->execute([$queryVector, $queryVector]);
$results = $stmt->fetchAll();

Elasticsearch + 向量插件(适合已有ES的场景)

// 安装: composer require elasticsearch/elasticsearch
$client = Elastic\Elasticsearch\ClientBuilder::create()
    ->setHosts(['localhost:9200'])
    ->build();
// 创建索引
$client->indices()->create([
    'index' => 'documents',
    'body' => [
        'mappings' => [
            'properties' => [
                'vector' => [
                    'type' => 'dense_vector',
                    'dims' => 768,
                    'index' => true,
                    'similarity' => 'cosine'
                ],
                'text' => ['type' => 'text']
            ]
        ]
    ]
]);
// 插入数据
$client->index([
    'index' => 'documents',
    'body' => [
        'text' => '文档1',
        'vector' => [0.1, 0.2, ...]
    ]
]);
// 向量搜索
$results = $client->search([
    'index' => 'documents',
    'body' => [
        'knn' => [
            'field' => 'vector',
            'query_vector' => [0.15, 0.25, ...],
            'k' => 10,
            'num_candidates' => 100
        ]
    ]
]);

纯PHP实现(仅适用于小数据量)

class VectorSearch {
    public static function cosineSimilarity(array $vec1, array $vec2): float {
        $dotProduct = 0;
        $norm1 = 0;
        $norm2 = 0;
        for ($i = 0; $i < count($vec1); $i++) {
            $dotProduct += $vec1[$i] * $vec2[$i];
            $norm1 += $vec1[$i] ** 2;
            $norm2 += $vec2[$i] ** 2;
        }
        return $dotProduct / (sqrt($norm1) * sqrt($norm2));
    }
    public static function search(array $vectors, array $query, int $k = 10): array {
        $scores = [];
        foreach ($vectors as $id => $vector) {
            $scores[$id] = self::cosineSimilarity($query, $vector);
        }
        arsort($scores);
        return array_slice($scores, 0, $k, true);
    }
}
// 使用示例
$vectors = [
    1 => [0.1, 0.2, 0.3],
    2 => [0.4, 0.5, 0.6],
    // ...
];
$query = [0.15, 0.25, 0.35];
$results = VectorSearch::search($vectors, $query, 10);

推荐选择建议

场景 推荐方案 理由
新项目 pgvector 成本低,维护简单,功能足够
大规模(>1000万) Milvus 性能最好,支持分布式
已有ES ES向量搜索 无需新增基础设施
小数据(<10万) 纯PHP实现 无额外依赖,简单快速

向量生成注意事项

无论使用哪种方案,都需要提前生成向量:

// 使用 OpenAI embedding
function getEmbedding(string $text): array {
    $response = file_get_contents('https://api.openai.com/v1/embeddings', false, 
        stream_context_create([
            'http' => [
                'method' => 'POST',
                'header' => "Content-Type: application/json\r\nAuthorization: Bearer YOUR_API_KEY",
                'content' => json_encode(['model' => 'text-embedding-ada-002', 'input' => $text])
            ]
        ])
    );
    $data = json_decode($response, true);
    return $data['data'][0]['embedding'];
}

推荐从 pgvector 开始,成本最低且功能完善,后续可根据需要迁移到专业的向量数据库。

抱歉,评论功能暂时关闭!