Wywołania narzędzi

Wywoływanie narzędzi, nazywane też wywołaniem funkcji, to ustrukturyzowany sposób przekazywania Możliwość wysyłania żądań z powrotem do aplikacji, która je wywołała. Ty narzędzia, które chcesz udostępnić modelowi, w razie potrzeby wysyłać do aplikacji żądania narzędzi, aby spełnić Twoje oczekiwania.

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

Przyznawanie LLM dostępu do informacji, na których nie był trenowany

  • często zmieniające się informacje, takie jak menu dnia restauracji czy stanie asortymentu w Twoim sklepie.
  • Informacje dotyczące domeny aplikacji, np. informacje o produkcie.

Zwróć uwagę na pokrywanie się z generowaniem rozszerzonego przez wyszukiwanie (RAG), które jest też umożliwia LLM integrowanie faktów z pokoleniami. RAG to cięższe rozwiązanie, które najlepiej sprawdza się w przypadku dużej czy informacje, które są najważniejsze w odniesieniu do promptu, są niejednoznaczne. Wł. Z drugiej strony przy pobieraniu informacji potrzebnych LLM jest funkcja wywołaniem usługi lub bazą danych, bardziej odpowiednie są wywołania narzędzia.

Wprowadzenie pewnego determinizmu do przepływu pracy LLM

  • wykonywanie obliczeń, których LLM nie jest w stanie w niezawodny sposób wykonać.
  • Wymuszanie generowania przez LLM dosłownego tekstu w określonych okolicznościach, takich jak w odpowiedzi na pytanie o warunki korzystania z aplikacji.

Wykonywanie działania po zainicjowaniu przez LLM

  • Włączanie i wyłączanie oświetlenia w asystencie domowym z technologią LLM
  • Rezerwowanie stolików w restauracji opartej na LLM

Zanim zaczniesz

Jeśli chcesz uruchomić przykładowe fragmenty kodu z tej strony, najpierw wykonaj czynności podane w Pierwsze kroki. We wszystkich przykładach zakładamy, że ma już skonfigurowany projekt z zainstalowanymi zależnościami Genkit.

Na tej stronie omawiamy jedną z zaawansowanych funkcji abstrakcji modelu Genkit generate(), więc zanim zagłębimy się w temat funkcji, zapoznaj się z treści dostępnych na stronie Generowanie treści za pomocą modeli AI. Zalecenia Warto też znać system Genkit do definiowania schematów wejściowych i wyjściowych Zostało to omówione na stronie Przepływy.

Omówienie funkcji wywoływania narzędzi

Ogólnie to taka interakcja z LLM przy użyciu funkcji wywoływania narzędzi wygląda jak:

  1. Aplikacja wywołująca wysyła do LLM żądanie, a także zawiera listę narzędzi, których LLM może użyć do wygenerowania odpowiedzi.
  2. LLM generuje pełną odpowiedź lub wywołanie narzędzia w określonym formacie.
  3. Jeśli rozmówca otrzyma pełną odpowiedź, żądanie zostanie zrealizowane, zakończenie interakcji; ale jeśli rozmówca otrzyma wywołanie narzędzia, za pomocą dowolnej logiki i wysyła nowe żądanie do LLM zawierające oryginalny prompt lub jego odmianę, a także wynik jako wywołania narzędzia.
  4. LLM obsługuje nowy prompt tak jak w kroku 2.

Aby to działało, musi być spełnione kilka warunków:

  • Model musi być wytrenowany tak, aby wysyłał żądania narzędzi, gdy jest wymagane do wykonania . Większość większych modeli udostępnianych przez internetowe interfejsy API, takie jak Gemini i Claude, ale mniejsze i bardziej wyspecjalizowane modele często nie są w stanie tego zrobić. Genkit zwróci błąd, jeśli spróbujesz udostępnić narzędzia modelowi, który tego nie robi. są obsługiwane.
  • Aplikacja wywołująca musi dostarczyć definicje narzędzi dla modelu w funkcji w oczekiwanym formacie.
  • Aplikacja wywołująca musi poprosić model o wygenerowanie wywołania narzędzia w oczekiwanym przez aplikację formacie.

Wywoływanie narzędzi w usłudze Genkit

Genkit to pojedynczy interfejs do wywoływania narzędzi z modelami, które go obsługują. Każda wtyczka modelu zapewnia spełnienie 2 ostatnich z powyższych kryteriów. funkcja generate() automatycznie wykonuje pętlę wywołania narzędzia omówiono to wcześniej.

Obsługa modelu

Obsługa wywoływania narzędzi zależy od modelu, interfejsu API modelu i wtyczki Genkit. Zapoznaj się z odpowiednią dokumentacją, aby określić, czy wywołanie narzędzia może być obsługiwane. Dodatkowo:

  • Genkit zwróci błąd, jeśli spróbujesz udostępnić narzędzia modelowi, który tego nie robi. są obsługiwane.
  • Jeśli wtyczka eksportuje odwołania do modelu, właściwość info.supports.tools wskazuje, czy obsługuje ona wywołania narzędzi.

Narzędzia do definiowania

Za pomocą funkcji defineTool() wpisz definicje narzędzi:

const specialToolInputSchema = z.object({ meal: z.enum(["breakfast", "lunch", "dinner"]) });
const specialTool = defineTool(
  {
    name: "specialTool",
    description: "Retrieves today's special for the given meal",
    inputSchema: specialToolInputSchema,
    outputSchema: z.string(),
  },
  async ({ meal }): Promise<string> => {
    // Retrieve up-to-date information and return it. Here, we just return a
    // fixed value.
    return "Baked beans on toast";
  }
);

Składnia używana w tym miejscu wygląda tak samo jak składnia defineFlow(). jednak wszystkie cztery parametry name, description, inputSchema i outputSchema są Podczas tworzenia definicji narzędzia zwróć szczególną uwagę na sformułowania opisowych parametrów, ponieważ są one niezbędne dla LLM do efektywne wykorzystanie dostępnych narzędzi.

Dodawanie narzędzi do promptów

Po zdefiniowaniu narzędzi określ je w parametrze narzędzi generate():

const llmResponse = await generate({
  model: gemini15Flash,
  prompt,
  tools: [specialTool],
});

Możesz udostępnić wiele narzędzi, LLM w razie potrzeby będzie wywoływać narzędzia aby dokończyć prompt.

Bezpośrednia obsługa wywołań narzędzi

Domyślnie Genkit wywołuje LLM wielokrotnie, aż każde wywołanie narzędzia . Jeśli chcesz mieć większą kontrolę nad pętlą wywołań narzędzia, na przykład zastosuj bardziej skomplikowaną logikę, ustaw parametr returnToolRequests na true. Teraz to Ty musisz zadbać o realizację wszystkich żądań narzędzia:

let generateOptions: GenerateOptions = {
  model: gemini15Flash,
  prompt,
  tools: [specialTool],
  returnToolRequests: true,
};
let llmResponse;
while (true) {
  llmResponse = await 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 specialTool(specialToolInputSchema.parse(part.toolRequest?.input)),
            },
          };
        default:
          throw Error('Tool not found');
        }
      }));
    generateOptions.history = llmResponse.toHistory();
    generateOptions.prompt = toolResponses;
}