A chamada de ferramenta, também conhecida como chamada de função, é uma maneira estruturada de fornecer aos LLMs a capacidade de retornar solicitações ao aplicativo que os chamou. Você define as ferramentas que quer disponibilizar para o modelo, e ele vai fazer solicitações de ferramentas para o app conforme necessário para atender às solicitações.
Os casos de uso de chamadas de ferramentas geralmente se enquadram em alguns temas:
Dar acesso a um LLM a informações com as quais ele não foi treinado
- Informações que mudam com frequência, como o preço de uma ação ou a previsão do tempo.
- Informações específicas do domínio do app, como informações do produto ou perfis de usuário.
Observe a sobreposição com a geração aumentada de recuperação (RAG), que também é uma maneira de permitir que um LLM integre informações factuais às gerações. A RAG é uma solução mais pesada que é mais adequada quando você tem uma grande quantidade de informações ou quando as informações mais relevantes para um comando são ambíguas. Por outro lado, se a recuperação das informações necessárias para o LLM for uma chamada de função simples ou pesquisa de banco de dados, a chamada de ferramenta será mais apropriada.
Como introduzir um grau de determinismo em um fluxo de trabalho de LLM
- Fazer cálculos que o LLM não consegue realizar.
- Forçar um LLM a gerar texto literal em determinadas circunstâncias, como ao responder a uma pergunta sobre os termos de serviço de um app.
Realizar uma ação quando iniciada por um LLM
- Acender e apagar luzes em um assistente doméstico com LLM
- Reservar mesas em um agente de restaurante com LLM
Antes de começar
Se você quiser executar os exemplos de código nesta página, primeiro conclua as etapas no guia Primeiros passos. Todos os exemplos partem do princípio de que você já configurou um projeto com as dependências do Genkit instaladas.
Esta página discute um dos recursos avançados da abstração de modelo do Genkit. Portanto, antes de se aprofundar demais, você precisa conhecer o conteúdo da página Como gerar conteúdo com modelos de IA. Você também precisa conhecer o sistema do Genkit para definir esquemas de entrada e saída, que é discutido na página Fluxos.
Visão geral da chamada de ferramenta
De modo geral, esta é a aparência de uma interação típica de chamada de ferramenta com um LLM:
- O aplicativo de chamada solicita o LLM com uma solicitação e também inclui uma lista de ferramentas que o LLM pode usar para gerar uma resposta.
- O LLM gera uma resposta completa ou uma solicitação de chamada de ferramenta em um formato específico.
- Se o autor da chamada receber uma resposta completa, a solicitação será atendida e a interação será encerrada. No entanto, se o autor da chamada receber uma chamada de ferramenta, ele vai executar a lógica apropriada e enviar uma nova solicitação para o LLM contendo o comando original ou alguma variação dele, além do resultado da chamada de ferramenta.
- O LLM processa a nova solicitação, como na etapa 2.
Para que isso funcione, é preciso atender a vários requisitos:
- O modelo precisa ser treinado para fazer solicitações de ferramentas quando necessário para concluir uma instrução. A maioria dos modelos maiores fornecidos por APIs da Web, como Gemini e Claude, pode fazer isso, mas modelos menores e mais especializados geralmente não conseguem. O Genkit vai gerar um erro se você tentar fornecer ferramentas a um modelo que não oferece suporte a elas.
- O aplicativo de chamada precisa fornecer definições de ferramentas para o modelo no formato esperado.
- O aplicativo de chamada precisa solicitar que o modelo gere solicitações de chamada de ferramenta no formato esperado pelo aplicativo.
Chamada de ferramenta com o Genkit
O Genkit oferece uma única interface para chamadas de ferramentas com modelos compatíveis.
Cada plug-in de modelo garante que os dois últimos critérios acima sejam atendidos, e
a função generate()
da instância do Genkit executa automaticamente o ciclo de chamadas de ferramentas
descrito anteriormente.
Suporte a modelos
O suporte a chamadas de ferramentas depende do modelo, da API do modelo e do plug-in do Genkit. Consulte a documentação relevante para determinar se a chamada de ferramentas tem suporte. Além disso:
- O Genkit vai gerar um erro se você tentar fornecer ferramentas a um modelo que não oferece suporte a elas.
- Se o plug-in exporta referências de modelo, a propriedade
info.supports.tools
vai indicar se ele oferece suporte à chamada de ferramentas.
Como definir ferramentas
Use a função defineTool()
da instância do Genkit para escrever definições de ferramentas:
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.`;
}
);
A sintaxe aqui é semelhante à sintaxe defineFlow()
. No entanto, os parâmetros name
,
description
e inputSchema
são obrigatórios. Ao escrever uma definição de ferramenta, tenha cuidado especial com a redação e a descrição desses parâmetros. Elas são vitais para que o LLM use de maneira eficaz as
ferramentas disponíveis.
Como usar as ferramentas
Inclua ferramentas definidas nos comandos para gerar conteúdo.
Gerar
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' });
Arquivo de comando
---
system: "Answer questions using the tools you have."
tools: [getWeather]
input:
schema:
location: string
---
What is the weather in {{location}}?
Em seguida, execute o comando no código da seguinte maneira:
// 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],
});
O Genkit processará automaticamente a chamada de ferramenta se o LLM precisar usar a
ferramenta getWeather
para responder ao comando.
Como definir ferramentas dinamicamente no momento da execução
Como a maioria das coisas no Genkit, as ferramentas precisam ser predefinidas durante a inicialização do app. Isso é necessário para que você possa interagir com suas ferramentas na interface do desenvolvedor do Genkit. Essa é a maneira recomendada. No entanto, há cenários em que a ferramenta precisa ser definida dinamicamente de acordo com a solicitação do usuário.
É possível definir ferramentas dinamicamente usando a função ai.dynamicTool
. Essa
função é muito semelhante ao método ai.defineTool
. No entanto, as ferramentas dinâmicas
não são rastreadas pelo ambiente de execução do Genkit. Portanto, não é possível usar a interface do desenvolvedor do Genkit para
interagir com ele. Em vez disso, transmita-o para a chamada ai.generate
por
referência. Para ferramentas comuns, você também pode usar um nome de ferramenta de 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;
});
Ao definir ferramentas dinâmicas, para especificar esquemas de entrada e saída, use o Zod, conforme mostrado no exemplo anterior, ou transmita um esquema JSON construído manualmente.
const getWeather = ai.dynamicTool(
{
name: "getWeather",
description: "Gets the current weather in a given location",
inputJsonSchema: myInputJsonSchema,
outputJsonSchema: myOutputJsonSchema,
},
async (input) => { /* ... */ }
);
As ferramentas dinâmicas não exigem a função de implementação. Se você não transmitir a função, a ferramenta vai se comportar como uma interrupção, e você poderá fazer o tratamento manual de chamadas de ferramentas:
const getWeather = ai.dynamicTool(
{
name: "getWeather",
description: "Gets the current weather in a given location",
inputJsonSchema: myInputJsonSchema,
outputJsonSchema: myOutputJsonSchema,
}
);
Usar interrupções para pausar o ciclo de ferramentas
Por padrão, o Genkit chama o LLM repetidamente até que todas as chamadas de ferramentas sejam resolução. É possível pausar condicionalmente a execução em situações em que você quer, por exemplo:
- Fazer uma pergunta ao usuário ou mostrar a interface.
- Confirme uma ação potencialmente arriscada com o usuário.
- Solicitar aprovação fora da banda para uma ação.
As interrupções são ferramentas especiais que podem interromper o loop e retornar o controle ao código para que você possa lidar com cenários mais avançados. Acesse o guia de interrupções para saber como usá-las.
Processar explicitamente chamadas de ferramentas
Se quiser ter controle total sobre esse loop de chamada de ferramenta, por exemplo, para
aplicar uma lógica mais complexa, defina o parâmetro returnToolRequests
como true
.
Agora é
sua responsabilidade garantir que todas as solicitações de ferramentas sejam atendidas:
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;
}