Skip to content
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

Import a Space as a tool: Exception: Tool's 'forward' method should take 'self' as its first argument, ... #69

Open
didierguillevic opened this issue Jan 4, 2025 · 1 comment

Comments

@didierguillevic
Copy link

didierguillevic commented Jan 4, 2025

Hi,

Going through the smolagents documentation :-) :-)

The Import a Space as a tool example is not running as expected.

Code:

image_generation_tool = Tool.from_space(
    "black-forest-labs/FLUX.1-schnell",
    name="image_generator",
    description="Generate an image from a prompt"
)

image_generation_tool("A sunny beach")

Output:

---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
Cell In[28], [line 1](vscode-notebook-cell:?execution_count=28&line=1)
----> [1](vscode-notebook-cell:?execution_count=28&line=1) image_generation_tool = smolagents.Tool.from_space(
      [2](vscode-notebook-cell:?execution_count=28&line=2)     "black-forest-labs/FLUX.1-schnell",
      [3](vscode-notebook-cell:?execution_count=28&line=3)     name="image_generator",
      [4](vscode-notebook-cell:?execution_count=28&line=4)     description="Generate an image from a prompt"
      [5](vscode-notebook-cell:?execution_count=28&line=5) )
      [7](vscode-notebook-cell:?execution_count=28&line=7) image_generation_tool("A sunny beach")

File /opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:657, in Tool.from_space(space_id, name, description, api_name, token)
    [652](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:652)             return output[
    [653](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:653)                 0
    [654](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:654)             ]  # Sometime the space also returns the generation seed, in which case the result is at index 0
    [655](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:655)         return output
--> [657](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:657) return SpaceToolWrapper(
    [658](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:658)     space_id=space_id,
    [659](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:659)     name=name,
    [660](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:660)     description=description,
    [661](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:661)     api_name=api_name,
    [662](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:662)     token=token,
    [663](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:663) )

File /opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:107, in validate_after_init.<locals>.new_init(self, *args, **kwargs)
    [104](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:104) @wraps(original_init)
    [105](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:105) def new_init(self, *args, **kwargs):
    [106](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:106)     original_init(self, *args, **kwargs)
--> [107](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:107)     self.validate_arguments()

File /opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:217, in Tool.validate_arguments(self)
    [214](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:214) signature = inspect.signature(self.forward)
    [216](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:216) if not set(signature.parameters.keys()) == set(self.inputs.keys()):
--> [217](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:217)     raise Exception(
    [218](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:218)         "Tool's 'forward' method should take 'self' as its first argument, then its next arguments should match the keys of tool attribute 'inputs'."
    [219](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:219)     )
    [221](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:221) json_schema = _convert_type_hints_to_json_schema(self.forward)
    [222](https://file+.vscode-resource.vscode-cdn.net/opt/anaconda3/envs/smol/lib/python3.10/site-packages/smolagents/tools.py:222) for key, value in self.inputs.items():

Exception: Tool's 'forward' method should take 'self' as its first argument, then its next arguments should match the keys of tool attribute 'inputs'.

Environment:

  • smolagents==1.0.0
  • torch==2.5.1
  • macOS 15.2 (M processor)
@lelayf
Copy link

lelayf commented Jan 5, 2025

Confirming the same issue with that specific example.

The root cause is that method SpaceToolWrapper.forward relies on *args and **kwargs in its signature:

def forward(self, *args, **kwargs):
    # Preprocess args and kwargs:
    args = list(args)
    for i, arg in enumerate(args):
        args[i] = self.sanitize_argument_for_prediction(arg)
    for arg_name, arg in kwargs.items():
        kwargs[arg_name] = self.sanitize_argument_for_prediction(arg)

    output = self.client.predict(*args, api_name=self.api_name, **kwargs)
    if isinstance(output, tuple) or isinstance(output, list):
        return output[
            0
        ]  # Sometime the space also returns the generation seed, in which case the result is at index 0
    return output

When it is instantiated, the call to validate_arguments raises an exception if the input spec retrieved from the space does not match the forward signature spec. In this case the forward signature is still very generic as a odict_keys(['args', 'kwargs']), and it does not match the expected space input params which come as a dict(['prompt']).

The PipelineTool has a similar situation and avoids the failure by having a is_pipeline_tool class variable that the validation checks against to bypass signature matching.

# Validate forward function signature, except for PipelineTool
if not (
    hasattr(self, "is_pipeline_tool")
    and getattr(self, "is_pipeline_tool") is True
):

I think we should:

  • add a skip_forward_signature_validation class variable in the SpaceToolWrapper
  • rename PipelineTool.is_pipeline_tool to PipelineTool.skip_forward_signature_validation
  • modify the validate_arguments method to check skip_forward_signature_validation instead of is_pipeline_tool

lelayf pushed a commit to lelayf/smolagents that referenced this issue Jan 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants