parent
e06652ed8b
commit
37894599c2
@ -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)
|
@ -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()
|
@ -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()
|
Loading…
Reference in new issue