• Amazon DynamoDB 设计与建模最佳实践之 AI 数字人场景


    25a6ff70d5afdfb51371d6d87b126815.gif

    互联网浪潮中,科技改变生活,真切地让我们感受到工作的提效、生活的便利、娱乐的多样化。伴随更多的业务需求和极速的系统膨胀,作为核心价值的数据存储方案设计也变得愈发重要,NoSQL (Not only SQL) 也逐渐深入人心。亚马逊云科技秉承专门构建的理念,为客户提供完整的云原生数据战略体系,为不同业务类型,提供最优解。

    92410a80b7fe4348bebcb6b70c608cc3.png

    01

    Why DynamoDB?

    自 2007 年的第一篇“Dynamo 研究论文”,到 2012 年 Amazon DynamoDB 服务的推出。现在,亚马逊云科技在大型非关系数据库和云服务技术领域 18 年持续投入,带给我们一款为互联网规模的应用程序而生、快速、高度可靠且具有成本效益的 NoSQL 数据库服务。

    Amazon DynamoDB 是一种完全托管式、无服务器的 NoSQL 键值数据库,旨在运行任何规模的高性能应用程序。每天持续处理超过 10 万亿个请求。且可提供无限的可扩展性,稳定的个位数毫秒级性能和高达 99.999% 的可用性。

    3dc94441a445383c1f93af998b5d2482.png

    基于 Amazon DynamoDB 的能力和使用场景,如何以最佳实践的方式在 AI 场景发挥作用,是很多客户关心的话题。

    02

    业务场景描述

    AIGC(AI-Generated Content,人工智能生成内容)风靡全球,而 LLM (Large Language Model) 创造力和智慧是最惊艳的部分。但是在工程化的过程中,我们希望数字人可以有“记忆”,来延续对话的上下文。那么会话的记忆存储,就需要一个可以承载高并发、低延迟的数据库来支撑业务。

    2.1 架构图详解

    根据业务需求,将 Amazon Bedrock 的 Claude2 模型和 Amazon DynamoDB 结合,来实现智能“问答”和“记忆”。

    问答流程:

    1. user 发起访问

    2. 基于 Amazon Elastic Kubernetes Service (Amazon EKS) 运行的 AI 数字人应用,接收对话请求

    3. APP 查询 DynamoDB 会话的历史记录,并结合当前会话内容,整合信息

    4. 发送整合后信息到 Amazon Bedrock Claude2,获取“回答”

    5. APP 发送“回答”给 user

    777b65780dd3a36b7332d162d4307e00.png

    03

    数据查询/存储方案

    在理清业务需求和技术实现架构之后,我们需要针对会话历史信息的存储和查询,进行详尽的技术拆解。

    3.1 表设计和实体关系详解

    • 聊天会话表用于记录用户和 AI 数字人之间的聊天 ID (chat_id)。

    • 应用程序会根据用户 ID (user_id) 和 AI 数字人 (ai_id),获取当前#ACTIVE#的 chat_id。

    • 用户可以选择删除旧的 chat_id(软删除,在数据库要保留这条记录,通过 delete_time 时间戳等信息来表示历史聊天)。

    • 用户也可以重启聊天会话,同时删除旧的聊天会话,创建一个新的聊天会话。

    • 因此,一个用户跟 AI 数字人之间允许有多条聊天会话记录,但是同一时间有且仅有一条处于活跃状态#ACTIVE#的聊天会话记录。

    3.1.1 ERD(数据库实体关系图)

    3f74df22a82b189c1dd657d5222a411a.png

    涉及的实体包括:用户(user_id),AI 数字人(ai_id),聊天会话(chat_id)


    用户跟 AI 数字人之间是多对多的关系:

    • 用户可以跟多个 AI 数字人存在多条聊天会话记录;

    • AI 数字人也可以跟多个用户存在多条聊天会话记录;

    3.1.2 访问模式(聊天会话的增删改查)

    • 创建新的聊天会话 – CreateChat

    • 获取指定聊天会话 – GetChatByUser_Id_and_AI_Id

    • 删除聊天会话 – DeleteChat

    • 重启聊天会话 – RenewChat

    • 更新指定会话 AI_Version – UpdateAIVersionByChat_Id

    04

    DynamoDB 数据建模&表格设计

    4.1 表格设计

    我们需要一个基表存储数据,同时需要一个 GSI (Global Secondary Index) 辅助查询。

    • 基表名称:chat_session

    • 全局二级索引名称:GSI1_chat(选择 Keys_Only 模式)

    表格定义:

    04153e222dd03535528bd7ffb13c61ba.png

    4.2 表格设计技巧

    Amazon DynamoDB 是一个全托管,且简单易用的数据库。但是如何发挥其性能优势,也是需要我们知其善用。


    这里我们就罗列一些小技巧:

    • 有效利用 DynamoDB 排序键的特性:
      例如标记活跃状态的 SK 前缀是#ACTIVE#,以#字符开头,让这条记录在排序过程中保持置顶。

    • 兼顾业务和技术的 Key 设计:
      场景 1. chat_id,我们可以使用 ULID (一种全局唯一且可以按字典序排序的标识符格式),其比随机 UUID 增加了时间戳,查询性能会更好。
      场景 2. 在以 user_id & ai_id 作为查询条件,且以时间维度排序所有历史聊天会话的场景,ULID 就可以提供更好的查询性能。

    f9acc0ebc4c1757701be7e8c09563f84.png

    4.3 表数据样例

    • 基表插入数据后的样式

    a5a6a2d0c173a0ddb992a9c91d6e3433.png

    • GSI 的数据样式

    a65386c07500c9b6367042f04adc1dd4.png

    05

    访问模式实现

    在完成表格设计之后,如何消费数据,以满足业务需求?后续内容会详细介绍。

    5.1 创建新的聊天会话 – CreateChat

    在基表 chat_session 上执行 putItem 操作,通过条件判断表达式(ConditionExpression),确定当前表中不存在这条记录,才执行写入新的聊天会话。如果条件判断检查失败,则返回应用端 ConditionalCheckFailedException,表示数据库中存在这条记录。需要应用端做业务逻辑判断再操作。

    1. put_item_params = {
    2.    'TableName': 'chat_session',
    3.    'Item': {
    4.        'PK': {'S': user_id},
    5.        'SK': {'S': '#ACTIVE#' + ai_id},
    6.        'chat_id': {'S': chat_id},
    7.        'create_time': {'S': create_timestamp},
    8.        'GSI1PK': {'S': chat_id}
    9.    },
    10.    'ConditionExpression': 'attribute_not_exists(PK) AND attribute_not_exists(SK)'
    11. }

    5.2 获取指定聊天会话 –

    GetChatByUser_Id_and_AI_Id

    在基表 chat_session 上执行 getItem 操作,指定 PK=user_id and SK=#ACTIVE#ai_id,获取返回结果。

    5.3 标记删除聊天会话 – 

    DeleteChat

    组合操作完成这个场景,首先 getItem 获取到当前活跃聊天会话记录的所有属性。然后事务写入,插入一条有 delete_time 的历史会话记录,并删除当前活跃聊天会话记录。相关步骤参数见下面:

    第一步:getItem PK=user_id and SK=#ACTIVE#ai_id, 可以复用上面的 getChatByUser_id_and_ai_id 函数。获取到这条 Item 所有信息记录下来。

    第二步:事务写入
    putItem PK=user_id and SK=ai_id#OLD#chat_id,其他属性包括 chat_id, ai_version,create_time,delete_time.
    deleteItem PK=user_id and SK=#ACTIVE#ai_id

    5.4 重新启动聊天会话 – 

    RenewChat

    组合操作完成这个场景,跟上面软删除很类似,只是在事务写入时候,使用 updateItem。首先 getItem 获取到当前活跃聊天会话记录的所有属性。然后事务写入,插入一条有 delete_time 的历史会话记录,然后更新当前活跃聊天会话记录,为最新的 ai_version,chat_id。相关步骤参数见下面:

    第一步:getItem PK=user_id and SK=#ACTIVE#ai_id, 可复用 getChatByUser_id_and_ai_id 函数。获取到这条 Item 所有信息记录下来。

    第二步:事务写入
    putItem PK=user_id and SK=ai_id#OLD#chat_id,其他属性包括 chat_id,ai_version,create_time,delete_time
    updateItem PK=user_id and SK=#ACTIVE#ai_id,其他属性包括 chat_id,ai_version,create_time,GSI1PK

    5.5 更新指定会话 AI_Version –

    UpdateAIVersionByChat_Id

    第一步:GSI1_chat 中 getItem PK=chat_id;拿到基表的 PK,SK


    第二步:基表 chat_session 中 updateItem,PK=user_id,SK=#ACTIVE#ai_id

    5.6 访问模式和实现方法汇总

    为便于理解,我们将前面的访问模式,结合具体的实现方法,通过表格的形式进行汇总。

    2acc9f7d7e8caa7ec18223f4e36a0258.png

    总结

    通过以上内容,我们希望你理解“专门构建”的含义,不再根据数据库设计业务,而是通过业务选择适合的数据库。在类似场景下,DynamoDB 作为 Key-Value 数据库,可以充分发挥高并发、低延迟、高稳定性的特点,支撑核心业务的稳定运行。也希望通过本文,带来更清晰的 DynamoDB 的建模方法、建表模式,以及高性能查询的最佳实践。

    参考链接

    • Amazon DynamoDB

      https://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/GettingStartedDynamoDB.html

    • Gaming profile schema design in DynamoDB

      https://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/data-modeling-schema-gaming-profile.html

    本篇作者

    9e7744ed3082c2ccb43bd1aa680a1f4e.jpeg

    许晓亮

    亚马逊云科技解决方案架构师,负责基于亚马逊云科技云计算方案架构的咨询和设计,在国内推广亚马逊云科技云平台技术和各种解决方案。擅长数据库和大数据领域,结合云原生特性,为客户设计高效稳定的全球化系统方案。

    40fe9053f31f402684d3dc9e1927d488.jpeg

    李君

    亚马逊云科技数据库解决方案技术专家,负责基于亚马逊云计算数据库产品的技术咨询与解决方案工作,特别专注于从 SQL 到 NoSQL 数据库的设计、测试、迁移、运维及优化等工作。

    18c37e40f909766fc49bf74647c16427.gif

    星标不迷路,开发更极速!

    关注后记得星标「亚马逊云开发者」

    d0b002e474f83f16b044d845ffb44e7b.gif

    听说,点完下面4个按钮

    就不会碰到bug了!

    188f30dffbbe1e0242e457acf456d99a.gif

  • 相关阅读:
    Vue Router - 路由的使用、两种切换方式、两种传参方式、嵌套方式
    camshift实现目标跟踪
    【EMC专题】电快速瞬变脉冲群抗扰度测试
    LeetCode高频题84. 柱状图中最大的矩形,单调栈求位置i左边右边距离i最近且比i位置小的位置,然后结算面积
    51单片机学习笔记3 C51数据类型及最小系统
    【图论】最小生成树(python和cpp)
    什么是人工智能 人工智能简介
    基于spring boot开发的6个秋招必备项目,搞起来
    C++算法 通配符匹配
    【Java编程进阶】标识符和关键字
  • 原文地址:https://blog.csdn.net/u012365585/article/details/136669420