From 8683f07a1d4f12ed2c805e7941f833cb5dda3800 Mon Sep 17 00:00:00 2001 From: Dirk Brand <51947788+dirkbrnd@users.noreply.github.com> Date: Fri, 20 Dec 2024 16:46:12 +0200 Subject: [PATCH] Make older functions compatible with tool calling (#1605) ## Description Some older custom function implementations where the description and parameters were manually specified (e.g. as built in `composio-phidata`) were not compatible with the new way of building tools for models. This addresses it by keeping parameters/description if it was set on the Function. --------- Co-authored-by: Anurag --- cookbook/tools/composio_tools.py | 1 - phi/tools/function.py | 13 ++++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cookbook/tools/composio_tools.py b/cookbook/tools/composio_tools.py index 69650892b..9aa8575dc 100644 --- a/cookbook/tools/composio_tools.py +++ b/cookbook/tools/composio_tools.py @@ -1,7 +1,6 @@ from phi.agent import Agent from composio_phidata import Action, ComposioToolSet # type: ignore - toolset = ComposioToolSet() composio_tools = toolset.get_tools(actions=[Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER]) diff --git a/phi/tools/function.py b/phi/tools/function.py index a8174e147..452fad808 100644 --- a/phi/tools/function.py +++ b/phi/tools/function.py @@ -53,7 +53,7 @@ class Function(BaseModel): # The parameters the functions accepts, described as a JSON Schema object. # To describe a function that accepts no parameters, provide the value {"type": "object", "properties": {}}. parameters: Dict[str, Any] = Field( - default_factory=lambda: {"type": "object", "properties": {}}, + default_factory=lambda: {"type": "object", "properties": {}, "required": []}, description="JSON Schema object describing function parameters", ) strict: Optional[bool] = None @@ -139,6 +139,12 @@ def process_entrypoint(self, strict: bool = False): return parameters = {"type": "object", "properties": {}, "required": []} + + params_set_by_user = False + # If the user set the parameters (i.e. they are different from the default), we should keep them + if self.parameters != parameters: + params_set_by_user = True + try: sig = signature(self.entrypoint) type_hints = get_type_hints(self.entrypoint) @@ -174,8 +180,9 @@ def process_entrypoint(self, strict: bool = False): except Exception as e: logger.warning(f"Could not parse args for {self.name}: {e}", exc_info=True) - self.description = getdoc(self.entrypoint) or self.description - self.parameters = parameters + self.description = self.description or getdoc(self.entrypoint) + if not params_set_by_user: + self.parameters = parameters self.entrypoint = validate_call(self.entrypoint) def get_type_name(self, t: Type[T]):