Skip to content

Commit eafe2e9

Browse files
twishabansalkurtisvgYuan325anubhav756
authored
feat(toolbox-core): updated generated docstring to include parameters and their descriptions (#127)
* feat: add authenticated parameters support * chore: add asyncio dep * chore: run itest * chore: add type hint * fix: call tool instead of client * chore: correct arg name * feat: add support for bound parameters * chore: add tests for bound parameters * docs: update syntax error on readme (#121) * ci: added release please config (#112) * ci: add release please config * chore: add initial version * chore: specify initial version as string * chore: Update .release-please-manifest.json * chore: add empty json * chore: small change * chore: try fixing config * chore: try fixing config again * chore: remove release-as * chore: add changelog sections * chore: better release notes * chore: better release notes * chore: change toolbox-langchain version * chore: separate PRs for packages * chore: change PR style * added basic e2e tests * change license year * add test deps * fix tests * fix tests * fix tests * add new test case * fix docstring * added todo * cleanup * add bind param test case * make bind params dynamic * try fix test errors * lint * remove redundant test * test fix * fix docstring * feat: add authenticated parameters support * chore: add asyncio dep * chore: run itest * chore: add type hint * fix: call tool instead of client * chore: correct arg name * chore: address feedback * chore: address more feedback * feat: add support for bound parameters * chore: add tests for bound parameters * chore: address feedback * revert package file changes * fix error message * revert package files * lint * fix error message * Update packages/toolbox-core/tests/test_e2e.py Co-authored-by: Anubhav Dhawan <anubhav756@gmail.com> * try changing docstring to include args and their descriptions * fix docstring * lint * fix test * lint * added return type annotation * Add docstrings * use and update schema # Conflicts: # packages/toolbox-core/src/toolbox_core/tool.py * lint * lint * revert changes to e2e test file # Conflicts: # packages/toolbox-core/tests/test_e2e.py * change string to str and in arg type * small change * fix imports * remove toolschema usage * lint * move create_docstring method outside the class. * lint --------- Co-authored-by: Kurtis Van Gent <31518063+kurtisvg@users.noreply.github.com> Co-authored-by: Yuan <45984206+Yuan325@users.noreply.github.com> Co-authored-by: Anubhav Dhawan <anubhav756@gmail.com>
1 parent 827129f commit eafe2e9

File tree

3 files changed

+39
-23
lines changed

3 files changed

+39
-23
lines changed

packages/toolbox-core/src/toolbox_core/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ def __parse_tool(
8383
session=self.__session,
8484
base_url=self.__base_url,
8585
name=name,
86-
desc=schema.description,
87-
params=[p.to_param() for p in params],
86+
description=schema.description,
87+
params=params,
8888
# create a read-only values for the maps to prevent mutation
8989
required_authn_params=types.MappingProxyType(authn_params),
9090
auth_service_token_getters=types.MappingProxyType(auth_token_getters),

packages/toolbox-core/src/toolbox_core/tool.py

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
import asyncio
1717
import types
18-
from inspect import Parameter, Signature
18+
from inspect import Signature
1919
from typing import (
2020
Any,
2121
Callable,
@@ -28,6 +28,8 @@
2828

2929
from aiohttp import ClientSession
3030

31+
from toolbox_core.protocol import ParameterSchema
32+
3133

3234
class ToolboxTool:
3335
"""
@@ -47,8 +49,8 @@ def __init__(
4749
session: ClientSession,
4850
base_url: str,
4951
name: str,
50-
desc: str,
51-
params: Sequence[Parameter],
52+
description: str,
53+
params: Sequence[ParameterSchema],
5254
required_authn_params: Mapping[str, list[str]],
5355
auth_service_token_getters: Mapping[str, Callable[[], str]],
5456
bound_params: Mapping[str, Union[Callable[[], Any], Any]],
@@ -61,31 +63,30 @@ def __init__(
6163
session: The `aiohttp.ClientSession` used for making API requests.
6264
base_url: The base URL of the Toolbox server API.
6365
name: The name of the remote tool.
64-
desc: The description of the remote tool (used as its docstring).
65-
params: A list of `inspect.Parameter` objects defining the tool's
66-
arguments and their types/defaults.
66+
description: The description of the remote tool.
67+
params: The args of the tool.
6768
required_authn_params: A dict of required authenticated parameters to a list
6869
of services that provide values for them.
6970
auth_service_token_getters: A dict of authService -> token (or callables that
7071
produce a token)
7172
bound_params: A mapping of parameter names to bind to specific values or
7273
callables that are called to produce values as needed.
73-
7474
"""
75-
7675
# used to invoke the toolbox API
7776
self.__session: ClientSession = session
7877
self.__base_url: str = base_url
7978
self.__url = f"{base_url}/api/tool/{name}/invoke"
80-
81-
self.__desc = desc
79+
self.__description = description
8280
self.__params = params
81+
inspect_type_params = [param.to_param() for param in self.__params]
8382

8483
# the following properties are set to help anyone that might inspect it determine usage
8584
self.__name__ = name
86-
self.__doc__ = desc
87-
self.__signature__ = Signature(parameters=params, return_annotation=str)
88-
self.__annotations__ = {p.name: p.annotation for p in params}
85+
self.__doc__ = create_docstring(self.__description, self.__params)
86+
self.__signature__ = Signature(
87+
parameters=inspect_type_params, return_annotation=str
88+
)
89+
self.__annotations__ = {p.name: p.annotation for p in inspect_type_params}
8990
# TODO: self.__qualname__ ??
9091

9192
# map of parameter name to auth service required by it
@@ -100,8 +101,8 @@ def __copy(
100101
session: Optional[ClientSession] = None,
101102
base_url: Optional[str] = None,
102103
name: Optional[str] = None,
103-
desc: Optional[str] = None,
104-
params: Optional[list[Parameter]] = None,
104+
description: Optional[str] = None,
105+
params: Optional[Sequence[ParameterSchema]] = None,
105106
required_authn_params: Optional[Mapping[str, list[str]]] = None,
106107
auth_service_token_getters: Optional[Mapping[str, Callable[[], str]]] = None,
107108
bound_params: Optional[Mapping[str, Union[Callable[[], Any], Any]]] = None,
@@ -113,9 +114,8 @@ def __copy(
113114
session: The `aiohttp.ClientSession` used for making API requests.
114115
base_url: The base URL of the Toolbox server API.
115116
name: The name of the remote tool.
116-
desc: The description of the remote tool (used as its docstring).
117-
params: A list of `inspect.Parameter` objects defining the tool's
118-
arguments and their types/defaults.
117+
description: The description of the remote tool.
118+
params: The args of the tool.
119119
required_authn_params: A dict of required authenticated parameters that need
120120
a auth_service_token_getter set for them yet.
121121
auth_service_token_getters: A dict of authService -> token (or callables
@@ -129,7 +129,7 @@ def __copy(
129129
session=check(session, self.__session),
130130
base_url=check(base_url, self.__base_url),
131131
name=check(name, self.__name__),
132-
desc=check(desc, self.__desc),
132+
description=check(description, self.__description),
133133
params=check(params, self.__params),
134134
required_authn_params=check(
135135
required_authn_params, self.__required_authn_params
@@ -258,7 +258,6 @@ def bind_parameters(
258258
for p in self.__params:
259259
if p.name not in bound_params:
260260
new_params.append(p)
261-
262261
all_bound_params = dict(self.__bound_parameters)
263262
all_bound_params.update(bound_params)
264263

@@ -268,6 +267,19 @@ def bind_parameters(
268267
)
269268

270269

270+
def create_docstring(description: str, params: Sequence[ParameterSchema]) -> str:
271+
"""Convert tool description and params into its function docstring"""
272+
docstring = description
273+
if not params:
274+
return docstring
275+
docstring += "\n\nArgs:"
276+
for p in params:
277+
docstring += (
278+
f"\n {p.name} ({p.to_param().annotation.__name__}): {p.description}"
279+
)
280+
return docstring
281+
282+
271283
def identify_required_authn_params(
272284
req_authn_params: Mapping[str, list[str]], auth_service_names: Iterable[str]
273285
) -> dict[str, list[str]]:

packages/toolbox-core/tests/test_client.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,11 @@ async def test_load_tool_success(aioresponses, test_tool_str):
9292
assert callable(loaded_tool)
9393
# Assert introspection attributes are set correctly
9494
assert loaded_tool.__name__ == TOOL_NAME
95-
assert loaded_tool.__doc__ == test_tool_str.description
95+
expected_description = (
96+
test_tool_str.description
97+
+ f"\n\nArgs:\n param1 (str): Description of Param1"
98+
)
99+
assert loaded_tool.__doc__ == expected_description
96100

97101
# Assert signature inspection
98102
sig = inspect.signature(loaded_tool)

0 commit comments

Comments
 (0)