ब्लॉग पर वापस जाएं

API और SDKगाइड

OpenAI-संगत API के साथ Python में फ़ंक्शन कॉलिंग

टूल भेजें, tool_calls पढ़ें और role tool के साथ परिणाम लौटाएँ: MiniMax-M2.7 के साथ Python में दो-चरणीय फ़ंक्शन कॉलिंग लूप।

CheapTokens Team द्वाराप्रकाशित अपडेट किया गया 10 मिनट का पाठ

दो-चरणीय टूल कॉल लूप का आरेख: टूल भेजें, tool_calls पढ़ें, परिणाम को टूल संदेश के रूप में लौटाएँ
इस पृष्ठ पर
  1. फ़ंक्शन कॉलिंग कैसे काम करती है
  2. क्लाइंट सेट अप करें
  3. एक फ़ंक्शन घोषित करें और पहला अनुरोध भेजें
  4. आपको क्या दिखना चाहिए
  5. कई कॉल और लंबे लूप
  6. MiniMax-M2.7 टूल लूप के लिए क्यों उपयुक्त है
  7. यदि यह काम न करे
  8. अगले कदम

फ़ंक्शन कॉलिंग (टूल कॉलिंग) एक मॉडल को आपके कोड से किसी फ़ंक्शन को चलाने के लिए कहने देती है। आप अनुरोध के साथ एक tools सूची भेजते हैं, मॉडल टेक्स्ट के बजाय tool_calls के साथ उत्तर देता है, आप स्वयं फ़ंक्शन चलाते हैं, और उसका परिणाम role: tool वाले संदेश में वापस भेजते हैं। फिर मॉडल अंतिम उत्तर लिखता है। यह गाइड पूरा लूप Python में OpenAI-संगत एंडपॉइंट https://api.cheaptokens.dev/v1/chat/completions के साथ MiniMax-M2.7 (id MiniMaxAI/MiniMax-M2.7, 180K कॉन्टेक्स्ट, प्रति उत्तर अधिकतम 8,192 आउटपुट टोकन) पर दिखाती है।

कैटलॉग के हर मॉडल के लिए टूल कॉलिंग समर्थित के रूप में सूचीबद्ध है (CheapTokens docs, 22 अक्टूबर 2026 को जाँचा गया)। आपको एक API कुंजी चाहिए; यदि आपने अभी तक कोई अनुरोध नहीं किया है, तो अपने पहले API अनुरोध से शुरू करें।

फ़ंक्शन कॉलिंग कैसे काम करती है#

मॉडल कभी कुछ नहीं चलाता। वह केवल एक संरचित अनुरोध बनाता है: "get_weather को {\"city\": \"Paris\"} के साथ कॉल करें"। आपका प्रोग्राम असली काम करता है और रिपोर्ट करता है। इससे दो अनुरोधों का लूप बनता है:

  1. अनुरोध 1. आप उपयोगकर्ता संदेश और tools सूची भेजते हैं। मॉडल या तो टेक्स्ट में उत्तर देता है या एक या अधिक tool_calls लौटाता है।
  2. आपका कोड. आप प्रत्येक कॉल को पार्स करते हैं, मेल खाने वाला फ़ंक्शन चलाते हैं और परिणाम एकत्र करते हैं।
  3. अनुरोध 2. आप पूरी बातचीत फिर से भेजते हैं: मूल संदेश, tool_calls वाला सहायक संदेश, और प्रत्येक कॉल के लिए एक role: tool संदेश। मॉडल अंतिम उत्तर लिखने के लिए परिणामों का उपयोग करता है।

हर अनुरोध पूरा इतिहास फिर से भेजता है, इसलिए टूल लूप एकल प्रश्न की तुलना में अधिक इनपुट टोकन उपयोग करते हैं। यदि यह आपके लिए नया है, तो टोकन क्या है पढ़ें।

क्लाइंट सेट अप करें#

OpenAI SDK (pip install openai) इंस्टॉल करें और अपनी कुंजी स्रोत कोड के बजाय एक एनवायरनमेंट वेरिएबल में रखें:

bash
export CHEAPTOKENS_API_KEY="your-key-here"

बेस URL https://api.cheaptokens.dev/v1 है। मॉडल id CheapTokens दस्तावेज़ से लें: अलग-अलग प्रदाता एक ही मॉडल को अलग-अलग नाम देते हैं। यह गाइड MiniMaxAI/MiniMax-M2.7 का उपयोग करती है।

एक फ़ंक्शन घोषित करें और पहला अनुरोध भेजें#

एक फ़ंक्शन का वर्णन tools सरणी में किया जाता है। प्रत्येक प्रविष्टि में type: function और एक function ऑब्जेक्ट होता है जिसमें name, description और JSON Schema के रूप में लिखा गया parameters होता है। विवरण वही है जो मॉडल पढ़ता है ताकि तय कर सके कि फ़ंक्शन कब कॉल करना है, इसलिए इसे एक छोटा, ठोस वाक्य लिखें।

नीचे एक पूरी स्क्रिप्ट है। मौसम फ़ंक्शन नकली डेटा वाला एक स्टब है, इसलिए उदाहरण को किसी अतिरिक्त सेवा की आवश्यकता नहीं है:

python
import json
import os

from openai import OpenAI

client = OpenAI(
    base_url='https://api.cheaptokens.dev/v1',
    api_key=os.environ['CHEAPTOKENS_API_KEY'],
)
MODEL = 'MiniMaxAI/MiniMax-M2.7'


def get_weather(city: str) -> dict:
    # Stub with fake data: replace with a real lookup
    fake = {'Paris': 14, 'Tokyo': 19}
    return {'city': city, 'temp_c': fake.get(city, 10)}


FUNCTIONS = {'get_weather': get_weather}

tools = [
    {
        'type': 'function',
        'function': {
            'name': 'get_weather',
            'description': 'Get the current temperature in Celsius for a city.',
            'parameters': {
                'type': 'object',
                'properties': {
                    'city': {'type': 'string', 'description': 'City name, for example Paris'},
                },
                'required': ['city'],
            },
        },
    }
]

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

# Step 1: the model decides whether to call a function
first = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
message = first.choices[0].message

if not message.tool_calls:
    print(message.content)
    raise SystemExit

# Step 2: run every requested call and send the results back
messages.append(message)
for call in message.tool_calls:
    args = json.loads(call.function.arguments)
    result = FUNCTIONS[call.function.name](**args)
    messages.append({
        'role': 'tool',
        'tool_call_id': call.id,
        'content': json.dumps(result),
    })

final = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
print(final.choices[0].message.content)

तीन विवरण तय करते हैं कि लूप काम करता है या नहीं:

  • call.function.arguments एक JSON स्ट्रिंग है, डिक्शनरी नहीं। इसे json.loads से पार्स करें।
  • प्रत्येक role: tool संदेश में उस कॉल का tool_call_id होना चाहिए जिसका वह उत्तर देता है, जो call.id है।
  • टूल संदेश का content एक स्ट्रिंग है। संरचित परिणामों के लिए json.dumps का उपयोग करें।

आपको क्या दिखना चाहिए#

यदि आप पहले अनुरोध के बाद फ़ील्ड प्रिंट करते हैं, तो वे इस तरह दिखते हैं (कॉल id हर रन पर अलग होता है):

text
finish_reason: tool_calls
call.id: call_abc123
call.function.name: get_weather
call.function.arguments: {"city": "Paris"}

फिर स्क्रिप्ट अंतिम उत्तर प्रिंट करती है, "It is currently 14 °C in Paris." जैसा एक सादा वाक्य। शब्दावली हर रन में बदलती है; संख्या आपके फ़ंक्शन से आती है।

कई कॉल और लंबे लूप#

एक मॉडल एक ही प्रतिक्रिया में एक से अधिक कॉल लौटा सकता है, उदाहरण के लिए जब आप दो शहरों के मौसम के बारे में पूछते हैं। इसीलिए उदाहरण message.tool_calls पर लूप करता है और प्रत्येक कॉल का उत्तर उसकी अपनी id से देता है। OpenAI की फ़ंक्शन कॉलिंग गाइड भी यही व्यवहार बताती है: auto के डिफ़ॉल्ट tool_choice के साथ मॉडल शून्य, एक या कई फ़ंक्शन कॉल कर सकता है (OpenAI docs, 22 अक्टूबर 2026 को जाँचा गया; पेज पर अंतिम-अद्यतन तिथि नहीं है और यह नए Responses API आकार का वर्णन करता है, जबकि यह गाइड /v1/chat/completions एंडपॉइंट के Chat Completions आकार का उपयोग करती है)।

एजेंट दो चरणों को तब तक दोहराते हैं जब तक मॉडल टूल माँगना बंद न कर दे। अनुरोधों को एक लूप में लपेटें और हमेशा एक चरण सीमा सेट करें:

python
for _ in range(5):  # safety limit against endless loops
    response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
    message = response.choices[0].message
    if not message.tool_calls:
        print(message.content)
        break
    messages.append(message)
    for call in message.tool_calls:
        args = json.loads(call.function.arguments)
        result = FUNCTIONS[call.function.name](**args)
        messages.append({'role': 'tool', 'tool_call_id': call.id, 'content': json.dumps(result)})

यदि आप चाहते हैं कि उत्तर टोकन दर टोकन दिखे, तो इसे Python में स्ट्रीमिंग के साथ मिलाएँ।

MiniMax-M2.7 टूल लूप के लिए क्यों उपयुक्त है#

एक टूल लूप बढ़ते इतिहास के साथ कई अनुरोध भेजता है। उस पैटर्न के लिए CheapTokens MiniMax-M2.7 प्रदान करता है: 180K कॉन्टेक्स्ट, प्रति उत्तर अधिकतम 8,192 आउटपुट टोकन, दिन के किसी भी समय एक ही मूल्य बिना पीक आवर्स के, और सभी मॉडलों के लिए एक बैलेंस। इनपुट और आउटपुट को मिलाकर गिनने पर, यह OpenRouter के संदर्भ मूल्य से सस्ता है (CheapTokens मूल्य तुलना, 31 अक्टूबर 2026 को जाँची गई)।

प्रति 1M टोकन वर्तमान मूल्य: इनपुट $0.05, आउटपुट $0.15। एक उदाहरण वर्कलोड के रूप में (माप नहीं), कुल मिलाकर लगभग 2,700 इनपुट और 350 आउटपुट टोकन वाले ऊपर के दो-अनुरोध राउंड ट्रिप की लागत $0.00019 है। पूरी मूल्य सूची मूल्य पेज पर है।

किसी अन्य मॉडल को आज़माने के लिए, केवल id बदलें; id की सूची मॉडल पेज पर है।

यदि यह काम न करे#

  • message.tool_calls None है। मॉडल ने टेक्स्ट में उत्तर दिया। फ़ंक्शन description को अधिक विशिष्ट बनाएँ, और सुनिश्चित करें कि प्रश्न को वास्तव में फ़ंक्शन की आवश्यकता है।
  • arguments पर json.JSONDecodeError। मॉडल ने अमान्य JSON उत्पन्न किया। json.loads को try/except में लपेटें और त्रुटि टेक्स्ट को टूल परिणाम के रूप में वापस भेजें, ताकि मॉडल सुधारे गए आर्ग्युमेंट के साथ पुनः प्रयास कर सके।
  • दूसरा अनुरोध विफल हो जाता है या मॉडल परिणाम को अनदेखा करता है। जाँचें कि प्रत्येक कॉल के लिए मेल खाने वाली tool_call_id वाला ठीक एक role: tool संदेश है, और tool_calls वाला सहायक संदेश उनसे पहले इतिहास में है।
  • FUNCTIONS[...] में KeyError। मॉडल ने ऐसे फ़ंक्शन का नाम लिया जिसे आपने पंजीकृत नहीं किया। क्रैश होने के बजाय टूल परिणाम के रूप में एक छोटी त्रुटि स्ट्रिंग लौटाएँ।
  • उत्तर कट गया है। finish_reason जाँचें: मान length का अर्थ है आउटपुट टोकन सीमा पूरी हो गई। AI उत्तर वाक्य के बीच में क्यों रुकता है देखें।
  • 401 या प्रमाणीकरण त्रुटियाँ। जाँचें कि कुंजी CHEAPTOKENS_API_KEY में है और बेस URL /v1 पर समाप्त होता है।

अगले कदम#

स्टब को एक असली फ़ंक्शन से बदलें: एक डेटाबेस क्वेरी, एक सर्च कॉल या एक कैलकुलेटर। tools और FUNCTIONS में अधिक प्रविष्टियाँ जोड़ें, और हर फ़ंक्शन परिणाम को छोटा रखें, क्योंकि यह प्रत्येक अगले अनुरोध पर इतिहास में वापस जाता है। कुंजी प्राप्त करने और पहली कॉल करने के लिए, CheapTokens docs खोलें।