Skip to main content

func2llmtool - Python function to LLM tool

Usage

from func2llmtool.core import FuncInfo  # this library
import litellm  # or other LLM library
fi = FuncInfo.from_func(my_function)  # your def my_function()
litellm.completion(model='inference/mymodel', messages=[], tools=[fi()])

Installation

Install latest from the GitHub repository:

$ pip install git+https://github.com/NumesSanguis/func2llmtool.git

or from pypi

$ pip install func2llmtool

Documentation

How to use

Let’s turn our weather function into a tool a LLM can use. The default output format is “litellm”. Supported:

# define our tool function with docstring and variable annotations
def get_weather(
    city: str  # City name
) -> str:  # Returns the weather in a city, e.g. "rainy"
    """Get the current weather for a city."""

    if city.lower() == "tokyo": weather = "sunny"
    elif city.lower() == "amsterdam": weather = "cloudy"
    else: weather = "rainy"

    return weather

Extract the required data:

fi = FuncInfo.from_func(get_weather)
fi  # same as print(fi)
{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get the current weather for a city. Return type: string (Returns the weather in a city, e.g. \"rainy\")",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "City name"
                }
            },
            "required": [
                "city"
            ],
            "additionalProperties": false
        }
    }
}

Return the data without pretty printing:

fi()  # same as: fi.to_tool_dict()
{'type': 'function',
 'function': {'name': 'get_weather',
  'description': 'Get the current weather for a city. Return type: string (Returns the weather in a city, e.g. "rainy")',
  'parameters': {'type': 'object',
   'properties': {'city': {'type': 'string', 'description': 'City name'}},
   'required': ['city'],
   'additionalProperties': False}}}

Format output dict according to OpenAI standard:

fi.to_tool_dict(format="openai")
{'type': 'function',
 'name': 'get_weather',
 'description': 'Get the current weather for a city. Return type: string (Returns the weather in a city, e.g. "rainy")',
 'parameters': {'type': 'object',
  'properties': {'city': {'type': 'string', 'description': 'City name'}},
  'required': ['city'],
  'additionalProperties': False},
 'strict': True}

We can also provide the function name as long as it is in your Python globals:

FuncInfo.from_func('get_weather')()
{'type': 'function',
 'function': {'name': 'get_weather',
  'description': 'Get the current weather for a city. Return type: string (Returns the weather in a city, e.g. "rainy")',
  'parameters': {'type': 'object',
   'properties': {'city': {'type': 'string', 'description': 'City name'}},
   'required': ['city'],
   'additionalProperties': False}}}

Other docstring styles - Numpy

# define our tool function with numpy-style docstring
def get_weather_numpy_style(city: str) -> str:
    """
    Get the current weather for a city.

    Parameters
    ----------
    city : str
        City name

    Returns
    -------
    str
        The weather in a city, e.g. "rainy"
    """

    if city.lower() == "tokyo": weather = "sunny"
    elif city.lower() == "amsterdam": weather = "cloudy"
    else: weather = "rainy"

    return weather
FuncInfo.from_func(get_weather_numpy_style)()
{'type': 'function',
 'function': {'name': 'get_weather_numpy_style',
  'description': 'Get the current weather for a city. Return type: string (The weather in a city, e.g. "rainy")',
  'parameters': {'type': 'object',
   'properties': {'city': {'type': 'string', 'description': 'City name'}},
   'required': ['city'],
   'additionalProperties': False}}}

LiteLLM example - Attach tool info to LLM

Here we show how to attach the tool info to a LLM request, handle its tool request, return our tool output, and get our question about the weather answered.

import os
import litellm
from litellm.caching.caching import Cache
# set ENV variables for LLM usage; https://console.groq.com/keys
# os.environ["GROQ_API_KEY"] = "your-api-key"

Prepare our LLM call:

# groq is a fast inference provider (not to be confused with grok by X), which offers a free tier
MODEL = 'groq/llama-3.1-8b-instant'  # any model supported by LiteLLM and for which you set a key
MESSAGES = []
TOOLS = [fi()]
litellm.cache = Cache(type="disk")
litellm.suppress_debug_info = True  # prevent "Provider List: https://docs.litellm.ai/docs/providers" spam
# optional instructions
# MESSAGES.append({"role": "system", "content": "Use the results from tool calls to answer questions."})
MESSAGES.append({"role": "user", "content": "What is the weather in city Tokyo?"})

Call model with our Python function available as tool:

resp = litellm.completion(model=MODEL, messages=MESSAGES, tools=TOOLS, caching=True)
print(resp.choices[0].message.model_dump())
{'content': None, 'role': 'assistant', 'tool_calls': [{'function': {'arguments': '{"city":"Tokyo"}', 'name': 'get_weather'}, 'id': 'hjgzy4gz9', 'type': 'function'}], 'function_call': None, 'provider_specific_fields': None}

Note the 'tool_calls': [{'function': {'arguments': '{"city":"Tokyo"}', 'name': 'get_weather'}, ... part. This is the tool call that the LLM made. Let’s execute it and inform the LLM.

# example only shows how to handle 1 tool call (multiple can be requested in parallel)
tc = resp.choices[0].message.tool_calls[0]
tc
ChatCompletionMessageToolCall(function=Function(arguments='{"city":"Tokyo"}', name='get_weather'), id='hjgzy4gz9', type='function')
# The id associated to the tool call, so the LLM knows which output is associated to which tool call
tc.id
'hjgzy4gz9'
# The arguments are a JSON string, so we need to convert them before calling our function
import json

func_args = json.loads(tc.function.arguments)
func_args
{'city': 'Tokyo'}

Add tool call and usage to message history:

# keep track of the tool call by the LLM in our message history
MESSAGES.append({k:v for k,v in resp.choices[0].message.model_dump().items() if v is not None})
# Add tool call result to message history
MESSAGES.append({'role': 'tool', 'tool_call_id': tc.id, 'content': get_weather(**func_args)})
# We now have all info to query the LLM again
print(MESSAGES)
[{'role': 'user', 'content': 'What is the weather in city Tokyo?'}, {'role': 'assistant', 'tool_calls': [{'function': {'arguments': '{"city":"Tokyo"}', 'name': 'get_weather'}, 'id': 'hjgzy4gz9', 'type': 'function'}]}, {'role': 'tool', 'tool_call_id': 'hjgzy4gz9', 'content': 'sunny'}]

Give our LLM back the tool execution results and ask it to answer our initial question.

resp2 = litellm.completion(model=MODEL, messages=MESSAGES, tools=TOOLS, caching=True)
print(resp2.choices[0].message.content)
It's currently sunny in Tokyo.

Alternatives to this library

# LiteLLM has a build-in function, but it is not as flexible what is supported.
# Note the missing parameter description and nothing about what's returned
litellm.utils.function_to_dict(get_weather)
{'name': 'get_weather',
 'description': 'Get the current weather for a city.',
 'parameters': {'type': 'object',
  'properties': {'city': {'type': 'string'}},
  'required': ['city']}}
# gets the 'city' description, but nothing about what's returned
litellm.utils.function_to_dict(get_weather_numpy_style)
{'name': 'get_weather_numpy_style',
 'description': 'Get the current weather for a city.',
 'parameters': {'type': 'object',
  'properties': {'city': {'type': 'string', 'description': 'City name'}},
  'required': ['city']}}

Metadata

Release files for func2llmtool 0.0.2

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

Source distribution (sdist)

Source distribution for func2llmtool 0.0.2
File Size Uploaded
func2llmtool-0.0.2.tar.gz 19.7 kB Details

Built distribution (wheel)

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

Total release size: 36.1 kB

Release files / func2llmtool-0.0.2.tar.gz

Download URL func2llmtool-0.0.2.tar.gz
Size 19.7 kB
Tags Source
SHA-256 checksum
How to use checksums
c88adee2eaecbdd3df347c5f08b4540eea3adf4ef59c8ea6b2ca6a23062e37aa
BLAKE2b-256 checksum
How to use checksums
f7d0deae885f60fa36c8e2993c33c1d4358edaee9e976d22f73e9e5ecdd45547
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.12

Release files / func2llmtool-0.0.2-py3-none-any.whl

Download URL func2llmtool-0.0.2-py3-none-any.whl
Size 16.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
94927427d1c7485a47c0e046252f0cbdb43486ac8b999e2b9f1c52ea61715380
BLAKE2b-256 checksum
How to use checksums
1c1ee1f12f07f54ff31f913fd88c757b7d85559a4cd4aab9bf9d968a871e4567
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.12

Release history Release notifications | RSS feed

This release

0.0.2 This release

2 release files

0.0.1

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