ENTITY - Extração de Entidades de Texto
O que é este Node?
O ENTITY é o node responsável por extrair automaticamente entidades estruturadas de textos através de análise de padrões e expressões regulares. Ele identifica e classifica informações como emails, telefones, CPFs e nomes de pessoas dentro de qualquer texto fornecido.
Por que este Node existe?
Em conversas por WhatsApp, usuários frequentemente compartilham informações importantes misturadas em textos corridos: "Meu email é joao@empresa.com e meu telefone é (11) 98765-4321". Processar manualmente essas mensagens para extrair dados estruturados seria trabalhoso e propenso a erros. O ENTITY existe para:
- Automatizar Coleta de Dados: Extrair automaticamente emails, telefones, CPFs e nomes sem precisar fazer perguntas específicas
- Validar Presença de Informações: Verificar se o usuário forneceu os dados necessários em suas mensagens
- Estruturar Dados Não-Estruturados: Transformar textos livres em dados organizados e utilizáveis
- Facilitar Cadastros: Permitir que usuários enviem todas suas informações de uma vez, sem formulários rígidos
Como funciona internamente?
Quando o ENTITY é executado, o sistema:
- Recebe o Texto: Obtém o texto a ser analisado do parâmetro
text - Valida Entrada: Verifica se o texto foi fornecido, caso contrário retorna erro
- Define Tipos de Busca: Usa
entityTypesse fornecido, ou procura todos os tipos por padrão (email, phone, cpf, person) - Aplica Regex para Email: Busca padrões de email usando expressão regular
/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g - Aplica Regex para Telefone: Busca telefones brasileiros usando
/(\(?\d{2}\)?\s?)?9?\d{4}-?\d{4}/g - Aplica Regex para CPF: Busca CPFs usando
/\d{3}\.?\d{3}\.?\d{3}-?\d{2}/g - Aplica Regex para Nomes: Busca nomes próprios capitalizados usando
/\b[A-Z][a-z]+(\s+[A-Z][a-z]+)+\b/g - Monta Array de Entidades: Cada entidade encontrada é adicionada com seu tipo, valor e confiança
- Retorna Resultado: Devolve objeto com todas as entidades encontradas, contagem total e timestamp
Código interno (ai-processing-executor.service.ts:169-234):
private async executeEntity(parameters: any, context: any): Promise<any> {
const { text, entityTypes } = parameters;
this.logger.log(`🔍 ENTITY - Extracting entities from: "${text?.substring(0, 50)}..."`);
if (!text) {
throw new Error('Text is required for entity extraction');
}
// Simple entity extraction simulation
const entities: any[] = [];
// Email extraction
const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
const emails = text.match(emailRegex) || [];
emails.forEach(email => {
entities.push({
type: 'email',
value: email,
confidence: 0.9
});
});
// Phone extraction (Brazilian format)
const phoneRegex = /(\(?\d{2}\)?\s?)?9?\d{4}-?\d{4}/g;
const phones = text.match(phoneRegex) || [];
phones.forEach(phone => {
entities.push({
type: 'phone',
value: phone,
confidence: 0.8
});
});
// CPF extraction
const cpfRegex = /\d{3}\.?\d{3}\.?\d{3}-?\d{2}/g;
const cpfs = text.match(cpfRegex) || [];
cpfs.forEach(cpf => {
entities.push({
type: 'cpf',
value: cpf,
confidence: 0.85
});
});
// Name extraction (capitalized words)
const nameRegex = /\b[A-Z][a-z]+(\s+[A-Z][a-z]+)+\b/g;
const names = text.match(nameRegex) || [];
names.forEach(name => {
entities.push({
type: 'person',
value: name,
confidence: 0.7
});
});
return {
success: true,
action: 'entities_extracted',
text: text,
entityTypes: entityTypes || ['email', 'phone', 'cpf', 'person'],
entities: entities,
totalFound: entities.length,
timestamp: new Date().toISOString()
};
}
Quando você DEVE usar este Node?
Use ENTITY sempre que precisar de extrair informações estruturadas de textos livres fornecidos por usuários:
Casos de uso
- Cadastro Simplificado: "Envie seus dados: nome, email e telefone" - extrair todas as informações de uma mensagem
- Validação de Documentos: Verificar se o usuário forneceu CPF em suas mensagens
- Coleta Inteligente: Permitir que usuários enviem dados de múltiplas formas sem rigidez de formato
- Análise de Histórico: Buscar emails, telefones ou CPFs em conversas antigas
- Preenchimento Automático: Extrair dados para preencher formulários automaticamente
Quando NÃO usar ENTITY
- Dados já estruturados: Use VARIABLE diretamente se já tem o dado isolado
- Validação complexa: Use nodes específicos (EMAIL, PHONE) para validações mais rigorosas
- Formatos internacionais: ENTITY está otimizado para padrões brasileiros (telefone, CPF)
- Precisão crítica: Para situações que exigem 100% de precisão, use validação manual adicional
Parâmetros Detalhados
text (string, obrigatório)
O que é: O texto que será analisado para extração de entidades. Pode ser uma mensagem do usuário, um texto longo, ou qualquer conteúdo que contenha dados estruturados.
Padrão: Nenhum (obrigatório)
Flow completo para testar:
{
"name": "Teste ENTITY - Parâmetro text",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Coletar Mensagem",
"parameters": {
"message": "Envie uma mensagem com suas informações (nome, email, telefone)",
"variable": "user_message"
}
}
},
{
"id": "entity_1",
"type": "entity",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Extrair Entidades",
"parameters": {
"text": "{{user_message}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Mostrar Resultado",
"parameters": {
"message": "Encontrei {{entity_1.totalFound}} entidades:\n\n{{entity_1.entities}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "entity_1" },
{ "source": "entity_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste:
- Inicie o flow
- Digite: "Olá, meu nome é João Silva, email joao@empresa.com e telefone (11) 98765-4321"
- O sistema mostrará todas as entidades encontradas: nome (João Silva), email (joao@empresa.com) e telefone ((11) 98765-4321)
entityTypes (array, opcional)
O que é: Lista de tipos específicos de entidades que você deseja extrair. Permite filtrar a busca para apenas os tipos necessários. Valores possíveis: 'email', 'phone', 'cpf', 'person'.
Padrão: ['email', 'phone', 'cpf', 'person'] (todos os tipos)
Flow completo para testar:
{
"name": "Teste ENTITY - Parâmetro entityTypes",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Coletar Texto",
"parameters": {
"message": "Envie um texto com várias informações",
"variable": "user_text"
}
}
},
{
"id": "entity_1",
"type": "entity",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Buscar Apenas Emails",
"parameters": {
"text": "{{user_text}}",
"entityTypes": ["email"]
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Mostrar Emails",
"parameters": {
"message": "Emails encontrados: {{entity_1.totalFound}}\n\nDetalhes:\n{{entity_1.entities}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "entity_1" },
{ "source": "entity_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste:
- Inicie o flow
- Digite: "Contatos: maria@empresa.com, João Silva (11) 98765-4321 CPF: 123.456.789-00"
- O sistema mostrará APENAS os emails encontrados (maria@empresa.com), ignorando nome, telefone e CPF
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| text | string | Sim | Texto a ser analisado para extração de entidades |
| entityTypes | array | Não | Tipos específicos a extrair: ['email', 'phone', 'cpf', 'person'] (padrão: todos) |
Tipos de Entidades Suportados
email (confiança: 90%)
Pattern: [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
Exemplos:
phone (confiança: 80%)
Pattern: (\(?\d{2}\)?\s?)?9?\d{4}-?\d{4} (formato brasileiro)
Exemplos:
- (11) 98765-4321
- 11987654321
- 98765-4321
- 3456-7890
cpf (confiança: 85%)
Pattern: \d{3}\.?\d{3}\.?\d{3}-?\d{2}
Exemplos:
- 123.456.789-00
- 12345678900
- 123456789-00
person (confiança: 70%)
Pattern: \b[A-Z][a-z]+(\s+[A-Z][a-z]+)+\b (palavras capitalizadas)
Exemplos:
- João Silva
- Maria da Conceição
- Pedro Henrique Santos
Nota: Nomes de uma palavra só (ex: "João") não são detectados para evitar falsos positivos.
Exemplo 1: Cadastro Simplificado Completo
Objetivo: Permitir que o usuário envie todos seus dados em uma única mensagem livre, extrair as informações automaticamente e confirmar os dados encontrados.
JSON para Importar
{
"name": "Cadastro com Extração Automática",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "message_1",
"type": "message",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Solicitar Dados",
"parameters": {
"message": "Bem-vindo ao cadastro!\n\nPor favor, envie em uma única mensagem:\n- Seu nome completo\n- Email\n- Telefone\n- CPF"
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Receber Dados",
"parameters": {
"variable": "dados_usuario"
}
}
},
{
"id": "entity_1",
"type": "entity",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Extrair Informações",
"parameters": {
"text": "{{dados_usuario}}"
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Validar Dados",
"parameters": {
"condition": "{{entity_1.totalFound}} >= 4"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 1100, "y": 50 },
"data": {
"label": "Confirmação",
"parameters": {
"message": "Dados recebidos com sucesso!\n\n✅ Total de informações encontradas: {{entity_1.totalFound}}\n\nDados extraídos:\n{{entity_1.entities}}\n\nCadastro concluído!"
}
}
},
{
"id": "message_3",
"type": "message",
"position": { "x": 1100, "y": 150 },
"data": {
"label": "Dados Incompletos",
"parameters": {
"message": "❌ Encontrei apenas {{entity_1.totalFound}} informações.\n\nPor favor, envie novamente incluindo:\n- Nome completo\n- Email\n- Telefone\n- CPF"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1300, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "message_1" },
{ "source": "message_1", "target": "input_1" },
{ "source": "input_1", "target": "entity_1" },
{ "source": "entity_1", "target": "condition_1" },
{ "source": "condition_1", "target": "message_2", "label": "true" },
{ "source": "condition_1", "target": "message_3", "label": "false" },
{ "source": "message_2", "target": "end_1" },
{ "source": "message_3", "target": "end_1" }
]
}
Saída esperada:
Sistema: Bem-vindo ao cadastro!
Por favor, envie em uma única mensagem:
- Seu nome completo
- Email
- Telefone
- CPF
Usuário: Oi, sou João Silva, meu email é joao.silva@empresa.com, telefone (11) 98765-4321 e CPF 123.456.789-00
Sistema: Dados recebidos com sucesso!
✅ Total de informações encontradas: 4
Dados extraídos:
[{"type":"person","value":"João Silva","confidence":0.7},{"type":"email","value":"joao.silva@empresa.com","confidence":0.9},{"type":"phone","value":"(11) 98765-4321","confidence":0.8},{"type":"cpf","value":"123.456.789-00","confidence":0.85}]
Cadastro concluído!
Exemplo 2: Extração Seletiva de Emails para Newsletter
Objetivo: Buscar apenas emails em mensagens de usuários que desejam se cadastrar na newsletter, ignorando outros dados.
JSON para Importar
{
"name": "Cadastro Newsletter - Apenas Emails",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "message_1",
"type": "message",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Solicitar Email",
"parameters": {
"message": "📧 Newsletter Semanal\n\nEnvie seu email para receber nossas novidades!"
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Receber Mensagem",
"parameters": {
"variable": "mensagem"
}
}
},
{
"id": "entity_1",
"type": "entity",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Extrair Email",
"parameters": {
"text": "{{mensagem}}",
"entityTypes": ["email"]
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Email Encontrado?",
"parameters": {
"condition": "{{entity_1.totalFound}} > 0"
}
}
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 1100, "y": 50 },
"data": {
"label": "Salvar Email",
"parameters": {
"name": "email_cadastrado",
"value": "{{entity_1.entities[0].value}}"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 1300, "y": 50 },
"data": {
"label": "Confirmação",
"parameters": {
"message": "✅ Email cadastrado com sucesso!\n\n📧 {{email_cadastrado}}\n\nVocê receberá nossa newsletter semanalmente."
}
}
},
{
"id": "message_3",
"type": "message",
"position": { "x": 1100, "y": 150 },
"data": {
"label": "Email Não Encontrado",
"parameters": {
"message": "❌ Não encontrei um email válido na sua mensagem.\n\nExemplo: seuemail@exemplo.com\n\nPor favor, tente novamente."
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1500, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "message_1" },
{ "source": "message_1", "target": "input_1" },
{ "source": "input_1", "target": "entity_1" },
{ "source": "entity_1", "target": "condition_1" },
{ "source": "condition_1", "target": "variable_1", "label": "true" },
{ "source": "condition_1", "target": "message_3", "label": "false" },
{ "source": "variable_1", "target": "message_2" },
{ "source": "message_2", "target": "end_1" },
{ "source": "message_3", "target": "end_1" }
]
}
Saída esperada:
Sistema: 📧 Newsletter Semanal
Envie seu email para receber nossas novidades!
Usuário: Olá, quero me cadastrar! Meu email é maria@exemplo.com
Sistema: ✅ Email cadastrado com sucesso!
📧 maria@exemplo.com
Você receberá nossa newsletter semanalmente.
Exemplo 3: Validação de CPF em Documentação
Objetivo: Extrair e validar CPF de mensagens enviadas por usuários durante processo de verificação de identidade.
JSON para Importar
{
"name": "Verificação de CPF",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "message_1",
"type": "message",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Solicitar CPF",
"parameters": {
"message": "🆔 Verificação de Identidade\n\nPara continuar, envie seu CPF.\n\nFormatos aceitos:\n- 123.456.789-00\n- 12345678900"
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Receber CPF",
"parameters": {
"variable": "mensagem_cpf"
}
}
},
{
"id": "entity_1",
"type": "entity",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Extrair CPF",
"parameters": {
"text": "{{mensagem_cpf}}",
"entityTypes": ["cpf"]
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 900, "y": 100 },
"data": {
"label": "CPF Encontrado?",
"parameters": {
"condition": "{{entity_1.totalFound}} == 1"
}
}
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 1100, "y": 50 },
"data": {
"label": "Armazenar CPF",
"parameters": {
"name": "cpf_usuario",
"value": "{{entity_1.entities[0].value}}"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 1300, "y": 50 },
"data": {
"label": "CPF Validado",
"parameters": {
"message": "✅ CPF identificado!\n\n📋 {{cpf_usuario}}\n\nConfiança: {{entity_1.entities[0].confidence}}\n\nVerificação em andamento..."
}
}
},
{
"id": "condition_2",
"type": "condition",
"position": { "x": 1100, "y": 150 },
"data": {
"label": "Múltiplos CPFs?",
"parameters": {
"condition": "{{entity_1.totalFound}} > 1"
}
}
},
{
"id": "message_3",
"type": "message",
"position": { "x": 1300, "y": 150 },
"data": {
"label": "Múltiplos CPFs",
"parameters": {
"message": "⚠️ Encontrei {{entity_1.totalFound}} CPFs na sua mensagem.\n\nPor favor, envie apenas UM CPF por vez."
}
}
},
{
"id": "message_4",
"type": "message",
"position": { "x": 1300, "y": 250 },
"data": {
"label": "CPF Não Encontrado",
"parameters": {
"message": "❌ CPF não identificado.\n\nVerifique o formato:\n✓ 123.456.789-00\n✓ 12345678900\n\nTente novamente."
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1500, "y": 150 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "message_1" },
{ "source": "message_1", "target": "input_1" },
{ "source": "input_1", "target": "entity_1" },
{ "source": "entity_1", "target": "condition_1" },
{ "source": "condition_1", "target": "variable_1", "label": "true" },
{ "source": "condition_1", "target": "condition_2", "label": "false" },
{ "source": "variable_1", "target": "message_2" },
{ "source": "condition_2", "target": "message_3", "label": "true" },
{ "source": "condition_2", "target": "message_4", "label": "false" },
{ "source": "message_2", "target": "end_1" },
{ "source": "message_3", "target": "end_1" },
{ "source": "message_4", "target": "end_1" }
]
}
Saída esperada:
Sistema: 🆔 Verificação de Identidade
Para continuar, envie seu CPF.
Formatos aceitos:
- 123.456.789-00
- 12345678900
Usuário: Meu CPF é 123.456.789-00
Sistema: ✅ CPF identificado!
📋 123.456.789-00
Confiança: 0.85
Verificação em andamento...
Resposta do Node
{
"success": true,
"action": "entities_extracted",
"text": "Olá, meu nome é João Silva, email joao@empresa.com e telefone (11) 98765-4321",
"entityTypes": ["email", "phone", "cpf", "person"],
"entities": [
{
"type": "person",
"value": "João Silva",
"confidence": 0.7
},
{
"type": "email",
"value": "joao@empresa.com",
"confidence": 0.9
},
{
"type": "phone",
"value": "(11) 98765-4321",
"confidence": 0.8
}
],
"totalFound": 3,
"timestamp": "2025-01-15T10:30:00.000Z"
}
Campos da resposta:
success: Sempretruese a extração foi executadaaction: Sempre"entities_extracted"text: Texto original que foi analisadoentityTypes: Array com os tipos buscadosentities: Array de objetos com cada entidade encontradatype: Tipo da entidade (email, phone, cpf, person)value: Valor extraídoconfidence: Nível de confiança (0.7 a 0.9)totalFound: Número total de entidades encontradastimestamp: Data/hora da extração
Boas Práticas
✅ SIM:
- Valide o resultado: Sempre verifique
totalFoundantes de usar as entidades - Use entityTypes: Filtre tipos específicos para melhor performance e precisão
- Combine com validação: Use nodes específicos (EMAIL, PHONE) para validação adicional dos dados extraídos
- Trate múltiplos resultados: Prepare seu flow para quando múltiplas entidades forem encontradas
- Mostre confiança ao usuário: Informe o nível de certeza quando relevante
- Confirme dados: Sempre peça confirmação ao usuário antes de salvar dados extraídos
❌ NÃO:
- Não confie cegamente: Regex pode ter falsos positivos, especialmente em nomes de pessoas
- Não ignore erros: Sempre trate caso nenhuma entidade seja encontrada
- Não use para validação final: ENTITY extrai, mas não valida completamente (ex: CPF pode estar em formato correto mas ser inválido)
- Não espere 100% de precisão em nomes: Nomes de uma palavra ou em minúsculas não serão detectados
- Não use para formatos internacionais: Os regex são otimizados para padrões brasileiros
Dicas
💡 Dica 1 - Combine tipos para contextos específicos: Em um cadastro de cliente, use ["person", "email", "phone"]. Para verificação fiscal, use apenas ["cpf"].
💡 Dica 2 - Acesse entidades específicas: Use {{entity_1.entities[0].value}} para pegar a primeira entidade encontrada, ou itere pelo array quando múltiplas entidades forem necessárias.
💡 Dica 3 - Confiança indica precisão: Emails têm 90% de confiança (maior precisão), nomes têm 70% (mais propensos a falsos positivos). Use isso para decidir se precisa de confirmação manual.
💡 Dica 4 - Pré-processe o texto: Se possível, remova quebras de linha e caracteres especiais desnecessários antes de passar para o ENTITY para melhor detecção.
💡 Dica 5 - Feedback ao usuário: Quando totalFound for 0, explique claramente o formato esperado com exemplos concretos.
💡 Dica 6 - Telefones flexíveis: O regex aceita telefones com ou sem DDD, com ou sem formatação. Normalize depois se necessário.
💡 Dica 7 - Use SWITCH para distribuir tipos: Depois da extração, use SWITCH no tipo da entidade para processar cada um de forma diferente.
Próximo Node
→ SENTIMENT - Análise de sentimento em textos → FORMATTER - Formatação avançada de dados extraídos → VALIDATOR - Validação rigorosa de dados → VARIABLE - Armazenar entidades extraídas