Compare commits

...

3 commits

Author SHA1 Message Date
nsde f9edbf1bc0 Fixed the autocredits 2023-08-16 16:27:16 +02:00
nsde f6cd1f7aa2 Some fixes? 2023-08-16 15:06:16 +02:00
nsde 8c05fd9d87 Commented out rate-limiting etc. 2023-08-16 12:08:58 +02:00
10 changed files with 74 additions and 86 deletions

View file

@ -1,59 +0,0 @@
max-credits: 100001
max-credits-owner: 694201337
start-credits: 1000
costs:
other: 10
chat-models:
gpt-3: 10
gpt-4: 30
gpt-4-32k: 100
## Roles Explanation
# Bonuses: They are a multiplier for costs
# They work like: final_cost = cost * bonus
# Rate limits: Limit the requests of the user
# The rate limit is by how many seconds until a new request can be done.
## TODO: Setup proper rate limit settings for each role
## Current settings are:
## **NOT MEANT FOR PRODUCTION. DO NOT USE WITH THESE SETTINGS.**
roles:
owner:
bonus: 0.1
rate_limit:
other: 60
gpt-3: 60
gpt-4: 35
gpt-4-32k: 5
admin:
bonus: 0.3
rate_limit:
other: 60
gpt-3: 60
gpt-4: 30
gpt-4-32k: 4
helper:
bonus: 0.4
rate_limit:
other: 60
gpt-3: 60
gpt-4: 25
gpt-4-32k: 3
booster:
bonus: 0.5
rate_limit:
other: 60
gpt-3: 60
gpt-4: 20
gpt-4-32k: 2
default:
bonus: 0
rate_limit:
other: 60
gpt-3: 60
gpt-4: 15
gpt-4-32k: 1

19
api/config/credits.yml Normal file
View file

@ -0,0 +1,19 @@
max-credits: 100001
max-credits-owner: 694201337
start-credits: 1000
costs:
other: 10
chat-models:
gpt-3: 10
gpt-4: 30
gpt-4-32k: 100
# bonuses are multiplier for costs:
# final_cost = cost * bonus
bonuses:
owner: 0.1
admin: 0.3
helper: 0.4
booster: 0.5

View file

@ -21,7 +21,7 @@ UA_SIMPLIFY = {
conn = AsyncIOMotorClient(os.getenv('MONGO_URI')) conn = AsyncIOMotorClient(os.getenv('MONGO_URI'))
async def _get_collection(collection_name: str): async def _get_collection(collection_name: str):
return conn['nova-core'][collection_name] return conn[os.getenv('MONGO_NAME', 'nova-test')][collection_name]
async def replacer(text: str, dict_: dict) -> str: async def replacer(text: str, dict_: dict) -> str:
# This seems to exist for a very specific and dumb purpose :D # This seems to exist for a very specific and dumb purpose :D

View file

@ -26,7 +26,7 @@ class StatsManager:
self.conn = AsyncIOMotorClient(os.getenv('MONGO_URI')) self.conn = AsyncIOMotorClient(os.getenv('MONGO_URI'))
async def _get_collection(self, collection_name: str): async def _get_collection(self, collection_name: str):
return self.conn['nova-core'][collection_name] return self.conn[os.getenv('MONGO_NAME', 'nova-test')][collection_name]
async def add_date(self): async def add_date(self):
date = datetime.datetime.now(pytz.timezone('GMT')).strftime('%Y.%m.%d') date = datetime.datetime.now(pytz.timezone('GMT')).strftime('%Y.%m.%d')

View file

@ -9,7 +9,7 @@ from motor.motor_asyncio import AsyncIOMotorClient
load_dotenv() load_dotenv()
with open('config/config.yml', encoding='utf8') as f: with open('config/credits.yml', encoding='utf8') as f:
credits_config = yaml.safe_load(f) credits_config = yaml.safe_load(f)
## MONGODB Setup ## MONGODB Setup
@ -33,10 +33,10 @@ class UserManager:
self.conn = AsyncIOMotorClient(os.getenv('MONGO_URI')) self.conn = AsyncIOMotorClient(os.getenv('MONGO_URI'))
async def _get_collection(self, collection_name: str): async def _get_collection(self, collection_name: str):
return self.conn['nova-core'][collection_name] return self.conn[os.getenv('MONGO_NAME', 'nova-test')][collection_name]
async def get_all_users(self): async def get_all_users(self):
return self.conn['nova-core']['users'] return self.conn[os.getenv('MONGO_NAME', 'nova-test')]['users']
async def create(self, discord_id: str = '') -> dict: async def create(self, discord_id: str = '') -> dict:
chars = string.ascii_letters + string.digits chars = string.ascii_letters + string.digits

View file

@ -26,12 +26,12 @@ import yaml
load_dotenv() load_dotenv()
## Loads config which contains rate limits ## Loads config which contains rate limits
with open('config/config.yml', encoding='utf8') as f: with open('config/credits.yml', encoding='utf8') as f:
config = yaml.safe_load(f) config = yaml.safe_load(f)
## Where all rate limit requested data will be stored. ## Where all rate limit requested data will be stored.
# Rate limit data is **not persistent** (It will be deleted on server stop/restart). # Rate limit data is **not persistent** (It will be deleted on server stop/restart).
user_last_request_time = {} # user_last_request_time = {}
DEMO_PAYLOAD = { DEMO_PAYLOAD = {
'model': 'gpt-3.5-turbo', 'model': 'gpt-3.5-turbo',
@ -93,18 +93,18 @@ async def stream(
## Rate limits user. ## Rate limits user.
# If rate limit is exceeded, error code 429. Otherwise, lets the user pass but notes down # If rate limit is exceeded, error code 429. Otherwise, lets the user pass but notes down
# last request time for future requests. # last request time for future requests.
if user: # if user:
role = user.get('role', 'default') # role = user.get('role', 'default')
rate_limit = config['roles'][role]['rate_limit'].get(payload['model'], 10) # rate_limit = config['roles'][role]['rate_limit'].get(payload['model'], 10)
last_request_time = user_last_request_time.get(user['api_key']) # last_request_time = user_last_request_time.get(user['api_key'])
time_since_last_request = datetime.now() - last_request_time # time_since_last_request = datetime.datetime.now() - last_request_time
if time_since_last_request < datetime.timedelta(seconds=rate_limit): # if time_since_last_request < datetime.timedelta(seconds=rate_limit):
yield await errors.yield_error(429, "Rate limit exceeded', 'You are making requests too quickly. Please wait and try again later. Ask a administrator if you think this shouldn't happen. ") # yield await errors.yield_error(429, 'Rate limit exceeded', "You are making requests too quickly. Please wait and try again later. Ask a administrator if you think this shouldn't happen.")
return # return
else: # else:
user_last_request_time[user['_id']] = datetime.now() # user_last_request_time[user['_id']] = datetime.datetime.now()
## Setup managers ## Setup managers
db = UserManager() db = UserManager()
@ -169,7 +169,10 @@ async def stream(
headers=target_request.get('headers', {}), headers=target_request.get('headers', {}),
cookies=target_request.get('cookies'), cookies=target_request.get('cookies'),
ssl=False, ssl=False,
timeout=aiohttp.ClientTimeout(total=float(os.getenv('TRANSFER_TIMEOUT', '120'))), timeout=aiohttp.ClientTimeout(
connect=3.0,
total=float(os.getenv('TRANSFER_TIMEOUT', '120'))
),
) as response: ) as response:
if response.content_type == 'application/json': if response.content_type == 'application/json':
data = await response.json() data = await response.json()

View file

@ -16,8 +16,8 @@ load_dotenv()
models_list = json.load(open('models.json')) models_list = json.load(open('models.json'))
with open('config/config.yml', encoding='utf8') as f: with open('config/credits.yml', encoding='utf8') as f:
config = yaml.safe_load(f) credits_config = yaml.safe_load(f)
async def handle(incoming_request): async def handle(incoming_request):
""" """
@ -62,7 +62,7 @@ async def handle(incoming_request):
if path_contains_models: if path_contains_models:
return fastapi.responses.JSONResponse(content=models_list) return fastapi.responses.JSONResponse(content=models_list)
costs = config['costs'] costs = credits_config['costs']
cost = costs['other'] cost = costs['other']
if 'chat/completions' in path: if 'chat/completions' in path:
@ -77,7 +77,7 @@ async def handle(incoming_request):
if policy_violation: if policy_violation:
return await errors.error(400, f'The request contains content which violates this model\'s policies for "{policy_violation}".', 'We currently don\'t support any NSFW models.') return await errors.error(400, f'The request contains content which violates this model\'s policies for "{policy_violation}".', 'We currently don\'t support any NSFW models.')
role_cost_multiplier = config['roles'][user['role']]['bonus'] role_cost_multiplier = credits_config['bonuses'].get(user['role'], 1)
cost = round(cost * role_cost_multiplier) cost = round(cost * role_cost_multiplier)
if user['credits'] < cost: if user['credits'] < cost:

View file

@ -1,9 +1,15 @@
from users import UserManager import os
from dotenv import load_dotenv
load_dotenv()
async def get_all_users(client):
users = client[os.getenv('MONGO_NAME', 'nova-test')]['users']
return users
async def update_credits(pymongo_client, settings=None): async def update_credits(pymongo_client, settings=None):
manager = UserManager() users = await get_all_users(pymongo_client)
users = await manager.get_all_users(pymongo_client)
if not settings: if not settings:
users.update_many({}, {'$inc': {'credits': 2500}}) users.update_many({}, {'$inc': {'credits': 2500}})
@ -11,4 +17,8 @@ async def update_credits(pymongo_client, settings=None):
else: else:
for key, value in settings.items(): for key, value in settings.items():
users.update_many( users.update_many(
{'level': key}, {'$inc': {'credits': int(value)}}) {'level': key},
{'$inc':
{'credits': int(value)}
}
)

View file

@ -1 +1,13 @@
# Script to start the production server
# Copy files to production
cp -r * /home/nova-prod
# Copy env file to production
cp env/.prod.env /home/nova-prod/.env
# Change directory
cd /home/nova-prod
# Start screen
screen -S nova-api python run prod screen -S nova-api python run prod

View file

@ -69,7 +69,10 @@ def test_library():
return completion['choices'][0]['message']['content'] return completion['choices'][0]['message']['content']
def test_library_moderation(): def test_library_moderation():
try:
return closedai.Moderation.create('I wanna kill myself, I wanna kill myself; It\'s all I hear right now, it\'s all I hear right now') return closedai.Moderation.create('I wanna kill myself, I wanna kill myself; It\'s all I hear right now, it\'s all I hear right now')
except closedai.errors.InvalidRequestError as exc:
return True
def test_models(): def test_models():
response = httpx.get( response = httpx.get(