mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-09 08:08:32 +00:00
improving tool usage for crewai enterprise tools
This commit is contained in:
@@ -197,6 +197,42 @@ class CrewStructuredTool:
|
||||
validated_args = self.args_schema.model_validate(raw_args)
|
||||
return validated_args.model_dump()
|
||||
except Exception as e:
|
||||
# Check if this is a "Field required" error and try to fix it
|
||||
error_str = str(e)
|
||||
if "Field required" in error_str:
|
||||
# Try to parse missing fields from the error
|
||||
import re
|
||||
from pydantic import ValidationError
|
||||
|
||||
if isinstance(e, ValidationError):
|
||||
# Extract missing fields from validation error
|
||||
missing_fields = []
|
||||
for error_detail in e.errors():
|
||||
if error_detail.get('type') == 'missing':
|
||||
field_path = error_detail.get('loc', ())
|
||||
if field_path:
|
||||
missing_fields.append(field_path[0])
|
||||
|
||||
if missing_fields:
|
||||
# Create a copy of raw_args and add missing fields with None
|
||||
fixed_args = dict(raw_args) if isinstance(raw_args, dict) else {}
|
||||
for field in missing_fields:
|
||||
if field not in fixed_args:
|
||||
fixed_args[field] = None
|
||||
|
||||
# Try validation again with fixed args
|
||||
try:
|
||||
self._logger.log("debug", f"Auto-fixing missing fields: {missing_fields}")
|
||||
validated_args = self.args_schema.model_validate(fixed_args)
|
||||
return validated_args.model_dump()
|
||||
except Exception as retry_e:
|
||||
# If it still fails, raise the original error with additional context
|
||||
raise ValueError(
|
||||
f"Arguments validation failed: {e}\n"
|
||||
f"Attempted to auto-fix missing fields {missing_fields} but still failed: {retry_e}"
|
||||
)
|
||||
|
||||
# For other validation errors, raise as before
|
||||
raise ValueError(f"Arguments validation failed: {e}")
|
||||
|
||||
async def ainvoke(
|
||||
|
||||
@@ -250,9 +250,54 @@ class ToolUsage:
|
||||
self._run_attempts += 1
|
||||
if self._run_attempts > self._max_parsing_attempts:
|
||||
self._telemetry.tool_usage_error(llm=self.function_calling_llm)
|
||||
|
||||
# Check if this is a validation error with missing fields
|
||||
error_str = str(e)
|
||||
if "Arguments validation failed" in error_str and "Field required" in error_str:
|
||||
# Extract the field name that's missing
|
||||
import re
|
||||
field_match = re.search(r'(\w+)\s*Field required', error_str)
|
||||
if field_match:
|
||||
missing_field = field_match.group(1)
|
||||
|
||||
# Create a more helpful error message
|
||||
error_message = (
|
||||
f"Tool validation error: The '{missing_field}' parameter is required but was not provided.\n\n"
|
||||
f"SOLUTION: Include ALL parameters in your tool call, even optional ones (use null for optional parameters):\n"
|
||||
f'{{"tool_name": "{tool.name}", "arguments": {{'
|
||||
)
|
||||
|
||||
# Get all expected parameters from the tool schema
|
||||
if hasattr(tool, 'args_schema'):
|
||||
schema_props = tool.args_schema.model_json_schema().get('properties', {})
|
||||
param_examples = []
|
||||
for param_name, param_info in schema_props.items():
|
||||
if param_name == missing_field:
|
||||
param_examples.append(f'"{param_name}": "YOUR_VALUE_HERE"')
|
||||
else:
|
||||
# Check if it's optional by looking at required fields
|
||||
is_required = param_name in tool.args_schema.model_json_schema().get('required', [])
|
||||
if not is_required:
|
||||
param_examples.append(f'"{param_name}": null')
|
||||
else:
|
||||
param_examples.append(f'"{param_name}": "value"')
|
||||
|
||||
error_message += ', '.join(param_examples)
|
||||
error_message += '}}\n\n'
|
||||
|
||||
error_message += f"Original error: {e}\n"
|
||||
error_message += f"Tool description: {tool.description}"
|
||||
else:
|
||||
# Use the original error message
|
||||
error_message = self._i18n.errors("tool_usage_exception").format(
|
||||
error=e, tool=tool.name, tool_inputs=tool.description
|
||||
)
|
||||
else:
|
||||
# Use the original error message for non-validation errors
|
||||
error_message = self._i18n.errors("tool_usage_exception").format(
|
||||
error=e, tool=tool.name, tool_inputs=tool.description
|
||||
)
|
||||
|
||||
error = ToolUsageErrorException(
|
||||
f"\n{error_message}.\nMoving on then. {self._i18n.slice('format').format(tool_names=self.tools_names)}"
|
||||
).message
|
||||
|
||||
Reference in New Issue
Block a user