A aálise de sentimentos tornou-se uma ferramenta indispensável para empresas que buscam interpretar o feedback dos usuários em larga escala. Integrar modelos de Processamento de Linguagem Natural (NLP), como o StructBERT, diretamente em aplicações front-end modernas permite a criação de experiências interativas e inteligentes. Neste guia, exploraremos como conectar o framework Vue.js a um serviço de classificação de sentimentos, focando em boas práticas de implementação e arquitetura.
Configuração do Ambiente e Dependências
Para iniciar, utilizaremos o ecossistema Vue 3. Caso ainda não tenha um projeto configurado, utilize o gerenciador de pacotes de sua preferência para instanciar a aplicação:
# Iniciando um novo projeto Vue
npm create vue@latest
# Entrando no diretório
cd analise-sentimento-app
# Instalando o cliente HTTP para requisições
npm install axios
O StructBERT é geralmente servido via API REST devido à sua complexidade computacional. Para este exemplo, consideraremos um endpoint que recebe uma string e retorna a polaridade do texto com sua respectiva confiança.
Desenvolvimento do Componente de Aálise
Adotaremos o padrão <script setup> do Vue 3 para garantir um código mais conciso e performático. O componente principal lidará com a entrada de dados do usuário e a comunicação com o backend.
<script setup>
import { ref, reactive } from 'vue';
import axios from 'axios';
const campoTexto = ref('');
const estadoAnalise = reactive({
estaProcessando: false,
resultado: null,
erro: null
});
const API_ENDPOINT = 'http://api-exemplo-nlp.com/v1/structbert/sentiment';
async function processarSentimento() {
if (!campoTexto.value.trim()) return;
estadoAnalise.estaProcessando = true;
estadoAnalise.erro = null;
estadoAnalise.resultado = null;
try {
const { data } = await axios.post(API_ENDPOINT, {
content: campoTexto.value
});
estadoAnalise.resultado = {
label: data.sentiment === 'positive' ? 'Positivo' : 'Negativo',
score: (data.confidence * 100).toFixed(2),
classeCss: data.sentiment
};
} catch (err) {
estadoAnalise.erro = 'Falha na comunicação com o servidor de IA.';
console.error('Erro de API:', err);
} finally {
estadoAnalise.estaProcessando = false;
}
}
</script>
<template>
<div class="container-nlp">
<h2>Detector de Emoções Literárias</h2>
<textarea
v-model="campoTexto"
placeholder="Escreva sua opinião aqui para análise..."
:disabled="estadoAnalise.estaProcessando"
></textarea>
<button
@click="processarSentimento"
:disabled="estadoAnalise.estaProcessando"
>
{{ estadoAnalise.estaProcessando ? 'Processando Modelos...' : 'Analisar Texto' }}
</button>
<div v-if="estadoAnalise.resultado" :class="['card-resultado', estadoAnalise.resultado.classeCss]">
<p>Sentimento Identificado: <strong>{{ estadoAnalise.resultado.label }}</strong></p>
<div class="barra-progresso">
<div class="preenchimento" :style="{ width: estadoAnalise.resultado.score + '%' }"></div>
</div>
<small>Confiança do Modelo: {{ estadoAnalise.resultado.score }}%</small>
</div>
<p v-if="estadoAnalise.erro" class="alerta-erro">{{ estadoAnalise.erro }}</p>
</div>
</template>
<style scoped>
.container-nlp {
max-width: 500px;
margin: 2rem auto;
font-family: sans-serif;
}
textarea {
width: 100%;
height: 120px;
padding: 1rem;
border: 2px solid #eaeaea;
border-radius: 8px;
resize: none;
}
button {
width: 100%;
padding: 0.8rem;
margin-top: 1rem;
background-color: #4b6cb7;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
}
button:disabled {
background-color: #bdc3c7;
}
.card-resultado {
margin-top: 1.5rem;
padding: 1rem;
border-radius: 8px;
}
.positive { background-color: #d4edda; color: #155724; }
.negative { background-color: #f8d7da; color: #721c24; }
.barra-progresso {
height: 8px;
background: #eee;
border-radius: 4px;
margin: 10px 0;
}
.preenchimento {
height: 100%;
background: currentColor;
border-radius: 4px;
transition: width 0.5s ease;
}
</style>
Gerenciamento de Histórico e Persistência
Para enriquecer a aplicação, podemos implementar uma funcionalidade de cache local para armazenar as últimas análises realizadas, evitando chamadas repetitivas e melhorando a UX.
import { onMounted, watch } from 'vue';
const listaHistorico = ref([]);
onMounted(() => {
const cache = localStorage.getItem('historico_nlp');
if (cache) listaHistorico.value = JSON.parse(cache);
});
// Observa mudanças no histórico para persistir dados
watch(listaHistorico, (novaLista) => {
localStorage.setItem('historico_nlp', JSON.stringify(novaLista.slice(0, 5)));
}, { deep: true });
function adicionarAoHistorico(item) {
listaHistorico.value.unshift({
id: Date.now(),
texto: campoTexto.value,
...item
});
}
Estratégias de Otimização e Resiliência
Em ambientes de produção, requisições de IA podem ser custosas ou demoradas. É recomendável implementar uma lógica de "retry" (tentativa automática) para falhas de rede intermitentes.
async function requisicaoComRetentativa(dados, tentativas = 2) {
try {
return await axios.post(API_ENDPOINT, dados);
} catch (erro) {
if (tentativas <= 0) throw erro;
// Aguarda 1.5 segundos antes de tentar novamente
await new Promise(resolve => setTimeout(resolve, 1500));
return requisicaoComRetentativa(dados, tentativas - 1);
}
}
Além disso, para campos de entrada que disparam análises automaticamente enquanto o usuário digita, a técnica de Debounce é essencial para não sobrecarregar o servidor de inferência do StructBERT.
let temporizadorDebounce;
const inputInteligente = () => {
clearTimeout(temporizadorDebounce);
temporizadorDebounce = setTimeout(() => {
processarSentimento();
}, 800);
};
Considerações sobre o Modelo StructBERT
O StructBERT introduz tarefas de pré-treinamento que forçam o modelo a entender a estrutura das sentenças (Word Structural Objective e Sentence Structural Objective), o que o torna particularmente eficaz em capturar nuances gramaticais em idiomas como o chinês e o português, superando frequentemente o BERT padrão em tarefas de classificação de sentimento. Ao integrar este modelo com o Vue.js, garantimos que a robustez do processamento de linguagem natural seja apresentada através de uma interface fluida e responsiva.