Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for calling tools in conversations #4

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

jhrozek
Copy link
Contributor

@jhrozek jhrozek commented Oct 6, 2024

This PR adds support for calling tools in conversations along with a couple of
utilities to register and drive the tools and an example calling out to
trusty.

The code is not super polished, as an example it always only evaluates the first function
call or doesn't really check the stop reasons well. But it's a working PoC of what we could do.

What is this good for?

Calling a function enables the model to compute realtime information.

How does calling out to tools differ from RAG?

RAG is more useful for data that doesn't change that much and that we can prepare beforehand.
In the context of Minder, we might want to store ruletypes and profiles into a vector database
to provide them to the model as RAG, but we'd want to call a function to get up-to-date information
about an entity.

CLI examples

There is a small CLI app that calls to trusty and gives the user summary of information
about a package the user queries.

To run the app with OpenAI:

BACKEND=openai OPENAI_API_KEY=BLAH go run ./examples/tools/main.go "I want to use the python invokehttp package in my project. Is it a good idea?"

or with Ollama:

BACKEND=ollama go run ./examples/tools/main.go "I want to use the python invokehttp package in my project. Is it a good idea?"

@lukehinds
Copy link
Contributor

Sorry for late reply @jhrozek , do you think it would be possible to make this a generic http backend, without the trusty'isms (I guess mainly the struct around trusty's payload and the URL etc). The thinking is over time this might become a generic go to library used by folks outside of stacklok.

@jhrozek
Copy link
Contributor Author

jhrozek commented Oct 9, 2024

Sorry for late reply @jhrozek , do you think it would be possible to make this a generic http backend, without the trusty'isms (I guess mainly the struct around trusty's payload and the URL etc). The thinking is over time this might become a generic go to library used by folks outside of stacklok.

I can make the example more generic, but the parameters of the tool will always be specific to the tool. But at the same time, the back end only needs to know the tool name (to return it back), the tool description (to match the tool in prompts) and the parameters which are a generic map[string]any.

Adds two helper utilities for converting a structure to map[string]any
as well as printing as JSON.
Both OpenAI Ollama have the same API structure for executing tools. This
commit adds a tool registry that the library user can use to register a
new tool that the model will be able to call.
Adds a Converse method for Ollama. Due to how Ollama models are
implemented (ollama/ollama#6127) we try to
detect if a non-existing tool was called and just route the prompt to
the model again with tools disabled.
Implements conversationw with tool support for OpenAI. The OpenAI models
expect an assistant message that includes the details about the function
call and the function call ID in the response.
Adds Converse as a back end method, making it usable by library clients.
Adds an example of tool function with pretend weather reports.

Example invocations:
```
BACKEND=ollama go run ./examples/tools/main.go "What is the weather in London?"
2024/10/17 22:42:11 No model selected with the MODEL env variable.
Defaulting to  qwen2.5
2024/10/17 22:42:11 Using Ollama backend:  qwen2.5
2024/10/17 22:42:14 Tool called
2024/10/17 22:42:14 Response:
2024/10/17 22:42:14 The current temperature in London is 15°C and the conditions are rainy.
```
@jhrozek
Copy link
Contributor Author

jhrozek commented Oct 17, 2024

Sorry it took me so long to get back! I rebased the patch atop the current master and took the new structures like Prompt into use which made the PR a bit smaller. I also added a less involved and more generic example instead of the Trusty one. This example pretends to be a weather forecast:

BACKEND=ollama go run ./examples/tools/main.go "What is the weather in London?"
2024/10/17 22:47:00 No model selected with the MODEL env variable. Defaulting to  qwen2.5
2024/10/17 22:47:00 Using Ollama backend:  qwen2.5
2024/10/17 22:47:08 Tool called
2024/10/17 22:47:09 Response:
2024/10/17 22:47:09 The current temperature in London is 15°C and the conditions are rainy.

or with OpenAI:

BACKEND=openai OPENAI_API_KEY=blah go run ./examples/tools/main.go "What is the weather in Stockholm?"
2024/10/17 22:47:36 No model selected with the MODEL env variable. Defaulting to  gpt-4o-mini
2024/10/17 22:47:36 Using OpenAI backend:  gpt-4o-mini
2024/10/17 22:47:37 Tool called
2024/10/17 22:47:38 Response:
2024/10/17 22:47:38 The weather in Stockholm is currently 10°C and sunny.

@jhrozek
Copy link
Contributor Author

jhrozek commented Oct 17, 2024

btw there are no tests now. it's something I'd like to fix if we agree about the code direction

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants