查询向量
Perform similarity search and retrieve vectors using JavaScript SDK or Postgres.
此功能处于测试阶段
预计会有快速变化、功能有限,并可能出现破坏性更新。随着我们改进体验并扩大访问,欢迎分享反馈。
🌐 Expect rapid changes, limited features, and possible breaking updates. Share feedback as we refine the experience and expand access.
向量相似度搜索使用距离度量找到与查询向量最相似的向量。你可以用 JavaScript SDK 查询向量,也可以直接用 SQL 从 Postgres 查询。
🌐 Vector similarity search finds vectors most similar to a query vector using distance metrics. You can query vectors using the JavaScript SDK or directly from Postgres using SQL.
与 pgvector 的比较
向量桶和它们使用的任何 外部数据封装器 (FDW) 只支持一种相似性搜索算法,即 <===> 距离运算符。
🌐 Vector buckets and any Foreign Data Wrappers (FDW) they use only support one similarity search algorithm, the <===> distance operator.
基础相似性搜索 #
🌐 Basic similarity search
import { createClient } from '@supabase/supabase-js'const supabase = createClient('https://your-project-id.supabase.co', 'your-service-key')const index = supabase.storage.vectors.from('embeddings').index('documents-openai')// Query with a vector embeddingconst { data, error } = await index.queryVectors({ queryVector: { float32: [0.1, 0.2, 0.3 /* ... embedding of 1536 dimensions ... */], }, topK: 5, returnDistance: true, returnMetadata: true,})if (error) { console.error('Query failed:', error)} else { // Results are ranked by similarity (lowest distance = most similar) data.vectors.forEach((result, rank) => { console.log(`${rank + 1}. ${result.metadata?.title}`) console.log(` Similarity score: ${result.distance.toFixed(4)}`) })}检索超过100个结果 #
🌐 Retrieve more than 100 results
托管向量桶每次响应最多返回100个查询结果。要获取更多的最近邻结果,请将 topK 设置为你需要的总结果数,最多可到10,000,并按照 nextToken 进行操作,直到响应中不再包含它。其他查询参数在请求间保持不变。
🌐 Hosted vector buckets return at most 100 query results per response. To retrieve more nearest-neighbor results, set topK to the total number of results you need, up to 10,000, and follow nextToken until the response omits it. Keep the other query parameters unchanged between requests.
import { } from '@supabase/supabase-js'const = ('https://your-project-id.supabase.co', 'your-service-key')const = ...('embeddings').('documents-openai')const = { : { : [0.1, 0.2, 0.3 /* ... embedding of 1536 dimensions ... */], }, : 1000, : true, : true,}const = []let : string | undefineddo { const { , } = await .({ ..., ...( ? { } : {}), }) if () { throw } .(....) = .} while ().(`Retrieved ${.} matches`)本地查询限制
本地向量桶使用 pgvector。它们接受最多 100 的 topK 值,并且不支持 queryVectors 的 nextToken。有关提供商特定限制,请参见 Vector Bucket 限制。
🌐 Local vector buckets use pgvector. They accept topK values up to 100 and do not support nextToken for queryVectors. See Vector Bucket limits for the provider-specific limits.
语义搜索 #
🌐 Semantic search
通过将查询文本嵌入来查找与查询相似的文档:
🌐 Find documents similar to a query by embedding the query text:
import { createClient } from '@supabase/supabase-js'import OpenAI from 'openai'const supabase = createClient(...)const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })async function semanticSearch(query, topK = 5) { // Embed the query const queryEmbedding = await openai.embeddings.create({ model: 'text-embedding-3-small', input: query }) const queryVector = queryEmbedding.data[0].embedding // Search for similar vectors const { data, error } = await supabase.storage.vectors .from('embeddings') .index('documents-openai') .queryVectors({ queryVector: { float32: queryVector }, topK, returnDistance: true, returnMetadata: true }) if (error) { throw error } return data.vectors.map((result) => ({ id: result.key, title: result.metadata?.title, similarity: 1 - result.distance, // Convert distance to similarity (0-1) metadata: result.metadata }))}// Usageconst results = await semanticSearch('How do I use vector search?')results.forEach((result) => { console.log(`${result.title} (${(result.similarity * 100).toFixed(1)}% similar)`)})筛选相似搜索 #
🌐 Filtered similarity search
const index = supabase.storage.vectors .from('embeddings') .index('documents-openai')// Search with metadata filterconst { data } = await index.queryVectors({ queryVector: { float32: [...embedding...] }, topK: 10, filter: { // Filter by metadata fields category: 'electronics', in_stock: true, price: { $lte: 500 } // Less than or equal to 500 }, returnDistance: true, returnMetadata: true})获取特定向量 #
🌐 Retrieving specific vectors
const index = supabase.storage.vectors.from('embeddings').index('documents-openai')const { data, error } = await index.getVectors({ keys: ['doc-1', 'doc-2', 'doc-3'], returnData: true, returnMetadata: true,})if (!error) { data.vectors.forEach((vector) => { console.log(`${vector.key}: ${vector.metadata?.title}`) })}列出向量 #
🌐 Listing vectors
const index = supabase.storage.vectors.from('embeddings').index('documents-openai')let nextToken = undefinedlet pageCount = 0do { const { data, error } = await index.listVectors({ maxResults: 100, nextToken, returnData: false, // Don't return embeddings for faster response returnMetadata: true, }) if (error) break pageCount++ console.log(`Page ${pageCount}: ${data.vectors.length} vectors`) data.vectors.forEach((vector) => { console.log(` - ${vector.key}: ${vector.metadata?.title}`) }) nextToken = data.nextToken} while (nextToken)混合搜索:向量 + 关系数据 #
🌐 Hybrid search: Vectors + relational data
将相似性搜索与 SQL 过滤和连接结合起来:
🌐 Combine similarity search with SQL filtering and joins:
async function hybridSearch(queryVector, filters) { const index = supabase.storage.vectors.from('embeddings').index('documents-openai') // Get similar vectors with filters const { data: vectorResults } = await index.queryVectors({ queryVector: { float32: queryVector }, topK: 100, filter: filters, returnDistance: true, returnMetadata: true, }) // Get additional details from relational database const { data: details } = await supabase .from('documents') .select('*') .in( 'id', vectorResults.vectors.map((v) => v.metadata?.doc_id) ) // Merge results return vectorResults.vectors.map((vector) => { const detail = details?.find((d) => d.id === vector.metadata?.doc_id) return { ...vector, ...detail, } })}真实案例 #
🌐 Real-world examples
RAG(检索增强生成) #
🌐 RAG (retrieval-augmented generation)
import OpenAI from 'openai'import { createClient } from '@supabase/supabase-js'async function retrieveContextForLLM(userQuery) { const supabase = createClient(...) const openai = new OpenAI() // 1. Embed the user query const queryEmbedding = await openai.embeddings.create({ model: 'text-embedding-3-small', input: userQuery }) // 2. Retrieve relevant documents const { data: vectorResults } = await supabase.storage.vectors .from('embeddings') .index('documents-openai') .queryVectors({ queryVector: { float32: queryEmbedding.data[0].embedding }, topK: 5, returnMetadata: true }) // 3. Use vectors to augment LLM prompt const context = vectorResults.vectors .map(v => v.metadata?.content || '') .join('\n\n') const response = await openai.chat.completions.create({ model: 'gpt-4', messages: [ { role: 'system', content: `Use the following context to answer the user's question:\n\n${context}` }, { role: 'user', content: userQuery } ] }) return response.choices[0].message.content}产品推荐 #
🌐 Product recommendations
async function recommendProducts(userEmbedding, topK = 5) { const supabase = createClient(...) // Find similar products const { data } = await supabase.storage.vectors .from('embeddings') .index('products-openai') .queryVectors({ queryVector: { float32: userEmbedding }, topK, filter: { in_stock: true }, returnMetadata: true }) return data.vectors.map((result) => ({ id: result.metadata?.product_id, name: result.metadata?.name, price: result.metadata?.price, similarity: 1 - result.distance }))}在相似性搜索前进行过滤 #
🌐 Filtering before similarity search
// Use metadata filters to reduce search scopeconst { data } = await index.queryVectors({ queryVector, topK: 100, filter: { category: 'electronics', // Pre-filter by category },})下一步 #
🌐 Next steps