Xata Chat Memory
Xata is a serverless data platform, based on PostgreSQL. It provides a type-safe TypeScript/JavaScript SDK for interacting with your database, and a UI for managing your data.
With the XataChatMessageHistory
class, you can use Xata databases for longer-term persistence of chat sessions.
Because Xata works via a REST API and has a pure TypeScript SDK, you can use this with Vercel Edge, Cloudflare Workers and any other Serverless environment.
Setupβ
Install the Xata CLIβ
npm install @xata.io/cli -g
Create a database to be used as a vector storeβ
In the Xata UI create a new database. You can name it whatever you want, but for this example we'll use langchain
.
When executed for the first time, the Xata LangChain integration will create the table used for storing the chat messages. If a table with that name already exists, it will be left untouched.
Initialize the projectβ
In your project, run:
xata init
and then choose the database you created above. This will also generate a xata.ts
or xata.js
file that defines the client you can use to interact with the database. See the Xata getting started docs for more details on using the Xata JavaScript/TypeScript SDK.
Usageβ
Each chat history session stored in Xata database must have a unique id.
In this example, the getXataClient()
function is used to create a new Xata client based on the environment variables. However, we recommend using the code generated by the xata init
command, in which case you only need to import the getXataClient()
function from the generated xata.ts
file.
- npm
- Yarn
- pnpm
npm install @langchain/openai @langchain/community @langchain/core
yarn add @langchain/openai @langchain/community @langchain/core
pnpm add @langchain/openai @langchain/community @langchain/core
import { BufferMemory } from "langchain/memory";
import { ChatOpenAI } from "@langchain/openai";
import { ConversationChain } from "langchain/chains";
import { XataChatMessageHistory } from "@langchain/community/stores/message/xata";
import { BaseClient } from "@xata.io/client";
// if you use the generated client, you don't need this function.
// Just import getXataClient from the generated xata.ts instead.
const getXataClient = () => {
if (!process.env.XATA_API_KEY) {
throw new Error("XATA_API_KEY not set");
}
if (!process.env.XATA_DB_URL) {
throw new Error("XATA_DB_URL not set");
}
const xata = new BaseClient({
databaseURL: process.env.XATA_DB_URL,
apiKey: process.env.XATA_API_KEY,
branch: process.env.XATA_BRANCH || "main",
});
return xata;
};
const memory = new BufferMemory({
chatHistory: new XataChatMessageHistory({
table: "messages",
sessionId: new Date().toISOString(), // Or some other unique identifier for the conversation
client: getXataClient(),
apiKey: process.env.XATA_API_KEY, // The API key is needed for creating the table.
}),
});
const model = new ChatOpenAI();
const chain = new ConversationChain({ llm: model, memory });
const res1 = await chain.invoke({ 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.invoke({ input: "What did I just say my name was?" });
console.log({ res2 });
/*
{
res1: {
text: "You said your name was Jim."
}
}
*/
API Reference:
- BufferMemory from
langchain/memory
- ChatOpenAI from
@langchain/openai
- ConversationChain from
langchain/chains
- XataChatMessageHistory from
@langchain/community/stores/message/xata
With pre-created tableβ
If you don't want the code to always check if the table exists, you can create the table manually in the Xata UI and pass createTable: false
to the constructor. The table must have the following columns:
sessionId
of typeString
type
of typeString
role
of typeString
content
of typeText
name
of typeString
additionalKwargs
of typeText
import { BufferMemory } from "langchain/memory";
import { ChatOpenAI } from "@langchain/openai";
import { ConversationChain } from "langchain/chains";
import { XataChatMessageHistory } from "@langchain/community/stores/message/xata";
import { BaseClient } from "@xata.io/client";
// Before running this example, see the docs at
// https://js.langchain.com/docs/modules/memory/integrations/xata
// if you use the generated client, you don't need this function.
// Just import getXataClient from the generated xata.ts instead.
const getXataClient = () => {
if (!process.env.XATA_API_KEY) {
throw new Error("XATA_API_KEY not set");
}
if (!process.env.XATA_DB_URL) {
throw new Error("XATA_DB_URL not set");
}
const xata = new BaseClient({
databaseURL: process.env.XATA_DB_URL,
apiKey: process.env.XATA_API_KEY,
branch: process.env.XATA_BRANCH || "main",
});
return xata;
};
const memory = new BufferMemory({
chatHistory: new XataChatMessageHistory({
table: "messages",
sessionId: new Date().toISOString(), // Or some other unique identifier for the conversation
client: getXataClient(),
createTable: false, // Explicitly set to false if the table is already created
}),
});
const model = new ChatOpenAI();
const chain = new ConversationChain({ llm: model, memory });
const res1 = await chain.invoke({ 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.invoke({ input: "What did I just say my name was?" });
console.log({ res2 });
/*
{
res1: {
text: "You said your name was Jim."
}
}
*/
API Reference:
- BufferMemory from
langchain/memory
- ChatOpenAI from
@langchain/openai
- ConversationChain from
langchain/chains
- XataChatMessageHistory from
@langchain/community/stores/message/xata