|
|
|
|
@ -1,75 +1,54 @@
|
|
|
|
|
import pytest
|
|
|
|
|
from unittest.mock import Mock, patch
|
|
|
|
|
# from unittest.mock import Mock, patch
|
|
|
|
|
|
|
|
|
|
from swarms.structs.agent_router import AgentRouter
|
|
|
|
|
from swarms.structs.agent import Agent
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
|
def test_agent():
|
|
|
|
|
"""Create a real agent for testing."""
|
|
|
|
|
with patch("swarms.structs.agent.LiteLLM") as mock_llm:
|
|
|
|
|
mock_llm.return_value.run.return_value = "Test response"
|
|
|
|
|
return Agent(
|
|
|
|
|
agent_name="test_agent",
|
|
|
|
|
agent_description="A test agent",
|
|
|
|
|
system_prompt="You are a test agent",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_agent_router_initialization_default():
|
|
|
|
|
"""Test AgentRouter initialization with default parameters."""
|
|
|
|
|
with patch("swarms.structs.agent_router.embedding"):
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
|
|
|
|
|
assert router.embedding_model == "text-embedding-ada-002"
|
|
|
|
|
assert router.n_agents == 1
|
|
|
|
|
assert router.api_key is None
|
|
|
|
|
assert router.api_base is None
|
|
|
|
|
assert router.agents == []
|
|
|
|
|
assert router.agent_embeddings == []
|
|
|
|
|
assert router.agent_metadata == []
|
|
|
|
|
assert router.embedding_model == "text-embedding-ada-002"
|
|
|
|
|
assert router.n_agents == 1
|
|
|
|
|
assert router.api_key is None
|
|
|
|
|
assert router.api_base is None
|
|
|
|
|
assert router.agents == []
|
|
|
|
|
assert router.agent_embeddings == []
|
|
|
|
|
assert router.agent_metadata == []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_agent_router_initialization_custom():
|
|
|
|
|
"""Test AgentRouter initialization with custom parameters."""
|
|
|
|
|
with patch("swarms.structs.agent_router.embedding"), patch(
|
|
|
|
|
"swarms.structs.agent.LiteLLM"
|
|
|
|
|
) as mock_llm:
|
|
|
|
|
mock_llm.return_value.run.return_value = "Test response"
|
|
|
|
|
agents = [
|
|
|
|
|
Agent(
|
|
|
|
|
agent_name="test1",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
),
|
|
|
|
|
Agent(
|
|
|
|
|
agent_name="test2",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
),
|
|
|
|
|
]
|
|
|
|
|
router = AgentRouter(
|
|
|
|
|
embedding_model="custom-model",
|
|
|
|
|
n_agents=3,
|
|
|
|
|
api_key="custom_key",
|
|
|
|
|
api_base="custom_base",
|
|
|
|
|
agents=agents,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert router.embedding_model == "custom-model"
|
|
|
|
|
assert router.n_agents == 3
|
|
|
|
|
assert router.api_key == "custom_key"
|
|
|
|
|
assert router.api_base == "custom_base"
|
|
|
|
|
assert len(router.agents) == 2
|
|
|
|
|
agents = [
|
|
|
|
|
Agent(
|
|
|
|
|
agent_name="test1",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
),
|
|
|
|
|
Agent(
|
|
|
|
|
agent_name="test2",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
),
|
|
|
|
|
]
|
|
|
|
|
router = AgentRouter(
|
|
|
|
|
embedding_model="text-embedding-ada-002",
|
|
|
|
|
n_agents=3,
|
|
|
|
|
api_key=None,
|
|
|
|
|
api_base=None,
|
|
|
|
|
agents=agents,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert router.embedding_model == "text-embedding-ada-002"
|
|
|
|
|
assert router.n_agents == 3
|
|
|
|
|
assert len(router.agents) == 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_cosine_similarity_identical_vectors():
|
|
|
|
|
@ -108,243 +87,212 @@ def test_cosine_similarity_different_lengths():
|
|
|
|
|
vec1 = [1.0, 0.0]
|
|
|
|
|
vec2 = [1.0, 0.0, 0.0]
|
|
|
|
|
|
|
|
|
|
with pytest.raises(
|
|
|
|
|
ValueError, match="Vectors must have the same length"
|
|
|
|
|
):
|
|
|
|
|
try:
|
|
|
|
|
router._cosine_similarity(vec1, vec2)
|
|
|
|
|
assert False, "Should have raised ValueError"
|
|
|
|
|
except ValueError as e:
|
|
|
|
|
assert "Vectors must have the same length" in str(e)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@patch("swarms.structs.agent_router.embedding")
|
|
|
|
|
def test_generate_embedding_success(mock_embedding):
|
|
|
|
|
"""Test successful embedding generation."""
|
|
|
|
|
mock_embedding.return_value.data = [
|
|
|
|
|
Mock(embedding=[0.1, 0.2, 0.3, 0.4])
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
def test_generate_embedding_success():
|
|
|
|
|
"""Test successful embedding generation with real API."""
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
result = router._generate_embedding("test text")
|
|
|
|
|
|
|
|
|
|
assert result == [0.1, 0.2, 0.3, 0.4]
|
|
|
|
|
mock_embedding.assert_called_once()
|
|
|
|
|
|
|
|
|
|
assert result is not None
|
|
|
|
|
assert isinstance(result, list)
|
|
|
|
|
assert len(result) > 0
|
|
|
|
|
assert all(isinstance(x, float) for x in result)
|
|
|
|
|
|
|
|
|
|
@patch("swarms.structs.agent_router.embedding")
|
|
|
|
|
def test_generate_embedding_error(mock_embedding):
|
|
|
|
|
"""Test embedding generation error handling."""
|
|
|
|
|
mock_embedding.side_effect = Exception("API Error")
|
|
|
|
|
|
|
|
|
|
def test_add_agent_success():
|
|
|
|
|
"""Test successful agent addition with real agent and streaming."""
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
agent = Agent(
|
|
|
|
|
agent_name="test_agent",
|
|
|
|
|
agent_description="A test agent",
|
|
|
|
|
system_prompt="You are a test agent",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
with pytest.raises(Exception, match="API Error"):
|
|
|
|
|
router._generate_embedding("test text")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@patch("swarms.structs.agent_router.embedding")
|
|
|
|
|
def test_add_agent_success(mock_embedding, test_agent):
|
|
|
|
|
"""Test successful agent addition."""
|
|
|
|
|
mock_embedding.return_value.data = [
|
|
|
|
|
Mock(embedding=[0.1, 0.2, 0.3])
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
router.add_agent(test_agent)
|
|
|
|
|
router.add_agent(agent)
|
|
|
|
|
|
|
|
|
|
assert len(router.agents) == 1
|
|
|
|
|
assert len(router.agent_embeddings) == 1
|
|
|
|
|
assert len(router.agent_metadata) == 1
|
|
|
|
|
assert router.agents[0] == test_agent
|
|
|
|
|
assert router.agent_embeddings[0] == [0.1, 0.2, 0.3]
|
|
|
|
|
assert router.agents[0] == agent
|
|
|
|
|
assert router.agent_metadata[0]["name"] == "test_agent"
|
|
|
|
|
|
|
|
|
|
# Test that agent can stream
|
|
|
|
|
streamed_chunks = []
|
|
|
|
|
|
|
|
|
|
@patch("swarms.structs.agent_router.embedding")
|
|
|
|
|
def test_add_agent_retry_error(mock_embedding, test_agent):
|
|
|
|
|
"""Test agent addition with retry mechanism failure."""
|
|
|
|
|
mock_embedding.side_effect = Exception("Embedding error")
|
|
|
|
|
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
|
|
|
|
|
# Should raise RetryError after retries are exhausted
|
|
|
|
|
with pytest.raises(Exception) as exc_info:
|
|
|
|
|
router.add_agent(test_agent)
|
|
|
|
|
|
|
|
|
|
# Check that it's a retry error or contains the original error
|
|
|
|
|
assert "Embedding error" in str(
|
|
|
|
|
exc_info.value
|
|
|
|
|
) or "RetryError" in str(exc_info.value)
|
|
|
|
|
|
|
|
|
|
def streaming_callback(chunk: str):
|
|
|
|
|
streamed_chunks.append(chunk)
|
|
|
|
|
|
|
|
|
|
@patch("swarms.structs.agent_router.embedding")
|
|
|
|
|
def test_add_agents_multiple(mock_embedding):
|
|
|
|
|
"""Test adding multiple agents."""
|
|
|
|
|
mock_embedding.return_value.data = [
|
|
|
|
|
Mock(embedding=[0.1, 0.2, 0.3])
|
|
|
|
|
]
|
|
|
|
|
response = agent.run("Say hello", streaming_callback=streaming_callback)
|
|
|
|
|
assert response is not None
|
|
|
|
|
assert len(streamed_chunks) > 0 or response != "", "Agent should stream or return response"
|
|
|
|
|
|
|
|
|
|
with patch("swarms.structs.agent.LiteLLM") as mock_llm:
|
|
|
|
|
mock_llm.return_value.run.return_value = "Test response"
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
agents = [
|
|
|
|
|
Agent(
|
|
|
|
|
agent_name="agent1",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
),
|
|
|
|
|
Agent(
|
|
|
|
|
agent_name="agent2",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
),
|
|
|
|
|
Agent(
|
|
|
|
|
agent_name="agent3",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
),
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
router.add_agents(agents)
|
|
|
|
|
|
|
|
|
|
assert len(router.agents) == 3
|
|
|
|
|
assert len(router.agent_embeddings) == 3
|
|
|
|
|
assert len(router.agent_metadata) == 3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@patch("swarms.structs.agent_router.embedding")
|
|
|
|
|
def test_find_best_agent_success(mock_embedding):
|
|
|
|
|
"""Test successful best agent finding."""
|
|
|
|
|
# Mock embeddings for agents and task
|
|
|
|
|
mock_embedding.side_effect = [
|
|
|
|
|
Mock(data=[Mock(embedding=[0.1, 0.2, 0.3])]), # agent1
|
|
|
|
|
Mock(data=[Mock(embedding=[0.4, 0.5, 0.6])]), # agent2
|
|
|
|
|
Mock(data=[Mock(embedding=[0.7, 0.8, 0.9])]), # task
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
with patch("swarms.structs.agent.LiteLLM") as mock_llm:
|
|
|
|
|
mock_llm.return_value.run.return_value = "Test response"
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
agent1 = Agent(
|
|
|
|
|
def test_add_agents_multiple():
|
|
|
|
|
"""Test adding multiple agents with real agents and streaming."""
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
agents = [
|
|
|
|
|
Agent(
|
|
|
|
|
agent_name="agent1",
|
|
|
|
|
agent_description="First agent",
|
|
|
|
|
system_prompt="Prompt 1",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
)
|
|
|
|
|
agent2 = Agent(
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
),
|
|
|
|
|
Agent(
|
|
|
|
|
agent_name="agent2",
|
|
|
|
|
agent_description="Second agent",
|
|
|
|
|
system_prompt="Prompt 2",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
)
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
),
|
|
|
|
|
Agent(
|
|
|
|
|
agent_name="agent3",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
),
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
router.add_agents(agents)
|
|
|
|
|
|
|
|
|
|
assert len(router.agents) == 3
|
|
|
|
|
assert len(router.agent_embeddings) == 3
|
|
|
|
|
assert len(router.agent_metadata) == 3
|
|
|
|
|
|
|
|
|
|
# Test that all agents can stream
|
|
|
|
|
for agent in agents:
|
|
|
|
|
streamed_chunks = []
|
|
|
|
|
|
|
|
|
|
def streaming_callback(chunk: str):
|
|
|
|
|
streamed_chunks.append(chunk)
|
|
|
|
|
|
|
|
|
|
response = agent.run("Say hi", streaming_callback=streaming_callback)
|
|
|
|
|
assert response is not None
|
|
|
|
|
assert len(streamed_chunks) > 0 or response != "", f"Agent {agent.agent_name} should stream or return response"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_find_best_agent_success():
|
|
|
|
|
"""Test successful best agent finding with real agents and streaming."""
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
agent1 = Agent(
|
|
|
|
|
agent_name="agent1",
|
|
|
|
|
agent_description="First agent that handles data extraction",
|
|
|
|
|
system_prompt="You are a data extraction specialist",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
)
|
|
|
|
|
agent2 = Agent(
|
|
|
|
|
agent_name="agent2",
|
|
|
|
|
agent_description="Second agent that handles summarization",
|
|
|
|
|
system_prompt="You are a summarization specialist",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
router.add_agent(agent1)
|
|
|
|
|
router.add_agent(agent2)
|
|
|
|
|
|
|
|
|
|
router.add_agent(agent1)
|
|
|
|
|
router.add_agent(agent2)
|
|
|
|
|
result = router.find_best_agent("Extract data from documents")
|
|
|
|
|
|
|
|
|
|
# Mock the similarity calculation to return predictable results
|
|
|
|
|
with patch.object(
|
|
|
|
|
router, "_cosine_similarity"
|
|
|
|
|
) as mock_similarity:
|
|
|
|
|
mock_similarity.side_effect = [
|
|
|
|
|
0.8,
|
|
|
|
|
0.6,
|
|
|
|
|
] # agent1 more similar
|
|
|
|
|
assert result is not None
|
|
|
|
|
assert result in [agent1, agent2]
|
|
|
|
|
|
|
|
|
|
result = router.find_best_agent("test task")
|
|
|
|
|
# Test that the found agent can stream
|
|
|
|
|
streamed_chunks = []
|
|
|
|
|
|
|
|
|
|
assert result == agent1
|
|
|
|
|
def streaming_callback(chunk: str):
|
|
|
|
|
streamed_chunks.append(chunk)
|
|
|
|
|
|
|
|
|
|
response = result.run("Test task", streaming_callback=streaming_callback)
|
|
|
|
|
assert response is not None
|
|
|
|
|
assert len(streamed_chunks) > 0 or response != "", "Found agent should stream or return response"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_find_best_agent_no_agents():
|
|
|
|
|
"""Test finding best agent when no agents are available."""
|
|
|
|
|
with patch("swarms.structs.agent_router.embedding"):
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
|
|
|
|
|
result = router.find_best_agent("test task")
|
|
|
|
|
|
|
|
|
|
assert result is None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@patch("swarms.structs.agent_router.embedding")
|
|
|
|
|
def test_find_best_agent_retry_error(mock_embedding):
|
|
|
|
|
"""Test error handling in find_best_agent with retry mechanism."""
|
|
|
|
|
mock_embedding.side_effect = Exception("API Error")
|
|
|
|
|
|
|
|
|
|
with patch("swarms.structs.agent.LiteLLM") as mock_llm:
|
|
|
|
|
mock_llm.return_value.run.return_value = "Test response"
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
router.agents = [
|
|
|
|
|
Agent(
|
|
|
|
|
agent_name="agent1",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
router.agent_embeddings = [[0.1, 0.2, 0.3]]
|
|
|
|
|
|
|
|
|
|
# Should raise RetryError after retries are exhausted
|
|
|
|
|
with pytest.raises(Exception) as exc_info:
|
|
|
|
|
router.find_best_agent("test task")
|
|
|
|
|
|
|
|
|
|
# Check that it's a retry error or contains the original error
|
|
|
|
|
assert "API Error" in str(
|
|
|
|
|
exc_info.value
|
|
|
|
|
) or "RetryError" in str(exc_info.value)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@patch("swarms.structs.agent_router.embedding")
|
|
|
|
|
def test_update_agent_history_success(mock_embedding, test_agent):
|
|
|
|
|
"""Test successful agent history update."""
|
|
|
|
|
mock_embedding.return_value.data = [
|
|
|
|
|
Mock(embedding=[0.1, 0.2, 0.3])
|
|
|
|
|
]
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
|
|
|
|
|
result = router.find_best_agent("test task")
|
|
|
|
|
|
|
|
|
|
assert result is None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_update_agent_history_success():
|
|
|
|
|
"""Test successful agent history update with real agent and streaming."""
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
router.add_agent(test_agent)
|
|
|
|
|
agent = Agent(
|
|
|
|
|
agent_name="test_agent",
|
|
|
|
|
agent_description="A test agent",
|
|
|
|
|
system_prompt="You are a test agent",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
router.add_agent(agent)
|
|
|
|
|
|
|
|
|
|
# Run agent to create history
|
|
|
|
|
streamed_chunks = []
|
|
|
|
|
|
|
|
|
|
def streaming_callback(chunk: str):
|
|
|
|
|
streamed_chunks.append(chunk)
|
|
|
|
|
|
|
|
|
|
agent.run("Hello, how are you?", streaming_callback=streaming_callback)
|
|
|
|
|
|
|
|
|
|
# Update agent history
|
|
|
|
|
router.update_agent_history("test_agent")
|
|
|
|
|
|
|
|
|
|
# Verify the embedding was regenerated
|
|
|
|
|
assert (
|
|
|
|
|
mock_embedding.call_count == 2
|
|
|
|
|
) # Once for add, once for update
|
|
|
|
|
assert len(router.agent_embeddings) == 1
|
|
|
|
|
assert router.agent_metadata[0]["name"] == "test_agent"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_update_agent_history_agent_not_found():
|
|
|
|
|
"""Test updating history for non-existent agent."""
|
|
|
|
|
with patch(
|
|
|
|
|
"swarms.structs.agent_router.embedding"
|
|
|
|
|
) as mock_embedding:
|
|
|
|
|
mock_embedding.return_value.data = [
|
|
|
|
|
Mock(embedding=[0.1, 0.2, 0.3])
|
|
|
|
|
]
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
|
|
|
|
|
# Should not raise an exception, just log a warning
|
|
|
|
|
router.update_agent_history("non_existent_agent")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@patch("swarms.structs.agent_router.embedding")
|
|
|
|
|
def test_agent_metadata_structure(mock_embedding, test_agent):
|
|
|
|
|
"""Test the structure of agent metadata."""
|
|
|
|
|
mock_embedding.return_value.data = [
|
|
|
|
|
Mock(embedding=[0.1, 0.2, 0.3])
|
|
|
|
|
]
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
|
|
|
|
|
# Should not raise an exception, just log a warning
|
|
|
|
|
router.update_agent_history("non_existent_agent")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_agent_metadata_structure():
|
|
|
|
|
"""Test the structure of agent metadata with real agent."""
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
router.add_agent(test_agent)
|
|
|
|
|
agent = Agent(
|
|
|
|
|
agent_name="test_agent",
|
|
|
|
|
agent_description="A test agent",
|
|
|
|
|
system_prompt="You are a test agent",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
router.add_agent(agent)
|
|
|
|
|
|
|
|
|
|
metadata = router.agent_metadata[0]
|
|
|
|
|
assert "name" in metadata
|
|
|
|
|
@ -357,25 +305,148 @@ def test_agent_metadata_structure(mock_embedding, test_agent):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_agent_router_edge_cases():
|
|
|
|
|
"""Test various edge cases."""
|
|
|
|
|
with patch(
|
|
|
|
|
"swarms.structs.agent_router.embedding"
|
|
|
|
|
) as mock_embedding:
|
|
|
|
|
mock_embedding.return_value.data = [
|
|
|
|
|
Mock(embedding=[0.1, 0.2, 0.3])
|
|
|
|
|
]
|
|
|
|
|
"""Test various edge cases with real router."""
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
# Test with empty string task
|
|
|
|
|
result = router.find_best_agent("")
|
|
|
|
|
assert result is None
|
|
|
|
|
|
|
|
|
|
# Test with empty string task
|
|
|
|
|
result = router.find_best_agent("")
|
|
|
|
|
assert result is None
|
|
|
|
|
# Test with very long task description
|
|
|
|
|
long_task = "test " * 1000
|
|
|
|
|
result = router.find_best_agent(long_task)
|
|
|
|
|
# Should either return None or handle gracefully
|
|
|
|
|
assert result is None or result is not None
|
|
|
|
|
|
|
|
|
|
# Test with very long task description
|
|
|
|
|
long_task = "test " * 1000
|
|
|
|
|
result = router.find_best_agent(long_task)
|
|
|
|
|
assert result is None
|
|
|
|
|
|
|
|
|
|
def test_router_with_agent_streaming():
|
|
|
|
|
"""Test that agents in router can stream when run."""
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
|
|
|
|
|
agent1 = Agent(
|
|
|
|
|
agent_name="streaming_agent1",
|
|
|
|
|
agent_description="Agent for testing streaming",
|
|
|
|
|
system_prompt="You are a helpful assistant",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
agent2 = Agent(
|
|
|
|
|
agent_name="streaming_agent2",
|
|
|
|
|
agent_description="Another agent for testing streaming",
|
|
|
|
|
system_prompt="You are a helpful assistant",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
router.add_agent(agent1)
|
|
|
|
|
router.add_agent(agent2)
|
|
|
|
|
|
|
|
|
|
# Test each agent streams
|
|
|
|
|
for agent in router.agents:
|
|
|
|
|
streamed_chunks = []
|
|
|
|
|
|
|
|
|
|
def streaming_callback(chunk: str):
|
|
|
|
|
if chunk:
|
|
|
|
|
streamed_chunks.append(chunk)
|
|
|
|
|
|
|
|
|
|
response = agent.run("Tell me a short joke", streaming_callback=streaming_callback)
|
|
|
|
|
assert response is not None
|
|
|
|
|
assert len(streamed_chunks) > 0 or response != "", f"Agent {agent.agent_name} should stream"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_router_find_and_run_with_streaming():
|
|
|
|
|
"""Test finding best agent and running it with streaming."""
|
|
|
|
|
router = AgentRouter()
|
|
|
|
|
|
|
|
|
|
agent1 = Agent(
|
|
|
|
|
agent_name="math_agent",
|
|
|
|
|
agent_description="Handles mathematical problems",
|
|
|
|
|
system_prompt="You are a math expert",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
agent2 = Agent(
|
|
|
|
|
agent_name="writing_agent",
|
|
|
|
|
agent_description="Handles writing tasks",
|
|
|
|
|
system_prompt="You are a writing expert",
|
|
|
|
|
model_name="gpt-4o-mini",
|
|
|
|
|
max_loops=1,
|
|
|
|
|
verbose=False,
|
|
|
|
|
print_on=False,
|
|
|
|
|
streaming_on=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
router.add_agent(agent1)
|
|
|
|
|
router.add_agent(agent2)
|
|
|
|
|
|
|
|
|
|
# Find best agent for a math task
|
|
|
|
|
best_agent = router.find_best_agent("Solve 2 + 2")
|
|
|
|
|
|
|
|
|
|
if best_agent:
|
|
|
|
|
streamed_chunks = []
|
|
|
|
|
|
|
|
|
|
def streaming_callback(chunk: str):
|
|
|
|
|
if chunk:
|
|
|
|
|
streamed_chunks.append(chunk)
|
|
|
|
|
|
|
|
|
|
response = best_agent.run("What is 2 + 2?", streaming_callback=streaming_callback)
|
|
|
|
|
assert response is not None
|
|
|
|
|
assert len(streamed_chunks) > 0 or response != "", "Best agent should stream when run"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
pytest.main([__file__])
|
|
|
|
|
# List of all test functions
|
|
|
|
|
tests = [
|
|
|
|
|
test_agent_router_initialization_default,
|
|
|
|
|
test_agent_router_initialization_custom,
|
|
|
|
|
test_cosine_similarity_identical_vectors,
|
|
|
|
|
test_cosine_similarity_orthogonal_vectors,
|
|
|
|
|
test_cosine_similarity_opposite_vectors,
|
|
|
|
|
test_cosine_similarity_different_lengths,
|
|
|
|
|
test_generate_embedding_success,
|
|
|
|
|
test_add_agent_success,
|
|
|
|
|
test_add_agents_multiple,
|
|
|
|
|
test_find_best_agent_success,
|
|
|
|
|
test_find_best_agent_no_agents,
|
|
|
|
|
test_update_agent_history_success,
|
|
|
|
|
test_update_agent_history_agent_not_found,
|
|
|
|
|
test_agent_metadata_structure,
|
|
|
|
|
test_agent_router_edge_cases,
|
|
|
|
|
test_router_with_agent_streaming,
|
|
|
|
|
test_router_find_and_run_with_streaming,
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# Run all tests
|
|
|
|
|
print("Running all tests...")
|
|
|
|
|
passed = 0
|
|
|
|
|
failed = 0
|
|
|
|
|
|
|
|
|
|
for test_func in tests:
|
|
|
|
|
try:
|
|
|
|
|
print(f"\n{'='*60}")
|
|
|
|
|
print(f"Running: {test_func.__name__}")
|
|
|
|
|
print(f"{'='*60}")
|
|
|
|
|
test_func()
|
|
|
|
|
print(f"✓ PASSED: {test_func.__name__}")
|
|
|
|
|
passed += 1
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"✗ FAILED: {test_func.__name__}")
|
|
|
|
|
print(f" Error: {str(e)}")
|
|
|
|
|
import traceback
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
failed += 1
|
|
|
|
|
|
|
|
|
|
print(f"\n{'='*60}")
|
|
|
|
|
print(f"Test Summary: {passed} passed, {failed} failed")
|
|
|
|
|
print(f"{'='*60}")
|
|
|
|
|
|