UNPKG

@langchain/community

Version:
1 lines 7.97 kB
{"version":3,"file":"aurora_dsql.cjs","names":["BaseListChatMessageHistory"],"sources":["../../../src/stores/message/aurora_dsql.ts"],"sourcesContent":["import { BaseListChatMessageHistory } from \"@langchain/core/chat_history\";\nimport {\n BaseMessage,\n StoredMessage,\n mapChatMessagesToStoredMessages,\n mapStoredMessagesToChatMessages,\n} from \"@langchain/core/messages\";\nimport pg from \"pg\";\n\n/**\n * Type definition for the input parameters required when instantiating a\n * AuroraDsqlChatMessageHistory object.\n */\nexport type AuroraDsqlChatMessageHistoryInput = {\n /**\n * Name of the table to use when storing and retrieving chat message\n */\n tableName?: string;\n /**\n * Session ID to use when storing and retrieving chat message history.\n */\n sessionId: string;\n /**\n * Configuration object for the Postgres pool. If provided the\n * AuroraDsqlChatMessageHistory object will create a new pool using\n * the provided configuration. Otherwise it will use the provided\n * pool.\n */\n poolConfig?: pg.PoolConfig;\n /**\n * Postgres pool to use. If provided the PostgresChatMessageHistory\n * object will use the provided pool. Otherwise it will create a\n * new pool using the provided configuration.\n */\n pool?: pg.Pool;\n /**\n * If true, the table name will be escaped. ('lAnGcHaIn' will be escaped to '\"lAnGcHaIn\"')\n */\n escapeTableName?: boolean;\n};\n\nexport interface StoredAuroraDsqlMessageData {\n name: string | undefined;\n role: string | undefined;\n content: string;\n additional_kwargs?: Record<string, unknown>;\n type: string;\n tool_call_id: string | undefined;\n}\n\n/**\n * Class for managing chat message history using a Amazon Aurora DSQL Database as a\n * storage backend. Extends the BaseListChatMessageHistory class.\n * @example\n * ```typescript\n * const chatHistory = new AuroraDsqlChatMessageHistory({\n * tableName: \"langchain_chat_histories\",\n * sessionId: \"lc-example\",\n * pool: new pg.Pool({\n * host: \"your_dsql_endpoint\",\n * port: 5432,\n * user: \"admin\",\n * password: \"your_token\",\n * database: \"postgres\",\n * ssl: true\n * }),\n * });\n * ```\n */\nexport class AuroraDsqlChatMessageHistory extends BaseListChatMessageHistory {\n lc_namespace = [\"langchain\", \"stores\", \"message\", \"aurora_dsql\"];\n\n pool: pg.Pool;\n\n tableName = \"langchain_chat_histories\";\n\n sessionId: string;\n\n private initialized = false;\n\n /**\n * Creates a new AuroraDsqlChatMessageHistory.\n * @param {AuroraDsqlChatMessageHistoryInput} fields The input fields for the AuroraDsqlChatMessageHistory.\n * @param {string} fields.tableName The name of the table name to use. Defaults to `langchain_chat_histories`.\n * @param {string} fields.sessionId The session ID to use when storing and retrieving chat message history.\n * @param {pg.Pool} fields.pool The Postgres pool to use. If provided, the AuroraDsqlChatMessageHistory will use the provided pool.\n * @param {pg.PoolConfig} fields.poolConfig The configuration object for the Postgres pool. If no pool is provided, the config will be used to create a new pool.\n * If `pool` is provided, it will be used as the Postgres pool even if `poolConfig` is also provided.\n * @throws If neither `pool` nor `poolConfig` is provided.\n */\n constructor(fields: AuroraDsqlChatMessageHistoryInput) {\n super(fields);\n const { tableName, sessionId, pool, poolConfig, escapeTableName } = fields;\n // Ensure that either a client or config is provided\n if (!pool && !poolConfig) {\n throw new Error(\n \"AuroraDsqlChatMessageHistory requires either a pool instance or pool config\"\n );\n }\n this.pool = pool ?? new pg.Pool(poolConfig);\n const _tableName = tableName || this.tableName;\n this.tableName = escapeTableName\n ? pg.escapeIdentifier(_tableName)\n : _tableName;\n this.sessionId = sessionId;\n }\n\n /**\n * Checks if the table has been created and creates it if it hasn't.\n * @returns Promise that resolves when the table's existence is ensured.\n */\n private async ensureTable(): Promise<void> {\n if (this.initialized) return;\n\n const query = `\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n created_at timestamp default current_timestamp,\n session_id VARCHAR(255) NOT NULL,\n message TEXT NOT NULL\n );`;\n\n try {\n await this.pool.query(query);\n await this.createIndex();\n // oxlint-disable-next-line typescript/no-explicit-any\n } catch (e: any) {\n // This error indicates that the table already exists\n // Due to asynchronous nature of the code, it is possible that\n // the table is created between the time we check if it exists\n // and the time we try to create it. It can be safely ignored.\n // If it's not this error, rethrow it.\n if (!(\"code\" in e) || e.code !== \"23505\") {\n throw e;\n }\n }\n this.initialized = true;\n }\n\n private async createIndex() {\n const query = `CREATE INDEX ASYNC IF NOT EXISTS idx_on_session_id on ${this.tableName} (session_id);`;\n await this.pool.query(query);\n }\n\n async addMessage(message: BaseMessage): Promise<void> {\n await this.ensureTable();\n\n const map = mapChatMessagesToStoredMessages([message])[0];\n\n const query = `INSERT INTO ${this.tableName} (session_id, message) VALUES ($1, $2)`;\n\n await this.pool.query(query, [\n this.sessionId,\n JSON.stringify({ ...map?.data, type: map?.type }),\n ]);\n }\n\n async getMessages(): Promise<BaseMessage[]> {\n await this.ensureTable();\n\n const query = `SELECT message FROM ${this.tableName} WHERE session_id = $1 ORDER BY created_at asc`;\n\n const res = await this.pool.query(query, [this.sessionId]);\n\n const storedMessages: StoredMessage[] = res.rows.map(\n (row: { message: string }) => {\n const { type, ...data } = JSON.parse(\n row.message\n ) as StoredAuroraDsqlMessageData;\n return { type, data };\n }\n );\n return mapStoredMessagesToChatMessages(storedMessages);\n }\n\n async clear(): Promise<void> {\n await this.ensureTable();\n\n const query = `DELETE FROM ${this.tableName} WHERE session_id = $1`;\n await this.pool.query(query, [this.sessionId]);\n }\n\n /**\n * End the Postgres pool.\n */\n async end(): Promise<void> {\n await this.pool.end();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAqEA,IAAa,+BAAb,cAAkDA,6BAAAA,2BAA2B;CAC3E,eAAe;EAAC;EAAa;EAAU;EAAW;EAAc;CAEhE;CAEA,YAAY;CAEZ;CAEA,cAAsB;;;;;;;;;;;CAYtB,YAAY,QAA2C;AACrD,QAAM,OAAO;EACb,MAAM,EAAE,WAAW,WAAW,MAAM,YAAY,oBAAoB;AAEpE,MAAI,CAAC,QAAQ,CAAC,WACZ,OAAM,IAAI,MACR,8EACD;AAEH,OAAK,OAAO,QAAQ,IAAI,GAAA,QAAG,KAAK,WAAW;EAC3C,MAAM,aAAa,aAAa,KAAK;AACrC,OAAK,YAAY,kBACb,GAAA,QAAG,iBAAiB,WAAW,GAC/B;AACJ,OAAK,YAAY;;;;;;CAOnB,MAAc,cAA6B;AACzC,MAAI,KAAK,YAAa;EAEtB,MAAM,QAAQ;iCACe,KAAK,UAAU;;;;;;AAO5C,MAAI;AACF,SAAM,KAAK,KAAK,MAAM,MAAM;AAC5B,SAAM,KAAK,aAAa;WAEjB,GAAQ;AAMf,OAAI,EAAE,UAAU,MAAM,EAAE,SAAS,QAC/B,OAAM;;AAGV,OAAK,cAAc;;CAGrB,MAAc,cAAc;EAC1B,MAAM,QAAQ,yDAAyD,KAAK,UAAU;AACtF,QAAM,KAAK,KAAK,MAAM,MAAM;;CAG9B,MAAM,WAAW,SAAqC;AACpD,QAAM,KAAK,aAAa;EAExB,MAAM,OAAA,GAAA,yBAAA,iCAAsC,CAAC,QAAQ,CAAC,CAAC;EAEvD,MAAM,QAAQ,eAAe,KAAK,UAAU;AAE5C,QAAM,KAAK,KAAK,MAAM,OAAO,CAC3B,KAAK,WACL,KAAK,UAAU;GAAE,GAAG,KAAK;GAAM,MAAM,KAAK;GAAM,CAAC,CAClD,CAAC;;CAGJ,MAAM,cAAsC;AAC1C,QAAM,KAAK,aAAa;EAExB,MAAM,QAAQ,uBAAuB,KAAK,UAAU;AAYpD,UAAA,GAAA,yBAAA,kCAVY,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC,KAAK,UAAU,CAAC,EAEd,KAAK,KAC9C,QAA6B;GAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,MAC7B,IAAI,QACL;AACD,UAAO;IAAE;IAAM;IAAM;IAExB,CACqD;;CAGxD,MAAM,QAAuB;AAC3B,QAAM,KAAK,aAAa;EAExB,MAAM,QAAQ,eAAe,KAAK,UAAU;AAC5C,QAAM,KAAK,KAAK,MAAM,OAAO,CAAC,KAAK,UAAU,CAAC;;;;;CAMhD,MAAM,MAAqB;AACzB,QAAM,KAAK,KAAK,KAAK"}