API embedding در ایران: امبدینگ چیست و کدام مدل را انتخاب کنی
امبدینگ چیست و API آن چطور کار میکند: text-embedding-3-small، Qwen3 Embedding و bge-m3 با کلید یوتاپن، پرداخت تومانی و کد Python و curl آماده.

امبدینگ (embedding) یعنی تبدیل متن به فهرستی از عددها (یک بردار)، طوری که متنهای هممعنی بردارهای نزدیک به هم بگیرند. «قرارداد اجاره» و «اجارهنامهٔ ملک مسکونی» با کلمههای متفاوت یک چیز را میگویند و بردارشان نزدیک است. «دستور پخت قورمهسبزی» بردار دوری میگیرد. برای سنجیدن این نزدیکی معمولاً شباهت کسینوسی را حساب میکنی: عددی که هرچه به ۱ نزدیکتر باشد، دو متن از نظر معنا به هم نزدیکترند. مدل embedding متن تولید نمیکند و جواب نمیدهد. فقط همین بردار را برمیگرداند و بقیهٔ کار با کد خودت است.
API embedding یوتاپن، یعنی مسیر POST /v1/embeddings، همان قرارداد OpenAI را دارد. با SDK رسمی OpenAI و فقط با عوض کردن base_url، تابع client.embeddings.create را صدا میزنی و با همان کلید sk-up- به بیش از ۳۰ مدل embedding دسترسی داری، از openai/text-embedding-3-small تا Qwen3 Embedding و Gemini Embedding. پرداخت از کیف پول تومانی است و آدرس API داخل ایران است.
embedding به چه دردی میخورد
هر جا که بخواهی «معنا» را مقایسه کنی، نه کلمهها را، embedding به کار میآید. کاربردهای رایج:
- جستجوی معنایی. کاربر مینویسد «چطور پولم را پس بگیرم» و صفحهٔ «شرایط مرجوعی کالا» پیدا میشود، با اینکه هیچ کلمهٔ مشترکی ندارند. جستجوی
LIKEیا full-text این را پیدا نمیکند. - RAG. تکههای اسنادت را embed میکنی، نزدیکترین تکهها به سؤال را پیدا میکنی و همراه سؤال به یک مدل زبانی میدهی تا با استناد به همان اسناد جواب بدهد.
- پیدا کردن تکراریها. تیکتهای پشتیبانی، نظرهای کاربران یا آگهیهایی که با کلمههای متفاوت یک چیز را میگویند، بردار نزدیک میگیرند. با یک آستانهٔ شباهت میتوانی آنها را ادغام یا علامتگذاری کنی.
- خوشهبندی. هزاران نظر کاربر را embed میکنی و با k-means یا الگوریتم مشابه گروهشان میکنی تا ببینی کاربران بیشتر از چه چیزی حرف میزنند.
- پیشنهاد محتوا. «مقالههای مرتبط» یا «محصولات مشابه» را با نزدیکی بردار توضیح محصول یا متن مقاله انتخاب میکنی.
- دستهبندی ساده. برای هر دسته چند نمونه embed میکنی و متن تازه را به دستهای میدهی که نزدیکترین نمونهها را دارد. برای خیلی از کارها لازم نیست مدلی آموزش بدهی.
نکتهٔ مهم: embedding خودش جستجو نمیکند. بردارها را باید جایی نگه داری، از یک آرایهٔ numpy برای چند هزار تکه تا pgvector یا Qdrant برای حجم بیشتر، و مقایسه را خودت انجام بدهی.
صدا زدن API embedding با Python و curl
اگر قبلاً با API خود OpenAI کار کردهای، چیز تازهای وجود ندارد. فقط base_url و کلید عوض میشوند و شناسهٔ مدل باید با پیشوند سازنده نوشته شود. جزئیات جابهجایی کد موجود در راهنمای عوض کردن base_url در SDK OpenAI آمده.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.uttapen.ir/v1",
api_key=os.environ["UTTAPEN_API_KEY"], # sk-up-...
)
emb = client.embeddings.create(
model="openai/text-embedding-3-small",
input=["قرارداد اجاره", "اجارهنامهٔ ملک مسکونی", "دستور پخت قورمهسبزی"],
)
vectors = [d.embedding for d in emb.data]
print(len(vectors), len(vectors[0]), emb.usage.prompt_tokens)
input میتواند یک رشته یا فهرستی از رشتهها باشد. برای حجم بالا فهرست بفرست، چون کل فهرست یک درخواست حساب میشود. هر درخواست حداکثر ۲۰۴۸ ورودی میگیرد و دستهٔ بزرگتر را باید تکه کنی. emb.usage.prompt_tokens تعداد توکن ورودی را میگوید که مبنای هزینه است.
همان درخواست با curl:
curl -s "https://api.uttapen.ir/v1/embeddings" \
-H "Authorization: Bearer $UTTAPEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"openai/text-embedding-3-small","input":["قرارداد اجاره","اجارهنامهٔ ملک"]}' \
| jq '.data | length, (.[0].embedding | length)'
چند چیز که پیش از نوشتن کد اصلی باید بدانی:
- فقط مدل embedding. اگر شناسهٔ یک مدل chat را به
/v1/embeddingsبفرستی، یا برعکس مدل embedding را بهchat/completions، خطای400 invalid_requestمیگیری و هزینهای کم نمیشود. - پارامتر
dimensions. روی مدلهایopenai/text-embedding-3-*کار میکند و طول بردار را کوتاهتر میکند. بردار کوتاهتر جای کمتری در دیتابیس میگیرد و مقایسهاش سریعتر است. برای مدلهای دیگر به این پارامتر تکیه نکن. - محدودیتها. درخواستهای embeddings در همان سقف «درخواست در دقیقه»ی کلید شمرده میشوند و در سقف درخواست همزمان هر کاربر هم حساب میشوند. جزئیات و کد تلاش دوباره در مستندات محدودیت نرخ آمده. اگر دستههای خیلی بزرگ را همزمان بفرستی، ممکن است
503 server_busyبگیری. در این حالت دسته را کوچکتر کن وRetry-Afterرا رعایت کن. - LangChain. اگر از
OpenAIEmbeddingsاستفاده میکنی،check_embedding_ctx_length=Falseبگذار. وگرنه متن با توکنشمار محلی OpenAI شکسته میشود. بقیهٔ تنظیمات در مستندات یکپارچهسازیها است.
جزئیات SDK در مستندات Python آمده و نمونههای Node، Go و PHP هم در صفحههای کناری همان بخش هستند. نسخهٔ کامل curl هم در مستندات curl آمده.
کدام مدل embedding را انتخاب کنم
کاتالوگ یوتاپن امروز بیش از ۳۰ مدل embedding دارد و فهرست کامل با قیمت زنده در دستهٔ مدلهای embedding است. اینجا عدد بنچمارک یا رتبهٔ کیفیت نمیآوریم، چون کیفیت embedding روی متن فارسی به دامنهٔ متن تو بستگی دارد و باید روی دادهٔ خودت بسنجی. ستون «توضیح سازنده» از توضیحی آمده که خود سازندهٔ مدل منتشر کرده. قیمتها تومان بهازای هر یک میلیون توکن ورودیاند و از کاتالوگ زنده خوانده میشوند.
| مدل | توضیح سازنده | قیمت ورودی (تومان / ۱M توکن) |
|---|---|---|
openai/text-embedding-3-small | نسخهٔ بهبودیافته و کارآمدتر ada؛ پنجرهٔ ۸۱۹۲ توکن | ۶٬۹۲۴ |
openai/text-embedding-3-large | توانمندترین مدل embedding شرکت OpenAI برای متن انگلیسی و غیرانگلیسی | ۴۵٬۰۰۹ |
qwen/qwen3-embedding-8b | مخصوص embedding و رتبهبندی، با توان چندزبانه و متن بلند؛ پنجرهٔ ۳۲ هزار توکن | ۳٬۴۶۲ |
baai/bge-m3 | بردار ۱۰۲۴ بعدی برای بازیابی چندزبانه و متن بلند | ۳٬۴۶۲ |
google/gemini-embedding-001 | یک مدل برای حوزههای علمی، حقوقی، مالی و کد | ۵۱٬۹۳۳ |
google/gemini-embedding-2 | اولین مدل embedding چندوجهی Google: متن و تصویر در یک فضای برداری | ۶۹٬۲۴۴ |
mistralai/codestral-embed-2505 | مخصوص کد و مخزن کد | ۵۱٬۹۳۳ |
بقیهٔ فهرست هم گزینههای قابلتوجهی دارد: intfloat/multilingual-e5-large که به گفتهٔ سازنده بیش از ۹۰ زبان را پوشش میدهد، خانوادهٔ voyageai/voyage-4 که چندزبانه است و بردار را در طولهای ۲۰۴۸ تا ۲۵۶ میدهد، voyageai/voyage-code-4 برای کد، و perplexity/pplx-embed-v1 در دو اندازه برای بازیابی در مقیاس وب. openai/text-embedding-ada-002 را سازندهاش مدل قدیمی (legacy) میداند. فقط وقتی سراغش برو که بردارهای قدیمیات با همین مدل ساخته شدهاند.
چند نکتهٔ عملی برای انتخاب:
- برای متن فارسی، مدل چندزبانه انتخاب کن. مدلهایی مثل
bge-base-en-v1.5،e5-base-v2وgte-largeبه گفتهٔ خود سازنده برای انگلیسی ساخته شدهاند و پنجرهٔ ۵۱۲ توکنی دارند. برای فارسی ازtext-embedding-3-small،qwen3-embedding-8b،bge-m3یاmultilingual-e5-largeشروع کن. فقط یادت باشد پنجرهٔmultilingual-e5-largeهم ۵۱۲ توکن است و برای تکههای کوتاه مناسب است. text-embedding-3-smallنقطهٔ شروع امنی است. ارزان است، با کتابخانهها و ابزارها سازگار است وdimensionsرا پشتیبانی میکند. صفحهاش در یوتاپن قیمت زنده و جزئیات را نشان میدهد.- اگر اسنادت بلند است، به پنجرهٔ مدل نگاه کن. پنجرهٔ مدلهای Qwen3 Embedding ۳۲ هزار توکن و پنجرهٔ مدلهای OpenAI ۸۱۹۲ توکن است. با این حال برای جستجو معمولاً تکههای کوچکتر نتیجهٔ بهتری میدهند، پس پنجرهٔ بزرگ دلیلی برای embed کردن کل یک سند در یک بردار نیست.
- برای کد، مدلهای مخصوص کد مثل Codestral Embed یا voyage-code-4 را هم امتحان کن.
- مدل را وسط کار عوض نکن. بردارهای دو مدل مختلف، و حتی یک مدل با
dimensionsمتفاوت، با هم قابل مقایسه نیستند. اگر مدل را عوض کردی، باید همهٔ اسناد را دوباره embed کنی. پس شناسهٔ مدل و طول بردار را کنار هر بردار ذخیره کن.
هزینهٔ embedding چطور حساب میشود
مدل embedding خروجی متنی ندارد، پس هزینه فقط بابت توکنهای ورودی است و بر اساس مصرف واقعی از کیف پول کم میشود. قیمت تومانی هر مدل در جدول بالا زنده است و با نرخ ارز و قیمت سازنده تغییر میکند، برای همین در متن عدد ثابت نمینویسیم.
برای برآورد کار خودت، یک نمونهٔ کوچک از اسنادت را embed کن و usage.prompt_tokens را بخوان. بعد آن را به نسبت حجم کل اسنادت بزرگ کن. متن فارسی معمولاً توکن بیشتری از متن انگلیسی همطول مصرف میکند و تعداد دقیقش به توکنایزر هر مدل بستگی دارد. اینکه یک درخواست فارسی چند توکن است را با عدد واقعی جداگانه بررسی کردهایم.
دو چیز هزینه را واقعاً پایین نگه میدارد:
- فقط یک بار embed کن. بردار هر سند را ذخیره کن و فقط وقتی سند تغییر کرد دوباره بسازش. یک هش از متن کنار بردار نگه دار تا تغییر را تشخیص بدهی.
- سؤال کاربر ارزان است. در جستجو هر بار فقط متن کوتاه پرسش embed میشود. هزینهٔ اصلی همان ساخت اولیهٔ ایندکس است.
کیف پول برای همهٔ مدلها مشترک است. با همان شارژی که مدل embedding را صدا میزنی، مدل chat مرحلهٔ پاسخ RAG را هم صدا میزنی. توضیح کلی قیمتگذاری در صفحهٔ قیمتها است.
نکتههای متن فارسی پیش از embed کردن
اینها توصیههای عمومیاند، نه قاعدهٔ یک مدل خاص، ولی روی کیفیت جستجوی فارسی اثر واضحی دارند:
- ی و ک را یکسان کن. متنی که از منابع مختلف جمع شده گاهی «ي» و «ك» عربی دارد و گاهی «ی» و «ک» فارسی. برای ماشین اینها دو حرف متفاوتاند. پیش از embed کردن، هم اسناد و هم پرسش کاربر را با یک تابع ساده یکسان کن.
- نیمفاصله را نگه دار. بعضی ابزارهای تمیزکاری نیمفاصله (U+200C) را حذف یا به فاصله تبدیل میکنند و «میشود» به «می شود» تبدیل میشود. نیمفاصله را نگه دار و فقط نسخههای اشتباهش را درست کن.
- اعراب و کشیده را حذف کن. «ـــ» و اعراب معمولاً معنا را عوض نمیکنند ولی توکن اضافه میسازند.
- عددها را یکسان کن. اگر کاربر ممکن است «۱۴۰۵» یا «1405» بنویسد، یک شکل را انتخاب کن و همهجا همان را بنویس.
- همان پیشپردازش برای سند و پرسش. هر تمیزکاریای که روی اسناد انجام دادی، دقیقاً همان را روی پرسش کاربر هم انجام بده.
بعد از این یکسانسازی، دو سه مدل از جدول بالا را روی چند ده پرسش واقعی کاربرانت مقایسه کن. این آزمون از هر رتبهبندی عمومی برای دادهٔ تو قابلاعتمادتر است.
قدم بعدی: ساختن RAG
حالا که میدانی embedding چیست و چطور صدایش بزنی، قدم بعدی معمولاً ساختن یک سیستم پرسشوپاسخ روی اسناد خودت است. راهنمای RAG روی اسناد فارسی کل مسیر را در یک فایل پایتون پیاده میکند: تکهکردن متن فارسی با حفظ نیمفاصله، embedding دستهای، جستجوی کسینوسی با numpy و پاسخ مدل با شمارهٔ منبع.
سؤالهای رایج
text-embedding-3-small API را از ایران چطور صدا بزنم؟
با SDK رسمی OpenAI و base_url="https://api.uttapen.ir/v1"، شناسهٔ openai/text-embedding-3-small را به client.embeddings.create بده. کلید sk-up- را از داشبورد یوتاپن میگیری و کیف پول را به تومان شارژ میکنی. VPN و کارت ارزی لازم نیست. کدی که برای API خود OpenAI نوشتهای، با عوض کردن همین دو مقدار و افزودن پیشوند openai/ به نام مدل کار میکند.
طول بردار text-embedding-3-small را میتوانم کم کنم؟
بله. پارامتر dimensions روی مدلهای openai/text-embedding-3-* کار میکند. فقط یادت باشد بردارهایی که با طولهای مختلف ساخته شدهاند با هم قابل مقایسه نیستند. اسناد و پرسشها باید با یک مدل و یک طول embed شوند.
چرا خطای 400 invalid_request میگیرم؟
رایجترین دلیل این است که شناسهٔ یک مدل chat را به /v1/embeddings فرستادهای، یا مدل embedding را به chat/completions. شناسه را از دستهٔ مدلهای embedding کپی کن. اگر شناسه را بدون نام سازنده بفرستی (مثل text-embedding-3-small بدون openai/)، خطا 404 model_not_found است، نه 400.
کدام مدل embedding برای فارسی بهتر است؟
ما عدد مقایسهای برای فارسی منتشر نمیکنیم، چون نتیجه به نوع متن بستگی دارد. مدلهای چندزبانه مثل text-embedding-3-small، qwen/qwen3-embedding-8b، baai/bge-m3 و intfloat/multilingual-e5-large نقطهٔ شروع خوبیاند. دو سه تا را روی بیست پرسش واقعی خودت امتحان کن و بهترین را نگه دار.
embedding متن را پیش شما ذخیره میکنید؟
در مسیر API، متن ورودی و پاسخ در لاگ یا دیتابیس ما ذخیره نمیشود و فقط متادیتایی مثل تعداد توکن و هزینه ثبت میشود (جزئیات حریم خصوصی). نگه داشتن بردارها کار خود توست.
مقالههای مرتبط
- RAG برای اسناد فارسی: chunk، embedding، جستجوی کسینوسی و پاسخ با ارجاع — با کدپیادهسازی کامل RAG فارسی در یک فایل پایتون: تکهکردن متن با حفظ نیمفاصله، embedding از /v1/embeddings، جستجوی کسینوسی با numpy و پاسخ با شمارهٔ منبع.
- Claude Code در ایران: کلود کد چیست و چطور با Claude کد بزنیکلود کد (Claude Code) چیست، چرا استفاده از آن در ایران سخت است و چطور با opencode یا Cline و کلید یوتاپن از ترمینال و VS Code با مدل Claude کد بزنی.
- خروجی JSON از هوش مصنوعی با structured output و JSON Schemaگرفتن JSON معتبر از مدل زبانی با response_format: فرق json_object و json_schema و tool calling، استخراج فیلد از متن فارسی با Python و مدیریت خطا.
با شماره موبایل ثبتنام کن، کیف پول را شارژ کن و کلید بگیر. ساخت کلید API ←