Update app.py
Browse files
app.py
CHANGED
@@ -1,17 +1,18 @@
|
|
1 |
-
|
2 |
-
|
3 |
import asyncio
|
4 |
import gradio as gr
|
5 |
import requests
|
6 |
import re
|
|
|
7 |
|
|
|
|
|
8 |
from api_usage import (
|
9 |
get_subscription,
|
10 |
check_key_availability,
|
11 |
get_orgs_me,
|
12 |
check_key_ant_availability,
|
13 |
check_ant_rate_limit,
|
14 |
-
check_key_gemini_availability,
|
15 |
check_key_azure_availability,
|
16 |
get_azure_status,
|
17 |
get_azure_deploy,
|
@@ -31,9 +32,9 @@ from api_usage import (
|
|
31 |
)
|
32 |
|
33 |
# βββββββββββββββββββββββββββββββββββββββββ
|
34 |
-
# Key-specific helper functions (μλ³Έ μ μ§)
|
35 |
# βββββββββββββββββββββββββββββββββββββββββ
|
36 |
-
def get_key_oai_info(key):
|
37 |
session = requests.Session()
|
38 |
status, org_data = check_key_availability(session, key)
|
39 |
|
@@ -61,25 +62,25 @@ def get_key_oai_info(key):
|
|
61 |
org_data = orgs_me
|
62 |
|
63 |
subscription_info = get_subscription(key, session, org_data)
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
return info_dict
|
80 |
|
81 |
|
82 |
-
async def get_key_ant_info(key, rate_limit, claude_model):
|
83 |
key_avai = await check_key_ant_availability(key, claude_model)
|
84 |
info_dict = {
|
85 |
"key_type": "Anthropic Claude",
|
@@ -111,18 +112,20 @@ async def get_key_ant_info(key, rate_limit, claude_model):
|
|
111 |
return info_dict
|
112 |
|
113 |
|
114 |
-
|
115 |
-
|
|
|
|
|
116 |
info_dict = {
|
117 |
-
"key": key,
|
118 |
"key_availability": key_avai[0],
|
119 |
"status": key_avai[1],
|
120 |
-
#"models": key_avai[2],
|
121 |
}
|
122 |
return info_dict
|
123 |
|
124 |
|
125 |
-
def get_key_azure_info(endpoint, api_key):
|
126 |
key_avai = check_key_azure_availability(endpoint, api_key)
|
127 |
info_dict = {
|
128 |
"key_type": "Microsoft Azure OpenAI",
|
@@ -137,18 +140,20 @@ def get_key_azure_info(endpoint, api_key):
|
|
137 |
}
|
138 |
if key_avai[0]:
|
139 |
azure_deploy = get_azure_deploy(endpoint, api_key)
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
|
|
|
|
146 |
info_dict["models"] = key_avai[1]
|
147 |
-
info_dict["deployments"] = azure_deploy
|
148 |
return info_dict
|
149 |
|
150 |
|
151 |
-
def get_key_mistral_info(key):
|
152 |
key_avai = check_key_mistral_availability(key)
|
153 |
info_dict = {
|
154 |
"key_type": "Mistral AI",
|
@@ -159,14 +164,15 @@ def get_key_mistral_info(key):
|
|
159 |
}
|
160 |
if key_avai:
|
161 |
quota_info = check_mistral_quota(key)
|
162 |
-
|
163 |
-
|
164 |
-
|
|
|
165 |
info_dict["models"] = key_avai
|
166 |
return info_dict
|
167 |
|
168 |
|
169 |
-
def get_key_replicate_info(key):
|
170 |
key_avai = check_key_replicate_availability(key)
|
171 |
info_dict = {
|
172 |
"key_type": "Replicate",
|
@@ -176,15 +182,15 @@ def get_key_replicate_info(key):
|
|
176 |
"has_quota": "",
|
177 |
"hardware_available": "",
|
178 |
}
|
179 |
-
if key_avai[0]:
|
180 |
-
info_dict["account_name"] = key_avai[1]
|
181 |
-
info_dict["type"] = key_avai[1]
|
182 |
info_dict["has_quota"] = key_avai[2]
|
183 |
info_dict["hardware_available"] = key_avai[3]
|
184 |
return info_dict
|
185 |
|
186 |
|
187 |
-
async def get_key_aws_info(key):
|
188 |
key_avai = await check_key_aws_availability(key)
|
189 |
info_dict = {
|
190 |
"key_type": "Amazon AWS Claude",
|
@@ -198,7 +204,7 @@ async def get_key_aws_info(key):
|
|
198 |
"aws_bedrock_full_access": "",
|
199 |
"enabled_region": "",
|
200 |
"models_usage": "",
|
201 |
-
"cost_and_usage": key_avai[1],
|
202 |
}
|
203 |
if key_avai[0]:
|
204 |
info_dict["username"] = key_avai[1]
|
@@ -214,7 +220,7 @@ async def get_key_aws_info(key):
|
|
214 |
return info_dict
|
215 |
|
216 |
|
217 |
-
def get_key_openrouter_info(key):
|
218 |
key_avai = check_key_or_availability(key)
|
219 |
info_dict = {
|
220 |
"key_type": "OpenRouter",
|
@@ -229,25 +235,41 @@ def get_key_openrouter_info(key):
|
|
229 |
"sonnet_per_request_tokens_limit": "",
|
230 |
"opus_per_request_tokens_limit": "",
|
231 |
}
|
232 |
-
if key_avai[0]:
|
233 |
models_info = check_key_or_limits(key)
|
234 |
-
info_dict["is_free_tier"] = key_avai[1]
|
235 |
-
info_dict["limit"] = key_avai[1]
|
236 |
-
info_dict["limit_remaining"] = key_avai[1]
|
237 |
-
|
238 |
-
info_dict["
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
info_dict["usage"] = key_avai[1]
|
247 |
return info_dict
|
248 |
|
249 |
|
250 |
-
async def get_key_gcp_info(key, type):
|
251 |
key_avai = await check_gcp_anthropic(key, type)
|
252 |
info_dict = {
|
253 |
"key_type": "Vertex AI (GCP)",
|
@@ -257,12 +279,12 @@ async def get_key_gcp_info(key, type):
|
|
257 |
}
|
258 |
if key_avai[0]:
|
259 |
info_dict["enabled_region"] = key_avai[2]
|
260 |
-
|
261 |
info_dict["status"] = key_avai[1]
|
262 |
return info_dict
|
263 |
|
264 |
|
265 |
-
def get_key_groq_info(key):
|
266 |
key_avai = check_groq_status(key)
|
267 |
info_dict = {
|
268 |
"key_type": "Groq",
|
@@ -272,7 +294,7 @@ def get_key_groq_info(key):
|
|
272 |
return info_dict
|
273 |
|
274 |
|
275 |
-
def get_key_nai_info(key):
|
276 |
key_avai = check_nai_status(key)
|
277 |
info_dict = {
|
278 |
"key_type": "NovelAI",
|
@@ -282,18 +304,18 @@ def get_key_nai_info(key):
|
|
282 |
return info_dict
|
283 |
|
284 |
|
285 |
-
def get_key_elevenlabs_info(key):
|
286 |
key_avai = check_elevenlabs_status(key)
|
287 |
info_dict = {
|
288 |
"key_type": "ElevenLabs",
|
289 |
"key_availability": key_avai[0],
|
290 |
-
"user_info": key_avai[1],
|
291 |
-
"voices_info": key_avai[2],
|
292 |
}
|
293 |
return info_dict
|
294 |
|
295 |
|
296 |
-
def get_key_xai_info(key):
|
297 |
key_avai = check_xai_status(key)
|
298 |
info_dict = {
|
299 |
"key_type": "xAI Grok",
|
@@ -302,12 +324,12 @@ def get_key_xai_info(key):
|
|
302 |
"models": "",
|
303 |
}
|
304 |
if key_avai[0]:
|
305 |
-
info_dict["key_status"] = key_avai[1]
|
306 |
-
info_dict["models"] = key_avai[2]
|
307 |
return info_dict
|
308 |
|
309 |
|
310 |
-
def get_key_stability_info(key):
|
311 |
key_avai = check_stability_status(key)
|
312 |
info_dict = {
|
313 |
"key_type": "Stability AI",
|
@@ -317,149 +339,202 @@ def get_key_stability_info(key):
|
|
317 |
"models": "",
|
318 |
}
|
319 |
if key_avai[0]:
|
320 |
-
info_dict["account_info"] = key_avai[1]
|
321 |
-
info_dict["credits"] = key_avai[2]
|
322 |
-
info_dict["models"] = key_avai[3]
|
323 |
return info_dict
|
324 |
|
325 |
|
326 |
-
def get_key_deepseek_info(key):
|
327 |
key_avai = check_deepseek_status(key)
|
328 |
info_dict = {
|
329 |
-
"key_type": "
|
330 |
"key_availability": key_avai[0],
|
331 |
"balance": "",
|
332 |
"models": "",
|
333 |
}
|
334 |
if key_avai[0]:
|
335 |
-
info_dict["models"] = key_avai[1]
|
336 |
-
info_dict["balance"] = key_avai[2]
|
337 |
return info_dict
|
338 |
|
339 |
|
340 |
-
def not_supported(key):
|
341 |
return {
|
342 |
"key_type": "Not supported",
|
343 |
-
"
|
|
|
344 |
}
|
345 |
|
346 |
|
347 |
# βββββββββββββββββββββββββββββββββββββββββ
|
348 |
-
#
|
349 |
# βββββββββββββββββββββββββββββββββββββββββ
|
350 |
-
async def process_single_key(key: str, rate_limit: bool, claude_model: str) ->
|
351 |
-
"""μ£Όμ΄μ§ key νλλ₯Ό λΆμν΄ μ 보 dict λ°ν."""
|
352 |
_key = key.strip()
|
353 |
|
|
|
|
|
|
|
354 |
# OpenRouter
|
355 |
if re.match(re.compile(r"sk-or-v1-[a-z0-9]{64}"), _key):
|
356 |
-
|
|
|
357 |
|
358 |
# Anthropic Claude
|
359 |
-
if re.match(re.compile(r"sk-ant-api03-[a-zA-Z0-9\-_]{93}AA"), _key) or
|
360 |
-
|
361 |
-
|
362 |
-
|
|
|
363 |
|
364 |
# Stability
|
365 |
if re.match(re.compile(r"sk-[a-zA-Z0-9]{48}"), _key) and len(_key) == 51 and "T3BlbkFJ" not in _key:
|
366 |
-
|
|
|
367 |
|
368 |
# Deepseek
|
369 |
if re.match(re.compile(r"sk-[a-f0-9]{32}"), _key):
|
370 |
-
|
|
|
371 |
|
372 |
-
# OpenAI
|
373 |
if _key.startswith("sk-"):
|
374 |
-
|
|
|
375 |
|
376 |
-
# Google Gemini
|
377 |
if _key.startswith("AIzaSy"):
|
378 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
379 |
|
380 |
# NovelAI
|
381 |
if _key.startswith("pst-"):
|
382 |
-
|
|
|
383 |
|
384 |
# Replicate
|
385 |
if (_key.startswith("r8_") and len(_key) == 40) or (_key.islower() and len(_key) == 40):
|
386 |
-
|
|
|
387 |
|
388 |
# xAI
|
389 |
if _key.startswith("xai-"):
|
390 |
-
|
|
|
391 |
|
392 |
# Azure endpoint: "name:key"
|
393 |
-
if len(_key.split(":")) == 2
|
394 |
-
|
395 |
-
|
|
|
|
|
|
|
|
|
396 |
|
397 |
# Azure endpoint: "https://xxx.openai.azure.com;key"
|
398 |
-
if "openai.azure.com" in _key.split(";")[0]:
|
399 |
-
endpoint, api_key = _key.split(";")
|
400 |
-
|
|
|
401 |
|
402 |
# AWS
|
403 |
-
if _key.startswith("AKIA") and len(_key.split(":")[0]) == 20 and _key.split(":")[0].isupper():
|
404 |
-
|
|
|
405 |
|
406 |
# ElevenLabs
|
407 |
-
if re.
|
408 |
-
|
|
|
409 |
|
410 |
# Mistral
|
411 |
-
if re.
|
412 |
-
|
|
|
413 |
|
414 |
# Groq
|
415 |
if re.match(re.compile(r"gsk_[a-zA-Z0-9]{20}WGdyb3FY[a-zA-Z0-9]{24}"), _key):
|
416 |
-
|
|
|
417 |
|
418 |
# GCP - refresh token
|
419 |
-
if re.match(re.compile(r"[\w\-]+:[\w\-@\.]
|
420 |
-
|
|
|
|
|
|
|
421 |
|
422 |
# GCP - service account
|
423 |
if re.match(re.compile(r"[\w\-]+:[\w\-@\.]+:.+\\n"), _key):
|
424 |
-
|
|
|
|
|
|
|
425 |
|
426 |
# Not supported
|
427 |
-
|
|
|
|
|
428 |
|
429 |
|
430 |
# βββββββββββββββββββββββββββββββββββββββββ
|
431 |
-
# μ¬λ¬ key λΉλκΈ° μ²λ¦¬ ν¨μ
|
432 |
# βββββββββββββββββββββββββββββββββββββββββ
|
433 |
-
async def sort_keys(text: str, rate_limit: bool, claude_model: str):
|
434 |
-
"""ν
μ€νΈ λ°μ€μ μ
λ ₯λ μ¬λ¬ ν€λ₯Ό μ€ λ¨μλ‘
|
435 |
keys = [k.strip() for k in text.splitlines() if k.strip()]
|
|
|
|
|
|
|
436 |
tasks = [process_single_key(k, rate_limit, claude_model) for k in keys]
|
437 |
results = await asyncio.gather(*tasks)
|
438 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
439 |
|
440 |
|
441 |
# βββββββββββββββββββββββββββββββββββββββββ
|
442 |
# UI util
|
443 |
# βββββββββββββββββββββββββββββββββββββββββ
|
444 |
-
def clear_inputs(
|
445 |
-
return ""
|
446 |
|
447 |
|
448 |
# βββββββββββββββββββββββββββββββββββββββββ
|
449 |
-
# Gradio UI
|
450 |
# βββββββββββββββββββββββββββββββββββββββββ
|
451 |
with gr.Blocks() as demo:
|
452 |
gr.Markdown(
|
453 |
"""
|
454 |
-
#
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
|
|
463 |
"""
|
464 |
)
|
465 |
|
@@ -468,38 +543,54 @@ GCP format:
|
|
468 |
"claude-3-sonnet-20240229",
|
469 |
"claude-3-opus-20240229",
|
470 |
"claude-3-5-sonnet-20240620",
|
471 |
-
"claude-3-5-sonnet-20241022",
|
472 |
-
"claude-3-5-haiku-20241022",
|
473 |
]
|
474 |
|
475 |
with gr.Row():
|
476 |
-
with gr.Column():
|
477 |
key_box = gr.Textbox(
|
478 |
lines=5,
|
479 |
max_lines=20,
|
480 |
-
label="API Key(s)
|
481 |
-
placeholder="
|
482 |
-
)
|
483 |
-
claude_model = gr.Dropdown(
|
484 |
-
claude_options,
|
485 |
-
value="claude-3-haiku-20240307",
|
486 |
-
label="Claude API model (filter/concurrent checkμ©)",
|
487 |
)
|
488 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
489 |
|
490 |
with gr.Row():
|
491 |
-
clear_button = gr.Button("Clear")
|
492 |
-
submit_button = gr.Button("
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
493 |
|
494 |
-
|
495 |
-
|
|
|
|
|
|
|
|
|
496 |
|
497 |
-
|
498 |
submit_button.click(
|
499 |
fn=sort_keys,
|
500 |
inputs=[key_box, rate_limit, claude_model],
|
501 |
-
outputs=[info],
|
502 |
api_name="sort_keys",
|
503 |
)
|
504 |
|
|
|
505 |
demo.launch()
|
|
|
|
|
|
|
1 |
import asyncio
|
2 |
import gradio as gr
|
3 |
import requests
|
4 |
import re
|
5 |
+
from typing import List, Dict, Tuple, Any # νμ
ννΈ μΆκ°
|
6 |
|
7 |
+
# api_usage λͺ¨λμ μ¬μ©μμ νκ²½μ λ§κ² μ‘΄μ¬νλ€κ³ κ°μ ν©λλ€.
|
8 |
+
# νμν ν¨μλ€μ μν¬νΈ (μ€μ μ¬μ© μ ν΄λΉ λͺ¨λ νμ)
|
9 |
from api_usage import (
|
10 |
get_subscription,
|
11 |
check_key_availability,
|
12 |
get_orgs_me,
|
13 |
check_key_ant_availability,
|
14 |
check_ant_rate_limit,
|
15 |
+
check_key_gemini_availability, # μ΄ ν¨μλ (bool, str) ννμ λ°ννλ€κ³ κ°μ
|
16 |
check_key_azure_availability,
|
17 |
get_azure_status,
|
18 |
get_azure_deploy,
|
|
|
32 |
)
|
33 |
|
34 |
# βββββββββββββββββββββββββββββββββββββββββ
|
35 |
+
# Key-specific helper functions (μλ³Έ μ μ§ - Gemini ν¬ν¨)
|
36 |
# βββββββββββββββββββββββββββββββββββββββββ
|
37 |
+
def get_key_oai_info(key: str) -> Dict[str, Any]:
|
38 |
session = requests.Session()
|
39 |
status, org_data = check_key_availability(session, key)
|
40 |
|
|
|
62 |
org_data = orgs_me
|
63 |
|
64 |
subscription_info = get_subscription(key, session, org_data)
|
65 |
+
if subscription_info:
|
66 |
+
info_dict.update(
|
67 |
+
{
|
68 |
+
"gpt4_availability": subscription_info.get("has_gpt4", ""),
|
69 |
+
"gpt4_32k_availability": subscription_info.get("has_gpt4_32k", ""),
|
70 |
+
"default_org": subscription_info.get("default_org", ""),
|
71 |
+
"org_description": subscription_info.get("org_description", ""),
|
72 |
+
"organization": subscription_info.get("organization", ""),
|
73 |
+
"models": subscription_info.get("models", ""),
|
74 |
+
"requests_per_minute": subscription_info.get("rpm", ""),
|
75 |
+
"tokens_per_minute": subscription_info.get("tpm", ""),
|
76 |
+
"quota": subscription_info.get("quota", ""),
|
77 |
+
"all_models": subscription_info.get("all_models", ""),
|
78 |
+
}
|
79 |
+
)
|
80 |
return info_dict
|
81 |
|
82 |
|
83 |
+
async def get_key_ant_info(key: str, rate_limit: bool, claude_model: str) -> Dict[str, Any]:
|
84 |
key_avai = await check_key_ant_availability(key, claude_model)
|
85 |
info_dict = {
|
86 |
"key_type": "Anthropic Claude",
|
|
|
112 |
return info_dict
|
113 |
|
114 |
|
115 |
+
# μ¬μ©μμ μλ³Έ get_key_gemini_info ν¨μ μ μ§
|
116 |
+
def get_key_gemini_info(key: str) -> Dict[str, Any]:
|
117 |
+
"""Gemini ν€ μ 보λ₯Ό κ°μ Έμ΅λλ€ (μ¬μ©μ μλ³Έ λ²μ )."""
|
118 |
+
key_avai = check_key_gemini_availability(key) # (bool, str) νν λ°ν κ°μ
|
119 |
info_dict = {
|
120 |
+
"key": key, # μλ³Έμλ key νλκ° μμμ
|
121 |
"key_availability": key_avai[0],
|
122 |
"status": key_avai[1],
|
123 |
+
#"models": key_avai[2], # μλ³Έμλ λͺ¨λΈ μ λ³΄κ° μ£Όμ μ²λ¦¬λ¨
|
124 |
}
|
125 |
return info_dict
|
126 |
|
127 |
|
128 |
+
def get_key_azure_info(endpoint: str, api_key: str) -> Dict[str, Any]:
|
129 |
key_avai = check_key_azure_availability(endpoint, api_key)
|
130 |
info_dict = {
|
131 |
"key_type": "Microsoft Azure OpenAI",
|
|
|
140 |
}
|
141 |
if key_avai[0]:
|
142 |
azure_deploy = get_azure_deploy(endpoint, api_key)
|
143 |
+
if azure_deploy:
|
144 |
+
status = get_azure_status(endpoint, api_key, azure_deploy)
|
145 |
+
if status:
|
146 |
+
info_dict["gpt35_availability"] = status[1]
|
147 |
+
info_dict["gpt4_availability"] = status[2]
|
148 |
+
info_dict["gpt4_32k_availability"] = status[3]
|
149 |
+
info_dict["dall_e_3_availability"] = status[4]
|
150 |
+
info_dict["moderation_status"] = status[0]
|
151 |
info_dict["models"] = key_avai[1]
|
152 |
+
info_dict["deployments"] = azure_deploy if azure_deploy else "N/A"
|
153 |
return info_dict
|
154 |
|
155 |
|
156 |
+
def get_key_mistral_info(key: str) -> Dict[str, Any]:
|
157 |
key_avai = check_key_mistral_availability(key)
|
158 |
info_dict = {
|
159 |
"key_type": "Mistral AI",
|
|
|
164 |
}
|
165 |
if key_avai:
|
166 |
quota_info = check_mistral_quota(key)
|
167 |
+
if quota_info:
|
168 |
+
info_dict["has_quota"] = quota_info[0]
|
169 |
+
if quota_info[1]:
|
170 |
+
info_dict["limits"] = quota_info[1]
|
171 |
info_dict["models"] = key_avai
|
172 |
return info_dict
|
173 |
|
174 |
|
175 |
+
def get_key_replicate_info(key: str) -> Dict[str, Any]:
|
176 |
key_avai = check_key_replicate_availability(key)
|
177 |
info_dict = {
|
178 |
"key_type": "Replicate",
|
|
|
182 |
"has_quota": "",
|
183 |
"hardware_available": "",
|
184 |
}
|
185 |
+
if key_avai[0] and isinstance(key_avai[1], dict):
|
186 |
+
info_dict["account_name"] = key_avai[1].get("username", "")
|
187 |
+
info_dict["type"] = key_avai[1].get("type", "")
|
188 |
info_dict["has_quota"] = key_avai[2]
|
189 |
info_dict["hardware_available"] = key_avai[3]
|
190 |
return info_dict
|
191 |
|
192 |
|
193 |
+
async def get_key_aws_info(key: str) -> Dict[str, Any]:
|
194 |
key_avai = await check_key_aws_availability(key)
|
195 |
info_dict = {
|
196 |
"key_type": "Amazon AWS Claude",
|
|
|
204 |
"aws_bedrock_full_access": "",
|
205 |
"enabled_region": "",
|
206 |
"models_usage": "",
|
207 |
+
"cost_and_usage": key_avai[1] if not key_avai[0] else "",
|
208 |
}
|
209 |
if key_avai[0]:
|
210 |
info_dict["username"] = key_avai[1]
|
|
|
220 |
return info_dict
|
221 |
|
222 |
|
223 |
+
def get_key_openrouter_info(key: str) -> Dict[str, Any]:
|
224 |
key_avai = check_key_or_availability(key)
|
225 |
info_dict = {
|
226 |
"key_type": "OpenRouter",
|
|
|
235 |
"sonnet_per_request_tokens_limit": "",
|
236 |
"opus_per_request_tokens_limit": "",
|
237 |
}
|
238 |
+
if key_avai[0] and isinstance(key_avai[1], dict):
|
239 |
models_info = check_key_or_limits(key)
|
240 |
+
info_dict["is_free_tier"] = key_avai[1].get("is_free_tier", "")
|
241 |
+
info_dict["limit"] = key_avai[1].get("limit", "")
|
242 |
+
info_dict["limit_remaining"] = key_avai[1].get("limit_remaining", "")
|
243 |
+
usage_val = key_avai[1].get("usage")
|
244 |
+
info_dict["usage"] = f"${format(usage_val, '.4f')}" if isinstance(usage_val, (int, float)) else ""
|
245 |
+
|
246 |
+
balance_val = models_info[0] if models_info else None
|
247 |
+
rate_limit_val = key_avai[2] if len(key_avai) > 2 else None
|
248 |
+
|
249 |
+
if balance_val is not None:
|
250 |
+
info_dict["balance"] = f"${format(balance_val, '.4f')}"
|
251 |
+
elif rate_limit_val is not None:
|
252 |
+
try:
|
253 |
+
estimated_balance = float(rate_limit_val) / 60
|
254 |
+
info_dict["balance"] = f"${format(estimated_balance, '.4f')} (estimated)"
|
255 |
+
except (ValueError, TypeError):
|
256 |
+
info_dict["balance"] = "$N/A (estimation failed)"
|
257 |
+
else:
|
258 |
+
info_dict["balance"] = "$N/A"
|
259 |
+
|
260 |
+
info_dict["rate_limit_per_minite"] = rate_limit_val if rate_limit_val is not None else ""
|
261 |
+
|
262 |
+
if models_info and isinstance(models_info[1], dict):
|
263 |
+
model_limits = models_info[1]
|
264 |
+
info_dict["4_turbo_per_request_tokens_limit"] = model_limits.get("openai/gpt-4o", "")
|
265 |
+
info_dict["sonnet_per_request_tokens_limit"] = model_limits.get("anthropic/claude-3.5-sonnet:beta", "")
|
266 |
+
info_dict["opus_per_request_tokens_limit"] = model_limits.get("anthropic/claude-3-opus:beta", "")
|
267 |
+
elif not key_avai[0] and len(key_avai) > 1:
|
268 |
info_dict["usage"] = key_avai[1]
|
269 |
return info_dict
|
270 |
|
271 |
|
272 |
+
async def get_key_gcp_info(key: str, type: int) -> Dict[str, Any]:
|
273 |
key_avai = await check_gcp_anthropic(key, type)
|
274 |
info_dict = {
|
275 |
"key_type": "Vertex AI (GCP)",
|
|
|
279 |
}
|
280 |
if key_avai[0]:
|
281 |
info_dict["enabled_region"] = key_avai[2]
|
282 |
+
elif len(key_avai) > 1:
|
283 |
info_dict["status"] = key_avai[1]
|
284 |
return info_dict
|
285 |
|
286 |
|
287 |
+
def get_key_groq_info(key: str) -> Dict[str, Any]:
|
288 |
key_avai = check_groq_status(key)
|
289 |
info_dict = {
|
290 |
"key_type": "Groq",
|
|
|
294 |
return info_dict
|
295 |
|
296 |
|
297 |
+
def get_key_nai_info(key: str) -> Dict[str, Any]:
|
298 |
key_avai = check_nai_status(key)
|
299 |
info_dict = {
|
300 |
"key_type": "NovelAI",
|
|
|
304 |
return info_dict
|
305 |
|
306 |
|
307 |
+
def get_key_elevenlabs_info(key: str) -> Dict[str, Any]:
|
308 |
key_avai = check_elevenlabs_status(key)
|
309 |
info_dict = {
|
310 |
"key_type": "ElevenLabs",
|
311 |
"key_availability": key_avai[0],
|
312 |
+
"user_info": key_avai[1] if len(key_avai) > 1 else "",
|
313 |
+
"voices_info": key_avai[2] if len(key_avai) > 2 else "",
|
314 |
}
|
315 |
return info_dict
|
316 |
|
317 |
|
318 |
+
def get_key_xai_info(key: str) -> Dict[str, Any]:
|
319 |
key_avai = check_xai_status(key)
|
320 |
info_dict = {
|
321 |
"key_type": "xAI Grok",
|
|
|
324 |
"models": "",
|
325 |
}
|
326 |
if key_avai[0]:
|
327 |
+
info_dict["key_status"] = key_avai[1] if len(key_avai) > 1 else ""
|
328 |
+
info_dict["models"] = key_avai[2] if len(key_avai) > 2 else ""
|
329 |
return info_dict
|
330 |
|
331 |
|
332 |
+
def get_key_stability_info(key: str) -> Dict[str, Any]:
|
333 |
key_avai = check_stability_status(key)
|
334 |
info_dict = {
|
335 |
"key_type": "Stability AI",
|
|
|
339 |
"models": "",
|
340 |
}
|
341 |
if key_avai[0]:
|
342 |
+
info_dict["account_info"] = key_avai[1] if len(key_avai) > 1 else ""
|
343 |
+
info_dict["credits"] = key_avai[2] if len(key_avai) > 2 else ""
|
344 |
+
info_dict["models"] = key_avai[3] if len(key_avai) > 3 else ""
|
345 |
return info_dict
|
346 |
|
347 |
|
348 |
+
def get_key_deepseek_info(key: str) -> Dict[str, Any]:
|
349 |
key_avai = check_deepseek_status(key)
|
350 |
info_dict = {
|
351 |
+
"key_type": "DeepSeek",
|
352 |
"key_availability": key_avai[0],
|
353 |
"balance": "",
|
354 |
"models": "",
|
355 |
}
|
356 |
if key_avai[0]:
|
357 |
+
info_dict["models"] = key_avai[1] if len(key_avai) > 1 else ""
|
358 |
+
info_dict["balance"] = key_avai[2] if len(key_avai) > 2 else ""
|
359 |
return info_dict
|
360 |
|
361 |
|
362 |
+
def not_supported(key: str) -> Dict[str, Any]:
|
363 |
return {
|
364 |
"key_type": "Not supported",
|
365 |
+
"key_availability": False,
|
366 |
+
"status": "Unknown key format",
|
367 |
}
|
368 |
|
369 |
|
370 |
# βββββββββββββββββββββββββββββββββββββββββ
|
371 |
+
# λ¨μΌ ν€ λΉλκΈ° μ²λ¦¬ (μ
λ°μ΄νΈλ¨)
|
372 |
# βββββββββββββββββββββββββββββββββββββββββ
|
373 |
+
async def process_single_key(key: str, rate_limit: bool, claude_model: str) -> Dict[str, Any]:
|
374 |
+
"""μ£Όμ΄μ§ key νλλ₯Ό λΆμν΄ μ 보 dict λ°ν. Gemini ν€μ μλ μ¬λΆ νλκ·Έ ν¬ν¨."""
|
375 |
_key = key.strip()
|
376 |
|
377 |
+
if not _key:
|
378 |
+
return {"key": "", "key_type": "Empty", "key_availability": False}
|
379 |
+
|
380 |
# OpenRouter
|
381 |
if re.match(re.compile(r"sk-or-v1-[a-z0-9]{64}"), _key):
|
382 |
+
result = get_key_openrouter_info(_key)
|
383 |
+
return {"key": _key, **result} # key_typeμ get_key_openrouter_infoμμ λ°ν
|
384 |
|
385 |
# Anthropic Claude
|
386 |
+
if re.match(re.compile(r"sk-ant-api03-[a-zA-Z0-9\-_]{93}AA"), _key) or \
|
387 |
+
(_key.startswith("sk-ant-") and len(_key) == 93) or \
|
388 |
+
(len(_key) == 89 and re.match(re.compile(r"sk-[a-zA-Z0-9]{86}"), _key)):
|
389 |
+
result = await get_key_ant_info(_key, rate_limit, claude_model)
|
390 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
391 |
|
392 |
# Stability
|
393 |
if re.match(re.compile(r"sk-[a-zA-Z0-9]{48}"), _key) and len(_key) == 51 and "T3BlbkFJ" not in _key:
|
394 |
+
result = get_key_stability_info(_key)
|
395 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
396 |
|
397 |
# Deepseek
|
398 |
if re.match(re.compile(r"sk-[a-f0-9]{32}"), _key):
|
399 |
+
result = get_key_deepseek_info(_key)
|
400 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
401 |
|
402 |
+
# OpenAI (λ€λ₯Έ sk- ν¨ν΄λ³΄λ€ λ€μ μμΌ ν¨)
|
403 |
if _key.startswith("sk-"):
|
404 |
+
result = get_key_oai_info(_key)
|
405 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
406 |
|
407 |
+
# Google Gemini μ²λ¦¬ (μμ λ¨)
|
408 |
if _key.startswith("AIzaSy"):
|
409 |
+
gemini_info = get_key_gemini_info(_key) # μλ³Έ ν¨μ νΈμΆ
|
410 |
+
# μλ μ¬λΆ νλκ·Έ μΆκ° (status νμΈ)
|
411 |
+
is_working = gemini_info.get("key_availability") and gemini_info.get("status") == "Working"
|
412 |
+
# κ²°κ³Ό λμ
λ리 ꡬμ±: μλ³Έ μ 보 + key_type + μλ μ¬λΆ νλκ·Έ
|
413 |
+
# gemini_infoμ μ΄λ―Έ 'key'κ° ν¬ν¨λμ΄ μμ
|
414 |
+
result = {
|
415 |
+
"key_type": "Google Gemini", # νμ
μ 보 λͺ
μμ μΆκ°
|
416 |
+
**gemini_info,
|
417 |
+
"is_gemini_working": is_working # μλ μ¬λΆ νλκ·Έ
|
418 |
+
}
|
419 |
+
return result
|
420 |
|
421 |
# NovelAI
|
422 |
if _key.startswith("pst-"):
|
423 |
+
result = get_key_nai_info(_key)
|
424 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
425 |
|
426 |
# Replicate
|
427 |
if (_key.startswith("r8_") and len(_key) == 40) or (_key.islower() and len(_key) == 40):
|
428 |
+
result = get_key_replicate_info(_key)
|
429 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
430 |
|
431 |
# xAI
|
432 |
if _key.startswith("xai-"):
|
433 |
+
result = get_key_xai_info(_key)
|
434 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
435 |
|
436 |
# Azure endpoint: "name:key"
|
437 |
+
if len(_key.split(":")) == 2:
|
438 |
+
name, potential_key = _key.split(":", 1)
|
439 |
+
if re.fullmatch(r'[a-fA-F0-9]{32}', potential_key) and "openai.azure.com" not in name:
|
440 |
+
endpoint = f"https://{name}.openai.azure.com/"
|
441 |
+
api_key = potential_key
|
442 |
+
result = get_key_azure_info(endpoint, api_key)
|
443 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
444 |
|
445 |
# Azure endpoint: "https://xxx.openai.azure.com;key"
|
446 |
+
if ";" in _key and "openai.azure.com" in _key.split(";")[0]:
|
447 |
+
endpoint, api_key = _key.split(";", 1)
|
448 |
+
result = get_key_azure_info(endpoint, api_key)
|
449 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
450 |
|
451 |
# AWS
|
452 |
+
if _key.startswith("AKIA") and len(_key.split(":")[0]) == 20 and _key.split(":")[0].isalnum() and _key.split(":")[0].isupper() and len(_key.split(':')) == 2:
|
453 |
+
result = await get_key_aws_info(_key)
|
454 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
455 |
|
456 |
# ElevenLabs
|
457 |
+
if re.fullmatch(r"[a-f0-9]{32}", _key) or re.fullmatch(r"sk_[a-f0-9]{48}", _key):
|
458 |
+
result = get_key_elevenlabs_info(_key)
|
459 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
460 |
|
461 |
# Mistral
|
462 |
+
if re.fullmatch(r"[a-zA-Z0-9]{32}", _key) and not _key.startswith('sk-'):
|
463 |
+
result = get_key_mistral_info(_key)
|
464 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
465 |
|
466 |
# Groq
|
467 |
if re.match(re.compile(r"gsk_[a-zA-Z0-9]{20}WGdyb3FY[a-zA-Z0-9]{24}"), _key):
|
468 |
+
result = get_key_groq_info(_key)
|
469 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
470 |
|
471 |
# GCP - refresh token
|
472 |
+
if re.match(re.compile(r"[\w\-]+:[\w\-@\.]+:.+:.+"), _key):
|
473 |
+
parts = _key.split(':')
|
474 |
+
if len(parts) >= 4:
|
475 |
+
result = await get_key_gcp_info(_key, 0)
|
476 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
477 |
|
478 |
# GCP - service account
|
479 |
if re.match(re.compile(r"[\w\-]+:[\w\-@\.]+:.+\\n"), _key):
|
480 |
+
parts = _key.split(':')
|
481 |
+
if len(parts) >= 3:
|
482 |
+
result = await get_key_gcp_info(_key, 1)
|
483 |
+
return {"key": _key, **result} # key_type ν¬ν¨
|
484 |
|
485 |
# Not supported
|
486 |
+
result = not_supported(_key) # key_type, key_availability, status ν¬ν¨
|
487 |
+
# ν€ κ° μΆκ°νμ¬ λ°ν
|
488 |
+
return {"key": _key, **result}
|
489 |
|
490 |
|
491 |
# βββββββββββββββββββββββββββββββββββββββββ
|
492 |
+
# μ¬λ¬ key λΉλκΈ° μ²λ¦¬ ν¨μ (μ
λ°μ΄νΈλ¨)
|
493 |
# βββββββββββββββββββββββββββββββββββββββββ
|
494 |
+
async def sort_keys(text: str, rate_limit: bool, claude_model: str) -> Tuple[List[Dict[str, Any]], str]:
|
495 |
+
"""ν
μ€νΈ λ°μ€μ μ
λ ₯λ μ¬λ¬ ν€λ₯Ό μ€ λ¨μλ‘ λΆμνκ³ , μ 체 κ²°κ³Όμ μλνλ Gemini ν€ λͺ©λ‘μ λ°ν."""
|
496 |
keys = [k.strip() for k in text.splitlines() if k.strip()]
|
497 |
+
if not keys:
|
498 |
+
return [], ""
|
499 |
+
|
500 |
tasks = [process_single_key(k, rate_limit, claude_model) for k in keys]
|
501 |
results = await asyncio.gather(*tasks)
|
502 |
+
|
503 |
+
# μλνλ Gemini ν€λ§ νν°λ§ (is_gemini_working νλκ·Έ μ¬μ©)
|
504 |
+
working_gemini_keys = []
|
505 |
+
for result in results:
|
506 |
+
# is_gemini_working ν€κ° μ‘΄μ¬νκ³ TrueμΈμ§ νμΈ
|
507 |
+
if result.get("is_gemini_working"): # get() μ¬μ©νμ¬ ν€ λΆμ¬ μ μ€λ₯ λ°©μ§
|
508 |
+
# μλ³Έ get_key_gemini_infoλ 'key' νλλ₯Ό ν¬ν¨νλ―λ‘ λ°λ‘ μ¬μ©
|
509 |
+
working_gemini_keys.append(result["key"])
|
510 |
+
|
511 |
+
# κ²°κ³Όλ₯Ό JSONμ© λ¦¬μ€νΈμ Gemini ν€ λͺ©λ‘ λ¬Έμμ΄λ‘ λ°ν
|
512 |
+
return results, "\n".join(working_gemini_keys)
|
513 |
|
514 |
|
515 |
# βββββββββββββββββββββββββββββββββββββββββ
|
516 |
# UI util
|
517 |
# βββββββββββββββββββββββββββββββββββββββββ
|
518 |
+
def clear_inputs(): # μ
λ ₯ μΈμ μ κ±° (key_box κ°μ νμ μμ)
|
519 |
+
return "", "", "" # λͺ¨λ μ
λ ₯/μΆλ ₯ μ΄κΈ°ν
|
520 |
|
521 |
|
522 |
# βββββββββββββββββββββββββββββββββββββββββ
|
523 |
+
# Gradio UI (μ
λ°μ΄νΈλ¨)
|
524 |
# βββββββββββββββββββββββββββββββββββββββββ
|
525 |
with gr.Blocks() as demo:
|
526 |
gr.Markdown(
|
527 |
"""
|
528 |
+
# Multi-API Key Status Checker (Gemini Enhanced)
|
529 |
+
*(Based on shaocongma, CncAnon1, su, Drago, kingbased key checkers)*
|
530 |
+
Check the status and details of various API keys including OpenAI, Anthropic, Gemini, Azure, Mistral, Replicate, AWS Claude, OpenRouter, Vertex AI (GCP Anthropic), Groq, NovelAI, ElevenLabs, xAI, Stability AI, and DeepSeek.
|
531 |
+
|
532 |
+
**Key Formats:**
|
533 |
+
* **AWS:** `AWS_ACCESS_KEY_ID:AWS_SECRET_ACCESS_KEY` (root might not be accurate)
|
534 |
+
* **Azure:** `RESOURCE_NAME:API_KEY` **or** `https://RESOURCE_NAME.openai.azure.com;API_KEY`
|
535 |
+
* **GCP Service Account:** `PROJECT_ID:CLIENT_EMAIL:PRIVATE_KEY` (ensure `\\n` is included for newlines in the key)
|
536 |
+
* **GCP Refresh Token:** `PROJECT_ID:CLIENT_ID:CLIENT_SECRET:REFRESH_TOKEN`
|
537 |
+
* **Other keys:** Standard format provided by the vendor.
|
538 |
"""
|
539 |
)
|
540 |
|
|
|
543 |
"claude-3-sonnet-20240229",
|
544 |
"claude-3-opus-20240229",
|
545 |
"claude-3-5-sonnet-20240620",
|
|
|
|
|
546 |
]
|
547 |
|
548 |
with gr.Row():
|
549 |
+
with gr.Column(scale=1):
|
550 |
key_box = gr.Textbox(
|
551 |
lines=5,
|
552 |
max_lines=20,
|
553 |
+
label="API Key(s) - One per line",
|
554 |
+
placeholder="Enter one API key per line here.",
|
|
|
|
|
|
|
|
|
|
|
555 |
)
|
556 |
+
with gr.Row():
|
557 |
+
claude_model = gr.Dropdown(
|
558 |
+
claude_options,
|
559 |
+
value="claude-3-haiku-20240307",
|
560 |
+
label="Claude Model (for filter/concurrent check)",
|
561 |
+
scale=3
|
562 |
+
)
|
563 |
+
rate_limit = gr.Checkbox(label="Check Claude concurrent limit (exp.)", scale=1)
|
564 |
|
565 |
with gr.Row():
|
566 |
+
clear_button = gr.Button("Clear All")
|
567 |
+
submit_button = gr.Button("Check Keys", variant="primary")
|
568 |
+
|
569 |
+
with gr.Column(scale=2):
|
570 |
+
info = gr.JSON(label="API Key Information (All Results)", open=True)
|
571 |
+
# Gemini μ μ© μΆλ ₯ λ°μ€ μΆκ°
|
572 |
+
gemini_keys_output = gr.Textbox(
|
573 |
+
label="Working Gemini Keys",
|
574 |
+
info="Lists Gemini keys confirmed as 'Working'.",
|
575 |
+
lines=3,
|
576 |
+
max_lines=10,
|
577 |
+
interactive=False, # μ¬μ©μκ° νΈμ§ λΆκ°
|
578 |
+
)
|
579 |
|
580 |
+
# Clear λ²νΌ ν΄λ¦ μ μ
λ ₯ λ°μ€μ μΆλ ₯ λ°μ€ λͺ¨λ μ΄κΈ°ν
|
581 |
+
clear_button.click(
|
582 |
+
fn=clear_inputs, # μμ λ ν¨μ μ¬μ©
|
583 |
+
inputs=None,
|
584 |
+
outputs=[key_box, info, gemini_keys_output]
|
585 |
+
)
|
586 |
|
587 |
+
# Submit λ²νΌ ν΄λ¦ μ sort_keys ν¨μ νΈμΆ λ° κ²°κ³Ό λΆλ°°
|
588 |
submit_button.click(
|
589 |
fn=sort_keys,
|
590 |
inputs=[key_box, rate_limit, claude_model],
|
591 |
+
outputs=[info, gemini_keys_output], # λ κ°μ μΆλ ₯ μ»΄ν¬λνΈμ κ²°κ³Ό λ§€ν
|
592 |
api_name="sort_keys",
|
593 |
)
|
594 |
|
595 |
+
# demo.launch(share=True) # νμμ 곡μ λ§ν¬ νμ±ν
|
596 |
demo.launch()
|