Skip to main content
Pemanggilan Alat

Pemanggilan fungsi

Model Bahasa Besar (LLM) tidak dapat mengakses data real-time atau sistem eksternal. Pemanggilan Fungsi memungkinkan model memanggil alat eksternal, seperti API, database, dan user-defined function, sehingga mampu mengambil informasi atau melakukan tindakan di luar kemampuan bawaannya.

Cara kerja

Pemanggilan Fungsi bekerja melalui interaksi multi-langkah antara aplikasi Anda dan LLM:
  1. Lakukan panggilan model pertama Aplikasi mengirim pertanyaan pengguna dan daftar alat yang tersedia ke LLM.
  2. Menerima instruksi pemanggilan alat dari model Jika model memutuskan untuk memanggil alat eksternal, model tersebut mengembalikan instruksi JSON yang menentukan nama fungsi dan parameter input.
    Jika model memutuskan untuk tidak memanggil alat, respons akan dikembalikan dalam bahasa alami.
  3. Jalankan alat dalam aplikasi Aplikasi menjalankan alat yang ditentukan dan mendapatkan output-nya.
  4. Lakukan panggilan model kedua Tambahkan output alat ke array messages dan panggil model lagi.
  5. Menerima respons akhir dari model Model menggabungkan output alat dengan pertanyaan pengguna untuk menghasilkan respons dalam bahasa alami.
Gambar berikut menunjukkan alur kerja.

Model yang didukung

  • Qwen
  • DeepSeek
  • GLM
  • Kimi
  • MiniMax
  • Model generasi teks
    • Qwen-Max: seri Qwen3.8-Max, Qwen3.7-Max, Qwen3.6-Max, Qwen3-Max, dan Qwen-Max
    • Qwen-Plus: seri Qwen3.7-Plus, Qwen3.6-Plus, Qwen3.5-Plus, dan Qwen-Plus
    • Qwen-Flash: seri Qwen3.7-Flash, Qwen3.6-Flash, Qwen3.5-Flash, dan Qwen-Flash
    • Qwen-Coder: seri Qwen3-Coder, Qwen2.5-Coder, dan Qwen-Coder
    • Qwen-Turbo: seri Qwen-Turbo
    • Seri open source Qwen3.6
    • Seri open source Qwen3.5
    • Seri open source Qwen3
    • Seri open source Qwen2.5
    • Seri open source Qwen3.8
  • Model multimodal
    • Qwen-VL: seri Qwen3-VL-Plus dan Qwen3-VL-Flash
    • Qwen-Omni: seri Qwen3.5-Omni-Plus, Qwen3.5-Omni-Flash, dan Qwen3-Omni-Flash
    • Qwen-Omni-Realtime: seri Qwen3.5-Omni-Plus-Realtime dan Qwen3.5-Omni-Flash-Realtime
    • Seri open source Qwen3-VL
  • Model obrolan suara
    • Qwen-Audio-Realtime: seri Qwen-Audio-3.0-Realtime-Plus dan Qwen-Audio-3.0-Realtime-Flash

Memulai

Sebelum memulai, dapatkan Kunci API dan konfigurasikan sebagai Variabel lingkungan. Jika Anda menggunakan SDK OpenAI atau SDK DashScope, Anda juga harus menginstal SDK. Contoh berikut menunjukkan alur lengkap Pemanggilan Fungsi untuk skenario kueri cuaca.
  • Kompatibel dengan OpenAI
  • DashScope
from openai import OpenAI
from datetime import datetime
import json
import os
import random

client = OpenAI(
    # Kunci API berbeda-beda berdasarkan wilayah. Untuk mendapatkan Kunci API, lihat https://www.alibabacloud.com/help/en/model-studio/get-api-key
    # Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: api_key="sk-xxx",
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # Wilayah Singapura. Ganti {WorkspaceId} dengan ID Ruang Kerja aktual Anda. URL berbeda-beda berdasarkan wilayah.
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)
# Simulasikan pertanyaan pengguna
USER_QUESTION = "Bagaimana cuaca di Singapura?"
# Definisikan daftar alat
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Berguna saat Anda ingin menanyakan cuaca di kota tertentu.",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "Kota atau distrik, seperti Singapura atau New York.",
                    }
                },
                "required": ["location"],
            },
        },
    },
]

# Simulasikan alat kueri cuaca
def get_current_weather(arguments):
    weather_conditions = ["Sunny", "Cloudy", "Rainy"]
    random_weather = random.choice(weather_conditions)
    location = arguments["location"]
    return f"The weather in {location} today is {random_weather}."

# Enkapsulasi fungsi respons model
def get_response(messages):
    completion = client.chat.completions.create(
        model="qwen3.8-max",
        extra_body={"enable_thinking": False},
        messages=messages,
        tools=tools,
    )
    return completion

messages = [{"role": "user", "content": USER_QUESTION}]
response = get_response(messages)
assistant_output = response.choices[0].message
if assistant_output.content is None:
    assistant_output.content = ""
messages.append(assistant_output)
# Jika tidak diperlukan pemanggilan alat, cetak konten secara langsung
if assistant_output.tool_calls is None:
    print(f"Tidak perlu pemanggilan alat. Respons langsung: {assistant_output.content}")
else:
    # Masuk ke loop pemanggilan alat
    while assistant_output.tool_calls is not None:
        tool_call = assistant_output.tool_calls[0]
        tool_call_id = tool_call.id
        func_name = tool_call.function.name
        arguments = json.loads(tool_call.function.arguments)
        print(f"Memanggil alat [{func_name}], argumen: {arguments}")
        # Jalankan alat
        tool_result = get_current_weather(arguments)
        # Buat pesan balasan alat
        tool_message = {
            "role": "tool",
            "tool_call_id": tool_call_id,
            "content": tool_result,  # Pertahankan output alat asli
        }
        print(f"Alat mengembalikan: {tool_message['content']}")
        messages.append(tool_message)
        # Panggil model lagi untuk mendapatkan respons ringkasan dalam bahasa alami
        response = get_response(messages)
        assistant_output = response.choices[0].message
        if assistant_output.content is None:
            assistant_output.content = ""
        messages.append(assistant_output)
    print(f"Respons akhir Asisten: {assistant_output.content}")
Setelah menjalankan kode, output berikut ditampilkan:
Memanggil alat [get_current_weather], argumen: {'location': 'Singapura'}
Alat mengembalikan: The weather in Singapore today is Cloudy.
Respons akhir Asisten: The weather in Singapore today is cloudy.

Cara menggunakan

Pemanggilan Fungsi mendukung dua cara untuk meneruskan informasi alat:
  • Metode 1: Meneruskan informasi melalui parameter tools (direkomendasikan) Untuk informasi lebih lanjut, lihat Cara menggunakan. Ikuti langkah-langkah untuk mendefinisikan alat, membuat array messages, melakukan Pemanggilan Fungsi, menjalankan fungsi alat, dan meminta LLM merangkum output fungsi alat.
  • Metode 2: Meneruskan informasi melalui Pesan Sistem Meneruskan informasi melalui parameter tools memberikan hasil terbaik karena server secara otomatis menyesuaikan dengan templat prompt optimal. Jika Anda menggunakan model Qwen dan tidak ingin menggunakan parameter tools, lihat Meneruskan informasi alat melalui Pesan Sistem.
Bagian berikut menggunakan API kompatibel OpenAI sebagai contoh untuk menjelaskan penggunaan detail Pemanggilan Fungsi dengan parameter tools. Asumsikan skenario bisnis yang menerima dua jenis pertanyaan: kueri cuaca dan kueri waktu.

1. Definisikan alat

Alat menghubungkan LLM ke layanan eksternal. Anda harus terlebih dahulu mendefinisikan alat.

1.1. Buat fungsi alat

Buat dua fungsi alat: alat kueri cuaca dan alat kueri waktu.
  • Alat kueri cuaca Alat ini menerima parameter arguments. Format arguments adalah {"location": "lokasi yang dikueri"}. Output alat adalah string dalam format: "{lokasi} hari ini {cuaca}".
    Untuk tujuan demonstrasi, alat kueri cuaca yang didefinisikan di sini tidak benar-benar menanyakan cuaca. Alat ini secara acak memilih dari cerah, berawan, atau hujan. Dalam skenario bisnis nyata, Anda dapat menggantinya dengan alat seperti Amap Weather.
  • Alat kueri waktu Alat kueri waktu tidak memerlukan parameter input apa pun. Output alat adalah string dalam format: "Waktu saat ini: {waktu yang dikueri}.".
    Jika Anda menggunakan Node.js, jalankan npm install date-fns untuk menginstal paket date-fns guna mendapatkan waktu.
## Langkah 1: Definisikan fungsi alat

# Tambahkan impor untuk modul random
import random
from datetime import datetime

# Simulasikan alat kueri cuaca. Contoh output: "The weather in Beijing today is rainy."
def get_current_weather(arguments):
    # Definisikan daftar kondisi cuaca alternatif
    weather_conditions = ["Sunny", "Cloudy", "Rainy"]
    # Pilih kondisi cuaca secara acak
    random_weather = random.choice(weather_conditions)
    # Ekstrak informasi lokasi dari JSON
    location = arguments["location"]
    # Kembalikan informasi cuaca yang diformat
    return f"The weather in {location} today is {random_weather}."

# Alat untuk menanyakan waktu saat ini. Contoh output: "Current time: 2024-04-15 17:15:18."
def get_current_time():
    # Dapatkan tanggal dan waktu saat ini
    current_datetime = datetime.now()
    # Format tanggal dan waktu saat ini
    formatted_time = current_datetime.strftime('%Y-%m-%d %H:%M:%S')
    # Kembalikan waktu saat ini yang diformat
    return f"Current time: {formatted_time}."

# Uji fungsi alat dan cetak hasilnya. Anda dapat menghapus empat baris kode uji berikut saat menjalankan langkah-langkah selanjutnya.
print("Menguji output alat:")
print(get_current_weather({"location": "Shanghai"}))
print(get_current_time())
print("\n")
Setelah menjalankan alat, output berikut ditampilkan:
Keluaran alat pengujian:
Cuaca di Shanghai hari ini Berawan.
Waktu saat ini: 2025-01-08 20:21:45.

1.2. Buat array tools

Sebelum manusia dapat memilih alat, mereka perlu memahami fungsinya, skenario penggunaannya, dan parameter inputnya. Hal yang sama berlaku untuk LLM. Model memilih alat yang sesuai berdasarkan informasi ini. Berikan informasi alat dalam format JSON berikut.
  • Field type diatur ke "function".
  • Field function adalah objek.
    • Field name adalah nama fungsi alat kustom. Kami merekomendasikan menggunakan nama yang sama dengan fungsi, seperti get_current_weather atau get_current_time.
    • Field description menjelaskan kemampuan fungsi alat. LLM merujuk ke field ini untuk memutuskan apakah akan menggunakan fungsi alat.
    • Field parameters menjelaskan parameter input fungsi alat. Ini adalah objek. LLM merujuk ke field ini untuk mengekstrak parameter input. Jika fungsi alat tidak memerlukan parameter input, Anda tidak perlu menentukan field parameters.
      • Field type diatur ke "object".
      • Field properties menjelaskan nama, tipe data, dan deskripsi parameter input. Ini adalah objek. Kuncinya adalah nama parameter input, dan nilainya adalah tipe data dan deskripsi parameter input.
      • Field required menentukan parameter mana yang wajib. Ini adalah array.
Untuk alat kueri cuaca, format informasi deskripsi alat adalah sebagai berikut:
{
    "type": "function",
    "function": {
        "name": "get_current_weather",
        "description": "Berguna saat Anda ingin menanyakan cuaca di kota tertentu.",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "Kota atau distrik, seperti Beijing, Hangzhou, atau Yuhang."
                }
            },
            "required": ["location"]
        }
    }
}
Sebelum melakukan Pemanggilan Fungsi, definisikan array informasi alat (tools) dalam kode Anda. Array ini mencakup nama fungsi, deskripsi, dan definisi parameter untuk setiap alat. Array ini diteruskan sebagai parameter dalam permintaan selanjutnya.
# Tempel kode berikut setelah kode Langkah 1

## Langkah 2: Buat array tools

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_time",
            "description": "Berguna saat Anda ingin mengetahui waktu saat ini.",
            "parameters": {}
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Berguna saat Anda ingin menanyakan cuaca di kota tertentu.",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "Kota atau distrik, seperti Beijing, Hangzhou, atau Yuhang.",
                    }
                },
                "required": ["location"]
            }
        }
    }
]
tool_name = [tool["function"]["name"] for tool in tools]
print(f"Dibuat {len(tools)} alat: {tool_name}\n")

2. Buat array messages

Pemanggilan Fungsi meneruskan instruksi dan konteks ke LLM melalui array messages. Sebelum melakukan panggilan, array messages harus berisi Pesan Sistem dan Pesan Pengguna.

Pesan Sistem

Meskipun fungsi dan skenario penggunaan alat telah dijelaskan saat Anda membuat array tools, lebih menekankan kapan harus memanggil alat dalam Pesan Sistem biasanya meningkatkan akurasi pemanggilan alat. Untuk skenario saat ini, Anda dapat mengatur Prompt Sistem menjadi:
Anda adalah asisten yang membantu. Jika pengguna bertanya tentang cuaca, panggil fungsi 'get_current_weather';
jika pengguna bertanya tentang waktu, panggil fungsi 'get_current_time'.
Harap jawab pertanyaan dengan nada yang ramah.

Pesan Pengguna

Pesan Pengguna digunakan untuk meneruskan pertanyaan pengguna. Mengasumsikan pengguna bertanya "Cuaca di Shanghai", array messages pada titik ini adalah:
# Langkah 3: Buat array messages
# Tempel kode berikut setelah kode Langkah 2
# Contoh Pesan Pengguna untuk model generasi teks
messages = [
    {
        "role": "system",
        "content": """Anda adalah asisten yang membantu. Jika pengguna bertanya tentang cuaca, panggil fungsi 'get_current_weather';
     jika pengguna bertanya tentang waktu, panggil fungsi 'get_current_time'.
     Harap jawab pertanyaan dengan nada yang ramah.""",
    },
    {
        "role": "user",
        "content": "Cuaca di Shanghai"
    }
]

# Contoh Pesan Pengguna untuk model multimodal
# messages=[
#  {
#         "role": "system",
#         "content": """Anda adalah asisten yang membantu. Jika pengguna bertanya tentang cuaca, panggil fungsi 'get_current_weather';
#      jika pengguna bertanya tentang waktu, panggil fungsi 'get_current_time'.
#      Harap jawab pertanyaan dengan nada yang ramah.""",
#     },
#     {"role": "user",
#      "content": [{"type": "image_url","image_url": {"url": "https://img.alicdn.com/imgextra/i2/O1CN01FbTJon1ErXVGMRdsN_!!6000000000405-0-tps-1024-683.jpg"}},
#                  {"type": "text", "text": "Tanyakan cuaca saat ini untuk lokasi dalam gambar"}]},
# ]

print("array messages dibuat\n")
Karena alat yang tersedia mencakup kueri cuaca dan waktu, Anda juga dapat menanyakan waktu saat ini.

3. Lakukan Pemanggilan Fungsi

Teruskan tools dan messages yang telah dibuat ke LLM untuk melakukan Pemanggilan Fungsi. LLM menentukan apakah akan memanggil alat. Jika iya, LLM mengembalikan nama fungsi alat dan parameternya.
Untuk model yang didukung, lihat Model yang didukung.
# Langkah 4: Lakukan pemanggilan fungsi
# Tempel kode berikut setelah kode Langkah 3
from openai import OpenAI
import os

client = OpenAI(
    // Kunci API berbeda-beda berdasarkan wilayah. Untuk mendapatkan Kunci API, lihat https://www.alibabacloud.com/help/en/model-studio/get-api-key
    // Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: api_key="sk-xxx",
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    // Wilayah Singapura. Ganti {WorkspaceId} dengan ID Ruang Kerja aktual Anda. URL berbeda-beda berdasarkan wilayah.
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

def function_calling():
    completion = client.chat.completions.create(
        // Contoh ini menggunakan qwen3.8-max. Anda dapat mengubah nama model sesuai kebutuhan. Untuk daftar model, lihat https://www.alibabacloud.com/help/en/model-studio/getting-started/models
        model="qwen3.8-max",
        extra_body={"enable_thinking": False},
        messages=messages,
        tools=tools
    )
    print("Objek yang dikembalikan:")
    print(completion.choices[0].message.model_dump_json())
    print("\n")
    return completion

print("Melakukan pemanggilan fungsi...")
completion = function_calling()
Karena pengguna bertanya tentang cuaca di Shanghai, LLM menentukan nama fungsi alat yang akan digunakan sebagai "get_current_weather" dan parameter input fungsi sebagai "{\"location\": \"Shanghai\"}".
{
    "content": "",
    "refusal": null,
    "role": "assistant",
    "audio": null,
    "function_call": null,
    "tool_calls": [
        {
            "id": "call_6596dafa2a6a46f7a217da",
            "function": {
                "arguments": "{\"location\": \"Shanghai\"}",
                "name": "get_current_weather"
            },
            "type": "function",
            "index": 0
        }
    ]
}
Perhatikan bahwa jika LLM menentukan bahwa tidak diperlukan alat untuk pertanyaan tersebut, LLM akan merespons langsung melalui parameter content. Saat Anda memasukkan "Hello", parameter tool_calls kosong, dan format objek yang dikembalikan adalah:
{
    "content": "Hello! Bagaimana saya bisa membantu Anda? Saya sangat pandai menjawab pertanyaan tentang cuaca atau waktu.",
    "refusal": null,
    "role": "assistant",
    "audio": null,
    "function_call": null,
    "tool_calls": null
}
Jika parameter tool_calls kosong, program Anda dapat langsung mengembalikan content tanpa menjalankan langkah-langkah berikutnya.
Jika Anda ingin LLM memilih alat tertentu setiap kali melakukan Pemanggilan Fungsi, lihat Pemanggilan alat paksa.

4. Jalankan fungsi alat

Menjalankan fungsi alat menerjemahkan keputusan model menjadi operasi aktual.
Proses menjalankan fungsi alat diselesaikan oleh lingkungan komputasi Anda, bukan LLM.
LLM hanya mengeluarkan string. Sebelum menjalankan fungsi alat, Anda perlu mengurai nama fungsi alat dan parameter inputnya secara terpisah.
  • Fungsi alat Buat pemetaan function_mapper dari nama fungsi alat ke entitas fungsi alat untuk memetakan string fungsi alat yang dikembalikan ke entitas fungsi alat.
  • Parameter input Parameter input yang dikembalikan oleh Pemanggilan Fungsi adalah string JSON. Gunakan alat untuk menguraikannya menjadi objek JSON guna mengekstrak informasi parameter input.
Setelah diurai, teruskan parameter ke fungsi alat dan jalankannya untuk mendapatkan hasil output.
# Langkah 5: Jalankan fungsi alat
# Tempelkan kode berikut setelah kode Langkah 4
import json

print("Menjalankan fungsi alat...")
# Dapatkan nama fungsi dan parameter input dari hasil yang dikembalikan
function_name = completion.choices[0].message.tool_calls[0].function.name
arguments_string = completion.choices[0].message.tool_calls[0].function.arguments

# Gunakan modul json untuk mengurai string parameter
arguments = json.loads(arguments_string)
# Buat tabel pemetaan fungsi
function_mapper = {
    "get_current_weather": get_current_weather,
    "get_current_time": get_current_time
}
# Dapatkan entitas fungsi
function = function_mapper[function_name]
# Jika parameter input kosong, panggil fungsi secara langsung
if arguments == {}:
    function_output = function()
# Jika tidak, teruskan parameter lalu panggil fungsi
else:
    function_output = function(arguments)
# Cetak output alat
print(f"Output fungsi alat: {function_output}\n")
Setelah menjalankan kode, output berikut ditampilkan:
The weather in Shanghai today is Cloudy.
Dalam skenario bisnis nyata, banyak alat melakukan tindakan spesifik (seperti mengirim email atau mengunggah file) daripada menanyakan data, dan tidak mengeluarkan string. Kami merekomendasikan menambahkan informasi deskripsi status (seperti "Email berhasil dikirim" atau "Operasi gagal") untuk alat semacam itu agar membantu LLM memahami status eksekusi.

5. Biarkan LLM merangkum output fungsi alat

Format output fungsi alat relatif tetap. Mengembalikannya langsung kepada pengguna mungkin terdengar kaku. Kirim output alat ke konteks model dan panggil model lagi untuk menghasilkan respons bergaya bahasa alami.
  1. Tambahkan Pesan Asisten Setelah Anda melakukan Pemanggilan Fungsi, Anda akan memperoleh Pesan Asisten melalui completion.choices[0].message. Pertama, tambahkan pesan tersebut ke array messages.
  2. Tambahkan Pesan Alat Tambahkan output alat ke array messages dalam format {"role": "tool", "content": "output alat", "tool_call_id": completion.choices[0].message.tool_calls[0].id}.
    • Pastikan output alat dalam format string.
    • tool_call_id adalah pengenal unik yang dihasilkan sistem untuk setiap permintaan pemanggilan alat. Model mungkin meminta untuk memanggil beberapa alat sekaligus. Saat mengembalikan beberapa hasil alat ke model, tool_call_id memastikan bahwa hasil output alat dapat dicocokkan dengan maksud pemanggilannya.
# Langkah 6: Kirim output alat ke LLM
# Tempel kode berikut setelah kode Langkah 5

messages.append(completion.choices[0].message)
print("Pesan asisten ditambahkan")
messages.append({"role": "tool", "content": function_output, "tool_call_id": completion.choices[0].message.tool_calls[0].id})
print("Pesan alat ditambahkan\n")
Pada titik ini, array messages adalah:
[
  Pesan Sistem -- Memandu strategi pemanggilan alat model
  Pesan Pengguna -- Pertanyaan pengguna
  Pesan Asisten -- Informasi pemanggilan alat yang dikembalikan model
  Pesan Alat -- Informasi output alat (mungkin ada beberapa Pesan Alat jika digunakan pemanggilan alat paralel, seperti yang dijelaskan di bawah)
]
Setelah memperbarui array messages, jalankan kode berikut.
# Langkah 7: Biarkan LLM merangkum output alat
# Tempel kode berikut setelah kode Langkah 6
print("Merangkum output alat...")
completion = function_calling()
Anda dapat mengambil konten respons dari content: "Cuaca di Shanghai hari ini berawan. Jika Anda memiliki pertanyaan lain, jangan ragu untuk bertanya."
{
    "content": "Cuaca di Shanghai hari ini berawan. Jika Anda memiliki pertanyaan lain, jangan ragu untuk bertanya.",
    "refusal": null,
    "role": "assistant",
    "audio": null,
    "function_call": null,
    "tool_calls": null
}
Anda sekarang telah menyelesaikan alur Pemanggilan Fungsi secara lengkap.

Penggunaan lanjutan

Tentukan metode pemanggilan alat

Pemanggilan alat paralel

Kueri cuaca kota tunggal hanya memerlukan satu pemanggilan alat. Jika pertanyaan memerlukan beberapa pemanggilan alat, seperti "Bagaimana cuaca di Beijing dan Shanghai?" atau "Bagaimana cuaca di Hangzhou dan jam berapa sekarang?", setelah Anda melakukan Pemanggilan Fungsi, hanya satu informasi pemanggilan alat yang akan dikembalikan. Misalnya, jika Anda bertanya "Bagaimana cuaca di Beijing dan Shanghai?":
{
    "content": "",
    "refusal": null,
    "role": "assistant",
    "audio": null,
    "function_call": null,
    "tool_calls": [
        {
            "id": "call_61a2bbd82a8042289f1ff2",
            "function": {
                "arguments": "{\"location\": \"Beijing\"}",
                "name": "get_current_weather"
            },
            "type": "function",
            "index": 0
        }
    ]
}
Hasil yang dikembalikan hanya berisi parameter input untuk Beijing. Untuk memastikan hasil mencakup semua fungsi alat dan parameter input, Anda dapat mengatur parameter permintaan parallel_tool_calls ke true saat Anda melakukan Pemanggilan Fungsi.
Pemanggilan alat paralel cocok untuk tugas yang tidak memiliki dependensi. Jika ada dependensi antar tugas (input alat A terkait dengan output alat B), lihat Memulai untuk mengimplementasikan pemanggilan alat serial (memanggil satu alat dalam satu waktu) melalui loop while.
def function_calling():
    completion = client.chat.completions.create(
        model="qwen3.8-max",  // Contoh ini menggunakan qwen3.8-max. Anda dapat mengubah nama model sesuai kebutuhan.
        extra_body={"enable_thinking": False},
        messages=messages,
        tools=tools,
        // Parameter baru
        parallel_tool_calls=True
    )
    print("Objek yang dikembalikan:")
    print(completion.choices[0].message.model_dump_json())
    print("\n")
    return completion

print("Melakukan pemanggilan fungsi...")
completion = function_calling()
Array tool_calls dalam objek yang dikembalikan berisi informasi parameter input untuk Beijing dan Shanghai:
{
    "content": "",
    "role": "assistant",
    "tool_calls": [
        {
            "function": {
                "name": "get_current_weather",
                "arguments": "{\"location\": \"Beijing\"}"
            },
            "index": 0,
            "id": "call_c2d8a3a24c4d4929b26ae2",
            "type": "function"
        },
        {
            "function": {
                "name": "get_current_weather",
                "arguments": "{\"location\": \"Shanghai\"}"
            },
            "index": 1,
            "id": "call_dc7f2f678f1944da9194cd",
            "type": "function"
        }
    ]
}

Pemanggilan alat paksa

LLM menghasilkan konten dengan tingkat ketidakpastian tertentu dan mungkin memilih alat yang salah. Untuk memaksa penggunaan atau menonaktifkan alat tertentu untuk jenis pertanyaan tertentu, Anda dapat memodifikasi parameter tool_choice. Nilai default parameter tool_choice adalah "auto", yang berarti LLM secara otonom memutuskan cara melakukan pemanggilan alat.
Saat LLM merangkum output fungsi alat, hapus parameter tool_choice. Jika tidak, API akan tetap mengembalikan informasi pemanggilan alat.
  • Paksa penggunaan alat tertentu Jika Anda ingin Pemanggilan Fungsi memaksa memanggil alat tertentu untuk jenis pertanyaan tertentu, Anda dapat mengatur parameter tool_choice ke {"type": "function", "function": {"name": "the_function_to_call"}}. LLM tidak akan berpartisipasi dalam pemilihan alat dan hanya akan mengeluarkan informasi parameter input. Mengasumsikan skenario saat ini hanya melibatkan pertanyaan kueri cuaca, Anda dapat memodifikasi kode function_calling menjadi:
def function_calling():
    completion = client.chat.completions.create(
        model="qwen3.8-max",
        extra_body={"enable_thinking": False},
        messages=messages,
        tools=tools,
        tool_choice={"type": "function", "function": {"name": "get_current_weather"}}
    )
    print(completion.model_dump_json())

function_calling()
async function functionCalling() {
    const response = await openai.chat.completions.create({
        model: "qwen3.8-max",
        enable_thinking: false,
        messages: messages,
        tools: tools,
        tool_choice: {"type": "function", "function": {"name": "get_current_weather"}}
    });
    console.log("Objek yang dikembalikan:");
    console.log(JSON.stringify(response.choices[0].message));
    console.log("\n");
    return response;
}

const response = await functionCalling();
Tidak peduli pertanyaan apa yang dimasukkan, fungsi alat dalam objek yang dikembalikan akan menjadi get_current_weather.
Sebelum menggunakan strategi ini, pastikan pertanyaan terkait dengan alat yang dipilih. Jika tidak, mungkin mengembalikan hasil yang tidak terduga.
Paksa penggunaan minimal satu alat Untuk beberapa pertanyaan yang memerlukan alat, LLM mungkin memutuskan bahwa tidak perlu melakukan pemanggilan. Untuk memastikan Pemanggilan Fungsi selalu melakukan pemanggilan alat (sehingga parameter tool_calls dalam objek yang dikembalikan tidak kosong), Anda dapat mengatur parameter tool_choice ke "required". Dengan pengaturan ini, Pemanggilan Fungsi akan selalu mengembalikan informasi alat beserta parameter inputnya. Jika semua pertanyaan dalam skenario saat ini memerlukan pemanggilan alat, Anda dapat memodifikasi kode function_calling menjadi:
def function_calling():
    completion = client.chat.completions.create(
        model="qwen3.8-max",
        extra_body={"enable_thinking": False},
        messages=messages,
        tools=tools,
        tool_choice="required"
    )
    print(completion.model_dump_json())

function_calling()
Dengan konfigurasi tersebut, parameter tool_calls dalam objek yang dikembalikan tidak akan pernah kosong, terlepas dari pertanyaan yang dimasukkan.
Sebelum menerapkan strategi ini, pastikan pertanyaan tersebut relevan dengan alat yang tersedia. Jika tidak, hasil yang dikembalikan mungkin tidak sesuai harapan.
  • Paksa tidak menggunakan alat Jika Anda perlu Pemanggilan Fungsi tidak pernah melakukan pemanggilan alat (objek yang dikembalikan berisi konten respons dalam content dan parameter tool_calls kosong), Anda dapat mengatur parameter tool_choice ke "none", atau jangan teruskan parameter tools. Parameter tool_calls yang dikembalikan oleh Pemanggilan Fungsi akan selalu kosong. Mengasumsikan tidak ada pertanyaan dalam skenario saat ini yang memerlukan pemanggilan alat, Anda dapat memodifikasi kode function_calling menjadi:
def function_calling():
    completion = client.chat.completions.create(
        model="qwen3.8-max",
        extra_body={"enable_thinking": False},
        messages=messages,
        tools=tools,
        tool_choice="none"
    )
    print(completion.model_dump_json())

function_calling()
async function functionCalling() {
    const completion = await openai.chat.completions.create({
        model: "qwen3.8-max",
        enable_thinking: false,
        messages: messages,
        tools: tools,
        tool_choice: "none"
    });
    console.log("Objek yang dikembalikan:");
    console.log(JSON.stringify(completion.choices[0].message));
    console.log("\n");
    return completion;
}

const completion = await functionCalling();

Percakapan multi-putaran

Pengguna mungkin bertanya "Cuaca di Beijing" pada putaran pertama, lalu "Bagaimana dengan Shanghai?" pada putaran kedua. Jika konteks model tidak memiliki informasi dari putaran pertama, model tidak dapat menentukan alat mana yang akan dipanggil. Dalam skenario percakapan multi-putaran, pertahankan array messages lengkap setelah setiap putaran. Tambahkan Pesan Pengguna baru ke array ini lalu lakukan Pemanggilan Fungsi dan langkah-langkah selanjutnya. Struktur messages adalah sebagai berikut:
[
  Pesan Sistem -- Memandu strategi pemanggilan alat model
  Pesan Pengguna -- Pertanyaan pengguna
  Pesan Asisten -- Informasi pemanggilan alat yang dikembalikan model
  Pesan Alat -- Informasi output alat
  Pesan Asisten -- Ringkasan model atas informasi pemanggilan alat
  Pesan Pengguna -- Pertanyaan pengguna putaran kedua
]

keluaran streaming

Menggunakan keluaran streaming memungkinkan Anda mendapatkan informasi nama fungsi alat dan parameter input secara real-time, yang meningkatkan pengalaman pengguna. Dalam kasus ini:
  • Informasi parameter untuk pemanggilan alat dikembalikan dalam potongan sebagai aliran data.
  • Nama fungsi alat dikembalikan dalam potongan data pertama dari respons aliran.
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    // Wilayah Singapura. Ganti {WorkspaceId} dengan ID Ruang Kerja aktual Anda. URL berbeda-beda berdasarkan wilayah.
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Berguna saat Anda ingin menanyakan cuaca di kota tertentu.",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "Kota atau distrik, seperti Beijing, Hangzhou, atau Yuhang.",
                    }
                },
                "required": ["location"],
            },
        },
    },
]

stream = client.chat.completions.create(
    model="qwen3.8-max",
    extra_body={"enable_thinking": False},
    messages=[{"role": "user", "content": "Cuaca di Hangzhou?"}],
    tools=tools,
    stream=True
)

for chunk in stream:
    delta = chunk.choices[0].delta
    print(delta.tool_calls)
Setelah menjalankan kode, output berikut ditampilkan:
[ChoiceDeltaToolCall(index=0, id='call_8f08d2b0fc0c4d8fab7123', function=ChoiceDeltaToolCallFunction(arguments='{"location":', name='get_current_weather'), type='function')]
[ChoiceDeltaToolCall(index=0, id='', function=ChoiceDeltaToolCallFunction(arguments=' "Hangzhou"}', name=None), type='function')]
None
Jalankan kode berikut untuk merakit informasi parameter input (arguments):
tool_calls = {}
for response_chunk in stream:
    delta_tool_calls = response_chunk.choices[0].delta.tool_calls
    if delta_tool_calls:
        for tool_call_chunk in delta_tool_calls:
            call_index = tool_call_chunk.index
            tool_call_chunk.function.arguments = tool_call_chunk.function.arguments or ""
            if call_index not in tool_calls:
                tool_calls[call_index] = tool_call_chunk
            else:
                tool_calls[call_index].function.arguments += tool_call_chunk.function.arguments
print(tool_calls[0].model_dump_json())
Output berikut ditampilkan:
{"index":0,"id":"call_16c72bef988a4c6c8cc662","function":{"arguments":"{\"location\": \"Hangzhou\"}","name":"get_current_weather"},"type":"function"}
Pada langkah di mana LLM merangkum output fungsi alat, Pesan Asisten yang ditambahkan perlu sesuai dengan format di bawah ini. Cukup ganti elemen dalam tool_calls di bawah dengan konten di atas.
{
    "content": "",
    "refusal": None,
    "role": "assistant",
    "audio": None,
    "function_call": None,
    "tool_calls": [
        {
            "id": "call_xxx",
            "function": {
                "arguments": '{"location": "xx"}',
                "name": "get_current_weather",
            },
            "type": "function",
            "index": 0,
        }
    ],
}

Pemanggilan alat dengan API Responses

Contoh sebelumnya didasarkan pada API Chat Completions dan DashScope OpenAI. Jika Anda menggunakan API Responses OpenAI, proses keseluruhan sama, tetapi format API memiliki perbedaan berikut:
DimensiChat CompletionsAPI Responses
Format definisi alat
{
    "type": "function",
    "function": {
        "name":...,
        "parameters":...
    }
}
{
    "type": "function",
    "name":...,
    "parameters":...
}
Output pemanggilan alatresponse.choices[0].message.tool_callsItem dalam response.output di mana type adalah function_call
Umpan balik hasil alat
{
    "role": "tool",
    "tool_call_id":...,
    "content":...
}
{
    "type": "function_call_output",
    "call_id":...,
    "output":...
}
Respons akhirresponse.choices[0].message.contentresponse.output_text
from openai import OpenAI
import json
import os
import random

// Inisialisasi klien
client = OpenAI(
    // Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: api_key="sk-xxx",
    // Kunci API berbeda-beda berdasarkan wilayah. Untuk mendapatkan Kunci API, lihat https://www.alibabacloud.com/help/en/model-studio/get-api-key
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)
// Simulasikan pertanyaan pengguna
USER_QUESTION = "Bagaimana cuaca di Singapura?"
// Definisikan daftar alat
tools = [
    {
        "type": "function",
        "name": "get_current_weather",
        "description": "Berguna saat Anda ingin menanyakan cuaca di kota tertentu.",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "Kota atau distrik, seperti Singapura atau London.",
                }
            },
            "required": ["location"],
        },
    }
]

// Simulasikan alat kueri cuaca
def get_current_weather(arguments):
    weather_conditions = ["Sunny", "Cloudy", "Rainy"]
    random_weather = random.choice(weather_conditions)
    location = arguments["location"]
    return f"The weather in {location} today is {random_weather}."

// Enkapsulasi fungsi respons model
def get_response(input_data):
    response = client.responses.create(
        model="qwen3.8-max",
        extra_body={"enable_thinking": False},
        input=input_data,
        tools=tools,
    )
    return response

// Pertahankan konteks percakapan
conversation = [{"role": "user", "content": USER_QUESTION}]

response = get_response(conversation)
function_calls = [item for item in response.output if item.type == "function_call"]
// Jika tidak diperlukan pemanggilan alat, cetak konten secara langsung
if not function_calls:
    print(f"Respons akhir Asisten: {response.output_text}")
else:
    // Masuk ke loop pemanggilan alat
    while function_calls:
        for fc in function_calls:
            func_name = fc.name
            arguments = json.loads(fc.arguments)
            print(f"Memanggil alat [{func_name}], argumen: {arguments}")
            // Jalankan alat
            tool_result = get_current_weather(arguments)
            print(f"Alat mengembalikan: {tool_result}")
            // Tambahkan pasangan pemanggilan dan hasil alat ke konteks
            conversation.append(
                {
                    "type": "function_call",
                    "name": fc.name,
                    "arguments": fc.arguments,
                    "call_id": fc.call_id,
                }
            )
            conversation.append(
                {
                    "type": "function_call_output",
                    "call_id": fc.call_id,
                    "output": tool_result,
                }
            )
        // Panggil model lagi dengan konteks lengkap
        response = get_response(conversation)
        function_calls = [
            item for item in response.output if item.type == "function_call"
        ]
    print(f"Respons akhir Asisten: {response.output_text}")

Pemanggilan alat untuk model omni-modal

Model omni-modal mendukung pemanggilan alat. Metode pemanggilan untuk seri Qwen-Omni dan seri Qwen-Omni-Realtime berbeda.

Seri Qwen-Omni

Seri Qwen3.5-Omni-Plus, Qwen3.5-Omni-Flash, dan Qwen3-Omni-Flash mendukung pemanggilan alat melalui API kompatibel OpenAI. Tahap mendapatkan informasi alat berbeda dari model lain dalam hal berikut:
  • keluaran streaming wajib: Qwen-Omni hanya mendukung keluaran streaming. Saat mendapatkan informasi alat, Anda juga harus mengatur stream=True.
  • Output teks saja direkomendasikan: Model hanya memerlukan informasi teks saat mendapatkan informasi alat (nama dan parameter fungsi). Untuk menghindari menghasilkan audio yang tidak perlu, kami merekomendasikan mengatur modalities=["text"]. Saat output mencakup modalitas teks dan audio, Anda perlu melewati potongan data audio saat mendapatkan informasi alat.
Untuk informasi lebih lanjut tentang Qwen-Omni, lihat Non-real-time (Qwen-Omni).
from openai import OpenAI
import os

client = OpenAI(
    // Kunci API berbeda-beda berdasarkan wilayah. Untuk mendapatkan Kunci API, lihat https://www.alibabacloud.com/help/en/model-studio/get-api-key
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    // Wilayah Singapura. Ganti {WorkspaceId} dengan ID Ruang Kerja aktual Anda. URL berbeda-beda berdasarkan wilayah.
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Berguna saat Anda ingin menanyakan cuaca di kota tertentu.",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "Kota atau distrik, seperti Beijing, Hangzhou, atau Yuhang.",
                    }
                },
                "required": ["location"],
            },
        },
    },
]

completion = client.chat.completions.create(
    model="qwen3.5-omni-plus",
    messages=[{"role": "user", "content": "Cuaca di Hangzhou?"}],

    // Atur modalitas data output. Nilai yang valid: ["text"], ["text","audio"]. Kami merekomendasikan mengaturnya ke ["text"].
    modalities=["text"],

    // stream harus diatur ke True, jika tidak akan terjadi error.
    stream=True,
    tools=tools
)

for chunk in completion:
    // Jika output mencakup modalitas audio, ubah kondisi berikut menjadi: if chunk.choices and not hasattr(chunk.choices[0].delta, "audio"):
    if chunk.choices:
        delta = chunk.choices[0].delta
        print(delta.tool_calls)
Setelah menjalankan kode, output berikut ditampilkan:
[ChoiceDeltaToolCall(index=0, id='call_391c8e5787bc4972a388aa', function=ChoiceDeltaToolCallFunction(arguments=None, name='get_current_weather'), type='function')]
[ChoiceDeltaToolCall(index=0, id='call_391c8e5787bc4972a388aa', function=ChoiceDeltaToolCallFunction(arguments=' {"location": "Hangzhou"}', name=None), type='function')]
None
Untuk kode merakit informasi parameter input (arguments), lihat keluaran streaming.

Seri Qwen-Omni-Realtime

Seri Qwen3.5-Omni-Plus-Realtime dan Qwen3.5-Omni-Flash-Realtime mendukung pemanggilan alat dan cocok untuk skenario percakapan suara. Anda dapat memanggilnya melalui SDK DashScope atau protokol WebSocket asli. Alur kerja: Setelah membuat koneksi WebSocket, teruskan definisi alat melalui session.update untuk memasuki alur interaksi berikut: Fase 1: Input suara dan pemanggilan alat
  1. Pengguna mengajukan pertanyaan dengan suara. Klien mengumpulkan audio dan mengirimkannya ke server (sesuai dengan metode append_audio()). Setelah VAD server mendeteksi akhir ucapan, server melakukan inferensi model dan menentukan bahwa alat perlu dipanggil.
  2. Server mengembalikan informasi pemanggilan alat ke klien (sesuai dengan event response.function_call_arguments.done), termasuk nama fungsi (name), parameter input fungsi (arguments), dan pengenal panggilan (call_id). Contohnya sebagai berikut:
{
    "type": "response.function_call_arguments.done",
    "response_id": "resp_JnTOsWXlFhKcFohZbtfz6",
    "item_id": "item_Rhcms7CauTNsQprV5S4Hr",
    "output_index": 0,
    "name": "get_current_weather",
    "call_id": "call_2be200f4cafe419b9530dd",
    "arguments": "{\"location\": \"Hangzhou\"}"
}
  1. Klien menjalankan fungsi alat yang sesuai secara lokal berdasarkan nama fungsi dan parameter input untuk mendapatkan hasil eksekusi.
Fase 2: Klien mengirim kembali hasil alat dan memicu respons akhir
  1. Klien mengirim hasil eksekusi alat kembali ke server (sesuai dengan event conversation.item.create), termasuk pengenal panggilan (call_id) dan hasil eksekusi (output). Contohnya sebagai berikut:
{
    "type": "conversation.item.create",
    "item": {
        "type": "function_call_output",
        "call_id": "call_2be200f4cafe419b9530dd",
        "output": "The weather in Hangzhou today is sunny, with a temperature of 25°C and a light breeze."
    }
}
  1. Klien terus mengirim event response.create untuk memicu server menghasilkan jawaban suara akhir berdasarkan hasil eksekusi alat.
  2. Klien menerima suara dan teks yang dikembalikan server (sesuai dengan event response.audio.delta dan response.audio_transcript.delta) dan memutar respons suara ke pengguna.
Seri Qwen-Omni-Realtime tidak mendukung parameter tool_choice dan parallel_tool_calls.
Untuk informasi lebih lanjut tentang Qwen-Omni-Realtime, lihat Real-time (Qwen-Omni-Realtime), Event klien, dan Event sisi server.
SDK Python DashScope
import os
import uuid
import threading
import traceback
import json
import base64
import signal
import sys
import time
from typing import Dict, Any, Optional, List
import pyaudio
import queue
import contextlib
import dashscope
from dashscope.audio.qwen_omni import *

# ==================== Definisi Konstanta ====================
VOICE = 'Tina'
MODEL = "qwen3.5-omni-plus-realtime"
# Untuk mengakses wilayah Beijing, ganti WS_URL dengan: wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/realtime
WS_URL = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtime"
# Konfigurasikan kunci API. Jika Anda belum mengatur variabel lingkungan, ganti baris berikut dengan kunci API Anda: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.getenv('DASHSCOPE_API_KEY')
AUDIO_SAMPLE_RATE = 16000
AUDIO_CHUNK_SIZE = 3200
OUTPUT_AUDIO_SAMPLE_RATE = 24000

# ==================== Definisi Alat (Tool) ====================
def get_train_price(src: str, dst: str) -> str:
    """Kueri harga tiket kereta"""
    return f"The train ticket price from {src} to {dst} is 100-200 CNY."

def get_flight_price(src: str, dst: str) -> str:
    """Kueri harga tiket pesawat"""
    return f"The flight ticket price from {src} to {dst} is 200-300 USD."

def get_current_weather(location: str) -> str:
    """Kueri cuaca di kota tertentu"""
    return f"The weather in {location} today is changing from haze to sunny, with a temperature of 4/-4°C and a light breeze."

# Definisi alat (tool) format OpenAI terpadu
TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Berguna saat Anda ingin menanyakan cuaca di kota tertentu.",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "Sebuah kota atau distrik, seperti Beijing, Hangzhou, atau Yuhang.",
                    }
                },
                "required": ["location"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_flight_price",
            "description": "Berguna saat Anda ingin menanyakan harga tiket pesawat.",
            "parameters": {
                "type": "object",
                "properties": {
                    "src": {
                        "type": "string",
                        "description": "Kota keberangkatan penerbangan, seperti Beijing atau Hangzhou.",
                    },
                    "dst": {
                        "type": "string",
                        "description": "Kota kedatangan penerbangan, seperti Beijing atau Hangzhou.",
                    },
                },
                "required": ["src", "dst"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_train_price",
            "description": "Berguna saat Anda ingin menanyakan harga tiket kereta.",
            "parameters": {
                "type": "object",
                "properties": {
                    "src": {
                        "type": "string",
                        "description": "Kota keberangkatan kereta, seperti Beijing atau Hangzhou.",
                    },
                    "dst": {
                        "type": "string",
                        "description": "Kota kedatangan kereta, seperti Beijing atau Hangzhou.",
                    },
                },
                "required": ["src", "dst"],
            },
        },
    },
]

# Pemetaan nama alat (tool) ke fungsi
TOOL_FUNCTIONS = {
    "get_current_weather": get_current_weather,
    "get_flight_price": get_flight_price,
    "get_train_price": get_train_price,
}

# ==================== Penanganan Panggilan Alat (Tool Call) ====================
def handle_tool_call(tool_call_response: Dict[str, Any]) -> Dict[str, Any]:
    """
    Menangani permintaan panggilan alat (tool call)

    Args:
        tool_call_response: Informasi panggilan alat yang berisi nama, argumen, dan call_id

    Returns:
        Respons panggilan alat yang diperbarui yang berisi bidang output
    """
    try:
        function_name = tool_call_response['name']
        tool_call_arguments = json.loads(tool_call_response['arguments'])

        print(f'[Tool Call] Start processing: name={function_name}, args={tool_call_arguments}')

        # Temukan fungsi yang sesuai
        if function_name not in TOOL_FUNCTIONS:
            tool_call_response['output'] = f"Client did not find the tool: {function_name}"
            print(f'[Tool Call] Error: Tool not found {function_name}')
            return tool_call_response

        # Panggil fungsi
        func = TOOL_FUNCTIONS[function_name]
        result = func(**tool_call_arguments)
        tool_call_response['output'] = result

        print(f'[Tool Call] Completed: {result}')
        return tool_call_response

    except Exception as e:
        error_msg = f"Tool call failed: {str(e)}"
        tool_call_response['output'] = error_msg
        print(f'[Tool Call] Exception: {error_msg}')
        traceback.print_exc()
        return tool_call_response

def send_tool_call_response(conversation: OmniRealtimeConversation, response: Dict[str, Any]) -> None:
    """Mengirimkan hasil panggilan alat (tool call) ke server"""
    conversation.create_item({
        "id": 'item_' + uuid.uuid4().hex,
        "type": "function_call_output",
        "call_id": response['call_id'],
        "output": response["output"],
    })

# ==================== Pemutar Audio PCM ====================
class PCMPlayer:
    """
    Pemutar Audio PCM

    Menggunakan arsitektur dual-thread untuk pemutaran audio real-time:
    - Thread decoding: Mendekode data audio yang dienkode base64 menjadi data PCM mentah
    - Thread pemutaran: Menulis data PCM ke perangkat output audio

    Mendukung penambahan data audio secara dinamis, pembatalan pemutaran, penyimpanan file audio, dll.
    """

    def __init__(self, pya: pyaudio.PyAudio, sample_rate=24000, chunk_size_ms=100, save_file=False):
        """
        Menginisialisasi pemutar PCM

        Args:
            pya: Instans pyaudio.PyAudio
            sample_rate: Laju pengambilan sampel audio (Hz), default 24000
            chunk_size_ms: Ukuran chunk audio (milidetik), memengaruhi latensi pembatalan pemutaran, default 100ms
            save_file: Apakah akan menyimpan audio yang diputar ke file (result.pcm), default False
        """

        self.pya = pya
        self.sample_rate = sample_rate
        self.chunk_size_bytes = chunk_size_ms * sample_rate * 2 // 1000
        self.player_stream = pya.open(format=pyaudio.paInt16,
                                       channels=1,
                                       rate=sample_rate,
                                       output=True)

        self.raw_audio_buffer: queue.Queue = queue.Queue()
        self.b64_audio_buffer: queue.Queue = queue.Queue()
        self.status_lock = threading.Lock()
        self.status = 'playing'
        self.decoder_thread = threading.Thread(target=self.decoder_loop)
        self.player_thread = threading.Thread(target=self.player_loop)
        self.decoder_thread.start()
        self.player_thread.start()
        self.complete_event: threading.Event = None
        self.save_file = save_file
        if self.save_file:
            self.out_file = open('result.pcm', 'wb')

    def decoder_loop(self):
        """Thread decoding: Mendekode data audio base64 menjadi data PCM mentah"""
        while self.status != 'stop':
            recv_audio_b64 = None
            with contextlib.suppress(queue.Empty):
                recv_audio_b64 = self.b64_audio_buffer.get(timeout=0.1)
            if recv_audio_b64 is None:
                continue
            recv_audio_raw = base64.b64decode(recv_audio_b64)
            # dorong data audio mentah ke antrian per chunk
            for i in range(0, len(recv_audio_raw), self.chunk_size_bytes):
                chunk = recv_audio_raw[i:i + self.chunk_size_bytes]
                self.raw_audio_buffer.put(chunk)
                if self.save_file:
                    self.out_file.write(chunk)

    def player_loop(self):
        """Thread pemutaran: Menulis data PCM ke perangkat output audio"""
        while self.status != 'stop':
            recv_audio_raw = None
            with contextlib.suppress(queue.Empty):
                recv_audio_raw = self.raw_audio_buffer.get(timeout=0.1)
            if recv_audio_raw is None:
                if self.complete_event:
                    self.complete_event.set()
                continue
            # tulis chunk ke pemutar audio pyaudio, tunggu hingga selesai memutar chunk ini.
            self.player_stream.write(recv_audio_raw)

    def cancel_playing(self):
        """Batalkan pemutaran: Kosongkan semua antrian buffer"""
        self.b64_audio_buffer.queue.clear()
        self.raw_audio_buffer.queue.clear()

    def add_data(self, data):
        """Tambahkan data audio yang dienkode base64 ke antrian pemutaran"""
        self.b64_audio_buffer.put(data)

    def wait_for_complete(self):
        """Tunggu hingga pemutaran selesai"""
        self.complete_event = threading.Event()
        self.complete_event.wait()
        self.complete_event = None

    def shutdown(self):
        """Matikan pemutar dan lepaskan sumber daya"""
        self.status = 'stop'
        self.decoder_thread.join()
        self.player_thread.join()
        self.player_stream.close()
        if self.save_file:
            self.out_file.close()

# ==================== Manajer Audio ====================
class AudioManager:
    """Mengelola sumber daya input dan output audio"""

    def __init__(self):
        self.pya: Optional[pyaudio.PyAudio] = None
        self.mic_stream: Optional[pyaudio.Stream] = None
        self.player: Optional[PCMPlayer] = None

    def initialize(self) -> None:
        """Inisialisasi perangkat audio"""
        print('Initializing audio devices...')
        self.pya = pyaudio.PyAudio()
        self.mic_stream = self.pya.open(
            format=pyaudio.paInt16,
            channels=1,
            rate=AUDIO_SAMPLE_RATE,
            input=True
        )
        self.player = PCMPlayer(self.pya, sample_rate=OUTPUT_AUDIO_SAMPLE_RATE)
        print('Audio devices initialized')

    def read_audio_chunk(self) -> Optional[bytes]:
        """Baca sebuah chunk data audio"""
        if not self.mic_stream:
            return None
        try:
            return self.mic_stream.read(AUDIO_CHUNK_SIZE, exception_on_overflow=False)
        except Exception as e:
            print(f'[Error] Failed to read audio data: {e}')
            return None

    def cleanup(self) -> None:
        """Bersihkan sumber daya audio"""
        print('Cleaning up audio resources...')
        if self.player:
            self.player.shutdown()
        if self.mic_stream:
            self.mic_stream.close()
        if self.pya:
            self.pya.terminate()
        print('Audio resources cleaned up')

# ==================== Penangan Callback ====================
class OmniCallback(OmniRealtimeCallback):
    """Penangan callback percakapan real-time Omni"""

    def __init__(self, audio_manager: AudioManager):
        self.audio_manager = audio_manager
        self.tool_calls: Dict[str, Dict[str, Any]] = {}
        self.all_response_text: str = ''
        self.last_package_time: float = 0
        self.is_first_text: bool = True
        self.is_first_audio: bool = True
        self.conversation: Optional[OmniRealtimeConversation] = None

    def set_conversation(self, conversation: OmniRealtimeConversation) -> None:
        """Atur referensi instans percakapan"""
        self.conversation = conversation

    def on_open(self) -> None:
        """Callback saat koneksi terjalin"""
        print('Connection established')
        self.audio_manager.initialize()
        self.last_package_time = time.time() * 1000
        self.is_first_text = True
        self.is_first_audio = True
        self.tool_calls = {}
        self.all_response_text = ''

    def on_close(self, close_status_code: int, close_msg: str) -> None:
        """Callback saat koneksi ditutup"""
        print(f'Connection closed: code={close_status_code}, msg={close_msg}')
        self.audio_manager.cleanup()
        sys.exit(0)

    def on_event(self, response: Dict[str, Any]) -> None:
        """Tangani callback event"""
        try:
            event_type = response.get('type', '')

            # Sesi dibuat
            if event_type == 'session.created':
                print(f'Session started: {response["session"]["id"]}')

            # Speech-to-text selesai
            elif event_type == 'conversation.item.input_audio_transcription.completed':
                print(f'User question: {response.get("transcript", "")}')

            # Respons teks inkremental
            elif event_type in ('response.audio_transcript.delta', 'response.text.delta'):
                if self.is_first_text:
                    self.is_first_text = False
                    latency = time.time() * 1000 - self.last_package_time
                    print(f'Time to first token (VAD end): {latency:.0f} ms')

                text = response.get('delta', '')
                self.all_response_text += text

            # Respons audio inkremental
            elif event_type == 'response.audio.delta':
                if self.is_first_audio:
                    self.is_first_audio = False
                    latency = time.time() * 1000 - self.last_package_time
                    print(f'Time to first audio (VAD end): {latency:.0f} ms')

                audio_interval = time.time() * 1000 - self.last_package_time
                print(f'Audio interval: {audio_interval:.0f} ms')
                self.last_package_time = time.time() * 1000

                recv_audio_b64 = response.get('delta', '')
                if self.audio_manager.player:
                    self.audio_manager.player.add_data(recv_audio_b64)

            # VAD mendeteksi awal ucapan
            elif event_type == 'input_audio_buffer.speech_started':
                print('====== VAD detected speech start ======')
                if self.audio_manager.player:
                    self.audio_manager.player.cancel_playing()

            # VAD mendeteksi akhir ucapan
            elif event_type == 'input_audio_buffer.speech_stopped':
                print('====== VAD detected speech end ======')
                self.last_package_time = time.time() * 1000
                self.is_first_text = True
                self.is_first_audio = True
                self.tool_calls = {}

            # Argumen panggilan fungsi selesai
            elif event_type == 'response.function_call_arguments.done':
                print('====== Received tool call request ======')
                call_id = response.get('call_id', '')
                self.tool_calls[call_id] = response.copy()
                self.tool_calls[call_id]['processed'] = False

            # Respons selesai
            elif event_type == 'response.done':
                print('====== Response completed ======')
                print(f'Full response: {self.all_response_text}')

                if self.conversation:
                    response_id = self.conversation.get_last_response_id()
                    text_delay = self.conversation.get_last_first_text_delay()
                    audio_delay = self.conversation.get_last_first_audio_delay()

                    # Cetak metrik terperinci hanya jika semua tersedia
                    if response_id is not None and text_delay is not None and audio_delay is not None:
                        print(f'[Metric] Response ID: {response_id}, '
                              f'Time to first token: {text_delay:.0f}ms, '
                              f'Time to first audio: {audio_delay:.0f}ms')
                    else:
                        print('[Metrik] Informasi metrik untuk sementara tidak tersedia (kemungkinan respons setelah panggilan alat)')

                self.all_response_text = ''

        except Exception as e:
            print(f'[Error] Exception handling event: {e}')
            traceback.print_exc()

    def process_pending_tool_calls(self) -> bool:
        """
        Memproses panggilan alat (tool call) yang tertunda

        Returns:
            Apakah ada panggilan alat baru yang memerlukan respons
        """
        has_pending = False

        for call_id, tool_call in self.tool_calls.items():
            if not tool_call.get('processed', False):
                has_pending = True
                tool_call['processed'] = True

                # Tangani panggilan alat (tool call)
                result = handle_tool_call(tool_call)

                # Kirim hasilnya ke server
                if self.conversation:
                    send_tool_call_response(self.conversation, result)

        return has_pending

# ==================== Program Utama ====================
def main():
    """Fungsi utama"""
    print('Initializing Omni real-time conversation...')

    # Buat manajer audio
    audio_manager = AudioManager()

    # Buat penangan callback
    callback = OmniCallback(audio_manager)

    # Buat instans percakapan
    conversation = OmniRealtimeConversation(
        api_key=dashscope.api_key,
        url=WS_URL,
        model=MODEL,
        callback=callback,
    )

    # Atur referensi percakapan di callback
    callback.set_conversation(conversation)

    # Buat koneksi
    conversation.connect()

    # Konfigurasikan parameter sesi
    omni_output_modalities = [MultiModality.AUDIO, MultiModality.TEXT]

    conversation.update_session(
        output_modalities=omni_output_modalities,
        voice=VOICE,
        input_audio_format=AudioFormat.PCM_16000HZ_MONO_16BIT,
        output_audio_format=AudioFormat.PCM_24000HZ_MONO_16BIT,
        enable_input_audio_transcription=True,
        enable_turn_detection=True,
        turn_detection_type='server_vad',
        tools=TOOLS,
    )

    # Siapkan penanganan sinyal
    def signal_handler(sig, frame):
        print('\nMenerima Ctrl+C, menghentikan...')
        conversation.close()
        audio_manager.cleanup()
        print('Percakapan real-time Omni dihentikan')
        sys.exit(0)

    signal.signal(signal.SIGINT, signal_handler)
    print("Tekan Ctrl+C untuk menghentikan percakapan...\n")

    # Loop utama: terus-menerus mengirim audio dan memeriksa panggilan alat (tool call)
    try:
        while True:
            # Proses panggilan alat (tool call) yang tertunda
            has_tool_calls = callback.process_pending_tool_calls()

            if has_tool_calls:
                print("*** Panggilan alat selesai, membuat respons baru ***")
                conversation.create_response(
                    instructions=None,
                    output_modalities=omni_output_modalities
                )
                print('====== Pemrosesan panggilan alat selesai ======\n')

            # Baca dan kirim data audio
            audio_data = audio_manager.read_audio_chunk()
            if audio_data:
                audio_b64 = base64.b64encode(audio_data).decode('ascii')
                conversation.append_audio(audio_b64)
            else:
                break

    except KeyboardInterrupt:
        signal_handler(signal.SIGINT, None)
    except Exception as e:
        print(f'[Error] Main loop exception: {e}')
        traceback.print_exc()
    finally:
        conversation.close()
        audio_manager.cleanup()

if __name__ == '__main__':
    main()

Pemanggilan alat untuk model pemikiran mendalam

Model pemikiran mendalam melakukan inferensi sebelum menghasilkan informasi pemanggilan alat, sehingga meningkatkan interpretabilitas dan keandalan keputusan.
  1. Proses berpikir Model menganalisis maksud pengguna, mengidentifikasi alat yang diperlukan, memverifikasi legalitas parameter, serta merancang strategi pemanggilan langkah demi langkah.
  2. Pemanggilan alat Model menghasilkan satu atau beberapa permintaan pemanggilan fungsi dalam format terstruktur.
    Pemanggilan alat paralel didukung.
Berikut adalah contoh pemanggilan alat menggunakan model pemikiran mendalam dalam mode streaming.
Untuk informasi lebih lanjut tentang model pemikiran mendalam generasi teks, lihat Pemikiran mendalam. Untuk informasi lebih lanjut tentang model pemikiran mendalam multimodal, lihat Pemahaman gambar dan video dan Non-real-time (Qwen-Omni).
Parameter tool_choice hanya dapat diatur ke "auto" (nilai default, artinya model memilih alat secara otonom) atau "none" (memaksa model tidak memilih alat).
Dalam mode berpikir (enable_thinking=True), parameter tool_choice tidak mendukung nilai "required" atau objek (misalnya, {"type": "function", "function": {...}}). Mengatur tool_choice ke salah satu nilai tersebut saat mode berpikir diaktifkan akan menyebabkan permintaan gagal dengan error Parameter tool_choice tidak mendukung diatur ke required atau object dalam mode berpikir. Jangan mengandalkan tool_choice="required" sebagai jaminan bahwa tool_calls tidak kosong dalam mode berpikir. Jika Anda memerlukan pemanggilan alat MCP yang andal saat mode berpikir diaktifkan, gunakan API Responses untuk terhubung ke MCP sebagai gantinya.
  • Kompatibel dengan OpenAI
  • DashScope
  • Python
  • Node.js
  • HTTP

Kode contoh

import os
from openai import OpenAI

# Inisialisasi klien OpenAI dan konfigurasikan layanan DashScope Alibaba Cloud
client = OpenAI(
    # Kunci API bervariasi menurut Wilayah. Untuk mendapatkan Kunci API, lihat https://www.alibabacloud.com/help/en/model-studio/get-api-key
    # Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan kunci API Model Studio Anda: api_key="sk-xxx",
    api_key=os.getenv("DASHSCOPE_API_KEY"),  # Baca Kunci API dari variabel lingkungan
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

# Tentukan daftar alat yang tersedia
tools = [
    # Alat 1: Dapatkan waktu saat ini
    {
        "type": "function",
        "function": {
            "name": "get_current_time",
            "description": "Berguna saat Anda ingin mengetahui waktu saat ini.",
            "parameters": {}  # Tidak ada parameter yang diperlukan
        }
    },
    # Alat 2: Dapatkan cuaca di kota tertentu
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Berguna saat Anda ingin menanyakan cuaca di kota tertentu.",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "Sebuah kota atau distrik, seperti Beijing, Hangzhou, atau Yuhang."
                    }
                },
                "required": ["location"]  # Parameter yang diperlukan
            }
        }
    }
]

messages = [{"role": "user", "content": input("Silakan masukkan pertanyaan Anda:")}]

# Contoh paket untuk model multimodal
# messages = [{
#     "role": "user",
#     "content": [
#              {"type": "image_url","image_url": {"url": "https://img.alicdn.com/imgextra/i4/O1CN014CJhzi20NOzo7atOC_!!6000000006837-2-tps-2048-1365.png"}},
#              {"type": "text", "text": "Berdasarkan lokasi pada gambar, bagaimana cuaca saat ini di sana?"}]
#     }]

completion = client.chat.completions.create(
    # Contoh ini menggunakan qwen3.8-max. Anda dapat menggantinya dengan model pemikiran mendalam lainnya.
    model="qwen3.8-max",
    messages=messages,
    extra_body={
        # Aktifkan pemikiran mendalam. Parameter ini tidak valid untuk model qwen3-30b-a3b-thinking-2507, qwen3-235b-a22b-thinking-2507, dan QwQ.
        "enable_thinking": True
    },
    tools=tools,
    parallel_tool_calls=True,
    stream=True,
    # Hapus komentar untuk mendapatkan informasi konsumsi token
    # stream_options={
    #     "include_usage": True
    # }
)

reasoning_content = ""  # Tentukan proses pemikiran yang lengkap
answer_content = ""     # Tentukan tanggapan yang lengkap
tool_info = []          # Simpan informasi pemanggilan alat
is_answering = False   # Tentukan apakah proses pemikiran telah berakhir dan tanggapan telah dimulai
print("="*20+"Proses Pemikiran"+"="*20)
for chunk in completion:
    if not chunk.choices:
        # Proses informasi statistik Penggunaan
        print("\n"+"="*20+"Penggunaan"+"="*20)
        print(chunk.usage)
    else:
        delta = chunk.choices[0].delta
        # Proses proses pemikiran AI (chain of thought)
        if hasattr(delta, 'reasoning_content') and delta.reasoning_content is not None:
            reasoning_content += delta.reasoning_content
            print(delta.reasoning_content,end="",flush=True)  # Keluarkan proses pemikiran secara real time

        # Proses konten tanggapan akhir
        else:
            if not is_answering:  # Cetak judul saat memasuki fase tanggapan untuk pertama kalinya
                is_answering = True
                print("\n"+"="*20+"Konten Tanggapan"+"="*20)
            if delta.content is not None:
                answer_content += delta.content
                print(delta.content,end="",flush=True)  # Alirkan konten tanggapan

            # Proses informasi pemanggilan alat (mendukung pemanggilan alat paralel)
            if delta.tool_calls is not None:
                for tool_call in delta.tool_calls:
                    index = tool_call.index  # Indeks pemanggilan alat, untuk pemanggilan paralel

                    # Perluas daftar penyimpanan informasi alat secara dinamis
                    while len(tool_info) <= index:
                        tool_info.append({})

                    # Kumpulkan ID pemanggilan alat (untuk pemanggilan fungsi berikutnya)
                    if tool_call.id:
                        tool_info[index]['id'] = tool_info[index].get('id', '') + tool_call.id

                    # Kumpulkan nama fungsi (untuk perutean berikutnya ke fungsi tertentu)
                    if tool_call.function and tool_call.function.name:
                        tool_info[index]['name'] = tool_info[index].get('name', '') + tool_call.function.name

                    # Kumpulkan parameter fungsi (format string JSON, memerlukan penguraian berikutnya)
                    if tool_call.function and tool_call.function.arguments:
                        tool_info[index]['arguments'] = tool_info[index].get('arguments', '') + tool_call.function.arguments

print(f"\n"+"="*19+"Informasi Pemanggilan Alat"+"="*19)
if not tool_info:
    print("Tidak ada pemanggilan alat")
else:
    print(tool_info)

Hasil pengembalian

Masukkan "Cuaca di empat kota metropolitan" untuk mendapatkan hasil berikut:
====================Proses Berpikir====================
Baiklah, pengguna bertanya tentang cuaca di empat kota metropolitan. Pertama, saya perlu mengklarifikasi kota metropolitan mana yang dimaksud. Menurut pembagian administratif Tiongkok, kota metropolitan mencakup Beijing, Shanghai, Tianjin, dan Chongqing. Jadi pengguna ingin mengetahui kondisi cuaca di keempat kota ini.

Selanjutnya, saya perlu memeriksa alat yang tersedia. Alat yang disediakan mencakup fungsi get_current_weather, yang mengambil parameter lokasi bertipe string. Setiap kota perlu ditanyakan secara terpisah karena fungsi hanya dapat menanyakan satu lokasi dalam satu waktu. Oleh karena itu, saya perlu memanggil fungsi ini sekali untuk setiap kota metropolitan.

Kemudian, saya perlu mempertimbangkan cara menghasilkan pemanggilan alat yang benar. Setiap pemanggilan harus mencakup nama kota sebagai parameter. Misalnya, pemanggilan pertama untuk Beijing, kedua untuk Shanghai, dan seterusnya. Saya perlu memastikan nama parameter adalah `location` dan nilainya adalah nama kota yang benar.

Juga, pengguna mungkin menginginkan informasi cuaca untuk setiap kota, jadi saya perlu memastikan setiap pemanggilan fungsi benar. Ini mungkin memerlukan empat pemanggilan berturut-turut, satu untuk setiap kota. Namun, berdasarkan aturan penggunaan alat, mungkin perlu ditangani dalam beberapa langkah, atau beberapa pemanggilan mungkin dihasilkan sekaligus. Tetapi menurut contoh, tampaknya hanya satu fungsi yang dipanggil dalam satu waktu, jadi mungkin perlu dilakukan langkah demi langkah.

Akhirnya, saya perlu mengonfirmasi apakah ada faktor lain yang perlu dipertimbangkan, seperti apakah parameter sudah benar, nama kota akurat, dan apakah saya perlu menangani situasi error yang mungkin terjadi, seperti kota tidak ada atau API tidak tersedia. Tetapi untuk saat ini, empat kota metropolitan sudah jelas, jadi seharusnya tidak masalah.
====================Konten Respons====================

===================Informasi Pemanggilan Alat===================
[{'id': 'call_767af2834c12488a8fe6e3', 'name': 'get_current_weather', 'arguments': '{"location": "Beijing"}'}, {'id': 'call_2cb05a349c89437a947ada', 'name': 'get_current_weather', 'arguments': '{"location": "Shanghai"}'}, {'id': 'call_988dd180b2ca4b0a864ea7', 'name': 'get_current_weather', 'arguments': '{"location": "Tianjin"}'}, {'id': 'call_4e98c57ea96a40dba26d12', 'name': 'get_current_weather', 'arguments': '{"location": "Chongqing"}'}]

Tayang

Uji akurasi pemanggilan alat

  • Bangun sistem evaluasi: Buat set data uji yang mencerminkan skenario bisnis dunia nyata dan definisikan metrik evaluasi yang jelas, seperti akurasi pemilihan alat, akurasi ekstraksi parameter, dan tingkat keberhasilan end-to-end.
  • Optimalkan prompt Berdasarkan masalah yang diidentifikasi selama pengujian, seperti pemilihan alat atau parameter yang salah, Anda dapat mengoptimalkan prompt sistem, deskripsi alat, dan deskripsi parameter.
  • Tingkatkan model Jika pengaturan prompt gagal meningkatkan kinerja, meningkatkan ke versi model yang lebih kuat, seperti qwen3.6-plus, adalah metode yang paling langsung dan efektif.

Kontrol dinamis jumlah alat

Saat aplikasi mengintegrasikan puluhan bahkan ratusan alat, menyediakan semuanya ke model dapat menyebabkan masalah berikut:
  • Penurunan kinerja: Kesulitan model dalam memilih alat yang benar dari kumpulan alat yang besar meningkat secara dramatis.
  • Biaya dan latensi: Banyak deskripsi alat akan mengonsumsi sejumlah besar token input, yang menyebabkan peningkatan biaya dan respons yang lebih lambat.
Solusi: Tambahkan lapisan routing/pengambilan alat sebelum memanggil model. Lapisan ini menyaring pustaka alat berdasarkan kueri pengguna untuk menyediakan subset kecil alat yang relevan ke model. Metode utama untuk mengimplementasikan routing alat:
  • Pengambilan semantik Konversi deskripsi alat (description) menjadi vektor menggunakan model penyematan dan simpan di database vektor. Saat pengguna mengirimkan kueri, Anda dapat melakukan pencarian kemiripan vektor pada vektor kueri untuk mengingat K alat teratas yang paling relevan.
  • Pengambilan hibrid Metode ini menggabungkan pencocokan kabur dari pengambilan semantik dengan pencocokan eksak dari kata kunci tradisional atau tag metadata. Untuk melakukan ini, tambahkan field tags atau keywords ke alat. Selama pengambilan, melakukan pencarian vektor dan penyaringan kata kunci secara bersamaan dapat secara signifikan meningkatkan akurasi recall, terutama untuk skenario frekuensi tinggi atau spesifik.
  • Router LLM ringan Untuk logika routing yang lebih kompleks, Anda dapat menggunakan model yang lebih kecil, lebih cepat, dan lebih murah, seperti Qwen-Flash, sebagai model router. Tugas model ini adalah mengeluarkan daftar nama alat yang relevan berdasarkan kueri pengguna.
Saran praktis
  • Jaga set kandidat tetap ringkas: Terlepas dari metode yang digunakan, kami merekomendasikan menyediakan tidak lebih dari 20 alat ke model utama. Ini memberikan keseimbangan optimal antara beban kognitif model, biaya, latensi, dan akurasi.
  • Strategi penyaringan berlapis: Anda dapat membangun strategi routing berbentuk corong. Misalnya, Anda dapat terlebih dahulu menggunakan pencocokan aturan atau kata kunci berbiaya rendah untuk menyaring alat yang jelas tidak relevan. Kemudian, Anda dapat melakukan pengambilan semantik pada alat yang tersisa untuk meningkatkan efisiensi dan kualitas.

Prinsip keamanan alat

Saat memberikan kemampuan eksekusi alat ke LLM, keamanan adalah pertimbangan utama. Prinsip intinya adalah hak istimewa minimal dan konfirmasi manusia.
  • Prinsip hak istimewa minimal: Set alat yang disediakan ke model harus secara ketat mematuhi prinsip hak istimewa minimal. Secara default, alat harus read-only, seperti alat untuk menanyakan cuaca atau mencari dokumen. Hindari memberikan izin "write" apa pun yang melibatkan perubahan status atau operasi sumber daya.
  • Isolasi alat berbahaya: Jangan berikan alat berbahaya secara langsung ke LLM, seperti alat untuk mengeksekusi kode arbitrer (code interpreter), mengoperasikan sistem file (fs.delete), melakukan operasi hapus atau perbarui database (db.drop_table), atau menangani transaksi keuangan (payment.transfer).
  • Keterlibatan manusia: Tinjauan manual dan proses konfirmasi diperlukan untuk semua operasi berhak istimewa tinggi atau tidak dapat dibatalkan. Model dapat menghasilkan permintaan operasi, tetapi tombol "execute" akhir harus diklik oleh pengguna manusia. Misalnya, model dapat menyiapkan email, tetapi pengguna harus mengonfirmasi operasi pengiriman.

Optimasi pengalaman pengguna

Proses pemanggilan fungsi melibatkan beberapa langkah, dan masalah pada langkah apa pun dapat berdampak negatif pada pengalaman pengguna.

Atasi kegagalan eksekusi alat

Kegagalan eksekusi alat umum terjadi. Anda dapat mengadopsi strategi berikut:
  • Upaya maksimum: Tetapkan batas upaya ulang yang wajar, seperti 3, untuk menghindari waktu tunggu pengguna yang lama atau pemborosan sumber daya sistem akibat kegagalan berkelanjutan.
  • Berikan respons cadangan: Jika upaya ulang habis atau ditemui kesalahan yang tidak dapat diselesaikan, kembalikan prompt yang jelas dan ramah kepada pengguna, seperti: "Maaf, saya tidak dapat menemukan informasi yang relevan saat ini. Layanan mungkin sedang sibuk. Silakan coba lagi nanti."

Atasi latensi pemrosesan

Latensi tinggi dapat mengurangi kepuasan pengguna. Anda dapat mengimplementasikan optimasi di frontend dan backend.
  • Tetapkan timeout: Tetapkan timeout yang independen dan wajar untuk setiap langkah proses pemanggilan fungsi. Jika terjadi timeout, operasi harus segera dihentikan dan umpan balik diberikan kepada pengguna.
  • Berikan umpan balik instan: Saat pemanggilan fungsi dimulai, kami merekomendasikan menampilkan prompt pada antarmuka, seperti "Menanyakan cuaca untuk Anda..." atau "Mencari informasi yang relevan...". Ini memberikan umpan balik real-time kepada pengguna tentang kemajuan.

Penagihan

Selain token dalam array messages, deskripsi alat juga ditagih sebagai token input.
Kami merekomendasikan meneruskan informasi alat ke model bahasa besar (LLM) menggunakan parameter tools, seperti yang dijelaskan dalam bagian Cara menggunakan. Untuk meneruskan informasi alat melalui Pesan Sistem, gunakan templat prompt dalam kode berikut untuk kinerja model optimal:
  • Kompatibel dengan OpenAI
  • DashScope
  • Python
  • Node.js

Kode contoh

import os
from openai import OpenAI
import json

client = OpenAI(
    // Kunci API berbeda-beda berdasarkan wilayah. Untuk mendapatkan Kunci API, lihat https://www.alibabacloud.com/help/en/model-studio/get-api-key
    // Jika Anda belum mengonfigurasi variabel lingkungan, ganti baris berikut dengan Kunci API Model Studio Anda: api_key="sk-xxx",
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    // Wilayah Singapura. Ganti {WorkspaceId} dengan ID Ruang Kerja aktual Anda. URL berbeda-beda berdasarkan wilayah.
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

// Prompt Sistem kustom, yang dapat dimodifikasi sesuai kebutuhan Anda
custom_prompt = "Anda adalah asisten cerdas yang bertanggung jawab untuk memanggil berbagai alat untuk membantu pengguna menyelesaikan masalah. Anda dapat memilih alat yang sesuai dan memanggilnya dengan benar berdasarkan kebutuhan pengguna."

tools = [
    // Alat 1: Dapatkan waktu saat ini
    {
        "type": "function",
        "function": {
            "name": "get_current_time",
            "description": "Berguna saat Anda ingin mengetahui waktu saat ini.",
            "parameters": {}
        }
    },
    // Alat 2: Dapatkan cuaca di kota tertentu
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Berguna saat Anda ingin menanyakan cuaca di kota tertentu.",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "Kota atau distrik, seperti Beijing, Hangzhou, atau Yuhang."
                    }
                },
                "required": ["location"]
            }
        }
    }
]

// Iterasi melalui daftar alat untuk membangun deskripsi untuk setiap alat
tools_descriptions = []
for tool in tools:
    tool_json = json.dumps(tool, ensure_ascii=False)
    tools_descriptions.append(tool_json)

// Gabungkan semua deskripsi alat menjadi satu string
tools_content = "\n".join(tools_descriptions)

system_prompt = f"""{custom_prompt}

# Alat

Anda dapat memanggil satu atau beberapa fungsi untuk membantu kueri pengguna.

Anda diberikan tanda tangan fungsi dalam tag XML <tools></tools>:
<tools>
{tools_content}
</tools>

Untuk setiap pemanggilan fungsi, kembalikan objek json dengan nama fungsi dan argumen dalam tag XML <tool_call></tool_call>:
<tool_call>
{{"name": <function-name>, "arguments": <args-json-object>}}
</tool_call>"""

messages = [
    {"role": "system", "content": system_prompt},
    {"role": "user", "content": "Jam berapa sekarang?"}
]

completion = client.chat.completions.create(
    model="qwen3.8-max",
    extra_body={"enable_thinking": False},
    messages=messages,
)
print(completion.model_dump_json())
Setelah menjalankan kode di atas, Anda dapat menggunakan parser XML untuk mengekstrak informasi pemanggilan alat—termasuk nama fungsi dan parameter input—dari antara tag <tool_call> dan </tool_call>.

Kode error

Jika panggilan model gagal dan mengembalikan pesan error, lihat Kode Error untuk menyelesaikan masalah.
Rencana Token (Team Edition)
Model playground
Statistik dan Pemantauan
Asset Center
Dukungan layanan