0Pricing
AI Engineering Academy · Lektion

Parallele Funktionsaufrufe

Verarbeiten Sie Antworten, in denen das Modell mehrere Funktionen gleichzeitig aufruft, führen Sie diese mit asyncio parallel aus und bündeln Sie die Ergebnisse in einem einzigen anschließenden API-Aufruf.

Parallele Funktionsaufrufe ist eine kostenlose AI Engineering Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des AI Engineering Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der AI Engineering Academy-Kurs umfasst insgesamt 4 Lektionen.

Teile dieser Lektion wurden noch nicht übersetzt und werden auf Englisch angezeigt.

What Is Parallel Function Calling?

OpenAI's models can call multiple functions simultaneously in a single response when the answer requires information from several independent sources. Instead of chaining tool calls sequentially — each waiting for the previous one — the model emits multiple tool calls at once. Your application executes them in parallel and sends all results back together, dramatically reducing latency.

Recognizing Parallel Tool Calls

When the model issues parallel tool calls, the response message contains a tool_calls list with more than one entry. Each entry has a unique id, function name, and arguments. You must process all of them before making the follow-up API call — the model expects results for every tool call it issued.

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"})

Executing Tool Calls with asyncio

Run multiple tool calls concurrently using asyncio.gather(). Each tool function runs in a separate coroutine, and all results are collected when all coroutines complete. This is far faster than sequential execution when each tool call makes a network request.

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 results

Sending All Results Back Together

After executing all parallel tool calls, add every result as a separate role='tool' message to the conversation. Each message must include its matching tool_call_id. Send all of them in a single follow-up API call so the model can synthesize all results into one coherent answer.

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.content

Using ThreadPoolExecutor for Sync Tools

If your tool functions are synchronous (using requests rather than httpx async), you can still run them in parallel using concurrent.futures.ThreadPoolExecutor. This is simpler to set up but slightly less efficient than pure async code.

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 results

Handling Individual Tool Failures

When executing tool calls in parallel, one may fail while others succeed. Never let one failure block the others. Use return_exceptions=True in asyncio.gather() to collect all results even if some raise exceptions. Convert exceptions to error strings so the model receives all results and can reason about partial failures.

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 results

When Models Use Parallel Calls

The model issues parallel tool calls when it determines the required information can be gathered independently — one result doesn't depend on another. Examples: fetching stock prices for multiple tickers, getting weather in multiple cities, or querying multiple database tables. Sequential calls happen when results are dependent — first look up a user ID, then fetch orders for that ID.

Rate Limiting Parallel Calls

Running many tool calls in parallel can overwhelm external APIs with simultaneous requests. Use a semaphore to cap the maximum number of concurrent tool calls. This respects API rate limits while still executing more efficiently than pure sequential processing.

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)
    ]

Chaining Sequential and Parallel Calls

Real agentic workflows often mix sequential and parallel calls. The model might first call lookup_user(email), then — using the returned user_id — call get_orders(user_id) and get_preferences(user_id) in parallel. Implement the outer loop to detect which calls can be parallelized (independent) and which must be sequential (dependent).

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.'

Measuring Latency Improvement

Parallel tool calls can dramatically reduce latency. If each of three tool calls takes 500ms sequentially, the total is 1500ms. Running them in parallel reduces it to ~500ms — a 3x speedup. Always measure and compare sequential vs parallel execution in your specific scenario, accounting for concurrency overhead and rate limit constraints.

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 Parallel Tool Calls

When debugging parallel tool call issues, log the full request-response cycle: the model's message with all tool_calls, each result added to the conversation, and the final model response. If a tool result is missing or out of order, the model may produce inconsistent answers. Structured logging with tool_call_id as a correlation key makes tracing issues much easier.

Quick Check

Test your understanding of parallel function calling with OpenAI.

Lesson Recap

In this lesson you learned: parallel tool calls appear as multiple entries in the tool_calls list, asyncio.gather executes them concurrently for maximum speed, and each result needs its matching tool_call_id when sent back to the model. Next up we build a natural language database interface using function calling to translate plain English queries into SQL.

Häufig gestellte Fragen

Ist die Lektion „Parallele Funktionsaufrufe“ kostenlos?

Ja — der vollständige Text von „Parallele Funktionsaufrufe“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des AI Engineering Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der AI Engineering Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Parallele Funktionsaufrufe“?

Verarbeiten Sie Antworten, in denen das Modell mehrere Funktionen gleichzeitig aufruft, führen Sie diese mit asyncio parallel aus und bündeln Sie die Ergebnisse in einem einzigen anschließenden API-A… Du übst AI Engineering Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um AI Engineering Academy zu starten?

Keine Vorkenntnisse erforderlich. AI Engineering Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „Parallele Funktionsaufrufe“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser AI Engineering Academy-Lektion Code schreiben und ausführen?

Ja. Jede AI Engineering Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Funktionsschemas für die API definieren
  2. Tool-Aufrufe in Ihrer Anwendung verarbeiten
  3. Parallele Funktionsaufrufe
  4. Eine natürlichsprachliche Datenbankschnittstelle entwickeln
← Zurück zu AI Engineering Academy