Embeddings
Vektor dari teks: satu endpoint, ditagih token input saja.
Ringkasan
Satu rute, satu tujuan: mengubah teks menjadi vektor. Sinkron, JSON, dan tidak ada streaming.
/v1/embeddingsbutuh API keyBody-nya JSON dengan Content-Type: application/json, dan API key di header Authorization. Responsnya diteruskan apa adanya dari model, jadi bentuk yang kamu baca adalah bentuk embeddings yang SDK-mu sudah kenal — MenvoraRouter tidak membungkusnya ulang.
Tidak ada mode streaming di sini: satu request menghasilkan satu himpunan vektor, dan responsnya datang sebagai satu body utuh, bukan potongan bertahap.
Body request
Hanya model dan input yang wajib.
| Field | Tipe | Wajib | Artinya |
|---|---|---|---|
model | string | Wajib | Id model embeddings, persis seperti di katalog. Model itu harus membawa capabilities.embeddings: true. |
input | string | string[] | Wajib | Satu teks, atau array teks. Array berarti banyak teks dalam satu request — semuanya ditagih, dan semuanya kembali dalam satu respons. |
encoding_format | string | Opsional | Diteruskan apa adanya. Bentuk angka yang keluar mengikuti apa yang model hormati. |
dimensions | integer | Opsional | Diteruskan apa adanya, untuk model yang bisa memotong panjang vektornya. |
Seperti rute media lain, field di luar tabel ini tidak dibuang: body diteruskan ke model apa adanya. Kami hanya memvalidasi yang tertulis di atas.
Satuan tagih
Embeddings ditagih per token, dan hanya token input.
Tidak ada completion di endpoint ini, jadi tidak ada yang ditagih untuk output. Yang dihitung hanya token input yang kamu kirim, dengan tarif input model itu. Ini bukan penyederhanaan: permintaan embedding memang tidak punya keluaran teks yang bisa ditagih.
max_tokens tidak punya arti di sini. Body-nya diteruskan, jadi field itu tidak ditolak, tapi tidak ada output yang bisa dibatasi — jangan mengandalkannya untuk mengatur biaya seperti di jalur chat.
Tarifnya dibaca dari objek harga di katalog. Di /v1/models namanya price.unit dan price.unit_price_display; di /public/catalog namanya pricing.price.unit dan pricing.price.unitPriceDisplay — dua permukaan itu memakai penulisan field yang berbeda. Untuk model embeddings, unit berisi token dan teks harganya menyebut tarif input per satu juta token.
Gerbang kapabilitas
Endpoint ini menuntut capabilities.embeddings: true pada modelnya. Pemeriksaannya berjalan sebelum saldo ditahan, jadi penolakan tidak memotong saldo dan tidak meninggalkan tahanan.
| Hasil | Kapan | Apa artinya |
|---|---|---|
| Lolos | Model membawa capabilities.embeddings: true. | Permintaan dijalankan. |
422 capability_mismatch | Model membawa capabilities.embeddings: false. | Pakai model lain. Model itu menyatakan dirinya bukan model embeddings. |
422 capabilities_not_declared | capabilities model null, atau tidak menyebut embeddings. | Deklarasikan capabilities.embeddings = true pada model itu lebih dulu. Belum dideklarasikan bukan berarti tidak mampu, tapi juga tidak diloloskan. |
Ada satu penolakan lain yang bukan soal kapabilitas: model yang jalur medianya tidak tersedia di platform ini dijawab 501 surface_not_served. Request-mu benar dan modelnya ada — yang belum ada adalah jalur untuk melayaninya.
Contoh
Ganti <id-dari-katalog> dengan id model yang membawa capabilities.embeddings: true di katalog. Contoh tidak menuliskan satu id pun, karena model yang melayani embeddings bergantung katalog yang berlaku untukmu.
curl https://api.menvora.web.id/v1/embeddings \
-H "Authorization: Bearer sk-nusa-..." \
-H "Content-Type: application/json" \
-d '{
"model": "<id-dari-katalog>",
"input": ["kalimat pertama", "kalimat kedua"]
}'Satu input berupa array tetap satu request. Kalau kamu mengirim sepuluh kalimat sekaligus, biayanya adalah token kesepuluh kalimat itu — bukan sepuluh kali biaya satu kalimat ditambah ongkos per request.
Embedding bukan chat
Ini bukan rute chat yang kebetulan mengembalikan angka. Model yang hanya bisa chat akan ditolak 422 di gerbang kapabilitas — bukan diterima lalu diam-diam dihitung sebagai token chat. Dua hal itu berbeda: yang pertama memberitahumu modelnya salah, yang kedua menagihmu untuk sesuatu yang tidak pernah kamu minta.
Konsekuensi praktisnya: jangan mengarahkan kode embedding ke model chat karena "kelihatannya jalan". Kalau sebuah model belum mendeklarasikan embeddings, permintaannya tidak akan dijalankan sama sekali.
Kalau kamu perlu vektor dari banyak dokumen, kirim per batch lewat input array selama muat dalam satu body. Batas ukuran body berlaku sama seperti rute lain; untuk korpus besar, potong sendiri di sisimu.