# Embeddings

> POST /v1/embeddings text-কে vector বানায়, যা search, retrieval আর clustering-এর কাজে লাগে। catalog থেকে embedding model খোঁজা, request ও response, billing আর যেসব error আসতে পারে, সব এখানে।

`POST https://tokens.bd/v1/embeddings` হলো OpenAI-compatible embeddings endpoint। আপনি text পাঠান, প্রতিটা input-এর জন্য একটা করে vector ফেরত পান। এই vector জমিয়ে রেখে semantic search, RAG-এর retrieval, duplicate খোঁজা বা clustering-এ ব্যবহার করা যায়। gateway আগে আপনার key, plan আর সীমা যাচাই করে, তারপর body-টা যে model-এর নাম দিয়েছেন তার upstream provider-এর কাছে পাঠিয়ে দেয়।

এই endpoint শুধু **embedding model**-এর সাথে চলে। `deepseek/deepseek-v4.1-flash`-এর মতো chat model এখানে কাজ করে না, পাঠালে fail করবে। তাই আগে পরের section-টা পড়ে নিন।

## Embedding model খুঁজে নেওয়া

Tokens `GET /v1/models`-এ কোনো capability flag যোগ করে না, তাই ওই list-এ শুধু id-ই থাকে। embedding model খুঁজতে এভাবে এগোন:

1. [model catalog](/models) খুলে `embed` লিখে search করুন। search মেলে model-এর নাম, id আর provider ধরে।
2. model-এর পেজ খুলে context window আর প্রতি million token-এর input price দেখে নিন।
3. আপনার key দিয়ে model-টা call করা যায় কি না দেখুন: ওই key-র জন্য `GET /v1/models`-এ id-টা থাকতে হবে ([কোনো model কেন বাদ পড়ে](/docs/models-and-usage))।

catalog-এ একটাও embedding model না থাকলে বুঝবেন আপনার অ্যাকাউন্টে এখনো কোনোটা চালু নেই, আর `/v1/embeddings`-এর দেওয়ার মতো কিছু নেই। তালিকায় না আসা পর্যন্ত এখনকার embedding provider-ই ব্যবহার করতে থাকুন। catalog বদলায় বলে এই পেজে কোনো model-এর নাম দেওয়া হয়নি। নিচের উদাহরণগুলো id-টা environment variable থেকে পড়ে নেয়:

```bash
export EMBEDDING_MODEL="the-id-from-the-catalog"
```

## Embeddings তৈরি করা

:::code-tabs

```bash title="cURL"
curl https://tokens.bd/v1/embeddings \
  -H "Authorization: Bearer $TOKENS_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "model": "$EMBEDDING_MODEL",
  "input": ["How do I reset my password?", "Where can I change my billing email?"],
  "encoding_format": "float"
}
EOF
```

```python title="Python"
import os
from openai import OpenAI

client = OpenAI(base_url="https://tokens.bd/v1", api_key=os.environ["TOKENS_API_KEY"])

resp = client.embeddings.create(
    model=os.environ["EMBEDDING_MODEL"],
    input=["How do I reset my password?", "Where can I change my billing email?"],
    encoding_format="float",
)

vectors = [item.embedding for item in resp.data]
print(len(vectors), "vectors of", len(vectors[0]), "numbers")
print(resp.usage)
```

```typescript title="Node.js"
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://tokens.bd/v1", apiKey: process.env.TOKENS_API_KEY });

const resp = await client.embeddings.create({
  model: process.env.EMBEDDING_MODEL!,
  input: ["How do I reset my password?", "Where can I change my billing email?"],
  encoding_format: "float",
});

const vectors = resp.data.map((item) => item.embedding);
console.log(vectors.length, "vectors of", vectors[0].length, "numbers");
console.log(resp.usage);
```

:::

`Content-Type: application/json` header-টা ভুলবেন না। এটা না থাকলে gateway body পড়তে পারে না, আর `model` field দেওয়া থাকলেও 400 `invalid_request` দিয়ে বলে যে request-এ `model` field নেই।

## Request-এর field

body চলে OpenAI-র embeddings format মেনে। OpenAI-র API reference-এর সাথে 2026 সালের অক্টোবরে মিলিয়ে দেখা হয়েছে।

| Field             | Type            | নোট                                                                                                                         |
| ----------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `model`           | string          | বাধ্যতামূলক। embedding model-এর id, catalog-এ যেভাবে লেখা আছে ঠিক সেভাবে।                                                  |
| `input`           | string or array | বাধ্যতামূলক। একটা string, অথবা এক request-এ embed করার জন্য string-এর array। OpenAI-র format-এ token id-ও দেওয়া যায়।      |
| `encoding_format` | string          | `"float"` (raw API-তে default) বা `"base64"`। সমর্থন আছে কি না, সেটা model-এর provider-এর ওপর নির্ভর করে।                    |
| `dimensions`      | integer         | ছোট output vector। OpenAI-র নিজের API-তে সব model এটা নেয় না। আপনার model নেবে কি না, ঠিক করে তার provider।                |
| `user`            | string          | end-user-এর একটা identifier, যা provider-এর কাছে পাঠানো হয়।                                                                |

:::note[Parameter নির্ভর করে upstream model-এর ওপর]
gateway এই body থেকে শুধু `model` পড়ে, আর কিছু না। বাকি field-গুলো provider-এর কাছে যেমন আছে তেমনই যায়। তাই যে সীমাগুলো আসলে কাজে লাগে (প্রতি input-এ সর্বোচ্চ token, এক request-এ কয়টা input, `dimensions` চলে কি না, vector কত বড়), সেগুলো provider-এর, আর model ভেদে আলাদা। OpenAI-র নিজের embedding model-এর জন্য OpenAI-র docs বলে প্রতি input-এ 8,192 token, input array-তে সর্বোচ্চ 2,048টা item, আর পুরো এক request-এ 300,000 token। অন্য model-এর বেলায় এই সংখ্যা ধরে নেবেন না।
:::

request body সব মিলিয়ে 10 MB পর্যন্ত হতে পারে। এর চেয়ে বড় হলে 413 `request_entity_too_large` আসে।

### Python SDK default-এ base64 চায়

`encoding_format` না দিলে OpenAI-র Python SDK নিজে থেকে `"base64"` পাঠায় আর result নিজেই decode করে (SDK-র source দেখে মিলিয়েছি, অক্টোবর 2026)। এটা তখনই চলে, যখন model-এর provider base64 সমর্থন করে। call fail করলে বা vector অদ্ভুত এলে উপরের উদাহরণের মতো `encoding_format="float"` দিয়ে দিন। Node.js SDK-তেও স্পষ্ট করে দিয়ে দিলে কোনো ক্ষতি নেই।

## Response-এর উদাহরণ

এখানে vector ছোট করে দেখানো হয়েছে। আসল vector-এ শ'য়ে শ'য়ে বা হাজার হাজার সংখ্যা থাকে, তাই request-এর তুলনায় response body অনেক বড় হয়।

```json
{
  "object": "list",
  "data": [
    { "object": "embedding", "index": 0, "embedding": [0.0123, -0.0456, 0.0789] },
    { "object": "embedding", "index": 1, "embedding": [0.0311, -0.0127, 0.0644] }
  ],
  "model": "the-id-from-the-catalog",
  "usage": { "prompt_tokens": 14, "total_tokens": 14 }
}
```

`data`-তে প্রতিটা input-এর জন্য একটা করে entry থাকে, একই ক্রমে। `index` হলো input-টার অবস্থান। body আসে provider থেকে, তাই বাড়তি field আসতে পারে, আর vector কত বড় হবে সেটা model ঠিক করে। `completion_tokens` নেই, কারণ embedding request কোনো text তৈরি করে না।

## দুটো vector তুলনা করা

একই model-এর vector-গুলো cosine similarity দিয়ে তুলনা করা যায়। Python-এ ছোট একটা উদাহরণ:

```python
import math

def cosine(a, b):
    dot = sum(x * y for x, y in zip(a, b))
    return dot / (math.sqrt(sum(x * x for x in a)) * math.sqrt(sum(y * y for y in b)))

print(cosine(vectors[0], vectors[1]))
```

আলাদা model-এর vector, বা একই model-এর আলাদা `dimensions`-এর vector, কখনো একসাথে তুলনা বা index করবেন না। প্রতিটা vector-এর পাশে model-এর id আর `dimensions` রেখে দিন, তাহলে কখন আবার embed করতে হবে সেটা বোঝা যাবে।

## Billing আর সীমা

- **হিসাব।** embeddings-এর বিল হয় provider-এর জানানো `usage.prompt_tokens` ধরে, model-এর প্রতি million token-এর input price-এ। output-এর দিক নেই। প্রতিটা model-এর দাম [model catalog](/models) আর [pricing](/pricing)-এ আছে। provider usage না পাঠালে gateway request আর response-এর size দেখে আন্দাজ করে নেয়।
- **`max_tokens` নেই।** chat-এর মতো এখানে output-এর জন্য কিছু আটকে রাখা হয় না। admission শুধু request-এর size থেকে সবচেয়ে খারাপ ক্ষেত্রের খরচ ধরে রাখে, তাই আপনার ব্যালান্স ওই আন্দাজ মেটাতে না পারলে তবেই টাকার অভাবে request ফিরিয়ে দেওয়া হয়। দাম দিতে হয় আসল usage-এর।
- **Rate limit।** প্রতিটা embeddings request আপনার per-minute limit-এ একটা request হিসেবে গোনা হয় আর চলার সময় একটা concurrency slot ধরে রাখে, request ছোট হোক বা বড়। তাই প্রতি text-এর জন্য আলাদা request না পাঠিয়ে, model-এর provider-এর সীমার ভেতরে অনেকগুলো input এক `input` array-তে দিন। [rate limits](/docs/rate-limits) পেজ দেখুন।
- **Fail করা request-এর বিল হয় না।** provider 400 বা তার ওপরের status দিলে সেটা কোনো চার্জ ছাড়াই আপনার কাছে ফেরত আসে।
- **Stream হয় না।** embeddings-এ `stream` mode নেই।

## Embeddings endpoint-এ chat model দিলে

এখানে chat model পাঠানোই সবচেয়ে চেনা ভুল। কী দেখবেন, সেটা model-এর provider-এর ওপর নির্ভর করে, Tokens-এর কোনো বাঁধা নিয়ম নেই:

| Response                                                   | কারণ                                                                                                                                      |
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| 400 `invalid_request`, "rejected by the upstream provider" | provider request নিয়েছে, কিন্তু ফিরিয়ে দিয়েছে, কারণ model-টা embeddings বানাতে পারে না।                                                  |
| 404 `model_not_found`                                      | ওই model-এর জন্য provider-এর কাছে embeddings route নেই। catalog-এ নেই এমন id দিলেও এটাই আসে।                                              |
| 400 `endpoint_not_supported_for_model`                     | model-টা শুধু এমন provider-এর মাধ্যমে চলে যে Anthropic Messages protocol বোঝে, আর সেখানে embeddings নেই। কিছুই পাঠানো হয়নি।              |
| 502 `upstream_unreachable`                                 | model-এর কয়েকটা provider আছে, আর প্রতিটাই fail করেছে বা request ফিরিয়ে দিয়েছে।                                                         |

সব ক্ষেত্রেই catalog থেকে একটা embedding model বেছে নিন। upstream-এর message বদলে একটা সাধারণ message বসানো হয়, তাই Support-এর সাথে যোগাযোগ করার সময় `x-tokens-request-id` header-টা দিন। পুরো তালিকা [errors](/docs/errors) পেজে।

## Error

gateway-র error OpenAI-র error shape-এ আসে, সাথে থাকে একটা `code`, যা ধরে আপনি branch করতে পারেন। প্রতিটা response-এ `x-tokens-request-id` header থাকে। এখানে সবচেয়ে বেশি যেগুলো পাবেন:

| Status | Code                                 | কী করবেন                                                                     |
| ------ | ------------------------------------ | ---------------------------------------------------------------------------- |
| 400    | `invalid_request`                    | `model` আর `input` দেখুন, আর `Content-Type: application/json` পাঠিয়েছেন কি না।   |
| 402    | `insufficient_credits`, `no_funding` | [billing](/dashboard/billing) থেকে টাকা যোগ করুন বা renew করুন।              |
| 403    | `model_not_allowed_on_key`           | key-র allow-list-এ এই model নেই। অন্য key ব্যবহার করুন।                      |
| 404    | `model_not_found`                    | `GET /v1/models` দিয়ে id মিলিয়ে নিন, নয়তো model-টা embedding model নয়।    |
| 413    | `request_entity_too_large`           | এক request-এ কম input পাঠান।                                                 |
| 429    | `rate_limited`, `concurrency_limit`  | `Retry-After` পর্যন্ত অপেক্ষা করুন, আর input-গুলো কম request-এ ভাগ করে নিন। |

বড় আকারে bulk indexing চালালে [rate limits](/docs/rate-limits) পেজের মতো backoff সহ retry যোগ করুন, আর একসাথে চলা request-এর সংখ্যা plan-এর concurrency limit-এর নিচে রাখুন।

## আরও পড়ুন

- [Chat completions](/docs/chat-completions): text তৈরির জন্য।
- [Token counting](/docs/token-counting): অনেক বড় corpus embed করার আগে input-এর size আন্দাজ করতে।
- [Models and usage](/docs/models-and-usage): `GET /v1/models` আর `GET /v1/tokens/usage`-এর জন্য।

---
Page: https://tokens.bd/bn/docs/embeddings
