Skip to content

Commit e6cd7a8

Browse files
authored
Merge pull request #1326 from hughiwnl/autosavelogic2
autosave logic for sequential and concurrent
2 parents bf6e06f + a767693 commit e6cd7a8

File tree

6 files changed

+352
-1
lines changed

6 files changed

+352
-1
lines changed

examples/multi_agent/concurrent_examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ This directory contains examples demonstrating concurrent execution patterns for
44

55
## Examples
66

7+
- [concurrent_workflow_autosave_example.py](concurrent_workflow_autosave_example.py) - **Autosave feature example** - Shows how to automatically save conversation history
78
- [asi.py](asi.py) - ASI (Artificial Super Intelligence) example
89
- [concurrent_example_dashboard.py](concurrent_example_dashboard.py) - Dashboard for concurrent workflows
910
- [concurrent_example.py](concurrent_example.py) - Basic concurrent execution
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/env python3
2+
"""
3+
ConcurrentWorkflow Autosave Example
4+
5+
This example demonstrates how to use the autosave feature to automatically
6+
save conversation history after workflow execution.
7+
8+
Usage:
9+
python concurrent_workflow_autosave_example.py
10+
"""
11+
12+
from swarms import Agent, ConcurrentWorkflow
13+
14+
15+
def main():
16+
"""Example: Using ConcurrentWorkflow with autosave enabled."""
17+
18+
# Create worker agents
19+
writer = Agent(
20+
agent_name="Writer",
21+
agent_description="Content writer",
22+
model_name="gpt-4o-mini",
23+
max_loops=1,
24+
verbose=False,
25+
)
26+
27+
editor = Agent(
28+
agent_name="Editor",
29+
agent_description="Content editor",
30+
model_name="gpt-4o-mini",
31+
max_loops=1,
32+
verbose=False,
33+
)
34+
35+
# Create workflow with autosave enabled
36+
# No need to set WORKSPACE_DIR - it defaults to 'agent_workspace' automatically!
37+
workflow = ConcurrentWorkflow(
38+
name="content-workflow",
39+
description="Content creation workflow",
40+
agents=[writer, editor],
41+
autosave=True, # Enable autosave - conversation will be saved automatically
42+
)
43+
44+
print(f"Workspace directory: {workflow.swarm_workspace_dir}")
45+
46+
# Run a task
47+
result = workflow.run("Write a short paragraph about artificial intelligence.")
48+
49+
# Conversation history is automatically saved to:
50+
# {workspace_dir}/swarms/ConcurrentWorkflow/content-workflow-{timestamp}/conversation_history.json
51+
print(f"\n✅ Task completed! Conversation saved to:")
52+
print(f" {workflow.swarm_workspace_dir}/conversation_history.json")
53+
54+
55+
if __name__ == "__main__":
56+
# No setup needed - autosave works out of the box!
57+
# WORKSPACE_DIR defaults to 'agent_workspace' if not set
58+
main()

examples/multi_agent/sequential_workflow/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ This directory contains examples demonstrating sequential workflow patterns for
44

55
## Examples
66

7+
- [sequential_workflow_autosave_example.py](sequential_workflow_autosave_example.py) - **Autosave feature example** - Shows how to automatically save conversation history
78
- [concurrent_workflow.py](concurrent_workflow.py) - Concurrent workflow patterns
89
- [sequential_wofkflow.py](sequential_wofkflow.py) - Sequential workflow (typo in filename)
910
- [sequential_worflow_test.py](sequential_worflow_test.py) - Sequential workflow testing
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env python3
2+
"""
3+
SequentialWorkflow Autosave Example
4+
5+
This example demonstrates how to use the autosave feature to automatically
6+
save conversation history after workflow execution.
7+
8+
Usage:
9+
python sequential_workflow_autosave_example.py
10+
"""
11+
12+
from swarms import Agent, SequentialWorkflow
13+
14+
15+
def main():
16+
"""Example: Using SequentialWorkflow with autosave enabled."""
17+
18+
# Create worker agents
19+
writer = Agent(
20+
agent_name="Writer",
21+
agent_description="Content writer",
22+
model_name="gpt-4o-mini",
23+
max_loops=1,
24+
verbose=False,
25+
)
26+
27+
editor = Agent(
28+
agent_name="Editor",
29+
agent_description="Content editor",
30+
model_name="gpt-4o-mini",
31+
max_loops=1,
32+
verbose=False,
33+
)
34+
35+
# Create workflow with autosave enabled
36+
# No need to set WORKSPACE_DIR - it defaults to 'agent_workspace' automatically!
37+
workflow = SequentialWorkflow(
38+
name="content-workflow",
39+
description="Content creation workflow",
40+
agents=[writer, editor],
41+
max_loops=1,
42+
autosave=True, # Enable autosave - conversation will be saved automatically
43+
)
44+
45+
print(f"Workspace directory: {workflow.swarm_workspace_dir}")
46+
47+
# Run a task
48+
result = workflow.run("Write a short paragraph about artificial intelligence.")
49+
50+
# Conversation history is automatically saved to:
51+
# {workspace_dir}/swarms/SequentialWorkflow/content-workflow-{timestamp}/conversation_history.json
52+
print(f"\n✅ Task completed! Conversation saved to:")
53+
print(f" {workflow.swarm_workspace_dir}/conversation_history.json")
54+
55+
56+
if __name__ == "__main__":
57+
# No setup needed - autosave works out of the box!
58+
# WORKSPACE_DIR defaults to 'agent_workspace' if not set
59+
main()

swarms/structs/concurrent_workflow.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import concurrent.futures
2+
import json
3+
import os
24
import time
35
from typing import Callable, List, Optional, Union
46

7+
from loguru import logger as loguru_logger
58
from swarms.structs.agent import Agent
69
from swarms.structs.conversation import Conversation
710
from swarms.structs.swarm_id import swarm_id
@@ -11,6 +14,8 @@
1114
history_output_formatter,
1215
)
1316
from swarms.utils.loguru_logger import initialize_logger
17+
from swarms.utils.swarm_autosave import get_swarm_workspace_dir
18+
from swarms.utils.workspace_utils import get_workspace_dir
1419

1520
logger = initialize_logger(log_folder="concurrent_workflow")
1621

@@ -76,6 +81,8 @@ def __init__(
7681
max_loops: int = 1,
7782
auto_generate_prompts: bool = False,
7883
show_dashboard: bool = False,
84+
autosave: bool = True,
85+
verbose: bool = False,
7986
):
8087
self.id = id if id is not None else swarm_id()
8188
self.name = name
@@ -86,6 +93,9 @@ def __init__(
8693
self.auto_generate_prompts = auto_generate_prompts
8794
self.output_type = output_type
8895
self.show_dashboard = show_dashboard
96+
self.autosave = autosave
97+
self.verbose = verbose
98+
self.swarm_workspace_dir = None
8999
self.metadata_output_path = (
90100
f"concurrent_workflow_name_{name}_id_{self.id}.json"
91101
)
@@ -107,6 +117,10 @@ def __init__(
107117
if self.show_dashboard is True:
108118
self.agents = self.fix_agents()
109119

120+
# Setup autosave workspace if enabled
121+
if self.autosave:
122+
self._setup_autosave()
123+
110124
def fix_agents(self):
111125
"""
112126
Configure agents for dashboard mode.
@@ -554,7 +568,27 @@ def run(
554568
result = self._run(
555569
task, img, imgs, streaming_callback
556570
)
571+
572+
# Save conversation history after successful execution
573+
if self.autosave and self.swarm_workspace_dir:
574+
try:
575+
self._save_conversation_history()
576+
except Exception as e:
577+
logger.warning(
578+
f"Failed to save conversation history: {e}"
579+
)
580+
557581
return result
582+
except Exception as e:
583+
# Save conversation history on error
584+
if self.autosave and self.swarm_workspace_dir:
585+
try:
586+
self._save_conversation_history()
587+
except Exception as save_error:
588+
logger.warning(
589+
f"Failed to save conversation history on error: {save_error}"
590+
)
591+
raise
558592
finally:
559593
# Always cleanup resources
560594
self.cleanup()
@@ -599,3 +633,84 @@ def batch_run(
599633
)
600634
)
601635
return results
636+
637+
def _setup_autosave(self):
638+
"""
639+
Setup workspace directory for saving conversation history.
640+
641+
Creates the workspace directory structure if autosave is enabled.
642+
Only conversation history will be saved to this directory.
643+
"""
644+
try:
645+
# Set default workspace directory if not set
646+
if not os.getenv("WORKSPACE_DIR"):
647+
default_workspace = os.path.join(os.getcwd(), "agent_workspace")
648+
os.environ["WORKSPACE_DIR"] = default_workspace
649+
# Clear the cache so get_workspace_dir() picks up the new value
650+
get_workspace_dir.cache_clear()
651+
if self.verbose:
652+
loguru_logger.info(
653+
f"WORKSPACE_DIR not set, using default: {default_workspace}"
654+
)
655+
656+
class_name = self.__class__.__name__
657+
swarm_name = self.name or "concurrent-workflow"
658+
self.swarm_workspace_dir = get_swarm_workspace_dir(
659+
class_name, swarm_name, use_timestamp=True
660+
)
661+
662+
if self.swarm_workspace_dir:
663+
if self.verbose:
664+
loguru_logger.info(
665+
f"Autosave enabled. Conversation history will be saved to: {self.swarm_workspace_dir}"
666+
)
667+
except Exception as e:
668+
loguru_logger.warning(
669+
f"Failed to setup autosave for ConcurrentWorkflow: {e}"
670+
)
671+
# Don't raise - autosave failures shouldn't break initialization
672+
self.swarm_workspace_dir = None
673+
674+
def _save_conversation_history(self):
675+
"""
676+
Save conversation history as a separate JSON file to the workspace directory.
677+
678+
Saves the conversation history to:
679+
workspace_dir/swarms/ConcurrentWorkflow/{workflow-name}-{id}/conversation_history.json
680+
"""
681+
if not self.swarm_workspace_dir:
682+
return
683+
684+
try:
685+
# Get conversation history
686+
conversation_data = []
687+
if hasattr(self, "conversation") and self.conversation:
688+
if hasattr(self.conversation, "conversation_history"):
689+
conversation_data = self.conversation.conversation_history
690+
elif hasattr(self.conversation, "to_dict"):
691+
conversation_data = self.conversation.to_dict()
692+
else:
693+
conversation_data = []
694+
695+
# Create conversation history file path
696+
conversation_path = os.path.join(
697+
self.swarm_workspace_dir, "conversation_history.json"
698+
)
699+
700+
# Save conversation history as JSON
701+
with open(conversation_path, "w", encoding="utf-8") as f:
702+
json.dump(
703+
conversation_data,
704+
f,
705+
indent=2,
706+
default=str,
707+
)
708+
709+
if self.verbose:
710+
loguru_logger.debug(
711+
f"Saved conversation history to {conversation_path}"
712+
)
713+
except Exception as e:
714+
loguru_logger.warning(
715+
f"Failed to save conversation history: {e}"
716+
)

0 commit comments

Comments
 (0)