diff --git a/INFO/DOCS/capturas/coconews.png b/INFO/DOCS/capturas/coconews.png deleted file mode 100644 index 36fa2181..00000000 Binary files a/INFO/DOCS/capturas/coconews.png and /dev/null differ diff --git a/INFO/DOCS/capturas/grafo-eco-corp-disperso.png b/INFO/DOCS/capturas/grafo-eco-corp-disperso.png deleted file mode 100644 index ab0fa18a..00000000 Binary files a/INFO/DOCS/capturas/grafo-eco-corp-disperso.png and /dev/null differ diff --git a/INFO/DOCS/capturas/grafo-eco-corp.png b/INFO/DOCS/capturas/grafo-eco-corp.png deleted file mode 100644 index c6a354c4..00000000 Binary files a/INFO/DOCS/capturas/grafo-eco-corp.png and /dev/null differ diff --git a/INFO/DOCS/capturas/grafo-glob-war.png b/INFO/DOCS/capturas/grafo-glob-war.png deleted file mode 100644 index aa803a04..00000000 Binary files a/INFO/DOCS/capturas/grafo-glob-war.png and /dev/null differ diff --git a/INFO/DOCS/capturas/grafo-popl-up.png b/INFO/DOCS/capturas/grafo-popl-up.png deleted file mode 100644 index 963f3edd..00000000 Binary files a/INFO/DOCS/capturas/grafo-popl-up.png and /dev/null differ diff --git a/INFO/DOCS/capturas/home.png b/INFO/DOCS/capturas/home.png deleted file mode 100644 index f5c6ac7f..00000000 Binary files a/INFO/DOCS/capturas/home.png and /dev/null differ diff --git a/INFO/DOCS/capturas/stats.png b/INFO/DOCS/capturas/stats.png deleted file mode 100644 index 9dbf2f7c..00000000 Binary files a/INFO/DOCS/capturas/stats.png and /dev/null differ diff --git a/INFO/DOCS/diagramas/fuentes-y-clasificacion.svg b/INFO/DOCS/diagramas/fuentes-y-clasificacion.svg deleted file mode 100644 index 9ab32c6e..00000000 --- a/INFO/DOCS/diagramas/fuentes-y-clasificacion.svg +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - -DE DÓNDE SALEN LOS DATOS -Cuatro fuentes, una etiqueta que viaja con cada documento, y los filtros que salen de ahí. - -1 · LO QUE ENTRA - -236 feeds RSS -› prensa de 5 idiomas -› agencias y cabeceras -› medios locales y de exilio - -API de Wikipedia -› 28.266 artículos -› por tema y palabra clave -› el contexto histórico - -WikiLeaks -› 36.182 documentos -› archivo completo por torrent -› cables, correos, informes - -Imágenes -› og:image de cada artículo -› fotos de Wikipedia -› descritas con Qwen3-VL - - - - - -2 · LA ETIQUETA NO SE CALCULA: VIAJA CON LA FUENTE -Cada feed del catálogo lleva escrito su tema y su subtema. Al ingerir un artículo, el artículo los hereda. -No hay clasificador automático: la decisión es editorial y está en el catálogo, no en el texto. -Es simple y es auditable — se ve de un vistazo por qué un artículo está donde está — pero tiene un coste: si un -medio de clima publica sobre geopolítica, ese artículo entra igualmente como clima. - -coconews_feeds -nombre -"Ariana News – Dari" -tema -"guerra global" -subtema -"Afganistán" - - -GLOB-WAR -49 feeds -guerra global -· Internacional -· Asia -· Oriente Medio -· Defensa -· Geopolítica -· Afganistán -· Europa -· Conflictos -· Rusia -· Humanitario - - - -INT-SEC -19 feeds -inteligencia y seguridad -· Ciberseguridad -· Análisis -· Defensa -· Inteligencia -· Internacional -· Europa -· España -· EEUU - - - -CLIMATE -120 feeds -cambio climático -· Internacional -· EEUU -· Ciencia -· Biodiversidad -· Energía -· Asia -· Tecnología -· ONG -· Salud -· España - - - -ECO-CORP -24 feeds -economía y corporaciones -· Internacional -· Tecnología -· EEUU -· España -· Gestión -· Corporaciones -· Comercio - - - -POPL-UP -24 feeds -demografía y sociedad -· España -· Internacional -· EEUU -· Salud -· Derechos Humanos -· Política -· Migración -· Europa -· Reino Unido - - -3 · CINCO TEMAS, Y LOS SUBTEMAS QUE EXISTEN DE VERDAD -Los subtemas son geográficos y de sección, no conceptuales. No hay un subtema "energía renovable": hay "Energía", que es lo que -trae el catálogo. El menú de la web todavía ofrece algunos que no existen en la base y por eso filtran a cero. - - -4 · LO QUE PUEDES FILTRAR -tema -la vista que eliges: GLOB-WAR, INT-SEC… -subtema -desplegable, hereda del feed -fecha -Semanal (7 días) o Todas -palabra clave -busca dentro del texto -nodos -cuántos traer, hasta 500 -% similitud -umbral mínimo para dibujar una arista -país / región -solo en coconews -entidad -persona u organización, vía NER - -upleaks.org — software libre — gitea.laenre.net/hacklab/FLUJOS - \ No newline at end of file diff --git a/INFO/DOCS/diagramas/gen_fuentes_svg.py b/INFO/DOCS/diagramas/gen_fuentes_svg.py deleted file mode 100644 index 16286272..00000000 --- a/INFO/DOCS/diagramas/gen_fuentes_svg.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env python3 -# Genera el diagrama de fuentes y clasificacion de UP-LEAKS. -import io, sys - -W = 1500 -NEON, NEON2 = "#39ff14", "#7cff5a" -BG, PANEL = "#050505", "#0d0f0d" -GRIS, GRIS2 = "#8a938a", "#5a625a" -CIAN, AMBAR, MAGENTA, ROJO = "#3ad6ff", "#ffb020", "#ff5ea8", "#ff4d4d" - -# color por tema, el mismo de la web -TEMAS = [ - ("GLOB-WAR", "guerra global", "#ff3b3b", 49, - ["Internacional", "Asia", "Oriente Medio", "Defensa", "Geopolítica", - "Afganistán", "Europa", "Conflictos", "Rusia", "Humanitario"]), - ("INT-SEC", "inteligencia y seguridad", "#4a6bff", 19, - ["Ciberseguridad", "Análisis", "Defensa", "Inteligencia", - "Internacional", "Europa", "España", "EEUU"]), - ("CLIMATE", "cambio climático", "#5fe36a", 120, - ["Internacional", "EEUU", "Ciencia", "Biodiversidad", "Energía", - "Asia", "Tecnología", "ONG", "Salud", "España"]), - ("ECO-CORP", "economía y corporaciones", "#ffe600", 24, - ["Internacional", "Tecnología", "EEUU", "España", - "Gestión", "Corporaciones", "Comercio"]), - ("POPL-UP", "demografía y sociedad", "#ff9b30", 24, - ["España", "Internacional", "EEUU", "Salud", "Derechos Humanos", - "Política", "Migración", "Europa", "Reino Unido"]), -] - -FUENTES = [ - ("236 feeds RSS", CIAN, ["prensa de 5 idiomas", "agencias y cabeceras", - "medios locales y de exilio"]), - ("API de Wikipedia", CIAN, ["28.266 artículos", "por tema y palabra clave", - "el contexto histórico"]), - ("WikiLeaks", CIAN, ["36.182 documentos", "archivo completo por torrent", - "cables, correos, informes"]), - ("Imágenes", CIAN, ["og:image de cada artículo", "fotos de Wikipedia", - "descritas con Qwen3-VL"]), -] - -FILTROS = [ - ("tema", "la vista que eliges: GLOB-WAR, INT-SEC…"), - ("subtema", "desplegable, hereda del feed"), - ("fecha", "Semanal (7 días) o Todas"), - ("palabra clave","busca dentro del texto"), - ("nodos", "cuántos traer, hasta 500"), - ("% similitud", "umbral mínimo para dibujar una arista"), - ("país / región","solo en coconews"), - ("entidad", "persona u organización, vía NER"), -] - -o = [] -a = o.append - - -def caja(x, y, w, h, color, ancho=1.5, relleno=PANEL, op=1.0): - a(f'') - - -def txt(x, y, s, color=GRIS, size=12, anchor="start", peso="normal", ls=0): - a(f'{s}') - - -# ── cabecera ────────────────────────────────────────────────────────────── -cuerpo = [] -a_real = a -o_head = [] - -Y = 130 -# FUENTES -fw, fgap = 340, 26 -fx0 = (W - (4 * fw + 3 * fgap)) / 2 -fh = 118 - -# CLASIFICACION -Y2 = Y + fh + 96 -h_clas = 128 - -# TEMAS -Y3 = Y2 + h_clas + 86 -tw, tgap = 276, 20 -tx0 = (W - (5 * tw + 4 * tgap)) / 2 -th = 44 + 10 * 20 + 16 - -# FILTROS -Y4 = Y3 + th + 108 -h_filt = 44 + 4 * 30 + 16 - -H = Y4 + h_filt + 54 - -a(f'') -a('') -for nom, col in (("f1", CIAN), ("f2", NEON), ("f3", MAGENTA)): - a(f'' - f'') -a('') -a(f'') - -txt(46, 54, 'DE DÓNDE SALEN LOS DATOS', NEON, 27, peso="bold", ls=3) -txt(46, 80, 'Cuatro fuentes, una etiqueta que viaja con cada documento, y los filtros que salen de ahí.', GRIS, 14) -a(f'') - -# ── 1. FUENTES ──────────────────────────────────────────────────────────── -txt(46, Y - 12, '1 · LO QUE ENTRA', CIAN, 13, ls=2) -centros = [] -for i, (nom, col, lineas) in enumerate(FUENTES): - x = fx0 + i * (fw + fgap) - caja(x, Y, fw, fh, col, 1.5, PANEL, 0.85) - txt(x + 18, Y + 30, nom, col, 16, peso="bold") - for j, l in enumerate(lineas): - txt(x + 18, Y + 56 + j * 20, '› ' + l, GRIS, 11.5) - centros.append(x + fw / 2) - -# ── 2. LA ETIQUETA ──────────────────────────────────────────────────────── -cx = W / 2 -for c in centros: - a(f'') - -caja(46, Y2, W - 92, h_clas, NEON, 1.8) -txt(64, Y2 + 28, '2 · LA ETIQUETA NO SE CALCULA: VIAJA CON LA FUENTE', NEON, 13, ls=2) -txt(64, Y2 + 56, - 'Cada feed del catálogo lleva escrito su tema y su subtema. Al ingerir un artículo, el artículo los hereda.', GRIS, 12.5) -txt(64, Y2 + 76, - 'No hay clasificador automático: la decisión es editorial y está en el catálogo, no en el texto.', GRIS, 12.5) -txt(64, Y2 + 104, - 'Es simple y es auditable — se ve de un vistazo por qué un artículo está donde está — pero tiene un coste: si un', GRIS2, 11.5) -txt(64, Y2 + 120, - 'medio de clima publica sobre geopolítica, ese artículo entra igualmente como clima.', GRIS2, 11.5) - -# tarjeta de ejemplo, a la derecha del bloque -ex_x, ex_w = W - 500, 436 -caja(ex_x, Y2 + 16, ex_w, 96, AMBAR, 1.2, "#12100a", 0.8) -txt(ex_x + 16, Y2 + 38, 'coconews_feeds', AMBAR, 11.5, ls=1) -for j, (k, v) in enumerate([('nombre', '"Ariana News – Dari"'), - ('tema', '"guerra global"'), - ('subtema', '"Afganistán"')]): - txt(ex_x + 16, Y2 + 60 + j * 18, k, GRIS2, 11.5) - txt(ex_x + 110, Y2 + 60 + j * 18, v, NEON2 if k != 'nombre' else GRIS, 11.5) - -# ── 3. TEMAS Y SUBTEMAS ─────────────────────────────────────────────────── -_e3 = '3 · CINCO TEMAS, Y LOS SUBTEMAS QUE EXISTEN DE VERDAD' -for i, (etq, tema, col, nfeeds, subs) in enumerate(TEMAS): - x = tx0 + i * (tw + tgap) - caja(x, Y3, tw, th, col, 1.6, PANEL, 0.9) - a(f'') - txt(x + 14, Y3 + 21, etq, col, 14, peso="bold", ls=1) - txt(x + tw - 14, Y3 + 21, f'{nfeeds} feeds', GRIS2, 11, anchor="end") - txt(x + 14, Y3 + 44, tema, GRIS2, 10.5) - for j, s in enumerate(subs[:10]): - txt(x + 14, Y3 + 66 + j * 20, '· ' + s, GRIS, 11.5) - a(f'') - -a(f'') -txt(46, Y3 - 11, _e3, NEON2, 13, ls=2) - -txt(46, Y3 + th + 24, - 'Los subtemas son geográficos y de sección, no conceptuales. No hay un subtema "energía renovable": hay "Energía", que es lo que', - GRIS2, 11.5) -txt(46, Y3 + th + 40, - 'trae el catálogo. El menú de la web todavía ofrece algunos que no existen en la base y por eso filtran a cero.', - GRIS2, 11.5) - -# ── 4. FILTROS ──────────────────────────────────────────────────────────── -caja(46, Y4, W - 92, h_filt, MAGENTA, 1.5) -_e4 = '4 · LO QUE PUEDES FILTRAR' -a(f'') -txt(46, Y4 - 11, _e4, MAGENTA, 13, ls=2) -for i, (nom, desc) in enumerate(FILTROS): - col_i, fila = divmod(i, 4) - x = 70 + col_i * ((W - 140) / 2) - y = Y4 + 40 + fila * 30 - txt(x, y, nom, MAGENTA, 12.5) - txt(x + 150, y, desc, GRIS, 12) - -a(f'') - -txt(46, H - 22, 'upleaks.org — software libre — gitea.laenre.net/hacklab/FLUJOS', GRIS2, 11) -a('') - -io.open(sys.argv[1], 'w', encoding='utf-8').write('\n'.join(o)) -print("escrito", sys.argv[1], "| alto:", H) diff --git a/README.md b/README.md index 763377c2..e2e2b1f9 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,12 @@ Cruza lo que publica la prensa con lo que dicen los documentos filtrados, y lo dibuja como un grafo que se puede recorrer. -**[upleaks.org](https://upleaks.org)** · **[Wiki](https://gitea.laenre.net/hacklab/FLUJOS/wiki)** — arquitectura, fuentes, instalación y recorrido por la interfaz - ---- - -## La idea +En marcha: **[upleaks.org](https://upleaks.org)** ![Flujos de información](INFO/DOCS/diagramas/flujos-de-informacion.svg) +## La idea + Cuatro agencias —Reuters, AFP, AP, EFE— abastecen a casi toda la prensa del planeta. Abres diez periódicos distintos y lees el mismo despacho diez veces. Esa repetición parece pluralidad y no lo es. @@ -23,88 +21,16 @@ lo mismo. El resultado no es un buscador. Es un mapa donde se ve qué se cuenta, quién lo cuenta y qué había escrito sobre eso antes de que se contara. +## Qué hay dentro ahora mismo + | | | |---|---| | Noticias | 98.110 de 236 feeds en 5 idiomas | | Artículos de Wikipedia | 28.266 | | Documentos de WikiLeaks | 36.182 | | Fragmentos vectorizados | 531.306 | -| Entidades extraídas | 76.857 | | Aristas del grafo | 115.035.059 | ---- - -## Cómo se ve - -### La portada - -![Portada](INFO/DOCS/capturas/home.png) - -Cinco temáticas, cada una con su color, y ese color se mantiene después en el grafo. -Arriba: coconews, el buzón de periodistas y las estadísticas. Abajo, los cuatro canales -del proyecto, incluido el servicio Tor. - -### El grafo - -![Grafo de GLOB-WAR](INFO/DOCS/capturas/grafo-glob-war.png) - -Cada punto es un documento y cada línea dice que dos documentos hablan de lo mismo. Lo que -hay que buscar es una arista entre una noticia y un leak: algo que se publicó hoy y un -documento que ya lo decía. - -A la izquierda los parámetros —ventana de fechas, número de nodos, umbral de similitud, -palabra clave, subtemática—. Arriba a la derecha, **Semanal** (últimos 7 días, por defecto) -o **Todas** (una muestra de todo el archivo). - -![Grafo de ECO-CORP](INFO/DOCS/capturas/grafo-eco-corp.png) - -Con el umbral bajo, el grafo se llena y se ve la estructura general. Las miniaturas son -noticias con foto, servidas por un proxy interno: Three.js no puede texturizar imágenes de -otro dominio sin CORS, y casi ningún periódico las manda. - -![Grafo disperso](INFO/DOCS/capturas/grafo-eco-corp-disperso.png) - -Con el umbral alto, casi todo se desconecta y solo sobrevive un núcleo. Esta es la vista -que sirve para buscar de verdad: el grafo lleno es para hacerse una idea, el grafo pelado -es donde aparece lo que está relacionado sin lugar a dudas. - -### Coconews - -![Coconews](INFO/DOCS/capturas/coconews.png) - -Las noticias en crudo, sin grafo. Filtros por tema, país o región y entidad, y en el -lateral el reparto en vivo del corpus por temática y por idioma — la forma más rápida de -ver que no está equilibrado y en qué dirección. - -Los contadores de arriba son el termómetro de la cadena de workers: si el número de -traducidas o de procesadas por NER se descuelga del total, es que uno se ha caído. - -### Estadísticas - -![Estadísticas](INFO/DOCS/capturas/stats.png) - -El estado del corpus, recalculado cada 6 horas y servido cacheado — contar 115 millones de -aristas en cada carga de página no es razonable. - -Ese `sim. promedio ~10.6%` resume por qué hubo que rehacer el motor de correlación: son 110 -millones de pares con un parecido medio del 10%, así que casi ninguno significa nada. - -Recorrido completo, número a número, en la -[wiki](https://gitea.laenre.net/hacklab/FLUJOS/wiki/Recorrido-por-la-interfaz). - ---- - -## De dónde salen los datos - -![De dónde salen los datos](INFO/DOCS/diagramas/fuentes-y-clasificacion.svg) - -Cuatro fuentes. La etiqueta de tema y subtema no se calcula del texto: viaja escrita en el -feed y el artículo la hereda al entrar. Es una decisión editorial, no estadística — -auditable, y corregible editando una fila del catálogo. - -Más detalle en -[De dónde salen los datos](https://gitea.laenre.net/hacklab/FLUJOS/wiki/Fuentes-y-clasificacion). - ## Arquitectura ![Arquitectura](INFO/DOCS/diagramas/arquitectura.svg) @@ -120,7 +46,8 @@ estaba. El estado vive en MongoDB, no en un orquestador. - `coconews/workers/embedder.py` — vectoriza con MiniLM multilingüe (384 dimensiones) - `FLUJOS_DATOS/COMPARACIONES/motor_comparacion.py` — correlación semántica noticia↔leak ---- +La documentación técnica de cada pieza está en [`INFO/DOCS/CONTEXT/`](INFO/DOCS/CONTEXT/), +y la [wiki](https://gitea.laenre.net/hacklab/FLUJOS/wiki) cuenta el conjunto. ## Requisitos @@ -173,9 +100,6 @@ python3 FLUJOS_DATOS/COMPARACIONES/motor_comparacion.py --salida comparaciones_v El motor de correlación acepta `--dry-run` para calibrar umbrales antes de escribir nada. -Guía completa en la -[wiki](https://gitea.laenre.net/hacklab/FLUJOS/wiki/Instalacion). - ## Como servicio Las unidades de `coconews/systemd/` son plantillas. El script las rellena con tu ruta, @@ -201,7 +125,7 @@ FLUJOS/ │ ├── TORRENTS/ documentos de WikiLeaks │ ├── COMPARACIONES/ correlación semántica │ └── IMAGENES/ scraper y análisis de imágenes -└── INFO/DOCS/ documentación técnica, diagramas y capturas +└── INFO/DOCS/ documentación técnica y diagramas ``` ## Envíos @@ -209,23 +133,6 @@ FLUJOS/ Hay un buzón para periodistas y filtradores en `/journalist`. Los envíos se guardan fuera del webroot, nunca se sirven como estáticos y no se registra la IP de quien envía. -## Documentación - -| | | -|---|---| -| [De dónde salen los datos](https://gitea.laenre.net/hacklab/FLUJOS/wiki/Fuentes-y-clasificacion) | Las fuentes, cómo se clasifican y qué puedes filtrar | -| [Recorrido por la interfaz](https://gitea.laenre.net/hacklab/FLUJOS/wiki/Recorrido-por-la-interfaz) | Pantalla por pantalla, qué es cada número y cada control | -| [Arquitectura](https://gitea.laenre.net/hacklab/FLUJOS/wiki/Arquitectura) | Los cinco procesos y cómo se coordinan sin hablarse | -| [Scrapeo de noticias](https://gitea.laenre.net/hacklab/FLUJOS/wiki/Scrapeo-de-noticias) | Los 236 feeds, el ciclo de ingesta, traducción y entidades | -| [Wikipedia y leaks](https://gitea.laenre.net/hacklab/FLUJOS/wiki/Wikipedia-y-leaks) | El contexto histórico y el archivo de documentos | -| [Correlación semántica](https://gitea.laenre.net/hacklab/FLUJOS/wiki/Correlacion-semantica) | Cómo se decide que dos textos hablan de lo mismo | -| [La visualización](https://gitea.laenre.net/hacklab/FLUJOS/wiki/La-visualizacion) | El grafo 3D y cómo leerlo | -| [Instalación](https://gitea.laenre.net/hacklab/FLUJOS/wiki/Instalacion) | Levantarlo desde cero | -| [Linaje](https://gitea.laenre.net/hacklab/FLUJOS/wiki/Linaje) | Project PM, Barrett Brown, WikiLeaks | - -La documentación técnica de cada pieza está también en -[`INFO/DOCS/CONTEXT/`](INFO/DOCS/CONTEXT/). - --- > No basta con hablar de cambio.