Sistema de Análise de Sentimento de Tweets em Tempo Real com .NET
No mundo hiperconectado de hoje, a capacidade de entender a opinião pública em tempo real não é um luxo, mas uma necessidade estratégica. Milhares de mensagens são postadas a cada segundo, e saber se seus clientes ou o público em geral estão se sentindo positivos, negativos ou neutros sobre sua marca ou produto é uma mina de ouro de dados.
É aqui que entra o Sistema de Análise de Sentimento de Texto em Tempo Real com .NET.
Este não é um projeto C# comum de CRUD (Create, Read, Update, Delete). Ele nos desafia a mergulhar em uma arquitetura de alta relevância no mercado: a combinação de Inteligência Artificial (IA) com comunicação em tempo real. Usaremos o poder do ecossistema .NET para construir uma solução full-stack, onde o C# será a linguagem unificadora, desde o modelo de Machine Learning até a interface de usuário.
O objetivo é transformar um fluxo constante de dados brutos de texto em informações acionáveis, exibindo a classificação do sentimento em um dashboard dinâmico e instantâneo. Este projeto não apenas aprimora suas habilidades em C# e ASP.NET Core, mas também o insere no campo da Data Science e Web Sockets (via SignalR), qualificações altamente procuradas por empresas modernas.
Estrutura e Arquitetura do Projeto
O sistema será composto por três camadas principais que se comunicam de forma eficiente, todas construídas no ecra .NET:
Camada | Componente | Função | Tecnologias Chave |
Backend & ML | API de Entrada | Recebe os dados de texto para análise. | ASP.NET Core Minimal APIs |
Serviço de Análise | Carrega o modelo e executa a previsão do sentimento para o texto. | ML.NET (Classificação de Texto) | |
Tempo Real | Hub de Notificação | Canal de comunicação bidirecional aberto que envia atualizações instantâneas. | ASP.NET Core SignalR (Hubs) |
Serviço de Broadcast | Distribui o resultado da análise (texto + sentimento) para o Hub. | IHubContext<T> do SignalR | |
Frontend | Dashboard | Interface que exibe a lista de textos e suas classificações dinamicamente. | Blazor WebAssembly ou Blazor Server |
Cliente de Tempo Real | Conecta-se ao Hub e atualiza a interface assim que um novo dado é recebido. | SignalR Client (nativo no Blazor) |
1. Configuração do Projeto e ML.NET
A espinha dorsal do projeto começa com o backend ASP.NET Core e a integração do Machine Learning.
A. Instalação de Pacotes NuGet
Instale os seguintes pacotes no seu projeto ASP.NET Core Web API:
dotnet add package Microsoft.ML
dotnet add package Microsoft.ML.FastTree
B. Definição do Modelo de Dados
As classes abaixo definem a estrutura de dados para comunicação com o ML.NET e o restante da aplicação.
using Microsoft.ML.Data;
// 1. Classe de Entrada (O que o modelo irá receber)
public class SentimentData
{
// O texto do "tweet" que queremos classificar.
[LoadColumn(0)]
public string TweetText { get; set; }
// O rótulo (Label) usado APENAS para treinamento.
[LoadColumn(1), ColumnName("Label")]
public bool Sentiment { get; set; }
}
// 2. Classe de Saída (O que o modelo irá retornar)
public class SentimentPrediction
{
// O valor do sentimento previsto (true = positivo, false = negativo)
[ColumnName("PredictedLabel")]
public bool Prediction { get; set; }
// A probabilidade da previsão (confiança do modelo)
public float Probability { get; set; }
// A pontuação bruta (score)
public float Score { get; set; }
}
C. Criação do Serviço de Treinamento e Previsão
A classe SentimentAnalysisService
encapsula a lógica do ML.NET.
using Microsoft.ML;
using Microsoft.ML.Data;
public class SentimentAnalysisService
{
private readonly MLContext _mlContext;
private ITransformer _model;
public SentimentAnalysisService()
{
_mlContext = new MLContext(seed: 0);
// O modelo deve ser carregado ou treinado ao iniciar
LoadOrCreateTrainedModel();
}
// Método para simular o carregamento/criação de um modelo
private void LoadOrCreateTrainedModel()
{
// **IMPORTANTE: Em um projeto real, você deve carregar um modelo pré-treinado (.zip) aqui**
// Ex: _model = _mlContext.Model.Load("sentimentModel.zip", out var modelSchema);
// Para este exemplo, treinamos um modelo MINIMAL com dados de amostra.
var sampleData = new List<SentimentData>
{
new SentimentData { TweetText = "Amei o novo produto, super recomendo!", Sentiment = true },
new SentimentData { TweetText = "Que horror, tive uma experiência terrível.", Sentiment = false },
new SentimentData { TweetText = "É ok, nada demais.", Sentiment = true },
new SentimentData { TweetText = "O serviço de suporte foi incrível!", Sentiment = true }
};
IDataView trainingDataView = _mlContext.Data.LoadFromEnumerable(sampleData);
// Define o pipeline de treinamento (FeaturizeText + SdcaLogisticRegression)
var pipeline = _mlContext.Transforms.Text.FeaturizeText(
outputColumnName: "Features",
inputColumnName: nameof(SentimentData.TweetText))
.Append(_mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(
labelColumnName: "Label",
featureColumnName: "Features"));
// Treina o modelo
_model = pipeline.Fit(trainingDataView);
// **Em produção, você salvaria este modelo:** // _mlContext.Model.Save(_model, trainingDataView.Schema, "sentimentModel.zip");
}
/// <summary>
/// Classifica o sentimento de um texto.
/// </summary>
/// <param name="text">O texto a ser analisado.</param>
/// <returns>A previsão de sentimento.</returns>
public SentimentPrediction PredictSentiment(string text)
{
// Cria um motor de previsão a partir do modelo
var predictionEngine = _mlContext.Model.CreatePredictionEngine<SentimentData, SentimentPrediction>(_model);
var sampleData = new SentimentData { TweetText = text };
// Faz a previsão
return predictionEngine.Predict(sampleData);
}
}
2. Implementação da API, SignalR e Comunicação em Tempo Real
A mágica do tempo real acontece no arquivo Program.cs
. Usamos a Injeção de Dependência para fornecer o serviço de ML.NET e o IHubContext
do SignalR para broadcast.
using Microsoft.AspNetCore.SignalR;
var builder = WebApplication.CreateBuilder(args);
// Adicionar Injeção de Dependência do nosso serviço ML.NET
builder.Services.AddSingleton<SentimentAnalysisService>();
// Adicionar SignalR (para a próxima etapa de tempo real)
builder.Services.AddSignalR();
// Adicionar CORS (necessário para o Blazor Frontend rodando em outra porta/domínio)
builder.Services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", policy =>
{
policy.AllowAnyHeader()
.AllowAnyMethod()
// Ajuste para a URL do seu Blazor Frontend, permitindo SignalR (AllowCredentials)
.WithOrigins("http://localhost:5000", "http://localhost:5001")
.AllowCredentials();
});
});
var app = builder.Build();
app.UseCors("CorsPolicy");
// Mapeamento do SignalR Hub
app.MapHub<SentimentHub>("/sentimentHub");
// --- Minimal API Endpoint para Análise ---
app.MapPost("/api/analyze", async (string tweetText,
SentimentAnalysisService service,
IHubContext<SentimentHub> hubContext) =>
{
if (string.IsNullOrWhiteSpace(tweetText))
{
return Results.BadRequest("O texto não pode estar vazio.");
}
// 1. Realiza a previsão do sentimento
var prediction = service.PredictSentiment(tweetText);
// 2. Formata o resultado para envio (JSON)
var result = new
{
Text = tweetText,
// Converte o booleano de previsão para uma string amigável
Sentiment = prediction.Prediction ? "Positivo" : "Negativo",
Confidence = Math.Round(prediction.Probability, 4)
};
// 3. Comunica o resultado em TEMPO REAL para TODOS os clientes via SignalR
// O SendAsync usa o método 'ReceiveSentimentUpdate' que será consumido no frontend Blazor.
await hubContext.Clients.All.SendAsync("ReceiveSentimentUpdate", result);
// Retorna o resultado da API (para quem a chamou)
return Results.Ok(result);
});
app.Run();
// --- Classe do SignalR Hub ---
// Esta classe é apenas o identificador para o SignalR.
// A lógica de envio (broadcast) é feita via IHubContext no endpoint da API.
public class SentimentHub : Hub
{
}
Testando o Backend: API e Tempo Real
Você validou a integração do ML.NET e configurou o SignalR. O próximo passo crucial é testar se o fluxo completo está funcionando antes de construir o frontend.
1. Teste da API com uma Ferramenta HTTP (Postman/Insomnia)
Use um cliente HTTP para simular um novo dado de texto chegando ao sistema.
Detalhes da Requisição:
Método:
POST
URL:
https://localhost:[PORTA]/api/analyze
Parâmetro de Consulta (Query Param): Adicione
tweetText
com um texto de teste.Exemplo:
https://localhost:[PORTA]/api/analyze?tweetText=Este é um teste incrível!
Resposta Esperada (Status 200 OK):
Seu backend deve retornar um JSON formatado, confirmando a classificação.
{
"text": "Este é um teste incrível!",
"sentiment": "Positivo",
"confidence": 0.9854
}
2. Teste da Comunicação em Tempo Real (SignalR CLI)
O SignalR precisa de um cliente persistente. A ferramenta de linha de comando oficial da Microsoft é a forma mais simples de validar o broadcast.
Pré-requisito: Instale a ferramenta global SignalR CLI:
dotnet tool install -g Microsoft.AspNetCore.SignalR.Client.Cli
Passos:
Inicie a Escuta do Cliente SignalR:
Abra seu terminal e execute:
Bashdotnet signalr listen --urls "https://localhost:[PORTA]/sentimentHub" --hubpath "sentimentHub"
O terminal agora está esperando mensagens e deve mostrar
Connected to 'https://localhost:[PORTA]/sentimentHub'
.Dispare o Evento da API:
Com o terminal escutando, use o Postman (ou outro cliente HTTP) para enviar uma nova requisição POST para o endpoint /api/analyze.
Analise a Saída do Terminal:
Imediatamente após a API retornar o Status 200 OK no Postman, você deve ver uma saída no terminal do SignalR:
[INVOCATION] Target: ReceiveSentimentUpdate, Arguments: [{"text":"O dia está perfeito!","sentiment":"Positivo","confidence":0.75}]
Se o JSON aparecer no terminal do SignalR, o broadcast em tempo real está perfeitamente configurado e a arquitetura está pronta para o frontend!
Próximos Passos: O Frontend com Blazor
Com o backend totalmente validado — o ML.NET classificando e o SignalR transmitindo instantaneamente — o foco agora é construir o Dashboard Dinâmico que consumirá esse fluxo de dados em tempo real.
O Blazor é a escolha ideal, pois permite que você continue a usar C# e .NET para todo o desenvolvimento frontend, eliminando a necessidade de JavaScript complexo para o cliente SignalR.
Escolha do Modelo de Hospedagem
Antes de começar, você precisa escolher como o Blazor será hospedado:
Modelo | Onde o App Roda | Comunicação | Cenário Ideal |
Blazor Server | Servidor | Utiliza uma conexão SignalR persistente para sincronizar o DOM (renderização no servidor). | Ótimo para latência baixa, inicialização rápida e para manter a lógica sensível no servidor. |
Blazor WebAssembly (WASM) | Navegador (Cliente) | O runtime .NET é baixado e roda no cliente. Comunica-se com o backend via APIs (HTTP) ou SignalR (WebSockets). | Perfeito para escalabilidade (offload de processamento para o cliente) e suporte a offline. |
Para este projeto, onde a funcionalidade principal é a comunicação em tempo real via SignalR, ambos os modelos funcionam perfeitamente. O Blazor Server já usa o SignalR para toda a comunicação UI, mas o Blazor WASM usa a mesma biblioteca Microsoft.AspNetCore.SignalR.Client
para se conectar ao seu SentimentHub
.
Implementação do Cliente SignalR no Blazor
A lógica de conexão será a mesma, independentemente do modelo de hospedagem Blazor que você escolher (WASM ou Server). Você usará a classe HubConnectionBuilder
.
1. Classe de Modelo de Dados no Frontend
Crie a mesma estrutura de dados (ou uma versão simplificada) que você usou para enviar o resultado da API.
// Localizada no seu projeto Blazor (Componente ou Models)
public class SentimentResult
{
public string Text { get; set; }
public string Sentiment { get; set; } // "Positivo" ou "Negativo"
public float Confidence { get; set; }
}
2. Lógica do Componente Blazor (Exemplo: SentimentDashboard.razor
)
Este componente será responsável por conectar-se ao Hub e receber as atualizações em tempo real.
@page "/sentiment-dashboard"
@using Microsoft.AspNetCore.SignalR.Client
@implements IAsyncDisposable
@inject NavigationManager NavigationManager // Para obter a URL base
<h2>Análise de Sentimento em Tempo Real</h2>
@if (hubConnection is null)
{
<p><em>Conectando-se ao SignalR Hub...</em></p>
}
else
{
<p>Conexão estabelecida. Recebendo dados instantaneamente.</p>
}
<div class="sentiment-feed">
@foreach (var result in recentResults)
{
<div class="@(result.Sentiment == "Positivo" ? "alert-success" : "alert-danger")">
<strong>@result.Sentiment</strong> (@(result.Confidence.ToString("P0"))): @result.Text
</div>
}
</div>
@code {
private HubConnection? hubConnection;
private List<SentimentResult> recentResults = new();
// Define o número máximo de resultados a serem exibidos no painel
private const int MaxResults = 10;
protected override async Task OnInitializedAsync()
{
// Constrói a URL do Hub: usa a URL base do seu app + o endpoint do Hub.
var hubUrl = NavigationManager.ToAbsoluteUri("/sentimentHub");
hubConnection = new HubConnectionBuilder()
.WithUrl(hubUrl)
.WithAutomaticReconnect() // Garante reconexão automática se a conexão cair
.Build();
// 1. Define o Método Receptor
// Este nome ('ReceiveSentimentUpdate') deve ser EXATAMENTE o mesmo usado no .SendAsync() da sua Minimal API.
hubConnection.On<SentimentResult>("ReceiveSentimentUpdate", (result) =>
{
// 2. Adiciona o novo resultado
recentResults.Insert(0, result);
// 3. Limita o número de resultados para não sobrecarregar o painel
if (recentResults.Count > MaxResults)
{
recentResults.RemoveAt(MaxResults);
}
// 4. Notifica o Blazor para re-renderizar a UI (necessário em alguns contextos)
StateHasChanged();
});
// 5. Inicia a conexão
await hubConnection.StartAsync();
}
// Implementação para garantir que a conexão SignalR seja fechada ao sair
public async ValueTask DisposeAsync()
{
if (hubConnection is not null)
{
await hubConnection.DisposeAsync();
}
}
}
Ao implementar este código no Blazor, seu frontend estará escutando ativamente o servidor. Cada vez que uma requisição POST
for enviada para /api/analyze
no backend, o SignalR fará o broadcast, e o método ReceiveSentimentUpdate
será invocado no seu Blazor para atualizar o dashboard instantaneamente.
Com o frontend pronto, você terá concluído o ciclo ML.NET API
SignalR
Blazor e terá um sistema de análise de sentimento em tempo real totalmente funcional!
Conclusão
Com a integração das três camadas — ML.NET, ASP.NET Core SignalR, e Blazor — você concluiu a construção de um sistema de análise de sentimento em tempo real de altíssimo valor.
Este projeto representa muito mais do que a simples combinação de bibliotecas. Ele demonstra sua capacidade de:
Orquestrar Arquiteturas Modernas: Você foi além do desenvolvimento web tradicional, criando um sistema distribuído que lida com processamento intensivo (Machine Learning) e comunicação de baixa latência (WebSockets).
Unificar a Stack com .NET: Você usou C# em toda a arquitetura, do backend de processamento de dados (ML.NET) ao frontend dinâmico (Blazor), otimizando a produtividade e a manutenção do código.
Transformar Dados em Ação: O fluxo é instantâneo: cada dado de texto bruto é transformado em um insight acionável (Positivo ou Negativo) e exibido no dashboard, permitindo que a sua equipe tome decisões estratégicas no momento exato em que a opinião pública se forma.
O sistema construído é uma fundação robusta. A partir daqui, as possibilidades de expansão são vastas: você pode integrar modelos de Machine Learning mais complexos, conectar a API a serviços de streaming de dados reais (como Kafka ou Azure Event Hubs), ou adicionar visualizações de dados avançadas para monitorar a tendência de sentimento ao longo do tempo.
Parabéns por dominar esta poderosa arquitetura! Este é o tipo de projeto que realmente impulsiona a inovação e o seu portfólio no mercado.
Comentários
Postar um comentário