PaoloLuigiBarletto's picture
Update app.py
aa6855c verified
Raw
History Blame Contribute Delete
7.01 kB
import json
import os
import gradio as gr
import numpy
from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification
# ==============================
# MODELLO ITALIAN SENTIMENT
# ==============================
print("πŸ”„ Caricamento modello...")
tokenizer = AutoTokenizer.from_pretrained(
"MilaNLProc/feel-it-italian-sentiment",
use_fast=False
)
model = AutoModelForSequenceClassification.from_pretrained(
"MilaNLProc/feel-it-italian-sentiment"
)
sentiment_pipeline = pipeline(
"text-classification",
model=model,
tokenizer=tokenizer,
truncation=True,
max_length=512
)
print("βœ… Modello caricato!")
# ==============================
# CHUNKING
# ==============================
def chunk_text(text, max_chars=400):
if not text or not text.strip():
return []
sentences = text.replace("\n", " ").split(". ")
chunks, current = [], ""
for s in sentences:
if len(current) + len(s) <= max_chars:
current += s + ". "
else:
chunks.append(current.strip())
current = s + ". "
if current.strip():
chunks.append(current.strip())
return chunks
# ==============================
# ANALISI SENTIMENT PER ARTICOLO
# ==============================
def analyze_article_sentiment(article):
text = article.get("content", "")
if not text.strip():
article["sentimentAnalysis"] = "UNKNOWN"
article["sentimentScore"] = None
article["chunksAnalyzed"] = 0
return article
chunks = chunk_text(text)
if not chunks:
article["sentimentAnalysis"] = "UNKNOWN"
article["sentimentScore"] = None
article["chunksAnalyzed"] = 0
return article
results = sentiment_pipeline(chunks)
scores = []
for r in results:
label = r["label"].lower()
if label == "negative":
scores.append(0.0)
elif label == "neutral":
scores.append(0.5)
elif label == "positive":
scores.append(1.0)
if not scores:
article["sentimentAnalysis"] = "UNKNOWN"
article["sentimentScore"] = None
article["chunksAnalyzed"] = len(chunks)
return article
avg_score = sum(scores) / len(scores)
if avg_score <= 0.4:
sentiment = "NEGATIVE"
elif avg_score < 0.66:
sentiment = "NEUTRAL"
else:
sentiment = "POSITIVE"
article["sentimentAnalysis"] = sentiment
article["sentimentScore"] = round(avg_score, 3)
article["chunksAnalyzed"] = len(chunks)
return article
# ==============================
# FUNZIONE PER GRADIO
# ==============================
def process_input_json():
"""
Legge input.json dal repository, processa gli articoli e restituisce output.json
"""
input_file = "input.json"
output_file = "/tmp/output.json"
# Verifica esistenza file
if not os.path.exists(input_file):
available_files = os.listdir()
error_msg = f"❌ File {input_file} non trovato!\n\nπŸ“‚ File disponibili nella directory:\n"
error_msg += "\n".join(f" - {f}" for f in available_files)
return None, error_msg
try:
# Leggi input
with open(input_file, 'r', encoding='utf-8') as f:
articles = json.load(f)
if not isinstance(articles, list):
return None, "❌ Errore: il file JSON deve contenere un array di articoli"
log = f"πŸ“Š Trovati {len(articles)} articoli da analizzare\n\n"
processed_articles = []
for i, article in enumerate(articles, 1):
title = article.get('title', 'N/A')[:60]
log += f"⏳ [{i}/{len(articles)}] {title}...\n"
processed_article = analyze_article_sentiment(article)
processed_articles.append(processed_article)
log += f" βœ… {processed_article['sentimentAnalysis']} "
log += f"(score: {processed_article['sentimentScore']}, "
log += f"chunks: {processed_article['chunksAnalyzed']})\n\n"
# Scrivi output
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(processed_articles, f, ensure_ascii=False, indent=2)
log += f"\nβœ… COMPLETATO! {len(processed_articles)} articoli processati.\n"
log += f"πŸ’Ύ Output salvato e pronto per il download"
return output_file, log
except Exception as e:
import traceback
error_msg = f"❌ Errore durante l'elaborazione:\n{str(e)}\n\n"
error_msg += f"Traceback:\n{traceback.format_exc()}"
return None, error_msg
def clear_outputs():
"""
Pulisce l'output file e il log
"""
return None, "🧹 Interfaccia pulita! Puoi modificare input.json e riprocessare."
# ==============================
# INTERFACCIA GRADIO
# ==============================
with gr.Blocks(title="Italian Sentiment Analyzer", theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🧠 Italian Sentiment Analyzer")
gr.Markdown("Analizza il sentiment di articoli italiani usando il modello Feel-IT")
gr.Markdown("### πŸ“‹ Istruzioni:")
gr.Markdown("1. Assicurati che `input.json` sia presente nel repository")
gr.Markdown("2. Clicca il pulsante per avviare l'analisi")
gr.Markdown("3. Scarica `output.json` con i risultati")
with gr.Row():
process_btn = gr.Button("πŸš€ Processa input.json", variant="primary", size="lg", scale=2)
clear_btn = gr.Button("🧹 Clear", variant="secondary", size="lg", scale=1)
with gr.Row():
with gr.Column(scale=1):
output_file = gr.File(label="πŸ’Ύ Scarica output.json")
with gr.Column(scale=2):
log_box = gr.Textbox(
label="πŸ“‹ Log elaborazione",
lines=20,
max_lines=30
)
process_btn.click(
fn=process_input_json,
inputs=None,
outputs=[output_file, log_box]
)
clear_btn.click(
fn=clear_outputs,
inputs=None,
outputs=[output_file, log_box]
)
gr.Markdown("---")
gr.Markdown("### πŸ“Š Logica di classificazione:")
gr.Markdown("- **NEGATIVE** πŸ”΄: score ≀ 0.4")
gr.Markdown("- **NEUTRAL** 🟑: 0.4 < score < 0.66")
gr.Markdown("- **POSITIVE** 🟒: score β‰₯ 0.66")
gr.Markdown("### 🎯 Campi aggiunti nell'output:")
gr.Markdown("- **sentimentAnalysis**: POSITIVE / NEUTRAL / NEGATIVE / UNKNOWN")
gr.Markdown("- **sentimentScore**: valore numerico da 0.0 (negativo) a 1.0 (positivo)")
gr.Markdown("- **chunksAnalyzed**: numero di chunks in cui Γ¨ stato suddiviso il testo")
# ==============================
# LAUNCH
# ==============================
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)