Modelos de linguagem de grande escala (LLMs), como o Qwen3, são tradicionalmente limitados à entrada e saída de texto. No entento, para que possam interagir com o mundo real — chamar APIs, consultar bancos de dados ou controlar dispositivos — precisamos de um mecanismo de "callback". Este artigo explora como implementar essa funcionalidade, transformando um modelo local que não suporta callbacks nativos em um sistema capaz de executar funções externas.
O Conceito de Callback em Modelos de Linguagem
Um callback permite que um modelo de IA solicite a execução de uma função local e use o resultado para gerar uma resposta final. O fluxo básico é:
- O modelo recebe uma pergunta do usuário.
- Ele gera um texto com um placeholder, como
${weather('2025-05-17')}. - O sistema local substitui o placeholder pelo resultado da função (ex.: "35°C").
- O modelo recebe o texto preenchido e produz a resposta final (ex.: "Use roupas leves.").
Isso é alcançado através de engenharia de prompt cuidadosa, onde o modelo é instruído a usar funções específicas para obter informações necessárias.
Implementação Prática com Qwen3 0.6B
Vamos demonstrra a implementação usando o modelo Qwen3 0.6B rodando localmente via Ollama. O código abaixo mostra como configurar o ambiente e executar o fluxo de callback.
Configuração do Ambiente
Primeiro, instale o Ollama (https://ollama.com/) e faça o download do modelo:
ollama pull qwen3:0.6b
Em seguida, configure o Python e as dependências:
brew install python
mkdir ~/qwen3-callback
cd ~/qwen3-callback
python3 -m venv .
source ./bin/activate
python3 -m pip install requests
Código Principle
Salve o seguinte código em um arquivo chamado callback.py:
import requests
import re
import json
# Configuração da API Ollama
OLLAMA_URL = "http://localhost:11434/api/generate"
MODELO = "qwen3:0.6b"
# Funções simuladas para callback
def temperatura(data):
# Simula retorno de temperatura
return 35
def buscar_produtos(item):
# Simula busca de produtos
return """
Lista de {item} por marca:
- Apple: MacBook Pro, MacBook Air
- Dell: XPS, Inspiron
- HP: Spectre, Envy
- Lenovo: ThinkPad, IdeaPad
"""
def buscar_precos(item):
# Simula preço de produto
return f"{item}: R$ 5.999,00"
# Função para chamar o Ollama
def chamar_ollama(prompt):
payload = {
"model": MODELO,
"prompt": prompt,
"stream": False,
"temperature": 1
}
resposta = requests.post(OLLAMA_URL, json=payload)
if resposta.status_code == 200:
return json.loads(resposta.text)["response"]
else:
raise Exception(f"Erro na API Ollama: {resposta.text}")
# Extrai texto após o marcador "Resposta"
def extrair_apos_resposta(texto):
marcadores = ["Resposta", "resposta", "Saída:", "saída:"]
posicao_max = -1
marcador_usado = None
for marcador in marcadores:
try:
pos = texto.rindex(marcador)
if pos > posicao_max:
posicao_max = pos
marcador_usado = marcador
except ValueError:
continue
if posicao_max != -1:
return texto[posicao_max + len(marcador_usado):].strip()
return texto.strip()
# Processa placeholders e executa funções
def processar_placeholders(texto):
padrao = r'\${([^}]+)\}'
matches = re.findall(padrao, texto)
if not matches:
return texto
for match in matches:
if '(' in match and ')' in match:
nome_funcao = match.split('(')[0].strip()
argumento = match.split('(')[1].rstrip(')').strip()
if nome_funcao == "temperatura":
resultado = temperatura(argumento)
texto = texto.replace(f"${{{match}}}", f"{resultado}")
elif nome_funcao == "buscar_produtos":
resultado = buscar_produtos(argumento)
texto = texto.replace(f"${{{match}}}", resultado)
elif nome_funcao == "buscar_precos":
resultado = buscar_precos(argumento)
texto = texto.replace(f"${{{match}}}", f"R$ {resultado}")
else:
texto = texto.replace(f"${{{match}}}", "[Função desconhecida]")
else:
texto = texto.replace(f"${{{match}}}", "[Placeholder inválido]")
return texto
# Fluxo principal
def main():
# Entrada do usuário
entrada = "O que devo vestir hoje?"
print(f"Usuário: {entrada}")
print("=" * 40)
# Primeira chamada: modelo gera placeholder
prompt_inicial = f"""
Hoje é 17 de maio de 2025.
Pergunta do usuário: {entrada}
Funções disponíveis:
- temperatura('2025-05-17'): retorna a temperatura em Celsius.
- buscar_produtos(item): retorna informações sobre produtos.
- buscar_precos(item): retorna o preço de um produto.
Instruções: Se a pergunta precisar de informações de uma função, gere uma saída no formato:
${{funcao(argumento)}} fornece informações. Responda: {entrada}
Caso contrário, responda diretamente.
Exemplo:
- Entrada: "Está calor hoje?" -> Saída: "${{temperatura('2025-05-17')}} fornece informações. Responda: Está calor hoje?"
"""
resposta1 = chamar_ollama(prompt_inicial)
print(f"Primeira resposta do modelo: {resposta1}")
texto_extraido = extrair_apos_resposta(resposta1)
print(f"Texto após marcador: {texto_extraido}")
texto_processado = processar_placeholders(texto_extraido)
print(f"Texto com placeholders processados: {texto_processado}")
# Segunda chamada: resposta final
prompt_final = f"""
Com base nas informações a seguir, responda à pergunta do usuário:
{texto_processado}
"""
resposta_final = chamar_ollama(prompt_final)
print(f"Resposta final: {resposta_final}")
if __name__ == "__main__":
main()
Execução e Resultados
Ao executar o script com python3 callback.py, a saída será similar a:
Usuário: O que devo vestir hoje?
Primeira resposta do modelo: ... (thinking) ...
${{temperatura('2025-05-17')}} fornece informações. Responda: O que devo vestir hoje?
Texto processado: 35 fornece informações. Responda: O que devo vestir hoje?
Resposta final: Com 35°C, recomenda-se usar roupas leves, como camiseta e shorts.
O modelo consultou a função de temperatura, obteve o valor 35°C, e então gerou uma recomendação de vestuário adequada.
Aplicações e Limitações
Este padrão de callback permite que modelos locais pequenos realizem tarefas que exigem dados externos ou computação. No entanto, o sucesso depende fortemente da qualidade dos prompts e da capacidade do modelo de seguir instruções com precisão. Modelos menores exigem prompts mais explícitos e podem falhar em cenários complexos.