or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

agents.mdchat-models.mdhub.mdindex.mdmiddleware.mdstorage.mdtools.md
tile.json

storage.mddocs/

Storage

Persistent storage implementations for key-value data.

BaseStore Interface

interface BaseStore<K, V> {
  mget(keys: K[]): Promise<(V | undefined)[]>;
  mset(keyValuePairs: [K, V][]): Promise<void>;
  mdelete(keys: K[]): Promise<void>;
  yieldKeys(prefix?: string): AsyncGenerator<K>;
}

InMemoryStore

In-memory key-value store (re-exported from @langchain/core/stores).

class InMemoryStore<T = any> implements BaseStore<string, T> {
  constructor();
  mget(keys: string[]): Promise<(T | undefined)[]>;
  mset(keyValuePairs: [string, T][]): Promise<void>;
  mdelete(keys: string[]): Promise<void>;
  yieldKeys(prefix?: string): AsyncGenerator<string>;
}

Examples:

import { InMemoryStore } from "langchain";

const store = new InMemoryStore<any>();

// Store values
await store.mset([
  ["user:1", { name: "Alice", age: 30 }],
  ["user:2", { name: "Bob", age: 25 }],
  ["config:theme", "dark"],
]);

// Retrieve
const [user1, theme] = await store.mget(["user:1", "config:theme"]);

// List keys
for await (const key of store.yieldKeys("user:")) {
  console.log(key);
}

// Delete
await store.mdelete(["user:1"]);

// Use with agent
import { createAgent } from "langchain";

const sessionStore = new InMemoryStore();
const agent = createAgent({
  model: "openai:gpt-4o",
  tools: [searchTool],
  store: sessionStore,
});

LocalFileStore

File system implementation (Node.js only). Available via langchain/storage/file_system.

class LocalFileStore implements BaseStore<string, Uint8Array> {
  constructor(config: { rootPath: string });
  mget(keys: string[]): Promise<(Uint8Array | undefined)[]>;
  mset(keyValuePairs: [string, Uint8Array][]): Promise<void>;
  mdelete(keys: string[]): Promise<void>;
  yieldKeys(prefix?: string): AsyncGenerator<string>;
}

Examples:

import { LocalFileStore } from "langchain/storage/file_system";

const store = new LocalFileStore({ rootPath: "./my-data" });

// Store text
const textEncoder = new TextEncoder();
await store.mset([
  ["greeting", textEncoder.encode("Hello!")],
]);

// Retrieve text
const textDecoder = new TextDecoder();
const [greeting] = await store.mget(["greeting"]);
if (greeting) {
  console.log(textDecoder.decode(greeting));
}

// Store binary
const binaryData = new Uint8Array([1, 2, 3, 4, 5]);
await store.mset([["binary-key", binaryData]]);

// List keys
for await (const key of store.yieldKeys()) {
  console.log(key);
}

// Use with agent
const memoryStore = new LocalFileStore({ rootPath: "./agent-memory" });
const agent = createAgent({
  model: "openai:gpt-4o",
  tools: [searchTool],
  store: memoryStore,
});

EncoderBackedStore

Store with encoding/decoding abstraction. Available via langchain/storage/encoder_backed.

class EncoderBackedStore<K, V, SerializedType = any> implements BaseStore<K, V> {
  constructor(config: {
    store: BaseStore<K, SerializedType>;
    keyEncoder: (key: K) => string;
    valueSerializer: (value: V) => SerializedType;
    valueDeserializer: (value: SerializedType) => V;
  });

  mget(keys: K[]): Promise<(V | undefined)[]>;
  mset(keyValuePairs: [K, V][]): Promise<void>;
  mdelete(keys: K[]): Promise<void>;
  yieldKeys(prefix?: string): AsyncGenerator<K>;
}

Examples:

import { EncoderBackedStore } from "langchain/storage/encoder_backed";
import { LocalFileStore } from "langchain/storage/file_system";

const fileStore = new LocalFileStore({ rootPath: "./data" });

// JSON encoding
const jsonStore = new EncoderBackedStore({
  store: fileStore,
  keyEncoder: (key) => key,
  valueSerializer: (value) => new TextEncoder().encode(JSON.stringify(value)),
  valueDeserializer: (value) => JSON.parse(new TextDecoder().decode(value)),
});

await jsonStore.mset([
  ["user:1", { name: "Alice", age: 30 }],
]);

const [user1] = await jsonStore.mget(["user:1"]);
console.log(user1);

// Compressed storage
import { gzip, gunzip } from "zlib";
import { promisify } from "util";

const gzipAsync = promisify(gzip);
const gunzipAsync = promisify(gunzip);

const compressedStore = new EncoderBackedStore({
  store: fileStore,
  keyEncoder: (key) => key,
  valueSerializer: async (value) => {
    const json = JSON.stringify(value);
    return await gzipAsync(Buffer.from(json));
  },
  valueDeserializer: async (value) => {
    const decompressed = await gunzipAsync(value);
    return JSON.parse(decompressed.toString());
  },
});

createDocumentStoreFromByteStore

Helper to create document store from byte store.

function createDocumentStoreFromByteStore(
  store: BaseStore<string, Uint8Array>
): EncoderBackedStore<string, Document, Uint8Array>;

Example:

import { createDocumentStoreFromByteStore } from "langchain/storage/encoder_backed";
import { LocalFileStore } from "langchain/storage/file_system";
import { Document } from "langchain";

const fileStore = new LocalFileStore({ rootPath: "./documents" });
const docStore = createDocumentStoreFromByteStore(fileStore);

const doc = new Document({
  pageContent: "This is document 1",
  metadata: { source: "file1.txt", timestamp: Date.now() },
});

await docStore.mset([["doc:1", doc]]);

const [retrieved] = await docStore.mget(["doc:1"]);
console.log(retrieved.pageContent);
console.log(retrieved.metadata);

Common Patterns

Namespacing:

const store = new InMemoryStore();

// Use prefixes
await store.mset([
  ["user:123:profile", userData],
  ["user:123:settings", userSettings],
  ["session:abc:data", sessionData],
]);

// Retrieve by namespace
for await (const key of store.yieldKeys("user:123:")) {
  const [value] = await store.mget([key]);
  console.log(key, value);
}

Hot/Cold Storage:

class CompositeStore {
  constructor(
    private hot: InMemoryStore,
    private cold: LocalFileStore
  ) {}

  async mget(keys: string[]) {
    const hotResults = await this.hot.mget(keys);
    const missingKeys = keys.filter((_, i) => !hotResults[i]);

    if (missingKeys.length > 0) {
      const coldResults = await this.cold.mget(missingKeys);
      const toCache = missingKeys
        .map((key, i) => [key, coldResults[i]] as [string, any])
        .filter(([, value]) => value !== undefined);
      await this.hot.mset(toCache);
    }

    return hotResults.map((value, i) =>
      value ?? (await this.cold.mget([keys[i]]))[0]
    );
  }

  async mset(pairs: [string, any][]) {
    await Promise.all([
      this.hot.mset(pairs),
      this.cold.mset(pairs),
    ]);
  }
}

Cache Pattern:

const cache = new InMemoryStore<string>();

async function getCachedData(key: string): Promise<string> {
  const [cached] = await cache.mget([key]);
  if (cached) return cached;

  const data = await fetchExpensiveData(key);
  await cache.mset([[key, data]]);
  return data;
}