master
parent
1ab3eeea55
commit
e3ef675fc1
@ -0,0 +1,73 @@
|
|||||||
|
name: Docker Build and Publish
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
# Publish semver tags as releases
|
||||||
|
tags: [ 'v*.*.*' ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "master" ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
# Use docker.io for Docker Hub if empty
|
||||||
|
REGISTRY: docker.io
|
||||||
|
# github.repository as <account>/<repo>
|
||||||
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
# This is used to complete the identity challenge
|
||||||
|
# with sigstore/fulcio when running outside of PRs.
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# Setup QEMU for multi-platform builds
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
# Setup Docker BuildX
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
# Login to Docker Hub
|
||||||
|
- name: Log into registry ${{ env.REGISTRY }}
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
# Extract metadata (tags, labels) for Docker
|
||||||
|
- name: Extract Docker metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
tags: |
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=pr
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}}
|
||||||
|
type=sha
|
||||||
|
|
||||||
|
# Build and push Docker image
|
||||||
|
- name: Build and push Docker image
|
||||||
|
id: build-and-push
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
@ -0,0 +1,65 @@
|
|||||||
|
from swarms import Agent
|
||||||
|
from swarms.structs.concurrent_workflow import ConcurrentWorkflow
|
||||||
|
|
||||||
|
# Initialize market research agent
|
||||||
|
market_researcher = Agent(
|
||||||
|
agent_name="Market-Researcher",
|
||||||
|
system_prompt="""You are a market research specialist. Your tasks include:
|
||||||
|
1. Analyzing market trends and patterns
|
||||||
|
2. Identifying market opportunities and threats
|
||||||
|
3. Evaluating competitor strategies
|
||||||
|
4. Assessing customer needs and preferences
|
||||||
|
5. Providing actionable market insights""",
|
||||||
|
model_name="claude-3-sonnet-20240229",
|
||||||
|
max_loops=1,
|
||||||
|
temperature=0.7,
|
||||||
|
# streaming_on=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Initialize financial analyst agent
|
||||||
|
financial_analyst = Agent(
|
||||||
|
agent_name="Financial-Analyst",
|
||||||
|
system_prompt="""You are a financial analysis expert. Your responsibilities include:
|
||||||
|
1. Analyzing financial statements
|
||||||
|
2. Evaluating investment opportunities
|
||||||
|
3. Assessing risk factors
|
||||||
|
4. Providing financial forecasts
|
||||||
|
5. Recommending financial strategies""",
|
||||||
|
model_name="claude-3-sonnet-20240229",
|
||||||
|
max_loops=1,
|
||||||
|
# streaming_on=True,
|
||||||
|
temperature=0.7,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Initialize technical analyst agent
|
||||||
|
technical_analyst = Agent(
|
||||||
|
agent_name="Technical-Analyst",
|
||||||
|
system_prompt="""You are a technical analysis specialist. Your focus areas include:
|
||||||
|
1. Analyzing price patterns and trends
|
||||||
|
2. Evaluating technical indicators
|
||||||
|
3. Identifying support and resistance levels
|
||||||
|
4. Assessing market momentum
|
||||||
|
5. Providing trading recommendations""",
|
||||||
|
model_name="claude-3-sonnet-20240229",
|
||||||
|
max_loops=1,
|
||||||
|
temperature=0.7,
|
||||||
|
# streaming_on=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create list of agents
|
||||||
|
agents = [market_researcher, financial_analyst, technical_analyst]
|
||||||
|
|
||||||
|
|
||||||
|
router = ConcurrentWorkflow(
|
||||||
|
name="market-analysis-router",
|
||||||
|
agents=agents,
|
||||||
|
max_loops=1,
|
||||||
|
# output_type="all",
|
||||||
|
show_dashboard=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
result = router.run(
|
||||||
|
"Analyze Tesla (TSLA) stock from market, financial, and technical perspectives"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(result)
|
@ -0,0 +1,55 @@
|
|||||||
|
from swarms import Agent
|
||||||
|
from swarms.structs.ma_utils import create_agent_map
|
||||||
|
|
||||||
|
# Initialize market research agent
|
||||||
|
market_researcher = Agent(
|
||||||
|
agent_name="Market-Researcher",
|
||||||
|
system_prompt="""You are a market research specialist. Your tasks include:
|
||||||
|
1. Analyzing market trends and patterns
|
||||||
|
2. Identifying market opportunities and threats
|
||||||
|
3. Evaluating competitor strategies
|
||||||
|
4. Assessing customer needs and preferences
|
||||||
|
5. Providing actionable market insights""",
|
||||||
|
model_name="claude-3-sonnet-20240229",
|
||||||
|
max_loops=1,
|
||||||
|
temperature=0.7,
|
||||||
|
# streaming_on=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Initialize financial analyst agent
|
||||||
|
financial_analyst = Agent(
|
||||||
|
agent_name="Financial-Analyst",
|
||||||
|
system_prompt="""You are a financial analysis expert. Your responsibilities include:
|
||||||
|
1. Analyzing financial statements
|
||||||
|
2. Evaluating investment opportunities
|
||||||
|
3. Assessing risk factors
|
||||||
|
4. Providing financial forecasts
|
||||||
|
5. Recommending financial strategies""",
|
||||||
|
model_name="claude-3-sonnet-20240229",
|
||||||
|
max_loops=1,
|
||||||
|
# streaming_on=True,
|
||||||
|
temperature=0.7,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Initialize technical analyst agent
|
||||||
|
technical_analyst = Agent(
|
||||||
|
agent_name="Technical-Analyst",
|
||||||
|
system_prompt="""You are a technical analysis specialist. Your focus areas include:
|
||||||
|
1. Analyzing price patterns and trends
|
||||||
|
2. Evaluating technical indicators
|
||||||
|
3. Identifying support and resistance levels
|
||||||
|
4. Assessing market momentum
|
||||||
|
5. Providing trading recommendations""",
|
||||||
|
model_name="claude-3-sonnet-20240229",
|
||||||
|
max_loops=1,
|
||||||
|
temperature=0.7,
|
||||||
|
# streaming_on=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create list of agents
|
||||||
|
agents = [market_researcher, financial_analyst, technical_analyst]
|
||||||
|
|
||||||
|
out = create_agent_map(agents)
|
||||||
|
print(out)
|
||||||
|
|
||||||
|
print(out.keys())
|
@ -1,57 +1,130 @@
|
|||||||
from concurrent.futures import Future
|
from swarms import Agent
|
||||||
from unittest.mock import Mock, create_autospec, patch
|
from swarms.structs.concurrent_workflow import ConcurrentWorkflow
|
||||||
|
|
||||||
from swarms.structs import Agent, ConcurrentWorkflow, Task
|
|
||||||
|
def test_basic_workflow():
|
||||||
|
"""Test basic workflow initialization and execution"""
|
||||||
def test_add():
|
# Create test agents
|
||||||
workflow = ConcurrentWorkflow(max_workers=2)
|
agent1 = Agent(
|
||||||
task = Mock(spec=Task)
|
agent_name="Test-Agent-1",
|
||||||
workflow.add(task)
|
system_prompt="You are a test agent 1",
|
||||||
assert task in workflow.tasks
|
model_name="claude-3-sonnet-20240229",
|
||||||
|
max_loops=1,
|
||||||
|
)
|
||||||
def test_run():
|
|
||||||
workflow = ConcurrentWorkflow(max_workers=2)
|
agent2 = Agent(
|
||||||
task1 = create_autospec(Task)
|
agent_name="Test-Agent-2",
|
||||||
task2 = create_autospec(Task)
|
system_prompt="You are a test agent 2",
|
||||||
workflow.add(task1)
|
model_name="claude-3-sonnet-20240229",
|
||||||
workflow.add(task2)
|
max_loops=1,
|
||||||
|
)
|
||||||
with patch(
|
|
||||||
"concurrent.futures.ThreadPoolExecutor"
|
# Create workflow
|
||||||
) as mock_executor:
|
workflow = ConcurrentWorkflow(
|
||||||
future1 = Future()
|
name="test-workflow", agents=[agent1, agent2], max_loops=1
|
||||||
future1.set_result(None)
|
)
|
||||||
future2 = Future()
|
|
||||||
future2.set_result(None)
|
# Run workflow
|
||||||
|
result = workflow.run("Test task")
|
||||||
mock_executor.return_value.__enter__.return_value.submit.side_effect = [
|
|
||||||
future1,
|
# Verify results
|
||||||
future2,
|
assert len(result) == 2
|
||||||
]
|
assert all(isinstance(r, dict) for r in result)
|
||||||
mock_executor.return_value.__enter__.return_value.as_completed.return_value = [
|
assert all("agent" in r and "output" in r for r in result)
|
||||||
future1,
|
|
||||||
future2,
|
|
||||||
]
|
def test_dashboard_workflow():
|
||||||
|
"""Test workflow with dashboard enabled"""
|
||||||
workflow.run()
|
agent = Agent(
|
||||||
|
agent_name="Dashboard-Test-Agent",
|
||||||
task1.execute.assert_called_once()
|
system_prompt="You are a test agent",
|
||||||
task2.execute.assert_called_once()
|
model_name="claude-3-sonnet-20240229",
|
||||||
|
max_loops=1,
|
||||||
|
)
|
||||||
def test_execute_task():
|
|
||||||
workflow = ConcurrentWorkflow(max_workers=2)
|
workflow = ConcurrentWorkflow(
|
||||||
task = create_autospec(Task)
|
name="dashboard-test",
|
||||||
workflow._execute_task(task)
|
agents=[agent],
|
||||||
task.execute.assert_called_once()
|
max_loops=1,
|
||||||
|
show_dashboard=True,
|
||||||
|
)
|
||||||
def test_agent_execution():
|
|
||||||
workflow = ConcurrentWorkflow(max_workers=2)
|
result = workflow.run("Test task")
|
||||||
agent = create_autospec(Agent)
|
|
||||||
task = Task(agent)
|
assert len(result) == 1
|
||||||
workflow.add(task)
|
assert isinstance(result[0], dict)
|
||||||
workflow._execute_task(task)
|
assert "agent" in result[0]
|
||||||
agent.execute.assert_called_once()
|
assert "output" in result[0]
|
||||||
|
|
||||||
|
|
||||||
|
def test_multiple_agents():
|
||||||
|
"""Test workflow with multiple agents"""
|
||||||
|
agents = [
|
||||||
|
Agent(
|
||||||
|
agent_name=f"Agent-{i}",
|
||||||
|
system_prompt=f"You are test agent {i}",
|
||||||
|
model_name="claude-3-sonnet-20240229",
|
||||||
|
max_loops=1,
|
||||||
|
)
|
||||||
|
for i in range(3)
|
||||||
|
]
|
||||||
|
|
||||||
|
workflow = ConcurrentWorkflow(
|
||||||
|
name="multi-agent-test", agents=agents, max_loops=1
|
||||||
|
)
|
||||||
|
|
||||||
|
result = workflow.run("Multi-agent test task")
|
||||||
|
|
||||||
|
assert len(result) == 3
|
||||||
|
assert all(isinstance(r, dict) for r in result)
|
||||||
|
assert all("agent" in r and "output" in r for r in result)
|
||||||
|
|
||||||
|
|
||||||
|
def test_error_handling():
|
||||||
|
"""Test workflow error handling"""
|
||||||
|
# Create an agent that will raise an exception
|
||||||
|
agent = Agent(
|
||||||
|
agent_name="Error-Agent",
|
||||||
|
system_prompt="You are a test agent that will raise an error",
|
||||||
|
model_name="invalid-model", # This will cause an error
|
||||||
|
max_loops=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
workflow = ConcurrentWorkflow(
|
||||||
|
name="error-test", agents=[agent], max_loops=1
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
workflow.run("Test task")
|
||||||
|
assert False, "Expected an error but none was raised"
|
||||||
|
except Exception as e:
|
||||||
|
assert str(e) != "" # Verify we got an error message
|
||||||
|
|
||||||
|
|
||||||
|
def test_max_loops():
|
||||||
|
"""Test workflow respects max_loops setting"""
|
||||||
|
agent = Agent(
|
||||||
|
agent_name="Loop-Test-Agent",
|
||||||
|
system_prompt="You are a test agent",
|
||||||
|
model_name="claude-3-sonnet-20240229",
|
||||||
|
max_loops=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
workflow = ConcurrentWorkflow(
|
||||||
|
name="loop-test",
|
||||||
|
agents=[agent],
|
||||||
|
max_loops=1, # This should override agent's max_loops
|
||||||
|
)
|
||||||
|
|
||||||
|
result = workflow.run("Test task")
|
||||||
|
|
||||||
|
assert len(result) == 1
|
||||||
|
assert isinstance(result[0], dict)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_basic_workflow()
|
||||||
|
test_dashboard_workflow()
|
||||||
|
test_multiple_agents()
|
||||||
|
test_error_handling()
|
||||||
|
test_max_loops()
|
||||||
|
Loading…
Reference in new issue