-
Notifications
You must be signed in to change notification settings - Fork 5.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: improve error handling of Agent component, solves Empty ExceptionWithMessageError #6097
base: main
Are you sure you want to change the base?
Conversation
if not isinstance(self.agent_llm, str): | ||
return self.agent_llm, None | ||
|
||
try: | ||
provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm) | ||
if not provider_info: | ||
msg = f"Invalid model provider: {self.agent_llm}" | ||
raise ValueError(msg) | ||
|
||
component_class = provider_info.get("component_class") | ||
display_name = component_class.display_name | ||
inputs = provider_info.get("inputs") | ||
prefix = provider_info.get("prefix", "") | ||
|
||
return self._build_llm_model(component_class, inputs, prefix), display_name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if not isinstance(self.agent_llm, str): | |
return self.agent_llm, None | |
try: | |
provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm) | |
if not provider_info: | |
msg = f"Invalid model provider: {self.agent_llm}" | |
raise ValueError(msg) | |
component_class = provider_info.get("component_class") | |
display_name = component_class.display_name | |
inputs = provider_info.get("inputs") | |
prefix = provider_info.get("prefix", "") | |
return self._build_llm_model(component_class, inputs, prefix), display_name | |
agent_llm = self.agent_llm | |
if not isinstance(agent_llm, str): | |
return agent_llm, None | |
provider_info = MODEL_PROVIDERS_DICT.get(agent_llm) | |
if provider_info is None: | |
msg = f"Invalid model provider: {agent_llm}" | |
raise ValueError(msg) | |
component_class = provider_info["component_class"] | |
display_name = component_class.display_name | |
inputs = provider_info["inputs"] | |
prefix = provider_info.get("prefix", "") | |
try: | |
llm_model = self._build_llm_model(component_class, inputs, prefix) | |
return llm_model, display_name | |
error_message = f"Error building {agent_llm} language model: {e!s}" | |
logger.error(error_message) | |
raise ValueError(f"Failed to initialize language model: {e!s}") from e |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like the diff is messed up here. I suppose there was a real optimization here but the output seems incorrect. This is happening due to our dependency on a diffing library that is buggy. We are looking to fix this
⚡️ Codeflash found optimizations for this PR📄 5,023% (50.23x) speedup for
|
Test | Status |
---|---|
⚙️ Existing Unit Tests | 🔘 None Found |
🌀 Generated Regression Tests | ✅ 6 Passed |
⏪ Replay Tests | 🔘 None Found |
🔎 Concolic Coverage Tests | 🔘 None Found |
📊 Tests Coverage | undefined |
🌀 Generated Regression Tests Details
from unittest.mock import MagicMock, patch
# imports
import pytest # used for our unit tests
from langflow.base.models.model_input_constants import MODEL_PROVIDERS_DICT
from langflow.components.agents.agent import AgentComponent
# function to test
from langflow.components.langchain_utilities.tool_calling import \
ToolCallingAgentComponent
from langflow.logging import logger
MODEL_PROVIDERS_DICT: dict[str, dict] = {}
# unit tests
# Mock classes and inputs for testing
class MockInput:
def __init__(self, name):
self.name = name
class MockComponentClass:
display_name = "MockComponentClass"
def set(self, **kwargs):
self.kwargs = kwargs
return self
def build_model(self):
return "mock_model"
class MockComponentClassThatRaisesException:
display_name = "MockComponentClass"
def set(self, **kwargs):
raise Exception("Mock exception during set")
@pytest.fixture
def setup_model_providers_dict():
global MODEL_PROVIDERS_DICT
MODEL_PROVIDERS_DICT = {
"valid_provider": {
"component_class": MockComponentClass,
"inputs": [MockInput(name="param1"), MockInput(name="param2")],
"prefix": "test_"
},
"incomplete_provider": {
"inputs": [MockInput(name="param1"), MockInput(name="param2")]
# Missing "component_class" and "prefix"
},
"large_input_provider": {
"component_class": MockComponentClass,
"inputs": [MockInput(name=f"param{i}") for i in range(1000)],
"prefix": "test_"
}
}
@pytest.fixture
def agent_component():
return AgentComponent()
def test_invalid_model_provider(setup_model_providers_dict, agent_component):
agent_component.agent_llm = "invalid_provider"
with pytest.raises(ValueError, match="Invalid model provider: invalid_provider"):
agent_component.get_llm()
def test_empty_model_providers_dict(agent_component):
global MODEL_PROVIDERS_DICT
MODEL_PROVIDERS_DICT = {}
agent_component.agent_llm = "any_provider"
with pytest.raises(ValueError, match="Invalid model provider: any_provider"):
agent_component.get_llm()
def test_logging_on_error(mock_logger, setup_model_providers_dict, agent_component):
agent_component.agent_llm = "invalid_provider"
with pytest.raises(ValueError):
agent_component.get_llm()
mock_logger.assert_called_with("Error building invalid_provider language model: Invalid model provider: invalid_provider")
def test_state_modification(setup_model_providers_dict, agent_component):
original_dict = MODEL_PROVIDERS_DICT.copy()
agent_component.agent_llm = "some_provider"
with pytest.raises(ValueError):
agent_component.get_llm()
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
from unittest.mock import Mock, patch
# imports
import pytest # used for our unit tests
from langflow.base.models.model_input_constants import MODEL_PROVIDERS_DICT
from langflow.components.agents.agent import AgentComponent
# function to test
from langflow.components.langchain_utilities.tool_calling import \
ToolCallingAgentComponent
from langflow.logging import logger
MODEL_PROVIDERS_DICT: dict[str, ModelProvidersDict] = {}
# unit tests
# Mock classes for testing
class MockComponentClass:
display_name = "MockComponent"
def set(self, **kwargs):
return self
def build_model(self):
return "MockModel"
class MockInput:
def __init__(self, name):
self.name = name
class MockModelObject:
pass
@pytest.fixture
def agent_component():
return AgentComponent()
def test_invalid_model_provider(agent_component):
# Edge case: invalid model provider string
agent_component.agent_llm = "invalid_provider"
with pytest.raises(ValueError, match="Invalid model provider: invalid_provider"):
agent_component.get_llm()
def test_empty_model_providers_dict(agent_component):
# Edge case: empty MODEL_PROVIDERS_DICT
agent_component.agent_llm = "valid_provider"
MODEL_PROVIDERS_DICT.clear()
with pytest.raises(ValueError, match="Invalid model provider: valid_provider"):
agent_component.get_llm()
def test_logging_errors(agent_component):
# Side effects: logging errors
agent_component.agent_llm = "invalid_provider"
with patch.object(logger, 'error') as mock_logger_error:
with pytest.raises(ValueError, match="Invalid model provider: invalid_provider"):
agent_component.get_llm()
mock_logger_error.assert_called_once_with("Error building invalid_provider language model: Invalid model provider: invalid_provider")
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
This pull request includes several changes to improve error handling and logging in the
langflow
backend. The most important changes include adding logging for exceptions, introducing a custom error class, updating the initialization of an existing error class, and refining validation and error handling in the agent component.Error Handling and Logging Improvements:
src/backend/base/langflow/base/agents/agent.py
: Added logging for exceptions in therun_agent
method to capture and log errors for better debugging.src/backend/base/langflow/base/agents/agent.py
: Imported thelogger
module to enable logging.Custom Error Class:
src/backend/base/langflow/base/agents/errors.py
: Introduced a newCustomBadRequestError
class to handle different types of bad request errors from various libraries (Anthropic
,Cohere
, andHTTPStatusError
).Existing Error Class Update:
src/backend/base/langflow/base/agents/events.py
: Updated theExceptionWithMessageError
class to include an additionalmessage
parameter and a__str__
method for better error message formatting.Agent Component Enhancements:
src/backend/base/langflow/components/agents/agent.py
: Improved validation and error handling in themessage_response
method, including logging specific exceptions and refining error messages. [1] [2]src/backend/base/langflow/components/agents/agent.py
: Adjusted theget_llm
method to handle invalid model providers and log errors more effectively.