Spaces:
Sleeping
Sleeping
Commit ·
7d6cbb8
1
Parent(s): e2d980c
changed proxy pool
Browse files- freeplay2api.py +88 -125
freeplay2api.py
CHANGED
|
@@ -327,14 +327,11 @@ class AccountManager:
|
|
| 327 |
def load_accounts(self):
|
| 328 |
with self.lock:
|
| 329 |
if not os.path.exists(self.filepath):
|
| 330 |
-
logging.info(f"DEBUG: Accounts file {self.filepath} does not exist, initializing empty accounts list")
|
| 331 |
self.accounts = []
|
| 332 |
return
|
| 333 |
with open(self.filepath, "r", encoding="utf-8") as f:
|
| 334 |
self.accounts = [json.loads(line) for line in f if line.strip()]
|
| 335 |
logging.info(f"Loaded {len(self.accounts)} accounts from {self.filepath}")
|
| 336 |
-
for i, acc in enumerate(self.accounts):
|
| 337 |
-
logging.info(f"DEBUG: Account {i}: email={acc.get('email')}, session_id type={type(acc.get('session_id'))}, session_id={repr(acc.get('session_id'))}")
|
| 338 |
|
| 339 |
def save_accounts(self):
|
| 340 |
# This operation is disabled to ensure the application is stateless.
|
|
@@ -384,54 +381,36 @@ class KeyMaintainer(threading.Thread):
|
|
| 384 |
try:
|
| 385 |
logging.info("KeyMaintainer: Starting maintenance cycle.")
|
| 386 |
accounts = self.manager.get_all_accounts()
|
| 387 |
-
logging.info(f"DEBUG: KeyMaintainer got {len(accounts)} accounts")
|
| 388 |
|
| 389 |
# Update balances
|
| 390 |
-
for
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
| 394 |
-
|
| 395 |
-
logging.info(f"
|
| 396 |
-
|
| 397 |
-
balance = self.client.check_balance(session_id)
|
| 398 |
-
if balance != account.get("balance"):
|
| 399 |
-
account["balance"] = balance
|
| 400 |
-
self.manager.update_account(account)
|
| 401 |
-
logging.info(f"Account {account['email']} balance updated to ${balance:.4f}")
|
| 402 |
-
except Exception as e:
|
| 403 |
-
logging.error(f"DEBUG: Error processing account {i} ({account.get('email')}): {type(e).__name__}: {e}")
|
| 404 |
-
import traceback
|
| 405 |
-
logging.error(f"DEBUG: Account processing traceback: {traceback.format_exc()}")
|
| 406 |
|
| 407 |
# Check if new accounts are needed
|
| 408 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 409 |
healthy_accounts = [
|
| 410 |
acc for acc in self.manager.get_all_accounts()
|
| 411 |
if acc.get("balance", 0) > self.config["LOW_BALANCE_THRESHOLD"]
|
| 412 |
]
|
| 413 |
needed = self.config["ACTIVE_KEY_THRESHOLD"] - len(healthy_accounts)
|
| 414 |
|
| 415 |
-
while needed > 0:
|
| 416 |
-
logging.info(f"Healthy accounts ({len(healthy_accounts)}) below threshold. Need to register {needed} new accounts. Retrying immediately.")
|
| 417 |
-
new_account = self.client.register()
|
| 418 |
-
if new_account:
|
| 419 |
-
self.manager.add_account(new_account)
|
| 420 |
-
|
| 421 |
-
healthy_accounts = [
|
| 422 |
-
acc for acc in self.manager.get_all_accounts()
|
| 423 |
-
if acc.get("balance", 0) > self.config["LOW_BALANCE_THRESHOLD"]
|
| 424 |
-
]
|
| 425 |
-
needed = self.config["ACTIVE_KEY_THRESHOLD"] - len(healthy_accounts)
|
| 426 |
-
except Exception as e:
|
| 427 |
-
logging.error(f"DEBUG: Error in account threshold check: {type(e).__name__}: {e}")
|
| 428 |
-
import traceback
|
| 429 |
-
logging.error(f"DEBUG: Threshold check traceback: {traceback.format_exc()}")
|
| 430 |
-
|
| 431 |
except Exception as e:
|
| 432 |
-
logging.error(f"Error in KeyMaintainer cycle: {
|
| 433 |
-
import traceback
|
| 434 |
-
logging.error(f"DEBUG: KeyMaintainer outer traceback: {traceback.format_exc()}")
|
| 435 |
|
| 436 |
time.sleep(self.config["CHECK_INTERVAL_SECONDS"])
|
| 437 |
|
|
@@ -609,106 +588,90 @@ async def chat_completions(
|
|
| 609 |
message["content"] = new_content
|
| 610 |
|
| 611 |
# 账户选择和重试逻辑
|
| 612 |
-
|
| 613 |
-
logging.info(f"DEBUG: chat_completions got {len(all_accounts)} total accounts")
|
| 614 |
-
max_retries = len(all_accounts)
|
| 615 |
-
|
| 616 |
for attempt in range(max_retries):
|
| 617 |
-
|
| 618 |
-
|
| 619 |
-
|
| 620 |
-
|
| 621 |
-
|
| 622 |
-
)
|
| 623 |
-
|
| 624 |
-
logging.info(f"DEBUG: Using account {account.get('email')} for chat attempt {attempt}")
|
| 625 |
-
logging.info(f"DEBUG: Account keys: {list(account.keys())}")
|
| 626 |
-
|
| 627 |
-
try:
|
| 628 |
-
params = {
|
| 629 |
-
"max_tokens": req.max_tokens,
|
| 630 |
-
"temperature": req.temperature,
|
| 631 |
-
"top_p": req.top_p,
|
| 632 |
-
}
|
| 633 |
-
response = freeplay_client.chat(
|
| 634 |
-
account["session_id"],
|
| 635 |
-
account["project_id"],
|
| 636 |
-
model_config,
|
| 637 |
-
messages_dict,
|
| 638 |
-
params,
|
| 639 |
-
)
|
| 640 |
-
|
| 641 |
-
if response.status_code == 200:
|
| 642 |
-
# 请求成功
|
| 643 |
-
if req.stream:
|
| 644 |
-
return StreamingResponse(
|
| 645 |
-
stream_generator(response, req.model, account),
|
| 646 |
-
media_type="text/event-stream",
|
| 647 |
-
)
|
| 648 |
-
else:
|
| 649 |
-
full_content = ""
|
| 650 |
-
for line in response.iter_lines(decode_unicode=True):
|
| 651 |
-
if line and line.startswith("data: "):
|
| 652 |
-
try:
|
| 653 |
-
data = json.loads(line[6:])
|
| 654 |
-
content = data.get("content", "")
|
| 655 |
-
if content is not None:
|
| 656 |
-
full_content += content
|
| 657 |
-
if data.get("cost") is not None:
|
| 658 |
-
break
|
| 659 |
-
except json.JSONDecodeError:
|
| 660 |
-
continue
|
| 661 |
-
|
| 662 |
-
# 更新余额
|
| 663 |
-
new_balance = freeplay_client.check_balance(account["session_id"])
|
| 664 |
-
account["balance"] = new_balance
|
| 665 |
-
account_manager.update_account(account)
|
| 666 |
-
logging.info(
|
| 667 |
-
f"Post-chat balance update for {account['email']}: ${new_balance:.4f}"
|
| 668 |
-
)
|
| 669 |
|
| 670 |
-
|
| 671 |
-
|
| 672 |
-
|
| 673 |
-
|
| 674 |
-
|
| 675 |
-
|
| 676 |
-
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
|
|
|
|
|
|
|
|
|
| 680 |
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
|
|
|
|
|
|
|
|
|
|
| 684 |
)
|
| 685 |
-
account["balance"] = 0.0 # 禁用账户
|
| 686 |
-
account_manager.update_account(account)
|
| 687 |
-
continue # 重试下一个
|
| 688 |
else:
|
| 689 |
-
|
| 690 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 691 |
)
|
| 692 |
-
|
| 693 |
-
|
| 694 |
-
|
| 695 |
-
|
| 696 |
-
|
| 697 |
-
|
| 698 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 699 |
|
| 700 |
except requests.exceptions.ProxyError:
|
| 701 |
# Proxy error was already logged and handled in FreeplayClient
|
| 702 |
logging.warning(f"Retrying request due to proxy error.")
|
| 703 |
# Don't disable the account, just retry with a new proxy (and potentially new account)
|
| 704 |
continue
|
| 705 |
-
|
| 706 |
except Exception as e:
|
| 707 |
logging.error(
|
| 708 |
-
f"Error with account {account
|
| 709 |
)
|
| 710 |
-
import traceback
|
| 711 |
-
logging.error(f"DEBUG: Account error traceback: {traceback.format_exc()}")
|
| 712 |
account["balance"] = 0.0 # 发生未知异常也禁用
|
| 713 |
account_manager.update_account(account)
|
| 714 |
continue
|
|
|
|
| 327 |
def load_accounts(self):
|
| 328 |
with self.lock:
|
| 329 |
if not os.path.exists(self.filepath):
|
|
|
|
| 330 |
self.accounts = []
|
| 331 |
return
|
| 332 |
with open(self.filepath, "r", encoding="utf-8") as f:
|
| 333 |
self.accounts = [json.loads(line) for line in f if line.strip()]
|
| 334 |
logging.info(f"Loaded {len(self.accounts)} accounts from {self.filepath}")
|
|
|
|
|
|
|
| 335 |
|
| 336 |
def save_accounts(self):
|
| 337 |
# This operation is disabled to ensure the application is stateless.
|
|
|
|
| 381 |
try:
|
| 382 |
logging.info("KeyMaintainer: Starting maintenance cycle.")
|
| 383 |
accounts = self.manager.get_all_accounts()
|
|
|
|
| 384 |
|
| 385 |
# Update balances
|
| 386 |
+
for account in accounts:
|
| 387 |
+
balance = self.client.check_balance(account["session_id"])
|
| 388 |
+
if balance != account.get("balance"):
|
| 389 |
+
account["balance"] = balance
|
| 390 |
+
self.manager.update_account(account)
|
| 391 |
+
logging.info(f"Account {account['email']} balance updated to ${balance:.4f}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 392 |
|
| 393 |
# Check if new accounts are needed
|
| 394 |
+
healthy_accounts = [
|
| 395 |
+
acc for acc in self.manager.get_all_accounts()
|
| 396 |
+
if acc.get("balance", 0) > self.config["LOW_BALANCE_THRESHOLD"]
|
| 397 |
+
]
|
| 398 |
+
needed = self.config["ACTIVE_KEY_THRESHOLD"] - len(healthy_accounts)
|
| 399 |
+
|
| 400 |
+
while needed > 0:
|
| 401 |
+
logging.info(f"Healthy accounts ({len(healthy_accounts)}) below threshold. Need to register {needed} new accounts. Retrying immediately.")
|
| 402 |
+
new_account = self.client.register()
|
| 403 |
+
if new_account:
|
| 404 |
+
self.manager.add_account(new_account)
|
| 405 |
+
|
| 406 |
healthy_accounts = [
|
| 407 |
acc for acc in self.manager.get_all_accounts()
|
| 408 |
if acc.get("balance", 0) > self.config["LOW_BALANCE_THRESHOLD"]
|
| 409 |
]
|
| 410 |
needed = self.config["ACTIVE_KEY_THRESHOLD"] - len(healthy_accounts)
|
| 411 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 412 |
except Exception as e:
|
| 413 |
+
logging.error(f"Error in KeyMaintainer cycle: {e}")
|
|
|
|
|
|
|
| 414 |
|
| 415 |
time.sleep(self.config["CHECK_INTERVAL_SECONDS"])
|
| 416 |
|
|
|
|
| 588 |
message["content"] = new_content
|
| 589 |
|
| 590 |
# 账户选择和重试逻辑
|
| 591 |
+
max_retries = len(account_manager.get_all_accounts())
|
|
|
|
|
|
|
|
|
|
| 592 |
for attempt in range(max_retries):
|
| 593 |
+
account = account_manager.get_account()
|
| 594 |
+
if not account:
|
| 595 |
+
raise HTTPException(
|
| 596 |
+
status_code=503, detail="No available accounts in the pool."
|
| 597 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 598 |
|
| 599 |
+
try:
|
| 600 |
+
params = {
|
| 601 |
+
"max_tokens": req.max_tokens,
|
| 602 |
+
"temperature": req.temperature,
|
| 603 |
+
"top_p": req.top_p,
|
| 604 |
+
}
|
| 605 |
+
response = freeplay_client.chat(
|
| 606 |
+
account["session_id"],
|
| 607 |
+
account["project_id"],
|
| 608 |
+
model_config,
|
| 609 |
+
messages_dict,
|
| 610 |
+
params,
|
| 611 |
+
)
|
| 612 |
|
| 613 |
+
if response.status_code == 200:
|
| 614 |
+
# 请求成功
|
| 615 |
+
if req.stream:
|
| 616 |
+
return StreamingResponse(
|
| 617 |
+
stream_generator(response, req.model, account),
|
| 618 |
+
media_type="text/event-stream",
|
| 619 |
)
|
|
|
|
|
|
|
|
|
|
| 620 |
else:
|
| 621 |
+
full_content = ""
|
| 622 |
+
for line in response.iter_lines(decode_unicode=True):
|
| 623 |
+
if line and line.startswith("data: "):
|
| 624 |
+
try:
|
| 625 |
+
data = json.loads(line[6:])
|
| 626 |
+
content = data.get("content", "")
|
| 627 |
+
if content is not None:
|
| 628 |
+
full_content += content
|
| 629 |
+
if data.get("cost") is not None:
|
| 630 |
+
break
|
| 631 |
+
except json.JSONDecodeError:
|
| 632 |
+
continue
|
| 633 |
+
|
| 634 |
+
# 更新余额
|
| 635 |
+
new_balance = freeplay_client.check_balance(account["session_id"])
|
| 636 |
+
account["balance"] = new_balance
|
| 637 |
+
account_manager.update_account(account)
|
| 638 |
+
logging.info(
|
| 639 |
+
f"Post-chat balance update for {account['email']}: ${new_balance:.4f}"
|
| 640 |
)
|
| 641 |
+
|
| 642 |
+
return ChatCompletionResponse(
|
| 643 |
+
model=req.model,
|
| 644 |
+
choices=[
|
| 645 |
+
ChatCompletionChoice(
|
| 646 |
+
message=ChatMessage(
|
| 647 |
+
role="assistant", content=full_content
|
| 648 |
+
)
|
| 649 |
+
)
|
| 650 |
+
],
|
| 651 |
+
)
|
| 652 |
+
|
| 653 |
+
elif response.status_code in [401, 403, 404]:
|
| 654 |
+
logging.warning(
|
| 655 |
+
f"Account {account['email']} failed with status {response.status_code}. Disabling it."
|
| 656 |
+
)
|
| 657 |
+
account["balance"] = 0.0 # 禁用账户
|
| 658 |
+
account_manager.update_account(account)
|
| 659 |
+
continue # 重试下一个
|
| 660 |
+
else:
|
| 661 |
+
logging.error(
|
| 662 |
+
f"API call failed with status {response.status_code}: {response.text}"
|
| 663 |
+
)
|
| 664 |
+
response.raise_for_status()
|
| 665 |
|
| 666 |
except requests.exceptions.ProxyError:
|
| 667 |
# Proxy error was already logged and handled in FreeplayClient
|
| 668 |
logging.warning(f"Retrying request due to proxy error.")
|
| 669 |
# Don't disable the account, just retry with a new proxy (and potentially new account)
|
| 670 |
continue
|
|
|
|
| 671 |
except Exception as e:
|
| 672 |
logging.error(
|
| 673 |
+
f"Error with account {account['email']}: {e}. Trying next account."
|
| 674 |
)
|
|
|
|
|
|
|
| 675 |
account["balance"] = 0.0 # 发生未知异常也禁用
|
| 676 |
account_manager.update_account(account)
|
| 677 |
continue
|