1. معرفی فراخوانی تابع

در مدل GPT، فراخوانی تابع به معنای ارائه توابع توصیفی به مدل از طریق یک رابط برنامه‌نویسی است، که امکان انتخاب هوشمندانه و خروجی دادن یک شیء JSON شامل پارامترها برای فراخوانی یک یا چند تابع را فراهم می‌کند. لازم به ذکر است که رابط کامل‌سازی گفتگو API به‌صورت مستقیم تابعی را اجرا نمی‌کند، بلکه JSON را تولید می‌کند که می‌تواند برای اجرای توابع در کد استفاده شود.

به زبان ساده، ویژگی فراخوانی تابع شامل ارائه مجموعه‌ای از تعاریف توابع (شامل شرح‌های تابع و شرح‌های پارامتر) به مدل GPT می‌شود. سپس مدل تصمیم می‌گیرد کدام تابع را براساس پرسش کاربر فراخوانی کند. از آنجایی که مدل نمی‌تواند توابع خارجی را اجرا کند، فقط می‌تواند با درخواستی برای فراخوانی تابع (شامل پارامترهای فراخوانی تابع) پاسخ دهد. پس از دریافت نتیجه درخواست مدل، برنامه ما فراخوانی تابع را به‌صورت محلی اجرا می‌کند. نتیجه فراخوانی تابع سپس با پرسش ترکیب شده و به مدل برای پردازش‌های بعدی ارسال می‌شود تا نتیجه نهایی را به کاربر برگرداند.

2. سناریوهای کاربردی فراخوانی تابع

در زیر چند مثال از کاربردهای عملی آن آمده است:

  • ایجاد یک دستیار برای پاسخ به سوالات با فراخوانی API‌های خارجی، مانند تعریف توابع مانند send_email(to: string, body: string) یا get_current_weather(location: string, unit: 'celsius' | 'fahrenheit').
  • تبدیل زبان طبیعی به فراخوانی‌های API، به‌عنوان مثال تبدیل "کی مشتریان برتر من هستند؟" به get_customers(min_revenue: int, created_before: string, limit: int) و سپس انجام یک فراخوانی داخلی API.
  • استخراج داده‌های ساختاری از متن، به‌عنوان مثال تعریف توابع مانند extract_data(name: string, birthday: string) یا sql_query(query: string).

با استفاده از ویژگی فراخوانی تابع، می‌توانیم عامل‌های هوش مصنوعی را پیاده‌سازی کنیم که با سیستم‌ها و پایگاه‌داده‌های محلی ما تعامل داشته و مثلاً به عنوان یک هوش مصنوعی، آب وجودی، بررسی قیمت‌های سهام، سفارش غذا یا رزرو بلیط انجام دهند.

3. مدل‌هایی که از فراخوانی تابع پشتیبانی می‌کنند

همه نسخه‌های مدل با داده‌های فراخوانی تابع آموزش دیده نشده است. در حال حاضر، مدل‌هایی که از فراخوانی تابع پشتیبانی می‌کنند به‌شرح زیر هستند: gpt-4, gpt-4-turbo-preview, gpt-4-0125-preview, gpt-4-1106-preview, gpt-4-0613, gpt-3.5-turbo, gpt-3.5-turbo-1106 و gpt-3.5-turbo-0613.

علاوه بر این، مدل‌های gpt-4-turbo-preview, gpt-4-0125-preview, gpt-4-1106-preview و gpt-3.5-turbo-1106 از فراخوانی تابع موازی پشتیبانی می‌کنند که امکان اجرای چند فراخوانی تابع به‌طور همزمان را فراهم می‌کند و می‌توانند این فراخوانی‌های تابع را به‌صورت همزمان انجام دهند تا نتایج موثر و کارآمدی تولید کنند.

توجه: ریسک پتانسیلی مرتبط با ویژگی فراخوانی تابع این است که ممکن است منجر به تولید پارامترهای اشتباه (مانند پارامترهای هیولا) توسط مدل شود. بنابراین، قبل از انجام هرگونه فعالیتی که بر تصمیم‌گیری‌های واقعی (مانند ارسال ایمیل، انتشار آنلاین، خرید و غیره) تأثیر می‌گذارد، منطقی است که یک فرایند تأیید کاربر را در سطح محصول شامل کنیم تا اطمینان حاصل کنیم که توابع فقط پس از تأیید کاربر اجرا شوند.

4. نمونه‌های فراخوانی تابع

4.1. نمونه پایتون

پیاده‌سازی فراخوانی تابع در پلتفرم OpenAI معمولاً شامل مراحل پایه زیر است. در زیر فرآیند کامل با یک مثال کد پایتون شرح داده شده است، با تمرکز بر روی درخواست هواشناسی.

گام 1: آماده‌سازی توابع فراخوانی‌پذیر و تعاریف توابع برای مدل

در ابتدا، نیاز داریم تابعی را که توسط مدل GPT فراخوانی شود تعریف کنیم. این معمولاً به معنای آماده‌کردن تابعی است که می‌تواند عملیات خاصی براساس پارامترهای ورودی انجام دهد، مانند ارتباط با یک API شخص ثالث.

import json

def get_current_weather(location, unit="fahrenheit"):
    return json.dumps({
        "location": location, 
        "temperature": "18", 
        "unit": unit
    })

مرحله ۲: فراخوانی مدل براساس پارامتر پرس و جو و ابزارها

بعداز آن، ما باید مدل GPT را از طریق API تکمیل گفتگو فراخوانی کرده و پارامتر query کاربر (برای مثال، "هوا چگونه است") و همچنین پارامتر tools که شامل توضیحات تابع get_current_weather است که به تازگی تعریف کرده‌ایم را وارد کنیم.

from openai import OpenAI

client = OpenAI()

tools = [{
    "type": "function",
    "function": {
        "name": "get_current_weather",
        "description": "دریافت وضعیت هوا فعلی برای یک مکان داده شده",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "نام شهر، به عنوان مثال: 'سان فرانسیسکو، کالیفرنیا'"
                },
                "unit": {
                    "type": "string",
                    "enum": ["سلسیوس", "فارنهایت"]
                }
            },
            "required": ["location"]
        }
    }
}]

response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "وضعیت هوای فعلی در سان فرانسیسکو چیست؟"}],
    tools=tools
)

مرحله ۳: اجرای تابع به صورت محلی

نتیجه‌ای که توسط مدل برگشت داده می‌شود شامل اطلاعاتی درباره تابع است که مدل می‌خواهد فراخوانی کند که معمولاً در پارامتر پاسخ tool_calls قرار دارد. سپس می‌توانیم بر اساس اطلاعات فراخوانی تابع موجود در پارامتر tool_calls فراخوانی مربوط به تابع مورد نظر را به صورت محلی اجرا کنیم.

tool_calls = response.choices[0].message.tool_calls

if tool_calls:
    arguments = json.loads(tool_calls[0].function.arguments)
    weather_info = get_current_weather(**arguments)
    print(weather_info) # در اینجا می‌توانیم اطلاعات هوا که توسط فراخوانی تابع به دست آمده است را ببینیم

مرحله ۴: دوباره فراخوانی مدل با نتیجه بازگشتی تابع

حالا ما می‌توانیم نتیجه بازگشتی تابع را به عنوان یک پیام جدید به مدل ارسال کنیم، تا مدل بتواند این نتایج را پردازش کرده و یک پاسخ منطبق با توضیحات کاربر ایجاد کند.

follow_up_response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "user", "content": "وضعیت هوای فعلی در سان فرانسیسکو چیست؟"},
        {"role": "function", "name": "get_current_weather", "content": weather_info}
    ],
    tools=tools
)

توضیح:

در مثال بالا، محتوای بازگشتی تابع از طریق پیام تابع به مدل GPT ارسال می‌شود به این شکل:

{"role": "function", "name": "get_current_weather", "content": weather_info}

در عمل، شما همچنین می‌توانید محتوای بازگشتی تابع را به عنوان محتوای مرجع در تنبیه پیام سیستمی سیستمی قرار دهید تا هنگام پاسخ دادن به سوالات از آنجا اشاره شود.

مرحله ۵: به دست آوردن پاسخ نهایی از مدل

سرانجام، ما می‌توانیم پاسخ نهایی مدل را به دست آورده و به کاربر ارائه دهیم. در این مرحله، مدل بر اساس اطلاعات هوا که ارائه کرده‌ایم یک پاسخ منطبق با کاربر ارائه خواهد داد.

final_output = follow_up_response.choices[0].message.content
print(final_output) # این خروجی اطلاعات هوایی است که می‌خواهیم به کاربر نشان دهیم

با پیروی از مراحل فوق، ما یک مثال کامل از پرس و جو هوا با استفاده از مدل GPT و فراخوانی توابع را تکمیل کرده‌ایم.

۴.۲. توضیح تابع فراخوانی تابع

4.2.1 معنای فیلدهای پارامتر 'ابزارها'

در هنگام فراخوانی یک تابع، شما باید اطلاعات مربوط به تابع را در پارامتر ابزارها تعریف کنید. پارامتر ابزارها یک آرایه است که شامل تعریف‌های چندین تابع می‌باشد و هر تعریف تابع شامل فیلدهای زیر می‌باشد:

  1. نوع: این فیلد نوع ابزار را نماینده می‌شود. در یک فراخوانی تابع، این فیلد باید به "تابع" تنظیم شود.
  2. تابع: این فیلد شامل اطلاعات دقیق درباره تابع می‌باشد و یک شیئ است که شامل فیلدهای خاص زیر می‌باشد:
    • نام: نام تابع که یک رشته می‌باشد.
    • توضیحات: توضیحات درباره هدف تابع که می‌تواند به مدل کمک کند تا پارامترهایی تولید کند که با انتظارات کاربر مطابقت داشته باشند.
    • پارامترها: شرح تعریف‌های پارامتر تابع است و یک شیئ است که شامل زیر-فیلدهای زیر می‌باشد:
      • نوع: تعریف نوع پارامتر که بیشتر باید به "اشیاء" تنظیم شود.
      • خصوصیت‌ها: تعریف‌های خاصی از هر پارامتر تابع است، که هر تعریف پارامتر شامل یک شیئ است که به طور معمول شامل زیر-فیلدهای خاصی زیر می‌باشد:
        • نوع: نوع داده‌ای پارامتر (مانند "رشته"، "صحیح"، "منطقی"، و غیره).
        • توضیحات: توضیحات پارامتر برای کمک به مدل درک هدف آن.
        • نشانه‌گان (اختیاری): وقتی نوع به "رشته" تنظیم می‌شود، فیلد نشانه‌گان می‌تواند یک آرایه از رشته‌ها باشد که مجموعه‌ای از مقادیر معتبر را نمایند.
      • مورد نیاز: یک آرایه از رشته‌ها که شامل اسامی پارامترهای مورد نیاز می‌باشد.

4.2.2 مثال‌های تعریف ابزارها

حالا بیایید چند مثال از تعریف‌های ابزارها ارائه دهیم تا به درک نحوه استفاده از هر فیلد کمک کنیم.

مثال 1: دریافت اطلاعات هوای فعلی

{
    "type": "function",
    "function": {
        "name": "دریافت_اطلاعات_هوای_فعلی",
        "description": "دریافت اطلاعات هوای فعلی برای مکان مشخص",
        "parameters": {
            "type": "object",
            "properties": {
                "مکان": {
                    "type": "string",
                    "description": "شهری که نیاز است برای آن هوا پرسیده شود، مانند 'سان فرانسیسکو، کالیفرنیا'"
                },
                "واحد": {
                    "type": "string",
                    "enum": ["سانتی‌گراد", "فارنهایت"],
                    "description": "واحد دما، 'سانتی‌گراد' برای سلسیوس و 'فارنهایت' برای فارنهایت"
                }
            },
            "required": ["مکان", "واحد"]
        }
    }
}

در مثال بالا، ما یک تابع به نام دریافت_اطلاعات_هوای_فعلی برای دریافت هوای فعلی یک مکان مشخص تعریف کرده‌ایم. پارامترها شامل مکان و واحد هستند، جایی که واحد دو مقدار معتبر دارد: "سانتی‌گراد" (درجه سلسیوس) و "فارنهایت" (درجه فارنهایت).

مثال 2: یافتن آلبوم‌های هنرمند خاص

{
    "type": "function",
    "function": {
        "name": "یافتن_آلبوم‌های_هنرمند",
        "description": "یافتن تمامی آلبوم‌های یک هنرمند خاص",
        "parameters": {
            "type": "object",
            "properties": {
                "نام_هنرمند": {
                    "type": "string",
                    "description": "نام هنرمند"
                }
            },
            "required": ["نام_هنرمند"]
        }
    }
}

در این مثال، ما یک تابع به نام یافتن_آلبوم‌های_هنرمند برای یافتن تمامی آلبوم‌های یک هنرمند خاص ایجاد کرده‌ایم. این تابع تنها نیاز به یک پارامتر دارد: نام_هنرمند (نام هنرمند).

4.3. مثالی از فراخوانی تابع درخواست HTTP

OpenAI یک API ارائه داده که از طریق پروتکل HTTP قابل دسترسی است. در زیر، نحوه استفاده از ویژگی فراخوانی تابع از طریق API HTTP را توضیح خواهیم داد. توسعه‌دهندگان زبان‌های برنامه‌نویسی دیگر می‌توانند به این مثال مراجعه نمایند.

4.3.1. مرحله 1: فراخوانی مدل با پرس و جو کاربر و اعلان تابع

در ابتدا، باید پرس و جو کاربر و لیست توابعی که پشتیبانی می‌کنیم را به مدل GPT ارسال کنیم تا مدل بتواند به طور خودکار تحلیل کند که کدام تابع را برای پاسخ به پرس و جو کاربر براساس سوال کاربر فراخوانی کند.

در مثال زیر، به GPT اعلام می‌کنیم که ما یک تابع get_current_weather داریم که می‌تواند برای یک شهر مشخص، اطلاعات هواشناسی را بازیابی کند.

curl --location 'https://api.aiproxy.io/v1/chat/completions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {OPENAI_KEY}' \
--data '{
    "model": "gpt-3.5-turbo",
    "messages": [
        {
            "role": "user",
            "content": "What's the weather like in Shanghai today?"
        }
    ],
    "tools": [
        {
            "type": "function",
            "function": {
                "name": "get_current_weather",
                "description": "Get the current weather information for the specified location",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The city for which weather needs to be queried, e.g. 'San Francisco, CA'"
                        },
                        "unit": {
                            "type": "string",
                            "enum": [
                                "celsius",
                                "fahrenheit"
                            ],
                            "description": "Temperature unit, 'celsius' for Celsius, 'fahrenheit' for Fahrenheit"
                        }
                    },
                    "required": [
                        "location",
                        "unit"
                    ]
                }
            }
        }
    ]
}'

توضیحات پارامتر درخواست:

{
    "model": "gpt-3.5-turbo", // مدل GPT برای فراخوانی
    "messages": [ // این لیست پیام‌ها برای GPT است، شامل پرس و جو کاربر می‌باشد
        {
            "role": "user",
            "content": "What's the weather like in Shanghai today?"
        }
    ],
    "tools": [
	  // این تعریف تابع شماست که به GPT از توابع موجود اطلاع می‌دهد
    ]
}

برای تعریف پارامتر tools به بخش 4.2.2 مراجعه کنید.

در پردازش عادی توسط مدل GPT، شما یک پاسخ API مشابه زیر دریافت خواهید کرد:

{
    "model": "gpt-3.5-turbo-0613",
    "object": "chat.completion",
    "usage": {
        "prompt_tokens": 122,
        "completion_tokens": 27,
        "total_tokens": 149
    },
    "id": "chatcmpl-8mL4hS4zNMocyR2ajKyAvSTcbNaao",
    "created": 1706531447,
    "choices": [
        {
            "index": 0,
            "delta": null,
            "message": {
                "role": "assistant",
                "tool_calls": [ // پارامتر tool_calls نمایانگر لیست توابعی است که GPT می‌خواهد فراخوانی کند
                    {
                        "id": "call_1iF09ttX1R9ESR18Ul2nLe1R",
                        "type": "function",
                        "function": {
                            "name": "get_current_weather",  // نشان می‌دهد که GPT می‌خواهد با فراخوانی تابع get_current_weather به پرس و جو کاربر پاسخ دهد
                            "arguments": "{\n  \"location\": \"Shanghai, China\",\n  \"unit\": \"celsius\"\n}" // این پارامتر ورودی برای فراخوانی تابع get_current_weather می‌باشد
                        }
                    }
                ]
            },
            "finish_reason": "tool_calls"
        }
    ]
}

4.3.2. مرحله 2: اجرای فراخوانی تابع محلی

از آنجا که مدل GPT خود نمی‌تواند فراخوانی‌های تابع خاص را اجرا کند و تنها به ما اطلاع می‌دهد که کدام تابع را می‌خواهد فراخوانی کند، برنامه‌ی محلی ما باید بر اساس پارامتر tool_calls که توسط مدل برگشت داده شده‌است، فراخوانی خاص تابع را اجرا کند. روش اجرای توابع محلی در زبان‌های برنامه‌نویسی مختلف متفاوت است. به عنوان مثال، در پایتون، می‌توانید به بخش قبل مراجعه کنید.

4.3.3. مرحله 3: بازخوانی مدل دوباره با نتیجه بازگشت تابع

زیرا فراخوانی تابع به صورت محلی اجرا می‌شود، ما باید نتیجه اجرای تابع و سوال کاربر را دوباره به مدل GPT منتقل کنیم تا پاسخ نهایی را بسازیم.

curl --location 'https://api.aiproxy.io/v1/chat/completions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer sk-Roc5MX1zEuVxiuaMaETV6wZ2jXcCehjUCzwP9AcNErUiwppQ' \
--data '{
    "model": "gpt-3.5-turbo",
    "messages": [
        {
            "role": "user",
            "content": "آب و هوای امروز شانگهای چطور است؟"
        },
        {
            "role": "function",
            "name": "get_current_weather",
            "content": "{\"city\":\"Shanghai\", \"temperature\":\"25 درجه سانتی‌گراد\"}"
        }
    ],
    "tools": [
        {
            "type": "function",
            "function": {
                "name": "get_current_weather",
                "description": "دریافت اطلاعات آب و هوای فعلی برای مکان مشخص شده",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "شهر برای جستجوی آب و هوا، مثلا 'San Francisco, CA'"
                        },
                        "unit": {
                            "type": "string",
                            "enum": [
                                "سانتی‌گراد",
                                "فارنهایت"
                            ],
                            "description": "واحد دما، 'سانتی‌گراد' برای سانتی‌گراد، 'فارنهایت' برای فارنهایت"
                        }
                    },
                    "required": [
                        "location",
                        "unit"
                    ]
                }
            }
        }
    ]
}'

توجه: درخواست فوق شامل یک پیام تابع اضافی است تا مدل GPT از مقدار بازگشتی تابع مطلع شود. GPT بر اساس اطلاعات بازگشت تابع به طور مستقیم به سوال کاربر پاسخ خواهد داد و دیگر تابع را فراخوانی نخواهد کرد.

پیام تابع نمایانگر مقدار بازگشت تابع است و به فرمت زیر است:

{
    "role": "function", // نوع پیام تابع است، نشان‌دهنده مقدار بازگشتی تابع get_current_weather است
    "name": "get_current_weather", // به GPT اطلاع می‌دهد که پیام فعلی مقدار بازگشتی تابع get_current_weather است
    "content": "{\"city\":\"Shanghai\",\"temperature\":\"25 درجه سانتی‌گراد\"}" // محتوای بازگشت تابع، می‌تواند به صورت JSON یا محتوای متنی دیگر باشد.
}

پاسخ نهایی تولید شده توسط GPT در زیر آمده است:

{
    "model": "gpt-3.5-turbo-0613",
    "object": "chat.completion",
    "usage": {
        "prompt_tokens": 144,
        "completion_tokens": 17,
        "total_tokens": 161
    },
    "id": "chatcmpl-8mLmvvKAjSql7rGF8fvQeddKhWYvr",
    "created": 1706534189,
    "choices": [
        {
            "index": 0,
            "delta": null,
            "message": {
                "role": "assistant",
                "content": "آب و هوای امروز در شانگهای 25 درجه سانتی‌گراد است."
            },
            "finish_reason": "stop"
        }
    ]
}