Tag: llm

  • Agentic Architecture Pattern: Translation Agent

    
        """
    Pattern 237: Translation Agent
    
    Purpose: Multi-language translation with context preservation, quality checking, and dialect support.
    Implements automatic language detection, translation memory, and terminology management.
    """
    
    from typing import Dict, Any, List, Optional, Set
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from collections import defaultdict
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class TranslationQuality(Enum):
        """Translation quality levels."""
        DRAFT = "draft"  # Quick, basic translation
        STANDARD = "standard"  # Good quality
        PROFESSIONAL = "professional"  # High quality
        CERTIFIED = "certified"  # Legal/official level
    
    
    class TranslationStyle(Enum):
        """Translation style preferences."""
        FORMAL = "formal"
        INFORMAL = "informal"
        TECHNICAL = "technical"
        CREATIVE = "creative"
        LITERAL = "literal"
    
    
    @dataclass
    class TranslationMemoryEntry:
        """Entry in translation memory."""
        source_text: str
        target_text: str
        source_lang: str
        target_lang: str
        quality: TranslationQuality
        created_at: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class Translation:
        """A translation result."""
        source_text: str
        translated_text: str
        source_lang: str
        target_lang: str
        quality: TranslationQuality
        style: TranslationStyle
        confidence: float = 0.0
        detected_lang: Optional[str] = None
        alternatives: List[str] = field(default_factory=list)
        preserved_terms: Dict[str, str] = field(default_factory=dict)
    
    
    class TranslationAgent:
        """
        Translation Agent - Multi-language translation with quality control.
        
        Features:
        - Automatic language detection
        - Multi-language support
        - Translation memory for consistency
        - Terminology management
        - Quality levels
        - Style preferences
        - Context preservation
        - Alternative translations
        """
        
        def __init__(self, name: str):
            self.name = name
            self.llm = ChatOpenAI(model="gpt-4", temperature=0.3)
            
            # Translation resources
            self.translation_memory: List[TranslationMemoryEntry] = []
            self.terminology: Dict[str, Dict[str, str]] = defaultdict(dict)  # term -> {lang: translation}
            self.supported_languages: Set[str] = {
                "English", "Spanish", "French", "German", "Italian", "Portuguese",
                "Chinese", "Japanese", "Korean", "Arabic", "Russian", "Hindi"
            }
            
            # Statistics
            self.statistics: Dict[str, Any] = {
                "total_translations": 0,
                "languages_used": defaultdict(int),
                "quality_distribution": {q.value: 0 for q in TranslationQuality},
                "memory_hits": 0
            }
        
        def translate(self,
                      text: str,
                      target_lang: str,
                      source_lang: Optional[str] = None,
                      quality: TranslationQuality = TranslationQuality.STANDARD,
                      style: TranslationStyle = TranslationStyle.FORMAL) -> Translation:
            """Translate text to target language."""
            
            # Detect source language if not provided
            if source_lang is None:
                source_lang = self._detect_language(text)
            
            # Check translation memory
            memory_match = self._check_translation_memory(text, source_lang, target_lang)
            if memory_match:
                self.statistics["memory_hits"] += 1
                return memory_match
            
            # Apply terminology
            terms_to_preserve = self._extract_terms(text, source_lang, target_lang)
            
            # Perform translation
            translated_text = self._perform_translation(
                text, source_lang, target_lang, quality, style, terms_to_preserve
            )
            
            # Generate alternatives
            alternatives = self._generate_alternatives(text, source_lang, target_lang, 2)
            
            # Calculate confidence
            confidence = self._calculate_confidence(text, translated_text, quality)
            
            # Create translation object
            translation = Translation(
                source_text=text,
                translated_text=translated_text,
                source_lang=source_lang,
                target_lang=target_lang,
                quality=quality,
                style=style,
                confidence=confidence,
                detected_lang=source_lang,
                alternatives=alternatives,
                preserved_terms=terms_to_preserve
            )
            
            # Add to translation memory
            self._add_to_memory(translation)
            
            # Update statistics
            self.statistics["total_translations"] += 1
            self.statistics["languages_used"][f"{source_lang}->{target_lang}"] += 1
            self.statistics["quality_distribution"][quality.value] += 1
            
            return translation
        
        def _detect_language(self, text: str) -> str:
            """Detect source language of text."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", "Detect the language of the given text. "
                          "Return only the language name (e.g., 'English', 'Spanish', 'French')."),
                ("human", f"Text: {text[:200]}\n\nLanguage:")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            detected = str(response.content).strip()
            return detected if detected in self.supported_languages else "English"
        
        def _perform_translation(self,
                                text: str,
                                source_lang: str,
                                target_lang: str,
                                quality: TranslationQuality,
                                style: TranslationStyle,
                                preserve_terms: Dict[str, str]) -> str:
            """Perform the actual translation."""
            
            quality_instructions = {
                TranslationQuality.DRAFT: "Provide a quick, basic translation focusing on meaning.",
                TranslationQuality.STANDARD: "Provide an accurate translation with natural flow.",
                TranslationQuality.PROFESSIONAL: "Provide a high-quality, polished translation with attention to nuance.",
                TranslationQuality.CERTIFIED: "Provide a precise, formal translation suitable for official documents."
            }
            
            style_instructions = {
                TranslationStyle.FORMAL: "Use formal language and professional tone.",
                TranslationStyle.INFORMAL: "Use casual, conversational language.",
                TranslationStyle.TECHNICAL: "Maintain technical terminology and precision.",
                TranslationStyle.CREATIVE: "Adapt idioms and expressions creatively.",
                TranslationStyle.LITERAL: "Translate as literally as possible while maintaining sense."
            }
            
            terms_note = ""
            if preserve_terms:
                terms_list = ", ".join([f"'{k}' as '{v}'" for k, v in preserve_terms.items()])
                terms_note = f"\n\nPreserve these terms: {terms_list}"
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are an expert translator from {source_lang} to {target_lang}. "
                          f"{quality_instructions.get(quality, '')} "
                          f"{style_instructions.get(style, '')} "
                          f"Maintain the original meaning, tone, and context.{terms_note}"),
                ("human", f"Translate to {target_lang}:\n\n{text}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content).strip()
        
        def _generate_alternatives(self,
                                   text: str,
                                   source_lang: str,
                                   target_lang: str,
                                   count: int) -> List[str]:
            """Generate alternative translations."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"Provide {count} alternative translations from {source_lang} to {target_lang}. "
                          f"Each alternative should capture different nuances or phrasings. "
                          f"Return only the translations, one per line."),
                ("human", f"Text: {text}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            alternatives = [line.strip() for line in str(response.content).split('\n') if line.strip()]
            return alternatives[:count]
        
        def _extract_terms(self, text: str, source_lang: str, target_lang: str) -> Dict[str, str]:
            """Extract and translate terminology."""
            preserved = {}
            
            # Check terminology database
            for term, translations in self.terminology.items():
                if term.lower() in text.lower() and target_lang in translations:
                    preserved[term] = translations[target_lang]
            
            return preserved
        
        def _check_translation_memory(self,
                                      text: str,
                                      source_lang: str,
                                      target_lang: str) -> Optional[Translation]:
            """Check if translation exists in memory."""
            for entry in self.translation_memory:
                if (entry.source_text == text and
                    entry.source_lang == source_lang and
                    entry.target_lang == target_lang):
                    
                    return Translation(
                        source_text=entry.source_text,
                        translated_text=entry.target_text,
                        source_lang=entry.source_lang,
                        target_lang=entry.target_lang,
                        quality=entry.quality,
                        style=TranslationStyle.FORMAL,
                        confidence=1.0,
                        detected_lang=source_lang
                    )
            
            return None
        
        def _add_to_memory(self, translation: Translation):
            """Add translation to memory."""
            entry = TranslationMemoryEntry(
                source_text=translation.source_text,
                target_text=translation.translated_text,
                source_lang=translation.source_lang,
                target_lang=translation.target_lang,
                quality=translation.quality
            )
            
            self.translation_memory.append(entry)
            
            # Limit memory size
            if len(self.translation_memory) > 1000:
                self.translation_memory = self.translation_memory[-1000:]
        
        def _calculate_confidence(self, source: str, translation: str, quality: TranslationQuality) -> float:
            """Calculate translation confidence score."""
            # Simple heuristic (in production, use back-translation or BLEU score)
            base_confidence = {
                TranslationQuality.DRAFT: 0.6,
                TranslationQuality.STANDARD: 0.8,
                TranslationQuality.PROFESSIONAL: 0.9,
                TranslationQuality.CERTIFIED: 0.95
            }
            
            confidence = base_confidence.get(quality, 0.8)
            
            # Adjust based on length similarity
            len_ratio = len(translation) / len(source) if len(source) > 0 else 1.0
            if 0.5 <= len_ratio  List[Translation]:
            """Translate multiple texts."""
            return [self.translate(text, target_lang, source_lang) for text in texts]
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get translation statistics."""
            return {
                "name": self.name,
                "supported_languages": len(self.supported_languages),
                "memory_size": len(self.translation_memory),
                "terminology_entries": len(self.terminology),
                **self.statistics
            }
    
    
    class TranslationPattern:
        """
        Translation Pattern - Manage translation agents.
        
        Coordinates multiple translation agents for different purposes.
        """
        
        def __init__(self):
            self.agents: Dict[str, TranslationAgent] = {}
        
        def create_agent(self, name: str) -> TranslationAgent:
            """Create a new translation agent."""
            agent = TranslationAgent(name)
            self.agents[name] = agent
            print(f"   Created translation agent: {name}")
            return agent
        
        def run(self,
                agent_name: str,
                text: str,
                target_lang: str,
                source_lang: Optional[str] = None,
                quality: TranslationQuality = TranslationQuality.STANDARD) -> Dict[str, Any]:
            """Perform translation using specified agent."""
            if agent_name not in self.agents:
                return {"error": f"Agent {agent_name} not found"}
            
            agent = self.agents[agent_name]
            translation = agent.translate(text, target_lang, source_lang, quality)
            
            print(f"\n=== Translation by {agent_name} ===")
            print(f"Source ({translation.source_lang}): {translation.source_text[:100]}...")
            print(f"Target ({translation.target_lang}): {translation.translated_text}")
            print(f"Quality: {translation.quality.value} | Confidence: {translation.confidence:.1%}")
            
            if translation.alternatives:
                print("\nAlternatives:")
                for i, alt in enumerate(translation.alternatives, 1):
                    print(f"  {i}. {alt}")
            
            if translation.preserved_terms:
                print(f"\nPreserved Terms: {', '.join(translation.preserved_terms.keys())}")
            
            return {
                "agent": agent_name,
                "source_lang": translation.source_lang,
                "target_lang": translation.target_lang,
                "confidence": translation.confidence,
                "statistics": agent.get_statistics()
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Translation Agent Pattern Demo ===\n")
        
        # Create pattern
        pattern = TranslationPattern()
        
        # Create agents
        print("1. Setting up translation agents...")
        
        universal_translator = pattern.create_agent("UniversalTranslator")
        technical_translator = pattern.create_agent("TechnicalTranslator")
        
        # Add terminology
        print("\n2. Adding terminology...")
        universal_translator.add_terminology("machine learning", {
            "Spanish": "aprendizaje automático",
            "French": "apprentissage automatique",
            "German": "maschinelles Lernen"
        })
        
        # Perform translations
        print("\n3. Performing translations...")
        
        text1 = "Artificial intelligence is transforming the way we live and work."
        result1 = pattern.run("UniversalTranslator", text1, "Spanish", quality=TranslationQuality.PROFESSIONAL)
        
        print("\n" + "="*60 + "\n")
        
        text2 = "Machine learning algorithms analyze data to make predictions."
        result2 = pattern.run("UniversalTranslator", text2, "French", source_lang="English")
        
        print("\n" + "="*60 + "\n")
        
        text3 = "The quick brown fox jumps over the lazy dog."
        result3 = pattern.run("UniversalTranslator", text3, "German", quality=TranslationQuality.STANDARD)
        
        # Print statistics
        print("\n" + "="*60)
        print("\n4. Translation Statistics:")
        stats = result3["statistics"]
        for key, value in stats.items():
            print(f"   {key}: {value}")
        
        print("\n✓ Multi-language translation with quality control complete!")
    
    
        

    Agentic Architecture Pattern: Translation Agent

    Pattern 237: 237 Translation Agent – Line-by-Line Explanation

    Overview

    Pattern 237: Translation Agent

    Purpose: Multi-language translation with context preservation, quality checking, and dialect support. Implements automatic language detection, translation memory, and terminology management.


    Code Structure Analysis

    File Information

    • Pattern Number: 237
    • Pattern Name: 237 Translation Agent
    • File Path: patterns\domain_specific\237_translation_agent.py
    • Total Lines: 412

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 237: Translation Agent
    
    Purpose: Multi-language translation with context preservation, quality checking, and dialect support.
    Implements automatic language detection, translation memory, and terminology management.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 237 Translation Agent 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 collections import defaultdict
    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, 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


    Enumerations

    TranslationQuality (Line 17)

    class TranslationQuality(Enum):
        DRAFT
        STANDARD
        PROFESSIONAL
        CERTIFIED
    

    Purpose: Translation quality levels.

    Values: – DRAFT: Represents draft – STANDARD: Represents standard – PROFESSIONAL: Represents professional – CERTIFIED: Represents certified

    TranslationStyle (Line 25)

    class TranslationStyle(Enum):
        FORMAL
        INFORMAL
        TECHNICAL
        CREATIVE
        LITERAL
    

    Purpose: Translation style preferences.

    Values: – FORMAL: Represents formal – INFORMAL: Represents informal – TECHNICAL: Represents technical – CREATIVE: Represents creative – LITERAL: Represents literal


    Classes

    TranslationQuality (Line 17)

    Description: Translation quality levels.

    TranslationStyle (Line 25)

    Description: Translation style preferences.

    TranslationMemoryEntry (Line 35)

    Description: Entry in translation memory.

    Translation (Line 46)

    Description: A translation result.

    TranslationAgent (Line 60)

    Description: Translation Agent – Multi-language translation with quality control.

    Features: – Automatic language detection – Multi-language support – Translation memory for consistency – Terminology management – Quality levels – Style preferences – Context preservation – Alternative translations

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference – name: Identifier or label

    translate (Line 95)
    def translate(self, text, target_lang, source_lang, quality, style):
        """Translate text to target language."""
    

    Purpose: Translate text to target language.

    Parameters: – self: Instance reference – text: Parameter for text – target_lang: Parameter for target_lang – source_lang: Parameter for source_lang – quality: Parameter for quality – style: Parameter for style

    _detect_language (Line 151)
    def _detect_language(self, text):
        """Detect source language of text."""
    

    Purpose: Detect source language of text.

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

    _perform_translation (Line 165)
    def _perform_translation(self, text, source_lang, target_lang, quality, style, preserve_terms):
        """Perform the actual translation."""
    

    Purpose: Perform the actual translation.

    Parameters: – self: Instance reference – text: Parameter for text – source_lang: Parameter for source_lang – target_lang: Parameter for target_lang – quality: Parameter for quality – style: Parameter for style – preserve_terms: Parameter for preserve_terms

    _generate_alternatives (Line 207)
    def _generate_alternatives(self, text, source_lang, target_lang, count):
        """Generate alternative translations."""
    

    Purpose: Generate alternative translations.

    Parameters: – self: Instance reference – text: Parameter for text – source_lang: Parameter for source_lang – target_lang: Parameter for target_lang – count: Parameter for count

    _extract_terms (Line 226)
    def _extract_terms(self, text, source_lang, target_lang):
        """Extract and translate terminology."""
    

    Purpose: Extract and translate terminology.

    Parameters: – self: Instance reference – text: Parameter for text – source_lang: Parameter for source_lang – target_lang: Parameter for target_lang

    _check_translation_memory (Line 237)
    def _check_translation_memory(self, text, source_lang, target_lang):
        """Check if translation exists in memory."""
    

    Purpose: Check if translation exists in memory.

    Parameters: – self: Instance reference – text: Parameter for text – source_lang: Parameter for source_lang – target_lang: Parameter for target_lang

    _add_to_memory (Line 260)
    def _add_to_memory(self, translation):
        """Add translation to memory."""
    

    Purpose: Add translation to memory.

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

    _calculate_confidence (Line 276)
    def _calculate_confidence(self, source, translation, quality):
        """Calculate translation confidence score."""
    

    Purpose: Calculate translation confidence score.

    Parameters: – self: Instance reference – source: Parameter for source – translation: Parameter for translation – quality: Parameter for quality

    add_terminology (Line 295)
    def add_terminology(self, term, translations):
        """Add term to terminology database."""
    

    Purpose: Add term to terminology database.

    Parameters: – self: Instance reference – term: Parameter for term – translations: Parameter for translations

    batch_translate (Line 299)
    def batch_translate(self, texts, target_lang, source_lang):
        """Translate multiple texts."""
    

    Purpose: Translate multiple texts.

    Parameters: – self: Instance reference – texts: Parameter for texts – target_lang: Parameter for target_lang – source_lang: Parameter for source_lang

    get_statistics (Line 303)
    def get_statistics(self):
        """Get translation statistics."""
    

    Purpose: Get translation statistics.

    Parameters: – self: Instance reference

    TranslationPattern (Line 314)

    Description: Translation Pattern – Manage translation agents.

    Coordinates multiple translation agents for different purposes.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    create_agent (Line 324)
    def create_agent(self, name):
        """Create a new translation agent."""
    

    Purpose: Create a new translation agent.

    Parameters: – self: Instance reference – name: Identifier or label

    run (Line 331)
    def run(self, agent_name, text, target_lang, source_lang, quality):
        """Perform translation using specified agent."""
    

    Purpose: Perform translation using specified agent.

    Parameters: – self: Instance reference – agent_name: Parameter for agent_name – text: Parameter for text – target_lang: Parameter for target_lang – source_lang: Parameter for source_lang – quality: Parameter for quality


    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 = TranslationQuality(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: Summarization Agent

    
        """
    Pattern 236: Summarization Agent
    
    Purpose: Intelligent text summarization with multiple strategies and customizable outputs.
    Implements extractive, abstractive, and hybrid summarization approaches.
    """
    
    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
    
    
    class SummarizationType(Enum):
        """Types of summarization strategies."""
        EXTRACTIVE = "extractive"  # Select key sentences
        ABSTRACTIVE = "abstractive"  # Generate new text
        HYBRID = "hybrid"  # Combination
        BULLET_POINTS = "bullet_points"  # Key points as bullets
        HEADLINE = "headline"  # Short headline/title
    
    
    class SummaryLength(Enum):
        """Target summary lengths."""
        BRIEF = "brief"  # 1-2 sentences
        SHORT = "short"  # 3-5 sentences
        MEDIUM = "medium"  # 1-2 paragraphs
        DETAILED = "detailed"  # 3+ paragraphs
    
    
    @dataclass
    class Document:
        """Document to summarize."""
        id: str
        title: str
        content: str
        metadata: Dict[str, Any] = field(default_factory=dict)
        word_count: int = 0
        
        def __post_init__(self):
            if self.word_count == 0:
                self.word_count = len(self.content.split())
    
    
    @dataclass
    class Summary:
        """Generated summary."""
        original_doc_id: str
        summary_text: str
        summary_type: SummarizationType
        length: SummaryLength
        key_points: List[str] = field(default_factory=list)
        compression_ratio: float = 0.0
        important_entities: List[str] = field(default_factory=list)
        metadata: Dict[str, Any] = field(default_factory=dict)
    
    
    class SummarizationAgent:
        """
        Summarization Agent - Intelligent text summarization.
        
        Features:
        - Multiple summarization strategies (extractive, abstractive, hybrid)
        - Customizable summary lengths
        - Key point extraction
        - Bullet point generation
        - Headline creation
        - Entity extraction
        - Compression ratio tracking
        """
        
        def __init__(self,
                     name: str,
                     summary_type: SummarizationType = SummarizationType.HYBRID,
                     default_length: SummaryLength = SummaryLength.MEDIUM):
            self.name = name
            self.summary_type = summary_type
            self.default_length = default_length
            self.llm = ChatOpenAI(model="gpt-4", temperature=0.3)
            
            # Statistics
            self.statistics: Dict[str, Any] = {
                "total_summaries": 0,
                "avg_compression_ratio": 0.0,
                "summary_type_usage": {t.value: 0 for t in SummarizationType}
            }
        
        def summarize(self,
                      document: Document,
                      summary_type: Optional[SummarizationType] = None,
                      length: Optional[SummaryLength] = None) -> Summary:
            """Generate summary for document."""
            summary_type = summary_type or self.summary_type
            length = length or self.default_length
            
            # Generate summary based on type
            if summary_type == SummarizationType.EXTRACTIVE:
                summary_text = self._extractive_summary(document, length)
            elif summary_type == SummarizationType.ABSTRACTIVE:
                summary_text = self._abstractive_summary(document, length)
            elif summary_type == SummarizationType.BULLET_POINTS:
                summary_text = self._bullet_point_summary(document, length)
            elif summary_type == SummarizationType.HEADLINE:
                summary_text = self._headline_summary(document)
            else:  # HYBRID
                summary_text = self._hybrid_summary(document, length)
            
            # Extract key points
            key_points = self._extract_key_points(document, 5)
            
            # Extract important entities
            entities = self._extract_entities(document)
            
            # Calculate compression ratio
            summary_words = len(summary_text.split())
            compression_ratio = summary_words / document.word_count if document.word_count > 0 else 0
            
            # Update statistics
            self.statistics["total_summaries"] += 1
            self.statistics["summary_type_usage"][summary_type.value] += 1
            
            # Update average compression ratio
            old_avg = self.statistics["avg_compression_ratio"]
            total = self.statistics["total_summaries"]
            self.statistics["avg_compression_ratio"] = (old_avg * (total - 1) + compression_ratio) / total
            
            return Summary(
                original_doc_id=document.id,
                summary_text=summary_text,
                summary_type=summary_type,
                length=length,
                key_points=key_points,
                compression_ratio=compression_ratio,
                important_entities=entities,
                metadata={
                    "original_word_count": document.word_count,
                    "summary_word_count": summary_words,
                    "title": document.title
                }
            )
        
        def _extractive_summary(self, document: Document, length: SummaryLength) -> str:
            """Extractive summarization - select important sentences."""
            # Split into sentences
            sentences = self._split_sentences(document.content)
            
            if not sentences:
                return document.content
            
            # Score sentences
            sentence_scores = self._score_sentences(sentences, document)
            
            # Determine number of sentences based on length
            num_sentences = self._get_sentence_count(length, len(sentences))
            
            # Select top sentences
            top_sentences = sorted(sentence_scores.items(), key=lambda x: x[1], reverse=True)[:num_sentences]
            
            # Sort by original order
            selected_indices = sorted([sentences.index(sent) for sent, _ in top_sentences])
            selected_sentences = [sentences[i] for i in selected_indices]
            
            return " ".join(selected_sentences)
        
        def _abstractive_summary(self, document: Document, length: SummaryLength) -> str:
            """Abstractive summarization - generate new text."""
            length_instructions = {
                SummaryLength.BRIEF: "in 1-2 sentences",
                SummaryLength.SHORT: "in 3-5 sentences",
                SummaryLength.MEDIUM: "in 1-2 concise paragraphs",
                SummaryLength.DETAILED: "in 3-4 detailed paragraphs"
            }
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are an expert summarization agent. Create a clear, accurate summary "
                          f"that captures the main ideas and key information. "
                          f"Summarize {length_instructions.get(length, 'concisely')}."),
                ("human", f"Title: {document.title}\n\nContent:\n{document.content}\n\n"
                         f"Provide a {length.value} summary:")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content).strip()
        
        def _bullet_point_summary(self, document: Document, length: SummaryLength) -> str:
            """Generate bullet point summary."""
            num_points = {
                SummaryLength.BRIEF: 3,
                SummaryLength.SHORT: 5,
                SummaryLength.MEDIUM: 7,
                SummaryLength.DETAILED: 10
            }
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are an expert at creating concise bullet point summaries. "
                          f"Extract the most important information as clear, actionable bullet points."),
                ("human", f"Title: {document.title}\n\nContent:\n{document.content}\n\n"
                         f"Create {num_points.get(length, 5)} key bullet points:")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content).strip()
        
        def _headline_summary(self, document: Document) -> str:
            """Generate headline-style summary."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", "You are an expert at creating compelling, accurate headlines. "
                          "Create a concise headline (5-12 words) that captures the essence of the content."),
                ("human", f"Content:\n{document.content}\n\nGenerate headline:")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content).strip()
        
        def _hybrid_summary(self, document: Document, length: SummaryLength) -> str:
            """Hybrid summarization - combine extractive and abstractive."""
            # First, get key sentences (extractive)
            extractive_summary = self._extractive_summary(document, length)
            
            # Then, refine with abstractive approach
            prompt = ChatPromptTemplate.from_messages([
                ("system", "You are refining a summary. Improve the flow and clarity while "
                          "maintaining all key information. Keep it concise and well-structured."),
                ("human", f"Original Title: {document.title}\n\n"
                         f"Key sentences extracted:\n{extractive_summary}\n\n"
                         f"Refine into a {length.value} summary:")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content).strip()
        
        def _extract_key_points(self, document: Document, max_points: int = 5) -> List[str]:
            """Extract key points from document."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"Extract the top {max_points} key points from the content. "
                          f"Each point should be a clear, concise statement (one sentence)."),
                ("human", f"Content:\n{document.content}\n\nKey points:")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            # Parse response into list
            content = str(response.content)
            points = [line.strip() for line in content.split('\n') if line.strip()]
            
            # Remove numbering if present
            points = [re.sub(r'^\d+[\.\)]\s*', '', point) for point in points]
            
            return points[:max_points]
        
        def _extract_entities(self, document: Document) -> List[str]:
            """Extract important entities (names, places, concepts)."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", "Extract the most important entities from the content: "
                          "people, places, organizations, key concepts. "
                          "Return as a comma-separated list."),
                ("human", f"Content:\n{document.content[:500]}\n\nEntities:")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            # Parse entities
            content = str(response.content)
            entities = [e.strip() for e in content.split(',') if e.strip()]
            
            return entities[:10]
        
        def _split_sentences(self, text: str) -> List[str]:
            """Split text into sentences."""
            # Simple sentence splitting (in production, use proper NLP)
            sentences = re.split(r'[.!?]+', text)
            sentences = [s.strip() for s in sentences if s.strip() and len(s.strip()) > 10]
            return sentences
        
        def _score_sentences(self, sentences: List[str], document: Document) -> Dict[str, float]:
            """Score sentences for importance."""
            scores = {}
            
            # Get word frequencies
            words = re.findall(r'\w+', document.content.lower())
            word_freq = {}
            for word in words:
                if len(word) > 3:  # Ignore short words
                    word_freq[word] = word_freq.get(word, 0) + 1
            
            # Score each sentence
            for sentence in sentences:
                score = 0.0
                sentence_words = re.findall(r'\w+', sentence.lower())
                
                # Word frequency score
                for word in sentence_words:
                    score += word_freq.get(word, 0)
                
                # Position bonus (earlier sentences often more important)
                position = sentences.index(sentence)
                position_bonus = 1.0 / (position + 1)
                score += position_bonus * 10
                
                # Length penalty (very short or very long sentences)
                word_count = len(sentence_words)
                if 10 <= word_count  int:
            """Determine number of sentences based on target length."""
            ratios = {
                SummaryLength.BRIEF: 0.1,
                SummaryLength.SHORT: 0.2,
                SummaryLength.MEDIUM: 0.35,
                SummaryLength.DETAILED: 0.5
            }
            
            count = int(total_sentences * ratios.get(length, 0.2))
            return max(1, min(count, total_sentences))
        
        def batch_summarize(self, documents: List[Document]) -> List[Summary]:
            """Summarize multiple documents."""
            return [self.summarize(doc) for doc in documents]
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get summarization statistics."""
            return {
                "name": self.name,
                "default_strategy": self.summary_type.value,
                "default_length": self.default_length.value,
                **self.statistics
            }
    
    
    class SummarizationPattern:
        """
        Summarization Pattern - Manage summarization agents.
        
        Coordinates multiple summarization agents for different needs.
        """
        
        def __init__(self):
            self.agents: Dict[str, SummarizationAgent] = {}
        
        def create_agent(self,
                         name: str,
                         summary_type: SummarizationType = SummarizationType.HYBRID,
                         default_length: SummaryLength = SummaryLength.MEDIUM) -> SummarizationAgent:
            """Create a new summarization agent."""
            agent = SummarizationAgent(name, summary_type, default_length)
            self.agents[name] = agent
            print(f"   Created summarization agent: {name} ({summary_type.value}, {default_length.value})")
            return agent
        
        def run(self,
                agent_name: str,
                document: Document,
                summary_type: Optional[SummarizationType] = None) -> Dict[str, Any]:
            """Generate summary using specified agent."""
            if agent_name not in self.agents:
                return {"error": f"Agent {agent_name} not found"}
            
            agent = self.agents[agent_name]
            summary = agent.summarize(document, summary_type=summary_type)
            
            print(f"\n=== Summary by {agent_name} ===")
            print(f"Document: {document.title}")
            print(f"Original: {document.word_count} words")
            print(f"Summary Type: {summary.summary_type.value}")
            print(f"Compression: {summary.compression_ratio:.1%}\n")
            print(f"Summary:\n{summary.summary_text}\n")
            
            if summary.key_points:
                print("Key Points:")
                for i, point in enumerate(summary.key_points, 1):
                    print(f"  {i}. {point}")
            
            if summary.important_entities:
                print(f"\nImportant Entities: {', '.join(summary.important_entities[:5])}")
            
            return {
                "agent": agent_name,
                "document_id": document.id,
                "summary_length": len(summary.summary_text.split()),
                "compression_ratio": summary.compression_ratio,
                "statistics": agent.get_statistics()
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Summarization Agent Pattern Demo ===\n")
        
        # Create pattern
        pattern = SummarizationPattern()
        
        # Create agents
        print("1. Setting up summarization agents...")
        
        news_agent = pattern.create_agent("NewsDigest", SummarizationType.ABSTRACTIVE, SummaryLength.SHORT)
        research_agent = pattern.create_agent("ResearchSummarizer", SummarizationType.HYBRID, SummaryLength.MEDIUM)
        quick_agent = pattern.create_agent("QuickScan", SummarizationType.BULLET_POINTS, SummaryLength.BRIEF)
        
        # Create sample documents
        print("\n2. Creating sample documents...")
        
        doc1 = Document(
            id="doc1",
            title="Advances in Artificial Intelligence",
            content="""
            Artificial intelligence has made remarkable progress in recent years, transforming industries 
            and daily life. Machine learning algorithms now power everything from recommendation systems 
            to autonomous vehicles. Deep learning, a subset of machine learning, has achieved breakthrough 
            results in image recognition, natural language processing, and game playing. Neural networks 
            with millions of parameters can now understand context, generate human-like text, and even 
            create original artwork. However, challenges remain in areas such as explainability, bias, 
            and ethical considerations. Researchers are working on making AI systems more transparent 
            and fair. The future of AI promises even more sophisticated applications, including advanced 
            medical diagnosis, climate modeling, and personalized education. As AI continues to evolve, 
            collaboration between technologists, ethicists, and policymakers becomes increasingly important 
            to ensure responsible development and deployment.
            """
        )
        
        doc2 = Document(
            id="doc2",
            title="Climate Change and Renewable Energy",
            content="""
            Climate change poses one of the greatest challenges of our time. Rising global temperatures 
            are causing more frequent extreme weather events, sea level rise, and ecosystem disruption. 
            The transition to renewable energy sources is critical for reducing greenhouse gas emissions. 
            Solar and wind power have become increasingly cost-competitive with fossil fuels. Many countries 
            are setting ambitious targets for carbon neutrality by 2050. Battery technology improvements 
            are making energy storage more viable. Electric vehicles are gaining market share rapidly. 
            However, the transition requires significant infrastructure investment and policy support. 
            Individual actions also matter, from reducing consumption to supporting sustainable businesses.
            """
        )
        
        # Generate summaries
        print("\n3. Generating summaries...")
        
        # Abstractive summary
        result1 = pattern.run("NewsDigest", doc1)
        
        print("\n" + "="*60 + "\n")
        
        # Hybrid summary
        result2 = pattern.run("ResearchSummarizer", doc2)
        
        print("\n" + "="*60 + "\n")
        
        # Bullet point summary
        result3 = pattern.run("QuickScan", doc1, summary_type=SummarizationType.BULLET_POINTS)
        
        # Print statistics
        print("\n" + "="*60)
        print("\n4. Summarization Statistics:")
        stats = result3["statistics"]
        for key, value in stats.items():
            print(f"   {key}: {value}")
        
        print("\n✓ Intelligent summarization with multiple strategies complete!")
    
    
        

    Agentic Architecture Pattern: Summarization Agent

    Pattern 236: 236 Summarization Agent – Line-by-Line Explanation

    Overview

    Pattern 236: Summarization Agent

    Purpose: Intelligent text summarization with multiple strategies and customizable outputs. Implements extractive, abstractive, and hybrid summarization approaches.


    Code Structure Analysis

    File Information

    • Pattern Number: 236
    • Pattern Name: 236 Summarization Agent
    • File Path: patterns\domain_specific\236_summarization_agent.py
    • Total Lines: 478

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 236: Summarization Agent
    
    Purpose: Intelligent text summarization with multiple strategies and customizable outputs.
    Implements extractive, abstractive, and hybrid summarization approaches.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 236 Summarization Agent 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

    SummarizationType (Line 17)

    class SummarizationType(Enum):
        EXTRACTIVE
        ABSTRACTIVE
        HYBRID
        BULLET_POINTS
        HEADLINE
    

    Purpose: Types of summarization strategies.

    Values: – EXTRACTIVE: Represents extractive – ABSTRACTIVE: Represents abstractive – HYBRID: Represents hybrid – BULLET_POINTS: Represents bullet points – HEADLINE: Represents headline

    SummaryLength (Line 26)

    class SummaryLength(Enum):
        BRIEF
        SHORT
        MEDIUM
        DETAILED
    

    Purpose: Target summary lengths.

    Values: – BRIEF: Represents brief – SHORT: Represents short – MEDIUM: Represents medium – DETAILED: Represents detailed


    Classes

    SummarizationType (Line 17)

    Description: Types of summarization strategies.

    SummaryLength (Line 26)

    Description: Target summary lengths.

    Document (Line 35)

    Description: Document to summarize.

    Methods:

    __post_init__ (Line 43)
    def __post_init__(self):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    Summary (Line 49)

    Description: Generated summary.

    SummarizationAgent (Line 61)

    Description: Summarization Agent – Intelligent text summarization.

    Features: – Multiple summarization strategies (extractive, abstractive, hybrid) – Customizable summary lengths – Key point extraction – Bullet point generation – Headline creation – Entity extraction – Compression ratio tracking

    Methods:

    __init__ (Line 75)
    def __init__(self, name, summary_type, default_length):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – name: Identifier or label – summary_type: Parameter for summary_type – default_length: Parameter for default_length

    summarize (Line 91)
    def summarize(self, document, summary_type, length):
        """Generate summary for document."""
    

    Purpose: Generate summary for document.

    Parameters: – self: Instance reference – document: Parameter for document – summary_type: Parameter for summary_type – length: Parameter for length

    _extractive_summary (Line 145)
    def _extractive_summary(self, document, length):
        """Extractive summarization - select important sentences."""
    

    Purpose: Extractive summarization – select important sentences.

    Parameters: – self: Instance reference – document: Parameter for document – length: Parameter for length

    _abstractive_summary (Line 168)
    def _abstractive_summary(self, document, length):
        """Abstractive summarization - generate new text."""
    

    Purpose: Abstractive summarization – generate new text.

    Parameters: – self: Instance reference – document: Parameter for document – length: Parameter for length

    _bullet_point_summary (Line 190)
    def _bullet_point_summary(self, document, length):
        """Generate bullet point summary."""
    

    Purpose: Generate bullet point summary.

    Parameters: – self: Instance reference – document: Parameter for document – length: Parameter for length

    _headline_summary (Line 211)
    def _headline_summary(self, document):
        """Generate headline-style summary."""
    

    Purpose: Generate headline-style summary.

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

    _hybrid_summary (Line 224)
    def _hybrid_summary(self, document, length):
        """Hybrid summarization - combine extractive and abstractive."""
    

    Purpose: Hybrid summarization – combine extractive and abstractive.

    Parameters: – self: Instance reference – document: Parameter for document – length: Parameter for length

    _extract_key_points (Line 243)
    def _extract_key_points(self, document, max_points):
        """Extract key points from document."""
    

    Purpose: Extract key points from document.

    Parameters: – self: Instance reference – document: Parameter for document – max_points: Parameter for max_points

    _extract_entities (Line 263)
    def _extract_entities(self, document):
        """Extract important entities (names, places, concepts)."""
    

    Purpose: Extract important entities (names, places, concepts).

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

    _split_sentences (Line 281)
    def _split_sentences(self, text):
        """Split text into sentences."""
    

    Purpose: Split text into sentences.

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

    _score_sentences (Line 288)
    def _score_sentences(self, sentences, document):
        """Score sentences for importance."""
    

    Purpose: Score sentences for importance.

    Parameters: – self: Instance reference – sentences: Parameter for sentences – document: Parameter for document

    _get_sentence_count (Line 322)
    def _get_sentence_count(self, length, total_sentences):
        """Determine number of sentences based on target length."""
    

    Purpose: Determine number of sentences based on target length.

    Parameters: – self: Instance reference – length: Parameter for length – total_sentences: Parameter for total_sentences

    batch_summarize (Line 334)
    def batch_summarize(self, documents):
        """Summarize multiple documents."""
    

    Purpose: Summarize multiple documents.

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

    get_statistics (Line 338)
    def get_statistics(self):
        """Get summarization statistics."""
    

    Purpose: Get summarization statistics.

    Parameters: – self: Instance reference

    SummarizationPattern (Line 348)

    Description: Summarization Pattern – Manage summarization agents.

    Coordinates multiple summarization agents for different needs.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    create_agent (Line 358)
    def create_agent(self, name, summary_type, default_length):
        """Create a new summarization agent."""
    

    Purpose: Create a new summarization agent.

    Parameters: – self: Instance reference – name: Identifier or label – summary_type: Parameter for summary_type – default_length: Parameter for default_length

    run (Line 368)
    def run(self, agent_name, document, summary_type):
        """Generate summary using specified agent."""
    

    Purpose: Generate summary using specified agent.

    Parameters: – self: Instance reference – agent_name: Parameter for agent_name – document: Parameter for document – summary_type: Parameter for summary_type


    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 = SummarizationType(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: Search Agent

    
        """
    Pattern 235: Search Agent
    
    Purpose: Intelligent search agent with query processing, ranking, and retrieval strategies.
    Implements semantic search, keyword search, and hybrid approaches with relevance scoring.
    """
    
    from typing import Dict, Any, List, Optional, Set
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from collections import defaultdict
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    import re
    
    
    class SearchType(Enum):
        """Types of search strategies."""
        KEYWORD = "keyword"  # Keyword matching
        SEMANTIC = "semantic"  # Semantic/meaning-based
        FUZZY = "fuzzy"  # Fuzzy matching
        BOOLEAN = "boolean"  # Boolean operators (AND, OR, NOT)
        HYBRID = "hybrid"  # Combination of strategies
    
    
    class SearchScope(Enum):
        """Scope of search."""
        TITLE = "title"
        CONTENT = "content"
        TAGS = "tags"
        METADATA = "metadata"
        ALL = "all"
    
    
    @dataclass
    class Document:
        """Document to be searched."""
        id: str
        title: str
        content: str
        tags: List[str] = field(default_factory=list)
        metadata: Dict[str, Any] = field(default_factory=dict)
        created_at: datetime = field(default_factory=datetime.now)
        views: int = 0
        popularity: float = 0.0
    
    
    @dataclass
    class SearchQuery:
        """Processed search query."""
        original_query: str
        processed_terms: List[str]
        operators: Dict[str, List[str]] = field(default_factory=dict)  # AND, OR, NOT
        filters: Dict[str, Any] = field(default_factory=dict)
        scope: SearchScope = SearchScope.ALL
    
    
    @dataclass
    class SearchResult:
        """A single search result."""
        document: Document
        relevance_score: float
        matched_fields: List[str]
        highlights: List[str] = field(default_factory=list)
        rank: int = 0
    
    
    class SearchAgent:
        """
        Search Agent - Intelligent search with multiple strategies.
        
        Features:
        - Query processing and understanding
        - Multiple search strategies (keyword, semantic, fuzzy, boolean)
        - Relevance scoring and ranking
        - Result highlighting
        - Search filters
        - Query expansion
        - Search analytics
        """
        
        def __init__(self,
                     name: str,
                     search_type: SearchType = SearchType.HYBRID):
            self.name = name
            self.search_type = search_type
            self.llm = ChatOpenAI(model="gpt-4", temperature=0.3)
            
            # Document store
            self.documents: Dict[str, Document] = {}
            self.inverted_index: Dict[str, Set[str]] = defaultdict(set)  # term -> doc_ids
            
            # Statistics
            self.statistics: Dict[str, Any] = {
                "total_searches": 0,
                "documents_indexed": 0,
                "avg_results_per_query": 0.0,
                "search_type_usage": defaultdict(int)
            }
        
        def add_document(self, document: Document):
            """Add document to search index."""
            self.documents[document.id] = document
            self._index_document(document)
            self.statistics["documents_indexed"] += 1
        
        def _index_document(self, document: Document):
            """Build inverted index for document."""
            # Index title
            for term in self._tokenize(document.title):
                self.inverted_index[term].add(document.id)
            
            # Index content
            for term in self._tokenize(document.content):
                self.inverted_index[term].add(document.id)
            
            # Index tags
            for tag in document.tags:
                self.inverted_index[tag.lower()].add(document.id)
        
        def search(self,
                   query: str,
                   max_results: int = 10,
                   scope: SearchScope = SearchScope.ALL,
                   filters: Optional[Dict[str, Any]] = None) -> List[SearchResult]:
            """Execute search query."""
            self.statistics["total_searches"] += 1
            self.statistics["search_type_usage"][self.search_type.value] += 1
            
            # Process query
            processed_query = self._process_query(query, scope, filters)
            
            # Execute search strategy
            if self.search_type == SearchType.KEYWORD:
                results = self._keyword_search(processed_query)
            elif self.search_type == SearchType.SEMANTIC:
                results = self._semantic_search(processed_query)
            elif self.search_type == SearchType.FUZZY:
                results = self._fuzzy_search(processed_query)
            elif self.search_type == SearchType.BOOLEAN:
                results = self._boolean_search(processed_query)
            else:  # HYBRID
                results = self._hybrid_search(processed_query)
            
            # Apply filters
            if filters:
                results = self._apply_filters(results, filters)
            
            # Rank results
            results = self._rank_results(results, processed_query)
            
            # Limit results
            results = results[:max_results]
            
            # Add highlights
            for result in results:
                result.highlights = self._generate_highlights(result.document, processed_query)
            
            # Update statistics
            if results:
                avg = self.statistics["avg_results_per_query"]
                total = self.statistics["total_searches"]
                self.statistics["avg_results_per_query"] = (avg * (total - 1) + len(results)) / total
            
            return results
        
        def _process_query(self,
                          query: str,
                          scope: SearchScope,
                          filters: Optional[Dict[str, Any]]) -> SearchQuery:
            """Process and understand query."""
            # Extract boolean operators
            operators = {
                "AND": [],
                "OR": [],
                "NOT": []
            }
            
            # Simple boolean parsing
            if " AND " in query.upper():
                operators["AND"] = re.split(r'\s+AND\s+', query, flags=re.IGNORECASE)
                query = " ".join(operators["AND"])
            elif " OR " in query.upper():
                operators["OR"] = re.split(r'\s+OR\s+', query, flags=re.IGNORECASE)
            elif " NOT " in query.upper():
                parts = re.split(r'\s+NOT\s+', query, flags=re.IGNORECASE)
                query = parts[0]
                operators["NOT"] = parts[1:] if len(parts) > 1 else []
            
            # Tokenize
            processed_terms = self._tokenize(query)
            
            return SearchQuery(
                original_query=query,
                processed_terms=processed_terms,
                operators=operators,
                filters=filters or {},
                scope=scope
            )
        
        def _tokenize(self, text: str) -> List[str]:
            """Tokenize text into terms."""
            # Simple tokenization (in production, use proper NLP)
            text = text.lower()
            text = re.sub(r'[^\w\s]', ' ', text)
            return [term for term in text.split() if len(term) > 2]
        
        def _keyword_search(self, query: SearchQuery) -> List[SearchResult]:
            """Keyword-based search."""
            doc_scores: Dict[str, float] = defaultdict(float)
            doc_matches: Dict[str, Set[str]] = defaultdict(set)
            
            # Find matching documents
            for term in query.processed_terms:
                if term in self.inverted_index:
                    for doc_id in self.inverted_index[term]:
                        doc_scores[doc_id] += 1.0
                        doc_matches[doc_id].add(term)
            
            # Create results
            results = []
            for doc_id, score in doc_scores.items():
                document = self.documents[doc_id]
                
                # TF-IDF-like scoring
                term_frequency = score / len(query.processed_terms)
                doc_frequency = len(doc_matches[doc_id]) / len(self.inverted_index.get(list(doc_matches[doc_id])[0], {doc_id}))
                relevance_score = term_frequency * doc_frequency
                
                results.append(SearchResult(
                    document=document,
                    relevance_score=relevance_score,
                    matched_fields=list(doc_matches[doc_id])
                ))
            
            return results
        
        def _semantic_search(self, query: SearchQuery) -> List[SearchResult]:
            """Semantic/meaning-based search using LLM."""
            # Use LLM to understand query intent and find relevant documents
            doc_summaries = "\n".join([
                f"{doc_id}: {doc.title} - {doc.content[:100]}"
                for doc_id, doc in list(self.documents.items())[:50]
            ])
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", "You are a search expert. Analyze the query and rank documents by relevance. "
                          "Return document IDs in order of relevance, separated by commas."),
                ("human", f"Query: {query.original_query}\n\nDocuments:\n{doc_summaries}\n\n"
                         f"Return top relevant document IDs:")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            # Parse LLM response
            relevant_doc_ids = [doc_id.strip() for doc_id in str(response.content).split(",")[:20]]
            
            # Create results with semantic scores
            results = []
            for i, doc_id in enumerate(relevant_doc_ids):
                if doc_id in self.documents:
                    results.append(SearchResult(
                        document=self.documents[doc_id],
                        relevance_score=1.0 - (i * 0.05),  # Decreasing score
                        matched_fields=["semantic"]
                    ))
            
            return results
        
        def _fuzzy_search(self, query: SearchQuery) -> List[SearchResult]:
            """Fuzzy matching search."""
            results = []
            
            for doc_id, document in self.documents.items():
                # Calculate fuzzy match score
                score = 0.0
                matched_fields = []
                
                for term in query.processed_terms:
                    # Title fuzzy match
                    if self._fuzzy_match(term, document.title):
                        score += 2.0
                        matched_fields.append("title")
                    
                    # Content fuzzy match
                    if self._fuzzy_match(term, document.content):
                        score += 1.0
                        matched_fields.append("content")
                    
                    # Tag match
                    for tag in document.tags:
                        if self._fuzzy_match(term, tag):
                            score += 1.5
                            matched_fields.append("tags")
                
                if score > 0:
                    results.append(SearchResult(
                        document=document,
                        relevance_score=score / len(query.processed_terms),
                        matched_fields=list(set(matched_fields))
                    ))
            
            return results
        
        def _fuzzy_match(self, term: str, text: str) -> bool:
            """Simple fuzzy matching."""
            term = term.lower()
            text = text.lower()
            
            # Exact match
            if term in text:
                return True
            
            # Partial match (at least 70% characters)
            match_threshold = int(len(term) * 0.7)
            matched_chars = sum(1 for c in term if c in text)
            return matched_chars >= match_threshold
        
        def _boolean_search(self, query: SearchQuery) -> List[SearchResult]:
            """Boolean operator search (AND, OR, NOT)."""
            if query.operators["AND"]:
                # All terms must match
                doc_ids: Optional[Set[str]] = None
                for term in query.operators["AND"]:
                    term_docs = set()
                    for t in self._tokenize(term):
                        term_docs.update(self.inverted_index.get(t, set()))
                    
                    doc_ids = term_docs if doc_ids is None else doc_ids & term_docs
                
                doc_ids = doc_ids or set()
                
            elif query.operators["OR"]:
                # Any term can match
                doc_ids = set()
                for term in query.operators["OR"]:
                    for t in self._tokenize(term):
                        doc_ids.update(self.inverted_index.get(t, set()))
            
            else:
                # Default keyword search
                return self._keyword_search(query)
            
            # Exclude NOT terms
            if query.operators["NOT"]:
                exclude_ids = set()
                for term in query.operators["NOT"]:
                    for t in self._tokenize(term):
                        exclude_ids.update(self.inverted_index.get(t, set()))
                doc_ids -= exclude_ids
            
            # Create results
            results = []
            for doc_id in doc_ids:
                if doc_id in self.documents:
                    results.append(SearchResult(
                        document=self.documents[doc_id],
                        relevance_score=1.0,
                        matched_fields=["boolean"]
                    ))
            
            return results
        
        def _hybrid_search(self, query: SearchQuery) -> List[SearchResult]:
            """Hybrid search combining multiple strategies."""
            # Combine keyword and semantic search
            keyword_results = self._keyword_search(query)
            fuzzy_results = self._fuzzy_search(query)
            
            # Merge results with weighted scores
            combined: Dict[str, SearchResult] = {}
            
            # Weight: keyword 60%, fuzzy 40%
            for result in keyword_results:
                combined[result.document.id] = SearchResult(
                    document=result.document,
                    relevance_score=result.relevance_score * 0.6,
                    matched_fields=result.matched_fields
                )
            
            for result in fuzzy_results:
                if result.document.id in combined:
                    combined[result.document.id].relevance_score += result.relevance_score * 0.4
                    combined[result.document.id].matched_fields.extend(result.matched_fields)
                else:
                    combined[result.document.id] = SearchResult(
                        document=result.document,
                        relevance_score=result.relevance_score * 0.4,
                        matched_fields=result.matched_fields
                    )
            
            return list(combined.values())
        
        def _apply_filters(self,
                           results: List[SearchResult],
                           filters: Dict[str, Any]) -> List[SearchResult]:
            """Apply filters to search results."""
            filtered = []
            
            for result in results:
                doc = result.document
                include = True
                
                # Apply each filter
                if "tags" in filters:
                    if not any(tag in doc.tags for tag in filters["tags"]):
                        include = False
                
                if "min_views" in filters:
                    if doc.views < filters["min_views"]:
                        include = False
                
                if "created_after" in filters:
                    if doc.created_at  List[SearchResult]:
            """Rank search results."""
            # Sort by relevance score (descending)
            sorted_results = sorted(results, key=lambda r: r.relevance_score, reverse=True)
            
            # Assign ranks
            for i, result in enumerate(sorted_results, 1):
                result.rank = i
            
            return sorted_results
        
        def _generate_highlights(self,
                               document: Document,
                               query: SearchQuery) -> List[str]:
            """Generate highlighted snippets."""
            highlights = []
            content_lower = document.content.lower()
            
            for term in query.processed_terms[:3]:  # Top 3 terms
                # Find term in content
                idx = content_lower.find(term.lower())
                if idx != -1:
                    # Extract context (50 chars before and after)
                    start = max(0, idx - 50)
                    end = min(len(document.content), idx + len(term) + 50)
                    snippet = document.content[start:end]
                    
                    # Add ellipsis
                    if start > 0:
                        snippet = "..." + snippet
                    if end  Dict[str, Any]:
            """Get search statistics."""
            return {
                "name": self.name,
                "search_strategy": self.search_type.value,
                **self.statistics
            }
    
    
    class SearchPattern:
        """
        Search Pattern - Manage search agents for different domains.
        
        Coordinates multiple search agents with different strategies.
        """
        
        def __init__(self):
            self.agents: Dict[str, SearchAgent] = {}
        
        def create_agent(self,
                         name: str,
                         search_type: SearchType = SearchType.HYBRID) -> SearchAgent:
            """Create a new search agent."""
            agent = SearchAgent(name, search_type)
            self.agents[name] = agent
            print(f"   Created search agent: {name} ({search_type.value})")
            return agent
        
        def run(self,
                agent_name: str,
                query: str,
                max_results: int = 5) -> Dict[str, Any]:
            """Execute search query."""
            if agent_name not in self.agents:
                return {"error": f"Agent {agent_name} not found"}
            
            agent = self.agents[agent_name]
            results = agent.search(query, max_results)
            
            print(f"\n=== Search Results from {agent_name} ===")
            print(f"Query: \"{query}\"")
            print(f"Found {len(results)} results\n")
            
            for result in results:
                print(f"#{result.rank}. {result.document.title} (Score: {result.relevance_score:.2f})")
                print(f"   Tags: {', '.join(result.document.tags)}")
                if result.highlights:
                    print(f"   Preview: {result.highlights[0]}")
                print()
            
            return {
                "agent": agent_name,
                "query": query,
                "results_count": len(results),
                "statistics": agent.get_statistics()
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Search Agent Pattern Demo ===\n")
        
        # Create pattern
        pattern = SearchPattern()
        
        # Create search agents
        print("1. Setting up search agents...")
        
        web_search = pattern.create_agent("WebSearch", SearchType.HYBRID)
        doc_search = pattern.create_agent("DocSearch", SearchType.KEYWORD)
        
        # Add sample documents
        print("\n2. Indexing documents...")
        
        documents = [
            Document("d1", "Introduction to Machine Learning",
                    "Machine learning is a subset of artificial intelligence that focuses on data and algorithms.",
                    ["AI", "ML", "tutorial"]),
            Document("d2", "Deep Learning Fundamentals",
                    "Deep learning uses neural networks with multiple layers to learn from data.",
                    ["AI", "deep-learning", "neural-networks"]),
            Document("d3", "Natural Language Processing Guide",
                    "NLP enables computers to understand, interpret and generate human language.",
                    ["NLP", "AI", "language"]),
            Document("d4", "Computer Vision Applications",
                    "Computer vision allows machines to interpret and understand visual information.",
                    ["CV", "AI", "image-processing"]),
            Document("d5", "Reinforcement Learning Basics",
                    "Reinforcement learning trains agents through trial and error using rewards.",
                    ["RL", "AI", "agents"]),
            Document("d6", "Data Science with Python",
                    "Python is the leading language for data science and machine learning.",
                    ["python", "data-science", "tutorial"]),
        ]
        
        for doc in documents:
            web_search.add_document(doc)
        
        # Execute searches
        print("\n3. Executing searches...")
        
        queries = [
            "machine learning neural networks",
            "python data science",
            "artificial intelligence applications"
        ]
        
        for query in queries:
            result = pattern.run("WebSearch", query, max_results=3)
        
        # Print statistics
        print("\n4. Search Statistics:")
        stats = result["statistics"]
        for key, value in stats.items():
            print(f"   {key}: {value}")
        
        print("\n✓ Intelligent search with ranking and relevance scoring complete!")
    
    
        

    Agentic Architecture Pattern: Search Agent

    Pattern 235: 235 Search Agent – Line-by-Line Explanation

    Overview

    Pattern 235: Search Agent

    Purpose: Intelligent search agent with query processing, ranking, and retrieval strategies. Implements semantic search, keyword search, and hybrid approaches with relevance scoring.


    Code Structure Analysis

    File Information

    • Pattern Number: 235
    • Pattern Name: 235 Search Agent
    • File Path: patterns\domain_specific\235_search_agent.py
    • Total Lines: 581

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 235: Search Agent
    
    Purpose: Intelligent search agent with query processing, ranking, and retrieval strategies.
    Implements semantic search, keyword search, and hybrid approaches with relevance scoring.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 235 Search Agent 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 collections import defaultdict
    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, 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


    Enumerations

    SearchType (Line 18)

    class SearchType(Enum):
        KEYWORD
        SEMANTIC
        FUZZY
        BOOLEAN
        HYBRID
    

    Purpose: Types of search strategies.

    Values: – KEYWORD: Represents keyword – SEMANTIC: Represents semantic – FUZZY: Represents fuzzy – BOOLEAN: Represents boolean – HYBRID: Represents hybrid

    SearchScope (Line 27)

    class SearchScope(Enum):
        TITLE
        CONTENT
        TAGS
        METADATA
        ALL
    

    Purpose: Scope of search.

    Values: – TITLE: Represents title – CONTENT: Represents content – TAGS: Represents tags – METADATA: Represents metadata – ALL: Represents all


    Classes

    SearchType (Line 18)

    Description: Types of search strategies.

    SearchScope (Line 27)

    Description: Scope of search.

    Document (Line 37)

    Description: Document to be searched.

    SearchQuery (Line 50)

    Description: Processed search query.

    SearchResult (Line 60)

    Description: A single search result.

    SearchAgent (Line 69)

    Description: Search Agent – Intelligent search with multiple strategies.

    Features: – Query processing and understanding – Multiple search strategies (keyword, semantic, fuzzy, boolean) – Relevance scoring and ranking – Result highlighting – Search filters – Query expansion – Search analytics

    Methods:

    __init__ (Line 83)
    def __init__(self, name, search_type):
        """No method docstring."""
    

    Purpose: No method docstring.

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

    add_document (Line 102)
    def add_document(self, document):
        """Add document to search index."""
    

    Purpose: Add document to search index.

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

    _index_document (Line 108)
    def _index_document(self, document):
        """Build inverted index for document."""
    

    Purpose: Build inverted index for document.

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

    search (Line 122)
    def search(self, query, max_results, scope, filters):
        """Execute search query."""
    

    Purpose: Execute search query.

    Parameters: – self: Instance reference – query: Parameter for query – max_results: Parameter for max_results – scope: Parameter for scope – filters: Parameter for filters

    _process_query (Line 168)
    def _process_query(self, query, scope, filters):
        """Process and understand query."""
    

    Purpose: Process and understand query.

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

    _tokenize (Line 202)
    def _tokenize(self, text):
        """Tokenize text into terms."""
    

    Purpose: Tokenize text into terms.

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

    _keyword_search (Line 209)
    def _keyword_search(self, query):
        """Keyword-based search."""
    

    Purpose: Keyword-based search.

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

    _semantic_search (Line 239)
    def _semantic_search(self, query):
        """Semantic/meaning-based search using LLM."""
    

    Purpose: Semantic/meaning-based search using LLM.

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

    _fuzzy_search (Line 272)
    def _fuzzy_search(self, query):
        """Fuzzy matching search."""
    

    Purpose: Fuzzy matching search.

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

    _fuzzy_match (Line 307)
    def _fuzzy_match(self, term, text):
        """Simple fuzzy matching."""
    

    Purpose: Simple fuzzy matching.

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

    _boolean_search (Line 321)
    def _boolean_search(self, query):
        """Boolean operator search (AND, OR, NOT)."""
    

    Purpose: Boolean operator search (AND, OR, NOT).

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

    _hybrid_search (Line 366)
    def _hybrid_search(self, query):
        """Hybrid search combining multiple strategies."""
    

    Purpose: Hybrid search combining multiple strategies.

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

    _apply_filters (Line 396)
    def _apply_filters(self, results, filters):
        """Apply filters to search results."""
    

    Purpose: Apply filters to search results.

    Parameters: – self: Instance reference – results: Parameter for results – filters: Parameter for filters

    _rank_results (Line 424)
    def _rank_results(self, results, query):
        """Rank search results."""
    

    Purpose: Rank search results.

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

    _generate_highlights (Line 437)
    def _generate_highlights(self, document, query):
        """Generate highlighted snippets."""
    

    Purpose: Generate highlighted snippets.

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

    …and 1 more methods

    SearchPattern (Line 472)

    Description: Search Pattern – Manage search agents for different domains.

    Coordinates multiple search agents with different strategies.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    create_agent (Line 482)
    def create_agent(self, name, search_type):
        """Create a new search agent."""
    

    Purpose: Create a new search agent.

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

    run (Line 491)
    def run(self, agent_name, query, max_results):
        """Execute search query."""
    

    Purpose: Execute search query.

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


    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 = SearchType(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: Recommendation Agent

    
        """
    Pattern 234: Recommendation Agent
    
    Purpose: Personalized recommendation system that learns user preferences and suggests relevant items.
    Implements collaborative filtering, content-based filtering, and hybrid approaches.
    """
    
    from typing import Dict, Any, List, Optional, Set
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from collections import defaultdict
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    import math
    
    
    class RecommendationType(Enum):
        """Types of recommendation strategies."""
        COLLABORATIVE = "collaborative"  # Based on similar users
        CONTENT_BASED = "content_based"  # Based on item features
        HYBRID = "hybrid"  # Combination of both
        POPULAR = "popular"  # Based on popularity
        PERSONALIZED = "personalized"  # LLM-based personalization
    
    
    class ItemCategory(Enum):
        """Categories of items."""
        MOVIE = "movie"
        BOOK = "book"
        PRODUCT = "product"
        RESTAURANT = "restaurant"
        MUSIC = "music"
        ARTICLE = "article"
        COURSE = "course"
    
    
    @dataclass
    class Item:
        """Item to recommend."""
        id: str
        title: str
        category: ItemCategory
        tags: List[str] = field(default_factory=list)
        features: Dict[str, Any] = field(default_factory=dict)
        popularity_score: float = 0.0
        average_rating: float = 0.0
        description: str = ""
    
    
    @dataclass
    class UserProfile:
        """User profile with preferences."""
        user_id: str
        rated_items: Dict[str, float] = field(default_factory=dict)  # item_id -> rating
        viewed_items: Set[str] = field(default_factory=set)
        purchased_items: Set[str] = field(default_factory=set)
        preferred_tags: List[str] = field(default_factory=list)
        preferred_categories: List[ItemCategory] = field(default_factory=list)
        interaction_history: List[Dict[str, Any]] = field(default_factory=list)
    
    
    @dataclass
    class Recommendation:
        """A single recommendation."""
        item: Item
        score: float
        reason: str
        recommendation_type: RecommendationType
    
    
    class RecommendationAgent:
        """
        Recommendation Agent - Personalized recommendations using multiple strategies.
        
        Features:
        - Collaborative filtering (user-based similarity)
        - Content-based filtering (item features)
        - Hybrid recommendations
        - Popularity-based recommendations
        - LLM-enhanced personalization
        - User profile learning
        """
        
        def __init__(self,
                     name: str,
                     recommendation_type: RecommendationType = RecommendationType.HYBRID):
            self.name = name
            self.recommendation_type = recommendation_type
            self.llm = ChatOpenAI(model="gpt-4", temperature=0.7)
            
            # Data stores
            self.items: Dict[str, Item] = {}
            self.user_profiles: Dict[str, UserProfile] = {}
            
            # Statistics
            self.statistics: Dict[str, Any] = {
                "recommendations_made": 0,
                "users_served": 0,
                "items_added": 0,
                "strategy_usage": defaultdict(int)
            }
        
        def add_item(self, item: Item):
            """Add item to recommendation system."""
            self.items[item.id] = item
            self.statistics["items_added"] += 1
        
        def add_user(self, user_id: str) -> UserProfile:
            """Add or get user profile."""
            if user_id not in self.user_profiles:
                self.user_profiles[user_id] = UserProfile(user_id=user_id)
            return self.user_profiles[user_id]
        
        def record_rating(self, user_id: str, item_id: str, rating: float):
            """Record user rating for an item."""
            profile = self.add_user(user_id)
            profile.rated_items[item_id] = rating
            profile.interaction_history.append({
                "action": "rating",
                "item_id": item_id,
                "value": rating,
                "timestamp": datetime.now()
            })
            
            # Update item average rating
            if item_id in self.items:
                item = self.items[item_id]
                ratings = [p.rated_items.get(item_id, 0) for p in self.user_profiles.values() 
                          if item_id in p.rated_items]
                if ratings:
                    item.average_rating = sum(ratings) / len(ratings)
        
        def record_view(self, user_id: str, item_id: str):
            """Record user viewing an item."""
            profile = self.add_user(user_id)
            profile.viewed_items.add(item_id)
            profile.interaction_history.append({
                "action": "view",
                "item_id": item_id,
                "timestamp": datetime.now()
            })
        
        def recommend(self,
                      user_id: str,
                      count: int = 5,
                      exclude_seen: bool = True) -> List[Recommendation]:
            """Generate recommendations for user."""
            profile = self.add_user(user_id)
            self.statistics["users_served"] = len(self.user_profiles)
            
            # Choose recommendation strategy
            if self.recommendation_type == RecommendationType.COLLABORATIVE:
                recommendations = self._collaborative_filtering(profile, count, exclude_seen)
            elif self.recommendation_type == RecommendationType.CONTENT_BASED:
                recommendations = self._content_based_filtering(profile, count, exclude_seen)
            elif self.recommendation_type == RecommendationType.POPULAR:
                recommendations = self._popular_recommendations(profile, count, exclude_seen)
            elif self.recommendation_type == RecommendationType.PERSONALIZED:
                recommendations = self._llm_personalized_recommendations(profile, count, exclude_seen)
            else:  # HYBRID
                recommendations = self._hybrid_recommendations(profile, count, exclude_seen)
            
            self.statistics["recommendations_made"] += len(recommendations)
            self.statistics["strategy_usage"][self.recommendation_type.value] += 1
            
            return recommendations
        
        def _collaborative_filtering(self,
                                     profile: UserProfile,
                                     count: int,
                                     exclude_seen: bool) -> List[Recommendation]:
            """Collaborative filtering based on similar users."""
            if not profile.rated_items:
                return self._popular_recommendations(profile, count, exclude_seen)
            
            # Find similar users
            similar_users = self._find_similar_users(profile)
            
            # Aggregate recommendations from similar users
            item_scores: Dict[str, float] = defaultdict(float)
            
            for similar_user_id, similarity in similar_users[:5]:  # Top 5 similar users
                similar_profile = self.user_profiles[similar_user_id]
                
                for item_id, rating in similar_profile.rated_items.items():
                    if exclude_seen and (item_id in profile.rated_items or 
                                        item_id in profile.viewed_items):
                        continue
                    
                    # Weight by similarity and rating
                    item_scores[item_id] += similarity * rating
            
            # Create recommendations
            recommendations = []
            for item_id, score in sorted(item_scores.items(), key=lambda x: x[1], reverse=True)[:count]:
                if item_id in self.items:
                    recommendations.append(Recommendation(
                        item=self.items[item_id],
                        score=score,
                        reason="Based on users with similar tastes",
                        recommendation_type=RecommendationType.COLLABORATIVE
                    ))
            
            return recommendations
        
        def _content_based_filtering(self,
                                     profile: UserProfile,
                                     count: int,
                                     exclude_seen: bool) -> List[Recommendation]:
            """Content-based filtering using item features."""
            if not profile.rated_items:
                return self._popular_recommendations(profile, count, exclude_seen)
            
            # Build user preference profile from rated items
            preferred_tags = self._extract_preferred_tags(profile)
            
            # Score items based on feature similarity
            item_scores: Dict[str, float] = {}
            
            for item_id, item in self.items.items():
                if exclude_seen and (item_id in profile.rated_items or 
                                    item_id in profile.viewed_items):
                    continue
                
                # Calculate similarity score based on tags
                tag_overlap = len(set(item.tags) & set(preferred_tags))
                category_match = 1.0 if item.category in profile.preferred_categories else 0.5
                
                score = (tag_overlap * 2.0 + category_match) * item.average_rating
                item_scores[item_id] = score
            
            # Create recommendations
            recommendations = []
            for item_id, score in sorted(item_scores.items(), key=lambda x: x[1], reverse=True)[:count]:
                matching_tags = list(set(self.items[item_id].tags) & set(preferred_tags))
                reason = f"Matches your interests: {', '.join(matching_tags[:3])}"
                
                recommendations.append(Recommendation(
                    item=self.items[item_id],
                    score=score,
                    reason=reason,
                    recommendation_type=RecommendationType.CONTENT_BASED
                ))
            
            return recommendations
        
        def _popular_recommendations(self,
                                    profile: UserProfile,
                                    count: int,
                                    exclude_seen: bool) -> List[Recommendation]:
            """Popularity-based recommendations."""
            # Score by popularity and ratings
            item_scores = []
            
            for item_id, item in self.items.items():
                if exclude_seen and (item_id in profile.rated_items or 
                                    item_id in profile.viewed_items):
                    continue
                
                # Combine popularity and average rating
                score = item.popularity_score * 0.5 + item.average_rating * 0.5
                item_scores.append((item_id, score))
            
            # Create recommendations
            recommendations = []
            for item_id, score in sorted(item_scores, key=lambda x: x[1], reverse=True)[:count]:
                recommendations.append(Recommendation(
                    item=self.items[item_id],
                    score=score,
                    reason="Popular among all users",
                    recommendation_type=RecommendationType.POPULAR
                ))
            
            return recommendations
        
        def _hybrid_recommendations(self,
                                   profile: UserProfile,
                                   count: int,
                                   exclude_seen: bool) -> List[Recommendation]:
            """Hybrid approach combining multiple strategies."""
            # Get recommendations from different strategies
            collab_recs = self._collaborative_filtering(profile, count, exclude_seen)
            content_recs = self._content_based_filtering(profile, count, exclude_seen)
            popular_recs = self._popular_recommendations(profile, count, exclude_seen)
            
            # Combine and deduplicate
            all_recs: Dict[str, Recommendation] = {}
            
            # Weight: collaborative 40%, content 40%, popular 20%
            for rec in collab_recs:
                all_recs[rec.item.id] = Recommendation(
                    item=rec.item,
                    score=rec.score * 0.4,
                    reason="Hybrid: Similar users + Your preferences",
                    recommendation_type=RecommendationType.HYBRID
                )
            
            for rec in content_recs:
                if rec.item.id in all_recs:
                    all_recs[rec.item.id].score += rec.score * 0.4
                else:
                    all_recs[rec.item.id] = Recommendation(
                        item=rec.item,
                        score=rec.score * 0.4,
                        reason="Hybrid: Matches your interests",
                        recommendation_type=RecommendationType.HYBRID
                    )
            
            for rec in popular_recs:
                if rec.item.id in all_recs:
                    all_recs[rec.item.id].score += rec.score * 0.2
                else:
                    all_recs[rec.item.id] = Recommendation(
                        item=rec.item,
                        score=rec.score * 0.2,
                        reason="Hybrid: Popular choice",
                        recommendation_type=RecommendationType.HYBRID
                    )
            
            # Sort and return top recommendations
            sorted_recs = sorted(all_recs.values(), key=lambda x: x.score, reverse=True)
            return sorted_recs[:count]
        
        def _llm_personalized_recommendations(self,
                                             profile: UserProfile,
                                             count: int,
                                             exclude_seen: bool) -> List[Recommendation]:
            """LLM-enhanced personalized recommendations."""
            # Get baseline recommendations
            baseline_recs = self._hybrid_recommendations(profile, count * 2, exclude_seen)
            
            if not baseline_recs:
                return []
            
            # Use LLM to refine and personalize
            items_info = "\n".join([
                f"- {rec.item.title} (Category: {rec.item.category.value}, "
                f"Tags: {', '.join(rec.item.tags[:3])}, Rating: {rec.item.average_rating:.1f})"
                for rec in baseline_recs[:10]
            ])
            
            user_history = ", ".join([
                self.items[item_id].title 
                for item_id in list(profile.rated_items.keys())[:5]
                if item_id in self.items
            ])
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", "You are a recommendation expert. Analyze user preferences and "
                          "select the most relevant items to recommend. Explain why each fits the user."),
                ("human", f"User has liked: {user_history}\n\n"
                         f"Available items:\n{items_info}\n\n"
                         f"Select top {count} items and explain why they match user preferences.")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            # Return top recommendations with LLM explanation
            return baseline_recs[:count]
        
        # Helper methods
        def _find_similar_users(self, profile: UserProfile) -> List[tuple]:
            """Find users with similar rating patterns."""
            similarities = []
            
            for other_id, other_profile in self.user_profiles.items():
                if other_id == profile.user_id:
                    continue
                
                # Calculate cosine similarity based on ratings
                similarity = self._calculate_user_similarity(profile, other_profile)
                if similarity > 0:
                    similarities.append((other_id, similarity))
            
            return sorted(similarities, key=lambda x: x[1], reverse=True)
        
        def _calculate_user_similarity(self,
                                       profile1: UserProfile,
                                       profile2: UserProfile) -> float:
            """Calculate similarity between two users."""
            # Find common rated items
            common_items = set(profile1.rated_items.keys()) & set(profile2.rated_items.keys())
            
            if not common_items:
                return 0.0
            
            # Cosine similarity
            dot_product = sum(
                profile1.rated_items[item] * profile2.rated_items[item]
                for item in common_items
            )
            
            magnitude1 = math.sqrt(sum(r**2 for r in profile1.rated_items.values()))
            magnitude2 = math.sqrt(sum(r**2 for r in profile2.rated_items.values()))
            
            if magnitude1 == 0 or magnitude2 == 0:
                return 0.0
            
            return dot_product / (magnitude1 * magnitude2)
        
        def _extract_preferred_tags(self, profile: UserProfile) -> List[str]:
            """Extract preferred tags from user's rated items."""
            tag_scores: Dict[str, float] = defaultdict(float)
            
            for item_id, rating in profile.rated_items.items():
                if item_id in self.items:
                    item = self.items[item_id]
                    for tag in item.tags:
                        tag_scores[tag] += rating
            
            # Return tags sorted by preference
            return [tag for tag, _ in sorted(tag_scores.items(), key=lambda x: x[1], reverse=True)]
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get recommendation system statistics."""
            return {
                "name": self.name,
                "total_items": len(self.items),
                "total_users": len(self.user_profiles),
                "recommendation_strategy": self.recommendation_type.value,
                **self.statistics
            }
    
    
    class RecommendationPattern:
        """
        Recommendation Pattern - Manage recommendation systems.
        
        Coordinates multiple recommendation agents for different domains.
        """
        
        def __init__(self):
            self.agents: Dict[str, RecommendationAgent] = {}
        
        def create_agent(self,
                         name: str,
                         recommendation_type: RecommendationType = RecommendationType.HYBRID) -> RecommendationAgent:
            """Create a new recommendation agent."""
            agent = RecommendationAgent(name, recommendation_type)
            self.agents[name] = agent
            print(f"   Created recommendation agent: {name} ({recommendation_type.value})")
            return agent
        
        def run(self,
                agent_name: str,
                user_id: str,
                count: int = 5) -> Dict[str, Any]:
            """Generate recommendations for user."""
            if agent_name not in self.agents:
                return {"error": f"Agent {agent_name} not found"}
            
            agent = self.agents[agent_name]
            recommendations = agent.recommend(user_id, count)
            
            print(f"\n=== Recommendations from {agent_name} for User: {user_id} ===\n")
            
            for i, rec in enumerate(recommendations, 1):
                print(f"{i}. {rec.item.title} (Score: {rec.score:.2f})")
                print(f"   Category: {rec.item.category.value} | Rating: {rec.item.average_rating:.1f}/5.0")
                print(f"   Reason: {rec.reason}\n")
            
            return {
                "agent": agent_name,
                "user": user_id,
                "recommendations": len(recommendations),
                "statistics": agent.get_statistics()
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Recommendation Agent Pattern Demo ===\n")
        
        # Create pattern
        pattern = RecommendationPattern()
        
        # Create agents
        print("1. Setting up recommendation agents...")
        
        movie_agent = pattern.create_agent("MovieRecommender", RecommendationType.HYBRID)
        book_agent = pattern.create_agent("BookRecommender", RecommendationType.CONTENT_BASED)
        
        # Add sample movies
        print("\n2. Adding sample items...")
        
        movies = [
            Item("m1", "The Matrix", ItemCategory.MOVIE, 
                 ["sci-fi", "action", "philosophical"], popularity_score=0.95),
            Item("m2", "Inception", ItemCategory.MOVIE,
                 ["sci-fi", "thriller", "mind-bending"], popularity_score=0.92),
            Item("m3", "Interstellar", ItemCategory.MOVIE,
                 ["sci-fi", "drama", "space"], popularity_score=0.90),
            Item("m4", "The Shawshank Redemption", ItemCategory.MOVIE,
                 ["drama", "inspiring", "classic"], popularity_score=0.98),
            Item("m5", "Pulp Fiction", ItemCategory.MOVIE,
                 ["crime", "comedy", "nonlinear"], popularity_score=0.88),
            Item("m6", "The Dark Knight", ItemCategory.MOVIE,
                 ["action", "superhero", "crime"], popularity_score=0.94),
            Item("m7", "Blade Runner 2049", ItemCategory.MOVIE,
                 ["sci-fi", "philosophical", "visual"], popularity_score=0.82),
            Item("m8", "Arrival", ItemCategory.MOVIE,
                 ["sci-fi", "drama", "linguistics"], popularity_score=0.85)
        ]
        
        for movie in movies:
            movie_agent.add_item(movie)
        
        # Simulate user interactions
        print("   Adding user ratings...")
        
        # User 1 likes sci-fi
        movie_agent.record_rating("user1", "m1", 5.0)
        movie_agent.record_rating("user1", "m2", 4.5)
        movie_agent.record_rating("user1", "m3", 4.0)
        
        # User 2 likes drama
        movie_agent.record_rating("user2", "m4", 5.0)
        movie_agent.record_rating("user2", "m3", 3.5)
        
        # User 3 similar to user1
        movie_agent.record_rating("user3", "m1", 4.8)
        movie_agent.record_rating("user3", "m2", 4.7)
        movie_agent.record_rating("user3", "m7", 4.5)
        
        # Get recommendations
        print("\n3. Generating recommendations...")
        
        result = pattern.run("MovieRecommender", "user1", count=3)
        
        # Print statistics
        print("\n4. System Statistics:")
        stats = result["statistics"]
        for key, value in stats.items():
            print(f"   {key}: {value}")
        
        print("\n✓ Personalized recommendations generated using multiple strategies!")
    
        

    Agentic Architecture Pattern: Recommendation Agent

    Pattern 234: 234 Recommendation Agent – Line-by-Line Explanation

    Overview

    Pattern 234: Recommendation Agent

    Purpose: Personalized recommendation system that learns user preferences and suggests relevant items. Implements collaborative filtering, content-based filtering, and hybrid approaches.


    Code Structure Analysis

    File Information

    • Pattern Number: 234
    • Pattern Name: 234 Recommendation Agent
    • File Path: patterns\domain_specific\234_recommendation_agent.py
    • Total Lines: 539

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 234: Recommendation Agent
    
    Purpose: Personalized recommendation system that learns user preferences and suggests relevant items.
    Implements collaborative filtering, content-based filtering, and hybrid approaches.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 234 Recommendation Agent 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 collections import defaultdict
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    import math  # 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


    Enumerations

    RecommendationType (Line 18)

    class RecommendationType(Enum):
        COLLABORATIVE
        CONTENT_BASED
        HYBRID
        POPULAR
        PERSONALIZED
    

    Purpose: Types of recommendation strategies.

    Values: – COLLABORATIVE: Represents collaborative – CONTENT_BASED: Represents content based – HYBRID: Represents hybrid – POPULAR: Represents popular – PERSONALIZED: Represents personalized

    ItemCategory (Line 27)

    class ItemCategory(Enum):
        MOVIE
        BOOK
        PRODUCT
        RESTAURANT
        MUSIC
        ARTICLE
        COURSE
    

    Purpose: Categories of items.

    Values: – MOVIE: Represents movie – BOOK: Represents book – PRODUCT: Represents product – RESTAURANT: Represents restaurant – MUSIC: Represents music – ARTICLE: Represents article – COURSE: Represents course


    Classes

    RecommendationType (Line 18)

    Description: Types of recommendation strategies.

    ItemCategory (Line 27)

    Description: Categories of items.

    Item (Line 39)

    Description: Item to recommend.

    UserProfile (Line 52)

    Description: User profile with preferences.

    Recommendation (Line 64)

    Description: A single recommendation.

    RecommendationAgent (Line 72)

    Description: Recommendation Agent – Personalized recommendations using multiple strategies.

    Features: – Collaborative filtering (user-based similarity) – Content-based filtering (item features) – Hybrid recommendations – Popularity-based recommendations – LLM-enhanced personalization – User profile learning

    Methods:

    __init__ (Line 85)
    def __init__(self, name, recommendation_type):
        """No method docstring."""
    

    Purpose: No method docstring.

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

    add_item (Line 104)
    def add_item(self, item):
        """Add item to recommendation system."""
    

    Purpose: Add item to recommendation system.

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

    add_user (Line 109)
    def add_user(self, user_id):
        """Add or get user profile."""
    

    Purpose: Add or get user profile.

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

    record_rating (Line 115)
    def record_rating(self, user_id, item_id, rating):
        """Record user rating for an item."""
    

    Purpose: Record user rating for an item.

    Parameters: – self: Instance reference – user_id: Parameter for user_id – item_id: Parameter for item_id – rating: Parameter for rating

    record_view (Line 134)
    def record_view(self, user_id, item_id):
        """Record user viewing an item."""
    

    Purpose: Record user viewing an item.

    Parameters: – self: Instance reference – user_id: Parameter for user_id – item_id: Parameter for item_id

    recommend (Line 144)
    def recommend(self, user_id, count, exclude_seen):
        """Generate recommendations for user."""
    

    Purpose: Generate recommendations for user.

    Parameters: – self: Instance reference – user_id: Parameter for user_id – count: Parameter for count – exclude_seen: Parameter for exclude_seen

    _collaborative_filtering (Line 169)
    def _collaborative_filtering(self, profile, count, exclude_seen):
        """Collaborative filtering based on similar users."""
    

    Purpose: Collaborative filtering based on similar users.

    Parameters: – self: Instance reference – profile: Parameter for profile – count: Parameter for count – exclude_seen: Parameter for exclude_seen

    _content_based_filtering (Line 207)
    def _content_based_filtering(self, profile, count, exclude_seen):
        """Content-based filtering using item features."""
    

    Purpose: Content-based filtering using item features.

    Parameters: – self: Instance reference – profile: Parameter for profile – count: Parameter for count – exclude_seen: Parameter for exclude_seen

    _popular_recommendations (Line 248)
    def _popular_recommendations(self, profile, count, exclude_seen):
        """Popularity-based recommendations."""
    

    Purpose: Popularity-based recommendations.

    Parameters: – self: Instance reference – profile: Parameter for profile – count: Parameter for count – exclude_seen: Parameter for exclude_seen

    _hybrid_recommendations (Line 277)
    def _hybrid_recommendations(self, profile, count, exclude_seen):
        """Hybrid approach combining multiple strategies."""
    

    Purpose: Hybrid approach combining multiple strategies.

    Parameters: – self: Instance reference – profile: Parameter for profile – count: Parameter for count – exclude_seen: Parameter for exclude_seen

    _llm_personalized_recommendations (Line 325)
    def _llm_personalized_recommendations(self, profile, count, exclude_seen):
        """LLM-enhanced personalized recommendations."""
    

    Purpose: LLM-enhanced personalized recommendations.

    Parameters: – self: Instance reference – profile: Parameter for profile – count: Parameter for count – exclude_seen: Parameter for exclude_seen

    _find_similar_users (Line 364)
    def _find_similar_users(self, profile):
        """Find users with similar rating patterns."""
    

    Purpose: Find users with similar rating patterns.

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

    _calculate_user_similarity (Line 379)
    def _calculate_user_similarity(self, profile1, profile2):
        """Calculate similarity between two users."""
    

    Purpose: Calculate similarity between two users.

    Parameters: – self: Instance reference – profile1: Parameter for profile1 – profile2: Parameter for profile2

    _extract_preferred_tags (Line 403)
    def _extract_preferred_tags(self, profile):
        """Extract preferred tags from user's rated items."""
    

    Purpose: Extract preferred tags from user’s rated items.

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

    get_statistics (Line 416)
    def get_statistics(self):
        """Get recommendation system statistics."""
    

    Purpose: Get recommendation system statistics.

    Parameters: – self: Instance reference

    RecommendationPattern (Line 427)

    Description: Recommendation Pattern – Manage recommendation systems.

    Coordinates multiple recommendation agents for different domains.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    create_agent (Line 437)
    def create_agent(self, name, recommendation_type):
        """Create a new recommendation agent."""
    

    Purpose: Create a new recommendation agent.

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

    run (Line 446)
    def run(self, agent_name, user_id, count):
        """Generate recommendations for user."""
    

    Purpose: Generate recommendations for user.

    Parameters: – self: Instance reference – agent_name: Parameter for agent_name – user_id: Parameter for user_id – count: Parameter for count


    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 = RecommendationType(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: Virtual Assistant

    
        """
    Pattern 233: Virtual Assistant
    
    Purpose: Personalized AI assistant that executes tasks, manages schedules, and provides proactive help.
    Handles calendar, reminders, information retrieval, and task management with user preferences.
    """
    
    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime, timedelta
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class TaskType(Enum):
        """Types of tasks the assistant can handle."""
        SCHEDULE = "schedule"  # Calendar events
        REMINDER = "reminder"  # Set reminders
        SEARCH = "search"  # Information retrieval
        EMAIL = "email"  # Email management
        TODO = "todo"  # Task management
        WEATHER = "weather"  # Weather info
        NEWS = "news"  # News updates
        CALCULATION = "calculation"  # Math calculations
        TRANSLATION = "translation"  # Language translation
        GENERAL = "general"  # General assistance
    
    
    class Priority(Enum):
        """Task priority levels."""
        LOW = "low"
        MEDIUM = "medium"
        HIGH = "high"
        URGENT = "urgent"
    
    
    @dataclass
    class CalendarEvent:
        """Calendar event."""
        title: str
        start_time: datetime
        end_time: datetime
        description: str = ""
        location: str = ""
        attendees: List[str] = field(default_factory=list)
        reminder_minutes: int = 15
    
    
    @dataclass
    class Reminder:
        """Reminder for user."""
        message: str
        remind_at: datetime
        priority: Priority = Priority.MEDIUM
        recurring: bool = False
        completed: bool = False
    
    
    @dataclass
    class TodoItem:
        """Todo list item."""
        task: str
        priority: Priority = Priority.MEDIUM
        due_date: Optional[datetime] = None
        completed: bool = False
        tags: List[str] = field(default_factory=list)
    
    
    @dataclass
    class UserPreferences:
        """User preferences and profile."""
        name: str
        timezone: str = "UTC"
        preferred_language: str = "English"
        work_hours: tuple = (9, 17)  # 9 AM to 5 PM
        interests: List[str] = field(default_factory=list)
        notification_style: str = "normal"  # normal, minimal, detailed
    
    
    class VirtualAssistant:
        """
        Virtual Assistant - Personalized AI assistant for task execution and scheduling.
        
        Features:
        - Calendar management with scheduling
        - Reminder system with priorities
        - Todo list management
        - Information retrieval and search
        - Proactive suggestions
        - Personalized responses based on user preferences
        """
        
        def __init__(self,
                     name: str,
                     user_preferences: Optional[UserPreferences] = None):
            self.name = name
            self.user_preferences = user_preferences or UserPreferences(name="User")
            self.llm = ChatOpenAI(model="gpt-4", temperature=0.7)
            
            # State management
            self.calendar: List[CalendarEvent] = []
            self.reminders: List[Reminder] = []
            self.todo_list: List[TodoItem] = []
            self.conversation_context: List[str] = []
            
            # Task handlers
            self.task_handlers: Dict[TaskType, Callable] = {
                TaskType.SCHEDULE: self._handle_schedule,
                TaskType.REMINDER: self._handle_reminder,
                TaskType.SEARCH: self._handle_search,
                TaskType.TODO: self._handle_todo,
                TaskType.WEATHER: self._handle_weather,
                TaskType.CALCULATION: self._handle_calculation,
                TaskType.GENERAL: self._handle_general
            }
            
            # Statistics
            self.statistics: Dict[str, Any] = {
                "tasks_completed": 0,
                "events_scheduled": 0,
                "reminders_set": 0,
                "proactive_suggestions": 0
            }
        
        def assist(self, user_request: str) -> str:
            """Process user request and provide assistance."""
            # Add to conversation context
            self.conversation_context.append(user_request)
            
            # Determine task type
            task_type = self._classify_task(user_request)
            
            # Execute appropriate handler
            handler = self.task_handlers.get(task_type, self._handle_general)
            response = handler(user_request)
            
            # Check for proactive suggestions
            suggestions = self._generate_proactive_suggestions()
            if suggestions:
                response += f"\n\n💡 Proactive suggestion: {suggestions}"
                self.statistics["proactive_suggestions"] += 1
            
            self.statistics["tasks_completed"] += 1
            
            return response
        
        def _classify_task(self, user_request: str) -> TaskType:
            """Classify the type of task from user request."""
            request_lower = user_request.lower()
            
            # Pattern matching for task classification
            if any(word in request_lower for word in ["schedule", "meeting", "appointment", "calendar", "book"]):
                return TaskType.SCHEDULE
            elif any(word in request_lower for word in ["remind", "reminder", "alert", "notify"]):
                return TaskType.REMINDER
            elif any(word in request_lower for word in ["search", "find", "look up", "google", "what is"]):
                return TaskType.SEARCH
            elif any(word in request_lower for word in ["todo", "task", "add to list", "need to do"]):
                return TaskType.TODO
            elif any(word in request_lower for word in ["weather", "temperature", "forecast", "rain"]):
                return TaskType.WEATHER
            elif any(word in request_lower for word in ["calculate", "compute", "math", "+", "-", "*", "/"]):
                return TaskType.CALCULATION
            else:
                return TaskType.GENERAL
        
        # Task handlers
        def _handle_schedule(self, request: str) -> str:
            """Handle calendar scheduling."""
            # Extract event details using LLM
            prompt = ChatPromptTemplate.from_messages([
                ("system", "Extract event details from the user's scheduling request. "
                          "Provide: title, date, time, and any other relevant details."),
                ("human", "{request}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"request": request})
            
            # Create event (simplified - in production would parse LLM response)
            event = CalendarEvent(
                title="Meeting",
                start_time=datetime.now() + timedelta(days=1, hours=2),
                end_time=datetime.now() + timedelta(days=1, hours=3),
                description=request
            )
            
            self.calendar.append(event)
            self.statistics["events_scheduled"] += 1
            
            return f"✓ Scheduled: {event.title} for {event.start_time.strftime('%Y-%m-%d at %H:%M')}. " \
                   f"I'll remind you 15 minutes before."
        
        def _handle_reminder(self, request: str) -> str:
            """Handle reminder setting."""
            # Determine reminder time and message
            reminder = Reminder(
                message=request,
                remind_at=datetime.now() + timedelta(hours=1),  # Default 1 hour
                priority=Priority.MEDIUM
            )
            
            self.reminders.append(reminder)
            self.statistics["reminders_set"] += 1
            
            return f"✓ Reminder set: '{reminder.message}' for {reminder.remind_at.strftime('%Y-%m-%d at %H:%M')}"
        
        def _handle_search(self, request: str) -> str:
            """Handle information search."""
            # Use LLM for information retrieval
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, a helpful virtual assistant. "
                          f"Provide concise, accurate information in response to user queries. "
                          f"User's interests: {', '.join(self.user_preferences.interests or ['general topics'])}"),
                ("human", "{query}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"query": request})
            
            return f"🔍 Search result: {response.content}"
        
        def _handle_todo(self, request: str) -> str:
            """Handle todo list management."""
            # Extract task from request
            task_text = request.replace("add", "").replace("to do", "").replace("todo", "").strip()
            
            todo = TodoItem(
                task=task_text,
                priority=Priority.MEDIUM,
                due_date=None
            )
            
            self.todo_list.append(todo)
            
            incomplete_count = sum(1 for t in self.todo_list if not t.completed)
            return f"✓ Added to todo list: '{todo.task}'. You now have {incomplete_count} pending tasks."
        
        def _handle_weather(self, request: str) -> str:
            """Handle weather queries."""
            # Simulate weather response (in production, would call weather API)
            return f"☀️ Weather forecast: Currently 72°F and sunny. " \
                   f"Perfect weather for outdoor activities!"
        
        def _handle_calculation(self, request: str) -> str:
            """Handle mathematical calculations."""
            import re
            
            # Extract numbers and operators
            numbers = re.findall(r'\d+\.?\d*', request)
            
            if len(numbers) >= 2:
                try:
                    # Simple calculation (in production, use safer evaluation)
                    if '+' in request:
                        result = sum(float(n) for n in numbers)
                        return f"🔢 Calculation: {' + '.join(numbers)} = {result}"
                    elif '-' in request:
                        result = float(numbers[0]) - float(numbers[1])
                        return f"🔢 Calculation: {numbers[0]} - {numbers[1]} = {result}"
                    elif '*' in request or 'times' in request:
                        result = float(numbers[0]) * float(numbers[1])
                        return f"🔢 Calculation: {numbers[0]} × {numbers[1]} = {result}"
                    elif '/' in request or 'divided' in request:
                        result = float(numbers[0]) / float(numbers[1])
                        return f"🔢 Calculation: {numbers[0]} ÷ {numbers[1]} = {result:.2f}"
                except:
                    pass
            
            return "I can help with calculations. Please provide a clear mathematical expression."
        
        def _handle_general(self, request: str) -> str:
            """Handle general assistance requests."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, a personalized virtual assistant for {self.user_preferences.name}. "
                          f"Be helpful, friendly, and proactive. Provide clear, actionable responses. "
                          f"User interests: {', '.join(self.user_preferences.interests or ['general topics'])}. "
                          f"Preferred language: {self.user_preferences.preferred_language}."),
                ("human", "{request}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"request": request})
            
            return response.content
        
        def _generate_proactive_suggestions(self) -> Optional[str]:
            """Generate proactive suggestions based on context."""
            current_hour = datetime.now().hour
            
            # Morning suggestion
            if 6 <= current_hour  0:
                next_event = min(self.calendar, key=lambda e: e.start_time)
                if next_event.start_time.date() == datetime.now().date():
                    return f"You have '{next_event.title}' at {next_event.start_time.strftime('%H:%M')} today."
            
            # Pending tasks suggestion
            if len(self.todo_list) > 5:
                incomplete = [t for t in self.todo_list if not t.completed]
                if len(incomplete) > 3:
                    return f"You have {len(incomplete)} pending tasks. Would you like me to prioritize them?"
            
            # Reminder check
            upcoming_reminders = [r for r in self.reminders 
                                 if not r.completed and r.remind_at  List[CalendarEvent]:
            """Get schedule for a specific date."""
            target_date = date or datetime.now()
            return [e for e in self.calendar if e.start_time.date() == target_date.date()]
        
        def get_pending_tasks(self) -> List[TodoItem]:
            """Get all pending todo items."""
            return [t for t in self.todo_list if not t.completed]
        
        def complete_task(self, task_index: int) -> str:
            """Mark a todo task as completed."""
            if 0 <= task_index  str:
            """Get daily summary."""
            today_events = self.get_schedule()
            pending_tasks = self.get_pending_tasks()
            active_reminders = [r for r in self.reminders if not r.completed]
            
            summary = f"📊 Daily Summary for {self.user_preferences.name}:\n"
            summary += f"   • Events today: {len(today_events)}\n"
            summary += f"   • Pending tasks: {len(pending_tasks)}\n"
            summary += f"   • Active reminders: {len(active_reminders)}\n"
            
            return summary
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get assistant statistics."""
            return {
                "name": self.name,
                "user": self.user_preferences.name,
                "total_events": len(self.calendar),
                "total_reminders": len(self.reminders),
                "pending_tasks": len(self.get_pending_tasks()),
                **self.statistics
            }
    
    
    class VirtualAssistantPattern:
        """
        Virtual Assistant Pattern - Manage personalized AI assistants.
        
        Coordinates multiple virtual assistants for different users.
        """
        
        def __init__(self):
            self.assistants: Dict[str, VirtualAssistant] = {}
        
        def create_assistant(self, name: str, user_preferences: UserPreferences) -> VirtualAssistant:
            """Create a new virtual assistant."""
            assistant = VirtualAssistant(name, user_preferences)
            self.assistants[name] = assistant
            print(f"   Created assistant: {name} for {user_preferences.name}")
            return assistant
        
        def run(self, assistant_name: str, requests: List[str]) -> Dict[str, Any]:
            """Run series of requests with assistant."""
            if assistant_name not in self.assistants:
                return {"error": f"Assistant {assistant_name} not found"}
            
            assistant = self.assistants[assistant_name]
            responses = []
            
            print(f"\n=== {assistant_name} Assistance Session ===\n")
            
            for request in requests:
                print(f"User: {request}")
                response = assistant.assist(request)
                print(f"{assistant_name}: {response}\n")
                responses.append(response)
            
            # Show summary
            print(assistant.get_summary())
            
            return {
                "assistant": assistant_name,
                "requests_handled": len(requests),
                "responses": responses,
                "statistics": assistant.get_statistics()
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Virtual Assistant Pattern Demo ===\n")
        
        # Create pattern
        pattern = VirtualAssistantPattern()
        
        # Create user preferences
        print("1. Setting up virtual assistants...")
        
        user_prefs = UserPreferences(
            name="Alice",
            timezone="America/New_York",
            preferred_language="English",
            interests=["technology", "productivity", "health"]
        )
        
        assistant = pattern.create_assistant("Jarvis", user_prefs)
        
        # Add some initial data
        assistant.todo_list.append(TodoItem(task="Review project proposal", priority=Priority.HIGH))
        assistant.todo_list.append(TodoItem(task="Call dentist", priority=Priority.MEDIUM))
        
        # Run assistance session
        print("\n2. Running assistance session...")
        
        requests = [
            "What's on my schedule today?",
            "Add a reminder to buy groceries",
            "Schedule a meeting for tomorrow at 2 PM",
            "What's 25 times 4?",
            "Add 'Prepare presentation' to my todo list",
            "Search for information about artificial intelligence",
            "What's the weather like?",
            "Show me my pending tasks"
        ]
        
        result = pattern.run("Jarvis", requests)
        
        # Print statistics
        print("\n3. Assistant Statistics:")
        stats = result["statistics"]
        for key, value in stats.items():
            print(f"   {key}: {value}")
        
        print("\n✓ Virtual assistant provided personalized help and task management!")
            self.state.current_step += 1
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, implementing Virtual Assistant. "
                          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 VirtualAssistantPattern:
        """
        Virtual Assistant - Enhanced implementation
        
        This pattern provides comprehensive functionality for virtual assistant
        with full LangChain/LangGraph integration.
        
        Features:
        - Multi-agent coordination
        - State management
        - Execution tracking
        - LangGraph workflow integration
        """
        
        def __init__(self, config: VirtualAssistantConfig = None):
            self.config = config or VirtualAssistantConfig()
            self.agents: Dict[str, VirtualAssistantAgent] = {}
            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 Virtual Assistant. 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: VirtualAssistantAgent):
            """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": "Virtual Assistant",
                    "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": "Virtual Assistant",
                "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("=== Virtual Assistant Demo ===\n")
        
        # Create configuration
        config = VirtualAssistantConfig(
            model_name="gpt-4",
            temperature=0.7,
            enable_logging=True
        )
        
        # Create pattern
        pattern = VirtualAssistantPattern(config)
        
        # Create and register agents
        agent1 = VirtualAssistantAgent("Agent1", config)
        agent2 = VirtualAssistantAgent("Agent2", config)
        pattern.register_agent(agent1)
        pattern.register_agent(agent2)
        
        print("\nExecuting pattern workflow...")
        
        # Execute with workflow
        result1 = pattern.run("Demonstrate virtual assistant 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: Virtual Assistant

    Pattern 233: 233 Virtual Assistant – Line-by-Line Explanation

    Overview

    Pattern 233: Virtual Assistant

    Purpose: Personalized AI assistant that executes tasks, manages schedules, and provides proactive help. Handles calendar, reminders, information retrieval, and task management with user preferences.


    Code Structure Analysis

    File Information

    • Pattern Number: 233
    • Pattern Name: 233 Virtual Assistant
    • File Path: patterns\domain_specific\233_virtual_assistant.py
    • Total Lines: 640

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 233: Virtual Assistant
    
    Purpose: Personalized AI assistant that executes tasks, manages schedules, and provides proactive help.
    Handles calendar, reminders, information retrieval, and task management with user preferences.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 233 Virtual Assistant pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime, timedelta
    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, Callable: Type hints for better code documentation – from dataclasses import dataclass, field: Data class decorators for clean data structures – from datetime import datetime, timedelta: 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


    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

    # Usage example not available
    

    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: Chatbot

    
        """
    Pattern 232: Chatbot
    
    Purpose: Goal-oriented chatbot with intent recognition, dialogue flow, and response generation.
    Handles predefined intents, manages conversation state, and provides structured responses.
    """
    
    from typing import Dict, Any, List, Optional, Callable
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from collections import defaultdict
    import re
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class IntentType(Enum):
        """Common chatbot intents."""
        GREETING = "greeting"
        FAREWELL = "farewell"
        HELP = "help"
        FAQ = "faq"
        BOOKING = "booking"
        INQUIRY = "inquiry"
        COMPLAINT = "complaint"
        FEEDBACK = "feedback"
        CHITCHAT = "chitchat"
        UNKNOWN = "unknown"
    
    
    class FlowState(Enum):
        """States in conversation flow."""
        INITIAL = "initial"
        COLLECTING_INFO = "collecting_info"
        CONFIRMING = "confirming"
        PROCESSING = "processing"
        COMPLETED = "completed"
        ERROR = "error"
    
    
    @dataclass
    class Intent:
        """Recognized user intent."""
        type: IntentType
        confidence: float
        entities: Dict[str, Any] = field(default_factory=dict)
        raw_input: str = ""
    
    
    @dataclass
    class Response:
        """Chatbot response."""
        text: str
        intent: IntentType
        follow_up_questions: List[str] = field(default_factory=list)
        actions: List[str] = field(default_factory=list)
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class ConversationFlow:
        """Manages conversation flow state."""
        current_state: FlowState = FlowState.INITIAL
        required_fields: List[str] = field(default_factory=list)
        collected_fields: Dict[str, Any] = field(default_factory=dict)
        flow_type: Optional[IntentType] = None
    
    
    class Chatbot:
        """
        Chatbot - Goal-oriented dialogue with intent recognition and flow management.
        
        Features:
        - Intent recognition with pattern matching
        - Entity extraction
        - Dialogue flow management
        - FAQ handling
        - Context-aware responses
        """
        
        def __init__(self,
                     name: str,
                     domain: str = "general",
                     supported_intents: Optional[List[IntentType]] = None):
            self.name = name
            self.domain = domain
            self.supported_intents = supported_intents or [intent for intent in IntentType]
            self.llm = ChatOpenAI(model="gpt-4", temperature=0.7)
            
            # Intent patterns
            self.intent_patterns: Dict[IntentType, List[str]] = self._init_intent_patterns()
            
            # FAQ knowledge base
            self.faq_db: Dict[str, str] = {}
            
            # Conversation state
            self.current_flow: Optional[ConversationFlow] = None
            self.conversation_history: List[Dict[str, Any]] = []
            
            # Response handlers
            self.response_handlers: Dict[IntentType, Callable] = self._init_response_handlers()
            
            # Statistics
            self.statistics: Dict[str, Any] = {
                "total_messages": 0,
                "intent_counts": defaultdict(int),
                "avg_confidence": 0.0,
                "flow_completions": 0
            }
        
        def _init_intent_patterns(self) -> Dict[IntentType, List[str]]:
            """Initialize intent recognition patterns."""
            return {
                IntentType.GREETING: [
                    r'\b(hi|hello|hey|greetings|good morning|good afternoon)\b',
                    r'^(hi|hello|hey)[\s!.]*$'
                ],
                IntentType.FAREWELL: [
                    r'\b(bye|goodbye|see you|farewell|take care)\b',
                    r'^(bye|goodbye)[\s!.]*$'
                ],
                IntentType.HELP: [
                    r'\b(help|assist|support|how do i|how can|what can)\b',
                    r'^(help|assist me)\b'
                ],
                IntentType.FAQ: [
                    r'\b(what is|tell me about|explain|how does|when is|where is)\b',
                    r'\?$'
                ],
                IntentType.BOOKING: [
                    r'\b(book|reserve|appointment|schedule|availability)\b',
                    r'\b(i want to book|make a reservation)\b'
                ],
                IntentType.INQUIRY: [
                    r'\b(information|details|more about|interested in)\b',
                    r'\b(can you tell|would like to know)\b'
                ],
                IntentType.COMPLAINT: [
                    r'\b(problem|issue|complaint|not working|broken|unhappy)\b',
                    r'\b(dissatisfied|disappointed|frustrated)\b'
                ],
                IntentType.FEEDBACK: [
                    r'\b(feedback|suggestion|recommend|improve|better)\b',
                    r'\b(would like to suggest|my opinion)\b'
                ],
                IntentType.CHITCHAT: [
                    r'\b(weather|today|how are you|nice day|weekend)\b',
                    r'\b(thanks|thank you|appreciate)\b'
                ]
            }
        
        def _init_response_handlers(self) -> Dict[IntentType, Callable]:
            """Initialize intent-specific response handlers."""
            return {
                IntentType.GREETING: self._handle_greeting,
                IntentType.FAREWELL: self._handle_farewell,
                IntentType.HELP: self._handle_help,
                IntentType.FAQ: self._handle_faq,
                IntentType.BOOKING: self._handle_booking,
                IntentType.INQUIRY: self._handle_inquiry,
                IntentType.COMPLAINT: self._handle_complaint,
                IntentType.FEEDBACK: self._handle_feedback,
                IntentType.CHITCHAT: self._handle_chitchat,
                IntentType.UNKNOWN: self._handle_unknown
            }
        
        def chat(self, user_input: str) -> Response:
            """Process user input and generate response."""
            self.statistics["total_messages"] += 1
            
            # Recognize intent
            intent = self._recognize_intent(user_input)
            self.statistics["intent_counts"][intent.type.value] += 1
            
            # Extract entities
            entities = self._extract_entities(user_input, intent.type)
            intent.entities = entities
            
            # Generate response using appropriate handler
            handler = self.response_handlers.get(intent.type, self._handle_unknown)
            response = handler(intent)
            
            # Record in history
            self.conversation_history.append({
                "user_input": user_input,
                "intent": intent.type.value,
                "confidence": intent.confidence,
                "response": response.text,
                "timestamp": datetime.now()
            })
            
            # Update statistics
            self._update_statistics()
            
            return response
        
        def _recognize_intent(self, user_input: str) -> Intent:
            """Recognize user intent from input."""
            user_lower = user_input.lower()
            best_intent = IntentType.UNKNOWN
            max_confidence = 0.0
            
            # Pattern matching
            for intent_type, patterns in self.intent_patterns.items():
                if intent_type not in self.supported_intents:
                    continue
                
                for pattern in patterns:
                    if re.search(pattern, user_lower):
                        # Simple confidence based on pattern specificity
                        confidence = 0.7 + (0.3 * len(pattern) / 100)
                        if confidence > max_confidence:
                            max_confidence = confidence
                            best_intent = intent_type
            
            # If no pattern matched, use LLM for classification
            if max_confidence  max_confidence:
                    best_intent = llm_intent
                    max_confidence = llm_confidence
            
            return Intent(
                type=best_intent,
                confidence=min(1.0, max_confidence),
                raw_input=user_input
            )
        
        def _llm_classify_intent(self, user_input: str) -> tuple:
            """Use LLM to classify intent when patterns don't match."""
            intent_options = ", ".join([i.value for i in self.supported_intents])
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are an intent classifier for a {self.domain} chatbot. "
                          f"Classify the user input into one of these intents: {intent_options}. "
                          f"Respond with ONLY the intent name."),
                ("human", "{input}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"input": user_input})
            
            # Parse response
            intent_str = response.content.strip().lower()
            
            for intent_type in self.supported_intents:
                if intent_type.value in intent_str:
                    return intent_type, 0.6
            
            return IntentType.UNKNOWN, 0.3
        
        def _extract_entities(self, user_input: str, intent_type: IntentType) -> Dict[str, Any]:
            """Extract entities from user input."""
            entities = {}
            
            # Simple entity extraction patterns
            # Date/time
            date_pattern = r'\b(\d{1,2}[/-]\d{1,2}[/-]\d{2,4}|\d{4}-\d{2}-\d{2})\b'
            dates = re.findall(date_pattern, user_input)
            if dates:
                entities["date"] = dates[0]
            
            # Time
            time_pattern = r'\b(\d{1,2}:\d{2}\s*(?:am|pm)?)\b'
            times = re.findall(time_pattern, user_input.lower())
            if times:
                entities["time"] = times[0]
            
            # Email
            email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
            emails = re.findall(email_pattern, user_input)
            if emails:
                entities["email"] = emails[0]
            
            # Phone
            phone_pattern = r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b'
            phones = re.findall(phone_pattern, user_input)
            if phones:
                entities["phone"] = phones[0]
            
            # Numbers
            number_pattern = r'\b\d+\b'
            numbers = re.findall(number_pattern, user_input)
            if numbers and intent_type == IntentType.BOOKING:
                entities["quantity"] = numbers[0]
            
            return entities
        
        # Intent handlers
        def _handle_greeting(self, intent: Intent) -> Response:
            """Handle greeting intent."""
            responses = [
                f"Hello! I'm {self.name}, your {self.domain} assistant. How can I help you today?",
                f"Hi there! Welcome to {self.name}. What can I do for you?",
                f"Greetings! I'm here to assist you with {self.domain}. What do you need?"
            ]
            
            import random
            return Response(
                text=random.choice(responses),
                intent=IntentType.GREETING,
                follow_up_questions=["What can I help you with today?"]
            )
        
        def _handle_farewell(self, intent: Intent) -> Response:
            """Handle farewell intent."""
            responses = [
                "Goodbye! Feel free to come back if you need anything!",
                "Take care! Have a great day!",
                "Bye! Thanks for chatting with me!"
            ]
            
            import random
            return Response(
                text=random.choice(responses),
                intent=IntentType.FAREWELL
            )
        
        def _handle_help(self, intent: Intent) -> Response:
            """Handle help request."""
            capabilities = [
                f"- Answer questions about {self.domain}",
                "- Help with bookings and appointments",
                "- Provide information and support",
                "- Handle complaints and feedback"
            ]
            
            help_text = f"I can help you with:\n" + "\n".join(capabilities)
            
            return Response(
                text=help_text,
                intent=IntentType.HELP,
                follow_up_questions=["What would you like to do?"]
            )
        
        def _handle_faq(self, intent: Intent) -> Response:
            """Handle FAQ query."""
            # Check if question matches FAQ database
            for question, answer in self.faq_db.items():
                if any(word in intent.raw_input.lower() for word in question.lower().split()):
                    return Response(
                        text=answer,
                        intent=IntentType.FAQ,
                        follow_up_questions=["Is there anything else you'd like to know?"]
                    )
            
            # Use LLM for dynamic FAQ
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are a helpful {self.domain} assistant. "
                          f"Provide clear, concise answers to user questions."),
                ("human", "{question}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"question": intent.raw_input})
            
            return Response(
                text=response.content,
                intent=IntentType.FAQ,
                follow_up_questions=["Do you have any other questions?"]
            )
        
        def _handle_booking(self, intent: Intent) -> Response:
            """Handle booking request."""
            # Initialize or update booking flow
            if not self.current_flow or self.current_flow.flow_type != IntentType.BOOKING:
                self.current_flow = ConversationFlow(
                    current_state=FlowState.COLLECTING_INFO,
                    required_fields=["date", "time", "email"],
                    flow_type=IntentType.BOOKING
                )
            
            # Collect entities
            for field, value in intent.entities.items():
                if field in self.current_flow.required_fields:
                    self.current_flow.collected_fields[field] = value
            
            # Check what's still missing
            missing_fields = [f for f in self.current_flow.required_fields 
                             if f not in self.current_flow.collected_fields]
            
            if missing_fields:
                field = missing_fields[0]
                return Response(
                    text=f"I'd be happy to help you book! What {field} would you prefer?",
                    intent=IntentType.BOOKING,
                    follow_up_questions=[f"Please provide your {field}"]
                )
            else:
                # All info collected
                self.current_flow.current_state = FlowState.CONFIRMING
                booking_details = ", ".join([f"{k}: {v}" for k, v in 
                                            self.current_flow.collected_fields.items()])
                return Response(
                    text=f"Great! I've got your booking for {booking_details}. Shall I confirm?",
                    intent=IntentType.BOOKING,
                    follow_up_questions=["Reply 'yes' to confirm or 'no' to cancel"],
                    actions=["prepare_booking"]
                )
        
        def _handle_inquiry(self, intent: Intent) -> Response:
            """Handle general inquiry."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are a knowledgeable {self.domain} assistant. "
                          f"Provide helpful information about user inquiries."),
                ("human", "{inquiry}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"inquiry": intent.raw_input})
            
            return Response(
                text=response.content,
                intent=IntentType.INQUIRY,
                follow_up_questions=["Would you like more details about anything?"]
            )
        
        def _handle_complaint(self, intent: Intent) -> Response:
            """Handle complaint."""
            return Response(
                text="I'm sorry to hear you're experiencing issues. Let me help resolve this. "
                     "Can you provide more details about the problem?",
                intent=IntentType.COMPLAINT,
                follow_up_questions=["What specific issue are you facing?"],
                actions=["escalate_to_support"]
            )
        
        def _handle_feedback(self, intent: Intent) -> Response:
            """Handle feedback."""
            return Response(
                text="Thank you for your feedback! We really appreciate your input. "
                     "Your suggestions help us improve our service.",
                intent=IntentType.FEEDBACK,
                actions=["record_feedback"]
            )
        
        def _handle_chitchat(self, intent: Intent) -> Response:
            """Handle casual conversation."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", "You are a friendly chatbot. Engage in brief, pleasant conversation."),
                ("human", "{message}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({"message": intent.raw_input})
            
            return Response(
                text=response.content,
                intent=IntentType.CHITCHAT
            )
        
        def _handle_unknown(self, intent: Intent) -> Response:
            """Handle unknown intent."""
            return Response(
                text="I'm not sure I understood that. Could you rephrase, or ask me for help?",
                intent=IntentType.UNKNOWN,
                follow_up_questions=["Try asking in a different way", "Type 'help' to see what I can do"]
            )
        
        def add_faq(self, question: str, answer: str):
            """Add FAQ to knowledge base."""
            self.faq_db[question.lower()] = answer
            print(f"   Added FAQ: {question}")
        
        def _update_statistics(self):
            """Update chatbot statistics."""
            if self.conversation_history:
                confidences = [h["confidence"] for h in self.conversation_history]
                self.statistics["avg_confidence"] = sum(confidences) / len(confidences)
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get chatbot statistics."""
            return {
                "name": self.name,
                "domain": self.domain,
                "total_messages": self.statistics["total_messages"],
                "intent_distribution": dict(self.statistics["intent_counts"]),
                "avg_confidence": self.statistics["avg_confidence"],
                "faq_count": len(self.faq_db)
            }
    
    
    class ChatbotPattern:
        """
        Chatbot Pattern - Manage goal-oriented chatbots.
        
        Coordinates multiple chatbots for different domains.
        """
        
        def __init__(self):
            self.chatbots: Dict[str, Chatbot] = {}
        
        def register_chatbot(self, chatbot: Chatbot):
            """Register a chatbot."""
            self.chatbots[chatbot.name] = chatbot
            print(f"   Registered chatbot: {chatbot.name} ({chatbot.domain})")
        
        def run(self, chatbot_name: str, conversation: List[str]) -> Dict[str, Any]:
            """Run conversation with chatbot."""
            if chatbot_name not in self.chatbots:
                return {"error": f"Chatbot {chatbot_name} not found"}
            
            chatbot = self.chatbots[chatbot_name]
            responses = []
            
            print(f"\n=== Conversation with {chatbot_name} ===\n")
            
            for user_input in conversation:
                print(f"User: {user_input}")
                response = chatbot.chat(user_input)
                print(f"{chatbot_name}: {response.text}")
                if response.follow_up_questions:
                    print(f"   Follow-up: {response.follow_up_questions[0]}")
                print()
                responses.append(response)
            
            return {
                "chatbot": chatbot_name,
                "turns": len(conversation),
                "responses": responses,
                "statistics": chatbot.get_statistics()
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Chatbot Pattern Demo ===\n")
        
        # Create pattern
        pattern = ChatbotPattern()
        
        # Create chatbots for different domains
        print("1. Creating chatbots...")
        
        customer_service = Chatbot(
            name="CustomerServiceBot",
            domain="customer service",
            supported_intents=[IntentType.GREETING, IntentType.HELP, IntentType.FAQ, 
                              IntentType.COMPLAINT, IntentType.FAREWELL]
        )
        
        # Add FAQs
        customer_service.add_faq("What are your hours", "We're open Monday-Friday, 9 AM to 5 PM.")
        customer_service.add_faq("How do I return", "Returns are accepted within 30 days with receipt.")
        customer_service.add_faq("Shipping cost", "Shipping is free for orders over $50.")
        
        pattern.register_chatbot(customer_service)
        
        booking_bot = Chatbot(
            name="BookingBot",
            domain="restaurant reservations",
            supported_intents=[IntentType.GREETING, IntentType.BOOKING, IntentType.INQUIRY, IntentType.FAREWELL]
        )
        pattern.register_chatbot(booking_bot)
        
        # Run conversations
        print("\n2. Running conversations...")
        
        # Customer service conversation
        cs_conversation = [
            "Hello!",
            "I have a problem with my order",
            "It arrived damaged",
            "Thank you for your help"
        ]
        
        result1 = pattern.run("CustomerServiceBot", cs_conversation)
        
        # Booking conversation
        booking_conversation = [
            "Hi, I'd like to make a reservation",
            "For tomorrow at 7 PM",
            "My email is john@example.com",
            "Yes, please confirm"
        ]
        
        result2 = pattern.run("BookingBot", booking_conversation)
        
        # Print statistics
        print("\n3. Chatbot Statistics:")
        for name, chatbot in pattern.chatbots.items():
            stats = chatbot.get_statistics()
            print(f"\n   {name}:")
            for key, value in stats.items():
                if isinstance(value, float):
                    print(f"      {key}: {value:.3f}")
                elif isinstance(value, dict):
                    print(f"      {key}:")
                    for k, v in value.items():
                        print(f"         {k}: {v}")
                else:
                    print(f"      {key}: {value}")
        
        print("\n✓ Chatbots handled conversations with intent recognition and flow!")
    
        

    Agentic Architecture Pattern: Chatbot

    Pattern 232: 232 Chatbot – Line-by-Line Explanation

    Overview

    Pattern 232: Chatbot

    Purpose: Goal-oriented chatbot with intent recognition, dialogue flow, and response generation. Handles predefined intents, manages conversation state, and provides structured responses.


    Code Structure Analysis

    File Information

    • Pattern Number: 232
    • Pattern Name: 232 Chatbot
    • File Path: patterns\domain_specific\232_chatbot.py
    • Total Lines: 596

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 232: Chatbot
    
    Purpose: Goal-oriented chatbot with intent recognition, dialogue flow, and response generation.
    Handles predefined intents, manages conversation state, and provides structured responses.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 232 Chatbot pattern.


    Imports Section

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

    Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional, Callable: Type hints for better code documentation – from dataclasses import dataclass, field: Data class decorators for clean data structures – from datetime import datetime: Date and time utilities – from enum import Enum: Enumeration support for fixed sets of values – from langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration


    Enumerations

    IntentType (Line 18)

    class IntentType(Enum):
        GREETING
        FAREWELL
        HELP
        FAQ
        BOOKING
        INQUIRY
        COMPLAINT
        FEEDBACK
        CHITCHAT
        UNKNOWN
    

    Purpose: Common chatbot intents.

    Values: – GREETING: Represents greeting – FAREWELL: Represents farewell – HELP: Represents help – FAQ: Represents faq – BOOKING: Represents booking – INQUIRY: Represents inquiry – COMPLAINT: Represents complaint – FEEDBACK: Represents feedback – CHITCHAT: Represents chitchat – UNKNOWN: Represents unknown

    FlowState (Line 32)

    class FlowState(Enum):
        INITIAL
        COLLECTING_INFO
        CONFIRMING
        PROCESSING
        COMPLETED
        ERROR
    

    Purpose: States in conversation flow.

    Values: – INITIAL: Represents initial – COLLECTING_INFO: Represents collecting info – CONFIRMING: Represents confirming – PROCESSING: Represents processing – COMPLETED: Successfully finished – ERROR: Error severity level


    Classes

    IntentType (Line 18)

    Description: Common chatbot intents.

    FlowState (Line 32)

    Description: States in conversation flow.

    Intent (Line 43)

    Description: Recognized user intent.

    Response (Line 52)

    Description: Chatbot response.

    ConversationFlow (Line 62)

    Description: Manages conversation flow state.

    Chatbot (Line 70)

    Description: Chatbot – Goal-oriented dialogue with intent recognition and flow management.

    Features: – Intent recognition with pattern matching – Entity extraction – Dialogue flow management – FAQ handling – Context-aware responses

    Methods:

    __init__ (Line 82)
    def __init__(self, name, domain, supported_intents):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – name: Identifier or label – domain: Parameter for domain – supported_intents: Parameter for supported_intents

    _init_intent_patterns (Line 112)
    def _init_intent_patterns(self):
        """Initialize intent recognition patterns."""
    

    Purpose: Initialize intent recognition patterns.

    Parameters: – self: Instance reference

    _init_response_handlers (Line 153)
    def _init_response_handlers(self):
        """Initialize intent-specific response handlers."""
    

    Purpose: Initialize intent-specific response handlers.

    Parameters: – self: Instance reference

    chat (Line 168)
    def chat(self, user_input):
        """Process user input and generate response."""
    

    Purpose: Process user input and generate response.

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

    _recognize_intent (Line 198)
    def _recognize_intent(self, user_input):
        """Recognize user intent from input."""
    

    Purpose: Recognize user intent from input.

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

    _llm_classify_intent (Line 230)
    def _llm_classify_intent(self, user_input):
        """Use LLM to classify intent when patterns don't match."""
    

    Purpose: Use LLM to classify intent when patterns don’t match.

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

    _extract_entities (Line 253)
    def _extract_entities(self, user_input, intent_type):
        """Extract entities from user input."""
    

    Purpose: Extract entities from user input.

    Parameters: – self: Instance reference – user_input: Parameter for user_input – intent_type: Parameter for intent_type

    _handle_greeting (Line 291)
    def _handle_greeting(self, intent):
        """Handle greeting intent."""
    

    Purpose: Handle greeting intent.

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

    _handle_farewell (Line 306)
    def _handle_farewell(self, intent):
        """Handle farewell intent."""
    

    Purpose: Handle farewell intent.

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

    _handle_help (Line 320)
    def _handle_help(self, intent):
        """Handle help request."""
    

    Purpose: Handle help request.

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

    _handle_faq (Line 337)
    def _handle_faq(self, intent):
        """Handle FAQ query."""
    

    Purpose: Handle FAQ query.

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

    _handle_booking (Line 364)
    def _handle_booking(self, intent):
        """Handle booking request."""
    

    Purpose: Handle booking request.

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

    _handle_inquiry (Line 402)
    def _handle_inquiry(self, intent):
        """Handle general inquiry."""
    

    Purpose: Handle general inquiry.

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

    _handle_complaint (Line 419)
    def _handle_complaint(self, intent):
        """Handle complaint."""
    

    Purpose: Handle complaint.

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

    _handle_feedback (Line 429)
    def _handle_feedback(self, intent):
        """Handle feedback."""
    

    Purpose: Handle feedback.

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

    …and 5 more methods

    ChatbotPattern (Line 484)

    Description: Chatbot Pattern – Manage goal-oriented chatbots.

    Coordinates multiple chatbots for different domains.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register_chatbot (Line 494)
    def register_chatbot(self, chatbot):
        """Register a chatbot."""
    

    Purpose: Register a chatbot.

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

    run (Line 499)
    def run(self, chatbot_name, conversation):
        """Run conversation with chatbot."""
    

    Purpose: Run conversation with chatbot.

    Parameters: – self: Instance reference – chatbot_name: Parameter for chatbot_name – conversation: Parameter for conversation


    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 = IntentType(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: Conversational Agent

    
        """
    Pattern 231: Conversational Agent
    
    Purpose: Engage in natural multi-turn dialogue with context awareness and personality.
    Maintains conversation history, understands context, and provides coherent responses.
    """
    
    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from collections import deque
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
    
    
    class ConversationMode(Enum):
        """Modes of conversation."""
        CASUAL = "casual"  # Friendly, informal chat
        PROFESSIONAL = "professional"  # Formal, business-like
        SUPPORTIVE = "supportive"  # Empathetic, helpful
        EDUCATIONAL = "educational"  # Explanatory, teaching
    
    
    @dataclass
    class Message:
        """A single message in conversation."""
        role: str  # "user" or "assistant"
        content: str
        timestamp: datetime = field(default_factory=datetime.now)
        metadata: Dict[str, Any] = field(default_factory=dict)
    
    
    @dataclass
    class ConversationTurn:
        """A complete turn in the conversation."""
        turn_number: int
        user_message: str
        agent_response: str
        context_used: List[str]
        intent: Optional[str] = None
        sentiment: Optional[str] = None
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class ConversationContext:
        """Context information for conversation."""
        user_name: Optional[str] = None
        user_preferences: Dict[str, Any] = field(default_factory=dict)
        topics_discussed: List[str] = field(default_factory=list)
        current_topic: Optional[str] = None
        conversation_goal: Optional[str] = None
    
    
    class ConversationalAgent:
        """
        Conversational Agent - Natural multi-turn dialogue with context awareness.
        
        Engages in coherent conversations by maintaining history, understanding
        context, adapting tone, and providing relevant responses.
        """
        
        def __init__(self,
                     name: str,
                     personality: str = "helpful and friendly",
                     mode: ConversationMode = ConversationMode.CASUAL,
                     max_history: int = 20):
            self.name = name
            self.personality = personality
            self.mode = mode
            self.max_history = max_history
            self.llm = ChatOpenAI(model="gpt-4", temperature=0.8)
            
            # Conversation state
            self.conversation_history: deque = deque(maxlen=max_history)
            self.turns: List[ConversationTurn] = []
            self.context = ConversationContext()
            self.current_turn = 0
            
            # Statistics
            self.statistics: Dict[str, Any] = {
                "total_turns": 0,
                "total_messages": 0,
                "topics_covered": 0,
                "avg_response_length": 0.0
            }
        
        def converse(self, user_input: str) -> str:
            """Process user input and generate response."""
            self.current_turn += 1
            
            # Add user message to history
            user_msg = Message(role="user", content=user_input)
            self.conversation_history.append(user_msg)
            
            # Analyze input
            intent = self._detect_intent(user_input)
            sentiment = self._detect_sentiment(user_input)
            
            # Extract context
            context_items = self._extract_context(user_input)
            
            # Generate response with context
            response = self._generate_response(user_input, context_items)
            
            # Add assistant message to history
            agent_msg = Message(role="assistant", content=response)
            self.conversation_history.append(agent_msg)
            
            # Record turn
            turn = ConversationTurn(
                turn_number=self.current_turn,
                user_message=user_input,
                agent_response=response,
                context_used=context_items,
                intent=intent,
                sentiment=sentiment
            )
            self.turns.append(turn)
            
            # Update statistics
            self.statistics["total_turns"] = self.current_turn
            self.statistics["total_messages"] = len(self.conversation_history)
            self._update_statistics()
            
            return response
        
        def _detect_intent(self, user_input: str) -> str:
            """Detect user intent from input."""
            user_lower = user_input.lower()
            
            if any(word in user_lower for word in ["?", "what", "how", "why", "when", "where"]):
                return "question"
            elif any(word in user_lower for word in ["please", "can you", "could you", "would you"]):
                return "request"
            elif any(word in user_lower for word in ["thank", "thanks", "appreciate"]):
                return "gratitude"
            elif any(word in user_lower for word in ["hello", "hi", "hey", "greetings"]):
                return "greeting"
            elif any(word in user_lower for word in ["bye", "goodbye", "see you"]):
                return "farewell"
            else:
                return "statement"
        
        def _detect_sentiment(self, user_input: str) -> str:
            """Detect sentiment of user input."""
            user_lower = user_input.lower()
            
            positive_words = ["good", "great", "excellent", "happy", "love", "wonderful"]
            negative_words = ["bad", "terrible", "hate", "sad", "angry", "frustrated"]
            
            positive_count = sum(1 for word in positive_words if word in user_lower)
            negative_count = sum(1 for word in negative_words if word in user_lower)
            
            if positive_count > negative_count:
                return "positive"
            elif negative_count > positive_count:
                return "negative"
            else:
                return "neutral"
        
        def _extract_context(self, user_input: str) -> List[str]:
            """Extract relevant context from conversation history."""
            context_items = []
            
            # Add recent conversation context
            recent_messages = list(self.conversation_history)[-4:]  # Last 2 turns
            if len(recent_messages) > 1:
                context_items.append(f"Recent context: {recent_messages[-2].content[:50]}...")
            
            # Add current topic if set
            if self.context.current_topic:
                context_items.append(f"Current topic: {self.context.current_topic}")
            
            # Add user preferences if relevant
            if self.context.user_preferences:
                context_items.append(f"User preferences: {list(self.context.user_preferences.keys())[:2]}")
            
            return context_items
        
        def _generate_response(self, user_input: str, context_items: List[str]) -> str:
            """Generate contextually appropriate response."""
            # Build conversation history for LLM
            messages = []
            
            # System message with personality and mode
            system_prompt = f"""You are {self.name}, a {self.personality} conversational agent.
    Conversation mode: {self.mode.value}.
    Maintain context awareness and provide coherent, relevant responses.
    Be natural, engaging, and adapt to the user's tone."""
            messages.append(SystemMessage(content=system_prompt))
            
            # Add recent conversation history
            for msg in list(self.conversation_history)[-6:]:  # Last 3 turns
                if msg.role == "user":
                    messages.append(HumanMessage(content=msg.content))
                else:
                    messages.append(AIMessage(content=msg.content))
            
            # Add current user message if not already in history
            if not self.conversation_history or self.conversation_history[-1].content != user_input:
                messages.append(HumanMessage(content=user_input))
            
            # Generate response
            response = self.llm.invoke(messages)
            
            return response.content if hasattr(response, 'content') else str(response)
        
        def set_context(self, key: str, value: Any):
            """Set context information."""
            if key == "user_name":
                self.context.user_name = value
            elif key == "topic":
                self.context.current_topic = value
                if value not in self.context.topics_discussed:
                    self.context.topics_discussed.append(value)
            elif key == "goal":
                self.context.conversation_goal = value
            else:
                self.context.user_preferences[key] = value
            
            print(f"   Context updated: {key} = {value}")
        
        def switch_mode(self, mode: ConversationMode):
            """Switch conversation mode."""
            old_mode = self.mode
            self.mode = mode
            print(f"   Switched from {old_mode.value} to {mode.value} mode")
        
        def get_conversation_summary(self) -> Dict[str, Any]:
            """Get summary of conversation."""
            if not self.turns:
                return {"total_turns": 0}
            
            intents = {}
            sentiments = {}
            for turn in self.turns:
                intents[turn.intent] = intents.get(turn.intent, 0) + 1
                sentiments[turn.sentiment] = sentiments.get(turn.sentiment, 0) + 1
            
            return {
                "total_turns": len(self.turns),
                "topics_discussed": self.context.topics_discussed,
                "intent_distribution": intents,
                "sentiment_distribution": sentiments,
                "current_topic": self.context.current_topic,
                "conversation_mode": self.mode.value
            }
        
        def _update_statistics(self):
            """Update conversation statistics."""
            if self.turns:
                total_length = sum(len(turn.agent_response) for turn in self.turns)
                self.statistics["avg_response_length"] = total_length / len(self.turns)
                self.statistics["topics_covered"] = len(self.context.topics_discussed)
        
        def get_statistics(self) -> Dict[str, Any]:
            """Get comprehensive statistics."""
            return {
                "name": self.name,
                "personality": self.personality,
                "mode": self.mode.value,
                **self.statistics
            }
        
        def reset_conversation(self):
            """Reset conversation state."""
            self.conversation_history.clear()
            self.turns.clear()
            self.context = ConversationContext()
            self.current_turn = 0
            print(f"   Conversation reset for {self.name}")
    
    
    class ConversationalPattern:
        """
        Conversational Pattern - Manage natural dialogue agents.
        
        Coordinates conversational agents for multi-turn interactions.
        """
        
        def __init__(self):
            self.agents: Dict[str, ConversationalAgent] = {}
        
        def register_agent(self, agent: ConversationalAgent):
            """Register conversational agent."""
            self.agents[agent.name] = agent
            print(f"   Registered agent: {agent.name}")
        
        def run(self, agent_name: str, conversation: List[str]) -> Dict[str, Any]:
            """Run conversation with agent."""
            if agent_name not in self.agents:
                return {"error": f"Agent {agent_name} not found"}
            
            agent = self.agents[agent_name]
            responses = []
            
            print(f"\n=== Conversation with {agent_name} ===\n")
            
            for user_input in conversation:
                print(f"User: {user_input}")
                response = agent.converse(user_input)
                print(f"{agent_name}: {response}\n")
                responses.append(response)
            
            summary = agent.get_conversation_summary()
            
            return {
                "agent": agent_name,
                "turns": len(conversation),
                "responses": responses,
                "summary": summary
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Conversational Agent Pattern Demo ===\n")
        
        # Create pattern
        pattern = ConversationalPattern()
        
        # Create conversational agents with different personalities
        print("1. Creating conversational agents...")
        
        friendly_agent = ConversationalAgent(
            name="FriendlyBot",
            personality="warm, empathetic, and encouraging",
            mode=ConversationMode.SUPPORTIVE
        )
        pattern.register_agent(friendly_agent)
        
        professional_agent = ConversationalAgent(
            name="ProfessionalBot",
            personality="professional, concise, and efficient",
            mode=ConversationMode.PROFESSIONAL
        )
        pattern.register_agent(professional_agent)
        
        # Set context
        print("\n2. Setting context...")
        friendly_agent.set_context("user_name", "Alex")
        friendly_agent.set_context("topic", "productivity")
        
        # Run conversations
        print("\n3. Running conversations...")
        
        friendly_conversation = [
            "Hi! I'm feeling a bit overwhelmed with work.",
            "I have so many tasks and don't know where to start.",
            "That's helpful! What about prioritizing them?",
            "Thanks for the advice!"
        ]
        
        result1 = pattern.run("FriendlyBot", friendly_conversation)
        
        professional_conversation = [
            "I need help organizing my project timeline.",
            "The deadline is in 3 weeks.",
            "What's the best approach for risk management?"
        ]
        
        result2 = pattern.run("ProfessionalBot", professional_conversation)
        
        # Print summaries
        print("\n4. Conversation Summaries:")
        for agent_name, agent in pattern.agents.items():
            summary = agent.get_conversation_summary()
            print(f"\n   {agent_name}:")
            print(f"      Total turns: {summary['total_turns']}")
            print(f"      Topics: {summary.get('topics_discussed', [])}")
            print(f"      Intents: {summary.get('intent_distribution', {})}")
            print(f"      Sentiments: {summary.get('sentiment_distribution', {})}")
        
        # Statistics
        print("\n5. Agent Statistics:")
        for agent_name, agent in pattern.agents.items():
            stats = agent.get_statistics()
            print(f"\n   {agent_name}:")
            for key, value in stats.items():
                if isinstance(value, float):
                    print(f"      {key}: {value:.2f}")
                else:
                    print(f"      {key}: {value}")
        
        print("\n✓ Conversational agents engaged in natural dialogue!")
    
        

    Agentic Architecture Pattern: Conversational Agent

    Pattern 231: 231 Conversational Agent – Line-by-Line Explanation

    Overview

    Pattern 231: Conversational Agent

    Purpose: Engage in natural multi-turn dialogue with context awareness and personality. Maintains conversation history, understands context, and provides coherent responses.


    Code Structure Analysis

    File Information

    • Pattern Number: 231
    • Pattern Name: 231 Conversational Agent
    • File Path: patterns\domain_specific\231_conversational_agent.py
    • Total Lines: 389

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 231: Conversational Agent
    
    Purpose: Engage in natural multi-turn dialogue with context awareness and personality.
    Maintains conversation history, understands context, and provides coherent responses.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 231 Conversational Agent pattern.


    Imports Section

    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from collections import deque
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langchain_core.messages import HumanMessage, AIMessage, SystemMessage  # 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 langchain_core.messages import HumanMessage, AIMessage, SystemMessage: LangChain framework integration


    Enumerations

    ConversationMode (Line 18)

    class ConversationMode(Enum):
        CASUAL
        PROFESSIONAL
        SUPPORTIVE
        EDUCATIONAL
    

    Purpose: Modes of conversation.

    Values: – CASUAL: Represents casual – PROFESSIONAL: Represents professional – SUPPORTIVE: Represents supportive – EDUCATIONAL: Represents educational


    Classes

    ConversationMode (Line 18)

    Description: Modes of conversation.

    Message (Line 27)

    Description: A single message in conversation.

    ConversationTurn (Line 36)

    Description: A complete turn in the conversation.

    ConversationContext (Line 48)

    Description: Context information for conversation.

    ConversationalAgent (Line 57)

    Description: Conversational Agent – Natural multi-turn dialogue with context awareness.

    Engages in coherent conversations by maintaining history, understanding context, adapting tone, and providing relevant responses.

    Methods:

    __init__ (Line 65)
    def __init__(self, name, personality, mode, max_history):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – name: Identifier or label – personality: Parameter for personality – mode: Parameter for mode – max_history: Parameter for max_history

    converse (Line 90)
    def converse(self, user_input):
        """Process user input and generate response."""
    

    Purpose: Process user input and generate response.

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

    _detect_intent (Line 130)
    def _detect_intent(self, user_input):
        """Detect user intent from input."""
    

    Purpose: Detect user intent from input.

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

    _detect_sentiment (Line 147)
    def _detect_sentiment(self, user_input):
        """Detect sentiment of user input."""
    

    Purpose: Detect sentiment of user input.

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

    _extract_context (Line 164)
    def _extract_context(self, user_input):
        """Extract relevant context from conversation history."""
    

    Purpose: Extract relevant context from conversation history.

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

    _generate_response (Line 183)
    def _generate_response(self, user_input, context_items):
        """Generate contextually appropriate response."""
    

    Purpose: Generate contextually appropriate response.

    Parameters: – self: Instance reference – user_input: Parameter for user_input – context_items: Parameter for context_items

    set_context (Line 211)
    def set_context(self, key, value):
        """Set context information."""
    

    Purpose: Set context information.

    Parameters: – self: Instance reference – key: Parameter for key – value: Parameter for value

    switch_mode (Line 226)
    def switch_mode(self, mode):
        """Switch conversation mode."""
    

    Purpose: Switch conversation mode.

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

    get_conversation_summary (Line 232)
    def get_conversation_summary(self):
        """Get summary of conversation."""
    

    Purpose: Get summary of conversation.

    Parameters: – self: Instance reference

    _update_statistics (Line 252)
    def _update_statistics(self):
        """Update conversation statistics."""
    

    Purpose: Update conversation statistics.

    Parameters: – self: Instance reference

    get_statistics (Line 259)
    def get_statistics(self):
        """Get comprehensive statistics."""
    

    Purpose: Get comprehensive statistics.

    Parameters: – self: Instance reference

    reset_conversation (Line 268)
    def reset_conversation(self):
        """Reset conversation state."""
    

    Purpose: Reset conversation state.

    Parameters: – self: Instance reference

    ConversationalPattern (Line 277)

    Description: Conversational Pattern – Manage natural dialogue agents.

    Coordinates conversational agents for multi-turn interactions.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register_agent (Line 287)
    def register_agent(self, agent):
        """Register conversational agent."""
    

    Purpose: Register conversational agent.

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

    run (Line 292)
    def run(self, agent_name, conversation):
        """Run conversation with agent."""
    

    Purpose: Run conversation with agent.

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


    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 = ConversationMode(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: Digital Twin

    
        """
    Pattern 230: Digital Twin
    
    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 DigitalTwinConfig:
        """Configuration for Digital Twin."""
        model_name: str = "gpt-4"
        temperature: float = 0.7
        max_iterations: int = 10
        enable_logging: bool = True
    
    
    @dataclass
    class DigitalTwinState:
        """State information for Digital Twin."""
        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 DigitalTwinAgent:
        """Agent implementing Digital Twin."""
        
        def __init__(self, name: str, config: DigitalTwinConfig = None):
            self.name = name
            self.config = config or DigitalTwinConfig()
            self.llm = ChatOpenAI(
                model=self.config.model_name,
                temperature=self.config.temperature
            )
            self.state = DigitalTwinState()
            self.execution_history: List[Dict[str, Any]] = []
        
        def process(self, input_data: Any) -> Dict[str, Any]:
            """Process input according to Digital Twin."""
            self.state.current_step += 1
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, implementing Digital Twin. "
                          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 DigitalTwinPattern:
        """
        Digital Twin - Enhanced implementation
        
        This pattern provides comprehensive functionality for digital twin
        with full LangChain/LangGraph integration.
        
        Features:
        - Multi-agent coordination
        - State management
        - Execution tracking
        - LangGraph workflow integration
        """
        
        def __init__(self, config: DigitalTwinConfig = None):
            self.config = config or DigitalTwinConfig()
            self.agents: Dict[str, DigitalTwinAgent] = {}
            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 Digital Twin. 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: DigitalTwinAgent):
            """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": "Digital Twin",
                    "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": "Digital Twin",
                "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("=== Digital Twin Demo ===\n")
        
        # Create configuration
        config = DigitalTwinConfig(
            model_name="gpt-4",
            temperature=0.7,
            enable_logging=True
        )
        
        # Create pattern
        pattern = DigitalTwinPattern(config)
        
        # Create and register agents
        agent1 = DigitalTwinAgent("Agent1", config)
        agent2 = DigitalTwinAgent("Agent2", config)
        pattern.register_agent(agent1)
        pattern.register_agent(agent2)
        
        print("\nExecuting pattern workflow...")
        
        # Execute with workflow
        result1 = pattern.run("Demonstrate digital twin 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: Digital Twin

    Pattern 230: 230 Digital Twin – Line-by-Line Explanation

    Overview

    Pattern 230: Digital Twin

    Purpose: Enhanced implementation with full LangChain/LangGraph integration


    Code Structure Analysis

    File Information

    • Pattern Number: 230
    • Pattern Name: 230 Digital Twin
    • File Path: patterns\multi_modal\230_digital_twin.py
    • Total Lines: 247

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 230: Digital Twin
    
    Purpose: Enhanced implementation with full LangChain/LangGraph integration
    """
    

    Explanation: This module docstring describes the purpose and key features of the 230 Digital Twin 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

    DigitalTwinConfig (Line 18)

    Description: Configuration for Digital Twin.

    DigitalTwinState (Line 27)

    Description: State information for Digital Twin.

    DigitalTwinAgent (Line 36)

    Description: Agent implementing Digital Twin.

    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 Digital Twin."""
    

    Purpose: Process input according to Digital Twin.

    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

    DigitalTwinPattern (Line 85)

    Description: Digital Twin – Enhanced implementation

    This pattern provides comprehensive functionality for digital twin 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 = DigitalTwinConfig(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: Avatar

    
        """
    Pattern 229: Avatar
    
    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 AvatarConfig:
        """Configuration for Avatar."""
        model_name: str = "gpt-4"
        temperature: float = 0.7
        max_iterations: int = 10
        enable_logging: bool = True
    
    
    @dataclass
    class AvatarState:
        """State information for Avatar."""
        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 AvatarAgent:
        """Agent implementing Avatar."""
        
        def __init__(self, name: str, config: AvatarConfig = None):
            self.name = name
            self.config = config or AvatarConfig()
            self.llm = ChatOpenAI(
                model=self.config.model_name,
                temperature=self.config.temperature
            )
            self.state = AvatarState()
            self.execution_history: List[Dict[str, Any]] = []
        
        def process(self, input_data: Any) -> Dict[str, Any]:
            """Process input according to Avatar."""
            self.state.current_step += 1
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, implementing Avatar. "
                          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 AvatarPattern:
        """
        Avatar - Enhanced implementation
        
        This pattern provides comprehensive functionality for avatar
        with full LangChain/LangGraph integration.
        
        Features:
        - Multi-agent coordination
        - State management
        - Execution tracking
        - LangGraph workflow integration
        """
        
        def __init__(self, config: AvatarConfig = None):
            self.config = config or AvatarConfig()
            self.agents: Dict[str, AvatarAgent] = {}
            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 Avatar. 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: AvatarAgent):
            """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": "Avatar",
                    "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": "Avatar",
                "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("=== Avatar Demo ===\n")
        
        # Create configuration
        config = AvatarConfig(
            model_name="gpt-4",
            temperature=0.7,
            enable_logging=True
        )
        
        # Create pattern
        pattern = AvatarPattern(config)
        
        # Create and register agents
        agent1 = AvatarAgent("Agent1", config)
        agent2 = AvatarAgent("Agent2", config)
        pattern.register_agent(agent1)
        pattern.register_agent(agent2)
        
        print("\nExecuting pattern workflow...")
        
        # Execute with workflow
        result1 = pattern.run("Demonstrate avatar 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: Avatar

    Pattern 229: 229 Avatar – Line-by-Line Explanation

    Overview

    Pattern 229: Avatar

    Purpose: Enhanced implementation with full LangChain/LangGraph integration


    Code Structure Analysis

    File Information

    • Pattern Number: 229
    • Pattern Name: 229 Avatar
    • File Path: patterns\multi_modal\229_avatar.py
    • Total Lines: 247

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 229: Avatar
    
    Purpose: Enhanced implementation with full LangChain/LangGraph integration
    """
    

    Explanation: This module docstring describes the purpose and key features of the 229 Avatar 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

    AvatarConfig (Line 18)

    Description: Configuration for Avatar.

    AvatarState (Line 27)

    Description: State information for Avatar.

    AvatarAgent (Line 36)

    Description: Agent implementing Avatar.

    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 Avatar."""
    

    Purpose: Process input according to Avatar.

    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

    AvatarPattern (Line 85)

    Description: Avatar – Enhanced implementation

    This pattern provides comprehensive functionality for avatar 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 = AvatarConfig(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: Virtual Agent

    
        """
    Pattern 228: Virtual Agent
    
    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 VirtualAgentConfig:
        """Configuration for Virtual Agent."""
        model_name: str = "gpt-4"
        temperature: float = 0.7
        max_iterations: int = 10
        enable_logging: bool = True
    
    
    @dataclass
    class VirtualAgentState:
        """State information for Virtual Agent."""
        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 VirtualAgentAgent:
        """Agent implementing Virtual Agent."""
        
        def __init__(self, name: str, config: VirtualAgentConfig = None):
            self.name = name
            self.config = config or VirtualAgentConfig()
            self.llm = ChatOpenAI(
                model=self.config.model_name,
                temperature=self.config.temperature
            )
            self.state = VirtualAgentState()
            self.execution_history: List[Dict[str, Any]] = []
        
        def process(self, input_data: Any) -> Dict[str, Any]:
            """Process input according to Virtual Agent."""
            self.state.current_step += 1
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, implementing Virtual Agent. "
                          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 VirtualAgentPattern:
        """
        Virtual Agent - Enhanced implementation
        
        This pattern provides comprehensive functionality for virtual agent
        with full LangChain/LangGraph integration.
        
        Features:
        - Multi-agent coordination
        - State management
        - Execution tracking
        - LangGraph workflow integration
        """
        
        def __init__(self, config: VirtualAgentConfig = None):
            self.config = config or VirtualAgentConfig()
            self.agents: Dict[str, VirtualAgentAgent] = {}
            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 Virtual Agent. 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: VirtualAgentAgent):
            """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": "Virtual Agent",
                    "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": "Virtual Agent",
                "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("=== Virtual Agent Demo ===\n")
        
        # Create configuration
        config = VirtualAgentConfig(
            model_name="gpt-4",
            temperature=0.7,
            enable_logging=True
        )
        
        # Create pattern
        pattern = VirtualAgentPattern(config)
        
        # Create and register agents
        agent1 = VirtualAgentAgent("Agent1", config)
        agent2 = VirtualAgentAgent("Agent2", config)
        pattern.register_agent(agent1)
        pattern.register_agent(agent2)
        
        print("\nExecuting pattern workflow...")
        
        # Execute with workflow
        result1 = pattern.run("Demonstrate virtual agent 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: Virtual Agent

    Pattern 228: 228 Virtual Agent – Line-by-Line Explanation

    Overview

    Pattern 228: Virtual Agent

    Purpose: Enhanced implementation with full LangChain/LangGraph integration


    Code Structure Analysis

    File Information

    • Pattern Number: 228
    • Pattern Name: 228 Virtual Agent
    • File Path: patterns\multi_modal\228_virtual_agent.py
    • Total Lines: 247

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 228: Virtual Agent
    
    Purpose: Enhanced implementation with full LangChain/LangGraph integration
    """
    

    Explanation: This module docstring describes the purpose and key features of the 228 Virtual Agent 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

    VirtualAgentConfig (Line 18)

    Description: Configuration for Virtual Agent.

    VirtualAgentState (Line 27)

    Description: State information for Virtual Agent.

    VirtualAgentAgent (Line 36)

    Description: Agent implementing Virtual Agent.

    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 Virtual Agent."""
    

    Purpose: Process input according to Virtual Agent.

    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

    VirtualAgentPattern (Line 85)

    Description: Virtual Agent – Enhanced implementation

    This pattern provides comprehensive functionality for virtual agent 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 = VirtualAgentConfig(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