亚马逊AWS官方博客

Amazon Bedrock 监控与日志记录实践

Amazon Bedrock 是一项由亚马逊云科技提供的完全托管的服务,它允许用户通过单一的 API 接口访问来自多家领先人工智能公司的高性能基础模型(Foundation Models,简称 FM)。这些公司包括 AI21 Labs、Anthropic、Cohere、Meta、Mistral AI、Stability AI 以及 Amazon 自身。Bedrock 旨在简化生成式人工智能应用程序的构建和扩展过程,为用户提供包括安全性、隐私性和负责任的人工智能实践在内的一系列广泛功能。

使用 Amazon Bedrock,用户可以轻松试验和评估不同的基础模型,找到最适合其特定使用案例的模型。用户还可以利用自己的数据对模型进行微调,以实现个性化定制。此外,Bedrock 提供了无服务器体验,这意味着用户无需管理任何基础设施,可以安全地将生成式人工智能功能集成和部署到他们的应用程序中,同时利用他们已经熟悉的 AWS 服务。

尽管提供了强大的生成式人工智能功能,但为了确保其在企业级应用中的可靠性、安全性和合规性,监控和日志是必不可少的。

下面我们将以 Claude 3 模型作为例子,来配置 Amazon Bedrock 的监控和日志,以监控对模型的调用。

使用 CloudWatch 监控 Amazon Bedrock 模型调用指标

当我们使用 Bedrock 时,与我们所使用的 Bedrock 同一个 Region 的 CloudWatch 服务中会自动生成 Bedrock 的监控指标(metric)。

我们可以选中 CloudWatch 服务的 All metrics,这会显示本 Region 所有使用服务的监控指标:

我们选中其中的 Bedrock 服务,可以看到以模型 ID 为维度的指标和跨模型的指标,当前我们更关心 Claude 3 的调用指标,因此,选择“By ModelId”:

这时我们就可以在指标(Metrics)中看到,Claude 3 所提供的调用指标:

  • Invocations:指的是调用次数,包括对 InvokeModel API 和 InvokeModelWithResponseStream API 操作的请求数。
  • InvocationLatency:指的是调用时延,单位是毫秒。这个时延仅是模型收到请求并返回结果的时延,并不包括客户端通过 Internet 访问的网络时延。
  • InputTokenCount:指的是输入的 Token 数。
  • OutputTokenCount:指的是输出的 Token 数。
  • InvocationThrottles:指的是调用被限流的次数。

此外还有 InvocationClientErrors和InvocationServerErrors 等错误计数。

当我们选中这些指标时,即可看到对应的指标曲线:

但此时,由于 CloudWatch 默认的指标统计方式是平均值,并且统计周期是 5 分钟,导致我们的 Invocation 指标数据会不准确,也不能很好地反映流量突发的情况。这时我们需要到 Graphed metrics 中进行调整。选中 Graphed metrics 这个 tab 页,修改统计周期和 Invocations 这个指标的统计算法:

我们把 Invocations 这个指标的统计算法修改为“SUM”后,Invocations 才是我们实际调用次数的平均值。

由于 Graphed metrics 不能保存,导致我们每次看都需要手动调整,所以我们可以把这个监控图标添加到 CloudWatch 的 Dashboard 中,这样以后就可以直接看 Dashboard,不用再手动调整统计周期和算法。

我们把统计周期和统计算法都调整好后,在图标上部的 Actions 下拉菜单中选中 Add to dashboard:

在弹出的对话框中,创建新的 Dashboard,输入 Dashboard 名称,点击 Create 创建 Dashboard。输入监控图表(Widget)的 title,再点 Add to dashboard:

成功添加 Dashboard,我们以后就可以直接在 CloudWatch 左侧导航栏的 Dashboards 中看到,同时我们可以根据需要修改图表的宽度,用本地时间显示等:

Claude 3 调用日志

Bedrock 默认并不启用日志功能,如果需要模型的调用日志,需要手动开启:

在 Bedrock 服务左侧的导航栏中,选择 Settings,并开启 Model Invocation logging。日志将会以 json 格式保存,可以选择将日志保存到 S3和/或 CloudWatch。为便于后续使用 Athena 等其他大数据工具进行细致分析,我们选择将日志保存到 S3。

将日志保存到 S3 需要在 S3 对应的 bucket 配置资源策略,具体策略如下:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AmazonBedrockLogsWrite",
            "Effect": "Allow",
            "Principal": {
                "Service": "bedrock.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::bucketName/AWSLogs/accountID/BedrockModelInvocationLogs/*",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "accountID"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:bedrock:regionName:accountID:*"
                }
            }
        }
    ]
}

需要根据实际情况替换该策略中 bucketName,accountID,regionName。

在 S3 中保存的日志会自动根据年/月/日进行 partition,后续使用 athena 查询时,可以利用这些 partition 信息快速定位我们要查询的日志。

在 Select the data types to include with logs 中,我们可以选择日志要记录的项目,如果没有勾选 TEXT、Image 等附加的内容,默认的日志格式如下,每次对模型的调用都会产生一条日志,记录了模型调用的基本信息:

{
    "schemaType": "ModelInvocationLog",
    "schemaVersion": "1.0",
    "timestamp": "2024-05-08T07:35:54Z",
    "accountId": "123456789012",
    "identity":
    {
        "arn": "arn:aws:sts::123456789012:assumed-role/IAMrolesAnywhereRole/00ef8d937d5223beef"
    },
    "region": "us-west-2",
    "requestId": "a842bc1e-61d2-4e8a-96de-e3b48eec6b34",
    "operation": "InvokeModel",
    "modelId": "anthropic.claude-3-sonnet-20240229-v1:0",
    "input":
    {
        "inputContentType": "application/json",
        "inputTokenCount": 533
    },
    "output":
    {
        "outputContentType": "application/json",
        "outputTokenCount": 284
    }
}

日志中除了调用者的 Identify 外,还记录了调用的模型,调用方式,输入及输出的 token 数量等。其中 requestId 每次模型调用不一样,如果我们在模型调用过程中出现问题,希望开 case 获得后台帮助时,提供出现问题调用的 requestId 可以帮助后台快速地定位到出现问题的调用,从而快速解决问题。

在 Select the data types to include with logs 中,如果勾选了 TEXT 后,json 格式的日志中将会增加 inputBodyJson和outputBodyJson 的 key,并分别在这两个 key 中记录用户输入的 prompt 和模型应答的具体内容。如果勾选了 Image 后,在保存日志的 S3 桶中还将有一个 data 的文件夹,如果对 Claude 3 调用时输入了图片,是多模态的调用,那么该文件夹中会保存每次调用的 prompt 文本以及 base64 编码的图片。

从客户端获取模型调用信息

除了从 CloudWatch 监控的 Metrics 和日志外,还可以直接在客户端直接获取模型调用的信息。

当我们用 InvokeModel API 调用模型时,在返回的 response 里,我们可以从 response 的 http header 里获得本次模型调用的关键信息:

{
    "ResponseMetadata":
    {
        "RequestId": "6b14d2a7-e5ce-4b6a-bdda-78b7285ae399",
        "HTTPStatusCode": 200,
        "HTTPHeaders":
        {
            "date": "Thu, 09 May 2024 06:36:49 GMT",
            "content-type": "application/json",
            "content-length": "342",
            "connection": "keep-alive",
            "x-amzn-requestid": "6b14d2a7-e5ce-4b6a-bdda-78b7285ae399",
            "x-amzn-bedrock-invocation-latency": "1771",
            "x-amzn-bedrock-output-token-count": "23",
            "x-amzn-bedrock-input-token-count": "15"
        },
        "RetryAttempts": 0
    },
    "contentType": "application/json",
    "body": ...
}

在 response 的 http header 里,以“x-amzn-”开始的几个 header 分别记录了 request id,调用时延(这个时延是模型推理的时延,并不包含客户端到模型所在 region 的这段网络时延),输入 token 数,输出 token 数。

InvokeModelWithResponseStream API 则有些不同,在 response 的 http header 中仅保留了 request id、retry attempts 等信息,并没有包含 token、时延等信息。由于 InvokeModelWithResponseStream API 的返回是流式的,是一段连续的分为 chunk 的片段,每个 chunk 片段包含了 type 和具体的内容。当 chunk 的 type 是“content_block_delta”时,这个 chunk 包含的是模型返回的内容,当 chunk 的 type 是“message_stop”时,这说明模型的回答已全部完成,在这个 chunk 里,会包含输入、输出 token 数,时延,首字节时延等信息:

{
    "type": "message_stop",
    "amazon-bedrock-invocationMetrics":
    {
        "inputTokenCount": 13,
        "outputTokenCount": 345,
        "invocationLatency": 9240,
        "firstByteLatency": 500
    }
}

无论是 InvokeModel API 还是 InvokeModelWithResponseStream API,我们都可以直接从客户端获得每次调用具体的指标情况。

总结

Amazon Bedrock 为用户提供了一套强大的工具来监控和记录 AI 模型的使用情况,从而帮助用户更好地理解和优化他们的 AI 应用程序。通过 CloudWatch 的监控指标和详细的日志记录,用户可以确保他们的应用程序在企业级部署中的可靠性、安全性和合规性。此外,客户端的直接信息获取功能进一步增强了用户对模型调用过程的透明度和控制力。

本篇作者

陆毅

亚马逊云科技高级解决方案架构师,拥有 20 年传统 IT 和公有云行业经验。擅长云上基础设施的架构设计、运维等。