-
Notifications
You must be signed in to change notification settings - Fork 1
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
Function calling vllm #8
Changes from 18 commits
8b60241
b1932fc
ec522e0
3efd44c
ad8cb80
dde9521
400d612
4139701
80f8260
22ec060
ed9f7ef
7ac3801
4da8fc5
595dfc8
96f5e5e
241024f
60dbdb3
1a41188
b22fdda
31a492a
c4ae437
f58668b
bd24e5f
0992305
8572716
a300ca7
919478a
68d19ce
585ae1e
68b35b8
bb575c3
dbb0c2e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The readme should also indicate what one should do with functional.py ? Replace the original one (I prefer this option), copy/paste the relevant part .... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "To use this implementation, you must replace |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Functions calling | ||
|
||
## Deploy a new function | ||
To avoid repeatedly specifying all attributes related to tools and tool_choice when functions calling, you can create a classe inherit ```functions.ToolFunctions```. | ||
maxDavid40 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
You need to instantiate 4 attributes: | ||
- description (string) | ||
- parameters (dict) | ||
- name (string) | ||
- tool_type (string) | ||
|
||
Each attributes correpondings as [Openai api](https://platform.openai.com/docs/api-reference/chat/create#chat-create-tools) | ||
maxDavid40 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Called functions | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we specify that this endpoints has to be called, only if happy_vllm server is deployed with pre defined tools? |
||
After deploy you REST API, you can call it with the following rutes ```/v1/chat/completions_tools``` | ||
maxDavid40 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## To know | ||
|
||
With vllm 0.5.0 to 0.5.3.post1, tool_choice's option ```auto``` and ```required``` are not yet implemented. You can only use one function by deployement : | ||
maxDavid40 marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it one function for each deployement or one function for each call ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for each deployement |
||
|
||
``` | ||
{ | ||
maxDavid40 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"type": "function", | ||
"function": {"name": "get_current_weather"} | ||
} | ||
``` | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import logging | ||
from copy import copy | ||
from typing import Union | ||
from argparse import Namespace | ||
|
||
|
||
class ToolFunctions: | ||
maxDavid40 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
Represents a tool function with specific attributes. | ||
|
||
Attributes: | ||
description (str): Description of the tool function. | ||
parameters (dict): Parameters required for the tool function. | ||
name (str): Name of the tool function. | ||
tool_type (str): Type of the tool function. | ||
|
||
Methods: | ||
__init__(description: Union[str, None], parameters: Union[dict, None], name: Union[str, None], tool_type: Union[str, None]): | ||
Initializes a ToolFunctions instance with the provided attributes. Raises NotImplementedError if any attribute is None. | ||
|
||
_check_attributes(): | ||
Checks if the required attributes (description, parameters, name, tool_type) are not None. | ||
Raises NotImplementedError if any attribute is None. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it should be a value error. In my opinion, the NotImplementedError is only used for missing methods, not missing attributes. I may be mistaken There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After reading python doc, should be AttributeError. |
||
|
||
generate_dict() -> dict: | ||
Generates and returns a dictionary representation of the tool function, including its type, name, description, and parameters. | ||
""" | ||
def __init__(self, description:Union[str, None], parameters:Union[dict, None], name:Union[str, None], tool_type:Union[str, None]): | ||
self.description:str = description | ||
maxDavid40 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self.parameters:dict = parameters | ||
self.name:str = name | ||
self.tool_type:str = tool_type | ||
self._check_attributes() | ||
|
||
def _check_attributes(self): | ||
if not self.description: | ||
raise NotImplementedError("This attributes must be different to None") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ValueError ? (see comment above) |
||
if not self.parameters: | ||
raise NotImplementedError("This attributes must be different to None") | ||
if not self.name: | ||
raise NotImplementedError("This attributes must be different to None") | ||
if not self.tool_type: | ||
raise NotImplementedError("This attributes must be different to None") | ||
|
||
def generate_dict(self): | ||
return { | ||
"type": self.tool_type, | ||
"function": { | ||
"name": self.name, | ||
"description": self.description, | ||
"parameters": self.parameters, | ||
|
||
} | ||
} | ||
|
||
|
||
class Weather(ToolFunctions): | ||
""" | ||
Represents a example tool function about the weather. | ||
maxDavid40 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
def __init__(self): | ||
tool_type = "function" | ||
name = "get_current_weather" | ||
description = "Get current weather" | ||
parameters = { | ||
"type": "object", | ||
"properties": { | ||
"location": { | ||
"type": "string", | ||
"description": "The city and state, e.g. San Francisco, CA", | ||
}, | ||
"format": { | ||
"type": "string", | ||
"enum": ["celsius", "fahrenheit"], | ||
"description": "The temperature unit to use. Infer this from the users location.", | ||
}, | ||
}, | ||
"required": ["location", "format"] | ||
} | ||
super().__init__(description=description, parameters=parameters, name=name, tool_type=tool_type) | ||
|
||
|
||
TOOLS_DICT = { | ||
maxDavid40 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
'weather': Weather(), | ||
} | ||
TOOLS = ['weather'] | ||
|
||
|
||
def get_tools(): | ||
maxDavid40 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return TOOLS_DICT, TOOLS | ||
|
||
|
||
def reset_tools_dict_and_tools(): | ||
maxDavid40 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
Resets the global variables TOOLS_DICT and TOOLS with new default values. | ||
|
||
Returns: | ||
tuple: A tuple containing the updated values of TOOLS_DICT and TOOLS. | ||
TOOLS_DICT is a dictionary with keys for different tools and corresponding values, | ||
and TOOLS is an empty list. | ||
""" | ||
global TOOLS_DICT | ||
global TOOLS | ||
TOOLS_DICT = { | ||
'weather': Weather() | ||
} | ||
TOOLS = ['weather'] | ||
|
||
|
||
def get_tools_prompt() -> dict: | ||
maxDavid40 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
Returns a dictionary containing information about selected tools. | ||
|
||
Returns: | ||
dict or None: A dictionary containing information about selected tools, structured as follows: | ||
- "tools": A list of dictionaries, each representing a tool's generated dictionary. | ||
- "tool_choice": A dictionary containing type and function details of the first tool in the list, | ||
or None if TOOLS is empty. | ||
Returns None if TOOLS is empty. | ||
""" | ||
tools_dict = copy(TOOLS_DICT) | ||
tools = copy(TOOLS) | ||
if tools: | ||
return { | ||
"tools": [tools_dict[t].generate_dict() for t in tools], | ||
"tool_choice": [ | ||
{ | ||
"type": tools_dict[t].tool_type, | ||
"function": {"name":tools_dict[t].name} | ||
} | ||
for t in tools | ||
][0] | ||
} | ||
else: | ||
return None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The readme should indicate where the subclass created should be put in order to be able to use it (in TOOLS and TOOLS_DICT)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid repeatedly specifying all attributes related to tools and tool_choice when using functions calling, you can create a classe inheriting from
functions.ToolFunctions
.You need to instantiate 4 attributes:
Each attributes correpondings to Openai api
After the class is created, you have to declare in TOOLS_DICT and TOOLS global variables in
functions_tools.function_tools_util.py
(add weather function tool for example).