🧪 Tools: convert functions (and others) into Tools
While detailed, manually crafted specifications are ideal, utilities for converting different types of callables into Tools can be helpful for users.
- from a function (with optional parsing of docstrings) - this is the minimum requirement
To explore and see if feasible:
- from (function +) Pydantic schema (to allow customization, easier and more pythonic than JSON schema)
- from a Haystack component
- from a Haystack Pipeline
@anakin87 Just want to understand this. Is the idea that I code a python function and only use this to create a Tool Object?
I'm working on something like this:
from typing import Annotated, Literal
from haystack_experimental.dataclasses import Tool
def get_weather(
city: Annotated[str, "the city for which to get the weather"] = "Munich",
unit: Annotated[Literal["Celsius", "Fahrenheit"], "the unit for the temperature"] = "Celsius"):
"""A simple function to get the current weather for a location."""
return f"Weather report for {city}: 20 {unit}, sunny"
tool = Tool.from_function(get_weather)
print(tool)
>>> Tool(name='get_weather', description='A simple function to get the current weather for a location.',
>>> parameters={
>>> 'type': 'object',
>>> 'properties': {
>>> 'city': {'type': 'string', 'description': 'the city for which to get the weather', 'default': 'Munich'},
>>> 'unit': {
>>> 'type': 'string',
>>> 'enum': ['Celsius', 'Fahrenheit'],
>>> 'description': 'the unit for the temperature',
>>> 'default': 'Celsius',
>>> },
>>> }
>>> },
>>> function=<function get_weather at 0x7f7b3a8a9b80>)
Related PR: https://github.com/deepset-ai/haystack-experimental/pull/114
awesome, this looks super cool!
Update
-
In https://github.com/deepset-ai/haystack-experimental/pull/114, we introduced the conversion of a function into a Tool (example).
-
Converting a component into a Tool is currently not possible using
from_function. While experimenting, it became evident that several components accept non-primitive python types as input (Document,ChatMessage, ...). This makes it difficult to use a LLM to produce a valid call for them. We could see if there is a demand for this feature in the future. -
To convert a Pipeline into a Tool, we can wrap it in a function and use
from_function. I tend to prefer this approach because a Pipeline can be called with several valid inputs and this makes users express explicitly how they want to invoke it. Other automatic approaches are interesting, however, as can be seen in the experiment by @vblagoje.
Yes, agreed @anakin87 - users can also prepare dataclass (Document, ChatMessage) instances in these functions from primitive inputs and pass dataclass instances to pipelines as inputs. I would regard automatic pipeline invocation as tools as a north star we should aim for but right now we can provide immediate benefits to our users via function "bridges" that are almost as good.
It is possible to create the tools:
- manually
- from a function
I'm closing this issue and moving the discussion of potential directions to explore in #8505.