标签: Bedrock

  • RAG 中的混合搜索对决!OpenSearch Serverless VS Aurora Serverless

    RAG 中的混合搜索对决!OpenSearch Serverless VS Aurora Serverless

    前言

    今天我要对可作为 Amazon Bedrock Knowledge Bases 向量数据库(搜索引擎)的工具进行对比。

    目前,Bedrock Knowledge Base 中支持混合搜索的向量数据库如下:

    • OpenSearch Serverless
    • OpenSearch Managed Cluster(OpenSearch 托管集群)
    • Aurora Serverless V2(PostgreSQL)
    • MongoDB Atlas

    本次,我将针对其中使用率较高的OpenSearch ServerlessAurora Serverless V2(PostgreSQL) ,对比二者在混合搜索中的精度表现。

    概述

    混合搜索是一种结合向量(语义)搜索关键词(全文)搜索来查找相关文档的搜索方式。这种方式既能通过向量搜索实现基于语义的检索,又能通过关键词搜索,在检索过程中纳入指定关键词的考量。

    OpenSearch Serverless 与 Aurora Serverless V2(PostgreSQL)的对比

    下面我将对本次作为数据存储使用的 OpenSearch Serverless 和 Aurora Serverless V2(PostgreSQL)进行简单对比。

    对比维度OpenSearch ServerlessAurora Serverless V2(PostgreSQL)
    混合搜索(Bedrock Knowledge Bases)支持支持
    中文支持可使用 Kuromoji 等中文形态素分析PostgreSQL 标准全文搜索(目前不支持中文形态素分析)
    向量存储格式支持浮点数 / 二进制两种格式浮点数(基于 pgvector 插件)
    计费单位OCU / 小时(最小 1 个 OCU,含 0.5 计算 OCU+0.5 存储 OCU)ACU / 小时(最小 0.5 个 ACU)
    最小配置计费示例175.22 美元(1 个 OCU:175.2 美元,存储:0.02 美元)87.83 美元(1 个 ACU:87.60 美元,I/O:0.13 美元)

    (参考链接:aws.amazon.comaws.amazon.com

    OpenSearch Serverless 支持中文形态素分析,因此即便使用中文,也能高精度地进行关键词搜索。另一方面,Aurora Serverless V2(PostgreSQL)在最小配置下的费用更具优势,但由于其默认不支持中文形态素分析,因此在中文混合搜索的精度方面存在不确定性。

    精度对比实验

    为对比 OpenSearch Serverless 与 Aurora Serverless V2(PostgreSQL)的精度,本次将开展以下两类实验:

    1. 英文数据集的搜索精度对比
    2. 中文数据集的搜索精度对比

    尤其对于中文数据集,由于 Aurora Serverless V2(PostgreSQL)不支持中文形态素分析,预计 OpenSearch Serverless 在精度上会更具优势。

    1. 实验设置

    以下是本次实验使用的基本设置。首先,Bedrock Knowledge Base 的基础设置如下,仅向量存储工具为两者的差异点。

    嵌入模型(Embedding Model)嵌入类型(Embedding Type)分块策略(Chunking Strategy)
    Titan Text Embeddings V21024 维浮点数向量嵌入分层分块(父块:2000 字符,子块:500 字符,重叠:50 字符)

    精度对比将通过 Bedrock Evaluations 完成。

    (参考链接:docs.aws.amazon.com

    本次对比将采用以下两项指标,指标取值范围均为 0~1,数值越大表示对问题的回答质量越高:

    • Context relevance(上下文相关性):衡量获取的文本与问题在上下文层面的关联程度
    • Context coverage(上下文覆盖率):衡量获取的文本对正确数据中全部信息的覆盖程度

    2. 混合搜索对比(英文数据集)

    1. 数据集

    本次实验使用的数据集如下:Amazon Reviews 2023(2023 年亚马逊评论数据集)

    (参考链接:amazon-reviews-2023.github.io

    该数据集包含约 2.8 万组 “产品 ID – 评论” 数据,示例如下:

    product/productId: B000GKXY4S
    product/title: Crazy Shape Scissor Set
    product/price: unknown
    review/userId: A1QA985ULVCQOB
    review/profileName: Carleen M. Amadio "Lady Dragonfly"
    review/helpfulness: 2/2
    review/score: 5.0
    review/time: 1314057600
    review/summary: Fun for adults too!
    review/text: I really enjoy these scissors for my inspiration books that I am making (like collage, but in books) and using these different textures these give is just wonderful, makes a great statement with the pictures and sayings. Want more, perfect for any need you have even for gifts as well. Pretty cool!
    

    2. 结果(英文)

    对比结果如下,
    数值越高,评估结果越好。

    指标类型OpenSearch无服务器Aurora Serverless V2(PostgreSQL)
    上下文相关性0.060.07
    上下文覆盖0.190.18

    3. 混合搜索对比(中文数据集)

    那么,接下来将对核心中文数据集的(检索)精度展开比较分析。​

    1. OpenSearch(中文分词设置示例)

    由于 OpenSearch Serverless 可使用 Kuromoji 形态素分析(中文分词工具),因此需进行相关配置。

    通过该配置,中文文本能被正确分割,进而有望提升关键词搜索的精度。

    配置示例

    PUT bedrock-knowledge-base-hybrid-index
    {
      "mappings": {
        "properties": {
          "AMAZON_BEDROCK_METADATA": {
            "type": "text",
            "index": false
          },
          "AMAZON_BEDROCK_TEXT_CHUNK": {
            "type": "text",
            "analyzer": "custom_kuromoji_analyzer"
          },
          "bedrock-knowledge-base-default-vector": {
            "type": "knn_vector",
            "dimension": 1024,
            "method": {
              "name": "hnsw",
              "engine": "faiss",
              "space_type": "cosinesimil"
            }
          },
          "id": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      },
      "settings": {
        "index": {
          "knn.algo_param": {
            "ef_search": "512"
          },
          "knn": "true",
          "analysis": {
            "analyzer": {
              "custom_kuromoji_analyzer": {
                "tokenizer": "kuromoji_tokenizer",
                "filter": [
                  "kuromoji_baseform",
                  "ja_stop"
                ],
                "char_filter": [
                  "icu_normalizer"
                ]
              }
            }
          }
        }
      }
    }
    
    

    2. 插入的中文文档

    本次使用的数据集,是让 ChatGPT 输出的,具体如下。
    在混合检索时,我们期望能以 “张居正生平” 作为关键词,检索到相关信息。

    张居正像(现藏于中国国家博物馆)

    时代 明朝中后期(嘉靖、隆庆、万历年间)

    生诞 嘉靖四年五月初三日(1525 年 5 月 24 日)

    死没 万历十年六月二十日(1582 年 7 月 9 日)(58 岁卒)

    改名 无(一直以 “张居正” 为名,字叔大,号太岳)

    字:叔大

    号:太岳

    谥号:文忠(万历朝初赠,后被追夺,天启朝恢复)

    墓所:湖北省荆州市沙市区张居正墓

    官职:吏部左侍郎兼东阁大学士、礼部尚书兼武英殿大学士、少师兼太子太师、吏部尚书、中极殿大学士(内阁首辅)

    主要事迹 1. 推行 “一条鞭法”,将田赋、徭役和杂税合并,按田亩折算银两征收,简化税制,增加财政收入;2. 实施 “考成法”,考核各级官吏政绩,整顿吏治,提高行政效率;3. 重用戚继光、李成梁等将领,加强北方边防,抵御蒙古部落侵扰,稳定边疆局势;4. 主持治理黄河、淮河,任用潘季驯负责河工,疏通河道,减少水患,保障农业生产。

    评估用数据集示例

    • 问题:请告知张居正被任命为吏部尚书的年份
    • 答案:张居正于明万历元年(公元 1573 年) 正式被任命为吏部尚书。

    3. 结果(中文)

    以下是中文数据集的精度对比结果。数值越大,代表评价结果越好。

    Metric typeOpenSearch ServerlessAurora Serverless V2(PostgreSQL)
    Context relevance0.450.43
    Context coverage1.000.93

    如上表所示,尽管优势微弱,但 OpenSearch Serverless 在两项指标上均超过 Aurora Serverless V2(PostgreSQL)。尤其在衡量 “问题回答覆盖度” 的上下文覆盖率(Context coverage)指标上,OpenSearch Serverless 的优势更为明显。

    我们认为,这一差异源于 OpenSearch Serverless 通过 Kuromoji 实现了中文形态素分析支持,进而在混合搜索的关键词搜索精度上形成了优势。

    此外,我们也对比了两者的搜索速度,结果如下:我们连续执行 5 种不同查询,去除最大值与最小值后计算 “截尾平均值”(Trimmed Mean)进行对比。

    OpenSearch Serverless(秒)Aurora Serverless V2(PostgreSQL)(秒)
    0.48 秒0.55 秒

    从搜索速度来看,OpenSearch Serverless 同样具备更快的检索表现。

    总结

    本次实验对比了在 Bedrock 知识库中,分别使用 OpenSearch Serverless 与 Aurora Serverless V2(PostgreSQL)实现混合搜索的效果。结果显示,在中文搜索的精度与速度上,OpenSearch Serverless 均优于 Aurora Serverless V2(PostgreSQL)。

    需要说明的是,本次验证基于 “数据量较少” 的场景,因此两者的差距并不显著;若后续数据量增加,结果可能会发生变化。不过,从整体来看,两款工具在精度与速度上均具备较高性能,建议根据实际使用场景数据量选择合适的工具。

  • 借助 StrandsAgents+AgentCore Memory 实现符合个人偏好的智能体

    借助 StrandsAgents+AgentCore Memory 实现符合个人偏好的智能体

    近年来,随着对话式 AI 的应用不断深入,为每位用户提供个性化体验变得愈发重要。当前所需的智能体,已不再是简单的一问一答模式,而是能够理解 “用户是谁、拥有怎样的关注点与目标” 后再进行响应的智能体。

    在本文中,我们将结合 Strands Agents 与 Bedrock AgentCore,对可记忆并活用用户对话历史的个性化智能体进行实现与验证。

    1. 引言

    首先,我们将对各个构成要素进行简单介绍。

    1.1 什么是 Strands Agents

    Strands Agents 是一套能够灵活设计并构建对话式智能体行为及对话流程的机制。通过组合多个工具,可在对话过程中实现所需的处理(如 API 调用、数据检索、记忆查询等)。

    相关内容也可参考 GitHub 链接:github.com

    1.1.1 Strands Agents 工具

    在 Strands Agents 中,“工具” 指的是智能体所使用的外部功能。本文将重点介绍用于处理对话记忆的 “Agent Core Memory” 工具。

    相关参考链接:github.com

    1.2 什么是 Bedrock AgentCore

    Bedrock AgentCore 是一项托管服务,为智能体的开发与运行提供所需功能。它具备以下功能,可助力智能体的顺畅构建:

    • 提供运行环境
    • 与各类工具联动
    • 认证与授权功能
    • 按用户管理记忆等

    官方参考链接:aws.amazon.com

    1.2.1 AgentCore 记忆功能(AgentCore Memory)

    AgentCore 具备 “Memory(记忆)” 功能,可让智能体拥有短期记忆与长期记忆。

    其中,长期记忆尤为重要,它能够记录通过与用户对话获取的事实信息,并在后续对话中加以活用。例如,通过记忆用户 “擅长 Python”“喜欢旅行” 等偏好与特征,智能体在之后的对话中,就能给出更贴合用户需求的响应与建议。

    需要注意的是,并非所有已记忆的内容都会被调用,系统会动态检索并使用与当前对话相关的信息。

    ChatGPT 也具备记忆功能,能够记住用户的个人信息与偏好,而通过 Bedrock AgentCore,我们可以自行实现同等功能,从而达成自然的个性化体验。

    官方文档参考链接:docs.aws.amazon.com

    2. 验证

    我们将实际创建智能体,验证其能否在保存、检索记忆的同时进行对话。

    由于短期记忆可通过 StrandsAgents 的 ConversationManager 进行管理,因此本次验证将重点关注长期记忆。

    我们已通过 AgentCore 的控制台,创建了启用 “用户偏好” 策略的记忆模块。

    2.1 结构图

    2.2 实现过程

    以下为智能体的实现代码。为了获取与特定用户的对话记录,我们设置了可通过参数接收 “与谁对话” 这一信息的功能。

    class MemoryAgent:
        PROMPT = dedent("""\
            请你扮演一个能为用户提供个性化服务、贴合用户需求的助手。
            请利用与用户过往的交互信息,理解用户想要做的事情。
    
            以下内容仅需在你内部处理,不得告知用户。
            请自然地进行互动。
            - 对于用户的输入内容,不得修改,需全部通过agent_core_memory的record工具进行记录。
            - 在对话过程中,若话题发生变化或开启新话题,请通过agent_core_memory的retrieve工具,从过往交互记录中获取与用户相关的信息。
            以上内容仅需在你内部处理,不得告知用户。
        """)
    
        def __init__(self, actor_id: str, session_id: str):
            model = BedrockModel(
                model_id='us.anthropic.claude-sonnet-4-20250514-v1:0',
                streaming=True,
                additional_request_fields={
                    'thinking': {'type': 'enabled', 'budget_tokens': 4000},
                    'anthropic_beta': ['interleaved-thinking-2025-05-14'],
                },
                region_name='us-west-2',
            )
    
            # 此处准备AgentCore Memory
            # 可指定使用的记忆模块以及长期记忆的整理策略
            provider = AgentCoreMemoryToolProvider(
                memory_id=MEMORY_ID,
                actor_id=actor_id,
                session_id=session_id,
                namespace=f'/strategies/{STRATEGY_ID}/actors/{actor_id}',
                region='us-west-2',
            )
    
            self.agent = Agent(
                model=model,
                system_prompt=self.PROMPT,
                tools=provider.tools,
            )
    
        async def stream(self, prompt):
            async for event in self.agent.stream_async(prompt):
                if text := event.get('event', {}).get('contentBlockDelta', {}).get('delta', {}).get('text', ''):
                    yield text
                for content in event.get('message', {}).get('content', []):
                    if isinstance(content, dict) and (tool_use := content.get('toolUse', '')):
                        logger.info('## 工具使用:%s', tool_use)
    

    2.3 尝试对话

    我平时习惯使用 “Python+Angular” 的组合开发应用。如果智能体生成的应用也采用这种技术组合,我不仅更容易理解,还能直接将其投入实际应用。

    本次验证中,我首先明确告知智能体需用 Python+Angular 实现,随后在不额外说明的情况下让其开发应用,以此检验它是否会主动使用 Angular。若智能体在未明确告知的情况下仍能选择 Angular,就说明它理解了我的偏好,实现了个性化,称得上是贴心的智能体。

    2.3.1 未理解用户偏好的情况

    我们先确认未设置 Strands Agents Tools、不使用记忆功能时的智能体表现。

    首次对话:明确告知所用框架并让智能体实现

    “请用 Python+Angular 开发一个 LLM 聊天 GUI 应用。”

    智能体按照需求,使用 Python+Angular 实现了应用:

    “将为您开发 LLM 聊天应用。我们将以 Python(FastAPI)作为后端,Angular 作为前端进行构建。”(其余省略)

    另起线程:不告知框架,让智能体实现

    若让同一个智能体开发,它有可能从对话历史中推断出需使用 Angular。为避免这种情况,我先停止了智能体应用,重新初始化一个新的智能体,再发出以下请求:“开发一个 RAG 聊天 GUI 应用。”

    由于新智能体未保留之前的对话记忆,不记得上次使用 Angular 作为前端框架的情况。因此,它并未采用我习惯使用的 Angular,而是生成了基于 Streamlit 的代码:

    “将为您开发 RAG 聊天 GUI 应用。我们将使用 Streamlit,构建一个包含文档上传、向量检索、聊天功能的完整应用。”(其余省略)

    2.3.2 已理解用户偏好的情况

    接下来,我们启用 Strands Agents Tools 的 Memory(记忆)工具,通过使用 AgentCore Memory,验证智能体是否能记住过往对话,从而成为具备个性化能力的智能体。

    首次对话:明确告知所用框架并让智能体实现

    “请用 Python+Angular 开发一个 LLM 聊天 GUI 应用。”

    智能体同样按照需求完成了开发:

    “好的,我们来用 Python + Angular 开发 LLM 聊天 GUI 应用!将采用全栈架构,打造一个实用的聊天应用。”(其余省略)

    另起线程:不告知框架,让智能体实现

    此处我们同样先创建一个新的智能体,再发起请求:“开发一个 RAG 聊天 GUI 应用。”

    智能体回复:

    “参考过往的交互记录,发现您对用 Python 和 Angular 开发 LLM 聊天应用很感兴趣!本次我们来开发一个集成了 RAG(检索增强生成)功能的聊天 GUI 应用吧。

    以下为您建议的技术架构:

    技术栈

    • 后端:Python(FastAPI)
    • 前端:Angular
    • RAG:LangChain + 向量数据库(Chroma/FAISS)
    • LLM:OpenAI API 或 Hugging Face

    (其余省略)”

    可见,智能体记住了此前用户使用 Python+Angular 开发 GUI 应用的偏好,因此主动提议采用相同技术架构进行开发。

    这表明 AgentCore Memory 实现了预期功能,能够输出符合用户偏好的响应。

    2.4 查看 Memory的内容

    由于无法从 AWS 控制台直接查看 Memory 的内容,我们通过 AWS 命令行工具(AWSCLI)获取相关数据。

    从获取的结果中可以看出,智能体已将 “对开发 LLM 应用感兴趣”“使用 Python+Angular 开发应用” 识别为用户的偏好。

    $ aws bedrock-agentcore list-memory-records \
        --memory-id $memoryId \
        --namespace /strategies/memory_preference/actors/sy
    {
        "memoryRecordSummaries": [
            {
                "memoryRecordId": "mem-cacf3145-324f-4f30-8e83-dade742bc2e0",
                "content": {
                    "text": "{\"context\":\"对开发LLM(大型语言模型)聊天应用表现出兴趣\",\"preference\":\"对基于LLM的聊天应用感兴趣\",\"categories\":[\"人工智能\",\"技术\",\"应用开发\"]}"
                },
                "memoryStrategyId": "memory_preference",
                "namespaces": ["/strategies/memory_preference/actors/sy"]
            },
            {
                "memoryRecordId": "mem-77a9f50f-8589-4229-874b-2dcac251708f",
                "content": {
                    "text": "{\"context\":\"用户要求使用Python+Angular开发LLM聊天GUI应用\",\"preference\":\"对使用Python和Angular开发应用感兴趣\",\"categories\":[\"编程\",\"软件开发\",\"技术\"]}"
                },
                "memoryStrategyId": "memory_preference",
                "namespaces": ["/strategies/memory_preference/actors/sy"]
            }
        ]
    }
    

    当 Strands Agents 的智能体调用该 Memory 时,可通过向量检索获取匹配度高的内容作为相关记忆。

    以下是第二次运行智能体时,Strands Agents 实际执行的工具调用内容,从中可看出其利用了向量检索的分数来获取相关记忆:

    agent.agent.tool.agent_core_memory(
        action='retrieve',
        query='RAG 聊天 GUI 应用 开发 编程',
    )
    {
        "memoryRecordSummaries": [
            {
                "content": {
                    "text": "{\"context\":\"用户要求使用Python+Angular开发LLM聊天GUI应用\",\"preference\":\"对使用Python和Angular开发应用感兴趣\",\"categories\":[\"编程\",\"软件开发\",\"技术\"]}"
                },
                "namespaces": ["/strategies/memory_preference/actors/sy"],
                "score": 0.49530885
            }
        ]
    }
    

    3. 应用示例

    通过将 Strands Agents Tools 与 AgentCore Memory 相结合,智能体能够记住对话上下文,并根据用户的偏好和目标提供个性化服务。

    此处将介绍几个在实际业务或服务中的应用场景。

    客户支持

    将用户过往的咨询内容及问题处理记录存储在长期记忆中,用户无需每次都从基础情况开始说明。例如,在处理错误问题时,智能体可实现 “上次出现的是XX错误,这次看起来是△△错误呢” 这类理解上下文的支持服务。

    持续学习支持

    作为教育类应用或企业内部培训的辅助工具,智能体可记录学习者的进度及薄弱领域,并据此调整出题内容和讲解方式。用户能获得 “以前你对这个问题不太擅长,这次已经能解出来了呢” 这类反馈,从而得到更具持续性的学习支持。

    个性化推荐系统

    在提供产品推荐或内容建议的应用中,智能体可结合用户的偏好及过往选择进行推荐。例如,旅行方案推荐智能体可实现 “上次您更喜欢安静的温泉胜地,这次为您推荐氛围相似的〇〇地区” 这类响应。

    4. 总结

    通过将 Strands Agents 与 Bedrock AgentCore 的 Memory 功能相结合,能够实现传统对话式 AI 难以做到的 “保持上下文”“结合个人偏好提供服务” 等能力。

    本文通过一个简单的聊天应用,对 AgentCore Memory 的功能进行了验证。

    结果表明,利用 Memory 工具能够为用户提供更自然、更具连贯性的体验。

    未来,还需要应对更复杂的应用场景,例如提升记忆的准确性、实现记忆的删除与修改控制、支持多用户使用等。可以说,让智能体具备 “记忆” 能力,是未来 AI 应用发展中的关键功能之一。

  • 尝试用 Cline × Amazon Bedrock 进行 CRUD 应用的全栈开发

    最近,Cline 作为一款开发辅助 AI 智能体备受关注。

    相关参考链接:github.com

    Cline 是 Visual Studio Code(VSCode)的扩展插件,其特点不仅限于生成代码,还能连贯完成命令执行、运行验证及调试等一系列操作。

    Cline 支持指定任意生成式 AI 模型来生成代码。因此,将其与安全性高、可在实际开发场景中运用的 Amazon Bedrock 结合,便能在业务场景中发挥作用。本次,我们将以 Bedrock 作为大语言模型(LLM),围绕 “能否开发具备 CRUD 功能的应用” 这一目标,以开发 TODO 应用为主题展开尝试。

    概述

    什么是 Cline?

    Cline 是一款以 VSCode 扩展插件形式提供的 AI 智能体,只需简单指令,就能生成整个应用的代码。

    其核心特点如下:

    • 可完成命令执行(例如:创建 / 删除文件或目录、安装依赖库、启动已开发的应用等);
    • 可自动完成运行验证与调试;
    • 数据不会发送至 Cline 服务器(因支持配置任意生成式 AI 模型的 API,并通过该 API 生成内容)。

    使用 Amazon Bedrock 的优势

    如前所述,Cline 可与多种生成式 AI 模型联动,本次我们选择使用 Amazon Bedrock。使用 Bedrock 的优势如下:

    • 输入数据不会被用于模型训练,安全性更有保障;
    • 只需通过配置,即可切换使用多个模型。

    基于以上原因,在业务场景中使用 Cline 时,Amazon Bedrock 会成为极具竞争力的选择。接下来,我们就实际尝试用 Cline × Amazon Bedrock 开发具备 CRUD 功能的 Web 应用。

    TODO 应用的概述

    本次开发的 TODO 应用,最终实现效果如下:

    该 TODO 应用支持填写标题、截止日期和说明来添加任务,同时会记录任务的 “是否完成” 状态,还具备删除功能。下面我们开始为开发这款 TODO 应用做准备。

    开发前的准备工作

    创建 IAM 用户

    我们创建了供 Cline 调用 Bedrock 时使用的 IAM 用户,并为其配置了以下权限。实际场景中应进一步缩小权限范围,本次为简化操作,暂赋予 Bedrock 全访问权限。此外,由于 Cline 需要会话令牌,因此还为该用户配置了获取会话令牌的权限。

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "AllowBedrockAll",
          "Effect": "Allow",
          "Action": "bedrock:*",
          "Resource": "*"
        },
        {
          "Sid": "AllowStsGetSessionToken",
          "Effect": "Allow",
          "Action": "sts:GetSessionToken",
          "Resource": "*"
        }
      ]
    }
    

    Cline 的配置

    我们对 Cline 进行了调用 Bedrock 所需的配置。在配置界面中,填入了上一节创建的 IAM 用户的访问密钥、密钥和会话令牌。

    本次选用的模型是 Claude 3.7 Sonnet。此前曾尝试用成本更低的 Claude 3.5 Haiku 开发应用,但模型精度不稳定,例如明明需要显示 “Task Completed”,但应包含 Docker 文件的文件夹中却未生成任何文件等问题。虽然 Cline 在调试阶段会尝试修复这些问题,但过程中需要反复试错修改,既耗费时间,也产生了不必要的成本。因此,若要开发的不是简单脚本,而是像 CRUD 应用这样具备一定复杂度的完整系统,从一开始就使用 Claude 3.7 Sonnet,模型精度会更稳定。

    搭建 Linux 命令执行环境

    Cline 的一大核心特点是支持执行命令,但它默认倾向于执行 Linux 命令。

    而本次我们在 Windows 环境下进行验证,VSCode 的默认终端是 Powershell。若不做调整,Cline 会尝试执行 Linux 命令,导致命令全部报错。

    因此,为了在 Windows 环境下也能执行 Linux 命令,我们按以下步骤进行了设置:

    1. 安装 Git Bash;
    2. 将 Git Bash 设置为 VSCode 的默认终端。

    开发 TODO 应用

    提示词

    本次传递给 Cline 的任务提示词如下:

    请开发一个 TODO 应用
    
    #需求
    
    -支持将任务以带复选框(Checkbox)的项目形式进行添加和删除。
    
    -已完成的任务,通过勾选复选框,文字需变为浅色并添加删除线。
    
    -支持为每个任务输入截止日期(非必填项)。
    
    #约束条件
    
    -采用 PostgreSQL 实现 CRUD(创建、读取、更新、删除)操作。
    
    -通过 Docker 搭建数据库(DB)。
    
    -后端与前端不使用 Docker,直接在运行环境中启动。
    
    -开发完成后,需完成应用的启动操作。
    
    -界面需设计得现代且美观。

    此外,我们在 Cline 的设置界面中,按以下内容配置了 “Custom Instructions”。

    Custom Instructions 是用于编写通用规则等内容的部分,会在每次向 AI 发送请求时,自动追加到提示词的末尾。

    #运行环境信息
    
    -运行环境为 Windows。
    
    -Docker 环境由 Rancher Desktop 提供。
    
    #实现规则
    ##通用规则
    
    -为每个代码块添加中文注释。
    
    -按合理的文件夹结构创建项目
    
    ##后端
    
    -按 Google 风格编写文档字符串(docstring)。
    
    -使用 Python 实现。
    
    -通过 pyenv、Poetry 创建虚拟环境(pyenv 与 Poetry 已提前在环境中安装完成)。
    
    ##前端
    
    -使用 React 实现。
    
    -通过 npm 进行包管理。

    在 Custom Instructions 中,我们指定 “环境搭建工具使用已提前安装的版本”。若未做此指定,Cline 会尝试从安装这些工具开始操作,过程中会出现大量试错,额外耗费时间与成本。因此,开发环境的准备工作由人工完成会更高效。

    使用 Cline 的开发结果

    根据上一节的提示词向 Cline 下达指令后,Cline 自动完成了以下一系列操作:

    1. 创建文件夹结构
    2. 安装所需依赖库
    3. 设计数据库 schema(表结构)
    4. 通过 Docker 搭建数据库
    5. 实现并启动前端与后端
    6. 运行验证与调试

    最终生成的成果如下

    本次仅使用简单提示词,未过多指定细节,但 Cline 仍以接近人工开发的水平完成了项目,例如:

    • 前端使用 Material-UI(Material Design 组件库)
    • 后端使用 FastAPI,并创建了模型类
    • 数据库 schema 中包含 “创建时间”“更新时间” 字段

    此外,本次开发的代码量约为 0.5KL,耗费成本约 5.2 美元。与人工完成 “从开发到运行验证” 所需的人力成本相比,成本大幅降低。

    试用应用

    接下来,我们实际试用一下这款应用。下图展示了 “添加任务后,将其中 1 个任务标记为已完成” 的效果

    我们尝试直接访问数据库,发现操作结果已实时同步到数据库中

    另外,当我们从界面中删除已完成的任务时,数据库中也执行了物理删除操作

    总结

    通过 “Cline×Amazon Bedrock” 的组合,我们借助安全的生成式 AI 模型,完成了 CRUD 应用从 “界面开发” 到 “数据库实现” 的全流程开发与运行验证。

    同时,我们也得出了以下几点感受:

    1. 开发环境的准备工作,由人工提前完成效率更高;
    2. 若要稳定且精准地开发 “CRUD 应用” 这类具备一定复杂度的项目,需使用 Claude 3.7 Sonnet 模型。

    借助 Amazon Bedrock,Cline 在业务场景中的实用性大幅提升,未来我们将积极推动其应用。

  • 活用 Amazon Bedrock 的 Rerank API 提升 RAG 精度

    活用 Amazon Bedrock 的 Rerank API 提升 RAG 精度

    在 RAG(检索增强生成:Retrieval-Augmented Generation)为用户提供准确信息的过程中,检索精度尤为关键。

    而提升检索精度的方法之一便是 “重排序(Rerank)”。

    通过执行重排序操作,将检索得到的结果按相关度重新排序,能更轻松地针对用户所需信息给出回答。

    如今,Amazon Bedrock 已新增支持重排序的模型,且可与 Bedrock Knowledge Base 搭配使用。

    以往,实现这一功能需要自行托管模型等,颇为繁琐;而现在,只需在向 Knowledge Base 发起的检索请求中添加相关设置,即可一并执行检索与重排序操作,且仅能获取重排序后的结果。

    本次我们将实际使用重排序模型,验证检索结果会发生怎样的变化。

    1. 前言

    1.1 什么是重排序(Rerank)

    在包含 Bedrock Knowledge Base 在内的 RAG 检索中,向量检索的应用十分广泛。

    然而,仅依靠向量检索往往无法达到足够的检索精度,难以给出恰当的回答。

    因此,对通过向量检索获取的文档进行重排序处理,可使相关度更高的文档出现在检索结果的靠前位置。

    重新排序的图像

    1.2 以往的实现方式

    此前,要在 RAG 系统中集成重排序处理,需搭建 SageMaker 实例、托管重排序专用模型并执行推理。

    例如,在 2024 年 8 月时,若要使用 Cohere Rerank 3,就需按照下述文章的说明创建 SageMaker 实例。

    aws.amazon.com

    这种方式存在诸多问题,如需要投入精力准备 SageMaker 实例与重排序模型,且会产生运营成本。

    1.3 Bedrock 支持的重排序模型

    自 2024 年 12 月起,可通过 Bedrock 使用重排序模型。

    借助该重排序模型,无需自行托管模型,仅通过调用 API 即可执行重排序操作。

    这不仅省去了运营管理的繁琐工作,还无需一直启动服务器,只需根据使用量付费,让用户能轻松开启重排序功能的使用。

    除了可通过 Bedrock 的 InvokeModel API 调用外,还支持通过 Bedrock Knowledge Base 的 Rerank API、Retrieve API、RetrieveAndGenerate API、RetrieveAndGenerateStream API 进行调用。

    截至 2025 年 1 月,提供的模型有 Amazon Rerank 1.0(以下简称 Amazon Rerank 模型)和 Cohere Rerank 3.5(以下简称 Cohere Rerank 模型)。

    2. 尝试应用重排序模型

    本次验证将使用本文中已采用的、模拟酒店评论检索的数据。

    此次以 “烤肉好吃的酒店” 为检索词,期望 “使用本地产蔬菜和肉类制作的烤肉料理” 的第 10 条评论以及 “炭火烤制的牛排” 的第 7 条评论能出现在检索结果的靠前位置。

    重排序模型选用 Amazon Rerank 模型。

    序号内容
    1这家酒店的温泉堪称顶级疗愈。源泉直供的温泉水格外柔和,泡完后肌肤感觉滑溜溜的。从露天温泉能眺望到美丽的群山,夜晚还能一边泡澡一边欣赏满天繁星。这是一家让人想反复前往的温泉酒店。
    2酒店的温泉非常舒服,能让人彻底放松。室内温泉和露天温泉各具特色,尤其是从露天温泉看到的庭院景色美不胜收,可欣赏到四季不同的美景。水温也恰到好处,长时间浸泡也不会觉得疲惫。
    3早就听闻这是一家以温泉为特色的酒店,实际体验远超预期。因直接使用天然温泉源泉,水质极佳,泡完后身体持续暖暖的。我们还预约了私人温泉,在专属空间里度过了惬意的时光。
    4温泉区域宽敞开阔,视野极佳。从露天温泉能一览大海,可伴着海浪声悠闲度日。水温也不会过高,能慢慢暖遍全身,非常满意。此外,还支持当日往返使用,让人能轻松前来,这点很贴心。
    5温泉散发着令人舒心的硫磺香气,让人真切感受到来到了温泉胜地。温泉水功效显著,能明显感觉到肌肤变得光滑。这里有多个温泉池,有时特定时段还能独享,让人体验到奢华感。另外,泡完温泉后提供的冰镇饮品也是个惊喜服务。
    6酒店的餐食宛如艺术品。大量使用本地新鲜食材制作的怀石料理,不仅外观精美,每一道菜都能让人感受到制作的用心。尤其是用当季海鲜制作的刺身,堪称绝品,仅凭这一点就想再次前来。
    7晚餐有很多本地特色菜,非常满意。特别是炭火烤制的牛排,入口即化,美味得让人想一再续盘。早餐种类也很丰富,用本地蔬菜制作的沙拉和手工豆腐都很美味。
    8晚餐是套餐形式,每道菜都很好吃,其中最令人印象深刻的是用本地采摘的蔬菜制作的前菜和自制甜点。采用凸显食材本味的简单烹饪方式,充分展现了食材的优良品质。早餐营养均衡,刚出炉的面包尤其美味。
    9酒店的餐食超出预期。因靠近海边,大量使用新鲜海鲜,刺身和煮鱼都非常好吃。晚餐分量充足,每道菜的调味都饱含心意。早餐的日式料理也很美味,尤其是温泉蛋堪称绝品。
    10晚餐是大量使用本地食材制作的创意料理,每道菜都能感受到巧思。特别是用本地产蔬菜和肉类制作的烤肉料理,堪称绝品,充分凸显了食材本身的味道。早餐也很用心,有手工果酱和刚出炉的面包等,非常满意。

    2.1 通过 Bedrock 的 InvokeModel API 使用

    InvokeModel API 是用于调用 Bedrock 所提供模型的 API。

    在请求体(body)中输入想要进行重排序的文档列表以及用户的查询语句后,就能在响应结果中获取到按与用户查询语句相关度从高到低重新排序的文档,以及各自的相关度(分数)。

    代码

    query = "烤肉好吃的酒店"
    documents = [
        "这家酒店的温泉堪称顶级疗愈。源泉直供的温泉水格外柔和,泡完后肌肤感觉滑溜溜的。从露天温泉能眺望到美丽的群山,夜晚还能一边泡澡一边欣赏满天繁星。这是一家让人想反复前往的温泉酒店。",
        # (省略)
    ]
    
    response = bedrock.invoke_model(
        modelId="amazon.rerank-v1:0",
        body=json.dumps({
            "query": query,
            "documents": documents,
            "top_n": 3,
        }),
    )
    
    body = json.loads(response["body"].read())
    pprint.pprint(body["results"])
    

    输出

    [{'index': 9, 'relevance_score': 0.001466458403084568},
     {'index': 6, 'relevance_score': 0.0005013742398679934},
     {'index': 8, 'relevance_score': 0.0003640086870995012}]
    

    ※重排序结果中包含的索引(index)以 0 为起始,为了与上方表格保持一致,需在索引数值上加 1。

    结果

    序号内容
    10晚餐是大量使用本地食材制作的创意料理,每道菜都能感受到巧思。特别是用本地产蔬菜和肉类制作的烤肉料理,堪称绝品,充分凸显了食材本身的味道。早餐也很用心,有手工果酱和刚出炉的面包等,非常满意。
    7晚餐有很多本地特色菜,非常满意。特别是炭火烤制的牛排,入口即化,美味得让人想一再续盘。早餐种类也很丰富,用本地蔬菜制作的沙拉和手工豆腐都很美味。
    9酒店的餐食超出预期。因靠近海边,大量使用新鲜海鲜,刺身和煮鱼都非常好吃。晚餐分量充足,每道菜的调味都饱含心意。早餐的日式料理也很美味,尤其是温泉蛋堪称绝品。

    可以确认,正如预期的那样,第 10 条和第 7 条评论内容排在了靠前位置。

    2.2 通过 Bedrock Knowledge Base 的 Rerank API 使用

    Rerank API 是作为 Knowledge Base 的功能提供的,但其本质与上述的 InvokeModel 相同,输入文档列表和用户查询语句后,就能得到重排序后的文档列表。

    代码

    region = boto3.Session().region_name
    amazon_rerank_arn = f"arn:aws:bedrock:{region}::foundation-model/amazon.rerank-v1:0"
    
    response = bedrock_agent.rerank(
        queries=[
            {
                "type": "TEXT",
                "textQuery": {
                    "text": query,
                },
            },
        ],
        sources=[
            {
                "inlineDocumentSource": {
                    "textDocument": {
                        "text": document,
                    },
                    "type": "TEXT",
                },
                "type": "INLINE",
            } for document in documents
        ],
        rerankingConfiguration={
            "type": "BEDROCK_RERANKING_MODEL",
            "bedrockRerankingConfiguration": {
                "numberOfResults": 3,
                "modelConfiguration": {
                    "modelArn": amazon_rerank_arn,
                },
            },
        },
    )
    
    pprint.pprint(response["results"])
    

    输出

    [{'index': 9, 'relevanceScore': 0.0014664584305137396},
     {'index': 6, 'relevanceScore': 0.0005013742484152317},
     {'index': 8, 'relevanceScore': 0.0003640086797531694}]
    

    可以确认,得到了与使用 InvokeModel 时完全相同的结果。

    2.3 通过 Bedrock Knowledge Base 的 Retrieve API 使用

    与 InvokeModel、Rerank API 不同,在 Retrieve API 中,无需传入文档列表作为输入。

    该 API 以用户的查询语句为输入,先通过用户查询语句检索向量数据库,再将检索结果作为文档列表进行重排序。

    为了使用 Retrieve API,我们先创建了知识库,并将上述内容逐条作为一个数据块进行存储。

    首先确认不进行重排序时的结果。

    代码

    response = bedrock_agent.retrieve(
        knowledgeBaseId=knowledgebase_id,
        retrievalConfiguration={
            "vectorSearchConfiguration": {
                "numberOfResults": 3,
                "overrideSearchType": "SEMANTIC",
            },
        },
        retrievalQuery={
            "text": query,
        },
    )
    
    pprint.pprint(response["retrievalResults"])
    

    输出

    [{'content': {'text': '酒店的餐食宛如艺术品。大量使用本地新鲜食材制作的怀石料理,不仅外观精美,每一道菜都能让人感受到制作的用心。尤其是用当季海鲜制作的刺身,堪称绝品,仅凭这一点就想再次前来。',
                  'type': 'TEXT'},
      'location': {'s3Location': {'uri': 's3://xxx/006.txt'},
                   'type': 'S3'},
      'score': 0.43565163},
     {'content': {'text': '酒店的餐食超出预期。因靠近海边,大量使用新鲜海鲜,刺身和煮鱼都非常好吃。晚餐分量充足,每道菜的调味都饱含心意。早餐的日式料理也很美味,尤其是温泉蛋堪称绝品。',
                  'type': 'TEXT'},
      'location': {'s3Location': {'uri': 's3://xxx/009.txt'},
                   'type': 'S3'},
      'score': 0.435101},
     {'content': {'text': '晚餐是大量使用本地食材制作的创意料理,每道菜都能感受到巧思。特别是用本地产蔬菜和肉类制作的烤肉料理,堪称绝品,充分凸显了食材本身的味道。早餐也很用心,有手工果酱和刚出炉的面包等,非常满意。',
                  'type': 'TEXT'},
      'location': {'s3Location': {'uri': 's3://xxx/010.txt'},
                   'type': 'S3'},
      'score': 0.4281698}]
    

    结果

    序号内容
    6酒店的餐食宛如艺术品。大量使用本地新鲜食材制作的怀石料理,不仅外观精美,每一道菜都能让人感受到制作的用心。尤其是用当季海鲜制作的刺身,堪称绝品,仅凭这一点就想再次前来。
    9酒店的餐食超出预期。因靠近海边,大量使用新鲜海鲜,刺身和煮鱼都非常好吃。晚餐分量充足,每道菜的调味都饱含心意。早餐的日式料理也很美味,尤其是温泉蛋堪称绝品。
    10晚餐是大量使用本地食材制作的创意料理,每道菜都能感受到巧思。特别是用本地产蔬菜和肉类制作的烤肉料理,堪称绝品,充分凸显了食材本身的味道。早餐也很用心,有手工果酱和刚出炉的面包等,非常满意。

    当获取前 3 条结果时,第 10 条评论排在第 3 位,而第 7 条评论未出现在检索结果中。

    若使用这样的检索结果进行 RAG,恐怕难以得到高精度的回答。

    接下来,在 Retrieve API 中指定重排序模型,确认检索结果会发生怎样的变化。

    代码

    response = bedrock_agent.retrieve(
        knowledgeBaseId=knowledgebase_id,
        retrievalConfiguration={
            "vectorSearchConfiguration": {
                # (1) 首次检索时获取 10 条结果
                "numberOfResults": 10,
                "overrideSearchType": "SEMANTIC",
                "rerankingConfiguration": {
                    "bedrockRerankingConfiguration": {
                        "modelConfiguration": {
                            "modelArn": amazon_rerank_arn,
                        },
                        # (2) 对检索得到的 10 条结果进行重排序,并返回前 3 条
                        "numberOfRerankedResults": 3,
                    },
                    "type": "BEDROCK_RERANKING_MODEL",
                },
            },
        },
        retrievalQuery={
            "text": query,
        },
    )
    
    pprint.pprint(response)
    

    输出

    [{'content': {'text': '晚餐是大量使用本地食材制作的创意料理,每道菜都能感受到巧思。特别是用本地产蔬菜和肉类制作的烤肉料理,堪称绝品,充分凸显了食材本身的味道。早餐也很用心,有手工果酱和刚出炉的面包等,非常满意。',
                  'type': 'TEXT'},
      'location': {'s3Location': {'uri': 's3://xxx/010.txt'},
                   'type': 'S3'},
      'score': 0.0014721895568072796},
     {'content': {'text': '晚餐有很多本地特色菜,非常满意。特别是炭火烤制的牛排,入口即化,美味得让人想一再续盘。早餐种类也很丰富,用本地蔬菜制作的沙拉和手工豆腐都很美味。',
                  'type': 'TEXT'},
      'location': {'s3Location': {'uri': 's3://xxx/007.txt'},
                   'type': 'S3'},
      'score': 0.0004994205664843321},
     {'content': {'text': '酒店的餐食超出预期。因靠近海边,大量使用新鲜海鲜,刺身和煮鱼都非常好吃。晚餐分量充足,每道菜的调味都饱含心意。早餐的日式料理也很美味,尤其是温泉蛋堪称绝品。',
                  'type': 'TEXT'},
      'location': {'s3Location': {'uri': 's3://xxx/009.txt'},
                   'type': 'S3'},
      'score': 0.0003640086797531694}]
    

    结果

    序号内容
    10晚餐是大量使用本地食材制作的创意料理,每道菜都能感受到巧思。特别是用本地产蔬菜和肉类制作的烤肉料理,堪称绝品,充分凸显了食材本身的味道。早餐也很用心,有手工果酱和刚出炉的面包等,非常满意。
    7晚餐有很多本地特色菜,非常满意。特别是炭火烤制的牛排,入口即化,美味得让人想一再续盘。早餐种类也很丰富,用本地蔬菜制作的沙拉和手工豆腐都很美味。
    9酒店的餐食超出预期。因靠近海边,大量使用新鲜海鲜,刺身和煮鱼都非常好吃。晚餐分量充足,每道菜的调味都饱含心意。早餐的日式料理也很美味,尤其是温泉蛋堪称绝品。

    通过执行重排序,第 10 条和第 7 条内容占据了前 2 位。

    这样一来,就能为用户提供更多其所需的信息了。

    3. Amazon Rerank 模型与 Cohere Rerank 模型的对比

    接下来,我们使用同样可在 Bedrock 上使用的 Cohere Rerank 模型对相同内容进行测试。

    只需将 modelArn 替换为 Cohere Rerank 模型对应的 ARN,就能切换所使用的重排序模型。

    操作起来非常简便。

    代码

    cohere_rerank_arn = f"arn:aws:bedrock:{region}::foundation-model/cohere.rerank-v3-5:0"
    # (省略)
    

    输出

    [{'content': {'text': '晚餐是大量使用本地食材制作的创意料理,每道菜都能感受到巧思。特别是用本地产蔬菜和肉类制作的烤肉料理,堪称绝品,充分凸显了食材本身的味道。早餐也很用心,有手工果酱和刚出炉的面包等,非常满意。',
                  'type': 'TEXT'},
      'location': {'s3Location': {'uri': 's3://xxx/010.txt'},
                   'type': 'S3'},
      'score': 0.3279808461666107},
     {'content': {'text': '酒店的餐食宛如艺术品。大量使用本地新鲜食材制作的怀石料理,不仅外观精美,每一道菜都能让人感受到制作的用心。尤其是用当季海鲜制作的刺身,堪称绝品,仅凭这一点就想再次前来。',
                  'type': 'TEXT'},
      'location': {'s3Location': {'uri': 's3://xxx/006.txt'},
                   'type': 'S3'},
      'score': 0.1456373631954193},
     {'content': {'text': '晚餐有很多本地特色菜,非常满意。特别是炭火烤制的和牛牛排,入口即化,美味得让人想一再续盘。早餐种类也很丰富,用本地蔬菜制作的沙拉和手工豆腐都很美味。',
                  'type': 'TEXT'},
      'location': {'s3Location': {'uri': 's3://xxx/007.txt'},
                   'type': 'S3'},
      'score': 0.11919290572404861}]
    

    结果

    序号内容
    10晚餐是大量使用本地食材制作的创意料理,每道菜都能感受到巧思。特别是用本地产蔬菜和肉类制作的烤肉料理,堪称绝品,充分凸显了食材本身的味道。早餐也很用心,有手工果酱和刚出炉的面包等,非常满意。
    6酒店的餐食宛如艺术品。大量使用本地新鲜食材制作的怀石料理,不仅外观精美,每一道菜都能让人感受到制作的用心。尤其是用当季海鲜制作的刺身,堪称绝品,仅凭这一点就想再次前来。
    7晚餐有很多本地特色菜,非常满意。特别是炭火烤制的和牛牛排,入口即化,美味得让人想一再续盘。早餐种类也很丰富,用本地蔬菜制作的沙拉和手工豆腐都很美味。

    与使用 Amazon Rerank 模型时相比,第 7 条的排名下降了一位,但仍在前三之列。

    第 6 条内容虽然是关于海鲜料理而非肉类料理的评论,但它是关于美味料理的评论,而非温泉相关,因此我认为其得分较高。

    这样一来,在 RAG 生成回答时,也能在不缺失信息的情况下进行内容生成了。

    4. 其他

    4.1 调用速度

    我们对 Amazon Rerank 模型与 Cohere Rerank 模型的响应速度是否存在差异进行了验证。

    针对俄勒冈区域的模型,我们分别对相同请求各执行 5 次,通过比较响应时间的平均值来分析差异。

    Amazon Rerank 模型

    序号响应时间(秒)
    10.895
    20.687
    30.734
    40.828
    50.775
    平均0.784

    Cohere Rerank 模型

    序号响应时间(秒)
    10.454
    20.508
    30.533
    40.495
    50.453
    平均0.489

    对比结果显示,Cohere Rerank 模型的速度约为 Amazon Rerank 模型的 1.5 倍。

    4.2 费用

    本次使用的模型费用如下表所示。

    虽然相较于非重排序模型(例如 Amazon Nova Lite 为每 1000 个输出令牌 0.00024 美元),这些重排序模型的费用略显偏高,但这也意味着仅通过 API 调用就能使用到如此复杂的功能。

    序号模型费用
    1Amazon Rerank 模型1 美元 / 1000 次查询
    2Cohere Rerank 模型2 美元 / 1000 次查询

    总结

    我们对 Bedrock 新增的重排序模型进行了验证,确认其对改善检索结果具有实际作用。

    实验表明,通过执行重排序操作,能够使更贴合用户输入的内容出现在检索结果的靠前位置。

    此外,Bedrock Knowledge Base 的优势在于,无需自行开发实现,仅通过修改设置就能实现检索效果的大幅提升。

    本次验证仅进行到检索(retrieve)阶段,而若使用 retrieve_and_generate 功能,还可将回答生成的过程也交由 Bedrock 完成。

    未来,我希望活用 Bedrock 的重排序功能,开发出更贴合用户意图的 RAG 系统。

  • 使用 Aurora Serverless v2 作为 Amazon Bedrock Knowledge Bases 的向量数据库

    使用 Aurora Serverless v2 作为 Amazon Bedrock Knowledge Bases 的向量数据库

    今天我尝试了使用 Amazon Bedrock Knowledge Bases,并将 Amazon Aurora PostgreSQL 用作向量数据库。

    去年 12 月,Amazon Bedrock Knowledge Bases 新增了可快速创建 Aurora PostgreSQL 作为向量数据库的功能,大幅简化了设置流程。

    本次我也将利用这一快速创建功能进行设置。

    aws.amazon.com

    1. 将 Aurora PostgreSQL 配置为向量存储

    事前准备

    本次将 S3 用作 RAG(检索增强生成)的外部数据源。之后,我们会确认 LLM(大语言模型)的回答是否参考了存储在 S3 中的资料。

    Knowledge Bases 的创建

    在 AWS 管理控制台中,进入 Bedrock 页面,仅通过 GUI 操作即可轻松创建 Knowledge Bases。

    点击 “Knowledge Base with vector store”(带向量存储的知识库),即可跳转至 Knowledge Bases 创建页面。

    在 “步骤 2 配置数据源” 中,指定事前准备好的 S3 的 URI。而 “步骤 3 选择嵌入模型并配置向量数据库” 则是本次的核心内容。

    向量数据库的选项中新增了 “Amazon Aurora PostgreSQL Serverless” 这一项目,请选择此项。

    ※向量数据库的可选范围因区域而异,本文中测试使用的是东京区域。

    之后点击 “下一步”,确认创建内容后即可完成设置。仅需通过 GUI 操作即可完成,直观又简单!

    在 RDS 控制台中可以确认已创建的数据库。

    数据库表的创建情况如下所示。

    Bedrock_Knowledge_Base_Cluster=> \d bedrock_knowledge_base
            Table "bedrock_integration.bedrock_knowledge_base"
      Column   |        Type         | Collation | Nullable | Default
    -----------+---------------------+-----------+----------+---------
     id        | uuid                |           | not null |
     embedding | public.vector(1536) |           |          |
     chunks    | text                |           |          |
     metadata  | jsonb               |           |          |
    Indexes:
        "bedrock_knowledge_base_pkey" PRIMARY KEY, btree (id)
        "bedrock_knowledge_base_embedding_idx" hnsw (embedding public.vector_l2_ops)
    

    Knowledge Bases 的测试

    选择已创建的 Knowledge Bases 后,会出现 “测试知识库”页面。在此处向 LLM 提问,测试是否能返回预期的回答。

    本次我提出了 “敏捷开发的优势是什么?“ 这一问题。结果如预期般返回了参考了事前准备并存储在 S3 中的资料的回答,看起来运行正常。

    2. 与 OpenSearch Serverless 的对比

    OpenSearch Serverless 是被广泛用作向量数据库的代表性服务。此处将整理其与 Aurora Serverless v2 在实际使用中的差异。

    功能

    当使用 Aurora PostgreSQL 作为向量数据库时,仅支持语义搜索这一种检索类型。

    而使用 OpenSearch Serverless 时,则可在混合搜索与语义搜索之间进行选择。

    • 语义搜索:并非简单的关键词匹配,而是检索语义上相关的信息。
    • 混合搜索:将关键词检索与语义搜索相结合进行信息检索。

    从检索功能性来看,OpenSearch Serverless 更具优势。若需融入关键词检索功能,建议选择 OpenSearch Serverless。

    成本

    OpenSearch Serverless 的计算费用采用计时收费模式,即便处于未使用状态,仍会产生每小时的费用。以美国东部(弗吉尼亚北部)区域为例,每个单位的费用为 0.24 美元 / 小时。根据文档说明,至少会按 2 个单位计费,因此每月的费用约为 0.24 美元 / 小时 × 720 小时 × 2 = 345 美元。

    相比之下,Aurora Serverless v2 不仅单价低廉(0.12 美元 / 单位 / 小时),还支持缩容至 0 个单位。因此,能够有效控制未使用状态下的成本。

    aws.amazon.com

    查看此前通过快速创建功能搭建的 Aurora PostgreSQL 实例配置,确认其确实支持缩容至 0 个单位,与预期一致。

    在 CloudWatch 中查看单位使用率(ACU),可以确认实例在未使用时会自动缩容至 0 个单位。

    3. 检索速度确认

    最后,我们将验证文档数量增加时的检索速度及 ACU(Aurora 计算单位)变化情况。数据源采用 Kaggle 上的 “BBC News Summary” 数据集,将约 9000 条数据存储至 S3 中。

    参照 “1. 将 Aurora PostgreSQL 配置为 Bedrock Knowledge Bases 的向量数据库” 中的方法,向 LLM 发起提问。结果显示,与文档数量较少时相同,回答在数十毫秒内即可返回。对于本次使用的数据集规模而言,检索速度似乎不存在明显问题。

    查看 ACU 数据可知:文档导入时的 ACU 使用率约为 30%(16(最大扩容单位数)× 0.3 = 5 个单位),LLM 生成回答时的 ACU 使用率约为 15%(16 × 0.15 = 2.5 个单位)。

    向量数据库的 ReadLatency(读取延迟)控制在 0.01 秒以内,使用体验较为流畅。

    4. 总结

    本次尝试了在 Bedrock Knowledge Bases 中使用 Aurora Serverless v2 作为向量数据库。

    借助快速创建功能,仅需几次 GUI 点击操作,即可轻松完成向量数据库的搭建。对于 “控制未使用状态下成本” 这一需求,也能够轻松实现。

    最后提醒

    仅删除 Bedrock Knowledge Bases,并不能移除通过快速创建功能生成的向量数据库等其他关联资源。若不再需要这些资源,请务必手动删除,避免遗漏。

  • 借助 Amazon Nova 模型与 Bedrock Knowledge Base 实现视频检索

    借助 Amazon Nova 模型与 Bedrock Knowledge Base 实现视频检索

    不知您是否有过想要检索视频的经历?

    比如,只依稀记得视频里提到过某些内容,但这些内容并未体现在视频标题中,导致无论如何都找不到对应的视频。

    或许如果能像使用 Google 搜索那样检索就好了,但对于公司内部的视频或工作中使用的视频而言,事情往往没那么简单。

    为了解决这类困扰,我们尝试利用 Amazon Nova 模型与 Amazon Bedrock Knowledge Base 开发了一款工具。

    通过使用 Bedrock Knowledge Base,无需自行开发文档导入与检索功能,只需将视频的摘要结果存入 S3,即可轻松实现联动。

    也就是说,能够在最大限度降低开发成本的同时,开发出高性能的应用程序。

    构成图

    1. 视频检索想要实现的目标

    如果视频标题中包含目标语句,那么通过标题就能进行检索,但对于仅在视频部分内容中提及的信息等,很难通过字符串进行检索。

    此外,有时用户并非对某一特定视频感兴趣,而是希望广泛检索主题相同的视频。

    在本次视频检索项目中,为实现此类模糊检索,我们考虑通过 Bedrock Knowledge Base 进行向量检索。

    2. 实现方法

    大致步骤如下:

    1. 使 Amazon Nova 模型可对视频进行摘要处理
    2. 使摘要结果可导入 Bedrock Knowledge Base
    3. 实现视频检索处理
    4. 制作检索界面

    下面分别进行详细说明。

    2.1. 使 Amazon Nova 模型可对视频进行摘要处理

    通过模型生成摘要

    Amazon Nova 模型除了可接收文本、图像输入外,还能接收视频输入。

    我们将视频及其文字稿与下述提示词一同输入模型,让模型生成摘要文本。

    本次我们从 YouTube 频道视频中,选取了时长 1 分钟以内的视频,并上传至 S3。

    视频上传至 S3 后,Lambda 会接收事件触发,调用 Amazon Nova Lite 为这些视频生成说明文本,并将文本文件上传至 S3。

    该文本文件随后将成为 Knowledge Base 的导入对象。

    system_prompt = [
        {
            "text": dedent("""\
                您的任务是分析给定的视频,并说明视频中呈现的内容。
                视频的文字稿结果已记载在「文字稿:xxx」部分,请将其作为说明的依据。
                您的回复必须严格仅由视频的说明文本构成。
                请尽可能详细地进行说明。
                摘要请以中文呈现。
            """)
        }
    ]
    use_messages = [
        {
            "role": "user",
            "content": [
                {"text": f"视频名: {filename}"},
                {
                    "video": {
                        "format": "mp4",
                        "source": {"bytes": b64_content},
                    },
                },
                {"text": f"文字稿: {transcript}"},
                {"text": "请用中文说明此视频。"},
            ],
        }
    ]
    config = {"temperature": 0}
    body = {
        "schemaVersion": "messages-v1",
        "system": system_prompt,
        "messages": use_messages,
        "inferenceConfig": config,
    }
    
    response = bedrock_agent.invoke_model(
        modelId=MODEL_ID,
        body=json.dumps(body),
        contentType="application/json",
    )
    model_response = json.loads(response["body"].read())
    content = model_response["output"]["message"]["content"][0]["text"]
    

    模型会返回如下响应:

    此外,由于本次仅针对短时长视频,因此采用了直接向 API 提交视频的方式,但如果文件体积较大,则需要采取诸如读取上传至 S3 的文件、将视频分段传输后再合并等方法。

    2.2. 使摘要结果可导入 Bedrock Knowledge Base

    导入 Knowledge Base

    接下来需要通过 Knowledge Base 进行同步,以导入上述说明文本。但如果直接导入,无法实现原始视频与上传的文本文件之间的关联。

    为解决这一问题,我们使用了 Knowledge Base 的 metadata.json 功能。

    在此 JSON 文件中记载的内容,会在 Knowledge Base 同步时作为元数据保存到 OpenSearch Serverless 中,可供检索时获取。

    本次我们在元数据中指定了视频的 URL,用于检索后的界面显示。

    {
      "metadataAttributes": {
        "original_path": "s3://bucket/path/to/video.mp4"
      }
    }
    

    当视频的说明文本与对应的 metadata.json 配置完成后,即可对 Knowledge Base 进行同步。

    2.3. 实现视频检索处理

    执行检索

    检索时使用了 Knowledge Base 的 Retrieve API。

    此外,通过在检索后设置分数下限作为阈值,可确保经重排序后被判定为相关性较低的视频不纳入检索结果。

    const input = {
      knowledgeBaseId,
      retrievalQuery: {
        text: query.trim(),
      }
      retrievalConfiguration: {
        vectorSearchConfiguration: {
          numberOfResults: 20,
          overrideSearchType: "HYBRID",
          rerankingConfiguration: {
            bedrockRerankingConfiguration: {
              modelConfiguration: {
                modelArn: AMAZON_RERANK_MODEL,
              },
              numberOfRerankedResults: 10,
            },
            type: "BEDROCK_RERANKING_MODEL",
          },
        },
      },
    };
    const command = new RetrieveCommand(input);
    return client.send(command);
    

    可按如下方式获取视频的概要及视频文件路径:

    {
      "retrievalResults": [{
        "content": {
          "text": "该视频介绍了远程办公中的 IT 工程师想吃的豆沙包排名……",
          "type": "TEXT"
        },
        "location": {
          "s3Location": {
            "uri": "s3://bucket/path/to/summary.txt"
          },
          "type": "S3"
        },
        "metadata": {
          "original_path": "s3://bucket/path/to/video.mp4"
        }
      }]
    }
    

    2.4. 制作检索界面

    本次使用 bolt.new 制作了执行上述检索的界面。

    虽然我不太擅长前端开发,但只需用中文下达指令,就能制作出非常不错的应用,这一点让我很惊喜。

    制作的检索应用
    检索结果

    3. 结果

    3.1. 尝试用视频中包含的语句进行检索

    首先,我们尝试使用既包含在视频标题中、也包含在生成式 AI 生成的摘要文本中的关键词进行检索。

    经确认,目标视频会显示在检索结果的第一位。

    当遇到 “想再看那个视频,但用传统检索方式搜不到” 的情况时,使用这款应用就能立即找到想看的视频。

    “美味的豆沙包”

    3.2. 尝试用视频中不包含的语句进行检索

    接下来,我们尝试用未出现在标题和摘要文本中,但凭借向量检索可能捕捉到相关内容的语句进行了检索。

    此次检索也成功命中了一段视频,内容是 2018 年参加在美国旧金山举办的 “Elastic {ON}” 大会时的场景。

    虽然本次知识库中仅导入了 Elastic {ON} 相关的视频,但如果预先导入其他海外大会的视频,就能实现 “并非想找某一特定视频,而是希望广泛获取同类视频” 的需求。

    海外大会的场景

    总结

    目前,Bedrock Knowledge Base 尚无法直接输入视频,但通过使用 Amazon Nova 生成视频说明文本,我们间接实现了视频检索功能。

    虽然通过自行对视频进行嵌入处理也能实现相同功能,但 Bedrock Knowledge Base 的优势在于可轻松集成内容导入与检索能力。

    内容导入仅需将文件放入 S3 并执行 “同步” 操作即可,检索也只需调用 Retrieve API。借助 Retrieve API,还能通过重排序功能轻松优化检索结果。

  • 使用 GraphRAG Toolkit 在 Amazon Bedrock 中构建 GraphRAG

    使用 GraphRAG Toolkit 在 Amazon Bedrock 中构建 GraphRAG

    此次,我想借助 AWS 提供的开源工具 GraphRAG Toolkit,入门 GraphRAG 技术。

    使用 GraphRAG Toolkit,能够以低代码方式实现基于 Amazon Neptune 和 Amazon OpenSearch Serverless 的 GraphRAG 系统。

    另外,请注意,它与 2024 年 12 月起可在 Bedrock Knowledge Base 中使用的 GraphRAG 是不同的工具,请勿混淆。

    1. 前言

    1.1. 什么是 GraphRAG?

    传统的 RAG(检索增强生成)采用关键词检索或向量检索来获取相关信息,而 GraphRAG 则利用知识图谱,更深入地理解检索结果的上下文,从而提取相关性更高的信息。

    在传统 RAG 中,只有通过关键词检索或向量检索命中的信息才能用于回答生成;而在 GraphRAG 中,以关键词检索或向量检索得到的结果为起点,对图谱进行遍历,即便未在检索中命中但与上下文相关的信息也能被获取,并用于回答生成。

    也就是说,GraphRAG 利用结构化的实体间关系,实现了精度更高的信息检索与上下文理解。

    1.2. 什么是 GraphRAG Toolkit?

    GraphRAG Toolkit 是 AWS 提供的开源 GraphRAG 库,提供了诸多简化基于 GraphRAG 的系统构建的功能。(参考链接:github.com

    该工具可将 Amazon Neptune Database 用作图数据库,将 Amazon OpenSearch Serverless 用作向量数据库。

    通过使用此工具包,能够从非结构化数据中提取实体及其关系,将其作为知识图谱存储;并通过针对该知识图谱查询用户问题,构建可提供相关性更高信息的应用程序。本次我们将使用该工具包来尝试 GraphRAG 技术。

    GraphRAG Toolkit 中知识图谱的基本结构

    知识图谱是一种将数据构建为实体(实际存在的事物)及其关系(关联性)的结构化数据模型,用于表达数据间的语义关联。

    通过将信息整理为 “实体” 与 “关系” 的网络,能够实现考虑关联性的检索以及逻辑性的推理。

    在 GraphRAG Toolkit 中,知识图谱通过以下术语和结构构建。(自上而下,概念从抽象宏观逐渐过渡到具体微观。)

    序号项目概述示例
    1文档(Source)表示原始文档的属性https://docs.aws.amazon.com/neptune/latest/userguide/intro.html
    2片段(Chunk)文档分割后的小单位Amazon Neptune is a fast, reliable, fully managed graph database service that makes it easy to build and run applications that work with highly connected datasets. The core of Neptune is…
    3主题(Topic)片段中记载的核心主题Amazon Neptune
    4语句(Statement)片段中书写的句子或语句The core of Neptune is a purpose-built, high-performance graph database engine.
    5事实(Fact)从语句中提炼出的事实Amazon Neptune HAS high-performance
    6实体事实的主语、宾语,对应现实世界的 “事物” 或 “概念”Amazon Neptune

    知识图谱示意图(链接:https://github.com/awslabs/graphrag-toolkit/blob/main/images/lexical-graph.png

    1.3. 什么是 Amazon Neptune?

    Amazon Neptune 是 AWS 提供的全托管型图数据库服务,能够高效管理和操作数据间的关系。

    Neptune 支持多种图模型,可实现灵活的数据操作。它不仅可用于构建知识图谱,还在社交网络分析、推荐系统等多种场景中得到应用。

    此外,其一大优势在于能够控制成本 —— 可在不使用的时段 “停止” 服务,在开发环境中还能选用 T3 实例等相对经济的实例类型。

    2. 构建环境

    本次将通过 GraphRAG Toolkit 提供的 CloudFormation 模板来搭建环境。

    架构图
    序号项目概述
    1Amazon Neptune存储知识图谱并提供检索功能
    2Amazon OpenSearch Service配合图检索使用,用于向量检索
    3Amazon Bedrock从片段中提取主题、语句、事实、实体;生成用于存入向量数据库的向量・提取模型:Claude-3-Sonnet・向量化模型:Titan Text Embedding V2
    4Notebook(笔记本)操作 GraphRAG Toolkit,执行文档导入与检索操作

    3. 导入数据

    使用上述 CloudFormation 模板搭建环境后,系统会提供多个示例笔记本。数据导入可选择以下两种笔记本之一:

    • 01-Combined-Extract-and-Build.ipynb:一站式完成从文档中提取实体等信息及构建图谱的操作
    • 02-Separate-Extract-and-Build.ipynb:将实体等信息的提取与图谱构建拆分为独立步骤执行

    文档导入按以下流程进行:

    1. 文档分割(Chunking):将文档拆分为细小的单元
    2. 提取命题(Proposition):将片段传入大语言模型(LLM),提取命题命题是为提取构建知识图谱所需的 6 类要素而生成的预处理结果,会对原始文档进行清洗,例如将复杂句子拆分为简单易懂的句子、展开代词和缩写等。
    3. 提取核心要素:将命题传入 LLM,提取主题、语句、事实、实体
    4. 构建并导入知识图谱:根据提取的实体等信息构建知识图谱,存入图数据库
    5. 向量化并导入向量数据库:将语句传入 LLM 进行嵌入(Embedding)处理,生成向量后存入向量数据库

    使用 GraphRAG Toolkit 时,只需调用 extract 方法,即可一键执行上述所有流程,上手非常简单。

    3.1. 确认待导入的数据

    本次将使用 02-Separate-Extract-and-Build.ipynb 笔记本,确认提取模型如何处理原始文档,使其转化为可导入图数据库的格式。

    执行笔记本中的 “Extract(提取)” 阶段后,LLM 会解析文档,提取实体、属性以及各类关系。提取结果将保存至 extracted/ 目录下。

    通过修改配置,也可将提取结果保存至 S3。这样一来,可将已处理的数据存储在 S3 中,当新增数据需要重新构建知识图谱、或需在其他数据库中构建相同知识图谱时,无需重复执行提取操作,既能规避 LLM 的调用限制,又能节省成本。

    实际输出到 extracted/ 目录的 JSON 文件内容如下(因篇幅有限,已大幅省略)。从中可以看出,前文所述的命题、主题、语句、事实、实体均以嵌套形式存储。

    {
      "id_": "aws:xxxx",
      "metadata": {
        "url": "https://docs.aws.amazon.com/neptune-analytics/latest/userguide/what-is-neptune-analytics.html",
        "aws::graph::propositions": [
          // 命题
          "Neptune Analytics is a memory-optimized graph database engine for analytics",
          "Neptune Analytics allows getting insights and finding trends by processing large amounts of graph data in seconds"
        ],
        "aws::graph::topics": {
          "topics": [
            {
              // 主题
              "value": "Neptune Analytics",
              "entities": [
                {
                  // 实体
                  "value": "Neptune Analytics",
                  "classification": "Software"
                }
              ],
              "statements": [
                {
                  // 语句
                  "value": "Neptune Analytics is a memory-optimized graph database engine for analytics",
                  "facts": [
                    // 事实
                    {
                      "subject": {
                        "value": "Neptune Analytics",
                        "classification": "Software"
                      },
                      "predicate": {
                        "value": "OPTIMIZED FOR"
                      },
                      "complement": "memory"
                    }
                  ]
                }
              ]
            }
          ]
        }
      }
    }
    

    此外,对于中文文档,它也能很好地完成信息提取。

    {
      "id_": "aws:xxxx",
      "metadata": {
        "aws::graph::propositions": [
          // 命题
          "知识表示的方法",
          "知识图谱将数据表现为实体与关系的网络",
          "知识图谱是一种易于捕捉信息语义的强大方法"
        ],
        "aws::graph::topics": {
          "topics": [
            {
              // 主题
              "value": "Knowledge Representation",
              "entities": [
                {
                  // 实体
                  "value": "知识图谱(知识图谱)",
                  "classification": "Concept(概念)"
                }
              ],
              "statements": [
                {
                  // 语句
                  "value": "知识图谱将数据表现为实体与关系的网络",
                  "facts": [
                    // 事实
                    {
                      "subject": {
                        "value": "知识图谱(知识图谱)",
                        "classification": "Concept(概念)"
                      },
                      "predicate": {
                        "value": "REPRESENTS(表示)"
                      },
                      "object": {
                        "value": "数据(数据)",
                        "classification": "Concept(概念)"
                      }
                    }
                  ]
                }
              ]
            }
          ]
        }
      }
    }
    

    3.2. 确认已导入的数据

    通过 CloudFormation 部署 Notebook 时,图探索器(Graph Explorer)会同时完成部署。打开该图探索器,即可直观查看已构建的知识图谱。

    图探索器的打开方式

    下图展示了使用 GraphRAG Toolkit 导入 Amazon Neptune 文档后构建的知识图谱的部分内容。

    如前文所述,可以看到知识图谱分为文档、片段、主题、语句、事实、实体等层级,且各层级之间的关系均有明确标注。

    实际构建的知识图谱(部分)

    4. 检索

    在 GraphRAG 中,首先通过向量检索找到作为起点的节点,随后遍历知识图谱,最终返回检索结果。

    GraphRAG Toolkit 主要提供两种检索方法,具体如下表所示:

    序号检索方法优点缺点用途
    1TraversalBasedRetriever・处理轻量化・结果可重复性高・对未知词汇及专有名词的适配性强・灵活性较低・检索精度偏低按类别整理的 FAQ 等场景
    2SemanticGuidedRetriever・可探索符合问题意图的信息・能考虑复杂关联性・可确保检索结果的多样性・计算成本高,处理负载重需要灵活、高级的信息检索场景(如匹配问题意图、需多样化信息等)

    4.1. TraversalBasedRetriever(基于遍历的检索器)

    TraversalBasedRetriever 是通过按顺序遍历图谱结构来扩展信息的检索方法。由于它会按固定顺序遍历知识图谱,因此处理过程较为轻量化。

    TraversalBasedRetriever 包含两种具体实现方式,可单独使用其中一种,也可组合使用两种。默认设置下,返回的是两种方式组合后的结果。

    1. EntityBasedSearch(基于实体的检索)

    从查询字符串中提取关键词,在图谱中查找匹配的实体(自下而上,Bottom up)。找到匹配的实体后,从该实体出发,向事实、命题、主题等更宏观的概念层级遍历,从而完成检索。

    其特点是,即便面对未知词汇或专有名词,也能依据预先构建的知识图谱收集相关信息。由于检索从实体出发,往往能广泛获取与该实体相关的信息。

    2. ChunkBasedSearch(基于片段的检索)

    利用查询与片段间的向量相似度进行检索(自上而下,Top down)。从检索命中的片段出发,向主题、命题、事实等更微观的概念层级遍历,从而完成检索。

    由于检索从与查询语义相近的片段开始,往往能精准获取关联性更强的信息。

    4.2. SemanticGuidedRetriever(基于语义引导的检索器)

    SemanticGuidedRetriever 对语句(Statement)进行向量化处理后执行检索。针对通过向量检索获取的语句,采用波束搜索(Beam Search)与路径解析技术,从邻近节点开始探索,筛选出关联性强的信息。

    此外,该检索器还集成了多种为回答生成筛选所需信息的机制,例如:通过重排序(Rerank)筛选符合问题意图的检索结果;通过多样性过滤器确保回答信息不仅局限于相似内容,而是具备多样性。

    通过结合向量检索与图谱检索的混合模式,SemanticGuidedRetriever 既能保持较高的信息关联性,又能返回范围更广的检索结果,但相应地会增加处理负载。

    4.3. 确认检索结果

    可使用 GraphRAG Toolkit 中包含的 04-Querying.ipynb 笔记本,测试上述两种检索方法。

    我们针对每个检索器提出了 “Neptune Database 与 Neptune Analytics 有什么区别?” 的问题,并确认了大语言模型(LLM)的回答及回答所使用的文档。

    TraversalBasedRetriever

    Neptune Database 与 Neptune Analytics 呈互补关系。

    Neptune Database 是托管型图数据库服务,提供数据的持久化存储、备份、复制等功能。[https://docs.aws.amazon.com/neptune/latest/userguide/intro.html]

    而 Neptune Analytics 是用于高速分析大规模图数据的内存引擎,可从 Neptune Database 或 S3 读取图数据,通过执行预构建的图算法或自定义查询进行分析。

    [https://docs.aws.amazon.com/neptune-analytics/latest/userguide/what-is-neptune-analytics.html]

    也就是说,Neptune Database 负责图数据的持久化存储与管理,Neptune Analytics 则是实现该数据高速分析处理的服务。通过将数据存储与分析分离,可使两者各自实现专注于自身功能的性能优化。[https://docs.aws.amazon.com/neptune-analytics/latest/userguide/neptune-analytics-features.html]

    ■ 文档

    [
      {
        "source": "https://docs.aws.amazon.com/neptune-analytics/latest/userguide/what-is-neptune-analytics.html",
        "topic": "Neptune Analytics",
        "statements": [
          "Neptune Analytics can load data from a Neptune Database graph",
          "Neptune Analytics complements Amazon Neptune Database, a popular managed graph database",
          "Neptune Analytics can load data from a Neptune Database snapshot",
          "The Neptune Analytics vs Neptune Database page explains when to use Neptune Analytics and when to use Neptune Database",
          "Neptune Analytics can load graph data stored in Amazon S3"
        ]
      },
      {
        "source": "https://docs.aws.amazon.com/neptune/latest/userguide/intro.html",
        "topic": "Amazon Neptune",
        "statements": [
          "Neptune Analytics is an analytics database engine.",
          "Neptune Analytics complements Neptune database.",
          "The Neptune database has continuous backup to Amazon S3",
          "Amazon Neptune automatically detects database crashes and restarts",
          "Amazon Neptune increases database performance and availability"
        ]
      }
    ]
    

    4.3.1. SemanticGuidedRetriever(基于语义引导的检索器)

    Neptune Database 与 Neptune Analytics 是不同的产品,主要区别如下:

    Neptune Database 是托管型图数据库服务,可实现数据的持久化存储与低延迟的查询执行。[https://docs.aws.amazon.com/neptune/latest/userguide/intro.html]

    而 Neptune Analytics 是用于在内存中分析图数据的引擎,可将大规模图数据集加载到内存中,高速执行预先准备的高级分析算法及自定义 Cypher 查询。

    [https://docs.aws.amazon.com/neptune-analytics/latest/userguide/what-is-neptune-analytics.html]

    Neptune Analytics 适用于数据分析、数据科学及探索性工作负载。

    也就是说,Neptune Database 的主要目的是数据的持久化存储与低延迟查询执行,而 Neptune Analytics 的主要目的是在内存中实现大规模图数据的高速分析。此外,Neptune Analytics 也可从 Neptune Database 读取数据并进行分析。[https://docs.aws.amazon.com/neptune-analytics/latest/userguide/what-is-neptune-analytics.html]

    ■ 文档

    <sources>
      <source_1>
        <source_1_metadata>
          <url>https://docs.aws.amazon.com/neptune-analytics/latest/userguide/what-is-neptune-analytics.html</url>
        </source_1_metadata>
        <statement_1.1>Neptune Analytics is a memory-optimized graph database engine for analytics</statement_1.1>
        <statement_1.2>Neptune Analytics is a memory-optimized graph database engine for analytics</statement_1.2>
        <statement_1.3>Neptune Analytics can load data from a Neptune Database graph</statement_1.3>
        <statement_1.4>Neptune Analytics can load data from a Neptune Database snapshot</statement_1.4>
        <statement_1.5>Neptune Analytics is an ideal choice for data-science workloads that require fast iteration for data, analytical and algorithmic processing, or vector search on graph data</statement_1.5>
      </source_1>
      <source_2>
        <source_2_metadata>
          <url>https://docs.aws.amazon.com/neptune/latest/userguide/intro.html</url>
        </source_2_metadata>
        <statement_2.1>Neptune Analytics is an analytics database engine.</statement_2.1>
        <statement_2.2>Neptune Analytics is a solution for quickly analyzing existing graph databases.</statement_2.2>
        <statement_2.3>Neptune Analytics is a solution for quickly analyzing graph datasets stored in a data lake.</statement_2.3>
        <statement_2.4>Amazon Neptune is a fully managed graph database service</statement_2.4>
        <statement_2.5>Amazon Neptune is a fully managed graph database service</statement_2.5>
      </source_2>
    </sources>
    

    直观来看,使用 SemanticGuidedRetriever 得到的回答似乎更准确,但不同检索方法在检索精度上的差异等问题,我们将留作后续的验证课题。

    此外,TraversalBasedRetriever 与 SemanticGuidedRetriever 返回结果中包含的文档格式存在差异,不过据了解,该问题将在后续更新中实现统一。

    总结

    本次我们通过 GraphRAG Toolkit,了解了 GraphRAG 处理数据的具体流程。通过实际运行并确认内部机制,我认为已经理解了 GraphRAG 的特性。

    同时,我们也发现,借助 GraphRAG Toolkit 能够非常轻松地构建 GraphRAG 系统。该工具包封装了将数据导入图数据库前的繁琐处理流程,这一点十分令人满意。

  • Amazon Bedrock Flows 尝试实现交互式流程

    Amazon Bedrock Flows 尝试实现交互式流程

    前言

    Amazon Bedrock Flows 新增支持了多轮对话功能这一新特性。(参考链接:aws.amazon.com

    以往,用户需要在单次提示词中输入处理所需的全部信息,而借助多轮对话形式,AI 能够轻松实现适时追问缺失信息的功能。此次,我们就利用这一多轮对话功能来实现交互式流程。

    1. 概述

    Amazon Bedrock Flows 是什么?

    Amazon Bedrock Flows 是 AWS 提供的基于 GUI 的生成式 AI 框架。借助它,我们可以轻松构建专属的 AI 代理及聊天机器人。

    多轮对话功能是什么?

    此次新增支持的多轮对话功能,能够实现对话式流程,即向用户追问缺失的信息。

    例如,以旅行计划的建议与预订流程为例,单次对话与多轮对话存在如下区别:

    单次对话与多轮对话示例对比

    在以往的单次对话中,若要从输入文本中提取必要信息并进行处理,输入文本必须包含所有必要信息。倘若输入中缺少必要信息,流程会直接进入后续处理环节。因此,可能会导致无法处理,或者 AI 自行推测生成必要信息,从而出现非预期的行为。

    而使用多轮对话功能后,若存在信息缺失,流程不会进入下一步,而是会向用户进行追问。如此一来,借助多轮对话功能,能够轻松实现更自然的对话流程。

    在 Amazon Bedrock Flows 中创建多轮对话流程

    接下来,为大家介绍在 Amazon Bedrock Flows 中使用多轮对话功能的方法。本次将以示例形式,创建一个基于预算、PC 用途、台式机或笔记本电脑等条件推荐 PC 的流程。

    流程概述

    首先,本次创建的流程整体结构如下:

    PC 推荐流程

    用户输入由代理节点接收。提示词节点虽也能以文本形式接收用户输入,但由于多轮对话功能是代理独有的功能,因此此处使用代理。

    随后,代理提取预算、PC 用途、台式机或笔记本电脑这三类信息,并将其传递给后续的 AWS Lambda 函数以进行 PC 推荐。

    Lambda 函数的推荐逻辑较为简单,仅返回与提取的信息组合相对应的 PC 名称。

    创建支持多轮对话的代理

    首先,创建用于接收用户输入并提取 PC 推荐所需信息的代理。本次传递给代理的指令如下:

    请分析用户输入,并提取以下 3 个参数。
    
    # 需提取的信息
    1. 价格区间(price_range)
       - 若用户预算低于 15 万日元,返回 "lower_than_150000yen"
       - 若用户预算高于或等于 15 万日元,返回 "higher_than_150000yen"
    
    2. 用途(use_case)
       - 若需要游戏用 PC,返回 "game"
       - 若用于工作、文档制作、邮件等商务用途,返回 "business"
    
    3. PC 类型(pc_type)
       - 若需要台式机,返回 "desktop"
       - 若需要笔记本电脑,返回 "laptop"
    
    # 输出格式
    提取所需信息后,请以以下 JSON 格式返回结果。
    
    {
      "price_range": "lower_than_150000yen",
      "use_case": "game",
      "pc_type": "laptop"
    }
    

    接下来,进行多轮对话的设置:在 “其他设置” 中将 “用户输入” 设为 “启用”。这样即可实现多轮对话功能。

    (此处对应 “代理的多轮对话功能设置” 相关内容)

    创建 PC 推荐 Lambda 函数

    接下来,创建用于接收代理输出的 JSON 并返回推荐 PC 的 Lambda 函数。本次在函数中简单定义了一份 PC 列表。

    运行

    # PC 推荐映射表
    PC_RECOMMENDATION_MAP = {
        "lower_than_150000yen.game.desktop": "ASUS ROG Strix G15",
        "lower_than_150000yen.game.laptop": "Dell G15 Ryzen Edition",
        "lower_than_150000yen.business.desktop": "HP Pavilion Desktop TP01",
        "lower_than_150000yen.business.laptop": "Lenovo ThinkPad E14",
        "higher_than_150000yen.game.desktop": "Alienware Aurora R15",
        "higher_than_150000yen.game.laptop": "Razer Blade 15 Advanced",
        "higher_than_150000yen.business.desktop": "Apple Mac Studio",
        "higher_than_150000yen.business.laptop": "Apple MacBook Pro 16-inch",
    }
    
    def lambda_handler(event, context):
        # 获取输入参数
        input_str = event.get("node", {}).get("inputs", [])[0].get("value", "")
    
        # 从代理输出的文本中提取 JSON 并解析
        match = re.search(r'\{.*?\}', input_str, re.DOTALL)
        json_str = match.group(0) if match else None
        pc_params = json.loads(json_str)
    
        # 推荐 PC
        recommend_key = f"{pc_params['price_range']}.{pc_params['use_case']}.{pc_params['pc_type']}"
        recommended_pc = PC_RECOMMENDATION_MAP.get(recommend_key, "no_recommended_pc")
    
        if recommended_pc == "no_recommended_pc":
            response = "暂无推荐的 PC。"
        else:
            response = f"推荐您选择 {recommended_pc}。"
    
        return response
    

    尝试进行多轮对话

    下面,我们来与创建好的流程进行对话测试。

    面对模糊问题时,是否会追问具体内容?

    测试面对用户的模糊问题时,系统是否会追问具体内容。

    首先,来看多轮对话功能关闭时的结果,以及此时代理传递给后续环节的输出。

    此处,我们输入模糊的价格表述:“想要一台价格亲民的 PC”。

    多轮对话功能关闭时的结果

    从这一结果来看,即便多轮对话功能处于关闭状态,代理似乎也试图进行追问,但追问的内容并未传递给用户,而是直接发送至后续处理环节,进而导致了错误。

    另一方面,多轮对话功能开启时的结果如下:

    多轮对话功能开启时的结果

    从结果可以看出,代理并未进入下一步处理,而是针对用户的模糊提问追问了具体信息。

    此外,Lambda 中定义的推荐 PC 如下表所示,符合预期的 “Lenovo ThinkPad E14” 被成功推荐。

    价格区间用途PC 类型推荐 PC
    7000元以下游戏台式机ASUS ROG Strix G15
    7000元以下游戏笔记本电脑Dell G15 Ryzen Edition
    7000元以下商务台式机HP Pavilion Desktop TP01
    7000元以下商务笔记本电脑Lenovo ThinkPad E14
    7000元以下游戏台式机Alienware Aurora R15
    7000元以下游戏笔记本电脑Razer Blade 15 Advanced
    7000元以下商务台式机Apple Mac Studio
    7000元以下商务笔记本电脑Apple MacBook Pro 16-inch

    能否基于多次交互而非单次交流给出回答?

    接下来,我们测试当对话发生多次往复时,系统是否能基于此前的全部对话内容给出回答。

    以下测试中,我们将 PC 相关信息分多次提供给系统。

    往复对话的回答结果

    从结果可见,尽管信息被拆分成了 3 次对话传递,但系统依然包含了首个用户消息中 “预算控制在9000 元以内” 这一信息,并成功推荐了符合预期的 PC。

    总结

    通过 Amazon Bedrock Flows 的多轮对话功能,我们发现:即便用户输入模糊,或对话发生多次往复,系统也能准确提取所需信息。借助该功能,我们可以轻松构建自然对话形式的 AI 服务,建议大家务必尝试一下。