Oi pessoal, Nina aqui, de volta ao agntbox.com!
Você sabe, parece que foi ontem que eu estava tentando explicar para a minha tia Maria o que era uma “rede neural” (spoiler: não foi bem). Avançando para hoje, a IA está praticamente em toda parte. Desde me ajudar a redigir e-mails até gerar imagens para as minhas ridículas campanhas de D&D, essas ferramentas estão tornando nossas vidas, bem, mais fáceis. Mas com tantas opções surgindo diariamente, é fácil se perder no barulho. E, para ser honesta, muitas delas prometem mundos e fundos, mas entregam… um balão pequeno, um pouco murchinho.
É por isso que hoje eu quero falar sobre algo com o qual venho brincando nos últimos meses, algo que realmente cumpriu sua promessa: API de Chamada de Função da OpenAI. Especificamente, como isso está mudando a minha maneira de pensar sobre a construção de aplicações de IA verdadeiramente interativas, movendo-se além da simples geração de texto para ações reais e úteis. Esqueça aqueles chatbots pesados do passado; estamos falando de IA que pode entender a intenção e então fazer coisas no mundo real (ou pelo menos, dentro do mundo da sua aplicação).
Lembro de ter tentado construir um simples bot de clima há alguns anos. Envolvia regex intermináveis, declarações condicionais e uma oração para que o usuário digitasse exatamente o que eu esperava. Foi um pesadelo. A API de Chamada de Função? Parece mágica em comparação. Vamos nessa.
Além de Apenas Conversar: Por Que a Chamada de Função é Importante
Pense nisso: a maioria dos modelos de IA se destaca em entender a linguagem natural e gerar texto semelhante ao humano. Isso é fantástico para escrever posts em blogs (não este, obviamente, isso sou eu!), resumir documentos ou até mesmo fazer brainstorming de ideias. Mas e se você quiser que sua IA realmente interaja com sistemas externos? E se você quiser que ela:
- Busque um voo?
- Peça um café?
- Recupere dados específicos de um banco de dados?
- Envie um e-mail?
É aí que os modelos tradicionais de texto-para-texto batem na parede. Eles podem te dizer como fazer algo, mas não conseguem fazer isso por conta própria. Essa lacuna é exatamente o que a API de Chamada de Função da OpenAI visa preencher. Ela permite que você descreva as funções disponíveis para o modelo, e então o modelo decide se e quando chamar uma dessas funções, com base na entrada do usuário.
A beleza disso é que a IA não está realmente executando a função em si. Em vez disso, ela gera um objeto JSON estruturado que informa sua aplicação qual função chamar e com quais argumentos. Sua aplicação então pega esse JSON, executa a função real e retorna o resultado para a IA. Isso cria um loop poderoso: Usuário -> IA (identifica função) -> Sua App (executa função) -> IA (processa resultado) -> Usuário (recebe resposta/confirmação).
Meu Momento “Aha!”: Um Cenário de Casa Inteligente
Meu momento pessoal de “aha!” com a Chamada de Função surgiu quando eu tentava tornar minha configuração de casa inteligente um pouco mais inteligente. Tenho um monte de luzes Philips Hue, um termostato inteligente e alguns plugs inteligentes. Eu construí um aplicativo simples em Flask que expõe esses dispositivos como endpoints de API. Antes da Chamada de Função, eu tinha um sistema complicado de palavras-chave que acionavam ações específicas. “Acenda as luzes da sala de estar” funcionava, mas “Ei, está um pouco escuro aqui, você pode tornar a sala de estar mais iluminada?” só me rendia um olhar em branco do meu aplicativo.
Com a Chamada de Função, defini funções como set_light_brightness(room: str, brightness: int) ou adjust_thermostat(temperature: int). Então, descrevi essas funções para o modelo da OpenAI. Agora, quando eu digo, “Está um pouco escuro aqui, você pode fazer a sala de estar mais iluminada?”, o modelo identifica corretamente que eu quero usar set_light_brightness para a “sala de estar” e pode até inferir um valor padrão de “brilho” ou pedir esclarecimentos. É uma mudança sutil, mas profunda, na naturalidade da interação.
Como Funciona: Um Mergulho Rápido (Sem Parte Profunda, Eu Prometo)
A ideia central é bem simples. Você fornece ao modelo da OpenAI uma lista de funções que sua aplicação pode realizar, junto com seus parâmetros. Você descreve essas funções usando um Schema JSON, que é uma forma padrão de descrever a estrutura dos dados JSON. Pense nisso como um projeto para suas funções.
Quando você envia a mensagem de um usuário para o modelo, você também envia essa lista de funções. O modelo então analisa a mensagem do usuário e decide se uma das suas funções seria útil para atender à intenção do usuário. Se decidir chamar uma função, retorna uma mensagem contendo o nome da função a chamar e os argumentos a serem passados, tudo em um formato JSON estruturado.
Exemplo Prático: Uma Ferramenta Simples de Clima
Vamos passar por um exemplo super básico: uma ferramenta de clima. Imagine que você tem um endpoint de API que pode buscar dados de clima para uma cidade específica.
Primeiro, você definiria sua função. Em Python, ela poderia ser assim:
def get_current_weather(location: str, unit: str = "fahrenheit"):
"""
Obtém o clima atual em uma determinada localização.
Args:
location (str): A cidade e estado, por exemplo, San Francisco, CA
unit (str, opcional): A unidade de temperatura. Pode ser 'celsius' ou 'fahrenheit'. Padrão é 'fahrenheit'.
Returns:
dict: Um dicionário contendo informações sobre o clima.
"""
# Em uma aplicação real, você chamaria uma API externa de clima aqui
if location == "Boston, MA":
return {"location": "Boston, MA", "temperature": "50", "unit": unit, "forecast": "cloudy"}
elif location == "San Francisco, CA":
return {"location": "San Francisco, CA", "temperature": "68", "unit": unit, "forecast": "sunny"}
else:
return {"location": location, "temperature": "N/A", "unit": unit, "forecast": "unknown"}
Em seguida, você descreveria essa função para a OpenAI usando um Schema JSON. Isso informa ao modelo o que a função faz, quais argumentos recebe e seus tipos.
functions = [
{
"name": "get_current_weather",
"description": "Obtém o clima atual em uma determinada localização",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "A cidade e estado, por exemplo, San Francisco, CA",
},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
},
}
]
Agora, quando um usuário pergunta, “>Como está o clima em Boston?”, você enviaria isso para a API da OpenAI:
import openai
# Supondo que você tenha sua chave de API da OpenAI configurada
messages = [{"role": "user", "content": "Como está o clima em Boston?"}]
response = openai.chat.completions.create(
model="gpt-3.5-turbo-0613", # Ou gpt-4-0613 para melhores resultados
messages=messages,
functions=functions,
function_call="auto", # Isso informa ao modelo para chamar uma função se achar apropriado
)
response_message = response.choices[0].message
O objeto response_message conterá um atributo function_call. Não será uma resposta de texto direto. Em vez disso, terá uma aparência semelhante a esta:
{
"role": "assistant",
"function_call": {
"name": "get_current_weather",
"arguments": "{\n \"location\": \"Boston, MA\"\n}"
}
}
Sua aplicação então analisa isso, chama sua função get_current_weather com location="Boston, MA", e obtém o resultado. Então, você alimenta esse resultado de volta ao modelo da OpenAI:
# Supondo que 'response_message' seja o que veio acima
if response_message.function_call:
function_name = response_message.function_call.name
function_args = json.loads(response_message.function_call.arguments)
# Executa a função
function_response = get_current_weather(
location=function_args.get("location"),
unit=function_args.get("unit")
)
# Adiciona a chamada da função e sua resposta ao histórico de mensagens
messages.append(response_message) # A chamada da função do assistente
messages.append(
{
"role": "function",
"name": function_name,
"content": json.dumps(function_response),
}
)
# Obtém uma nova resposta do modelo, agora com a saída da função
second_response = openai.chat.completions.create(
model="gpt-3.5-turbo-0613",
messages=messages,
)
print(second_response.choices[0].message.content)
E é aí que você receberá uma resposta em linguagem natural como, “O clima atual em Boston, MA é de 50 graus Fahrenheit e nublado.”
Minha Experiência: O Bom, as Particularidades e o que Aprendi
Uso da Chamada de Função realmente mudou a forma como eu abordo a construção de recursos impulsionados por IA. Parece menos como adivinhar o que o usuário quer e mais como guiar a IA para entender e agir.
O Bom:
- Redução de Engenharia de Prompt: Sério, isso é grande. Em vez de escrever prompts elaborados tentando forçar a IA a um formato de saída específico ou esperando que ela entenda o que fazer, você apenas lhe dá as ferramentas (suas funções) e deixa que ela decida.
- Aumento da Precisão na Intenção: O modelo é surpreendentemente bom em descobrir qual função chamar, mesmo com frases ambíguas. Isso torna a experiência do usuário muito mais suave.
- Saídas Estruturadas: Receber um objeto JSON de volta para chamadas de função é um sonho para os desenvolvedores. Nada mais tentando analisar linguagem natural em dados estruturados.
- Extensibilidade: À medida que sua aplicação cresce, você apenas adiciona mais definições de funções. A lógica principal para interagir com a IA permanece praticamente a mesma.
As Particularidades (e Como Eu Lidei Com Elas):
- Chamadas excessivas de funções: Às vezes, o modelo pode ser um pouco ansioso em chamar uma função, mesmo quando uma simples resposta em texto seria suficiente. Descobri que ser muito preciso nas descrições das minhas funções e adicionar exemplos claros no prompt inicial do modelo (se necessário) ajudou. Além disso, você pode definir
function_call="none"para impedir explicitamente chamadas de funções oufunction_call={"name": "my_function"}para forçar uma chamada de função específica. - Incompatibilidade de Argumentos: O modelo pode às vezes tentar chamar uma função com argumentos que não correspondem exatamente ao seu esquema ou inventar argumentos. Isso geralmente acontece quando a descrição da função não está cristalina. Iterar na
descriptionda função e em seusparametersé fundamental. - A Dança de Múltiplas Interações: Lembre-se, você está construindo uma conversa. Após seu aplicativo executar uma função, você deve alimentar o resultado de volta ao modelo como uma mensagem de papel de “função”. Esquecer isso quebra o fluxo da conversa e a IA não saberá o que aconteceu. Esse foi um erro comum para mim inicialmente.
- Considerações de Custo: Cada turno na conversa, especialmente quando funções estão envolvidas, consome tokens. Se você tiver muitas funções ou resultados de funções muito verbosos, isso pode se acumular. Fique atento ao tamanho das descrições das suas funções e aos dados que você retorna das suas funções.
Uma lição específica: ao descrever suas funções, não liste apenas os parâmetros. Explique por que alguém usaria essa função e que tipo de entrada ela espera. Por exemplo, em vez de apenas location: str, diga location: A cidade e o estado, por exemplo, 'San Francisco, CA' ou 'New York City, NY'. Esses pequenos detalhes fazem uma grande diferença na precisão com que o modelo interpreta a intenção do usuário.
Resumo Acionável para Seu Próximo Projeto de IA
Se você está construindo algo que vai além da simples geração de texto, recomendo fortemente explorar a API de Chamadas de Função da OpenAI. Aqui estão minhas sugestões:
- Comece Simples: Não tente integrar todos os endpoints de API que você tem de uma vez. Escolha uma ou duas ações principais que sua IA deve ser capaz de realizar e defina funções para elas.
- Seja Explícito nas Descrições das Suas Funções: Pense nas descrições das suas funções como mini-prompts para a IA. Quanto mais claramente você descrever o que a função faz, seus parâmetros e exemplos de entrada válida, melhor o modelo irá funcionar.
- Trate Erros com Elegância: Suas funções externas podem falhar. Certifique-se de que seu aplicativo possa capturar esses erros e fornecer uma mensagem de erro útil de volta à IA (e, subsequentemente, ao usuário). A IA pode então se desculpar ou sugerir alternativas.
- Fique Atento à Janela de Contexto: Lembre-se de que todo o histórico da conversa, incluindo chamadas de funções e seus resultados, conta para a janela de contexto do modelo. Para interações longas e complexas, você pode precisar de estratégias para gerenciar o contexto (por exemplo, resumindo turnos passados).
- Teste, Teste, Teste: Teste suas funções com vários prompts de usuários, incluindo os ambíguos, para ver como o modelo os interpreta. Este processo iterativo é crucial para refinar suas descrições de funções.
A chamada de funções é um passo significativo em direção a assistentes de IA verdadeiramente úteis e interativos. Isso nos aproxima de um futuro onde a IA não é apenas um parceiro de conversa, mas um agente capaz que pode nos ajudar a realizar tarefas. Experimente – você pode descobrir que isso muda sua abordagem ao desenvolvimento de IA também.
Até a próxima, continue construindo coisas legais!
Nina
🕒 Published: