কনটেন্টে যান
ফাংশন কলিং

ফাংশন কলিং

রিকোয়েস্টে আপনার ফাংশনগুলো বর্ণনা করুন, মডেল যে কলগুলো চালাতে চায় সেগুলো উত্তরে জানায়। আপনার কোড সেগুলো চালিয়ে ফলাফল ফেরত পাঠায়: API টুল কল ফেরত দেয়, নিজে কোনো টুল চালায় না।

POST https://api.shannon-ai.com/v1/chat/completions

এই পেজের নমুনাগুলো /v1/chat/completions ব্যবহার করে। একই লুপ /v1/responses ও /v1/messages-এও চলে; কোনো ফরম্যাট কিছু আলাদাভাবে লিখলে নিচের অংশগুলোতে তিনটিই দেখানো হয়েছে।

import json
from openai import OpenAI

client = OpenAI(api_key="YOUR_API_KEY", base_url="https://api.shannon-ai.com/v1")

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get the current weather for a city.",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "City name, for example Paris"},
                "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
            },
            "required": ["city"],
        },
    },
}]

def get_weather(city, unit="celsius"):
    # Your code: ask a weather service here.
    return {"city": city, "temperature": 18, "unit": unit, "conditions": "cloudy"}

messages = [{"role": "user", "content": "What is the weather in Paris right now?"}]
answer = None

for _ in range(5):  # the API sets no limit on rounds: set your own
    response = client.chat.completions.create(
        model="Kimi-K3-3BIT-REAP",
        messages=messages,
        tools=tools,
    )
    choice = response.choices[0]
    if choice.finish_reason != "tool_calls":
        answer = choice.message.content
        break

    messages.append(choice.message)  # the assistant turn with its tool_calls
    for call in choice.message.tool_calls:
        args = json.loads(call.function.arguments)  # arguments is a JSON string
        result = get_weather(**args)
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": json.dumps(result),
        })

print(answer)

প্রথম উত্তর প্রশ্নের জবাব দেয় না। এটি একটি কল চায়:

200 JSON
{
  "id": "chatcmpl-5b0c1d8e7f6a4b3c9d2e1f0a8b7c6d5e",
  "object": "chat.completion",
  "created": 1791590400,
  "model": "Kimi-K3-3BIT-REAP",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "reasoning_content": "The user asks for the current weather in Paris. I should call get_weather.",
        "tool_calls": [
          {
            "id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
            "type": "function",
            "function": {
              "name": "get_weather",
              "arguments": "{\"city\":\"Paris\"}"
            }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ],
  "usage": {
    "prompt_tokens": 312,
    "completion_tokens": 58,
    "total_tokens": 370,
    "prompt_tokens_details": {"cached_tokens": 0},
    "completion_tokens_details": {"reasoning_tokens": 31}
  }
}

ফলাফল পাঠানোর পর পরের উত্তরটি একটি সাধারণ জবাব: message.content-এ টেক্সট থাকে এবং finish_reason হয় stop।

লুপ, ধাপে ধাপে

ধাপ কে কী ঘটে
1 আপনি messages পাঠান tools-এর সাথে, অর্থাৎ মডেল যেসব ফাংশন চাইতে পারে তার তালিকা।
2 মডেল উত্তরে tool_calls ও finish_reason: "tool_calls" থাকে। প্রতিটি কল একটি ফাংশনের নাম ও তার আর্গুমেন্ট দেয়।
3 আপনি প্রতিটি কলের arguments পার্স করুন এবং আপনার ফাংশন চালান।
4 আপনি অ্যাসিস্ট্যান্ট মেসেজ এবং প্রতি কলের জন্য একটি tool মেসেজ messages-এ যোগ করুন, তারপর একই tools দিয়ে রিকোয়েস্ট আবার পাঠান।
5 মডেল মডেল finish_reason: "stop" সহ টেক্সটে উত্তর দেয়, অথবা আরও কল চায়। সেক্ষেত্রে ধাপ 3-এ ফিরে যান।

একটি রিকোয়েস্ট মানে মডেলের একটি টার্ন। API রিকোয়েস্টগুলোর মাঝে কোনো কথোপকথন ধরে রাখে না এবং রাউন্ডের সংখ্যা নির্ধারণ করে না: messages আপনার কোড ধরে রাখে এবং কখন থামবে তা ঠিক করে।

টুল সংজ্ঞায়িত করা

tools হলো একটি অ্যারে, প্রতি ফাংশনে একটি এন্ট্রি। ক্যাটালগের প্রতিটি মডেল এটি গ্রহণ করে; GET /v1/models প্রতিটি id-র জন্য capabilities.tools: true জানায়।

ফিল্ড টাইপ বিবরণ
type string সবসময় function।
function.name string মডেল এই ফাংশন চাইতে যে নাম ব্যবহার করে। আবশ্যক।
function.description string ফাংশনটি কী করে, সহজ ভাষায়।
function.parameters object আর্গুমেন্টগুলো JSON Schema হিসেবে, ওপরের স্তরে type: "object" সহ। নিচে Schema কিওয়ার্ড দেখুন।

প্রতিটি এন্ডপয়েন্টে টুল লেখার নিজস্ব ধরন আছে। আপনি যে এন্ডপয়েন্ট কল করছেন তার ধরনটি পাঠান:

{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "Get the current weather for a city.",
    "parameters": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string",
          "description": "City name, for example Paris"
        },
        "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
      },
      "required": ["city"]
    }
  }
}

tool_choice

tool_choice বলে মডেল টুল কল করতে পারবে, নাকি করতেই হবে। এটি শুধু tools-এর সাথে পড়া হয়।

মান বিবরণ যারা প্রয়োগ করে
"auto" মডেল ঠিক করে টেক্সটে উত্তর দেবে নাকি টুল কল করবে। এটিই ডিফল্ট। সব মডেল
"required" উত্তরে অন্তত একটি টুল কল হয়। হোস্টেড ওপেন-ওয়েট মডেল
{"type": "function", "function": {"name": "get_weather"}} উত্তরে এই ফাংশনটি কল হয়। নামটি tools-এর ফাংশনগুলোর একটি হতে হবে। অন্য ফাংশনের কল উত্তর থেকে বাদ যায়। হোস্টেড ওপেন-ওয়েট মডেল

Shannon মডেলগুলো (shannon-*) প্রতিটি রিকোয়েস্টে নিজে ঠিক করে, auto-র মতো।

required বা নাম দেওয়া ফাংশন ব্যবহার করলে tool_calls পড়ার আগে finish_reason দেখুন। মডেল কোনো কল না করলে উত্তর হয় finish_reason: "stop" সহ টেক্সট উত্তর।

অর্থ /v1/chat/completions /v1/responses /v1/messages
মডেল ঠিক করে "auto" "auto" {"type": "auto"}
অন্তত একটি টুল কল করা "required" "required" {"type": "any"}
নির্দিষ্ট একটি ফাংশন কল করা {"type": "function", "function": {"name": "get_weather"}} {"type": "function", "name": "get_weather"} {"type": "tool", "name": "get_weather"}

সামঞ্জস্যের জন্য গ্রহণ করা হয়: tool_choice: "none" ও parallel_tool_calls। টুল কল ছাড়া একটি টার্নের জন্য রিকোয়েস্ট tools ছাড়া পাঠান।

উত্তরে টুল কল

ফিল্ড টাইপ বিবরণ
finish_reason string উত্তরে অন্তত একটি কল থাকলে tool_calls।
message.tool_calls array প্রতি কলে একটি এন্ট্রি। মডেল কল চাইলেই কেবল ফিল্ডটি থাকে।
tool_calls[].id string call_-এর পরে 32টি হেক্সাডেসিমাল অক্ষর। ফলাফলের সাথে এটি tool_call_id হিসেবে ফেরত পাঠান।
tool_calls[].type string সবসময় function।
tool_calls[].function.name string যে ফাংশন চালাতে হবে।
tool_calls[].function.arguments string আর্গুমেন্টগুলো JSON string হিসেবে, কিছু না থাকলে "{}"। ব্যবহারের আগে এটি পার্স করুন।
message.content string | null উত্তরে শুধু কল থাকলে null। হোস্টেড ওপেন-ওয়েট মডেল কলের পাশে টেক্সটও ফেরত দিতে পারে; Shannon মডেলগুলো null দেয়।

প্রতিটি ফরম্যাটে একই কল। /v1/responses-এ এটি output-এর একটি function_call আইটেম, arguments JSON string হিসেবে। /v1/messages-এ এটি একটি tool_use কনটেন্ট ব্লক, যার input একটি JSON অবজেক্ট, id শুরু হয় toolu_ দিয়ে, এবং stop_reason হলো tool_use।

{
  "finish_reason": "tool_calls",
  "message": {
    "role": "assistant",
    "content": null,
    "tool_calls": [
      {
        "id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
        "type": "function",
        "function": {
          "name": "get_weather",
          "arguments": "{\"city\":\"Paris\"}"
        }
      }
    ]
  }
}

এক টার্নে একাধিক কল

একটি উত্তরে একাধিক কল থাকতে পারে। প্রতিটি চালান এবং পরের রিকোয়েস্টে প্রতি কলের জন্য একটি করে ফলাফল পাঠান, প্রতিটিতে নিজের tool_call_id সহ।

হোস্টেড ওপেন-ওয়েট মডেল প্রতিটি আলাদা কল একবার করে ফেরত দেয়: একই নাম ও একই আর্গুমেন্টের দুটি কল একটি হয়ে আসে।

স্ট্রিম করা টুল কল

stream: true হলে একটি কল একটি অখণ্ড টুকরো হিসেবে আসে: চাঙ্কে সম্পূর্ণ arguments string থাকে, তাই জোড়া লাগানোর মতো খণ্ড নেই। index টার্নের কলগুলো 0 থেকে গোনে।

data: একটি চাঙ্ক, ফরম্যাট করা
{
  "id": "chatcmpl-5b0c1d8e7f6a4b3c9d2e1f0a8b7c6d5e",
  "object": "chat.completion.chunk",
  "created": 1791590400,
  "model": "Kimi-K3-3BIT-REAP",
  "choices": [
    {
      "index": 0,
      "delta": {
        "tool_calls": [
          {
            "index": 0,
            "id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
            "type": "function",
            "function": {
              "name": "get_weather",
              "arguments": "{\"city\":\"Paris\"}"
            }
          }
        ]
      },
      "finish_reason": null
    }
  ]
}
এন্ডপয়েন্ট কী আসে
/v1/chat/completions প্রতি কলে একটি chat.completion.chunk, কলটি delta.tool_calls[0]-এ। শেষ চাঙ্কে finish_reason: "tool_calls" ও usage থাকে।
/v1/responses প্রতি কলে: response.output_item.added (খালি arguments সহ একটি function_call আইটেম), response.function_call_arguments.delta (পুরো string), response.function_call_arguments.done, response.output_item.done।
/v1/messages প্রতি কলে: content_block_start (খালি input সহ একটি tool_use ব্লক), একটি content_block_delta যার input_json_delta.partial_json পুরো আর্গুমেন্ট টেক্সট, content_block_stop। এরপর message_delta বহন করে stop_reason: "tool_use"।

shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite, shannon-2-pro ও shannon-coder-1-এ tools সহ স্ট্রিম করা রিকোয়েস্ট টার্নের শেষে একটি content ডেল্টায় তার উত্তরের টেক্সট পৌঁছে দেয়। স্ট্রিমিং

ফলাফল ফেরত পাঠানো

দ্বিতীয় রিকোয়েস্ট কথোপকথনটি আবার পাঠায় এবং দুটি জিনিস যোগ করে: কল চেয়েছিল যে অ্যাসিস্ট্যান্ট টার্ন, এবং প্রতি কলের জন্য একটি ফলাফল।

{
  "messages": [
    {"role": "user", "content": "What is the weather in Paris right now?"},
    {
      "role": "assistant",
      "content": null,
      "tool_calls": [
        {
          "id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
          "type": "function",
          "function": {
            "name": "get_weather",
            "arguments": "{\"city\":\"Paris\"}"
          }
        }
      ]
    },
    {
      "role": "tool",
      "tool_call_id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
      "content": "{\"city\":\"Paris\",\"temperature\":18,\"unit\":\"celsius\",\"conditions\":\"cloudy\"}"
    }
  ]
}
  • ফলাফলের আগে অ্যাসিস্ট্যান্ট টার্নটি যেভাবে পেয়েছেন সেভাবেই ফেরত পাঠান। প্রতিটি ফলাফল id দিয়ে তার কলের সাথে মেলে: /v1/chat/completions-এ tool_call_id, /v1/responses-এ call_id, /v1/messages-এ tool_use_id।
  • ফলাফল হলো টেক্সট। অবজেক্টকে JSON string-এ সিরিয়ালাইজ করে content-এ দিন (/v1/responses-এ output)। /v1/messages-এ tool_result ব্লকের content একটি string বা টেক্সট ব্লকের তালিকা।
  • অ্যাসিস্ট্যান্ট টার্নে function.arguments JSON string-ই থাকে, ঠিক যেভাবে এসেছিল।
  • কথোপকথন টুল ফলাফল দিয়ে শেষ হতে পারে। নতুন ইউজার মেসেজ লাগে না: মডেল ফলাফল থেকেই এগিয়ে চলে।
  • আপনার ফাংশন ব্যর্থ হলে ব্যর্থতাটি ফলাফলের টেক্সট হিসেবে পাঠান। তখন মডেল তা জানাতে পারে বা অন্য কল চাইতে পারে।

Schema কিওয়ার্ড

parameters (/v1/messages-এ input_schema) একটি JSON Schema। Shannon 3 পরিবার (shannon-3, shannon-3-pro, shannon-3.1, shannon-3.1-pro) এবং হোস্টেড ওপেন-ওয়েট মডেল এটি যেমন পাঠান তেমনই পায়।

shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite, shannon-2-pro ও shannon-coder-1 তিনটি এন্ডপয়েন্টেই এই উপসেটটি পায়:

আচরণ কিওয়ার্ড
যেমন পাঠানো তেমন পড়া হয় নিচের সারিগুলোতে যেসব কিওয়ার্ডের নাম নেই সেগুলো সবই, যেমন type, properties, required, items, enum, description, minimum, maximum, anyOf ও allOf, schema-র প্রতিটি স্তরে।
format int32, int64, float, double, byte, date, date-time ও enum মানগুলোর জন্য পড়া হয়।
oneOf anyOf হিসেবে পড়া হয়।
এই মডেলগুলো যে schema পায় তার অংশ নয় $schema, $id, $ref, $defs, $comment, definitions, additionalProperties, unevaluatedProperties, patternProperties, propertyNames, examples, default, title, const, not, if, then, else, contains, minContains, maxContains, dependentRequired, dependentSchemas, dependencies, readOnly, writeOnly, deprecated, contentEncoding, contentMediaType, contentSchema, multipleOf, uniqueItems; সংখ্যা হলে exclusiveMinimum ও exclusiveMaximum; format-এর অন্য মানগুলো।

আচরণ ও সীমা

  • API টুলের সর্বোচ্চ সংখ্যা বা রাউন্ডের সর্বোচ্চ সংখ্যা নির্ধারণ করে না।
  • রিকোয়েস্ট বডি 32 MiB পর্যন্ত হতে পারে, এবং ফলাফলসহ কথোপকথন মডেলের কনটেক্সট উইন্ডোতে ধরতে হবে।
  • রিকোয়েস্টে tools থাকলে shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite ও shannon-2-pro ডিফল্ট temperature 0.2 ব্যবহার করে। অন্য মান দিতে temperature পাঠান।
  • প্রতিটি রাউন্ড আলাদা রিকোয়েস্ট: এটি আপনার ব্যালেন্স থেকে খরচ করে এবং অন্য যেকোনো রিকোয়েস্টের মতো ফ্লাড প্রোটেকশনে গণনা হয়। সীমা ও ব্যালেন্স

এরর

টুল কল স্ট্যাটাস 200 সহ একটি স্বাভাবিক উত্তর। এই এররগুলো রিকোয়েস্ট নিজেকে নিয়ে:

স্ট্যাটাস টাইপ বার্তা কখন
400 invalid_request_error unknown model: <id> model প্রকাশিত তালিকার কোনো id নয়।
422 invalid_request_error Failed to deserialize the JSON body into the target type: … tools অ্যারে নয়, অথবা অন্য কোনো ফিল্ডের JSON type ভুল।
413 invalid_request_error Failed to buffer the request body: … রিকোয়েস্ট বডি 32 MiB-এর চেয়ে বড়। এররে code: "request_too_large" থাকে।

আর্গুমেন্ট লেখে মডেল। বাইরের যেকোনো ইনপুটের মতো, ফাংশন চালানোর আগে আপনার schema-র সাথে মিলিয়ে দেখুন।

অথেনটিকেশন, ব্যালেন্স ও সার্ভার এরর প্রতিটি রিকোয়েস্টের মতোই। এরর হ্যান্ডলিং