رفتن به محتوای اصلی
هوشوانا

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

پارامترهای درخواست

پارامترنوعتوضیح
modelstringشناسه‌ی مدل، مثل openai/gpt-4o-mini. اگر حذف شود، مدل پیش‌فرض کلید استفاده می‌شود
messagesarrayفهرست پیام‌ها با نقش‌های system، user، assistant و tool (الزامی)
max_tokensintegerحداکثر توکن خروجی. روی برآورد اولیه‌ی هزینه هم اثر دارد
temperaturenumberمیزان تصادفی بودن خروجی، معمولاً بین ۰ و ۲
top_pnumberنمونه‌برداری هسته‌ای. معمولاً یا این یا temperature را تغییر دهید
stopstring یا arrayرشته‌هایی که تولید متن با رسیدن به آن‌ها متوقف می‌شود
streambooleanارسال پاسخ به صورت تکه‌تکه با SSE
stream_optionsobjectبا {"include_usage": true} آمار مصرف در آخرین تکه‌ی استریم می‌آید
toolsarrayتعریف توابعی که مدل می‌تواند فراخوانی کند
tool_choicestring یا objectauto، none، required یا انتخاب یک تابع مشخص
response_formatobjectjson_object یا json_schema برای خروجی ساختاریافته
seedintegerبرای تکرارپذیری نسبی، در مدل‌هایی که پشتیبانی می‌کنند
userstringشناسه‌ی کاربر نهایی شما برای پیگیری (اطلاعات شخصی نفرستید)
hooshvanaobjectافزونه‌ی هوشوانا، مثلاً اتصال پایگاه دانش (پایین‌تر توضیح داده شده)

همه‌ی مدل‌ها همه‌ی پارامترها را پشتیبانی نمی‌کنند. مثلاً برخی مدل‌های استدلالی temperature را نادیده می‌گیرند. قابلیت‌های هر مدل در کاتالوگ مدل‌ها آمده است.

درخواست ساده

Shell
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
  }'

نمونه‌ی پاسخ:

JSON
{
  "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

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

JavaScript
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:

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 باشد:

Python
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 باشد:

Python
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 ساختار دقیق خروجی را تعیین می‌کنید:

JSON
{
  "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 به درخواست چت اضافه کرده است. با آن می‌توانید یک یا چند پایگاه دانش را به درخواست وصل کنید. متن‌های مرتبط بازیابی و به عنوان زمینه با ارجاع به منبع در اختیار مدل قرار می‌گیرند:

Python
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 از بررسی نوع عبور کنید):

JavaScript
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. جدول کامل و روش برخورد با هر کدام در خطاها و کدها آمده است.