0Pricing
AI Engineering Academy · درس

معالجة استدعاءات الأدوات في تطبيقكم

اكتشفوا finish_reason tool_calls في استجابة API، واستخرجوا أسماء الدوال ومعاملاتها، ونفذوا دالة Python المطابقة، ثم أرسلوا النتيجة إلى النموذج.

معالجة استدعاءات الأدوات في تطبيقكم درس مجاني في AI Engineering Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Engineering Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.

بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.

The Tool Call Response Object

When the model decides to call a function, the API response contains a tool_calls list on the message object. Each tool call has a unique id, the function.name to call, and function.arguments — a JSON string of the arguments the model wants to pass. Your application code is responsible for parsing this and executing the function.

from openai import OpenAI
import json

client = OpenAI()

response = client.chat.completions.create(
    model='gpt-4o',
    messages=[{'role': 'user', 'content': 'What is the weather in Paris?'}],
    tools=tools  # defined previously
)

message = response.choices[0].message

if response.choices[0].finish_reason == 'tool_calls':
    for tool_call in message.tool_calls:
        print('Call ID:', tool_call.id)
        print('Function name:', tool_call.function.name)
        print('Arguments (JSON string):', tool_call.function.arguments)

Parsing Function Arguments

The function.arguments field is a JSON-encoded string, not a Python dict. You must parse it with json.loads(). Always wrap this in a try/except — the model occasionally produces malformed JSON despite schema guidance, and you need to handle that gracefully.

import json

def parse_tool_call(tool_call) -> dict:
    '''Parse a tool call's arguments from JSON string to dict.'''
    try:
        args = json.loads(tool_call.function.arguments)
        return args
    except json.JSONDecodeError as e:
        print(f'Failed to parse arguments for {tool_call.function.name}: {e}')
        print(f'Raw arguments: {tool_call.function.arguments}')
        return {}

# Usage
tool_call = message.tool_calls[0]
args = parse_tool_call(tool_call)
print('Parsed args:', args)  # {'location': 'Paris', 'unit': 'celsius'}

Dispatching to the Right Function

Use the function.name to dispatch to the correct Python function. A clean pattern is to keep your functions in a dictionary mapping name to callable. This avoids brittle if/elif chains and makes it easy to add new tools later.

def get_current_weather(location: str, unit: str = 'celsius') -> str:
    # Real implementation calls a weather API
    return f'{location}: 18{chr(176)}C, partly cloudy'

def create_calendar_event(title: str, start_time: str, duration_minutes: int, **kwargs) -> str:
    return f'Event created: {title} at {start_time} for {duration_minutes} minutes'

# Tool registry: maps function names to callables
TOOL_REGISTRY = {
    'get_current_weather': get_current_weather,
    'create_calendar_event': create_calendar_event
}

def execute_tool_call(tool_call) -> str:
    name = tool_call.function.name
    args = parse_tool_call(tool_call)

    if name not in TOOL_REGISTRY:
        return f'Unknown function: {name}'

    try:
        result = TOOL_REGISTRY[name](**args)
        return str(result)
    except Exception as e:
        return f'Function {name} raised an error: {str(e)}'

Sending Results Back to the Model

After executing the function, you must send the result back to the model in a follow-up API call. Add the assistant's message (which contains the tool_calls) to the conversation, then add a new message with role='tool', the tool_call_id, and the function result as content. Then call the API again.

def run_tool_call_loop(messages: list, tools: list) -> str:
    response = client.chat.completions.create(
        model='gpt-4o',
        messages=messages,
        tools=tools
    )
    message = response.choices[0].message
    messages.append(message)  # Add assistant's tool_calls message

    # Execute all tool calls and collect results
    for tool_call in (message.tool_calls or []):
        result = execute_tool_call(tool_call)
        # Add each tool result as a 'tool' role message
        messages.append({
            'role': 'tool',
            'tool_call_id': tool_call.id,
            'content': result
        })

    # Second API call with results appended
    final_response = client.chat.completions.create(
        model='gpt-4o',
        messages=messages,
        tools=tools
    )
    return final_response.choices[0].message.content

The Full Conversation Turn

A complete tool call interaction involves four messages in the conversation history: the user's message, the assistant's message requesting a tool call, the tool result message, and the assistant's final response incorporating the result. Understanding this structure is essential for building multi-turn tool-using assistants.

# The full message history for a tool-calling conversation:
conversation = [
    {'role': 'user', 'content': 'What is the weather in Tokyo?'},

    # Model requests a tool call (added by run_tool_call_loop)
    # {'role': 'assistant', 'content': None, 'tool_calls': [...]},

    # Application sends tool result back
    # {'role': 'tool', 'tool_call_id': 'call_abc123', 'content': 'Tokyo: 22C, sunny'},

    # Model produces final human-readable response
    # {'role': 'assistant', 'content': 'The weather in Tokyo is 22 degrees Celsius and sunny.'}
]

final_answer = run_tool_call_loop(
    [{'role': 'user', 'content': 'What is the weather in Tokyo?'}],
    tools
)
print(final_answer)

Handling the Case Where No Tool Is Called

Sometimes the model answers directly without calling any tool — finish_reason will be 'stop' rather than 'tool_calls'. Always check for this case before trying to process tool calls. A robust implementation handles both branches cleanly.

def smart_complete(user_message: str) -> str:
    messages = [{'role': 'user', 'content': user_message}]
    response = client.chat.completions.create(
        model='gpt-4o',
        messages=messages,
        tools=tools
    )
    choice = response.choices[0]

    if choice.finish_reason == 'stop':
        # Model answered directly without calling a tool
        return choice.message.content

    elif choice.finish_reason == 'tool_calls':
        # Process tool calls
        messages.append(choice.message)
        for tc in choice.message.tool_calls:
            result = execute_tool_call(tc)
            messages.append({'role': 'tool', 'tool_call_id': tc.id, 'content': result})
        # Get final answer
        final = client.chat.completions.create(model='gpt-4o', messages=messages)
        return final.choices[0].message.content

    return 'Unexpected finish reason: ' + choice.finish_reason

Validating Arguments Before Execution

The model may occasionally pass arguments that fail business logic validation — a negative duration, an invalid email, or a date in the past. Validate arguments before calling the real function and return a descriptive error string if validation fails. The model can then correct its arguments in the next turn.

from pydantic import BaseModel, ValidationError
from datetime import datetime

class CreateEventArgs(BaseModel):
    title: str
    start_time: str  # ISO 8601
    duration_minutes: int

def safe_create_event(tool_call) -> str:
    try:
        raw_args = json.loads(tool_call.function.arguments)
        validated = CreateEventArgs(**raw_args)
        # Additional business rule
        event_time = datetime.fromisoformat(validated.start_time)
        if event_time < datetime.now():
            return 'Error: start_time must be in the future.'
        return create_calendar_event(**validated.dict())
    except ValidationError as e:
        return f'Invalid arguments: {e}'

Logging Tool Call Interactions

Always log tool call interactions for debugging and analytics. Log the function name, arguments, result, and execution time. This data helps you identify which tools are called most frequently, which fail, and what argument patterns the model produces — invaluable for improving your schemas and function implementations.

import time
import logging

logger = logging.getLogger('tool_calls')

def logged_execute(tool_call) -> str:
    name = tool_call.function.name
    args_str = tool_call.function.arguments
    start = time.time()
    result = execute_tool_call(tool_call)
    elapsed = time.time() - start

    logger.info(
        'Tool call executed',
        extra={
            'function': name,
            'arguments': args_str,
            'result_length': len(result),
            'elapsed_ms': round(elapsed * 1000)
        }
    )
    return result

Tool Call Security Considerations

Never execute arbitrary functions based on model output without validation. Always whitelist the exact function names in your TOOL_REGISTRY, validate all arguments, and check authorization before executing actions. The model is an untrusted caller — a malicious prompt could try to invoke destructive functions if your dispatch logic is too permissive.

  • Only allow functions explicitly listed in TOOL_REGISTRY
  • Validate inputs with Pydantic before execution
  • Require authorization for write/delete operations

Returning Rich Structured Results

Tool results don't have to be plain strings. You can return JSON-formatted data, tables, or summaries. Returning structured data as JSON lets the model parse and reference specific fields in its final answer. For large results, return a summary with key facts rather than dumping all raw data into the context.

def get_order_status(order_id: str) -> str:
    # Fetch from real database
    order = {'id': order_id, 'status': 'shipped', 'estimated_delivery': '2024-03-15', 'carrier': 'FedEx', 'tracking': 'FX123456'}
    # Return concise summary, not raw DB record
    return (
        f'Order {order_id}: Status={order["status"]}, '
        f'Estimated delivery: {order["estimated_delivery"]}, '
        f'Carrier: {order["carrier"]}, Tracking: {order["tracking"]}'
    )

Multi-Turn Tool-Using Conversations

A powerful pattern is a multi-turn conversation where the model calls tools across multiple user messages, building up context. Always maintain the full conversation history including past tool calls and results so the model can reference previous answers without re-calling tools unnecessarily.

Quick Check

Test your understanding of processing tool calls in your application.

Lesson Recap

In this lesson you learned: tool call arguments arrive as a JSON string that must be parsed with json.loads(), a TOOL_REGISTRY dictionary maps function names to callables for clean dispatch, and results go back to the model as role='tool' messages with matching tool_call_ids. Next up we handle the case where the model calls multiple functions simultaneously with parallel function calling.

الأسئلة الشائعة

هل درس «معالجة استدعاءات الأدوات في تطبيقكم» مجاني؟

نعم — نص درس «معالجة استدعاءات الأدوات في تطبيقكم» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Engineering Academy، انتقل إلى CoddyKit PRO. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.

ماذا ستتعلم في «معالجة استدعاءات الأدوات في تطبيقكم»؟

اكتشفوا finish_reason tool_calls في استجابة API، واستخرجوا أسماء الدوال ومعاملاتها، ونفذوا دالة Python المطابقة، ثم أرسلوا النتيجة إلى النموذج. تتمرن على AI Engineering Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ AI Engineering Academy؟

لا تُشترط خبرة سابقة. AI Engineering Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «معالجة استدعاءات الأدوات في تطبيقكم»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس AI Engineering Academy هذا؟

نعم. كل درس في AI Engineering Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. تعريف مخططات الدوال لواجهة API
  2. معالجة استدعاءات الأدوات في تطبيقكم
  3. استدعاء الدوال بالتوازي
  4. بناء واجهة قاعدة بيانات باللغة الطبيعية
← العودة إلى AI Engineering Academy