Memoria para un agente de IA

TeselaDB

TeselaDB

Equipo de TeselaDB

25 minIntermedio

Guarda lo que un agente aprende de cada usuario con su vector y recupera lo más parecido a la conversación actual.

Un agente que recuerda a cada usuario guarda frases cortas, como una preferencia o un dato de su proyecto, y en cada conversación recupera las que más se parecen a lo que se está hablando. En TeselaDB, esas memorias son documentos con su vector, un índice vectorial con un filtro por usuario y un índice TTL que las olvida pasado un tiempo.

Lo que vas a construir

Una colección memories en la base agent con un índice vectorial filtrado por userId y una consulta que devuelve las dos memorias de un usuario más cercanas a la conversación. Las memorias de más de 90 días se borran solas.

Requisitos

  • mongosh y un usuario con readWrite sobre la base agent.
  • Un modelo de embeddings para tus textos. Los ejemplos usan vectores de tres dimensiones escritos a mano para que veas el resultado exacto; con un modelo real, numDimensions es el tamaño de sus vectores.

1. Guarda las memorias

Cada memoria lleva el usuario, el texto, su vector y la fecha. Dos son de Ana y una de Luis, cuyo vector está cerca de uno de los de Ana, así que después puedes comprobar que la búsqueda de un usuario nunca devuelve las memorias del otro:

JavaScript
db.memories.insertMany([
  { userId: "ana", text: "Prefiere respuestas en español", embedding: [0.9, 0.1, 0.0], createdAt: new Date() },
  { userId: "ana", text: "Trabaja con un clúster de tres nodos", embedding: [0.1, 0.9, 0.1], createdAt: new Date() },
  { userId: "luis", text: "Prefiere respuestas cortas", embedding: [0.8, 0.2, 0.1], createdAt: new Date() },
]);

2. Crea el índice vectorial

El campo userId va como filtro, así que una búsqueda nunca mezcla las memorias de dos usuarios. El bucle espera a que el índice se pueda consultar:

JavaScript
db.memories.createSearchIndex({
  name: "memory",
  type: "vectorSearch",
  definition: {
    fields: [
      { type: "vector", path: "embedding", numDimensions: 3, similarity: "cosine" },
      { type: "filter", path: "userId" },
    ],
  },
});
while (!db.memories.getSearchIndexes("memory")[0]?.queryable) sleep(100);

3. Olvida lo antiguo

Un índice TTL sobre createdAt borra cada memoria 90 días después de guardarla:

JavaScript
db.memories.createIndex({ createdAt: 1 }, { expireAfterSeconds: 60 * 60 * 24 * 90 });

Probarlo

Busca las dos memorias de Ana más cercanas al vector de la conversación, [1, 0, 0] en este ejemplo. Con exact: true la búsqueda compara con todos los vectores y da el mismo resultado en cualquier réplica. El filtro la deja dentro de las memorias de Ana:

JavaScript
db.memories.aggregate([
  {
    $vectorSearch: {
      index: "memory",
      path: "embedding",
      queryVector: [1, 0, 0],
      exact: true,
      limit: 2,
      filter: { userId: "ana" },
    },
  },
  { $project: { _id: 0, text: 1 } },
]);
[
  { text: 'Prefiere respuestas en español' },
  { text: 'Trabaja con un clúster de tres nodos' }
]

Las memorias de Luis no aparecen aunque su vector esté cerca, porque el filtro deja fuera a los demás usuarios. Si tu agente usa MCP, la herramienta aggregate del servidor MCP lanza esta misma consulta.

Limpiar

JavaScript
db.memories.drop();

Al borrar la colección de prueba se borran también sus dos índices, el vectorial y el TTL.

Siguientes pasos