账号里明明已经开通了 Bedrock,代码跑起来却先给你一个 AccessDeniedException,换成另一个模型 ID 又变成 ResourceNotFoundException,好不容易跑通了,月底账单又对不上——这是把托管模型接进项目时最常见的三段式翻车。下面我不谈模型谁更强,只从一次最小请求出发,把整个过程拆成鉴权、调用、核价三步:先把凭据和区域理顺,再发一个能返回 token 用量的请求,最后回到定价页确认自己到底在为哪些计量项付费。

第一步 鉴权:先分清长期凭据和短期密钥
Bedrock 的请求走的是 AWS 的签名体系,所以“鉴权”这件事本质上不是拿一个 OpenAI 风格的 API Key 去调,而是让请求带上能被 IAM 认出来的身份。目前常见两条路:
- IAM 凭据 + SigV4 签名:用 IAM 用户、角色或实例配置文件,由 SDK 自动签名。适合生产环境,权限可以用策略精确控制到某个模型 ARN。
- Bedrock API 密钥:AWS 提供的一种短期密钥形式(资料中提到 30 天有效期的密钥),出门左转即可调用,适合本地试验和快速验证,但不要当成长期方案塞进生产配置。
无论走哪条路,最小权限大致需要两类动作:调用推理接口的权限,以及(如果要用控制台或列举模型)读取模型的权限。生产上更推荐按模型 ARN 授权,而不是图省事给 *。
# 本地试验可以用环境变量注入短期密钥
export AWS_REGION="us-east-1"
export AWS_BEARER_TOKEN_BEDROCK="bedrock-api-key-xxxxxxxx"
# 生产环境更常见:让 SDK 用 IAM 角色自动签名
import boto3
session = boto3.Session(region_name="us-east-1")
client = session.client("bedrock-runtime")
一个容易忽略的点:区域决定了你能看到哪些模型。同一个模型 ID 在 A 区域可用、在 B 区域可能直接报找不到;价格也可能按区域分档。所以选区域时不要只按“离我近”,而要按“这个模型在这个区域上架了没有、单价是多少”来定。
第二步 调用:先跑通一个带用量回执的请求
第一次调用不要直接上业务逻辑,先用官方推荐的统一推理接口发一条最短的消息,确认三件事:能通、返回结构对、用量字段有值。Bedrock 的 Converse 接口在多模型之间保持了比较一致的请求结构,切换模型时改动较小。
import boto3
client = boto3.client("bedrock-runtime", region_name="us-east-1")
resp = client.converse(
modelId="<控制台中确认可用的模型 ID>",
messages=[{"role": "user", "content": [{"text": "用一句话解释什么是向量检索"}]}],
inferenceConfig={"maxTokens": 256, "temperature": 0.3},
)
print(resp["output"]["message"]["content"][0]["text"])
print("用量:", resp["usage"]) # inputTokens / outputTokens / totalTokens
print("延迟:", resp["metrics"]["latencyMs"])
关键字段就三个:modelId 必须与控制台里显示的完全一致(大小写、版本后缀都算);inferenceConfig.maxTokens 决定输出上限,它直接关系到单次成本上限;usage 是后面核价和对账的依据,务必在日志里留下来。
如果这一步就失败,先按错误类型分流,不要盲目改代码:
| 报错 | 大概率原因 | 处理方向 |
|---|---|---|
AccessDeniedException | 凭据没有该模型的调用权限,或跨账号角色未授信 | 检查 IAM 策略里的模型 ARN 与资源范围 |
ResourceNotFoundException | 模型 ID 写错,或该模型未在当前区域上架 | 回控制台核对 ID 与区域 |
ValidationException | 请求体字段不合法,如消息结构或参数越界 | 对照接口文档收紧参数 |
ThrottlingException | 触发了每分钟请求数或 token 配额 | 降并发 + 退避重试 |
ModelNotReadyException | 模型冷启动或暂时不可用 | 稍后重试,并准备降级模型 |
第三步 核价:单价只是成本公式里的一个变量
跑通之后,最容易被低估的是“账单为什么比预估高”。Bedrock 的计费不是单一单价乘以次数,至少要拆成四层来看:
- 模态与模型:定价取决于模态、提供商和模型,不同模型、不同上下文长度档位的单价都可能不同。
- 输入与输出分开计:通常按每百万 token 分别标价,输出单价普遍高于输入,所以长回答比长提示更贵。
- 服务套餐:除了默认的标准按需套餐,还有面向不同性能与成本需求的套餐(如优先级、预留等),需要在调用时通过额外参数指定,现有应用不指定就继续走标准套餐。
- 附加项:批量推理通常比按需更便宜(资料中提到低约 50% 的量级);如果涉及微调,还要算训练小时数和模型存储月费。
所以核价的正确姿势是:先在定价页按“提供商 → 模型 → 区域”定位到你的那一行,把输入单价和输出单价抄下来,再乘上你自己统计的 token 量。用一张表把预算摆平:
| 项目 | 取值来源 | 示例(请按官方页面替换) |
|---|---|---|
| 输入单价 / 百万 token | 定价页对应模型与区域 | <input_price> |
| 输出单价 / 百万 token | 同上 | <output_price> |
| 日均输入 token | 应用日志汇总 | 200 万 |
| 日均输出 token | 应用日志汇总 | 50 万 |
| 日成本估算 | 输入量×输入单价 + 输出量×输出单价 | 按实际单价计算 |

需要提醒的是,模型 ID、单价和区域支持都属于高频变动的信息,写进文档或制成预算表时一定要标注核验时间,并在发布前回官方定价页和控制台再对一遍,别把半年前的数字当现值用。
配额、重试与成本观察
调用量一上来,最先撞上的往往不是钱而是配额。Bedrock 的限流按账户和模型维度计算,短时间高并发就会拿到 ThrottlingException。与其在业务代码里到处 try/except,不如在客户端层统一配好重试:
from botocore.config import Config
client = boto3.client(
"bedrock-runtime",
region_name="us-east-1",
config=Config(
retries={"max_attempts": 5, "mode": "adaptive"}, # 自适应退避
connect_timeout=5,
read_timeout=60,
),
)
自己做重试时要加指数退避和抖动,并给重试设上限;对幂等性敏感的业务,还要避免把已经产生计费的请求重复放大。更好的做法是提前申请配额提升,把峰值压在额度之内。
成本观察则建议从第一天就做三件事:
- 打标签:给调用方资源加上业务维度标签,方便在成本管理里按项目拆分。
- 留日志:把每次请求的模型 ID、输入输出 token 数、延迟、是否重试写进结构化日志,这是唯一能对上账的原始数据。
- 设告警:对日成本或 token 总量设阈值告警,比月底看账单被动接受要划算得多。

怎么算这一步走完了
一次合格的接入验证,标准不是“能返回文字”,而是:控制台里确认了模型在当前区域可用;凭据权限收敛到了具体模型;最小请求能返回 usage 里的 token 数;预算表里的单价是刚从官方页面抄下来的、带核验时间的现值;日志里能查到每一次调用的用量;限流时有退避而不是硬扛。
做到这几条,你手里就有一条可复现、可核价、可排错的调用链,后面换模型、调参数、加并发,都只是在这条链上做局部替换,而不是重新踩一遍坑。

评论列表 (1条):
加载更多评论 Loading...