Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -7,8 +7,9 @@ from textblob import TextBlob
|
|
7 |
import nltk
|
8 |
from nltk.tokenize import sent_tokenize
|
9 |
|
10 |
-
# Download
|
11 |
-
nltk.download('punkt')
|
|
|
12 |
|
13 |
# Load embeddings model
|
14 |
model = SentenceTransformer('all-MiniLM-L6-v2')
|
@@ -42,7 +43,7 @@ PERGUNTAS = [
|
|
42 |
}
|
43 |
]
|
44 |
|
45 |
-
# Add tone categories
|
46 |
TONE_PATTERNS = {
|
47 |
"confiante": ["certamente", "sem dúvida", "confio", "tenho certeza", "definitivamente"],
|
48 |
"reflexivo": ["penso que", "considero", "reflito", "analiso", "pondero"],
|
@@ -51,7 +52,7 @@ TONE_PATTERNS = {
|
|
51 |
"emocional": ["sinto", "emocionalmente", "impactado", "motivado", "frustrado"]
|
52 |
}
|
53 |
|
54 |
-
# Enhanced response system
|
55 |
RESPOSTAS_COACH = {
|
56 |
"autoconhecimento": {
|
57 |
"positive": [
|
@@ -139,8 +140,10 @@ class EnhancedCoach:
|
|
139 |
self.response_quality_metrics = []
|
140 |
|
141 |
def analyze_response_quality(self, text: str) -> Dict[str, float]:
|
142 |
-
|
143 |
-
|
|
|
|
|
144 |
|
145 |
metrics = {
|
146 |
"depth": self._calculate_depth(text),
|
@@ -153,26 +156,22 @@ class EnhancedCoach:
|
|
153 |
return metrics
|
154 |
|
155 |
def _calculate_depth(self, text: str) -> float:
|
156 |
-
"""Measures response depth based on length and unique word usage."""
|
157 |
words = text.lower().split()
|
158 |
unique_words = len(set(words))
|
159 |
return min(1.0, (len(words) * unique_words) / 1000)
|
160 |
|
161 |
def _calculate_clarity(self, sentences: List[str]) -> float:
|
162 |
-
"""Measures clarity based on sentence structure."""
|
163 |
if not sentences:
|
164 |
return 0.0
|
165 |
avg_length = sum(len(s.split()) for s in sentences) / len(sentences)
|
166 |
return 1.0 if 10 <= avg_length <= 20 else 0.7
|
167 |
|
168 |
def _calculate_specificity(self, text: str) -> float:
|
169 |
-
"""Measures specificity based on concrete details."""
|
170 |
specific_indicators = ["exemplo", "especificamente", "concretamente",
|
171 |
"situação", "caso", "quando", "onde", "como"]
|
172 |
return min(1.0, sum(text.lower().count(ind) for ind in specific_indicators) / 5)
|
173 |
|
174 |
def _calculate_actionability(self, sentences: List[str]) -> float:
|
175 |
-
"""Measures actionability based on action verbs and concrete steps."""
|
176 |
action_verbs = ["implementar", "fazer", "criar", "desenvolver", "estabelecer",
|
177 |
"planejar", "executar", "medir", "avaliar"]
|
178 |
if not sentences:
|
@@ -182,25 +181,18 @@ class EnhancedCoach:
|
|
182 |
return min(1.0, actionable / len(sentences))
|
183 |
|
184 |
def analisar_tom(self, texto: str) -> Tuple[str, float]:
|
185 |
-
"""Analisa o tom predominante na resposta usando TextBlob e padrões lexicais."""
|
186 |
texto_lower = texto.lower()
|
187 |
-
|
188 |
-
# Análise de sentimento com TextBlob
|
189 |
blob = TextBlob(texto)
|
190 |
|
191 |
-
# Contagem de padrões de tom
|
192 |
tone_scores = {}
|
193 |
for tone, patterns in TONE_PATTERNS.items():
|
194 |
score = sum(texto_lower.count(pattern) for pattern in patterns)
|
195 |
-
# Normalize with TextBlob polarity
|
196 |
tone_scores[tone] = score * (1 + abs(blob.sentiment.polarity))
|
197 |
|
198 |
-
# Get predominant tone
|
199 |
predominant_tone = max(tone_scores.items(), key=lambda x: x[1])
|
200 |
return predominant_tone[0], predominant_tone[1]
|
201 |
|
202 |
def analisar_sentimento(self, texto: str) -> str:
|
203 |
-
"""Analisa o sentimento geral da resposta."""
|
204 |
positive_words = ["consegui", "superei", "aprendi", "melhorei", "efetivo"]
|
205 |
negative_words = ["difícil", "desafiador", "complicado", "problema", "falha"]
|
206 |
|
@@ -215,7 +207,6 @@ class EnhancedCoach:
|
|
215 |
return "neutral"
|
216 |
|
217 |
def extrair_acao_especifica(self, texto: str) -> str:
|
218 |
-
"""Extrai uma ação específica mencionada na resposta."""
|
219 |
sentences = texto.split('.')
|
220 |
for sentence in sentences:
|
221 |
if any(action in sentence.lower() for action in ["eu", "minha", "realizei", "fiz"]):
|
@@ -243,7 +234,6 @@ class EnhancedCoach:
|
|
243 |
return melhor_resposta.format(specific_action=acao_especifica.lower())
|
244 |
|
245 |
def gerar_resposta(self, texto_usuario: str) -> str:
|
246 |
-
# First, analyze response quality
|
247 |
quality_metrics = self.analyze_response_quality(texto_usuario)
|
248 |
|
249 |
if quality_metrics["depth"] < 0.3 or quality_metrics["specificity"] < 0.2:
|
@@ -262,7 +252,6 @@ Alguns aspectos que enriqueceriam sua reflexão:
|
|
262 |
tempo = (datetime.now() - self.inicio).seconds // 60
|
263 |
return self.gerar_sumario_final(tempo)
|
264 |
|
265 |
-
# Analyze tone
|
266 |
tom_predominante, intensidade = self.analisar_tom(texto_usuario)
|
267 |
self.tone_history.append(tom_predominante)
|
268 |
|
@@ -274,7 +263,6 @@ Alguns aspectos que enriqueceriam sua reflexão:
|
|
274 |
pergunta_atual["categoria"]
|
275 |
)
|
276 |
|
277 |
-
# Add tone-specific insights
|
278 |
tom_insight = self._gerar_insight_tom(tom_predominante, intensidade)
|
279 |
padrao_identificado = self._analisar_padroes()
|
280 |
|
@@ -292,7 +280,6 @@ Alguns aspectos que enriqueceriam sua reflexão:
|
|
292 |
return resposta
|
293 |
|
294 |
def _gerar_insight_tom(self, tom: str, intensidade: float) -> str:
|
295 |
-
"""Gera insights baseados no tom da resposta."""
|
296 |
insights = {
|
297 |
"confiante": "Sua confiança ao abordar este tema é notável. Como você construiu esta segurança?",
|
298 |
"reflexivo": "Sua abordagem reflexiva traz profundidade à análise. Continue explorando diferentes perspectivas.",
|
@@ -329,15 +316,12 @@ Alguns aspectos que enriqueceriam sua reflexão:
|
|
329 |
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..."""
|
330 |
|
331 |
def gerar_sumario_final(self, tempo: int) -> str:
|
332 |
-
# Analyze patterns in responses
|
333 |
sentimentos = [self.analisar_sentimento(resp) for resp in self.historico_respostas]
|
334 |
predominante = max(set(sentimentos), key=sentimentos.count)
|
335 |
|
336 |
-
# Add tone pattern analysis
|
337 |
tone_pattern = max(set(self.tone_history), key=self.tone_history.count)
|
338 |
tone_insight = f"\n\n#### Padrão de Comunicação:\nSeu estilo predominante é {tone_pattern}, o que sugere {self._interpretar_padrao_tom(tone_pattern)}"
|
339 |
|
340 |
-
# Analyze overall response quality metrics
|
341 |
avg_metrics = {
|
342 |
key: sum(m[key] for m in self.response_quality_metrics) / len(self.response_quality_metrics)
|
343 |
for key in ["depth", "clarity", "specificity", "actionability"]
|
@@ -375,7 +359,6 @@ Alguns aspectos que enriqueceriam sua reflexão:
|
|
375 |
Deseja iniciar uma nova jornada de desenvolvimento com outros temas?"""
|
376 |
|
377 |
def _interpretar_padrao_tom(self, tom: str) -> str:
|
378 |
-
"""Interpreta o significado do padrão de tom predominante."""
|
379 |
interpretacoes = {
|
380 |
"confiante": "uma base sólida para influenciar e liderar equipes.",
|
381 |
"reflexivo": "uma capacidade valiosa de considerar múltiplas perspectivas.",
|
@@ -397,17 +380,17 @@ Tome um momento para conectar com suas experiências e compartilhe sua perspecti
|
|
397 |
def criar_interface():
|
398 |
coach = EnhancedCoach()
|
399 |
|
400 |
-
with gr.Blocks(title="Coach de Liderança") as app:
|
401 |
gr.Markdown("""
|
402 |
# 🚀 Coach de Liderança
|
403 |
-
|
404 |
Desenvolva sua liderança através de reflexão guiada e feedback personalizado.
|
405 |
""")
|
406 |
|
407 |
chat = gr.Chatbot(
|
408 |
value=[[None, coach.primeira_pergunta()]],
|
409 |
height=600,
|
410 |
-
show_label=False
|
|
|
411 |
)
|
412 |
|
413 |
with gr.Row():
|
|
|
7 |
import nltk
|
8 |
from nltk.tokenize import sent_tokenize
|
9 |
|
10 |
+
# Download NLTK data
|
11 |
+
nltk.download(['punkt', 'punkt_tab'])
|
12 |
+
nltk.download('punkt', language='portuguese')
|
13 |
|
14 |
# Load embeddings model
|
15 |
model = SentenceTransformer('all-MiniLM-L6-v2')
|
|
|
43 |
}
|
44 |
]
|
45 |
|
46 |
+
# Add tone categories
|
47 |
TONE_PATTERNS = {
|
48 |
"confiante": ["certamente", "sem dúvida", "confio", "tenho certeza", "definitivamente"],
|
49 |
"reflexivo": ["penso que", "considero", "reflito", "analiso", "pondero"],
|
|
|
52 |
"emocional": ["sinto", "emocionalmente", "impactado", "motivado", "frustrado"]
|
53 |
}
|
54 |
|
55 |
+
# Enhanced response system
|
56 |
RESPOSTAS_COACH = {
|
57 |
"autoconhecimento": {
|
58 |
"positive": [
|
|
|
140 |
self.response_quality_metrics = []
|
141 |
|
142 |
def analyze_response_quality(self, text: str) -> Dict[str, float]:
|
143 |
+
try:
|
144 |
+
sentences = sent_tokenize(text, language='portuguese')
|
145 |
+
except LookupError:
|
146 |
+
sentences = [s.strip() for s in text.split('.') if s.strip()]
|
147 |
|
148 |
metrics = {
|
149 |
"depth": self._calculate_depth(text),
|
|
|
156 |
return metrics
|
157 |
|
158 |
def _calculate_depth(self, text: str) -> float:
|
|
|
159 |
words = text.lower().split()
|
160 |
unique_words = len(set(words))
|
161 |
return min(1.0, (len(words) * unique_words) / 1000)
|
162 |
|
163 |
def _calculate_clarity(self, sentences: List[str]) -> float:
|
|
|
164 |
if not sentences:
|
165 |
return 0.0
|
166 |
avg_length = sum(len(s.split()) for s in sentences) / len(sentences)
|
167 |
return 1.0 if 10 <= avg_length <= 20 else 0.7
|
168 |
|
169 |
def _calculate_specificity(self, text: str) -> float:
|
|
|
170 |
specific_indicators = ["exemplo", "especificamente", "concretamente",
|
171 |
"situação", "caso", "quando", "onde", "como"]
|
172 |
return min(1.0, sum(text.lower().count(ind) for ind in specific_indicators) / 5)
|
173 |
|
174 |
def _calculate_actionability(self, sentences: List[str]) -> float:
|
|
|
175 |
action_verbs = ["implementar", "fazer", "criar", "desenvolver", "estabelecer",
|
176 |
"planejar", "executar", "medir", "avaliar"]
|
177 |
if not sentences:
|
|
|
181 |
return min(1.0, actionable / len(sentences))
|
182 |
|
183 |
def analisar_tom(self, texto: str) -> Tuple[str, float]:
|
|
|
184 |
texto_lower = texto.lower()
|
|
|
|
|
185 |
blob = TextBlob(texto)
|
186 |
|
|
|
187 |
tone_scores = {}
|
188 |
for tone, patterns in TONE_PATTERNS.items():
|
189 |
score = sum(texto_lower.count(pattern) for pattern in patterns)
|
|
|
190 |
tone_scores[tone] = score * (1 + abs(blob.sentiment.polarity))
|
191 |
|
|
|
192 |
predominant_tone = max(tone_scores.items(), key=lambda x: x[1])
|
193 |
return predominant_tone[0], predominant_tone[1]
|
194 |
|
195 |
def analisar_sentimento(self, texto: str) -> str:
|
|
|
196 |
positive_words = ["consegui", "superei", "aprendi", "melhorei", "efetivo"]
|
197 |
negative_words = ["difícil", "desafiador", "complicado", "problema", "falha"]
|
198 |
|
|
|
207 |
return "neutral"
|
208 |
|
209 |
def extrair_acao_especifica(self, texto: str) -> str:
|
|
|
210 |
sentences = texto.split('.')
|
211 |
for sentence in sentences:
|
212 |
if any(action in sentence.lower() for action in ["eu", "minha", "realizei", "fiz"]):
|
|
|
234 |
return melhor_resposta.format(specific_action=acao_especifica.lower())
|
235 |
|
236 |
def gerar_resposta(self, texto_usuario: str) -> str:
|
|
|
237 |
quality_metrics = self.analyze_response_quality(texto_usuario)
|
238 |
|
239 |
if quality_metrics["depth"] < 0.3 or quality_metrics["specificity"] < 0.2:
|
|
|
252 |
tempo = (datetime.now() - self.inicio).seconds // 60
|
253 |
return self.gerar_sumario_final(tempo)
|
254 |
|
|
|
255 |
tom_predominante, intensidade = self.analisar_tom(texto_usuario)
|
256 |
self.tone_history.append(tom_predominante)
|
257 |
|
|
|
263 |
pergunta_atual["categoria"]
|
264 |
)
|
265 |
|
|
|
266 |
tom_insight = self._gerar_insight_tom(tom_predominante, intensidade)
|
267 |
padrao_identificado = self._analisar_padroes()
|
268 |
|
|
|
280 |
return resposta
|
281 |
|
282 |
def _gerar_insight_tom(self, tom: str, intensidade: float) -> str:
|
|
|
283 |
insights = {
|
284 |
"confiante": "Sua confiança ao abordar este tema é notável. Como você construiu esta segurança?",
|
285 |
"reflexivo": "Sua abordagem reflexiva traz profundidade à análise. Continue explorando diferentes perspectivas.",
|
|
|
316 |
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..."""
|
317 |
|
318 |
def gerar_sumario_final(self, tempo: int) -> str:
|
|
|
319 |
sentimentos = [self.analisar_sentimento(resp) for resp in self.historico_respostas]
|
320 |
predominante = max(set(sentimentos), key=sentimentos.count)
|
321 |
|
|
|
322 |
tone_pattern = max(set(self.tone_history), key=self.tone_history.count)
|
323 |
tone_insight = f"\n\n#### Padrão de Comunicação:\nSeu estilo predominante é {tone_pattern}, o que sugere {self._interpretar_padrao_tom(tone_pattern)}"
|
324 |
|
|
|
325 |
avg_metrics = {
|
326 |
key: sum(m[key] for m in self.response_quality_metrics) / len(self.response_quality_metrics)
|
327 |
for key in ["depth", "clarity", "specificity", "actionability"]
|
|
|
359 |
Deseja iniciar uma nova jornada de desenvolvimento com outros temas?"""
|
360 |
|
361 |
def _interpretar_padrao_tom(self, tom: str) -> str:
|
|
|
362 |
interpretacoes = {
|
363 |
"confiante": "uma base sólida para influenciar e liderar equipes.",
|
364 |
"reflexivo": "uma capacidade valiosa de considerar múltiplas perspectivas.",
|
|
|
380 |
def criar_interface():
|
381 |
coach = EnhancedCoach()
|
382 |
|
383 |
+
with gr.Blocks(title="Coach de Liderança", theme=gr.themes.Base()) as app:
|
384 |
gr.Markdown("""
|
385 |
# 🚀 Coach de Liderança
|
|
|
386 |
Desenvolva sua liderança através de reflexão guiada e feedback personalizado.
|
387 |
""")
|
388 |
|
389 |
chat = gr.Chatbot(
|
390 |
value=[[None, coach.primeira_pergunta()]],
|
391 |
height=600,
|
392 |
+
show_label=False,
|
393 |
+
type="messages"
|
394 |
)
|
395 |
|
396 |
with gr.Row():
|