Category: aiml-architecture

  • Agentic Architecture Pattern: Iterative Refinement

    
        """
    Pattern 80: Iterative Refinement Pattern
    
    Progressively improves output through multiple refinement iterations with
    external feedback. Each iteration addresses specific issues identified in feedback.
    """
    
    from typing import Dict, Any, List, Optional
    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"
        SUGGESTION = "suggestion"
        CORRECTION = "correction"
    
    
    @dataclass
    class Feedback:
        """External feedback on output."""
        iteration: int
        feedback_type: FeedbackType
        content: str
        severity: float = 0.5  # 0.0 (minor) to 1.0 (critical)
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class RefinementIteration:
        """Single refinement iteration."""
        iteration_number: int
        input_query: str
        output: str
        feedback: List[Feedback]
        improvements: List[str]
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    class IterativeRefinementAgent:
        """Agent that refines output based on feedback."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
            self.iterations: List[RefinementIteration] = []
        
        def generate_initial(self, query: str) -> str:
            """Generate initial output."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}. Provide a comprehensive response."),
                ("human", "{query}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"query": query})
            return response.content
        
        def refine_with_feedback(self, query: str, previous_output: str, 
                                feedback_list: List[Feedback]) -> tuple[str, List[str]]:
            """Refine output based on feedback."""
            feedback_text = "\n".join([
                f"- [{fb.feedback_type.value}] {fb.content} (severity: {fb.severity})"
                for fb in feedback_list
            ])
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}. Improve your previous response based on feedback."),
                ("human", """Original Query: {query}
    
    Previous Response: {previous_output}
    
    Feedback Received:
    {feedback}
    
    Provide an improved response that addresses ALL feedback points. 
    Then list specific improvements made.""")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({
                "query": query,
                "previous_output": previous_output,
                "feedback": feedback_text
            })
            
            # Parse improvements (assume agent lists them)
            output = response.content
            improvements = self._extract_improvements(output)
            
            return output, improvements
        
        def _extract_improvements(self, output: str) -> List[str]:
            """Extract improvement list from output."""
            lines = output.split("\n")
            improvements = []
            in_improvements = False
            
            for line in lines:
                if "improvement" in line.lower() or "changes made" in line.lower():
                    in_improvements = True
                    continue
                if in_improvements and line.strip().startswith(("-", "*", "•")):
                    improvements.append(line.strip()[1:].strip())
            
            return improvements if improvements else ["General improvements applied"]
    
    
    class IterativeRefinementPattern:
        """
        Iterative Refinement Pattern - Progressive improvement with feedback.
        
        Generates initial output, receives external feedback, refines iteratively
        until quality criteria met or max iterations reached.
        """
        
        def __init__(self, max_iterations: int = 5):
            self.max_iterations = max_iterations
            self.agents: Dict[str, IterativeRefinementAgent] = {}
        
        def register_agent(self, agent: IterativeRefinementAgent):
            """Register refinement agent."""
            self.agents[agent.name] = agent
        
        def run(self, query: str, feedback_provider: Callable[[str, int], List[Feedback]],
                stopping_criterion: Callable[[List[RefinementIteration]], bool] = None) -> Dict[str, Any]:
            """
            Execute iterative refinement.
            
            Args:
                query: Input query/task
                feedback_provider: Function that generates feedback for output
                stopping_criterion: Optional function to determine when to stop
            """
            print(f"=== Iterative Refinement Pattern ===\n")
            print(f"Query: {query}\n")
            
            for agent in self.agents.values():
                print(f"\n{agent.name} - Starting refinement process...")
                
                # Initial generation
                print(f"\n  Iteration 1: Initial generation")
                output = agent.generate_initial(query)
                print(f"  Output: {output[:150]}...")
                
                # Get feedback
                feedback_list = feedback_provider(output, 1)
                print(f"  Feedback: {len(feedback_list)} points received")
                
                iteration = RefinementIteration(
                    iteration_number=1,
                    input_query=query,
                    output=output,
                    feedback=feedback_list,
                    improvements=[]
                )
                agent.iterations.append(iteration)
                
                # Refinement loop
                for i in range(2, self.max_iterations + 1):
                    if stopping_criterion and stopping_criterion(agent.iterations):
                        print(f"\n  Stopping criterion met at iteration {i-1}")
                        break
                    
                    if not feedback_list or all(fb.feedback_type == FeedbackType.POSITIVE 
                                               for fb in feedback_list):
                        print(f"\n  All feedback positive, stopping at iteration {i-1}")
                        break
                    
                    print(f"\n  Iteration {i}: Refining based on feedback")
                    output, improvements = agent.refine_with_feedback(
                        query, output, feedback_list
                    )
                    print(f"  Output: {output[:150]}...")
                    print(f"  Improvements: {len(improvements)} changes made")
                    
                    # Get new feedback
                    feedback_list = feedback_provider(output, i)
                    print(f"  Feedback: {len(feedback_list)} points received")
                    
                    iteration = RefinementIteration(
                        iteration_number=i,
                        input_query=query,
                        output=output,
                        feedback=feedback_list,
                        improvements=improvements
                    )
                    agent.iterations.append(iteration)
            
            return {
                "pattern": "IterativeRefinement",
                "agents": len(self.agents),
                "iterations_per_agent": {name: len(agent.iterations) 
                                        for name, agent in self.agents.items()},
                "final_outputs": {name: agent.iterations[-1].output 
                                for name, agent in self.agents.items()}
            }
    
    
    # Example usage
    if __name__ == "__main__":
        from typing import Callable
        
        print("=== Iterative Refinement Pattern Demo ===\n")
        
        # Create pattern
        pattern = IterativeRefinementPattern(max_iterations=4)
        
        # Create agent
        agent = IterativeRefinementAgent("ContentWriter")
        pattern.register_agent(agent)
        
        # Simulated feedback provider
        def provide_feedback(output: str, iteration: int) -> List[Feedback]:
            """Simulate external reviewer feedback."""
            if iteration == 1:
                return [
                    Feedback(iteration, FeedbackType.NEGATIVE, 
                            "Add more specific examples", severity=0.8),
                    Feedback(iteration, FeedbackType.SUGGESTION,
                            "Structure with clear headings", severity=0.6),
                    Feedback(iteration, FeedbackType.CORRECTION,
                            "Fix technical accuracy in section 2", severity=0.9)
                ]
            elif iteration == 2:
                return [
                    Feedback(iteration, FeedbackType.POSITIVE,
                            "Examples are now clear", severity=0.0),
                    Feedback(iteration, FeedbackType.SUGGESTION,
                            "Add a conclusion section", severity=0.5)
                ]
            elif iteration == 3:
                return [
                    Feedback(iteration, FeedbackType.POSITIVE,
                            "Excellent structure and content", severity=0.0)
                ]
            return []
        
        # Run refinement
        query = "Write a technical article about microservices architecture"
        summary = pattern.run(query, provide_feedback)
        
        print(f"\n\n=== Summary ===")
        print(f"Total iterations: {summary['iterations_per_agent']['ContentWriter']}")
        print(f"Final output length: {len(summary['final_outputs']['ContentWriter'])} chars")
        
        print(f"\n=== Refinement History ===")
        for iteration in agent.iterations:
            print(f"\nIteration {iteration.iteration_number}:")
            print(f"  Feedback points: {len(iteration.feedback)}")
            print(f"  Improvements made: {len(iteration.improvements)}")
            if iteration.improvements:
                print(f"  Changes: {iteration.improvements[0][:60]}...")
        
        print("\n✓ Iterative refinement with external feedback complete!")
    
        

    Agentic Architecture Pattern: Iterative Refinement

    Pattern 80: 80 Iterative Refinement – Line-by-Line Explanation

    Overview

    Pattern 80: Iterative Refinement Pattern

    Progressively improves output through multiple refinement iterations with external feedback. Each iteration addresses specific issues identified in feedback.


    Code Structure Analysis

    File Information

    • Pattern Number: 80
    • Pattern Name: 80 Iterative Refinement
    • File Path: patterns\execution_control\80_iterative_refinement.py
    • Total Lines: 261

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 80: Iterative Refinement Pattern
    
    Progressively improves output through multiple refinement iterations with
    external feedback. Each iteration addresses specific issues identified in feedback.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 80 Iterative Refinement pattern.


    Imports Section

    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
        from typing import Callable  # First 20 imports shown
    

    Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional: 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 – from typing import Callable: Type hints for better code documentation


    Enumerations

    FeedbackType (Line 16)

    class FeedbackType(Enum):
        POSITIVE
        NEGATIVE
        SUGGESTION
        CORRECTION
    

    Purpose: Types of feedback.

    Values: – POSITIVE: Represents positive – NEGATIVE: Represents negative – SUGGESTION: Represents suggestion – CORRECTION: Represents correction


    Classes

    FeedbackType (Line 16)

    Description: Types of feedback.

    Feedback (Line 25)

    Description: External feedback on output.

    RefinementIteration (Line 35)

    Description: Single refinement iteration.

    IterativeRefinementAgent (Line 45)

    Description: Agent that refines output based on feedback.

    Methods:

    __init__ (Line 48)
    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”)

    generate_initial (Line 53)
    def generate_initial(self, query):
        """Generate initial output."""
    

    Purpose: Generate initial output.

    Parameters: – self: Instance reference – query: Parameter for query

    refine_with_feedback (Line 64)
    def refine_with_feedback(self, query, previous_output, feedback_list):
        """Refine output based on feedback."""
    

    Purpose: Refine output based on feedback.

    Parameters: – self: Instance reference – query: Parameter for query – previous_output: Parameter for previous_output – feedback_list: Parameter for feedback_list

    _extract_improvements (Line 98)
    def _extract_improvements(self, output):
        """Extract improvement list from output."""
    

    Purpose: Extract improvement list from output.

    Parameters: – self: Instance reference – output: Parameter for output

    IterativeRefinementPattern (Line 114)

    Description: Iterative Refinement Pattern – Progressive improvement with feedback.

    Generates initial output, receives external feedback, refines iteratively until quality criteria met or max iterations reached.

    Methods:

    __init__ (Line 122)
    def __init__(self, max_iterations):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – max_iterations: Parameter for max_iterations

    register_agent (Line 126)
    def register_agent(self, agent):
        """Register refinement agent."""
    

    Purpose: Register refinement agent.

    Parameters: – self: Instance reference – agent: Parameter for agent

    run (Line 130)
    def run(self, query, feedback_provider, stopping_criterion):
        """Execute iterative refinement.
    
    Args:
        query: Input query/task
        feedback_provider: Function that generates feedback for output
        stopping_criterion: Optional function to determine when to stop"""
    

    Purpose: Execute iterative refinement.

    Args: query: Input query/task feedback_provider: Function that generates feedback for output stopping_criterion: Optional function to determine when to stop

    Parameters: – self: Instance reference – query: Parameter for query – feedback_provider: Parameter for feedback_provider – stopping_criterion: Parameter for stopping_criterion


    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

  • Agentic Architecture Pattern: Self Refinement

    
        """
    Pattern 79: Self-Refinement Pattern
    
    Agents iteratively refine outputs using self-feedback without external critique.
    Automatically improves responses through multiple refinement iterations.
    """
    
    from typing import Dict, Any, List, Optional
    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 RefinementCriteria(Enum):
        """Criteria for refinement evaluation."""
        CLARITY = "clarity"
        ACCURACY = "accuracy"
        COMPLETENESS = "completeness"
        COHERENCE = "coherence"
        CONCISENESS = "conciseness"
    
    
    @dataclass
    class RefinementStep:
        """Single refinement iteration."""
        step_number: int
        original_text: str
        refined_text: str
        improvements_made: List[str]
        criteria_scores: Dict[RefinementCriteria, float]
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    class SelfRefiningAgent:
        """Agent with self-refinement capabilities."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
            self.refinement_history: List[RefinementStep] = []
        
        def generate_initial(self, task: str) -> str:
            """Generate initial response."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}. Provide your response to the task."),
                ("human", "{task}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"task": task})
            
            return str(response.content)
        
        def self_critique(self, text: str, criteria: List[RefinementCriteria]) -> tuple[List[str], Dict[RefinementCriteria, float]]:
            """Critique own output against criteria."""
            criteria_text = "\n".join([f"- {c.value.capitalize()}" for c in criteria])
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name} critiquing your own work. Be honest and specific."),
                ("human", f"Your text:\n{text}\n\n"
                         f"Evaluate your text on these criteria:\n{criteria_text}\n\n"
                         f"For each criterion:\n"
                         f"1. Rate it from 0.0 to 1.0\n"
                         f"2. Identify specific improvements needed\n\n"
                         f"Format: criterion_name: score | improvement")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            # Parse response
            improvements = []
            scores = {}
            
            for line in str(response.content).split('\n'):
                line = line.strip()
                if '|' in line:
                    parts = line.split('|')
                    if len(parts) >= 2:
                        improvement = parts[1].strip()
                        if improvement:
                            improvements.append(improvement)
                        
                        # Try to extract score
                        score_part = parts[0].strip()
                        for criterion in criteria:
                            if criterion.value in score_part.lower():
                                import re
                                nums = re.findall(r'0\.\d+|1\.0|1', score_part)
                                if nums:
                                    try:
                                        scores[criterion] = float(nums[0])
                                    except:
                                        scores[criterion] = 0.5
            
            # Fill in missing scores
            for criterion in criteria:
                if criterion not in scores:
                    scores[criterion] = 0.5
            
            return improvements[:5], scores
        
        def refine_text(self, original: str, improvements: List[str]) -> str:
            """Refine text based on identified improvements."""
            improvements_text = "\n".join([f"{i+1}. {imp}" for i, imp in enumerate(improvements)])
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}. Improve your text based on self-critique."),
                ("human", f"Original text:\n{original}\n\n"
                         f"Improvements to make:\n{improvements_text}\n\n"
                         f"Provide the refined version that addresses these improvements.")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content)
    
    
    class SelfRefinementPattern:
        """
        Self-Refinement Pattern - Iterative self-improvement without external feedback.
        
        Agent generates output, self-critiques against criteria, and refines
        through multiple iterations until quality threshold is met.
        """
        
        def __init__(self, max_iterations: int = 3, 
                     criteria: Optional[List[RefinementCriteria]] = None):
            self.max_iterations = max_iterations
            self.criteria = criteria or [
                RefinementCriteria.CLARITY,
                RefinementCriteria.ACCURACY,
                RefinementCriteria.COMPLETENESS
            ]
            self.agent: Optional[SelfRefiningAgent] = None
        
        def set_agent(self, agent: SelfRefiningAgent):
            """Set the self-refining agent."""
            self.agent = agent
        
        def refine(self, task: str, quality_threshold: float = 0.8) -> tuple[str, List[RefinementStep]]:
            """Execute self-refinement process."""
            if not self.agent:
                raise ValueError("No agent set")
            
            print(f"\n🔄 Starting self-refinement: {task}\n")
            
            # Initial generation
            text = self.agent.generate_initial(task)
            print(f"📝 Initial output:\n   {text[:200]}...\n")
            
            steps = []
            
            # Refinement iterations
            for iteration in range(self.max_iterations):
                print(f"🔧 Refinement iteration {iteration + 1}:")
                
                # Self-critique
                improvements, scores = self.agent.self_critique(text, self.criteria)
                avg_score = sum(scores.values()) / len(scores) if scores else 0
                
                print(f"   Criteria scores:")
                for criterion, score in scores.items():
                    print(f"   - {criterion.value}: {score:.2f}")
                print(f"   Average: {avg_score:.2f}")
                
                # Check if quality threshold met
                if avg_score >= quality_threshold:
                    print(f"   ✅ Quality threshold reached: {avg_score:.2f} >= {quality_threshold}")
                    break
                
                # Refine
                print(f"   Applying {len(improvements)} improvements...")
                refined = self.agent.refine_text(text, improvements)
                
                # Record step
                step = RefinementStep(
                    step_number=iteration,
                    original_text=text,
                    refined_text=refined,
                    improvements_made=improvements,
                    criteria_scores=scores
                )
                steps.append(step)
                self.agent.refinement_history.append(step)
                
                text = refined
            
            print(f"\n✅ Final refined output:\n   {text[:200]}...\n")
            return text, steps
        
        def get_improvement_metrics(self, steps: List[RefinementStep]) -> Dict[str, Any]:
            """Calculate improvement metrics."""
            if not steps:
                return {"iterations": 0}
            
            initial_scores = steps[0].criteria_scores if steps else {}
            final_scores = steps[-1].criteria_scores if steps else {}
            
            improvements = {}
            for criterion in self.criteria:
                initial = initial_scores.get(criterion, 0)
                final = final_scores.get(criterion, 0)
                improvements[criterion.value] = final - initial
            
            total_improvements = sum(len(step.improvements_made) for step in steps)
            
            return {
                "iterations": len(steps),
                "total_improvements_applied": total_improvements,
                "score_improvements": improvements,
                "initial_avg_score": sum(initial_scores.values()) / len(initial_scores) if initial_scores else 0,
                "final_avg_score": sum(final_scores.values()) / len(final_scores) if final_scores else 0
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Self-Refinement Pattern Demo ===\n")
        
        # Create self-refining agent
        print("1. Creating self-refining agent...")
        agent = SelfRefiningAgent("Refiner")
        
        # Create pattern with criteria
        pattern = SelfRefinementPattern(
            max_iterations=3,
            criteria=[
                RefinementCriteria.CLARITY,
                RefinementCriteria.ACCURACY,
                RefinementCriteria.COMPLETENESS,
                RefinementCriteria.COHERENCE
            ]
        )
        pattern.set_agent(agent)
        
        # Test tasks
        tasks = [
            "Explain blockchain technology",
            "Write a product description for a smart watch",
            "Describe the scientific method"
        ]
        
        all_metrics = []
        
        for i, task in enumerate(tasks, 1):
            print(f"\n{'='*70}")
            print(f"Task {i}/{len(tasks)}: {task}")
            print(f"{'='*70}")
            
            # Execute self-refinement
            final_text, steps = pattern.refine(task, quality_threshold=0.75)
            
            # Get metrics
            metrics = pattern.get_improvement_metrics(steps)
            all_metrics.append(metrics)
            
            print(f"📊 Refinement Metrics:")
            print(f"   Iterations: {metrics['iterations']}")
            print(f"   Total improvements: {metrics['total_improvements_applied']}")
            print(f"   Initial avg score: {metrics['initial_avg_score']:.2f}")
            print(f"   Final avg score: {metrics['final_avg_score']:.2f}")
            print(f"   Overall improvement: {metrics['final_avg_score'] - metrics['initial_avg_score']:+.2f}")
            
            print(f"\n   Score improvements by criterion:")
            for criterion, improvement in metrics['score_improvements'].items():
                print(f"   - {criterion}: {improvement:+.2f}")
        
        # Overall statistics
        print(f"\n\n{'='*70}")
        print("📈 Overall Statistics")
        print(f"{'='*70}")
        
        avg_iterations = sum(m['iterations'] for m in all_metrics) / len(all_metrics)
        avg_improvements = sum(m['total_improvements_applied'] for m in all_metrics) / len(all_metrics)
        avg_score_gain = sum(m['final_avg_score'] - m['initial_avg_score'] for m in all_metrics) / len(all_metrics)
        
        print(f"   Tasks processed: {len(tasks)}")
        print(f"   Avg iterations: {avg_iterations:.1f}")
        print(f"   Avg improvements per task: {avg_improvements:.1f}")
        print(f"   Avg score improvement: {avg_score_gain:+.2f}")
        
        # Show refinement progression for last task
        if agent.refinement_history:
            print(f"\n   Refinement progression (last task):")
            for step in agent.refinement_history[-3:]:
                avg = sum(step.criteria_scores.values()) / len(step.criteria_scores)
                print(f"   Step {step.step_number + 1}: {avg:.2f} -> {len(step.improvements_made)} improvements")
        
        print("\n✓ Self-refinement pattern enabled automatic quality improvement!")
    
        

    Agentic Architecture Pattern: Self Refinement

    Pattern 79: 79 Self Refinement – Line-by-Line Explanation

    Overview

    Pattern 79: Self-Refinement Pattern

    Agents iteratively refine outputs using self-feedback without external critique. Automatically improves responses through multiple refinement iterations.


    Code Structure Analysis

    File Information

    • Pattern Number: 79
    • Pattern Name: 79 Self Refinement
    • File Path: patterns\execution_control\79_self_refinement.py
    • Total Lines: 294

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 79: Self-Refinement Pattern
    
    Agents iteratively refine outputs using self-feedback without external critique.
    Automatically improves responses through multiple refinement iterations.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 79 Self Refinement pattern.


    Imports Section

    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
                                import re  # First 20 imports shown
    

    Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional: 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

    RefinementCriteria (Line 16)

    class RefinementCriteria(Enum):
        CLARITY
        ACCURACY
        COMPLETENESS
        COHERENCE
        CONCISENESS
    

    Purpose: Criteria for refinement evaluation.

    Values: – CLARITY: Represents clarity – ACCURACY: Represents accuracy – COMPLETENESS: Represents completeness – COHERENCE: Represents coherence – CONCISENESS: Represents conciseness


    Classes

    RefinementCriteria (Line 16)

    Description: Criteria for refinement evaluation.

    RefinementStep (Line 26)

    Description: Single refinement iteration.

    SelfRefiningAgent (Line 36)

    Description: Agent with self-refinement capabilities.

    Methods:

    __init__ (Line 39)
    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”)

    generate_initial (Line 44)
    def generate_initial(self, task):
        """Generate initial response."""
    

    Purpose: Generate initial response.

    Parameters: – self: Instance reference – task: Parameter for task

    self_critique (Line 56)
    def self_critique(self, text, criteria):
        """Critique own output against criteria."""
    

    Purpose: Critique own output against criteria.

    Parameters: – self: Instance reference – text: Parameter for text – criteria: Parameter for criteria

    refine_text (Line 105)
    def refine_text(self, original, improvements):
        """Refine text based on identified improvements."""
    

    Purpose: Refine text based on identified improvements.

    Parameters: – self: Instance reference – original: Parameter for original – improvements: Parameter for improvements

    SelfRefinementPattern (Line 122)

    Description: Self-Refinement Pattern – Iterative self-improvement without external feedback.

    Agent generates output, self-critiques against criteria, and refines through multiple iterations until quality threshold is met.

    Methods:

    __init__ (Line 130)
    def __init__(self, max_iterations, criteria):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – max_iterations: Parameter for max_iterations – criteria: Parameter for criteria

    set_agent (Line 140)
    def set_agent(self, agent):
        """Set the self-refining agent."""
    

    Purpose: Set the self-refining agent.

    Parameters: – self: Instance reference – agent: Parameter for agent

    refine (Line 144)
    def refine(self, task, quality_threshold):
        """Execute self-refinement process."""
    

    Purpose: Execute self-refinement process.

    Parameters: – self: Instance reference – task: Parameter for task – quality_threshold: Parameter for quality_threshold

    get_improvement_metrics (Line 195)
    def get_improvement_metrics(self, steps):
        """Calculate improvement metrics."""
    

    Purpose: Calculate improvement metrics.

    Parameters: – self: Instance reference – steps: Parameter for steps


    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 = RefinementCriteria(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

  • Agentic Architecture Pattern: Reflection

    
        """
    Pattern 78: Reflection Pattern
    
    Agents reflect on their outputs, identify improvements, and refine responses.
    Implements self-critique and iterative improvement through reflection.
    """
    
    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    @dataclass
    class ReflectionCycle:
        """Single reflection cycle."""
        cycle_id: int
        original_output: str
        reflection: str
        improvements: List[str]
        refined_output: str
        quality_score: float  # 0 to 1
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class ReflectionMetrics:
        """Metrics for reflection pattern."""
        total_cycles: int
        avg_quality_improvement: float
        final_quality_score: float
        total_improvements: int
    
    
    class ReflectiveAgent:
        """Agent with reflection capabilities."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
            self.reflection_history: List[ReflectionCycle] = []
        
        def generate(self, task: str) -> str:
            """Generate initial response."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}. Provide your best answer to the task."),
                ("human", "{task}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"task": task})
            
            return str(response.content)
        
        def reflect(self, task: str, output: str) -> tuple[str, List[str]]:
            """Reflect on output and identify improvements."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name} reflecting on your previous response. "
                          f"Be critical and identify specific improvements."),
                ("human", f"Task: {task}\n\n"
                         f"Your previous response:\n{output}\n\n"
                         f"Reflect on your response:\n"
                         f"1. What did you do well?\n"
                         f"2. What could be improved?\n"
                         f"3. What specific changes would make it better?\n\n"
                         f"Provide your reflection and list 2-3 specific improvements.")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            reflection_text = str(response.content)
            
            # Extract improvements
            improvements = []
            lines = reflection_text.split('\n')
            for line in lines:
                line = line.strip()
                if line and (line[0].isdigit() or line.startswith('-') or line.startswith('•')):
                    improvements.append(line.lstrip('0123456789.-•) ').strip())
            
            return reflection_text, improvements[:5]  # Max 5 improvements
        
        def refine(self, task: str, previous_output: str, 
                   improvements: List[str]) -> str:
            """Refine output based on improvements."""
            improvements_text = "\n".join([f"- {imp}" for imp in improvements])
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}. Improve your previous response based on reflections."),
                ("human", f"Task: {task}\n\n"
                         f"Previous response:\n{previous_output}\n\n"
                         f"Identified improvements:\n{improvements_text}\n\n"
                         f"Provide an improved response that addresses these points.")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content)
        
        def evaluate_quality(self, task: str, output: str) -> float:
            """Evaluate quality of output (0 to 1)."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are an objective quality evaluator."),
                ("human", f"Task: {task}\n\n"
                         f"Response: {output}\n\n"
                         f"Rate the quality of this response on a scale of 0 to 1, where:\n"
                         f"0 = Very poor, 0.5 = Acceptable, 1 = Excellent\n\n"
                         f"Consider accuracy, completeness, clarity, and relevance.\n"
                         f"Respond with just a number between 0 and 1.")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            try:
                # Extract number from response
                import re
                numbers = re.findall(r'0\.\d+|1\.0|1', str(response.content))
                if numbers:
                    score = float(numbers[0])
                    return min(1.0, max(0.0, score))
            except:
                pass
            
            return 0.5  # Default score
    
    
    class ReflectionPattern:
        """
        Reflection Pattern - Self-critique and iterative improvement.
        
        Agent generates output, reflects on it, identifies improvements,
        and refines the response through multiple reflection cycles.
        """
        
        def __init__(self, max_cycles: int = 3, quality_threshold: float = 0.85):
            self.max_cycles = max_cycles
            self.quality_threshold = quality_threshold
            self.agent: Optional[ReflectiveAgent] = None
        
        def set_agent(self, agent: ReflectiveAgent):
            """Set the reflective agent."""
            self.agent = agent
        
        def execute(self, task: str) -> tuple[str, List[ReflectionCycle]]:
            """Execute reflection pattern on task."""
            if not self.agent:
                raise ValueError("No agent set for reflection")
            
            print(f"\n🔄 Starting reflection pattern for: {task}\n")
            
            # Initial generation
            output = self.agent.generate(task)
            quality = self.agent.evaluate_quality(task, output)
            
            print(f"📝 Initial output (quality: {quality:.2f}):")
            print(f"   {output[:150]}...")
            
            reflection_cycles = []
            
            # Reflection cycles
            for cycle_num in range(self.max_cycles):
                print(f"\n🔍 Reflection Cycle {cycle_num + 1}:")
                
                # Reflect
                reflection, improvements = self.agent.reflect(task, output)
                
                print(f"   Found {len(improvements)} improvements:")
                for imp in improvements[:3]:
                    print(f"   - {imp[:80]}...")
                
                # Refine
                refined_output = self.agent.refine(task, output, improvements)
                new_quality = self.agent.evaluate_quality(task, refined_output)
                
                print(f"   New quality: {new_quality:.2f} (was {quality:.2f})")
                
                # Record cycle
                cycle = ReflectionCycle(
                    cycle_id=cycle_num,
                    original_output=output,
                    reflection=reflection,
                    improvements=improvements,
                    refined_output=refined_output,
                    quality_score=new_quality
                )
                
                reflection_cycles.append(cycle)
                self.agent.reflection_history.append(cycle)
                
                # Update for next cycle
                output = refined_output
                quality = new_quality
                
                # Check if quality threshold met
                if quality >= self.quality_threshold:
                    print(f"\n✅ Quality threshold reached: {quality:.2f} >= {self.quality_threshold}")
                    break
            
            print(f"\n✓ Reflection complete after {len(reflection_cycles)} cycles")
            print(f"   Final output (quality: {quality:.2f}):")
            print(f"   {output[:150]}...")
            
            return output, reflection_cycles
        
        def get_metrics(self, cycles: List[ReflectionCycle]) -> ReflectionMetrics:
            """Calculate metrics from reflection cycles."""
            if not cycles:
                return ReflectionMetrics(0, 0.0, 0.0, 0)
            
            quality_improvements = []
            for i in range(len(cycles) - 1):
                improvement = cycles[i + 1].quality_score - cycles[i].quality_score
                quality_improvements.append(improvement)
            
            avg_improvement = sum(quality_improvements) / len(quality_improvements) if quality_improvements else 0
            
            total_improvements = sum(len(cycle.improvements) for cycle in cycles)
            final_quality = cycles[-1].quality_score
            
            return ReflectionMetrics(
                total_cycles=len(cycles),
                avg_quality_improvement=avg_improvement,
                final_quality_score=final_quality,
                total_improvements=total_improvements
            )
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Reflection Pattern Demo ===\n")
        
        # Create reflective agent
        print("1. Creating reflective agent...")
        agent = ReflectiveAgent("Thinker")
        
        # Create reflection pattern
        pattern = ReflectionPattern(max_cycles=3, quality_threshold=0.85)
        pattern.set_agent(agent)
        
        # Test tasks
        tasks = [
            "Explain quantum computing to a 10-year-old",
            "Write a strategy for reducing carbon emissions in cities",
            "Design an algorithm to detect fake news"
        ]
        
        all_metrics = []
        
        for i, task in enumerate(tasks, 1):
            print(f"\n{'='*60}")
            print(f"Task {i}/{len(tasks)}")
            print(f"{'='*60}")
            
            # Execute reflection
            final_output, cycles = pattern.execute(task)
            
            # Get metrics
            metrics = pattern.get_metrics(cycles)
            all_metrics.append(metrics)
            
            print(f"\n📊 Metrics for this task:")
            print(f"   Reflection cycles: {metrics.total_cycles}")
            print(f"   Avg quality improvement: {metrics.avg_quality_improvement:+.3f}")
            print(f"   Final quality: {metrics.final_quality_score:.2f}")
            print(f"   Total improvements identified: {metrics.total_improvements}")
        
        # Overall statistics
        print(f"\n\n{'='*60}")
        print("📈 Overall Statistics")
        print(f"{'='*60}")
        
        avg_cycles = sum(m.total_cycles for m in all_metrics) / len(all_metrics)
        avg_final_quality = sum(m.final_quality_score for m in all_metrics) / len(all_metrics)
        total_improvements = sum(m.total_improvements for m in all_metrics)
        
        print(f"   Tasks processed: {len(tasks)}")
        print(f"   Avg reflection cycles: {avg_cycles:.1f}")
        print(f"   Avg final quality: {avg_final_quality:.2f}")
        print(f"   Total improvements: {total_improvements}")
        
        print("\n✓ Reflection pattern enabled self-improvement!")
    
        

    Agentic Architecture Pattern: Reflection

    Pattern 78: 78 Reflection – Line-by-Line Explanation

    Overview

    Pattern 78: Reflection Pattern

    Agents reflect on their outputs, identify improvements, and refine responses. Implements self-critique and iterative improvement through reflection.


    Code Structure Analysis

    File Information

    • Pattern Number: 78
    • Pattern Name: 78 Reflection
    • File Path: patterns\execution_control\78_reflection.py
    • Total Lines: 286

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 78: Reflection Pattern
    
    Agents reflect on their outputs, identify improvements, and refine responses.
    Implements self-critique and iterative improvement through reflection.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 78 Reflection pattern.


    Imports Section

    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
                import re  # First 20 imports shown
    

    Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional: 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 langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration


    Classes

    ReflectionCycle (Line 16)

    Description: Single reflection cycle.

    ReflectionMetrics (Line 28)

    Description: Metrics for reflection pattern.

    ReflectiveAgent (Line 36)

    Description: Agent with reflection capabilities.

    Methods:

    __init__ (Line 39)
    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”)

    generate (Line 44)
    def generate(self, task):
        """Generate initial response."""
    

    Purpose: Generate initial response.

    Parameters: – self: Instance reference – task: Parameter for task

    reflect (Line 56)
    def reflect(self, task, output):
        """Reflect on output and identify improvements."""
    

    Purpose: Reflect on output and identify improvements.

    Parameters: – self: Instance reference – task: Parameter for task – output: Parameter for output

    refine (Line 85)
    def refine(self, task, previous_output, improvements):
        """Refine output based on improvements."""
    

    Purpose: Refine output based on improvements.

    Parameters: – self: Instance reference – task: Parameter for task – previous_output: Parameter for previous_output – improvements: Parameter for improvements

    evaluate_quality (Line 103)
    def evaluate_quality(self, task, output):
        """Evaluate quality of output (0 to 1)."""
    

    Purpose: Evaluate quality of output (0 to 1).

    Parameters: – self: Instance reference – task: Parameter for task – output: Parameter for output

    ReflectionPattern (Line 131)

    Description: Reflection Pattern – Self-critique and iterative improvement.

    Agent generates output, reflects on it, identifies improvements, and refines the response through multiple reflection cycles.

    Methods:

    __init__ (Line 139)
    def __init__(self, max_cycles, quality_threshold):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – max_cycles: Parameter for max_cycles – quality_threshold: Parameter for quality_threshold

    set_agent (Line 144)
    def set_agent(self, agent):
        """Set the reflective agent."""
    

    Purpose: Set the reflective agent.

    Parameters: – self: Instance reference – agent: Parameter for agent

    execute (Line 148)
    def execute(self, task):
        """Execute reflection pattern on task."""
    

    Purpose: Execute reflection pattern on task.

    Parameters: – self: Instance reference – task: Parameter for task

    get_metrics (Line 209)
    def get_metrics(self, cycles):
        """Calculate metrics from reflection cycles."""
    

    Purpose: Calculate metrics from reflection cycles.

    Parameters: – self: Instance reference – cycles: Parameter for cycles


    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 = ReflectionCycle(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

  • Agentic Architecture Pattern: React

    
        """
    Pattern 77: ReAct (Reasoning + Acting) Pattern
    Interleaves reasoning traces with task-specific actions.
    """
    
    from typing import Dict, Any, List, Optional, Callable
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from pydantic import BaseModel
    from enum import Enum
    
    
    class StepType(str, Enum):
        THOUGHT = "thought"
        ACTION = "action"
        OBSERVATION = "observation"
    
    
    class ReActStep(BaseModel):
        """Represents a step in the ReAct cycle."""
        type: StepType
        content: str
        step_number: int
    
    
    class ReActPattern:
        """
        ReAct Pattern - Reasoning and Acting in an interleaved manner.
        The agent alternates between thinking about what to do and taking actions.
        """
        
        def __init__(self, model_name: str = "gpt-4"):
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
            self.available_actions = self._define_actions()
            self.trace: List[ReActStep] = []
        
        def _define_actions(self) -> Dict[str, Callable]:
            """Define available actions the agent can take."""
            return {
                "search": lambda query: f"Search results for: {query}",
                "calculate": lambda expr: f"Calculation result: {eval(expr)}",
                "lookup": lambda term: f"Definition of {term}: [simulated lookup]",
                "finish": lambda answer: f"Final Answer: {answer}"
            }
        
        def think(self, question: str, context: str = "") -> str:
            """Reasoning step - agent thinks about next action."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", """You are using the ReAct (Reasoning + Acting) pattern.
                
                Think step-by-step about how to answer this question.
                You can use these actions: {actions}
                
                Context so far:
                {context}
                
                Provide your thought process about what to do next."""),
                ("human", "Question: {question}\n\nThought:")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({
                "question": question,
                "actions": ", ".join(self.available_actions.keys()),
                "context": context or "No previous steps"
            })
            
            return response.content
        
        def act(self, thought: str) -> tuple[str, str]:
            """Action step - agent takes an action based on reasoning."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", """Based on this thought, decide which action to take.
                
                Available actions: {actions}
                
                Thought: {thought}
                
                Respond with: Action: [action_name]([argument])
                For example: Action: search(quantum computing)"""),
                ("human", "What action should be taken?")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({
                "thought": thought,
                "actions": ", ".join(self.available_actions.keys())
            })
            
            # Parse action
            action_str = response.content
            action_name = "search"
            action_arg = thought[:30]
            
            if "Action:" in action_str:
                try:
                    action_part = action_str.split("Action:")[1].strip()
                    action_name = action_part.split("(")[0].strip()
                    action_arg = action_part.split("(")[1].split(")")[0].strip()
                except:
                    pass
            
            return action_name, action_arg
        
        def observe(self, action_name: str, action_arg: str) -> str:
            """Observation step - observe the result of the action."""
            if action_name in self.available_actions:
                try:
                    result = self.available_actions[action_name](action_arg)
                    return result
                except Exception as e:
                    return f"Error executing {action_name}: {e}"
            return f"Unknown action: {action_name}"
        
        def run(self, question: str, max_steps: int = 5) -> Dict[str, Any]:
            """
            Execute the ReAct pattern: Think -> Act -> Observe -> Repeat.
            """
            self.trace = []
            context = ""
            final_answer = None
            
            for step_num in range(max_steps):
                # Step 1: Think (Reasoning)
                thought = self.think(question, context)
                self.trace.append(ReActStep(
                    type=StepType.THOUGHT,
                    content=thought,
                    step_number=step_num + 1
                ))
                
                # Step 2: Act
                action_name, action_arg = self.act(thought)
                action_str = f"{action_name}({action_arg})"
                self.trace.append(ReActStep(
                    type=StepType.ACTION,
                    content=action_str,
                    step_number=step_num + 1
                ))
                
                # Check if we're done
                if action_name == "finish":
                    final_answer = action_arg
                    break
                
                # Step 3: Observe
                observation = self.observe(action_name, action_arg)
                self.trace.append(ReActStep(
                    type=StepType.OBSERVATION,
                    content=observation,
                    step_number=step_num + 1
                ))
                
                # Update context
                context += f"\nStep {step_num + 1}:\n  Thought: {thought}\n  Action: {action_str}\n  Observation: {observation}"
            
            return {
                "question": question,
                "trace": self.trace,
                "final_answer": final_answer,
                "total_steps": len(self.trace) // 3
            }
        
        def format_trace(self) -> str:
            """Format the trace for display."""
            output = []
            for step in self.trace:
                prefix = {
                    StepType.THOUGHT: "💭 Thought",
                    StepType.ACTION: "⚡ Action",
                    StepType.OBSERVATION: "👁 Observation"
                }[step.type]
                output.append(f"{prefix} {step.step_number}: {step.content}")
            return "\n".join(output)
    
    
    # Example usage
    if __name__ == "__main__":
        agent = ReActPattern()
        
        question = "What is 15% of 240?"
        
        print("=== ReAct Pattern: Reasoning + Acting ===\n")
        print(f"Question: {question}\n")
        
        result = agent.run(question, max_steps=3)
        
        print("=== Execution Trace ===\n")
        print(agent.format_trace())
        
        if result["final_answer"]:
            print(f"\n=== Final Answer ===")
            print(result["final_answer"])
    
        

    Agentic Architecture Pattern: React

    Pattern 77: 77 React – Line-by-Line Explanation

    Overview

    Pattern 77: ReAct (Reasoning + Acting) Pattern Interleaves reasoning traces with task-specific actions.


    Code Structure Analysis

    File Information

    • Pattern Number: 77
    • Pattern Name: 77 React
    • File Path: patterns\execution_control\77_react.py
    • Total Lines: 194

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 77: ReAct (Reasoning + Acting) Pattern
    Interleaves reasoning traces with task-specific actions.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 77 React pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Callable
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from pydantic import BaseModel
    from enum import Enum  # 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 langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration – from enum import Enum: Enumeration support for fixed sets of values


    Enumerations

    StepType (Line 13)

    class StepType(Enum):
        THOUGHT
        ACTION
        OBSERVATION
    

    Purpose: No enum docstring.

    Values: – THOUGHT: Represents thought – ACTION: Represents action – OBSERVATION: Represents observation


    Classes

    StepType (Line 13)

    Description: No class docstring.

    ReActStep (Line 19)

    Description: Represents a step in the ReAct cycle.

    ReActPattern (Line 26)

    Description: ReAct Pattern – Reasoning and Acting in an interleaved manner. The agent alternates between thinking about what to do and taking actions.

    Methods:

    __init__ (Line 32)
    def __init__(self, model_name):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – model_name: LLM model to use (e.g., “gpt-4”)

    _define_actions (Line 37)
    def _define_actions(self):
        """Define available actions the agent can take."""
    

    Purpose: Define available actions the agent can take.

    Parameters: – self: Instance reference

    think (Line 46)
    def think(self, question, context):
        """Reasoning step - agent thinks about next action."""
    

    Purpose: Reasoning step – agent thinks about next action.

    Parameters: – self: Instance reference – question: Parameter for question – context: Parameter for context

    act (Line 70)
    def act(self, thought):
        """Action step - agent takes an action based on reasoning."""
    

    Purpose: Action step – agent takes an action based on reasoning.

    Parameters: – self: Instance reference – thought: Parameter for thought

    observe (Line 105)
    def observe(self, action_name, action_arg):
        """Observation step - observe the result of the action."""
    

    Purpose: Observation step – observe the result of the action.

    Parameters: – self: Instance reference – action_name: Parameter for action_name – action_arg: Parameter for action_arg

    run (Line 115)
    def run(self, question, max_steps):
        """Execute the ReAct pattern: Think -> Act -> Observe -> Repeat."""
    

    Purpose: Execute the ReAct pattern: Think -> Act -> Observe -> Repeat.

    Parameters: – self: Instance reference – question: Parameter for question – max_steps: Parameter for max_steps

    format_trace (Line 164)
    def format_trace(self):
        """Format the trace for display."""
    

    Purpose: Format the trace for display.

    Parameters: – self: Instance reference


    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 = StepType(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

  • Agentic Architecture Pattern: Graph Of Thought

    
        """
    Pattern 76: Graph-of-Thought Pattern
    
    Reasoning as a graph structure with nodes (thoughts) and edges (relationships).
    Allows parallel exploration, backtracking, and aggregation of multiple reasoning paths.
    """
    
    from typing import Dict, Any, List, Optional, Set
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langgraph.graph import StateGraph, END
    from typing_extensions import TypedDict
    
    
    class ThoughtType(Enum):
        """Type of thought node."""
        HYPOTHESIS = "hypothesis"
        EVIDENCE = "evidence"
        REASONING = "reasoning"
        CONCLUSION = "conclusion"
        QUESTION = "question"
    
    
    @dataclass
    class ThoughtNode:
        """Node in the thought graph."""
        node_id: str
        content: str
        thought_type: ThoughtType
        confidence: float = 0.5  # 0.0 to 1.0
        parent_ids: List[str] = field(default_factory=list)
        child_ids: List[str] = field(default_factory=list)
        metadata: Dict[str, Any] = field(default_factory=dict)
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class ThoughtEdge:
        """Edge connecting thoughts."""
        from_id: str
        to_id: str
        relationship: str  # supports, contradicts, questions, leads_to
        strength: float = 0.5  # 0.0 to 1.0
    
    
    class GraphOfThoughtState(TypedDict):
        """State for graph-of-thought workflow."""
        problem: str
        nodes: List[ThoughtNode]
        edges: List[ThoughtEdge]
        current_node_id: Optional[str]
        explored_ids: Set[str]
        conclusions: List[str]
    
    
    class GraphOfThoughtPattern:
        """
        Graph-of-Thought Pattern - Non-linear reasoning with graph structure.
        
        Thoughts are organized as a graph allowing:
        - Parallel exploration of multiple paths
        - Backtracking when needed
        - Aggregation of insights from different branches
        - Complex relationship modeling
        """
        
        def __init__(self, model_name: str = "gpt-4"):
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
            self.graph = StateGraph(GraphOfThoughtState)
            self._build_graph()
            self.workflow = self.graph.compile()
        
        def _build_graph(self):
            """Build the LangGraph workflow."""
            self.graph.add_node("generate_hypotheses", self._generate_hypotheses)
            self.graph.add_node("explore_path", self._explore_path)
            self.graph.add_node("evaluate_node", self._evaluate_node)
            self.graph.add_node("aggregate_insights", self._aggregate_insights)
            
            self.graph.set_entry_point("generate_hypotheses")
            
            self.graph.add_edge("generate_hypotheses", "explore_path")
            self.graph.add_edge("explore_path", "evaluate_node")
            
            self.graph.add_conditional_edges(
                "evaluate_node",
                self._should_continue_exploration,
                {
                    "explore": "explore_path",
                    "aggregate": "aggregate_insights",
                }
            )
            
            self.graph.add_edge("aggregate_insights", END)
        
        def _generate_hypotheses(self, state: GraphOfThoughtState) -> GraphOfThoughtState:
            """Generate initial hypothesis nodes."""
            print(f"\n   Generating hypotheses for: {state['problem']}")
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", "Generate 3 diverse hypotheses or approaches to solve this problem. "
                          "Each should explore a different angle. Return one per line."),
                ("human", "{problem}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"problem": state['problem']})
            
            hypotheses = [h.strip() for h in response.content.split('\n') if h.strip()][:3]
            
            nodes = []
            for i, hypothesis in enumerate(hypotheses):
                node = ThoughtNode(
                    node_id=f"hyp_{i}",
                    content=hypothesis,
                    thought_type=ThoughtType.HYPOTHESIS,
                    confidence=0.5
                )
                nodes.append(node)
                print(f"   - Hypothesis {i+1}: {hypothesis[:60]}...")
            
            state["nodes"] = nodes
            state["edges"] = []
            state["explored_ids"] = set()
            state["conclusions"] = []
            
            return state
        
        def _explore_path(self, state: GraphOfThoughtState) -> GraphOfThoughtState:
            """Explore a thought path by expanding a node."""
            # Find unexplored node
            unexplored = [n for n in state["nodes"] 
                         if n.node_id not in state["explored_ids"]]
            
            if not unexplored:
                return state
            
            current_node = unexplored[0]
            state["current_node_id"] = current_node.node_id
            
            print(f"\n   Exploring: {current_node.content[:60]}...")
            
            # Generate reasoning from this node
            prompt = ChatPromptTemplate.from_messages([
                ("system", "Based on this thought, generate 2 follow-up thoughts: "
                          "either supporting evidence, counterarguments, or logical next steps. "
                          "Return one per line."),
                ("human", "{thought}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"thought": current_node.content})
            
            follow_ups = [f.strip() for f in response.content.split('\n') if f.strip()][:2]
            
            for i, follow_up in enumerate(follow_ups):
                child_id = f"{current_node.node_id}_child_{i}"
                child_node = ThoughtNode(
                    node_id=child_id,
                    content=follow_up,
                    thought_type=ThoughtType.REASONING,
                    parent_ids=[current_node.node_id],
                    confidence=0.6
                )
                state["nodes"].append(child_node)
                current_node.child_ids.append(child_id)
                
                # Create edge
                edge = ThoughtEdge(
                    from_id=current_node.node_id,
                    to_id=child_id,
                    relationship="leads_to",
                    strength=0.7
                )
                state["edges"].append(edge)
                
                print(f"   - Follow-up: {follow_up[:50]}...")
            
            state["explored_ids"].add(current_node.node_id)
            
            return state
        
        def _evaluate_node(self, state: GraphOfThoughtState) -> GraphOfThoughtState:
            """Evaluate current node's confidence."""
            current_id = state.get("current_node_id")
            if not current_id:
                return state
            
            current_node = next((n for n in state["nodes"] if n.node_id == current_id), None)
            if not current_node:
                return state
            
            # Simple evaluation based on depth and branching
            depth = len([p for p in current_node.parent_ids])
            children_count = len(current_node.child_ids)
            
            # Update confidence
            current_node.confidence = min(1.0, 0.5 + (children_count * 0.1) + (depth * 0.05))
            
            return state
        
        def _should_continue_exploration(self, state: GraphOfThoughtState) -> str:
            """Decide whether to continue exploring or aggregate."""
            explored = len(state["explored_ids"])
            total = len(state["nodes"])
            
            # Explore at least 5 nodes or until 80% explored
            if explored  0 and explored / total  GraphOfThoughtState:
            """Aggregate insights from the thought graph."""
            print(f"\n   Aggregating insights from {len(state['nodes'])} thoughts...")
            
            # Find leaf nodes (conclusions)
            leaf_nodes = [n for n in state["nodes"] if not n.child_ids]
            
            # Prepare summary of reasoning paths
            paths_summary = []
            for leaf in leaf_nodes[:3]:  # Top 3 paths
                path = self._trace_path(leaf, state["nodes"])
                paths_summary.append(" → ".join([n.content[:40] for n in path]))
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", "Given these reasoning paths, synthesize a final conclusion. "
                          "Be comprehensive and consider all perspectives."),
                ("human", "Problem: {problem}\n\nReasoning paths:\n{paths}\n\nProvide final conclusion:")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({
                "problem": state['problem'],
                "paths": "\n".join([f"{i+1}. {p}" for i, p in enumerate(paths_summary)])
            })
            
            state["conclusions"] = [response.content]
            print(f"   - Synthesized conclusion")
            
            return state
        
        def _trace_path(self, node: ThoughtNode, all_nodes: List[ThoughtNode]) -> List[ThoughtNode]:
            """Trace path from root to this node."""
            path = [node]
            current = node
            
            while current.parent_ids:
                parent_id = current.parent_ids[0]
                parent = next((n for n in all_nodes if n.node_id == parent_id), None)
                if not parent:
                    break
                path.insert(0, parent)
                current = parent
            
            return path
        
        def run(self, problem: str) -> Dict[str, Any]:
            """Execute graph-of-thought reasoning."""
            print(f"\n=== Graph-of-Thought Pattern ===")
            
            initial_state: GraphOfThoughtState = {
                "problem": problem,
                "nodes": [],
                "edges": [],
                "current_node_id": None,
                "explored_ids": set(),
                "conclusions": []
            }
            
            final_state = self.workflow.invoke(initial_state)
            
            return {
                "pattern": "GraphOfThought",
                "problem": problem,
                "total_nodes": len(final_state["nodes"]),
                "total_edges": len(final_state["edges"]),
                "explored_nodes": len(final_state["explored_ids"]),
                "conclusions": final_state["conclusions"],
                "graph_structure": {
                    "nodes": len(final_state["nodes"]),
                    "edges": len(final_state["edges"]),
                    "hypotheses": len([n for n in final_state["nodes"] 
                                      if n.thought_type == ThoughtType.HYPOTHESIS])
                }
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Graph-of-Thought Pattern Demo ===\n")
        
        pattern = GraphOfThoughtPattern()
        
        # Complex problem requiring non-linear reasoning
        problem = """
        A company wants to reduce its carbon footprint by 50% in 2 years.
        They have manufacturing plants, offices, and a delivery fleet.
        What strategy should they pursue?
        """
        
        print("Problem:", problem.strip())
        
        result = pattern.run(problem)
        
        print(f"\n=== Results ===")
        print(f"Total thought nodes: {result['total_nodes']}")
        print(f"Explored nodes: {result['explored_nodes']}")
        print(f"Graph edges: {result['total_edges']}")
        print(f"Hypotheses generated: {result['graph_structure']['hypotheses']}")
        
        print(f"\n=== Final Conclusion ===")
        for conclusion in result['conclusions']:
            print(f"{conclusion}")
        
        print("\n✓ Graph-of-thought reasoning completed with non-linear exploration!")
    
        

    Agentic Architecture Pattern: Graph Of Thought

    Pattern 76: 76 Graph Of Thought – Line-by-Line Explanation

    Overview

    Pattern 76: Graph-of-Thought Pattern

    Reasoning as a graph structure with nodes (thoughts) and edges (relationships). Allows parallel exploration, backtracking, and aggregation of multiple reasoning paths.


    Code Structure Analysis

    File Information

    • Pattern Number: 76
    • Pattern Name: 76 Graph Of Thought
    • File Path: patterns\execution_control\76_graph_of_thought.py
    • Total Lines: 319

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 76: Graph-of-Thought Pattern
    
    Reasoning as a graph structure with nodes (thoughts) and edges (relationships).
    Allows parallel exploration, backtracking, and aggregation of multiple reasoning paths.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 76 Graph Of Thought pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Set
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langgraph.graph import StateGraph, END
    from typing_extensions import TypedDict  # First 20 imports shown
    

    Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional, Set: 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 – from langgraph.graph import StateGraph, END: LangGraph for workflow orchestration – from typing_extensions import TypedDict: Type hints for better code documentation


    Enumerations

    ThoughtType (Line 18)

    class ThoughtType(Enum):
        HYPOTHESIS
        EVIDENCE
        REASONING
        CONCLUSION
        QUESTION
    

    Purpose: Type of thought node.

    Values: – HYPOTHESIS: Represents hypothesis – EVIDENCE: Represents evidence – REASONING: Represents reasoning – CONCLUSION: Represents conclusion – QUESTION: Represents question


    Classes

    ThoughtType (Line 18)

    Description: Type of thought node.

    ThoughtNode (Line 28)

    Description: Node in the thought graph.

    ThoughtEdge (Line 41)

    Description: Edge connecting thoughts.

    GraphOfThoughtState (Line 49)

    Description: State for graph-of-thought workflow.

    GraphOfThoughtPattern (Line 59)

    Description: Graph-of-Thought Pattern – Non-linear reasoning with graph structure.

    Thoughts are organized as a graph allowing: – Parallel exploration of multiple paths – Backtracking when needed – Aggregation of insights from different branches – Complex relationship modeling

    Methods:

    __init__ (Line 70)
    def __init__(self, model_name):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – model_name: LLM model to use (e.g., “gpt-4”)

    _build_graph (Line 76)
    def _build_graph(self):
        """Build the LangGraph workflow."""
    

    Purpose: Build the LangGraph workflow.

    Parameters: – self: Instance reference

    _generate_hypotheses (Line 99)
    def _generate_hypotheses(self, state):
        """Generate initial hypothesis nodes."""
    

    Purpose: Generate initial hypothesis nodes.

    Parameters: – self: Instance reference – state: Current workflow state

    _explore_path (Line 132)
    def _explore_path(self, state):
        """Explore a thought path by expanding a node."""
    

    Purpose: Explore a thought path by expanding a node.

    Parameters: – self: Instance reference – state: Current workflow state

    _evaluate_node (Line 186)
    def _evaluate_node(self, state):
        """Evaluate current node's confidence."""
    

    Purpose: Evaluate current node’s confidence.

    Parameters: – self: Instance reference – state: Current workflow state

    _should_continue_exploration (Line 205)
    def _should_continue_exploration(self, state):
        """Decide whether to continue exploring or aggregate."""
    

    Purpose: Decide whether to continue exploring or aggregate.

    Parameters: – self: Instance reference – state: Current workflow state

    _aggregate_insights (Line 215)
    def _aggregate_insights(self, state):
        """Aggregate insights from the thought graph."""
    

    Purpose: Aggregate insights from the thought graph.

    Parameters: – self: Instance reference – state: Current workflow state

    _trace_path (Line 245)
    def _trace_path(self, node, all_nodes):
        """Trace path from root to this node."""
    

    Purpose: Trace path from root to this node.

    Parameters: – self: Instance reference – node: Parameter for node – all_nodes: Parameter for all_nodes

    run (Line 260)
    def run(self, problem):
        """Execute graph-of-thought reasoning."""
    

    Purpose: Execute graph-of-thought reasoning.

    Parameters: – self: Instance reference – problem: Parameter for problem


    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 = ThoughtType(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

  • Agentic Architecture Pattern: Tree Of Thought

    
        """
    Pattern 75: Tree-of-Thought Pattern
    
    Explores multiple reasoning paths in parallel, evaluates them, and
    selects the best solution. Enables deliberate decision making through
    search over thought trees.
    """
    
    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    import uuid
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    @dataclass
    class ThoughtNode:
        """Node in the thought tree."""
        id: str
        content: str
        parent_id: Optional[str]
        children_ids: List[str] = field(default_factory=list)
        score: float = 0.0
        depth: int = 0
        is_terminal: bool = False
        evaluation: Optional[str] = None
    
    
    class TreeOfThoughtPattern:
        """
        Tree-of-Thought Pattern - Explores multiple reasoning branches.
        
        Generates multiple thought paths, evaluates them, and searches
        for the best solution through tree exploration.
        """
        
        def __init__(self, model_name: str = "gpt-4", max_depth: int = 3, branches_per_node: int = 3):
            self.llm = ChatOpenAI(model=model_name, temperature=0.9)
            self.evaluator_llm = ChatOpenAI(model=model_name, temperature=0.3)
            self.max_depth = max_depth
            self.branches_per_node = branches_per_node
            self.nodes: Dict[str, ThoughtNode] = {}
            self.root_id: Optional[str] = None
        
        def generate_thoughts(self, problem: str, parent_thought: Optional[str] = None, depth: int = 0) -> List[str]:
            """Generate multiple thought branches."""
            if depth >= self.max_depth:
                return []
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", "You are a creative problem solver. Generate diverse approaches to solve the problem. "
                          "Each approach should be distinct and explore different angles."),
                ("human", f"Problem: {problem}\n"
                         f"{'Current thought: ' + parent_thought if parent_thought else ''}\n\n"
                         f"Generate {self.branches_per_node} different next steps or approaches. "
                         f"Provide them as a numbered list (1. ... 2. ... 3. ...)")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            content = str(response.content)
            
            # Parse thoughts from response
            thoughts = []
            for line in content.split('\n'):
                line = line.strip()
                if line and (line[0].isdigit() or line.startswith('-') or line.startswith('•')):
                    # Remove numbering/bullets
                    thought = line.lstrip('0123456789.-•) ').strip()
                    if thought:
                        thoughts.append(thought)
            
            return thoughts[:self.branches_per_node]
        
        def evaluate_thought(self, problem: str, thought: str) -> float:
            """Evaluate quality of a thought."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", "You are an expert evaluator. Rate how promising this thought/approach is "
                          "for solving the problem. Consider feasibility, creativity, and likelihood of success."),
                ("human", f"Problem: {problem}\n"
                         f"Thought/Approach: {thought}\n\n"
                         f"Rate this approach from 0.0 (terrible) to 10.0 (excellent). "
                         f"Provide only the numeric rating.")
            ])
            
            chain = prompt | self.evaluator_llm
            response = chain.invoke({})
            content = str(response.content).strip()
            
            # Extract numeric rating
            try:
                # Find first number in response
                import re
                match = re.search(r'(\d+\.?\d*)', content)
                if match:
                    score = float(match.group(1))
                    return min(10.0, max(0.0, score))
            except:
                pass
            
            return 5.0  # Default middle score
        
        def build_tree(self, problem: str):
            """Build tree of thoughts."""
            # Create root node
            root_id = str(uuid.uuid4())
            self.root_id = root_id
            
            root_node = ThoughtNode(
                id=root_id,
                content=f"Problem: {problem}",
                parent_id=None,
                depth=0
            )
            self.nodes[root_id] = root_node
            
            # Build tree level by level
            nodes_to_expand = [root_node]
            
            while nodes_to_expand:
                current_node = nodes_to_expand.pop(0)
                
                if current_node.depth >= self.max_depth:
                    current_node.is_terminal = True
                    continue
                
                # Generate child thoughts
                thoughts = self.generate_thoughts(
                    problem,
                    current_node.content if current_node.depth > 0 else None,
                    current_node.depth
                )
                
                for thought in thoughts:
                    # Create child node
                    child_id = str(uuid.uuid4())
                    child_node = ThoughtNode(
                        id=child_id,
                        content=thought,
                        parent_id=current_node.id,
                        depth=current_node.depth + 1
                    )
                    
                    # Evaluate thought
                    score = self.evaluate_thought(problem, thought)
                    child_node.score = score
                    child_node.evaluation = f"Score: {score:.1f}/10.0"
                    
                    self.nodes[child_id] = child_node
                    current_node.children_ids.append(child_id)
                    
                    # Add to expansion queue if not at max depth
                    if child_node.depth  List[ThoughtNode]:
            """Get highest-scoring path from root to leaf."""
            if not self.root_id:
                return []
            
            def find_best_path_recursive(node_id: str) -> tuple[List[ThoughtNode], float]:
                """Recursively find best path."""
                node = self.nodes[node_id]
                
                if not node.children_ids or node.is_terminal:
                    return ([node], node.score)
                
                best_path = [node]
                best_score = node.score
                
                for child_id in node.children_ids:
                    child_path, child_score = find_best_path_recursive(child_id)
                    total_score = node.score + child_score
                    
                    if total_score > best_score:
                        best_score = total_score
                        best_path = [node] + child_path
                
                return (best_path, best_score)
            
            path, _ = find_best_path_recursive(self.root_id)
            return path
        
        def run(self, problem: str) -> Dict[str, Any]:
            """Execute tree-of-thought reasoning."""
            print(f"   Building thought tree (depth={self.max_depth}, branches={self.branches_per_node})...")
            
            # Build tree
            self.build_tree(problem)
            
            # Find best solution path
            best_path = self.get_best_path()
            
            # Analyze tree
            total_nodes = len(self.nodes)
            terminal_nodes = sum(1 for n in self.nodes.values() if n.is_terminal)
            avg_score = sum(n.score for n in self.nodes.values()) / total_nodes if total_nodes > 0 else 0
            
            return {
                "pattern": "TreeOfThought",
                "problem": problem,
                "total_thoughts": total_nodes,
                "terminal_thoughts": terminal_nodes,
                "average_score": avg_score,
                "best_path_length": len(best_path),
                "best_path": [{"depth": n.depth, "thought": n.content, "score": n.score} for n in best_path],
                "best_solution": best_path[-1].content if best_path else None
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Tree-of-Thought Pattern Demo ===\n")
        
        # Create pattern
        pattern = TreeOfThoughtPattern(max_depth=2, branches_per_node=3)
        
        # Solve problem
        print("1. Solving problem with tree-of-thought reasoning...")
        problem = "How can we reduce carbon emissions in urban transportation?"
        
        result = pattern.run(problem)
        
        print(f"\n2. Tree Statistics:")
        print(f"   Total Thoughts Explored: {result['total_thoughts']}")
        print(f"   Terminal Thoughts: {result['terminal_thoughts']}")
        print(f"   Average Score: {result['average_score']:.2f}/10.0")
        
        print(f"\n3. Best Reasoning Path:")
        for step in result['best_path']:
            indent = "   " * step['depth']
            print(f"{indent}└─ [{step['score']:.1f}] {step['thought'][:80]}...")
        
        print(f"\n4. Best Solution:")
        print(f"   {result['best_solution']}")
        
        print("\n✓ Tree-of-thought pattern explored multiple reasoning paths!")
    
        

    Agentic Architecture Pattern: Tree Of Thought

    Pattern 75: 75 Tree Of Thought – Line-by-Line Explanation

    Overview

    Pattern 75: Tree-of-Thought Pattern

    Explores multiple reasoning paths in parallel, evaluates them, and selects the best solution. Enables deliberate decision making through search over thought trees.


    Code Structure Analysis

    File Information

    • Pattern Number: 75
    • Pattern Name: 75 Tree Of Thought
    • File Path: patterns\execution_control\75_tree_of_thought.py
    • Total Lines: 239

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 75: Tree-of-Thought Pattern
    
    Explores multiple reasoning paths in parallel, evaluates them, and
    selects the best solution. Enables deliberate decision making through
    search over thought trees.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 75 Tree Of Thought pattern.


    Imports Section

    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    import uuid
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
                import re  # First 20 imports shown
    

    Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional: 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 langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration


    Classes

    ThoughtNode (Line 18)

    Description: Node in the thought tree.

    TreeOfThoughtPattern (Line 30)

    Description: Tree-of-Thought Pattern – Explores multiple reasoning branches.

    Generates multiple thought paths, evaluates them, and searches for the best solution through tree exploration.

    Methods:

    __init__ (Line 38)
    def __init__(self, model_name, max_depth, branches_per_node):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – model_name: LLM model to use (e.g., “gpt-4”) – max_depth: Parameter for max_depth – branches_per_node: Parameter for branches_per_node

    generate_thoughts (Line 46)
    def generate_thoughts(self, problem, parent_thought, depth):
        """Generate multiple thought branches."""
    

    Purpose: Generate multiple thought branches.

    Parameters: – self: Instance reference – problem: Parameter for problem – parent_thought: Parameter for parent_thought – depth: Parameter for depth

    evaluate_thought (Line 76)
    def evaluate_thought(self, problem, thought):
        """Evaluate quality of a thought."""
    

    Purpose: Evaluate quality of a thought.

    Parameters: – self: Instance reference – problem: Parameter for problem – thought: Parameter for thought

    build_tree (Line 104)
    def build_tree(self, problem):
        """Build tree of thoughts."""
    

    Purpose: Build tree of thoughts.

    Parameters: – self: Instance reference – problem: Parameter for problem

    get_best_path (Line 157)
    def get_best_path(self):
        """Get highest-scoring path from root to leaf."""
    

    Purpose: Get highest-scoring path from root to leaf.

    Parameters: – self: Instance reference

    run (Line 185)
    def run(self, problem):
        """Execute tree-of-thought reasoning."""
    

    Purpose: Execute tree-of-thought reasoning.

    Parameters: – self: Instance reference – problem: Parameter for problem


    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 = ThoughtNode(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

  • Agentic Architecture Pattern: Chain Of Thought

    
        """
    Pattern 74: Chain Of Thought
    
    Purpose: Enhanced implementation with full LangChain/LangGraph integration
    """
    
    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langgraph.graph import StateGraph, END
    from typing_extensions import TypedDict
    
    
    @dataclass
    class ChainOfThoughtConfig:
        """Configuration for Chain Of Thought."""
        model_name: str = "gpt-4"
        temperature: float = 0.7
        max_iterations: int = 10
        enable_logging: bool = True
    
    
    @dataclass
    class ChainOfThoughtState:
        """State information for Chain Of Thought."""
        current_step: int = 0
        data: Dict[str, Any] = field(default_factory=dict)
        results: List[Any] = field(default_factory=list)
        metadata: Dict[str, Any] = field(default_factory=dict)
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    class ChainOfThoughtAgent:
        """Agent implementing Chain Of Thought."""
        
        def __init__(self, name: str, config: ChainOfThoughtConfig = None):
            self.name = name
            self.config = config or ChainOfThoughtConfig()
            self.llm = ChatOpenAI(
                model=self.config.model_name,
                temperature=self.config.temperature
            )
            self.state = ChainOfThoughtState()
            self.execution_history: List[Dict[str, Any]] = []
        
        def process(self, input_data: Any) -> Dict[str, Any]:
            """Process input according to Chain Of Thought."""
            self.state.current_step += 1
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, implementing Chain Of Thought. "
                          f"Provide clear, structured responses."),
                ("human", "Process this input: {input_data}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"input_data": str(input_data)})
            
            result = {
                "agent": self.name,
                "step": self.state.current_step,
                "input": input_data,
                "output": str(response.content),
                "timestamp": datetime.now()
            }
            
            self.execution_history.append(result)
            self.state.results.append(result)
            
            return result
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get agent statistics."""
            return {
                "name": self.name,
                "total_executions": len(self.execution_history),
                "current_step": self.state.current_step,
                "results_count": len(self.state.results)
            }
    
    
    class ChainOfThoughtPattern:
        """
        Chain Of Thought - Enhanced implementation
        
        This pattern provides comprehensive functionality for chain of thought
        with full LangChain/LangGraph integration.
        
        Features:
        - Multi-agent coordination
        - State management
        - Execution tracking
        - LangGraph workflow integration
        """
        
        def __init__(self, config: ChainOfThoughtConfig = None):
            self.config = config or ChainOfThoughtConfig()
            self.agents: Dict[str, ChainOfThoughtAgent] = {}
            self.workflow = self._build_workflow()
            self.execution_log: List[Dict[str, Any]] = []
        
        def _build_workflow(self) -> StateGraph:
            """Build LangGraph workflow for pattern execution."""
            
            class WorkflowState(TypedDict):
                input: str
                processed: str
                output: str
                metadata: Dict[str, Any]
            
            def process_input(state: WorkflowState) -> WorkflowState:
                """Process input node."""
                return {
                    **state,
                    "processed": f"Processed: {state['input']}",
                    "metadata": {"step": "process_input"}
                }
            
            def generate_output(state: WorkflowState) -> WorkflowState:
                """Generate output node."""
                llm = ChatOpenAI(model=self.config.model_name, temperature=self.config.temperature)
                
                prompt = ChatPromptTemplate.from_messages([
                    ("system", "You are implementing Chain Of Thought. Generate comprehensive output."),
                    ("human", "{input}")
                ])
                
                chain = prompt | llm
                response = chain.invoke({"input": state["processed"]})
                
                return {
                    **state,
                    "output": str(response.content),
                    "metadata": {**state.get("metadata", {}), "step": "generate_output"}
                }
            
            # Build workflow graph
            workflow = StateGraph(WorkflowState)
            workflow.add_node("process", process_input)
            workflow.add_node("generate", generate_output)
            workflow.set_entry_point("process")
            workflow.add_edge("process", "generate")
            workflow.add_edge("generate", END)
            
            return workflow.compile()
        
        def register_agent(self, agent: ChainOfThoughtAgent):
            """Register an agent with the pattern."""
            self.agents[agent.name] = agent
            if self.config.enable_logging:
                print(f"Registered agent: {agent.name}")
        
        def execute(self, input_data: Any, agent_name: str = None) -> Dict[str, Any]:
            """Execute the pattern with given input."""
            
            # Use workflow if no specific agent requested
            if agent_name is None:
                result = self.workflow.invoke({
                    "input": str(input_data),
                    "processed": "",
                    "output": "",
                    "metadata": {}
                })
                
                execution_record = {
                    "pattern": "Chain Of Thought",
                    "input": input_data,
                    "output": result.get("output", ""),
                    "metadata": result.get("metadata", {}),
                    "timestamp": datetime.now()
                }
                
                self.execution_log.append(execution_record)
                return execution_record
            
            # Execute with specific agent
            agent = self.agents.get(agent_name)
            if not agent:
                raise ValueError(f"Agent {agent_name} not found")
            
            result = agent.process(input_data)
            self.execution_log.append(result)
            return result
        
        def run(self, input_data: Any) -> Dict[str, Any]:
            """Main execution method."""
            return self.execute(input_data)
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get pattern statistics."""
            return {
                "pattern": "Chain Of Thought",
                "total_executions": len(self.execution_log),
                "registered_agents": len(self.agents),
                "agents": [agent.get_statistics() for agent in self.agents.values()]
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Chain Of Thought Demo ===\n")
        
        # Create configuration
        config = ChainOfThoughtConfig(
            model_name="gpt-4",
            temperature=0.7,
            enable_logging=True
        )
        
        # Create pattern
        pattern = ChainOfThoughtPattern(config)
        
        # Create and register agents
        agent1 = ChainOfThoughtAgent("Agent1", config)
        agent2 = ChainOfThoughtAgent("Agent2", config)
        pattern.register_agent(agent1)
        pattern.register_agent(agent2)
        
        print("\nExecuting pattern workflow...")
        
        # Execute with workflow
        result1 = pattern.run("Demonstrate chain of thought functionality")
        print(f"\nWorkflow Result:")
        print(f"  Output: {result1['output'][:150]}...")
        
        # Execute with specific agents
        result2 = pattern.execute("Specific task for Agent1", agent_name="Agent1")
        print(f"\nAgent1 Result:")
        print(f"  Output: {result2['output'][:150]}...")
        
        result3 = pattern.execute("Specific task for Agent2", agent_name="Agent2")
        print(f"\nAgent2 Result:")
        print(f"  Output: {result3['output'][:150]}...")
        
        # Show statistics
        print("\n=== Statistics ===")
        stats = pattern.get_statistics()
        print(f"Pattern: {stats['pattern']}")
        print(f"Total Executions: {stats['total_executions']}")
        print(f"Registered Agents: {stats['registered_agents']}")
        print(f"\nAgent Statistics:")
        for agent_stats in stats['agents']:
            print(f"  {agent_stats['name']}: {agent_stats['total_executions']} executions")
    
        

    Agentic Architecture Pattern: Chain Of Thought

    Pattern 74: 74 Chain Of Thought – Line-by-Line Explanation

    Overview

    Pattern 74: Chain Of Thought

    Purpose: Enhanced implementation with full LangChain/LangGraph integration


    Code Structure Analysis

    File Information

    • Pattern Number: 74
    • Pattern Name: 74 Chain Of Thought
    • File Path: patterns\execution_control\74_chain_of_thought.py
    • Total Lines: 247

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 74: Chain Of Thought
    
    Purpose: Enhanced implementation with full LangChain/LangGraph integration
    """
    

    Explanation: This module docstring describes the purpose and key features of the 74 Chain Of Thought pattern.


    Imports Section

    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langgraph.graph import StateGraph, END
    from typing_extensions import TypedDict  # First 20 imports shown
    

    Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional: 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 – from langgraph.graph import StateGraph, END: LangGraph for workflow orchestration – from typing_extensions import TypedDict: Type hints for better code documentation


    Classes

    ChainOfThoughtConfig (Line 18)

    Description: Configuration for Chain Of Thought.

    ChainOfThoughtState (Line 27)

    Description: State information for Chain Of Thought.

    ChainOfThoughtAgent (Line 36)

    Description: Agent implementing Chain Of Thought.

    Methods:

    __init__ (Line 39)
    def __init__(self, name, config):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – name: Identifier or label – config: Configuration settings

    process (Line 49)
    def process(self, input_data):
        """Process input according to Chain Of Thought."""
    

    Purpose: Process input according to Chain Of Thought.

    Parameters: – self: Instance reference – input_data: Parameter for input_data

    get_statistics (Line 75)
    def get_statistics(self):
        """Get agent statistics."""
    

    Purpose: Get agent statistics.

    Parameters: – self: Instance reference

    ChainOfThoughtPattern (Line 85)

    Description: Chain Of Thought – Enhanced implementation

    This pattern provides comprehensive functionality for chain of thought with full LangChain/LangGraph integration.

    Features: – Multi-agent coordination – State management – Execution tracking – LangGraph workflow integration

    Methods:

    __init__ (Line 99)
    def __init__(self, config):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – config: Configuration settings

    _build_workflow (Line 105)
    def _build_workflow(self):
        """Build LangGraph workflow for pattern execution."""
    

    Purpose: Build LangGraph workflow for pattern execution.

    Parameters: – self: Instance reference

    register_agent (Line 150)
    def register_agent(self, agent):
        """Register an agent with the pattern."""
    

    Purpose: Register an agent with the pattern.

    Parameters: – self: Instance reference – agent: Parameter for agent

    execute (Line 156)
    def execute(self, input_data, agent_name):
        """Execute the pattern with given input."""
    

    Purpose: Execute the pattern with given input.

    Parameters: – self: Instance reference – input_data: Parameter for input_data – agent_name: Parameter for agent_name

    run (Line 188)
    def run(self, input_data):
        """Main execution method."""
    

    Purpose: Main execution method.

    Parameters: – self: Instance reference – input_data: Parameter for input_data

    get_statistics (Line 192)
    def get_statistics(self):
        """Get pattern statistics."""
    

    Purpose: Get pattern statistics.

    Parameters: – self: Instance reference

    WorkflowState (Line 108)

    Description: No class docstring.


    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 = ChainOfThoughtConfig(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

  • Agentic Architecture Pattern: Pipeline

    
        """
    Pattern 73: Pipeline Pattern
    
    Data flows through a series of processing stages with transformations
    at each stage. Similar to Unix pipes or data processing pipelines.
    """
    
    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    @dataclass
    class PipelineStage:
        """Stage in the processing pipeline."""
        name: str
        processor: Callable[[Any], Any]
        description: str = ""
        input_type: Optional[str] = None
        output_type: Optional[str] = None
    
    
    @dataclass
    class PipelineResult:
        """Result from pipeline execution."""
        success: bool
        input_data: Any
        output_data: Optional[Any]
        stages_executed: List[str]
        stage_outputs: Dict[str, Any]
        execution_time: float
        error: Optional[str] = None
    
    
    class PipelineAgent:
        """Agent that acts as a pipeline stage."""
        
        def __init__(self, name: str, role: str, model_name: str = "gpt-4"):
            self.name = name
            self.role = role
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
        
        def transform(self, data: Any) -> Any:
            """Transform input data."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, a {self.role}. "
                          f"Transform the input data according to your role."),
                ("human", f"Input: {data}\n\nProvide transformed output.")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            return str(response.content)
    
    
    class PipelinePattern:
        """
        Pipeline Pattern - Sequential data transformation chain.
        
        Data flows through stages with each stage transforming the data.
        Stages can be agents, functions, or any callable processor.
        """
        
        def __init__(self):
            self.stages: List[PipelineStage] = []
            self.execution_log: List[PipelineResult] = []
        
        def add_stage(self, stage: PipelineStage):
            """Add stage to pipeline."""
            self.stages.append(stage)
        
        def add_agent_stage(self, agent: PipelineAgent, description: str = ""):
            """Add agent as pipeline stage."""
            stage = PipelineStage(
                name=agent.name,
                processor=agent.transform,
                description=description or f"{agent.role} processing"
            )
            self.stages.append(stage)
        
        def add_function_stage(self, name: str, func: Callable[[Any], Any], description: str = ""):
            """Add function as pipeline stage."""
            stage = PipelineStage(
                name=name,
                processor=func,
                description=description
            )
            self.stages.append(stage)
        
        def execute(self, input_data: Any) -> PipelineResult:
            """Execute data through pipeline."""
            start_time = datetime.now()
            
            stages_executed = []
            stage_outputs = {}
            current_data = input_data
            
            try:
                for stage in self.stages:
                    print(f"   Executing stage: {stage.name}...")
                    
                    # Process data through stage
                    current_data = stage.processor(current_data)
                    
                    # Log execution
                    stages_executed.append(stage.name)
                    stage_outputs[stage.name] = current_data
                
                execution_time = (datetime.now() - start_time).total_seconds()
                
                result = PipelineResult(
                    success=True,
                    input_data=input_data,
                    output_data=current_data,
                    stages_executed=stages_executed,
                    stage_outputs=stage_outputs,
                    execution_time=execution_time
                )
                
            except Exception as e:
                execution_time = (datetime.now() - start_time).total_seconds()
                
                result = PipelineResult(
                    success=False,
                    input_data=input_data,
                    output_data=None,
                    stages_executed=stages_executed,
                    stage_outputs=stage_outputs,
                    execution_time=execution_time,
                    error=str(e)
                )
            
            self.execution_log.append(result)
            return result
        
        def run(self, input_data: Any) -> Dict[str, Any]:
            """Run pipeline and return results."""
            result = self.execute(input_data)
            
            return {
                "pattern": "Pipeline",
                "success": result.success,
                "stages_executed": len(result.stages_executed),
                "total_stages": len(self.stages),
                "execution_time": result.execution_time,
                "output": result.output_data,
                "error": result.error
            }
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get pipeline statistics."""
            if not self.execution_log:
                return {"total_runs": 0}
            
            return {
                "total_runs": len(self.execution_log),
                "successful_runs": sum(1 for r in self.execution_log if r.success),
                "failed_runs": sum(1 for r in self.execution_log if not r.success),
                "avg_execution_time": sum(r.execution_time for r in self.execution_log) / len(self.execution_log),
                "total_stages": len(self.stages)
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Pipeline Pattern Demo ===\n")
        
        # Create pipeline
        pipeline = PipelinePattern()
        
        # Add agent-based stages
        print("1. Building pipeline with agents...")
        extractor = PipelineAgent("Extractor", "data extractor")
        transformer = PipelineAgent("Transformer", "data transformer")
        validator = PipelineAgent("Validator", "data validator")
        
        pipeline.add_agent_stage(extractor, "Extract key information")
        pipeline.add_agent_stage(transformer, "Transform to target format")
        pipeline.add_agent_stage(validator, "Validate output quality")
        
        # Add function-based stage
        def format_output(data: Any) -> str:
            return f"[FORMATTED] {str(data).upper()}"
        
        pipeline.add_function_stage("Formatter", format_output, "Format final output")
        
        # Execute pipeline
        print("\n2. Executing pipeline...")
        input_text = "Process this customer feedback: The product is great but shipping was slow."
        result = pipeline.run(input_text)
        
        print(f"\n3. Pipeline Results:")
        print(f"   Success: {result['success']}")
        print(f"   Stages Executed: {result['stages_executed']}/{result['total_stages']}")
        print(f"   Execution Time: {result['execution_time']:.2f}s")
        
        if result['output']:
            print(f"\n4. Final Output:")
            print(f"   {str(result['output'])[:150]}...")
        
        # Statistics
        stats = pipeline.get_statistics()
        print(f"\n5. Pipeline Statistics:")
        print(f"   Total Runs: {stats['total_runs']}")
        print(f"   Success Rate: {stats['successful_runs']}/{stats['total_runs']}")
        
        print("\n✓ Pipeline pattern processed data through transformation stages!")
    
        

    Agentic Architecture Pattern: Pipeline

    Pattern 73: 73 Pipeline – Line-by-Line Explanation

    Overview

    Pattern 73: Pipeline Pattern

    Data flows through a series of processing stages with transformations at each stage. Similar to Unix pipes or data processing pipelines.


    Code Structure Analysis

    File Information

    • Pattern Number: 73
    • Pattern Name: 73 Pipeline
    • File Path: patterns\execution_control\73_pipeline.py
    • Total Lines: 210

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 73: Pipeline Pattern
    
    Data flows through a series of processing stages with transformations
    at each stage. Similar to Unix pipes or data processing pipelines.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 73 Pipeline pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime
    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 langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration


    Classes

    PipelineStage (Line 16)

    Description: Stage in the processing pipeline.

    PipelineResult (Line 26)

    Description: Result from pipeline execution.

    PipelineAgent (Line 37)

    Description: Agent that acts as a pipeline stage.

    Methods:

    __init__ (Line 40)
    def __init__(self, name, role, model_name):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – name: Identifier or label – role: Parameter for role – model_name: LLM model to use (e.g., “gpt-4”)

    transform (Line 45)
    def transform(self, data):
        """Transform input data."""
    

    Purpose: Transform input data.

    Parameters: – self: Instance reference – data: Input data to process

    PipelinePattern (Line 58)

    Description: Pipeline Pattern – Sequential data transformation chain.

    Data flows through stages with each stage transforming the data. Stages can be agents, functions, or any callable processor.

    Methods:

    __init__ (Line 66)
    def __init__(self):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    add_stage (Line 70)
    def add_stage(self, stage):
        """Add stage to pipeline."""
    

    Purpose: Add stage to pipeline.

    Parameters: – self: Instance reference – stage: Parameter for stage

    add_agent_stage (Line 74)
    def add_agent_stage(self, agent, description):
        """Add agent as pipeline stage."""
    

    Purpose: Add agent as pipeline stage.

    Parameters: – self: Instance reference – agent: Parameter for agent – description: Parameter for description

    add_function_stage (Line 83)
    def add_function_stage(self, name, func, description):
        """Add function as pipeline stage."""
    

    Purpose: Add function as pipeline stage.

    Parameters: – self: Instance reference – name: Identifier or label – func: Parameter for func – description: Parameter for description

    execute (Line 92)
    def execute(self, input_data):
        """Execute data through pipeline."""
    

    Purpose: Execute data through pipeline.

    Parameters: – self: Instance reference – input_data: Parameter for input_data

    run (Line 138)
    def run(self, input_data):
        """Run pipeline and return results."""
    

    Purpose: Run pipeline and return results.

    Parameters: – self: Instance reference – input_data: Parameter for input_data

    get_statistics (Line 152)
    def get_statistics(self):
        """Get pipeline statistics."""
    

    Purpose: Get pipeline statistics.

    Parameters: – self: Instance reference


    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 = PipelineStage(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

  • Agentic Architecture Pattern: Parallel Agent

    
        """
    Pattern 72: Parallel Agent Pattern
    
    Multiple agents execute tasks concurrently for faster processing.
    Features parallel execution, result aggregation, and synchronization.
    """
    
    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    import asyncio
    import time
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    @dataclass
    class ParallelTask:
        """Task to be executed in parallel."""
        task_id: str
        description: str
        agent_name: Optional[str] = None
        input_data: Any = None
        result: Optional[str] = None
        status: str = "pending"  # pending, running, completed, failed
        start_time: Optional[datetime] = None
        end_time: Optional[datetime] = None
        duration: float = 0
    
    
    @dataclass
    class ParallelExecution:
        """Record of parallel execution."""
        execution_id: str
        tasks: List[ParallelTask]
        total_time: float
        speedup: float  # vs sequential execution
        efficiency: float  # speedup / num_agents
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    class ParallelAgent:
        """Agent that can execute tasks concurrently."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
            self.tasks_completed = 0
        
        async def execute_task_async(self, task: ParallelTask) -> str:
            """Execute task asynchronously."""
            task.status = "running"
            task.start_time = datetime.now()
            task.agent_name = self.name
            
            # Simulate work with LLM
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, executing a task in parallel with other agents."),
                ("human", f"Task: {task.description}\n"
                         f"Input: {task.input_data}\n\n"
                         f"Execute this task (provide brief result).")
            ])
            
            chain = prompt | self.llm
            
            # Simulate some processing time
            await asyncio.sleep(0.1)  # Small delay to simulate work
            
            response = chain.invoke({})
            result = str(response.content)[:200]
            
            task.end_time = datetime.now()
            task.duration = (task.end_time - task.start_time).total_seconds()
            task.result = result
            task.status = "completed"
            self.tasks_completed += 1
            
            return result
    
    
    class ParallelAgentPattern:
        """
        Parallel Agent Pattern - Concurrent task execution.
        
        Multiple agents work simultaneously on different tasks,
        reducing total execution time through parallelism.
        """
        
        def __init__(self):
            self.agents: List[ParallelAgent] = []
            self.execution_history: List[ParallelExecution] = []
        
        def register_agent(self, agent: ParallelAgent):
            """Register agent for parallel execution."""
            self.agents.append(agent)
        
        async def execute_parallel(self, tasks: List[ParallelTask]) -> ParallelExecution:
            """Execute tasks in parallel across available agents."""
            start_time = time.time()
            
            print(f"\n   Executing {len(tasks)} tasks in parallel with {len(self.agents)} agents...")
            
            # Assign tasks to agents (round-robin)
            task_assignments = []
            for i, task in enumerate(tasks):
                agent = self.agents[i % len(self.agents)]
                task_assignments.append(agent.execute_task_async(task))
            
            # Execute all tasks concurrently
            await asyncio.gather(*task_assignments)
            
            total_time = time.time() - start_time
            
            # Calculate metrics
            avg_task_duration = sum(t.duration for t in tasks) / len(tasks)
            sequential_time = sum(t.duration for t in tasks)
            speedup = sequential_time / total_time if total_time > 0 else 1
            efficiency = speedup / len(self.agents) if self.agents else 0
            
            print(f"   ✓ Completed in {total_time:.2f}s")
            print(f"   Speedup: {speedup:.2f}x (vs sequential: {sequential_time:.2f}s)")
            print(f"   Efficiency: {efficiency:.1%}")
            
            # Record execution
            execution = ParallelExecution(
                execution_id=f"exec_{len(self.execution_history)}",
                tasks=tasks,
                total_time=total_time,
                speedup=speedup,
                efficiency=efficiency
            )
            self.execution_history.append(execution)
            
            return execution
        
        def execute_parallel_sync(self, tasks: List[ParallelTask]) -> ParallelExecution:
            """Synchronous wrapper for parallel execution."""
            return asyncio.run(self.execute_parallel(tasks))
        
        def aggregate_results(self, tasks: List[ParallelTask]) -> Dict[str, Any]:
            """Aggregate results from parallel tasks."""
            completed = [t for t in tasks if t.status == "completed"]
            failed = [t for t in tasks if t.status == "failed"]
            
            results = {
                "total_tasks": len(tasks),
                "completed": len(completed),
                "failed": len(failed),
                "results": {t.task_id: t.result for t in completed},
                "agent_contributions": {}
            }
            
            # Count tasks per agent
            for task in completed:
                if task.agent_name:
                    results["agent_contributions"][task.agent_name] = \
                        results["agent_contributions"].get(task.agent_name, 0) + 1
            
            return results
        
        def run(self, scenario: str) -> Dict[str, Any]:
            """Execute parallel agent pattern."""
            total_executions = len(self.execution_history)
            avg_speedup = (sum(e.speedup for e in self.execution_history) / total_executions 
                          if total_executions > 0 else 0)
            avg_efficiency = (sum(e.efficiency for e in self.execution_history) / total_executions 
                             if total_executions > 0 else 0)
            
            return {
                "pattern": "ParallelAgent",
                "total_agents": len(self.agents),
                "total_executions": total_executions,
                "average_speedup": avg_speedup,
                "average_efficiency": avg_efficiency,
                "scenario": scenario
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Parallel Agent Pattern Demo ===\n")
        
        # Create pattern
        pattern = ParallelAgentPattern()
        
        # Register parallel agents
        print("1. Registering parallel agents...")
        agents = [
            ParallelAgent("Worker1"),
            ParallelAgent("Worker2"),
            ParallelAgent("Worker3"),
            ParallelAgent("Worker4"),
        ]
        
        for agent in agents:
            pattern.register_agent(agent)
        
        print(f"   Registered {len(agents)} agents")
        
        # Create tasks for parallel execution
        print("\n2. Creating tasks...")
        tasks = [
            ParallelTask("t1", "Analyze customer feedback", input_data="feedback_batch_1"),
            ParallelTask("t2", "Process invoice data", input_data="invoices_q4"),
            ParallelTask("t3", "Generate sales report", input_data="sales_data_nov"),
            ParallelTask("t4", "Classify support tickets", input_data="tickets_batch_5"),
            ParallelTask("t5", "Extract document insights", input_data="documents_set_3"),
            ParallelTask("t6", "Summarize meeting notes", input_data="meetings_week_45"),
            ParallelTask("t7", "Validate data quality", input_data="dataset_v2"),
            ParallelTask("t8", "Transform data format", input_data="raw_exports"),
        ]
        
        print(f"   Created {len(tasks)} tasks")
        
        # Execute in parallel
        print("\n3. Executing tasks in parallel...")
        execution = pattern.execute_parallel_sync(tasks)
        
        # Show task assignments
        print("\n4. Task Distribution:")
        for agent in agents:
            agent_tasks = [t for t in tasks if t.agent_name == agent.name]
            print(f"   {agent.name}: {len(agent_tasks)} tasks")
            for task in agent_tasks:
                print(f"      - {task.task_id}: {task.description} ({task.duration:.2f}s)")
        
        # Aggregate results
        print("\n5. Results Aggregation:")
        aggregated = pattern.aggregate_results(tasks)
        print(f"   Total Tasks: {aggregated['total_tasks']}")
        print(f"   Completed: {aggregated['completed']}")
        print(f"   Failed: {aggregated['failed']}")
        
        # Performance metrics
        print("\n6. Performance Metrics:")
        summary = pattern.run("Parallel data processing")
        print(f"   Agents: {summary['total_agents']}")
        print(f"   Average Speedup: {summary['average_speedup']:.2f}x")
        print(f"   Average Efficiency: {summary['average_efficiency']:.1%}")
        
        print("\n✓ Parallel agents executed tasks concurrently for faster processing!")
    
        

    Agentic Architecture Pattern: Parallel Agent

    Pattern 72: 72 Parallel Agent – Line-by-Line Explanation

    Overview

    Pattern 72: Parallel Agent Pattern

    Multiple agents execute tasks concurrently for faster processing. Features parallel execution, result aggregation, and synchronization.


    Code Structure Analysis

    File Information

    • Pattern Number: 72
    • Pattern Name: 72 Parallel Agent
    • File Path: patterns\execution_control\72_parallel_agent.py
    • Total Lines: 242

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 72: Parallel Agent Pattern
    
    Multiple agents execute tasks concurrently for faster processing.
    Features parallel execution, result aggregation, and synchronization.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 72 Parallel Agent pattern.


    Imports Section

    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    import asyncio
    import time
    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: 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 langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration


    Classes

    ParallelTask (Line 18)

    Description: Task to be executed in parallel.

    ParallelExecution (Line 32)

    Description: Record of parallel execution.

    ParallelAgent (Line 42)

    Description: Agent that can execute tasks concurrently.

    Methods:

    __init__ (Line 45)
    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”)

    ParallelAgentPattern (Line 81)

    Description: Parallel Agent Pattern – Concurrent task execution.

    Multiple agents work simultaneously on different tasks, reducing total execution time through parallelism.

    Methods:

    __init__ (Line 89)
    def __init__(self):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register_agent (Line 93)
    def register_agent(self, agent):
        """Register agent for parallel execution."""
    

    Purpose: Register agent for parallel execution.

    Parameters: – self: Instance reference – agent: Parameter for agent

    execute_parallel_sync (Line 136)
    def execute_parallel_sync(self, tasks):
        """Synchronous wrapper for parallel execution."""
    

    Purpose: Synchronous wrapper for parallel execution.

    Parameters: – self: Instance reference – tasks: Parameter for tasks

    aggregate_results (Line 140)
    def aggregate_results(self, tasks):
        """Aggregate results from parallel tasks."""
    

    Purpose: Aggregate results from parallel tasks.

    Parameters: – self: Instance reference – tasks: Parameter for tasks

    run (Line 161)
    def run(self, scenario):
        """Execute parallel agent pattern."""
    

    Purpose: Execute parallel agent pattern.

    Parameters: – self: Instance reference – scenario: Parameter for scenario


    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 = ParallelTask(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

  • Agentic Architecture Pattern: Sequential Agent

    
        """
    Pattern 71: Sequential Agent Pattern
    
    Agents execute tasks in a strict sequential order, with each agent processing
    the output of the previous agent in a linear chain.
    """
    
    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langgraph.graph import StateGraph, END
    from typing_extensions import TypedDict
    
    
    @dataclass
    class SequentialTask:
        """Task in sequential execution."""
        task_id: str
        agent_name: str
        input_data: Any
        output_data: Optional[Any] = None
        status: str = "pending"  # pending, running, completed, failed
        start_time: Optional[datetime] = None
        end_time: Optional[datetime] = None
        error: Optional[str] = None
    
    
    class SequentialState(TypedDict):
        """State for sequential execution workflow."""
        tasks: List[SequentialTask]
        current_index: int
        input_data: Any
        final_output: Optional[Any]
        execution_log: List[str]
    
    
    class SequentialAgent:
        """Agent that processes data sequentially."""
        
        def __init__(self, name: str, role: str, model_name: str = "gpt-4"):
            self.name = name
            self.role = role
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
        
        def process(self, input_data: Any) -> Any:
            """Process input and return output."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, a {self.role}. "
                          f"Process the input and provide your output for the next agent."),
                ("human", f"Input: {input_data}\n\nProvide your processed output.")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            return str(response.content)
    
    
    class SequentialAgentPattern:
        """
        Sequential Agent Pattern - Linear execution chain.
        
        Uses LangGraph to manage sequential workflow where each agent
        processes the output of the previous agent in strict order.
        """
        
        def __init__(self):
            self.agents: List[SequentialAgent] = []
            self.execution_history: List[SequentialTask] = []
        
        def add_agent(self, agent: SequentialAgent):
            """Add agent to sequential chain."""
            self.agents.append(agent)
        
        def build_graph(self) -> StateGraph:
            """Build sequential execution graph."""
            workflow = StateGraph(SequentialState)
            
            def execute_next(state: SequentialState) -> SequentialState:
                """Execute next agent in sequence."""
                current_idx = state["current_index"]
                tasks = state["tasks"]
                
                if current_idx >= len(tasks):
                    # All tasks completed
                    if tasks:
                        state["final_output"] = tasks[-1].output_data
                    return state
                
                task = tasks[current_idx]
                task.status = "running"
                task.start_time = datetime.now()
                
                try:
                    # Get agent
                    agent = self.agents[current_idx]
                    
                    # Get input (previous output or initial input)
                    if current_idx == 0:
                        input_data = state["input_data"]
                    else:
                        input_data = tasks[current_idx - 1].output_data
                    
                    # Execute agent
                    output = agent.process(input_data)
                    
                    task.output_data = output
                    task.status = "completed"
                    task.end_time = datetime.now()
                    
                    log_msg = f"Agent {agent.name} completed: {str(output)[:50]}..."
                    state["execution_log"].append(log_msg)
                    
                except Exception as e:
                    task.status = "failed"
                    task.error = str(e)
                    task.end_time = datetime.now()
                    state["execution_log"].append(f"Agent {task.agent_name} failed: {str(e)}")
                
                # Move to next
                state["current_index"] = current_idx + 1
                
                return state
            
            def should_continue(state: SequentialState) -> str:
                """Check if should continue to next agent."""
                if state["current_index"] >= len(state["tasks"]):
                    return "end"
                
                current_task = state["tasks"][state["current_index"]]
                if current_task.status == "failed":
                    return "end"
                
                return "continue"
            
            workflow.add_node("execute", execute_next)
            workflow.set_entry_point("execute")
            
            workflow.add_conditional_edges(
                "execute",
                should_continue,
                {
                    "continue": "execute",
                    "end": END
                }
            )
            
            return workflow.compile()
        
        def run(self, input_data: Any) -> Dict[str, Any]:
            """Execute sequential agent chain."""
            # Create tasks for each agent
            tasks = [
                SequentialTask(
                    task_id=f"task_{i}",
                    agent_name=agent.name,
                    input_data=input_data if i == 0 else None
                )
                for i, agent in enumerate(self.agents)
            ]
            
            initial_state: SequentialState = {
                "tasks": tasks,
                "current_index": 0,
                "input_data": input_data,
                "final_output": None,
                "execution_log": []
            }
            
            # Build and execute graph
            graph = self.build_graph()
            final_state = graph.invoke(initial_state)
            
            # Store history
            self.execution_history.extend(final_state["tasks"])
            
            return {
                "pattern": "Sequential",
                "agents_executed": len([t for t in final_state["tasks"] if t.status == "completed"]),
                "total_agents": len(self.agents),
                "final_output": final_state["final_output"],
                "execution_log": final_state["execution_log"],
                "success": all(t.status == "completed" for t in final_state["tasks"])
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Sequential Agent Pattern Demo ===\n")
        
        # Create pattern
        pattern = SequentialAgentPattern()
        
        # Create agent chain
        print("1. Creating sequential agent chain...")
        researcher = SequentialAgent("Researcher", "research analyst")
        writer = SequentialAgent("Writer", "content writer")
        editor = SequentialAgent("Editor", "editor and proofreader")
        formatter = SequentialAgent("Formatter", "document formatter")
        
        # Add agents in order
        pattern.add_agent(researcher)
        pattern.add_agent(writer)
        pattern.add_agent(editor)
        pattern.add_agent(formatter)
        
        # Execute sequential workflow
        print("\n2. Executing sequential workflow...")
        result = pattern.run("Write a blog post about AI agents")
        
        print(f"\n3. Results:")
        print(f"   Success: {result['success']}")
        print(f"   Agents Executed: {result['agents_executed']}/{result['total_agents']}")
        print(f"\n4. Execution Log:")
        for log in result['execution_log']:
            print(f"   - {log}")
        
        print(f"\n5. Final Output:")
        print(f"   {str(result['final_output'])[:200]}...")
        
        print("\n✓ Sequential agent pattern executed tasks in linear order!")
    
        

    Agentic Architecture Pattern: Sequential Agent

    Pattern 71: 71 Sequential Agent – Line-by-Line Explanation

    Overview

    Pattern 71: Sequential Agent Pattern

    Agents execute tasks in a strict sequential order, with each agent processing the output of the previous agent in a linear chain.


    Code Structure Analysis

    File Information

    • Pattern Number: 71
    • Pattern Name: 71 Sequential Agent
    • File Path: patterns\execution_control\71_sequential_agent.py
    • Total Lines: 223

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 71: Sequential Agent Pattern
    
    Agents execute tasks in a strict sequential order, with each agent processing
    the output of the previous agent in a linear chain.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 71 Sequential Agent pattern.


    Imports Section

    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langgraph.graph import StateGraph, END
    from typing_extensions import TypedDict  # First 20 imports shown
    

    Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional: 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 langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration – from langgraph.graph import StateGraph, END: LangGraph for workflow orchestration – from typing_extensions import TypedDict: Type hints for better code documentation


    Classes

    SequentialTask (Line 18)

    Description: Task in sequential execution.

    SequentialState (Line 30)

    Description: State for sequential execution workflow.

    SequentialAgent (Line 39)

    Description: Agent that processes data sequentially.

    Methods:

    __init__ (Line 42)
    def __init__(self, name, role, model_name):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – name: Identifier or label – role: Parameter for role – model_name: LLM model to use (e.g., “gpt-4”)

    process (Line 47)
    def process(self, input_data):
        """Process input and return output."""
    

    Purpose: Process input and return output.

    Parameters: – self: Instance reference – input_data: Parameter for input_data

    SequentialAgentPattern (Line 60)

    Description: Sequential Agent Pattern – Linear execution chain.

    Uses LangGraph to manage sequential workflow where each agent processes the output of the previous agent in strict order.

    Methods:

    __init__ (Line 68)
    def __init__(self):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    add_agent (Line 72)
    def add_agent(self, agent):
        """Add agent to sequential chain."""
    

    Purpose: Add agent to sequential chain.

    Parameters: – self: Instance reference – agent: Parameter for agent

    build_graph (Line 76)
    def build_graph(self):
        """Build sequential execution graph."""
    

    Purpose: Build sequential execution graph.

    Parameters: – self: Instance reference

    run (Line 151)
    def run(self, input_data):
        """Execute sequential agent chain."""
    

    Purpose: Execute sequential agent chain.

    Parameters: – self: Instance reference – input_data: Parameter for input_data


    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 = SequentialTask(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