如何用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
相关产品推荐
相关产品推荐

