varios cambios esteticos y optimizaciones

This commit is contained in:
jlimolina 2025-11-25 03:13:54 +01:00
parent e3a99d9604
commit 9a243db633
8 changed files with 64 additions and 105 deletions

View file

@ -34,7 +34,7 @@ EVENT_DIST_THRESHOLD = float(os.environ.get("EVENT_DIST_THRESHOLD", "0.25"))
EMB_MODEL = os.environ.get(
"EMB_MODEL",
"sentence-transformers/paraphrase-multilingual-mpnet-base-v2",
"sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
)
@ -43,12 +43,6 @@ def get_conn():
def ensure_schema(conn):
"""
Asumimos que las tablas y columnas (eventos, traducciones.evento_id,
eventos_noticias, función/trigger) ya existen por los scripts init-db.
Aquí solo nos aseguramos de que existan ciertos índices clave
(idempotente).
"""
with conn.cursor() as cur:
cur.execute(
"""
@ -66,10 +60,6 @@ def ensure_schema(conn):
def fetch_pending_traducciones(conn) -> List[int]:
"""
Traducciones con status 'done', sin evento asignado
y que ya tienen embedding en traduccion_embeddings para EMB_MODEL.
"""
with conn.cursor() as cur:
cur.execute(
"""
@ -91,10 +81,6 @@ def fetch_pending_traducciones(conn) -> List[int]:
def fetch_embeddings_for(conn, tr_ids: List[int]) -> Dict[int, np.ndarray]:
"""
Devuelve un diccionario {traduccion_id: vector_numpy}
leyendo de traduccion_embeddings.embedding para el EMB_MODEL.
"""
if not tr_ids:
return {}
@ -122,10 +108,6 @@ def fetch_embeddings_for(conn, tr_ids: List[int]) -> Dict[int, np.ndarray]:
def fetch_centroids(conn) -> List[Dict[str, Any]]:
"""
Carga todos los centroides actuales desde eventos.
Solo usamos campos de clustering: id, centroid, total_traducciones.
"""
with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur:
cur.execute(
"""
@ -142,7 +124,6 @@ def fetch_centroids(conn) -> List[Dict[str, Any]]:
raw = r["centroid"]
cnt = int(r["total_traducciones"] or 1)
if not isinstance(raw, (list, tuple)):
# centroid se almacena como JSONB array → en Python suele llegar como list
continue
arr = np.array([float(x or 0.0) for x in raw], dtype="float32")
if arr.size == 0:
@ -167,12 +148,6 @@ def cosine_distance(a: np.ndarray, b: np.ndarray) -> float:
def fetch_traduccion_info(conn, tr_id: int) -> Optional[Dict[str, Any]]:
"""
Devuelve info básica para un tr_id:
- noticia_id
- fecha de la noticia
- un título representativo para el evento (traducido u original).
"""
with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur:
cur.execute(
"""
@ -199,16 +174,13 @@ def fetch_traduccion_info(conn, tr_id: int) -> Optional[Dict[str, Any]]:
def _insert_evento_noticia(cur, evento_id: int, info: Dict[str, Any]) -> None:
"""
Inserta relación en eventos_noticias (idempotente).
"""
if not info or not info.get("noticia_id"):
return
cur.execute(
"""
INSERT INTO eventos_noticias (evento_id, noticia_id, traduccion_id)
VALUES (%s, %s, %s)
ON CONFLICT (evento_id, traduccion_id) DO NOTHING;
ON CONFLICT (evento_id, noticia_id) DO NOTHING;
""",
(evento_id, info["noticia_id"], info["traduccion_id"]),
)
@ -220,20 +192,11 @@ def assign_to_event(
vec: np.ndarray,
centroids: List[Dict[str, Any]],
) -> None:
"""
Asigna una traducción a un evento existente (si distancia <= umbral)
o crea un evento nuevo con este vector como centroide.
Además:
- Actualiza fecha_inicio, fecha_fin, n_noticias del evento.
- Rellena eventos_noticias (evento_id, noticia_id, traduccion_id).
"""
if vec is None or vec.size == 0:
return
info = fetch_traduccion_info(conn, tr_id)
# Si no hay centroides todavía → primer evento
if not centroids:
centroid_list = [float(x) for x in vec.tolist()]
with conn.cursor() as cur:
@ -255,7 +218,6 @@ def assign_to_event(
),
)
else:
# Fallback mínimo si no hay info de noticia
cur.execute(
"""
INSERT INTO eventos (centroid, total_traducciones)
@ -267,19 +229,16 @@ def assign_to_event(
new_id = cur.fetchone()[0]
# Vincular traducción al evento
cur.execute(
"UPDATE traducciones SET evento_id = %s WHERE id = %s;",
(new_id, tr_id),
)
# Rellenar tabla de relación
_insert_evento_noticia(cur, new_id, info or {})
centroids.append({"id": new_id, "vec": vec.copy(), "n": 1})
return
# Buscar el centroide más cercano
best_idx: Optional[int] = None
best_dist: float = 1.0
@ -290,7 +249,6 @@ def assign_to_event(
best_idx = i
with conn.cursor() as cur:
# Asignar a evento existente si está por debajo del umbral
if best_idx is not None and best_dist <= EVENT_DIST_THRESHOLD:
c = centroids[best_idx]
n_old = c["n"]
@ -323,7 +281,6 @@ def assign_to_event(
),
)
else:
# Sin info de fecha: solo actualizamos centroid/contador
cur.execute(
"""
UPDATE eventos
@ -334,7 +291,6 @@ def assign_to_event(
(Json(centroid_list), c["id"]),
)
# Vincular traducción y relación
cur.execute(
"UPDATE traducciones SET evento_id = %s WHERE id = %s;",
(c["id"], tr_id),
@ -343,7 +299,6 @@ def assign_to_event(
return
# Si no hay evento adecuado → crear uno nuevo
centroid_list = [float(x) for x in vec.tolist()]
if info and info.get("fecha"):