Merge pull request #120 from duckdoom4/remove-magic-values

Add missing models / Code cleanup
Kaveen Kumarasinghe 2 years ago committed by GitHub
commit e4e390c640
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,8 +5,9 @@ import re
import discord
from models.deepl_model import TranslationModel
from services.moderations_service import ModerationOptions
from services.usage_service import UsageService
from models.openai_model import Model
from models.openai_model import ImageSize, Model, ModelLimits, Models, Mode
from services.environment_service import EnvService
usage_service = UsageService(Path(os.environ.get("DATA_DIR", os.getcwd())))
@ -34,26 +35,27 @@ class Settings_autocompleter:
): # Behaves a bit weird if you go back and edit the parameter without typing in a new command
"""gets valid values for the value option"""
values = {
"max_conversation_length": [str(num) for num in range(1, 500, 2)],
"num_images": [str(num) for num in range(1, 4 + 1)],
"mode": ["temperature", "top_p"],
"model": ["text-davinci-003", "text-curie-001"],
"max_conversation_length": [str(num) for num in range(ModelLimits.MIN_CONVERSATION_LENGTH, ModelLimits.MAX_CONVERSATION_LENGTH + 1, 2)],
"num_images": [str(num) for num in range(ModelLimits.MIN_NUM_IMAGES, ModelLimits.MAX_NUM_IMAGES + 1)],
"mode": Mode.ALL_MODES,
"model": Models.TEXT_MODELS,
"low_usage_mode": ["True", "False"],
"image_size": ["256x256", "512x512", "1024x1024"],
"image_size": ImageSize.ALL_SIZES,
"summarize_conversation": ["True", "False"],
"welcome_message_enabled": ["True", "False"],
"num_static_conversation_items": [str(num) for num in range(5, 20 + 1)],
"num_conversation_lookback": [str(num) for num in range(5, 15 + 1)],
"summarize_threshold": [str(num) for num in range(800, 3500, 50)],
"num_static_conversation_items": [str(num) for num in range(ModelLimits.MIN_NUM_STATIC_CONVERSATION_ITEMS, ModelLimits.MAX_NUM_STATIC_CONVERSATION_ITEMS + 1)],
"num_conversation_lookback": [str(num) for num in range(ModelLimits.MIN_NUM_CONVERSATION_LOOKBACK, ModelLimits.MAX_NUM_CONVERSATION_LOOKBACK + 1)],
"summarize_threshold": [str(num) for num in range(ModelLimits.MIN_SUMMARIZE_THRESHOLD, ModelLimits.MAX_SUMMARIZE_THRESHOLD + 1, 50)],
"type": ["warn", "delete"],
}
for parameter in values:
if parameter == ctx.options["parameter"]:
options = values.get(ctx.options["parameter"], [])
if options:
return [
value
for value in values[ctx.options["parameter"]]
for value in options
if value.startswith(ctx.value.lower())
]
await ctx.interaction.response.defer() # defer so the autocomplete in int values doesn't error but rather just says not found
return []
@ -64,7 +66,7 @@ class Settings_autocompleter:
print(f"The value is {ctx.value}")
return [
value
for value in ["warn", "delete", "reset"]
for value in ModerationOptions.OPTIONS
if value.startswith(ctx.value.lower())
]

@ -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.DAVINCI
self._model = Models.DEFAULT
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.DAVINCI
self._model = Models.DEFAULT
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}\nNote 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,

@ -19,6 +19,13 @@ class ModerationResult:
DELETE = "delete"
NONE = "none"
class ModerationOptions:
WARN = "warn"
DELETE = "delete"
RESET = "reset"
OPTIONS = [WARN, DELETE, RESET]
class ThresholdSet:
def __init__(self, h_t, hv_t, sh_t, s_t, sm_t, v_t, vg_t):

Loading…
Cancel
Save