Update app.py
Browse files
app.py
CHANGED
@@ -3,286 +3,114 @@ import plotly.graph_objects as go
|
|
3 |
from sentence_transformers import SentenceTransformer
|
4 |
import numpy as np
|
5 |
|
6 |
-
# Initialize the model
|
7 |
model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
|
8 |
|
9 |
-
# Questionário DISC
|
10 |
DISC_QUESTIONS = [
|
11 |
-
{
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
]
|
37 |
-
},
|
38 |
-
{
|
39 |
-
"pergunta": "Ao lidar com mudanças no ambiente de trabalho, você:",
|
40 |
-
"opcoes": [
|
41 |
-
("D", "Abraça a mudança e lidera a implementação"),
|
42 |
-
("I", "Entusiasma os outros sobre as novas possibilidades"),
|
43 |
-
("S", "Adapta-se gradualmente seguindo o processo"),
|
44 |
-
("C", "Analisa os impactos antes de aceitar")
|
45 |
-
]
|
46 |
-
},
|
47 |
-
{
|
48 |
-
"pergunta": "Sob pressão no trabalho, você tende a:",
|
49 |
-
"opcoes": [
|
50 |
-
("D", "Tornar-se mais direto e focado em resultados"),
|
51 |
-
("I", "Buscar apoio e interação com a equipe"),
|
52 |
-
("S", "Manter a calma e seguir metodicamente"),
|
53 |
-
("C", "Concentrar-se em detalhes e procedimentos")
|
54 |
-
]
|
55 |
-
}
|
56 |
]
|
57 |
|
58 |
-
# Base de conhecimento enriquecida para análise semântica
|
59 |
DISC_INSIGHTS = {
|
60 |
-
'D': {
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
'baixo': [
|
85 |
-
"Você prefere uma comunicação mais objetiva e focada",
|
86 |
-
"Sua abordagem analítica favorece resultados concretos",
|
87 |
-
"Você valoriza dados e fatos em suas interações",
|
88 |
-
"Sua comunicação tende a ser mais formal e estruturada",
|
89 |
-
"Você prioriza eficiência sobre interações sociais"
|
90 |
-
]
|
91 |
-
},
|
92 |
-
'S': {
|
93 |
-
'alto': [
|
94 |
-
"Sua consistência e confiabilidade são pontos fortes",
|
95 |
-
"Você demonstra grande habilidade para trabalho em equipe",
|
96 |
-
"Sua paciência e capacidade de escuta são diferenciais",
|
97 |
-
"Você contribui para a estabilidade do ambiente",
|
98 |
-
"Sua lealdade é uma característica muito valorizada"
|
99 |
-
],
|
100 |
-
'baixo': [
|
101 |
-
"Você se adapta facilmente a mudanças e novos cenários",
|
102 |
-
"Sua flexibilidade é um ponto forte em ambientes dinâmicos",
|
103 |
-
"Você lida bem com múltiplas tarefas simultâneas",
|
104 |
-
"Sua versatilidade permite rápidas adaptações",
|
105 |
-
"Você aprecia variedade e novos desafios"
|
106 |
-
]
|
107 |
-
},
|
108 |
-
'C': {
|
109 |
-
'alto': [
|
110 |
-
"Sua precisão e atenção aos detalhes são notáveis",
|
111 |
-
"Você tem forte capacidade analítica e organizacional",
|
112 |
-
"Sua busca por qualidade é uma característica marcante",
|
113 |
-
"Você valoriza processos bem estruturados",
|
114 |
-
"Sua abordagem sistemática garante resultados consistentes"
|
115 |
-
],
|
116 |
-
'baixo': [
|
117 |
-
"Você demonstra flexibilidade com regras e processos",
|
118 |
-
"Sua praticidade favorece resultados rápidos",
|
119 |
-
"Você se adapta bem a ambientes menos estruturados",
|
120 |
-
"Sua tolerância à ambiguidade é um diferencial",
|
121 |
-
"Você equilibra qualidade com agilidade"
|
122 |
-
]
|
123 |
-
}
|
124 |
}
|
125 |
|
126 |
def get_intensity_level(percentual):
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
elif percentual >=
|
131 |
-
|
132 |
-
elif percentual >= 40:
|
133 |
-
return "moderado"
|
134 |
-
elif percentual >= 25:
|
135 |
-
return "baixo"
|
136 |
-
else:
|
137 |
-
return "muito baixo"
|
138 |
|
139 |
def generate_semantic_insights(perfil, percentual):
|
140 |
-
"""Gera insights baseados em análise semântica."""
|
141 |
nivel = "alto" if percentual >= 50 else "baixo"
|
142 |
insights = DISC_INSIGHTS[perfil][nivel]
|
143 |
-
|
144 |
-
# Criar embedding do perfil
|
145 |
profile_embedding = model.encode(" ".join(insights))
|
146 |
-
|
147 |
-
|
148 |
-
similarities = np.array([np.dot(profile_embedding, model.encode(insight))
|
149 |
-
for insight in insights])
|
150 |
-
top_insights = [insights[i] for i in similarities.argsort()[-3:]]
|
151 |
-
|
152 |
-
return top_insights
|
153 |
|
154 |
def calcular_perfil(respostas):
|
155 |
-
|
156 |
-
contagem = {'D': 0, 'I': 0, 'S': 0, 'C': 0}
|
157 |
-
|
158 |
-
for resposta in respostas:
|
159 |
-
if resposta:
|
160 |
-
perfil = resposta.split()[0]
|
161 |
-
contagem[perfil] += 1
|
162 |
-
|
163 |
total = sum(contagem.values())
|
164 |
-
if total > 0
|
165 |
-
percentuais = {k: (v/total) * 100 for k, v in contagem.items()}
|
166 |
-
else:
|
167 |
-
percentuais = {k: 0 for k in contagem.keys()}
|
168 |
-
|
169 |
-
return percentuais
|
170 |
|
171 |
def create_disc_plot(percentuais):
|
172 |
-
"""Cria visualização do perfil DISC."""
|
173 |
cores = {'D': '#FF4B4B', 'I': '#FFD700', 'S': '#4CAF50', 'C': '#2196F3'}
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
textposition='auto',
|
182 |
-
)
|
183 |
-
])
|
184 |
-
|
185 |
-
fig.update_layout(
|
186 |
-
title='Perfil DISC',
|
187 |
-
yaxis_range=[0, 100],
|
188 |
-
template='plotly_white',
|
189 |
-
height=400
|
190 |
-
)
|
191 |
-
return fig
|
192 |
|
193 |
def gerar_relatorio(percentuais):
|
194 |
-
"""Gera relatório detalhado com insights baseados em NLP."""
|
195 |
perfis = dict(sorted(percentuais.items(), key=lambda x: x[1], reverse=True))
|
196 |
-
principal = list(perfis.keys())[
|
197 |
-
|
198 |
-
|
199 |
-
#
|
200 |
-
principal_insights = generate_semantic_insights(principal, perfis[principal])
|
201 |
-
secundario_insights = generate_semantic_insights(secundario, perfis[secundario])
|
202 |
-
|
203 |
-
# Criar listas formatadas de insights
|
204 |
-
insights_principais = "\n".join([f"• {insight}" for insight in principal_insights])
|
205 |
-
insights_secundarios = "\n".join([f"• {insight}" for insight in secundario_insights])
|
206 |
-
|
207 |
-
report = f"""# Análise de Perfil DISC
|
208 |
-
|
209 |
-
## Visão Geral
|
210 |
-
Seu perfil principal é {principal} com {perfis[principal]:.1f}% (nível {get_intensity_level(perfis[principal])})
|
211 |
-
Perfil secundário: {secundario} com {perfis[secundario]:.1f}% (nível {get_intensity_level(perfis[secundario])})
|
212 |
-
|
213 |
-
## Insights Principais
|
214 |
-
{insights_principais}
|
215 |
-
|
216 |
-
## Influências Secundárias
|
217 |
-
{insights_secundarios}
|
218 |
-
|
219 |
-
## Distribuição DISC Completa:
|
220 |
-
{', '.join([f'{k}: {v:.1f}%' for k, v in perfis.items()])}
|
221 |
-
|
222 |
-
## Observação
|
223 |
-
Este perfil representa suas tendências comportamentais naturais.
|
224 |
-
Os comportamentos podem ser adaptados conforme o contexto e as necessidades específicas."""
|
225 |
-
|
226 |
-
return report
|
227 |
-
|
228 |
-
import gradio as gr
|
229 |
-
import plotly.graph_objects as go
|
230 |
-
from sentence_transformers import SentenceTransformer
|
231 |
-
import numpy as np
|
232 |
-
|
233 |
-
# [Previous code remains the same until create_interface function]
|
234 |
|
235 |
def create_interface():
|
236 |
-
"""Cria interface moderna do teste."""
|
237 |
with gr.Blocks() as iface:
|
238 |
gr.Markdown("# 🎯 Análise de Perfil DISC")
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
gr.Markdown(f"### {i}. {q['pergunta']}")
|
244 |
-
radio = gr.Radio(
|
245 |
-
choices=[f"{p} - {d}" for p, d in q['opcoes']],
|
246 |
-
label=f"Questão {i}" # Added label for better accessibility
|
247 |
-
)
|
248 |
-
radios.append(radio)
|
249 |
-
|
250 |
-
# Resultados
|
251 |
-
plot = gr.Plot()
|
252 |
-
output = gr.Markdown()
|
253 |
-
|
254 |
-
# Botões
|
255 |
-
analyze_btn = gr.Button("Analisar Perfil")
|
256 |
-
reset_btn = gr.Button("Novo Teste")
|
257 |
|
258 |
def process_results(*answers):
|
259 |
-
|
260 |
-
if any(answer is None for answer in answers):
|
261 |
-
return None, "Por favor, responda todas as questões antes de analisar."
|
262 |
-
|
263 |
-
perc = calcular_perfil(answers)
|
264 |
-
return create_disc_plot(perc), gerar_relatorio(perc)
|
265 |
-
|
266 |
-
def reset_form():
|
267 |
-
return [None] * len(radios) + [None, None]
|
268 |
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
inputs=radios,
|
273 |
-
outputs=[plot, output],
|
274 |
-
api_name="analyze" # Added API name for better tracking
|
275 |
-
)
|
276 |
-
|
277 |
-
reset_btn.click(
|
278 |
-
fn=reset_form,
|
279 |
-
inputs=None,
|
280 |
-
outputs=radios + [plot, output],
|
281 |
-
api_name="reset" # Added API name for better tracking
|
282 |
-
)
|
283 |
-
|
284 |
return iface
|
285 |
|
286 |
if __name__ == "__main__":
|
287 |
-
|
288 |
-
iface.launch(show_error=True) # Added show_error for better debugging
|
|
|
3 |
from sentence_transformers import SentenceTransformer
|
4 |
import numpy as np
|
5 |
|
|
|
6 |
model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
|
7 |
|
|
|
8 |
DISC_QUESTIONS = [
|
9 |
+
{"pergunta": "Em situações de trabalho em equipe, você geralmente:",
|
10 |
+
"opcoes": [("D", "Assume a liderança e toma decisões rápidas"),
|
11 |
+
("I", "Motiva o grupo e mantém o ambiente animado"),
|
12 |
+
("S", "Apoia os colegas e mantém a harmonia"),
|
13 |
+
("C", "Analisa detalhadamente antes de agir")]},
|
14 |
+
{"pergunta": "Quando enfrenta um desafio no trabalho, você:",
|
15 |
+
"opcoes": [("D", "Enfrenta diretamente e busca soluções imediatas"),
|
16 |
+
("I", "Discute com outros e busca diferentes perspectivas"),
|
17 |
+
("S", "Mantém a calma e segue um processo estabelecido"),
|
18 |
+
("C", "Pesquisa todas as informações disponíveis primeiro")]},
|
19 |
+
{"pergunta": "Em reuniões profissionais, você costuma:",
|
20 |
+
"opcoes": [("D", "Ir direto ao ponto e focar em resultados"),
|
21 |
+
("I", "Participar ativamente e compartilhar ideias"),
|
22 |
+
("S", "Ouvir atentamente e contribuir quando solicitado"),
|
23 |
+
("C", "Tomar notas e questionar os detalhes")]},
|
24 |
+
{"pergunta": "Ao lidar com mudanças no ambiente de trabalho, você:",
|
25 |
+
"opcoes": [("D", "Abraça a mudança e lidera a implementação"),
|
26 |
+
("I", "Entusiasma os outros sobre as novas possibilidades"),
|
27 |
+
("S", "Adapta-se gradualmente seguindo o processo"),
|
28 |
+
("C", "Analisa os impactos antes de aceitar")]},
|
29 |
+
{"pergunta": "Sob pressão no trabalho, você tende a:",
|
30 |
+
"opcoes": [("D", "Tornar-se mais direto e focado em resultados"),
|
31 |
+
("I", "Buscar apoio e interação com a equipe"),
|
32 |
+
("S", "Manter a calma e seguir metodicamente"),
|
33 |
+
("C", "Concentrar-se em detalhes e procedimentos")]}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
]
|
35 |
|
|
|
36 |
DISC_INSIGHTS = {
|
37 |
+
'D': {'alto': ["Você demonstra forte capacidade de liderança e tomada de decisão",
|
38 |
+
"Sua orientação para resultados é uma característica marcante",
|
39 |
+
"Você tende a enfrentar desafios de forma direta e decisiva"],
|
40 |
+
'baixo': ["Você prefere uma abordagem mais colaborativa e consensual",
|
41 |
+
"Sua tendência é buscar harmonia nas relações profissionais",
|
42 |
+
"Você demonstra cuidado ao tomar decisões importantes"]},
|
43 |
+
'I': {'alto': ["Seu entusiasmo e otimismo são características marcantes",
|
44 |
+
"Você tem grande habilidade para inspirar e motivar pessoas",
|
45 |
+
"Sua comunicação expressiva é um diferencial importante"],
|
46 |
+
'baixo': ["Você prefere uma comunicação mais objetiva e focada",
|
47 |
+
"Sua abordagem analítica favorece resultados concretos",
|
48 |
+
"Você valoriza dados e fatos em suas interações"]},
|
49 |
+
'S': {'alto': ["Sua consistência e confiabilidade são pontos fortes",
|
50 |
+
"Você demonstra grande habilidade para trabalho em equipe",
|
51 |
+
"Sua paciência e capacidade de escuta são diferenciais"],
|
52 |
+
'baixo': ["Você se adapta facilmente a mudanças e novos cenários",
|
53 |
+
"Sua flexibilidade é um ponto forte em ambientes dinâmicos",
|
54 |
+
"Você lida bem com múltiplas tarefas simultâneas"]},
|
55 |
+
'C': {'alto': ["Sua precisão e atenção aos detalhes são notáveis",
|
56 |
+
"Você tem forte capacidade analítica e organizacional",
|
57 |
+
"Sua busca por qualidade é uma característica marcante"],
|
58 |
+
'baixo': ["Você demonstra flexibilidade com regras e processos",
|
59 |
+
"Sua praticidade favorece resultados rápidos",
|
60 |
+
"Você se adapta bem a ambientes menos estruturados"]}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
}
|
62 |
|
63 |
def get_intensity_level(percentual):
|
64 |
+
if percentual >= 75: return "muito alto"
|
65 |
+
elif percentual >= 60: return "alto"
|
66 |
+
elif percentual >= 40: return "moderado"
|
67 |
+
elif percentual >= 25: return "baixo"
|
68 |
+
return "muito baixo"
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
|
70 |
def generate_semantic_insights(perfil, percentual):
|
|
|
71 |
nivel = "alto" if percentual >= 50 else "baixo"
|
72 |
insights = DISC_INSIGHTS[perfil][nivel]
|
|
|
|
|
73 |
profile_embedding = model.encode(" ".join(insights))
|
74 |
+
similarities = np.array([np.dot(profile_embedding, model.encode(insight)) for insight in insights])
|
75 |
+
return [insights[i] for i in similarities.argsort()[-3:]]
|
|
|
|
|
|
|
|
|
|
|
76 |
|
77 |
def calcular_perfil(respostas):
|
78 |
+
contagem = {k: sum(1 for r in respostas if r and r.startswith(k)) for k in 'DISC'}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
total = sum(contagem.values())
|
80 |
+
return {k: (v/total)*100 if total > 0 else 0 for k, v in contagem.items()}
|
|
|
|
|
|
|
|
|
|
|
81 |
|
82 |
def create_disc_plot(percentuais):
|
|
|
83 |
cores = {'D': '#FF4B4B', 'I': '#FFD700', 'S': '#4CAF50', 'C': '#2196F3'}
|
84 |
+
return go.Figure(data=[go.Bar(x=list(percentuais.keys()), y=list(percentuais.values()),
|
85 |
+
marker_color=[cores[k] for k in percentuais.keys()],
|
86 |
+
text=[f'{v:.1f}%' for v in percentuais.values()],
|
87 |
+
textposition='auto')]).update_layout(title='Perfil DISC',
|
88 |
+
yaxis_range=[0, 100],
|
89 |
+
template='plotly_white',
|
90 |
+
height=400)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
|
92 |
def gerar_relatorio(percentuais):
|
|
|
93 |
perfis = dict(sorted(percentuais.items(), key=lambda x: x[1], reverse=True))
|
94 |
+
principal, secundario = list(perfis.keys())[:2]
|
95 |
+
insights_p = "\n".join([f"• {i}" for i in generate_semantic_insights(principal, perfis[principal])])
|
96 |
+
insights_s = "\n".join([f"• {i}" for i in generate_semantic_insights(secundario, perfis[secundario])])
|
97 |
+
return f"""# Análise de Perfil DISC\n\n## Visão Geral\nPerfil principal: {principal} ({perfis[principal]:.1f}% - {get_intensity_level(perfis[principal])})\nPerfil secundário: {secundario} ({perfis[secundario]:.1f}% - {get_intensity_level(perfis[secundario])})\n\n## Insights Principais\n{insights_p}\n\n## Influências Secundárias\n{insights_s}\n\n## Distribuição DISC\n{', '.join([f'{k}: {v:.1f}%' for k, v in perfis.items()])}\n\n## Observação\nEste perfil representa suas tendências comportamentais naturais."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
|
99 |
def create_interface():
|
|
|
100 |
with gr.Blocks() as iface:
|
101 |
gr.Markdown("# 🎯 Análise de Perfil DISC")
|
102 |
+
radios = [gr.Radio(choices=[f"{p} - {d}" for p, d in q['opcoes']], label=f"{i+1}. {q['pergunta']}")
|
103 |
+
for i, q in enumerate(DISC_QUESTIONS)]
|
104 |
+
plot, output = gr.Plot(), gr.Markdown()
|
105 |
+
analyze_btn, reset_btn = gr.Button("Analisar Perfil"), gr.Button("Novo Teste")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
|
107 |
def process_results(*answers):
|
108 |
+
return (None, "Por favor, responda todas as questões.") if any(a is None for a in answers) else (create_disc_plot(calcular_perfil(answers)), gerar_relatorio(calcular_perfil(answers)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
|
110 |
+
analyze_btn.click(fn=process_results, inputs=radios, outputs=[plot, output])
|
111 |
+
reset_btn.click(fn=lambda: [None]*(len(radios)+2), outputs=radios+[plot, output])
|
112 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
return iface
|
114 |
|
115 |
if __name__ == "__main__":
|
116 |
+
create_interface().launch(show_error=True)
|
|