fix(bedrock): fall back to sync calls from acall

This commit is contained in:
ViditOstwal
2026-09-21 13:57:12 +05:30
parent 0374c63129
commit 07a2b26abb
2 changed files with 56 additions and 4 deletions

View File

@@ -1,5 +1,6 @@
from __future__ import annotations
import asyncio
from collections.abc import Mapping, Sequence
from contextlib import AsyncExitStack
import json
@@ -485,15 +486,25 @@ class BedrockCompletion(BaseLLM):
Generated text response or structured output.
Raises:
NotImplementedError: If aiobotocore is not installed.
LLMContextLengthExceededError: If context window is exceeded.
"""
effective_response_model = response_model or self.response_format
if not AIOBOTOCORE_AVAILABLE:
raise NotImplementedError(
"Async support for AWS Bedrock requires aiobotocore. "
'Install with: uv add "crewai[bedrock]"'
logging.warning(
"aiobotocore is not installed; falling back to synchronous AWS "
"Bedrock calls in a worker thread. Install `crewai[bedrock]` "
"for native async support."
)
return await asyncio.to_thread(
self.call,
messages,
tools=tools,
callbacks=callbacks,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
response_model=effective_response_model,
)
with llm_call_context():

View File

@@ -1,4 +1,6 @@
import logging
import os
import threading
from unittest.mock import patch, MagicMock
import pytest
@@ -210,6 +212,45 @@ def test_bedrock_completion_call():
mock_call.assert_called_once_with("Hello, how are you?")
@pytest.mark.asyncio
async def test_bedrock_acall_falls_back_to_sync_call_without_aiobotocore(caplog):
"""Async Bedrock calls remain usable when only the sync SDK is installed."""
llm = LLM(model="bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0")
callbacks = [MagicMock()]
available_functions = {"lookup": MagicMock()}
call_thread_id: int | None = None
def sync_call(*args, **kwargs):
nonlocal call_thread_id
call_thread_id = threading.get_ident()
return "fallback response"
with caplog.at_level(logging.WARNING):
with (
patch.object(bedrock_completion, "AIOBOTOCORE_AVAILABLE", False),
patch.object(llm, "call", side_effect=sync_call) as mock_call,
):
event_loop_thread_id = threading.get_ident()
result = await llm.acall(
"Hello, how are you?",
callbacks=callbacks,
available_functions=available_functions,
)
assert result == "fallback response"
assert call_thread_id != event_loop_thread_id
assert "falling back to synchronous AWS Bedrock calls" in caplog.text
mock_call.assert_called_once_with(
"Hello, how are you?",
tools=None,
callbacks=callbacks,
available_functions=available_functions,
from_task=None,
from_agent=None,
response_model=None,
)
def test_bedrock_completion_called_during_crew_execution():
"""
Test that BedrockCompletion.call is actually invoked when running a crew