hrlima commited on
Commit
f6b6cdf
·
verified ·
1 Parent(s): 2f70844

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -117
app.py CHANGED
@@ -1,137 +1,103 @@
1
- import os
2
- import json
3
  import firebase_admin
4
  from firebase_admin import credentials, firestore
5
- from flask import Flask, request, jsonify
6
- from transformers import AutoTokenizer, AutoModelForSequenceClassification
7
- import torch
8
- import torch.nn.functional as F
9
 
10
  app = Flask(__name__)
11
 
12
- # =============================
13
- # Inicialização segura do Firebase
14
- # =============================
15
- firebase_key = os.getenv("FIREBASE_KEY")
16
- if not firebase_key:
17
- raise RuntimeError("❌ FIREBASE_KEY não encontrado nos Secrets do Space.")
18
-
19
  try:
20
- cred_dict = json.loads(firebase_key)
21
- cred = credentials.Certificate(cred_dict)
22
- if not firebase_admin._apps:
 
23
  firebase_admin.initialize_app(cred)
24
- db = firestore.client()
25
- print("✅ Firebase conectado com sucesso.")
 
 
26
  except Exception as e:
27
  print(f"❌ Erro ao inicializar Firebase: {e}")
28
- db = None
29
-
30
- # =============================
31
- # Inicialização do modelo Transformers
32
- # =============================
33
- MODEL_NAME = "pysentimiento/robertuito-emotion-analysis" # modelo em espanhol
34
- tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
35
- model = AutoModelForSequenceClassification.from_pretrained(MODEL_NAME)
36
- labels = model.config.id2label # mapeia ids para rótulos de emoção
37
-
38
- # =============================
39
- # Fallback baseado em palavras-chave
40
- # =============================
41
- fallback_map = {
42
- "alegria": ["feliz", "contente", "satisfeito", "alegre", "animado"],
43
- "tristeza": ["triste", "chateado", "melancólico", "desanimado"],
44
- "depressao": ["deprimido", "sem vontade", "desesperança", "sem energia"],
45
- "raiva": ["irritado", "zangado", "raiva", "frustrado"],
46
- "ansiedade": ["ansioso", "preocupado", "tenso", "estressado"],
47
- }
48
-
49
- def fallback_emotion(text):
50
- lower = text.lower()
51
- detected = []
52
- for key, words in fallback_map.items():
53
- if any(word in lower for word in words):
54
- detected.append(key)
55
- if not detected:
56
- detected = ["tristeza"]
57
- return detected
58
-
59
- # =============================
60
- # Rota de teste
61
- # =============================
62
- @app.route("/")
63
- def index():
64
- return jsonify({"status": "online", "message": "API Flask funcionando no Space!"})
65
-
66
- # =============================
67
- # Rota principal de análise de emoção
68
- # =============================
69
  @app.route("/analyze", methods=["POST"])
70
- def analyze():
71
  try:
72
- data = request.get_json()
73
- if not data or "text" not in data:
 
 
74
  return jsonify({"error": "Campo 'text' é obrigatório"}), 400
75
 
76
- text = data["text"]
77
- print(f"🧠 Recebido texto para análise: {text}")
78
-
79
- # Tokenização e predição
80
- inputs = tokenizer(text, return_tensors="pt", truncation=True)
81
- with torch.no_grad():
82
- outputs = model(**inputs)
83
- probs = F.softmax(outputs.logits, dim=-1).squeeze()
84
- prob_dict = {labels[i]: round(float(probs[i]), 4) for i in range(len(labels))}
85
-
86
- # Escolhe emoção principal
87
- main_emotion = max(prob_dict, key=prob_dict.get)
88
- detected = [main_emotion]
89
-
90
- # Se nenhuma emoção significativa (prob < 0.2), fallback
91
- if prob_dict[main_emotion] < 0.2:
92
- detected = fallback_emotion(text)
93
- main_emotion = detected[0]
94
- status = "fallback"
95
- suggestion = "Não foi possível identificar claramente a emoção. Fallback baseado em palavras-chave."
96
- else:
97
- status = "ok"
98
- suggestion = "Sugestão não disponível."
99
-
100
- # Resultado final
101
  result = {
102
- "status": status,
103
- "emotion": main_emotion,
104
- "emode": detected,
105
- "probabilities": prob_dict,
106
- "suggestion": suggestion,
107
  }
108
 
109
- # Salva no Firestore
110
- if db:
111
- db.collection("emotions").add({
112
- "text": text,
113
- **result
114
- })
115
-
116
- return jsonify(result)
117
 
118
  except Exception as e:
119
- print(f"❌ Erro detalhado na rota /analyze: {e}")
120
- detected = fallback_emotion(data.get("text", "")) if data else ["tristeza"]
121
- return jsonify({
122
- "status": "fallback",
123
- "emotion": detected[0],
124
- "emode": detected,
125
- "probabilities": {k: 0.0 for k in fallback_map.keys()},
126
- "suggestion": "Erro na análise. Fallback baseado em palavras-chave.",
127
- "debug": str(e)
128
- }), 500
129
-
130
- # =============================
131
- # Inicialização do servidor
132
- # =============================
133
- if __name__ == "__main__":
134
- port = int(os.environ.get("PORT", 7860))
135
- app.run(host="0.0.0.0", port=port, debug=False)
136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
 
 
1
+ from flask import Flask, request, jsonify
 
2
  import firebase_admin
3
  from firebase_admin import credentials, firestore
4
+ from huggingface_hub import InferenceClient
5
+ import os
6
+ import json
 
7
 
8
  app = Flask(__name__)
9
 
10
+ # =============== 🔥 Firebase Initialization ==================
 
 
 
 
 
 
11
  try:
12
+ firebase_json = os.getenv("FIREBASE_CONFIG")
13
+ if firebase_json:
14
+ cred_dict = json.loads(firebase_json)
15
+ cred = credentials.Certificate(cred_dict)
16
  firebase_admin.initialize_app(cred)
17
+ db = firestore.client()
18
+ print("✅ Firebase conectado com sucesso.")
19
+ else:
20
+ print("⚠️ Variável FIREBASE_CONFIG não encontrada.")
21
  except Exception as e:
22
  print(f"❌ Erro ao inicializar Firebase: {e}")
23
+
24
+ # =============== 🤖 Hugging Face API ==================
25
+ HF_TOKEN = os.getenv("HF_TOKEN")
26
+ if not HF_TOKEN:
27
+ raise RuntimeError("❌ HF_TOKEN não encontrado nos Secrets do Space.")
28
+
29
+ client = InferenceClient(token=HF_TOKEN)
30
+
31
+ # Lista de emoções permitidas
32
+ TARGET_EMOTIONS = ["tristeza", "ansiedade", "insegurança", "raiva", "alegria"]
33
+
34
+ # =============== 🧩 Função de análise ==================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  @app.route("/analyze", methods=["POST"])
36
+ def analyze_text():
37
  try:
38
+ data = request.get_json(force=True)
39
+ text = data.get("text", "").strip()
40
+
41
+ if not text:
42
  return jsonify({"error": "Campo 'text' é obrigatório"}), 400
43
 
44
+ # Chamada ao modelo Hugging Face
45
+ response = client.text_classification(
46
+ model="SamLowe/roberta-base-go_emotions", # multilabel + multilingue
47
+ inputs=text,
48
+ )
49
+
50
+ # Extrai as labels com maior score
51
+ best = max(response, key=lambda x: x["score"])
52
+ detected_label = best["label"].lower()
53
+
54
+ # Mapeia as emoções do modelo para as suas emoções personalizadas
55
+ mapped_emotion = "insegurança"
56
+ if "happy" in detected_label or "joy" in detected_label or "content" in detected_label:
57
+ mapped_emotion = "alegria"
58
+ elif "anger" in detected_label or "annoyance" in detected_label:
59
+ mapped_emotion = "raiva"
60
+ elif "sad" in detected_label or "grief" in detected_label:
61
+ mapped_emotion = "tristeza"
62
+ elif "anxiety" in detected_label or "fear" in detected_label or "worry" in detected_label:
63
+ mapped_emotion = "ansiedade"
64
+ elif "nervous" in detected_label or "confusion" in detected_label or "embarrassment" in detected_label:
65
+ mapped_emotion = "insegurança"
66
+
 
 
67
  result = {
68
+ "emotion": mapped_emotion,
69
+ "score": round(best["score"], 4),
70
+ "emode": [mapped_emotion],
71
+ "suggestion": gerar_sugestao(mapped_emotion),
72
+ "status": "ok"
73
  }
74
 
75
+ return jsonify(result), 200
 
 
 
 
 
 
 
76
 
77
  except Exception as e:
78
+ return jsonify({"error": str(e)}), 500
79
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
81
+ def gerar_sugestao(emocao):
82
+ """Sugestões personalizadas por emoção"""
83
+ sugestoes = {
84
+ "alegria": "Continue cultivando momentos positivos!",
85
+ "tristeza": "Procure descansar e conversar com alguém de confiança.",
86
+ "raiva": "Respire fundo, tente se afastar um pouco da situação.",
87
+ "ansiedade": "Tente uma pausa breve, respiração profunda e se hidratar.",
88
+ "insegurança": "Lembre-se do quanto você já conquistou, confie em você!",
89
+ }
90
+ return sugestoes.get(emocao, "Tudo bem sentir isso — observe sem se julgar.")
91
+
92
+
93
+ @app.route("/", methods=["GET"])
94
+ def home():
95
+ return jsonify({
96
+ "message": "API Flask funcionando no Space!",
97
+ "status": "online"
98
+ })
99
+
100
+
101
+ if __name__ == "__main__":
102
+ app.run(host="0.0.0.0", port=7860)
103