agsamantha/node_modules/@langchain/community/dist/stores/message/planetscale.js

169 lines
6.1 KiB
JavaScript
Raw Normal View History

2024-10-02 20:15:21 +00:00
import { Client as PlanetScaleClient, } from "@planetscale/database";
import { BaseListChatMessageHistory } from "@langchain/core/chat_history";
import { mapChatMessagesToStoredMessages, mapStoredMessagesToChatMessages, } from "@langchain/core/messages";
/**
* Class for storing and retrieving chat message history from a
* PlanetScale database. Extends the BaseListChatMessageHistory class.
* @example
* ```typescript
* const chatHistory = new PlanetScaleChatMessageHistory({
* tableName: "stored_message",
* sessionId: "lc-example",
* config: {
* url: "ADD_YOURS_HERE",
* },
* });
* const chain = new ConversationChain({
* llm: new ChatOpenAI(),
* memory: chatHistory,
* });
* const response = await chain.invoke({
* input: "What did I just say my name was?",
* });
* console.log({ response });
* ```
*/
export class PlanetScaleChatMessageHistory extends BaseListChatMessageHistory {
get lc_secrets() {
return {
"config.host": "PLANETSCALE_HOST",
"config.username": "PLANETSCALE_USERNAME",
"config.password": "PLANETSCALE_PASSWORD",
"config.url": "PLANETSCALE_DATABASE_URL",
};
}
constructor(fields) {
super(fields);
Object.defineProperty(this, "lc_namespace", {
enumerable: true,
configurable: true,
writable: true,
value: ["langchain", "stores", "message", "planetscale"]
});
Object.defineProperty(this, "client", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "connection", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "tableName", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "sessionId", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "tableInitialized", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
const { sessionId, config, client, tableName } = fields;
if (client) {
this.client = client;
}
else if (config) {
this.client = new PlanetScaleClient(config);
}
else {
throw new Error("Either a client or config must be provided to PlanetScaleChatMessageHistory");
}
this.connection = this.client.connection();
this.tableName = tableName || "langchain_chat_histories";
this.tableInitialized = false;
this.sessionId = sessionId;
}
/**
* Private method to ensure that the necessary table exists in the
* PlanetScale database before performing any operations. If the table
* does not exist, it is created.
* @returns Promise that resolves to void.
*/
async ensureTable() {
if (this.tableInitialized) {
return;
}
const query = `CREATE TABLE IF NOT EXISTS ${this.tableName} (id BINARY(16) PRIMARY KEY, session_id VARCHAR(255), type VARCHAR(255), content VARCHAR(255), role VARCHAR(255), name VARCHAR(255), additional_kwargs VARCHAR(255));`;
await this.connection.execute(query);
const indexQuery = `ALTER TABLE ${this.tableName} MODIFY id BINARY(16) DEFAULT (UUID_TO_BIN(UUID()));`;
await this.connection.execute(indexQuery);
this.tableInitialized = true;
}
/**
* Method to retrieve all messages from the PlanetScale database for the
* current session.
* @returns Promise that resolves to an array of BaseMessage objects.
*/
async getMessages() {
await this.ensureTable();
const query = `SELECT * FROM ${this.tableName} WHERE session_id = :session_id`;
const params = {
session_id: this.sessionId,
};
const rawStoredMessages = await this.connection.execute(query, params);
const storedMessagesObject = rawStoredMessages.rows;
const orderedMessages = storedMessagesObject.map((message) => {
const data = {
content: message.content,
additional_kwargs: JSON.parse(message.additional_kwargs),
};
if (message.role) {
data.role = message.role;
}
if (message.name) {
data.name = message.name;
}
return {
type: message.type,
data,
};
});
return mapStoredMessagesToChatMessages(orderedMessages);
}
/**
* Method to add a new message to the PlanetScale database for the current
* session.
* @param message The BaseMessage object to be added to the database.
* @returns Promise that resolves to void.
*/
async addMessage(message) {
await this.ensureTable();
const messageToAdd = mapChatMessagesToStoredMessages([message]);
const query = `INSERT INTO ${this.tableName} (session_id, type, content, role, name, additional_kwargs) VALUES (:session_id, :type, :content, :role, :name, :additional_kwargs)`;
const params = {
session_id: this.sessionId,
type: messageToAdd[0].type,
content: messageToAdd[0].data.content,
role: messageToAdd[0].data.role,
name: messageToAdd[0].data.name,
additional_kwargs: JSON.stringify(messageToAdd[0].data.additional_kwargs),
};
await this.connection.execute(query, params);
}
/**
* Method to delete all messages from the PlanetScale database for the
* current session.
* @returns Promise that resolves to void.
*/
async clear() {
await this.ensureTable();
const query = `DELETE FROM ${this.tableName} WHERE session_id = :session_id`;
const params = {
session_id: this.sessionId,
};
await this.connection.execute(query, params);
}
}