RockChinQ / CallingGPT

Build your own ChatGPT plugin platform with GPT's function calling ability | func call by GPT
66 stars 3 forks source link

Args type parsing in functions #2

Closed rzc331 closed 1 year ago

rzc331 commented 1 year ago

I might be wrong about this, it seems that only string-type args are now supported?

https://github.com/RockChinQ/CallingGPT/blob/e49643a7001a8d556aa6e7b535eeca9528ea12a7/CallingGPT/entities/namespace.py#L92C9-L93

I tried to implement other arg types, among which I found list to be most tricky. As my understanding, one has to recursively define the type of the element in the list, until the element is not a list (e.g. List[List[str]]). There might be same issue with dict.

If the type of element in the list is not clearly defined, there will be an error like this

InvalidRequestError                       Traceback (most recent call last)
    [... skipping hidden 1 frame]

C:\Users\CHU~1\AppData\Local\Temp/ipykernel_32712/1691176088.py in <module>
----> 1 session.ask("how's it going?")

~\PycharmProjects\catalyst\CallingGPT\CallingGPT\session\session.py in ask(self, msg)
     48 
---> 49         resp = openai.ChatCompletion.create(
     50             **args

C:\ProgramData\Miniconda3\envs\catalyst\lib\site-packages\openai\api_resources\chat_completion.py in create(cls, *args, **kwargs)
     24             try:
---> 25                 return super().create(*args, **kwargs)
     26             except TryAgain as e:

C:\ProgramData\Miniconda3\envs\catalyst\lib\site-packages\openai\api_resources\abstract\engine_api_resource.py in create(cls, api_key, api_base, api_type, request_id, api_version, organization, **params)
    152 
--> 153         response, _, api_key = requestor.request(
    154             "post",

C:\ProgramData\Miniconda3\envs\catalyst\lib\site-packages\openai\api_requestor.py in request(self, method, url, params, headers, files, stream, request_id, request_timeout)
    297         )
--> 298         resp, got_stream = self._interpret_response(result, stream)
    299         return resp, got_stream, self.api_key

C:\ProgramData\Miniconda3\envs\catalyst\lib\site-packages\openai\api_requestor.py in _interpret_response(self, result, stream)
    699             return (
--> 700                 self._interpret_response_line(
    701                     result.content.decode("utf-8"),

C:\ProgramData\Miniconda3\envs\catalyst\lib\site-packages\openai\api_requestor.py in _interpret_response_line(self, rbody, rcode, rheaders, stream)
    762         if stream_error or not 200 <= rcode < 300:
--> 763             raise self.handle_error_response(
    764                 rbody, rcode, resp.data, rheaders, stream_error=stream_error

<class 'str'>: (<class 'TypeError'>, TypeError('__str__ returned non-string (type list)'))

During handling of the above exception, another exception occurred:

TypeError                                 Traceback (most recent call last)
    [... skipping hidden 1 frame]

C:\ProgramData\Miniconda3\envs\catalyst\lib\site-packages\IPython\core\interactiveshell.py in showtraceback(self, exc_tuple, filename, tb_offset, exception_only, running_compiled_code)
   2080                                             value, tb, tb_offset=tb_offset)
   2081 
-> 2082                     self._showtraceback(etype, value, stb)
   2083                     if self.call_pdb:
   2084                         # drop into debugger

C:\ProgramData\Miniconda3\envs\catalyst\lib\site-packages\ipykernel\zmqshell.py in _showtraceback(self, etype, evalue, stb)
    541             'traceback' : stb,
    542             'ename' : str(etype.__name__),
--> 543             'evalue' : str(evalue),
    544         }
    545 

TypeError: __str__ returned non-string (type list)
RockChinQ commented 1 year ago

Thank you for your issue.

The code you referenced means convert str to string which's the standard type name of str arg in function schema and other type (e.g int float) don't need to convert.

As for the list and dict types you mentioned, I haven't tested them yet. Can you provide some sample functions?

rzc331 commented 1 year ago

The code you referenced means convert str to string which's the standard type name of str arg in function schema and other type (e.g int float) don't need to convert.

I tried int, and got the error code

'int' is not valid under any of the given schemas

As for the list and dict types you mentioned, I haven't tested them yet. Can you provide some sample functions?

I wrote a dummy function:

def create_shopping_list(shopping_list: list):
    """
    Create a shopping list that we should buy today

    Args:
        shopping_list(list): a list of the chemicals that we need to buy today

    Returns:
        String of all the item in the shopping list
    """
    return ', '.join(shopping_list)

which will cause the error TypeError: __str__ returned non-string (type list) I mentioned above when we ask the first prompt

As long as we change the type from list to str, it works

RockChinQ commented 1 year ago

fixed, upgrade CallingGPT and try:

def hello() -> None:
    """Print "Hello, world!"""
    print("Hello, world!")

def greet(user: str) -> str:
    """Return a greeting to `user`.

    Args:
        user: the name to greet
    """
    return "Hello, {}!".format(user)

def add_up(a: int, b: float) -> float:
    """Add `a` and `b` and return the result.

    Args:
        a: the first number
        b: the second number
    """
    return a + b

def get_not(b: bool) -> bool:
    """Return the opposite of `b`.

    Args:
        b: the boolean to negate
    """
    return not b

def list_to_str(l: list[int]) -> str:  # if you don't specific the type of list element, the type will be set to `string` by default
    """Return a string representation of `l`.

    Args:
        l: the list to convert
    """
    return str(l)

def dict_to_str(d: dict) -> str:
    """Return a string representation of `d`.

    Args:
        d: the dict to convert
    """

    return str(d)
RockChinQ commented 1 year ago

well, list's recursively parsing is still not supported now.

rzc331 commented 1 year ago

well, list's recursively parsing is still not supported now.

Thanks for prompt fix! It somehow works for me now!

rzc331 commented 1 year ago

Noticed another minor issue:

If a "from ... import ..." statement exists in the module, the imported function will also be parsed in the namespace. Not sure if it's desired, because the doc_str of the imported external functions may not follow the required format

RockChinQ commented 1 year ago

Noticed another minor issue:

If a "from ... import ..." statement exists in the module, the imported function will also be parsed in the namespace. Not sure if it's desired, because the doc_str of the imported external functions may not follow the required format

fixed