UNPKG

@langchain/community

Version:
1 lines 9.48 kB
{"version":3,"file":"xata.cjs","names":["BaseListChatMessageHistory","BaseClient","XataApiClient"],"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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"}