Fable5

前置条件

  1. Fable 5 必须走 Mantle 端点(原生 Anthropic Messages API), 用 anthropic SDK 的 AnthropicBedrockMantle 客户端。
  2. 模型 ID 是 anthropic.claude-fable-5(注意 anthropic. 前缀,不是 us. 前缀)。
  3. 标准 bedrock-runtime 的 converse / invoke_model 调 Fable 5 会报: ValidationException: data retention mode ‘default’ is not available for this model —— Fable 5 要求非默认的数据保留模式,标准端点无法设置,只有 Mantle 端点能处理。
  4. 认证:只能用 AWS profile(SigV4)。 Bedrock API key(bearer token,AWS_BEARER_TOKEN_BEDROCK)对 Mantle 端点返回 401, 它只在标准 bedrock-runtime 端点有效 —— 而标准端点又跑不了 Fable 5。 所以 Fable 5 = Mantle 端点 + AWS profile,两者缺一不可。
#!/usr/bin/env python3
"""
调通 Claude Fable 5 on AWS Bedrock.
依赖: pip install "anthropic[bedrock]"   (已验证 anthropic==0.116.0)
区域: us-east-1
"""

import time
from anthropic import AnthropicBedrockMantle

REGION = "us-east-1"
MODEL_ID = "anthropic.claude-fable-5"   # 注意前缀是 anthropic. 不是 us.


def make_client() -> AnthropicBedrockMantle:
    # 用默认 AWS profile 的 SigV4 认证(凭据取自 ~/.aws 或环境变量)。
    # 不要设置 AWS_BEARER_TOKEN_BEDROCK —— Mantle 端点不认它。
    return AnthropicBedrockMantle(aws_region=REGION)


def test_basic():
    c = make_client()
    print(f"[basic] {MODEL_ID} @ {REGION}")
    t0 = time.time()
    m = c.messages.create(
        model=MODEL_ID,
        max_tokens=64,
        messages=[{"role": "user", "content": "你是什么模型"}],
        # Fable 5 thinking 始终开启,不要传 thinking 参数(传 disabled 会 400)。
        # 需要控制深度用 output_config={"effort": "high"} 之类。
    )
    txt = "".join(b.text for b in m.content if b.type == "text")
    print(f"  -> {txt!r}  ({time.time()-t0:.2f}s, "
          f"in/out={m.usage.input_tokens}/{m.usage.output_tokens} tok, "
          f"stop={m.stop_reason})")


def test_stream():
    c = make_client()
    print(f"\n[stream] {MODEL_ID}")
    t0 = time.time()
    with c.messages.stream(
        model=MODEL_ID,
        max_tokens=128,
        messages=[{"role": "user", "content": "Count from 1 to 5, one number per line."}],
    ) as s:
        for txt in s.text_stream:
            print(txt, end="", flush=True)
        fm = s.get_final_message()
    print(f"\n  --- {time.time()-t0:.2f}s, stop={fm.stop_reason}, "
          f"out={fm.usage.output_tokens} tok ---")


if __name__ == "__main__":
    test_basic()
    test_stream()
    print("\n全部通过。")