UNPKG

@langchain/community

Version:
1 lines • 9.78 kB
{"version":3,"file":"xata.cjs","names":["chatMemoryColumns: Schemas.Column[]","BaseListChatMessageHistory","fields: XataChatMessageHistoryInput<XataClient>","BaseClient","XataApiClient","orderedMessages: StoredMessage[]","message: storedMessagesDTO","message: BaseMessage","schema: GetTableSchemaResponse | null"],"sources":["../../../src/stores/message/xata.ts"],"sourcesContent":["import {\n BaseClient,\n BaseClientOptions,\n GetTableSchemaResponse,\n Schemas,\n XataApiClient,\n parseWorkspacesUrlParts,\n} from \"@xata.io/client\";\nimport { BaseListChatMessageHistory } from \"@langchain/core/chat_history\";\nimport {\n BaseMessage,\n StoredMessage,\n StoredMessageData,\n mapChatMessagesToStoredMessages,\n mapStoredMessagesToChatMessages,\n} from \"@langchain/core/messages\";\n\n/**\n * An object type that represents the input for the XataChatMessageHistory\n * class.\n */\nexport type XataChatMessageHistoryInput<XataClient> = {\n sessionId: string;\n config?: BaseClientOptions;\n client?: XataClient;\n table?: string;\n createTable?: boolean;\n apiKey?: string;\n};\n\n/**\n * An interface that represents the data transfer object for stored\n * messages.\n */\ninterface storedMessagesDTO {\n id: string;\n sessionId: string;\n type: string;\n content: string;\n role?: string;\n name?: string;\n additionalKwargs: string;\n}\n\nconst chatMemoryColumns: Schemas.Column[] = [\n { name: \"sessionId\", type: \"string\" },\n { name: \"type\", type: \"string\" },\n { name: \"role\", type: \"string\" },\n { name: \"content\", type: \"text\" },\n { name: \"name\", type: \"string\" },\n { name: \"additionalKwargs\", type: \"text\" },\n];\n\n/**\n * A class for managing chat message history using Xata.io client. It\n * extends the BaseListChatMessageHistory class and provides methods to\n * get, add, and clear messages. It also ensures the existence of a table\n * where the chat messages are stored.\n * @example\n * ```typescript\n * const chatHistory = new XataChatMessageHistory({\n * table: \"messages\",\n * sessionId: new Date().toISOString(),\n * client: new BaseClient({\n * databaseURL: process.env.XATA_DB_URL,\n * apiKey: process.env.XATA_API_KEY,\n * branch: \"main\",\n * }),\n * apiKey: process.env.XATA_API_KEY,\n * });\n *\n * const chain = new ConversationChain({\n * llm: new ChatOpenAI({ model: \"gpt-4o-mini\" }),\n * memory: new BufferMemory({ chatHistory }),\n * });\n *\n * const response = await chain.invoke({\n * input: \"What did I just say my name was?\",\n * });\n * console.log({ response });\n * ```\n */\nexport class XataChatMessageHistory<\n XataClient extends BaseClient,\n> extends BaseListChatMessageHistory {\n lc_namespace = [\"langchain\", \"stores\", \"message\", \"xata\"];\n\n public client: XataClient;\n\n private sessionId: string;\n\n private table: string;\n\n private tableInitialized: boolean;\n\n private createTable: boolean;\n\n private apiClient: XataApiClient;\n\n constructor(fields: XataChatMessageHistoryInput<XataClient>) {\n super(fields);\n\n const { sessionId, config, client, table } = fields;\n this.sessionId = sessionId;\n this.table = table || \"memory\";\n if (client) {\n this.client = client;\n } else if (config) {\n this.client = new BaseClient(config) as XataClient;\n } else {\n throw new Error(\n \"Either a client or a config must be provided to XataChatMessageHistoryInput\"\n );\n }\n if (fields.createTable !== false) {\n this.createTable = true;\n const apiKey = fields.apiKey || fields.config?.apiKey;\n if (!apiKey) {\n throw new Error(\n \"If createTable is set, an apiKey must be provided to XataChatMessageHistoryInput, either directly or through the config object\"\n );\n }\n this.apiClient = new XataApiClient({ apiKey });\n } else {\n this.createTable = false;\n }\n this.tableInitialized = false;\n }\n\n /**\n * Retrieves all messages associated with the session ID, ordered by\n * creation time.\n * @returns A promise that resolves to an array of BaseMessage instances.\n */\n async getMessages(): Promise<BaseMessage[]> {\n await this.ensureTable();\n const records = await this.client.db[this.table]\n .filter({ sessionId: this.sessionId })\n .sort(\"xata.createdAt\", \"asc\")\n .getAll();\n\n const rawStoredMessages = records as unknown as storedMessagesDTO[];\n const orderedMessages: StoredMessage[] = rawStoredMessages.map(\n (message: storedMessagesDTO) => {\n const data = {\n content: message.content,\n additional_kwargs: JSON.parse(message.additionalKwargs),\n } as StoredMessageData;\n if (message.role) {\n data.role = message.role;\n }\n if (message.name) {\n data.name = message.name;\n }\n\n return {\n type: message.type,\n data,\n };\n }\n );\n return mapStoredMessagesToChatMessages(orderedMessages);\n }\n\n /**\n * Adds a new message to the database.\n * @param message The BaseMessage instance to be added.\n * @returns A promise that resolves when the message has been added.\n */\n async addMessage(message: BaseMessage): Promise<void> {\n await this.ensureTable();\n const messageToAdd = mapChatMessagesToStoredMessages([message]);\n await this.client.db[this.table].create({\n sessionId: this.sessionId,\n type: messageToAdd[0].type,\n content: messageToAdd[0].data.content,\n role: messageToAdd[0].data.role,\n name: messageToAdd[0].data.name,\n additionalKwargs: JSON.stringify(messageToAdd[0].data.additional_kwargs),\n });\n }\n\n /**\n * Deletes all messages associated with the session ID.\n * @returns A promise that resolves when the messages have been deleted.\n */\n async clear(): Promise<void> {\n await this.ensureTable();\n const records = await this.client.db[this.table]\n .select([\"id\"])\n .filter({ sessionId: this.sessionId })\n .getAll();\n const ids = records.map((m) => m.id);\n await this.client.db[this.table].delete(ids);\n }\n\n /**\n * Checks if the table exists and creates it if it doesn't. This method is\n * called before any operation on the table.\n * @returns A promise that resolves when the table has been ensured.\n */\n private async ensureTable(): Promise<void> {\n if (!this.createTable) {\n return;\n }\n if (this.tableInitialized) {\n return;\n }\n\n const { databaseURL, branch } = await this.client.getConfig();\n const [, , host, , database] = databaseURL.split(\"/\");\n const urlParts = parseWorkspacesUrlParts(host);\n if (urlParts == null) {\n throw new Error(\"Invalid databaseURL\");\n }\n const { workspace, region } = urlParts;\n const tableParams = {\n workspace,\n region,\n database,\n branch,\n table: this.table,\n };\n\n let schema: GetTableSchemaResponse | null = null;\n try {\n schema = await this.apiClient.tables.getTableSchema(tableParams);\n } catch {\n // pass\n }\n if (schema == null) {\n await this.apiClient.tables.createTable(tableParams);\n await this.apiClient.tables.setTableSchema({\n ...tableParams,\n schema: {\n columns: chatMemoryColumns,\n },\n });\n }\n }\n}\n"],"mappings":"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"}