|
|
@ -7,45 +7,108 @@ from swarms.utils.loguru_logger import initialize_logger
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
from tenacity import retry, stop_after_attempt, wait_exponential
|
|
|
|
from tenacity import retry, stop_after_attempt, wait_exponential
|
|
|
|
from swarms.structs.swarm_router import SwarmType
|
|
|
|
from swarms.structs.swarm_router import SwarmType
|
|
|
|
|
|
|
|
from typing import Any
|
|
|
|
|
|
|
|
|
|
|
|
logger = initialize_logger(log_folder="swarms_api")
|
|
|
|
logger = initialize_logger(log_folder="swarms_api")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AgentInput(BaseModel):
|
|
|
|
class AgentInput(BaseModel):
|
|
|
|
agent_name: Optional[str] = Field(None, description="Agent Name", max_length=100)
|
|
|
|
agent_name: Optional[str] = Field(
|
|
|
|
description: Optional[str] = Field(None, description="Description", max_length=500)
|
|
|
|
None,
|
|
|
|
|
|
|
|
description="The name of the agent, limited to 100 characters.",
|
|
|
|
|
|
|
|
max_length=100,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
description: Optional[str] = Field(
|
|
|
|
|
|
|
|
None,
|
|
|
|
|
|
|
|
description="A detailed description of the agent's purpose and capabilities, up to 500 characters.",
|
|
|
|
|
|
|
|
max_length=500,
|
|
|
|
|
|
|
|
)
|
|
|
|
system_prompt: Optional[str] = Field(
|
|
|
|
system_prompt: Optional[str] = Field(
|
|
|
|
None, description="System Prompt", max_length=500
|
|
|
|
None,
|
|
|
|
|
|
|
|
description="The initial prompt or instructions given to the agent, up to 500 characters.",
|
|
|
|
|
|
|
|
max_length=500,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
model_name: Optional[str] = Field(
|
|
|
|
model_name: Optional[str] = Field(
|
|
|
|
"gpt-4o", description="Model Name", max_length=500
|
|
|
|
"gpt-4o",
|
|
|
|
|
|
|
|
description="The name of the model used by the agent, limited to 500 characters.",
|
|
|
|
|
|
|
|
max_length=500,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
auto_generate_prompt: Optional[bool] = Field(
|
|
|
|
auto_generate_prompt: Optional[bool] = Field(
|
|
|
|
False, description="Auto Generate Prompt"
|
|
|
|
False,
|
|
|
|
|
|
|
|
description="Indicates whether the agent should automatically generate prompts.",
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
max_tokens: Optional[int] = Field(
|
|
|
|
|
|
|
|
8192,
|
|
|
|
|
|
|
|
description="The maximum number of tokens the agent can use in its responses.",
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
temperature: Optional[float] = Field(
|
|
|
|
|
|
|
|
0.5,
|
|
|
|
|
|
|
|
description="Controls the randomness of the agent's responses; higher values result in more random outputs.",
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
role: Optional[str] = Field(
|
|
|
|
|
|
|
|
"worker",
|
|
|
|
|
|
|
|
description="The role assigned to the agent, such as 'worker' or 'manager'.",
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
max_loops: Optional[int] = Field(
|
|
|
|
|
|
|
|
1,
|
|
|
|
|
|
|
|
description="The maximum number of iterations the agent is allowed to perform.",
|
|
|
|
)
|
|
|
|
)
|
|
|
|
max_tokens: Optional[int] = Field(None, description="Max Tokens")
|
|
|
|
|
|
|
|
temperature: Optional[float] = Field(0.5, description="Temperature")
|
|
|
|
|
|
|
|
role: Optional[str] = Field("worker", description="Role")
|
|
|
|
|
|
|
|
max_loops: Optional[int] = Field(1, description="Max Loops")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SwarmRequest(BaseModel):
|
|
|
|
class SwarmRequest(BaseModel):
|
|
|
|
name: Optional[str] = Field(None, description="Swarm Name", max_length=100)
|
|
|
|
name: Optional[str] = Field(
|
|
|
|
description: Optional[str] = Field(None, description="Description", max_length=500)
|
|
|
|
"swarms-01",
|
|
|
|
agents: Optional[List[AgentInput]] = Field(None, description="Agents")
|
|
|
|
description="The name of the swarm, limited to 100 characters.",
|
|
|
|
max_loops: Optional[int] = Field(None, description="Max Loops")
|
|
|
|
max_length=100,
|
|
|
|
swarm_type: Optional[SwarmType] = Field(None, description="Swarm Type")
|
|
|
|
)
|
|
|
|
rearrange_flow: Optional[str] = Field(None, description="Flow")
|
|
|
|
description: Optional[str] = Field(
|
|
|
|
task: Optional[str] = Field(None, description="Task")
|
|
|
|
None,
|
|
|
|
img: Optional[str] = Field(None, description="Img")
|
|
|
|
description="A comprehensive description of the swarm's objectives and scope, up to 500 characters.",
|
|
|
|
return_history: Optional[bool] = Field(True, description="Return History")
|
|
|
|
max_length=500,
|
|
|
|
rules: Optional[str] = Field(None, description="Rules")
|
|
|
|
)
|
|
|
|
|
|
|
|
agents: Optional[List[AgentInput]] = Field(
|
|
|
|
class SwarmResponse(BaseModel):
|
|
|
|
None,
|
|
|
|
swarm_id: str
|
|
|
|
description="A list of agents that are part of the swarm.",
|
|
|
|
status: str
|
|
|
|
)
|
|
|
|
result: Optional[str]
|
|
|
|
max_loops: Optional[int] = Field(
|
|
|
|
error: Optional[str]
|
|
|
|
1,
|
|
|
|
|
|
|
|
description="The maximum number of iterations the swarm can execute.",
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
swarm_type: Optional[SwarmType] = Field(
|
|
|
|
|
|
|
|
None,
|
|
|
|
|
|
|
|
description="The type of swarm, defining its operational structure and behavior.",
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
rearrange_flow: Optional[str] = Field(
|
|
|
|
|
|
|
|
None,
|
|
|
|
|
|
|
|
description="The flow or sequence in which agents are rearranged during the swarm's operation.",
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
task: Optional[str] = Field(
|
|
|
|
|
|
|
|
None,
|
|
|
|
|
|
|
|
description="The specific task or objective the swarm is designed to accomplish.",
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
img: Optional[str] = Field(
|
|
|
|
|
|
|
|
None,
|
|
|
|
|
|
|
|
description="A URL to an image associated with the swarm, if applicable.",
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
return_history: Optional[bool] = Field(
|
|
|
|
|
|
|
|
True,
|
|
|
|
|
|
|
|
description="Determines whether the full history of the swarm's operations should be returned.",
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
rules: Optional[str] = Field(
|
|
|
|
|
|
|
|
None,
|
|
|
|
|
|
|
|
description="Any specific rules or guidelines that the swarm should follow.",
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
output_type: Optional[str] = Field(
|
|
|
|
|
|
|
|
"str",
|
|
|
|
|
|
|
|
description="The format in which the swarm's output should be returned, such as 'str', 'json', or 'dict'.",
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# class SwarmResponse(BaseModel):
|
|
|
|
|
|
|
|
# swarm_id: str
|
|
|
|
|
|
|
|
# status: str
|
|
|
|
|
|
|
|
# result: Optional[str]
|
|
|
|
|
|
|
|
# error: Optional[str]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class HealthResponse(BaseModel):
|
|
|
|
class HealthResponse(BaseModel):
|
|
|
@ -94,6 +157,9 @@ class SwarmsAPIClient:
|
|
|
|
self.api_key = api_key or os.getenv("SWARMS_API_KEY")
|
|
|
|
self.api_key = api_key or os.getenv("SWARMS_API_KEY")
|
|
|
|
|
|
|
|
|
|
|
|
if not self.api_key:
|
|
|
|
if not self.api_key:
|
|
|
|
|
|
|
|
logger.error(
|
|
|
|
|
|
|
|
"API key not provided and SWARMS_API_KEY env var not found"
|
|
|
|
|
|
|
|
)
|
|
|
|
raise SwarmAuthenticationError(
|
|
|
|
raise SwarmAuthenticationError(
|
|
|
|
"API key not provided and SWARMS_API_KEY env var not found"
|
|
|
|
"API key not provided and SWARMS_API_KEY env var not found"
|
|
|
|
)
|
|
|
|
)
|
|
|
@ -110,6 +176,10 @@ class SwarmsAPIClient:
|
|
|
|
"Content-Type": "application/json",
|
|
|
|
"Content-Type": "application/json",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
logger.info(
|
|
|
|
|
|
|
|
"SwarmsAPIClient initialized with base_url: {}",
|
|
|
|
|
|
|
|
self.base_url,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@retry(
|
|
|
|
@retry(
|
|
|
|
stop=stop_after_attempt(3),
|
|
|
|
stop=stop_after_attempt(3),
|
|
|
@ -125,13 +195,17 @@ class SwarmsAPIClient:
|
|
|
|
Returns:
|
|
|
|
Returns:
|
|
|
|
HealthResponse object or formatted output
|
|
|
|
HealthResponse object or formatted output
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
logger.info("Performing health check")
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
response = self.client.get(f"{self.base_url}/health")
|
|
|
|
response = self.client.get(f"{self.base_url}/health")
|
|
|
|
response.raise_for_status()
|
|
|
|
response.raise_for_status()
|
|
|
|
health_response = HealthResponse(**response.json())
|
|
|
|
health_response = HealthResponse(**response.json())
|
|
|
|
return self.format_output(health_response, self.format_type)
|
|
|
|
logger.info("Health check successful")
|
|
|
|
|
|
|
|
return self.format_output(
|
|
|
|
|
|
|
|
health_response, self.format_type
|
|
|
|
|
|
|
|
)
|
|
|
|
except httpx.HTTPError as e:
|
|
|
|
except httpx.HTTPError as e:
|
|
|
|
logger.error(f"Health check failed: {str(e)}")
|
|
|
|
logger.error("Health check failed: {}", str(e))
|
|
|
|
raise SwarmAPIError(f"Health check failed: {str(e)}")
|
|
|
|
raise SwarmAPIError(f"Health check failed: {str(e)}")
|
|
|
|
|
|
|
|
|
|
|
|
@retry(
|
|
|
|
@retry(
|
|
|
@ -139,9 +213,7 @@ class SwarmsAPIClient:
|
|
|
|
wait=wait_exponential(multiplier=1, min=4, max=10),
|
|
|
|
wait=wait_exponential(multiplier=1, min=4, max=10),
|
|
|
|
reraise=True,
|
|
|
|
reraise=True,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
async def run(
|
|
|
|
async def arun(self, swarm_request: SwarmRequest) -> Any:
|
|
|
|
self, swarm_request: SwarmRequest
|
|
|
|
|
|
|
|
) -> SwarmResponse:
|
|
|
|
|
|
|
|
"""Create and run a new swarm.
|
|
|
|
"""Create and run a new swarm.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
Args:
|
|
|
@ -151,26 +223,78 @@ class SwarmsAPIClient:
|
|
|
|
Returns:
|
|
|
|
Returns:
|
|
|
|
SwarmResponse object or formatted output
|
|
|
|
SwarmResponse object or formatted output
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
logger.info(
|
|
|
|
|
|
|
|
"Creating and running a new swarm with request: {}",
|
|
|
|
|
|
|
|
swarm_request,
|
|
|
|
|
|
|
|
)
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
response = self.client.post(
|
|
|
|
response = self.client.post(
|
|
|
|
f"{self.base_url}/v1/swarm/completions",
|
|
|
|
f"{self.base_url}/v1/swarm/completions",
|
|
|
|
json=swarm_request.model_dump(),
|
|
|
|
json=swarm_request.model_dump(),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
response.raise_for_status()
|
|
|
|
response.raise_for_status()
|
|
|
|
swarm_response = SwarmResponse(**response.json())
|
|
|
|
logger.info("Swarm creation and run successful")
|
|
|
|
return self.format_output(swarm_response, self.format_type)
|
|
|
|
return self.format_output(
|
|
|
|
|
|
|
|
response.json(), self.format_type
|
|
|
|
|
|
|
|
)
|
|
|
|
except httpx.HTTPStatusError as e:
|
|
|
|
except httpx.HTTPStatusError as e:
|
|
|
|
if e.response.status_code == 401:
|
|
|
|
if e.response.status_code == 401:
|
|
|
|
|
|
|
|
logger.error("Invalid API key")
|
|
|
|
raise SwarmAuthenticationError("Invalid API key")
|
|
|
|
raise SwarmAuthenticationError("Invalid API key")
|
|
|
|
elif e.response.status_code == 422:
|
|
|
|
elif e.response.status_code == 422:
|
|
|
|
|
|
|
|
logger.error("Invalid request parameters")
|
|
|
|
raise SwarmValidationError(
|
|
|
|
raise SwarmValidationError(
|
|
|
|
"Invalid request parameters"
|
|
|
|
"Invalid request parameters"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
logger.error(f"Swarm creation failed: {str(e)}")
|
|
|
|
logger.error("Swarm creation failed: {}", str(e))
|
|
|
|
raise SwarmAPIError(f"Swarm creation failed: {str(e)}")
|
|
|
|
raise SwarmAPIError(f"Swarm creation failed: {str(e)}")
|
|
|
|
except Exception as e:
|
|
|
|
except Exception as e:
|
|
|
|
logger.error(
|
|
|
|
logger.error(
|
|
|
|
f"Unexpected error during swarm creation: {str(e)}"
|
|
|
|
"Unexpected error during swarm creation: {}", str(e)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@retry(
|
|
|
|
|
|
|
|
stop=stop_after_attempt(3),
|
|
|
|
|
|
|
|
wait=wait_exponential(multiplier=1, min=4, max=10),
|
|
|
|
|
|
|
|
reraise=True,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
def run(self, swarm_request: SwarmRequest) -> Any:
|
|
|
|
|
|
|
|
"""Create and run a new swarm.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
swarm_request: SwarmRequest object containing the swarm configuration
|
|
|
|
|
|
|
|
output_format: Desired output format ('pydantic', 'json', 'dict')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
SwarmResponse object or formatted output
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
logger.info(
|
|
|
|
|
|
|
|
"Creating and running a new swarm with request: {}",
|
|
|
|
|
|
|
|
swarm_request,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
response = self.client.post(
|
|
|
|
|
|
|
|
f"{self.base_url}/v1/swarm/completions",
|
|
|
|
|
|
|
|
json=swarm_request.model_dump(),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
print(response.json())
|
|
|
|
|
|
|
|
logger.info("Swarm creation and run successful")
|
|
|
|
|
|
|
|
return response.json()
|
|
|
|
|
|
|
|
except httpx.HTTPStatusError as e:
|
|
|
|
|
|
|
|
if e.response.status_code == 401:
|
|
|
|
|
|
|
|
logger.error("Invalid API key")
|
|
|
|
|
|
|
|
raise SwarmAuthenticationError("Invalid API key")
|
|
|
|
|
|
|
|
elif e.response.status_code == 422:
|
|
|
|
|
|
|
|
logger.error("Invalid request parameters")
|
|
|
|
|
|
|
|
raise SwarmValidationError(
|
|
|
|
|
|
|
|
"Invalid request parameters"
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
logger.error("Swarm creation failed: {}", str(e))
|
|
|
|
|
|
|
|
raise SwarmAPIError(f"Swarm creation failed: {str(e)}")
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
|
|
logger.error(
|
|
|
|
|
|
|
|
"Unexpected error during swarm creation: {}", str(e)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
raise
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
|
@ -181,7 +305,7 @@ class SwarmsAPIClient:
|
|
|
|
)
|
|
|
|
)
|
|
|
|
async def run_batch(
|
|
|
|
async def run_batch(
|
|
|
|
self, swarm_requests: List[SwarmRequest]
|
|
|
|
self, swarm_requests: List[SwarmRequest]
|
|
|
|
) -> List[SwarmResponse]:
|
|
|
|
) -> List[Any]:
|
|
|
|
"""Create and run multiple swarms in batch.
|
|
|
|
"""Create and run multiple swarms in batch.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
Args:
|
|
|
@ -191,36 +315,54 @@ class SwarmsAPIClient:
|
|
|
|
Returns:
|
|
|
|
Returns:
|
|
|
|
List of SwarmResponse objects or formatted outputs
|
|
|
|
List of SwarmResponse objects or formatted outputs
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
logger.info(
|
|
|
|
|
|
|
|
"Creating and running batch swarms with requests: {}",
|
|
|
|
|
|
|
|
swarm_requests,
|
|
|
|
|
|
|
|
)
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
response = self.client.post(
|
|
|
|
response = self.client.post(
|
|
|
|
f"{self.base_url}/v1/swarm/batch/completions",
|
|
|
|
f"{self.base_url}/v1/swarm/batch/completions",
|
|
|
|
json=[req.model_dump() for req in swarm_requests],
|
|
|
|
json=[req.model_dump() for req in swarm_requests],
|
|
|
|
)
|
|
|
|
)
|
|
|
|
response.raise_for_status()
|
|
|
|
response.raise_for_status()
|
|
|
|
swarm_responses = [SwarmResponse(**resp) for resp in response.json()]
|
|
|
|
logger.info("Batch swarm creation and run successful")
|
|
|
|
return [self.format_output(resp, self.format_type) for resp in swarm_responses]
|
|
|
|
return [
|
|
|
|
|
|
|
|
self.format_output(resp, self.format_type)
|
|
|
|
|
|
|
|
for resp in response.json()
|
|
|
|
|
|
|
|
]
|
|
|
|
except httpx.HTTPStatusError as e:
|
|
|
|
except httpx.HTTPStatusError as e:
|
|
|
|
if e.response.status_code == 401:
|
|
|
|
if e.response.status_code == 401:
|
|
|
|
|
|
|
|
logger.error("Invalid API key")
|
|
|
|
raise SwarmAuthenticationError("Invalid API key")
|
|
|
|
raise SwarmAuthenticationError("Invalid API key")
|
|
|
|
elif e.response.status_code == 422:
|
|
|
|
elif e.response.status_code == 422:
|
|
|
|
|
|
|
|
logger.error("Invalid request parameters")
|
|
|
|
raise SwarmValidationError(
|
|
|
|
raise SwarmValidationError(
|
|
|
|
"Invalid request parameters"
|
|
|
|
"Invalid request parameters"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
logger.error(f"Batch swarm creation failed: {str(e)}")
|
|
|
|
logger.error("Batch swarm creation failed: {}", str(e))
|
|
|
|
raise SwarmAPIError(
|
|
|
|
raise SwarmAPIError(
|
|
|
|
f"Batch swarm creation failed: {str(e)}"
|
|
|
|
f"Batch swarm creation failed: {str(e)}"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
except Exception as e:
|
|
|
|
except Exception as e:
|
|
|
|
logger.error(
|
|
|
|
logger.error(
|
|
|
|
f"Unexpected error during batch swarm creation: {str(e)}"
|
|
|
|
"Unexpected error during batch swarm creation: {}",
|
|
|
|
|
|
|
|
str(e),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
raise
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
|
|
def get_logs(self):
|
|
|
|
def get_logs(self):
|
|
|
|
response = self.client.get(f"{self.base_url}/v1/swarm/logs")
|
|
|
|
logger.info("Retrieving logs")
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
response = self.client.get(
|
|
|
|
|
|
|
|
f"{self.base_url}/v1/swarm/logs"
|
|
|
|
|
|
|
|
)
|
|
|
|
response.raise_for_status()
|
|
|
|
response.raise_for_status()
|
|
|
|
logs = response.json()
|
|
|
|
logs = response.json()
|
|
|
|
|
|
|
|
logger.info("Logs retrieved successfully")
|
|
|
|
return self.format_output(logs, self.format_type)
|
|
|
|
return self.format_output(logs, self.format_type)
|
|
|
|
|
|
|
|
except httpx.HTTPError as e:
|
|
|
|
|
|
|
|
logger.error("Failed to retrieve logs: {}", str(e))
|
|
|
|
|
|
|
|
raise SwarmAPIError(f"Failed to retrieve logs: {str(e)}")
|
|
|
|
|
|
|
|
|
|
|
|
def format_output(self, data, output_format: str):
|
|
|
|
def format_output(self, data, output_format: str):
|
|
|
|
"""Format the output based on the specified format.
|
|
|
|
"""Format the output based on the specified format.
|
|
|
@ -232,18 +374,32 @@ class SwarmsAPIClient:
|
|
|
|
Returns:
|
|
|
|
Returns:
|
|
|
|
Formatted data
|
|
|
|
Formatted data
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
logger.info(
|
|
|
|
|
|
|
|
"Formatting output with format: {}", output_format
|
|
|
|
|
|
|
|
)
|
|
|
|
if output_format == "json":
|
|
|
|
if output_format == "json":
|
|
|
|
return data.model_dump_json(indent=4) if isinstance(data, BaseModel) else json.dumps(data)
|
|
|
|
return (
|
|
|
|
|
|
|
|
data.model_dump_json(indent=4)
|
|
|
|
|
|
|
|
if isinstance(data, BaseModel)
|
|
|
|
|
|
|
|
else json.dumps(data)
|
|
|
|
|
|
|
|
)
|
|
|
|
elif output_format == "dict":
|
|
|
|
elif output_format == "dict":
|
|
|
|
return data.model_dump() if isinstance(data, BaseModel) else data
|
|
|
|
return (
|
|
|
|
|
|
|
|
data.model_dump()
|
|
|
|
|
|
|
|
if isinstance(data, BaseModel)
|
|
|
|
|
|
|
|
else data
|
|
|
|
|
|
|
|
)
|
|
|
|
return data # Default to returning the pydantic model
|
|
|
|
return data # Default to returning the pydantic model
|
|
|
|
|
|
|
|
|
|
|
|
def close(self):
|
|
|
|
def close(self):
|
|
|
|
"""Close the HTTP client."""
|
|
|
|
"""Close the HTTP client."""
|
|
|
|
|
|
|
|
logger.info("Closing HTTP client")
|
|
|
|
self.client.close()
|
|
|
|
self.client.close()
|
|
|
|
|
|
|
|
|
|
|
|
async def __aenter__(self):
|
|
|
|
async def __aenter__(self):
|
|
|
|
|
|
|
|
logger.info("Entering async context")
|
|
|
|
return self
|
|
|
|
return self
|
|
|
|
|
|
|
|
|
|
|
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
|
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
|
|
|
|
|
|
logger.info("Exiting async context")
|
|
|
|
self.close()
|
|
|
|
self.close()
|
|
|
|