fix(translation): preserve multimodal tool results - #389
Conversation
Signed-off-by: Ting-Hong Shieh <32212900+ting-hong-shieh@users.noreply.github.com>
WalkthroughAnthropic document and tool-result blocks now retain normalized multimodal content. OpenAI Chat translation keeps text in ChangesMultimodal tool-result translation
Estimated code review effort: 3 (Moderate) | ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/switchyard-translation/src/codecs/anthropic/buffered.rs`:
- Around line 625-648: Update decode_anthropic_file_source so its final
unsupported-source fallback stores Value::Object(block.clone()) rather than only
source.clone(), preserving the document wrapper for encode_one_anthropic_block.
Add a regression test covering an unsupported document source and verifying the
re-encoded block retains the complete original document structure.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 1f81d3d1-0110-497d-b9c4-ca5e5eb91786
📒 Files selected for processing (3)
crates/switchyard-translation/src/codecs/anthropic/buffered.rscrates/switchyard-translation/src/codecs/openai_chat/buffered.rscrates/switchyard-translation/tests/request_translation.rs
Signed-off-by: Ting-Hong Shieh <32212900+ting-hong-shieh@users.noreply.github.com>
|
@ting-hong-shieh Thanks for putting this PR. Can you please attach a snapshot of the output or trace before this fix and after the fix. Will be easy to understand and review with that. Thanks |
|
Thanks, @ayushag-nv. I ran the same buffered Anthropic → OpenAI Chat translation at the PR base ( Input [
{"type": "text", "text": "here it is:"},
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": "iVBORw0KGgo="
}
}
]Before ( {
"messages": [
{
"role": "tool",
"tool_call_id": "toolu_1",
"content": "here it is: {\"source\":{\"data\":\"iVBORw0KGgo=\",\"media_type\":\"image/png\",\"type\":\"base64\"},\"type\":\"image\"}"
}
],
"diagnostics": []
}The image block is serialized into ordinary tool-message text. After ( {
"messages": [
{
"role": "tool",
"tool_call_id": "toolu_1",
"content": "here it is:"
},
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "data:image/png;base64,iVBORw0KGgo="
}
}
]
}
],
"diagnostics": [
{
"code": "lossy_conversion",
"severity": "Warning",
"message": "OpenAI Chat tool messages only support text; non-text tool-result content was moved to a user message",
"source": "anthropic_messages",
"target": "openai_chat"
}
]
}Text now remains in the tool message, while the image is preserved as multimodal content in the following user message. The role lowering is also reported through the existing lossy-conversion diagnostic. |
Signed-off-by: Elias Shieh <32212900+ting-hong-shieh@users.noreply.github.com>
d7fcd6d to
664626c
Compare
What changed
text,image, anddocumentblocks nested in Anthropictool_result.contentwhen decoding into the neutral IR.toolmessages and lower non-text output into a following multimodalusermessage.Why
The Anthropic decoder previously flattened every non-text block inside
tool_result.contentinto JSON text. By the time the OpenAI Chat encoder ran, the image or document structure had already been lost, so the downstream model received base64 or metadata as ordinary text.OpenAI Chat tool messages accept text content but not image or file parts. User messages accept those multimodal parts, so the translation now splits the content at that protocol boundary instead of silently stringifying it.
Closes #380.
Validation
cargo fmt --all --checkcargo clippy --workspace --all-targets -- -D warningscargo test --workspaceRegression coverage includes base64 images, base64 documents, parallel tool-result ordering, diagnostics, and strict rejection policy.
Summary by CodeRabbit
New Features
Bug Fixes