Bagikan melalui


Apa itu Plugin?

Plugin adalah komponen kunci dari Semantic Kernel. Jika Anda telah menggunakan plugin dari ekstensi ChatGPT atau Copilot di Microsoft 365, Anda sudah terbiasa dengannya. Dengan plugin, Anda dapat merangkum API yang ada ke dalam koleksi yang dapat digunakan oleh AI. Ini memungkinkan Anda untuk memberi AI Anda kemampuan untuk melakukan tindakan yang tidak akan dapat dilakukan sebaliknya.

Di balik layar, Kernel Semantik memanfaatkan fungsi memanggil, fitur asli dari sebagian besar LLM terbaru untuk memungkinkan LLM, melakukan perencanaan dan memanggil API Anda. Dengan panggilan fungsi, LLM dapat meminta (yaitu, memanggil) fungsi tertentu. Semantic Kernel kemudian melakukan marsekal permintaan ke fungsi yang sesuai di basis kode Anda dan mengembalikan hasilnya kembali ke LLM sehingga LLM dapat menghasilkan respons akhir.

Semantic Kernel Plugin

Tidak semua SDK AI memiliki konsep analog untuk plugin (sebagian besar hanya memiliki fungsi atau alat). Namun, dalam skenario perusahaan, plugin sangat berharga karena merangkum serangkaian fungsionalitas yang mencerminkan bagaimana pengembang perusahaan sudah mengembangkan layanan dan API. Plugin juga bekerja dengan baik dengan injeksi dependensi. Dalam konstruktor plugin, Anda dapat menyuntikkan layanan yang diperlukan untuk melakukan pekerjaan plugin (misalnya, koneksi database, klien HTTP, dll.). Ini sulit dicapai dengan SDK lain yang tidak memiliki plugin.

Anatomi plugin

Pada tingkat tinggi, plugin adalah sekelompok fungsi yang dapat diekspos ke aplikasi dan layanan AI. Fungsi dalam plugin kemudian dapat diorkestrasi oleh aplikasi AI untuk mencapai permintaan pengguna. Dalam Semantic Kernel, Anda dapat memanggil fungsi-fungsi ini secara otomatis dengan panggilan fungsi.

Nota

Di platform lain, fungsi sering disebut sebagai "alat" atau "tindakan". Di Kernel Semantik, kami menggunakan istilah "fungsi" karena biasanya didefinisikan sebagai fungsi asli di basis kode Anda.

Namun, hanya menyediakan fungsi, tidak cukup untuk membuat plugin. Untuk mendukung orkestrasi otomatis dengan panggilan fungsi, plugin juga perlu memberikan detail yang secara semantik menjelaskan bagaimana mereka berperilaku. Segala sesuatu dari input, output, dan efek samping fungsi perlu dijelaskan dengan cara yang dapat dipahami AI, jika tidak, AI tidak akan memanggil fungsi dengan benar.

Misalnya, plugin WriterPlugin sampel di sebelah kanan memiliki fungsi dengan deskripsi semantik yang menjelaskan apa yang dilakukan setiap fungsi. LLM kemudian dapat menggunakan deskripsi ini untuk memilih fungsi terbaik yang akan dipanggil untuk memenuhi permintaan pengguna.

Dalam gambar di sebelah kanan, LLM kemungkinan akan memanggil fungsi ShortPoem dan StoryGen untuk memenuhi permintaan pengguna berkat deskripsi semantik yang disediakan.

deskripsi semantik dalam plugin WriterPlugin

Mengimpor berbagai jenis plugin

Ada dua cara utama untuk mengimpor plugin ke Kernel Semantik: menggunakan kode asli atau menggunakan spesifikasi OpenAPI . Yang pertama memungkinkan Anda untuk menulis plugin di basis kode yang ada yang dapat memanfaatkan dependensi dan layanan yang sudah Anda miliki. Yang terakhir memungkinkan Anda mengimpor plugin dari spesifikasi OpenAPI, yang dapat dibagikan di berbagai bahasa dan platform pemrograman.

Di bawah ini kami memberikan contoh sederhana mengimpor dan menggunakan plugin asli. Untuk mempelajari selengkapnya tentang cara mengimpor berbagai jenis plugin ini, lihat artikel berikut:

Tips

Saat memulai, sebaiknya gunakan plugin kode asli. Saat aplikasi Anda matang, dan saat Anda bekerja di seluruh tim lintas platform, Anda mungkin ingin mempertimbangkan untuk menggunakan spesifikasi OpenAPI untuk berbagi plugin di berbagai bahasa dan platform pemrograman.

Berbagai jenis fungsi plugin

Dalam plugin, Anda biasanya akan memiliki dua jenis fungsi yang berbeda, yaitu yang mengambil data untuk augmentasi generasi pengambilan data (RAG) dan yang mengotomatiskan tugas. Meskipun setiap jenis secara fungsional sama, mereka biasanya digunakan secara berbeda dalam aplikasi yang menggunakan Semantic Kernel.

Misalnya, dengan fungsi penarikan data, Anda mungkin ingin menggunakan strategi seperti caching dan penggunaan model perantara yang lebih murah untuk meringkas, guna meningkatkan kinerja. Sedangkan dengan fungsi otomatisasi tugas, Anda mungkin ingin menerapkan proses persetujuan human-in-the-loop untuk memastikan bahwa tugas diselesaikan dengan benar.

Untuk mempelajari selengkapnya tentang berbagai jenis fungsi plugin, lihat artikel berikut:

Mulai menggunakan plugin

Menggunakan plugin dalam Semantic Kernel selalu merupakan proses tiga langkah:

  1. Tentukan plugin Anda
  2. Tambahkan plugin ke kernel Anda
  3. Dan kemudian panggil fungsi-fungsi plugin baik dalam prompt dengan menggunakan pemanggilan fungsi

Di bawah ini kami akan memberikan contoh tingkat tinggi tentang cara menggunakan plugin dalam Kernel Semantik. Lihat tautan di atas untuk informasi lebih rinci tentang cara membuat dan menggunakan plugin.

1) Tentukan plugin Anda

Cara term mudah untuk membuat plugin adalah dengan mendefinisikan kelas dan menganotasi metodenya dengan atribut KernelFunction. Ini memberi tahu Semantic Kernel bahwa ini adalah fungsi yang dapat dipanggil oleh AI atau direferensikan dalam masukan.

Anda juga dapat mengimpor plugin dari spesifikasi OpenAPI .

Di bawah ini, kita akan membuat plugin yang dapat mengambil status lampu dan mengubah keadaannya.

Tips

Karena sebagian besar LLM telah dilatih dengan Python untuk panggilan fungsi, disarankan untuk menggunakan snake case untuk nama fungsi dan nama properti bahkan jika Anda menggunakan C# atau Java SDK.

using System.ComponentModel;
using Microsoft.SemanticKernel;

public class LightsPlugin
{
   // Mock data for the lights
   private readonly List<LightModel> lights = new()
   {
      new LightModel { Id = 1, Name = "Table Lamp", IsOn = false, Brightness = 100, Hex = "FF0000" },
      new LightModel { Id = 2, Name = "Porch light", IsOn = false, Brightness = 50, Hex = "00FF00" },
      new LightModel { Id = 3, Name = "Chandelier", IsOn = true, Brightness = 75, Hex = "0000FF" }
   };

   [KernelFunction("get_lights")]
   [Description("Gets a list of lights and their current state")]
   public async Task<List<LightModel>> GetLightsAsync()
   {
      return lights
   }

   [KernelFunction("get_state")]
   [Description("Gets the state of a particular light")]
   public async Task<LightModel?> GetStateAsync([Description("The ID of the light")] int id)
   {
      // Get the state of the light with the specified ID
      return lights.FirstOrDefault(light => light.Id == id);
   }

   [KernelFunction("change_state")]
   [Description("Changes the state of the light")]
   public async Task<LightModel?> ChangeStateAsync(int id, LightModel LightModel)
   {
      var light = lights.FirstOrDefault(light => light.Id == id);

      if (light == null)
      {
         return null;
      }

      // Update the light with the new state
      light.IsOn = LightModel.IsOn;
      light.Brightness = LightModel.Brightness;
      light.Hex = LightModel.Hex;

      return light;
   }
}

public class LightModel
{
   [JsonPropertyName("id")]
   public int Id { get; set; }

   [JsonPropertyName("name")]
   public string Name { get; set; }

   [JsonPropertyName("is_on")]
   public bool? IsOn { get; set; }

   [JsonPropertyName("brightness")]
   public byte? Brightness { get; set; }

   [JsonPropertyName("hex")]
   public string? Hex { get; set; }
}
from typing import TypedDict, Annotated

class LightModel(TypedDict):
   id: int
   name: str
   is_on: bool | None
   brightness: int | None
   hex: str | None

class LightsPlugin:
   lights: list[LightModel] = [
      {"id": 1, "name": "Table Lamp", "is_on": False, "brightness": 100, "hex": "FF0000"},
      {"id": 2, "name": "Porch light", "is_on": False, "brightness": 50, "hex": "00FF00"},
      {"id": 3, "name": "Chandelier", "is_on": True, "brightness": 75, "hex": "0000FF"},
   ]

   @kernel_function
   async def get_lights(self) -> List[LightModel]:
      """Gets a list of lights and their current state."""
      return self.lights

   @kernel_function
   async def get_state(
      self,
      id: Annotated[int, "The ID of the light"]
   ) -> Optional[LightModel]:
      """Gets the state of a particular light."""
      for light in self.lights:
         if light["id"] == id:
               return light
      return None

   @kernel_function
   async def change_state(
      self,
      id: Annotated[int, "The ID of the light"],
      new_state: LightModel
   ) -> Optional[LightModel]:
      """Changes the state of the light."""
      for light in self.lights:
         if light["id"] == id:
               light["is_on"] = new_state.get("is_on", light["is_on"])
               light["brightness"] = new_state.get("brightness", light["brightness"])
               light["hex"] = new_state.get("hex", light["hex"])
               return light
      return None
public class LightsPlugin {

  // Mock data for the lights
  private final Map<Integer, LightModel> lights = new HashMap<>();

  public LightsPlugin() {
    lights.put(1, new LightModel(1, "Table Lamp", false));
    lights.put(2, new LightModel(2, "Porch light", false));
    lights.put(3, new LightModel(3, "Chandelier", true));
  }

  @DefineKernelFunction(name = "get_lights", description = "Gets a list of lights and their current state")
  public List<LightModel> getLights() {
    System.out.println("Getting lights");
    return new ArrayList<>(lights.values());
  }

  @DefineKernelFunction(name = "change_state", description = "Changes the state of the light")
  public LightModel changeState(
      @KernelFunctionParameter(name = "id", description = "The ID of the light to change") int id,
      @KernelFunctionParameter(name = "isOn", description = "The new state of the light") boolean isOn) {
    System.out.println("Changing light " + id + " " + isOn);
    if (!lights.containsKey(id)) {
      throw new IllegalArgumentException("Light not found");
    }

    lights.get(id).setIsOn(isOn);

    return lights.get(id);
  }
}

Perhatikan bahwa kami memberikan deskripsi untuk fungsi, dan parameter. Ini penting bagi AI untuk memahami apa yang dilakukan fungsi dan cara menggunakannya.

Tips

Jangan takut untuk memberikan deskripsi terperinci untuk fungsi Anda jika AI mengalami masalah saat memanggilnya. Beberapa contoh bidikan, rekomendasi kapan harus menggunakan (dan tidak menggunakan) fungsi, dan panduan tentang di mana mendapatkan parameter yang diperlukan semuanya dapat membantu.

2) Tambahkan plugin ke kernel Anda

Setelah menentukan plugin, Anda dapat menambahkannya ke kernel dengan membuat instans baru plugin dan menambahkannya ke koleksi plugin kernel.

Contoh ini menunjukkan cara term mudah untuk menambahkan kelas sebagai plugin dengan metode AddFromType. Untuk mempelajari tentang cara lain menambahkan plugin, lihat artikel menambahkan plugin asli.

var builder = new KernelBuilder();
builder.Plugins.AddFromType<LightsPlugin>("Lights")
Kernel kernel = builder.Build();
kernel = Kernel()
kernel.add_plugin(
   LightsPlugin(),
   plugin_name="Lights",
)
// Import the LightsPlugin
KernelPlugin lightPlugin = KernelPluginFactory.createFromObject(new LightsPlugin(),
    "LightsPlugin");
// Create a kernel with Azure OpenAI chat completion and plugin
Kernel kernel = Kernel.builder()
    .withAIService(ChatCompletionService.class, chatCompletionService)
    .withPlugin(lightPlugin)
    .build();

3) Memanggil fungsi plugin

Terakhir, Anda dapat meminta AI memanggil fungsi plugin Anda dengan menggunakan panggilan fungsi. Di bawah ini adalah contoh yang menunjukkan cara membujuk AI untuk memanggil fungsi get_lights dari plugin Lights sebelum memanggil fungsi change_state untuk menyalakan lampu.

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;

// Create a kernel with Azure OpenAI chat completion
var builder = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(modelId, endpoint, apiKey);

// Build the kernel
Kernel kernel = builder.Build();
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();

// Add a plugin (the LightsPlugin class is defined below)
kernel.Plugins.AddFromType<LightsPlugin>("Lights");

// Enable planning
OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new() 
{
    FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};

// Create a history store the conversation
var history = new ChatHistory();
history.AddUserMessage("Please turn on the lamp");

// Get the response from the AI
var result = await chatCompletionService.GetChatMessageContentAsync(
   history,
   executionSettings: openAIPromptExecutionSettings,
   kernel: kernel);

// Print the results
Console.WriteLine("Assistant > " + result);

// Add the message from the agent to the chat history
history.AddAssistantMessage(result);
import asyncio

from semantic_kernel import Kernel
from semantic_kernel.functions import kernel_function
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.chat_completion_client_base import ChatCompletionClientBase
from semantic_kernel.contents.chat_history import ChatHistory
from semantic_kernel.functions.kernel_arguments import KernelArguments

from semantic_kernel.connectors.ai.open_ai.prompt_execution_settings.azure_chat_prompt_execution_settings import (
    AzureChatPromptExecutionSettings,
)

async def main():
   # Initialize the kernel
   kernel = Kernel()

   # Add Azure OpenAI chat completion
   chat_completion = AzureChatCompletion(
      deployment_name="your_models_deployment_name",
      api_key="your_api_key",
      base_url="your_base_url",
   )
   kernel.add_service(chat_completion)

   # Add a plugin (the LightsPlugin class is defined below)
   kernel.add_plugin(
      LightsPlugin(),
      plugin_name="Lights",
   )

   # Enable planning
   execution_settings = AzureChatPromptExecutionSettings()
   execution_settings.function_choice_behavior = FunctionChoiceBehavior.Auto()

   # Create a history of the conversation
   history = ChatHistory()
   history.add_message("Please turn on the lamp")

   # Get the response from the AI
   result = await chat_completion.get_chat_message_content(
      chat_history=history,
      settings=execution_settings,
      kernel=kernel,
   )

   # Print the results
   print("Assistant > " + str(result))

   # Add the message from the agent to the chat history
   history.add_message(result)

# Run the main function
if __name__ == "__main__":
    asyncio.run(main())
// Enable planning
InvocationContext invocationContext = new InvocationContext.Builder()
    .withReturnMode(InvocationReturnMode.LAST_MESSAGE_ONLY)
    .withToolCallBehavior(ToolCallBehavior.allowAllKernelFunctions(true))
    .build();

// Create a history to store the conversation
ChatHistory history = new ChatHistory();
history.addUserMessage("Turn on light 2");

List<ChatMessageContent<?>> results = chatCompletionService
    .getChatMessageContentsAsync(history, kernel, invocationContext)
    .block();

System.out.println("Assistant > " + results.get(0));

Dengan kode di atas, Anda harus mendapatkan respons yang terlihat seperti berikut:

Peranan Pesan
🔵 Pengguna Nyalakan lampu
🔴 Asisten (panggilan fungsi) Lights.get_lights()
🟢 Alat [{ "id": 1, "name": "Table Lamp", "isOn": false, "brightness": 100, "hex": "FF0000" }, { "id": 2, "name": "Porch light", "isOn": false, "brightness": 50, "hex": "00FF00" }, { "id": 3, "name": "Chandelier", "isOn": true, "brightness": 75, "hex": "0000FF" }]
🔴 Asisten (panggilan fungsi) Lights.change_state(1, { "isOn": true })
🟢 Alat { "id": 1, "name": "Table Lamp", "isOn": true, "brightness": 100, "hex": "FF0000" }
🔴 Asisten Lampu sekarang menyala

Tips

Meskipun Anda dapat memanggil fungsi plugin secara langsung, ini tidak disarankan karena AI harus menjadi yang memutuskan fungsi mana yang akan dipanggil. Jika Anda memerlukan kontrol eksplisit atas fungsi mana yang dipanggil, pertimbangkan untuk menggunakan metode standar di basis kode Anda alih-alih plugin.

Rekomendasi umum untuk penulisan plugin

Mengingat bahwa setiap skenario memiliki persyaratan unik, menggunakan desain plugin yang berbeda, dan dapat menggabungkan beberapa LLM, sangat sulit menyediakan panduan serba guna untuk desain plugin. Namun, di bawah ini adalah beberapa rekomendasi dan pedoman umum untuk memastikan bahwa plugin ramah AI dan dapat dengan mudah dan efisien dikonsumsi oleh LLM.

Impor hanya plugin yang diperlukan

Impor hanya plugin yang berisi fungsi yang diperlukan untuk skenario spesifik Anda. Pendekatan ini tidak hanya akan mengurangi jumlah token input yang digunakan tetapi juga meminimalkan terjadinya kesalahan fungsi-panggilan ke fungsi yang tidak digunakan dalam skenario. Secara keseluruhan, strategi ini harus meningkatkan akurasi panggilan fungsi dan mengurangi jumlah positif palsu.

Selain itu, OpenAI merekomendasikan agar Anda menggunakan tidak lebih dari 20 alat dalam satu panggilan API; idealnya, tidak lebih dari 10 alat. Seperti yang dinyatakan oleh OpenAI: "Kami sarankan Anda menggunakan tidak lebih dari 20 alat dalam satu panggilan API. Pengembang biasanya melihat pengurangan kemampuan model untuk memilih alat yang benar setelah mereka memiliki antara 10-20 alat yang ditentukan."* Untuk informasi lebih lanjut, Anda dapat mengunjungi dokumentasi mereka di OpenAI Function Calling Guide.

Membuat plugin yang ramah AI

Untuk meningkatkan kemampuan LLM untuk memahami dan menggunakan plugin, disarankan untuk mengikuti panduan berikut:

  • Gunakan nama fungsi deskriptif dan ringkas: Pastikan bahwa nama fungsi menyampaikan tujuannya dengan jelas untuk membantu model memahami kapan harus memilih setiap fungsi. Jika nama fungsi ambigu, pertimbangkan untuk mengganti nama untuk kejelasan. Hindari menggunakan singkatan atau akronim untuk mempersingkat nama fungsi. Gunakan DescriptionAttribute untuk memberikan konteks dan instruksi tambahan hanya jika perlu, meminimalkan konsumsi token.

  • Minimalkan parameter fungsi: Batasi jumlah parameter fungsi dan gunakan jenis primitif jika memungkinkan. Pendekatan ini mengurangi konsumsi token dan menyederhanakan tanda tangan fungsi, sehingga memudahkan LLM untuk mencocokkan parameter fungsi secara efektif.

  • Beri nama parameter fungsi dengan jelas: Gunakan nama yang deskriptif untuk parameter fungsi agar tujuannya lebih mudah dipahami. Hindari menggunakan singkatan atau akronim untuk mempersingkat nama parameter, karena ini akan membantu LLM dalam penalaran tentang parameter dan memberikan nilai yang akurat. Seperti halnya nama fungsi, gunakan DescriptionAttribute hanya jika perlu untuk meminimalkan konsumsi token.

Temukan keseimbangan yang tepat antara jumlah fungsi dan tanggung jawabnya

Di satu sisi, memiliki fungsi dengan satu tanggung jawab adalah praktik yang baik yang memungkinkan untuk menjaga fungsi tetap sederhana dan dapat digunakan kembali di beberapa skenario. Di sisi lain, setiap panggilan fungsi menimbulkan overhead dalam hal latensi pulang pergi jaringan dan jumlah token input dan output yang digunakan: token input digunakan untuk mengirim definisi fungsi dan hasil pemanggilan ke LLM, sementara token output digunakan saat menerima panggilan fungsi dari model. Atau, satu fungsi dengan beberapa tanggung jawab dapat diimplementasikan untuk mengurangi jumlah token yang dikonsumsi dan mengurangi overhead jaringan, meskipun ini mengorbankan fleksibilitas penggunaan kembali dalam skenario lain.

Namun, mengonsolidasikan banyak tanggung jawab ke dalam satu fungsi dapat meningkatkan jumlah dan kompleksitas parameter fungsi dan jenis pengembaliannya. Kompleksitas ini dapat menyebabkan situasi di mana model mungkin berjuang untuk mencocokkan parameter fungsi dengan benar, yang mengakibatkan parameter yang terlewat atau nilai dengan jenis yang salah. Oleh karena itu, penting untuk mencapai keseimbangan yang tepat antara jumlah fungsi untuk mengurangi overhead jaringan dan jumlah tanggung jawab yang dimiliki setiap fungsi, memastikan bahwa model dapat secara akurat mencocokkan parameter fungsi.

Mengubah fungsi Kernel Semantik

Gunakan teknik transformasi untuk fungsi Kernel Semantik yang dijelaskan dalam posting blog Transforming Semantic Kernel Functions untuk:

  • Mengubah perilaku fungsi: Ada skenario di mana perilaku default fungsi mungkin tidak selaras dengan hasil yang diinginkan dan tidak layak untuk memodifikasi implementasi fungsi asli. Dalam kasus seperti itu, Anda dapat membuat fungsi baru yang membungkus yang asli dan memodifikasi perilakunya yang sesuai.

  • Memberikan informasi konteks: Functions mungkin memerlukan parameter yang tidak dapat atau tidak boleh disimpulkan OLEH LLM. Misalnya, jika fungsi perlu bertindak atas nama pengguna saat ini atau memerlukan informasi autentikasi, konteks ini biasanya tersedia untuk aplikasi host tetapi tidak untuk LLM. Dalam kasus seperti itu, Anda dapat mengubah fungsi untuk memanggil yang asli sambil menyediakan informasi konteks yang diperlukan dari aplikasi hosting, bersama dengan argumen yang disediakan oleh LLM.

  • Ubah daftar parameter, jenis, dan nama: Jika fungsi asli memiliki tanda tangan kompleks yang sulit ditafsirkan OLEH LLM, Anda dapat mengubah fungsi menjadi satu dengan tanda tangan yang lebih sederhana yang dapat dipahami LLM dengan lebih mudah. Ini mungkin melibatkan perubahan nama parameter, jenis, jumlah parameter, dan parameter kompleks yang meratakan atau tidak terkait, di antara penyesuaian lainnya.

Pemanfaatan kondisi lokal

Saat merancang plugin yang beroperasi pada himpunan data yang relatif besar atau rahasia, seperti dokumen, artikel, atau email yang berisi informasi sensitif, pertimbangkan untuk menggunakan status lokal untuk menyimpan data asli atau hasil menengah yang tidak perlu dikirim ke LLM. Fungsi untuk skenario tersebut dapat menerima dan mengembalikan id status, memungkinkan Anda mencari dan mengakses data secara lokal alih-alih meneruskan data aktual ke LLM, hanya untuk menerimanya kembali sebagai argumen untuk pemanggilan fungsi berikutnya.

Dengan menyimpan data secara lokal, Anda dapat menjaga informasi tetap privat dan aman sambil menghindari konsumsi token yang tidak perlu selama panggilan fungsi. Pendekatan ini tidak hanya meningkatkan privasi data tetapi juga meningkatkan efisiensi keseluruhan dalam memproses himpunan data besar atau sensitif.

Menyediakan skema jenis pengembalian fungsi ke model AI

Gunakan salah satu teknik yang dijelaskan dalam bagian Menyediakan skema jenis pengembalian fungsi ke LLM untuk menyediakan skema jenis pengembalian fungsi ke model AI.

Dengan menggunakan skema jenis pengembalian yang terdefinisi dengan baik, model AI dapat secara akurat mengidentifikasi properti yang dimaksudkan, menghilangkan potensi ketidakakuratan yang mungkin muncul ketika model membuat asumsi berdasarkan informasi yang tidak lengkap atau ambigu tanpa adanya skema. Akibatnya, ini meningkatkan akurasi panggilan fungsi, yang mengarah ke hasil yang lebih andal dan tepat.