fix(llms/aws_bedrock): iterate Converse content blocks for Anthropic text (#6369)
This commit is contained in:
@@ -579,11 +579,20 @@ class AWSBedrockLLM(LLMBase):
|
|||||||
# Use converse API for Anthropic models
|
# Use converse API for Anthropic models
|
||||||
response = self.client.converse(**converse_params)
|
response = self.client.converse(**converse_params)
|
||||||
|
|
||||||
# Parse Converse API response
|
# Parse Converse API response. Claude reasoning models can emit a
|
||||||
|
# `reasoningContent` block before the `text` block, so iterate to
|
||||||
|
# find the first block that carries text instead of indexing
|
||||||
|
# content[0] (same approach as the MiniMax branch below).
|
||||||
if hasattr(response, 'output') and hasattr(response.output, 'message'):
|
if hasattr(response, 'output') and hasattr(response.output, 'message'):
|
||||||
return response.output.message.content[0].text
|
for block in response.output.message.content:
|
||||||
|
if hasattr(block, 'text'):
|
||||||
|
return block.text
|
||||||
|
return ""
|
||||||
elif 'output' in response and 'message' in response['output']:
|
elif 'output' in response and 'message' in response['output']:
|
||||||
return response['output']['message']['content'][0]['text']
|
for block in response['output']['message']['content']:
|
||||||
|
if 'text' in block:
|
||||||
|
return block['text']
|
||||||
|
return ""
|
||||||
else:
|
else:
|
||||||
return str(response)
|
return str(response)
|
||||||
|
|
||||||
|
|||||||
@@ -506,3 +506,51 @@ class TestParseResponseLegacy:
|
|||||||
response = {"body": body}
|
response = {"body": body}
|
||||||
result = llm._parse_response(response, tools=None)
|
result = llm._parse_response(response, tools=None)
|
||||||
assert result == "hello from ai21"
|
assert result == "hello from ai21"
|
||||||
|
|
||||||
|
|
||||||
|
class TestAnthropicConverseContentParsing:
|
||||||
|
"""The Anthropic Converse branch must not assume content[0] is the text
|
||||||
|
block: Claude reasoning models emit a reasoningContent block before the
|
||||||
|
text block, and some stop conditions produce an empty content array. The
|
||||||
|
parser iterates for the first block carrying text, like the MiniMax branch.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_text_after_reasoning_content_block(self, mock_boto3):
|
||||||
|
mock_boto3.converse.return_value = {
|
||||||
|
"output": {
|
||||||
|
"message": {
|
||||||
|
"content": [
|
||||||
|
{"reasoningContent": {"reasoningText": {"text": "step by step..."}}},
|
||||||
|
{"text": "final answer"},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
llm = _make_llm("anthropic.claude-3-5-sonnet-20240620-v1:0", mock_boto3)
|
||||||
|
|
||||||
|
assert llm.generate_response(MESSAGES) == "final answer"
|
||||||
|
|
||||||
|
def test_empty_content_returns_empty_string(self, mock_boto3):
|
||||||
|
mock_boto3.converse.return_value = {"output": {"message": {"content": []}}}
|
||||||
|
llm = _make_llm("anthropic.claude-3-5-sonnet-20240620-v1:0", mock_boto3)
|
||||||
|
|
||||||
|
assert llm.generate_response(MESSAGES) == ""
|
||||||
|
|
||||||
|
def test_plain_text_content_still_returned(self, mock_boto3):
|
||||||
|
mock_boto3.converse.return_value = _converse_response("plain answer")
|
||||||
|
llm = _make_llm("anthropic.claude-3-5-sonnet-20240620-v1:0", mock_boto3)
|
||||||
|
|
||||||
|
assert llm.generate_response(MESSAGES) == "plain answer"
|
||||||
|
|
||||||
|
def test_object_style_response_iterates_blocks(self, mock_boto3):
|
||||||
|
# Defensive attr-style branch: object wrapper with a reasoning block first.
|
||||||
|
from types import SimpleNamespace
|
||||||
|
|
||||||
|
reasoning_block = SimpleNamespace(reasoningContent={"reasoningText": {"text": "hmm"}})
|
||||||
|
text_block = SimpleNamespace(text="object answer")
|
||||||
|
mock_boto3.converse.return_value = SimpleNamespace(
|
||||||
|
output=SimpleNamespace(message=SimpleNamespace(content=[reasoning_block, text_block]))
|
||||||
|
)
|
||||||
|
llm = _make_llm("anthropic.claude-3-5-sonnet-20240620-v1:0", mock_boto3)
|
||||||
|
|
||||||
|
assert llm.generate_response(MESSAGES) == "object answer"
|
||||||
|
|||||||
Reference in New Issue
Block a user