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

[UPDATE] clearify "to_string()" #127

Open
mustaphahaadi opened this issue Feb 13, 2025 · 3 comments
Open

[UPDATE] clearify "to_string()" #127

mustaphahaadi opened this issue Feb 13, 2025 · 3 comments
Labels
documentation Improvements or additions to documentation

Comments

@mustaphahaadi
Copy link

The last line, print(calculator.to_string()), is causing confusion because it results in an AttributeError: 'function' object has no attribute 'to_string'. It seems like the intention was to demonstrate a conversion to a string format, such as "Tool Name: calculator, Description: Multiply two integers., Arguments: a: int, b: int, Outputs: int". However, this is not clearly communicated in the code.

In contrast, the second example, which introduces a decorator that implements the to_string method, is much clearer and makes more sense.

Could you clarify the purpose of the to_string() call in the first example or remove it to avoid confusion?
Thank you!

@mustaphahaadi mustaphahaadi added the documentation Improvements or additions to documentation label Feb 13, 2025
@alex-ber
Copy link

+1

@Anto59290
Copy link

I made the same remark, see #124 ;)

@lesong36
Copy link

lesong36 commented Feb 14, 2025

finally got it, but frankly, Langchain tool definition is more graceful.

simply define the function does't work, we need to define the class.

class Tool:
"""
A class representing a reusable piece of code (Tool).

Attributes:
    name (str): Name of the tool.
    description (str): A textual description of what the tool does.
    func (callable): The function this tool wraps.
    arguments (list): A list of argument.
    outputs (str or list): The return type(s) of the wrapped function.
"""
def __init__(self, 
             name: str, 
             description: str, 
             func: callable, 
             arguments: list,
             outputs: str):
    self.name = name
    self.description = description
    self.func = func
    self.arguments = arguments
    self.outputs = outputs

def to_string(self) -> str:
    """
    Return a string representation of the tool, 
    including its name, description, arguments, and outputs.
    """
    args_str = ", ".join([
        f"{arg_name}: {arg_type}" for arg_name, arg_type in self.arguments
    ])
    
    return (
        f"Tool Name: {self.name},"
        f" Description: {self.description},"
        f" Arguments: {args_str},"
        f" Outputs: {self.outputs}"
    )

def __call__(self, *args, **kwargs):
    """
    Invoke the underlying function (callable) with provided arguments.
    """
    return self.func(*args, **kwargs)

calculator_tool = Tool(
"calculator", # name
"Multiply two integers.", # description
calculator, # function to call
[("a", "int"), ("b", "int")], # inputs (names and types)
"int", # output
)

calculator_tool.to_string()

OR

import inspect

def tool(func):
"""
A decorator that creates a Tool instance from the given function.
"""
# Get the function signature
signature = inspect.signature(func)

# Extract (param_name, param_annotation) pairs for inputs
arguments = []
for param in signature.parameters.values():
    annotation_name = (
        param.annotation.__name__ 
        if hasattr(param.annotation, '__name__') 
        else str(param.annotation)
    )
    arguments.append((param.name, annotation_name))

# Determine the return annotation
return_annotation = signature.return_annotation
if return_annotation is inspect._empty:
    outputs = "No return annotation"
else:
    outputs = (
        return_annotation.__name__ 
        if hasattr(return_annotation, '__name__') 
        else str(return_annotation)
    )

# Use the function's docstring as the description (default if None)
description = func.__doc__ or "No description provided."

# The function name becomes the Tool name
name = func.__name__

# Return a new Tool instance
return Tool(
    name=name, 
    description=description, 
    func=func, 
    arguments=arguments, 
    outputs=outputs
)

@tool
def calculator(a: int, b: int) -> int:
"""Multiply two integers."""
return a * b

print(calculator.to_string())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

4 participants