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:
- 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.
- Model LLM generuje pełną odpowiedź lub żądanie wywołania narzędzia w określonym formacie.
- 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.
- 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;
}