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 uma chamada de função ou pesquisa de banco de dados for tudo o que for necessário para extrair as informações necessárias para o LLM, 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 o Gemini, pode fazer isso, mas modelos menores e mais especializados geralmente não conseguem. O Genkit vai gerar um erro se você tentar fornecer ferramentas para 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 mencionados na seção
anterior sejam atendidos, e a função genkit.Generate()
realiza automaticamente
o ciclo de chamada de ferramenta 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 exportar referências de modelo, a propriedade
ModelInfo.Supports.Tools
vai indicar se ele oferece suporte à chamada de ferramentas.
Como definir ferramentas
Use a função genkit.DefineTool()
para escrever definições de ferramentas:
import (
"context"
"log"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
func main() {
ctx := context.Background()
g, err := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.GoogleAI{}),
genkit.WithDefaultModel("googleai/gemini-2.0-flash"),
)
if err != nil {
log.Fatal(err)
}
getWeatherTool := genkit.DefineTool(
g, "getWeather", "Gets the current weather in a given location",
func(ctx *ai.ToolContext, location string) (string, error) {
// Here, we would typically make an API call or database query. For this
// example, we just return a fixed value.
return fmt.Sprintf("The current weather in %s is 63°F and sunny.", location);
})
}
A sintaxe aqui é semelhante à sintaxe genkit.DefineFlow()
. No entanto, você
precisa escrever uma descrição. Tenha cuidado redobrado com a escrita e os detalhes
da descrição, porque é essencial para que o LLM decida usá-la adequadamente.
Como usar as ferramentas
Inclua ferramentas definidas nos comandos para gerar conteúdo.
Gerar
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("What is the weather in San Francisco?"),
ai.WithTools(getWeatherTool),
)
DefinePrompt
weatherPrompt, err := genkit.DefinePrompt(g, "weatherPrompt",
ai.WithPrompt("What is the weather in {{location}}?"),
ai.WithTools(getWeatherTool),
)
if err != nil {
log.Fatal(err)
}
resp, err := weatherPrompt.Execute(ctx,
with.Input(map[string]any{"location": "San Francisco"}),
)
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 named weatherPrompt.prompt exists in ./prompts dir.
weatherPrompt := genkit.LookupPrompt("weatherPrompt")
if weatherPrompt == nil {
log.Fatal("no prompt named 'weatherPrompt' found")
}
resp, err := weatherPrompt.Execute(ctx,
ai.WithInput(map[string]any{"location": "San Francisco"}),
)
O Genkit processará automaticamente a chamada de ferramenta se o LLM precisar usar a
ferramenta getWeather
para responder ao comando.
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 a opção WithReturnToolRequests()
como true
. Agora é
sua responsabilidade garantir que todas as solicitações de ferramentas sejam atendidas:
getWeatherTool := genkit.DefineTool(
g, "getWeather", "Gets the current weather in a given location",
func(ctx *ai.ToolContext, location string) (string, error) {
// Tool implementation...
})
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("What is the weather in San Francisco?"),
ai.WithTools(getWeatherTool),
ai.WithReturnToolRequests(true),
)
if err != nil {
log.Fatal(err)
}
parts := []*Part{}
for _, req := range resp.ToolRequests() {
tool := genkit.LookupTool(g, req.Name)
if tool == nil {
log.Fatalf("tool %q not found", req.Name)
}
output, err := tool.RunRaw(ctx, req.Input)
if err != nil {
log.Fatalf("tool %q execution failed: %v", err)
}
parts = append(parts,
ai.NewToolResponsePart(&ai.ToolResponse{
Name: req.Name,
Ref: req.Ref,
Output: output,
}))
}
resp, err = genkit.Generate(ctx, g,
ai.WithMessages(resp.History()..., NewMessage(ai.RoleTool, nil, parts...)),
)
if err != nil {
log.Fatal(err)
}