He construido desde cero la LLM Wiki de Karpathy sobre mis artículos

Durante un año he escrito en AiTalk acumulando, artículo tras artículo, una especie de diario personal sobre la inteligencia artificial. En un momento dado me encontré con 164 archivos en una carpeta, cada uno lleno de conceptos, nombres, empresas, modelos, todos citados y nunca realmente conectados entre sí. Sabía que había escrito algo sobre un tema determinado, no recordaba dónde, y recuperarlo significaba abrir archivos uno por uno, confiando en la memoria o en un afortunado "buscar en el texto". Un archivo, en definitiva, no un conocimiento.
El problema me recordó a ciertas escenas de Memento, la película de Christopher Nolan en la que el protagonista se tatuaba en la piel los hechos que ya no podía retener: cada prueba existía, aislada, pero sin un hilo que la uniera al resto. Yo tenía el mismo problema a menor escala, un archivo de texto en lugar de tatuajes, con una sensación de todos modos similar: información presente, conexión ausente.
La solución a la que me acerqué no nació de una intuición mía, sino de un patrón muy conocido que circula en la comunidad de desarrolladores bajo el nombre que le dio su creador, Andrej Karpathy: la LLM Wiki. La idea, en resumen, es que en lugar de hacer que un modelo busque en vuestros documentos cada vez que hacéis una pregunta, le hacéis leer los documentos una vez, dejáis que construya páginas estructuradas y conectadas entre sí, y luego le hacéis consultar ese conocimiento ya compilado cuando le hacéis preguntas. Ya había hablado de ello en un artículo anterior; aquí quería contar lo que ocurre cuando dejáis de hablar de ello y probáis a construirla de verdad, con vuestros 164 archivos, vuestros errores y vuestras dudas.
No partía como experto en este tipo de sistemas, partía como un curioso con un problema concreto que resolver. Lo que sigue es el relato honesto del camino, incluidas las opciones que descarté y aquellas de las que, aún hoy, no estoy del todo seguro.
El método que no buscaba
La primera tentación, cuando tenéis un problema de este tipo, es confiar en un script. Pensé en una extracción de conceptos con librerías como spaCy o NLTK, un trabajo rápido de análisis de texto. Lo descarté casi de inmediato, porque ese tipo de herramientas reconoce entidades y palabras clave, no el significado de un razonamiento a lo largo de todo un artículo, y yo necesitaba exactamente eso.
También pensé en Obsidian, tal vez con algún plugin de la comunidad pensado para construir grafos de conocimiento. Ya lo había probado en el pasado para otros proyectos, y la sensación era siempre la misma: una capa de configuración entre el resultado y yo que restaba más control del que aportaba.
Quedaba el camino más transitado, un sistema RAG clásico con una base de datos vectorial como Chroma o Weaviate. Funciona, está contrastado, pero resuelve un problema diferente al mío: recupera fragmentos de texto pertinentes para cada pregunta, sin acumular nunca una comprensión que crezca con el tiempo. Cada consulta parte de cero, un poco como el pececito Dory de Buscando a Nemo, que vuelve a empezar el descubrimiento del mundo cada pocos segundos. Simpático como personaje, menos práctico como arquitectura de conocimiento.
También analicé soluciones más elaboradas. Graphify, sobre el que había escrito en el pasado, construye grafos de conocimiento a partir del parsing sintáctico del código, pensado para agentes como Claude Code o Cursor en codebase reales: una herramienta potente, pero orientada a un caso de uso diferente de mi flujo de markdown puro. Microsoft GraphRAG me pareció excesivo para un proyecto personal, con una infraestructura que tendría que mantener durante años solo para consultar mis propios artículos. MeMex-Zero-RAG está listo para producción, pero pensado para agentes conectados mediante MCP, no para un uso autónomo como el mío. El proyecto de la comunidad obsidian-llm-wiki se acercaba más a lo que buscaba, pero seguía ligado a Obsidian, y yo quería algo aún más minimalista.
Al final descarté todas las soluciones ya preparadas, incluidas las más cercanas a mi caso de uso, y decidí construir el patrón desde cero. No por esnobismo hacia las herramientas existentes, sino simplemente porque la idea de intentarlo con mis propias manos, más por juego que por necesidad, me parecía la mejor manera de entender de verdad cómo funciona el mecanismo bajo la superficie, con la posibilidad de aprender algo por el camino aunque el resultado final fuera imperfecto.
Como agente elegí OpenCode, de código abierto (open source) y agnóstico respecto al modelo, capaz de trabajar tanto con proveedores en la nube como con modelos locales: no una solución prefabricada para construir wikis, solo un buen ejecutor al que confiar las reglas. Le pasé el patrón Karpathy en su forma más sencilla, una carpeta raw/ con las fuentes inmutables, una carpeta wiki/ con el conocimiento compilado, y empecé a construir todo lo demás desde ahí, un archivo de reglas a la vez, sin bases de datos, sin sistemas de embedding que gestionar, sin más infraestructura que el sistema de archivos (filesystem).
Cómo funciona, en la práctica
El proyecto vive en una estructura sencilla: dentro de raw/articoli/ están los 164 archivos markdown originales; dentro de wiki/ se han formado con el tiempo tres subcarpetas: concepts/ para las ideas y temas recurrentes, entities/ para personas, empresas y herramientas, y synthesis/ para las páginas de comparación y análisis transversal, además de un index.md que actúa como mapa general y un log.md que registra cada operación.
El núcleo del sistema es un archivo que llamé AGENTS.md, la brújula que OpenCode consulta antes de cualquier intervención. Allí escribí las reglas básicas: los archivos en raw/ permanecen inmutables; cada página de la wiki debe tener una fuente citada en el formato [Fuente: raw/nombre-archivo.md]; los enlaces entre páginas siguen la sintaxis de los wikilinks [[Nombre de la Página]]; y cada página lleva un frontmatter YAML con título, fechas de creación y actualización, categoría, tags y fuentes. Añadí también un estándar de calidad mínimo: cada página debe enlazarse al menos con otras dos páginas existentes, de lo contrario queda huérfana, aislada del resto de la red.
Escribir ese archivo me recordó al trabajo de world-building que se realiza en ciertos juegos de rol de mesa, donde antes de jugar debéis establecer las reglas del mundo para que todo lo que ocurra después tenga una coherencia interna. AGENTS.md es exactamente eso: no contenido, sino reglas para generar contenido de forma coherente.

Diez lotes, muchas sorpresas
Para el trabajo de ingest elegí DeepSeek V4 Flash, gratuito a través de OpenCode Zen, una elección pragmática más que ideológica: los contenidos ya eran públicos, por lo que no había problemas de privacidad al pasarlos por un servicio en la nube, y la velocidad del modelo se adaptaba bien a un proyecto de esta escala.
Procedí por lotes, numerando los archivos progresivamente y lanzando cada vez el mismo comando: "procesa el siguiente lote de archivos aún no procesados siguiendo AGENTS.md", seguido de un control de linter (lint) para verificar enlaces rotos, citas que faltaran o páginas huérfanas. Diez lotes en total, desde los primeros quince archivos hasta los últimos veinticuatro, con un rendimiento de páginas creadas decreciente lote tras lote: muchas páginas nuevas al principio, cuando los conceptos fundamentales aún debían tomar forma, cada vez menos con el paso del tiempo, porque gran parte de la nueva información terminaba enriqueciendo páginas ya existentes en lugar de generar nuevas. Señal, creo, de que la red de conocimiento estaba convergiendo de manera efectiva hacia una estructura estable.
El resultado final, al término de los diez lotes más una recuperación dirigida de archivos rezagados, fue de 154 páginas de contenido a partir de 164 artículos fuente: 68 páginas de conceptos, 80 de entidades, 5 de síntesis, cero enlaces rotos, cero páginas huérfanas, frontmatter válido en las 156 páginas totales (contando índice y log), y una media de casi ocho enlaces por página. Los principales centros (hubs) de la red, aquellos con más enlaces entrantes, resultaron ser seguridad-ai, large-language-models, regulación de la IA y ética de la IA: no es una sorpresa, dado lo mucho que esos temas se repiten transversalmente en gran parte de lo que escribo, pero verlo verificado por la propia estructura de la wiki fue agradable, casi una contraprueba de coherencia de mi propio trabajo.
La mayor sorpresa, sin embargo, llegó al observar el espacio ocupado en disco: todo el proyecto, las 154 páginas más el índice y el log, pesa 4,4 megabytes. Un sistema RAG con embeddings vectoriales, para el mismo volumen de artículos, habría ocupado probablemente entre 50 und 200 megabytes, considerando los índices y vectores necesarios para la búsqueda semántica. Aquí, en cambio, solo hay texto estructurado, sin chunks, sin embeddings que guardar: el conocimiento compilado pesa incluso menos que los artículos fuente que lo generaron. Una wiki que cabe cómodamente en una memoria USB, que se sincroniza mediante git en pocos segundos, que se traslada a otro ordenador con un simple copiar y pegar. Es difícil no pensar en esto en relación con lo mucho que, por lo general, la infraestructura en torno a la inteligencia artificial tiene la tendencia opuesta: crecer constantemente en tamaño y complejidad.

Donde el ser humano sigue siendo necesario
Sería cómodo presentar el proyecto como un proceso automático, iniciado y dejado correr hasta el resultado final. No fue así, y precisamente este punto me parece el más interesante de compartir.
Durante los diez lotes tuve que intervenir en varias ocasiones. Tres archivos se habían quedado atrás, presentes solo en el índice y no procesados aún, y tuve que lanzar un ingest dirigido para recuperarlos. Algunas entidades importantes, como Dario Amodei, Elon Musk, Sam Altman, Jensen Huang, Hugging Face, Tesla y Waymo, no tenían página propia a pesar de estar citadas en múltiples artículos—quince páginas que añadí más tarde al percatarme de la laguna solo al consultar la wiki. Corregí un problema de codificación (encoding) en el nombre de un archivo, arreglé diecinueve páginas con la fecha de actualización incorrecta, añadí una segunda fuente a treinta y un conceptos que solo tenían una, e integré una sección de conclusiones en cuatro páginas de síntesis que carecían de ellas.
Ninguna de estas intervenciones fue dramática, pero todas me enseñaron algo sobre el límite real del sistema: cuando los lotes son voluminosos, con muchos archivos procesados en una sola sesión, el modelo tiende a perder de vista detalles menores, un poco como cuando leéis demasiados capítulos de una novela coral en una sola sesión y al final confundís a algunos personajes secundarios. Me recordó a ciertos manga con decenas de personajes introducidos en el mismo arco argumental, donde incluso el lector más atento acaba perdiendo algunos hilos secundarios, para luego encontrarlos algunos tomos más adelante.
No obstante, ahora que he alineado el archivo en la Wiki, de aquí en adelante, procederé con ingests de un artículo a la vez en lugar de lotes amplios. Es una hipótesis que aún debo verificar sobre el terreno; mi intuición es que la precisión mejorará al gestionar menos información por ingest, pero aún no dispongo de datos suficientes para afirmarlo con certeza. Queda, de todos modos, la lección más importante de todo el camino: el patrón de Karpathy no es automatización total, es colaboración entre el ser humano y el modelo, donde el primero supervisa, corrige y enriquece lo que el segundo genera.
La misma wiki, sin la nube
Una vez completada la wiki con el modelo en la nube, me pregunté si todo el sistema podría funcionar también offline, con un modelo privado cargado en mi ordenador. Las razones eran diversas: la privacidad, ya que en ese caso los datos nunca saldrían de la máquina; el control, porque podría elegir cualquier modelo sin depender de un proveedor externo; y los costes, reducidos a cero una vez cargado el modelo.
Utilicé LM Studio como motor local, con el servidor activo en el puerto 8001, y como modelo elegí Ornith 1.0 de 35 mil millones de parámetros, sobre el que había escrito en un artículo dedicado: en mis pruebas, tanto en los test como en el uso diario, demostró ser el más preciso de los probados, aunque sigue siendo posible seleccionar cualquier otro modelo cargado en LM Studio.
Para conectar OpenCode al servidor local elegí la vía manual, modificando directamente el archivo de configuración con un nuevo proveedor que apunta al endpoint local, en lugar de confiar en el plugin opencode-lmstudio, que también habría ofrecido ventajas concretas como la detección automática de los modelos cargados y la gestión dinámica de puertos y endpoints. Elegí la configuración manual por un motivo práctico—mi caso de uso prevé consultas ocasionales en una wiki ya completa, no un cambio frecuente de modelo—y por un motivo más personal: quería entender a fondo qué había escrito en ese archivo de configuración, sin intermediarios. Reconozco que para un uso más dinámico, con cambios frecuentes de arquitectura, el plugin seguiría siendo la opción más cómoda.
Las pruebas me sorprendieron en sentido positivo. Una pregunta sencilla sobre un concepto ya tratado, como MTV, encontró correctamente referencia en la página dedicada a la música y la inteligencia artificial. Una pregunta más compleja, que pedía enumerar las principales empresas del sector y sus respectivos directores ejecutivos citando las fuentes, produjo una respuesta precisa sobre ocho empresas, con citas que apuntaban correctamente a las páginas de la wiki compilada y no a los archivos originales raw—una señal de que el modelo estaba utilizando efectivamente la estructura que yo había construido. Incluso detectó por sí mismo dos lagunas—Mark Zuckerberg citado solo marginalmente y Sundar Pichai ausente por completo—un detalle importante a destacar, porque el modelo de hecho detectó lagunas durante una búsqueda y me permitió colmarlas con una sencilla solicitud.
La primera respuesta llegó con lentitud—el tiempo necesario para cargar todo el contexto de la wiki—, las siguientes fueron mucho más rápidas gracias a la caché. Tuve que elevar el límite de contexto de 25.000 a 160.000 tokens para permitir que el modelo leyera toda la estructura sin recortes, y descubrí que, a diferencia del modelo en la nube utilizado para el ingest, el local no sigue automáticamente el patrón si no le indicáis explícitamente que lea AGENTS.md y que recurra únicamente a la carpeta wiki/. Un detalle que parece pequeño, pero que en realidad define la diferencia entre una respuesta pertinente y una genérica.

Qué falta aún
Al final del camino me llevo a casa más preguntas abiertas que certezas definitivas, y creo que es justo así. He aprendido que el patrón de Karpathy funciona en la práctica, con herramientas totalmente de código abierto (open source) y sin infraestructuras complejas; he aprendido que la supervisión humana sigue siendo indispensable, no un recurso temporal a la espera de modelos mejores; y he aprendido que la compacidad de este enfoque, esos 4,4 megabytes totales, no es un detalle técnico marginal, sino una cualidad que hace que el proyecto sea realmente portátil y fácil de compartir.
Siguen abiertas cuestiones sobre las que aún no tengo respuesta. ¿El ingest archivo por archivo, que acabo de empezar a adoptar en lugar de los lotes amplios, mejorará realmente la precisión como creo, o solo introducirá más lentitud sin beneficios proporcionales? Desearía automatizar la adición a la wiki en el mismo momento en que publico un nuevo artículo, en lugar de acordarme semanas después. También me gustaría añadir una sección dedicada a los modelos lingüísticos como entidades en sí mismas, con ChatGPT y Claude a la cabeza, hoy solo mencionados de pasada dentro de otras páginas.
Hay, por último, una pregunta más de fondo, la que me ha acompañado durante todo el camino: cuánto de este conocimiento compilado refleja realmente lo que pienso y cuánto es ya una síntesis del modelo que se ha colado entre mis propios artículos y yo. No tengo una respuesta definitiva; por ahora me limito a comprobar, corregir y enriquecer, consciente de que el propio proyecto está diseñado para mejorar aprendiendo cosas nuevas por el camino, tal como estoy intentando hacer yo.