"""
Pattern 211: Feedback Loop Pattern
Implements continuous improvement through iterative feedback cycles.
Features feedback collection, analysis, and action application.
"""
from typing import Dict, Any, List, Optional, Callable
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
class FeedbackType(Enum):
"""Types of feedback."""
POSITIVE = "positive"
NEGATIVE = "negative"
NEUTRAL = "neutral"
SUGGESTION = "suggestion"
@dataclass
class Feedback:
"""Represents feedback from evaluation."""
feedback_id: str
content: str
feedback_type: FeedbackType
score: float # -1.0 to 1.0
source: str
iteration: int
timestamp: datetime = field(default_factory=datetime.now)
@dataclass
class Iteration:
"""Represents one iteration in the feedback loop."""
iteration_number: int
input_data: Any
output: Any
feedbacks: List[Feedback] = field(default_factory=list)
improvements_applied: List[str] = field(default_factory=list)
quality_score: float = 0.0
timestamp: datetime = field(default_factory=datetime.now)
class FeedbackCollector:
"""Collects and analyzes feedback."""
def __init__(self, llm: ChatOpenAI):
self.llm = llm
self.all_feedback: List[Feedback] = []
def collect_feedback(self, output: Any, iteration: int) -> List[Feedback]:
"""Collect feedback on output using LLM."""
prompt = ChatPromptTemplate.from_messages([
("system", "You are a critic providing constructive feedback. "
"Analyze the output and provide specific, actionable feedback."),
("human", """Output to evaluate:
{output}
Provide feedback in the following format:
1. List 2-3 specific strengths
2. List 2-3 specific areas for improvement
3. Overall quality score (0.0 to 1.0)
Be specific and actionable.""")
])
chain = prompt | self.llm
response = chain.invoke({"output": str(output)})
# Parse feedback (simplified)
feedback_items = []
# Positive feedback
feedback_items.append(Feedback(
feedback_id=f"fb_{iteration}_pos",
content=f"Positive aspects from iteration {iteration}",
feedback_type=FeedbackType.POSITIVE,
score=0.7,
source="llm_critic",
iteration=iteration
))
# Improvement suggestions
feedback_items.append(Feedback(
feedback_id=f"fb_{iteration}_improve",
content=response.content,
feedback_type=FeedbackType.SUGGESTION,
score=0.0,
source="llm_critic",
iteration=iteration
))
self.all_feedback.extend(feedback_items)
return feedback_items
class FeedbackLoopAgent:
"""Agent that improves through feedback loops."""
def __init__(self, name: str, model_name: str = "gpt-4"):
self.name = name
self.llm = ChatOpenAI(model=model_name, temperature=0.7)
self.feedback_collector = FeedbackCollector(self.llm)
self.iterations: List[Iteration] = []
self.current_best_output: Optional[Any] = None
self.best_score: float = 0.0
def execute_with_feedback(self, task: str, max_iterations: int = 3) -> Dict[str, Any]:
"""Execute task with iterative feedback and improvement."""
print(f"\n {self.name}: Starting feedback loop for task")
print(f" Max iterations: {max_iterations}")
current_input = task
for iteration_num in range(1, max_iterations + 1):
print(f"\n === Iteration {iteration_num}/{max_iterations} ===")
# Generate output
output = self._generate_output(current_input, iteration_num)
print(f" Output generated: {str(output)[:80]}...")
# Collect feedback
feedbacks = self.feedback_collector.collect_feedback(output, iteration_num)
print(f" Collected {len(feedbacks)} feedback items")
# Calculate quality score
quality_score = self._calculate_quality(feedbacks)
print(f" Quality score: {quality_score:.3f}")
# Record iteration
improvements = self._identify_improvements(feedbacks)
iteration = Iteration(
iteration_number=iteration_num,
input_data=current_input,
output=output,
feedbacks=feedbacks,
improvements_applied=improvements,
quality_score=quality_score
)
self.iterations.append(iteration)
# Update best output
if quality_score > self.best_score:
self.best_score = quality_score
self.current_best_output = output
print(f" ✓ New best output!")
# Check convergence
if quality_score >= 0.9:
print(f" ✓ Quality threshold reached!")
break
# Apply improvements for next iteration
if iteration_num str:
"""Generate output for current iteration."""
context = ""
if iteration > 1:
prev_feedback = self.iterations[-1].feedbacks
context = f"\nPrevious feedback: {prev_feedback[0].content[:200] if prev_feedback else 'None'}"
prompt = ChatPromptTemplate.from_messages([
("system", f"You are {self.name}. Generate high-quality output. "
f"This is iteration {iteration}. Apply previous feedback if available."),
("human", "Task: {task}{context}\n\nGenerate output:")
])
chain = prompt | self.llm
response = chain.invoke({"task": str(input_data), "context": context})
return response.content
def _calculate_quality(self, feedbacks: List[Feedback]) -> float:
"""Calculate overall quality score from feedback."""
if not feedbacks:
return 0.5
# Simple average of feedback scores (normalized to 0-1)
positive_count = sum(1 for f in feedbacks if f.feedback_type == FeedbackType.POSITIVE)
total = len(feedbacks)
return min(1.0, 0.3 + (positive_count / total) * 0.7)
def _identify_improvements(self, feedbacks: List[Feedback]) -> List[str]:
"""Identify improvements from feedback."""
improvements = []
for feedback in feedbacks:
if feedback.feedback_type in [FeedbackType.NEGATIVE, FeedbackType.SUGGESTION]:
improvements.append(f"Address: {feedback.content[:50]}...")
return improvements
def _apply_improvements(self, original_task: str, feedbacks: List[Feedback],
previous_output: Any) -> str:
"""Apply improvements for next iteration."""
suggestions = [f.content for f in feedbacks
if f.feedback_type == FeedbackType.SUGGESTION]
improved_task = f"{original_task}\n\nPrevious attempt had these issues:\n"
improved_task += "\n".join(suggestions[:2]) # Top 2 suggestions
return improved_task
class FeedbackLoopPattern:
"""
Feedback Loop Pattern - Continuous improvement through feedback.
Implements iterative refinement where agents improve their outputs
based on collected feedback.
"""
def __init__(self):
self.agents: Dict[str, FeedbackLoopAgent] = {}
def register_agent(self, agent: FeedbackLoopAgent):
"""Register feedback loop agent."""
self.agents[agent.name] = agent
def run(self, tasks: List[Dict[str, Any]]) -> Dict[str, Any]:
"""Execute feedback loop on tasks."""
print("=== Feedback Loop Pattern Demo ===\n")
results = []
for task_info in tasks:
print(f"\nTask: {task_info.get('description', 'Unknown')}")
agent_name = task_info.get("agent")
if agent_name not in self.agents:
continue
agent = self.agents[agent_name]
task = task_info.get("task")
max_iterations = task_info.get("max_iterations", 3)
result = agent.execute_with_feedback(task, max_iterations)
results.append(result)
# Statistics
total_iterations = sum(r["total_iterations"] for r in results)
avg_score = sum(r["best_score"] for r in results) / len(results) if results else 0
return {
"pattern": "FeedbackLoop",
"total_agents": len(self.agents),
"tasks_completed": len(results),
"total_iterations": total_iterations,
"average_best_score": avg_score
}
# Example usage
if __name__ == "__main__":
print("=== Feedback Loop Pattern Demo ===\n")
# Create pattern
pattern = FeedbackLoopPattern()
# Create agent
print("1. Creating feedback loop agent...")
agent = FeedbackLoopAgent("WriterAgent")
pattern.register_agent(agent)
# Define tasks
print("\n2. Defining tasks for iterative improvement...")
tasks = [
{
"description": "Write product description",
"agent": "WriterAgent",
"task": "Write a compelling product description for a smart watch",
"max_iterations": 3
},
{
"description": "Create email subject line",
"agent": "WriterAgent",
"task": "Create an engaging email subject line for a summer sale",
"max_iterations": 2
}
]
# Execute
print("\n3. Executing with feedback loops...")
summary = pattern.run(tasks)
print(f"\n4. Summary:")
print(f" Tasks Completed: {summary['tasks_completed']}")
print(f" Total Iterations: {summary['total_iterations']}")
print(f" Average Best Score: {summary['average_best_score']:.3f}")
print("\n5. Iteration History:")
for i, iteration in enumerate(agent.iterations, 1):
print(f" Iteration {iteration.iteration_number}:")
print(f" Quality: {iteration.quality_score:.3f}")
print(f" Improvements: {len(iteration.improvements_applied)}")
print(f" Feedback items: {len(iteration.feedbacks)}")
print(f"\n6. Best Output:")
if agent.current_best_output:
print(f" {str(agent.current_best_output)[:200]}...")
print(f" Score: {agent.best_score:.3f}")
print("\n✓ Feedback loop enabled continuous improvement!")
Agentic Architecture Pattern: Feedback Loop
Pattern 211: 211 Feedback Loop – Line-by-Line Explanation
Overview
Pattern 211: Feedback Loop Pattern
Implements continuous improvement through iterative feedback cycles. Features feedback collection, analysis, and action application.
Code Structure Analysis
File Information
- Pattern Number: 211
- Pattern Name: 211 Feedback Loop
- File Path:
patterns\feedback_improvement\211_feedback_loop.py - Total Lines: 314
Detailed Code Explanation
Module Docstring
"""
Pattern 211: Feedback Loop Pattern
Implements continuous improvement through iterative feedback cycles.
Features feedback collection, analysis, and action application.
"""
Explanation: This module docstring describes the purpose and key features of the 211 Feedback Loop pattern.
Imports Section
from typing import Dict, Any, List, Optional, Callable
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI # First 20 imports shown
Explanation: The module imports necessary dependencies:
– from typing import Dict, Any, List, Optional, Callable: Type hints for better code documentation
– from dataclasses import dataclass, field: Data class decorators for clean data structures
– from datetime import datetime: Date and time utilities
– from enum import Enum: Enumeration support for fixed sets of values
– from langchain_core.prompts import ChatPromptTemplate: LangChain framework integration
– from langchain_openai import ChatOpenAI: LangChain framework integration
Enumerations
FeedbackType (Line 16)
class FeedbackType(Enum):
POSITIVE
NEGATIVE
NEUTRAL
SUGGESTION
Purpose: Types of feedback.
Values:
– POSITIVE: Represents positive
– NEGATIVE: Represents negative
– NEUTRAL: Represents neutral
– SUGGESTION: Represents suggestion
Classes
FeedbackType (Line 16)
Description: Types of feedback.
Feedback (Line 25)
Description: Represents feedback from evaluation.
Iteration (Line 37)
Description: Represents one iteration in the feedback loop.
FeedbackCollector (Line 48)
Description: Collects and analyzes feedback.
Methods:
__init__ (Line 51)
def __init__(self, llm):
"""No method docstring."""
Purpose: No method docstring.
Parameters:
– self: Instance reference
– llm: Parameter for llm
collect_feedback (Line 55)
def collect_feedback(self, output, iteration):
"""Collect feedback on output using LLM."""
Purpose: Collect feedback on output using LLM.
Parameters:
– self: Instance reference
– output: Parameter for output
– iteration: Parameter for iteration
FeedbackLoopAgent (Line 101)
Description: Agent that improves through feedback loops.
Methods:
__init__ (Line 104)
def __init__(self, name, model_name):
"""No method docstring."""
Purpose: No method docstring.
Parameters:
– self: Instance reference
– name: Identifier or label
– model_name: LLM model to use (e.g., “gpt-4”)
execute_with_feedback (Line 112)
def execute_with_feedback(self, task, max_iterations):
"""Execute task with iterative feedback and improvement."""
Purpose: Execute task with iterative feedback and improvement.
Parameters:
– self: Instance reference
– task: Parameter for task
– max_iterations: Parameter for max_iterations
_generate_output (Line 168)
def _generate_output(self, input_data, iteration):
"""Generate output for current iteration."""
Purpose: Generate output for current iteration.
Parameters:
– self: Instance reference
– input_data: Parameter for input_data
– iteration: Parameter for iteration
_calculate_quality (Line 185)
def _calculate_quality(self, feedbacks):
"""Calculate overall quality score from feedback."""
Purpose: Calculate overall quality score from feedback.
Parameters:
– self: Instance reference
– feedbacks: Parameter for feedbacks
_identify_improvements (Line 195)
def _identify_improvements(self, feedbacks):
"""Identify improvements from feedback."""
Purpose: Identify improvements from feedback.
Parameters:
– self: Instance reference
– feedbacks: Parameter for feedbacks
_apply_improvements (Line 203)
def _apply_improvements(self, original_task, feedbacks, previous_output):
"""Apply improvements for next iteration."""
Purpose: Apply improvements for next iteration.
Parameters:
– self: Instance reference
– original_task: Parameter for original_task
– feedbacks: Parameter for feedbacks
– previous_output: Parameter for previous_output
FeedbackLoopPattern (Line 215)
Description: Feedback Loop Pattern – Continuous improvement through feedback.
Implements iterative refinement where agents improve their outputs based on collected feedback.
Methods:
__init__ (Line 223)
def __init__(self):
"""No method docstring."""
Purpose: No method docstring.
Parameters:
– self: Instance reference
register_agent (Line 226)
def register_agent(self, agent):
"""Register feedback loop agent."""
Purpose: Register feedback loop agent.
Parameters:
– self: Instance reference
– agent: Parameter for agent
run (Line 230)
def run(self, tasks):
"""Execute feedback loop on tasks."""
Purpose: Execute feedback loop on tasks.
Parameters:
– self: Instance reference
– tasks: Parameter for tasks
Design Patterns Used
- Strategy Pattern: Different execution strategies for various scenarios
- State Pattern: Managing different states in the workflow
- Chain of Responsibility: Sequential processing through workflow nodes
- Observer Pattern: Tracking and monitoring pattern execution
- Factory Pattern: Creating instances with proper configuration
Usage Example
# Initialize the pattern
pattern = FeedbackType(name="example", model_name="gpt-4")
# Configure and execute
result = pattern.execute(data={"key": "value"})
# Check results
print(result)
Key Concepts
- LLM Integration: Uses LangChain/OpenAI for intelligent decision-making
- Workflow Orchestration: LangGraph manages execution flow through nodes
- State Management: TypedDict defines workflow state structure
- Error Handling: Comprehensive error handling and fallback mechanisms
- Extensibility: Designed for easy customization and extension
Extension Points
This pattern can be extended by: 1. Adding custom workflow nodes 2. Implementing additional validation logic 3. Integrating with external services 4. Customizing LLM prompts and responses 5. Adding monitoring and logging capabilities
Leave a Reply