本文基于Github上作者jief123的方案编写。Github官方文档方案采用CDK形式部署,而本文是描述如何手工部署。
一、背景
Bedrock服务提供的多种大模型使用中需要遵循各模型原厂的合规要求。为了实现网络加速,可在全球统一配置一个Bedrock流量入口,为全球多地区的应用加速。
整个架构的主要步骤如下:
- Bedrock的模型调用选择us-west-2区域
- 配置CloudFront加速加速点,仅使用北美和欧洲的POP节点
- 在CloudFront特定的us-east-1区域的Lambda控制台配置Lambda@Edge,然后关联到CloudFront
- 修改代码重定向流量到CloudFront发布点
二、确认Bedrock上模型权限已经打开
通过AWS官方文档查询Bedrock的互联网Endpoint调用地址,例如在us-west-2,地址是bedrock.us-west-2.amazonaws.com
。其他区域的Endpoint,请查询本文末尾的参考文档。
三、配置CloudFront
在控制台左上角,输入CloudFront,然后点击服务打开控制台。如下截图。
点击新建发布点按钮,创建新的发布点。如下截图。
在发布点创建向导界面,在Origin
源位置,输入上一步确认的Bedrock的互联网节点,例如本文使用us-west-2,地址是bedrock.us-west-2.amazonaws.com
。在访问协议中,选择HTTPS only
。本页其他选项无须改动,继续向下滚动页面。如下截图。
在Enable Origin Shield
位置,选择Yes
,然后把Origin Shield
的区域选择为us-west-2
,与Bedrock所在Region一致。本页其他选项无须改动,继续向下滚动页面。如下截图。
在Default cache behavior
位置,选择允许的HTTP方法是GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
。这样配置的原因是Bedrock使用的是POST方法。本页其他选项无须改动,继续向下滚动页面。如下截图。
在缓存回源策略Cache key and origin requests
位置,选择默认的Cache policy and origin request policy (recommended)
,然后在Cache policy
位置选择CachingDisabled
,在Origin request policy - optional
位置选择AllViewer
。本页其他选项无须改动,继续向下滚动页面。如下截图。
在Web Application Firewall (WAF)
的位置,选择不启用Web Application Firewall (WAF)
。如果后续需要WAF的话,可以在后期额外配置。在Settings
下的Price class
位置,选择Use only North America and Europe
。注意这个选项很重要,这样可以避免不合规的地区发起的调用。本页其他选项无须改动,继续向下滚动页面。如下截图。
本页其他选项无须改动,继续向下滚动页面。点击创建按钮,完成创建。如下截图。
创建后,在发布点页面,将可以看到CloudFront为新创建的分配点自动创建了一个Endpoint,即Distribution domain name
,其域名是xxxxx.cloudfront.net
的域名。将这个域名复制下来,最后代码中将会使用这个Endpoint。如下截图。
至此CloudFront发布点创建完成。
四、配置Lambda@Edge
1、创建Lambda@Edge
进去控制台,切换到us-east-1区域。就需要注意,无论您的Bedrock使用哪一个区域,Lambda@Edge必须部署在us-east-1区域。只有us-east-1区域的Lambda才可以与CloudFront进行集成。因此请切换当前区域。
查找Lambda服务,点击并进入。如下截图。
在Lambda控制台上,点击Create function
按钮创建新的函数。如下截图。
在创建向导中,选择类型是Use a blueprint
,在Blueprint
里边,从下拉框选择Modify HTTP response header
选项,这里选这个是为了使用Lambda自己的权限模版,这样比从空白开始创建配置更简单。在名称位置,输入自定义名称,例如bedrock-proxy
。如下截图。
在执行者权限Excution role
位置,选择Create a new role from AWS policy templates
,然后输入角色名称例如bedrock-proxy
。其他选项无须修改。继续向下滚动页面。如下截图。
将页面滚动到最下方,在代码部分,无须修改,稍后创建后再修改。点击右下角的Create
按钮创建函数。如下截图。
由此创建函数完毕。
2、上传代码并发布新版本
函数创建完毕,页面提示是否要将Lambda@Edge和CloudFront发布点关联。这里选择取消,不进行关联。如下截图。
创建Lambda函数完毕。现在修改代码,粘贴如下代码到编辑窗口:
export const handler = async (event) => {
const request = event.Records[0].cf.request;
const headers = request.headers;
request.origin = {
custom: {
domainName: `bedrock-runtime.us-west-2.amazonaws.com`,
port: 443,
protocol: 'https',
sslProtocols: ['TLSv1.2'],
readTimeout: 60,
keepaliveTimeout: 5,
customHeaders: {}
}
};
return request;
};
粘贴完毕后,点击左侧的Deploy
部署按钮。如下截图。
部署完毕后,还要发布新版本。在Lambda控制台上切换到最后一个标签页Versions
,然后点击右上角的Publish new version
,发布新版本。如下截图。
在发布向导中,输入一个友好备注信息,这里不需要填写版本号码,因为Lambda会自动生成版本好。如下截图。
创建新版本号完成。点击版本号进入详情页面。如下截图。
从右上角可看到本Lambda的ARN,将其复制下来,下一步会使用。如下截图。
发布新代码完成。
3、关联到CloudFront发布点
进入CloudFront发布点界面,选择前文创建的CloudFront发布点。点击进入详情。如下截图。
在发布点里边,找到行为Behaviors
标签页,选择默认的行为,点击编辑按钮。如下截图。
将页面滚动到最下方,找到Function associations
位置,找到Origin request
的下拉框,在下拉框中选择Lambda@Edge
,然后在ARN位置输入上一步复制出来的ARN,然后点击保存修改按钮。如下截图。
以上步骤如果无法通过,很可能是之前创建Lambda@Edge时候么有选择正确的区域,请参考本文前序章节创建Lambda@Edge的部分。
返回CloudFront发布点,可以看到刚修改的发布点,显示为部署中Deploying
,需要等到显示部署完成后,才可以发起测试。这一步将把Lambda函数部署到CloudFront的全球几百个加速点,可能需要5分钟时间才能完成。
至此CloudFront和Lambda绑定完成。等待几分钟即可访问。
五、在调用Bedrock的代码中指定Endpoint
本文以Python语言使用的Boto3 SDK为例,在调用Boto3过程中,可以在Session中加入参数指定Endpoint入口。
例如代码如下:
import boto3
import json
region_name = 'us-west-2'
#model_id = 'anthropic.claude-3-5-sonnet-20241022-v2:0'
model_id = 'anthropic.claude-3-5-sonnet-20240620-v1:0'
message_text = "写一段废话文学,不超过500个汉字,要求全都是废话,说了又仿佛没说。"
system_prompt = [
{ "text": "你是写文章助手" }
]
#session = boto3.Session(region_name='us-west-2')
session = boto3.Session(
aws_access_key_id='XXXXXXXXXXXXXX',
aws_secret_access_key='XXXXXXXXXXXXXXXXXXXXXXXXXXXX',
region_name='us-west-2'
)
bedrock = session.client(
service_name="bedrock-runtime",
endpoint_url='https://dptp3eos7v8rh.cloudfront.net'
)
message_list = []
initial_message = {
"role": "user",
"content": [
{ "text": message_text }
],
}
message_list.append(initial_message)
response = bedrock.converse(
modelId = model_id,
system = system_prompt ,
messages = message_list ,
inferenceConfig={
"maxTokens": 2000,
"temperature": 0
},
)
# debug
# print(response)
# Only get content from response
response_message = response['output']['message']['content'][0]['text']
print(response_message)
# Print token usage
print("\n\n--- Token usage ---")
print("Usage:", json.dumps(response['usage'], indent=4))
执行完毕,可看到正常返回结果。
人生如梦,梦如人生。我们每个人都在这个世界上走着自己的路,追寻着内心的声音。有人说生活是一杯白开水,平淡无奇;也有人说生活是一杯咖啡,苦涩中带着醇香。其实生活就像一面镜
子,你对它微笑,它就对你微笑;你对它皱眉,它就对你皱眉。所以说,态度决定一切。
我们常常在追求完美的路上迷失了自我,殊不知真正的完美是接纳不完美。就像蝴蝶,如果不经历破茧的痛苦,怎能展翅高飞?所以说,没有伤痛就没有成长。生活中难免会遇到挫折和困难,但
这恰恰是上天给我们的礼物,让我们变得更加坚强。
时间就像海绵里的水,挤一挤总是有的。我们要学会珍惜时间,因为时间是我们最宝贵的财富。古人云:一寸光阴一寸金,寸金难买寸光阴。这句话诠释了时间的珍贵。所以,让我们携手并进,
共同努力,创造美好的未来!
--- Token usage ---
Usage: {
"inputTokens": 50,
"outputTokens": 391,
"totalTokens": 441
}
至此确认CloudFront、Lambda@Edge和Bedrock都工作正常。
六、参考文档
Bedrock CloudFront 加速方案
https://github.com/jief123/bedrockproxy
Bedrock Endpoint