Além do texto: imagem, documento, vídeo e áudio
- ⬜👋 Sua primeira chamada: a Converse API na prática(AWS Bedrock — GenAI em Produção)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
"Só dá para mandar texto? Consigo mandar uma imagem? Um PDF? E um vídeo?" — essas perguntas aparecem no primeiro dia de quem sai do hello world de chat. A resposta curta é sim: a Converse API é multimodal por design. Você não troca de endpoint nem de SDK — troca o tipo de bloco dentro do content da mensagem. Este módulo é o mapa das modalidades: o que cada uma aceita, os limites reais e o código para mandar cada uma.
As modalidades entram como ContentBlocks
Toda mensagem da Converse tem um content, que é uma lista de blocos. Cada bloco tem uma chave que diz o tipo. Texto é só um dos tipos — o mesmo array aceita imagem, documento e vídeo lado a lado com o texto.
- text — a string do prompt. O tipo mais comum, mas nunca o único disponível.
- image — visão (vision): png, jpeg, gif, webp. Para OCR, descrição e análise visual.
- document — arquivos: pdf, csv, doc, docx, xls, xlsx, html, txt, md. O modelo lê o conteúdo do arquivo.
- video — vídeo (mp4 e outros), nos modelos que suportam. Sumarização e QA sobre gravações.
- reasoningContent, toolUse e toolResult — blocos que aparecem em raciocínio e tool use; cobertos em módulos próprios.
Áudio é caso à parte: Nova Sonic
Áudio NÃO entra como um ContentBlock da Converse padrão. Voz é atendida pelo Amazon Nova Sonic, um modelo de speech-to-speech que roda por uma API bidirecional de streaming (InvokeModelWithBidirectionalStream) — você abre um canal e troca áudio em tempo real, não manda um bloco 'audio' num converse(). É uma modalidade e um fluxo próprios; não confunda com os quatro blocos de texto/imagem/documento/vídeo.
O mapa das modalidades
Antes do código, fixe os limites que a Converse impõe. Eles mudam por modalidade e são a fonte número um de erro 400 de quem começa (mandar imagem grande demais, PDF acima do teto, esquecer o bloco text do documento).
| Modalidade | Formatos | Limites na Converse |
|---|---|---|
| Texto | Qualquer string UTF-8 | Limitado pela janela de contexto do modelo (tokens), não por MB |
| Imagem | png, jpeg, gif, webp | Até 20 imagens/request; cada uma ≤ 3,75 MB e ≤ 8000×8000 px |
| Documento | pdf, csv, doc, docx, xls, xlsx, html, txt, md | Até 5 docs/request; ≤ 4,5 MB cada (exceção: PDF em Claude 4+ e PDF/DOCX na Nova); exige bloco text junto |
| Vídeo | mp4, mkv, mov, webm e outros | Só em modelos com suporte a vídeo (ex.: Nova Pro / Nova 2); via bytes ou S3 URI |
| Áudio | — (fora do Converse padrão) | Nova Sonic: streaming speech-to-speech por API bidirecional dedicada |
Imagem: dando visão ao modelo
Mandar uma imagem transforma o LLM num modelo de visão: ele descreve, faz OCR, lê um gráfico, compara telas, modera conteúdo. Na Converse os limites são concretos e vale memorizá-los:
- Formatos aceitos: png, jpeg, gif, webp — o campo format deve bater com os bytes reais.
- Até 20 imagens por request na Converse.
- Cada imagem ≤ 3,75 MB.
- Dimensão máxima 8000×8000 px.
- Casos típicos: OCR de nota fiscal, descrição de imagem, leitura de gráfico/diagrama, moderação visual, comparação de telas.
import boto3
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
# Lê o arquivo local; o SDK faz o base64 por baixo dos panos.
with open("diagrama.png", "rb") as f:
image_bytes = f.read()
resp = bedrock.converse(
modelId="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
messages=[
{
"role": "user",
"content": [
{"text": "Descreva o que aparece nesta imagem e extraia todo o texto visível."},
{
"image": {
"format": "png",
"source": {"bytes": image_bytes},
}
},
],
}
],
)
print(resp["output"]["message"]["content"][0]["text"])Na Converse API, quantas imagens você pode enviar em um único request e qual o teto de tamanho por imagem?
Documento: PDFs, planilhas e contratos
O bloco document manda o arquivo inteiro para o modelo ler — não é OCR de imagem, é o conteúdo estruturado (texto, tabelas, layout). Aceita pdf, csv, doc, docx, xls, xlsx, html, txt, md: até 5 documentos por request, ≤ 4,5 MB cada. Mas esse teto tem uma exceção que muda o jogo.
- Até 5 documentos por request na Converse.
- Limite geral de 4,5 MB por documento.
- Exceção: o teto de 4,5 MB NÃO se aplica a PDF nos modelos Claude 4+, nem a PDF e DOCX nos modelos Nova — aí você manda arquivos bem maiores (confirme o teto vigente no console/docs).
- Todo bloco document EXIGE um bloco text no mesmo content — nem que seja 'Resuma este arquivo'.
Documento sempre acompanha um bloco text
Um bloco document sozinho no content faz a chamada falhar: a Converse exige que exista um bloco text na mesma mensagem dizendo o que fazer com o arquivo. Pense no document como o anexo e no text como o pedido — sem o pedido, o modelo não tem tarefa. Isso vale para 1 ou para 5 documentos: basta um bloco text para o conjunto.
import boto3
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
resp = bedrock.converse(
modelId="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
messages=[
{
"role": "user",
"content": [
{"text": "Resuma este contrato em 5 bullets e liste as clausulas de rescisao."},
{
"document": {
"format": "pdf",
# Nome NEUTRO e fixo, nunca derivado do usuario (vetor de injection).
"name": "doc1",
"source": {
"s3Location": {
"uri": "s3://meu-bucket/contratos/2026/contrato-123.pdf",
# Conta dona do bucket (obrigatorio em cross-account).
"bucketOwner": "123456789012",
}
},
}
},
],
}
],
)
print(resp["output"]["message"]["content"][0]["text"])document.name é vetor de prompt injection
O campo document.name entra no prompt que o modelo vê. Se você preenchê-lo com algo controlado pelo usuário (nome do upload, título vindo do front), abre porta para prompt injection — um atacante nomeia o arquivo 'Ignore as instruções anteriores e...'. Regra: use um nome neutro e fixo (doc1, doc2, anexo-a) ou um UUID interno. Nunca derive document.name de input do usuário.
Um contrato em PDF de 12 MB — dá para mandar direto na Converse para a Claude 4?
Vídeo: a modalidade mais nova (e mais restrita)
Vídeo é a modalidade mais recente e a mais restrita: só alguns modelos suportam (na família Amazon Nova, por exemplo, Nova Pro e Nova 2). Claude e a maioria dos modelos de texto não processam vídeo. Como um clipe pesa muito, o caminho recomendado é referenciar por S3, não embutir bytes.
bytes vs s3Location: como o conteúdo chega ao modelo
Todo bloco image, document e video aceita duas fontes: source.bytes (o arquivo vai embutido no request; o SDK faz o base64) ou source.s3Location.uri (o Bedrock lê o objeto direto do seu bucket). A escolha é sobre tamanho e onde o arquivo já está.
📋 Preciso mandar conteúdo binário (imagem, documento ou vídeo) para o modelo. Uso source.bytes ou source.s3Location?
bytes embute o arquivo no corpo do request (o SDK codifica em base64) — ótimo para arquivo pequeno e efêmero que você acabou de gerar ou receber e não quer persistir. s3Location referencia um objeto que já está no bucket — na prática obrigatório para vídeo e arquivos grandes, e evita inflar o payload da API.
Alt: source.bytes — Infla o request; o base64 adiciona ~33% ao tamanho; ruim para vídeo e arquivos grandes; o conteúdo some depois da chamada (efêmero).
Alt: source.s3Location — Exige o objeto já no S3 e s3:GetObject na role; há o overhead de subir antes; precisa de bucketOwner para buckets cross-account.
S3 URI exige s3:GetObject (e bucketOwner cross-account)
Quando você usa source.s3Location, quem lê o objeto é o Bedrock em nome da sua chamada — a identidade IAM que invoca precisa de s3:GetObject naquele objeto. Para buckets de outra conta, informe bucketOwner (o account id dono do bucket) para se proteger de confused deputy. Já o source.bytes não exige permissão de S3 nenhuma, porque o arquivo vai embutido no request.
- → bytes: simples, e limitado pelo tamanho do payload
- → referência ao objeto exige permissão de leitura
- → arquivo grande vai por referência
- Fora da AWS
- Armazenamento
- Compute
- Segurança e identidade
- IA e machine learning
A escolha entre os dois não é de gosto: bytes no request esbarra no limite de tamanho do payload, e a referência ao objeto exige que o Bedrock tenha permissão de leitura no bucket. Confirme os limites vigentes por modalidade no console.
- Conteúdo pequeno: bytes no request. Mais simples e sem dependência de bucket. O teto é o tamanho do payload da requisição, que varia por modalidade.
- Conteúdo grande: referência ao objeto. O arquivo já vive no S3 e você passa a localização. Exige que o Bedrock tenha permissão de leitura — é o erro de configuração mais comum aqui.
- O modelo recebe blocos tipados. Cada modalidade é um bloco de conteúdo próprio na mensagem. Atenção ao nome do documento: ele entra no contexto e é vetor de injeção — use nome neutro.
- Quem precisa ler o objeto é o Bedrock. Ao passar a referência ao S3, a permissão de leitura tem de estar na role que o Bedrock assume — não na role da sua aplicação, que já leu o suficiente para montar o request. É a confusão que produz acesso negado com política aparentemente correta, porque a política correta está no lado errado.
- Confirme o limite antes de desenhar em volta dele. O teto de tamanho varia por modalidade e por modelo, e muda com o tempo. Desenhar o caminho de bytes no request para um tipo de arquivo cujo limite você não conferiu é descobrir o teto em produção, com o primeiro documento grande do primeiro cliente grande.
Você monta o bloco document e vai preencher document.name. De onde esse valor NUNCA deve vir?
reasoningContent: o raciocínio volta separado
Modelos de raciocínio (Claude com extended thinking, DeepSeek-R1, Nova com reasoning) não devolvem só text: devolvem também um bloco reasoningContent com o passo a passo do raciocínio, separado da resposta final. E ele vem com uma pegadinha de estado.
reasoningContent volta com signature — reenvie-a intacta
Em modelos de raciocínio, a resposta traz um bloco reasoningContent com reasoningText.text (o raciocínio) e uma signature (assinatura anti-tamper do provedor). Se você mantém histórico multi-turn, precisa REENVIAR o bloco reasoningContent com a signature intacta nas próximas turns — alterar ou omitir a signature causa erro de validação. Há ainda redactedContent: raciocínio que o provedor devolve criptografado (você não lê, mas reenvia igual). Detalhamos thinking em módulo próprio.
Próximo passo
Você já sabe mandar texto, imagem, documento e vídeo — e como o raciocínio volta. Mas qual modelo escolher para cada caso? Vision numa Claude, sumarização barata numa Nova, vídeo numa Nova Pro... É o próximo módulo: O catálogo de modelos — qual escolher para cada caso.
Perguntas frequentes
❓ Como enviar imagem ou PDF na mesma requisição do texto?
❓ Vale extrair texto do documento antes ou mandar o documento?
❓ Modelo multimodal substitui serviço de OCR?
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…