برنامج تعليمي: استدعاء الوظائف باستخدام واجهة برمجة تطبيقات Gemini


يُسهّل استدعاء الدوال عليك الحصول على مخرجات البيانات المنظَّمة من النماذج التوليدية. ويمكنك بعد ذلك استخدام هذه المخرجات لطلب واجهات برمجة تطبيقات أخرى وعرض بيانات الاستجابة ذات الصلة للنموذج. بعبارة أخرى، يساعدك استدعاء الوظيفة على ربط النماذج التوليدية بالأنظمة الخارجية، بحيث يتضمن المحتوى الذي يتم إنشاؤه أحدث المعلومات ودقتها.

يمكنك تقديم نماذج Gemini مع أوصاف للدوال. هذه هي الدوال التي تكتبها بلغة تطبيقك (أي أنها ليست دوال Google Cloud). قد يطلب منك النموذج استدعاء دالة وإعادة إرسال النتيجة لمساعدة النموذج في التعامل مع استعلامك.

اطّلِع على مقدّمة حول استدعاء الدوال البرمجية لمعرفة المزيد من المعلومات إذا لم يسبق لك ذلك.

إعداد مشروعك

قبل استدعاء واجهة برمجة تطبيقات Gemini، عليك إعداد مشروع Xcode الذي يتضمّن إعداد مفتاح واجهة برمجة التطبيقات، وإضافة حزمة SDK إلى مشروع Xcode وإعداد النموذج.

إعداد استدعاء الدالة

في هذا البرنامج التعليمي، ستجعل النموذج يتفاعل مع واجهة برمجة تطبيقات تبادل العملات الافتراضية التي تدعم المعلمات التالية:

المَعلمة النوع مطلوبة الوصف
currencyFrom سلسلة نعم العملة المطلوب التحويل منها
currencyTo سلسلة نعم العملة المطلوب التحويل إليها

مثال على طلب بيانات من واجهة برمجة التطبيقات

{
  "currencyFrom": "USD",
  "currencyTo": "SEK"
}

مثال على ردّ من واجهة برمجة التطبيقات

{
  "base": "USD",
  "rates": {"SEK": 0.091}
}

الخطوة 1: إنشاء الدالة التي تنشئ طلب البيانات من واجهة برمجة التطبيقات

إذا لم تكن قد فعلت ذلك بالفعل، فابدأ بإنشاء الدالة التي تنشئ طلب واجهة برمجة تطبيقات.

لأغراض التوضيح في هذا البرنامج التعليمي، بدلاً من إرسال طلب فعلي من واجهة برمجة التطبيقات، ستعرض قيمًا ذات ترميز ثابت بالتنسيق نفسه الذي تعرضه واجهة برمجة التطبيقات الفعلية.

func makeAPIRequest(currencyFrom: String,
                    currencyTo: String) -> JSONObject {
  // This hypothetical API returns a JSON such as:
  // {"base":"USD","rates":{"SEK": 0.091}}
  return [
    "base": .string(currencyFrom),
    "rates": .object([currencyTo: .number(0.091)]),
  ]
}

الخطوة 2: إنشاء تعريف دالة

أنشئ تعريف الدالة الذي ستنتقل إلى النموذج التوليدي (الخطوة التالية في هذا البرنامج التعليمي).

ننصحك بتضمين أكبر قدر ممكن من التفاصيل في أوصاف الدالة والمَعلمات. ويستخدم النموذج التوليدي هذه المعلومات لتحديد الدالة التي يجب اختيارها وكيفية توفير قيم للمعلَمات في استدعاء الدالة.

let getExchangeRate = FunctionDeclaration(
  name: "getExchangeRate",
  description: "Get the exchange rate for currencies between countries",
  parameters: [
    "currencyFrom": Schema(
      type: .string,
      description: "The currency to convert from."
    ),
    "currencyTo": Schema(
      type: .string,
      description: "The currency to convert to."
    ),
  ],
  requiredParameters: ["currencyFrom", "currencyTo"]
)

الخطوة 3: تحديد تعريف الدالة أثناء إعداد النموذج

يمكنك تحديد تعريف الدالة عند إعداد النموذج التوليدي عن طريق ضبط معلَمة tools للنموذج:

// Use a model that supports function calling, like Gemini 1.0 Pro.
// See "Supported models" in the "Introduction to function calling" page.
let generativeModel = GenerativeModel(
  name: "gemini-1.0-pro",
  apiKey: apiKey,
  // Specify the function declaration.
  tools: [Tool(functionDeclarations: [getExchangeRate])]
)

الخطوة 4: إنشاء استدعاء دالة

يمكنك الآن المطالبة بالنموذج باستخدام الدالة المحددة.

والطريقة الموصى بها لاستخدام استدعاء الدالة هي من خلال واجهة الدردشة، نظرًا لأن استدعاءات الوظائف تتناسب بشكل جيد مع بنية الدردشة المتعددة الأدوار.

let chat = generativeModel.startChat()

let prompt = "How much is 50 US dollars worth in Swedish krona?"

// Send the message to the generative model
let response1 = try await chat.sendMessage(prompt)

// Check if the model responded with a function call
guard let functionCall = response1.functionCalls.first else {
  fatalError("Model did not respond with a function call.")
}
// Print an error if the returned function was not declared
guard functionCall.name == "getExchangeRate" else {
  fatalError("Unexpected function called: \(functionCall.name)")
}
// Verify that the names and types of the parameters match the declaration
guard case let .string(currencyFrom) = functionCall.args["currencyFrom"] else {
  fatalError("Missing argument: currencyFrom")
}
guard case let .string(currencyTo) = functionCall.args["currencyTo"] else {
  fatalError("Missing argument: currencyTo")
}

// Call the hypothetical API
let apiResponse = makeAPIRequest(currencyFrom: currencyFrom, currencyTo: currencyTo)

// Send the API response back to the model so it can generate a text response that can be
// displayed to the user.
let response = try await chat.sendMessage([ModelContent(
  role: "function",
  parts: [.functionResponse(FunctionResponse(
    name: functionCall.name,
    response: apiResponse
  ))]
)])

// Log the text response.
guard let modelResponse = response.text else {
  fatalError("Model did not respond with text.")
}
print(modelResponse)