Panggilan alat

Panggilan alat, yang juga dikenal sebagai panggilan fungsi, adalah cara terstruktur yang memberikan LLM kemampuan untuk membuat permintaan kembali ke aplikasi yang memanggilnya. Anda menentukan alat yang ingin disediakan untuk model, dan model akan membuat permintaan alat ke aplikasi Anda sesuai kebutuhan untuk memenuhi prompt yang Anda berikan.

Kasus penggunaan panggilan alat umumnya terbagi menjadi beberapa tema:

Memberikan LLM akses ke informasi yang tidak digunakan untuk melatihnya

  • Informasi yang sering berubah, seperti harga saham atau cuaca saat ini.
  • Informasi khusus untuk domain aplikasi Anda, seperti informasi produk atau profil pengguna.

Perhatikan tumpang-tindih dengan retrieval augmented generation (RAG), yang juga merupakan cara untuk memungkinkan LLM mengintegrasikan informasi faktual ke dalam pembuatannya. RAG adalah solusi yang lebih berat dan paling tepat digunakan jika Anda memiliki informasi dalam jumlah besar atau informasi yang paling relevan dengan prompt yang bersifat ambigu. Di sisi lain, panggilan alat lebih tepat untuk digunakan jika pengambilan informasi yang diperlukan LLM adalah panggilan fungsi sederhana atau pencarian database.

Memperkenalkan tingkat determinisme ke dalam alur kerja LLM

  • Melakukan penghitungan yang tidak dapat diselesaikan dengan andal oleh LLM.
  • Memaksa LLM untuk menghasilkan teks verbatim dalam situasi tertentu, seperti saat merespons pertanyaan tentang persyaratan layanan aplikasi.

Melakukan tindakan yang dimulai oleh LLM

  • Menyalakan dan mematikan lampu pada asisten rumah yang didukung teknologi LLM
  • Membuat reservasi meja pada agen restoran yang didukung teknologi LLM

Sebelum memulai

Jika Anda ingin menjalankan contoh kode di halaman ini, selesaikan langkah-langkah dalam panduan Memulai terlebih dahulu. Semua contoh mengasumsikan bahwa Anda telah menyiapkan project dengan dependensi Genkit terinstal.

Halaman ini membahas salah satu fitur lanjutan abstraksi model Genkit, jadi sebelum Anda mempelajarinya terlalu dalam, Anda harus memahami konten di halaman Membuat konten dengan model AI. Anda juga harus memahami sistem Genkit untuk menentukan skema input dan output, yang dibahas di halaman Flow.

Ringkasan panggilan alat

Pada tingkat tinggi, berikut adalah tampilan interaksi panggilan alat umum dengan LLM:

  1. Aplikasi panggilan meminta LLM melalui permintaan dan juga menyertakan dalam prompt, daftar alat yang dapat digunakan LLM untuk menghasilkan respons.
  2. LLM menghasilkan respons lengkap atau menghasilkan permintaan panggilan alat dalam format tertentu.
  3. Jika pemanggil menerima respons lengkap, permintaan akan terpenuhi dan interaksi berakhir; tetapi jika pemanggil menerima panggilan alat, pemanggil akan menjalankan logika apa pun yang sesuai dan mengirim permintaan baru ke LLM yang berisi prompt asli atau beberapa variasi darinya serta hasil panggilan alat.
  4. LLM menangani prompt baru seperti pada Langkah 2.

Agar dapat berfungsi, beberapa persyaratan harus dipenuhi:

  • Model harus dilatih untuk membuat permintaan alat saat diperlukan untuk menyelesaikan suatu prompt. Sebagian besar model yang lebih besar yang disediakan melalui API web, seperti Gemini dan Claude, dapat melakukannya, tetapi model yang lebih kecil dan lebih khusus sering kali tidak dapat melakukannya. Genkit akan menampilkan error jika Anda mencoba menyediakan alat ke model yang tidak mendukungnya.
  • Aplikasi panggilan harus memberikan definisi alat ke model dalam format yang diharapkan.
  • Aplikasi panggilan harus meminta model membuat permintaan panggilan alat dalam format yang diharapkan aplikasi.

Panggilan alat dengan Genkit

Genkit menyediakan satu antarmuka panggilan alat dengan model yang mendukungnya. Setiap plugin model memastikan bahwa dua kriteria terakhir di atas terpenuhi, dan fungsi generate() instance Genkit secara otomatis menjalankan loop panggilan alat yang dijelaskan sebelumnya.

Dukungan model

Dukungan panggilan alat bergantung pada model, API model, dan plugin Genkit. Lihat dokumentasi yang relevan untuk menentukan apakah panggilan alat kemungkinan besar akan didukung. Selain itu:

  • Genkit akan menampilkan error jika Anda mencoba menyediakan alat ke model yang tidak mendukungnya.
  • Jika plugin mengekspor referensi model, properti info.supports.tools akan menunjukkan apakah plugin mendukung panggilan alat.

Menentukan alat

Gunakan fungsi defineTool() instance Genkit untuk menulis definisi alat:

import { genkit, z } from 'genkit';
import { googleAI } from '@genkitai/google-ai';

const ai = genkit({
  plugins: [googleAI()],
  model: googleAI.model('gemini-2.0-flash'),
});

const getWeather = ai.defineTool(
  {
    name: 'getWeather',
    description: 'Gets the current weather in a given location',
    inputSchema: z.object({ 
      location: z.string().describe('The location to get the current weather for')
    }),
    outputSchema: z.string(),
  },
  async (input) => {
    // Here, we would typically make an API call or database query. For this
    // example, we just return a fixed value.
    return `The current weather in ${input.location} is 63°F and sunny.`;
  }
);

Sintaksis di sini terlihat seperti sintaksis defineFlow(); tetapi, parameter name, description, dan inputSchema diperlukan. Saat menulis definisi alat, perhatikan dengan cermat kata-kata dan deskripsi parameter ini. Hal ini sangat penting bagi LLM untuk menggunakan alat yang tersedia secara efektif.

Menggunakan alat

Sertakan alat yang ditentukan dalam prompt Anda untuk membuat konten.

Buat

const response = await ai.generate({
  prompt: 'What is the weather in Baltimore?',
  tools: [getWeather],
});

definePrompt

const weatherPrompt = ai.definePrompt(
  {
    name: 'weatherPrompt',
    tools: [getWeather],
  },
  'What is the weather in {{location}}?'
);

const response = await weatherPrompt({ location: 'Baltimore' });

Prompt file

---
system: "Answer questions using the tools you have."
tools: [getWeather]
input:
  schema:
    location: string
---

What is the weather in {{location}}?

Kemudian, Anda dapat menjalankan prompt dalam kode Anda sebagai berikut:

// assuming prompt file is named weatherPrompt.prompt
const weatherPrompt = ai.prompt('weatherPrompt');

const response = await weatherPrompt({ location: 'Baltimore' });

Chat

const chat = ai.chat({
  system: 'Answer questions using the tools you have.',
  tools: [getWeather],
});

const response = await chat.send('What is the weather in Baltimore?');

// Or, specify tools that are message-specific 
const response = await chat.send({
  prompt: 'What is the weather in Baltimore?',
  tools: [getWeather],
});

Genkit akan otomatis menangani panggilan alat jika LLM perlu menggunakan alat getWeather untuk menjawab prompt.

Menentukan alat secara dinamis saat runtime

Seperti sebagian besar hal di Genkit, alat harus ditentukan sebelumnya selama inisialisasi aplikasi Anda. Hal ini diperlukan agar Anda dapat berinteraksi dengan alat dari UI Developer Genkit. Ini biasanya adalah cara yang direkomendasikan. Namun, ada skenario saat alat harus ditentukan secara dinamis per permintaan pengguna.

Anda dapat menentukan alat secara dinamis menggunakan fungsi ai.dynamicTool. Fungsi ini sangat mirip dengan metode ai.defineTool. Namun, alat dinamis tidak dilacak oleh runtime Genkit, sehingga Anda tidak dapat menggunakan UI Developer Genkit untuk berinteraksi dengannya. Sebagai gantinya, Anda harus meneruskannya ke panggilan ai.generate dengan referensi (untuk alat reguler, Anda juga dapat menggunakan nama alat string).

import { genkit, z } from "genkit";
import { googleAI } from "@genkit-ai/googleai";

const ai = genkit({
  plugins: [googleAI()],
  model: googleAI.model("gemini-2.0-flash"),
});

const weatherFlow = ai.defineFlow("weatherFlow", async () => {
  const getWeather = ai.dynamicTool(
    {
      name: "getWeather",
      description: "Gets the current weather in a given location",
      inputSchema: z.object({
        location: z
          .string()
          .describe("The location to get the current weather for"),
      }),
      outputSchema: z.string(),
    },
    async (input) => {
      return `The current weather in ${input.location} is 63°F and sunny.`;
    }
  );

  const { text } = await ai.generate({
    prompt: "What is the weather in Baltimore?",
    tools: [getWeather],
  });

  return text;
});

Saat menentukan alat dinamis, untuk menentukan skema input dan output, Anda dapat menggunakan Zod seperti yang ditunjukkan pada contoh sebelumnya, atau Anda dapat meneruskan Skema JSON yang dibuat secara manual.

const getWeather = ai.dynamicTool(
  {
    name: "getWeather",
    description: "Gets the current weather in a given location",
    inputJsonSchema: myInputJsonSchema,
    outputJsonSchema: myOutputJsonSchema,
  },
  async (input) => { /* ... */ }
);

Alat dinamis tidak memerlukan fungsi penerapan. Jika Anda tidak meneruskan fungsi, alat akan berperilaku seperti gangguan dan Anda dapat melakukan penanganan panggilan alat manual:

const getWeather = ai.dynamicTool(
  {
    name: "getWeather",
    description: "Gets the current weather in a given location",
    inputJsonSchema: myInputJsonSchema,
    outputJsonSchema: myOutputJsonSchema,
  }
);

Menjeda loop alat menggunakan interupsi

Secara default, Genkit berulang kali memanggil LLM hingga setiap panggilan alat telah diselesaikan. Anda dapat menjeda eksekusi secara bersyarat dalam situasi yang Anda inginkan, misalnya:

  • Mengajukan pertanyaan kepada pengguna atau menampilkan UI.
  • Konfirmasi tindakan yang berpotensi berisiko dengan pengguna.
  • Meminta persetujuan di luar band untuk suatu tindakan.

Interupsi adalah alat khusus yang dapat menghentikan loop dan mengembalikan kontrol ke kode Anda sehingga Anda dapat menangani skenario yang lebih canggih. Buka panduan gangguan untuk mempelajari cara menggunakannya.

Menangani panggilan alat secara eksplisit

Jika Anda menginginkan kontrol penuh atas loop panggilan alat ini, misalnya untuk menerapkan logika yang lebih rumit, tetapkan parameter returnToolRequests ke true. Sekarang, Anda bertanggung jawab untuk memastikan semua permintaan alat terpenuhi:

const getWeather = ai.defineTool(
  {
    // ... tool definition ...
  },
  async ({ location }) => {
    // ... tool implementation ...
  },
);

const generateOptions: GenerateOptions = {
  prompt: "What's the weather like in Baltimore?",
  tools: [getWeather],
  returnToolRequests: true,
};

let llmResponse;
while (true) {
  llmResponse = await ai.generate(generateOptions);
  const toolRequests = llmResponse.toolRequests;
  if (toolRequests.length < 1) {
    break;
  }
  const toolResponses: ToolResponsePart[] = await Promise.all(
    toolRequests.map(async (part) => {
      switch (part.toolRequest.name) {
        case 'specialTool':
          return {
            toolResponse: {
              name: part.toolRequest.name,
              ref: part.toolRequest.ref,
              output: await getWeather(part.toolRequest.input),
            },
          };
        default:
          throw Error('Tool not found');
      }
    })
  );
  generateOptions.messages = llmResponse.messages;
  generateOptions.prompt = toolResponses;
}