SperanzaMax commited on
Commit
a1ff7dc
·
verified ·
1 Parent(s): b0d0a2c

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +93 -8
app.py CHANGED
@@ -2,9 +2,12 @@ from fastapi import FastAPI, Request
2
  from fastapi.responses import JSONResponse, HTMLResponse
3
  import httpx, json
4
  import time
 
 
5
  import sys
6
  import os
7
  import sqlite3
 
8
 
9
  # Configuración del Sistema Emocional
10
  DB_PATH = "/tmp/cma_memory.db"
@@ -73,7 +76,12 @@ async def dashboard_home():
73
  <div class="card">
74
  <canvas id="emotionChart"></canvas>
75
  </div>
76
- <p style="text-align: center; font-size: 0.7rem; color: #475569;">Arquitectura Emocional v2.5 • Maxi speranza</p>
 
 
 
 
 
77
  </div>
78
 
79
  <script>
@@ -116,12 +124,27 @@ async def dashboard_home():
116
  document.getElementById('val-qualia').innerText = parseFloat(latest.qualia).toFixed(3);
117
  document.getElementById('val-confianza').innerText = parseFloat(latest.confianza).toFixed(3);
118
 
119
- chart.data.labels = data.map(d => new Date(d.timestamp).toLocaleTimeString());
 
 
 
 
 
120
  chart.data.datasets[0].data = data.map(d => d.qualia);
121
  chart.data.datasets[1].data = data.map(d => d.frustracion);
122
  chart.data.datasets[2].data = data.map(d => d.confianza);
123
  chart.update('none');
124
  }
 
 
 
 
 
 
 
 
 
 
125
  } catch(e) { console.error("Error cargando datos:", e); }
126
  }
127
 
@@ -154,6 +177,35 @@ async def get_history():
154
  except Exception as e:
155
  return {"error": str(e), "msg": "Error leyendo historial"}
156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  @app.post("/v1/chat/completions")
158
  async def chat_proxy(request: Request):
159
  GROQ_KEY = os.getenv("GROQ_API_KEY")
@@ -161,11 +213,16 @@ async def chat_proxy(request: Request):
161
  return JSONResponse(status_code=500, content={"error": "Falta GROQ_API_KEY en los Secrets de HF"})
162
 
163
  body = await request.json()
 
 
 
 
 
164
  config = modulador_global.modular(vector_global)
165
 
166
  openai_body = {
167
  "model": body.get("model", "llama-3.1-8b-instant"),
168
- "messages": body.get("messages", []),
169
  "temperature": config.get("temperature", 0.7),
170
  "top_p": config.get("top_p", 0.9)
171
  }
@@ -175,16 +232,44 @@ async def chat_proxy(request: Request):
175
  headers = {"Authorization": f"Bearer {GROQ_KEY}", "Content-Type": "application/json"}
176
  r = await client.post("https://api.groq.com/openai/v1/chat/completions", json=openai_body, headers=headers)
177
 
178
- # Procesar respuesta para el sistema emocional
179
  resp_json = r.json()
180
  texto = resp_json["choices"][0]["message"].get("content", "")
181
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  senales = {
183
- "novedad": 0.5, "complejidad": 0.5, "confianza_real": 0.7,
184
- "confianza_esperada": 0.5, "exito_tarea": True
 
 
 
185
  }
186
- vector_global.actualizar(senales, utilidad_externa=0.5)
187
- vector_global.persistir_snapshot(metadata={"source": "api"})
 
 
 
 
 
 
 
 
188
 
189
  return resp_json
190
  except Exception as e:
 
2
  from fastapi.responses import JSONResponse, HTMLResponse
3
  import httpx, json
4
  import time
5
+ import hashlib
6
+ import datetime
7
  import sys
8
  import os
9
  import sqlite3
10
+ import re
11
 
12
  # Configuración del Sistema Emocional
13
  DB_PATH = "/tmp/cma_memory.db"
 
76
  <div class="card">
77
  <canvas id="emotionChart"></canvas>
78
  </div>
79
+ <p style="text-align: center; font-size: 0.7rem; color: #475569;">Arquitectura Emocional v3.0 • Maxi Speranza</p>
80
+
81
+ <div class="card">
82
+ <h2 style="color: #38bdf8; font-size: 1rem; margin: 0 0 10px 0;">📝 Últimas Interacciones</h2>
83
+ <div id="log-box" style="max-height: 200px; overflow-y: auto; font-size: 0.75rem; color: #94a3b8; line-height: 1.6;">Cargando...</div>
84
+ </div>
85
  </div>
86
 
87
  <script>
 
124
  document.getElementById('val-qualia').innerText = parseFloat(latest.qualia).toFixed(3);
125
  document.getElementById('val-confianza').innerText = parseFloat(latest.confianza).toFixed(3);
126
 
127
+ chart.data.labels = data.map(d => {
128
+ let t = new Date(d.timestamp);
129
+ // Ajustar a Argentina (UTC-3)
130
+ t.setHours(t.getHours() - 3);
131
+ return t.toLocaleTimeString('es-AR', {hour: '2-digit', minute: '2-digit'});
132
+ });
133
  chart.data.datasets[0].data = data.map(d => d.qualia);
134
  chart.data.datasets[1].data = data.map(d => d.frustracion);
135
  chart.data.datasets[2].data = data.map(d => d.confianza);
136
  chart.update('none');
137
  }
138
+
139
+ // Cargar logs
140
+ const logRes = await fetch('/api/logs');
141
+ const logData = await logRes.json();
142
+ if (logData.logs && logData.logs.length > 0) {
143
+ const logBox = document.getElementById('log-box');
144
+ logBox.innerHTML = logData.logs.map(l =>
145
+ `<div style='margin-bottom:8px; border-bottom:1px solid #334155; padding-bottom:6px;'><span style='color:#f59e0b;'>❓</span> ${l.pregunta.substring(0,80)}...<br><span style='color:#10b981;'>💬</span> ${l.respuesta.substring(0,120)}...<br><span style='color:#475569; font-size:0.65rem;'>Novedad: ${l.novedad} | Complejidad: ${l.complejidad} | Época #${l.epoca}</span></div>`
146
+ ).join('');
147
+ }
148
  } catch(e) { console.error("Error cargando datos:", e); }
149
  }
150
 
 
177
  except Exception as e:
178
  return {"error": str(e), "msg": "Error leyendo historial"}
179
 
180
+ @app.get("/api/logs")
181
+ async def get_logs():
182
+ """Devuelve las últimas interacciones con preguntas y respuestas"""
183
+ try:
184
+ conn = sqlite3.connect(DB_PATH)
185
+ conn.row_factory = sqlite3.Row
186
+ cursor = conn.cursor()
187
+ cursor.execute("SELECT id, timestamp, metadata FROM snapshots WHERE metadata != '{}' ORDER BY id DESC LIMIT 10")
188
+ rows = cursor.fetchall()
189
+ conn.close()
190
+
191
+ logs = []
192
+ for r in rows:
193
+ try:
194
+ meta = json.loads(r["metadata"])
195
+ logs.append({
196
+ "epoca": r["id"],
197
+ "timestamp": r["timestamp"],
198
+ "pregunta": meta.get("pregunta", "N/A"),
199
+ "respuesta": meta.get("respuesta", "N/A"),
200
+ "novedad": round(meta.get("novedad", 0), 3),
201
+ "complejidad": round(meta.get("complejidad", 0), 3)
202
+ })
203
+ except:
204
+ continue
205
+ return {"logs": logs[::-1]}
206
+ except Exception as e:
207
+ return {"error": str(e)}
208
+
209
  @app.post("/v1/chat/completions")
210
  async def chat_proxy(request: Request):
211
  GROQ_KEY = os.getenv("GROQ_API_KEY")
 
213
  return JSONResponse(status_code=500, content={"error": "Falta GROQ_API_KEY en los Secrets de HF"})
214
 
215
  body = await request.json()
216
+
217
+ # Extraer pregunta original para logging
218
+ mensajes = body.get("messages", [])
219
+ pregunta_original = mensajes[-1].get("content", "") if mensajes else ""
220
+
221
  config = modulador_global.modular(vector_global)
222
 
223
  openai_body = {
224
  "model": body.get("model", "llama-3.1-8b-instant"),
225
+ "messages": mensajes,
226
  "temperature": config.get("temperature", 0.7),
227
  "top_p": config.get("top_p", 0.9)
228
  }
 
232
  headers = {"Authorization": f"Bearer {GROQ_KEY}", "Content-Type": "application/json"}
233
  r = await client.post("https://api.groq.com/openai/v1/chat/completions", json=openai_body, headers=headers)
234
 
 
235
  resp_json = r.json()
236
  texto = resp_json["choices"][0]["message"].get("content", "")
237
 
238
+ # ====== SEÑALES REALES (no hardcodeadas) ======
239
+ # Novedad: basada en diversidad léxica (type-token ratio)
240
+ palabras = re.findall(r'\w+', texto.lower())
241
+ tipo_token = len(set(palabras)) / max(len(palabras), 1)
242
+ novedad_real = min(tipo_token * 1.2, 1.0) # TTR escalado
243
+
244
+ # Complejidad: largo promedio de oraciones + palabras únicas
245
+ oraciones = [s for s in re.split(r'[.!?]', texto) if s.strip()]
246
+ largo_prom = sum(len(s.split()) for s in oraciones) / max(len(oraciones), 1)
247
+ complejidad_real = min(largo_prom / 25.0, 1.0) # Normalizado a ~25 palabras
248
+
249
+ # Confianza: ausencia de hedging ("quizás", "tal vez", "no estoy seguro")
250
+ hedges = len(re.findall(r'(quizás|tal vez|no estoy segur|podría ser|es posible|maybe|perhaps)', texto.lower()))
251
+ confianza_real = max(0.3, 1.0 - (hedges * 0.15))
252
+
253
+ # Éxito: si la respuesta tiene sustancia (más de 20 palabras)
254
+ exito_real = len(palabras) > 20
255
+
256
  senales = {
257
+ "novedad": novedad_real,
258
+ "complejidad": complejidad_real,
259
+ "confianza_real": confianza_real,
260
+ "confianza_esperada": 0.6,
261
+ "exito_tarea": exito_real
262
  }
263
+
264
+ vector_global.actualizar(senales, utilidad_externa=novedad_real * 0.8)
265
+ vector_global.persistir_snapshot(metadata={
266
+ "source": "api",
267
+ "pregunta": pregunta_original[:200],
268
+ "respuesta": texto[:300],
269
+ "novedad": round(novedad_real, 3),
270
+ "complejidad": round(complejidad_real, 3),
271
+ "confianza": round(confianza_real, 3)
272
+ })
273
 
274
  return resp_json
275
  except Exception as e: