Skip to main content

LLM Helper

Visão Geral

O LLMHelper permite fazer chamadas de completion para LLMs diretamente dentro de actions, seguindo o padrão LiteLLM/OpenAI chat completions. Oferece suporte a modelos customizáveis, controle de temperatura e retorno estruturado JSON, além de gerar automaticamente generations no LangFuse para observabilidade.

Características Principais

  • 🔌 Padrão OpenAI: Interface compatível com chat completions
  • 🎯 Retorno estruturado: JSON schemas para dados organizados
  • 🌡️ Controle de temperatura: Ajuste de criatividade (0.0 a 1.0)
  • 🔍 Observabilidade: Generations automáticas no LangFuse
  • ⚙️ Flexível: Suporte a modelos customizados e parâmetros extras

🚀 Método Principal

completion(system_prompt, user_prompt, response_format=None, model=None, temperature=0.3, generation_name="llm-helper-completion", **kwargs)

Executa completion de LLM com suporte a retorno estruturado e observabilidade automática.

Parâmetros:

  • system_prompt (str): Obrigatório - Instruções e contexto para o modelo
  • user_prompt (str): Obrigatório - Mensagem/query do usuário
  • response_format (Dict): Schema JSON para retorno estruturado (opcional)
  • model (str): Modelo específico a usar (opcional, usa o mesmo modelo do agent se não passado)
  • temperature (float): Criatividade do modelo, 0.0 a 1.0 (padrão: 0.3)
  • generation_name (str): Nome do span no LangFuse (padrão: "llm-helper-completion")
  • **kwargs: Parâmetros adicionais (max_tokens, top_p, etc.)

Quando utilizar:

  • Processar dados complexos dentro de actions
  • Gerar conteúdo estruturado (JSON)
  • Análise de textos ou documentos
  • Transformações e extrações de dados
  • Qualquer tarefa que precise de LLM durante execução

Resultado esperado:

  • Com response_format: Objeto JSON parseado automaticamente
  • Sem response_format: {"content": "texto_da_resposta"}
  • Generation automática no LangFuse para tracking

📝 Exemplos Práticos

Exemplo 1: Retorno Estruturado (JSON Schema)

Baseado no exemplo de geração de nome pirata:

def gerar_nome_pirata(name: str):
# Schema JSON para resposta estruturada
pirate_response_schema = {
"type": "json_schema",
"json_schema": {
"name": "pirate_name_response",
"schema": {
"type": "object",
"properties": {
"pirate_name": {
"type": "string",
"description": "Nome de pirata gerado"
},
"pirate_title": {
"type": "string",
"description": "Título ou alcunha do pirata"
},
"origin_explanation": {
"type": "string",
"description": "Explicação de como o nome foi derivado"
},
"pirate_backstory": {
"type": "string",
"description": "Breve história de fundo do pirata"
},
"ship_name": {
"type": "string",
"description": "Nome do navio pirata"
}
},
"required": ["pirate_name", "pirate_title", "origin_explanation"],
"additionalProperties": False
}
}
}

system_prompt = """Você é um criativo gerador de nomes piratas.
Crie um nome pirata baseado no nome fornecido, inclua título/alcunha,
explique a derivação, crie história de fundo e nome do navio.
Seja criativo e divertido! Responda SEMPRE em português brasileiro."""

user_prompt = f"""Transforme o nome "{name}" em um nome de pirata épico.
Crie: nome pirata, título, explicação da derivação, história e nome do navio."""

# Chamada com retorno estruturado
llm_result = llm_helper.completion(
system_prompt=system_prompt,
user_prompt=user_prompt,
response_format=pirate_response_schema,
temperature=0.8, # Mais criativo
generation_name="pirate-name-generation"
)

# Resultado já é um objeto JSON parseado
pirate_name = llm_result['pirate_name']
pirate_title = llm_result['pirate_title']
backstory = llm_result['pirate_backstory']

return llm_result # Objeto completo com todos os campos

Exemplo 2: Retorno Simples (Texto)

def analisar_documento(text: str):
system_prompt = """Você é um especialista em análise de documentos.
Analise o texto fornecido e identifique se é um documento válido,
seu tipo e pontos importantes."""

user_prompt = f"Analise este documento:\n\n{text}"

# Chamada simples sem estrutura
result = llm_helper.completion(
system_prompt=system_prompt,
user_prompt=user_prompt,
temperature=0.1, # Mais determinístico
generation_name="document-analysis"
)

# Resultado: {"content": "Análise do documento..."}
analysis_text = result['content']

return analysis_text

Exemplo 3: Modelo e Parâmetros Customizados

def processar_com_modelo_especifico(data: str):
system_prompt = "Você é um assistente especializado."
user_prompt = f"Processe estes dados: {data}"

result = llm_helper.completion(
system_prompt=system_prompt,
user_prompt=user_prompt,
model="gpt-4o", # Modelo específico
temperature=0.7,
generation_name="custom-processing",
max_tokens=1000, # Parâmetro adicional
top_p=0.9, # Parâmetro adicional
)

return result['content']

🎯 Schemas JSON Estruturados

Formato do Response Format

# Estrutura básica do schema
response_format = {
"type": "json_schema",
"json_schema": {
"name": "nome_do_schema",
"schema": {
"type": "object",
"properties": {
"campo1": {
"type": "string",
"description": "Descrição do campo"
},
"campo2": {
"type": "number",
"description": "Campo numérico"
}
},
"required": ["campo1"],
"additionalProperties": False
}
}
}

Exemplos de Schemas Úteis

Extração de Dados Pessoais

personal_data_schema = {
"type": "json_schema",
"json_schema": {
"name": "personal_data_extraction",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string", "description": "Nome completo"},
"cpf": {"type": "string", "description": "CPF encontrado"},
"email": {"type": "string", "description": "Email encontrado"},
"phone": {"type": "string", "description": "Telefone encontrado"},
"address": {"type": "string", "description": "Endereço completo"},
"confidence": {"type": "number", "description": "Confiança na extração (0-1)"}
},
"required": ["name", "confidence"],
"additionalProperties": False
}
}
}

Classificação de Documentos

document_classification_schema = {
"type": "json_schema",
"json_schema": {
"name": "document_classification",
"schema": {
"type": "object",
"properties": {
"document_type": {
"type": "string",
"enum": ["RG", "CPF", "CNH", "Passport", "Unknown"],
"description": "Tipo do documento identificado"
},
"is_valid": {"type": "boolean", "description": "Se o documento é válido"},
"extracted_info": {
"type": "object",
"description": "Informações extraídas do documento"
},
"confidence_score": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Score de confiança"
}
},
"required": ["document_type", "is_valid", "confidence_score"],
"additionalProperties": False
}
}
}

💡 Casos de Uso Comuns

✅ Processamento de Formulários

def extrair_dados_formulario(form_text: str):
schema = {
"type": "json_schema",
"json_schema": {
"name": "form_data",
"schema": {
"type": "object",
"properties": {
"nome": {"type": "string"},
"email": {"type": "string"},
"telefone": {"type": "string"},
"endereco": {"type": "string"},
"servico_solicitado": {"type": "string"},
"observacoes": {"type": "string"}
},
"required": ["nome", "email"],
"additionalProperties": False
}
}
}

return llm_helper.completion(
system_prompt="Extraia dados estruturados deste formulário.",
user_prompt=form_text,
response_format=schema,
temperature=0.1
)

✅ Análise de Sentimento

def analisar_sentimento(message: str):
schema = {
"type": "json_schema",
"json_schema": {
"name": "sentiment_analysis",
"schema": {
"type": "object",
"properties": {
"sentiment": {
"type": "string",
"enum": ["positive", "negative", "neutral"]
},
"confidence": {"type": "number", "minimum": 0, "maximum": 1},
"emotions": {
"type": "array",
"items": {"type": "string"}
},
"summary": {"type": "string"}
},
"required": ["sentiment", "confidence"],
"additionalProperties": False
}
}
}

return llm_helper.completion(
system_prompt="Analise o sentimento desta mensagem.",
user_prompt=message,
response_format=schema,
generation_name="sentiment-analysis"
)

✅ Validação de Dados

def validar_cpf_com_llm(cpf: str, nome: str):
system_prompt = """Você é um validador de dados.
Analise se o CPF está no formato correto e se faz sentido
com o nome fornecido."""

result = llm_helper.completion(
system_prompt=system_prompt,
user_prompt=f"CPF: {cpf}, Nome: {nome}",
response_format={
"type": "json_schema",
"json_schema": {
"name": "cpf_validation",
"schema": {
"type": "object",
"properties": {
"is_valid_format": {"type": "boolean"},
"seems_legitimate": {"type": "boolean"},
"issues": {"type": "array", "items": {"type": "string"}},
"confidence": {"type": "number"}
},
"required": ["is_valid_format", "seems_legitimate"],
"additionalProperties": False
}
}
},
temperature=0.2
)

return result

⚠️ Considerações Importantes

Controle de Temperature

# Temperature baixa (0.0 - 0.3) - Mais determinístico
result = llm_helper.completion(
system_prompt="Extraia dados precisos...",
user_prompt=text,
temperature=0.1 # Para tarefas que precisam de precisão
)

# Temperature média (0.4 - 0.7) - Balanceado
result = llm_helper.completion(
system_prompt="Analise e sugira...",
user_prompt=text,
temperature=0.5 # Para análises balanceadas
)

# Temperature alta (0.8 - 1.0) - Mais criativo
result = llm_helper.completion(
system_prompt="Seja criativo...",
user_prompt=text,
temperature=0.8 # Para geração criativa
)

Tratamento de Erros

def chamada_segura_llm():
try:
result = llm_helper.completion(
system_prompt="...",
user_prompt="...",
response_format=schema,
temperature=0.3
)
return result
except Exception as e:
# Log automático já foi feito pelo LLMHelper
return {"error": f"Falha na chamada LLM: {str(e)}"}

Boas Práticas

# ✅ Bom - Schema bem definido
schema = {
"type": "json_schema",
"json_schema": {
"name": "clear_schema_name",
"schema": {
"type": "object",
"properties": {
"field": {
"type": "string",
"description": "Descrição clara"
}
},
"required": ["field"],
"additionalProperties": False # Importante!
}
}
}

# ✅ Bom - Generation names descritivos
llm_helper.completion(
system_prompt="...",
user_prompt="...",
generation_name="document-classification-cpf" # Específico
)

# ❌ Evitar - Schema muito complexo ou sem required
# ❌ Evitar - Temperature muito alta para dados estruturados
# ❌ Evitar - Prompts muito longos sem estrutura
Observabilidade Automática

O LLMHelper cria automaticamente generations no LangFuse para cada chamada, permitindo rastreamento completo de performance, custos e qualidade das respostas LLM dentro das Actions.

Cuidado com Temperature

Para dados estruturados e extrações precisas, use temperature baixa (0.0-0.3). Para tarefas criativas, use temperature alta (0.7-1.0). O padrão 0.3 é um bom equilíbrio para a maioria dos casos.

O LLMHelper oferece uma interface poderosa e flexível para integrar capacidades de LLM diretamente nas actions, com observabilidade completa e suporte a dados estruturados!


JSON Schema

  • What is JSON Schema? - Documentação oficial sobre JSON Schema, padrão utilizado para definir estruturas de dados no response_format

OpenAI Structured Outputs