smal fixes and better guardrail for parsing small models tools usage

This commit is contained in:
João Moura
2024-05-02 02:21:42 -03:00
parent 70cabec876
commit 4d9b0c6138
3 changed files with 6180 additions and 5907 deletions

View File

@@ -26,13 +26,13 @@ class ToolUsage:
Class that represents the usage of a tool by an agent.
Attributes:
task: Task being executed.
tools_handler: Tools handler that will manage the tool usage.
tools: List of tools available for the agent.
original_tools: Original tools available for the agent before being converted to BaseTool.
tools_description: Description of the tools available for the agent.
tools_names: Names of the tools available for the agent.
function_calling_llm: Language model to be used for the tool usage.
task: Task being executed.
tools_handler: Tools handler that will manage the tool usage.
tools: List of tools available for the agent.
original_tools: Original tools available for the agent before being converted to BaseTool.
tools_description: Description of the tools available for the agent.
tools_names: Names of the tools available for the agent.
function_calling_llm: Language model to be used for the tool usage.
"""
def __init__(
@@ -265,12 +265,12 @@ class ToolUsage:
model=model,
instructions=dedent(
"""\
The schema should have the following structure, only two keys:
- tool_name: str
- arguments: dict (with all arguments being passed)
The schema should have the following structure, only two keys:
- tool_name: str
- arguments: dict (with all arguments being passed)
Example:
{"tool_name": "tool name", "arguments": {"arg_name1": "value", "arg_name2": 2}}""",
Example:
{"tool_name": "tool name", "arguments": {"arg_name1": "value", "arg_name2": 2}}""",
),
max_attemps=1,
)
@@ -282,7 +282,8 @@ class ToolUsage:
tool_name = self.action.tool
tool = self._select_tool(tool_name)
try:
arguments = ast.literal_eval(self.action.tool_input)
tool_input = self._validate_tool_input(self.action.tool_input)
arguments = ast.literal_eval(tool_input)
except Exception:
return ToolUsageErrorException(
f'{self._i18n.errors("tool_arguments_error")}'
@@ -308,3 +309,50 @@ class ToolUsage:
return self._tool_calling(tool_string)
return calling
def _validate_tool_input(self, tool_input: str) -> dict:
try:
ast.literal_eval(tool_input)
return tool_input
except Exception:
# Clean and ensure the string is properly enclosed in braces
tool_input = tool_input.strip()
if not tool_input.startswith("{"):
tool_input = "{" + tool_input
if not tool_input.endswith("}"):
tool_input += "}"
# Manually split the input into key-value pairs
entries = tool_input.strip("{} ").split(",")
formatted_entries = []
for entry in entries:
if ":" not in entry:
continue # Skip malformed entries
key, value = entry.split(":", 1)
key = key.strip().strip(
'"'
) # Remove extraneous white spaces and quotes
value = value.strip()
# Check and format the value based on its type
if value.isdigit(): # Check if value is a digit, hence integer
formatted_value = value
elif value.lower() in [
"true",
"false",
"null",
]: # Check for boolean and null values
formatted_value = value.lower()
else:
# Assume the value is a string and needs quotes
formatted_value = '"' + value.strip('"').replace('"', '\\"') + '"'
# Rebuild the entry with proper quoting
formatted_entry = f'"{key}": {formatted_value}'
formatted_entries.append(formatted_entry)
# Reconstruct the JSON string
new_json_string = "{" + ", ".join(formatted_entries) + "}"
return new_json_string

File diff suppressed because it is too large Load Diff

View File

@@ -648,10 +648,10 @@ def test_agent_usage_metrics_are_captured_for_sequential_process():
result = crew.kickoff()
assert result == "Howdy!"
assert crew.usage_metrics == {
"completion_tokens": 51,
"prompt_tokens": 483,
"successful_requests": 3,
"total_tokens": 534,
"completion_tokens": 17,
"prompt_tokens": 160,
"successful_requests": 1,
"total_tokens": 177,
}
@@ -678,10 +678,10 @@ def test_agent_usage_metrics_are_captured_for_hierarchical_process():
result = crew.kickoff()
assert result == '"Howdy!"'
assert crew.usage_metrics == {
"total_tokens": 2592,
"prompt_tokens": 2048,
"completion_tokens": 544,
"successful_requests": 6,
"total_tokens": 1650,
"prompt_tokens": 1367,
"completion_tokens": 283,
"successful_requests": 3,
}