key_pool_pusher.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. """
  2. 号池数据推送服务
  3. 定时将分组和key数据推送到company_base_pool
  4. """
  5. import logging
  6. import asyncio
  7. from datetime import datetime
  8. import httpx
  9. import os
  10. logger = logging.getLogger(__name__)
  11. # company_base_pool的API地址
  12. COMPANY_BASE_POOL_URL = os.getenv("COMPANY_BASE_POOL_URL", "http://localhost:8011")
  13. SYNC_ENDPOINT = f"{COMPANY_BASE_POOL_URL}/api/admin/key-pool/sync"
  14. async def push_group_keys_to_pool(pool, group_id: int, api_key_ids: list):
  15. """
  16. 推送分组的key到company_base_pool
  17. Args:
  18. pool: 数据库连接池
  19. group_id: 分组ID
  20. api_key_ids: key ID列表
  21. """
  22. try:
  23. async with pool.acquire() as conn:
  24. # 设置search_path
  25. await conn.execute("SET search_path TO crawl")
  26. # 获取分组信息
  27. group = await conn.fetchrow("SELECT name FROM model_groups WHERE id = $1", group_id)
  28. if not group:
  29. return
  30. # 获取keys
  31. keys = await conn.fetch("""
  32. SELECT ak.key_value
  33. FROM api_keys ak
  34. JOIN group_keys gk ON gk.api_key_id = ak.id
  35. WHERE gk.group_id = $1 AND gk.is_active = TRUE
  36. """, group_id)
  37. if not keys:
  38. return
  39. api_keys = [k['key_value'] for k in keys]
  40. # 获取分组的provider(从绑定的模型推断)
  41. provider_row = await conn.fetchrow("""
  42. SELECT DISTINCT m.provider
  43. FROM models m
  44. WHERE m.group_id = $1 AND m.provider IS NOT NULL
  45. LIMIT 1
  46. """, group_id)
  47. provider = provider_row['provider'] if provider_row else "dashscope"
  48. # 推送到company_base_pool
  49. data = [{
  50. "group_name": group['name'],
  51. "provider": provider,
  52. "model_name": None,
  53. "api_keys": api_keys
  54. }]
  55. async with httpx.AsyncClient(timeout=30) as client:
  56. response = await client.post(SYNC_ENDPOINT, json=data)
  57. if response.status_code == 200:
  58. result = response.json()
  59. logger.info(f"推送分组 {group['name']} 到号池: {result}")
  60. else:
  61. logger.error(f"推送失败: {response.status_code} {response.text}")
  62. except Exception as e:
  63. logger.error(f"推送分组 {group_id} 失败: {e}")
  64. async def push_all_groups_to_pool(pool):
  65. """推送所有分组到company_base_pool"""
  66. try:
  67. async with pool.acquire() as conn:
  68. # 设置search_path
  69. await conn.execute("SET search_path TO crawl")
  70. # 获取所有有key的分组
  71. groups = await conn.fetch("""
  72. SELECT DISTINCT g.id, g.name
  73. FROM model_groups g
  74. JOIN group_keys gk ON gk.group_id = g.id
  75. WHERE gk.is_active = TRUE
  76. """)
  77. logger.info(f"开始推送 {len(groups)} 个分组到号池")
  78. for group in groups:
  79. await push_group_keys_to_pool(pool, group['id'], [])
  80. logger.info("推送完成")
  81. except Exception as e:
  82. logger.error(f"推送所有分组失败: {e}")