Skip to main content
Glama
lna-lab

distill-kura

by lna-lab

蒸留蔵 — distill-kura

Una memoria a largo plazo para agentes que se destila, no se acumula. El recuerdo funciona por significado, la escritura está controlada por evidencia, y un servidor puede contener varias memorias separadas — una por modo de agente — de modo que cambiar de modo cambia lo que el agente recuerda.

Se distribuye como un plugin de DeepSeek Harness, un servidor MCP para cualquier otro host, un servicio HTTP y una biblioteca de Python. Solo biblioteca estándar; sin base de datos vectorial, sin embeddings, sin framework.

        ┌── recall ──────────────────────────────────────────────┐
        │  question → whole index in one prompt → picked slugs   │
        │           → walk [[links]] → the neighbourhood         │  ~0.4 s
        └────────────────────────────────────────────────────────┘
        ┌── distil ──────────────────────────────────────────────┐
        │  journal → classed evidence → candidates → GATE        │
        │  → new? → composed → draft → judged → poured           │
        └────────────────────────────────────────────────────────┘

Por qué existe esto

Dos fallos matan la memoria a largo plazo de un agente, y la matan desde lados opuestos.

La recuperación por palabras clave pierde lo que necesitabas. Una pregunta sobre "chips de inferencia SSD" no comparte ninguna palabra con una memoria titulada "ejecutando el modelo de 2.6T desde un nivel SSD" — sin embargo, son el mismo tema. La búsqueda de palabras no devuelve nada; el agente responde desde la nada. La solución aquí no son los embeddings sino el reconocimiento: el índice completo (una línea por memoria, escrita como un disparador de reconocimiento) entra en un solo prompt, y un modelo pequeño nombra lo que es relevante para la pregunta. Un índice de ~500 memorias son alrededor de 6k tokens — un pequeño porcentaje de una ventana de contexto moderna, y reside en la caché de prefijo.

Escribirlo todo envenena el almacén. Un agente afirma algo; un destilador ingenuo registra la afirmación como un hecho; el siguiente agente la lee como verdad absoluta y la repite con más confianza. Ese bucle se refuerza a sí mismo, y las instrucciones del prompt no lo detienen — medido, no asumido. Así que la ruta de escritura está controlada por Python determinista: cada memoria candidata debe llevar citas que existan carácter por carácter en el material bruto, etiquetadas con su procedencia.

clase

qué es

qué autoriza

[USER]

las palabras del humano

"ellos decidieron", "ellos preguntaron"

[TOOL]

salida de máquina

números — la única fuente

[ACT]

una herramienta invocada

"esto se hizo"

[SELF]

la prosa del agente

un juicio, en primera persona, nunca un hecho desnudo

Una cita que no se encuentra textualmente se descarta. Un candidato sin ninguna cita superviviente se desecha. Un número sin un [TOOL] detrás se elimina. El texto que atribuye al humano una decisión, cuando no sobrevive ninguna cita [USER], se rechaza en la última puerta. Las ideas son bienvenidas — van a un archivo semilla, nunca al almacén, y se gradúan solo cuando la evidencia posterior las confirma.


Related MCP server: Memsolus MCP Server

Inicio rápido

git clone https://github.com/lna-lab/distill-kura && cd distill-kura
pip install -e .                       # or just run: python3 -m distill_kura.cli

cp kura.example.toml kura.toml         # edit: one model endpoint is enough to start
kura init main --path ~/kura/main      # create an empty store
kura serve                             # http://127.0.0.1:8085
curl -s -X POST localhost:8085/recall -H 'content-type: application/json' \
     -d '{"question":"what did we decide about the archive disk?","hops":1}'

Lleva el índice, para que el agente siempre sepa lo que se sabe:

kura weave                             # build the three-layer cloth
kura prefill                           # the block to put in the system prompt

Aliméntalo con las transcripciones de tu agente:

kura distill run      # drink a batch → candidates → gate → drafts
kura distill drafts   # look at what it wants to write
kura distill drain    # the scribe re-reads each draft cold: pour / fix / toss
kura distill night    # stay resident and do it whenever things go quiet

Nada entra en el almacén hasta drain (o un pour ejecutado a mano). Los borradores llevan su evidencia en un comentario HTML, para que siempre puedas ver por qué existe una memoria.


El mapa residente

El recuerdo por herramienta responde "¿qué sabes sobre X?" — pero solo una vez que el agente ha decidido preguntar. Nunca responde a la pregunta que el agente no piensa en hacer: ¿hay algo aquí en absoluto? Un agente que no puede ver el mapa no sabe lo que le falta, así que adivina, y una suposición segura sobre tu hogar es precisamente el fallo que este proyecto existe para prevenir.

Así que el índice también se lleva: un bloque permanente en el prompt del sistema, en cada turno.

kura weave      # re-weave the index into the three-layer cloth
kura prefill    # print the block a host should inject

Tres capas, porque el detalle solo compensa para cosas recientes

Una prueba A/B a ciegas — 20 preguntas, índice grueso vs índice reducido, puntuado sin saber cuál era cuál — decidió la forma:

banda

grueso

reducido

general

9

11

eventos recientes

4

1

doctrina

1

4

saltos entre dominios

1

4

Las líneas de doctrina eran idénticas byte a byte en ambos índices, y el índice reducido aún ganó esa banda: un entorno más ligero hace que las líneas permanentes funcionen mejor. El detalle no es la fuente de la perspicacia. Gana su lugar solo donde las cosas aún se están moviendo.

capa

regla

línea

fijado

frontmatter type en pinned_types

se mantiene completo

reciente

cambiado dentro de fresh_days

se mantiene completo

disparador

todo lo demás

comprimido a ~trigger_tokens

Las líneas de disparador las escribe el modelo scribe y se cachean en un libro mayor con clave en la descripción y el presupuesto, de modo que un re-tejido en estado estacionario no cuesta nada. Sin modelo accesible, el telar recorta mecánicamente en su lugar — un sistema de memoria no debe quedarse en blanco porque una GPU esté caída.

La edad no es mtime. cp -r, una restauración o un checkout restablecen cada marca de tiempo, todo el índice se vuelve "reciente", nada se recorta, y el mecanismo se ha apagado silenciosamente. Así que el telar prefiere una fecha escrita dentro de la memoria, y desconfía de cualquier mtime que una quinta parte del almacén comparta con un día calendario.

Dónde va, y por qué es una decisión de caché

- id: kura
  name: distill-kura
  config: { store: eq, promptOrder: -50 }   # before the persona

Una caché de prefijo se pierde desde el primer byte cambiado en adelante — medido en un servidor local: un preámbulo idéntico de 4.029 tokens se re-preció de 0.68 s a 0.14 s, añadir al final se mantiene en 0.14 s, y una palabra añadida al frente cuesta toda la caché (0.66 s). La persona normalmente lleva un reloj, así que cambia cada minuto; el mapa es el bloque más grande del prompt y cambia unas pocas veces al día. La cosa grande y estable va delante de la cosa que hace tictac.

El bloque en sí, por tanto, no contiene fecha, ni reloj, ni contador — y build() rechaza un encabezado que los tenga, en tiempo de construcción en lugar de a través de turnos misteriosamente lentos tres semanas después.

Nunca entrega medio mapa

situación

lo que recibe el agente

todo bien

el mapa, entre los marcadores <<<KURA-MAP>>>

por encima de budget_fraction

el mapa completo, y una advertencia en el JSON (nunca en el texto — un banner es contenido volátil)

por encima de hard_fraction

un stub sin líneas de índice, que dice que el mapa falta en lugar de estar vacío

kura inalcanzable

una nota explícita de que el mapa falta, nunca una cadena vacía

Un mapa truncado es el peor artefacto disponible: parece completo, y cada memoria por debajo del corte parece no existir. weave acortará la ventana de recientes para que quepa, pero nunca eliminará una línea — y si ningún ajuste alcanza el presupuesto, lo dice, conserva el mejor mapa y te dice dónde está el peso.

Cómo llevarlo a un host

host

mecanismo

DSH

plugin nativo — una systemPrompt.section, actualizada en segundo plano

Claude Code, VS Code, Goose

MCP instructions lleva un puntero corto (límite de 2KB); el mapa en sí viene de la herramienta kura_map o de un hook de sesión que ejecuta kura prefill

Claude Desktop, claude.ai

ignora instructions por completo — usa kura_map

cualquier otra cosa

GET /prefill?format=text, o kura prefill en un hook de shell

El campo instructions de MCP es un MAY en la especificación, y un índice de 9.000 tokens no puede viajar a través de un límite de 2KB de todos modos, así que este proyecto no finge lo contrario.


Modos: más de un kura

Una única memoria que sirve tanto para "ayúdame a construir esto" como para "ayúdame a pensar esto" no sirve bien a ninguna: el recuerdo que te ayuda a depurar es ruido en una conversación sobre qué hacer a continuación. Así que un almacén es un directorio, y un modo se asigna a un almacén.

[stores.maker]
path = "~/kura/maker"
label = "maker mode — building things"

[stores.eq]
path = "~/kura/eq"
label = "EQ mode — talking things through"

[modes]
maker = "maker"
eq    = "eq"

Cada ruta toma un selector, así que un proceso sirve a todos:

curl -s -X POST localhost:8085/recall -d '{"question":"...","mode":"eq"}'
curl -s localhost:8085/index?store=maker
curl -s localhost:8085/s/eq/doctor          # path form, for clients that only vary a base URL

Los almacenes no comparten memorias, ni índice, ni marca de agua del destilador. Cambiar de modo cambia genuinamente lo que se recuerda — no la misma memoria con una voz diferente.

La sala se elige antes de la conversación. Un modo es lo que envía el host — un preset de DSH, KURA_STORE en un entorno MCP, -s en la CLI — y es el hogar de toda la sesión. Nada en este proyecto lee un mensaje y decide a qué almacén pertenece; una conversación que se desvía de construir a sentir se queda donde empezó, y el host puede ofrecer otra sala para la siguiente sesión. Un selector desconocido es un error en la puerta, nunca una caída silenciosa al valor por defecto.

Una sala, muchas etiquetas. Una memoria vive en exactamente un almacén y puede llevar varias etiquetas que describen su carácter (decision, landmine, emotion-carried, …). Las etiquetas son palabras, no pesos: nada las clasifica, nada las cuenta, y una memoria de Develop etiquetada como emotion-carried sigue siendo una memoria de Develop. No hay ningún comando que mueva o copie una memoria a otro almacén, y un cambio de modo afecta solo a sesiones futuras. El mismo tema planteado en dos salas produce dos memorias, cada una destilada de la evidencia de esa sala — el "lo que aprendimos" de Research y el "lo que hicimos" de Develop son hechos diferentes, y nada cruza el límite para deduplicarlos.

Una sala amplia recuerda un poco más suavemente. Los almacenes estrechos con estatutos fijos reconocen con nitidez. Se espera que un almacén que acepta cualquier cosa — una sala USER que sigue a la persona en lugar de un propósito — sea más flexible, y a cambio es aquel cuya comprensión puede crecer: un profile.md junto a su estatuto, en frases, leído después del estatuto, redactado a partir de sus propias memorias y aplicado por una persona. Cinco salas así, con sus estatutos y una configuración, están en examples/rooms/.

Independiente como enrutamiento, no como confidencialidad. El servidor no tiene autenticación, así que cualquier proceso que pueda alcanzar su puerto puede nombrar cualquier almacén que contenga. Vincular un agente mantiene un modelo en su carril; no mantiene a un proceso fuera. Un nivel de confianza por proceso — docs/TRUST.md es corto y vale la pena leerlo antes de que entre un almacén privado. También cubre los dos límites que son fáciles de pasar por alto: dos almacenes que beben de una misma raíz de diario, y dos almacenes detrás de un mismo endpoint de modelo.

Con DeepSeek Harness

DSH cambia persona y herramientas según el preset del agente. distill-kura cambia memoria según el almacén. Vincúlalos y un cambio de preset mueve todo el yo:

# .agent-presets/eq/agent.cordis.yml
- id: kura-eq
  name: distill-kura
  config:
    url: http://127.0.0.1:8085
    store: eq            # this preset's memory
    readonly: true       # the CLIENT's own switch: do not even offer a write tool
    # (the store's own `write_policy` is the authority; this just keeps the tool
    #  out of the model's hands. Naming a store already binds the preset.)

Una dependencia, y por qué es un peer. El plugin importa defineTool de @deepseek-ai/dsh-tools. Una segunda copia local al perfil puede dividir la identidad Symbol local del paquete — incluso en la misma versión — y hacer que la primera llamada a la herramienta falle en undefined.prepare. Por lo tanto, el plugin declara el paquete como un peer "*" para que el perfil suministre su copia sin un desajuste de versión. Una copia física obsoleta aún puede requerir deduplicación; consulta las comprobaciones de instalación en examples/dsh-presets/.

Deja allowSwitch en su valor por defecto y el agente también obtiene kura_use, para que pueda moverse entre kura a mitad de conversación sin un cambio de preset. Herramientas: kura_recall, kura_read, kura_doctor, kura_list, kura_use y kura_remember (solo cuando el almacén es escribible). El cableado completo, incluido el puente MCP y la regla de reino isolate para filas de servicio, está en examples/dsh-presets/.

Persona es el negocio del anfitrión, no el nuestro. Este proyecto nunca renderiza ni inyecta una persona; solo registra, por almacén, qué archivo de persona le corresponde, legible en GET /profile?store=eq para que las dos mitades puedan mantenerse sincronizadas por quien sea dueño del preajuste. Las instrucciones de agente también permanecen con el mecanismo AGENTS.md del anfitrión; consulte AGENTS.md en este repositorio para las convenciones que un agente que trabaje en este código base debe seguir.

Con cualquier host MCP

{ "mcpServers": { "kura": {
    "command": "python3", "args": ["-m", "distill_kura.mcp"],
    "env": { "KURA_URL": "http://127.0.0.1:8085", "KURA_STORE": "eq", "KURA_READONLY": "1" }
}}}

Deje KURA_STORE sin definir para el modo libre: las herramientas aceptan un argumento opcional store y kura_use cambia para la sesión.


Modelos: uno por defecto, mejore un rol a la vez

Tres roles, no tres máquinas:

rol

cuándo se ejecuta

quiere

thinker

cada recuerdo

pequeño y rápido; debe juzgar relevancia por significado

brain

destilando: lee un lote completo de diario

longitud de contexto y paciencia

scribe

destilando: escribe la memoria, luego juzga borradores

buena prosa en su idioma, juicio

Declare solo [models.thinker] y un modelo hace los tres — el modelo con el que habla también es el editor que escribe y juzga sus memorias. Ese es el valor predeterminado y es uno justo: un modelo GPU capaz hace el trabajo del editor lo suficientemente bien en sus minutos inactivos, y kura tend lo detiene en el momento en que usted regresa (consulte "Sin supervisión" más abajo).

La ruta de mejora es darle al editor su propio asiento — un modelo más grande, una API en línea, o un modelo de CPU que no compite por la GPU en absoluto, para que el mantenimiento pueda continuar mientras usted habla. La casa donde se construyó esto ejecuta un MoE de 1 billón de parámetros en CPU a aproximadamente 3 tokens por segundo como editor: lento, pero nunca toca el asiento que la conversación usa, y las memorias que escribió durante cinco días son un tercio del almacén hoy. Mejore cualquiera de los otros roles de forma independiente — un modelo local más grande, o una API en línea (cualquier /chat/completions compatible con OpenAI; la clave se lee de una variable de entorno que usted nombra, nunca se almacena en la configuración):

[models.thinker]                       # always-on, local, small
url = "http://127.0.0.1:8000/v1"
model = "local-small"

[models.scribe]                        # upgrade just the writing
url = "https://api.example.com/v1"
model = "big-model"
api_key_env = "EXAMPLE_API_KEY"

Dos cosas que esto maneja por usted: los dialectos de esfuerzo de razonamiento difieren según la familia de modelos (reasoning_effort, thinking_effort, enable_thinking), por lo que todos se envían — uno desconocido es ignorado por la plantilla, mientras que un modelo dejado en pensamiento profundo por defecto puede gastar todo su presupuesto razonando y no devolver nada. Y el texto de la carta se coloca byte-idéntico al inicio del prompt de cada rol, de modo que en un modelo local lento los tres roles comparten un prefijo en caché en lugar de pagar tres prefills.

Un editor lento necesita el prefijo. La carta se encuentra byte-idéntica al inicio de cada llamada, por lo que un editor de CPU a 3 tok/s paga su prefill una vez por silencio, no una vez por borrador; en llama.cpp, mantenga --cache-reuse 0 fuera de la mesa para modelos recurrentes y deje que el servidor mantenga sus ranuras calientes (--slot-save-path). Las llamadas del editor son las que esperan una hora (timeout=3600) a propósito.

Si el thinker está caído, el recuerdo no se queda en silencio — cae a la superposición de palabras y etiqueta la respuesta como how=words, que las herramientas muestran como ⚠ degradado. La degradación silenciosa es peor que la degradación.

Sin supervisión: kura tend

El destilador, el vertedor y el telar están destinados a ejecutarse en las horas tranquilas, y el vigilante que decide cuándo es eso no necesita modelo:

kura distill catchup -s maker   # first: start from today, do not drink a year of history
kura tend -s maker              # stays resident; one process per store
kura tend -s maker --once       # one tick, for a scheduler or a test

Ejecute catchup una vez cuando apunte un destilador a un diario que nunca ha visto — de lo contrario, su primer acto es beber toda la historia, que para un diario de un año son días de tiempo de modelo gastados en reaprender lo que el almacén ya puede saber. Solo mueve las marcas hacia adelante, por lo que nunca puede perder progreso.

"Tranquilo" es el mtime del archivo de diario más reciente. Después de idle_min (10) de silencio, drena los borradores en espera (el editor lee cada uno en frío: verter / arreglar / desechar), o ejecuta una pasada de destilación cuando no hay ninguno; cuando algo se vertió, re-teje el mapa residente una vez; y ordena el índice una vez por silencio. Una pista que no tenía nada que hacer sale con código 2 y descansa durante backoff_min (20), por lo que un diario vacío no gira. Cuenta trabajo — vertido, desechado, arreglado, redactado — nunca lanzamientos. La salida de cada pista se mantiene en _still/tend.log. Y escribe un latido que kura doctor lee (tending.alive), porque un vigilante que muere en silencio es el único fallo que un vigilante no debe tener.

Cuando el diario cambia, una pista en ejecución se detiene: el editor suele ser la misma GPU con la que usted está a punto de hablar. Con el editor en un asiento separado — un modelo de CPU, otra máquina — establezca yield_on_return = false bajo [distill] y un veredicto en vuelo se deja terminar. Este es el vigilante con el que la casa ejecutó su editor de CPU durante cinco días, reconstruido con las lecciones que enseñó; docs/OPERATING.md tiene la unidad systemd.

Lo que este proyecto no incluye: un bucle de investigación autónomo que lea artículos y haga crecer el almacén por sí mismo. La casa tiene uno; necesita un modelo que pueda dejarse solo durante una hora por pregunta, y sus resultados no son evidencia en el sentido que la puerta usa. Se mantiene en el lado de la casa de la línea.


Cómo se ve una memoria

Un archivo, un hecho.

---
name: archive-on-slow-disk
description: the archive lives on the slow disk; the fast one stays scratch
metadata:
  type: project          # user | feedback | project | reference
  tags: ["decision", "landmine"]
  evidence_manifest: sha256:…
belongs_because: this store keeps how the machine is laid out and why
keep: which disk, and the reason
may_fade: the df figures from that afternoon
---

The archive goes on the slow disk. The fast disk is scratch space.

**Why:** the other way round burns write endurance for nothing.
**How to apply:** check which disk a target directory is on before writing there.
Related: [[disk-layout]]

Y una línea en MEMORY.md:

- [Archive on the slow disk](archive-on-slow-disk.md) — the archive lives on the slow disk; the fast one stays scratch

Esa línea es lo único que se lee cada vez. Es un disparador de reconocimiento, no un resumen: nombres propios, números, ⚠️ minas terrestres, la conclusión alcanzada. Si una línea pudiera intercambiarse con la línea de otra memoria y aún así leerse bien, no está haciendo su trabajo — kura distill tidy encuentra los casos mecánicamente detectables y los reescribe.

Las cuatro líneas bajo metadata/en la parte superior son curaduría, no hechos: tags son palabras sobre el carácter de la memoria — varias es normal, y una memoria escrita antes de que existieran simplemente no tiene ninguna — y las tres oraciones dicen por qué pertenece en este almacén, qué significado debe sobrevivir a cualquier adelgazamiento posterior, y qué detalle no necesita. El destilador las propone contra la carta del almacén; las etiquetas que afirman algo sobre el humano (entrusted, emotion-carried, recurred) se verifican contra las citas y la verificación se registra en el manifiesto. recurred se escribe una vez, por el destilador, cuando el humano vuelve a mencionar un tema desde otra sesión — es una propiedad, no un contador, y no hay número detrás.

kura doctor informa conteos, enlaces muertos, islas (memorias a las que nada enlaza), deriva del índice, líneas de etiqueta que no puede leer, manifiestos a los que una memoria apunta que ya no existen, el estado del perfil aprendido, y la capacidad del almacén en cuatro unidades lado a lado — memorias, tokens de índice, tokens de cuerpo, bytes — con limit y pressure dejados None. Es el ojo que el metabolismo necesita. Lo que sucede cuando un estante está lleno no está decidido aún: consulte docs/DESIGN.md §8.


La superficie HTTP

ruta

qué hace

POST /recall

{question, hops, top, chars, total_chars, store|mode} → seleccionado, recorrido, contexto. chars es por memoria; total_chars es un límite duro en todo el contexto

POST /remember

{slug, description, body, type, title, tags, belongs_because, keep, may_fade} — una escritura DIRECTA, rechazada a menos que write_policy = "direct-allowed"

POST /annotate

{slug, tags, belongs_because, keep, may_fade} — fusiona etiquetas / las tres oraciones en una memoria existente. La puerta directa: mismo rechazo que /remember. Una fusión que no agrega nada no toca nada

GET /index

el índice crudo

GET /prefill

el bloque residente, listo para inyectar (&format=text para un gancho)

GET /memory/<slug>

una memoria completa, con sus tags y annotations

GET /doctor

salud de un almacén (?all=1 para cada almacén)

GET /stores

almacenes, modos, y qué modelo llena cada rol

GET /profile

la carta del almacén, el perfil aprendido con su estado (ausente / presente / roto), y un puntero a su persona (nunca renderizado aquí)

GET /health

vivacidad

Cualquier ruta acepta ?store= / ?mode=, un campo store/mode en el cuerpo, o el prefijo de ruta /s/<name>/…. Sin autenticación: enlace a loopback, o ponga algo delante.


Notas de diseño que vale la pena leer antes de cambiar cosas

  • docs/DESIGN.md — por qué el reconocimiento supera a la búsqueda, qué compra la puerta, y el fallo que motivó cada mecanismo.

  • docs/OPERATING.md — ejecutarlo residente, programadores y códigos de salida, copias de seguridad, qué vigilar.

  • docs/TRUST.md — qué es y qué no es un límite de almacén, políticas de escritura, y los dos límites que son fáciles de pasar por alto (diarios compartidos, modelos compartidos). Léalo antes de que un almacén privado entre.

Algunas decisiones que parecen extrañas hasta que se topa con lo que previenen:

  • Reservar antes de beber. El destilador reclama un tramo de diario antes de leerlo, bajo un candado, y las marcas de agua solo avanzan. Dos destiladores cada uno escribiendo su propia instantánea borraron el progreso del otro y re-bebieron la misma agua una docena de veces.

  • Las marcas de agua son unidades por adaptador. Desplazamientos de bytes para transcripciones de solo anexo, números de secuencia para archivos que se reescriben (un desplazamiento de bytes en un archivo re-comprimido es una mentira).

  • Supresión de eco. Una cita que ya existe en el almacén no es material nuevo — es el almacén leyéndose a sí mismo a través de un resultado de herramienta. Sin esto, un sistema de memoria redescubre y re-registra sus propios contenidos para siempre.

  • La última puerta es un modelo, no un humano. Si una persona debe aprobar cada borrador, el sistema ha convertido silenciosamente a esa persona en su cuello de botella, y los borradores se acumulan para siempre. Nada en el bucle puede requerir a alguien que no esté siempre presente.

  • kura distill run sale con código 2 cuando no había nada que hacer. Un programador debe poder distinguir "hizo trabajo" de "no encontró nada", o un perro guardián gira en una cola vacía y mata de hambre los pasos que necesitan el tiempo de inactividad.

Medirlo, en lugar de afirmarlo

Dos preguntas se responden con un número y no deberían.

¿Cuánto más pequeño? store_ratio = tokens en las memorias e índice / tokens del diario crudo realmente consumido. ¿Qué se perdió? Esa es una medición diferente, y un almacén que conserva una memoria de cada cien obtiene una puntuación hermosa en la primera mientras es inútil.

kura bench compress                       # what this store cost, from the distiller's own metrics
kura bench compress --tokenizer-command "./count-tokens"   # exact, not estimated
kura bench retention --questions bench/fixtures/questions.json

Medido aquí, con los fixtures incluidos y el estimador integrado:

corpus

store_ratio

scripts/demo-clean-room.sh (charla ordinaria, mayormente relleno)

0.18

bench/fixtures/corpus.jsonl (denso: cada línea es señal)

1.14

El segundo no es un error. En material donde no hay relleno, destilar no comprime — cada memoria añade su por qué y cómo aplicarla, y el almacén sale ligeramente más grande que la transcripción. La proporción es una propiedad del corpus, no de esta herramienta, por eso no hay un número destacado aquí y por eso el comando informa con qué contó.

La retención se puntúa sin modelo: cada hecho plantado lleva un marcador que debe aparecer en lo que devuelve la recuperación, por lo que la puntuación es reproducible en la máquina de otro. Los distractores invierten — un hecho marcado con must_not_store cuesta un punto si el almacén lo conservó, porque un sistema de memoria se juzga tanto por lo que rechaza como por lo que conserva.

score 1.0 (10/10)   decision 1/1  number 2/2  negation 1/1  reversal 1/1
                    conditional 1/1  landmine 1/1  returning 1/1  distractor 2/2

Eso son diez hechos plantados en un dispositivo de prueba sintético, destilados por un Qwen3.8-27B local (NVFP4) como cerebro y escriba con max_items = 8, coverage_passes = 2, y puntuados con el mismo modelo como pensador. Un modelo diferente dará una puntuación diferente: la puntuación mide un canalización-más-modelo, y el dispositivo de prueba existe para que el modelo sea lo único que varíe. Mide si un hecho es localizable, no si la respuesta se lee bien — juzgar la prosa necesita un modelo, y entonces el punto de referencia deja de ser reproducible.

kura distill run escribe una línea por lote en _still/metrics.jsonl, que es de donde proviene el lado bruto. El lado canónico cuenta solo memorias cuya evidencia manifiesta apunta a un lote registrado — dividir un almacén completo por el material bruto de unos pocos lotes es un número en la dirección equivocada por un orden de magnitud, y la primera versión de este comando hizo exactamente eso. Las memorias que preceden a los manifiestos se informan como unattributed, no se incluyen silenciosamente. El lado bruto es siempre la estimación del destilador en el momento de la bebida, así que con --tokenizer-command la proporción se etiqueta como mixed.

Contra qué se ejecuta esto

requisito

Python

3.11+ (sin dependencias; pip install -e ".[dev]" solo añade pytest)

Node

20+, solo para el plugin DSH

zstd

solo para leer archivos de sesión DSH

endpoint de modelo

cualquier cosa que responda a POST <url>/chat/completions con la forma de OpenAI

"Compatible con OpenAI" es más estricto que "cualquier proveedor". La API nativa de un proveedor necesita una puerta de enlace compatible con OpenAI delante; su propia URL no basta. Un servicio estricto también rechaza campos de nivel superior desconocidos, así que establece dialect = "openai" (o "generic") — el "vllm" predeterminado envía chat_template_kwargs, que los servidores locales quieren y uno estricto responde con 400. El cliente reintenta una vez con un cuerpo simple y registra por qué una llamada falló en lugar de colapsar cada causa en un None silencioso.

Pruebas

python3 -m pytest tests -q                              # 145 tests, no model required
cd dsh-plugin && npm test                               # 24 more for the plugin

La puerta se prueba de forma adversarial: cada caso es una forma en que un modelo real intentó colar algo. test_containment.py está escrito de la misma manera — cada caso es un intento de escape, no un camino feliz — porque protege un agujero que era real: un almacén solía responder por cualquier archivo cuya ruta pudieras deletrear. La prueba de extremo a extremo ejecuta un ciclo completo de destilación→drenaje contra un servidor de modelos con guion en un socket real.

Licencia

MIT.

Install Server
A
license - permissive license
A
quality
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides AI agents with persistent, searchable memory that survives across conversations using semantic search, temporal versioning, and smart organization. Enables long-term context retention and cross-session continuity for AI assistants.
    14
  • A
    license
    A
    quality
    D
    maintenance
    Provides persistent long-term memory for AI agents through semantic search and automated knowledge graph extraction. It enables agents to store, recall, and reason over facts, preferences, and relationships across multiple conversations and sessions.
    14
    8
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    An agentic memory system that enables AI assistants to store, search, and manage persistent memories with semantic understanding using natural language instructions.
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to store, search, and recall semantic memories with three memory types (semantic, episodic, procedural) and auto-consolidation, compounding intelligence over time.
    16
    MIT

View all related MCP servers

Related MCP Connectors

  • Persistent memory for AI agents — verbatim conversations, searchable by meaning.

  • Persistent memory and knowledge management for AI agents with semantic search and 50+ tools.

  • Persistent memory and knowledge graphs for AI agents. Hybrid search, context checkpoints, and more.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lna-lab/distill-kura'

If you have feedback or need assistance with the MCP directory API, please join our Discord server