向量嵌入(Embeddings)
向量嵌入(Embeddings)是將文本轉換為高維向量的技術,常用於語義搜索、RAG(檢索增強生成)、文本分類和相似度計算。RouteAPI 提供標準的 OpenAI 兼容 Embeddings 接口,支持多個嵌入模型。
Endpoint
Section titled “Endpoint”POST /v1/embeddings完整地址:
https://api.routeapi.ai/v1/embeddings| 場景 | 說明 |
|---|---|
| 語義搜索 | 將文檔和查詢轉為向量,通過相似度檢索相關內容 |
| RAG | 檢索相關文檔片段作為上下文,增強大模型生成質量 |
| 文本分類 | 將文本向量化後用於聚類或分類任務 |
| 推薦系統 | 計算文本相似度用於內容推薦 |
| 去重檢測 | 通過向量相似度識別重複或近似內容 |
curl https://api.routeapi.ai/v1/embeddings \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "text-embedding-3-small", "input": "RouteAPI 是一個統一的 AI API 網關" }'curl https://api.routeapi.ai/v1/embeddings \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "text-embedding-3-small", "input": [ "第一段文本", "第二段文本", "第三段文本" ] }'| 字段 | 類型 | 必填 | 說明 |
|---|---|---|---|
model | string | 是 | 嵌入模型 ID |
input | string/array | 是 | 單個文本字符串或文本數組 |
encoding_format | string | 否 | 向量編碼格式,float 或 base64,默認 float |
dimensions | number | 否 | 返回向量維度(部分模型支持),用於降維 |
user | string | 否 | 終端用戶標識,用於追蹤和濫用監控 |
{ "object": "list", "data": [ { "object": "embedding", "index": 0, "embedding": [ 0.0023064255, -0.009327292, 0.015797347, ... ] } ], "model": "text-embedding-3-small", "usage": { "prompt_tokens": 8, "total_tokens": 8 }}響應字段說明
Section titled “響應字段說明”| 字段 | 說明 |
|---|---|
object | 固定為 list |
data | 嵌入結果數組 |
data[].embedding | 浮點數向量數組 |
data[].index | 輸入文本的索引位置 |
model | 實際使用的模型 ID |
usage.prompt_tokens | 輸入消耗的 token 數 |
usage.total_tokens | 總 token 數 |
支持的嵌入模型
Section titled “支持的嵌入模型”OpenAI 模型
Section titled “OpenAI 模型”| 模型 ID | 默認維度 | 性能 | 適用場景 |
|---|---|---|---|
text-embedding-3-small | 1536 | 高性價比 | 通用語義搜索、RAG |
text-embedding-3-large | 3072 | 高精度 | 複雜語義任務 |
text-embedding-ada-002 | 1536 | 穩定經典 | 向後兼容 |
Google 模型
Section titled “Google 模型”| 模型 ID | 默認維度 | 說明 |
|---|---|---|
text-embedding-004 | 768 | Google 最新嵌入模型 |
gemini-embedding-001 | 768 | Gemini 系列嵌入模型 |
| 模型 ID | 默認維度 | 供應商 |
|---|---|---|
text-embedding-v1 | 1024 | 百度文心 |
embedding-bert-512-v1 | 512 | 智譜 AI |
bge-large-zh | 1024 | 智源 BGE(中文) |
bge-large-en | 1024 | 智源 BGE(英文) |
模型可用性以控制台模型列表為準,不同賬戶可用模型可能不同。
批量大小限制
Section titled “批量大小限制”- 單次請求最多處理的文本數量取決於具體模型和服務配置。
- 建議單次請求不超過 100 條文本。
- 單個文本的 token 數通常不應超過模型的最大輸入限制(通常為 8192 tokens)。
批量優化建議
Section titled “批量優化建議”- 合並請求:將多個短文本合並到一次請求中,減少網絡往返。
- 並發控制:大批量任務可分批並發,建議並發數不超過 5。
- 錯誤處理:批量中某個文本失敗時,整個請求可能失敗,需要做好重試和錯誤處理。
Python(OpenAI SDK)
Section titled “Python(OpenAI SDK)”from openai import OpenAI
client = OpenAI( api_key="sk-your-routeapi-token", base_url="https://api.routeapi.ai/v1")
# 單個文本response = client.embeddings.create( model="text-embedding-3-small", input="RouteAPI 是一個統一的 AI API 網關")embedding = response.data[0].embeddingprint(f"向量維度: {len(embedding)}")print(f"前 5 個值: {embedding[:5]}")
# 批量文本texts = [ "人工智能正在改變世界", "機器學習是 AI 的核心技術", "深度學習推動了 AI 的發展"]response = client.embeddings.create( model="text-embedding-3-small", input=texts)for i, data in enumerate(response.data): print(f"文本 {i}: 維度 {len(data.embedding)}")Node.js(OpenAI SDK)
Section titled “Node.js(OpenAI SDK)”import OpenAI from 'openai';
const client = new OpenAI({ apiKey: 'sk-your-routeapi-token', baseURL: 'https://api.routeapi.ai/v1'});
async function getEmbedding() { // 單個文本 const response = await client.embeddings.create({ model: 'text-embedding-3-small', input: 'RouteAPI 是一個統一的 AI API 網關' });
const embedding = response.data[0].embedding; console.log(`向量維度: ${embedding.length}`); console.log(`前 5 個值: ${embedding.slice(0, 5)}`);
// 批量文本 const texts = [ '人工智能正在改變世界', '機器學習是 AI 的核心技術', '深度學習推動了 AI 的發展' ];
const batchResponse = await client.embeddings.create({ model: 'text-embedding-3-small', input: texts });
batchResponse.data.forEach((item, i) => { console.log(`文本 ${i}: 維度 ${item.embedding.length}`); });}
getEmbedding();curl https://api.routeapi.ai/v1/embeddings \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "text-embedding-3-small", "input": ["文本1", "文本2", "文本3"] }'語義相似度計算
Section titled “語義相似度計算”Python(使用 NumPy)
Section titled “Python(使用 NumPy)”import numpy as npfrom openai import OpenAI
client = OpenAI( api_key="sk-your-routeapi-token", base_url="https://api.routeapi.ai/v1")
def cosine_similarity(vec1, vec2): """計算余弦相似度""" return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
# 獲取兩段文本的嵌入向量texts = [ "RouteAPI 是一個 AI API 網關", "RouteAPI 提供統一的模型接入服務", "今天天氣很好"]
response = client.embeddings.create( model="text-embedding-3-small", input=texts)
embeddings = [data.embedding for data in response.data]
# 計算相似度sim_0_1 = cosine_similarity(embeddings[0], embeddings[1])sim_0_2 = cosine_similarity(embeddings[0], embeddings[2])
print(f"文本0 和 文本1 的相似度: {sim_0_1:.4f}") # 高相似度print(f"文本0 和 文本2 的相似度: {sim_0_2:.4f}") # 低相似度Node.js(使用數學庫)
Section titled “Node.js(使用數學庫)”import OpenAI from 'openai';
const client = new OpenAI({ apiKey: 'sk-your-routeapi-token', baseURL: 'https://api.routeapi.ai/v1'});
function cosineSimilarity(vec1, vec2) { const dotProduct = vec1.reduce((sum, val, i) => sum + val * vec2[i], 0); const mag1 = Math.sqrt(vec1.reduce((sum, val) => sum + val * val, 0)); const mag2 = Math.sqrt(vec2.reduce((sum, val) => sum + val * val, 0)); return dotProduct / (mag1 * mag2);}
async function computeSimilarity() { const texts = [ 'RouteAPI 是一個 AI API 網關', 'RouteAPI 提供統一的模型接入服務', '今天天氣很好' ];
const response = await client.embeddings.create({ model: 'text-embedding-3-small', input: texts });
const embeddings = response.data.map(d => d.embedding);
const sim_0_1 = cosineSimilarity(embeddings[0], embeddings[1]); const sim_0_2 = cosineSimilarity(embeddings[0], embeddings[2]);
console.log(`文本0 和 文本1 的相似度: ${sim_0_1.toFixed(4)}`); console.log(`文本0 和 文本2 的相似度: ${sim_0_2.toFixed(4)}`);}
computeSimilarity();向量數據庫集成
Section titled “向量數據庫集成”Pinecone 示例
Section titled “Pinecone 示例”from openai import OpenAIimport pinecone
# 初始化 RouteAPI 客戶端client = OpenAI( api_key="sk-your-routeapi-token", base_url="https://api.routeapi.ai/v1")
# 初始化 Pineconepinecone.init(api_key="your-pinecone-key", environment="your-env")index = pinecone.Index("your-index-name")
# 生成嵌入並存儲documents = [ {"id": "doc1", "text": "RouteAPI 是一個 AI API 網關"}, {"id": "doc2", "text": "支持多家 AI 模型供應商"}, {"id": "doc3", "text": "提供統一的接口和計費"}]
for doc in documents: # 生成嵌入 response = client.embeddings.create( model="text-embedding-3-small", input=doc["text"] ) embedding = response.data[0].embedding
# 存儲到 Pinecone index.upsert([(doc["id"], embedding, {"text": doc["text"]})])
# 查詢query = "什麼是 RouteAPI"query_response = client.embeddings.create( model="text-embedding-3-small", input=query)query_embedding = query_response.data[0].embedding
# 搜索相似文檔results = index.query(query_embedding, top_k=3, include_metadata=True)for match in results["matches"]: print(f"相似度: {match['score']:.4f}, 文本: {match['metadata']['text']}")Weaviate 示例
Section titled “Weaviate 示例”import weaviatefrom openai import OpenAI
# 初始化 RouteAPI 客戶端client = OpenAI( api_key="sk-your-routeapi-token", base_url="https://api.routeapi.ai/v1")
# 連接 Weaviateweaviate_client = weaviate.Client("http://localhost:8080")
# 創建 schema(如果不存在)schema = { "class": "Document", "vectorizer": "none", # 我們自己提供向量 "properties": [ {"name": "text", "dataType": ["text"]} ]}
# 插入文檔documents = [ "RouteAPI 是一個 AI API 網關", "支持多家 AI 模型供應商", "提供統一的接口和計費"]
for doc_text in documents: # 生成嵌入 response = client.embeddings.create( model="text-embedding-3-small", input=doc_text ) embedding = response.data[0].embedding
# 存儲到 Weaviate weaviate_client.data_object.create( data_object={"text": doc_text}, class_name="Document", vector=embedding )
# 查詢query = "什麼是 RouteAPI"query_response = client.embeddings.create( model="text-embedding-3-small", input=query)query_embedding = query_response.data[0].embedding
# 向量搜索results = weaviate_client.query.get("Document", ["text"]) \ .with_near_vector({"vector": query_embedding}) \ .with_limit(3) \ .with_additional(["distance"]) \ .do()
for item in results["data"]["Get"]["Document"]: print(f"距離: {item['_additional']['distance']:.4f}, 文本: {item['text']}")RAG 應用示例
Section titled “RAG 應用示例”from openai import OpenAI
client = OpenAI( api_key="sk-your-routeapi-token", base_url="https://api.routeapi.ai/v1")
# 知識庫文檔knowledge_base = [ "RouteAPI 是一個統一的 AI API 網關,聚合了 OpenAI、Claude、Gemini 等多家供應商。", "RouteAPI 提供統一的認證、計費和監控能力。", "RouteAPI 支持流式輸出、工具調用和多模態輸入。", "用戶可以通過控制台管理 API Token、查看用量日志和充值余額。"]
# 為知識庫生成嵌入kb_embeddings_response = client.embeddings.create( model="text-embedding-3-small", input=knowledge_base)kb_embeddings = [data.embedding for data in kb_embeddings_response.data]
# 用戶問題user_query = "RouteAPI 有哪些功能?"
# 為問題生成嵌入query_response = client.embeddings.create( model="text-embedding-3-small", input=user_query)query_embedding = query_response.data[0].embedding
# 計算相似度並檢索最相關的文檔import numpy as np
def cosine_similarity(vec1, vec2): return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
similarities = [cosine_similarity(query_embedding, kb_emb) for kb_emb in kb_embeddings]top_k = 2top_indices = np.argsort(similarities)[-top_k:][::-1]
# 構建上下文context = "\n".join([knowledge_base[i] for i in top_indices])
# 調用 Chat Completions 生成回答chat_response = client.chat.completions.create( model="gpt-5.5", messages=[ {"role": "system", "content": "你是一個 RouteAPI 助手。請根據提供的上下文回答用戶問題。"}, {"role": "user", "content": f"上下文:\n{context}\n\n問題:{user_query}"} ])
print(chat_response.choices[0].message.content)1. 選擇合適的嵌入模型
Section titled “1. 選擇合適的嵌入模型”| 考慮因素 | 建議 |
|---|---|
| 通用場景 | 使用 text-embedding-3-small,性價比高 |
| 高精度需求 | 使用 text-embedding-3-large,維度更高 |
| 中文語義 | 考慮 bge-large-zh 等中文優化模型 |
| 成本優先 | 選擇維度較低的模型或使用 dimensions 參數降維 |
2. 文本預處理
Section titled “2. 文本預處理”def preprocess_text(text): """文本預處理""" # 去除多余空白 text = " ".join(text.split()) # 限制長度(避免超過模型限制) max_tokens = 8000 # 預留一些空間 if len(text.split()) > max_tokens: text = " ".join(text.split()[:max_tokens]) return text
# 使用clean_text = preprocess_text(raw_text)response = client.embeddings.create( model="text-embedding-3-small", input=clean_text)3. 維度選擇
Section titled “3. 維度選擇”部分模型(如 text-embedding-3-small 和 text-embedding-3-large)支持通過 dimensions 參數自定義輸出維度:
# 降低維度以節省存儲和計算成本response = client.embeddings.create( model="text-embedding-3-small", input="RouteAPI 是一個 AI API 網關", dimensions=512 # 從默認 1536 降至 512)降維會略微損失精度,但可以顯著降低存儲成本和查詢延遲。建議在開發階段測試不同維度對業務指標的影響。
4. 成本優化
Section titled “4. 成本優化”- 批量處理:將多個文本合並到一次請求中。
- 緩存嵌入:對靜態文檔,生成一次嵌入後緩存起來重複使用。
- 選擇合適模型:不要盲目使用最大的模型,
text-embedding-3-small對多數場景已足夠。 - 降維:使用
dimensions參數降低向量維度。
5. 錯誤處理
Section titled “5. 錯誤處理”from openai import OpenAI, OpenAIError
client = OpenAI( api_key="sk-your-routeapi-token", base_url="https://api.routeapi.ai/v1")
def get_embedding_with_retry(text, max_retries=3): """帶重試的嵌入生成""" for attempt in range(max_retries): try: response = client.embeddings.create( model="text-embedding-3-small", input=text ) return response.data[0].embedding except OpenAIError as e: if attempt == max_retries - 1: raise print(f"請求失敗,重試 {attempt + 1}/{max_retries}: {e}") time.sleep(2 ** attempt) # 指數退避 return None6. 性能優化
Section titled “6. 性能優化”import asynciofrom openai import AsyncOpenAI
async_client = AsyncOpenAI( api_key="sk-your-routeapi-token", base_url="https://api.routeapi.ai/v1")
async def get_embeddings_batch(texts, batch_size=50): """異步批量獲取嵌入""" results = [] for i in range(0, len(texts), batch_size): batch = texts[i:i + batch_size] response = await async_client.embeddings.create( model="text-embedding-3-small", input=batch ) results.extend([data.embedding for data in response.data]) return results
# 使用texts = ["文本1", "文本2", ..., "文本1000"]embeddings = asyncio.run(get_embeddings_batch(texts))Q: 嵌入向量可以跨模型使用嗎?
不可以。不同模型生成的向量維度和語義空間不同,必須使用同一個模型生成查詢向量和文檔向量。
Q: 如何選擇相似度閾值?
余弦相似度範圍是 -1 到 1。一般:
-
0.8:高度相關
- 0.6-0.8:相關
- < 0.6:弱相關或不相關
具體閾值需要根據業務場景測試調優。
Q: 嵌入生成失敗常見原因?
| 錯誤 | 原因 | 解決方案 |
|---|---|---|
invalid_api_key | Token 無效 | 檢查 Authorization header |
model_not_found | 模型 ID 錯誤或不可用 | 檢查模型 ID 和賬戶權限 |
context_length_exceeded | 輸入文本過長 | 縮短文本或分段處理 |
rate_limit_exceeded | 請求過於頻繁 | 降低並發或增加間隔 |
Q: 如何處理多語言文本?
多數嵌入模型(如 text-embedding-3-small)支持多語言,但跨語言語義匹配效果取決於模型訓練。對中文場景,可優先考慮 bge-large-zh 等中文優化模型。
Q: 嵌入向量可以存儲多久?
嵌入向量是確定性的(相同輸入生成相同向量),可以長期存儲和復用,直到更換模型或模型版本更新。