文本向量化
POST /v1/embeddings —— 把文本转成向量,用于检索、聚类与相似度。
向量化是做什么的#
向量化把一段文本变成一串数字(一个向量),使得意思相近的文本得到方向相近的向量。有了它,"检索"就从"字面包含关键词"变成了"意思接近"——用户搜"退钱",能命中写着"退款"的那篇文档。
典型用法:把你的文档逐段向量化后存进向量数据库;用户提问时把问题也向量化,在库里找最接近的几段,再把这几段连同问题一起交给对话模型作答。这套做法叫检索增强生成(RAG)。
同一批数据必须用同一个模型
不同模型产出的向量互不兼容,维度不同,即使维度碰巧相同也不在同一个语义空间里。换模型意味着整库重算,所以选型要在灌数据之前定下来。
能力边界#
- 只接受目录声明了
embedding模态的模型;对话模型打到本端点会按用错端点处理。 input可以是字符串或字符串数组;数组最多 2048 条,空串不合法。encoding_format仅float/base64;dimensions若传必须 > 0(能否缩维看上游)。- 向量模型不应发送到
/v1/chat/completions,该端点无法产出可用的向量。
发起请求#
与 OpenAI 的 Embeddings 接口同形,改掉 base_url 与 api_key 就能用现成 SDK。向量模型只走这条端点:把向量模型名发到 /v1/chat/completions 不会得到有意义的结果,反过来把对话模型发到这里会被判成用错端点。
modelstring必填- 向量模型名,可在 模型广场 按 embedding 模态筛选。
inputstring | string[] | int[] | int[][]必填- 待向量化的内容。四种形态均可接受:单条文本、文本数组、单条 token id 数组、token id 数组的数组。数组形态单次最多 2048 条,超出限制返回
invalid_request。 encoding_formatstringfloat(默认)或base64。base64形态下向量原样回传,不经过解码再编码,可避免 float32 十进制转换带来的精度损失。dimensionsinteger- 降维后的输出维数,取决于模型是否支持。平台只校验其大于 0;具体上限随模型而异,超出所选模型的支持范围时由上游返回错误。
userstring- 调用方自定义的终端用户标识,透传给上游。
bash
curl https://ogrouter.ai/v1/embeddings \ -H "Authorization: Bearer $AIROUTER_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "text-embedding-3-small", "input": ["今天天气不错", "The weather is nice today"] }'响应#
data 按 index 与请求里 input 的顺序一一对应。即使只发了一条文本,data 也是数组。
json
{ "object": "list", "model": "text-embedding-3-small", "data": [ { "object": "embedding", "index": 0, "embedding": [0.0023, -0.0091, "..."] }, { "object": "embedding", "index": 1, "embedding": [0.0117, 0.0042, "..."] } ], "usage": { "prompt_tokens": 14, "total_tokens": 14 }}没有流式
向量化的结果是定长向量,一次返回完,
stream 在这里没有意义,也不接受。Python:一次编码多段文本
python
import osfrom openai import OpenAI
client = OpenAI(api_key=os.environ["AIROUTER_API_KEY"], base_url="https://ogrouter.ai/v1")
response = client.embeddings.create( model="openai/text-embedding-3-small", input=[ "订单在支付后 7 天内可以申请全额退款。", "我们的办公地址位于香港中环。", ],)
for item in response.data: print(item.index, len(item.embedding), item.embedding[:3])Node.js:批量编码后写进你的向量库
javascript
import OpenAI from 'openai';
const client = new OpenAI({ apiKey: process.env.AIROUTER_API_KEY, baseURL: 'https://ogrouter.ai/v1',});
const chunks = ['订单在支付后 7 天内可以申请全额退款。', '我们的办公地址位于香港中环。'];
const { data } = await client.embeddings.create({ model: 'openai/text-embedding-3-small', input: chunks,});
// data 与 input 顺序一致,用 index 对回原文for (const item of data) { await vectorStore.upsert({ text: chunks[item.index], vector: item.embedding });}Java:一次编码多段文本
java
import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;
String body = """ { "model": "openai/text-embedding-3-small", "input": ["订单在支付后 7 天内可以申请全额退款。", "我们的办公地址位于香港中环。"] } """;
HttpRequest request = HttpRequest.newBuilder(URI.create("https://ogrouter.ai/v1/embeddings")) .header("Authorization", "Bearer " + System.getenv("AIROUTER_API_KEY")) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(body)) .build();
HttpResponse<String> response = HttpClient.newHttpClient() .send(request, HttpResponse.BodyHandlers.ofString());
// data 与 input 顺序一致,用 index 对回原文System.out.println(response.body());计费#
只按输入 token 计价,没有输出项。向量化不生成 token,成本完全由输入长度决定,预扣中同样不含输出部分。
- 响应里的
usage.prompt_tokens与usage.total_tokens相等,这是预期行为。 - 预扣按估算值计算并留有余量,实结按上游报回来的真实 token 数;差额当场退回。
- 计费口径与对话一致,详见 计费。
常见错误#
错误封装、请求 ID 与重试建议与其它端点完全一致,见 错误处理。