Chat Completions
مرجع کامل endpoint چت هوشوانا: پارامترها، استریم SSE، فراخوانی ابزار، ورودی تصویر، خروجی JSON و json_schema، شیء usage و اتصال پایگاه دانش.
آخرین بهروزرسانی:
endpoint اصلی هوشوانا برای گفتگو با مدلهای زبانی، POST /chat/completions است. قالب درخواست و پاسخ دقیقاً با OpenAI سازگار است، پس SDKهای OpenAI و بیشتر کتابخانهها و ابزارهایی که با OpenAI کار میکنند (مثل LangChain و LlamaIndex) بدون تغییر کار میکنند. همین endpoint برای مدلهای Anthropic، Google، DeepSeek و بقیه هم قابل استفاده است و هوشوانا تفاوتهای ارائهدهندهها را پوشش میدهد.
POST https://hooshvana.ir/api/v1/chat/completionsپارامترهای درخواست
| پارامتر | نوع | توضیح |
|---|---|---|
model | string | شناسهی مدل، مثل openai/gpt-4o-mini. اگر حذف شود، مدل پیشفرض کلید استفاده میشود |
messages | array | فهرست پیامها با نقشهای system، user، assistant و tool (الزامی) |
max_tokens | integer | حداکثر توکن خروجی. روی برآورد اولیهی هزینه هم اثر دارد |
temperature | number | میزان تصادفی بودن خروجی، معمولاً بین ۰ و ۲ |
top_p | number | نمونهبرداری هستهای. معمولاً یا این یا temperature را تغییر دهید |
stop | string یا array | رشتههایی که تولید متن با رسیدن به آنها متوقف میشود |
stream | boolean | ارسال پاسخ به صورت تکهتکه با SSE |
stream_options | object | با {"include_usage": true} آمار مصرف در آخرین تکهی استریم میآید |
tools | array | تعریف توابعی که مدل میتواند فراخوانی کند |
tool_choice | string یا object | auto، none، required یا انتخاب یک تابع مشخص |
response_format | object | json_object یا json_schema برای خروجی ساختاریافته |
seed | integer | برای تکرارپذیری نسبی، در مدلهایی که پشتیبانی میکنند |
user | string | شناسهی کاربر نهایی شما برای پیگیری (اطلاعات شخصی نفرستید) |
hooshvana | object | افزونهی هوشوانا، مثلاً اتصال پایگاه دانش (پایینتر توضیح داده شده) |
همهی مدلها همهی پارامترها را پشتیبانی نمیکنند. مثلاً برخی مدلهای استدلالی temperature را نادیده میگیرند. قابلیتهای هر مدل در کاتالوگ مدلها آمده است.
درخواست ساده
curl https://hooshvana.ir/api/v1/chat/completions \
-H "Authorization: Bearer $HOOSHVANA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-4o-mini",
"messages": [
{"role": "system", "content": "You are a concise assistant. Reply in Persian."},
{"role": "user", "content": "فرق RAM و حافظهی ذخیرهسازی چیست؟"}
],
"max_tokens": 300
}'نمونهی پاسخ:
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1792000000,
"model": "openai/gpt-4o-mini",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "RAM حافظهی موقت و سریع است..." },
"finish_reason": "stop"
}
],
"usage": { "prompt_tokens": 38, "completion_tokens": 112, "total_tokens": 150 }
}مقدار finish_reason میتواند stop (پایان طبیعی)، length (رسیدن به max_tokens)، tool_calls (درخواست فراخوانی ابزار) یا content_filter باشد.
استریم
با "stream": true پاسخ به صورت Server-Sent Events ارسال میشود. هر خط با data: شروع میشود و یک شیء JSON دارد. استریم با خط data: [DONE] تمام میشود:
data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":""}}]}
data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"سلام"}}]}
data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":40,"total_tokens":52}}
data: [DONE]تکهی آخر با آرایهی خالی choices و شیء usage فقط وقتی میآید که stream_options.include_usage را فعال کرده باشید.
استریم با Python
import os
from openai import OpenAI
client = OpenAI(base_url="https://hooshvana.ir/api/v1", api_key=os.environ["HOOSHVANA_API_KEY"])
stream = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "یک داستان کوتاه دربارهی باران بنویس."}],
stream=True,
stream_options={"include_usage": True},
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if chunk.usage:
print()
print("tokens:", chunk.usage.total_tokens)استریم با Node.js
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://hooshvana.ir/api/v1",
apiKey: process.env.HOOSHVANA_API_KEY,
});
const stream = await client.chat.completions.create({
model: "openai/gpt-4o-mini",
messages: [{ role: "user", content: "یک داستان کوتاه دربارهی باران بنویس." }],
stream: true,
stream_options: { include_usage: true },
});
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content;
if (text) process.stdout.write(text);
if (chunk.usage) console.log("\ntokens:", chunk.usage.total_tokens);
}اگر کاربر وسط استریم اتصال را قطع کند، هزینهی توکنهایی که تا آن لحظه تولید شدهاند محاسبه میشود.
فراخوانی ابزار (Function Calling)
با فراخوانی ابزار، مدل میتواند تصمیم بگیرد یکی از توابع شما را با آرگومانهای مشخص صدا بزند. اجرای تابع با شماست و نتیجه را دوباره به مدل میدهید. چرخهی کامل در Python:
import json
import os
from openai import OpenAI
client = OpenAI(base_url="https://hooshvana.ir/api/v1", api_key=os.environ["HOOSHVANA_API_KEY"])
def get_order_status(order_id: str) -> dict:
# Replace with a real database lookup.
return {"order_id": order_id, "status": "shipped", "eta": "2 days"}
tools = [
{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Get the shipping status of an order by its id.",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "Order id, e.g. A-1024"}
},
"required": ["order_id"],
},
},
}
]
messages = [{"role": "user", "content": "سفارش A-1024 من کجاست؟"}]
first = client.chat.completions.create(
model="openai/gpt-4o-mini", messages=messages, tools=tools
)
msg = first.choices[0].message
if msg.tool_calls:
messages.append(msg) # keep the assistant turn that requested the tools
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = get_order_status(**args)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result, ensure_ascii=False),
})
final = client.chat.completions.create(
model="openai/gpt-4o-mini", messages=messages, tools=tools
)
print(final.choices[0].message.content)
else:
print(msg.content)چند نکته:
- مدل ممکن است در یک پاسخ چند ابزار را با هم درخواست کند. برای هر کدام یک پیام
toolباtool_call_idمربوط بفرستید. argumentsیک رشتهی JSON است که مدل تولید کرده. قبل از اجرا آن را اعتبارسنجی کنید و به آن اعتماد کامل نکنید.- برای اجبار به فراخوانی یک تابع مشخص:
"tool_choice": {"type": "function", "function": {"name": "get_order_status"}}.
ورودی تصویر (Vision)
مدلهایی که بینایی دارند (مثل openai/gpt-4o-mini، anthropic/claude-sonnet-4.6 و google/gemini-2.5-flash) تصویر را به عنوان بخشی از محتوای پیام میپذیرند. تصویر میتواند آدرس https یا دادهی base64 باشد:
import base64
# 1) Public HTTPS URL
by_url = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "در این تصویر چه میبینی؟"},
{"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}},
],
}],
)
# 2) Local file as base64 data URL
with open("receipt.png", "rb") as f:
b64 = base64.b64encode(f.read()).decode()
by_file = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "مبلغ کل این رسید را استخراج کن."},
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{b64}"}},
],
}],
)
print(by_file.choices[0].message.content)تصاویر هم توکن مصرف میکنند و هزینهشان در prompt_tokens حساب میشود. برای کاهش هزینه، تصاویر بزرگ را قبل از ارسال کوچک کنید.
خروجی JSON
حالت JSON
با {"type": "json_object"} مدل ملزم میشود JSON معتبر برگرداند. حتماً در پیامها هم صریحاً بخواهید خروجی JSON باشد:
resp = client.chat.completions.create(
model="openai/gpt-4o-mini",
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": "Return JSON with keys: sentiment, summary."},
{"role": "user", "content": "سفارشم دیر رسید ولی کیفیتش عالی بود."},
],
)
print(resp.choices[0].message.content)json_schema
در مدلهایی که پشتیبانی میکنند، با json_schema ساختار دقیق خروجی را تعیین میکنید:
{
"model": "openai/gpt-4o-mini",
"messages": [{ "role": "user", "content": "نام و شهر را استخراج کن: «مریم از اصفهان پیام داده است.»" }],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": { "type": "string" },
"city": { "type": "string" }
},
"required": ["name", "city"],
"additionalProperties": false
}
}
}
}اگر مدلی json_schema را پشتیبانی نکند، با خطای invalid_request روبهرو میشوید. در این صورت از json_object و اعتبارسنجی سمت خودتان استفاده کنید.
شیء usage
هر پاسخ غیراستریم شیء usage دارد که مبنای محاسبهی هزینه است:
| فیلد | معنی |
|---|---|
prompt_tokens | توکنهای ورودی (پیامها، ابزارها، تصاویر) |
completion_tokens | توکنهای خروجی، شامل توکنهای استدلال در مدلهای استدلالی |
total_tokens | مجموع |
prompt_tokens_details.cached_tokens | توکنهای ورودی که از کش خوانده شده و ارزانترند (در صورت پشتیبانی) |
نحوهی تبدیل این اعداد به تومان در قیمتگذاری و صورتحساب آمده است.
اتصال پایگاه دانش
هوشوانا یک فیلد اختصاصی به نام hooshvana به درخواست چت اضافه کرده است. با آن میتوانید یک یا چند پایگاه دانش را به درخواست وصل کنید. متنهای مرتبط بازیابی و به عنوان زمینه با ارجاع به منبع در اختیار مدل قرار میگیرند:
resp = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "شرایط مرجوعی کالا چیست؟"}],
extra_body={"hooshvana": {"knowledge_base_ids": ["kb_123"]}},
)در Node.js کافی است فیلد را مستقیم در بدنه بگذارید (در TypeScript ممکن است لازم باشد با // @ts-expect-error یا cast از بررسی نوع عبور کنید):
const resp = await client.chat.completions.create({
model: "openai/gpt-4o-mini",
messages: [{ role: "user", content: "شرایط مرجوعی کالا چیست؟" }],
hooshvana: { knowledge_base_ids: ["kb_123"] },
});خطاها
خطاها قالب OpenAI دارند و پیامشان فارسی است. رایجترینها: model_not_found، insufficient_balance، rate_limited و invalid_request. جدول کامل و روش برخورد با هر کدام در خطاها و کدها آمده است.