UNPKG

@langchain/community

Version:
1 lines 11.1 kB
{"version":3,"file":"dynamodb.cjs","names":["BaseListChatMessageHistory","DynamoDBClient","GetItemCommand","UpdateItemCommand","DeleteItemCommand"],"sources":["../../../src/stores/message/dynamodb.ts"],"sourcesContent":["import {\n DynamoDBClient,\n DynamoDBClientConfig,\n GetItemCommand,\n GetItemCommandInput,\n UpdateItemCommand,\n UpdateItemCommandInput,\n DeleteItemCommand,\n DeleteItemCommandInput,\n AttributeValue,\n} from \"@aws-sdk/client-dynamodb\";\n\nimport { BaseListChatMessageHistory } from \"@langchain/core/chat_history\";\nimport {\n BaseMessage,\n StoredMessage,\n mapChatMessagesToStoredMessages,\n mapStoredMessagesToChatMessages,\n} from \"@langchain/core/messages\";\n\n/**\n * Interface defining the fields required to create an instance of\n * `DynamoDBChatMessageHistory`. It includes the DynamoDB table name,\n * session ID, partition key, sort key, message attribute name, and\n * DynamoDB client configuration.\n */\nexport interface DynamoDBChatMessageHistoryFields {\n tableName: string;\n sessionId: string;\n partitionKey?: string;\n sortKey?: string;\n messageAttributeName?: string;\n config?: DynamoDBClientConfig;\n key?: Record<string, AttributeValue>;\n}\n\n/**\n * Interface defining the structure of a chat message as it is stored in\n * DynamoDB.\n */\ninterface DynamoDBSerializedChatMessage {\n M: {\n type: {\n S: string;\n };\n text: {\n S: string;\n };\n role?: {\n S: string;\n };\n additional_kwargs?: {\n S: string;\n };\n };\n}\n\n/**\n * Class providing methods to interact with a DynamoDB table to store and\n * retrieve chat messages. It extends the `BaseListChatMessageHistory`\n * class.\n */\nexport class DynamoDBChatMessageHistory extends BaseListChatMessageHistory {\n lc_namespace = [\"langchain\", \"stores\", \"message\", \"dynamodb\"];\n\n get lc_secrets(): { [key: string]: string } | undefined {\n return {\n \"config.credentials.accessKeyId\": \"AWS_ACCESS_KEY_ID\",\n \"config.credentials.secretAccessKey\": \"AWS_SECRETE_ACCESS_KEY\",\n \"config.credentials.sessionToken\": \"AWS_SESSION_TOKEN\",\n };\n }\n\n private tableName: string;\n\n private sessionId: string;\n\n private client: DynamoDBClient;\n\n private partitionKey = \"id\";\n\n private sortKey?: string;\n\n private messageAttributeName = \"messages\";\n\n private dynamoKey: Record<string, AttributeValue> = {};\n\n /**\n * Transforms a `StoredMessage` into a `DynamoDBSerializedChatMessage`.\n * The `DynamoDBSerializedChatMessage` format is suitable for storing in DynamoDB.\n *\n * @param message - The `StoredMessage` to be transformed.\n * @returns The transformed `DynamoDBSerializedChatMessage`.\n */\n private createDynamoDBSerializedChatMessage(\n message: StoredMessage\n ): DynamoDBSerializedChatMessage {\n const {\n type,\n data: { content, role, additional_kwargs },\n } = message;\n\n const isAdditionalKwargs =\n additional_kwargs && Object.keys(additional_kwargs).length;\n\n const dynamoSerializedMessage: DynamoDBSerializedChatMessage = {\n M: {\n type: {\n S: type,\n },\n text: {\n S: content,\n },\n additional_kwargs: isAdditionalKwargs\n ? { S: JSON.stringify(additional_kwargs) }\n : { S: \"{}\" },\n },\n };\n\n if (role) {\n dynamoSerializedMessage.M.role = { S: role };\n }\n\n return dynamoSerializedMessage;\n }\n\n constructor({\n tableName,\n sessionId,\n partitionKey,\n sortKey,\n messageAttributeName,\n config,\n key = {},\n }: DynamoDBChatMessageHistoryFields) {\n super();\n\n this.tableName = tableName;\n this.sessionId = sessionId;\n this.client = new DynamoDBClient(config ?? {});\n this.partitionKey = partitionKey ?? this.partitionKey;\n this.sortKey = sortKey;\n this.messageAttributeName =\n messageAttributeName ?? this.messageAttributeName;\n this.dynamoKey = key;\n\n // override dynamoKey with partition key and sort key when key not specified\n if (Object.keys(this.dynamoKey).length === 0) {\n this.dynamoKey[this.partitionKey] = { S: this.sessionId };\n if (this.sortKey) {\n this.dynamoKey[this.sortKey] = { S: this.sortKey };\n }\n }\n }\n\n /**\n * Retrieves all messages from the DynamoDB table and returns them as an\n * array of `BaseMessage` instances.\n * @returns Array of stored messages\n */\n async getMessages(): Promise<BaseMessage[]> {\n try {\n const params: GetItemCommandInput = {\n TableName: this.tableName,\n Key: this.dynamoKey,\n };\n\n const response = await this.client.send(new GetItemCommand(params));\n const items = response.Item\n ? (response.Item[this.messageAttributeName]?.L ?? [])\n : [];\n const messages = items\n .filter(\n (\n item\n ): item is AttributeValue & { M: DynamoDBSerializedChatMessage } =>\n item.M !== undefined\n )\n .map((item) => {\n const data: {\n role?: string;\n content: string | undefined;\n additional_kwargs?: Record<string, unknown>;\n } = {\n role: item.M?.role?.S,\n content: item.M?.text.S,\n additional_kwargs: item.M?.additional_kwargs?.S\n ? JSON.parse(item.M?.additional_kwargs.S)\n : undefined,\n };\n\n return {\n type: item.M?.type.S,\n data,\n };\n })\n .filter(\n (x): x is StoredMessage =>\n x.type !== undefined && x.data.content !== undefined\n );\n return mapStoredMessagesToChatMessages(messages);\n // oxlint-disable-next-line typescript/no-explicit-any\n } catch (error: any) {\n throw new Error(`Error getting messages: ${error.message}`);\n }\n }\n\n /**\n * Adds a new message to the DynamoDB table.\n * @param message The message to be added to the DynamoDB table.\n */\n async addMessage(message: BaseMessage) {\n try {\n const messages = mapChatMessagesToStoredMessages([message]);\n\n const params: UpdateItemCommandInput = {\n TableName: this.tableName,\n Key: this.dynamoKey,\n ExpressionAttributeNames: {\n \"#m\": this.messageAttributeName,\n },\n ExpressionAttributeValues: {\n \":empty_list\": {\n L: [],\n },\n \":m\": {\n L: messages.map(this.createDynamoDBSerializedChatMessage),\n },\n },\n UpdateExpression:\n \"SET #m = list_append(if_not_exists(#m, :empty_list), :m)\",\n };\n await this.client.send(new UpdateItemCommand(params));\n // oxlint-disable-next-line typescript/no-explicit-any\n } catch (error: any) {\n throw new Error(`Error adding message: ${error.message}`);\n }\n }\n\n /**\n * Adds new messages to the DynamoDB table.\n * @param messages The messages to be added to the DynamoDB table.\n */\n async addMessages(messages: BaseMessage[]): Promise<void> {\n try {\n const storedMessages = mapChatMessagesToStoredMessages(messages);\n const dynamoMessages = storedMessages.map(\n this.createDynamoDBSerializedChatMessage\n );\n\n const params: UpdateItemCommandInput = {\n TableName: this.tableName,\n Key: this.dynamoKey,\n ExpressionAttributeNames: {\n \"#m\": this.messageAttributeName,\n },\n ExpressionAttributeValues: {\n \":empty_list\": {\n L: [],\n },\n \":m\": {\n L: dynamoMessages,\n },\n },\n UpdateExpression:\n \"SET #m = list_append(if_not_exists(#m, :empty_list), :m)\",\n };\n await this.client.send(new UpdateItemCommand(params));\n // oxlint-disable-next-line typescript/no-explicit-any\n } catch (error: any) {\n throw new Error(`Error adding messages: ${error.message}`);\n }\n }\n\n /**\n * Deletes all messages from the DynamoDB table.\n */\n async clear(): Promise<void> {\n try {\n const params: DeleteItemCommandInput = {\n TableName: this.tableName,\n Key: this.dynamoKey,\n };\n await this.client.send(new DeleteItemCommand(params));\n // oxlint-disable-next-line typescript/no-explicit-any\n } catch (error: any) {\n throw new Error(`Error clearing messages: ${error.message}`);\n }\n }\n}\n"],"mappings":"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"}