0Pricing
AI Engineering Academy · บทเรียน

การเรียกใช้ฟังก์ชันแบบขนาน

จัดการการตอบกลับที่โมเดลเรียกใช้ฟังก์ชันหลายรายการพร้อมกัน เรียกใช้ฟังก์ชันเหล่านั้นแบบขนานด้วย asyncio และรวมผลลัพธ์เป็นการเรียก API ติดตามผลเพียงครั้งเดียว

การเรียกใช้ฟังก์ชันแบบขนาน เป็นบทเรียน AI Engineering Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Engineering Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน

การเรียกฟังก์ชันแบบขนานคืออะไร

โมเดลของ OpenAI สามารถเรียกใช้หลายฟังก์ชันพร้อมกันในการตอบกลับครั้งเดียว เมื่อคำตอบต้องใช้ข้อมูลจากแหล่งอิสระหลายแห่ง แทนที่จะเรียกเครื่องมือต่อกันทีละรายการ โดยแต่ละรายการต้องรอรายการก่อนหน้า โมเดลจะส่งการเรียกเครื่องมือหลายรายการออกมาพร้อมกัน แอปพลิเคชันของคุณจะเรียกใช้รายการเหล่านั้นแบบขนานและส่งผลลัพธ์ทั้งหมดกลับไปพร้อมกัน ซึ่งช่วยลดเวลาแฝงได้อย่างมาก

การตรวจจับการเรียกเครื่องมือแบบขนาน

เมื่อโมเดลส่งการเรียกเครื่องมือแบบขนาน ข้อความตอบกลับจะมีรายการ tool_calls ที่มีมากกว่าหนึ่งรายการ แต่ละรายการมี id ที่ไม่ซ้ำกัน ชื่อฟังก์ชัน และอาร์กิวเมนต์ คุณต้องประมวลผลทั้งหมดก่อนเรียก API ติดตามผล — โมเดลคาดหวังผลลัพธ์สำหรับการเรียกเครื่องมือทุกครั้งที่ส่งออกมา

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

การเรียกใช้การเรียกเครื่องมือด้วย asyncio

เรียกใช้การเรียกเครื่องมือหลายรายการพร้อมกันด้วย asyncio.gather() ฟังก์ชันเครื่องมือแต่ละรายการจะทำงานในคอรูทีนแยกกัน และผลลัพธ์ทั้งหมดจะถูกรวบรวมเมื่อคอรูทีนทั้งหมดทำงานเสร็จ วิธีนี้เร็วกว่าการเรียกใช้ตามลำดับมากเมื่อการเรียกเครื่องมือแต่ละครั้งต้องส่งคำขอผ่านเครือข่าย

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

การส่งผลลัพธ์ทั้งหมดกลับไปพร้อมกัน

หลังจากเรียกใช้การเรียกเครื่องมือแบบขนานทั้งหมดแล้ว ให้เพิ่มผลลัพธ์แต่ละรายการเป็นข้อความ role='tool' แยกจากกันในบทสนทนา แต่ละข้อความต้องมี tool_call_id ที่ตรงกัน ส่งข้อความทั้งหมดในการเรียก API ติดตามผลครั้งเดียว เพื่อให้โมเดลสังเคราะห์ผลลัพธ์ทั้งหมดเป็นคำตอบเดียวที่สอดคล้องกัน

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

การใช้ ThreadPoolExecutor สำหรับเครื่องมือแบบทำงานพร้อมกัน

หากฟังก์ชันเครื่องมือของคุณทำงานแบบพร้อมกันตามลำดับ (ใช้ requests แทน httpx แบบอะซิงโครนัส) คุณยังสามารถเรียกใช้ฟังก์ชันเหล่านั้นแบบขนานได้ด้วย concurrent.futures.ThreadPoolExecutor วิธีนี้ตั้งค่าได้ง่ายกว่า แต่มีประสิทธิภาพน้อยกว่าโค้ดแบบอะซิงโครนัสล้วนเล็กน้อย

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

การจัดการความล้มเหลวของเครื่องมือแต่ละรายการ

เมื่อเรียกใช้เครื่องมือแบบขนาน รายการหนึ่งอาจล้มเหลวในขณะที่รายการอื่นทำงานสำเร็จ อย่าให้ความล้มเหลวรายการเดียวขัดขวางรายการอื่น ใช้ return_exceptions=True ใน asyncio.gather() เพื่อรวบรวมผลลัพธ์ทั้งหมดแม้บางรายการจะทำให้เกิดข้อยกเว้น แปลงข้อยกเว้นเป็นสตริงข้อผิดพลาด เพื่อให้โมเดลได้รับผลลัพธ์ทั้งหมดและวิเคราะห์ความล้มเหลวบางส่วนได้

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

เวลาที่โมเดลใช้การเรียกแบบขนาน

โมเดลจะส่งการเรียกเครื่องมือแบบขนานเมื่อพิจารณาว่าสามารถรวบรวมข้อมูลที่ต้องใช้ได้อย่างอิสระต่อกัน — ผลลัพธ์หนึ่งไม่ขึ้นอยู่กับอีกผลลัพธ์หนึ่ง ตัวอย่างเช่น การดึงราคาหุ้นของหุ้นหลายตัว การรับข้อมูลสภาพอากาศของหลายเมือง หรือการสอบถามตารางฐานข้อมูลหลายตาราง การเรียกตามลำดับจะเกิดขึ้นเมื่อผลลัพธ์มีความเกี่ยวข้องกัน — ขั้นแรกค้นหา ID ผู้ใช้ จากนั้นดึงคำสั่งซื้อของ ID นั้น

การจำกัดอัตราการเรียกแบบขนาน

การเรียกเครื่องมือจำนวนมากแบบขนานอาจทำให้ API ภายนอกรับคำขอพร้อมกันมากเกินไป ใช้ Semaphore เพื่อจำกัดจำนวนการเรียกเครื่องมือพร้อมกันสูงสุด วิธีนี้ช่วยให้เป็นไปตามขีดจำกัดอัตราการเรียกของ API พร้อมกับยังทำงานได้มีประสิทธิภาพกว่าการประมวลผลตามลำดับล้วน

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

การเชื่อมต่อการเรียกตามลำดับและแบบขนาน

กระบวนการทำงานของเอเจนต์ในโลกจริงมักผสมการเรียกตามลำดับและแบบขนาน โมเดลอาจเรียก lookup_user(email) ก่อน จากนั้นใช้ user_id ที่ส่งคืนมาเรียก get_orders(user_id) และ get_preferences(user_id) แบบขนาน ให้ใช้ลูปภายนอกตรวจจับว่าการเรียกใดสามารถทำแบบขนานได้ (เป็นอิสระต่อกัน) และการเรียกใดต้องทำตามลำดับ (ขึ้นต่อกัน)

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

การวัดการปรับปรุงเวลาแฝง

การเรียกเครื่องมือแบบขนานช่วยลดเวลาแฝงได้อย่างมาก หากการเรียกเครื่องมือสามรายการใช้เวลา 500 มิลลิวินาทีต่อรายการเมื่อทำตามลำดับ เวลารวมจะเป็น 1500 มิลลิวินาที การเรียกแบบขนานจะลดเวลาเหลือประมาณ 500 มิลลิวินาที — เร็วขึ้น 3 เท่า ควรวัดและเปรียบเทียบการทำงานตามลำดับกับแบบขนานในสถานการณ์เฉพาะของคุณเสมอ โดยคำนึงถึงค่าใช้จ่ายจากการทำงานพร้อมกันและข้อจำกัดอัตราการเรียก

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

การแก้ไขข้อบกพร่องของการเรียกเครื่องมือแบบขนาน

เมื่อแก้ไขปัญหาการเรียกเครื่องมือแบบขนาน ให้บันทึกรอบการทำงานของคำขอและการตอบกลับทั้งหมด ได้แก่ ข้อความของโมเดลพร้อม tool_calls ทั้งหมด ผลลัพธ์แต่ละรายการที่เพิ่มลงในบทสนทนา และการตอบกลับสุดท้ายของโมเดล หากผลลัพธ์ของเครื่องมือขาดหายหรืออยู่นอกลำดับ โมเดลอาจสร้างคำตอบที่ไม่สอดคล้องกัน การบันทึกข้อมูลแบบมีโครงสร้างโดยใช้ tool_call_id เป็นคีย์เชื่อมโยง จะช่วยให้ติดตามปัญหาได้ง่ายขึ้นมาก

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจของคุณเกี่ยวกับการเรียกฟังก์ชันแบบขนานด้วย OpenAI

สรุปบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า การเรียกใช้เครื่องมือแบบขนานจะปรากฏเป็นหลายรายการในรายการ tool_calls asyncio.gather จะดำเนินการเรียกใช้พร้อมกันเพื่อความเร็วสูงสุด และ ผลลัพธ์แต่ละรายการต้องใช้ tool_call_id ที่ตรงกันเมื่อส่งกลับไปยังโมเดล ถัดไป เราจะสร้างส่วนติดต่อฐานข้อมูลด้วยภาษาธรรมชาติ โดยใช้การเรียกฟังก์ชันเพื่อแปลคำถามภาษาอังกฤษทั่วไปเป็น SQL

คำถามที่พบบ่อย

บทเรียน “การเรียกใช้ฟังก์ชันแบบขนาน” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การเรียกใช้ฟังก์ชันแบบขนาน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Engineering Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การเรียกใช้ฟังก์ชันแบบขนาน”

จัดการการตอบกลับที่โมเดลเรียกใช้ฟังก์ชันหลายรายการพร้อมกัน เรียกใช้ฟังก์ชันเหล่านั้นแบบขนานด้วย asyncio และรวมผลลัพธ์เป็นการเรียก API ติดตามผลเพียงครั้งเดียว คุณปฏิบัติ AI Engineering Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Engineering Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Engineering Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “การเรียกใช้ฟังก์ชันแบบขนาน” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน AI Engineering Academy นี้ได้ไหม

ได้ บทเรียน AI Engineering Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การกำหนดโครงสร้างฟังก์ชันสำหรับ API
  2. การประมวลผลการเรียกใช้เครื่องมือในแอปพลิเคชัน
  3. การเรียกใช้ฟังก์ชันแบบขนาน
  4. การสร้างส่วนติดต่อฐานข้อมูลด้วยภาษาธรรมชาติ
← กลับไปที่ AI Engineering Academy