[FIX][Mcp logic file path name] [Improvement][Majority voting] [Improvement][Agent markdown formatter]
parent
cd75b19127
commit
7b6b7c4980
@ -0,0 +1,165 @@
|
|||||||
|
from swarms import Agent
|
||||||
|
from swarms.structs.majority_voting import MajorityVoting
|
||||||
|
|
||||||
|
# System prompts for different coding expertise areas
|
||||||
|
PYTHON_EXPERT_PROMPT = """You are a senior Python developer with expertise in clean, efficient code.
|
||||||
|
Focus on:
|
||||||
|
- Clean, readable code structure
|
||||||
|
- Pythonic idioms and best practices
|
||||||
|
- Efficient algorithms and data structures
|
||||||
|
- Proper error handling and edge cases
|
||||||
|
- Documentation and code comments"""
|
||||||
|
|
||||||
|
GAME_DEV_EXPERT_PROMPT = """You are a game development specialist with focus on game mechanics.
|
||||||
|
Focus on:
|
||||||
|
- Smooth game loop implementation
|
||||||
|
- Intuitive game controls and mechanics
|
||||||
|
- Game state management
|
||||||
|
- Performance optimization for games
|
||||||
|
- User experience and gameplay flow"""
|
||||||
|
|
||||||
|
SOFTWARE_ARCHITECT_PROMPT = """You are a software architect who designs robust, maintainable systems.
|
||||||
|
Focus on:
|
||||||
|
- Modular, scalable architecture
|
||||||
|
- Separation of concerns
|
||||||
|
- Design patterns and principles
|
||||||
|
- Code maintainability and extensibility
|
||||||
|
- Best practices for larger codebases"""
|
||||||
|
|
||||||
|
CONSENSUS_EVALUATOR_PROMPT = """You are a senior code reviewer and technical lead who evaluates code quality comprehensively.
|
||||||
|
Your evaluation criteria include:
|
||||||
|
|
||||||
|
1. **Code Quality (25%)**:
|
||||||
|
- Readability and clarity
|
||||||
|
- Code structure and organization
|
||||||
|
- Naming conventions
|
||||||
|
- Documentation quality
|
||||||
|
|
||||||
|
2. **Functionality (25%)**:
|
||||||
|
- Correct game mechanics implementation
|
||||||
|
- Complete feature set
|
||||||
|
- Error handling and edge cases
|
||||||
|
- Game stability and robustness
|
||||||
|
|
||||||
|
3. **Performance & Efficiency (20%)**:
|
||||||
|
- Algorithm efficiency
|
||||||
|
- Memory usage optimization
|
||||||
|
- Smooth gameplay performance
|
||||||
|
- Resource management
|
||||||
|
|
||||||
|
4. **Best Practices (15%)**:
|
||||||
|
- Python conventions and idioms
|
||||||
|
- Design patterns usage
|
||||||
|
- Code reusability
|
||||||
|
- Maintainability
|
||||||
|
|
||||||
|
5. **Innovation & Creativity (15%)**:
|
||||||
|
- Creative solutions
|
||||||
|
- Unique features
|
||||||
|
- Code elegance
|
||||||
|
- Problem-solving approach
|
||||||
|
|
||||||
|
Provide detailed analysis with scores for each criterion and a final recommendation.
|
||||||
|
Compare implementations across multiple loops if applicable."""
|
||||||
|
|
||||||
|
|
||||||
|
def create_code_agents():
|
||||||
|
"""Create multiple coding agents with different expertise"""
|
||||||
|
agents = []
|
||||||
|
|
||||||
|
# Python Expert Agent
|
||||||
|
python_expert = Agent(
|
||||||
|
agent_name="Python-Code-Expert",
|
||||||
|
agent_description="Senior Python developer specializing in clean, efficient code",
|
||||||
|
system_prompt=PYTHON_EXPERT_PROMPT,
|
||||||
|
model_name="gpt-4o",
|
||||||
|
max_loops=1,
|
||||||
|
max_tokens=4000,
|
||||||
|
temperature=0.7,
|
||||||
|
)
|
||||||
|
agents.append(python_expert)
|
||||||
|
|
||||||
|
# Game Development Expert Agent
|
||||||
|
game_expert = Agent(
|
||||||
|
agent_name="Game-Dev-Specialist",
|
||||||
|
agent_description="Game development expert focusing on mechanics and user experience",
|
||||||
|
system_prompt=GAME_DEV_EXPERT_PROMPT,
|
||||||
|
model_name="gpt-4o",
|
||||||
|
max_loops=1,
|
||||||
|
max_tokens=4000,
|
||||||
|
temperature=0.7,
|
||||||
|
)
|
||||||
|
agents.append(game_expert)
|
||||||
|
|
||||||
|
return agents
|
||||||
|
|
||||||
|
|
||||||
|
def create_consensus_agent():
|
||||||
|
"""Create the consensus agent for code quality evaluation"""
|
||||||
|
return Agent(
|
||||||
|
agent_name="Code-Quality-Evaluator",
|
||||||
|
agent_description="Senior code reviewer evaluating implementations across multiple criteria",
|
||||||
|
system_prompt=CONSENSUS_EVALUATOR_PROMPT,
|
||||||
|
model_name="gpt-4o",
|
||||||
|
max_loops=1,
|
||||||
|
max_tokens=5000,
|
||||||
|
temperature=0.3, # Lower temperature for more consistent evaluation
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main function to run the Snake game code quality voting example"""
|
||||||
|
|
||||||
|
# Create agents
|
||||||
|
coding_agents = create_code_agents()
|
||||||
|
consensus_agent = create_consensus_agent()
|
||||||
|
|
||||||
|
# Create Majority Voting system with multi-loop capability
|
||||||
|
snake_game_voting = MajorityVoting(
|
||||||
|
name="Snake-Game-Code-Quality-Voting",
|
||||||
|
description="Multi-agent system for creating and evaluating Snake game implementations",
|
||||||
|
agents=coding_agents,
|
||||||
|
consensus_agent=consensus_agent,
|
||||||
|
max_loops=1, # Enable multi-loop refinement
|
||||||
|
verbose=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Define the coding task
|
||||||
|
coding_task = """
|
||||||
|
Create a complete Snake game implementation in Python using the following requirements:
|
||||||
|
|
||||||
|
**Core Requirements:**
|
||||||
|
1. **Game Board**: 20x20 grid with borders
|
||||||
|
2. **Snake**: Starts at center, grows when eating food
|
||||||
|
3. **Food**: Randomly placed, appears after being eaten
|
||||||
|
4. **Controls**: Arrow keys or WASD for movement
|
||||||
|
5. **Game Over**: When snake hits wall or itself
|
||||||
|
6. **Score**: Display current score and high score
|
||||||
|
|
||||||
|
**Technical Requirements:**
|
||||||
|
- Use Python standard library only (no external dependencies)
|
||||||
|
- Clean, well-documented code
|
||||||
|
- Proper error handling
|
||||||
|
- Efficient algorithms
|
||||||
|
- Modular design where possible
|
||||||
|
|
||||||
|
**Advanced Features (Bonus):**
|
||||||
|
- Increasing speed as score grows
|
||||||
|
- Pause functionality
|
||||||
|
- Game restart option
|
||||||
|
- Score persistence
|
||||||
|
- Smooth animations
|
||||||
|
|
||||||
|
**Output Format:**
|
||||||
|
Provide the complete, runnable Python code with proper structure and documentation.
|
||||||
|
Make sure the code is immediately executable and includes a main function.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Run the multi-loop voting system
|
||||||
|
result = snake_game_voting.run(coding_task)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@ -1,189 +0,0 @@
|
|||||||
import json
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
from typing import Dict
|
|
||||||
|
|
||||||
from swarms.utils.loguru_logger import initialize_logger
|
|
||||||
|
|
||||||
|
|
||||||
from swarms.telemetry.main import (
|
|
||||||
log_agent_data,
|
|
||||||
)
|
|
||||||
|
|
||||||
logger = initialize_logger(log_folder="onboarding_process")
|
|
||||||
|
|
||||||
|
|
||||||
class OnboardingProcess:
|
|
||||||
"""
|
|
||||||
This class handles the onboarding process for users. It collects user data including their
|
|
||||||
full name, first name, email, Swarms API key, and system data, then autosaves it in both a
|
|
||||||
main JSON file and a cache file for reliability. It supports loading previously saved or cached data.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
auto_save_path: str = "user_data.json",
|
|
||||||
cache_save_path: str = "user_data_cache.json",
|
|
||||||
) -> None:
|
|
||||||
"""
|
|
||||||
Initializes the OnboardingProcess with an autosave file path and a cache path.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
auto_save_path (str): The path where user data is automatically saved.
|
|
||||||
cache_save_path (str): The path where user data is cached for reliability.
|
|
||||||
"""
|
|
||||||
self.user_data: Dict[str, str] = {}
|
|
||||||
self.auto_save_path = auto_save_path
|
|
||||||
self.cache_save_path = cache_save_path
|
|
||||||
self.load_existing_data()
|
|
||||||
|
|
||||||
def load_existing_data(self) -> None:
|
|
||||||
"""
|
|
||||||
Loads existing user data from the auto-save file or cache if available.
|
|
||||||
"""
|
|
||||||
if os.path.exists(self.auto_save_path):
|
|
||||||
try:
|
|
||||||
with open(self.auto_save_path, "r") as f:
|
|
||||||
self.user_data = json.load(f)
|
|
||||||
logger.info(
|
|
||||||
"Existing user data loaded from {}",
|
|
||||||
self.auto_save_path,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
except json.JSONDecodeError as e:
|
|
||||||
logger.error(
|
|
||||||
"Failed to load user data from main file: {}", e
|
|
||||||
)
|
|
||||||
|
|
||||||
# Fallback to cache if main file fails
|
|
||||||
if os.path.exists(self.cache_save_path):
|
|
||||||
try:
|
|
||||||
with open(self.cache_save_path, "r") as f:
|
|
||||||
self.user_data = json.load(f)
|
|
||||||
logger.info(
|
|
||||||
"User data loaded from cache: {}",
|
|
||||||
self.cache_save_path,
|
|
||||||
)
|
|
||||||
except json.JSONDecodeError as e:
|
|
||||||
logger.error(
|
|
||||||
"Failed to load user data from cache: {}", e
|
|
||||||
)
|
|
||||||
|
|
||||||
def save_data(self, retry_attempts: int = 3) -> None:
|
|
||||||
"""
|
|
||||||
Saves the current user data to both the auto-save file and the cache file. If the main
|
|
||||||
save fails, the cache is updated instead. Implements retry logic with exponential backoff
|
|
||||||
in case both save attempts fail.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
retry_attempts (int): The number of retries if saving fails.
|
|
||||||
"""
|
|
||||||
attempt = 0
|
|
||||||
backoff_time = 1 # Starting backoff time (in seconds)
|
|
||||||
|
|
||||||
while attempt < retry_attempts:
|
|
||||||
try:
|
|
||||||
combined_data = {**self.user_data}
|
|
||||||
log_agent_data(combined_data)
|
|
||||||
return # Exit the function if saving was successful
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(
|
|
||||||
"Error saving user data (Attempt {}): {}",
|
|
||||||
attempt + 1,
|
|
||||||
e,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Retry after a short delay (exponential backoff)
|
|
||||||
time.sleep(backoff_time)
|
|
||||||
attempt += 1
|
|
||||||
backoff_time *= (
|
|
||||||
2 # Double the backoff time for each retry
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.error(
|
|
||||||
"Failed to save user data after {} attempts.",
|
|
||||||
retry_attempts,
|
|
||||||
)
|
|
||||||
|
|
||||||
def ask_input(self, prompt: str, key: str) -> None:
|
|
||||||
"""
|
|
||||||
Asks the user for input, validates it, and saves it in the user_data dictionary.
|
|
||||||
Autosaves and caches after each valid input.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
prompt (str): The prompt message to display to the user.
|
|
||||||
key (str): The key under which the input will be saved in user_data.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
ValueError: If the input is empty or only contains whitespace.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
response = input(prompt)
|
|
||||||
if response.strip().lower() == "quit":
|
|
||||||
logger.info(
|
|
||||||
"User chose to quit the onboarding process."
|
|
||||||
)
|
|
||||||
exit(0)
|
|
||||||
if not response.strip():
|
|
||||||
raise ValueError(
|
|
||||||
f"{key.capitalize()} cannot be empty."
|
|
||||||
)
|
|
||||||
self.user_data[key] = response.strip()
|
|
||||||
self.save_data()
|
|
||||||
|
|
||||||
return response
|
|
||||||
except ValueError as e:
|
|
||||||
logger.warning(e)
|
|
||||||
self.ask_input(prompt, key)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
logger.warning(
|
|
||||||
"Onboarding process interrupted by the user."
|
|
||||||
)
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
def collect_user_info(self) -> None:
|
|
||||||
"""
|
|
||||||
Initiates the onboarding process by collecting the user's full name, first name, email,
|
|
||||||
Swarms API key, and system data. Additionally, it reminds the user to set their WORKSPACE_DIR environment variable.
|
|
||||||
"""
|
|
||||||
logger.info("Initiating swarms cloud onboarding process...")
|
|
||||||
self.ask_input(
|
|
||||||
"Enter your first name (or type 'quit' to exit): ",
|
|
||||||
"first_name",
|
|
||||||
)
|
|
||||||
self.ask_input(
|
|
||||||
"Enter your Last Name (or type 'quit' to exit): ",
|
|
||||||
"last_name",
|
|
||||||
)
|
|
||||||
self.ask_input(
|
|
||||||
"Enter your email (or type 'quit' to exit): ", "email"
|
|
||||||
)
|
|
||||||
workspace = self.ask_input(
|
|
||||||
"Enter your WORKSPACE_DIR: This is where logs, errors, and agent configurations will be stored (or type 'quit' to exit). Remember to set this as an environment variable: https://docs.swarms.world/en/latest/swarms/install/quickstart/ || ",
|
|
||||||
"workspace_dir",
|
|
||||||
)
|
|
||||||
os.environ["WORKSPACE_DIR"] = workspace
|
|
||||||
logger.info(
|
|
||||||
"Important: Please ensure you have set your WORKSPACE_DIR environment variable as per the instructions provided."
|
|
||||||
)
|
|
||||||
logger.info(
|
|
||||||
"Additionally, remember to add your API keys for your respective models in your .env file."
|
|
||||||
)
|
|
||||||
logger.success("Onboarding process completed successfully!")
|
|
||||||
|
|
||||||
def run(self) -> None:
|
|
||||||
"""
|
|
||||||
Main method to run the onboarding process. It handles unexpected errors and ensures
|
|
||||||
proper finalization.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self.collect_user_info()
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("An unexpected error occurred: {}", e)
|
|
||||||
finally:
|
|
||||||
logger.info("Finalizing the onboarding process.")
|
|
||||||
|
|
||||||
|
|
||||||
# if __name__ == "__main__":
|
|
||||||
# onboarding = OnboardingProcess()
|
|
||||||
# onboarding.run()
|
|
||||||
@ -0,0 +1,129 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Test script to verify the improved formatter markdown rendering."""
|
||||||
|
|
||||||
|
from swarms.utils.formatter import Formatter
|
||||||
|
|
||||||
|
|
||||||
|
def test_formatter():
|
||||||
|
"""Test the formatter with various markdown content."""
|
||||||
|
formatter = Formatter(md=True)
|
||||||
|
|
||||||
|
# Test 1: Basic markdown with headers
|
||||||
|
content1 = """# Main Title
|
||||||
|
|
||||||
|
This is a paragraph with **bold** text and *italic* text.
|
||||||
|
|
||||||
|
## Section 1
|
||||||
|
- Item 1
|
||||||
|
- Item 2
|
||||||
|
- Item 3
|
||||||
|
|
||||||
|
### Subsection
|
||||||
|
This is another paragraph with `inline code`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
formatter.print_panel(
|
||||||
|
content1, title="Test 1: Basic Markdown", style="bold blue"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test 2: Code blocks with syntax highlighting
|
||||||
|
content2 = """## Code Examples
|
||||||
|
|
||||||
|
Here's a Python example:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def hello_world():
|
||||||
|
'''A simple hello world function.'''
|
||||||
|
print("Hello, World!")
|
||||||
|
return True
|
||||||
|
```
|
||||||
|
|
||||||
|
And here's some JavaScript:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function greet(name) {
|
||||||
|
console.log(`Hello, ${name}!`);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Plain text code block:
|
||||||
|
|
||||||
|
```
|
||||||
|
This is just plain text
|
||||||
|
without any syntax highlighting
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
|
||||||
|
formatter.print_panel(
|
||||||
|
content2, title="Test 2: Code Blocks", style="bold green"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test 3: Mixed content
|
||||||
|
content3 = """## Mixed Content Test
|
||||||
|
|
||||||
|
This paragraph includes **various** formatting options:
|
||||||
|
- Lists with `code`
|
||||||
|
- Links [like this](https://example.com)
|
||||||
|
- And more...
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Python code with comments
|
||||||
|
class Example:
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def greet(self):
|
||||||
|
return f"Hello, {self.name}!"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Table Example
|
||||||
|
|
||||||
|
| Column 1 | Column 2 | Column 3 |
|
||||||
|
|----------|----------|----------|
|
||||||
|
| Data 1 | Data 2 | Data 3 |
|
||||||
|
| Data 4 | Data 5 | Data 6 |
|
||||||
|
"""
|
||||||
|
|
||||||
|
formatter.print_panel(
|
||||||
|
content3, title="Test 3: Mixed Content", style="bold magenta"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test 4: Edge cases
|
||||||
|
content4 = """This content starts without a header
|
||||||
|
|
||||||
|
It should still be formatted correctly.
|
||||||
|
|
||||||
|
```
|
||||||
|
No language specified
|
||||||
|
```
|
||||||
|
|
||||||
|
Single line content."""
|
||||||
|
|
||||||
|
formatter.print_panel(
|
||||||
|
content4, title="Test 4: Edge Cases", style="bold yellow"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test 5: Empty content
|
||||||
|
formatter.print_panel(
|
||||||
|
"", title="Test 5: Empty Content", style="bold red"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test 6: Using print_markdown method
|
||||||
|
content6 = """# Direct Markdown Rendering
|
||||||
|
|
||||||
|
This uses the `print_markdown` method directly.
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Syntax highlighted code
|
||||||
|
result = 42 * 2
|
||||||
|
print(f"The answer is {result}")
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
|
||||||
|
formatter.print_markdown(
|
||||||
|
content6, title="Test 6: Direct Markdown", border_style="cyan"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_formatter()
|
||||||
Loading…
Reference in new issue