166 lines
5.2 KiB
Python
166 lines
5.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
import logging
|
|
import threading
|
|
import time
|
|
from datetime import datetime
|
|
|
|
import openai
|
|
import requests
|
|
|
|
desired_models = ["gpt-3.5-turbo", "gpt-4", "gpt-4-32k"]
|
|
|
|
|
|
def list_models(api_key):
|
|
openai.api_key = api_key
|
|
models = openai.Model.list()
|
|
return [model.id for model in models['data']]
|
|
|
|
|
|
def filter_models(models):
|
|
return [model for model in models if model in desired_models]
|
|
|
|
|
|
def get_limits(api_key):
|
|
headers = {
|
|
"authorization": f"Bearer {api_key}",
|
|
"Referer": "https://platform.openai.com/account/usage",
|
|
}
|
|
response = requests.get("https://api.openai.com/dashboard/billing/subscription", headers=headers)
|
|
|
|
if response.status_code == 200:
|
|
return True, response.json()
|
|
else:
|
|
return False, response.text
|
|
|
|
|
|
key_test_lock = threading.Lock()
|
|
|
|
|
|
def try_complete(api_key):
|
|
with key_test_lock:
|
|
openai.api_key = api_key
|
|
response = openai.ChatCompletion.create(
|
|
model="gpt-3.5-turbo",
|
|
max_tokens=1,
|
|
messages=[{'role': 'user', 'content': ''}]
|
|
)
|
|
|
|
|
|
# def test_key(api_key):
|
|
# # with key_test_lock: # not 100% sure it's thread-safe
|
|
# openai.api_key = api_key
|
|
# try:
|
|
# response = openai.Completion.create(
|
|
# engine="gpt-3.5-turbo",
|
|
# prompt='Hello there!',
|
|
# max_tokens=100
|
|
# )
|
|
# print(response.choices[0].text.strip())
|
|
# return True
|
|
# except Exception as e:
|
|
# print(f"An error occurred: {e}")
|
|
# return False
|
|
|
|
|
|
def check_key(api_key, retry_count=3):
|
|
result = f"{api_key}\n"
|
|
has_gpt_4_32k = False
|
|
model_ids = []
|
|
errors = []
|
|
|
|
usage_and_limits_success, usage_and_limits = get_limits(api_key)
|
|
if not usage_and_limits_success:
|
|
return {
|
|
'key': api_key,
|
|
'has_gpt_4': None,
|
|
'has_gpt_4_32k': None,
|
|
'has_only_turbo': None,
|
|
'org_id': None,
|
|
'soft_limit_usd': None,
|
|
'hard_limit_usd': None,
|
|
'access_until': None, # .strftime('%Y-%m-%d %H:%M:%S'),
|
|
'plan': None,
|
|
'plan_id': None,
|
|
'address': None,
|
|
'errors': usage_and_limits
|
|
}
|
|
|
|
if usage_and_limits is None:
|
|
logging.error(f"Failed to get usage and limits for API key {api_key}")
|
|
return
|
|
plan = usage_and_limits.get('plan')
|
|
if plan is None:
|
|
plan_title = ''
|
|
plan_id = ''
|
|
else:
|
|
plan_title = plan.get('title', '')
|
|
plan_id = plan.get('id', '')
|
|
access_until = datetime.fromtimestamp(usage_and_limits['access_until'])
|
|
org_id = usage_and_limits.get('account_name', '')
|
|
billing_address = usage_and_limits.get('billing_address', {})
|
|
if billing_address is not None:
|
|
billing_country = billing_address.get('country', '')
|
|
billing_city = billing_address.get('city', '')
|
|
else:
|
|
billing_country = ''
|
|
billing_city = ''
|
|
is_canceled = usage_and_limits.get('canceled', False)
|
|
canceled_at_raw = usage_and_limits.get('canceled_at', '')
|
|
canceled_at = datetime.fromtimestamp(canceled_at_raw) if canceled_at_raw is not None else None
|
|
|
|
models = list_models(api_key)
|
|
filtered_models = filter_models(models)
|
|
|
|
if filtered_models:
|
|
for model_id in filtered_models:
|
|
result += f" - {model_id}\n"
|
|
model_ids.append(model_id)
|
|
else:
|
|
result += " No desired models available.\n"
|
|
|
|
has_gpt_4 = "gpt-4" in model_ids
|
|
has_gpt_4_32k = "gpt-4-32k" in model_ids
|
|
has_only_turbo = "gpt-3.5-turbo" in model_ids and not has_gpt_4
|
|
|
|
try:
|
|
for attempts in range(retry_count):
|
|
try:
|
|
try_complete(api_key)
|
|
break
|
|
except Exception as e:
|
|
error_message = str(e)
|
|
if "The server is overloaded or not ready yet" in error_message:
|
|
logging.info(f'Error encountered when generating a completion on attempt {attempts + 1}: {error_message}. Retrying...')
|
|
time.sleep(5)
|
|
continue
|
|
else:
|
|
raise e
|
|
except Exception as e:
|
|
error_message = str(e)
|
|
if "You exceeded your current quota" in error_message and is_canceled:
|
|
errors.append('You exceeded your current quota')
|
|
elif "You exceeded your current quota" in error_message and not is_canceled:
|
|
errors.append('This key has exceeded its current quota')
|
|
elif "Your account is not active" in error_message:
|
|
errors.append('Error: Your account is not active, please check your billing details on our website.')
|
|
else:
|
|
errors.append(error_message)
|
|
|
|
# api_key_works = test_key(api_key)
|
|
|
|
return {
|
|
'api_key': api_key,
|
|
# 'api_key_works': api_key_works,
|
|
'has_gpt_4': has_gpt_4,
|
|
'has_gpt_4_32k': has_gpt_4_32k,
|
|
'has_only_turbo': has_only_turbo,
|
|
'org_id': org_id,
|
|
'soft_limit_usd': usage_and_limits['soft_limit_usd'],
|
|
'hard_limit_usd': float(usage_and_limits['hard_limit_usd']),
|
|
'access_until': access_until, # .strftime('%Y-%m-%d %H:%M:%S'),
|
|
'plan': plan_title,
|
|
'plan_id': plan_id,
|
|
'address': f'{billing_country}, {billing_city}',
|
|
'errors': errors
|
|
}
|