memweave: Memoria de agente de IA de infrarrojos cero con Markdown y SQLite: no se requiere una base de datos vectorial

Divulgación: memweave es un proyecto de código abierto que construí. Este artículo describe el problema que aborda y las decisiones de diseño detrás de él.

Imagínese esto: pasa una tarde construyendo un asistente de codificación de IA. Aprende las convenciones de su proyecto, recuerda que usa Valkey en lugar de Redis y conoce los patrones de prueba preferidos de su equipo. La sesión termina. Abre una nueva conversación a la mañana siguiente y te has olvidado de todo. De vuelta al punto de partida.

Este es el estado predeterminado de cada agente LLM. Los modelos no tienen estado por diseño. Cada llamada comienza con una pizarra en blanco. La memoria es tu problema a resolver.

La solución más común es incluir todo el historial de conversaciones en la ventana contextual. Funciona… hasta que deja de funcionar. Las ventanas de contexto son finitas y caras. Un agente de larga trayectoria acumula miles de muestras de historia, la mayoría de las cuales son irrelevantes para la cuestión actual. Termina pagando para alimentar repetidamente a su agente con las notas de depuración de la semana pasada cuando todo lo que necesita es una decisión de arquitectura de hace tres meses.

Entonces buscas una base de datos vectorial. Active Chroma o proporcione un índice Pinecone, incruste todo y realice consultas por similitud semántica. Esto también funciona, pero introduce una nueva clase de problemas:

Opacidad. La memoria de su agente vive en un índice binario que no puede abrir, leer ni razonar. ¿Qué sabe realmente su agente? Sólo puedes averiguarlo consultándolo. Sin control de versiones. No existe un git diff para una tienda de vectores. No se puede ver lo que un agente aprendió entre ejecuciones, auditar su conocimiento o revertir un mal recuerdo. Gastos generales de infraestructura. Incluso para un único agente local, ahora tiene un proceso de servidor que administrar, credenciales que configurar y un servicio que seguir ejecutando. Memoria rancia, sin remedio. Una base de datos vectorial clasifica los resultados por similitud semántica, punto. Una nota de depuración de hace seis meses compite en pie de igualdad con una decisión tomada esta mañana. El contexto más antiguo y obsoleto emerge con confianza junto con el conocimiento nuevo, y no existe ningún mecanismo incorporado para preferir lo reciente a lo obsoleto. Ediciones invisibles. Si desea corregir un recuerdo (corregir una suposición errónea que almacenó el agente), debe eliminarlo y volver a incrustarlo. No puede simplemente abrir el archivo y cambiar una línea.

El problema más profundo es que ninguna de estas herramientas fue diseñada para la memoria del agente. Fueron diseñados para la recuperación de documentos a escala. Usarlos para un agente personal o de ámbito de proyecto es como implementar un clúster de PostgreSQL para almacenar un archivo de configuración.

Hay una manera más sencilla.

El enfoque: Markdown + SQLite

Foto de Soragrit Wongsa en Unsplash

La idea central detrás de memweave es deliberadamente simple: las memorias son archivos .md que se escriben en el disco. memweave los indexa en una base de datos SQLite local y le permite buscar entre ellos con una búsqueda de vector semántico híbrido BM25 +. La base de datos es siempre una caché derivada; si la elimina, memweave la reconstruye a partir de los archivos. Los archivos son la fuente de la verdad.

pip instalar memweave

Aquí encontrará todo lo que necesita para darle a un agente memoria persistente:

import asyncio from pathlib import Path from memweave import MemWeave, MemoryConfig async def main(): async with MemWeave(MemoryConfig(workspace_dir=".")) as mem: # Escribe una memoria, solo un archivo de Markdown simple Memory_file = Path("memory/stack.md") Memory_file.parent.mkdir(exist_ok=True) Memory_file.write_text("Usamos Valkey en lugar de Redis. Latencia objetivo SLA: 5 ms p99.") await mem.add(memory_file) # Búsqueda en todas las memorias. # min_score=0.0 garantiza que los resultados aparezcan en un corpus pequeño; # en producción, el umbral predeterminado de 0,35 filtra las coincidencias de baja confianza. resultados = await mem.search("decisión de capa de almacenamiento en caché", min_score=0.0) para r en resultados: print(f"[{r.score:.2f}] {r.snippet} ← {r.path}:{r.start_line}") asyncio.run(main())

Producción:

[0.34] Usamos Valkey en lugar de Redis. Latencia objetivo SLA: 5 ms p99. ← memoria/pila.md:1

Cada resultado incluye su puntuación de relevancia, el archivo exacto del que procede y el número de línea: procedencia completa de la fuente lista para usar. No se necesita posprocesamiento para rastrear dónde se originó una respuesta.

Y como los recuerdos son sólo archivos, puedes inspeccionarlos con cualquier herramienta que ya tengas:

memoria cat/stack.md grep -r memoria "Valkey"/ memoria git diff/

Ese último comando, git diff Memory/, es el que cambia su forma de pensar sobre la memoria del agente. Cada dato que almacena su agente es una línea en un archivo. Cada sesión es un compromiso. Lo que su agente aprendió es tan auditable como cualquier otro cambio en su código base.

Por qué archivos y SQLite en lugar de una base de datos vectorial

Las bases de datos vectoriales se diseñaron para la recuperación de documentos a gran escala: millones de documentos, servicios multiinquilino e infraestructura de búsqueda de producción. Son excelentes en ese trabajo. La memoria del agente es un trabajo completamente diferente: cientos de miles de archivos, personales o relacionados con proyectos, donde el conocimiento es tan importante como el código mismo. Estas limitaciones me empujaron hacia un conjunto diferente de compensaciones:

memweave vs bases de datos vectoriales (imagen del autor)

Cada una de estas diferencias se agrava en la práctica, pero el control de versiones ilustra la brecha de manera más concreta. Considere lo que sucede cuando su agente almacena una suposición errónea; digamos, se enteró de que su equipo usa PostgreSQL cuando realmente migró a CockroachDB el último trimestre. Con una base de datos vectorial, corregir esto significa encontrar la incrustación correcta, eliminarla y volver a insertar la versión corregida a través de API. Con memweave, abres el archivo y arreglas la línea. Entonces lo cometes.

# git diff Memory/stack.md – Base de datos: PostgreSQL (principal), Redis (caché) + Base de datos: CockroachDB (principal, migrada en el primer trimestre de 2026), Valkey (caché) + Motivo: requisito de distribución geográfica del equipo de la plataforma

Esa diferencia ahora es parte del historial de su proyecto. Cualquier compañero de equipo (o cualquier futuro agente) puede ver qué cambió, cuándo y por qué. Este es el modelo operativo en torno al cual se construye memweave: la memoria del agente como un artefacto de primera clase de su proyecto, no un efecto secundario almacenado en un servicio que no puede inspeccionar.

Arquitectura

memweave se basa en una idea central: separar el almacenamiento de la búsqueda. Los archivos Markdown son la fuente de la verdad. La base de datos SQLite es un índice derivado: siempre reconstruible, nunca irremplazable.

┌─────────────────────────────── ───────────────────────────────┐ │ FUENTE DE LA VERDAD (archivos Markdown) │ │ memoria/MEMORIA.md ← conocimiento imperecedero │ │ memoria/2026-03-21.md ← registros diarios │ │ memoria/researcher_agent/ ← espacio de nombres con ámbito de agente │ └───────────────────────┬─────── ───────────────────────────────┘ │ fragmentación → hash → incrustación ┌───────────────────────▼─────── ───────────────────────────────┐ │ ÍNDICE DERIVADO (SQLite) │ │ fragmentos – texto + metadatos │ │ fragmentos_fts – índice de texto completo FTS5 (BM25) │ │ fragmentos_vec – índice SIMD sqlite-vec (coseno) │ │ embedding_cache – hash → vector (calcular una vez, reutilizar) │ │ archivos – Detección de cambios SHA-256 │ └───────────────────────┬─────── ───────────────────────────────┘ │ fusión híbrida → posprocesamiento ▼ lista [Resultado de búsqueda]

Esta separación tiene una consecuencia práctica que es fácil pasar por alto: perder la base de datos no es pérdida de datos. Perder los archivos lo es. Si el índice SQLite se elimina o está dañado, await mem.index() lo reconstruye completamente a partir de los archivos Markdown en el espacio de trabajo. No se han perdido datos. No es necesario volver a recuperar las incrustaciones si el caché está intacto.

La ruta de escritura

Cuando llamas a await mem.add(path) o await mem.index(), memweave procesa cada archivo a través de una canalización determinista, sin LLM involucrado en ningún paso:

Archivo .md │ ▼ fragmentación: división en fragmentos de texto superpuestos │ ▼ sha256(chunk_text): huella dactilar de cada fragmento por contenido │ ▼ búsqueda de caché integrada: consulta SQL masiva: ¿qué hashes ya están almacenados en caché? │ ├── acierto de caché ──────── reutilizar el vector almacenado, omitir llamada API │ └── pérdida de caché ──────── llamar a la API de incrustación (por lotes) │ ▼ almacenar en caché – escribir vector en tabla embedding_cache │ ▼ insertar en tablas FTS5 + sqlite-vec

El hash SHA-256 es la palanca clave de eficiencia. El hash de un fragmento está determinado completamente por su contenido de texto, por lo que si un archivo se vuelve a indexar y el 90% de sus fragmentos no cambian, solo los fragmentos modificados activan una llamada API. El resto se sirve desde la caché al instante.

El camino de la búsqueda

Cuando llama a await mem.search(query), ambos motores de búsqueda se ejecutan en paralelo con la misma consulta y sus resultados se combinan antes del posprocesamiento:

consulta │ ├─── FTS5 BM25 (palabra clave) ─────────────────────┐ │ coincidencia exacta de términos │ │ ▼ └─── sqlite-vec ANN (semántica) ────── ► puntuación de similitud de coseno de fusión ponderada = 0,7 × vector + 0,3 × BM25 │ ▼ canalización de posprocesamiento (umbral → decadencia → MMR) │ ▼ lista[Resultado de búsqueda]

Ejecutar ambos backends en paralelo es importante: BM25 detecta coincidencias exactas (códigos de error, valores de configuración, nombres propios) mientras que la búsqueda vectorial detecta contenido semánticamente relacionado incluso cuando no hay palabras clave superpuestas. Juntos cubren toda la gama de formas en que es probable que se consulte la memoria de un agente. El proceso de posprocesamiento que sigue a la fusión se trata en detalle en las siguientes secciones.

¿Por qué SQLite como capa de infraestructura?

La elección de SQLite merece una breve nota. SQLite no es un compromiso: es una opción deliberada para este caso de uso. Se envía con Python, no requiere servidor, admite búsqueda de texto completo a través de FTS5 y, con la extensión sqlite-vec, obtiene búsqueda de similitud vectorial acelerada por SIMD. Todo el almacén de memoria (fragmentos, incrustaciones, caché, metadatos de archivos) es un único archivo en el disco que puede copiar, realizar copias de seguridad o inspeccionar con cualquier navegador SQLite. Para la escala de memoria del agente (miles de archivos), no sólo es suficiente: es óptima.

Cómo memweave organiza la memoria: archivos permanentes, registros fechados y espacios de nombres de agentes

No todos los conocimientos envejecen por igual. La decisión de un equipo de utilizar CockroachDB en lugar de PostgreSQL es tan relevante hoy como el día en que se tomó. Una nota de depuración de una sesión de hace seis meses probablemente no lo sea. memweave impone esta distinción a nivel de archivo: sin etiquetado de metadatos, sin configuración, solo una convención de nomenclatura.

Hay dos tipos de archivos de memoria:

Tipos de archivos de memoria en memweave (imagen del autor)

La regla es simple: cualquier archivo cuyo nombre coincida con AAAA-MM-DD.md tiene fecha. Todo lo demás es siempre verde. memweave lee la fecha directamente desde el nombre del archivo: sin metadatos del sistema de archivos, sin análisis inicial, sin etiquetado manual.

Un espacio de trabajo típico se organiza de forma natural en torno a esta convención:

memoria/ ├── MEMORIA.md ← evergreen – hechos permanentes, siempre superficies ├── arquitectura.md ← evergreen – decisiones de pila, restricciones ├── 2026-01-15.md ← fechado – notas de sesión de enero ├── 2026-03-10.md ← fechado – notas de la sesión de marzo ├── 2026-04-11.md ← fechado – sesión de hoy, puntaje completo por ahora └── investigador_agente/ ├── hallazgos.md ← evergreen – conocimiento permanente del agente └── 2026-04-11.md ← fechado: el registro de sesión del agente decaerá

Con el tiempo, los archivos fechados se acumulan y desaparecen. Los archivos imperecederos permanecen anclados en su totalidad independientemente de cuánta historia se acumule a su alrededor. Un agente que pregunta sobre la pila tecnológica siempre obtiene arquitectura.md en la parte superior de sus resultados, incluso si desde entonces se han escrito cientos de registros de sesiones.

Espacios de nombres de agentes (habilita la memoria multiagente)

Cuando varios agentes comparten un espacio de trabajo, necesita una manera de mantener su conocimiento aislado sin tener que crear bases de datos separadas. memweave maneja esto a través de subdirectorios. El subdirectorio inmediato en memoria/ se convierte en la etiqueta de origen para cada archivo dentro de él:

Ejemplos de espacios de nombres del agente memweave (imagen del autor)

Cada agente escribe en su propio subdirectorio. Todos los agentes indexan con la misma base de datos SQLite. Las búsquedas son globales de forma predeterminada: cualquier agente puede leer las memorias de cualquier otro agente. Pase source_filter para limitar una búsqueda exclusivamente a un espacio de nombres:

# El investigador escribe en su propio espacio de nombres investigador = MemWeave(MemoryConfig(workspace_dir="./project")) escritor = MemWeave(MemoryConfig(workspace_dir="./project")) async con el investigador, escritor: # El investigador indexa sus hallazgos en memoria/researcher_agent/ await investigador.index() # El escritor consulta solo los resultados del espacio de nombres del investigador = await escritor.search( "agua helada en la Luna", source_filter="researcher_agent", )

Este patrón se adapta naturalmente a cualquier número de agentes. El conocimiento de cada agente está aislado por convención de ruta, se puede inspeccionar como una carpeta y se puede versionar de forma independiente: git log Memory/researcher_agent/ muestra exactamente lo que aprendió ese agente y cuándo.

canalización de búsqueda memweave

Cada llamada a mem.search(query) pasa por cinco etapas fijas en orden. Cada etapa es independiente, componible y sintonizable. Aquí está el proceso completo y luego cada etapa en detalle.

Canal de búsqueda de memweave de 5 etapas (imagen del autor)

Etapa 1: Fusión de puntuación híbrida

Ambos backends se ejecutan en paralelo con la misma consulta y sus puntuaciones se normalizan y luego se combinan linealmente:

puntuación_fusionada = α × puntuación_vectorial + (1 − α) × puntuación_bm25

Predeterminado α = 0,7. Cada backend aporta lo que mejor sabe hacer:

FTS5 BM25 clasifica por frecuencia de términos y frecuencia inversa de documentos. Es un ancla de precisión: los términos técnicos exactos, los códigos de error, los valores de configuración y los nombres propios obtienen una puntuación alta. Si su consulta y su documento utilizan las mismas palabras, BM25 las encuentra. La similitud del coseno sqlite-vec mide la distancia en el espacio de incrustación. Capta contenido semánticamente relacionado incluso cuando no hay palabras clave superpuestas: una consulta de "capa de almacenamiento en caché" mostrará un fragmento que menciona "latencia de Redis" porque las incrustaciones están cerca, aunque las palabras difieran.

La división 70/30 refleja la naturaleza de la mayoría de las consultas de memoria de los agentes: conceptuales y parafraseadas con mayor frecuencia que las búsquedas de cadenas exactas. Ajuste los pesos a través de HybridConfig, si su caso de uso se inclina hacia una recuperación técnica precisa:

de memweave.config import MemoryConfig, QueryConfig, HybridConfig config = MemoryConfig( consulta=QueryConfig( hybrid=HybridConfig( vector_weight=0.5, # peso igual para corpus con muchas palabras clave text_weight=0.5, ) ) )

Etapa 2: umbral de puntuación

eliminar resultado si fusionado_score < min_score (predeterminado: 0,35)

Una puerta de ruido que se ejecuta antes de las etapas de posprocesamiento más costosas. Sin él, los resultados de cola de baja confianza entran en MMR y en los cálculos de desintegración y desperdician cálculos. El valor predeterminado de 0,35 está calibrado para corpus de memoria de agente típicos: bájelo para espacios de trabajo pequeños donde desee que aparezcan más resultados, súbalo cuando la precisión importe más que la recuperación.

# Anulación por llamada: no se necesitan cambios de configuración resultados = await mem.search("decisión de arquitectura", min_score=0.5)

Etapa 3: Decaimiento temporal (optar por participar)

Los agentes acumulan conocimiento con el tiempo, pero no todo el conocimiento envejece por igual. Sin decaer, una nota de depuración obsoleta de hace seis meses puede superar una decisión tomada esta mañana simplemente porque está bien integrada. La decadencia temporal resuelve esto multiplicando la puntuación de cada resultado por un factor exponencial basado en la antigüedad de su archivo fuente.
La fórmula es decaimiento exponencial estándar:

λ = ln(2) / half_life_days multiplicador = exp(−λ × age_days) decayed_score = original_score × multiplicador

En age_days = 0, el multiplicador es 1,0, sin cambios. En age_days = half_life_days es exactamente 0,5. La curva es suave y continua: las puntuaciones nunca se ponen a cero, los viejos recuerdos siguen apareciendo, simplemente tienen una clasificación más baja que los recientes.

Los archivos Evergreen omiten esta etapa por completo: su multiplicador es siempre 1,0, independientemente de cuándo se escribieron.

de memweave.config import MemoryConfig, QueryConfig, TemporalDecayConfig config = MemoryConfig( query=QueryConfig( temporal_decay=TemporalDecayConfig( enable=True, half_life_days=30.0, # sintoniza tu flujo de trabajo ) ) )

Ajuste half_life_days a su flujo de trabajo: 7 para proyectos de rápido movimiento donde el contexto de una semana ya está obsoleto, 90 para repositorios de investigación o documentación donde el conocimiento sigue siendo relevante durante meses.

Etapa 4: Reclasificación de MMR (optar por participar)

Sin control de diversidad, los principales resultados de una búsqueda híbrida suelen estar casi duplicados: múltiples fragmentos del mismo archivo o diferentes frases del mismo hecho. Un agente que los carga todos en su ventana de contexto desperdicia tokens y pierde otros recuerdos relevantes pero distintos.

MMR (Relevancia marginal máxima) reordena los resultados después de la puntuación para equilibrar la relevancia con la diversidad. En cada paso de selección elige al candidato que maximiza:

MMR(cᵢ) = λ × relevancia(cᵢ) − (1 − λ) × max sim(cᵢ, cⱼ) para cⱼ ∈ S

Dónde:
S = conjunto de resultados ya seleccionados
relevancia (cᵢ) = puntuación fusionada de la Etapa 1, después de la decadencia temporal
sim(cᵢ, cⱼ) = Superposición del token Jaccard entre el candidato y cada resultado seleccionado
λ = dial de diversidad: 0 es diversidad pura, 1 es relevancia pura, valor predeterminado 0,7

¿Por qué Jaccard se superpone en lugar de semejanza de coseno?

Dos fragmentos que comparten muchas de las mismas palabras (incluso de archivos diferentes) son realmente redundantes para un agente que los carga como contexto. Jaccard detecta esto a nivel de token sin requerir una llamada de incorporación adicional por par.

┌──────────────┬───────────────────── ────────────────────────────────────┐ │ lambda_param │ Comportamiento │ ├──────────────┼───────────────────── ────────────────────────────────────┤ │ 1,0 │ Relevancia pura: idéntico a ningún MMR │ │ 0,7 │ Predeterminado: fuerte relevancia, ligero impulso a la diversidad │ │ 0,5 │ Igual peso entre relevancia y diversidad │ │ 0,0 │ Diversidad pura: resultados máximamente novedosos │ └──────────────┴───────────────────── ────────────────────────────────────┘ de memweave.config import MemoryConfig, QueryConfig, MMRConfig config = MemoryConfig( query=QueryConfig( mmr=MMRConfig(enabled=True, lambda_param=0.7) ) ) # O anular λ por llamada sin tocar la configuración divers_results = await mem.search("pasos de implementación", mmr_lambda=0.3)

Etapa 5: posprocesadores personalizados

Todos los procesadores registrados mediante mem.register_postprocessor() se ejecutan en último lugar, en orden de registro. Cada uno recibe la salida de la etapa anterior y puede filtrar, reordenar o volver a puntuar libremente: refuerzo de dominio específico, fijar un resultado en la parte superior o integrar una señal externa. La canalización incorporada se ejecuta primero; Las etapas personalizadas lo amplían sin reemplazarlo.

Ejemplo del mundo real utilizando memweave: registro de decisiones del club de lectura

La mejor manera de ver memweave en acción es ver a dos agentes responder la misma pregunta con diferentes estrategias de recuperación. El cuaderno ejecutable completo está disponible en ejemplos/book_club_demo.ipynb.

La configuración

El espacio de trabajo contiene 9 archivos de memoria que abarcan 18 meses de la historia de un club de lectura:

Conjunto de datos del club de lectura (imagen del autor)

Un archivo imperecedero contiene información permanente que siempre debería aparecer con toda su puntuación. Siete expedientes datados acumulan la historia del club. Un archivo escrito hoy contiene el estado actual.

La pregunta

A ambos agentes se les hace la misma pregunta:

“¿Qué género votó el club más recientemente?”

La respuesta correcta, basada en la información más reciente, es ciencia ficción, seguida probablemente por la ficción literaria. Pero un agente sin conciencia temporal no necesariamente encontrará esto.

Agente A: sin deterioro temporal

config = MemoryConfig( workspace_dir=WORKSPACE, embedding=EmbeddingConfig(model="text-embedding-3-small"), ) async with MemWeave(config) as mem: results = await mem.search( "¿Qué género votó el club más recientemente?", max_results=3, min_score=0.1,)

Los 3 mejores resultados del Agente A por similitud semántica bruta:

[0.339] 2025-11-03.md ← Voto de no ficción (hace 5 meses) [0.336] 2024-10-05.md ← Voto de fantasía (hace 18 meses) [0.320] 2025-05-10.md ← Voto misterioso (hace 11 meses)

El archivo de hoy no aparece entre los 3 primeros. Los archivos de “voto” más antiguos lo superan en similitud semántica pura porque contienen un lenguaje de votación más explícito. La respuesta del agente A:

"El club votó recientemente sobre el género de no ficción".

De hecho, está obsoleto: la votación de noviembre de 2025, no la más reciente.

Agente B: con deterioro temporal (vida media = 90 días)

async con MemWeave(config) como mem: results = await mem.search( "¿Qué género votó el club más recientemente?", max_results=3, min_score=0.1, decay_half_life_days=90.0,)

Los 3 mejores resultados del Agente B después de la penalización por edad:

[0.313] 2026-04-11.md ← Notas de hoy (multiplicador: 1.00) ↑ rango 1 [0.293] club_info.md ​​← Evergreen (multiplicador: 1.00) [0.128] 2025-12-30.md ← Plan de ciencia ficción (multiplicador: ~0.46)

El archivo de hoy flota al rango 1 después de que la penalización por edad colapsa las puntuaciones de los archivos más antiguos. La revisión de fin de año conserva ~46% de su puntuación; la votación de no ficción de noviembre de 2025 queda completamente fuera del top 3.

La respuesta del Agente B, basada en el expediente de hoy:

"El club votó recientemente a favor de la ciencia ficción".

Lo que esto demuestra

El problema de la memoria obsoleta es real y silencioso. El agente A no sabe que está mal. Devuelve una respuesta segura basada en las coincidencias semánticas con mayor puntuación, que resultan ser archivos más antiguos con un lenguaje de votación más explícito. No hay ningún error ni advertencia, sólo un contexto sutilmente desactualizado. La ventaja de la decadencia se agrava con la historia. Con 18 meses de expedientes, el contexto del Agente A se llena de votos cada vez más obsoletos. Cuanto más crece la memoria, peor se vuelve el problema y más dramática es la diferencia entre los dos agentes. club_info.md ​​(evergreen) aparece en el Agente B con la máxima puntuación. Con la decadencia habilitada, la penalización por edad borra los registros de votos obsoletos y la información permanente se eleva al top 3, a pesar de que nunca es la coincidencia semántica más cercana a la consulta. En el Agente A, los archivos más antiguos con lenguaje de votación explícito lo superan en similitud cruda. La inmunidad imperecedera está determinada por la ruta del archivo, no por el contenido. Un solo cambio de parámetro es todo lo que se necesita. decay_half_life_days=90.0 es la única diferencia entre el Agente A y el Agente B. Sin cambios de esquema, sin reindexación, sin etiquetado de metadatos.

Resumen

La memoria del agente no tiene por qué significar infraestructura. memweave hace una apuesta diferente: los recuerdos son simples archivos Markdown que puedes abrir, editar y git diff. Una base de datos SQLite local los indexa para una búsqueda híbrida: BM25 para coincidencias exactas, búsqueda vectorial para recuperación semántica, fusionados en una lista clasificada única. La decadencia temporal mantiene automáticamente el contexto reciente por encima de la historia obsoleta. MMR garantiza que los mejores resultados cubran diferentes aspectos de su consulta en lugar de repetir el mismo hecho. Un caché integrado significa que solo el contenido modificado llega a la API. Todo el almacén es un único archivo en el disco: sin servidor, sin Docker, sin servicio en la nube.

La demostración del club de lectura concreta el compromiso: dos agentes, una pregunta, una diferencia de parámetro, dos respuestas diferentes. El agente con decadencia temporal aparece en el archivo de hoy en el rango uno. El agente, sin él, saca a la luz una votación de hace cinco meses con un lenguaje de “votación” más explícito y, con confianza, da la respuesta incorrecta sin saberlo.

El punto más amplio es que el problema de la memoria obsoleta permanece silencioso. No hay ningún error ni advertencia, solo un contexto sutilmente desactualizado que se introduce en el modelo. Cuanto más crece la memoria, más archivos obsoletos se acumulan y más agresivamente compiten con los recientes en similitud semántica pura. La decadencia temporal es el único mecanismo que mantiene honesta la recuperación a medida que avanza la historia.

Empezar

pip instalar memweave

Si encuentra algo inesperado, encuentra un caso de uso que la biblioteca no cubre bien o simplemente desea compartir lo que creó: abra un problema o inicie una discusión en GitHub. Los comentarios serán muy apreciados.