零服务器部署 AI 应用:Lambda + Bedrock å

¨æµç¨‹å®žæˆ˜è®°å½•

折è
¾äº†ä¸¤å¤©ï¼Œç»ˆäºŽæŠŠä¸€å¥— Serverless AI 应用跑通了。从 Lambda 函数到 Bedrock 模型调用,踩了不少坑,这里完整记录下来。

为什么要用 Serverless 搞 AI

说实话,一开始我也没想用 Lambda。我们团队有个需求——做一个å†
部知识问答工å
·ï¼Œç”¨å¤§æ¨¡åž‹æ¥å›žç­”技术问题。最初的想法是起个 EC2 è·‘ FastAPI,但算了下成本:

  • 24 小时挂着 EC2:就算用 t3.medium,一个月也要几十美金
  • 实é™
    使用率
    :工作时间大概 8 小时,周末基本没人用
  • 真正在处理请求的时间:可能一天加起来就几分钟

这个利用率也太低了。后来想到 Lambda——按调用次数收费,没请求就是 $0,完美符合这个场景。

技术架构长什么样

整个链路å
¶å®žä¸å¤æ‚:

用户 → API Gateway → Lambda → Bedrock (Claude) → 返回结果

用到的亚马逊云科技服务:

  • API Gateway:HTTP å
    ¥å£ï¼Œå¤„理路由和认证
  • Lambda:业务逻辑,Python 3.12 runtime
  • Bedrock:调用 Claude 3.5 Sonnet 模型
  • IAM:权限控制,Lambda 需要 bedrock:InvokeModel 权限

第一步:写 Lambda 函数

å
ˆæŠŠæ ¸å¿ƒé€»è¾‘跑通。新建一个 lambda_function.py:

import json
import boto3

bedrock = boto3.client('bedrock-runtime', region_name='us-east-1')

def lambda_handler(event, context):
    # 从请求中拿到用户问题
    body = json.loads(event.get('body', '{}'))
    question = body.get('question', '')
    
    if not question:
        return {
            'statusCode': 400,
            'body': json.dumps({'error': '问题不能为空'})
        }
    
    # 调用 Bedrock Claude
    response = bedrock.invoke_model(
        modelId='anthropic.claude-3-5-sonnet-20241022-v2:0',
        contentType='application/json',
        accept='application/json',
        body=json.dumps({
            'anthropic_version': 'bedrock-2023-05-31',
            'max_tokens': 2048,
            'messages': [
                {
                    'role': 'user',
                    'content': question
                }
            ]
        })
    )
    
    result = json.loads(response['body'].read())
    answer = result['content'][0]['text']
    
    return {
        'statusCode': 200,
        'headers': {'Content-Type': 'application/json'},
        'body': json.dumps({'answer': answer})
    }

这段代码就做了三件事:

  1. 从 API Gateway 传过来的 event 里拿问题
  2. 调 Bedrock 的 Claude 模型
  3. 把回答返回去

第二步:é

ç½® IAM 权限

Lambda 执行角色需要这两个权限:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "bedrock:InvokeModel",
        "bedrock:InvokeModelWithResponseStream"
      ],
      "Resource": "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-5-sonnet-*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    }
  ]
}

这里有个坑——Bedrock 模型的 ARN 格式跟å
¶ä»–服务不太一样,账号那段是空的(两个冒号之间没东西)。第一次é
çš„æ—¶å€™å†™æˆäº† arn:aws:bedrock:us-east-1:123456789:foundation-model/...,结果一直报 AccessDenied,查了半天才发现。

第三步:API Gateway 集成

用 HTTP API(不是 REST API),更便宜更快:

# 创建 HTTP API
aws apigatewayv2 create-api \
  --name ai-qa-api \
  --protocol-type HTTP

# 创建 Lambda 集成
aws apigatewayv2 create-integration \
  --api-id YOUR_API_ID \
  --integration-type AWS_PROXY \
  --integration-uri arn:aws:lambda:us-east-1:ACCOUNT:function:ai-qa \
  --payload-format-version 2.0

# 创建路由
aws apigatewayv2 create-route \
  --api-id YOUR_API_ID \
  --route-key "POST /ask"

踩坑记录

坑 1:Lambda è¶

æ—¶

Lambda 默认è¶
时是 3 秒,但 Bedrock è°ƒ Claude 一次响应可能要 5-15 秒。第一次测试直接è¶
时了。

解决:把 Lambda è¶
时改成 30 秒。在控制台改或è€
用 CLI:

aws lambda update-function-configuration \
  --function-name ai-qa \
  --timeout 30

坑 2:冷启动延迟

Lambda 冷启动 + Bedrock 首次调用,第一次请求可能要等 10+ 秒。后面就正常了。

解决方案:

  • é
    ç½® Provisioned Concurrency(预置并发),保持几个实例常热
  • 或è€
    用 CloudWatch Events 定时 ping,保持函数温热
aws lambda put-provisioned-concurrency-config \
  --function-name ai-qa \
  --qualifier prod \
  --provisioned-concurrent-executions 2

坑 3:返回体大小限制

API Gateway 同步响应上限 10MB,Lambda 返回上限 6MB。一般问答没问题,但如果让模型生成长文,要注意这个限制。

坑 4:Bedrock 区域

不是所有区域都支持 Bedrock。目前 us-east-1 å’Œ us-west-2 模型最å
¨ã€‚如果你的 Lambda 在东京(ap-northeast-1),需要跨区域调用 Bedrock:

bedrock = boto3.client('bedrock-runtime', region_name='us-east-1')

跨区域调用会增加 50-100ms 延迟,但对于 AI 应用来说这个延迟基本可以忽略。

成本对比

跑了一个月,实é™
数据:

方案 月成本
EC2 t3.medium 24/7 ~$30
Lambda + API Gateway ~$3

Lambda 方案省了 90%。当然,如果你的 QPS 很高(比如每秒上百次请求),Lambda 反而可能更贵。按需选择就好。

Lambda 计费逻辑:

  • 每月前 100 万次请求å
    è´¹
  • 之后 $0.20/百万次
  • å†
    存按 GB-秒计费:$0.0000166667/GB-秒

以 256MB å†
存、平均执行 5 秒来算:

  • 每次调用成本 ≈ $0.0000208
  • 一天 100 次 = $0.002
  • 一个月 ≈ $0.06

Bedrock 调用费是另算的(按 token 计费),这里不展开。

进阶:流式响应

用户等 10 秒看到完整回答,体验不好。改成流式响应,边生成边返回:

def lambda_handler(event, context):
    body = json.loads(event.get('body', '{}'))
    question = body.get('question', '')
    
    response = bedrock.invoke_model_with_response_stream(
        modelId='anthropic.claude-3-5-sonnet-20241022-v2:0',
        contentType='application/json',
        accept='application/json',
        body=json.dumps({
            'anthropic_version': 'bedrock-2023-05-31',
            'max_tokens': 2048,
            'messages': [{'role': 'user', 'content': question}]
        })
    )
    
    # 流式处理需要 Lambda Response Streaming
    chunks = []
    for event_chunk in response['body']:
        chunk = json.loads(event_chunk['chunk']['bytes'])
        if chunk['type'] == 'content_block_delta':
            chunks.append(chunk['delta']['text'])
    
    return {
        'statusCode': 200,
        'body': json.dumps({'answer': ''.join(chunks)})
    }

真正的流式需要é
åˆ Lambda Response Streaming(函数 URL + RESPONSE_STREAM)或 WebSocket API。上面的写法只是把流式接收到的å†
容拼起来一次返回,适合简单场景。

总结

Lambda + Bedrock 搭 AI 应用,核心优势就一个字:省。省钱(按调用计费)、省心(不用管服务器)、省时(几个文件就能部署)。

适合的场景:

  • å†
    部工å
    ·ã€é—®ç­”机器人
  • 低频调用的 AI 功能(比如每天几百次)
  • 原型验证、快速上线

不适合的场景:

  • 高并发实时对话(WebSocket 场景建议用 ECS/EKS)
  • 需要 GPU 推理的自定义模型

如果你也在考虑怎么低成本上线一个 AI 功能,Lambda + Bedrock 可以试试。


📌 完整代码和 CloudFormation 模板我放在文末,有需要的直接拿走。所有代码基于亚马逊云科技 Lambda Python 3.12 运行时测试通过。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐