Wywołania narzędzi

Wywoływanie narzędzia, czyli wywoływanie funkcji, to uporządkowany sposób na umożliwienie LLM przesyłania żądań do aplikacji, która je wywołała. Ty określasz narzędzia, które chcesz udostępnić modelowi, a model będzie wysyłać do Twojej aplikacji żądania użycia narzędzia w miarę potrzeby, aby zrealizować prompty.

Przypadki użycia wywoływania narzędzi można ogólnie podzielić na kilka kategorii:

Udzielanie LLM dostępu do informacji, na podstawie których nie został on trenowany

  • często zmieniające się informacje, takie jak cena akcji lub aktualna pogoda;
  • informacje dotyczące Twojej domeny aplikacji, takie jak informacje o produkcie lub profilach użytkowników;

Zwróć uwagę na pokrywanie się z generowaniem rozszerzonym przez wyszukiwanie w zapisanych informacjach (RAG), które jest też sposobem na to, aby model LLM integrował informacje oparte na faktach w generowanych przez siebie treściach. RAG to bardziej złożone rozwiązanie, które najlepiej sprawdza się, gdy masz dużą ilość informacji lub informacje, które są najbardziej trafne w przypadku prompta, są niejednoznaczne. Jeśli jednak pobranie informacji, których potrzebuje LLM, wymaga prostego wywołania funkcji lub sprawdzenia w bazie danych, bardziej odpowiednie jest wywołanie narzędzia.

Wprowadzanie pewnego stopnia determinizmu w przepływie pracy LLM

  • wykonywanie obliczeń, których LLM nie może wykonać samodzielnie;
  • Wymuszanie generowania dosłownego tekstu przez model LLM w określonych okolicznościach, np. podczas udzielania odpowiedzi na pytanie dotyczące warunków korzystania z aplikacji.

Wykonywanie działania po jego zainicjowaniu przez LLM

  • Włączanie i wyłączanie światła za pomocą asystenta domowego opartego na LLM
  • Rezerwowanie stolików w usługach opartych na LLM

Zanim zaczniesz

Jeśli chcesz uruchomić przykłady kodu na tej stronie, najpierw wykonaj czynności opisane w przewodniku Początki. Wszystkie przykłady zakładają, że masz już skonfigurowany projekt z zainstalowanymi zależnościami Genkit.

Ta strona zawiera informacje o jednym z zaawansowanych funkcji abstrakcji modelu Genkit. Zanim zaczniesz zgłębiać ten temat, zapoznaj się z treścią strony Generowanie treści za pomocą modeli AI. Musisz też znać system Genkit do definiowania schematów danych wejściowych i wyjściowych, który opisany jest na stronie Procesy.

Omówienie wywoływania narzędzi

Ogólnie rzecz biorąc, typowa interakcja z LLM polegająca na wywołaniu narzędzia wygląda tak:

  1. Aplikacja wywołująca przesyła do LLM żądanie, a także zawiera w promptzie listę narzędzi, których LLM może użyć do wygenerowania odpowiedzi.
  2. Model LLM generuje pełną odpowiedź lub żądanie wywołania narzędzia w określonym formacie.
  3. Jeśli rozmówca otrzyma pełną odpowiedź, żądanie zostanie spełnione, a interakcja zakończy się. Jeśli jednak otrzyma wywołanie narzędzia, wykona odpowiednią logikę i wyśle nowe żądanie do LLM, zawierające pierwotny prompt lub jego wariant, a także wynik wywołania narzędzia.
  4. LLM obsługuje nowy prompt w sposób opisany w kroku 2.

Aby to działało, musisz spełnić kilka wymagań:

  • Model musi być wytrenowany, aby wysyłać żądania do narzędzia, gdy jest to potrzebne do wykonania promptu. Większość większych modeli udostępnianych przez interfejsy API w internecie, takich jak Gemini czy Claude, może to zrobić, ale mniejsze i bardziej wyspecjalizowane modele często nie. Jeśli spróbujesz udostępnić narzędzia modelowi, który ich nie obsługuje, Genkit wygeneruje błąd.
  • Aplikacja wywołująca musi przekazać model definicje narzędzi w oczekiwanym formacie.
  • Aplikacja wywołująca musi poprosić model o wygenerowanie żądań wywołania narzędzia w oczekiwanym przez aplikację formacie.

Narzędzia do wykonywania połączeń w Genkit

Genkit udostępnia jeden interfejs wywoływania narzędzia w przypadku modeli, które to obsługują. Każdy wtyczka modelu zapewnia spełnienie 2 ostatnich kryteriów wymienionych powyżej, a funkcja generate() instancji Genkit automatycznie wykonuje opisaną wcześniej pętlę wywoływania narzędzia.

Obsługa modelu

Obsługa wywoływania narzędzi zależy od modelu, interfejsu API modelu i wtyczki Genkit. Aby sprawdzić, czy narzędzie obsługuje wywoływanie, zapoznaj się z odpowiednią dokumentacją. Dodatkowo:

  • Jeśli spróbujesz udostępnić narzędzia modelowi, który ich nie obsługuje, Genkit wygeneruje błąd.
  • Jeśli wtyczka eksportuje odwołania do modelu, właściwość info.supports.tools wskazuje, czy obsługuje wywoływanie narzędzia.

Definiowanie narzędzi

Aby zapisać definicje narzędzi, użyj funkcji defineTool() instancji Genkit:

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

const ai = genkit({
  plugins: [googleAI()],
  model: gemini15Flash,
});

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.';
  }
);

Składnia ta wygląda tak samo jak składnia defineFlow(), ale parametry name, description i inputSchema są wymagane. Podczas tworzenia definicji narzędzia należy zwrócić szczególną uwagę na treść i opisowość tych parametrów. Są one niezbędne, aby model LLM mógł efektywnie korzystać z dostępnych narzędzi.

Korzystanie z narzędzi

Uwzględnij zdefiniowane narzędzia w promptach, aby generować treści.

Wygeneruj

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' });

Plik z promptami

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

What is the weather in {{location}}?

Następnie możesz uruchomić prompt w kodzie w ten sposób:

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

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

Czat

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 automatycznie obsłuży wywołanie narzędzia, jeśli LLM musi użyć narzędzia getWeather, aby odpowiedzieć na prompt.

Wstrzymywanie pętli narzędzia za pomocą przerw

Domyślnie Genkit wielokrotnie wywołuje LLM, dopóki wszystkie wywołania narzędzi nie zostaną rozwiązane. Możesz warunkowo wstrzymywać wykonywanie kodu w takich sytuacjach, gdy chcesz na przykład:

  • Zadaj użytkownikowi pytanie lub wyświetl interfejs użytkownika.
  • Zapytaj użytkownika o potwierdzenie potencjalnie ryzykownego działania.
  • Poproś o zatwierdzenie działania poza kanałem.

Przerwania to specjalne narzędzia, które mogą zatrzymać pętlę i przekazać kontrolę nad kodem, aby umożliwić obsługę bardziej zaawansowanych scenariuszy. Aby dowiedzieć się, jak ich używać, zapoznaj się z przewodnikiem po przerwach.

Wyraźne obsługiwanie wywołań narzędzia

Jeśli chcesz mieć pełną kontrolę nad pętlą wywoływania narzędzia, np. aby zastosować bardziej skomplikowaną logikę, ustaw parametr returnToolRequests na true. Teraz Twoim obowiązkiem jest dopilnowanie, aby wszystkie żądania dotyczące narzędzi zostały spełnione:

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;
}