Parallele und sequenzielle Aufrufe
Auf dieser Seite
Parallele und sequenzielle Aufrufe
Das Modell kann in einer einzigen Antwort mehrere Funktionsaufrufe auslösen. Dies geschieht automatisch, sobald es unabhängige Bedürfnisse identifiziert. Dies ist keine rein kosmetische Optimierung: Drei Aufrufe mit jeweils zwei Sekunden Dauer, die parallel ausgeführt werden, benötigen insgesamt nur zwei Sekunden. Werden sie hingegen nacheinander (sequenziell) abgearbeitet, dauert dies sechs Sekunden.
Der eigentliche Fokus dieser Lektion liegt nicht darauf, wie man Parallelisierung umsetzt – das übernimmt das Modell –, sondern darauf, Fälle zu erkennen, in denen Parallelisierung vermieden werden sollte. Zwei Aufrufe sind unabhängig, wenn die Ausführungsreihenfolge das Ergebnis nicht beeinflusst. Sobald eine Operation Daten liest, die eine andere schreibt, oder ein Parameter aus einem vorherigen Aufruf stammen muss, wird aus Parallelität ein schwer reproduzierbarer Fehler.
Parallele Aufrufe
Es muss nichts aktiviert werden: Dies ist das Standardverhalten. Eine Abfrage zu drei Städten erzeugt drei function_call-Elemente in derselben Antwort; Sie führen diese aus. Beachten Sie, dass das Modell die Bedeutung der Funktionen basierend auf Ihren Beschreibungen ermisst – die Beschreibungen steuern die Entscheidung, wie in fast allem in diesem Kurs.
from openai import OpenAI
import json
import asyncio
client = OpenAI()
tools = [
{
"type": "function",
"name": "get_meteo",
"description": "Aktuelles Wetter für eine Stadt abrufen",
"parameters": {
"type": "object",
"properties": {
"ville": {"type": "string"}
},
"required": ["ville"],
"additionalProperties": False
},
"strict": True
},
{
"type": "function",
"name": "get_taux_change",
"description": "Wechselkurs zwischen zwei Währungen abrufen",
"parameters": {
"type": "object",
"properties": {
"source": {"type": "string"},
"cible": {"type": "string"}
},
"required": ["source", "cible"],
"additionalProperties": False
},
"strict": True
}
]
response = client.responses.create(
model="gpt-5.6-terra",
input="Was ist das Wetter in Paris und Berlin, "
"und wie hoch ist der EUR/USD-Wechselkurs?",
tools=tools
)
# Das Modell emittiert 3 parallele Aufrufe
appels = [item for item in response.output if item.type == "function_call"]
print(f"Nombre d'appels : {len(appels)}")
# => Nombre d'appels : 3
Parallele Aufrufe auf der Client-Seite ausführen
Das Empfangen von drei Aufrufen gleichzeitig ist nutzlos, wenn Ihr Code sie nacheinander ausführt: Sie verlieren den gesamten Vorteil auf der Client-Seite. asyncio.gather ist das Minimum; fügen Sie für die Produktion zwei Vorsichtsmaßnahmen hinzu – eine Begrenzung der Parallelität, damit Sie nicht fünfzig gleichzeitige Verbindungen zu einem Service öffnen, der nur zehn unterstützt, und eine Fehlerbehandlung pro Aufruf, damit ein isolierter Fehler die anderen Ergebnisse nicht beeinträchtigt.
async def executer_fonction(name: str, arguments: str) -> dict:
args = json.loads(arguments)
if name == "get_meteo":
return await api_meteo(args["ville"])
elif name == "get_taux_change":
return await api_change(args["source"], args["cible"])
async def traiter_appels_paralleles(appels):
taches = [
executer_fonction(appel.name, appel.arguments)
for appel in appels
]
resultats = await asyncio.gather(*taches)
return [
{
"type": "function_call_output",
"call_id": appel.call_id,
"output": json.dumps(resultat)
}
for appel, resultat in zip(appels, resultats)
]
# Ausführen
resultats = asyncio.run(traiter_appels_paralleles(appels))
# Antwort an das Modell senden
response_finale = client.responses.create(
model="gpt-5.6-terra",
input=response.output + resultats,
tools=tools
)
print(response_finale.output_text)
Parallele Aufrufe deaktivieren
parallel_tool_calls=False zwingt das Modell, pro Antwort nur einen Aufruf zu emittieren. Nutzen Sie diese Einstellung bewusst: Sie tauschen Latenz gegen Sicherheit. Reservieren Sie sie für Funktionen, die etwas Externes schreiben, ändern oder auslösen.
response = client.responses.create(
model="gpt-5.6-terra",
input="Verarbeiten Sie diese drei Bestellungen",
tools=tools,
parallel_tool_calls=False # Ein Aufruf pro Antwort
)
Anwendungsfälle für die Deaktivierung der Parallelität:
- Operationen, die in einer bestimmten Reihenfolge ausgeführt werden müssen
- Funktionen mit Nebenwirkungen, die sich gegenseitig beeinträchtigen
- Wenn das Ergebnis eines Aufrufs den nächsten Aufruf bedingt
Sequenzielle Aufrufe mit einer Schleife
Die sequenzielle Ausführung wird nicht durch einen Parameter gesteuert: Sie ergibt sich aus der Schleife. Sie führen den Aufruf aus, senden das Ergebnis zurück, und das Modell entscheidet basierend auf dem, was es gerade gelernt hat, über den nächsten Schritt. Genau dies unterscheidet eine dynamische Kette von einem starren Plan – wenn Schritt 2 zeigt, dass Schritt 3 unnötig ist, wird das Modell diesen nicht aufrufen.
def boucle_function_calling(prompt: str, tools: list, max_tours: int = 10):
"""Vollständiger Zyklus für sequenzielle Funktionsaufrufe."""
messages_input = prompt
tour = 0
while tour < max_tours:
response = client.responses.create(
model="gpt-5.6-terra",
input=messages_input,
tools=tools,
parallel_tool_calls=False
)
# Prüfen auf Funktionsaufrufe
appels = [i for i in response.output if i.type == "function_call"]
if not appels:
# Modell ist fertig, antwortet mit Text
return response.output_text
# Jeden Aufruf ausführen
resultats = []
for appel in appels:
resultat = executer_fonction_sync(appel.name, appel.arguments)
resultats.append({
"type": "function_call_output",
"call_id": appel.call_id,
"output": json.dumps(resultat)
})
# Nächsten Zyklus vorbereiten
messages_input = response.output + resultats
tour += 1
return "Turn limit reached"
Arbeitsbeispiel: Verarbeitungs-Pipeline
Ein typischer Fall, in dem eine sequenzielle Ausführung zwingend erforderlich ist, da jeder Schritt das Ergebnis des vorherigen verbraucht:
tools_pipeline = [
{
"type": "function",
"name": "valider_commande",
"description": "Gültigkeit der Bestellung prüfen (Lager, Preis, Kunde)",
"parameters": {
"type": "object",
"properties": {
"commande_id": {"type": "string"}
},
"required": ["commande_id"],
"additionalProperties": False
},
"strict": True
},
{
"type": "function",
"name": "calculer_livraison",
"description": "Versandgebühren und -zeiten berechnen. "
"Erfordert eine validierte Bestellung.",
"parameters": {
"type": "object",
"properties": {
"commande_id": {"type": "string"},
"mode": {"type": "string", "enum": ["standard", "express"]}
},
"required": ["commande_id", "mode"],
"additionalProperties": False
},
"strict": True
},
{
"type": "function",
"name": "confirmer_commande",
"description": "Bestellung bestätigen und Zahlung auslösen. "
"Erfordert vorherige Validierung und Versandberechnung.",
"parameters": {
"type": "object",
"properties": {
"commande_id": {"type": "string"},
"livraison_id": {"type": "string"}
},
"required": ["commande_id", "livraison_id"],
"additionalProperties": False
},
"strict": True
}
]
# Das Modell wird natürlich in dieser Reihenfolge aufrufen:
# 1. valider_commande
# 2. calculer_livraison (unter Verwendung des Ergebnisses von Schritt 1)
# 3. confirmer_commande (unter Verwendung der Ergebnisse aus Schritt 1 und 2)
resultat = boucle_function_calling(
"Verarbeiten Sie Bestellung CMD-42567 mit Express-Versand",
tools_pipeline
)
Hybrides Muster: Parallel, dann sequenziell
In der Praxis folgen die meisten realen Workflows diesem gemischten Muster: Eine Sammelphase, in der alles gleichzeitig laufen kann, gefolgt von einer Verarbeitungsphase, die Abhängigkeiten respektiert. Sie müssen dafür nichts Besonderes programmieren – es ist die natürliche Konsequenz der Schleife, sofern Ihre Beschreibungen die Abhängigkeiten klar machen.
# Zyklus 1: Paralleles Datensammeln
# Das Modell ruft get_client UND get_stock parallel auf
# Zyklus 2: Sequenzielle Entscheidung basierend auf Ergebnissen
# Das Modell ruft valider_commande mit gesammelten Informationen auf
# Zyklus 3: Endgültige Aktion
# Das Modell ruft confirmer_commande auf
Dieses Muster wirkt natürlich: Das Modell parallelisiert automatisch, wenn Aufrufe unabhängig sind, und schaltet dann sequenziell um, sobald eine Abhängigkeit auftritt.
Kernaussagen
- Das Modell parallelisiert automatisch unabhängige Aufrufe
- Verwenden Sie
asyncio.gather, um parallele Aufrufe auf der Client-Seite auszuführen - Deaktivieren Sie mit
parallel_tool_calls=False, wenn die Reihenfolge wichtig ist - Implementieren Sie eine Schleife für mehrstufige Workflows
- Funktionsbeschreibungen leiten das Modell bei Abhängigkeiten zwischen Schritten