零服务器部署 AI 应用:Lambda + Bedrock 全流程实战记录

零服务器部署 AI 应用:Lambda + Bedrock 全流程实战记录 零服务器部署 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 runtimeBedrock:调用 Claude 3.5 Sonnet 模型IAM:权限控制,Lambda 需要bedrock:InvokeModel权限第一步:写 Lambda å‡½æ•°åˆæŠŠæ ¸å¿ƒé€»è¾‘è·‘é€šã€‚æ–°å»ºä¸€ä¸ªlambda_function.py:importjsonimportboto3 bedrockboto3.client(bedrock-runtime,region_nameus-east-1)deflambda_handler(event,context):# 从请求中拿到用户问题bodyjson.loads(event.get(body,{}))questionbody.get(question,)ifnotquestion:return{statusCode:400,body:json.dumps({error:问题不能为空})}# 调用 Bedrock Clauderesponsebedrock.invoke_model(modelIdanthropic.claude-3-5-sonnet-20241022-v2:0,contentTypeapplication/json,acceptapplication/json,bodyjson.dumps({anthropic_version:bedrock-2023-05-31,max_tokens:2048,messages:[{role:user,content:question}]}))resultjson.loads(response[body].read())answerresult[content][0][text]return{statusCode:200,headers:{Content-Type:application/json},body:json.dumps({answer:answer})}è¿™æ®µä»£ç å°±åšäº†ä¸‰ä»¶äº‹ï¼šä»Ž API Gateway ä¼ è¿‡æ¥çš„ event 里拿问题调 Bedrock çš„ Claude 模型把回答返回去第二步:éç½® 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 APIaws apigatewayv2 create-api\--nameai-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-version2.0# 创建路由aws apigatewayv2 create-route\--api-id YOUR_API_ID\--route-keyPOST /ask踩坑记录坑 1:Lambda è¶æ—¶Lambda é»˜è®¤è¶æ—¶æ˜¯ 3 秒,但 Bedrock è°ƒ Claude 一次响应可能要 5-15 ç§’ã€‚ç¬¬ä¸€æ¬¡æµ‹è¯•ç›´æŽ¥è¶æ—¶äº†ã€‚解决:把 Lambda è¶æ—¶æ”¹æˆ 30 秒。在控制台改或è€ç”¨ CLI:aws lambda update-function-configuration\--function-name ai-qa\--timeout30坑 2:冷启动延迟Lambda 冷启动 Bedrock 首次调用,第一次请求可能要等 10 秒。后面就正常了。解决方案:éç½® Provisioned Concurrencyï¼ˆé¢„ç½®å¹¶å‘ï¼‰ï¼Œä¿æŒå‡ ä¸ªå®žä¾‹å¸¸çƒ­æˆ–è€ç”¨ CloudWatch Events 定时 ping,保持函数温热aws lambda put-provisioned-concurrency-config\--function-name ai-qa\--qualifierprod\--provisioned-concurrent-executions2坑 3:返回体大小限制API Gateway 同步响应上限 10MB,Lambda 返回上限 6MB。一般问答没问题,但如果让模型生成长文,要注意这个限制。坑 4:Bedrock 区域不是所有区域都支持 Bedrock。目前us-east-1å’Œus-west-2模型最å¨ã€‚å¦‚æžœä½ çš„ Lambda 在东京(ap-northeast-1),需要跨区域调用 Bedrock:bedrockboto3.client(bedrock-runtime,region_nameus-east-1)è·¨åŒºåŸŸè°ƒç”¨ä¼šå¢žåŠ 50-100ms 延迟,但对于 AI åº”ç”¨æ¥è¯´è¿™ä¸ªå»¶è¿ŸåŸºæœ¬å¯ä»¥å¿½ç•¥ã€‚æˆæœ¬å¯¹æ¯”è·‘äº†ä¸€ä¸ªæœˆï¼Œå®žé™æ•°æ®ï¼šæ–¹æ¡ˆæœˆæˆæœ¬EC2 t3.medium 24/7~$30Lambda API Gateway~$3Lambda 方案省了 90%ã€‚å½“ç„¶ï¼Œå¦‚æžœä½ çš„ QPS 很高(比如每秒上百次请求),Lambda 反而可能更贵。按需选择就好。Lambda 计费逻辑:每月前 100 万次请求åè´¹ä¹‹åŽ $0.20/百万次å†å­˜æŒ‰ GB-秒计费:$0.0000166667/GB-秒以 256MB å†å­˜ã€å¹³å‡æ‰§è¡Œ 5 秒来算:每次调用成本 ≈ $0.0000208一天 100 次 $0.002一个月 ≈ $0.06Bedrock 调用费是另算的(按 token 计费),这里不展开。进阶:流式响应用户等 10 秒看到完整回答,体验不好。改成流式响应,边生成边返回:deflambda_handler(event,context):bodyjson.loads(event.get(body,{}))questionbody.get(question,)responsebedrock.invoke_model_with_response_stream(modelIdanthropic.claude-3-5-sonnet-20241022-v2:0,contentTypeapplication/json,acceptapplication/json,bodyjson.dumps({anthropic_version:bedrock-2023-05-31,max_tokens:2048,messages:[{role:user,content:question}]}))# 流式处理需要 Lambda Response Streamingchunks[]forevent_chunkinresponse[body]:chunkjson.loads(event_chunk[chunk][bytes])ifchunk[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 运行时测试通过。