Skip to main content

Stores

Storing data in key value format is quick and efficient, and can be a powerful tool for LLM applications. The BaseStore class provides a simple interface for getting, setting, deleting and iterating over lists of key value pairs.

The public API of BaseStore in LangChain JS offers four main methods:

abstract mget(keys: K[]): Promise<(V | undefined)[]>;

abstract mset(keyValuePairs: [K, V][]): Promise<void>;

abstract mdelete(keys: K[]): Promise<void>;

abstract yieldKeys(prefix?: string): AsyncGenerator<K | string>;

The m prefix stands for multiple, and indicates that these methods can be used to get, set and delete multiple key value pairs at once. The yieldKeys method is a generator function that can be used to iterate over all keys in the store, or all keys with a given prefix.

It's that simple!

So far LangChain.js has two base integrations for BaseStore:

Use Cases

Chat history

If you're building web apps with chat, the BaseStore family of integrations can come in very handy for storing and retrieving chat history.

Caching

The BaseStore family can be a useful alternative to our other caching integrations. For example the LocalFileStore allows for persisting data through the file system. It also is incredibly fast, so your users will be able to access cached data in a snap.

See the individual sections for deeper dives on specific storage providers.

Reading Data

In Memory

Reading data is simple with KV stores. Below is an example using the InMemoryStore and the .mget() method. We'll also set our generic value type to string so we can have type safety setting our strings.

Import the InMemoryStore class.

import { InMemoryStore } from "langchain/storage/in_memory";

Instantiate a new instance and pass string as our generic for the value type.

const store = new InMemoryStore<string>();

Next we can call .mset() to write multiple values at once.

const data: [string, string][] = [
["key1", "value1"],
["key2", "value2"],
];

await store.mset(data);

Finally, call the .mget() method to retrieve the values from our store.

const data = await store.mget(["key1", "key2"]);

console.log(data);
/**
* ["value1", "value2"]
*/

File System

When using the file system integration we need to instantiate via the fromPath method. This is required because it needs to preform checks to ensure the directory exists and is readable/writable. You also must use a directory when using LocalFileStore because each entry is stored as a unique file in the directory.

import { LocalFileStore } from "langchain/storage/file_system";
const pathToStore = "./my-store-directory";
const store = await LocalFileStore.fromPath(pathToStore);

To do this we can define an encoder for initially setting our data, and a decoder for when we retrieve data.

const encoder = new TextEncoder();
const decoder = new TextDecoder();
const data: [string, Uint8Array][] = [
["key1", encoder.encode(new Date().toDateString())],
["key2", encoder.encode(new Date().toDateString())],
];

await store.mset(data);
const data = await store.mget(["key1", "key2"]);

console.log(data.map((v) => decoder.decode(v)));
/**
* [ 'Wed Jan 03 2024', 'Wed Jan 03 2024' ]
*/

Writing Data

In Memory

Writing data is simple with KV stores. Below is an example using the InMemoryStore and the .mset() method. We'll also set our generic value type to Date so we can have type safety setting our dates.

Import the InMemoryStore class.

import { InMemoryStore } from "langchain/storage/in_memory";

Instantiate a new instance and pass Date as our generic for the value type.

const store = new InMemoryStore<Date>();

Finally we can call .mset() to write multiple values at once.

const data: [string, Date][] = [
["date1", new Date()],
["date2", new Date()],
];

await store.mset(data);

File System

When using the file system integration we need to instantiate via the fromPath method. This is required because it needs to preform checks to ensure the directory exists and is readable/writable. You also must use a directory when using LocalFileStore because each entry is stored as a unique file in the directory.

import { LocalFileStore } from "langchain/storage/file_system";
const pathToStore = "./my-store-directory";
const store = await LocalFileStore.fromPath(pathToStore);

When defining our data we must convert the values to Uint8Array because the file system integration only supports binary data.

To do this we can define an encoder for initially setting our data, and a decoder for when we retrieve data.

const encoder = new TextEncoder();
const decoder = new TextDecoder();
const data: [string, Uint8Array][] = [
["key1", encoder.encode(new Date().toDateString())],
["key2", encoder.encode(new Date().toDateString())],
];

await store.mset(data);

Help us out by providing feedback on this documentation page: