|
import gradio as gr |
|
import numpy as np |
|
from transformers import pipeline |
|
import pandas as pd |
|
|
|
|
|
CUSTOM_CSS = """ |
|
.container { |
|
max-width: 1200px; |
|
margin: 0 auto; |
|
padding: 20px; |
|
} |
|
.header-box { |
|
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%); |
|
color: white; |
|
padding: 2rem; |
|
border-radius: 10px; |
|
margin-bottom: 2rem; |
|
text-align: center; |
|
} |
|
.question-box { |
|
background: #f8f9fa; |
|
border: 1px solid #e9ecef; |
|
border-radius: 8px; |
|
padding: 1.5rem; |
|
margin-bottom: 1rem; |
|
box-shadow: 0 2px 4px rgba(0,0,0,0.05); |
|
} |
|
.category-title { |
|
color: #2a5298; |
|
border-bottom: 2px solid #2a5298; |
|
padding-bottom: 0.5rem; |
|
margin-bottom: 1rem; |
|
} |
|
.results-container { |
|
background: white; |
|
border-radius: 10px; |
|
padding: 2rem; |
|
box-shadow: 0 4px 6px rgba(0,0,0,0.1); |
|
} |
|
.profile-card { |
|
background: #f8f9fa; |
|
border-radius: 8px; |
|
padding: 1.5rem; |
|
margin-bottom: 1rem; |
|
text-align: center; |
|
} |
|
.slider-container { |
|
margin: 10px 0; |
|
} |
|
.button-primary { |
|
background: #2a5298 !important; |
|
color: white !important; |
|
padding: 12px 24px !important; |
|
font-weight: bold !important; |
|
} |
|
.results-title { |
|
font-size: 1.5rem; |
|
color: #2a5298; |
|
text-align: center; |
|
margin-bottom: 1rem; |
|
} |
|
""" |
|
|
|
class DiscAnalyzer: |
|
def __init__(self): |
|
self.disc_profiles = { |
|
'D': 'Dominância', |
|
'I': 'Influência', |
|
'S': 'Estabilidade', |
|
'C': 'Conformidade' |
|
} |
|
|
|
self.profile_descriptions = { |
|
'D': """ |
|
## Perfil Dominância (D) |
|
|
|
### Características Principais: |
|
- Direto e decisivo |
|
- Focado em resultados |
|
- Assume riscos calculados |
|
- Forte senso de liderança |
|
|
|
### Pontos Fortes: |
|
- Tomada de decisão rápida |
|
- Determinação |
|
- Orientação para resultados |
|
- Iniciativa |
|
|
|
### Sugestões de Desenvolvimento: |
|
- Desenvolver paciência |
|
- Considerar opiniões alheias |
|
- Praticar escuta ativa |
|
""", |
|
'I': """ |
|
## Perfil Influência (I) |
|
|
|
### Características Principais: |
|
- Comunicativo e entusiasta |
|
- Sociável e otimista |
|
- Persuasivo |
|
- Foco em relacionamentos |
|
|
|
### Pontos Fortes: |
|
- Networking |
|
- Comunicação |
|
- Motivação de equipes |
|
- Criatividade |
|
|
|
### Sugestões de Desenvolvimento: |
|
- Melhorar organização |
|
- Focar em detalhes |
|
- Gerenciar melhor o tempo |
|
""", |
|
'S': """ |
|
## Perfil Estabilidade (S) |
|
|
|
### Características Principais: |
|
- Paciente e consistente |
|
- Bom ouvinte |
|
- Leal e confiável |
|
- Trabalho em equipe |
|
|
|
### Pontos Fortes: |
|
- Cooperação |
|
- Confiabilidade |
|
- Suporte a equipe |
|
- Planejamento |
|
|
|
### Sugestões de Desenvolvimento: |
|
- Ser mais assertivo |
|
- Adaptar-se a mudanças |
|
- Expressar opiniões |
|
""", |
|
'C': """ |
|
## Perfil Conformidade (C) |
|
|
|
### Características Principais: |
|
- Analítico e preciso |
|
- Foco em qualidade |
|
- Organizado |
|
- Atenção aos detalhes |
|
|
|
### Pontos Fortes: |
|
- Análise crítica |
|
- Precisão |
|
- Organização |
|
- Controle de qualidade |
|
|
|
### Sugestões de Desenvolvimento: |
|
- Ser mais flexível |
|
- Tomar decisões mais rápidas |
|
- Desenvolver habilidades sociais |
|
""" |
|
} |
|
|
|
|
|
self.generator = pipeline( |
|
"text-generation", |
|
model="facebook/opt-125m", |
|
device="cpu" |
|
) |
|
|
|
def generate_llm_report(self, scores, perfil_principal): |
|
""" |
|
Gera relatório personalizado usando modelo do Hugging Face baseado nos scores DISC. |
|
Combina a saída do modelo com descrições predefinidas para maior qualidade. |
|
""" |
|
base_description = self.profile_descriptions[perfil_principal] |
|
|
|
prompt = f"""Analise o perfil DISC: |
|
D:{scores['D']:.1f}% I:{scores['I']:.1f}% S:{scores['S']:.1f}% C:{scores['C']:.1f}% |
|
Perfil Principal: {self.disc_profiles[perfil_principal]} |
|
""" |
|
try: |
|
llm_output = self.generator( |
|
prompt, |
|
max_length=300, |
|
num_return_sequences=1, |
|
temperature=0.7, |
|
top_p=0.9, |
|
do_sample=True |
|
) |
|
|
|
ai_insights = llm_output[0]['generated_text'].replace(prompt, "").strip() |
|
|
|
|
|
complete_report = f""" |
|
{base_description} |
|
|
|
### Análise Personalizada: |
|
{ai_insights} |
|
""" |
|
return complete_report |
|
|
|
except Exception as e: |
|
return base_description |
|
|
|
def avaliar_disc(self, *args): |
|
""" |
|
Avalia o perfil DISC baseado nas respostas do questionário. |
|
""" |
|
responses = [int(arg) for arg in args] |
|
|
|
scores = { |
|
'D': sum(responses[i] for i in [0, 4, 8, 12]) / 16 * 100, |
|
'I': sum(responses[i] for i in [1, 5, 9, 13]) / 16 * 100, |
|
'S': sum(responses[i] for i in [2, 6, 10, 14]) / 16 * 100, |
|
'C': sum(responses[i] for i in [3, 7, 11, 15]) / 16 * 100 |
|
} |
|
|
|
perfil_principal = max(scores, key=scores.get) |
|
relatorio_llm = self.generate_llm_report(scores, perfil_principal) |
|
|
|
|
|
df = pd.DataFrame({ |
|
"Dimensão": list(scores.keys()), |
|
"Score": list(scores.values()), |
|
"Descrição": [self.disc_profiles[k] for k in scores.keys()] |
|
}) |
|
|
|
return ( |
|
f"### Seu perfil principal é: {self.disc_profiles[perfil_principal]} ({perfil_principal})", |
|
relatorio_llm, |
|
df, |
|
gr.update(visible=True), |
|
gr.update(visible=False) |
|
) |
|
|
|
def create_disc_interface(): |
|
""" |
|
Cria a interface Gradio para o analisador DISC. |
|
""" |
|
analyzer = DiscAnalyzer() |
|
|
|
with gr.Blocks( |
|
title="Análise de Perfil DISC", |
|
theme=gr.themes.Soft( |
|
primary_hue="blue", |
|
secondary_hue="purple", |
|
), |
|
css=CUSTOM_CSS |
|
) as interface: |
|
|
|
with gr.Box(elem_classes=["header-box"]): |
|
gr.Markdown( |
|
""" |
|
# 🎯 Análise de Perfil DISC Profissional |
|
#### Descubra suas características comportamentais através de IA |
|
""" |
|
) |
|
|
|
|
|
with gr.Box(elem_classes=["container"]) as questionnaire_container: |
|
gr.Markdown( |
|
""" |
|
### 📝 Questionário DISC |
|
Avalie cada afirmação de acordo com sua identificação: |
|
|
|
- 1 = Discordo totalmente |
|
- 2 = Discordo parcialmente |
|
- 3 = Concordo parcialmente |
|
- 4 = Concordo totalmente |
|
""" |
|
) |
|
|
|
|
|
questions = { |
|
"Dominância (D)": [ |
|
"Sou direto e decisivo", |
|
"Gosto de assumir riscos", |
|
"Tomo iniciativa", |
|
"Busco resultados" |
|
], |
|
"Influência (I)": [ |
|
"Sou sociável e entusiasta", |
|
"Sou bom comunicador", |
|
"Sou persuasivo", |
|
"Sou motivador" |
|
], |
|
"Estabilidade (S)": [ |
|
"Sou paciente e cooperativo", |
|
"Sou bom ouvinte", |
|
"Trabalho bem em equipe", |
|
"Sou confiável" |
|
], |
|
"Conformidade (C)": [ |
|
"Sou preciso e analítico", |
|
"Sou organizado", |
|
"Sou detalhista", |
|
"Sou sistemático" |
|
] |
|
} |
|
|
|
sliders = [] |
|
for categoria, perguntas in questions.items(): |
|
with gr.Box(elem_classes=["question-box"]): |
|
gr.Markdown(f"#### {categoria}", elem_classes=["category-title"]) |
|
for i, pergunta in enumerate(perguntas, 1): |
|
with gr.Box(elem_classes=["slider-container"]): |
|
slider = gr.Slider( |
|
minimum=1, |
|
maximum=4, |
|
value=2, |
|
step=1, |
|
label=pergunta, |
|
interactive=True |
|
) |
|
sliders.append(slider) |
|
|
|
analyze_btn = gr.Button( |
|
"📊 Analisar Perfil", |
|
variant="primary", |
|
elem_classes=["button-primary"], |
|
size="lg" |
|
) |
|
|
|
|
|
with gr.Box(visible=False, elem_classes=["results-container"]) as results_container: |
|
gr.Markdown("### 📊 Resultados da Análise", elem_classes=["results-title"]) |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=1): |
|
perfil_output = gr.Markdown( |
|
label="Perfil Principal", |
|
elem_classes=["profile-card"] |
|
) |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=2): |
|
plot_output = gr.BarPlot( |
|
x="Dimensão", |
|
y="Score", |
|
title="Perfil DISC", |
|
tooltip=["Descrição", "Score"], |
|
height=400, |
|
color="Dimensão" |
|
) |
|
with gr.Column(scale=3): |
|
relatorio_output = gr.Markdown( |
|
label="Análise Detalhada", |
|
elem_classes=["report-content"] |
|
) |
|
|
|
|
|
new_test_btn = gr.Button( |
|
"🔄 Fazer Novo Teste", |
|
variant="secondary", |
|
size="lg" |
|
) |
|
|
|
|
|
analyze_btn.click( |
|
fn=analyzer.avaliar_disc, |
|
inputs=sliders, |
|
outputs=[ |
|
perfil_output, |
|
relatorio_output, |
|
plot_output, |
|
results_container, |
|
questionnaire_container |
|
] |
|
) |
|
|
|
new_test_btn.click( |
|
fn=lambda: [2] * 16 + [gr.update(visible=True), gr.update(visible=False)], |
|
inputs=None, |
|
outputs=sliders + [questionnaire_container, results_container] |
|
) |
|
|
|
return interface |
|
|
|
if __name__ == "__main__": |
|
interface = create_disc_interface() |
|
interface.launch( |
|
server_name="0.0.0.0", |
|
server_port=7860, |
|
share=True |
|
) |