Skip to main content

ToolUser

GitHub release Build Status License Python

Enable tool-use ability for any LLM model (DeepSeek V3/R1, etc.)

For some models/providers that doesn't natively support function calling (e.g. DeepSeek V3/R1), you can use this library to transform the tool calls to a user prompt, in Hermes template format by default.

Installation

pip install tooluser
from openai import AsyncOpenAI
from tooluser import make_tool_user

oai = make_tool_user(AsyncOpenAI())

res = await oai.chat.completions.create(
    model="deepseek/deepseek-chat-v3-0324", # From OpenRouter https://openrouter.ai/deepseek/deepseek-chat-v3-0324
    messages=[{"role": "user", "content": "What's the time in Shanghai?"}],
    tools=[
        {
            "type": "function",
            "function": {
                "name": "get_time",
                "description": "Get the time in a given location",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The location to get the time for",
                        },
                    },
                },
            },
        }
    ],
)

Check out the example.py for a runnable example.

Streaming Support

Yes, this library also supports streaming.

Check out the example_stream.py for a runnable example.

(LLM output for tool using is not streamed, because we use json-repair for it.)

Raw JSON Detection (Experimental)

Some LLMs occasionally forget to wrap function calls in <tool_call> tags and output raw JSON instead. This library can optionally detect such cases when they appear at the end of the response.

from tooluser import make_tool_user

# Enable raw JSON detection
client = make_tool_user(
    AsyncOpenAI(),
    enable_raw_json_detection=True
)

Example scenarios that will be detected:

  • "I'll help you with that. {"name": "get_weather", "arguments": {"location": "NYC"}}"
  • "Let me search for that information. {"name": "search_files", "arguments": {"pattern": "*.py"}}"

What won't be detected (to avoid false positives):

  • "Here's some data: {"name": "config", "arguments": {...}} for processing"
  • JSON that appears in the middle of the response

Note: This feature is disabled by default for maximum reliability. Only enable it if you're experiencing issues with LLMs that inconsistently use tool call tags.

Check out the example_raw_json.py for a runnable example.

What's Hermes template?

Function calling is implicitly a prompt template, to make the model understand how to output the structured response as we want. Hermes template is a widely adopted prompt template for function calling.

What happens under the hood?

As we want to make use of the OpenAI chat completion API, we do not directly use Hermes template to generate the LLM instruction, but we generate the Hermes style system prompt and user prompt.

The actually API call is:

System:

<tool_instruction>
You are a function calling AI model. You are provided with function signatures within <tools> </tools> XML tags. You may call one or more functions to assist with the user query. Don't make assumptions about what values to plug into functions.
<tools>
['{"type": "function", "function": {"name": "get_time", "description": "Get the time in a given location", "parameters": {"type": "object", "properties": {"location": {"type": "string", "description": "The location to get the time for"}}}}}']
</tools>

For each function call return a json object with function name and arguments within <tool_call> </tool_call> tags with the following schema:
<tool_call>
{"name": <function-name>, "arguments": <args-dict>}
</tool_call>

Here is an example of a tool call:
<tool_call>
{"name": "get_weather", "arguments": {"location": "San Francisco, CA", "unit": "celsius"}}
</tool_call>

</tool_instruction>

User:

What's the time in Shanghai?

Assistant:

<tool_call>
{"name": "get_time", "arguments": {"location": "Shanghai"}}
</tool_call>

Release files for tooluser 0.2.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tooluser 0.2.4
File Size Uploaded
tooluser-0.2.4.tar.gz 17.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tooluser 0.2.4
File Interpreter ABI Platform
tooluser-0.2.4-py3-none-any.whl Python 3 none any Details

Total release size: 31.8 kB

Release files / tooluser-0.2.4.tar.gz

Download URL tooluser-0.2.4.tar.gz
Size 17.7 kB
Tags Source
SHA-256 checksum
How to use checksums
77373e2e6096b55b01d6fbf7643a580d82ec1f41986713bba062d120e40c0d51
BLAKE2b-256 checksum
How to use checksums
328992968304c95bb95f8472df2a405aa9042d9326e01aaefdfa9c32db0197bb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via pdm/2.24.2 CPython/3.13.3 Linux/6.11.0-1014-azure

Release files / tooluser-0.2.4-py3-none-any.whl

Download URL tooluser-0.2.4-py3-none-any.whl
Size 14.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bd0ce22c9effc8432523db99c34d88c16bc8a64a6d313f2aa9635025bc44f9f3
BLAKE2b-256 checksum
How to use checksums
b9d9b6de1283831e5e40bc5546f016f7efd35d47d0da5cddc14fb0b1cca95ded
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via pdm/2.24.2 CPython/3.13.3 Linux/6.11.0-1014-azure

Release history Release notifications | RSS feed

This release

0.2.4 This release

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page