You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Vue3或Laravel/PHP结合OpenAI实现Pinecone/Zilliz向量数据库搜索?

Vue3 + Laravel/PHP 结合 OpenAI 与 Pinecone/Zilliz 实现向量搜索方案

一、Laravel/PHP 后端核心实现

1. 依赖安装与配置

  • 安装 OpenAI 和 Pinecone/Zilliz 的 PHP SDK
    composer require openai-php/client pinecone-php/client
    
  • 在 .env 文件中配置密钥与服务地址:
    OPENAI_API_KEY=your_openai_key
    PINECONE_API_KEY=your_pinecone_key
    PINECONE_ENVIRONMENT=us-east1-gcp # 对应你的Pinecone集群环境
    ZILLIZ_CLUSTER_ENDPOINT=your_zilliz_endpoint # 使用Zilliz时配置
    ZILLIZ_API_KEY=your_zilliz_key
    

2. 文本转向量服务封装

创建 app/Services/VectorService.php 类,处理向量生成、入库与搜索逻辑:

<?php

namespace App\Services;

use OpenAI\Client as OpenAIClient;
use Pinecone\Client as PineconeClient;

class VectorService
{
    protected $openai;
    protected $vectorDb;

    public function __construct()
    {
        // 初始化OpenAI客户端
        $this->openai = OpenAIClient::factory()->withApiKey(env('OPENAI_API_KEY'))->make();
        
        // 初始化向量数据库客户端(Pinecone/Zilliz通用,Zilliz兼容Pinecone API)
        $this->vectorDb = new PineconeClient(
            env('PINECONE_API_KEY', env('ZILLIZ_API_KEY')),
            env('PINECONE_ENVIRONMENT', ''),
            env('ZILLIZ_CLUSTER_ENDPOINT', '')
        );
    }

    // 将文本转换为OpenAI Embedding向量
    public function textToVector(string $text): array
    {
        $response = $this->openai->embeddings()->create([
            'model' => 'text-embedding-ada-002',
            'input' => $text,
        ]);

        return $response->embeddings[0]->embedding;
    }

    // 向量写入数据库
    public function upsertVector(string $id, array $vector, array $metadata = [])
    {
        $this->vectorDb->index('your-index-name')->upsert([
            'vectors' => [
                [
                    'id' => $id,
                    'values' => $vector,
                    'metadata' => $metadata
                ]
            ]
        ]);
    }

    // 向量相似性搜索
    public function searchVectors(array $queryVector, int $topK = 5): array
    {
        $response = $this->vectorDb->index('your-index-name')->query([
            'vector' => $queryVector,
            'topK' => $topK,
            'includeMetadata' => true
        ]);

        return $response->matches;
    }
}

3. 封装API接口

创建 app/Http/Controllers/SearchController.php,提供前端调用的接口:

<?php

namespace App\Http\Controllers;

use App\Services\VectorService;
use Illuminate\Http\Request;

class SearchController extends Controller
{
    protected $vectorService;

    public function __construct(VectorService $vectorService)
    {
        $this->vectorService = $vectorService;
    }

    // 向量搜索接口
    public function search(Request $request)
    {
        $request->validate(['query' => 'required|string']);
        
        $queryVector = $this->vectorService->textToVector($request->query);
        $results = $this->vectorService->searchVectors($queryVector);

        return response()->json(['data' => $results]);
    }

    // 批量导入文本生成向量入库接口
    public function import(Request $request)
    {
        $request->validate([
            'documents' => 'required|array',
            'documents.*.id' => 'required|string',
            'documents.*.text' => 'required|string',
            'documents.*.metadata' => 'nullable|array'
        ]);

        foreach ($request->documents as $doc) {
            $vector = $this->vectorService->textToVector($doc['text']);
            $this->vectorService->upsertVector($doc['id'], $vector, $doc['metadata'] ?? []);
        }

        return response()->json(['message' => '导入成功']);
    }
}

在 routes/api.php 中注册路由:

Route::post('/search', [SearchController::class, 'search']);
Route::post('/import', [SearchController::class, 'import']);

二、Vue3 前端交互实现

1. 搜索组件实现

创建 src/components/VectorSearch.vue 组件:

<template>
  <div class="search-container">
    <input 
      v-model="searchQuery" 
      type="text" 
      placeholder="输入搜索关键词..."
      @keyup.enter="handleSearch"
    />
    <button @click="handleSearch">搜索</button>
    
    <div v-if="results.length > 0" class="search-results">
      <h3>搜索结果</h3>
      <div v-for="result in results" :key="result.id" class="result-item">
        <p><strong>相似度:</strong> {{ result.score.toFixed(4) }}</p>
        <p><strong>内容:</strong> {{ result.metadata.text }}</p>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import axios from 'axios';

const searchQuery = ref('');
const results = ref([]);

const handleSearch = async () => {
  if (!searchQuery.value.trim()) return;
  
  try {
    const response = await axios.post('/api/search', {
      query: searchQuery.value
    });
    results.value = response.data.data;
  } catch (error) {
    console.error('搜索失败:', error);
  }
};
</script>

<style scoped>
.search-container {
  max-width: 600px;
  margin: 20px auto;
}
input {
  width: 70%;
  padding: 8px;
  margin-right: 8px;
}
button {
  padding: 8px 16px;
}
.search-results {
  margin-top: 20px;
}
.result-item {
  border: 1px solid #eee;
  padding: 10px;
  margin-bottom: 10px;
  border-radius: 4px;
}
</style>

2. 关键注意事项

  • 后端需配置CORS,可通过 fruitcake/laravel-cors 包快速实现
  • 向量数据库需提前创建对应维度的索引(与OpenAI Embedding维度一致,text-embedding-ada-002为1536维)
  • 生产环境需对接口做限流、鉴权处理

内容的提问来源于stack exchange,提问作者Vitaliy Kadatskikh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:40:31