qwen_agent/utils/agent_pool.py
朱潮 425f3c5bb4 chore: replace Chinese comments and log messages with English
Convert all Chinese comments, docstrings, logger/print output,
HTTPException detail messages, and API response messages to English
across the entire codebase. Functional zh/ja localized strings
(e.g. prompt templates, timezone display names, date formats) are
preserved as-is.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 19:45:35 +08:00

179 lines
5.5 KiB
Python

import asyncio
from typing import List, Optional
import logging
logger = logging.getLogger('app')
class AgentPool:
"""Assistant instance pool manager."""
def __init__(self, pool_size: int = 5):
"""
Initialize the assistant instance pool.
Args:
pool_size: Number of instances in the pool, defaults to 5
"""
self.pool_size = pool_size
self.pool: asyncio.Queue = asyncio.Queue(maxsize=pool_size)
self.semaphore = asyncio.Semaphore(pool_size)
self.agents = [] # Keep references to all created instances
async def initialize(self, agent_factory):
"""
Initialize the instance pool using the assistant factory function.
Args:
agent_factory: Factory function for creating assistant instances
"""
logger.info(f"Initializing assistant instance pool, size: {self.pool_size}")
for i in range(self.pool_size):
try:
agent = agent_factory()
await self.pool.put(agent)
self.agents.append(agent)
logger.info(f"Assistant instance {i+1}/{self.pool_size} created successfully")
except Exception as e:
logger.error(f"Failed to create assistant instance {i+1}: {e}")
raise
logger.info("Assistant instance pool initialization completed")
async def get_agent(self, timeout: Optional[float] = 30.0):
"""
Get an available assistant instance.
Args:
timeout: Timeout in seconds, defaults to 30
Returns:
Assistant instance
Raises:
asyncio.TimeoutError: Raised when acquisition times out
"""
try:
# Use the semaphore to control concurrency
await asyncio.wait_for(self.semaphore.acquire(), timeout=timeout)
# Get an instance from the pool
agent = await asyncio.wait_for(self.pool.get(), timeout=timeout)
logger.debug(f"Successfully acquired assistant instance, remaining pool size: {self.pool.qsize()}")
return agent
except asyncio.TimeoutError:
logger.error(f"Timed out while acquiring assistant instance ({timeout}s)")
raise
async def release_agent(self, agent):
"""
Return an assistant instance to the pool.
Args:
agent: Assistant instance to release
"""
try:
await self.pool.put(agent)
self.semaphore.release()
logger.debug(f"Released assistant instance, current pool size: {self.pool.qsize()}")
except Exception as e:
logger.error(f"Failed to release assistant instance: {e}")
# Release the semaphore even if putting back fails
self.semaphore.release()
def get_pool_stats(self) -> dict:
"""
Get pool status statistics.
Returns:
Dictionary containing pool status information
"""
return {
"pool_size": self.pool_size,
"available_agents": self.pool.qsize(),
"total_agents": len(self.agents),
"in_use_agents": len(self.agents) - self.pool.qsize()
}
async def shutdown(self):
"""Shut down the instance pool and clean up resources."""
logger.info("Shutting down assistant instance pool...")
# Clear the queue
while not self.pool.empty():
try:
agent = self.pool.get_nowait()
# Call cleanup if the instance provides it
if hasattr(agent, 'cleanup'):
await agent.cleanup()
except asyncio.QueueEmpty:
break
logger.info("Assistant instance pool has been shut down")
# Global instance pool singleton
_global_agent_pool: Optional[AgentPool] = None
def get_agent_pool() -> Optional[AgentPool]:
"""Get the global assistant instance pool."""
return _global_agent_pool
def set_agent_pool(pool: AgentPool):
"""Set the global assistant instance pool."""
global _global_agent_pool
_global_agent_pool = pool
async def init_global_agent_pool(pool_size: int = 5, agent_factory=None):
"""
Initialize the global assistant instance pool.
Args:
pool_size: Pool size
agent_factory: Instance factory function
"""
global _global_agent_pool
if _global_agent_pool is not None:
logger.warning("Global assistant instance pool already exists, skipping initialization")
return
if agent_factory is None:
raise ValueError("The agent_factory argument is required")
_global_agent_pool = AgentPool(pool_size=pool_size)
await _global_agent_pool.initialize(agent_factory)
logger.info("Global assistant instance pool initialization completed")
async def get_agent_from_pool(timeout: Optional[float] = 30.0):
"""
Get an assistant instance from the global pool.
Args:
timeout: Acquisition timeout in seconds
Returns:
Assistant instance
"""
if _global_agent_pool is None:
raise RuntimeError("Global assistant instance pool has not been initialized")
return await _global_agent_pool.get_agent(timeout)
async def release_agent_to_pool(agent):
"""
Release an assistant instance back to the global pool.
Args:
agent: Assistant instance to release
"""
if _global_agent_pool is None:
raise RuntimeError("Global assistant instance pool has not been initialized")
await _global_agent_pool.release_agent(agent)