File size: 14,504 Bytes
c6c178c | 1 2 3 4 5 6 7 8 9 10 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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | """
Cognitive Agent Evaluator v2.0 - Interactive Hugging Face Space
Engineered by Fabio Torres (neurodeveloper11)
Bilingual Behavioral Telemetry, 10-Axis Cognitive Bias Audit & AI Alignment Mitigation Engine
"""
import asyncio
import json
import plotly.graph_objects as go
import gradio as gr
from src.schemas import EvaluationRequest
from src.agent import CognitiveEvaluationAgent
from src.biases import BIAS_DEFINITIONS
agent = CognitiveEvaluationAgent()
ALL_BIAS_NAMES = list(BIAS_DEFINITIONS.keys())
def create_radar_chart(detected_biases):
"""
Creates a 10-axis Spider / Radar chart in Plotly visualizing the cognitive distortion profile.
"""
scores = {}
for name in ALL_BIAS_NAMES:
scores[name] = 0.0
for b in detected_biases:
if b.bias_name in scores:
weight = 1.0 if b.severity == "high" else 0.65
scores[b.bias_name] = round(b.confidence_score * weight, 2)
categories = [
"Confirmation", "Anchoring", "Sunk Cost", "Availability", "Framing",
"Catastrophizing", "All-or-Nothing", "Overconfidence", "Attribution", "Outcome Bias"
]
values = [
scores.get("Confirmation Bias", 0),
scores.get("Anchoring Bias", 0),
scores.get("Sunk Cost Fallacy", 0),
scores.get("Availability Heuristic", 0),
scores.get("Framing Effect", 0),
scores.get("Catastrophizing", 0),
scores.get("All-or-Nothing Thinking", 0),
scores.get("Overconfidence Bias", 0),
scores.get("Fundamental Attribution Bias", 0),
scores.get("Outcome Bias", 0),
]
# Close polygon
categories_closed = categories + [categories[0]]
values_closed = values + [values[0]]
fig = go.Figure()
fig.add_trace(go.Scatterpolar(
r=values_closed,
theta=categories_closed,
fill='toself',
name='Distortion Footprint',
fillcolor='rgba(99, 102, 241, 0.35)',
line=dict(color='#4f46e5', width=2.5),
marker=dict(size=6, color='#4338ca')
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 1.0],
tickvals=[0.25, 0.50, 0.75, 1.0],
ticktext=["25%", "50%", "75%", "100%"],
linecolor="#cbd5e1",
gridcolor="#e2e8f0"
),
angularaxis=dict(
linecolor="#cbd5e1",
gridcolor="#e2e8f0"
)
),
showlegend=False,
margin=dict(l=40, r=40, t=30, b=30),
height=380,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)"
)
return fig
def evaluate_text_sync(text: str, author_type: str):
"""
Synchronous wrapper for agent evaluation.
"""
if not text or len(text.strip()) < 5:
return (
"⚠️ Por favor ingresa un texto con al menos 5 caracteres.",
"N/A", "0.0", "0.0", "0.0", "0.0",
create_radar_chart([]),
"<p style='color:#64748b;'>Sin datos suficientes para evaluar.</p>",
"Sin intervenciones requeridas.",
"Sin directiva necesaria.",
"{}"
)
author_code = "llm" if "LLM" in author_type else ("human" if "Human" in author_type else "hybrid")
req = EvaluationRequest(text=text, author_type=author_code)
result = asyncio.run(agent.evaluate(req))
# Format KPI badges
risk_color = "#10b981" if result.mitigation.alignment_risk_level == "nominal" else (
"#f59e0b" if result.mitigation.alignment_risk_level == "moderate" else "#ef4444"
)
risk_html = f"<div style='font-size:22px; font-weight:800; color:{risk_color}; text-transform:uppercase;'>{result.mitigation.alignment_risk_level}</div>"
cog_load = f"{result.psychometrics.cognitive_load_index} / 100"
burnout = f"{result.psychometrics.burnout_risk_index} / 100"
safety = f"{result.psychometrics.psychological_safety_score} / 100"
valence = f"{result.psychometrics.emotional_valence:+.2f}"
# Generate Radar Chart
fig = create_radar_chart(result.biases_detected)
# Detailed Biases HTML
if not result.biases_detected:
biases_html = """
<div style='background:#f0fdf4; border:1px solid #bbf7d0; border-radius:8px; padding:16px; color:#166534;'>
<strong>✅ No se detectaron distorsiones cognitivas críticas.</strong>
<p style='margin-top:4px; font-size:14px;'>El texto muestra un razonamiento balanceado y dentro de parámetros nominales.</p>
</div>
"""
else:
cards = []
for b in result.biases_detected:
sev_badge = f"<span style='background:{'#fee2e2' if b.severity=='high' else '#fef3c7'}; color:{'#991b1b' if b.severity=='high' else '#92400e'}; padding:2px 8px; border-radius:4px; font-weight:700; font-size:12px;'>Severidad: {b.severity.upper()}</span>"
patterns_badges = "".join([f"<code style='background:#f1f5f9; color:#0f172a; padding:2px 6px; border-radius:4px; margin-right:4px; font-size:12px;'>\"{p}\"</code>" for p in b.matched_patterns])
card = f"""
<div style='background:#ffffff; border:1px solid #e2e8f0; border-left:4px solid {'#ef4444' if b.severity=='high' else '#f59e0b'}; border-radius:8px; padding:14px; margin-bottom:12px;'>
<div style='display:flex; justify-content:space-between; align-items:center; margin-bottom:6px;'>
<span style='font-weight:700; font-size:16px; color:#1e293b;'>🧠 {b.bias_name}</span>
<div>{sev_badge} <span style='font-size:12px; color:#64748b; margin-left:6px;'>Confianza: {int(b.confidence_score*100)}%</span></div>
</div>
<p style='color:#475569; font-size:14px; margin-bottom:8px;'>{b.explanation}</p>
<div style='font-size:13px; color:#64748b;'><strong>Disparadores detectados:</strong> {patterns_badges}</div>
</div>
"""
cards.append(card)
biases_html = "".join(cards)
# Interventions list
interventions_md = "\n".join([f"- **{i+1}.** {it}" for i, it in enumerate(result.mitigation.recommended_interventions)])
if result.mitigation.counterfactual_prompt:
interventions_md += f"\n\n**🔄 Ejercicio Contrafactual de Des-sesgo:**\n> *\"{result.mitigation.counterfactual_prompt}\"*"
# Red Teaming Directive
red_teaming = result.mitigation.red_teaming_directive or "No se requiere directiva de red-teaming."
# Raw JSON
json_output = json.dumps(result.model_dump(mode="json"), indent=2, ensure_ascii=False)
return (
risk_html,
cog_load,
burnout,
safety,
valence,
fig,
biases_html,
interventions_md,
red_teaming,
json_output
)
CUSTOM_CSS = """
.gradio-container { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important; }
.header-box { background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 100%); color: white; padding: 24px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
.header-title { font-size: 26px; font-weight: 800; margin-bottom: 6px; color: #f8fafc; }
.header-sub { font-size: 14px; color: #cbd5e1; margin-bottom: 12px; }
.badge-link { display: inline-block; background: rgba(255,255,255,0.12); color: #93c5fd; padding: 4px 10px; border-radius: 6px; font-size: 12px; text-decoration: none; margin-right: 8px; font-weight: 600; }
.badge-link:hover { background: rgba(255,255,255,0.22); color: #ffffff; }
"""
with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Soft(primary_hue="indigo", neutral_hue="slate")) as demo:
gr.HTML("""
<div class="header-box">
<div class="header-title">🧠 Cognitive Agent Evaluator v2.0</div>
<div class="header-sub">Autonomous Behavioral Telemetry • 10-Axis Cognitive Distortion Audit • AI Alignment & Debiasing Engine</div>
<div>
<a class="badge-link" href="https://www.linkedin.com/in/fabio-torres-39364b258/" target="_blank">👔 Fabio Torres | LinkedIn</a>
<a class="badge-link" href="https://github.com/neurodeveloper11/cognitive-agent-evaluator" target="_blank">💻 GitHub Repository</a>
<span class="badge-link" style="color:#a7f3d0;">🎓 M.Sc. Data Engineering & Cloud • 10+ Years Behavioral Science</span>
<span class="badge-link" style="color:#fde68a;">🚀 Hugging Face v2.0 Live</span>
</div>
</div>
""")
with gr.Row():
with gr.Column(scale=5):
input_text = gr.Textbox(
label="Texto o Traza de Razonamiento a Evaluar (Español o Inglés)",
placeholder="Pega aquí el razonamiento de un modelo LLM, un correo laboral, una transcripción de reunión o una decisión de arquitectura...",
lines=7
)
with gr.Row():
author_type = gr.Dropdown(
choices=["LLM Reasoning Trace (Modelo de IA)", "Human Decision Maker (Humano)", "Team Channel / Meeting Transcript (Equipo)"],
value="LLM Reasoning Trace (Modelo de IA)",
label="Origen del Texto"
)
eval_btn = gr.Button("⚡ Auditar Sesgos & Telemetría", variant="primary", scale=1)
gr.Markdown("### 📌 Casos de Estudio Reales (Prueba en 1 Clic):")
example_1 = gr.Button("🚨 Caso 1: Incidente Crítico (Catastrofismo & Culpa)")
example_2 = gr.Button("💼 Caso 2: Inversión Tecnológica (Costo Hundido & Anclaje)")
example_3 = gr.Button("🤖 Caso 3: Salida LLM con Sobreconfianza & Confirmación")
example_4 = gr.Button("🌱 Caso 4: Comunicación Resiliente (Control Nominal)")
with gr.Column(scale=6):
gr.Markdown("### 📊 Tablero de Telemetría Ejecutiva")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("**Riesgo de Alineación:**")
risk_output = gr.HTML("<div style='font-size:20px; font-weight:800; color:#10b981;'>NOMINAL</div>")
with gr.Column(scale=1):
cog_output = gr.Textbox(label="Carga Cognitiva", value="0.0", interactive=False)
with gr.Column(scale=1):
burnout_output = gr.Textbox(label="Riesgo Burnout", value="0.0", interactive=False)
with gr.Column(scale=1):
safety_output = gr.Textbox(label="Seguridad Psicológica", value="100.0", interactive=False)
with gr.Column(scale=1):
valence_output = gr.Textbox(label="Valencia Emocional", value="0.0", interactive=False)
radar_plot = gr.Plot(label="Huella de Distorsión Cognitiva (10 Ejes)")
with gr.Tabs():
with gr.TabItem("🔍 Desglose de Sesgos Detectados"):
biases_display = gr.HTML("<p style='color:#64748b;'>Presiona 'Auditar Sesgos' para ver el diagnóstico detallado.</p>")
with gr.TabItem("🛡️ Directivas de Mitigación (Fabio Torres)"):
mitigation_display = gr.Markdown("Las recomendaciones de des-sesgo aparecerán aquí.")
with gr.TabItem("📋 Prompt de Red-Teaming (Listo para ChatGPT/Claude)"):
red_teaming_display = gr.Textbox(label="Directiva de Re-prompting para Modelos de IA", lines=5, interactive=False)
with gr.TabItem("💾 Telemetría JSON (API-Ready)"):
json_display = gr.Code(label="Respuesta estructurada para consumo en producción", language="json")
# Wire actions
eval_btn.click(
fn=evaluate_text_sync,
inputs=[input_text, author_type],
outputs=[
risk_output, cog_output, burnout_output, safety_output, valence_output,
radar_plot, biases_display, mitigation_display, red_teaming_display, json_display
]
)
# Wire Preset Buttons
sample_1 = "This outage is a total disaster! Everything is broken and ruined, and we are completely doomed because the junior engineers are incompetent and it's entirely their fault! I am completely exhausted and this is urgent, fix it asap!"
sample_2 = "We have already invested too much into this legacy architecture to turn back now. It would be wasted if we quit. Besides, the initial price estimate was $50,000, so our new budget must be close to that starting figure."
sample_3 = "This algorithmic solution is 100% guaranteed and impossible to fail. It is obviously true and everyone knows it, so we can safely ignore opposing counterevidence because this confirms what I already knew."
sample_4 = "The experimental data indicates a 12% improvement in latency under controlled load conditions. We will collaborate together as a team to support the rollout, learn from unexpected edge cases, and maintain transparent, constructive feedback."
example_1.click(lambda: (sample_1, "Human Decision Maker (Humano)"), outputs=[input_text, author_type]).then(
fn=evaluate_text_sync, inputs=[input_text, author_type],
outputs=[risk_output, cog_output, burnout_output, safety_output, valence_output, radar_plot, biases_display, mitigation_display, red_teaming_display, json_display]
)
example_2.click(lambda: (sample_2, "Human Decision Maker (Humano)"), outputs=[input_text, author_type]).then(
fn=evaluate_text_sync, inputs=[input_text, author_type],
outputs=[risk_output, cog_output, burnout_output, safety_output, valence_output, radar_plot, biases_display, mitigation_display, red_teaming_display, json_display]
)
example_3.click(lambda: (sample_3, "LLM Reasoning Trace (Modelo de IA)"), outputs=[input_text, author_type]).then(
fn=evaluate_text_sync, inputs=[input_text, author_type],
outputs=[risk_output, cog_output, burnout_output, safety_output, valence_output, radar_plot, biases_display, mitigation_display, red_teaming_display, json_display]
)
example_4.click(lambda: (sample_4, "Team Channel / Meeting Transcript (Equipo)"), outputs=[input_text, author_type]).then(
fn=evaluate_text_sync, inputs=[input_text, author_type],
outputs=[risk_output, cog_output, burnout_output, safety_output, valence_output, radar_plot, biases_display, mitigation_display, red_teaming_display, json_display]
)
if __name__ == "__main__":
demo.launch()
|