#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 01 — Todo cabe en un solo fichero ================================= Episodio «¿Cómo se le da memoria a una IA?» — Punto 6 del guion, «Las tres decisiones» (acto III — El relato y lo que lo sostiene). La idea del episodio -------------------- Todos los recuerdos de un asistente con memoria pueden vivir en **un único fichero** en tu propia máquina: lo que dijiste, las fichas de lo que pasó, cómo eres, qué pasó y cuándo, y la bitácora del día. Consecuencias: * Tus recuerdos **no salen de tu casa**: no hay nube a la que subir nada. * Lo copias a un *pendrive* y tienes tu memoria entera en el bolsillo. * Lo borras y no queda rastro en ningún sitio. * Lo abres y lees qué sabe el asistente de ti. Qué hace este ejemplo --------------------- Crea ese fichero único —un `.json` con las cinco capas dentro—, lo enseña por pantalla, lo copia como si fuera a un *pendrive* y comprueba que la copia contiene exactamente lo mismo. Los recuerdos que trae son **fragmentos reales de una instancia de Valet en producción**, generalizados para publicarlos: sin nombres de terceros, sin lugares y sin datos que permitan identificarla. La gracia no es el formato, es que **cabe todo junto y es tuyo**. No necesita nada instalado (solo Python 3, que ya viene en casi cualquier Linux). Uso: python3 01-un-solo-fichero.py # escribe ./memoria-demo.json python3 01-un-solo-fichero.py /ruta/mi-memoria.json """ import json import os import shutil import sys # ───────────────────────────────────────────────────────────────────────────── # Las cinco capas del episodio, dentro de un solo diccionario. Son fragmentos # reales de una instancia de Valet en producción, generalizados para publicar. # Capa A: lo que dijiste (la grabación en bruto) # Capa B: lo que pasó (fichas con el sentido de la conversación) # Capa C: cómo eres (tu retrato + el tono del asistente; en producción, 19 normas) # Capa D: qué y cuándo (hechos sueltos con fecha) # Capa E: la bitácora (el relato del día, escrito solo) # ───────────────────────────────────────────────────────────────────────────── MEMORIA_DE_EJEMPLO = { "A_lo_que_dijiste": [ {"quien": "tú", "texto": "Resúmeme los artículos de RSS que tengo pendientes."}, { "quien": "asistente", "texto": "Hecho. Te dejo por aquí los temas y las decisiones que saco en limpio.", }, ], "B_lo_que_paso": [ { "fecha": "2026-10-24", "temas": [ "RSS", "Docker Compose", "cifrado de disco", "monitorización de servidores", "alternativas a Dropbox", ], # Fragmento real de la ficha (≈257 tokens en producción). "sintesis": "Resumen y selección de artículos de RSS pendientes; " "el usuario pidió un resumen y una selección de lo más relevante.", } ], "C_como_eres": { # El retrato: verdades que se destilan con el tiempo, no hechos de un día. "quien_eres": [ "Sales a correr con regularidad y te gusta anotar distancias y ritmos.", "Prefieres resolver las cosas por la mañana.", ], # Las normas de casa: cómo quieres que se comporte tu asistente. # Estas tres están citadas tal cual; en producción hay 19. "normas_de_casa": [ "No inventes ni rellenes contenidos no disponibles; informa con " "honestidad sobre limitaciones de acceso.", "Verifica antes y después de crear recordatorios o eventos.", "No registres afirmaciones subjetivas o no verificables como hechos " "en el timeline.", ], }, "D_que_y_cuando": [ { # Cambiado de 2026-10-20 a 2026-10-17: el 20 es una de las jornadas # de la bitácora (18, 19 y 20) y no puede llevar dos cifras distintas. # El 17 no colisiona con ningún día de la bitácora y mantiene el # orden ascendente de la línea del tiempo (17 · 21 · 22). "fecha": "2026-10-17", "hecho": "Corrí 9,00 km con 119 m de desnivel y ritmo medio de 6:44 min/km.", }, {"fecha": "2026-10-21", "hecho": "Cené fuera."}, {"fecha": "2026-10-22", "hecho": "Corregí el nombre en la ficha de Valet."}, ], "E_la_bitacora": [ { "fecha": "2026-10-18", "relato": "Hoy ha sido un día de esos en los que la lluvia y las " "decisiones se entrelazan de manera inesperada.", "animo": "buen día", "logros": [ "Ajustar el plan de entrenamiento a la lluvia", "Decidir una tirada de 40 min en vez de 13 km", ], "dificultades": ["Condiciones adversas"], "etiquetas": ["entrenamiento", "meteorología", "decisiones"], } ], } def ruta_por_defecto(): return os.path.join(os.getcwd(), "memoria-demo.json") def main(): ruta = sys.argv[1] if len(sys.argv) > 1 else ruta_por_defecto() # 1) Escribir el fichero único. with open(ruta, "w", encoding="utf-8") as f: json.dump(MEMORIA_DE_EJEMPLO, f, ensure_ascii=False, indent=2) print("=" * 68) print(" UN SOLO FICHERO CON TODA LA MEMORIA") print("=" * 68) print(f"\n Fichero: {ruta}") print(f" Tamaño : {os.path.getsize(ruta)} bytes (ocupa nada, ya lo ves)") # 2) Enseñar las cinco capas que viven dentro, sin entrar en tripas. print("\n Dentro de ese único fichero:\n") etiquetas = { "A_lo_que_dijiste": "A · lo que dijiste", "B_lo_que_paso": "B · lo que pasó", "C_como_eres": "C · cómo eres", "D_que_y_cuando": "D · qué y cuándo", "E_la_bitacora": "E · la bitácora", } for clave, etiqueta in etiquetas.items(): contenido = MEMORIA_DE_EJEMPLO[clave] n = len(contenido) if isinstance(contenido, list) else len(contenido.keys()) print(f" • {etiqueta:<20} → {n} elemento(s)") # 3) "Copiarlo al pendrive": es un fichero, se copia y punto. destino = ruta + ".copia-pendrive.json" shutil.copyfile(ruta, destino) iguales = open(ruta, "rb").read() == open(destino, "rb").read() print(f"\n Copia al pendrive: {destino}") print(f" ¿La copia es idéntica? {'sí ✔' if iguales else 'no ✘'}") # 4) "Abrirlo y leer qué sabe de ti": aquí lo enseñamos en crudo. print("\n Y si lo abres, esto es lo que el asistente sabe de ti:") print(" " + "-" * 64) perfil = MEMORIA_DE_EJEMPLO["C_como_eres"]["quien_eres"] for verdad in perfil: print(f" · {verdad}") print(" " + "-" * 64) print("\n Lo borras y no queda rastro en ningún sitio. Eso es la gracia.\n") if __name__ == "__main__": main()