tool_parse


Nametool_parse JSON
Version 0.2.1 PyPI version JSON
download
home_pagehttps://github.com/synacktraa/tool-parse
SummaryMaking LLM Tool-Calling Simpler.
upload_time2024-09-05 17:34:07
maintainerNone
docs_urlNone
authorHarsh Verma
requires_python<4.0,>=3.10
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <p align="center">Making LLM Tool-Calling Simpler.</p>

---

<p align="center">
    <a href="https://img.shields.io/github/v/release/synacktraa/tool-parse">
        <img src="https://img.shields.io/github/v/release/synacktraa/tool-parse" alt="tool-parse version">
    </a>
    <a href="https://img.shields.io/github/actions/workflow/status/synacktraa/tool-parse/master.yml?branch=master">
        <img src="https://img.shields.io/github/actions/workflow/status/synacktraa/tool-parse/master.yml?branch=master" alt="tool-parse build status">
    </a>
    <a href="https://codecov.io/gh/synacktraa/tool-parse">
        <img src="https://codecov.io/gh/synacktraa/tool-parse/branch/master/graph/badge.svg" alt="tool-parse codecov">
    </a>
    <a href="https://img.shields.io/github/license/synacktraa/tool-parse">
        <img src="https://img.shields.io/github/license/synacktraa/tool-parse" alt="tool-parse license">
    </a>
</p>

## 🚀 Installation

```sh
pip install tool-parse
```

## 🌟 Key Features

1. **Flexible Tool Registration:**

   - Support for functions (synchronous and asynchronous)
   - Compatible with `pydantic.BaseModel`, `typing.TypedDict`, and `typing.NamedTuple`
   - Multiple registration methods: decorators, direct passing, and key-value pairs
   - Supports any docstring format recognized by the `docstring_parser` library

2. **Extensive Parameter Type Support:**

   - Handles a wide range of parameter types:
     `str`, `int`, `float`, `bool`, `set`, `list`, `dict`, `pathlib.Path`,
     `typing.Set`, `typing.List`, `typing.Dict`, `typing.NamedTuple`,
     `typing.TypedDict`, `pydantic.BaseModel`, `typing.Literal`, `enum.Enum`
   - Supports optional parameters:
     `typing.Optional[<type>]`/`t.Union[<type>, None]`/`<type> | None`

3. **Lightweight and Flexible:**

   - Core package is lightweight
   - Optional dependencies (like `pydantic`) can be installed separately as needed

4. **Schema Generation and Tool Invocation:**
   - Generate schemas in 'base' and 'claude' formats
   - Easy tool invocation from call expressions or metadata

## Cookbooks

- [GorillaLLM Integration](https://colab.research.google.com/drive/1C2WCgIZ7LnkpLt3KARL9ROh4iLwaACa6?usp=sharing)

## Usage 🤗

### Creating independent tools

```python
from tool_parse import tool

@tool
def search_web(query: str, max_results: int = 10):
    """
    Search the web for given query
    :param query: The search query string
    :param max_results: Maximum number of results to return
    """
    ...

# Get tool schema
schema = search_web.marshal('base') # `base` and `claude` schema are available

# Invoke tool from LLM generated arguments
output = search_web.compile(arguments={"query": "Transformers"})
```

### Creating a tool registry

```python
from tool_parse import ToolRegistry

tr = ToolRegistry()
```

#### Defining tools and registering them

There are multiple ways of registering tools:

> Adding a docstring is optional, but it's good practice to include descriptions for parameters. The library supports any format recognized by the `docstring_parser` library, with sphinx format being a personal preference.

1. Decorating the object:

```python
from typing import TypedDict

@tr.register
class UserInfo(TypedDict):
    """
    User information schema
    :param name: The user's full name
    :param age: The user's age in years
    """
    name: str
    age: int

# Override name and description
@tr.register(name="search_web", description="Performs a web search")
def search_function(query: str, max_results: int = 10):
    """
    Search the web for given query
    :param query: The search query string
    :param max_results: Maximum number of results to return
    """
    ...
```

2. Passing the object directly:

```python
from typing import NamedTuple

class ProductInfo(NamedTuple):
    """
    Product information
    :param name: The product name
    :param price: The product price
    :param in_stock: Whether the product is in stock
    """
    name: str
    price: float
    in_stock: bool

tr.register(ProductInfo)

async def fetch_data(url: str, timeout: int = 30):
    """
    Fetch data from a given URL
    :param url: The URL to fetch data from
    :param timeout: Timeout in seconds
    """
    ...

tr.register(fetch_data, name="fetch_api_data", description="Fetches data from an API")
```

3. Using key-value pair:

> Note: This method doesn't allow overriding the description.

```python
from pydantic import BaseModel

class OrderModel(BaseModel):
    """
    Order information
    :param order_id: Unique identifier for the order
    :param items: List of items in the order
    :param total: Total cost of the order
    """
    order_id: str
    items: list[str]
    total: float

tr['create_order'] = OrderModel
```

4. Registering multiple tools at once:

> Note: This method doesn't allow overriding the name and description

```python
tr.register_multiple(UserInfo, search_function, ProductInfo)
```

#### Check if a name has already been registered

```python
'search_web' in tr  # Returns True if 'search_web' is registered, False otherwise
```

#### Get registered tools as schema

> `base` and `claude` formats are available. The default `base` format works with almost all providers.

- As a list of dictionaries:

  ```python
  tools = tr.marshal('base')  # list[dict]
  ```

- As a JSON string:

  ```python
  tools = tr.marshal(as_json=True)  # str
  ```

- Saving as a JSON file:

  ```python
  tools = tr.marshal('claude', persist_at='/path/to/tools_schema.json')  # list[dict]
  ```

- Get a single tool schema:
  ```python
  tool = tr['search_web']  # dict
  ```

#### Invoking a tool

- From a call expression:

  ```python
  result = tr.compile('search_web("Python programming", max_results=5)')
  ```

- From call metadata:

  ```python
  result = tr.compile(name='fetch_api_data', arguments={'url': 'https://api.example.com', 'timeout': 60})
  ```

> Important: The `tool-parse` library does not interact directly with LLM-specific APIs. It cannot make requests to any LLM directly. Its primary functions are generating schemas and invoking expressions or metadata generated from LLMs. This design provides developers with more flexibility to integrate or adapt various tools and libraries according to their project needs.

#### Combining two registries

> Note: A single `ToolRegistry` instance can hold as many tools as you need. Creating a new `ToolRegistry` instance is beneficial only when you require a distinct set of tools. This approach is particularly effective when deploying agents to utilize tools designed for specific tasks.

```python
new_registry = ToolRegistry()

@new_registry.register
def calculate_discount(
    original_price: float,
    discount_percentage: float = 10
):
    """
    Calculate the discounted price of an item
    :param original_price: The original price of the item
    :param discount_percentage: The discount percentage to apply
    """
    ...

combined_registry = tr + new_registry
```

## 🤝 Contributing

Contributions, issues, and feature requests are welcome! Feel free to check the [issues page](https://github.com/synacktraa/tool-parse/issues).

---

Made with ❤️ by [synacktra](https://github.com/synacktraa)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/synacktraa/tool-parse",
    "name": "tool_parse",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.10",
    "maintainer_email": null,
    "keywords": null,
    "author": "Harsh Verma",
    "author_email": "synacktra.work@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/9f/53/c12eefcf6a9a024ab36ab4b95af671c5c32b6f4f65ae96c6569e91bba85f/tool_parse-0.2.1.tar.gz",
    "platform": null,
    "description": "<p align=\"center\">Making LLM Tool-Calling Simpler.</p>\n\n---\n\n<p align=\"center\">\n    <a href=\"https://img.shields.io/github/v/release/synacktraa/tool-parse\">\n        <img src=\"https://img.shields.io/github/v/release/synacktraa/tool-parse\" alt=\"tool-parse version\">\n    </a>\n    <a href=\"https://img.shields.io/github/actions/workflow/status/synacktraa/tool-parse/master.yml?branch=master\">\n        <img src=\"https://img.shields.io/github/actions/workflow/status/synacktraa/tool-parse/master.yml?branch=master\" alt=\"tool-parse build status\">\n    </a>\n    <a href=\"https://codecov.io/gh/synacktraa/tool-parse\">\n        <img src=\"https://codecov.io/gh/synacktraa/tool-parse/branch/master/graph/badge.svg\" alt=\"tool-parse codecov\">\n    </a>\n    <a href=\"https://img.shields.io/github/license/synacktraa/tool-parse\">\n        <img src=\"https://img.shields.io/github/license/synacktraa/tool-parse\" alt=\"tool-parse license\">\n    </a>\n</p>\n\n## \ud83d\ude80 Installation\n\n```sh\npip install tool-parse\n```\n\n## \ud83c\udf1f Key Features\n\n1. **Flexible Tool Registration:**\n\n   - Support for functions (synchronous and asynchronous)\n   - Compatible with `pydantic.BaseModel`, `typing.TypedDict`, and `typing.NamedTuple`\n   - Multiple registration methods: decorators, direct passing, and key-value pairs\n   - Supports any docstring format recognized by the `docstring_parser` library\n\n2. **Extensive Parameter Type Support:**\n\n   - Handles a wide range of parameter types:\n     `str`, `int`, `float`, `bool`, `set`, `list`, `dict`, `pathlib.Path`,\n     `typing.Set`, `typing.List`, `typing.Dict`, `typing.NamedTuple`,\n     `typing.TypedDict`, `pydantic.BaseModel`, `typing.Literal`, `enum.Enum`\n   - Supports optional parameters:\n     `typing.Optional[<type>]`/`t.Union[<type>, None]`/`<type> | None`\n\n3. **Lightweight and Flexible:**\n\n   - Core package is lightweight\n   - Optional dependencies (like `pydantic`) can be installed separately as needed\n\n4. **Schema Generation and Tool Invocation:**\n   - Generate schemas in 'base' and 'claude' formats\n   - Easy tool invocation from call expressions or metadata\n\n## Cookbooks\n\n- [GorillaLLM Integration](https://colab.research.google.com/drive/1C2WCgIZ7LnkpLt3KARL9ROh4iLwaACa6?usp=sharing)\n\n## Usage \ud83e\udd17\n\n### Creating independent tools\n\n```python\nfrom tool_parse import tool\n\n@tool\ndef search_web(query: str, max_results: int = 10):\n    \"\"\"\n    Search the web for given query\n    :param query: The search query string\n    :param max_results: Maximum number of results to return\n    \"\"\"\n    ...\n\n# Get tool schema\nschema = search_web.marshal('base') # `base` and `claude` schema are available\n\n# Invoke tool from LLM generated arguments\noutput = search_web.compile(arguments={\"query\": \"Transformers\"})\n```\n\n### Creating a tool registry\n\n```python\nfrom tool_parse import ToolRegistry\n\ntr = ToolRegistry()\n```\n\n#### Defining tools and registering them\n\nThere are multiple ways of registering tools:\n\n> Adding a docstring is optional, but it's good practice to include descriptions for parameters. The library supports any format recognized by the `docstring_parser` library, with sphinx format being a personal preference.\n\n1. Decorating the object:\n\n```python\nfrom typing import TypedDict\n\n@tr.register\nclass UserInfo(TypedDict):\n    \"\"\"\n    User information schema\n    :param name: The user's full name\n    :param age: The user's age in years\n    \"\"\"\n    name: str\n    age: int\n\n# Override name and description\n@tr.register(name=\"search_web\", description=\"Performs a web search\")\ndef search_function(query: str, max_results: int = 10):\n    \"\"\"\n    Search the web for given query\n    :param query: The search query string\n    :param max_results: Maximum number of results to return\n    \"\"\"\n    ...\n```\n\n2. Passing the object directly:\n\n```python\nfrom typing import NamedTuple\n\nclass ProductInfo(NamedTuple):\n    \"\"\"\n    Product information\n    :param name: The product name\n    :param price: The product price\n    :param in_stock: Whether the product is in stock\n    \"\"\"\n    name: str\n    price: float\n    in_stock: bool\n\ntr.register(ProductInfo)\n\nasync def fetch_data(url: str, timeout: int = 30):\n    \"\"\"\n    Fetch data from a given URL\n    :param url: The URL to fetch data from\n    :param timeout: Timeout in seconds\n    \"\"\"\n    ...\n\ntr.register(fetch_data, name=\"fetch_api_data\", description=\"Fetches data from an API\")\n```\n\n3. Using key-value pair:\n\n> Note: This method doesn't allow overriding the description.\n\n```python\nfrom pydantic import BaseModel\n\nclass OrderModel(BaseModel):\n    \"\"\"\n    Order information\n    :param order_id: Unique identifier for the order\n    :param items: List of items in the order\n    :param total: Total cost of the order\n    \"\"\"\n    order_id: str\n    items: list[str]\n    total: float\n\ntr['create_order'] = OrderModel\n```\n\n4. Registering multiple tools at once:\n\n> Note: This method doesn't allow overriding the name and description\n\n```python\ntr.register_multiple(UserInfo, search_function, ProductInfo)\n```\n\n#### Check if a name has already been registered\n\n```python\n'search_web' in tr  # Returns True if 'search_web' is registered, False otherwise\n```\n\n#### Get registered tools as schema\n\n> `base` and `claude` formats are available. The default `base` format works with almost all providers.\n\n- As a list of dictionaries:\n\n  ```python\n  tools = tr.marshal('base')  # list[dict]\n  ```\n\n- As a JSON string:\n\n  ```python\n  tools = tr.marshal(as_json=True)  # str\n  ```\n\n- Saving as a JSON file:\n\n  ```python\n  tools = tr.marshal('claude', persist_at='/path/to/tools_schema.json')  # list[dict]\n  ```\n\n- Get a single tool schema:\n  ```python\n  tool = tr['search_web']  # dict\n  ```\n\n#### Invoking a tool\n\n- From a call expression:\n\n  ```python\n  result = tr.compile('search_web(\"Python programming\", max_results=5)')\n  ```\n\n- From call metadata:\n\n  ```python\n  result = tr.compile(name='fetch_api_data', arguments={'url': 'https://api.example.com', 'timeout': 60})\n  ```\n\n> Important: The `tool-parse` library does not interact directly with LLM-specific APIs. It cannot make requests to any LLM directly. Its primary functions are generating schemas and invoking expressions or metadata generated from LLMs. This design provides developers with more flexibility to integrate or adapt various tools and libraries according to their project needs.\n\n#### Combining two registries\n\n> Note: A single `ToolRegistry` instance can hold as many tools as you need. Creating a new `ToolRegistry` instance is beneficial only when you require a distinct set of tools. This approach is particularly effective when deploying agents to utilize tools designed for specific tasks.\n\n```python\nnew_registry = ToolRegistry()\n\n@new_registry.register\ndef calculate_discount(\n    original_price: float,\n    discount_percentage: float = 10\n):\n    \"\"\"\n    Calculate the discounted price of an item\n    :param original_price: The original price of the item\n    :param discount_percentage: The discount percentage to apply\n    \"\"\"\n    ...\n\ncombined_registry = tr + new_registry\n```\n\n## \ud83e\udd1d Contributing\n\nContributions, issues, and feature requests are welcome! Feel free to check the [issues page](https://github.com/synacktraa/tool-parse/issues).\n\n---\n\nMade with \u2764\ufe0f by [synacktra](https://github.com/synacktraa)\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Making LLM Tool-Calling Simpler.",
    "version": "0.2.1",
    "project_urls": {
        "Homepage": "https://github.com/synacktraa/tool-parse",
        "Repository": "https://github.com/synacktraa/tool-parse"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c95b39dec145be18a311bcdd659d0f15e3caa7e26dfe585daec9f9ec67b14633",
                "md5": "26851e9c97b499997dbf2248781537aa",
                "sha256": "7e85ef5a73969b747d69c7bb739d5e826cbc51674ca651c7813e64e8f536eb0f"
            },
            "downloads": -1,
            "filename": "tool_parse-0.2.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "26851e9c97b499997dbf2248781537aa",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.10",
            "size": 14155,
            "upload_time": "2024-09-05T17:34:06",
            "upload_time_iso_8601": "2024-09-05T17:34:06.718284Z",
            "url": "https://files.pythonhosted.org/packages/c9/5b/39dec145be18a311bcdd659d0f15e3caa7e26dfe585daec9f9ec67b14633/tool_parse-0.2.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9f53c12eefcf6a9a024ab36ab4b95af671c5c32b6f4f65ae96c6569e91bba85f",
                "md5": "ba4425c1f16e3dd5cb8e6dc81c076551",
                "sha256": "7f1aa4f3cc7104bfec2f4136f223ddcc8077ce75a3be5013f6c404887ddc0eea"
            },
            "downloads": -1,
            "filename": "tool_parse-0.2.1.tar.gz",
            "has_sig": false,
            "md5_digest": "ba4425c1f16e3dd5cb8e6dc81c076551",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.10",
            "size": 14199,
            "upload_time": "2024-09-05T17:34:07",
            "upload_time_iso_8601": "2024-09-05T17:34:07.733305Z",
            "url": "https://files.pythonhosted.org/packages/9f/53/c12eefcf6a9a024ab36ab4b95af671c5c32b6f4f65ae96c6569e91bba85f/tool_parse-0.2.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-09-05 17:34:07",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "synacktraa",
    "github_project": "tool-parse",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "tox": true,
    "lcname": "tool_parse"
}
        
Elapsed time: 4.00901s