@ -18,29 +18,102 @@ from discord import File
class Mode :
TOP_P = " top_p "
TEMPERATURE = " temperature "
TOP_P = " top_p "
ALL_MODES = [ TEMPERATURE , TOP_P ]
class Models :
# Text models
DAVINCI = " text-davinci-003 "
CURIE = " text-curie-001 "
BABBAGE = " text-babbage-001 "
ADA = " text-ada-001 "
# Code models
CODE_DAVINCI = " code-davinci-002 "
CODE_CUSHMAN = " code-cushman-001 "
# Embedding models
EMBEDDINGS = " text-embedding-ada-002 "
# Edit models
EDIT = " text-davinci-edit-001 "
CODE_EDIT = " code-davinci-edit-001 "
# Model collections
TEXT_MODELS = [ DAVINCI , CURIE , BABBAGE , ADA , CODE_DAVINCI , CODE_CUSHMAN ]
EDIT_MODELS = [ EDIT , CODE_EDIT ]
DEFAULT = DAVINCI
LOW_USAGE_MODEL = CURIE
# Tokens Mapping
TOKEN_MAPPING = {
" text-davinci-003 " : 4024 ,
" text-curie-001 " : 2024 ,
" text-babbage-001 " : 2024 ,
" text-ada-001 " : 2024 ,
" code-davinci-002 " : 7900 ,
" code-cushman-001 " : 2024 ,
}
@staticmethod
def get_max_tokens ( model : str ) - > int :
return Models . TOKEN_MAPPING . get ( model , 4024 )
class ImageSize :
LARGE = " 1024x1024 "
MEDIUM = " 512x512 "
SMALL = " 256x256 "
MEDIUM = " 512x512 "
LARGE = " 1024x1024 "
ALL_SIZES = [ SMALL , MEDIUM , LARGE ]
class ModelLimits :
MIN_TOKENS = 15
MAX_TOKENS = 4096
MIN_CONVERSATION_LENGTH = 1
MAX_CONVERSATION_LENGTH = 500
MIN_SUMMARIZE_THRESHOLD = 800
MAX_SUMMARIZE_THRESHOLD = 3500
MIN_NUM_IMAGES = 1
MAX_NUM_IMAGES = 4
MIN_NUM_STATIC_CONVERSATION_ITEMS = 5
MAX_NUM_STATIC_CONVERSATION_ITEMS = 20
MIN_NUM_CONVERSATION_LOOKBACK = 5
MAX_NUM_CONVERSATION_LOOKBACK = 15
MIN_TEMPERATURE = 0.0
MAX_TEMPERATURE = 2.0
MIN_TOP_P = 0.0
MAX_TOP_P = 1.0
MIN_PRESENCE_PENALTY = - 2.0
MAX_PRESENCE_PENALTY = 2.0
MIN_FREQUENCY_PENALTY = - 2.0
MAX_FREQUENCY_PENALTY = 2.0
MIN_BEST_OF = 1
MAX_BEST_OF = 3
MIN_PROMPT_MIN_LENGTH = 10
MAX_PROMPT_MIN_LENGTH = 4096
class Model :
def __init__ ( self , usage_service ) :
self . _mode = Mode . TEMPERATURE
self . _temp = 0.8 # Higher value means more random, lower value means more likely to be a coherent sentence
self . _top_p = 0.95 # 1 is equivalent to greedy sampling, 0.1 means that the model will only consider the top 10% of the probability distribution
self . _top_p = 1 # 1 is equivalent to greedy sampling, 0.1 means that the model will only consider the top 10% of the probability distribution
self . _max_tokens = 4000 # The maximum number of tokens the model can generate
self . _presence_penalty = (
0 # Penalize new tokens based on whether they appear in the text so far
@ -50,7 +123,7 @@ class Model:
self . _best_of = 1 # Number of responses to compare the loglikelihoods of
self . _prompt_min_length = 8
self . _max_conversation_length = 100
self . _model = Models . D AVINCI
self . _model = Models . D EFAULT
self . _low_usage_mode = False
self . usage_service = usage_service
self . DAVINCI_ROLES = [ " admin " , " Admin " , " GPT " , " gpt " ]
@ -94,11 +167,11 @@ class Model:
@num_static_conversation_items.setter
def num_static_conversation_items ( self , value ) :
value = int ( value )
if value < 3 :
raise ValueError ( " num_static_conversation_items must be >= 3 " )
if value > 20 :
if value < ModelLimits . MIN_NUM_STATIC_CONVERSATION_ITEMS :
raise ValueError ( f" Number of static conversation items must be >= { ModelLimits . MIN_NUM_STATIC_CONVERSATION_ITEMS } " )
if value > ModelLimits . MAX_NUM_STATIC_CONVERSATION_ITEMS :
raise ValueError (
" num_static_conversation_items must be <= 20 , this is to ensure reliability and reduce token wastage!"
f" Number of static conversation items must be <= { ModelLimits . MAX_NUM_STATIC_CONVERSATION_ITEMS } , this is to ensure reliability and reduce token wastage!"
)
self . _num_static_conversation_items = value
@ -109,11 +182,11 @@ class Model:
@num_conversation_lookback.setter
def num_conversation_lookback ( self , value ) :
value = int ( value )
if value < 3 :
raise ValueError ( " num_conversation_lookback must be >= 3 " )
if value > 15 :
if value < ModelLimits . MIN_NUM_CONVERSATION_LOOKBACK :
raise ValueError ( f" Number of conversations to look back on must be >= { ModelLimits . MIN_NUM_CONVERSATION_LOOKBACK } " )
if value > ModelLimits . MAX_NUM_CONVERSATION_LOOKBACK :
raise ValueError (
" num_conversation_lookback must be <= 15 , this is to ensure reliability and reduce token wastage!"
f" Number of conversations to look back on must be <= { ModelLimits . MIN_NUM_CONVERSATION_LOOKBACK } , this is to ensure reliability and reduce token wastage!"
)
self . _num_conversation_lookback = value
@ -128,7 +201,7 @@ class Model:
elif value . lower ( ) == " false " :
self . _welcome_message_enabled = False
else :
raise ValueError ( " Value must be either true or false!" )
raise ValueError ( " Value must be either ` true` or ` false` !" )
@property
def summarize_threshold ( self ) :
@ -137,9 +210,9 @@ class Model:
@summarize_threshold.setter
def summarize_threshold ( self , value ) :
value = int ( value )
if value < 800 or value > 4000 :
if value < ModelLimits . MIN_SUMMARIZE_THRESHOLD or value > ModelLimits . MAX_SUMMARIZE_THRESHOLD :
raise ValueError (
" Summarize threshold cannot be greater than 4000 or less than 800 !"
f" Summarize threshold should be a number between { ModelLimits . MIN_SUMMARIZE_THRESHOLD } and { ModelLimits . MAX_SUMMARIZE_THRESHOLD } !"
)
self . _summarize_threshold = value
@ -155,7 +228,7 @@ class Model:
elif value . lower ( ) == " false " :
value = False
else :
raise ValueError ( " Value must be either true or false!" )
raise ValueError ( " Value must be either ` true` or ` false` !" )
self . _summarize_conversations = value
@property
@ -164,11 +237,11 @@ class Model:
@image_size.setter
def image_size ( self , value ) :
if value in ImageSize . __dict__ . values ( ) :
if value in ImageSize . ALL_SIZES :
self . _image_size = value
else :
raise ValueError (
" Image size must be one of the following: SMALL(256x256), MEDIUM(512x512), LARGE(1024x1024) "
f " Image size must be one of the following: { ImageSize . ALL_SIZES } "
)
@property
@ -178,8 +251,8 @@ class Model:
@num_images.setter
def num_images ( self , value ) :
value = int ( value )
if value > 4 or value < = 0 :
raise ValueError ( " num_images must be less than 4 and at least 1. " )
if value < ModelLimits . MIN_NUM_IMAGES or value > ModelLimits . MAX_NUM_IMAGES :
raise ValueError ( f" Number of images to generate should be a number between { ModelLimits . MIN_NUM_IMAGES } and { ModelLimits . MAX_NUM_IMAGES } ! " )
self . _num_images = value
@property
@ -194,14 +267,14 @@ class Model:
elif value . lower ( ) == " false " :
value = False
else :
raise ValueError ( " Value must be either true or false!" )
raise ValueError ( " Value must be either ` true` or ` false` !" )
if value :
self . _model = Models . CURIE
self . _model = Models . LOW_USAGE_MODEL
self . max_tokens = 1900
self . model_max_tokens = 1000
else :
self . _model = Models . D AVINCI
self . _model = Models . D EFAULT
self . max_tokens = 4000
self . model_max_tokens = 4024
@ -211,12 +284,13 @@ class Model:
@model.setter
def model ( self , model ) :
if model not in [ Models . DAVINCI , Models . CURIE ] :
raise ValueError (
" Invalid model, must be text-davinci-003 or text-curie-001 "
)
if model not in Models . TEXT_MODELS :
raise ValueError ( f " Invalid model, must be one of: { Models . TEXT_MODELS } " )
self . _model = model
# Set the token count
self . _max_tokens = Models . get_max_tokens ( self . _model )
@property
def max_conversation_length ( self ) :
return self . _max_conversation_length
@ -224,11 +298,11 @@ class Model:
@max_conversation_length.setter
def max_conversation_length ( self , value ) :
value = int ( value )
if value < 1 :
raise ValueError ( " Max conversation length must be greater than 1 " )
if value > 500 :
if value < ModelLimits . MIN_CONVERSATION_LENGTH :
raise ValueError ( f " Max conversation length must be greater than { ModelLimits . MIN_CONVERSATION_LENGTH } " )
if value > ModelLimits . MAX_CONVERSATION_LENGTH :
raise ValueError (
" Max conversation length must be less than 500 , this will start using credits quick."
f " Max conversation length must be less than { ModelLimits . MIN_CONVERSATION_LENGTH } , this will start using credits quick."
)
self . _max_conversation_length = value
@ -238,14 +312,17 @@ class Model:
@mode.setter
def mode ( self , value ) :
if value not in [ Mode . TOP_P , Mode . TEMPERATURE ] :
raise ValueError ( " mode must be either ' top_p ' or ' temperature ' " )
if value not in Mode . ALL_MODES :
raise ValueError ( f " Mode must be one of: { Mode . ALL_MODES } " )
# Set the other mode to 1 (the default) so that it is not used
# See https://beta.openai.com/docs/api-reference/completions/create#completions/create-temperature
if value == Mode . TOP_P :
self . _top_p = 0.1
self . _temp = 0.7
self . _temp = 1
elif value == Mode . TEMPERATURE :
self . _top_p = 0.9
self . _temp = 0.6
self . _top_p = 1
else :
raise ValueError ( f " Unknown mode: { value } " )
self . _mode = value
@ -256,10 +333,9 @@ class Model:
@temp.setter
def temp ( self , value ) :
value = float ( value )
if value < 0 or value > 2 :
if value < ModelLimits . MIN_TEMPERATURE or value > ModelLimits . MAX_TEMPERATURE :
raise ValueError (
" temperature must be greater than 0 and less than 2, it is currently "
+ str ( value )
f " Temperature must be between { ModelLimits . MIN_TEMPERATURE } and { ModelLimits . MAX_TEMPERATURE } , it is currently: { value } "
)
self . _temp = value
@ -271,10 +347,9 @@ class Model:
@top_p.setter
def top_p ( self , value ) :
value = float ( value )
if value < 0 or value > 1 :
if value < ModelLimits . MIN_TOP_P or value > ModelLimits . MAX_TOP_P :
raise ValueError (
" top_p must be greater than 0 and less than 1, it is currently "
+ str ( value )
f " Top P must be between { ModelLimits . MIN_TOP_P } and { ModelLimits . MAX_TOP_P } , it is currently: { value } "
)
self . _top_p = value
@ -285,10 +360,9 @@ class Model:
@max_tokens.setter
def max_tokens ( self , value ) :
value = int ( value )
if value < 15 or value > 4096 :
if value < ModelLimits . MIN_TOKENS or value > ModelLimits . MAX_TOKENS :
raise ValueError (
" max_tokens must be greater than 15 and less than 4096, it is currently "
+ str ( value )
f " Max tokens must be between { ModelLimits . MIN_TOKENS } and { ModelLimits . MAX_TOKENS } , it is currently: { value } "
)
self . _max_tokens = value
@ -298,9 +372,10 @@ class Model:
@presence_penalty.setter
def presence_penalty ( self , value ) :
if int ( value ) < 0 :
value = float ( value )
if value < ModelLimits . MIN_PRESENCE_PENALTY or value > ModelLimits . MAX_PRESENCE_PENALTY :
raise ValueError (
" presence_penalty must be greater than 0, it is currently " + str ( value )
f" Presence penalty must be between { ModelLimits . MIN_PRESENCE_PENALTY } and { ModelLimits . MAX_PRESENCE_PENALTY } , it is currently: { value } "
)
self . _presence_penalty = value
@ -310,10 +385,10 @@ class Model:
@frequency_penalty.setter
def frequency_penalty ( self , value ) :
if int ( value ) < 0 :
value = float ( value )
if value < ModelLimits . MIN_FREQUENCY_PENALTY or value > ModelLimits . MAX_FREQUENCY_PENALTY :
raise ValueError (
" frequency_penalty must be greater than 0, it is currently "
+ str ( value )
f " Frequency penalty must be greater between { ModelLimits . MIN_FREQUENCY_PENALTY } and { ModelLimits . MAX_FREQUENCY_PENALTY } , it is currently: { value } "
)
self . _frequency_penalty = value
@ -324,10 +399,9 @@ class Model:
@best_of.setter
def best_of ( self , value ) :
value = int ( value )
if value < 1 or value > 3 :
if value < ModelLimits . MIN_BEST_OF or value > ModelLimits . MAX_BEST_OF :
raise ValueError (
" best_of must be greater than 0 and ideally less than 3 to save tokens, it is currently "
+ str ( value )
f " Best of must be between { ModelLimits . MIN_BEST_OF } and { ModelLimits . MAX_BEST_OF } , it is currently: { value } \n Note that increasing the value of this parameter will act as a multiplier on the number of tokens requested! "
)
self . _best_of = value
@ -338,10 +412,9 @@ class Model:
@prompt_min_length.setter
def prompt_min_length ( self , value ) :
value = int ( value )
if value < 10 or value > 4096 :
if value < ModelLimits . MIN_PROMPT_MIN_LENGTH or value > ModelLimits . MAX_PROMPT_MIN_LENGTH :
raise ValueError (
" prompt_min_length must be greater than 10 and less than 4096, it is currently "
+ str ( value )
f " Minimal prompt length must be between { ModelLimits . MIN_PROMPT_MIN_LENGTH } and { ModelLimits . MAX_PROMPT_MIN_LENGTH } , it is currently: { value } "
)
self . _prompt_min_length = value
@ -542,11 +615,10 @@ class Model:
# Validate that all the parameters are in a good state before we send the request
if len ( prompt ) < self . prompt_min_length :
raise ValueError (
" Prompt must be greater than 8 characters, it is currently "
+ str ( len ( prompt ) )
f " Prompt must be greater than { self . prompt_min_length } characters, it is currently: { len ( prompt ) } characters "
)
print ( " The prompt about to be sent is " + prompt )
print ( f " The prompt about to be sent is { prompt } " )
print (
f " Overrides -> temp: { temp_override } , top_p: { top_p_override } frequency: { frequency_penalty_override } , presence: { presence_penalty_override } "
)
@ -588,7 +660,7 @@ class Model:
async with aiohttp . ClientSession ( ) as session :
payload = {
" model " : Models . CURIE ,
" model " : Models . LOW_USAGE_MODEL ,
" prompt " : " test. " ,
" temperature " : 1 ,
" top_p " : 1 ,