Saltar al contenido principal

Observations

Una observation es el átomo de memoria en iLAB Memory. Cada hecho, preferencia, decisión, bugfix o pattern que persistís es una observation. Las session agrupan observations; los topic_key las hacen evolucionar; el scoring las rankea. Pero la observation es el ladrillo indivisible.

Anatomía

Cada observation tiene estos campos (el modelo Pydantic Observation):

CampoTipoNotas
idintAsignado por el store al insertar (None para drafts).
session_idstrLa sesión de la última actualización material (Braess #4).
user_idstrScope de propiedad. Toda lectura/escritura es por usuario.
typestrUno de los types permitidos — ver abajo.
titlestrCorto, legible para humanos.
contentstrEl cuerpo completo. Las regiones <private> se strippean antes de persistir.
topic_keystr | NoneKey opcional estable para upserts (ver Topic keys).
normalized_hashstr | NoneSHA-256 del content post-strip. Interno.
revision_countintSe incrementa en cada UPDATE (default 1).
created_at, updated_atstrISO 8601, UTC, con timezone.
nota

created_at se setea en el primer INSERT y nunca cambia. updated_at se refresca en cada UPDATE — eso alimenta el componente recency del scoring.

Los 5 types user-facing

La librería trae un set frozen de tipos de observation. v0.1.0 no soporta agregar tipos en runtime con la config default; te suscribís pasando Config(observation_types=(...)).

profile

Datos estables del usuario: nombre, rol, atributos. Máxima prioridad en ContextScore (1.0).

preference

Preferencias explícitas: "prefiere TypeScript sobre JavaScript", "responde en español". Prioridad 0.9.

decision

Decisiones arquitectónicas o de diseño tomadas durante la conversación. Prioridad 0.7.

discovery

Bugfixes, gotchas, edge cases aprendidos a la mala. Prioridad 0.5.

pattern

Convenciones de naming, estructura o estilo. Prioridad 0.6.

aviso

summary es un type reservado que usa internamente mem_session_summary y el path de auto-close. Llamar mem_save(type="summary", ...) levanta ValueError. Usá mem_session_summary(...) en su lugar.

Compact vs full vs public

iLAB Memory expone tres variantes del mismo registro. Es a propósito — diferentes superficies tienen diferentes restricciones de costo y de leak.

VarianteUsado porIncluyeExcluye
ObservationCallers de la librería (lectura completa)Todo
ObservationCompactmem_search, memories[] en mem_session_startid, type, title, topic_key, score, snippet, updated_atcontent, normalized_hash
ObservationPublicResponses de la API HTTPTodo lo visiblenormalized_hash (interno)
tip

Progressive disclosure: las listas devuelven ObservationCompact (~100 tokens). Cuando necesites el cuerpo, hidratá una observation por vez con mem_get_observation(observation_id).

Save, search, hidratación

from ilab_memory import ILabMemory

mem = ILabMemory.from_path("./mem.db")

result = mem.mem_save(
user_id="alice",
type="preference",
title="Saludo preferido",
content="Alice prefiere que la saluden como 'Ali'.",
topic_key="user/alice/greeting",
)

print(result.id, result.outcome) # ej. 1 'created'

Outcomes

mem_save siempre devuelve un SaveResult con uno de tres outcomes:

created

Se insertó una fila nueva. El id queda asignado. revision_count arranca en 1.

updated

Una fila existente matcheó (mismo topic_key, content distinto). La fila se actualizó in-place: revision_count incrementado, updated_at refrescado, created_at preservado, session_id sobreescrito con la sesión actual (Braess #4).

deduped

Una fila existente matcheó y el hash del content post-strip es idéntico. No hubo write. Se devuelve el id existente. La sesión igual se toca (D8: mem_save siempre extiende la vida de la sesión activa).

Seguridad cross-user

Cada lectura aplica el scope por user_id en el orchestrator. mem_get_observation(user_id="bob", observation_id=alice_obs_id) devuelve None — nunca levanta excepción, nunca filtra la existencia del dato del otro usuario.

Siguiente

  • Sessions — el contenedor que agrupa observations.
  • Topic keys — cómo hacer que las observations evolucionen en lugar de duplicarse.
  • Scoring — por qué compact.score se ve como se ve.