diff --git a/APIKey.py b/APIKey.py index 9f462b9..47fad1f 100644 --- a/APIKey.py +++ b/APIKey.py @@ -14,11 +14,15 @@ class APIKey: self.organizations = [] self.rpm = 0 self.tier = "" + self.has_special_models = False + self.the_one = False elif provider == Provider.ANTHROPIC: self.pozzed = False self.rate_limited = False self.has_quota = True + self.tier = "" + self.remaining_tokens = 0 elif provider == Provider.AI21: self.trial_elapsed = False @@ -57,6 +61,12 @@ class APIKey: self.limit_reached = False self.bought_credits = False + def clone(self): + cloned_key = APIKey(self.provider, self.api_key) + cloned_key.__dict__ = self.__dict__.copy() + return cloned_key + + class Provider(Enum): OPENAI = 1, ANTHROPIC = 2 diff --git a/Anthropic.py b/Anthropic.py index f8ffa79..6015676 100644 --- a/Anthropic.py +++ b/Anthropic.py @@ -27,11 +27,31 @@ async def check_anthropic(key: APIKey, session): key.has_quota = False return True + try: + key.remaining_tokens = int(response.headers['anthropic-ratelimit-tokens-remaining']) + tokenlimit = int(response.headers['anthropic-ratelimit-tokens-limit']) + ratelimit = int(response.headers['anthropic-ratelimit-requests-limit']) + key.tier = get_tier(tokenlimit, ratelimit) + except KeyError: + key.tier = "Evaluation Tier" + key.remaining_tokens = 2500000 + key.pozzed = any(message in text for message in pozzed_messages) return True +def get_tier(tokenlimit, ratelimit): + tier_mapping = { + (25000, 5): "Free", + (50000, 50): "Tier 1", + (100000, 1000): "Tier 2", + (200000, 2000): "Tier 3", + (400000, 4000): "Tier 4" + } + return tier_mapping.get((tokenlimit, ratelimit), "Scale Tier") + + def pretty_print_anthropic_keys(keys): print('-' * 90) print(f'Validated {len(keys)} working Anthropic keys:') @@ -42,8 +62,16 @@ def pretty_print_anthropic_keys(keys): rate_limited = sum(key.rate_limited for key in keys_with_quota) print(f'\nTotal keys with quota: {len(keys_with_quota)} (pozzed: {pozzed}, unpozzed: {len(keys_with_quota) - pozzed - rate_limited}, unsure/rate limited: {rate_limited})') + keys_by_tier = {} for key in keys_with_quota: - print(f'{key.api_key}' + (' | pozzed' if key.pozzed else "") + (' | rate limited' if key.rate_limited else "")) + if key.tier not in keys_by_tier: + keys_by_tier[key.tier] = [] + keys_by_tier[key.tier].append(key) + + for tier, keys_in_tier in keys_by_tier.items(): + print(f'\n{len(keys_in_tier)} keys found in {tier}:') + for key in keys_in_tier: + print(f'{key.api_key}' + (' | pozzed' if key.pozzed else "") + (' | rate limited' if key.rate_limited else "")) print(f'\nTotal keys without quota: {len(keys_without_quota)}') for key in keys_without_quota: diff --git a/OpenAI.py b/OpenAI.py index 88e26f5..93f1103 100644 --- a/OpenAI.py +++ b/OpenAI.py @@ -6,14 +6,21 @@ oai_t1_rpm_limits = {"gpt-3.5-turbo": 3500, "gpt-4": 500, "gpt-4-32k": 20} oai_tiers = {40000: 'Free', 60000: 'Tier1', 80000: 'Tier2', 160000: 'Tier3', 1000000: 'Tier4', 2000000: 'Tier5'} -async def get_oai_model(key: APIKey, session, retries): +async def get_oai_model(key: APIKey, session, retries, org=None): for _ in range(retries): - async with session.get(f'{oai_api_url}/models', headers={'Authorization': f'Bearer {key.api_key}'}) as response: + headers = {'Authorization': f'Bearer {key.api_key}'} + if org is not None: + headers['OpenAI-Organization'] = org + async with session.get(f'{oai_api_url}/models', headers=headers) as response: if response.status == 200: data = await response.json() models = data["data"] top_model = "gpt-3.5-turbo" for model in models: + if "ft:" in model["id"]: + key.has_special_models = True + if model["id"] == "gpt-4-base": + key.the_one = True if model["id"] == "gpt-4-32k": top_model = model["id"] break @@ -26,12 +33,13 @@ async def get_oai_model(key: APIKey, session, retries): await asyncio.sleep(0.5) -async def get_oai_key_attribs(key: APIKey, session, retries): +async def get_oai_key_attribs(key: APIKey, session, retries, org=None): chat_object = {"model": f'{key.model}', "messages": [{"role": "user", "content": ""}], "max_tokens": 0} for _ in range(retries): - async with session.post(f'{oai_api_url}/chat/completions', - headers={'Authorization': f'Bearer {key.api_key}', 'accept': 'application/json'}, - json=chat_object) as response: + headers = {'Authorization': f'Bearer {key.api_key}', 'accept': 'application/json'} + if org is not None: + headers['OpenAI-Organization'] = org + async with session.post(f'{oai_api_url}/chat/completions', headers=headers, json=chat_object) as response: if response.status in [400, 429]: data = await response.json() message = data["error"]["type"] @@ -57,14 +65,15 @@ async def get_oai_key_attribs(key: APIKey, session, retries): # this will weed out fake t4/t5 keys reporting a 10k rpm limit, those keys would have requested to have their rpm increased -async def get_oai_key_tier(key: APIKey, session, retries): +async def get_oai_key_tier(key: APIKey, session, retries, org=None): if key.trial: return 'Free' chat_object = {"model": f'gpt-3.5-turbo', "messages": [{"role": "user", "content": ""}], "max_tokens": 0} for _ in range(retries): - async with session.post(f'{oai_api_url}/chat/completions', - headers={'Authorization': f'Bearer {key.api_key}', 'accept': 'application/json'}, - json=chat_object) as response: + headers = {'Authorization': f'Bearer {key.api_key}', 'accept': 'application/json'} + if org is not None: + headers['OpenAI-Organization'] = org + async with session.post(f'{oai_api_url}/chat/completions', headers=headers, json=chat_object) as response: if response.status in [400, 429]: try: return oai_tiers[int(response.headers.get("x-ratelimit-limit-tokens"))] @@ -94,6 +103,22 @@ async def get_oai_org(key: APIKey, session, retries): await asyncio.sleep(0.5) +async def clone_key(key: APIKey, session, retries): + cloned_keys = set() + if len(key.organizations) <= 1: + return False + for org in key.organizations: + if org == key.default_org: + continue + new_key = key.clone() + new_key.default_org = org + results = await asyncio.gather(get_oai_model(new_key, session, retries, org), get_oai_key_attribs(new_key, session, retries, org)) + model_result, attribs_result = results + if model_result is not None and attribs_result is not None: + cloned_keys.add(new_key) + return cloned_keys + + def check_manual_increase(key: APIKey): if key.model == 'gpt-3.5-turbo' and key.rpm > 3500: return True @@ -106,7 +131,7 @@ def check_manual_increase(key: APIKey): return False -def pretty_print_oai_keys(keys): +def pretty_print_oai_keys(keys, cloned_keys): print('-' * 90) org_count = 0 quota_count = 0 @@ -162,13 +187,15 @@ def pretty_print_oai_keys(keys): + (f" | other orgs - {key.organizations}" if len(key.organizations) > 1 else "") + f" | {key.rpm} RPM" + (f" - {key.tier}" if key.tier else "") + (" (RPM increased via request)" if check_manual_increase(key) else "") - + (f" | TRIAL KEY" if key.trial else "")) + + (f" | TRIAL KEY" if key.trial else "") + + (f" | key has finetuned models" if key.has_special_models else "")) print(f'\nValidated {len(key_groups["gpt-4"]["no_quota"])} gpt-4 keys with no quota:') for key in key_groups["gpt-4"]["no_quota"]: print(f"{key.api_key}" + (f" | default org - {key.default_org}" if key.default_org else "") - + (f" | other orgs - {key.organizations}" if len(key.organizations) > 1 else "")) + + (f" | other orgs - {key.organizations}" if len(key.organizations) > 1 else "") + + (f" | key has finetuned models" if key.has_special_models else "")) print(f'\nValidated {len(key_groups["gpt-4-32k"]["has_quota"])} gpt-4-32k keys with quota:') for key in key_groups["gpt-4-32k"]["has_quota"]: @@ -177,12 +204,18 @@ def pretty_print_oai_keys(keys): + (f" | other orgs - {key.organizations}" if len(key.organizations) > 1 else "") + f" | {key.rpm} RPM" + (f" - {key.tier}" if key.tier else "") + (" (RPM increased via request)" if check_manual_increase(key) else "") - + (f" | TRIAL KEY" if key.trial else "")) + + (f" | TRIAL KEY" if key.trial else "") + + (f" | key has finetuned models" if key.has_special_models else "") + + (f" | !!!god key!!!" if key.the_one else "")) print(f'\nValidated {len(key_groups["gpt-4-32k"]["no_quota"])} gpt-4-32k keys with no quota:') for key in key_groups["gpt-4-32k"]["no_quota"]: print(f"{key.api_key}" + (f" | default org - {key.default_org}" if key.default_org else "") - + (f" | other orgs - {key.organizations}" if len(key.organizations) > 1 else "")) + + (f" | other orgs - {key.organizations}" if len(key.organizations) > 1 else "") + + (f" | key has finetuned models" if key.has_special_models else "") + + (f" | !!!god key!!!" if key.the_one else "")) + if cloned_keys: + print(f'\n--- Cloned {len(cloned_keys)} keys due to finding alternative orgs that could prompt ---') print(f'\n--- Total Valid OpenAI Keys: {len(keys)} ({quota_count} in quota, {no_quota_count} no quota, {org_count} orgs, {t5_count} Tier5) ---\n') diff --git a/main.py b/main.py index 6bc2fb6..0795718 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,6 @@ from Anthropic import check_anthropic, pretty_print_anthropic_keys from IO import IO -from OpenAI import get_oai_model, get_oai_key_attribs, get_oai_org, pretty_print_oai_keys +from OpenAI import get_oai_model, get_oai_key_attribs, get_oai_org, pretty_print_oai_keys, clone_key from AI21 import check_ai21, pretty_print_ai21_keys from MakerSuite import check_makersuite, pretty_print_makersuite_keys from AWS import check_aws, pretty_print_aws_keys @@ -49,6 +49,8 @@ else: inputted_keys.add(current_line.strip().split()[0].split(",")[0]) +# hold on let me land +cloned_keys = None async def validate_openai(key: APIKey, sem): retries = 10 async with sem, aiohttp.ClientSession() as session: @@ -62,6 +64,11 @@ async def validate_openai(key: APIKey, sem): return IO.conditional_print(f"OpenAI key '{key.api_key}' is valid", args.verbose) api_keys.add(key) + global cloned_keys + cloned_keys = await clone_key(key, session, retries) + if cloned_keys: + IO.conditional_print(f"Cloned OpenAI key '{key.api_key}'", args.verbose) + api_keys.update(cloned_keys) async def validate_anthropic(key: APIKey, retry_count, sem): @@ -232,7 +239,8 @@ def get_invalid_keys(valid_oai_keys, valid_anthropic_keys, valid_ai21_keys, vali valid_openrouter_keys_set = set([key.api_key for key in valid_openrouter_keys]) invalid_keys = inputted_keys - valid_oai_keys_set - valid_anthropic_keys_set - valid_ai21_keys_set - valid_makersuite_keys_set - valid_aws_keys_set - valid_azure_keys_set - valid_vertexai_keys_set - valid_mistral_keys_set - valid_openrouter_keys_set - if len(invalid_keys) < 1: + invalid_keys_len = len(invalid_keys) + len(cloned_keys) if cloned_keys else len(invalid_keys) + if invalid_keys_len < 1: return print('\nInvalid Keys:') for key in invalid_keys: @@ -276,14 +284,15 @@ def output_keys(): sys.stdout = IO(output_filename) if not args.proxyoutput: + invalid_keys = len(inputted_keys) - len(api_keys) + len(cloned_keys) if cloned_keys else len(inputted_keys) - len(api_keys) print("#" * 90) print(f"Key snapshot from {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print("#" * 90) - print(f'\n--- Checked {len(inputted_keys)} keys | {len(inputted_keys) - len(api_keys)} were invalid ---') + print(f'\n--- Checked {len(inputted_keys)} keys | {invalid_keys} were invalid ---') get_invalid_keys(valid_oai_keys, valid_anthropic_keys, valid_ai21_keys, valid_makersuite_keys, valid_aws_keys, valid_azure_keys, valid_vertexai_keys, valid_mistral_keys, valid_openrouter_keys) print() if valid_oai_keys: - pretty_print_oai_keys(valid_oai_keys) + pretty_print_oai_keys(valid_oai_keys, cloned_keys) if valid_anthropic_keys: pretty_print_anthropic_keys(valid_anthropic_keys) if valid_ai21_keys: