Skip to content

feat: Adds decorators to simplify tool registration #516

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

caua1503
Copy link

This commit introduces decorators and helper functions to simplify the process of defining and registering synchronous and asynchronous tools in the ollama-python library.

Main changes: - Added @ollama_tool and @ollama_async_tool decorators to ollama/_utils.py to automatically register functions as tools.

New helper functions in ollama/_utils.py:

  • get_tools(): Returns a list of all registered tools (synchronous and asynchronous). - get_tools_name(): Returns a dictionary mapping tool names to their respective functions.

  • get_name_async_tools(): Returns an array of asynchronous tool names.

  • ollama/__init__.py has been updated to export the new decorators and functions.

  • examples/tools.py has been updated to reflect the changes and simplify the example usage of manually defined tools.

  • New example files have been created:

  • examples/tools-decorators.py: Demonstrates the use of decorators for synchronous and asynchronous tools in a synchronous context.

  • examples/async-tools-decorators.py: Demonstrates the use of decorators in an asynchronous context with asyncio.

  • Tests have been added to tests/test_utils.py to cover the new decorators and helper functions (test_tool_and_async_tool_registration, test_get_tools_name_and_get_tools).

These changes aim to make it easier for developers to integrate custom functionality with ollama, reducing the need for boilerplate to define and manage tools.

caua1503 added 2 commits May 18, 2025 12:55
This commit introduces decorators and helper functions to simplify the process of defining and registering synchronous and asynchronous tools in the ollama-python library.

Main changes: - Added `@ollama_tool` and `@ollama_async_tool` decorators to `ollama/_utils.py` to automatically register functions as tools.

New helper functions in `ollama/_utils.py`: - `get_tools()`: Returns a list of all registered tools (synchronous and asynchronous). - `get_tools_name()`: Returns a dictionary mapping tool names to their respective functions.
- `get_name_async_tools()`: Returns an array of asynchronous tool names.
- `ollama/__init__.py` has been updated to export the new decorators and functions.
- `examples/tools.py` has been updated to reflect the changes and simplify the example usage of manually defined tools.

- New example files have been created:
- `examples/tools-decorators.py`: Demonstrates the use of decorators for synchronous and asynchronous tools in a synchronous context.
- `examples/async-tools-decorators.py`: Demonstrates the use of decorators in an asynchronous context with `asyncio`.
- Tests have been added to `tests/test_utils.py` to cover the new decorators and helper functions (`test_tool_and_async_tool_registration`, `test_get_tools_name_and_get_tools`).

These changes aim to make it easier for developers to integrate custom functionality with ollama, reducing the need for boilerplate to define and manage tools.
- Create dedicated _tools.py module for better organization
- Move tool-related functions from _utils.py to _tools.py (not including create_function_tool)
- Rename tool getter functions for clarity:
  * get_ollama_tools_name
  * get_ollama_tools
  * get_ollama_name_async_tools
- Add get_ollama_tool_description for enhanced AI context extraction (it returns a list with name and description, useful for adding to the "content" of the system)
- Fix wrapper function metadata preservation using functools.wraps
- Fix tool registration and lookup bugs found in tests
- Add comprehensive test suite in test_tools.py
- Improve code organization and modularity
- Add proper docstring handling for tool descriptions

This change improves the overall architecture of the tools system
and adds better support for AI context understanding through
proper function metadata and descriptions.
@caua1503
Copy link
Author

feat(tools): Refactor tools system and improve AI context handling

  • Create dedicated _tools.py module for better organization
  • Move tool-related functions from _utils.py to _tools.py (not including create_function_tool)
  • Rename tool getter functions for clarity:
    • get_ollama_tools_name
    • get_ollama_tools
    • get_ollama_name_async_tools
  • Add get_ollama_tool_description for enhanced AI context extraction (it returns a list with name and description, useful for adding to the "content" of the system)
  • Fix wrapper function metadata preservation using functools.wraps
  • Fix tool registration and lookup bugs found in tests
  • Add comprehensive test suite in test_tools.py
  • Improve code organization and modularity
  • Add proper docstring handling for tool descriptions

This change improves the overall architecture of the tools system
and adds better support for AI context understanding through
proper function metadata and descriptions.

@ParthSareen
Copy link
Member

Hey @caua1503 thanks for your PR.

We've discussed the use of decorators to support tool use before but there are a few challenges I have with this:

  1. Decorators are difficult to debug, especially as the end consumer in case things go wrong.
  2. They end up in various places in your code and now are decoupled from where the actual request is made which makes it difficult to know which tools are passed in when.
  3. We already have functions as tools to pass into each chat request. This keeps it coupled while allowing the reuse of the same client for different operations

@caua1503
Copy link
Author

Thanks for the feedback — it makes a lot of sense.

Based on your concerns about coupling and debugging difficulty, I’ve considered an alternative approach:

Each file or module can define its own local instance with tools = Tools()

Decorators are now used explicitly and locally via @tools.tool and @tools.async_tool

No global registration — each instance keeps track of its own tools

Developers can easily retrieve:

tools.get_tools() → all registered functions

tools.get_tool_names() → list of tool names

tools.get_async_names() → async tool names only

tools.get_descriptions() → name and description (useful for passing context to the system prompt)

This provides better modularity, avoids tool conflicts, and gives developers full control over which tools are available in each context, while still offering a clean and convenient syntax.

If this direction sounds more aligned with the project goals, I’d be happy to update the PR accordingly.

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

Successfully merging this pull request may close these issues.

2 participants