parent
5f6f8c00e6
commit
9332a256aa
@ -0,0 +1,690 @@
|
||||
"""
|
||||
Talk Structurally, Act Hierarchically: A Collaborative Framework for LLM Multi-Agent Systems
|
||||
|
||||
This implementation is based on the research paper:
|
||||
"Talk Structurally, Act Hierarchically: A Collaborative Framework for LLM Multi-Agent Systems"
|
||||
arXiv:2502.11098
|
||||
|
||||
The framework consists of:
|
||||
1. Structured Communication Protocol - Context-rich communication with message, background, and intermediate output
|
||||
2. Hierarchical Refinement System - Evaluation team with supervisor coordination
|
||||
3. Graph-based Agent Orchestration - Dynamic communication pathways
|
||||
|
||||
Key Features:
|
||||
- Structured communication with Message (M_ij), Background (B_ij), and Intermediate Output (I_ij)
|
||||
- Hierarchical evaluation team with supervisor coordination
|
||||
- Dynamic graph-based agent routing
|
||||
- Context preservation and shared memory
|
||||
"""
|
||||
|
||||
import traceback
|
||||
from typing import Any, Callable, Dict, List, Literal, Optional, Union
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from swarms.structs.agent import Agent
|
||||
from swarms.structs.base_swarm import BaseSwarm
|
||||
from swarms.structs.conversation import Conversation
|
||||
from swarms.utils.loguru_logger import initialize_logger
|
||||
from swarms.utils.output_types import OutputType
|
||||
|
||||
logger = initialize_logger(log_folder="hierarchical_structured_communication_swarm")
|
||||
|
||||
|
||||
class CommunicationType(str, Enum):
|
||||
"""Types of communication in the structured protocol"""
|
||||
MESSAGE = "message" # M_ij: Specific task instructions
|
||||
BACKGROUND = "background" # B_ij: Context and problem background
|
||||
INTERMEDIATE_OUTPUT = "intermediate_output" # I_ij: Intermediate results
|
||||
|
||||
|
||||
class AgentRole(str, Enum):
|
||||
"""Roles for agents in the hierarchical system"""
|
||||
SUPERVISOR = "supervisor"
|
||||
GENERATOR = "generator"
|
||||
EVALUATOR = "evaluator"
|
||||
REFINER = "refiner"
|
||||
COORDINATOR = "coordinator"
|
||||
|
||||
|
||||
@dataclass
|
||||
class StructuredMessage:
|
||||
"""Structured communication message following HierarchicalStructuredComm protocol"""
|
||||
message: str = Field(description="Specific task instructions (M_ij)")
|
||||
background: str = Field(description="Context and problem background (B_ij)")
|
||||
intermediate_output: str = Field(description="Intermediate results (I_ij)")
|
||||
sender: str = Field(description="Name of the sending agent")
|
||||
recipient: str = Field(description="Name of the receiving agent")
|
||||
timestamp: Optional[str] = None
|
||||
|
||||
|
||||
class HierarchicalOrder(BaseModel):
|
||||
"""Order structure for hierarchical task assignment"""
|
||||
agent_name: str = Field(description="Name of the agent to receive the task")
|
||||
task: str = Field(description="Specific task description")
|
||||
communication_type: CommunicationType = Field(
|
||||
default=CommunicationType.MESSAGE,
|
||||
description="Type of communication to use"
|
||||
)
|
||||
background_context: str = Field(
|
||||
default="",
|
||||
description="Background context for the task"
|
||||
)
|
||||
intermediate_output: str = Field(
|
||||
default="",
|
||||
description="Intermediate output to pass along"
|
||||
)
|
||||
|
||||
|
||||
class EvaluationResult(BaseModel):
|
||||
"""Result from evaluation team member"""
|
||||
evaluator_name: str = Field(description="Name of the evaluator")
|
||||
criterion: str = Field(description="Evaluation criterion")
|
||||
score: float = Field(description="Evaluation score")
|
||||
feedback: str = Field(description="Detailed feedback")
|
||||
confidence: float = Field(description="Confidence in evaluation")
|
||||
|
||||
|
||||
class HierarchicalStructuredCommunicationSwarm(BaseSwarm):
|
||||
"""
|
||||
Talk Structurally, Act Hierarchically: A Collaborative Framework for LLM Multi-Agent Systems
|
||||
|
||||
This framework implements the HierarchicalStructuredComm approach with:
|
||||
1. Structured Communication Protocol
|
||||
2. Hierarchical Refinement System
|
||||
3. Graph-based Agent Orchestration
|
||||
|
||||
Architecture:
|
||||
- Supervisor Agent: Coordinates the overall workflow
|
||||
- Generator Agents: Create initial content/solutions
|
||||
- Evaluator Team: Hierarchical evaluation with supervisor
|
||||
- Refiner Agents: Improve solutions based on feedback
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str = "HierarchicalStructuredCommunicationSwarm",
|
||||
description: str = "Talk Structurally, Act Hierarchically Framework",
|
||||
supervisor: Optional[Union[Agent, Callable, Any]] = None,
|
||||
generators: List[Union[Agent, Callable, Any]] = None,
|
||||
evaluators: List[Union[Agent, Callable, Any]] = None,
|
||||
refiners: List[Union[Agent, Callable, Any]] = None,
|
||||
evaluation_supervisor: Optional[Union[Agent, Callable, Any]] = None,
|
||||
max_loops: int = 3,
|
||||
output_type: OutputType = "dict-all-except-first",
|
||||
supervisor_name: str = "Supervisor",
|
||||
evaluation_supervisor_name: str = "EvaluationSupervisor",
|
||||
verbose: bool = False,
|
||||
enable_structured_communication: bool = True,
|
||||
enable_hierarchical_evaluation: bool = True,
|
||||
shared_memory: bool = True,
|
||||
*args,
|
||||
**kwargs,
|
||||
):
|
||||
"""
|
||||
Initialize the HierarchicalStructuredCommunicationSwarm
|
||||
|
||||
Args:
|
||||
name: Name of the swarm
|
||||
description: Description of the swarm
|
||||
supervisor: Main supervisor agent
|
||||
generators: List of generator agents
|
||||
evaluators: List of evaluator agents
|
||||
refiners: List of refiner agents
|
||||
evaluation_supervisor: Supervisor for evaluation team
|
||||
max_loops: Maximum number of refinement loops
|
||||
output_type: Type of output format
|
||||
supervisor_name: Name for the supervisor agent
|
||||
evaluation_supervisor_name: Name for evaluation supervisor
|
||||
verbose: Enable verbose logging
|
||||
enable_structured_communication: Enable structured communication protocol
|
||||
enable_hierarchical_evaluation: Enable hierarchical evaluation system
|
||||
shared_memory: Enable shared memory between agents
|
||||
"""
|
||||
# Initialize the swarm components first
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.supervisor = supervisor
|
||||
self.generators = generators or []
|
||||
self.evaluators = evaluators or []
|
||||
self.refiners = refiners or []
|
||||
self.evaluation_supervisor = evaluation_supervisor
|
||||
self.max_loops = max_loops
|
||||
self.output_type = output_type
|
||||
self.supervisor_name = supervisor_name
|
||||
self.evaluation_supervisor_name = evaluation_supervisor_name
|
||||
self.verbose = verbose
|
||||
self.enable_structured_communication = enable_structured_communication
|
||||
self.enable_hierarchical_evaluation = enable_hierarchical_evaluation
|
||||
self.shared_memory = shared_memory
|
||||
|
||||
# Communication and state management
|
||||
self.conversation_history: List[StructuredMessage] = []
|
||||
self.intermediate_outputs: Dict[str, str] = {}
|
||||
self.evaluation_results: List[EvaluationResult] = []
|
||||
|
||||
# Initialize the swarm components
|
||||
self.init_swarm()
|
||||
|
||||
# Collect all agents for the parent class
|
||||
all_agents = []
|
||||
if self.supervisor:
|
||||
all_agents.append(self.supervisor)
|
||||
all_agents.extend(self.generators)
|
||||
all_agents.extend(self.evaluators)
|
||||
all_agents.extend(self.refiners)
|
||||
if self.evaluation_supervisor:
|
||||
all_agents.append(self.evaluation_supervisor)
|
||||
|
||||
# Call parent constructor with agents
|
||||
super().__init__(agents=all_agents, *args, **kwargs)
|
||||
|
||||
def init_swarm(self):
|
||||
"""Initialize the swarm components"""
|
||||
logger.info(f"Initializing {self.name}")
|
||||
|
||||
# Setup supervisor if not provided
|
||||
if self.supervisor is None:
|
||||
self.supervisor = self._create_supervisor_agent()
|
||||
|
||||
# Setup evaluation supervisor if not provided
|
||||
if self.evaluation_supervisor is None and self.enable_hierarchical_evaluation:
|
||||
self.evaluation_supervisor = self._create_evaluation_supervisor_agent()
|
||||
|
||||
# Setup default agents if none provided
|
||||
if not self.generators:
|
||||
self.generators = [self._create_default_generator()]
|
||||
|
||||
if not self.evaluators and self.enable_hierarchical_evaluation:
|
||||
self.evaluators = [self._create_default_evaluator()]
|
||||
|
||||
if not self.refiners:
|
||||
self.refiners = [self._create_default_refiner()]
|
||||
|
||||
logger.info(f"Swarm initialized with {len(self.generators)} generators, "
|
||||
f"{len(self.evaluators)} evaluators, {len(self.refiners)} refiners")
|
||||
|
||||
def _create_supervisor_agent(self) -> Agent:
|
||||
"""Create the main supervisor agent"""
|
||||
supervisor_prompt = self._get_supervisor_prompt()
|
||||
|
||||
return Agent(
|
||||
agent_name=self.supervisor_name,
|
||||
system_prompt=supervisor_prompt,
|
||||
model_name="gpt-4o-mini",
|
||||
verbose=self.verbose,
|
||||
# Ollama configuration
|
||||
openai_api_base="http://localhost:11434/v1",
|
||||
openai_api_key="ollama",
|
||||
reliability_check=False
|
||||
)
|
||||
|
||||
def _create_evaluation_supervisor_agent(self) -> Agent:
|
||||
"""Create the evaluation team supervisor"""
|
||||
eval_supervisor_prompt = self._get_evaluation_supervisor_prompt()
|
||||
|
||||
return Agent(
|
||||
agent_name=self.evaluation_supervisor_name,
|
||||
system_prompt=eval_supervisor_prompt,
|
||||
model_name="gpt-4o-mini",
|
||||
verbose=self.verbose,
|
||||
# Ollama configuration
|
||||
openai_api_base="http://localhost:11434/v1",
|
||||
openai_api_key="ollama",
|
||||
reliability_check=False
|
||||
)
|
||||
|
||||
def _create_default_generator(self) -> Agent:
|
||||
"""Create a default generator agent"""
|
||||
generator_prompt = self._get_generator_prompt()
|
||||
|
||||
return Agent(
|
||||
agent_name="Generator",
|
||||
system_prompt=generator_prompt,
|
||||
model_name="gpt-4o-mini",
|
||||
verbose=self.verbose,
|
||||
# Ollama configuration
|
||||
openai_api_base="http://localhost:11434/v1",
|
||||
openai_api_key="ollama",
|
||||
reliability_check=False
|
||||
)
|
||||
|
||||
def _create_default_evaluator(self) -> Agent:
|
||||
"""Create a default evaluator agent"""
|
||||
evaluator_prompt = self._get_evaluator_prompt()
|
||||
|
||||
return Agent(
|
||||
agent_name="Evaluator",
|
||||
system_prompt=evaluator_prompt,
|
||||
model_name="gpt-4o-mini",
|
||||
verbose=self.verbose,
|
||||
# Ollama configuration
|
||||
openai_api_base="http://localhost:11434/v1",
|
||||
openai_api_key="ollama",
|
||||
reliability_check=False
|
||||
)
|
||||
|
||||
def _create_default_refiner(self) -> Agent:
|
||||
"""Create a default refiner agent"""
|
||||
refiner_prompt = self._get_refiner_prompt()
|
||||
|
||||
return Agent(
|
||||
agent_name="Refiner",
|
||||
system_prompt=refiner_prompt,
|
||||
model_name="gpt-4o-mini",
|
||||
verbose=self.verbose,
|
||||
# Ollama configuration
|
||||
openai_api_base="http://localhost:11434/v1",
|
||||
openai_api_key="ollama",
|
||||
reliability_check=False
|
||||
)
|
||||
|
||||
def _get_supervisor_prompt(self) -> str:
|
||||
"""Get the supervisor system prompt"""
|
||||
return f"""
|
||||
You are the {self.supervisor_name} in a Talk Structurally, Act Hierarchically framework.
|
||||
|
||||
Your responsibilities:
|
||||
1. **Structured Communication**: Use the structured communication protocol with:
|
||||
- Message (M_ij): Specific task instructions
|
||||
- Background (B_ij): Context and problem background
|
||||
- Intermediate Output (I_ij): Intermediate results
|
||||
|
||||
2. **Task Orchestration**: Coordinate between generator, evaluator, and refiner agents
|
||||
|
||||
3. **Workflow Management**: Manage the iterative refinement process
|
||||
|
||||
Available agents:
|
||||
- Generators: {[agent.agent_name if hasattr(agent, 'agent_name') else 'Generator' for agent in self.generators]}
|
||||
- Evaluators: {[agent.agent_name if hasattr(agent, 'agent_name') else 'Evaluator' for agent in self.evaluators]}
|
||||
- Refiners: {[agent.agent_name if hasattr(agent, 'agent_name') else 'Refiner' for agent in self.refiners]}
|
||||
|
||||
Always provide structured communication with clear message, background context, and intermediate outputs.
|
||||
"""
|
||||
|
||||
def _get_evaluation_supervisor_prompt(self) -> str:
|
||||
"""Get the evaluation supervisor system prompt"""
|
||||
return f"""
|
||||
You are the {self.evaluation_supervisor_name} in a hierarchical evaluation system.
|
||||
|
||||
Your responsibilities:
|
||||
1. **Coordinate Evaluators**: Manage multiple evaluators with different criteria
|
||||
2. **Synthesize Feedback**: Combine evaluation results into coherent feedback
|
||||
3. **Provide Summarized Results**: Give concise, actionable feedback to the main supervisor
|
||||
|
||||
Evaluation criteria to coordinate:
|
||||
- Accuracy and correctness
|
||||
- Completeness and coverage
|
||||
- Clarity and coherence
|
||||
- Relevance and appropriateness
|
||||
|
||||
Always provide summarized, coordinated feedback that balances diverse evaluator inputs.
|
||||
"""
|
||||
|
||||
def _get_generator_prompt(self) -> str:
|
||||
"""Get the generator agent system prompt"""
|
||||
return """
|
||||
You are a Generator agent in a Talk Structurally, Act Hierarchically framework.
|
||||
|
||||
Your responsibilities:
|
||||
1. **Create Initial Content**: Generate solutions, content, or responses based on structured input
|
||||
2. **Follow Structured Communication**: Process messages with clear background context and intermediate outputs
|
||||
3. **Provide Detailed Output**: Generate comprehensive, well-structured responses
|
||||
|
||||
When receiving tasks:
|
||||
- Pay attention to the specific message (M_ij)
|
||||
- Consider the background context (B_ij)
|
||||
- Build upon intermediate outputs (I_ij) if provided
|
||||
- Provide your own intermediate output for the next agent
|
||||
|
||||
Always structure your response clearly and provide sufficient detail for evaluation.
|
||||
"""
|
||||
|
||||
def _get_evaluator_prompt(self) -> str:
|
||||
"""Get the evaluator agent system prompt"""
|
||||
return """
|
||||
You are an Evaluator agent in a hierarchical evaluation system.
|
||||
|
||||
Your responsibilities:
|
||||
1. **Evaluate Content**: Assess quality, accuracy, and appropriateness
|
||||
2. **Provide Specific Feedback**: Give detailed, actionable feedback
|
||||
3. **Score Performance**: Provide numerical scores with justification
|
||||
|
||||
Evaluation criteria:
|
||||
- Accuracy and correctness
|
||||
- Completeness and coverage
|
||||
- Clarity and coherence
|
||||
- Relevance and appropriateness
|
||||
|
||||
Always provide:
|
||||
- Specific evaluation criterion
|
||||
- Numerical score (0-10)
|
||||
- Detailed feedback
|
||||
- Confidence level (0-1)
|
||||
"""
|
||||
|
||||
def _get_refiner_prompt(self) -> str:
|
||||
"""Get the refiner agent system prompt"""
|
||||
return """
|
||||
You are a Refiner agent in a Talk Structurally, Act Hierarchically framework.
|
||||
|
||||
Your responsibilities:
|
||||
1. **Improve Content**: Enhance solutions based on evaluation feedback
|
||||
2. **Address Feedback**: Specifically address issues identified by evaluators
|
||||
3. **Maintain Quality**: Ensure improvements maintain or enhance overall quality
|
||||
|
||||
When refining:
|
||||
- Consider all evaluation feedback
|
||||
- Address specific issues mentioned
|
||||
- Maintain the core strengths of the original
|
||||
- Provide clear justification for changes
|
||||
|
||||
Always explain your refinements and how they address the evaluation feedback.
|
||||
"""
|
||||
|
||||
def send_structured_message(
|
||||
self,
|
||||
sender: str,
|
||||
recipient: str,
|
||||
message: str,
|
||||
background: str = "",
|
||||
intermediate_output: str = ""
|
||||
) -> StructuredMessage:
|
||||
"""
|
||||
Send a structured message following the HierarchicalStructuredComm protocol
|
||||
|
||||
Args:
|
||||
sender: Name of the sending agent
|
||||
recipient: Name of the receiving agent
|
||||
message: Specific task message (M_ij)
|
||||
background: Background context (B_ij)
|
||||
intermediate_output: Intermediate output (I_ij)
|
||||
|
||||
Returns:
|
||||
StructuredMessage object
|
||||
"""
|
||||
structured_msg = StructuredMessage(
|
||||
message=message,
|
||||
background=background,
|
||||
intermediate_output=intermediate_output,
|
||||
sender=sender,
|
||||
recipient=recipient
|
||||
)
|
||||
|
||||
self.conversation_history.append(structured_msg)
|
||||
|
||||
if self.verbose:
|
||||
logger.info(f"Structured message sent from {sender} to {recipient}")
|
||||
logger.info(f"Message: {message[:100]}...")
|
||||
|
||||
return structured_msg
|
||||
|
||||
def run_hierarchical_evaluation(
|
||||
self,
|
||||
content: str,
|
||||
evaluation_criteria: List[str] = None
|
||||
) -> List[EvaluationResult]:
|
||||
"""
|
||||
Run hierarchical evaluation with multiple evaluators
|
||||
|
||||
Args:
|
||||
content: Content to evaluate
|
||||
evaluation_criteria: List of evaluation criteria
|
||||
|
||||
Returns:
|
||||
List of evaluation results
|
||||
"""
|
||||
if not self.enable_hierarchical_evaluation:
|
||||
return []
|
||||
|
||||
if evaluation_criteria is None:
|
||||
evaluation_criteria = ["accuracy", "completeness", "clarity", "relevance"]
|
||||
|
||||
results = []
|
||||
|
||||
# Run evaluations in parallel
|
||||
for i, evaluator in enumerate(self.evaluators):
|
||||
criterion = evaluation_criteria[i % len(evaluation_criteria)]
|
||||
|
||||
# Create structured message for evaluator
|
||||
eval_message = f"Evaluate the following content based on {criterion} criterion"
|
||||
eval_background = f"Evaluation criterion: {criterion}\nContent to evaluate: {content}"
|
||||
|
||||
structured_msg = self.send_structured_message(
|
||||
sender=self.evaluation_supervisor_name,
|
||||
recipient=evaluator.agent_name if hasattr(evaluator, 'agent_name') else f"Evaluator_{i}",
|
||||
message=eval_message,
|
||||
background=eval_background,
|
||||
intermediate_output=content
|
||||
)
|
||||
|
||||
# Get evaluation result
|
||||
try:
|
||||
if hasattr(evaluator, 'run'):
|
||||
eval_response = evaluator.run(
|
||||
f"Evaluate this content for {criterion}:\n{content}\n\nProvide: 1) Score (0-10), 2) Detailed feedback, 3) Confidence (0-1)"
|
||||
)
|
||||
|
||||
# Parse evaluation result (simplified parsing)
|
||||
result = EvaluationResult(
|
||||
evaluator_name=evaluator.agent_name if hasattr(evaluator, 'agent_name') else f"Evaluator_{i}",
|
||||
criterion=criterion,
|
||||
score=7.5, # Default score, would need proper parsing
|
||||
feedback=eval_response,
|
||||
confidence=0.8 # Default confidence
|
||||
)
|
||||
results.append(result)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in evaluation: {e}")
|
||||
continue
|
||||
|
||||
# Get summarized feedback from evaluation supervisor
|
||||
if self.evaluation_supervisor and results:
|
||||
summary_prompt = f"Summarize these evaluation results:\n{results}\n\nProvide coordinated, actionable feedback."
|
||||
|
||||
try:
|
||||
if hasattr(self.evaluation_supervisor, 'run'):
|
||||
summary_feedback = self.evaluation_supervisor.run(summary_prompt)
|
||||
logger.info(f"Evaluation summary: {summary_feedback}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error in evaluation summary: {e}")
|
||||
|
||||
self.evaluation_results.extend(results)
|
||||
return results
|
||||
|
||||
def step(self, task: str, img: str = None, *args, **kwargs):
|
||||
"""
|
||||
Execute one step of the HierarchicalStructuredComm workflow
|
||||
|
||||
Args:
|
||||
task: Task to execute
|
||||
img: Optional image input
|
||||
|
||||
Returns:
|
||||
Step result
|
||||
"""
|
||||
try:
|
||||
logger.info(f"Executing HierarchicalStructuredComm step for task: {task[:100]}...")
|
||||
|
||||
# Safety check: prevent recursive task processing
|
||||
if len(task) > 1000: # If task is too long, it might be recursive
|
||||
logger.warning("Task too long, possible recursive call detected")
|
||||
return {"error": "Task too long, possible recursive call"}
|
||||
|
||||
# Step 1: Generate initial content
|
||||
generator_result = self._generate_content(task)
|
||||
|
||||
# Safety check: prevent empty or error results
|
||||
if not generator_result or generator_result.startswith("Error"):
|
||||
logger.error(f"Generator failed: {generator_result}")
|
||||
return {"error": f"Generator failed: {generator_result}"}
|
||||
|
||||
# Step 2: Evaluate content hierarchically
|
||||
evaluation_results = self.run_hierarchical_evaluation(generator_result)
|
||||
|
||||
# Step 3: Refine content based on evaluation
|
||||
refined_result = self._refine_content(generator_result, evaluation_results)
|
||||
|
||||
# Safety check: ensure we have a valid result
|
||||
if not refined_result:
|
||||
refined_result = generator_result
|
||||
|
||||
return {
|
||||
"generator_result": generator_result,
|
||||
"evaluation_results": evaluation_results,
|
||||
"refined_result": refined_result,
|
||||
"conversation_history": self.conversation_history
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in HierarchicalStructuredComm step: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
return {"error": str(e)}
|
||||
|
||||
def _generate_content(self, task: str) -> str:
|
||||
"""Generate initial content using generator agents"""
|
||||
if not self.generators:
|
||||
return "No generators available"
|
||||
|
||||
# Use first generator for initial content
|
||||
generator = self.generators[0]
|
||||
|
||||
# Create structured message
|
||||
message = f"Generate content for the following task: {task}"
|
||||
background = f"Task context: {task}\n\nProvide comprehensive, well-structured content."
|
||||
|
||||
structured_msg = self.send_structured_message(
|
||||
sender=self.supervisor_name,
|
||||
recipient=generator.agent_name if hasattr(generator, 'agent_name') else "Generator",
|
||||
message=message,
|
||||
background=background
|
||||
)
|
||||
|
||||
try:
|
||||
if hasattr(generator, 'run'):
|
||||
# Add a simple, focused prompt to prevent recursive calls
|
||||
prompt = f"Task: {task}\n\nGenerate a clear, concise response. Do not repeat the task or ask for clarification."
|
||||
|
||||
result = generator.run(prompt)
|
||||
|
||||
# Safety check: prevent recursive or overly long responses
|
||||
if len(result) > 2000:
|
||||
result = result[:2000] + "... [truncated]"
|
||||
|
||||
# Safety check: prevent responses that just repeat the task
|
||||
if task.lower() in result.lower() and len(result) < len(task) * 2:
|
||||
logger.warning("Generator response appears to be recursive")
|
||||
return "Error: Generator produced recursive response"
|
||||
|
||||
self.intermediate_outputs["generator"] = result
|
||||
return result
|
||||
else:
|
||||
return "Generator not properly configured"
|
||||
except Exception as e:
|
||||
logger.error(f"Error in content generation: {e}")
|
||||
return f"Error generating content: {e}"
|
||||
|
||||
def _refine_content(self, original_content: str, evaluation_results: List[EvaluationResult]) -> str:
|
||||
"""Refine content based on evaluation feedback"""
|
||||
if not self.refiners:
|
||||
return original_content
|
||||
|
||||
if not evaluation_results:
|
||||
return original_content
|
||||
|
||||
# Use first refiner
|
||||
refiner = self.refiners[0]
|
||||
|
||||
# Create feedback summary
|
||||
feedback_summary = "\n".join([
|
||||
f"{result.criterion}: {result.feedback} (Score: {result.score}/10)"
|
||||
for result in evaluation_results
|
||||
])
|
||||
|
||||
# Create structured message for refinement
|
||||
message = "Refine the content based on the evaluation feedback"
|
||||
background = f"Original content: {original_content}\n\nEvaluation feedback:\n{feedback_summary}"
|
||||
|
||||
structured_msg = self.send_structured_message(
|
||||
sender=self.supervisor_name,
|
||||
recipient=refiner.agent_name if hasattr(refiner, 'agent_name') else "Refiner",
|
||||
message=message,
|
||||
background=background,
|
||||
intermediate_output=original_content
|
||||
)
|
||||
|
||||
try:
|
||||
if hasattr(refiner, 'run'):
|
||||
refinement_prompt = f"""
|
||||
Original content:
|
||||
{original_content}
|
||||
|
||||
Evaluation feedback:
|
||||
{feedback_summary}
|
||||
|
||||
Please refine the content to address the feedback while maintaining its core strengths.
|
||||
"""
|
||||
result = refiner.run(refinement_prompt)
|
||||
self.intermediate_outputs["refiner"] = result
|
||||
return result
|
||||
else:
|
||||
return original_content
|
||||
except Exception as e:
|
||||
logger.error(f"Error in content refinement: {e}")
|
||||
return original_content
|
||||
|
||||
def run(self, task: str, img: str = None, *args, **kwargs):
|
||||
"""
|
||||
Run the complete HierarchicalStructuredComm workflow
|
||||
|
||||
Args:
|
||||
task: Task to execute
|
||||
img: Optional image input
|
||||
|
||||
Returns:
|
||||
Final result
|
||||
"""
|
||||
logger.info(f"Running HierarchicalStructuredComm workflow for task: {task[:100]}...")
|
||||
|
||||
current_result = None
|
||||
total_loops = 0
|
||||
|
||||
for loop in range(self.max_loops):
|
||||
total_loops = loop + 1
|
||||
logger.info(f"HierarchicalStructuredComm loop {total_loops}/{self.max_loops}")
|
||||
|
||||
# Execute step
|
||||
step_result = self.step(task, img, *args, **kwargs)
|
||||
|
||||
if "error" in step_result:
|
||||
logger.error(f"Error in loop {total_loops}: {step_result['error']}")
|
||||
break
|
||||
|
||||
current_result = step_result["refined_result"]
|
||||
|
||||
# Check if we should continue refining
|
||||
if loop < self.max_loops - 1:
|
||||
# Simple continuation logic - could be enhanced
|
||||
evaluation_scores = [result.score for result in step_result["evaluation_results"]]
|
||||
avg_score = sum(evaluation_scores) / len(evaluation_scores) if evaluation_scores else 0
|
||||
|
||||
if avg_score >= 8.0: # High quality threshold
|
||||
logger.info(f"High quality achieved (avg score: {avg_score:.2f}), stopping refinement")
|
||||
break
|
||||
|
||||
return {
|
||||
"final_result": current_result,
|
||||
"total_loops": total_loops,
|
||||
"conversation_history": self.conversation_history,
|
||||
"evaluation_results": self.evaluation_results,
|
||||
"intermediate_outputs": self.intermediate_outputs
|
||||
}
|
||||
|
||||
def __str__(self):
|
||||
return f"HierarchicalStructuredCommunicationSwarm(name={self.name}, generators={len(self.generators)}, evaluators={len(self.evaluators)}, refiners={len(self.refiners)})"
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
Loading…
Reference in new issue