Chiamate di funzioni in parallelo
Gestisca le risposte in cui il modello chiama più funzioni contemporaneamente, le esegua in parallelo con asyncio e raccolga i risultati in un'unica chiamata API successiva.
Chiamate di funzioni in parallelo è una lezione AI Engineering Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Engineering Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Engineering Academy include 4 lezioni in totale.
Che cos'è il function calling parallelo?
I modelli di OpenAI possono chiamare più funzioni contemporaneamente in un'unica risposta quando per rispondere servono informazioni provenienti da diverse fonti indipendenti. Invece di concatenare le chiamate agli strumenti in modo sequenziale, attendendo ogni volta quella precedente, il modello emette più chiamate agli strumenti contemporaneamente. La Sua applicazione le esegue in parallelo e invia tutti i risultati insieme, riducendo notevolmente la latenza.
Riconoscere le chiamate parallele agli strumenti
Quando il modello esegue chiamate parallele agli strumenti, il messaggio di risposta contiene un elenco tool_calls con più di una voce. Ogni voce ha un id univoco, il nome della funzione e gli argomenti. Deve elaborarle tutte prima di effettuare la chiamata API successiva: il modello si aspetta un risultato per ogni chiamata allo strumento che ha emesso.
from openai import OpenAI
import json
client = OpenAI()
# A question that naturally requires two independent lookups
response = client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': 'Compare the weather in London and Tokyo right now.'}],
tools=tools
)
message = response.choices[0].message
print('Number of tool calls:', len(message.tool_calls))
# Might print: Number of tool calls: 2
for tc in message.tool_calls:
print(f' {tc.function.name}({tc.function.arguments})')
# get_current_weather({"location": "London"})
# get_current_weather({"location": "Tokyo"})Eseguire chiamate agli strumenti con asyncio
Esegua più chiamate agli strumenti contemporaneamente utilizzando asyncio.gather(). Ogni funzione dello strumento viene eseguita in una coroutine separata e tutti i risultati vengono raccolti al completamento di tutte le coroutine. È molto più veloce dell'esecuzione sequenziale quando ogni chiamata allo strumento effettua una richiesta di rete.
import asyncio
import json
async def execute_tool_call_async(tool_call) -> tuple:
'''Execute a single tool call and return (tool_call_id, result).'''
name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
# Async version of your tool (uses httpx, aiohttp, etc.)
if name == 'get_current_weather':
result = await async_get_weather(**args)
elif name == 'get_stock_price':
result = await async_get_stock(**args)
else:
result = f'Unknown tool: {name}'
return tool_call.id, str(result)
async def execute_all_parallel(tool_calls) -> list:
'''Execute all tool calls concurrently.'''
tasks = [execute_tool_call_async(tc) for tc in tool_calls]
results = await asyncio.gather(*tasks, return_exceptions=True)
return resultsInviare tutti i risultati insieme
Dopo aver eseguito tutte le chiamate parallele agli strumenti, aggiunga ogni risultato alla conversazione come messaggio role='tool' separato. Ogni messaggio deve includere il tool_call_id corrispondente. Li invii tutti in un'unica chiamata API successiva, così il modello potrà sintetizzare tutti i risultati in una risposta coerente.
async def run_parallel_tool_calls(user_message: str) -> str:
messages = [{'role': 'user', 'content': user_message}]
response = client.chat.completions.create(
model='gpt-4o', messages=messages, tools=tools
)
assistant_message = response.choices[0].message
messages.append(assistant_message) # Add assistant's tool_calls
if response.choices[0].finish_reason == 'tool_calls':
# Execute all tool calls in parallel
results = await execute_all_parallel(assistant_message.tool_calls)
# Add all results to conversation
for tool_call_id, result in results:
messages.append({
'role': 'tool',
'tool_call_id': tool_call_id,
'content': result
})
# One more API call to synthesize results
final = client.chat.completions.create(model='gpt-4o', messages=messages)
return final.choices[0].message.content
return assistant_message.contentUtilizzare ThreadPoolExecutor per gli strumenti sincroni
Se le funzioni degli strumenti sono sincrone e utilizzano requests anziché httpx asincrono, può comunque eseguirle in parallelo utilizzando concurrent.futures.ThreadPoolExecutor. È più semplice da configurare, ma leggermente meno efficiente del codice completamente asincrono.
from concurrent.futures import ThreadPoolExecutor, as_completed
import json
def execute_all_with_threads(tool_calls) -> list:
results = []
with ThreadPoolExecutor(max_workers=len(tool_calls)) as executor:
future_to_id = {
executor.submit(execute_tool_call, tc): tc.id
for tc in tool_calls
}
for future in as_completed(future_to_id):
tool_call_id = future_to_id[future]
try:
result = future.result(timeout=15)
except Exception as e:
result = f'Tool failed: {str(e)}'
results.append((tool_call_id, str(result)))
return resultsGestire i singoli errori degli strumenti
Quando esegue chiamate agli strumenti in parallelo, una può fallire mentre le altre hanno successo. Non permetta mai che un errore blocchi le altre. Utilizzi return_exceptions=True in asyncio.gather() per raccogliere tutti i risultati anche se alcune chiamate generano eccezioni. Converta le eccezioni in stringhe di errore, così il modello riceverà tutti i risultati e potrà ragionare sui fallimenti parziali.
async def safe_execute_all(tool_calls) -> list:
tasks = [execute_tool_call_async(tc) for tc in tool_calls]
raw_results = await asyncio.gather(*tasks, return_exceptions=True)
results = []
for tc, result in zip(tool_calls, raw_results):
if isinstance(result, Exception):
results.append((tc.id, f'Tool error: {str(result)}'))
else:
tool_call_id, output = result
results.append((tool_call_id, output))
return resultsQuando i modelli utilizzano chiamate parallele
Il modello esegue chiamate parallele agli strumenti quando determina che le informazioni necessarie possono essere raccolte in modo indipendente, cioè quando un risultato non dipende da un altro. Esempi: recuperare i prezzi delle azioni per più ticker, ottenere il meteo in più città o interrogare più tabelle di un database. Le chiamate sequenziali vengono utilizzate quando i risultati dipendono l'uno dall'altro: prima si cerca l'ID di un utente, poi si recuperano gli ordini per quell'ID.
Limitare la frequenza delle chiamate parallele
Eseguire molte chiamate agli strumenti in parallelo può sovraccaricare le API esterne con richieste simultanee. Utilizzi un semaforo per limitare il numero massimo di chiamate agli strumenti simultanee. In questo modo rispetta i limiti di frequenza dell'API, mantenendo comunque un'esecuzione più efficiente rispetto all'elaborazione completamente sequenziale.
import asyncio
async def rate_limited_execute_all(tool_calls, max_concurrent: int = 5) -> list:
semaphore = asyncio.Semaphore(max_concurrent)
async def limited_call(tc):
async with semaphore:
return await execute_tool_call_async(tc)
tasks = [limited_call(tc) for tc in tool_calls]
results = await asyncio.gather(*tasks, return_exceptions=True)
return [
(tc.id, str(r) if not isinstance(r, Exception) else f'Error: {r}')
for tc, r in zip(tool_calls, results)
]Concatenare chiamate sequenziali e parallele
I workflow agentici reali spesso combinano chiamate sequenziali e parallele. Il modello potrebbe prima chiamare lookup_user(email) e poi, utilizzando lo user_id restituito, chiamare get_orders(user_id) e get_preferences(user_id) in parallelo. Implementi il ciclo esterno in modo che rilevi quali chiamate possono essere eseguite in parallelo, perché indipendenti, e quali devono essere sequenziali, perché dipendenti.
async def multi_round_agent(user_message: str) -> str:
messages = [{'role': 'user', 'content': user_message}]
MAX_ROUNDS = 5
for _ in range(MAX_ROUNDS):
response = client.chat.completions.create(
model='gpt-4o', messages=messages, tools=tools
)
choice = response.choices[0]
messages.append(choice.message)
if choice.finish_reason == 'stop':
return choice.message.content # Done
if choice.finish_reason == 'tool_calls':
# Execute all tool calls in parallel (may be 1 or many)
results = await safe_execute_all(choice.message.tool_calls)
for tc_id, result in results:
messages.append({'role': 'tool', 'tool_call_id': tc_id, 'content': result})
# Loop continues for potentially sequential next call
return 'Max rounds reached.'Misurare il miglioramento della latenza
Le chiamate parallele agli strumenti possono ridurre notevolmente la latenza. Se ognuna di tre chiamate richiede 500 ms in sequenza, il totale è 1500 ms. Eseguendole in parallelo, il tempo si riduce a circa 500 ms, con un'accelerazione di 3 volte. Misuri e confronti sempre l'esecuzione sequenziale e parallela nello scenario specifico, tenendo conto dell'overhead della concorrenza e dei limiti di frequenza.
import time
import asyncio
async def benchmark_parallel_vs_sequential():
tool_calls = [...] # 5 independent tool calls
# Sequential
start = time.time()
for tc in tool_calls:
await execute_tool_call_async(tc)
sequential_time = time.time() - start
# Parallel
start = time.time()
await asyncio.gather(*[execute_tool_call_async(tc) for tc in tool_calls])
parallel_time = time.time() - start
print(f'Sequential: {sequential_time:.2f}s')
print(f'Parallel: {parallel_time:.2f}s')
print(f'Speedup: {sequential_time/parallel_time:.1f}x')Debugging delle chiamate parallele agli strumenti
Quando esegue il debugging dei problemi relativi alle chiamate parallele agli strumenti, registri l'intero ciclo richiesta-risposta: il messaggio del modello con tutte le tool_calls, ogni risultato aggiunto alla conversazione e la risposta finale del modello. Se manca un risultato o l'ordine non è corretto, il modello potrebbe produrre risposte incoerenti. La registrazione strutturata con tool_call_id come chiave di correlazione semplifica notevolmente il tracciamento dei problemi.
Verifica rapida
Verifichi la Sua comprensione del function calling parallelo con OpenAI.
Riepilogo della lezione
In questa lezione ha imparato che: le chiamate parallele agli strumenti compaiono come più elementi nell'elenco tool_calls, asyncio.gather le esegue in modo concorrente per ottenere la massima velocità e ogni risultato deve includere il tool_call_id corrispondente quando viene inviato nuovamente al modello. Ora costruiremo un'interfaccia per database in linguaggio naturale, usando il function calling per convertire query in inglese corrente in SQL.
Domande Frequenti
La lezione «Chiamate di funzioni in parallelo» è gratuita?
Sì — il testo completo di «Chiamate di funzioni in parallelo» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Engineering Academy, passa a CoddyKit PRO. Il corso AI Engineering Academy include 4 lezioni in totale.
Cosa imparerò in «Chiamate di funzioni in parallelo»?
Gestisca le risposte in cui il modello chiama più funzioni contemporaneamente, le esegua in parallelo con asyncio e raccolga i risultati in un'unica chiamata API successiva. Eserciti AI Engineering Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare AI Engineering Academy?
Non è richiesta alcuna esperienza precedente. AI Engineering Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Chiamate di funzioni in parallelo»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione AI Engineering Academy?
Sì. Ogni lezione AI Engineering Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Definire gli schemi delle funzioni per l'API
- Elaborare le chiamate agli strumenti nell'applicazione
- Chiamate di funzioni in parallelo
- Creare un'interfaccia al database in linguaggio naturale