You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
319 lines
10 KiB
319 lines
10 KiB
"""
|
|
Test file for LLM Council functionality.
|
|
|
|
Tests core functionalities of the LLM Council including:
|
|
- Initialization (default and custom)
|
|
- Running queries
|
|
- Batch processing
|
|
- Output formatting
|
|
"""
|
|
|
|
import pytest
|
|
from loguru import logger
|
|
from dotenv import load_dotenv
|
|
from swarms.structs.llm_council import LLMCouncil
|
|
from swarms.structs.agent import Agent
|
|
|
|
load_dotenv()
|
|
|
|
|
|
def test_llm_council_default_initialization():
|
|
"""Test LLM Council initialization with default council members."""
|
|
try:
|
|
logger.info("Testing LLM Council default initialization...")
|
|
|
|
council = LLMCouncil(
|
|
verbose=False, output_type="dict-all-except-first"
|
|
)
|
|
|
|
assert council is not None, "Council should be initialized"
|
|
assert (
|
|
council.name == "LLM Council"
|
|
), "Default name should be 'LLM Council'"
|
|
assert (
|
|
len(council.council_members) > 0
|
|
), "Should have council members"
|
|
assert (
|
|
council.chairman is not None
|
|
), "Chairman should be initialized"
|
|
assert (
|
|
council.conversation is not None
|
|
), "Conversation should be initialized"
|
|
|
|
logger.info(
|
|
f"✓ Council initialized with {len(council.council_members)} members"
|
|
)
|
|
logger.info("✓ Default initialization test passed")
|
|
|
|
except Exception as e:
|
|
logger.error(f"✗ Default initialization test failed: {e}")
|
|
raise
|
|
|
|
|
|
def test_llm_council_custom_initialization():
|
|
"""Test LLM Council initialization with custom council members."""
|
|
try:
|
|
logger.info("Testing LLM Council custom initialization...")
|
|
|
|
# Create custom council members with simpler models
|
|
custom_members = [
|
|
Agent(
|
|
agent_name="TestAgent1",
|
|
agent_description="First test agent",
|
|
system_prompt="You are a helpful test agent.",
|
|
model_name="gpt-4o-mini",
|
|
max_loops=1,
|
|
verbose=False,
|
|
),
|
|
Agent(
|
|
agent_name="TestAgent2",
|
|
agent_description="Second test agent",
|
|
system_prompt="You are a helpful test agent.",
|
|
model_name="gpt-4o-mini",
|
|
max_loops=1,
|
|
verbose=False,
|
|
),
|
|
]
|
|
|
|
council = LLMCouncil(
|
|
name="Custom Council",
|
|
council_members=custom_members,
|
|
chairman_model="gpt-4o-mini",
|
|
verbose=False,
|
|
output_type="string",
|
|
)
|
|
|
|
assert council is not None, "Council should be initialized"
|
|
assert (
|
|
council.name == "Custom Council"
|
|
), "Name should match custom value"
|
|
assert (
|
|
len(council.council_members) == 2
|
|
), "Should have 2 custom members"
|
|
assert (
|
|
council.council_members[0].agent_name == "TestAgent1"
|
|
), "First member should match"
|
|
assert (
|
|
council.council_members[1].agent_name == "TestAgent2"
|
|
), "Second member should match"
|
|
assert (
|
|
council.output_type == "string"
|
|
), "Output type should be 'string'"
|
|
|
|
logger.info("✓ Custom initialization test passed")
|
|
|
|
except Exception as e:
|
|
logger.error(f"✗ Custom initialization test failed: {e}")
|
|
raise
|
|
|
|
|
|
def test_llm_council_run():
|
|
"""Test LLM Council run method with a simple query."""
|
|
try:
|
|
logger.info("Testing LLM Council run method...")
|
|
|
|
# Use simpler models for testing
|
|
custom_members = [
|
|
Agent(
|
|
agent_name="TestAgent1",
|
|
agent_description="First test agent",
|
|
system_prompt="You are a helpful test agent. Provide concise answers.",
|
|
model_name="gpt-4o-mini",
|
|
max_loops=1,
|
|
verbose=False,
|
|
),
|
|
Agent(
|
|
agent_name="TestAgent2",
|
|
agent_description="Second test agent",
|
|
system_prompt="You are a helpful test agent. Provide concise answers.",
|
|
model_name="gpt-4o-mini",
|
|
max_loops=1,
|
|
verbose=False,
|
|
),
|
|
]
|
|
|
|
council = LLMCouncil(
|
|
council_members=custom_members,
|
|
chairman_model="gpt-4o-mini",
|
|
verbose=False,
|
|
output_type="dict-all-except-first",
|
|
)
|
|
|
|
query = "What is 2 + 2? Provide a brief answer."
|
|
result = council.run(query)
|
|
|
|
# Basic assertions
|
|
assert result is not None, "Result should not be None"
|
|
assert (
|
|
council.conversation is not None
|
|
), "Conversation should exist"
|
|
assert (
|
|
len(council.conversation.conversation_history) > 0
|
|
), "Conversation should have messages"
|
|
|
|
# Enhanced assertions to verify workflow steps
|
|
messages = council.conversation.conversation_history
|
|
|
|
# Step 1: Verify User query was added
|
|
user_messages = [
|
|
msg for msg in messages if msg.get("role") == "User"
|
|
]
|
|
assert (
|
|
len(user_messages) > 0
|
|
), "User query should be in conversation"
|
|
|
|
# Step 2: Verify all council members responded
|
|
member_responses = [
|
|
msg
|
|
for msg in messages
|
|
if msg.get("role") in ["TestAgent1", "TestAgent2"]
|
|
]
|
|
assert len(member_responses) == len(
|
|
custom_members
|
|
), f"All {len(custom_members)} council members should have responded"
|
|
|
|
# Step 3: Verify evaluations were performed
|
|
evaluation_messages = [
|
|
msg
|
|
for msg in messages
|
|
if "-Evaluation" in msg.get("role", "")
|
|
]
|
|
assert len(evaluation_messages) == len(
|
|
custom_members
|
|
), f"All {len(custom_members)} members should have evaluated"
|
|
|
|
# Step 4: Verify Chairman synthesis occurred
|
|
chairman_messages = [
|
|
msg for msg in messages if msg.get("role") == "Chairman"
|
|
]
|
|
assert (
|
|
len(chairman_messages) > 0
|
|
), "Chairman should have synthesized final response"
|
|
|
|
logger.info("✓ Run method test passed")
|
|
logger.info(
|
|
f"✓ Verified {len(member_responses)} member responses, {len(evaluation_messages)} evaluations, and {len(chairman_messages)} chairman synthesis"
|
|
)
|
|
|
|
except Exception as e:
|
|
logger.error(f"✗ Run method test failed: {e}")
|
|
raise
|
|
|
|
|
|
def test_llm_council_batched_run():
|
|
"""Test LLM Council batched_run method with multiple tasks."""
|
|
try:
|
|
logger.info("Testing LLM Council batched_run method...")
|
|
|
|
# Use simpler models for testing
|
|
custom_members = [
|
|
Agent(
|
|
agent_name="TestAgent1",
|
|
agent_description="First test agent",
|
|
system_prompt="You are a helpful test agent. Provide concise answers.",
|
|
model_name="gpt-4o-mini",
|
|
max_loops=1,
|
|
verbose=False,
|
|
),
|
|
Agent(
|
|
agent_name="TestAgent2",
|
|
agent_description="Second test agent",
|
|
system_prompt="You are a helpful test agent. Provide concise answers.",
|
|
model_name="gpt-4o-mini",
|
|
max_loops=1,
|
|
verbose=False,
|
|
),
|
|
]
|
|
|
|
council = LLMCouncil(
|
|
council_members=custom_members,
|
|
chairman_model="gpt-4o-mini",
|
|
verbose=False,
|
|
output_type="dict-all-except-first",
|
|
)
|
|
|
|
tasks = [
|
|
"What is 1 + 1?",
|
|
"What is 3 + 3?",
|
|
]
|
|
|
|
results = council.batched_run(tasks)
|
|
|
|
assert results is not None, "Results should not be None"
|
|
assert len(results) == len(
|
|
tasks
|
|
), f"Should have {len(tasks)} results"
|
|
assert all(
|
|
result is not None for result in results
|
|
), "All results should not be None"
|
|
|
|
logger.info(
|
|
f"✓ Batched run test passed with {len(results)} results"
|
|
)
|
|
|
|
except Exception as e:
|
|
logger.error(f"✗ Batched run test failed: {e}")
|
|
raise
|
|
|
|
|
|
def test_llm_council_output_types():
|
|
"""Test LLM Council with different output types."""
|
|
try:
|
|
logger.info(
|
|
"Testing LLM Council with different output types..."
|
|
)
|
|
|
|
# Use simpler models for testing
|
|
custom_members = [
|
|
Agent(
|
|
agent_name="TestAgent1",
|
|
agent_description="First test agent",
|
|
system_prompt="You are a helpful test agent. Provide concise answers.",
|
|
model_name="gpt-4o-mini",
|
|
max_loops=1,
|
|
verbose=False,
|
|
),
|
|
Agent(
|
|
agent_name="TestAgent2",
|
|
agent_description="Second test agent",
|
|
system_prompt="You are a helpful test agent. Provide concise answers.",
|
|
model_name="gpt-4o-mini",
|
|
max_loops=1,
|
|
verbose=False,
|
|
),
|
|
]
|
|
|
|
output_types = ["string", "dict-all-except-first", "final"]
|
|
|
|
for output_type in output_types:
|
|
logger.info(f"Testing output type: {output_type}")
|
|
|
|
council = LLMCouncil(
|
|
council_members=custom_members,
|
|
chairman_model="gpt-4o-mini",
|
|
verbose=False,
|
|
output_type=output_type,
|
|
)
|
|
|
|
query = "What is 5 + 5? Provide a brief answer."
|
|
result = council.run(query)
|
|
|
|
assert (
|
|
result is not None
|
|
), f"Result should not be None for output type {output_type}"
|
|
assert (
|
|
council.output_type == output_type
|
|
), f"Output type should be {output_type}"
|
|
|
|
logger.info(f"✓ Output type '{output_type}' test passed")
|
|
|
|
logger.info("✓ All output types test passed")
|
|
|
|
except Exception as e:
|
|
logger.error(f"✗ Output types test failed: {e}")
|
|
raise
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|