2025, Dec 03 06:02

Как исправить ошибку tagged union в AWS Bedrock при отправке текста и PDF в одном сообщении

Падение converse в AWS Bedrock: ParamValidationError при совмещении text и document в messages.content. Объясняем tagged union и показываем пример с PDF.

Передавать PDF и подсказку в AWS Bedrock Runtime одним блоком контента кажется безобидным, пока всё не рушится с загадочной ошибкой валидации. Если ваш вызов converse для модели amazon.nova-premier-v1:0 падает при объединении текста и документа, проблема не в модели. Дело в форме messages.content и в том, как Bedrock применяет тегированное объединение (tagged union).

Воспроизводимый пример в коде

Этот фрагмент открывает PDF, отправляет его вместе с подсказкой и вызывает ошибку валидации. Логика проста, но структура тела запроса не соответствует ожиданиям Bedrock.

def run_flow():
with open("file.pdf", "rb") as fh:
pdf_bytes = fh.read()
rt = boto3.client("bedrock-runtime", "us-east-1")
out = rt.converse(
modelId=MODEL_ID,
messages=[
{
"role": "user",
"content": [
{
"text": "explain this document",
"document": {
"format": "pdf",
"name": "file",
"source": {
"bytes": pdf_bytes,
},
},
},
],
},
],
)

print(out)
return out

Сервис отвечает прозрачной подсказкой:

botocore.exceptions.ParamValidationError: Parameter validation failed: Invalid number of parameters set for tagged union structure messages[0].content[0]. Can only set one of the following keys: text, image, document, video, toolUse, toolResult, guardContent, cachePoint, reasoningContent.

Что происходит на самом деле

В Bedrock Runtime поле messages[...].content — это массив блоков контента, и каждый блок — это объединение. В одном блоке можно задать только одного участника этого объединения. В официальном описании это сформулировано прямо:

Этот тип данных является UNION, поэтому при использовании или возврате может быть указан только один из следующих членов.

Размещение одновременно text и document в одном элементе content нарушает правило объединения. Поэтому валидатор отклоняет запрос, хотя оба поля по отдельности допустимы.

Решение: разделите контент на отдельные блоки

Правильный подход — отправлять PDF как один блок контента, а подсказку — как другой блок в рамках того же сообщения. Так каждый блок соблюдает ограничение объединения и при этом сохраняется задуманная семантика.

def run_flow():
with open("file.pdf", "rb") as fh:
pdf_bytes = fh.read()
rt = boto3.client("bedrock-runtime", "us-east-1")
out = rt.converse(
modelId=MODEL_ID,
messages=[
{
"role": "user",
"content": [
{
"document": {
"format": "pdf",
"name": "file",
"source": {
"bytes": pdf_bytes,
},
},
},
{
"text": "explain this document",
},
],
},
],
)

print(out)
return out

Почему это важно

Как только вы начинаете сочетать разные модальности в Bedrock Runtime, форма запроса становится столь же значимой, как и его содержимое. Непонимание контракта объединения приводит к жёстким остановкам ещё до запуска модели, и ошибка проявляется на стороне клиента. Зная, что messages.content — это массив однотипных блоков, вы экономите время, делаете запросы предсказуемыми и выстраиваете код в соответствии с тем, как API задуман для рассуждения над раздельными входами.

Выводы

Если нужно отправить подсказку и документ вместе, держите их в отдельных блоках контента внутри одного сообщения. Относитесь к каждому блоку как к строго одному типу: text, document, image и т. д. Эта небольшая структурная правка устраняет ошибку валидации и позволяет модели получить и файл, и инструкцию именно так, как задумано.