prxyasd commited on
Commit
ee6b440
Β·
verified Β·
1 Parent(s): 4708387

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +149 -61
app.py CHANGED
@@ -32,15 +32,18 @@ from api_usage import (
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
 
41
  info_dict = {
42
  "key_type": "OpenAI",
43
- "key_availability": True if status else False,
 
44
  "gpt4_availability": "",
45
  "gpt4_32k_availability": "",
46
  "default_org": "",
@@ -51,17 +54,63 @@ def get_key_oai_info(key: str) -> Dict[str, Any]:
51
  "tokens_per_minute": "",
52
  "quota": "",
53
  "all_models": "",
 
54
  }
55
 
56
- if not status:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  return info_dict
58
 
59
- if status == 403:
60
- status_me, orgs_me = get_orgs_me(session, key)
 
 
 
 
61
  if status_me == 200:
62
- org_data = orgs_me
 
 
 
 
 
63
 
64
- subscription_info = get_subscription(key, session, org_data)
65
  if subscription_info:
66
  info_dict.update(
67
  {
@@ -73,10 +122,39 @@ def get_key_oai_info(key: str) -> Dict[str, Any]:
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
 
@@ -367,10 +445,10 @@ def not_supported(key: str) -> Dict[str, Any]:
367
 
368
 
369
  # ─────────────────────────────────────────
370
- # 단일 ν‚€ 비동기 처리 (μ—…λ°μ΄νŠΈλ¨ - OpenAI, Anthropic μž‘λ™ ν”Œλž˜κ·Έ μΆ”κ°€)
371
  # ─────────────────────────────────────────
372
  async def process_single_key(key: str, rate_limit: bool, claude_model: str) -> Dict[str, Any]:
373
- """μ£Όμ–΄μ§„ key ν•˜λ‚˜λ₯Ό 뢄석해 정보 dict λ°˜ν™˜. μž‘λ™ν•˜λŠ” ν‚€λ“€μ˜ ν”Œλž˜κ·Έ 포함."""
374
  _key = key.strip()
375
 
376
  if not _key:
@@ -381,16 +459,11 @@ async def process_single_key(key: str, rate_limit: bool, claude_model: str) -> D
381
  result = get_key_openrouter_info(_key)
382
  return {"key": _key, **result}
383
 
384
- # Anthropic Claude (μž‘λ™ ν”Œλž˜κ·Έ μΆ”κ°€)
385
  if re.match(re.compile(r"sk-ant-api03-[a-zA-Z0-9\-_]{93}AA"), _key) or \
386
  (_key.startswith("sk-ant-") and len(_key) == 93) or \
387
  (len(_key) == 89 and re.match(re.compile(r"sk-[a-zA-Z0-9]{86}"), _key)):
388
  result = await get_key_ant_info(_key, rate_limit, claude_model)
389
- # Anthropic ν‚€ μž‘λ™ μ—¬λΆ€ νŒλ‹¨: key_availabilityκ°€ True이고 status에 였λ₯˜κ°€ μ—†μœΌλ©΄ μž‘λ™
390
- is_working = result.get("key_availability") and \
391
- not any(error_word in str(result.get("status", "")).lower()
392
- for error_word in ["error", "invalid", "expired", "forbidden", "unauthorized"])
393
- result["is_anthropic_working"] = is_working
394
  return {"key": _key, **result}
395
 
396
  # Stability
@@ -403,15 +476,12 @@ async def process_single_key(key: str, rate_limit: bool, claude_model: str) -> D
403
  result = get_key_deepseek_info(_key)
404
  return {"key": _key, **result}
405
 
406
- # OpenAI (λ‹€λ₯Έ sk- νŒ¨ν„΄λ³΄λ‹€ 뒀에 와야 함) (μž‘λ™ ν”Œλž˜κ·Έ μΆ”κ°€)
407
  if _key.startswith("sk-"):
408
- result = get_key_oai_info(_key)
409
- # OpenAI ν‚€ μž‘λ™ μ—¬λΆ€ νŒλ‹¨: key_availabilityκ°€ True이면 μž‘λ™
410
- is_working = result.get("key_availability") == True
411
- result["is_openai_working"] = is_working
412
  return {"key": _key, **result}
413
 
414
- # Google Gemini 처리 (κΈ°μ‘΄ μœ μ§€)
415
  if _key.startswith("AIzaSy"):
416
  gemini_info = get_key_gemini_info(_key)
417
  is_working = gemini_info.get("key_availability") and gemini_info.get("status") == "Working"
@@ -492,45 +562,51 @@ async def process_single_key(key: str, rate_limit: bool, claude_model: str) -> D
492
 
493
 
494
  # ─────────────────────────────────────────
495
- # μ—¬λŸ¬ key 비동기 처리 ν•¨μˆ˜ (μ—…λ°μ΄νŠΈλ¨ - λͺ¨λ“  μž‘λ™ ν‚€ λ°˜ν™˜)
496
  # ─────────────────────────────────────────
497
- async def sort_keys(text: str, rate_limit: bool, claude_model: str) -> Tuple[List[Dict[str, Any]], str]:
498
- """ν…μŠ€νŠΈ λ°•μŠ€μ— μž…λ ₯된 μ—¬λŸ¬ ν‚€λ₯Ό 쀄 λ‹¨μœ„λ‘œ λΆ„μ„ν•˜κ³ , 전체 결과와 μž‘λ™ν•˜λŠ” ν‚€ λͺ©λ‘μ„ λ°˜ν™˜."""
 
 
 
499
  keys = [k.strip() for k in text.splitlines() if k.strip()]
500
  if not keys:
501
- return [], ""
502
 
503
  tasks = [process_single_key(k, rate_limit, claude_model) for k in keys]
504
  results = await asyncio.gather(*tasks)
505
 
506
- # μž‘λ™ν•˜λŠ” 킀듀을 μˆ˜μ§‘
507
- working_keys = []
508
-
 
509
  for result in results:
510
- key_value = result.get("key", "")
511
- key_type = result.get("key_type", "")
512
-
513
- # OpenAI ν‚€ 확인
514
- if result.get("is_openai_working"):
515
- working_keys.append(f"[OpenAI] {key_value}")
516
-
517
- # Anthropic ν‚€ 확인
518
- elif result.get("is_anthropic_working"):
519
- working_keys.append(f"[Anthropic] {key_value}")
520
-
521
- # Gemini ν‚€ 확인 (κΈ°μ‘΄)
522
- elif result.get("is_gemini_working"):
523
- working_keys.append(f"[Gemini] {key_value}")
524
-
525
- # κ²°κ³Όλ₯Ό JSON용 λ¦¬μŠ€νŠΈμ™€ μž‘λ™ν•˜λŠ” ν‚€ λͺ©λ‘ λ¬Έμžμ—΄λ‘œ λ°˜ν™˜
526
- return results, "\n".join(working_keys)
 
 
527
 
528
 
529
  # ─────────────────────────────────────────
530
- # UI util
531
  # ─────────────────────────────────────────
532
  def clear_inputs():
533
- return "", "", ""
534
 
535
 
536
  # ─────────────────────────────────────────
@@ -539,9 +615,10 @@ def clear_inputs():
539
  with gr.Blocks() as demo:
540
  gr.Markdown(
541
  """
542
- # Multi-API Key Status Checker (Enhanced Working Keys Display)
543
  *(Based on shaocongma, CncAnon1, su, Drago, kingbased key checkers)*
544
  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.
 
545
 
546
  **Key Formats:**
547
  * **AWS:** `AWS_ACCESS_KEY_ID:AWS_SECRET_ACCESS_KEY` (root might not be accurate)
@@ -582,29 +659,40 @@ Check the status and details of various API keys including OpenAI, Anthropic, Ge
582
 
583
  with gr.Column(scale=2):
584
  info = gr.JSON(label=" API Key Information (All Results)", open=True)
585
- # μž‘λ™ν•˜λŠ” ν‚€λ“€ 좜λ ₯ λ°•μŠ€ (ν™•μž₯됨)
586
- working_keys_output = gr.Textbox(
587
- label="Working Keys (OpenAI, Anthropic, Gemini)",
588
- info="Lists all keys confirmed as working for OpenAI, Anthropic Claude, and Gemini services.",
589
- lines=5,
590
- max_lines=15,
 
 
 
 
 
 
 
 
 
 
 
 
 
591
  interactive=False,
592
  )
593
 
594
- # Clear λ²„νŠΌ 클릭 μ‹œ μž…λ ₯ λ°•μŠ€μ™€ 좜λ ₯ λ°•μŠ€ λͺ¨λ‘ μ΄ˆκΈ°ν™”
595
  clear_button.click(
596
  fn=clear_inputs,
597
  inputs=None,
598
- outputs=[key_box, info, working_keys_output]
599
  )
600
 
601
- # Submit λ²„νŠΌ 클릭 μ‹œ sort_keys ν•¨μˆ˜ 호좜 및 κ²°κ³Ό λΆ„λ°°
602
  submit_button.click(
603
  fn=sort_keys,
604
  inputs=[key_box, rate_limit, claude_model],
605
- outputs=[info, working_keys_output],
606
  api_name="sort_keys",
607
  )
608
 
609
- # demo.launch(share=True) # ν•„μš”μ‹œ 곡유 링크 ν™œμ„±ν™”
610
  demo.launch()
 
32
  )
33
 
34
  # ─────────────────────────────────────────
35
+ # Key-specific helper functions (OpenAI ν•¨μˆ˜ μˆ˜μ •λ¨)
36
  # ─────────────────────────────────────────
37
  def get_key_oai_info(key: str) -> Dict[str, Any]:
38
  session = requests.Session()
39
+ # raw_status_codeλŠ” HTTP 응닡 μ½”λ“œ λ˜λŠ” μœ μ‚¬ν•œ μƒνƒœ ν‘œμ‹œμž
40
+ # org_data_or_errorλŠ” 성곡 μ‹œ 데이터, μ‹€νŒ¨ μ‹œ μ—λŸ¬ 정보 λ“±
41
+ raw_status_code, org_data_or_error = check_key_availability(session, key)
42
 
43
  info_dict = {
44
  "key_type": "OpenAI",
45
+ "key_availability": False,
46
+ "has_sufficient_quota": True, # 기본적으둜 True둜 κ°€μ •, 문제 μ‹œ False둜 λ³€κ²½
47
  "gpt4_availability": "",
48
  "gpt4_32k_availability": "",
49
  "default_org": "",
 
54
  "tokens_per_minute": "",
55
  "quota": "",
56
  "all_models": "",
57
+ "status_message": ""
58
  }
59
 
60
+ org_data_for_subscription = None
61
+
62
+ if raw_status_code == 200:
63
+ info_dict["key_availability"] = True
64
+ org_data_for_subscription = org_data_or_error
65
+ elif raw_status_code == 401: # Unauthorized
66
+ info_dict["status_message"] = "Unauthorized: Invalid API key."
67
+ info_dict["has_sufficient_quota"] = False
68
+ return info_dict
69
+ elif raw_status_code == 403: # Forbidden
70
+ status_me, orgs_me_data = get_orgs_me(session, key)
71
+ if status_me == 200:
72
+ info_dict["key_availability"] = True
73
+ org_data_for_subscription = orgs_me_data
74
+ else:
75
+ info_dict["status_message"] = f"Forbidden, and get_orgs_me failed (status: {status_me}). Key might be inactive or lack permissions."
76
+ info_dict["has_sufficient_quota"] = False
77
+ return info_dict
78
+ elif raw_status_code == 429: # Too Many Requests (Rate Limit or Quota)
79
+ info_dict["key_availability"] = True # ν‚€ μžμ²΄λŠ” μœ νš¨ν•  수 있음
80
+ info_dict["has_sufficient_quota"] = False # μΏΌν„° λΆ€μ‘±μœΌλ‘œ κ°„μ£Ό
81
+ info_dict["status_message"] = "Rate limit or quota likely exceeded (initial check)."
82
+ if isinstance(org_data_or_error, dict) and "error" in org_data_or_error:
83
+ error_details = org_data_or_error["error"]
84
+ current_quota_message = error_details.get("message", "Quota details unavailable from initial check")
85
+ info_dict["quota"] = current_quota_message
86
+ if "insufficient_quota" not in current_quota_message.lower(): # 상세 λ©”μ‹œμ§€μ— insufficient_quotaκ°€ μ—†λ‹€λ©΄ μƒνƒœ λ©”μ‹œμ§€μ— μΆ”κ°€
87
+ info_dict["status_message"] += f" Error: {current_quota_message}"
88
+ # μ—¬κΈ°μ„œ λ°˜ν™˜ν•˜λ©΄ μ•„λž˜ ꡬ독 정보 확인을 κ±΄λ„ˆλ›°μ§€λ§Œ, has_sufficient_quotaκ°€ 이미 Falseμž„
89
+ # return info_dict # ν•„μš”μ— 따라 주석 ν•΄μ œν•˜μ—¬ 더 λΉ λ₯Έ λ°˜ν™˜ κ°€λŠ₯
90
+ else: # 기타 μ—λŸ¬
91
+ info_dict["status_message"] = f"Key check failed (status: {raw_status_code})."
92
+ if isinstance(org_data_or_error, dict) and "error" in org_data_or_error:
93
+ info_dict["status_message"] += f" Error: {org_data_or_error['error'].get('message', str(org_data_or_error))}"
94
+ elif isinstance(org_data_or_error, str):
95
+ info_dict["status_message"] += f" Details: {org_data_or_error}"
96
+ info_dict["has_sufficient_quota"] = False
97
  return info_dict
98
 
99
+ if not info_dict["key_availability"]:
100
+ return info_dict # ν‚€κ°€ μœ νš¨ν•˜μ§€ μ•ŠμœΌλ©΄ 더 이상 μ§„ν–‰ μ•ˆ 함
101
+
102
+ # org_data_for_subscription이 μ€€λΉ„λ˜μ§€ μ•Šμ€ 경우 (예: 초기 200μ΄μ—ˆμ§€λ§Œ org_dataκ°€ λΆ€μ μ ˆ)
103
+ if not org_data_for_subscription:
104
+ status_me, orgs_me_data = get_orgs_me(session, key)
105
  if status_me == 200:
106
+ org_data_for_subscription = orgs_me_data
107
+ else:
108
+ info_dict["status_message"] = (info_dict["status_message"] + " Could not identify organization for subscription.").strip()
109
+ info_dict["key_availability"] = False
110
+ info_dict["has_sufficient_quota"] = False
111
+ return info_dict
112
 
113
+ subscription_info = get_subscription(key, session, org_data_for_subscription)
114
  if subscription_info:
115
  info_dict.update(
116
  {
 
122
  "models": subscription_info.get("models", ""),
123
  "requests_per_minute": subscription_info.get("rpm", ""),
124
  "tokens_per_minute": subscription_info.get("tpm", ""),
125
+ "quota": subscription_info.get("quota", info_dict["quota"]),
126
  "all_models": subscription_info.get("all_models", ""),
127
  }
128
  )
129
+
130
+ error_info = subscription_info.get("error")
131
+ if error_info and isinstance(error_info, dict):
132
+ err_type = error_info.get("type", "").lower()
133
+ err_code = error_info.get("code", "").lower()
134
+ err_msg = error_info.get("message", "").lower()
135
+
136
+ if "insufficient_quota" in err_type or \
137
+ "insufficient_quota" in err_code or \
138
+ "you exceeded your current quota" in err_msg or \
139
+ "payment required" in err_msg or \
140
+ ("billing" in err_msg and "issue" in err_msg):
141
+ info_dict["has_sufficient_quota"] = False
142
+ new_quota_message = f"Insufficient: {error_info.get('message', err_type)}"
143
+ info_dict["quota"] = new_quota_message # μΏΌν„° ν•„λ“œμ— λͺ…μ‹œμ  λ©”μ‹œμ§€
144
+ info_dict["status_message"] = (info_dict["status_message"] + f" Quota/Billing issue: {error_info.get('message', err_type)}").strip()
145
+
146
+ # 계정 λΉ„ν™œμ„±ν™” λ“± 확인
147
+ if "account_deactivated" in str(subscription_info).lower() or \
148
+ "payment_failed" in str(subscription_info).lower():
149
+ info_dict["has_sufficient_quota"] = False
150
+ if "Account issue" not in info_dict["status_message"]: # 쀑볡 λ©”μ‹œμ§€ λ°©μ§€
151
+ info_dict["status_message"] = (info_dict["status_message"] + " Account issue (e.g., deactivated, payment failed).").strip()
152
+ else:
153
+ info_dict["status_message"] = (info_dict["status_message"] + " Failed to retrieve full subscription details.").strip()
154
+ info_dict["has_sufficient_quota"] = False
155
+ # ꡬ독 정보 μ—†μœΌλ©΄ key_availability도 False둜 κ°„μ£Όν•  수 있음.
156
+ # info_dict["key_availability"] = False # 주석 μ²˜λ¦¬ν•˜μ—¬ ν‚€ μžμ²΄λŠ” μœ νš¨ν•  수 μžˆμŒμ„ 남김
157
+
158
  return info_dict
159
 
160
 
 
445
 
446
 
447
  # ─────────────────────────────────────────
448
+ # 단일 ν‚€ 비동기 처리 (μ—…λ°μ΄νŠΈλ¨)
449
  # ─────────────────────────────────────────
450
  async def process_single_key(key: str, rate_limit: bool, claude_model: str) -> Dict[str, Any]:
451
+ """μ£Όμ–΄μ§„ key ν•˜λ‚˜λ₯Ό 뢄석해 정보 dict λ°˜ν™˜. Gemini ν‚€μ˜ μž‘λ™ μ—¬λΆ€ ν”Œλž˜κ·Έ 포함."""
452
  _key = key.strip()
453
 
454
  if not _key:
 
459
  result = get_key_openrouter_info(_key)
460
  return {"key": _key, **result}
461
 
462
+ # Anthropic Claude
463
  if re.match(re.compile(r"sk-ant-api03-[a-zA-Z0-9\-_]{93}AA"), _key) or \
464
  (_key.startswith("sk-ant-") and len(_key) == 93) or \
465
  (len(_key) == 89 and re.match(re.compile(r"sk-[a-zA-Z0-9]{86}"), _key)):
466
  result = await get_key_ant_info(_key, rate_limit, claude_model)
 
 
 
 
 
467
  return {"key": _key, **result}
468
 
469
  # Stability
 
476
  result = get_key_deepseek_info(_key)
477
  return {"key": _key, **result}
478
 
479
+ # OpenAI (λ‹€λ₯Έ sk- νŒ¨ν„΄λ³΄λ‹€ 뒀에 와야 함)
480
  if _key.startswith("sk-"):
481
+ result = get_key_oai_info(_key) # μˆ˜μ •λœ ν•¨μˆ˜ 호좜
 
 
 
482
  return {"key": _key, **result}
483
 
484
+ # Google Gemini 처리
485
  if _key.startswith("AIzaSy"):
486
  gemini_info = get_key_gemini_info(_key)
487
  is_working = gemini_info.get("key_availability") and gemini_info.get("status") == "Working"
 
562
 
563
 
564
  # ─────────────────────────────────────────
565
+ # μ—¬λŸ¬ key 비동기 처리 ν•¨μˆ˜ (μ—…λ°μ΄νŠΈλ¨)
566
  # ─────────────────────────────────────────
567
+ async def sort_keys(text: str, rate_limit: bool, claude_model: str) -> Tuple[List[Dict[str, Any]], str, str, str]:
568
+ """
569
+ ν…μŠ€νŠΈ λ°•μŠ€μ— μž…λ ₯된 μ—¬λŸ¬ ν‚€λ₯Ό 쀄 λ‹¨μœ„λ‘œ λΆ„μ„ν•˜κ³ ,
570
+ 전체 결과와 μž‘λ™ν•˜λŠ” OAI, Anthropic, Gemini ν‚€ λͺ©λ‘μ„ 각각 λ°˜ν™˜ν•©λ‹ˆλ‹€.
571
+ """
572
  keys = [k.strip() for k in text.splitlines() if k.strip()]
573
  if not keys:
574
+ return [], "", "", ""
575
 
576
  tasks = [process_single_key(k, rate_limit, claude_model) for k in keys]
577
  results = await asyncio.gather(*tasks)
578
 
579
+ working_gemini_keys = []
580
+ working_oai_keys = []
581
+ working_anthropic_keys = []
582
+
583
  for result in results:
584
+ key_value = result.get("key")
585
+ if not key_value:
586
+ continue
587
+
588
+ key_type = result.get("key_type")
589
+
590
+ # Gemini ν‚€ 필터링
591
+ if result.get("is_gemini_working"):
592
+ working_gemini_keys.append(key_value)
593
+ # OpenAI ν‚€ 필터링 (μˆ˜μ •λ¨: has_sufficient_quota 확인)
594
+ elif key_type == "OpenAI" and \
595
+ result.get("key_availability") is True and \
596
+ result.get("has_sufficient_quota") is True: # 이 ν•„λ“œκ°€ Trueμ—¬μ•Ό 함
597
+ working_oai_keys.append(key_value)
598
+ # Anthropic ν‚€ 필터링
599
+ elif key_type == "Anthropic Claude" and result.get("key_availability") is True:
600
+ working_anthropic_keys.append(key_value)
601
+
602
+ return results, "\n".join(working_oai_keys), "\n".join(working_anthropic_keys), "\n".join(working_gemini_keys)
603
 
604
 
605
  # ─────────────────────────────────────────
606
+ # UI util (μ—…λ°μ΄νŠΈλ¨)
607
  # ─────────────────────────────────────────
608
  def clear_inputs():
609
+ return "", "", "", "", ""
610
 
611
 
612
  # ─────────────────────────────────────────
 
615
  with gr.Blocks() as demo:
616
  gr.Markdown(
617
  """
618
+ # Multi-API Key Status Checker (OAI, Anthropic, Gemini Enhanced)
619
  *(Based on shaocongma, CncAnon1, su, Drago, kingbased key checkers)*
620
  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.
621
+ This version highlights working OpenAI (with sufficient quota), Anthropic, and Gemini keys in separate text boxes.
622
 
623
  **Key Formats:**
624
  * **AWS:** `AWS_ACCESS_KEY_ID:AWS_SECRET_ACCESS_KEY` (root might not be accurate)
 
659
 
660
  with gr.Column(scale=2):
661
  info = gr.JSON(label=" API Key Information (All Results)", open=True)
662
+ oai_keys_output = gr.Textbox(
663
+ label="Working OpenAI Keys (Sufficient Quota)",
664
+ info="Lists OpenAI keys confirmed as working and having sufficient quota.",
665
+ lines=3,
666
+ max_lines=10,
667
+ interactive=False,
668
+ )
669
+ anthropic_keys_output = gr.Textbox(
670
+ label="Working Anthropic Keys",
671
+ info="Lists Anthropic keys confirmed as working (key_availability is True).",
672
+ lines=3,
673
+ max_lines=10,
674
+ interactive=False,
675
+ )
676
+ gemini_keys_output = gr.Textbox(
677
+ label="Working Gemini Keys",
678
+ info="Lists Gemini keys confirmed as 'Working'.",
679
+ lines=3,
680
+ max_lines=10,
681
  interactive=False,
682
  )
683
 
 
684
  clear_button.click(
685
  fn=clear_inputs,
686
  inputs=None,
687
+ outputs=[key_box, info, oai_keys_output, anthropic_keys_output, gemini_keys_output]
688
  )
689
 
 
690
  submit_button.click(
691
  fn=sort_keys,
692
  inputs=[key_box, rate_limit, claude_model],
693
+ outputs=[info, oai_keys_output, anthropic_keys_output, gemini_keys_output],
694
  api_name="sort_keys",
695
  )
696
 
697
+ # demo.launch(share=True)
698
  demo.launch()