|
r"""_summary_ |
|
-*- coding: utf-8 -*- |
|
|
|
Module : data.utils.api.base_helper |
|
|
|
File Name : base_helper.py |
|
|
|
Description : API helper automatic registration, using HelperCompany can directly reflect the corresponding helper |
|
|
|
Creation Date : 2024-10-29 |
|
|
|
Author : Frank Kang([email protected]) |
|
""" |
|
|
|
from typing import Union, List, Optional |
|
from abc import ABCMeta |
|
from typing_extensions import Literal, override |
|
from ..base_company import BaseCompany |
|
from typing import Union |
|
|
|
|
|
class NotGiven: |
|
""" |
|
Copy from OpenAI |
|
|
|
A sentinel singleton class used to distinguish omitted keyword arguments |
|
from those passed in with the value None (which may have different behavior). |
|
|
|
For example: |
|
|
|
```py |
|
def get(timeout: Union[int, NotGiven, None] = NotGiven()) -> Response: |
|
... |
|
|
|
|
|
get(timeout=1) # 1s timeout |
|
get(timeout=None) # No timeout |
|
get() # Default timeout behavior, which may not be statically known at the method definition. |
|
``` |
|
""" |
|
|
|
def __bool__(self) -> Literal[False]: |
|
return False |
|
|
|
@override |
|
def __repr__(self) -> str: |
|
return "NOT_GIVEN" |
|
|
|
|
|
class HelperCompany(BaseCompany): |
|
"""_summary_ |
|
|
|
AI helper factory, inheriting BaseCompany |
|
|
|
For example: |
|
``` |
|
helper_company = HelperCompany.get() |
|
|
|
# Of course, you can also obtain the singleton using the following methods |
|
helper_company = HelperCompany() |
|
|
|
helper = helper_company[helper_name] |
|
``` |
|
|
|
@see data.utils.base_company.BaseCompany |
|
""" |
|
|
|
@override |
|
def __repr__(self) -> str: |
|
return "HelperCompany" |
|
|
|
|
|
class register_helper: |
|
"""_summary_ |
|
|
|
Automatically register helper annotation classes |
|
""" |
|
|
|
def __init__(self, helper_type, *args, **kwds): |
|
self.helper_type = helper_type |
|
self.init_args = args |
|
self.init_kwds = kwds |
|
|
|
def __call__(self, helper_cls, *args, **kwds): |
|
helper_name = helper_cls.__name__ |
|
if HelperCompany.get().register(self.helper_type, helper_cls): |
|
|
|
def _method(obj): |
|
return helper_name |
|
|
|
helper_cls.name = _method |
|
return helper_cls |
|
else: |
|
raise KeyError() |
|
|
|
|
|
class BaseHelper: |
|
"""_summary_ |
|
|
|
Base class for API helper |
|
""" |
|
|
|
__metaclass__ = ABCMeta |
|
|
|
def __init__(self, api_key, model, base_url) -> None: |
|
super(BaseHelper, self).__init__() |
|
self.api_key = api_key |
|
self.model = model |
|
self.base_url = base_url |
|
self.client = None |
|
|
|
def create( |
|
self, |
|
*args, |
|
messages: Union[str, List[str], List[int], object, None], |
|
stream: Optional[Literal[False]] | Literal[True] | NotGiven = None, |
|
temperature: Optional[float] | NotGiven = None, |
|
top_p: Optional[float] | NotGiven = None, |
|
max_tokens: int | NotGiven = None, |
|
seed: int | NotGiven = None, |
|
stop: Optional[Union[str, List[str], None]] | NotGiven = None, |
|
tools: Optional[object] | NotGiven = None, |
|
tool_choice: str | NotGiven = None, |
|
extra_headers: None | NotGiven = None, |
|
extra_body: None | NotGiven = None, |
|
timeout: float | None | NotGiven = None, |
|
**kwargs |
|
): |
|
""" |
|
Creates a model response for the given chat conversation. |
|
|
|
Args: |
|
messages: A list of messages comprising the conversation so far. |
|
[Example Python code](https://cookbook.openai.com/examples/how_to_format_inputs_to_chatgpt_models). |
|
|
|
stream: If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only |
|
[server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) |
|
as they become available, with the stream terminated by a `data: [DONE]` |
|
message. |
|
[Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). |
|
|
|
temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will |
|
make the output more random, while lower values like 0.2 will make it more |
|
focused and deterministic. |
|
|
|
We generally recommend altering this or `top_p` but not both. |
|
|
|
top_p: An alternative to sampling with temperature, called nucleus sampling, where the |
|
model considers the results of the tokens with top_p probability mass. So 0.1 |
|
means only the tokens comprising the top 10% probability mass are considered. |
|
|
|
We generally recommend altering this or `temperature` but not both. |
|
|
|
max_tokens: The maximum number of [tokens](/tokenizer) that can be generated in the chat |
|
completion. |
|
|
|
The total length of input tokens and generated tokens is limited by the model's |
|
context length. |
|
[Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) |
|
for counting tokens. |
|
|
|
seed: This feature is in Beta. If specified, our system will make a best effort to |
|
sample deterministically, such that repeated requests with the same `seed` and |
|
parameters should return the same result. Determinism is not guaranteed, and you |
|
should refer to the `system_fingerprint` response parameter to monitor changes |
|
in the backend. |
|
|
|
stop: Up to 4 sequences where the API will stop generating further tokens. |
|
|
|
tools: A list of tools the model may call. Currently, only functions are supported as a |
|
tool. Use this to provide a list of functions the model may generate JSON inputs |
|
for. A max of 128 functions are supported. |
|
|
|
tool_choice: Controls which (if any) tool is called by the model. `none` means the model will |
|
not call any tool and instead generates a message. `auto` means the model can |
|
pick between generating a message or calling one or more tools. `required` means |
|
the model must call one or more tools. Specifying a particular tool via |
|
`{"type": "function", "function": {"name": "my_function"}}` forces the model to |
|
call that tool. |
|
|
|
`none` is the default when no tools are present. `auto` is the default if tools |
|
are present. |
|
|
|
extra_headers: Send extra headers |
|
|
|
extra_body: Add additional JSON properties to the request |
|
|
|
timeout: Override the client-level default timeout for this request, in seconds |
|
""" |
|
return self.client.chat.completions.create( |
|
*args, |
|
model=self.model, |
|
messages=messages, |
|
stream=stream, |
|
temperature=temperature, |
|
top_p=top_p, |
|
max_tokens=max_tokens, |
|
seed=seed, |
|
stop=stop, |
|
tools=tools, |
|
tool_choice=tool_choice, |
|
extra_headers=extra_headers, |
|
extra_body=extra_body, |
|
timeout=timeout, |
|
**kwargs |
|
) |
|
|