|
import gradio as gr |
|
import torch |
|
from transformers import pipeline |
|
import plotly.graph_objects as go |
|
import pandas as pd |
|
|
|
|
|
|
|
|
|
|
|
try: |
|
classifier = pipeline( |
|
"text-classification", |
|
model="oliviercaron/fr-camembert-spplus-sentiment", |
|
device_map="auto", |
|
top_k=None |
|
) |
|
print("Modèle chargé avec succès.") |
|
except Exception as e: |
|
print(f"Erreur lors du chargement du modèle : {e}") |
|
classifier = None |
|
|
|
|
|
|
|
|
|
def analyze_sentiment(text: str): |
|
""" |
|
Analyse le sentiment d'un texte et retourne une synthèse, un graphique |
|
et un tableau détaillé des scores. |
|
""" |
|
if not classifier: |
|
|
|
return "Erreur : Le modèle d'analyse n'est pas disponible.", None, None |
|
|
|
if not text or not text.strip(): |
|
|
|
return None, None, None |
|
|
|
|
|
results = classifier(text)[0] |
|
|
|
|
|
results = sorted(results, key=lambda x: x['score'], reverse=True) |
|
|
|
|
|
labels = [r['label'] for r in results] |
|
scores_formatted = [f"{r['score'] * 100:.2f} %" for r in results] |
|
emoji_map = {"Positif": "🟢", "Négatif": "🔴", "Neutre": "⚪"} |
|
emojis = [emoji_map.get(label, "⚫") for label in labels] |
|
|
|
|
|
df_results = pd.DataFrame({ |
|
"": emojis, |
|
"Sentiment": labels, |
|
"Confiance": scores_formatted |
|
}) |
|
|
|
|
|
chart_scores = [r['score'] * 100 for r in results] |
|
colors = ['#22c55e' if label == 'Positif' else '#ef4444' if label == 'Négatif' else '#6b7280' for label in labels] |
|
|
|
fig = go.Figure(data=[ |
|
go.Bar( |
|
x=labels, y=chart_scores, marker_color=colors, |
|
text=[f'{s:.1f}%' for s in chart_scores], textposition='auto', |
|
) |
|
]) |
|
fig.update_layout( |
|
title_text="Distribution des Sentiments", |
|
xaxis_title="Sentiment", yaxis_title="Confiance (%)", |
|
yaxis=dict(range=[0, 100]), |
|
template="plotly_white", height=350, font=dict(size=14) |
|
) |
|
|
|
|
|
top_prediction = results[0] |
|
top_label_emoji = emoji_map.get(top_prediction['label'], "⚫") |
|
|
|
confidence_level = "Très élevée" if top_prediction['score'] > 0.9 else \ |
|
"Élevée" if top_prediction['score'] > 0.7 else \ |
|
"Modérée" if top_prediction['score'] > 0.5 else "Faible" |
|
|
|
summary_text = ( |
|
f"### {top_label_emoji} Prédiction principale : **{top_prediction['label']}**\n" |
|
f"**Niveau de confiance :** {confidence_level} ({top_prediction['score']*100:.1f}%)" |
|
) |
|
|
|
|
|
return summary_text, fig, df_results |
|
|
|
|
|
|
|
|
|
|
|
examples = [ |
|
"Accueil très aimable, explications claires, je suis satisfait.", |
|
"Personnel compétent et à l'écoute, démarche rapide et efficace.", |
|
"Excellent service, je recommande vivement cette démarche en ligne.", |
|
"Je n'ai pas d'avis particulier sur la question.", |
|
"Le service était correct, sans plus.", |
|
"RAS, tout s'est bien passé comme d'habitude.", |
|
"Très déçu, aucune réponse à mes emails depuis des semaines.", |
|
"Procédure beaucoup trop compliquée et inutilement longue.", |
|
] |
|
|
|
|
|
css = """ |
|
.gradio-container { |
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
|
max-width: 1024px; |
|
margin: auto; |
|
} |
|
.main-header { |
|
text-align: center; |
|
margin-bottom: 2rem; |
|
} |
|
""" |
|
|
|
|
|
|
|
|
|
with gr.Blocks(css=css, theme=gr.themes.Soft(), title="Analyse de sentiment") as iface: |
|
|
|
|
|
gr.HTML(""" |
|
<div class="main-header"> |
|
<h1>🇫🇷 Analyse de sentiment pour les Services Publics</h1> |
|
<p style="font-size: 1.1rem; color: #4b5563;"> |
|
Analyse des retours usagers avec le modèle <strong>fr-camembert-spplus-sentiment</strong> |
|
</p> |
|
<p style="font-size: 0.9rem; color: #6b7280;"> |
|
<a href="https://huggingface.co/oliviercaron/fr-camembert-spplus-sentiment" target="_blank">🤗 Voir le modèle sur HuggingFace</a> | |
|
<span>Données issues de la plateforme <a href="https://www.plus.transformation.gouv.fr/" target="_blank">Services Publics +</a></span> |
|
</p> |
|
</div> |
|
""") |
|
|
|
|
|
with gr.Row(variant="panel"): |
|
|
|
with gr.Column(scale=2): |
|
gr.Markdown("### 1. Saisissez votre texte") |
|
text_input = gr.Textbox( |
|
label="Commentaire de l'usager", |
|
placeholder="Ex: 'Très satisfait du service, réponse rapide et claire.'", |
|
lines=5, |
|
) |
|
|
|
analyze_btn = gr.Button("🔍 Analyse du sentiment", variant="primary", scale=1) |
|
|
|
gr.Markdown("### 💡 Ou testez avec des exemples") |
|
|
|
gr.Examples( |
|
examples=examples, |
|
inputs=text_input, |
|
label="Cliquez sur un exemple pour le tester", |
|
examples_per_page=8 |
|
) |
|
|
|
|
|
with gr.Column(scale=3): |
|
gr.Markdown("### 2. Consultez les résultats") |
|
with gr.Tabs(): |
|
|
|
with gr.TabItem("📊 Synthèse", id=0): |
|
summary_output = gr.Markdown(label="Conclusion de l'analyse") |
|
chart_output = gr.Plot(label="Distribution des scores") |
|
|
|
|
|
with gr.TabItem("📋 Scores détaillés", id=1): |
|
dataframe_output = gr.DataFrame( |
|
label="Tableau des probabilités par sentiment", |
|
headers=["", "Sentiment", "Confiance"], |
|
interactive=False, |
|
row_count=(3, "fixed"), |
|
col_count=(3, "fixed") |
|
) |
|
|
|
|
|
analyze_btn.click( |
|
fn=analyze_sentiment, |
|
inputs=[text_input], |
|
|
|
outputs=[summary_output, chart_output, dataframe_output] |
|
) |
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
iface.launch(debug=True) |