[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