DHEIVER commited on
Commit
f22733a
·
verified ·
1 Parent(s): 237f4d4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +97 -359
app.py CHANGED
@@ -1,383 +1,121 @@
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
- import json
8
- import os
9
- from pathlib import Path
10
-
11
- # Configuração inicial
12
- def setup_environment():
13
- """Configura o ambiente inicial e carrega os dados necessários."""
14
- # Verifica se o arquivo JSON existe
15
- if not Path("coach_data.json").exists():
16
- raise FileNotFoundError("O arquivo coach_data.json não foi encontrado")
17
 
18
- try:
19
- # Carrega os dados do JSON
20
- with open('coach_data.json', 'r', encoding='utf-8') as f:
21
- data = json.load(f)
22
- return (
23
- data['perguntas'],
24
- data['tone_patterns'],
25
- data['respostas_coach']
26
- )
27
- except json.JSONDecodeError:
28
- raise ValueError("Erro ao decodificar o arquivo JSON")
29
- except KeyError as e:
30
- raise KeyError(f"Chave obrigatória não encontrada no JSON: {e}")
31
-
32
- # Carrega o modelo de embeddings
33
- try:
34
- model = SentenceTransformer('all-MiniLM-L6-v2')
35
- except Exception as e:
36
- raise RuntimeError(f"Erro ao carregar o modelo de embeddings: {e}")
37
-
38
- # Carrega os dados do coach
39
- PERGUNTAS, TONE_PATTERNS, RESPOSTAS_COACH = setup_environment()
40
 
41
- class EnhancedCoach:
42
- def __init__(self):
43
- """Inicializa o coach com os estados necessários."""
44
- self.pergunta_atual = 0
45
- self.inicio = datetime.now()
46
- self.historico_respostas = []
47
- self.sessao_completa = False
48
- self.tone_history = []
49
- self.response_quality_metrics = []
50
 
51
- def analyze_response_quality(self, text: str) -> Dict[str, float]:
52
- """Analisa a qualidade da resposta do usuário."""
53
- sentences = [s.strip() for s in text.split('.') if s.strip()]
54
- words = text.lower().split()
55
-
56
- metrics = {
57
- "depth": self._calculate_depth(text, words),
58
- "clarity": self._calculate_clarity(sentences),
59
- "specificity": self._calculate_specificity(text, words),
60
- "actionability": self._calculate_actionability(sentences)
61
- }
62
-
63
- self.response_quality_metrics.append(metrics)
64
- return metrics
65
 
66
- def _calculate_depth(self, text: str, words: List[str]) -> float:
67
- """Calcula a profundidade da resposta."""
68
- if not words:
69
- return 0.0
70
-
71
- unique_words = len(set(words))
72
- word_length_avg = sum(len(word) for word in words) / len(words)
73
- sentences = [s.strip() for s in text.split('.') if s.strip()]
74
-
75
- word_variety = unique_words / len(words)
76
- sentence_length = len(sentences)
77
- complexity = word_length_avg / 5
78
-
79
- depth_score = (word_variety * 0.4 +
80
- min(sentence_length / 3, 1.0) * 0.4 +
81
- complexity * 0.2)
82
-
83
- return min(1.0, depth_score)
84
 
85
- def _calculate_clarity(self, sentences: List[str]) -> float:
86
- """Calcula a clareza da resposta."""
87
- if not sentences:
88
- return 0.0
89
- avg_length = sum(len(s.split()) for s in sentences) / len(sentences)
90
- return 1.0 if 10 <= avg_length <= 20 else 0.7
 
91
 
92
- def _calculate_specificity(self, text: str, words: List[str]) -> float:
93
- """Calcula a especificidade da resposta."""
94
- specific_indicators = [
95
- "exemplo", "especificamente", "concretamente",
96
- "situação", "caso", "quando", "onde", "como",
97
- "projeto", "equipe", "reunião", "feedback",
98
- "resultado", "impacto", "mudança", "melhoria",
99
- "implementei", "desenvolvi", "criei", "estabeleci",
100
- "eu", "minha", "nosso", "realizei", "fiz"
101
- ]
102
-
103
- indicator_count = sum(text.lower().count(ind) for ind in specific_indicators)
104
- response_length_factor = min(len(words) / 20, 1.0)
105
-
106
- return min(1.0, (indicator_count * 0.7 + response_length_factor * 0.3))
107
 
108
- def _calculate_actionability(self, sentences: List[str]) -> float:
109
- """Calcula a acionabilidade da resposta."""
110
- action_verbs = [
111
- "implementar", "fazer", "criar", "desenvolver", "estabelecer",
112
- "planejar", "executar", "medir", "avaliar", "iniciar",
113
- "construir", "liderar", "coordenar", "definir", "ajustar"
114
- ]
115
- if not sentences:
116
- return 0.0
117
- actionable = sum(1 for s in sentences
118
- if any(verb in s.lower() for verb in action_verbs))
119
- return min(1.0, actionable / len(sentences))
120
-
121
- def analisar_tom(self, texto: str) -> Tuple[str, float]:
122
- """Analisa o tom predominante da resposta."""
123
- texto_lower = texto.lower()
124
- blob = TextBlob(texto)
125
-
126
- tone_scores = {}
127
- for tone, patterns in TONE_PATTERNS.items():
128
- score = sum(texto_lower.count(pattern) for pattern in patterns)
129
- tone_scores[tone] = score * (1 + abs(blob.sentiment.polarity))
130
-
131
- predominant_tone = max(tone_scores.items(), key=lambda x: x[1])
132
- return predominant_tone[0], predominant_tone[1]
133
-
134
- def analisar_sentimento(self, texto: str) -> str:
135
- """Analisa o sentimento geral da resposta."""
136
- positive_words = [
137
- "consegui", "superei", "aprendi", "melhorei", "efetivo",
138
- "cresci", "evoluí", "realizei", "alcancei", "progresso"
139
- ]
140
- negative_words = [
141
- "difícil", "desafiador", "complicado", "problema", "falha",
142
- "obstáculo", "limitação", "erro", "confuso", "inseguro"
143
- ]
144
-
145
- texto_lower = texto.lower()
146
- positive_count = sum(1 for word in positive_words if word in texto_lower)
147
- negative_count = sum(1 for word in negative_words if word in texto_lower)
148
-
149
- if positive_count > negative_count:
150
- return "positive"
151
- elif negative_count > positive_count:
152
- return "improvement"
153
- return "neutral"
154
-
155
- def extrair_acao_especifica(self, texto: str) -> str:
156
- """Extrai uma ação específica da resposta do usuário."""
157
- sentences = texto.split('.')
158
- for sentence in sentences:
159
- if any(action in sentence.lower() for action in ["eu", "minha", "realizei", "fiz"]):
160
- return sentence.strip()
161
- return texto.split('.')[0].strip()
162
-
163
- def encontrar_melhor_resposta(self, texto_usuario: str, categoria: str) -> str:
164
- """Encontra a melhor resposta do coach baseada no texto do usuário."""
165
- sentimento = self.analisar_sentimento(texto_usuario)
166
- acao_especifica = self.extrair_acao_especifica(texto_usuario)
167
-
168
- respostas_categoria = RESPOSTAS_COACH[categoria][sentimento]
169
- user_embedding = model.encode(texto_usuario)
170
-
171
- melhor_resposta = None
172
- maior_similaridade = -1
173
-
174
- for template in respostas_categoria:
175
- context_embedding = model.encode(template["context"])
176
- similaridade = np.dot(user_embedding, context_embedding)
177
-
178
- if similaridade > maior_similaridade:
179
- maior_similaridade = similaridade
180
- melhor_resposta = template["response"]
181
-
182
- return melhor_resposta.format(specific_action=acao_especifica.lower())
183
 
184
- def gerar_resposta(self, texto_usuario: str) -> str:
185
- """Gera uma resposta completa do coach."""
186
- quality_metrics = self.analyze_response_quality(texto_usuario)
187
-
188
- if quality_metrics["depth"] < 0.15 and quality_metrics["specificity"] < 0.1:
189
- return """### Feedback Inicial 💭
190
-
191
- Para oferecer um feedback mais valioso, poderia compartilhar mais detalhes específicos sobre sua experiência?
192
- Alguns aspectos que enriqueceriam sua reflexão:
193
- - Exemplos concretos da situação
194
- - Ações específicas tomadas
195
- - Resultados observados"""
196
-
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
- tom_predominante, intensidade = self.analisar_tom(texto_usuario)
205
- self.tone_history.append(tom_predominante)
206
-
207
- pergunta_atual = PERGUNTAS[self.pergunta_atual]
208
- self.historico_respostas.append(texto_usuario)
209
-
210
- feedback = self.encontrar_melhor_resposta(
211
- texto_usuario,
212
- pergunta_atual["categoria"]
213
- )
214
-
215
- tom_insight = self._gerar_insight_tom(tom_predominante, intensidade)
216
- padrao_identificado = self._analisar_padroes()
217
-
218
- resposta = f"""### Feedback Personalizado 💭\n\n{feedback}{padrao_identificado}\n\n{tom_insight}"""
219
- resposta += self._gerar_pontos_aprofundamento()
220
-
221
- self.pergunta_atual += 1
222
- if self.pergunta_atual < len(PERGUNTAS):
223
- resposta += self._gerar_proxima_pergunta()
224
  else:
225
- self.sessao_completa = True
226
- tempo = (datetime.now() - self.inicio).seconds // 60
227
- resposta += self.gerar_sumario_final(tempo)
228
-
229
- return resposta
230
-
231
- def _gerar_insight_tom(self, tom: str, intensidade: float) -> str:
232
- """Gera insights baseados no tom da resposta."""
233
- insights = {
234
- "confiante": "Sua confiança ao abordar este tema é notável. Como você construiu esta segurança?",
235
- "reflexivo": "Sua abordagem reflexiva traz profundidade à análise. Continue explorando diferentes perspectivas.",
236
- "hesitante": "Percebo algumas incertezas naturais do processo. Que apoio ajudaria a fortalecer sua confiança?",
237
- "pragmatico": "Seu foco em resultados práticos é valioso. Como você equilibra isso com visão de longo prazo?",
238
- "emocional": "Sua conexão emocional com a liderança demonstra comprometimento genuíno."
239
- }
240
-
241
- if intensidade > 2:
242
- return f"\n\n💡 {insights[tom]} Sua expressão é particularmente intensa neste aspecto."
243
- return f"\n\n💡 {insights[tom]}"
244
-
245
- def _analisar_padroes(self) -> str:
246
- """Analisa padrões nas respostas do usuário."""
247
- if len(self.historico_respostas) <= 1:
248
- return ""
249
 
250
- sentimento_atual = self.analisar_sentimento(self.historico_respostas[-1])
251
- sentimento_anterior = self.analisar_sentimento(self.historico_respostas[-2])
252
-
253
- if sentimento_atual == sentimento_anterior == "positive":
254
- return "\n\n💡 Observo um padrão consistente de confiança em suas respostas. Continue desenvolvendo esses pontos fortes!"
255
- elif sentimento_atual == sentimento_anterior == "improvement":
256
- return "\n\n💡 Percebo que você está identificando áreas de desenvolvimento. Vamos focar em estratégias práticas para esses desafios."
257
- return ""
258
-
259
- def _gerar_pontos_aprofundamento(self) -> str:
260
- """Gera pontos para aprofundamento da reflexão."""
261
- return """
262
-
263
- #### Pontos para Aprofundamento:
264
- 1. Como essa experiência se conecta com seus valores de liderança?
265
- 2. Que recursos específicos você identificou como necessários?
266
- 3. Qual seria o próximo marco de desenvolvimento nessa área?"""
267
-
268
- def _gerar_proxima_pergunta(self) -> str:
269
- """Gera a próxima pergunta da sequência."""
270
- proxima = PERGUNTAS[self.pergunta_atual]
271
- 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..."""
272
-
273
- def primeira_pergunta(self) -> str:
274
- """Gera a mensagem inicial e primeira pergunta do coach."""
275
- return f"""### 👋 Bem-vindo à sua Jornada de Desenvolvimento!
276
-
277
- Vamos explorar aspectos importantes da sua liderança através de reflexões guiadas.
278
-
279
- {PERGUNTAS[0]['pergunta']}
280
-
281
- Tome um momento para conectar com suas experiências e compartilhe sua perspectiva..."""
282
 
283
- def gerar_sumario_final(self, tempo: int) -> str:
284
- """Gera o sumário final da sessão."""
285
- sentimentos = [self.analisar_sentimento(resp) for resp in self.historico_respostas]
286
- predominante = max(set(sentimentos), key=sentimentos.count)
287
 
288
- tone_pattern = max(set(self.tone_history), key=self.tone_history.count)
289
- tone_insight = f"\n\n#### Padrão de Comunicação:\nSeu estilo predominante é {tone_pattern}, o que sugere {self._interpretar_padrao_tom(tone_pattern)}"
 
 
290
 
291
- avg_metrics = {
292
- key: sum(m[key] for m in self.response_quality_metrics) / len(self.response_quality_metrics)
293
- for key in ["depth", "clarity", "specificity", "actionability"]
294
- }
295
-
296
- quality_insights = "\n\n#### Insights de Qualidade das Respostas:"
297
- if avg_metrics["depth"] > 0.7:
298
- quality_insights += "\n- Suas reflexões demonstram profundidade significativa"
299
- if avg_metrics["specificity"] > 0.7:
300
- quality_insights += "\n- Você fornece exemplos concretos e detalhados"
301
- if avg_metrics["actionability"] > 0.7:
302
- quality_insights += "\n- Suas respostas são orientadas para ação"
303
-
304
- if predominante == "positive":
305
- perfil = "Você demonstra forte autoconhecimento e confiança em sua liderança."
306
- elif predominante == "improvement":
307
- perfil = "Você demonstra excelente capacidade de identificar oportunidades de desenvolvimento."
308
- else:
309
- perfil = "Você demonstra uma abordagem equilibrada entre conquistas e desafios."
310
-
311
- return f"""
312
- ### 🎉 Jornada de Desenvolvimento Concluída!
313
-
314
- ⏱️ Tempo de reflexão: {tempo} minutos
315
- 📝 Temas explorados: {len(PERGUNTAS)}
316
-
317
- #### Perfil de Liderança Observado:
318
- {perfil}{tone_insight}{quality_insights}
319
-
320
- #### Recomendações Personalizadas:
321
- 1. Implemente uma ação específica mencionada em suas reflexões esta semana
322
- 2. Mantenha um diário de liderança focado nos temas discutidos
323
- 3. Estabeleça checkpoints mensais para revisar seu progresso
324
-
325
- Deseja iniciar uma nova jornada de desenvolvimento com outros temas?"""
326
-
327
- def _interpretar_padrao_tom(self, tom: str) -> str:
328
- """Interpreta o padrão de tom identificado nas respostas."""
329
- interpretacoes = {
330
- "confiante": "uma base sólida para influenciar e liderar equipes.",
331
- "reflexivo": "uma capacidade valiosa de considerar múltiplas perspectivas.",
332
- "hesitante": "uma oportunidade para fortalecer sua confiança através da prática.",
333
- "pragmatico": "um foco valioso em resultados e implementação.",
334
- "emocional": "uma forte conexão com o impacto humano da liderança."
335
- }
336
- return interpretacoes.get(tom, "um estilo único de liderança.")
337
-
338
- def criar_interface():
339
- """Cria a interface do usuário usando Gradio."""
340
- coach = EnhancedCoach()
341
-
342
- with gr.Blocks(title="Coach de Liderança", theme=gr.themes.Soft()) as app:
343
- gr.Markdown("""# 🚀 Coach de Liderança
344
- Desenvolva sua liderança através de reflexão guiada e feedback personalizado.""")
345
-
346
- chat = gr.Chatbot(
347
- value=[[None, coach.primeira_pergunta()]],
348
- height=600,
349
- show_label=False
350
- )
351
 
352
  with gr.Row():
353
- txt = gr.Textbox(
354
- placeholder="Compartilhe sua reflexão aqui...",
355
- lines=4,
356
- label="Sua Resposta"
357
- )
358
- btn = gr.Button("Enviar", variant="primary")
359
 
360
- def responder(mensagem, historico):
361
- if not mensagem.strip():
362
- return "", historico
363
-
364
- resposta = coach.gerar_resposta(mensagem)
365
- historico.append([mensagem, resposta])
366
- return "", historico
367
 
368
- txt.submit(responder, [txt, chat], [txt, chat])
369
- btn.click(responder, [txt, chat], [txt, chat])
370
 
371
- return app
372
 
373
  def main():
374
- """Função principal para iniciar a aplicação."""
375
- try:
376
- app = criar_interface()
377
- app.launch()
378
- except Exception as e:
379
- print(f"Erro ao iniciar a aplicação: {e}")
380
- raise
 
 
 
 
381
 
382
  if __name__ == "__main__":
383
  main()
 
1
  import gradio as gr
2
+ from transformers import pipeline, AutoModelForCausalLM, AutoTokenizer
3
+ import torch
4
+
5
+ # Configurando os modelos
6
+ def setup_models():
7
+ # Modelo para geração de perguntas (TinyLlama)
8
+ question_tokenizer = AutoTokenizer.from_pretrained("TinyLlama/TinyLlama-1.1B-Chat")
9
+ question_model = AutoModelForCausalLM.from_pretrained("TinyLlama/TinyLlama-1.1B-Chat")
 
 
 
 
 
 
 
10
 
11
+ # Modelo para reflexões (BLOOM)
12
+ reflection_tokenizer = AutoTokenizer.from_pretrained("bigscience/bloom-560m")
13
+ reflection_model = AutoModelForCausalLM.from_pretrained("bigscience/bloom-560m")
14
+
15
+ return (question_tokenizer, question_model), (reflection_tokenizer, reflection_model)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ # Geração de perguntas usando TinyLlama
18
+ def generate_question(question_pipeline):
19
+ prompt = """Generate one thought-provoking leadership question in Portuguese.
20
+ Focus on topics like: team management, decision making, conflict resolution, or motivation.
21
+ Question:"""
 
 
 
 
22
 
23
+ input_ids = question_pipeline[0](prompt, return_tensors="pt").input_ids
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
+ outputs = question_pipeline[1].generate(
26
+ input_ids,
27
+ max_length=100,
28
+ num_return_sequences=1,
29
+ temperature=0.7,
30
+ top_p=0.9,
31
+ do_sample=True
32
+ )
 
 
 
 
 
 
 
 
 
 
33
 
34
+ question = question_pipeline[0].decode(outputs[0], skip_special_tokens=True)
35
+ return question.split("Question:")[-1].strip()
36
+
37
+ # Geração de reflexões usando BLOOM
38
+ def generate_reflection(reflection_pipeline, question, answer):
39
+ prompt = f"""Com base na pergunta: "{question}"
40
+ E na resposta: "{answer}"
41
 
42
+ Gere uma reflexão construtiva sobre a resposta, considerando:
43
+ - Pontos fortes demonstrados
44
+ - Áreas para desenvolvimento
45
+ - Sugestões práticas
 
 
 
 
 
 
 
 
 
 
 
46
 
47
+ Reflexão:"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
+ input_ids = reflection_pipeline[0](prompt, return_tensors="pt").input_ids
50
+
51
+ outputs = reflection_pipeline[1].generate(
52
+ input_ids,
53
+ max_length=200,
54
+ num_return_sequences=1,
55
+ temperature=0.7,
56
+ top_p=0.9,
57
+ do_sample=True
58
+ )
59
+
60
+ reflection = reflection_pipeline[0].decode(outputs[0], skip_special_tokens=True)
61
+ return reflection.split("Reflexão:")[-1].strip()
62
+
63
+ # Interface Gradio
64
+ def create_interface(question_pipeline, reflection_pipeline):
65
+ def process_interaction(answer, history):
66
+ if not history:
67
+ # Primeira interação - gerar pergunta
68
+ question = generate_question(question_pipeline)
69
+ return "", history + [(question, None)]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  else:
71
+ # Gerar reflexão para resposta anterior
72
+ last_question = history[-1][0]
73
+ reflection = generate_reflection(reflection_pipeline, last_question, answer)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
+ # Gerar nova pergunta
76
+ new_question = generate_question(question_pipeline)
77
+
78
+ return "", history + [(last_question, answer), (reflection, None), (new_question, None)]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
+ with gr.Blocks(title="Mentor de Liderança - Powered by Open Source LLMs") as demo:
81
+ gr.Markdown("""
82
+ # 🎯 Mentor de Liderança AI
83
+ Desenvolva suas habilidades de liderança através de perguntas reflexivas e feedback personalizado.
84
 
85
+ Powered by:
86
+ - TinyLlama (Geração de Perguntas)
87
+ - BLOOM (Análise e Reflexões)
88
+ """)
89
 
90
+ chatbot = gr.Chatbot(height=400)
91
+ msg = gr.Textbox(label="Sua Resposta", placeholder="Digite sua resposta aqui...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
  with gr.Row():
94
+ submit = gr.Button("Enviar")
95
+ clear = gr.Button("Limpar Conversa")
 
 
 
 
96
 
97
+ submit.click(
98
+ process_interaction,
99
+ inputs=[msg, chatbot],
100
+ outputs=[msg, chatbot]
101
+ )
 
 
102
 
103
+ clear.click(lambda: ("", None), outputs=[msg, chatbot])
 
104
 
105
+ return demo
106
 
107
  def main():
108
+ # Configuração dos modelos
109
+ print("Inicializando modelos...")
110
+ question_pipeline, reflection_pipeline = setup_models()
111
+
112
+ # Criação e lançamento da interface
113
+ print("Criando interface...")
114
+ demo = create_interface(question_pipeline, reflection_pipeline)
115
+
116
+ # Lançamento do app
117
+ print("Lançando aplicação...")
118
+ demo.launch(share=True)
119
 
120
  if __name__ == "__main__":
121
  main()