diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 1fdf39b7..79245488 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -188,6 +188,7 @@ nav: - TaskQueueSwarm: "swarms/structs/taskqueue_swarm.md" - SwarmRearrange: "swarms/structs/swarm_rearrange.md" - MultiAgentRouter: "swarms/structs/multi_agent_router.md" + - MatrixSwarm: "swarms/structs/matrix_swarm.md" - Various Execution Methods: "swarms/structs/various_execution_methods.md" - Workflows: - ConcurrentWorkflow: "swarms/structs/concurrentworkflow.md" diff --git a/docs/swarms/structs/matrix_swarm.md b/docs/swarms/structs/matrix_swarm.md new file mode 100644 index 00000000..0ed3c190 --- /dev/null +++ b/docs/swarms/structs/matrix_swarm.md @@ -0,0 +1,247 @@ +# MatrixSwarm + +The `MatrixSwarm` class provides a framework for managing and operating on matrices of AI agents, enabling matrix-like operations similar to linear algebra. This allows for complex agent interactions and parallel processing capabilities. + +## Overview + +`MatrixSwarm` treats AI agents as elements in a matrix, allowing for operations like addition, multiplication, and transposition. This approach enables sophisticated agent orchestration and parallel processing patterns. + +## Installation + +```bash +pip3 install -U swarms +``` + +## Basic Usage + +```python +from swarms import Agent +from swarms.matrix import MatrixSwarm + +# Create a 2x2 matrix of agents +agents = [ + [Agent(agent_name="Agent-0-0"), Agent(agent_name="Agent-0-1")], + [Agent(agent_name="Agent-1-0"), Agent(agent_name="Agent-1-1")] +] + +# Initialize the matrix +matrix = MatrixSwarm(agents) +``` + +## Class Constructor + +```python +def __init__(self, agents: List[List[Agent]]) +``` + +### Parameters +- `agents` (`List[List[Agent]]`): A 2D list of Agent instances representing the matrix. + +### Raises +- `ValueError`: If the input is not a valid 2D list of Agent instances. + +## Methods + +### transpose() + +Transposes the matrix of agents by swapping rows and columns. + +```python +def transpose(self) -> MatrixSwarm +``` + +#### Returns +- `MatrixSwarm`: A new MatrixSwarm instance with transposed dimensions. + +--- + +### add(other) + +Performs element-wise addition of two agent matrices. + +```python +def add(self, other: MatrixSwarm) -> MatrixSwarm +``` + +#### Parameters +- `other` (`MatrixSwarm`): Another MatrixSwarm instance to add. + +#### Returns +- `MatrixSwarm`: A new MatrixSwarm resulting from the addition. + +#### Raises +- `ValueError`: If matrix dimensions are incompatible. + +--- + +### scalar_multiply(scalar) + +Scales the matrix by duplicating agents along rows. + +```python +def scalar_multiply(self, scalar: int) -> MatrixSwarm +``` + +#### Parameters +- `scalar` (`int`): The multiplication factor. + +#### Returns +- `MatrixSwarm`: A new MatrixSwarm with scaled dimensions. + +--- + +### multiply(other, inputs) + +Performs matrix multiplication (dot product) between two agent matrices. + +```python +def multiply(self, other: MatrixSwarm, inputs: List[str]) -> List[List[AgentOutput]] +``` + +#### Parameters +- `other` (`MatrixSwarm`): The second MatrixSwarm for multiplication. +- `inputs` (`List[str]`): Input queries for the agents. + +#### Returns +- `List[List[AgentOutput]]`: Matrix of operation results. + +#### Raises +- `ValueError`: If matrix dimensions are incompatible for multiplication. + +--- + +### subtract(other) + +Performs element-wise subtraction of two agent matrices. + +```python +def subtract(self, other: MatrixSwarm) -> MatrixSwarm +``` + +#### Parameters +- `other` (`MatrixSwarm`): Another MatrixSwarm to subtract. + +#### Returns +- `MatrixSwarm`: A new MatrixSwarm resulting from the subtraction. + +--- + +### identity(size) + +Creates an identity matrix of agents. + +```python +def identity(self, size: int) -> MatrixSwarm +``` + +#### Parameters +- `size` (`int`): Size of the identity matrix (NxN). + +#### Returns +- `MatrixSwarm`: An identity MatrixSwarm. + +--- + +### determinant() + +Computes the determinant of a square agent matrix. + +```python +def determinant(self) -> Any +``` + +#### Returns +- `Any`: The determinant result. + +#### Raises +- `ValueError`: If the matrix is not square. + +--- + +### save_to_file(path) + +Saves the matrix structure and metadata to a JSON file. + +```python +def save_to_file(self, path: str) -> None +``` + +#### Parameters +- `path` (`str`): File path for saving the matrix data. + +## Extended Example + +Here's a comprehensive example demonstrating various MatrixSwarm operations: + +```python +from swarms import Agent +from swarms.matrix import MatrixSwarm + +# Create agents with specific configurations +agents = [ + [ + Agent( + agent_name=f"Agent-{i}-{j}", + system_prompt="Your system prompt here", + model_name="gpt-4", + max_loops=1, + verbose=True + ) for j in range(2) + ] for i in range(2) +] + +# Initialize matrix +matrix = MatrixSwarm(agents) + +# Example operations +transposed = matrix.transpose() +scaled = matrix.scalar_multiply(2) + +# Run operations with inputs +inputs = ["Query 1", "Query 2"] +results = matrix.multiply(transposed, inputs) + +# Save results +matrix.save_to_file("matrix_results.json") +``` + +## Output Schema + +The `AgentOutput` class defines the structure for operation results: + +```python +class AgentOutput(BaseModel): + agent_name: str + input_query: str + output_result: Any + metadata: dict +``` + +## Best Practices + +1. **Initialization** + - Ensure all agents in the matrix are properly configured before initialization + - Validate matrix dimensions for your use case + +2. **Operation Performance** + - Consider computational costs for large matrices + - Use appropriate batch sizes for inputs + +3. **Error Handling** + - Implement proper error handling for agent operations + - Validate inputs before matrix operations + +4. **Resource Management** + - Monitor agent resource usage in large matrices + - Implement proper cleanup procedures + +## Limitations + +- Matrix operations are constrained by the underlying agent capabilities +- Performance may vary based on agent configuration and complexity +- Resource usage scales with matrix dimensions + +## See Also + +- [Swarms Documentation](https://github.com/kyegomez/swarms) +- [Agent Class Reference](https://github.com/kyegomez/swarms/tree/main/swarms) \ No newline at end of file diff --git a/docs/swarms/structs/swarm_router.md b/docs/swarms/structs/swarm_router.md index 07d8c2f5..53781837 100644 --- a/docs/swarms/structs/swarm_router.md +++ b/docs/swarms/structs/swarm_router.md @@ -33,7 +33,7 @@ Main class for routing tasks to different swarm types. | `flow` | str | The flow of the swarm. | | `return_json` | bool | Flag to enable/disable returning the result in JSON format. | | `auto_generate_prompts` | bool | Flag to enable/disable auto generation of prompts. | -| `swarm` | Union[AgentRearrange, MixtureOfAgents, SpreadSheetSwarm, SequentialWorkflow, ConcurrentWorkflow] | Instantiated swarm object. | +| `swarm` | Union[AgentRearrange, MixtureOfAgents, SpreadSheetSwarm, SequentialWorkflow, ConcurrentWorkflow, GroupChat, MultiAgentRouter] | Instantiated swarm object. | | `logs` | List[SwarmLog] | List of log entries captured during operations. | #### Methods: @@ -271,6 +271,39 @@ result = concurrent_router.run("Conduct a comprehensive market analysis for Prod ``` +### GroupChat + +Use Case: Simulating a group chat with multiple agents. + +```python +group_chat_router = SwarmRouter( + name="GroupChat", + description="Simulate a group chat with multiple agents", + max_loops=1, + agents=[financial_analyst, market_researcher, competitor_analyst], + swarm_type="GroupChat" +) + +result = group_chat_router.run("Conduct a comprehensive market analysis for Product X") +``` + +### MultiAgentRouter + +Use Case: Simulating a group chat with multiple agents. + +```python +multi_agent_router = SwarmRouter( + name="MultiAgentRouter", + description="Simulate a group chat with multiple agents", + max_loops=1, + agents=[financial_analyst, market_researcher, competitor_analyst], + swarm_type="MultiAgentRouter" +) + +result = multi_agent_router.run("Conduct a comprehensive market analysis for Product X") +``` + + ### Auto Select (Experimental) Autonomously selects the right swarm by conducting vector search on your input task or name or description or all 3. diff --git a/docs/swarms_memory/index.md b/docs/swarms_memory/index.md index 3d96b4ef..3b4011b0 100644 --- a/docs/swarms_memory/index.md +++ b/docs/swarms_memory/index.md @@ -161,7 +161,7 @@ print(result) We're excited to see how you leverage Swarms-Memory in your projects! Join our community on Discord to share your experiences, ask questions, and stay updated on the latest developments. - **🐦 Twitter**: [Follow us on Twitter](https://twitter.com/swarms_platform) -- **📢 Discord**: [Join the Agora Discord](https://discord.gg/agora) +- **📢 Discord**: [Join the Agora Discord](https://discord.gg/jM3Z6M9uMq) - **Swarms Platform**: [Visit our website](https://swarms.ai) - **📙 Documentation**: [Read the Docs](https://docs.swarms.ai) diff --git a/test_matrix_swarm.py b/test_matrix_swarm.py deleted file mode 100644 index 423640f1..00000000 --- a/test_matrix_swarm.py +++ /dev/null @@ -1,216 +0,0 @@ -from swarms.structs.matrix_swarm import MatrixSwarm, AgentOutput -from swarms import Agent - - -def create_test_matrix(rows: int, cols: int) -> MatrixSwarm: - """Helper function to create a test agent matrix""" - agents = [ - [ - Agent( - agent_name=f"TestAgent-{i}-{j}", - system_prompt="Test prompt", - ) - for j in range(cols) - ] - for i in range(rows) - ] - return MatrixSwarm(agents) - - -def test_init(): - """Test MatrixSwarm initialization""" - # Test valid initialization - matrix = create_test_matrix(2, 2) - assert isinstance(matrix, MatrixSwarm) - assert len(matrix.agents) == 2 - assert len(matrix.agents[0]) == 2 - - # Test invalid initialization - try: - MatrixSwarm([[1, 2], [3, 4]]) # Non-agent elements - assert False, "Should raise ValueError" - except ValueError: - pass - - try: - MatrixSwarm([]) # Empty matrix - assert False, "Should raise ValueError" - except ValueError: - pass - - -def test_transpose(): - """Test matrix transpose operation""" - matrix = create_test_matrix(2, 3) - transposed = matrix.transpose() - - assert len(transposed.agents) == 3 # Original cols become rows - assert len(transposed.agents[0]) == 2 # Original rows become cols - - # Verify agent positions - for i in range(2): - for j in range(3): - assert ( - matrix.agents[i][j].agent_name - == transposed.agents[j][i].agent_name - ) - - -def test_add(): - """Test matrix addition""" - matrix1 = create_test_matrix(2, 2) - matrix2 = create_test_matrix(2, 2) - - result = matrix1.add(matrix2) - assert len(result.agents) == 2 - assert len(result.agents[0]) == 2 - - # Test incompatible dimensions - matrix3 = create_test_matrix(2, 3) - try: - matrix1.add(matrix3) - assert False, "Should raise ValueError" - except ValueError: - pass - - -def test_scalar_multiply(): - """Test scalar multiplication""" - matrix = create_test_matrix(2, 2) - scalar = 3 - result = matrix.scalar_multiply(scalar) - - assert len(result.agents) == 2 - assert len(result.agents[0]) == 2 * scalar - - # Verify agent duplication - for i in range(len(result.agents)): - for j in range(0, len(result.agents[0]), scalar): - original_agent = matrix.agents[i][j // scalar] - for k in range(scalar): - assert ( - result.agents[i][j + k].agent_name - == original_agent.agent_name - ) - - -def test_multiply(): - """Test matrix multiplication""" - matrix1 = create_test_matrix(2, 3) - matrix2 = create_test_matrix(3, 2) - inputs = ["test query 1", "test query 2"] - - result = matrix1.multiply(matrix2, inputs) - assert len(result) == 2 # Number of rows in first matrix - assert len(result[0]) == 2 # Number of columns in second matrix - - # Verify output structure - for row in result: - for output in row: - assert isinstance(output, AgentOutput) - assert isinstance(output.input_query, str) - assert isinstance(output.metadata, dict) - - -def test_subtract(): - """Test matrix subtraction""" - matrix1 = create_test_matrix(2, 2) - matrix2 = create_test_matrix(2, 2) - - result = matrix1.subtract(matrix2) - assert len(result.agents) == 2 - assert len(result.agents[0]) == 2 - - -def test_identity(): - """Test identity matrix creation""" - matrix = create_test_matrix(3, 3) - identity = matrix.identity(3) - - assert len(identity.agents) == 3 - assert len(identity.agents[0]) == 3 - - # Verify diagonal elements are from original matrix - for i in range(3): - assert ( - identity.agents[i][i].agent_name - == matrix.agents[i][i].agent_name - ) - - # Verify non-diagonal elements are zero agents - for j in range(3): - if i != j: - assert identity.agents[i][j].agent_name.startswith( - "Zero-Agent" - ) - - -def test_determinant(): - """Test determinant calculation""" - # Test 1x1 matrix - matrix1 = create_test_matrix(1, 1) - det1 = matrix1.determinant() - assert det1 is not None - - # Test 2x2 matrix - matrix2 = create_test_matrix(2, 2) - det2 = matrix2.determinant() - assert det2 is not None - - # Test non-square matrix - matrix3 = create_test_matrix(2, 3) - try: - matrix3.determinant() - assert False, "Should raise ValueError" - except ValueError: - pass - - -def test_save_to_file(tmp_path): - """Test saving matrix to file""" - import os - - matrix = create_test_matrix(2, 2) - file_path = os.path.join(tmp_path, "test_matrix.json") - - matrix.save_to_file(file_path) - assert os.path.exists(file_path) - - # Verify file contents - import json - - with open(file_path, "r") as f: - data = json.load(f) - assert "agents" in data - assert "outputs" in data - assert len(data["agents"]) == 2 - assert len(data["agents"][0]) == 2 - - -def run_all_tests(): - """Run all test functions""" - test_functions = [ - test_init, - test_transpose, - test_add, - test_scalar_multiply, - test_multiply, - test_subtract, - test_identity, - test_determinant, - ] - - for test_func in test_functions: - try: - test_func() - print(f"✅ {test_func.__name__} passed") - except AssertionError as e: - print(f"❌ {test_func.__name__} failed: {str(e)}") - except Exception as e: - print( - f"❌ {test_func.__name__} failed with exception: {str(e)}" - ) - - -if __name__ == "__main__": - run_all_tests() diff --git a/tests/structs/test_matrix_swarm.py b/tests/structs/test_matrix_swarm.py index e69de29b..d10fe55e 100644 --- a/tests/structs/test_matrix_swarm.py +++ b/tests/structs/test_matrix_swarm.py @@ -0,0 +1,217 @@ +from swarms.structs.matrix_swarm import MatrixSwarm, AgentOutput +from swarms import Agent + + +def create_test_matrix(rows: int, cols: int) -> MatrixSwarm: + """Helper function to create a test agent matrix""" + agents = [ + [ + Agent( + agent_name=f"TestAgent-{i}-{j}", + model_name="gpt-4o", + system_prompt="Test prompt", + ) + for j in range(cols) + ] + for i in range(rows) + ] + return MatrixSwarm(agents) + + +def test_init(): + """Test MatrixSwarm initialization""" + # Test valid initialization + matrix = create_test_matrix(2, 2) + assert isinstance(matrix, MatrixSwarm) + assert len(matrix.agents) == 2 + assert len(matrix.agents[0]) == 2 + + # Test invalid initialization + try: + MatrixSwarm([[1, 2], [3, 4]]) # Non-agent elements + assert False, "Should raise ValueError" + except ValueError: + pass + + try: + MatrixSwarm([]) # Empty matrix + assert False, "Should raise ValueError" + except ValueError: + pass + + +def test_transpose(): + """Test matrix transpose operation""" + matrix = create_test_matrix(2, 3) + transposed = matrix.transpose() + + assert len(transposed.agents) == 3 # Original cols become rows + assert len(transposed.agents[0]) == 2 # Original rows become cols + + # Verify agent positions + for i in range(2): + for j in range(3): + assert ( + matrix.agents[i][j].agent_name + == transposed.agents[j][i].agent_name + ) + + +def test_add(): + """Test matrix addition""" + matrix1 = create_test_matrix(2, 2) + matrix2 = create_test_matrix(2, 2) + + result = matrix1.add(matrix2) + assert len(result.agents) == 2 + assert len(result.agents[0]) == 2 + + # Test incompatible dimensions + matrix3 = create_test_matrix(2, 3) + try: + matrix1.add(matrix3) + assert False, "Should raise ValueError" + except ValueError: + pass + + +def test_scalar_multiply(): + """Test scalar multiplication""" + matrix = create_test_matrix(2, 2) + scalar = 3 + result = matrix.scalar_multiply(scalar) + + assert len(result.agents) == 2 + assert len(result.agents[0]) == 2 * scalar + + # Verify agent duplication + for i in range(len(result.agents)): + for j in range(0, len(result.agents[0]), scalar): + original_agent = matrix.agents[i][j // scalar] + for k in range(scalar): + assert ( + result.agents[i][j + k].agent_name + == original_agent.agent_name + ) + + +def test_multiply(): + """Test matrix multiplication""" + matrix1 = create_test_matrix(2, 3) + matrix2 = create_test_matrix(3, 2) + inputs = ["test query 1", "test query 2"] + + result = matrix1.multiply(matrix2, inputs) + assert len(result) == 2 # Number of rows in first matrix + assert len(result[0]) == 2 # Number of columns in second matrix + + # Verify output structure + for row in result: + for output in row: + assert isinstance(output, AgentOutput) + assert isinstance(output.input_query, str) + assert isinstance(output.metadata, dict) + + +def test_subtract(): + """Test matrix subtraction""" + matrix1 = create_test_matrix(2, 2) + matrix2 = create_test_matrix(2, 2) + + result = matrix1.subtract(matrix2) + assert len(result.agents) == 2 + assert len(result.agents[0]) == 2 + + +def test_identity(): + """Test identity matrix creation""" + matrix = create_test_matrix(3, 3) + identity = matrix.identity(3) + + assert len(identity.agents) == 3 + assert len(identity.agents[0]) == 3 + + # Verify diagonal elements are from original matrix + for i in range(3): + assert ( + identity.agents[i][i].agent_name + == matrix.agents[i][i].agent_name + ) + + # Verify non-diagonal elements are zero agents + for j in range(3): + if i != j: + assert identity.agents[i][j].agent_name.startswith( + "Zero-Agent" + ) + + +def test_determinant(): + """Test determinant calculation""" + # Test 1x1 matrix + matrix1 = create_test_matrix(1, 1) + det1 = matrix1.determinant() + assert det1 is not None + + # Test 2x2 matrix + matrix2 = create_test_matrix(2, 2) + det2 = matrix2.determinant() + assert det2 is not None + + # Test non-square matrix + matrix3 = create_test_matrix(2, 3) + try: + matrix3.determinant() + assert False, "Should raise ValueError" + except ValueError: + pass + + +def test_save_to_file(tmp_path): + """Test saving matrix to file""" + import os + + matrix = create_test_matrix(2, 2) + file_path = os.path.join(tmp_path, "test_matrix.json") + + matrix.save_to_file(file_path) + assert os.path.exists(file_path) + + # Verify file contents + import json + + with open(file_path, "r") as f: + data = json.load(f) + assert "agents" in data + assert "outputs" in data + assert len(data["agents"]) == 2 + assert len(data["agents"][0]) == 2 + + +def run_all_tests(): + """Run all test functions""" + test_functions = [ + test_init, + test_transpose, + test_add, + test_scalar_multiply, + test_multiply, + test_subtract, + test_identity, + test_determinant, + ] + + for test_func in test_functions: + try: + test_func() + print(f"✅ {test_func.__name__} passed") + except AssertionError as e: + print(f"❌ {test_func.__name__} failed: {str(e)}") + except Exception as e: + print( + f"❌ {test_func.__name__} failed with exception: {str(e)}" + ) + + +if __name__ == "__main__": + run_all_tests()