Skip to content

Commit

Permalink
feat: add Momento as a standard cache and chat history provider (lang…
Browse files Browse the repository at this point in the history
…chain-ai#1416)

* chore: add .node-version to gitignore

Because I'm Using nodenv with multiple node versions installed, we use
the node local to specify the version to use in a particular repo.

* feat: add @gomomento/sdk as a dev, peer, optional dependency

* feat: add Momento as a standard caching provider

* feat: add Momento as a chat message history store

* chore: add momento to entrypoints

* docs: add examples and docs for Momento

* chore: make fields readonly

We make appropriate fields readonly.

* refactor: use factory method standard naming fromX

* refactor: extract `ensureCacheExists` to utility module

Previously both the Momento cache module and Momento chat history
modules had a `ensureCacheExists` function, which were identical. This
commit extracts the function to a single place in a utility module.

* Docs fixes

---------

Co-authored-by: jacoblee93 <[email protected]>
  • Loading branch information
malandis and jacoblee93 authored May 30, 2023
1 parent b8afb1e commit c5fa479
Show file tree
Hide file tree
Showing 17 changed files with 945 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ Chinook_Sqlite.sql
*.swp
*.swo

.node-version
28 changes: 28 additions & 0 deletions docs/docs/modules/memory/examples/momento.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
hide_table_of_contents: true
---

import CodeBlock from "@theme/CodeBlock";

# Momento-Backed Chat Memory

For distributed, serverless persistence across chat sessions, you can swap in a [Momento](https://gomomento.com/)-backed chat message history.
Because a Momento cache is instantly available and requires zero infrastructure maintenance, it's a great way to get started with chat history whether building locally or in production.

## Setup

You will need to install the [Momento Client Library](https://github.com/momentohq/client-sdk-javascript) in your project:

```bash npm2yarn
npm install @gomomento/sdk
```

You will also need an API key from [Momento](https://gomomento.com/). You can sign up for a free account [here](https://console.gomomento.com/).

## Usage

To distinguish one chat history session from another, we need a unique `sessionId`. You may also provide an optional `sessionTtl` to make sessions expire after a given number of seconds.

import MomentoExample from "@examples/memory/momento.ts";

<CodeBlock language="typescript">{MomentoExample}</CodeBlock>
14 changes: 14 additions & 0 deletions docs/docs/modules/models/llms/additional_functionality.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ import { OpenAI } from "langchain/llms/openai";
const model = new OpenAI({ cache: true });
```

### Caching with Momento

LangChain also provides a Momento-based cache. [Momento](https://gomomento.com) is a distributed, serverless cache that requires zero setup or infrastructure maintenance. To use it, you'll need to install the `@gomomento/sdk` package:

```bash npm2yarn
npm install @gomomento/sdk
```

Next you'll need to sign up and create an API key. Once you've done that, pass a `cache` option when you instantiate the LLM like this:

import MomentoCacheExample from "@examples/cache/momento.ts";

<CodeBlock language="typescript">{MomentoCacheExample}</CodeBlock>

### Caching with Redis

LangChain also provides a Redis-based cache. This is useful if you want to share the cache across multiple processes or servers. To use it, you'll need to install the `redis` package:
Expand Down
1 change: 1 addition & 0 deletions examples/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ TIGRIS_CLIENT_ID=ADD_YOURS_HERE
TIGRIS_CLIENT_SECRET=ADD_YOURS_HERE
NOTION_INTEGRATION_TOKEN=ADD_YOURS_HERE
FIGMA_ACCESS_TOKEN=ADD_YOURS_HERE
MOMENTO_AUTH_TOKEN=ADD_YOURS_HERE
1 change: 1 addition & 0 deletions examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"dependencies": {
"@clickhouse/client": "^0.0.14",
"@getmetal/metal-sdk": "^4.0.0",
"@gomomento/sdk": "^1.23.0",
"@opensearch-project/opensearch": "^2.2.0",
"@pinecone-database/pinecone": "^0.0.14",
"@prisma/client": "^4.11.0",
Expand Down
22 changes: 22 additions & 0 deletions examples/src/cache/momento.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { OpenAI } from "langchain/llms/openai";
import { MomentoCache } from "langchain/cache/momento";
import {
CacheClient,
Configurations,
CredentialProvider,
} from "@gomomento/sdk";

// See https://github.com/momentohq/client-sdk-javascript for connection options
const client = new CacheClient({
configuration: Configurations.Laptop.v1(),
credentialProvider: CredentialProvider.fromEnvironmentVariable({
environmentVariableName: "MOMENTO_AUTH_TOKEN",
}),
defaultTtlSeconds: 60 * 60 * 24,
});
const cache = await MomentoCache.fromProps({
client,
cacheName: "langchain",
});

const model = new OpenAI({ cache });
65 changes: 65 additions & 0 deletions examples/src/memory/momento.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
CacheClient,
Configurations,
CredentialProvider,
} from "@gomomento/sdk";
import { BufferMemory } from "langchain/memory";
import { ChatOpenAI } from "langchain/chat_models/openai";
import { ConversationChain } from "langchain/chains";
import { MomentoChatMessageHistory } from "langchain/stores/message/momento";

// See https://github.com/momentohq/client-sdk-javascript for connection options
const client = new CacheClient({
configuration: Configurations.Laptop.v1(),
credentialProvider: CredentialProvider.fromEnvironmentVariable({
environmentVariableName: "MOMENTO_AUTH_TOKEN",
}),
defaultTtlSeconds: 60 * 60 * 24,
});

// Create a unique session ID
const sessionId = new Date().toISOString();
const cacheName = "langchain";

const memory = new BufferMemory({
chatHistory: await MomentoChatMessageHistory.fromProps({
client,
cacheName,
sessionId,
sessionTtl: 300,
}),
});
console.log(
`cacheName=${cacheName} and sessionId=${sessionId} . This will be used to store the chat history. You can inspect the values at your Momento console at https://console.gomomento.com.`
);

const model = new ChatOpenAI({
modelName: "gpt-3.5-turbo",
temperature: 0,
});

const chain = new ConversationChain({ llm: model, memory });

const res1 = await chain.call({ input: "Hi! I'm Jim." });
console.log({ res1 });
/*
{
res1: {
text: "Hello Jim! It's nice to meet you. My name is AI. How may I assist you today?"
}
}
*/

const res2 = await chain.call({ input: "What did I just say my name was?" });
console.log({ res2 });

/*
{
res1: {
text: "You said your name was Jim."
}
}
*/

// See the chat history in the Momento
console.log(await memory.chatHistory.getMessages());
6 changes: 6 additions & 0 deletions langchain/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ retrievers/self_query.d.ts
cache.cjs
cache.js
cache.d.ts
cache/momento.cjs
cache/momento.js
cache/momento.d.ts
cache/redis.cjs
cache/redis.js
cache/redis.d.ts
Expand All @@ -313,6 +316,9 @@ stores/file/node.d.ts
stores/message/dynamodb.cjs
stores/message/dynamodb.js
stores/message/dynamodb.d.ts
stores/message/momento.cjs
stores/message/momento.js
stores/message/momento.d.ts
stores/message/redis.cjs
stores/message/redis.js
stores/message/redis.d.ts
Expand Down
21 changes: 21 additions & 0 deletions langchain/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,9 @@
"cache.cjs",
"cache.js",
"cache.d.ts",
"cache/momento.cjs",
"cache/momento.js",
"cache/momento.d.ts",
"cache/redis.cjs",
"cache/redis.js",
"cache/redis.d.ts",
Expand All @@ -325,6 +328,9 @@
"stores/message/dynamodb.cjs",
"stores/message/dynamodb.js",
"stores/message/dynamodb.d.ts",
"stores/message/momento.cjs",
"stores/message/momento.js",
"stores/message/momento.d.ts",
"stores/message/redis.cjs",
"stores/message/redis.js",
"stores/message/redis.d.ts",
Expand Down Expand Up @@ -379,6 +385,7 @@
"@clickhouse/client": "^0.0.14",
"@faker-js/faker": "^7.6.0",
"@getmetal/metal-sdk": "^4.0.0",
"@gomomento/sdk": "^1.23.0",
"@huggingface/inference": "^1.5.1",
"@jest/globals": "^29.5.0",
"@opensearch-project/opensearch": "^2.2.0",
Expand Down Expand Up @@ -449,6 +456,7 @@
"@aws-sdk/client-sagemaker-runtime": "^3.310.0",
"@clickhouse/client": "^0.0.14",
"@getmetal/metal-sdk": "*",
"@gomomento/sdk": "^1.23.0",
"@huggingface/inference": "^1.5.1",
"@opensearch-project/opensearch": "*",
"@pinecone-database/pinecone": "*",
Expand Down Expand Up @@ -504,6 +512,9 @@
"@getmetal/metal-sdk": {
"optional": true
},
"@gomomento/sdk": {
"optional": true
},
"@huggingface/inference": {
"optional": true
},
Expand Down Expand Up @@ -1168,6 +1179,11 @@
"import": "./cache.js",
"require": "./cache.cjs"
},
"./cache/momento": {
"types": "./cache/momento.d.ts",
"import": "./cache/momento.js",
"require": "./cache/momento.cjs"
},
"./cache/redis": {
"types": "./cache/redis.d.ts",
"import": "./cache/redis.js",
Expand All @@ -1188,6 +1204,11 @@
"import": "./stores/message/dynamodb.js",
"require": "./stores/message/dynamodb.cjs"
},
"./stores/message/momento": {
"types": "./stores/message/momento.d.ts",
"import": "./stores/message/momento.js",
"require": "./stores/message/momento.cjs"
},
"./stores/message/redis": {
"types": "./stores/message/redis.d.ts",
"import": "./stores/message/redis.js",
Expand Down
4 changes: 4 additions & 0 deletions langchain/scripts/create-entrypoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,13 @@ const entrypoints = {
"retrievers/self_query": "retrievers/self_query/index",
// cache
cache: "cache/index",
"cache/momento": "cache/momento",
"cache/redis": "cache/redis",
// stores
"stores/file/in_memory": "stores/file/in_memory",
"stores/file/node": "stores/file/node",
"stores/message/dynamodb": "stores/message/dynamodb",
"stores/message/momento": "stores/message/momento",
"stores/message/redis": "stores/message/redis",
"stores/message/upstash_redis": "stores/message/upstash_redis",
// experimental
Expand Down Expand Up @@ -220,9 +222,11 @@ const requiresOptionalDependency = [
"output_parsers/expression",
"chains/query_constructor",
"chains/query_constructor/ir",
"cache/momento",
"cache/redis",
"stores/file/node",
"stores/message/dynamodb",
"stores/message/momento",
"stores/message/redis",
"stores/message/upstash_redis",
];
Expand Down
Loading

0 comments on commit c5fa479

Please sign in to comment.