news 2026/8/21 22:32:31

【Bug已解决】How to send a base64 image to Bedrock via ConverseCommand as bytes 解决方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Bug已解决】How to send a base64 image to Bedrock via ConverseCommand as bytes 解决方案

【Bug已解决】How to send a base64 image to Bedrock via ConverseCommand as bytes 解决方案

一、现象长什么样

你在 AWS Bedrock 用Converse/ConverseCommand(SDK v3)给 Claude 传一张图,想把本地图片以 base64 形式发过去,却遇到:

  • 报错说image块的source格式不对;
  • 或你传了 base64 字符串,但 Bedrock 期望的是bytes(二进制),两者混用报错;
  • 文档里写source: { bytes: Uint8Array },但你手里是 base64 文本,不知道怎么转;
  • 你试过直接把 base64 字符串塞进bytes字段,报ValidationException
  • 图片相关的format(png/jpeg)也填错,导致模型收不到图。

一句话:BedrockConverse的图片块要求source.bytes是一个二进制字节流(如Uint8Array/bytes),而不是 base64 字符串——你需要先把 base64 解码成字节,再作为bytes传入,并正确声明format

二、背景

Bedrock 的ConverseAPI(以及 boto3 的converse、JS SDK 的ConverseCommand)对多模态图片有统一结构:

{ "image": { "format": "png", "source": { "bytes": <二进制字节> } } }

source有两种:bytes(直接二进制)或s3Location(存在 S3 的图片)。没有base64这个字段——Bedrock 不接收 base64 字符串,它要的是解码后的字节。

所以"我有一张 base64 图"的处理链路是:base64 文本 →base64.b64decode/Buffer.from(b64, 'base64')→ 字节 → 放进source.bytes。很多人卡在"直接把 base64 字符串当 bytes 传",于是校验失败。

三、根因

根因是把 base64 字符串直接当bytes传,而不是先解码成二进制

# 错误:base64 字符串不是 bytes block = {"image": {"format": "png", "source": {"bytes": "iVBORw0KGgo..."}}} # 字符串! -> 报错 # 正确:先解码 import base64 raw = base64.b64decode("iVBORw0KGgo...") block = {"image": {"format": "png", "source": {"bytes": raw}}} # bytes!

修复方向:在发送前把 base64 解码为字节对象(bytes/Uint8Array),并声明正确的format

四、最小可运行复现

下面用 Python(boto3)演示完整链路:

import base64 import boto3 # 假设你有一张 base64 编码的 PNG b64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+M8AAAMBAQDJ/pLvAAAAAElFTkSuQmCC" # 1) 解码成 bytes(关键) image_bytes = base64.b64decode(b64) # 2) 构造 image 块 image_block = { "image": { "format": "png", "source": {"bytes": image_bytes}, # 必须是 bytes,不是字符串 } } # 3) 发送 client = boto3.client("bedrock-runtime", region_name="us-west-2") resp = client.converse( modelId="anthropic.claude-3-5-sonnet-20241022-v2:0", messages=[{ "role": "user", "content": [ image_block, {"text": "这张图里有什么?"}, ], }], inferenceConfig={"maxTokens": 256}, ) print(resp["output"]["message"]["content"])

JS SDK(ConverseCommand)等价写法:

import { BedrockRuntimeClient, ConverseCommand } from "@aws-sdk/client-bedrock-runtime"; const b64 = "iVBORw0KGgo..."; const bytes = Uint8Array.from(Buffer.from(b64, "base64")); // base64 -> bytes const cmd = new ConverseCommand({ modelId: "anthropic.claude-3-5-sonnet-20241022-v2:0", messages: [{ role: "user", content: [ { image: { format: "png", source: { bytes } } }, { text: "这张图里有什么?" }, ], }], }); const res = await new BedrockRuntimeClient({ region: "us-west-2" }).send(cmd);

五、解决方案(第一层:最小直接修复)

最小修复是发送前把 base64 解码为字节,并声明format

import base64 def b64_to_image_block(b64: str, fmt: str = "png") -> dict: return { "image": { "format": fmt, "source": {"bytes": base64.b64decode(b64)}, } } # 用法 block = b64_to_image_block(my_b64, fmt="jpeg")

要点:

  • source.bytes必须是解码后的二进制,不是 base64 字符串;
  • format必须与实际图片格式一致(png/jpeg/gif/webp等);
  • 若图片已在 S3,直接用source: {"s3Location": {"uri": "s3://..."}},连解码都省了。

六、解决方案(第二层:结构化改进)

把"图片源构造"做成策略,统一处理 base64 / 文件路径 / S3 三种来源:

from dataclasses import dataclass import base64 from pathlib import Path from typing import Union @dataclass(frozen=True) class BedrockImageBytesPolicy: """Bedrock 图片块构造策略:base64/文件/S3 -> 合规 image 块。 规则: - base64: 解码成 bytes 再放 source.bytes - 文件: 读二进制 - s3: 用 s3Location - format 必须显式声明 """ def from_base64(self, b64: str, fmt: str) -> dict: return {"image": {"format": fmt, "source": {"bytes": base64.b64decode(b64)}}} def from_file(self, path: Union[str, Path], fmt: str) -> dict: data = Path(path).read_bytes() return {"image": {"format": fmt, "source": {"bytes": data}}} def from_s3(self, uri: str) -> dict: return {"image": {"source": {"s3Location": {"uri": uri}}}} def demo() -> None: policy = BedrockImageBytesPolicy() blk = policy.from_base64("iVBOR", "png") assert blk["image"]["source"]["bytes"] == base64.b64decode("iVBOR") print("base64 -> bytes 块 OK") if __name__ == "__main__": demo()

七、解决方案(第三层:断言 / CI 守护)

import base64 import pytest from your_module import BedrockImageBytesPolicy def test_from_base64_decodes(): policy = BedrockImageBytesPolicy() blk = policy.from_base64("aGVsbG8=", "png") # "hello" base64 assert blk["image"]["source"]["bytes"] == b"hello" assert blk["image"]["format"] == "png" def test_from_base64_not_string(): policy = BedrockImageBytesPolicy() blk = policy.from_base64("aGVsbG8=", "png") # bytes 字段必须是 bytes 而非 str assert isinstance(blk["image"]["source"]["bytes"], bytes) assert not isinstance(blk["image"]["source"]["bytes"], str) def test_from_s3_shape(): policy = BedrockImageBytesPolicy() blk = policy.from_s3("s3://bucket/k.png") assert blk["image"]["source"]["s3Location"]["uri"].startswith("s3://") def test_from_file(tmp_path): policy = BedrockImageBytesPolicy() p = tmp_path / "x.png" p.write_bytes(b"\x89PNG") blk = policy.from_file(p, "png") assert blk["image"]["source"]["bytes"] == b"\x89PNG" def test_format_declared(): policy = BedrockImageBytesPolicy() blk = policy.from_base64("aGk=", "jpeg") assert blk["image"]["format"] == "jpeg"

CI 里加一条:对任何图片输入,断言source.bytes是字节(非字符串),避免把 base64 当 bytes 传导致ValidationException

八、排查清单

  • 是否把 base64 字符串直接塞进了source.bytes?必须先b64decode成字节。
  • format是否与实际图片格式一致(png/jpeg/...)?
  • 图片在 S3 吗?可直接用s3Location,免解码。
  • JS 侧是否用Uint8Array.from(Buffer.from(b64,'base64'))
  • source字段名是否拼对?Bedrock 用bytes/s3Location,没有base64字段。
  • 多图是否都在同一条user消息的content里?

九、小结

在 Bedrock 用Converse传 base64 图片报格式错误,根因是 Bedrock 的图片块要求source.bytes解码后的二进制字节,而你直接把 base64 字符串当bytes传了——Bedrock 没有base64这个 source 字段。最小修复是发送前base64.b64decode成字节并声明format;结构化做法是抽成BedrockImageBytesPolicy,统一处理 base64/文件/S3 三种来源;最后用 pytest 守护"source.bytes必为字节(非字符串)",避免校验失败。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/21 22:31:43

C++可变参数模板:从类型安全到编译期计算的范式跃迁

1. 项目概述&#xff1a;从“变参函数”到“变参模板”的范式跃迁在C98/03的时代&#xff0c;如果你需要处理数量不定的参数&#xff0c;第一反应可能就是printf或scanf这类C风格变参函数&#xff0c;或者标准库里的va_list、va_start、va_arg、va_end那一套。用过的人都知道&a…

作者头像 李华
网站建设 2026/8/21 22:31:43

经管类学生考证清单:按实用性排了个序,从大一到毕业都覆盖了

经管类学生大概是大学里考证氛围最浓的群体之一。从大一的初级会计、证券从业&#xff0c;到大三大四的CPA、CFA&#xff0c;再到毕业后的各种进阶认证&#xff0c;考证似乎成了经管人的标配。但考什么、什么时候考、考了有什么用&#xff0c;其实很多人没想清楚。先说一个前提…

作者头像 李华
网站建设 2026/8/21 22:30:52

认知拜占庭容错:解决AI智能体诚实但错误的共识难题

1. 项目概述&#xff1a;当“诚实”成为共识的瓶颈 最近在跟几个做AI Agent和去中心化基础设施的朋友聊天&#xff0c;大家不约而同地提到了一个共同的痛点&#xff1a;当你的系统由一群自主决策、可能“心怀鬼胎”的智能体&#xff08;Agent&#xff09;组成时&#xff0c;如何…

作者头像 李华
网站建设 2026/8/21 22:28:35

3D建模软件横向评测:Blender、Maya、C4D等主流工具选型指南

这次我们来看一个关于3D建模软件的横向评测项目——“从夯到拉系列 建模软件大锐评”。这不是一个具体的开源工具&#xff0c;而是一系列深度技术评测内容&#xff0c;旨在为不同需求的3D创作者提供选型参考。对于刚入门的建模新手、寻求效率突破的资深美术&#xff0c;或是需要…

作者头像 李华
网站建设 2026/8/21 22:25:41

Cermet:基于SQL的Git推送权限精细控制开源方案

这次我们来看一个很有意思的开源项目&#xff1a;Cermet。它的核心目标不是解决什么复杂的算法问题&#xff0c;而是瞄准了一个非常具体且高频的痛点——如何安全、精细地控制对 GitHub 仓库的推送&#xff08; git push &#xff09;权限。如果你管理着一个团队或一个开源项…

作者头像 李华