0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-14 13:58:53 +08:00
discourse/plugins/discourse-ai/lib/completions/dialects
Takao Yokoyama cea4780cb3
FIX: AI: AWS Bedrock Converse image uploads were doubly base64-encoded (#39880)
## Summary

Image uploads delivered through the `aws_bedrock_converse` LLM provider
were rejected by Bedrock with `Could not process image` whenever an
agent / LLM had `vision_enabled` set to true.

Two related bugs are fixed:

### 1. `Dialects::Converse#upload_node` — base64 string passed where raw
bytes expected

In `plugins/discourse-ai/lib/completions/dialects/converse.rb`, image
content was emitted as:

```ruby
source: { bytes: details[:base64] }
```

`details[:base64]` is the upload's base64-encoded string (as produced by
`UploadEncoder`), but `Aws::BedrockRuntime::Client#converse` expects
**raw bytes** on the `:bytes` key — the SDK then base64-encodes them on
the wire. Passing the already-base64-encoded string causes Bedrock to
receive **doubly-encoded** data, which it cannot decode into a valid
image. Decoding back to raw bytes via
`Base64.decode64(details[:base64])` resolves the round-trip.

### 2. `AwsBedrockConverse#perform_completion!` — JSON-logging fails on
binary payloads

With raw bytes now flowing through `sdk_params`, the subsequent
`sdk_params.to_json` call (used to record the request in `start_log`)
raises `EncodingError` because PNG/JPEG bytes are not valid UTF-8. The
call is wrapped in `begin / rescue EncodingError` so the request can
still proceed; a placeholder string is recorded in the audit log instead
of the binary payload.

## Test plan

- A new spec case in
`plugins/discourse-ai/spec/lib/completions/dialects/converse_spec.rb`
asserts that `details[:base64]` is decoded back to raw bytes before
being emitted as `source: { bytes: ... }`. This guards against
regression.
- Verified end-to-end against `us.anthropic.claude-sonnet-4-6` via
Bedrock Converse on `ap-northeast-1` → `us-east-1` cross-region
inference profile: with this patch the model correctly describes
uploaded PNG attachments (a Loupe Browser version warning dialog)
instead of returning `Could not process image`.

## Reproduction (before the fix)

1. Configure an `aws_bedrock_converse` LLM in Discourse and assign it to
an `AiAgent` with `vision_enabled: true`.
2. Wire up `llm_triage` (or any path that goes through
`Dialects::Converse#upload_node`) to reply to a topic that contains an
image upload.
3. Observe:
`DiscourseAi::Completions::Endpoints::Base::CompletionFailed: The model
returned the following errors: Could not process image`

## Discovered while

Standing up a Discourse instance with Bedrock-backed AI as part of an
internal forum spike. Happy to iterate on the patch (e.g. tighten the
log fallback or extract a helper) if reviewers prefer a different shape.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Rafael Silva <xfalcox@gmail.com>
2026-05-26 15:16:49 -03:00
..
chat_gpt.rb FEATURE: extract text from document uploads for LLM prompts (#39634) 2026-05-05 08:16:23 +10:00
claude.rb FEATURE: extract text from document uploads for LLM prompts (#39634) 2026-05-05 08:16:23 +10:00
claude_tools.rb FEATURE: support thinking summary on responses API (#36013) 2025-11-18 07:54:14 +11:00
cohere_tools.rb
command.rb DEV: Remove unused VALID_ID_REGEX constants (#37432) 2026-02-02 16:25:04 +11:00
converse.rb FIX: AI: AWS Bedrock Converse image uploads were doubly base64-encoded (#39880) 2026-05-26 15:16:49 -03:00
converse_tools.rb FEATURE: Add AWS Bedrock Converse API provider (#38903) 2026-03-30 12:37:30 -03:00
dialect.rb FEATURE: extract text from document uploads for LLM prompts (#39634) 2026-05-05 08:16:23 +10:00
fake.rb
gemini.rb FEATURE: extract text from document uploads for LLM prompts (#39634) 2026-05-05 08:16:23 +10:00
mistral.rb DEV: Remove unused native_tool_support? (#37439) 2026-02-02 19:03:22 +11:00
nova.rb DEV: Update rubocop-discourse to 3.13 and autofix issues (#35073) 2025-10-06 16:11:01 +02:00
nova_tools.rb
ollama.rb
ollama_tools.rb
open_ai_compatible.rb
open_ai_responses.rb FEATURE: extract text from document uploads for LLM prompts (#39634) 2026-05-05 08:16:23 +10:00
open_ai_tools.rb FIX: properly terminate chains of tool calls across multiple providers (#36750) 2025-12-19 07:00:51 +11:00
xml_tools.rb DEV: Enable Style/RedundantParentheses rubocop rule (#40095) 2026-05-19 15:48:09 +02:00