กลับไปที่บล็อก

API และ SDKคู่มือ

Function calling ใน Python ด้วย API ที่เข้ากันได้กับ OpenAI

ส่ง tools อ่าน tool_calls และคืนผลลัพธ์ด้วย role tool: ลูป function calling สองขั้นตอนใน Python ด้วย MiniMax-M2.7

โดย CheapTokens Teamเผยแพร่เมื่อ อัปเดตเมื่อ ใช้เวลาอ่าน 6 นาที

แผนภาพลูปการเรียกเครื่องมือสองขั้นตอน: ส่ง tools อ่าน tool_calls คืนผลลัพธ์เป็นข้อความเครื่องมือ
ในหน้านี้
  1. หลักการทำงานของ function calling
  2. ตั้งค่าไคลเอนต์
  3. ประกาศฟังก์ชันและส่งคำขอแรก
  4. สิ่งที่คุณควรเห็น
  5. หลาย call และลูปที่ยาวขึ้น
  6. ทำไม MiniMax-M2.7 จึงเหมาะกับลูปเครื่องมือ
  7. หากใช้งานไม่ได้
  8. ขั้นตอนถัดไป

Function calling (tool calling) ช่วยให้โมเดลขอให้โค้ดของคุณรันฟังก์ชันได้ คุณส่งรายการ tools ไปพร้อมกับคำขอ โมเดลจะตอบกลับด้วย tool_calls แทนข้อความ คุณรันฟังก์ชันเอง แล้วส่งผลลัพธ์กลับไปในข้อความที่มี role: tool จากนั้นโมเดลจะเขียนคำตอบสุดท้าย คู่มือนี้แสดงลูปทั้งหมดใน Python กับ endpoint ที่เข้ากันได้กับ OpenAI https://api.cheaptokens.dev/v1/chat/completions ด้วย MiniMax-M2.7 (id MiniMaxAI/MiniMax-M2.7, context 180K, เอาต์พุตสูงสุด 8,192 โทเคนต่อคำตอบ)

Tool calling ระบุว่ารองรับสำหรับทุกโมเดลในแคตตาล็อก (CheapTokens docs, ตรวจสอบเมื่อ 22 ตุลาคม 2026) คุณต้องมี API key; หากยังไม่เคยส่งคำขอ ให้เริ่มที่ คำขอ API แรกของคุณ

หลักการทำงานของ function calling#

โมเดลไม่เคยรันอะไรเลย มันเพียงสร้างคำขอแบบมีโครงสร้าง: "เรียก get_weather ด้วย {\"city\": \"Paris\"}" โปรแกรมของคุณทำงานจริงและรายงานกลับมา นั่นทำให้เกิดลูปของคำขอสองครั้ง:

  1. คำขอที่ 1 คุณส่งข้อความของผู้ใช้พร้อมรายการ tools โมเดลจะตอบเป็นข้อความหรือคืน tool_calls หนึ่งรายการหรือมากกว่า
  2. โค้ดของคุณ คุณแยกวิเคราะห์แต่ละ call รันฟังก์ชันที่ตรงกัน และรวบรวมผลลัพธ์
  3. คำขอที่ 2 คุณส่งบทสนทนาทั้งหมดอีกครั้ง: ข้อความเดิม ข้อความของ assistant ที่มี tool_calls และข้อความ role: tool หนึ่งรายการต่อ call หนึ่งครั้ง โมเดลใช้ผลลัพธ์เพื่อเขียนคำตอบสุดท้าย

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

ตั้งค่าไคลเอนต์#

ติดตั้ง OpenAI SDK (pip install openai) และใส่คีย์ของคุณในตัวแปรสภาพแวดล้อมแทนที่จะใส่ในซอร์สโค้ด:

bash
export CHEAPTOKENS_API_KEY="your-key-here"

Base URL คือ https://api.cheaptokens.dev/v1 ใช้ model id จากเอกสาร CheapTokens: ผู้ให้บริการแต่ละรายตั้งชื่อโมเดลเดียวกันต่างกัน คู่มือนี้ใช้ MiniMaxAI/MiniMax-M2.7

ประกาศฟังก์ชันและส่งคำขอแรก#

ฟังก์ชันอธิบายไว้ในอาร์เรย์ tools แต่ละรายการมี type: function และออบเจกต์ function ที่มี name, description และ parameters เขียนเป็น JSON Schema คำอธิบายคือสิ่งที่โมเดลอ่านเพื่อตัดสินใจว่าจะเรียกฟังก์ชันเมื่อใด ดังนั้นเขียนเป็นประโยคสั้นและชัดเจน

ด้านล่างคือสคริปต์ที่สมบูรณ์ ฟังก์ชันสภาพอากาศเป็น stub ที่มีข้อมูลปลอม ตัวอย่างจึงไม่ต้องใช้บริการเพิ่มเติม:

python
import json
import os

from openai import OpenAI

client = OpenAI(
    base_url='https://api.cheaptokens.dev/v1',
    api_key=os.environ['CHEAPTOKENS_API_KEY'],
)
MODEL = 'MiniMaxAI/MiniMax-M2.7'


def get_weather(city: str) -> dict:
    # Stub with fake data: replace with a real lookup
    fake = {'Paris': 14, 'Tokyo': 19}
    return {'city': city, 'temp_c': fake.get(city, 10)}


FUNCTIONS = {'get_weather': get_weather}

tools = [
    {
        'type': 'function',
        'function': {
            'name': 'get_weather',
            'description': 'Get the current temperature in Celsius for a city.',
            'parameters': {
                'type': 'object',
                'properties': {
                    'city': {'type': 'string', 'description': 'City name, for example Paris'},
                },
                'required': ['city'],
            },
        },
    }
]

messages = [{'role': 'user', 'content': 'What is the weather in Paris right now?'}]

# Step 1: the model decides whether to call a function
first = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
message = first.choices[0].message

if not message.tool_calls:
    print(message.content)
    raise SystemExit

# Step 2: run every requested call and send the results back
messages.append(message)
for call in message.tool_calls:
    args = json.loads(call.function.arguments)
    result = FUNCTIONS[call.function.name](**args)
    messages.append({
        'role': 'tool',
        'tool_call_id': call.id,
        'content': json.dumps(result),
    })

final = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
print(final.choices[0].message.content)

รายละเอียดสามอย่างตัดสินว่าลูปจะทำงานได้หรือไม่:

  • call.function.arguments เป็น สตริง JSON ไม่ใช่ดิกชันนารี แยกวิเคราะห์ด้วย json.loads
  • ข้อความ role: tool แต่ละรายการต้องมี tool_call_id ของ call ที่มันตอบ ซึ่งก็คือ call.id
  • content ของข้อความเครื่องมือเป็นสตริง ใช้ json.dumps สำหรับผลลัพธ์แบบมีโครงสร้าง

สิ่งที่คุณควรเห็น#

หากคุณพิมพ์ฟิลด์หลังคำขอแรก จะมีลักษณะเช่นนี้ (call id ต่างกันในทุกครั้งที่รัน):

text
finish_reason: tool_calls
call.id: call_abc123
call.function.name: get_weather
call.function.arguments: {"city": "Paris"}

จากนั้นสคริปต์จะพิมพ์คำตอบสุดท้าย เป็นประโยคธรรมดาประมาณว่า "It is currently 14 °C in Paris." ถ้อยคำเปลี่ยนไปในแต่ละครั้งที่รัน ตัวเลขมาจากฟังก์ชันของคุณ

หลาย call และลูปที่ยาวขึ้น#

โมเดลสามารถคืน call มากกว่าหนึ่งรายการในคำตอบเดียว เช่น เมื่อคุณถามสภาพอากาศในสองเมือง นั่นคือเหตุผลที่ตัวอย่างวนลูปผ่าน message.tool_calls และตอบแต่ละ call ด้วย id ของมันเอง คู่มือ function calling ของ OpenAI อธิบายพฤติกรรมเดียวกัน: ด้วยค่าเริ่มต้น tool_choice เป็น auto โมเดลอาจเรียกศูนย์ หนึ่ง หรือหลายฟังก์ชัน (OpenAI docs, ตรวจสอบเมื่อ 22 ตุลาคม 2026; หน้าเว็บไม่มีวันที่อัปเดตล่าสุดและอธิบายรูปแบบ Responses API ที่ใหม่กว่า ขณะที่คู่มือนี้ใช้รูปแบบ Chat Completions ของ endpoint /v1/chat/completions)

เอเจนต์ทำสองขั้นตอนซ้ำจนกว่าโมเดลจะหยุดขอเครื่องมือ ครอบคำขอด้วยลูปและกำหนดขีดจำกัดจำนวนขั้นเสมอ:

python
for _ in range(5):  # safety limit against endless loops
    response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
    message = response.choices[0].message
    if not message.tool_calls:
        print(message.content)
        break
    messages.append(message)
    for call in message.tool_calls:
        args = json.loads(call.function.arguments)
        result = FUNCTIONS[call.function.name](**args)
        messages.append({'role': 'tool', 'tool_call_id': call.id, 'content': json.dumps(result)})

หากคุณต้องการให้คำตอบปรากฏทีละโทเคน ให้รวมกับ streaming ใน Python

ทำไม MiniMax-M2.7 จึงเหมาะกับลูปเครื่องมือ#

ลูปเครื่องมือส่งคำขอจำนวนมากพร้อมประวัติที่เพิ่มขึ้น สำหรับรูปแบบนั้น CheapTokens เสนอ MiniMax-M2.7: context 180K, เอาต์พุตสูงสุด 8,192 โทเคนต่อคำตอบ, ราคาเดียวตลอดเวลาของวันโดยไม่มีช่วงพีค และยอดคงเหลือเดียวสำหรับทุกโมเดล เมื่อนับอินพุตและเอาต์พุตรวมกัน ถูกกว่าราคาอ้างอิงของ OpenRouter (การเปรียบเทียบราคา CheapTokens, ตรวจสอบ 31 ตุลาคม 2026)

ราคาปัจจุบันต่อ 1M โทเคน: อินพุต $0.05, เอาต์พุต $0.15 ตัวอย่างภาระงาน (ไม่ใช่การวัดจริง) การไปกลับสองคำขอข้างต้นที่มีอินพุตประมาณ 2,700 และเอาต์พุต 350 โทเคนรวมกันมีค่าใช้จ่าย $0.00019 รายการราคาทั้งหมดอยู่ที่ หน้าราคา

หากต้องการลองโมเดลอื่น เปลี่ยนเฉพาะ id; รายการ id อยู่ที่ หน้ารุ่นโมเดล

หากใช้งานไม่ได้#

  • message.tool_calls เป็น None โมเดลตอบเป็นข้อความ ทำให้คำอธิบายฟังก์ชัน description เจาะจงมากขึ้น และตรวจสอบว่าคำถามจำเป็นต้องใช้ฟังก์ชันจริง ๆ
  • json.JSONDecodeError ที่ arguments โมเดลสร้าง JSON ที่ไม่ถูกต้อง ครอบ json.loads ด้วย try/except และส่งข้อความข้อผิดพลาดกลับเป็นผลลัพธ์เครื่องมือ เพื่อให้โมเดลลองใหม่ด้วยอาร์กิวเมนต์ที่แก้ไขแล้ว
  • คำขอที่สองล้มเหลวหรือโมเดลเพิกเฉยต่อผลลัพธ์ ตรวจสอบว่าแต่ละ call มีข้อความ role: tool หนึ่งรายการพอดีที่มี tool_call_id ตรงกัน และข้อความของ assistant ที่มี tool_calls อยู่ในประวัติก่อนหน้านั้น
  • KeyError ใน FUNCTIONS[...] โมเดลระบุชื่อฟังก์ชันที่คุณไม่ได้ลงทะเบียน คืนสตริงข้อผิดพลาดสั้น ๆ เป็นผลลัพธ์เครื่องมือแทนที่จะทำให้โปรแกรมพัง
  • คำตอบถูกตัด ตรวจสอบ finish_reason: ค่า length หมายถึงถึงขีดจำกัดโทเคนเอาต์พุตแล้ว ดู ทำไมคำตอบ AI จึงหยุดกลางประโยค
  • 401 หรือข้อผิดพลาดการยืนยันตัวตน ตรวจสอบว่าคีย์อยู่ใน CHEAPTOKENS_API_KEY และ base URL ลงท้ายด้วย /v1

ขั้นตอนถัดไป#

แทนที่ stub ด้วยฟังก์ชันจริง: การคิวรีฐานข้อมูล การเรียกค้นหา หรือเครื่องคิดเลข เพิ่มรายการใน tools และ FUNCTIONS และเก็บผลลัพธ์ของทุกฟังก์ชันให้สั้น เพราะมันจะกลับเข้าสู่ประวัติในทุกคำขอถัดไป หากต้องการรับคีย์และส่งคำขอแรก เปิด เอกสาร CheapTokens