Przetwarzanie wywołań narzędzi w aplikacji
Wykrywaj finish_reason tool_calls w odpowiedzi API, wyodrębniaj nazwy funkcji i argumenty, wykonuj odpowiednią funkcję Python, a następnie odsyłaj wynik do modelu.
Przetwarzanie wywołań narzędzi w aplikacji to bezpłatna lekcja AI Engineering Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Engineering Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Engineering Academy zawiera 4 lekcji w sumie.
Obiekt odpowiedzi wywołania narzędzia
Gdy model zdecyduje się wywołać funkcję, odpowiedź API zawiera listę tool_calls w obiekcie wiadomości. Każde wywołanie narzędzia ma unikalny id, nazwę funkcji w function.name oraz function.arguments — ciąg JSON zawierający argumenty, które model chce przekazać. Kod aplikacji odpowiada za przeanalizowanie tych danych i wykonanie funkcji.
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)Analizowanie argumentów funkcji
Pole function.arguments zawiera ciąg zakodowany w formacie JSON, a nie słownik języka Python. Należy je przeanalizować za pomocą json.loads(). Zawsze umieszczaj tę operację w bloku try/except — mimo wskazówek wynikających ze schematu model czasami generuje niepoprawny JSON, dlatego trzeba obsłużyć to w kontrolowany sposób.
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'}Przekierowywanie do właściwej funkcji
Użyj function.name, aby przekierować wywołanie do właściwej funkcji języka Python. Przejrzysty wzorzec polega na przechowywaniu funkcji w słowniku mapującym nazwy na obiekty wywoływalne. Unika to podatnych na błędy łańcuchów if/elif i ułatwia późniejsze dodawanie nowych narzędzi.
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)}'Odsyłanie wyników do modelu
Po wykonaniu funkcji należy odesłać wynik do modelu w kolejnym wywołaniu API. Dodaj do konwersacji wiadomość asystenta zawierającą tool_calls, a następnie dodaj nową wiadomość z role='tool', identyfikatorem tool_call_id i wynikiem funkcji jako treścią. Następnie ponownie wywołaj API.
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.contentPełny przebieg konwersacji
Kompletna interakcja z wywołaniem narzędzia obejmuje cztery wiadomości w historii konwersacji: wiadomość użytkownika, wiadomość asystenta z żądaniem wywołania narzędzia, wiadomość z wynikiem narzędzia oraz końcową odpowiedź asystenta uwzględniającą ten wynik. Zrozumienie tej struktury jest niezbędne do budowania asystentów korzystających z narzędzi w konwersacjach wieloetapowych.
# 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)Obsługa sytuacji, w której nie wywołano narzędzia
Czasami model odpowiada bezpośrednio, nie wywołując żadnego narzędzia — finish_reason będzie mieć wartość 'stop', a nie 'tool_calls'. Zawsze sprawdzaj ten przypadek przed próbą przetworzenia wywołań narzędzi. Solidna implementacja powinna prawidłowo obsługiwać obie ścieżki.
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_reasonWeryfikowanie argumentów przed wykonaniem
Model może czasami przekazać argumenty, które nie przejdą walidacji logiki biznesowej — ujemny czas trwania, nieprawidłowy adres e-mail lub datę z przeszłości. Zweryfikuj argumenty przed wywołaniem właściwej funkcji i zwróć opisowy ciąg błędu, jeśli walidacja się nie powiedzie. Model będzie wtedy mógł poprawić argumenty w następnej turze.
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}'Rejestrowanie interakcji z wywołaniami narzędzi
Zawsze rejestruj interakcje z wywołaniami narzędzi na potrzeby debugowania i analityki. Rejestruj nazwę funkcji, argumenty, wynik oraz czas wykonania. Dane te pomagają ustalić, które narzędzia są wywoływane najczęściej, które kończą się błędem i jakie wzorce argumentów generuje model — są niezwykle cenne przy ulepszaniu schematów i implementacji funkcji.
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 resultZagadnienia bezpieczeństwa wywołań narzędzi
Nigdy nie wykonuj dowolnych funkcji na podstawie danych wyjściowych modelu bez ich weryfikacji. Zawsze umieszczaj dokładne nazwy funkcji z TOOL_REGISTRY na liście dozwolonych, weryfikuj wszystkie argumenty i sprawdzaj uprawnienia przed wykonaniem operacji. Model jest niezaufanym wywołującym — złośliwy prompt może próbować wywołać funkcje destrukcyjne, jeśli logika przekierowywania będzie zbyt liberalna.
- Zezwalaj wyłącznie na funkcje jawnie wymienione w TOOL_REGISTRY
- Weryfikuj dane wejściowe za pomocą Pydantic przed wykonaniem
- Wymagaj autoryzacji dla operacji zapisu i usuwania
Zwracanie rozbudowanych wyników strukturalnych
Wyniki narzędzi nie muszą być zwykłymi ciągami tekstu. Można zwracać dane w formacie JSON, tabele lub podsumowania. Zwracanie uporządkowanych danych jako JSON pozwala modelowi analizować konkretne pola i odwoływać się do nich w końcowej odpowiedzi. W przypadku dużych wyników zwróć podsumowanie z najważniejszymi informacjami zamiast umieszczać w kontekście wszystkie surowe dane.
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"]}'
)Konwersacje wieloetapowe z użyciem narzędzi
Skuteczny wzorzec stanowi wieloetapowa konwersacja, w której model wywołuje narzędzia w odpowiedzi na kolejne wiadomości użytkownika, stopniowo budując kontekst. Zawsze zachowuj pełną historię konwersacji, w tym wcześniejsze wywołania narzędzi i ich wyniki, aby model mógł odwoływać się do poprzednich odpowiedzi bez niepotrzebnego ponownego wywoływania narzędzi.
Szybkie sprawdzenie
Sprawdź, czy rozumiesz przetwarzanie wywołań narzędzi w aplikacji.
Podsumowanie lekcji
W tej lekcji poznali Państwo następujące zagadnienia: argumenty wywołania narzędzia są przekazywane jako ciąg JSON, który należy przeanalizować za pomocą json.loads(), słownik TOOL_REGISTRY mapuje nazwy funkcji na obiekty wywoływalne, zapewniając przejrzyste przekierowywanie, a wyniki wracają do modelu jako wiadomości role='tool' z pasującymi identyfikatorami tool_call_ids. W następnej części zajmiemy się sytuacją, w której model wywołuje jednocześnie wiele funkcji, korzystając z równoległych wywołań funkcji.
Ucz się Python dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 30
- Lekcje
- 120
Często zadawane pytania
Czy lekcja „Przetwarzanie wywołań narzędzi w aplikacji” jest bezpłatna?
Tak — pełny tekst „Przetwarzanie wywołań narzędzi w aplikacji” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Engineering Academy, przejdź na CoddyKit PRO. Kurs AI Engineering Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Przetwarzanie wywołań narzędzi w aplikacji”?
Wykrywaj finish_reason tool_calls w odpowiedzi API, wyodrębniaj nazwy funkcji i argumenty, wykonuj odpowiednią funkcję Python, a następnie odsyłaj wynik do modelu. Ćwiczysz AI Engineering Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć AI Engineering Academy?
Nie wymagamy żadnego doświadczenia. AI Engineering Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Przetwarzanie wywołań narzędzi w aplikacji”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji AI Engineering Academy?
Tak. Każda lekcja AI Engineering Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Definiowanie schematów funkcji dla API
- Przetwarzanie wywołań narzędzi w aplikacji
- Równoległe wywoływanie funkcji
- Budowanie interfejsu bazy danych w języku naturalnym