Spaces:
Sleeping
Sleeping
import gradio as gr | |
from datetime import datetime | |
from sentence_transformers import SentenceTransformer | |
import numpy as np | |
from typing import Dict, List, Tuple | |
from textblob import TextBlob | |
import json | |
# Load embeddings model | |
model = SentenceTransformer('all-MiniLM-L6-v2') | |
# Load data from JSON | |
with open('coach_data.json', 'r', encoding='utf-8') as f: | |
data = json.load(f) | |
PERGUNTAS = data['perguntas'] | |
TONE_PATTERNS = data['tone_patterns'] | |
RESPOSTAS_COACH = data['respostas_coach'] | |
class EnhancedCoach: | |
def __init__(self): | |
self.pergunta_atual = 0 | |
self.inicio = datetime.now() | |
self.historico_respostas = [] | |
self.sessao_completa = False | |
self.tone_history = [] | |
self.response_quality_metrics = [] | |
def analyze_response_quality(self, text: str) -> Dict[str, float]: | |
sentences = [s.strip() for s in text.split('.') if s.strip()] | |
words = text.lower().split() | |
metrics = { | |
"depth": self._calculate_depth(text, words), | |
"clarity": self._calculate_clarity(sentences), | |
"specificity": self._calculate_specificity(text, words), | |
"actionability": self._calculate_actionability(sentences) | |
} | |
self.response_quality_metrics.append(metrics) | |
return metrics | |
def _calculate_depth(self, text: str, words: List[str]) -> float: | |
if not words: | |
return 0.0 | |
unique_words = len(set(words)) | |
word_length_avg = sum(len(word) for word in words) / len(words) | |
sentences = [s.strip() for s in text.split('.') if s.strip()] | |
word_variety = unique_words / len(words) | |
sentence_length = len(sentences) | |
complexity = word_length_avg / 5 | |
depth_score = (word_variety * 0.4 + | |
min(sentence_length / 3, 1.0) * 0.4 + | |
complexity * 0.2) | |
return min(1.0, depth_score) | |
def _calculate_clarity(self, sentences: List[str]) -> float: | |
if not sentences: | |
return 0.0 | |
avg_length = sum(len(s.split()) for s in sentences) / len(sentences) | |
return 1.0 if 10 <= avg_length <= 20 else 0.7 | |
def _calculate_specificity(self, text: str, words: List[str]) -> float: | |
specific_indicators = [ | |
"exemplo", "especificamente", "concretamente", | |
"situação", "caso", "quando", "onde", "como", | |
"projeto", "equipe", "reunião", "feedback", | |
"resultado", "impacto", "mudança", "melhoria", | |
"implementei", "desenvolvi", "criei", "estabeleci", | |
"eu", "minha", "nosso", "realizei", "fiz" | |
] | |
indicator_count = sum(text.lower().count(ind) for ind in specific_indicators) | |
response_length_factor = min(len(words) / 20, 1.0) | |
return min(1.0, (indicator_count * 0.7 + response_length_factor * 0.3)) | |
def _calculate_actionability(self, sentences: List[str]) -> float: | |
action_verbs = [ | |
"implementar", "fazer", "criar", "desenvolver", "estabelecer", | |
"planejar", "executar", "medir", "avaliar", "iniciar", | |
"construir", "liderar", "coordenar", "definir", "ajustar" | |
] | |
if not sentences: | |
return 0.0 | |
actionable = sum(1 for s in sentences | |
if any(verb in s.lower() for verb in action_verbs)) | |
return min(1.0, actionable / len(sentences)) | |
def analisar_tom(self, texto: str) -> Tuple[str, float]: | |
texto_lower = texto.lower() | |
blob = TextBlob(texto) | |
tone_scores = {} | |
for tone, patterns in TONE_PATTERNS.items(): | |
score = sum(texto_lower.count(pattern) for pattern in patterns) | |
tone_scores[tone] = score * (1 + abs(blob.sentiment.polarity)) | |
predominant_tone = max(tone_scores.items(), key=lambda x: x[1]) | |
return predominant_tone[0], predominant_tone[1] | |
def analisar_sentimento(self, texto: str) -> str: | |
positive_words = [ | |
"consegui", "superei", "aprendi", "melhorei", "efetivo", | |
"cresci", "evoluí", "realizei", "alcancei", "progresso" | |
] | |
negative_words = [ | |
"difícil", "desafiador", "complicado", "problema", "falha", | |
"obstáculo", "limitação", "erro", "confuso", "inseguro" | |
] | |
texto_lower = texto.lower() | |
positive_count = sum(1 for word in positive_words if word in texto_lower) | |
negative_count = sum(1 for word in negative_words if word in texto_lower) | |
if positive_count > negative_count: | |
return "positive" | |
elif negative_count > positive_count: | |
return "improvement" | |
return "neutral" | |
def extrair_acao_especifica(self, texto: str) -> str: | |
sentences = texto.split('.') | |
for sentence in sentences: | |
if any(action in sentence.lower() for action in ["eu", "minha", "realizei", "fiz"]): | |
return sentence.strip() | |
return texto.split('.')[0].strip() | |
def encontrar_melhor_resposta(self, texto_usuario: str, categoria: str) -> str: | |
sentimento = self.analisar_sentimento(texto_usuario) | |
acao_especifica = self.extrair_acao_especifica(texto_usuario) | |
respostas_categoria = RESPOSTAS_COACH[categoria][sentimento] | |
user_embedding = model.encode(texto_usuario) | |
melhor_resposta = None | |
maior_similaridade = -1 | |
for template in respostas_categoria: | |
context_embedding = model.encode(template["context"]) | |
similaridade = np.dot(user_embedding, context_embedding) | |
if similaridade > maior_similaridade: | |
maior_similaridade = similaridade | |
melhor_resposta = template["response"] | |
return melhor_resposta.format(specific_action=acao_especifica.lower()) | |
# Rest of the methods remain the same... | |
# (Previous implementation of gerar_resposta, _gerar_insight_tom, etc.) | |
def criar_interface(): | |
coach = EnhancedCoach() | |
with gr.Blocks(title="Coach de Liderança", theme=gr.themes.Soft()) as app: | |
gr.Markdown("""# 🚀 Coach de Liderança | |
Desenvolva sua liderança através de reflexão guiada e feedback personalizado.""") | |
chat = gr.Chatbot( | |
value=[[None, coach.primeira_pergunta()]], | |
height=600, | |
show_label=False | |
) | |
with gr.Row(): | |
txt = gr.Textbox( | |
placeholder="Compartilhe sua reflexão aqui...", | |
lines=4, | |
label="Sua Resposta" | |
) | |
btn = gr.Button("Enviar", variant="primary") | |
def responder(mensagem, historico): | |
if not mensagem.strip(): | |
return "", historico | |
resposta = coach.gerar_resposta(mensagem) | |
historico.append([mensagem, resposta]) | |
return "", historico | |
txt.submit(responder, [txt, chat], [txt, chat]) | |
btn.click(responder, [txt, chat], [txt, chat]) | |
return app | |
if __name__ == "__main__": | |
app = criar_interface() | |
app.launch() |