haystack icon indicating copy to clipboard operation
haystack copied to clipboard

🧪 Tools: convert functions (and others) into Tools

Open anakin87 opened this issue 1 year ago • 5 comments

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 avatar Aug 09 '24 14:08 anakin87

@anakin87 Just want to understand this. Is the idea that I code a python function and only use this to create a Tool Object?

Emil-io avatar Oct 02 '24 10:10 Emil-io

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

anakin87 avatar Oct 03 '24 15:10 anakin87

awesome, this looks super cool!

Emil-io avatar Oct 04 '24 09:10 Emil-io

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.

anakin87 avatar Oct 14 '24 07:10 anakin87

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.

vblagoje avatar Oct 14 '24 10:10 vblagoje

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.

anakin87 avatar Oct 30 '24 11:10 anakin87