Skip to content

Commit 5007af8

Browse files
committed
refactor(llm): remove dead provider helpers
1 parent c5b9d9a commit 5007af8

4 files changed

Lines changed: 0 additions & 287 deletions

File tree

lib/crewai/src/crewai/llms/base_llm.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -438,17 +438,6 @@ def supports_stop_words(self) -> bool:
438438
"""
439439
return DEFAULT_SUPPORTS_STOP_WORDS
440440

441-
def _supports_stop_words_implementation(self) -> bool:
442-
"""Check if stop words are configured for this LLM instance.
443-
444-
Native providers can override supports_stop_words() to return this value
445-
to ensure consistent behavior based on whether stop words are actually configured.
446-
447-
Returns:
448-
True if stop words are configured and can be applied
449-
"""
450-
return bool(self.stop_sequences)
451-
452441
def _apply_stop_words(self, content: str) -> str:
453442
"""Apply stop words to truncate response content.
454443

lib/crewai/src/crewai/llms/providers/anthropic/completion.py

Lines changed: 0 additions & 198 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,120 +1385,6 @@ def _execute_first_tool(
13851385
from_agent=from_agent,
13861386
)
13871387

1388-
# TODO: we drop this
1389-
def _handle_tool_use_conversation(
1390-
self,
1391-
initial_response: Message | BetaMessage,
1392-
tool_uses: list[_AnthropicToolUseBlock],
1393-
params: dict[str, Any],
1394-
available_functions: dict[str, Any],
1395-
from_task: Any | None = None,
1396-
from_agent: Any | None = None,
1397-
) -> str:
1398-
"""Handle the complete tool use conversation flow.
1399-
1400-
This implements the proper Anthropic tool use pattern:
1401-
1. Claude requests tool use
1402-
2. We execute the tools
1403-
3. We send tool results back to Claude
1404-
4. Claude processes results and generates final response
1405-
"""
1406-
tool_results = self._execute_tools_and_collect_results(
1407-
tool_uses, available_functions, from_task, from_agent
1408-
)
1409-
1410-
follow_up_params = params.copy()
1411-
1412-
assistant_content: list[
1413-
ThinkingBlock | ToolUseBlock | TextBlock | dict[str, Any]
1414-
] = []
1415-
for block in initial_response.content:
1416-
thinking_block = self._extract_thinking_block(block)
1417-
if thinking_block:
1418-
assistant_content.append(thinking_block)
1419-
elif _is_tool_use_block(block):
1420-
assistant_content.append(
1421-
{
1422-
"type": "tool_use",
1423-
"id": _tool_use_id(block),
1424-
"name": _tool_use_name(block),
1425-
"input": _tool_use_input(block),
1426-
}
1427-
)
1428-
elif hasattr(block, "text"):
1429-
assistant_content.append({"type": "text", "text": block.text})
1430-
1431-
assistant_message = {"role": "assistant", "content": assistant_content}
1432-
1433-
user_message = {"role": "user", "content": tool_results}
1434-
1435-
follow_up_params["messages"] = params["messages"] + [
1436-
assistant_message,
1437-
user_message,
1438-
]
1439-
1440-
try:
1441-
final_response: Message = self._get_sync_client().messages.create(
1442-
**follow_up_params
1443-
)
1444-
1445-
follow_up_usage = self._extract_anthropic_token_usage(final_response)
1446-
self._track_token_usage_internal(follow_up_usage)
1447-
1448-
final_content = ""
1449-
thinking_blocks: list[ThinkingBlock] = []
1450-
1451-
if final_response.content:
1452-
for content_block in final_response.content:
1453-
if hasattr(content_block, "text"):
1454-
final_content += content_block.text
1455-
else:
1456-
thinking_block = self._extract_thinking_block(content_block)
1457-
if thinking_block:
1458-
thinking_blocks.append(cast(ThinkingBlock, thinking_block))
1459-
1460-
if thinking_blocks:
1461-
self._previous_thinking_blocks = thinking_blocks
1462-
1463-
final_content = self._apply_stop_words(final_content)
1464-
1465-
finish_reason, final_response_id = self._extract_finish_reason_and_id(
1466-
final_response
1467-
)
1468-
1469-
self._emit_call_completed_event(
1470-
response=final_content,
1471-
call_type=LLMCallType.LLM_CALL,
1472-
from_task=from_task,
1473-
from_agent=from_agent,
1474-
messages=follow_up_params["messages"],
1475-
usage=follow_up_usage,
1476-
finish_reason=finish_reason,
1477-
response_id=final_response_id,
1478-
)
1479-
1480-
total_usage = {
1481-
"input_tokens": follow_up_usage.get("input_tokens", 0),
1482-
"output_tokens": follow_up_usage.get("output_tokens", 0),
1483-
"total_tokens": follow_up_usage.get("total_tokens", 0),
1484-
}
1485-
1486-
if total_usage.get("total_tokens", 0) > 0:
1487-
logging.info(f"Anthropic API tool conversation usage: {total_usage}")
1488-
1489-
return final_content
1490-
1491-
except Exception as e:
1492-
if is_context_length_exceeded(e):
1493-
logging.error(f"Context window exceeded in tool follow-up: {e}")
1494-
raise LLMContextLengthExceededError(str(e)) from e
1495-
1496-
logging.error(f"Tool follow-up conversation failed: {e}")
1497-
# Fallback to first tool result when follow-up fails
1498-
if tool_results:
1499-
return cast(str, tool_results[0]["content"])
1500-
raise e
1501-
15021388
async def _ahandle_completion(
15031389
self,
15041390
params: dict[str, Any],
@@ -1830,90 +1716,6 @@ async def _ahandle_streaming_completion(
18301716

18311717
return full_response
18321718

1833-
async def _ahandle_tool_use_conversation(
1834-
self,
1835-
initial_response: Message | BetaMessage,
1836-
tool_uses: list[_AnthropicToolUseBlock],
1837-
params: dict[str, Any],
1838-
available_functions: dict[str, Any],
1839-
from_task: Any | None = None,
1840-
from_agent: Any | None = None,
1841-
) -> str:
1842-
"""Handle the complete async tool use conversation flow.
1843-
1844-
This implements the proper Anthropic tool use pattern:
1845-
1. Claude requests tool use
1846-
2. We execute the tools
1847-
3. We send tool results back to Claude
1848-
4. Claude processes results and generates final response
1849-
"""
1850-
tool_results = self._execute_tools_and_collect_results(
1851-
tool_uses, available_functions, from_task, from_agent
1852-
)
1853-
1854-
follow_up_params = params.copy()
1855-
1856-
assistant_message = {"role": "assistant", "content": initial_response.content}
1857-
1858-
user_message = {"role": "user", "content": tool_results}
1859-
1860-
follow_up_params["messages"] = params["messages"] + [
1861-
assistant_message,
1862-
user_message,
1863-
]
1864-
1865-
try:
1866-
final_response: Message = await self._get_async_client().messages.create(
1867-
**follow_up_params
1868-
)
1869-
1870-
follow_up_usage = self._extract_anthropic_token_usage(final_response)
1871-
self._track_token_usage_internal(follow_up_usage)
1872-
1873-
final_content = ""
1874-
if final_response.content:
1875-
for content_block in final_response.content:
1876-
if hasattr(content_block, "text"):
1877-
final_content += content_block.text
1878-
1879-
final_content = self._apply_stop_words(final_content)
1880-
1881-
finish_reason, final_response_id = self._extract_finish_reason_and_id(
1882-
final_response
1883-
)
1884-
1885-
self._emit_call_completed_event(
1886-
response=final_content,
1887-
call_type=LLMCallType.LLM_CALL,
1888-
from_task=from_task,
1889-
from_agent=from_agent,
1890-
messages=follow_up_params["messages"],
1891-
usage=follow_up_usage,
1892-
finish_reason=finish_reason,
1893-
response_id=final_response_id,
1894-
)
1895-
1896-
total_usage = {
1897-
"input_tokens": follow_up_usage.get("input_tokens", 0),
1898-
"output_tokens": follow_up_usage.get("output_tokens", 0),
1899-
"total_tokens": follow_up_usage.get("total_tokens", 0),
1900-
}
1901-
1902-
if total_usage.get("total_tokens", 0) > 0:
1903-
logging.info(f"Anthropic API tool conversation usage: {total_usage}")
1904-
1905-
return final_content
1906-
1907-
except Exception as e:
1908-
if is_context_length_exceeded(e):
1909-
logging.error(f"Context window exceeded in tool follow-up: {e}")
1910-
raise LLMContextLengthExceededError(str(e)) from e
1911-
1912-
logging.error(f"Tool follow-up conversation failed: {e}")
1913-
if tool_results:
1914-
return cast(str, tool_results[0]["content"])
1915-
raise e
1916-
19171719
def supports_function_calling(self) -> bool:
19181720
"""Check if the model supports function calling."""
19191721
return self.supports_tools

lib/crewai/src/crewai/llms/providers/bedrock/completion.py

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,17 +2146,6 @@ def supports_multimodal(self) -> bool:
21462146
)
21472147
return any(model_lower.startswith(m) for m in vision_models)
21482148

2149-
def _is_nova_model(self) -> bool:
2150-
"""Check if the model is an Amazon Nova model.
2151-
2152-
Only Nova models support S3 links for multimedia.
2153-
2154-
Returns:
2155-
True if the model is a Nova model.
2156-
"""
2157-
model_lower = self.model.lower()
2158-
return "amazon.nova-" in model_lower
2159-
21602149
def get_file_uploader(self) -> Any:
21612150
"""Get a Bedrock S3 file uploader using this LLM's AWS credentials.
21622151
@@ -2185,49 +2174,6 @@ def get_file_uploader(self) -> Any:
21852174
except ImportError:
21862175
return None
21872176

2188-
def _get_document_format(self, content_type: str) -> str | None:
2189-
"""Map content type to Bedrock document format.
2190-
2191-
Args:
2192-
content_type: MIME type of the document.
2193-
2194-
Returns:
2195-
Bedrock format string or None if unsupported.
2196-
"""
2197-
format_map = {
2198-
"application/pdf": "pdf",
2199-
"text/csv": "csv",
2200-
"text/plain": "txt",
2201-
"text/markdown": "md",
2202-
"text/html": "html",
2203-
"application/msword": "doc",
2204-
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
2205-
"application/vnd.ms-excel": "xls",
2206-
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
2207-
}
2208-
return format_map.get(content_type)
2209-
2210-
def _get_video_format(self, content_type: str) -> str | None:
2211-
"""Map content type to Bedrock video format.
2212-
2213-
Args:
2214-
content_type: MIME type of the video.
2215-
2216-
Returns:
2217-
Bedrock format string or None if unsupported.
2218-
"""
2219-
format_map = {
2220-
"video/mp4": "mp4",
2221-
"video/quicktime": "mov",
2222-
"video/x-matroska": "mkv",
2223-
"video/webm": "webm",
2224-
"video/x-flv": "flv",
2225-
"video/mpeg": "mpeg",
2226-
"video/x-ms-wmv": "wmv",
2227-
"video/3gpp": "three_gp",
2228-
}
2229-
return format_map.get(content_type)
2230-
22312177
def format_text_content(self, text: str) -> dict[str, Any]:
22322178
"""Format text as a Bedrock content block.
22332179

lib/crewai/tests/llms/anthropic/test_anthropic.py

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,30 +1576,6 @@ def test_anthropic_dict_tool_use_blocks_execute_available_function():
15761576
assert result == "found CrewAI"
15771577

15781578

1579-
def test_anthropic_dict_tool_use_blocks_work_in_follow_up_conversation():
1580-
from crewai.llms.providers.anthropic.completion import AnthropicCompletion
1581-
1582-
llm = AnthropicCompletion(model="claude-fable-5")
1583-
initial_response = _dict_tool_use_response()
1584-
final_response = MagicMock()
1585-
final_response.content = [types.SimpleNamespace(text="Final answer")]
1586-
final_response.usage = MagicMock(input_tokens=4, output_tokens=3)
1587-
final_response.stop_reason = "end_turn"
1588-
final_response.id = "msg_final"
1589-
mock_client = MagicMock()
1590-
mock_client.messages.create.return_value = final_response
1591-
llm._client = mock_client
1592-
1593-
result = llm._handle_tool_use_conversation(
1594-
initial_response,
1595-
initial_response.content,
1596-
params={"messages": []},
1597-
available_functions={"search_web": lambda query: f"found {query}"},
1598-
)
1599-
1600-
assert result == "Final answer"
1601-
1602-
16031579
@pytest.mark.vcr()
16041580
def test_tool_search_discovers_and_calls_tool():
16051581
"""Tool search should discover the right tool and return a tool_use block."""

0 commit comments

Comments
 (0)