Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,392 +1,358 @@
|
|
1 |
import gradio as gr
|
2 |
from datetime import datetime
|
|
|
3 |
import numpy as np
|
4 |
-
from typing import Dict, List, Tuple
|
5 |
-
|
6 |
-
from wordcloud import WordCloud
|
7 |
-
import seaborn as sns
|
8 |
-
import pandas as pd
|
9 |
-
from collections import Counter
|
10 |
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
-
|
29 |
-
|
30 |
-
cont_negativas = sum(1 for word in palavras_negativas if word in texto_lower)
|
31 |
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
else:
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
return None
|
43 |
-
|
44 |
-
# Create the plot
|
45 |
-
fig, ax = plt.subplots(figsize=(8, 4))
|
46 |
-
sns.lineplot(data=valores, marker='o', ax=ax)
|
47 |
-
|
48 |
-
ax.set_title('Tendência de Sentimento nas Respostas')
|
49 |
-
ax.set_xlabel('Número da Resposta')
|
50 |
-
ax.set_ylabel('Sentimento')
|
51 |
-
ax.set_ylim(-1.5, 1.5)
|
52 |
-
ax.grid(True)
|
53 |
-
|
54 |
-
# Add horizontal lines for reference
|
55 |
-
ax.axhline(y=0, color='gray', linestyle='--', alpha=0.5)
|
56 |
-
|
57 |
-
plt.close()
|
58 |
-
return fig
|
59 |
|
60 |
-
def
|
61 |
-
|
62 |
-
|
63 |
-
|
|
|
|
|
|
|
|
|
|
|
64 |
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
# Create word cloud
|
69 |
-
wordcloud = WordCloud(
|
70 |
-
width=800,
|
71 |
-
height=400,
|
72 |
-
background_color='white',
|
73 |
-
colormap='viridis',
|
74 |
-
max_words=100
|
75 |
-
).generate(texto_completo)
|
76 |
-
|
77 |
-
# Create the plot
|
78 |
-
fig, ax = plt.subplots(figsize=(10, 5))
|
79 |
-
ax.imshow(wordcloud, interpolation='bilinear')
|
80 |
-
ax.axis('off')
|
81 |
-
ax.set_title('Nuvem de Palavras das Reflexões')
|
82 |
-
|
83 |
-
plt.close()
|
84 |
-
return fig
|
85 |
|
86 |
-
def
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
if cont_positivas > cont_negativas:
|
104 |
-
temas_fortes.append("- " + sentence.strip())
|
105 |
-
elif cont_negativas > cont_positivas:
|
106 |
-
areas_desenvolvimento.append("- " + sentence.strip())
|
107 |
-
break
|
108 |
else:
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
areas_desenvolvimento.append("- " + acao)
|
114 |
-
|
115 |
-
temas_fortes_str = "\n".join(temas_fortes[:3]) if temas_fortes else "Análise em andamento..."
|
116 |
-
areas_desenvolvimento_str = "\n".join(areas_desenvolvimento[:3]) if areas_desenvolvimento else "Análise em andamento..."
|
117 |
-
|
118 |
-
return temas_fortes_str, areas_desenvolvimento_str
|
119 |
|
120 |
-
|
121 |
-
|
122 |
-
coach = EnhancedCoach()
|
123 |
-
sentimentos = [coach.analisar_sentimento(resp) for resp in respostas]
|
124 |
-
|
125 |
-
# Convert sentiments to numeric values
|
126 |
-
valor_sentimento = {
|
127 |
-
'positive': 1,
|
128 |
-
'neutral': 0,
|
129 |
-
'improvement': -1
|
130 |
-
}
|
131 |
-
valores = [valor_sentimento[s] for s in sentimentos]
|
132 |
-
|
133 |
-
# Create the plot
|
134 |
-
fig, ax = plt.subplots(figsize=(8, 4))
|
135 |
-
sns.lineplot(data=valores, marker='o', ax=ax)
|
136 |
-
|
137 |
-
ax.set_title('Tendência de Sentimento nas Respostas')
|
138 |
-
ax.set_xlabel('Número da Resposta')
|
139 |
-
ax.set_ylabel('Sentimento')
|
140 |
-
ax.set_ylim(-1.5, 1.5)
|
141 |
-
ax.grid(True)
|
142 |
-
|
143 |
-
# Add horizontal lines for reference
|
144 |
-
ax.axhline(y=0, color='gray', linestyle='--', alpha=0.5)
|
145 |
-
|
146 |
-
return fig
|
147 |
|
148 |
-
|
149 |
-
|
150 |
-
# Combine all responses
|
151 |
-
texto_completo = ' '.join(respostas)
|
152 |
-
|
153 |
-
# Create word cloud
|
154 |
-
wordcloud = WordCloud(
|
155 |
-
width=800,
|
156 |
-
height=400,
|
157 |
-
background_color='white',
|
158 |
-
colormap='viridis',
|
159 |
-
max_words=100
|
160 |
-
).generate(texto_completo)
|
161 |
-
|
162 |
-
# Create the plot
|
163 |
-
fig, ax = plt.subplots(figsize=(10, 5))
|
164 |
-
ax.imshow(wordcloud, interpolation='bilinear')
|
165 |
-
ax.axis('off')
|
166 |
-
ax.set_title('Nuvem de Palavras das Reflexões')
|
167 |
-
|
168 |
-
return fig
|
169 |
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
|
188 |
def criar_interface():
|
189 |
coach = EnhancedCoach()
|
190 |
|
191 |
-
with gr.Blocks(title="Coach de Liderança"
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
Desenvolva sua liderança através de reflexão guiada e feedback personalizado.
|
198 |
-
""")
|
199 |
-
|
200 |
-
with gr.Column(scale=1):
|
201 |
-
timer = gr.Number(
|
202 |
-
value=0,
|
203 |
-
label="⏱️ Tempo de Reflexão (minutos)",
|
204 |
-
interactive=False
|
205 |
-
)
|
206 |
-
progress = gr.Slider(
|
207 |
-
value=0,
|
208 |
-
minimum=0,
|
209 |
-
maximum=len(PERGUNTAS),
|
210 |
-
step=1,
|
211 |
-
label="📊 Progresso",
|
212 |
-
interactive=False
|
213 |
-
)
|
214 |
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
show_label=False,
|
221 |
-
type="messages"
|
222 |
-
)
|
223 |
-
|
224 |
-
with gr.Row():
|
225 |
-
with gr.Column(scale=4):
|
226 |
-
txt = gr.Textbox(
|
227 |
-
placeholder="Compartilhe sua reflexão aqui...",
|
228 |
-
lines=4,
|
229 |
-
label="Sua Resposta"
|
230 |
-
)
|
231 |
-
|
232 |
-
with gr.Column(scale=1, min_width=100):
|
233 |
-
with gr.Row():
|
234 |
-
btn = gr.Button("Enviar", variant="primary")
|
235 |
-
clear = gr.Button("Limpar")
|
236 |
-
|
237 |
-
with gr.Row():
|
238 |
-
tema_atual = gr.Textbox(
|
239 |
-
value="Autoconhecimento",
|
240 |
-
label="🎯 Tema Atual",
|
241 |
-
interactive=False
|
242 |
-
)
|
243 |
-
tempo_resposta = gr.Textbox(
|
244 |
-
value="0:00",
|
245 |
-
label="⏱️ Tempo nesta resposta",
|
246 |
-
interactive=False
|
247 |
-
)
|
248 |
-
|
249 |
-
with gr.Tab("📊 Insights"):
|
250 |
-
with gr.Row():
|
251 |
-
with gr.Column():
|
252 |
-
sentiment_chart = gr.Plot(label="Análise de Sentimento")
|
253 |
-
with gr.Column():
|
254 |
-
word_cloud = gr.Plot(label="Nuvem de Palavras")
|
255 |
-
|
256 |
-
with gr.Row():
|
257 |
-
temas_fortes = gr.Textbox(
|
258 |
-
label="💪 Temas com Mais Confiança",
|
259 |
-
interactive=False,
|
260 |
-
lines=3
|
261 |
-
)
|
262 |
-
areas_desenvolvimento = gr.Textbox(
|
263 |
-
label="🎯 Áreas para Desenvolvimento",
|
264 |
-
interactive=False,
|
265 |
-
lines=3
|
266 |
-
)
|
267 |
-
|
268 |
-
with gr.Tab("📝 Notas & Recursos"):
|
269 |
-
with gr.Row():
|
270 |
-
notas = gr.Textbox(
|
271 |
-
placeholder="Faça anotações durante sua jornada...",
|
272 |
-
label="📝 Minhas Notas",
|
273 |
-
lines=5
|
274 |
-
)
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
with gr.Accordion("📚 Recursos por Tema", open=False):
|
278 |
-
gr.Markdown("""
|
279 |
-
### 🎯 Autoconhecimento
|
280 |
-
- [Artigo] Desenvolvendo Autoconsciência na Liderança
|
281 |
-
- [Exercício] Reflexão sobre Valores e Propósito
|
282 |
-
- [Ferramenta] Template de Diário de Liderança
|
283 |
-
|
284 |
-
### 💬 Comunicação
|
285 |
-
- [Guia] Comunicação Assertiva na Liderança
|
286 |
-
- [Checklist] Preparação para Feedbacks Difíceis
|
287 |
-
- [Framework] Estrutura de Comunicação Situacional
|
288 |
-
|
289 |
-
### 🤔 Tomada de Decisão
|
290 |
-
- [Modelo] Framework para Decisões Complexas
|
291 |
-
- [Exercício] Análise de Decisões Passadas
|
292 |
-
- [Template] Documentação de Decisões Importantes
|
293 |
-
""")
|
294 |
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
|
|
|
|
|
|
299 |
|
300 |
def responder(mensagem, historico):
|
301 |
-
"""Process user response and update interface"""
|
302 |
if not mensagem.strip():
|
303 |
-
return
|
304 |
-
txt: "",
|
305 |
-
chat: historico
|
306 |
-
}
|
307 |
-
|
308 |
-
# Format user message
|
309 |
-
msg_usuario = {
|
310 |
-
"role": "user",
|
311 |
-
"content": mensagem
|
312 |
-
}
|
313 |
|
314 |
-
# Generate and format coach response
|
315 |
resposta = coach.gerar_resposta(mensagem)
|
316 |
-
|
317 |
-
|
318 |
-
historico.append([msg_usuario, resposta])
|
319 |
-
|
320 |
-
# Update visualizations
|
321 |
-
sentiment_analysis = None
|
322 |
-
word_cloud_plot = None
|
323 |
-
strong_themes = ""
|
324 |
-
development_areas = ""
|
325 |
-
|
326 |
-
if len(coach.historico_respostas) > 1:
|
327 |
-
sentiment_analysis = analyze_sentiment_trend(coach.historico_respostas)
|
328 |
-
word_cloud_plot = generate_word_cloud(coach.historico_respostas)
|
329 |
-
strong_themes, development_areas = analyze_themes(coach.historico_respostas)
|
330 |
-
|
331 |
-
tempo_atual = int((datetime.now() - coach.inicio).total_seconds() / 60)
|
332 |
-
|
333 |
-
return {
|
334 |
-
txt: "",
|
335 |
-
chat: historico,
|
336 |
-
timer: tempo_atual,
|
337 |
-
progress: coach.pergunta_atual,
|
338 |
-
tema_atual: PERGUNTAS[min(coach.pergunta_atual, len(PERGUNTAS)-1)]["categoria"].title(),
|
339 |
-
tempo_resposta: "0:00",
|
340 |
-
sentiment_chart: sentiment_analysis,
|
341 |
-
word_cloud: word_cloud_plot,
|
342 |
-
temas_fortes: strong_themes,
|
343 |
-
areas_desenvolvimento: development_areas
|
344 |
-
}
|
345 |
-
|
346 |
-
def limpar_chat():
|
347 |
-
"""Reset chat and all related components"""
|
348 |
-
coach.__init__()
|
349 |
-
primeira_mensagem = coach.primeira_pergunta()
|
350 |
-
return {
|
351 |
-
chat: [[None, primeira_mensagem]],
|
352 |
-
txt: "",
|
353 |
-
progress: 0,
|
354 |
-
tema_atual: "Autoconhecimento",
|
355 |
-
tempo_resposta: "0:00",
|
356 |
-
sentiment_chart: None,
|
357 |
-
word_cloud: None,
|
358 |
-
temas_fortes: "",
|
359 |
-
areas_desenvolvimento: ""
|
360 |
-
}
|
361 |
-
|
362 |
-
# Event handlers
|
363 |
-
txt.submit(
|
364 |
-
responder,
|
365 |
-
[txt, chat],
|
366 |
-
[txt, chat, timer, progress, tema_atual, tempo_resposta,
|
367 |
-
sentiment_chart, word_cloud, temas_fortes, areas_desenvolvimento]
|
368 |
-
)
|
369 |
-
|
370 |
-
btn.click(
|
371 |
-
responder,
|
372 |
-
[txt, chat],
|
373 |
-
[txt, chat, timer, progress, tema_atual, tempo_resposta,
|
374 |
-
sentiment_chart, word_cloud, temas_fortes, areas_desenvolvimento]
|
375 |
-
)
|
376 |
|
377 |
-
|
378 |
-
|
379 |
-
None,
|
380 |
-
[chat, txt, progress, tema_atual, tempo_resposta,
|
381 |
-
sentiment_chart, word_cloud, temas_fortes, areas_desenvolvimento]
|
382 |
-
)
|
383 |
-
|
384 |
-
# Timer update
|
385 |
-
gr.on(
|
386 |
-
triggers=[gr.EventListener(every=1)],
|
387 |
-
fn=atualizar_timer,
|
388 |
-
outputs=[timer]
|
389 |
-
)
|
390 |
|
391 |
return app
|
392 |
|
|
|
1 |
import gradio as gr
|
2 |
from datetime import datetime
|
3 |
+
from sentence_transformers import SentenceTransformer
|
4 |
import numpy as np
|
5 |
+
from typing import Dict, List, Tuple
|
6 |
+
from textblob import TextBlob
|
|
|
|
|
|
|
|
|
7 |
|
8 |
+
# Load embeddings model
|
9 |
+
model = SentenceTransformer('all-MiniLM-L6-v2')
|
10 |
+
|
11 |
+
# Define questions with categories and context
|
12 |
+
PERGUNTAS = [
|
13 |
+
{
|
14 |
+
"categoria": "autoconhecimento",
|
15 |
+
"pergunta": "Qual foi seu maior desafio como líder e como você o superou?",
|
16 |
+
"contexto": "desafios liderança superação aprendizado desenvolvimento",
|
17 |
+
},
|
18 |
+
{
|
19 |
+
"categoria": "comunicacao",
|
20 |
+
"pergunta": "Como você adapta seu estilo de comunicação para diferentes membros da equipe?",
|
21 |
+
"contexto": "comunicação adaptação equipe feedback clareza",
|
22 |
+
},
|
23 |
+
{
|
24 |
+
"categoria": "decisao",
|
25 |
+
"pergunta": "Descreva uma decisão difícil recente e como você a tomou.",
|
26 |
+
"contexto": "decisão análise processo resultado impacto",
|
27 |
+
},
|
28 |
+
{
|
29 |
+
"categoria": "autoconhecimento",
|
30 |
+
"pergunta": "Como você identificou e desenvolveu seus pontos fortes como líder?",
|
31 |
+
"contexto": "fortalezas desenvolvimento crescimento reconhecimento",
|
32 |
+
},
|
33 |
+
{
|
34 |
+
"categoria": "comunicacao",
|
35 |
+
"pergunta": "Descreva uma situação em que você precisou dar feedback difícil. Como conduziu?",
|
36 |
+
"contexto": "feedback difícil comunicação empatia resolução",
|
37 |
+
}
|
38 |
+
]
|
39 |
+
|
40 |
+
# Add tone categories with associated words/phrases
|
41 |
+
TONE_PATTERNS = {
|
42 |
+
"confiante": ["certamente", "sem dúvida", "confio", "tenho certeza", "definitivamente"],
|
43 |
+
"reflexivo": ["penso que", "considero", "reflito", "analiso", "pondero"],
|
44 |
+
"hesitante": ["talvez", "pode ser", "não tenho certeza", "possivelmente", "acho que"],
|
45 |
+
"pragmatico": ["na prática", "concretamente", "efetivamente", "resultado", "implementei"],
|
46 |
+
"emocional": ["sinto", "emocionalmente", "impactado", "motivado", "frustrado"]
|
47 |
+
}
|
48 |
+
|
49 |
+
# Enhanced response system with more context and situation-specific feedback
|
50 |
+
RESPOSTAS_COACH = {
|
51 |
+
"autoconhecimento": {
|
52 |
+
"positive": [
|
53 |
+
{
|
54 |
+
"context": "superacao_clara",
|
55 |
+
"response": "Sua capacidade de superar esse desafio demonstra resiliência. Especialmente interessante foi como você {specific_action}. Como você pode usar essa experiência para orientar outros líderes em situações similares?",
|
56 |
+
"keywords": ["superei", "consegui", "aprendi", "mudei", "cresci"]
|
57 |
+
},
|
58 |
+
{
|
59 |
+
"context": "aprendizado_continuo",
|
60 |
+
"response": "Sua jornada de autodesenvolvimento é notável. O fato de você {specific_action} mostra maturidade. Que outros aspectos de liderança essa experiência te motivou a explorar?",
|
61 |
+
"keywords": ["desenvolvimento", "estudo", "aprendo", "busco", "evoluo"]
|
62 |
+
}
|
63 |
+
],
|
64 |
+
"neutral": [
|
65 |
+
{
|
66 |
+
"context": "em_processo",
|
67 |
+
"response": "Você está no caminho certo ao identificar esse desafio. Considerando que você {specific_action}, que recursos ou apoio adicional seriam úteis nesse momento?",
|
68 |
+
"keywords": ["tentando", "buscando", "desenvolvendo", "praticando"]
|
69 |
+
}
|
70 |
+
],
|
71 |
+
"improvement": [
|
72 |
+
{
|
73 |
+
"context": "dificuldade_identificada",
|
74 |
+
"response": "É importante reconhecer áreas de desenvolvimento. Sua menção sobre {specific_action} sugere autoconsciência. Vamos explorar estratégias específicas para fortalecer esse aspecto?",
|
75 |
+
"keywords": ["difícil", "complicado", "desafiador", "preciso melhorar"]
|
76 |
+
}
|
77 |
+
]
|
78 |
+
},
|
79 |
+
"comunicacao": {
|
80 |
+
"positive": [
|
81 |
+
{
|
82 |
+
"context": "adaptacao_efetiva",
|
83 |
+
"response": "Sua abordagem adaptativa é exemplar. O exemplo de como você {specific_action} demonstra sensibilidade às diferentes necessidades. Como você avalia a efetividade dessas adaptações?",
|
84 |
+
"keywords": ["adapto", "personalizo", "ajusto", "observo"]
|
85 |
+
}
|
86 |
+
],
|
87 |
+
"neutral": [
|
88 |
+
{
|
89 |
+
"context": "desenvolvendo_estilo",
|
90 |
+
"response": "Você está desenvolvendo um repertório interessante de estilos de comunicação. Sua estratégia de {specific_action} tem potencial. Que outros métodos você gostaria de experimentar?",
|
91 |
+
"keywords": ["testando", "experimentando", "tentando diferentes"]
|
92 |
+
}
|
93 |
+
],
|
94 |
+
"improvement": [
|
95 |
+
{
|
96 |
+
"context": "desafios_comunicacao",
|
97 |
+
"response": "Reconhecer desafios na comunicação é o primeiro passo. Considerando sua experiência com {specific_action}, que aspectos específicos você gostaria de desenvolver primeiro?",
|
98 |
+
"keywords": ["difícil comunicar", "não consegui", "preciso melhorar"]
|
99 |
+
}
|
100 |
+
]
|
101 |
+
},
|
102 |
+
"decisao": {
|
103 |
+
"positive": [
|
104 |
+
{
|
105 |
+
"context": "processo_estruturado",
|
106 |
+
"response": "Seu processo decisório é bem estruturado. A forma como você {specific_action} demonstra pensamento sistêmico. Como você poderia documentar essas práticas para futuras referências?",
|
107 |
+
"keywords": ["analisei", "considerei", "planejei", "estruturei"]
|
108 |
+
}
|
109 |
+
],
|
110 |
+
"neutral": [
|
111 |
+
{
|
112 |
+
"context": "balanceando_fatores",
|
113 |
+
"response": "Você está equilibrando diferentes fatores em suas decisões. Sua menção sobre {specific_action} mostra consciência. Que frameworks de decisão você conhece que poderiam complementar sua abordagem?",
|
114 |
+
"keywords": ["pesando", "considerando", "avaliando"]
|
115 |
+
}
|
116 |
+
],
|
117 |
+
"improvement": [
|
118 |
+
{
|
119 |
+
"context": "decisao_desafiadora",
|
120 |
+
"response": "Decisões complexas exigem coragem. Sua experiência com {specific_action} oferece aprendizados valiosos. Que apoio ou recursos adicionais teriam sido úteis nesse momento?",
|
121 |
+
"keywords": ["hesitei", "demorei", "incerto"]
|
122 |
+
}
|
123 |
+
]
|
124 |
}
|
125 |
+
}
|
126 |
+
|
127 |
+
class EnhancedCoach:
|
128 |
+
def __init__(self):
|
129 |
+
self.pergunta_atual = 0
|
130 |
+
self.inicio = datetime.now()
|
131 |
+
self.historico_respostas = []
|
132 |
+
self.sessao_completa = False
|
133 |
+
self.tone_history = []
|
134 |
+
|
135 |
+
def analisar_tom(self, texto: str) -> Tuple[str, float]:
|
136 |
+
"""Analisa o tom predominante na resposta usando TextBlob e padrões lexicais."""
|
137 |
+
texto_lower = texto.lower()
|
138 |
+
|
139 |
+
# Análise de sentimento com TextBlob
|
140 |
+
blob = TextBlob(texto)
|
141 |
+
|
142 |
+
# Contagem de padrões de tom
|
143 |
+
tone_scores = {}
|
144 |
+
for tone, patterns in TONE_PATTERNS.items():
|
145 |
+
score = sum(texto_lower.count(pattern) for pattern in patterns)
|
146 |
+
# Normalize with TextBlob polarity
|
147 |
+
tone_scores[tone] = score * (1 + abs(blob.sentiment.polarity))
|
148 |
+
|
149 |
+
# Get predominant tone
|
150 |
+
predominant_tone = max(tone_scores.items(), key=lambda x: x[1])
|
151 |
+
return predominant_tone[0], predominant_tone[1]
|
152 |
+
|
153 |
+
def analisar_sentimento(self, texto: str) -> str:
|
154 |
+
"""Analisa o sentimento geral da resposta."""
|
155 |
+
positive_words = ["consegui", "superei", "aprendi", "melhorei", "efetivo"]
|
156 |
+
negative_words = ["difícil", "desafiador", "complicado", "problema", "falha"]
|
157 |
+
|
158 |
+
texto_lower = texto.lower()
|
159 |
+
positive_count = sum(1 for word in positive_words if word in texto_lower)
|
160 |
+
negative_count = sum(1 for word in negative_words if word in texto_lower)
|
161 |
+
|
162 |
+
if positive_count > negative_count:
|
163 |
+
return "positive"
|
164 |
+
elif negative_count > positive_count:
|
165 |
+
return "improvement"
|
166 |
+
return "neutral"
|
167 |
+
|
168 |
+
def extrair_acao_especifica(self, texto: str) -> str:
|
169 |
+
"""Extrai uma ação específica mencionada na resposta."""
|
170 |
+
sentences = texto.split('.')
|
171 |
+
for sentence in sentences:
|
172 |
+
if any(action in sentence.lower() for action in ["eu", "minha", "realizei", "fiz"]):
|
173 |
+
return sentence.strip()
|
174 |
+
return texto.split('.')[0].strip()
|
175 |
+
|
176 |
+
def encontrar_melhor_resposta(self, texto_usuario: str, categoria: str) -> str:
|
177 |
+
sentimento = self.analisar_sentimento(texto_usuario)
|
178 |
+
acao_especifica = self.extrair_acao_especifica(texto_usuario)
|
179 |
+
|
180 |
+
respostas_categoria = RESPOSTAS_COACH[categoria][sentimento]
|
181 |
+
user_embedding = model.encode(texto_usuario)
|
182 |
+
|
183 |
+
melhor_resposta = None
|
184 |
+
maior_similaridade = -1
|
185 |
+
|
186 |
+
for template in respostas_categoria:
|
187 |
+
context_embedding = model.encode(template["context"])
|
188 |
+
similaridade = np.dot(user_embedding, context_embedding)
|
189 |
+
|
190 |
+
if similaridade > maior_similaridade:
|
191 |
+
maior_similaridade = similaridade
|
192 |
+
melhor_resposta = template["response"]
|
193 |
+
|
194 |
+
return melhor_resposta.format(specific_action=acao_especifica.lower())
|
195 |
|
196 |
+
def gerar_resposta(self, texto_usuario: str) -> str:
|
197 |
+
if self.sessao_completa:
|
198 |
+
self.__init__()
|
199 |
+
|
200 |
+
if self.pergunta_atual >= len(PERGUNTAS):
|
201 |
+
tempo = (datetime.now() - self.inicio).seconds // 60
|
202 |
+
return self.gerar_sumario_final(tempo)
|
203 |
+
|
204 |
+
# Analyze tone
|
205 |
+
tom_predominante, intensidade = self.analisar_tom(texto_usuario)
|
206 |
+
self.tone_history.append(tom_predominante)
|
207 |
|
208 |
+
pergunta_atual = PERGUNTAS[self.pergunta_atual]
|
209 |
+
self.historico_respostas.append(texto_usuario)
|
|
|
210 |
|
211 |
+
feedback = self.encontrar_melhor_resposta(
|
212 |
+
texto_usuario,
|
213 |
+
pergunta_atual["categoria"]
|
214 |
+
)
|
215 |
+
|
216 |
+
# Add tone-specific insights
|
217 |
+
tom_insight = self._gerar_insight_tom(tom_predominante, intensidade)
|
218 |
+
padrao_identificado = self._analisar_padroes()
|
219 |
+
|
220 |
+
resposta = f"""### Feedback Personalizado 💭\n\n{feedback}{padrao_identificado}\n\n{tom_insight}"""
|
221 |
+
resposta += self._gerar_pontos_aprofundamento()
|
222 |
+
|
223 |
+
self.pergunta_atual += 1
|
224 |
+
if self.pergunta_atual < len(PERGUNTAS):
|
225 |
+
resposta += self._gerar_proxima_pergunta()
|
226 |
else:
|
227 |
+
self.sessao_completa = True
|
228 |
+
tempo = (datetime.now() - self.inicio).seconds // 60
|
229 |
+
resposta += self.gerar_sumario_final(tempo)
|
230 |
+
|
231 |
+
return resposta
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
232 |
|
233 |
+
def _gerar_insight_tom(self, tom: str, intensidade: float) -> str:
|
234 |
+
"""Gera insights baseados no tom da resposta."""
|
235 |
+
insights = {
|
236 |
+
"confiante": "Sua confiança ao abordar este tema é notável. Como você construiu esta segurança?",
|
237 |
+
"reflexivo": "Sua abordagem reflexiva traz profundidade à análise. Continue explorando diferentes perspectivas.",
|
238 |
+
"hesitante": "Percebo algumas incertezas naturais do processo. Que apoio ajudaria a fortalecer sua confiança?",
|
239 |
+
"pragmatico": "Seu foco em resultados práticos é valioso. Como você equilibra isso com visão de longo prazo?",
|
240 |
+
"emocional": "Sua conexão emocional com a liderança demonstra comprometimento genuíno."
|
241 |
+
}
|
242 |
|
243 |
+
if intensidade > 2:
|
244 |
+
return f"\n\n💡 {insights[tom]} Sua expressão é particularmente intensa neste aspecto."
|
245 |
+
return f"\n\n💡 {insights[tom]}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
|
247 |
+
def _analisar_padroes(self) -> str:
|
248 |
+
if len(self.historico_respostas) <= 1:
|
249 |
+
return ""
|
250 |
+
|
251 |
+
sentimento_atual = self.analisar_sentimento(self.historico_respostas[-1])
|
252 |
+
sentimento_anterior = self.analisar_sentimento(self.historico_respostas[-2])
|
253 |
+
|
254 |
+
if sentimento_atual == sentimento_anterior == "positive":
|
255 |
+
return "\n\n💡 Observo um padrão consistente de confiança em suas respostas. Continue desenvolvendo esses pontos fortes!"
|
256 |
+
elif sentimento_atual == sentimento_anterior == "improvement":
|
257 |
+
return "\n\n💡 Percebo que você está identificando áreas de desenvolvimento. Vamos focar em estratégias práticas para esses desafios."
|
258 |
+
return ""
|
259 |
+
|
260 |
+
def _gerar_pontos_aprofundamento(self) -> str:
|
261 |
+
return """#### Pontos para Aprofundamento:
|
262 |
+
1. Como essa experiência se conecta com seus valores de liderança?
|
263 |
+
2. Que recursos específicos você identificou como necessários?
|
264 |
+
3. Qual seria o próximo marco de desenvolvimento nessa área?"""
|
265 |
+
|
266 |
+
def _gerar_proxima_pergunta(self) -> str:
|
267 |
+
proxima = PERGUNTAS[self.pergunta_atual]
|
268 |
+
return f"""\n\n### Próxima Reflexão: {proxima['categoria'].title()} 🎯\n\n{proxima['pergunta']}\n\nTome um momento para refletir e conectar com suas experiências..."""
|
269 |
+
|
270 |
+
def gerar_sumario_final(self, tempo: int) -> str:
|
271 |
+
# Analyze patterns in responses
|
272 |
+
sentimentos = [self.analisar_sentimento(resp) for resp in self.historico_respostas]
|
273 |
+
predominante = max(set(sentimentos), key=sentimentos.count)
|
274 |
|
275 |
+
# Add tone pattern analysis
|
276 |
+
tone_pattern = max(set(self.tone_history), key=self.tone_history.count)
|
277 |
+
tone_insight = f"\n\n#### Padrão de Comunicação:\nSeu estilo predominante é {tone_pattern}, o que sugere {self._interpretar_padrao_tom(tone_pattern)}"
|
278 |
|
279 |
+
if predominante == "positive":
|
280 |
+
perfil = "Você demonstra forte autoconhecimento e confiança em sua liderança."
|
281 |
+
elif predominante == "improvement":
|
282 |
+
perfil = "Você demonstra excelente capacidade de identificar oportunidades de desenvolvimento."
|
|
|
|
|
|
|
|
|
|
|
283 |
else:
|
284 |
+
perfil = "Você demonstra uma abordagem equilibrada entre conquistas e desafios."
|
285 |
+
|
286 |
+
return f"""
|
287 |
+
### 🎉 Jornada de Desenvolvimento Concluída!
|
|
|
|
|
|
|
|
|
|
|
|
|
288 |
|
289 |
+
⏱️ Tempo de reflexão: {tempo} minutos
|
290 |
+
📝 Temas explorados: {len(PERGUNTAS)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
|
292 |
+
#### Perfil de Liderança Observado:
|
293 |
+
{perfil}{tone_insight}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
294 |
|
295 |
+
#### Recomendações Personalizadas:
|
296 |
+
1. Implemente uma ação específica mencionada em suas reflexões esta semana
|
297 |
+
2. Mantenha um diário de liderança focado nos temas discutidos
|
298 |
+
3. Estabeleça checkpoints mensais para revisar seu progresso
|
299 |
+
|
300 |
+
Deseja iniciar uma nova jornada de desenvolvimento com outros temas?"""
|
301 |
+
|
302 |
+
def _interpretar_padrao_tom(self, tom: str) -> str:
|
303 |
+
"""Interpreta o significado do padrão de tom predominante."""
|
304 |
+
interpretacoes = {
|
305 |
+
"confiante": "uma base sólida para influenciar e liderar equipes.",
|
306 |
+
"reflexivo": "uma capacidade valiosa de considerar múltiplas perspectivas.",
|
307 |
+
"hesitante": "uma oportunidade para fortalecer sua confiança através da prática.",
|
308 |
+
"pragmatico": "um foco valioso em resultados e implementação.",
|
309 |
+
"emocional": "uma forte conexão com o impacto humano da liderança."
|
310 |
+
}
|
311 |
+
return interpretacoes.get(tom, "um estilo único de liderança.")
|
312 |
+
|
313 |
+
def primeira_pergunta(self):
|
314 |
+
return f"""### 👋 Bem-vindo à sua Jornada de Desenvolvimento!
|
315 |
+
|
316 |
+
Vamos explorar aspectos importantes da sua liderança através de reflexões guiadas.
|
317 |
+
|
318 |
+
{PERGUNTAS[0]['pergunta']}
|
319 |
+
|
320 |
+
Tome um momento para conectar com suas experiências e compartilhe sua perspectiva..."""
|
321 |
|
322 |
def criar_interface():
|
323 |
coach = EnhancedCoach()
|
324 |
|
325 |
+
with gr.Blocks(title="Coach de Liderança") as app:
|
326 |
+
gr.Markdown("""
|
327 |
+
# 🚀 Coach de Liderança
|
328 |
+
|
329 |
+
Desenvolva sua liderança através de reflexão guiada e feedback personalizado.
|
330 |
+
""")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
331 |
|
332 |
+
chat = gr.Chatbot(
|
333 |
+
value=[[None, coach.primeira_pergunta()]],
|
334 |
+
height=600,
|
335 |
+
show_label=False
|
336 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
337 |
|
338 |
+
with gr.Row():
|
339 |
+
txt = gr.Textbox(
|
340 |
+
placeholder="Compartilhe sua reflexão aqui...",
|
341 |
+
lines=4,
|
342 |
+
label="Sua Resposta"
|
343 |
+
)
|
344 |
+
btn = gr.Button("Enviar")
|
345 |
|
346 |
def responder(mensagem, historico):
|
|
|
347 |
if not mensagem.strip():
|
348 |
+
return "", historico
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
349 |
|
|
|
350 |
resposta = coach.gerar_resposta(mensagem)
|
351 |
+
historico.append([mensagem, resposta])
|
352 |
+
return "", historico
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
353 |
|
354 |
+
txt.submit(responder, [txt, chat], [txt, chat])
|
355 |
+
btn.click(responder, [txt, chat], [txt, chat])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
356 |
|
357 |
return app
|
358 |
|