Análises Estruturadas
As Análises Estruturadas permitem extrair insights e métricas de conversas ou qualquer texto, retornando resultados em JSON conforme os campos que você definiu na interface visual sem precisar lidar diretamente com schemas.
Visão Geral
O que são: Pense nelas como assistentes de IA que você configura para ler textos (como e-mails, transcrições de chamadas ou chats) e extrair informações específicas — como números, palavras-chave, ou respostas do tipo sim/não. O resultado é sempre um resumo organizado e padronizado (em formato JSON), pronto para ser usado, sem que você precise se preocupar com a formatação técnica complexa dos dados.
Quando usar: São ideais para automatizar tarefas como:
- Analisar o sentimento expresso em feedbacks de clientes (positivo, negativo, neutro).
- Identificar os principais assuntos discutidos em conversas de suporte ou vendas.
- Coletar dados para indicadores personalizados de desempenho, qualidade, ou qualquer outra métrica importante para o seu negócio.
Principais benefícios:
Padronização de relatórios e integrações: Por gerar resultados determinísticos em JSON, facilita a integração com qualquer sistema externo como CRMs, dashboards, planilhas Google Sheets, ou ferramentas de BI para análise automática de chamadas, conversas e textos.
Economia de tempo e recursos: Automatiza processos que seriam manuais e trabalhosos, permitindo que a IA faça análises complexas em segundos que levariam horas para serem realizadas por humanos.
Flexibilidade de análise: Permite criar diferentes tipos de análises para extrair insights específicos de acordo com suas necessidades de negócio.
Escalabilidade: Processa volumes grandes de conversas com consistência, mantendo a qualidade da análise mesmo com crescimento significativo de dados.
Criando uma Análise
Clique em Nova Análise no canto superior direito. Você verá duas opções:
- Criar nova: iniciar uma análise do zero.
- Usar template: escolher um dos templates disponíveis (Sumário, Tradução, Classificação de Texto, Análise de Sentimento, Extração de Entidades, Análise Estrutural, Análise de Discurso, Análise de Conversação, Análise de Desempenho de Atendente etc.) como ponto de partida.
Ao selecionar Criar nova, o modal de criação abre em branco. Ao selecionar Usar template, o modal abre com os campos do template pré‑preenchidos — você pode modificar, remover ou adicionar campos conforme seu caso de uso.
No modal de criação, preencha:
- Modelo: escolha um modelo compatível.
- Nome: identificador único (ex:
performance_atendimento
). - Descrição: objetivo da análise (ex: “Avalia tempo de resposta e resolução de chamados”). Esta descrição é importante pois o modelo de llm usará para entender o que você espera dele.
Pontos Importantes
Compatibilidade de Modelos: Ao criar uma análise, a lista de modelos exibirá apenas aqueles que suportam a extração de dados estruturados. Isso significa que nem todos os modelos de linguagem (LLMs) disponíveis na plataforma SipPulse AI serão compatíveis com esta funcionalidade.
Modelo de Custo: A utilização das Análises Estruturadas é cobrada por execução. O custo é calculado com base no volume de tokens de entrada (input) e saída (output) processados pelo modelo de IA escolhido.
Defina a Estrutura:
- Clique em + Campo para adicionar novos resultados.
- Escolha o Tipo (Número / Texto / Booleano / Enum / Lista de texto / Lista de números / etc)
- Informe o Nome do campo em formato
snake_case
(ex:nome_do_cliente
,valor_total
). Este padrão utiliza letras minúsculas e separa as palavras com underscores (_). Usarsnake_case
é importante para manter a consistência e facilitar a leitura e integração dos resultados JSON. - Adicione uma Descrição clara para o campo, explicando o que ele representa. Isso ajudará o modelo de IA a entender o que extrair e também facilitará a compreensão dos resultados por outros usuários.
- Marque Obrigatório, se for essencial para seu fluxo.
Clique em Salvar para criar a análise.
Dica
Templates são somente inspirações e ajudam a acelerar a configuração. Você pode usar, editar ou descartar qualquer campo pré‑preenchido.
Testando na interface
Após criar a sua análise, você verá ela na tabela de análises. Para testá-la, siga os passos abaixo:
- Na lista de análises, clique em ⚗️ Testar.
- No modal Executar Análise Estruturada, cole seu texto ou transcrição.
- Clique em Executar e confira o JSON resultante.
Dica
Utilize os testes para prototipar e validar a estrutura da análise antes de integrá-la em produção.
Integração com Agentes (Pós-Análise)
A integração com os agentes é um recurso bastante poderoso, permitindo que você automatize a execução de análises estruturadas ao encerrar uma conversa. Isso é especialmente útil para garantir que todas as interações sejam analisadas e relatórios sejam gerados automaticamente.
- Em Agentes → Criar/Editar → aba Pós-Análise, ative os toggles das análises desejadas.
- Salve o agente.
As análises serão executadas sempre que a conversa for encerrada, independentemente do método:
- Ligação de voz: quando o agente encerra a chamada.
- Chat: invocação de
end_dialog
em WhatsApp ou chat.- UI: clique no botão Encerrar conversa na janela da conversa.
- API: chamada ao endpoint
POST /threads/{id}/close
(veja docs).
Obtendo resultados
Via interface
Se você quiser ver as análises pela interface, clique no botão de informação da conversa (canto superior direito, ícone de "i") que você está monitorando. Caso haja alguma análise, você verá ela listada na sessão com o título de Pós-Análise.
Atenção
Para visualizar as análises na interface, certifique-se de que:
- A conversa foi encerrada.
- O agente associado à conversa possui as análises desejadas habilitadas na aba Pós-Análise.
Caso contrário, a seção de Pós-Análise não estará visível.
Via API
Você pode acessar a conversa a partir do endpoint GET /threads/{id}` (veja docs).
No retorno, você verá um campo post_analysis
com os resultados das análises. Exemplo de resposta:
{
"id": "thr_0196d90af689765f974e5d4c8631d47c",
"title": "Saudação em Português",
"status": "closed",
"history": [ /* mensagens */ ],
"post_analysis": [
{
"name": "conversa_suspeita",
"description": "Faz uma análise para saber se dada conversa é suspeita ou não.",
"content": {
"score": 0,
"reason": "A conversa é cordial e não apresenta conteúdo suspeito."
}
},
{
"name": "sentimento",
"description": "Determina sentimento da conversa",
"content": {
"sentiment": "neutro"
}
}
]
}
Via Webhook
Você também pode receber as análises via webhook, inscrevendo-se no evento thread.closed
. Se você não está familiarizado com os webhooks na plataforma, consulte a documentação de Webhooks.
Dentro do webhook você receberá um evento thread.closed
com o seguinte payload:
{
"event": "thread.closed",
"data": {
"id": "thr_0196d90af689765f974e5d4c8631d47c",
"title": "Saudação em Português",
"status": "closed",
"history": [ /* mensagens */ ],
"post_analysis": [ /* resultados das análises */ ]
}
}
Observação: omita campos sensíveis ou grandes (
history
,agent_snapshot
) para foco nos resultados.
Exemplos de Integração via API
Você pode incorporar análises estruturadas em qualquer fluxo do seu sistema, bastando chamar o endpoint de execução.
Importante
- Requisitos: você precisa ter uma análise criada e o ID dela para executar a análise. Você pode encontrar o ID na interface, clicando no botão com ícone ID
- Autenticação: utilize o header
api-key
com seu token de API. - Formato: o conteúdo deve ser enviado como um JSON com o campo
content
contendo o texto a ser analisado. - Retorno: o resultado da análise será retornado no campo
content
do JSON.
// Executa análise estruturada via API
enumir async function executeAnalysis(
content: string,
analysisId: string
): Promise<any> {
const baseUrl = 'https://api.sippulse.ai';
const apiKey = process.env.SIPPULSE_API_KEY;
const headers = {
'Content-Type': 'application/json',
'api-key': apiKey,
};
const response = await fetch(
`${baseUrl}/structured-analyses/${analysisId}/execute`,
{
method: 'POST',
headers,
body: JSON.stringify({ content }),
}
);
if (!response.ok) {
throw new Error(`Erro ao executar análise: ${response.status}`);
}
return response.json();
}
// Exemplo de uso:
(async () => {
const sampleContent = "Olá! Gostaria de saber se este atendimento foi satisfatório.";
const analysisId = "YOUR_ANALYSIS_ID";
try {
const result = await executeAnalysis(sampleContent, analysisId);
console.log("Resultado da análise:", JSON.stringify(result.content ?? result, null, 2));
} catch (err) {
console.error("Falha na execução:", err);
}
})();
import requests
import json
import os
API_BASE = 'https://api.sippulse.ai' # Abstraído em variável
SIPPULSE_API_KEY = os.environ.get('SIPPULSE_API_KEY')
def execute_analysis(content: str, analysis_id: str) -> dict:
"""Executa análise estruturada via API"""
headers = {
'Content-Type': 'application/json',
'api-key': SIPPULSE_API_KEY # Adicionado API Key
}
response = requests.post(
f"{API_BASE}/structured-analyses/{analysis_id}/execute", # Usando API_BASE
headers=headers,
json={'content': content}
)
if not response.ok:
raise Exception(f"Erro ao executar análise: {response.status_code} {response.text}")
return response.json()
# Exemplo de uso:
if __name__ == "__main__":
sample_content = "Olá! Gostaria de saber se este atendimento foi satisfatório."
analysis_id = "YOUR_ANALYSIS_ID" # Substitua pelo ID da sua análise
if not SIPPULSE_API_KEY:
print("Erro: A variável de ambiente SIPPULSE_API_KEY não está definida.")
else:
try:
result = execute_analysis(sample_content, analysis_id)
print("Resultado da análise:", json.dumps(result.get('content', result), indent=2))
except Exception as e:
print("Falha na execução:", e)
Caso de Uso: Transcrição de Áudio e Análise
Em cenários de envolvam transcrição de chamadas, você pode automatizar todo o fluxo de transcrição e análise em duas etapas:
- Transcrevendo o audio da chamada.
- Extraindo relatórios de desempenho, sentimento e indicadores de qualidade de atendimento ou qualquer outra métrica desejada.
- Armazenando os resultados em um banco de dados ou enviando para outro sistema.
Por que usar esse fluxo:
- Aproveitar automaticamente gravações de chamadas para gerar insights sem intervenção manual.
- Integrar com sistemas de call center ou CRM, acionando análises assim que o áudio estiver disponível.
- Monitorar qualidade de atendimento e métricas de negócios (tempo de resposta, satisfação, etc.).
Recomendação: adicione
format=diarization
na requisição de transcrição para separar falantes, melhorando a precisão de métricas como tempo de fala por participante e análise de sentimento.Como executar:
- Chamada direta: envie o áudio via API de transcrição e, ao receber a resposta, faça a chamada para análise estruturada no mesmo fluxo.
- Via Webhook: configure Webhook de transcrição em Webhooks → evento
asr.transcribe
. Ao receber o webhook, extraiabody.text
e dispare o endpoint de análise automaticamente.
import FormData from 'form-data';
import fs from 'fs';
const API_BASE = 'https://api.sippulse.ai';
const API_KEY = process.env.SIPPULSE_API_KEY;
async function transcribeAndAnalyze(
fileBuffer: Buffer,
analysisId: string
) {
// 1. Transcrever áudio com diarização
const form = new FormData();
form.append('file', fileBuffer, 'audio.wav');
form.append('model', 'pulse-precision');
form.append('format', 'diarization');
const asrRes = await fetch(`${API_BASE}/asr/transcribe`, {
method: 'POST',
body: form,
headers: {
'Content-Type': `multipart/form-data`,
'api-key': API_KEY,
}
});
if (!asrRes.ok) throw new Error('Erro na transcrição');
const { text } = await asrRes.json();
// 2. Executar análise estruturada
const analysisRes = await fetch(
`${API_BASE}/structured-analyses/${analysisId}/execute`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json', 'api-key': API_KEY },
body: JSON.stringify({ content: text }),
}
);
if (!analysisRes.ok) throw new Error('Erro na análise');
const { content } = await analysisRes.json();
return content;
}
// Exemplo de execução completa
(async () => {
const fileBuffer = fs.readFileSync('audio.wav');
const analysisId = 'YOUR_ANALYSIS_ID'; // Você pode copiar o ID da sua análise na interface, clicando no botão ID
try {
const results = await transcribeAndAnalyze(fileBuffer, analysisId);
console.log('Resultados da transcrição e análise:', JSON.stringify(results, null, 2));
} catch (err) {
console.error('Erro:', err);
}
})();
import requests
import json
import os
from io import BytesIO
API_BASE = 'https://api.sippulse.ai' # Abstraído em variável
SIPPULSE_API_KEY = os.environ.get('SIPPULSE_API_KEY')
def transcribe_and_analyze(
file_bytes: bytes,
analysis_id: str
) -> dict: # Alterado o tipo de retorno para dict para corresponder ao 'content'
headers_asr = {
'api-key': SIPPULSE_API_KEY # Adicionado API Key para ASR
}
# 1. Transcrição com diarização
resp_asr = requests.post(
f"{API_BASE}/asr/transcribe", # Usando API_BASE
files={
'file': ('audio.wav', BytesIO(file_bytes)),
'model': (None, 'pulse-precision'),
'format': (None, 'diarization')
},
headers=headers_asr # Adicionado headers com API Key
)
resp_asr.raise_for_status()
transcript = resp_asr.json()['text']
headers_analysis = {
'Content-Type': 'application/json',
'api-key': SIPPULSE_API_KEY # Adicionado API Key para Análise
}
# 2. Análise estruturada
resp_analysis = requests.post(
f"{API_BASE}/structured-analyses/{analysis_id}/execute", # Usando API_BASE
headers=headers_analysis, # Adicionado headers com API Key
json={'content': transcript}
)
resp_analysis.raise_for_status()
# Retorna o conteúdo da análise, similar ao exemplo TypeScript
return resp_analysis.json().get('content', resp_analysis.json())
if __name__ == '__main__':
if not SIPPULSE_API_KEY:
print("Erro: A variável de ambiente SIPPULSE_API_KEY não está definida.")
else:
# Simula a leitura de um arquivo de áudio para o exemplo
# Em um caso real, você leria um arquivo existente:
# with open('audio.wav', 'rb') as f:
# file_bytes = f.read()
# Para este exemplo, vamos criar um placeholder de bytes
try:
# Criar um arquivo audio.wav dummy para o exemplo rodar
if not os.path.exists('audio.wav'):
with open('audio.wav', 'wb') as f:
f.write(b'dummy audio data') # Conteúdo placeholder
with open('audio.wav', 'rb') as f:
file_bytes = f.read()
analysis_id = 'YOUR_ANALYSIS_ID' # Substitua pelo ID da sua análise
results = transcribe_and_analyze(file_bytes, analysis_id)
print('Resultados da transcrição e análise:', json.dumps(results, indent=2))
except FileNotFoundError:
print("Erro: O arquivo 'audio.wav' não foi encontrado. Crie um arquivo de áudio com este nome ou ajuste o caminho.")
except Exception as e:
print('Erro:', e)
Analisando transcrição a partir de Webhook
Ao configurar um webhook para o evento stt.transcription
, você pode automatizar a análise de conteúdo transcrito em tempo real. Isso é especialmente útil para processar gravações de chamadas ou áudios enviados para transcrição via API.
Como funciona o fluxo
- O áudio é enviado para transcrição através da API da SipPulse
- Quando a transcrição é concluída, um webhook é disparado para seu endpoint
- Seu servidor processa o webhook, extrai o texto transcrito e envia para análise estruturada
- Os resultados podem ser armazenados em seu banco de dados ou encaminhados para outros sistemas
Considerações importantes
- Validação de segurança: Sempre valide a assinatura do webhook para garantir que a requisição é legítima
- Tratamento assíncrono: Para evitar timeouts, processe análises complexas de forma assíncrona
- Tolerância a falhas: Implemente filas e retentativas para garantir que nenhuma transcrição seja perdida
Caso não tenha experiência com webhooks, é recomendável consultar a documentação de Webhooks para entender como configurar e validar as requisições.
Veja abaixo exemplos práticos em TypeScript e Python para implementar este fluxo:
import express, { Request, Response } from 'express';
import { createHmac } from 'crypto';
const app = express();
app.use(express.json());
// Segredo compartilhado para validar as requisições
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET || '';
function isSignatureValid(payload: string, timestamp: string, signature: string): boolean {
const message = `${payload}:${timestamp}`;
const hmac = createHmac('sha256', WEBHOOK_SECRET).update(message).digest('hex');
return hmac === signature;
}
app.post('/webhook/stt', async (req: Request, res: Response) => {
const event = req.headers['x-event'];
const timestamp = req.headers['x-timestamp'] as string;
const signature = req.headers['x-signature'] as string;
const payload = JSON.stringify(req.body);
// Verifica evento
if (event !== 'stt.transcription') {
// Se não for o evento esperado, retorna 200 OK sem processar
return res.status(200)
}
// Verifica janela de timestamp (±5 minutos)
if (Math.abs(Date.now() - Date.parse(timestamp)) > 5 * 60 * 1000) {
return res.status(400).json({ error: 'Timestamp expirado' });
}
// Valida assinatura
if (!isSignatureValid(payload, timestamp, signature)) {
return res.status(400).json({ error: 'Assinatura inválida' });
}
// Processa webhook
const { text } = req.body.payload;
const analysisId = process.env.ANALYSIS_ID;
const baseUrl = 'https://api.sippulse.ai';
const apiKey = process.env.SIPPULSE_API_KEY;
const headers = {
'Content-Type': 'application/json',
'api-key': apiKey,
};
try {
const response = await fetch(
`${baseUrl}/structured-analyses/${analysisId}/execute`,
{
method: 'POST',
headers,
body: JSON.stringify({ content: text }),
}
);
const result = await response.json();
console.log('Análise realizada', result.content);
res.status(200).send('OK');
} catch (err) {
console.error('Erro ao processar webhook de transcrição:', err);
res.status(500).send('Erro interno');
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Servidor Express rodando na porta ${PORT}`));
from fastapi import FastAPI, Request, HTTPException, Header
import hashlib
import hmac
import time
import json
import os
import requests
from datetime import datetime
from typing import Optional
app = FastAPI()
# Segredo compartilhado para validar as requisições
WEBHOOK_SECRET = os.environ.get('WEBHOOK_SECRET', '')
def is_signature_valid(payload: str, timestamp: str, signature: str) -> bool:
message = f"{payload}:{timestamp}"
expected = hmac.new(
WEBHOOK_SECRET.encode(),
message.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
@app.post('/webhook/stt')
async def receive_stt_webhook(
request: Request,
x_event: Optional[str] = Header(None, alias="x-event"),
x_timestamp: Optional[str] = Header(None, alias="x-timestamp"),
x_signature: Optional[str] = Header(None, alias="x-signature")
):
# Verifica evento
if x_event != 'stt.transcription':
# Se não for o evento esperado, retorna 200 OK sem processar
return {"status": "ok"}
# Obter o corpo da requisição como string
body = await request.body()
payload = body.decode('utf-8')
# Verifica janela de timestamp (±5 minutos)
timestamp_dt = datetime.fromisoformat(x_timestamp.replace('Z', '+00:00'))
time_diff = abs((datetime.now().timestamp() - timestamp_dt.timestamp()))
if time_diff > 5 * 60:
raise HTTPException(status_code=400, detail="Timestamp expirado")
# Valida assinatura
if not is_signature_valid(payload, x_timestamp, x_signature):
raise HTTPException(status_code=400, detail="Assinatura inválida")
# Processa webhook
data = json.loads(payload)
text = data.get('payload', {}).get('text')
analysis_id = os.environ.get('ANALYSIS_ID')
base_url = 'https://api.sippulse.ai'
api_key = os.environ.get('SIPPULSE_API_KEY')
headers = {
'Content-Type': 'application/json',
'api-key': api_key
}
try:
response = requests.post(
f"{base_url}/structured-analyses/{analysis_id}/execute",
headers=headers,
json={'content': text}
)
response.raise_for_status()
result = response.json()
print('Análise realizada', result.get('content'))
return {"status": "ok"}
except Exception as e:
print('Erro ao processar webhook de transcrição:', e)
raise HTTPException(status_code=500, detail="Erro interno")
if __name__ == "__main__":
import uvicorn
port = int(os.environ.get('PORT', 3000))
uvicorn.run(app, host="0.0.0.0", port=port)
Dica
Para aprender a configurar segredos, endpoints e eventos de webhook na plataforma, consulte a documentação de Webhooks.
Boas Práticas
- Teste cada análise na interface antes de habilitar em agentes.
- Use descrições claras nos campos para facilitar o entendimento do JSON.