Tag: architecture

  • Agentic Architecture Pattern: Rag

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

    Pattern 70: 70 Rag – Line-by-Line Explanation

    Overview

    Pattern 70: Rag

    Purpose: Enhanced implementation with full LangChain/LangGraph integration


    Code Structure Analysis

    File Information

    • Pattern Number: 70
    • Pattern Name: 70 Rag
    • File Path: patterns\memory_knowledge\70_rag.py
    • Total Lines: 247

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 70: Rag
    
    Purpose: Enhanced implementation with full LangChain/LangGraph integration
    """
    

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

    RagConfig (Line 18)

    Description: Configuration for Rag.

    RagState (Line 27)

    Description: State information for Rag.

    RagAgent (Line 36)

    Description: Agent implementing Rag.

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

    Purpose: Process input according to Rag.

    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

    RagPattern (Line 85)

    Description: Rag – Enhanced implementation

    This pattern provides comprehensive functionality for rag 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 = RagConfig(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: Vector Store

    
        """
    Pattern 69: Vector Store Pattern
    
    Agents store and retrieve information using vector embeddings and similarity search.
    Enables semantic search: finding similar content based on meaning, not just keywords.
    """
    
    from typing import Dict, Any, List, Optional, Tuple
    from dataclasses import dataclass, field
    from datetime import datetime
    import numpy as np
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI, OpenAIEmbeddings
    from langchain_community.vectorstores import FAISS
    from langchain_core.documents import Document
    
    
    @dataclass
    class VectorDocument:
        """Document with vector embedding."""
        doc_id: str
        content: str
        metadata: Dict[str, Any] = field(default_factory=dict)
        embedding: Optional[List[float]] = None
        created_at: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class SearchResult:
        """Result from vector similarity search."""
        document: VectorDocument
        similarity_score: float
        rank: int
    
    
    class VectorStore:
        """Vector storage with similarity search."""
        
        def __init__(self, embedding_model: str = "text-embedding-ada-002"):
            self.embeddings = OpenAIEmbeddings(model=embedding_model)
            self.documents: Dict[str, VectorDocument] = {}
            self.vector_store: Optional[FAISS] = None
            self.doc_id_to_index: Dict[str, int] = {}
        
        def add_document(self, doc: VectorDocument):
            """Add document to vector store."""
            self.documents[doc.doc_id] = doc
            
            # Create LangChain document
            lc_doc = Document(
                page_content=doc.content,
                metadata={**doc.metadata, "doc_id": doc.doc_id}
            )
            
            # Add to vector store
            if self.vector_store is None:
                self.vector_store = FAISS.from_documents([lc_doc], self.embeddings)
                self.doc_id_to_index[doc.doc_id] = 0
            else:
                # Add to existing store
                new_store = FAISS.from_documents([lc_doc], self.embeddings)
                self.vector_store.merge_from(new_store)
                self.doc_id_to_index[doc.doc_id] = len(self.doc_id_to_index)
        
        def add_documents_batch(self, docs: List[VectorDocument]):
            """Add multiple documents efficiently."""
            for doc in docs:
                self.documents[doc.doc_id] = doc
            
            # Create LangChain documents
            lc_docs = [
                Document(
                    page_content=doc.content,
                    metadata={**doc.metadata, "doc_id": doc.doc_id}
                )
                for doc in docs
            ]
            
            # Create or merge vector store
            if self.vector_store is None:
                self.vector_store = FAISS.from_documents(lc_docs, self.embeddings)
                for i, doc in enumerate(docs):
                    self.doc_id_to_index[doc.doc_id] = i
            else:
                new_store = FAISS.from_documents(lc_docs, self.embeddings)
                self.vector_store.merge_from(new_store)
                start_idx = len(self.doc_id_to_index)
                for i, doc in enumerate(docs):
                    self.doc_id_to_index[doc.doc_id] = start_idx + i
        
        def similarity_search(self, query: str, k: int = 5) -> List[SearchResult]:
            """Search for similar documents."""
            if self.vector_store is None:
                return []
            
            # Perform similarity search
            results = self.vector_store.similarity_search_with_score(query, k=k)
            
            search_results = []
            for rank, (doc, score) in enumerate(results):
                doc_id = doc.metadata.get("doc_id", "")
                if doc_id in self.documents:
                    search_results.append(SearchResult(
                        document=self.documents[doc_id],
                        similarity_score=1.0 / (1.0 + score),  # Convert distance to similarity
                        rank=rank + 1
                    ))
            
            return search_results
        
        def get_document(self, doc_id: str) -> Optional[VectorDocument]:
            """Get document by ID."""
            return self.documents.get(doc_id)
    
    
    class VectorStoreAgent:
        """Agent with vector store for semantic search."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
            self.vector_store = VectorStore()
            self.search_history: List[Tuple[str, List[SearchResult]]] = []
        
        def store_information(self, doc_id: str, content: str, metadata: Optional[Dict[str, Any]] = None):
            """Store information in vector store."""
            doc = VectorDocument(
                doc_id=doc_id,
                content=content,
                metadata=metadata or {}
            )
            self.vector_store.add_document(doc)
            print(f"   šŸ“¦ {self.name} stored: {doc_id} ({len(content)} chars)")
        
        def store_batch(self, documents: List[Tuple[str, str, Optional[Dict[str, Any]]]]):
            """Store multiple documents at once."""
            docs = [
                VectorDocument(doc_id=doc_id, content=content, metadata=metadata or {})
                for doc_id, content, metadata in documents
            ]
            self.vector_store.add_documents_batch(docs)
            print(f"   šŸ“¦ {self.name} stored {len(docs)} documents in batch")
        
        def search(self, query: str, k: int = 3) -> List[SearchResult]:
            """Search for similar content."""
            results = self.vector_store.similarity_search(query, k=k)
            self.search_history.append((query, results))
            
            print(f"   šŸ” {self.name} searched: '{query}' -> {len(results)} results")
            return results
        
        def answer_with_context(self, question: str, k: int = 3) -> str:
            """Answer question using retrieved context."""
            # Search for relevant documents
            results = self.search(question, k=k)
            
            if not results:
                return f"I don't have information to answer: {question}"
            
            # Build context from search results
            context = "\n\n".join([
                f"[{r.rank}] (similarity: {r.similarity_score:.2f})\n{r.document.content}"
                for r in results
            ])
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}. Answer questions based on the provided context."),
                ("human", f"Context from my knowledge base:\n{context}\n\n"
                         f"Question: {question}\n\n"
                         f"Answer based on the context above. If the context doesn't contain "
                         f"relevant information, say so. Keep answer concise (2-3 sentences).")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content)[:400]
    
    
    class VectorStorePattern:
        """
        Vector Store Pattern - Semantic search with embeddings.
        
        Agents store information as vector embeddings and retrieve similar
        content based on semantic meaning rather than keyword matching.
        """
        
        def __init__(self):
            self.agents: Dict[str, VectorStoreAgent] = {}
        
        def register_agent(self, agent: VectorStoreAgent):
            """Register agent with vector store."""
            self.agents[agent.name] = agent
        
        def run(self, scenario: str) -> Dict[str, Any]:
            """Execute vector store pattern."""
            total_docs = sum(len(agent.vector_store.documents) for agent in self.agents.values())
            total_searches = sum(len(agent.search_history) for agent in self.agents.values())
            
            return {
                "pattern": "VectorStore",
                "scenario": scenario,
                "total_agents": len(self.agents),
                "total_documents": total_docs,
                "total_searches": total_searches
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Vector Store Pattern Demo ===\n")
        
        # Create pattern
        pattern = VectorStorePattern()
        
        # Create agent with vector store
        print("1. Creating agent with vector store...")
        agent = VectorStoreAgent("Librarian")
        pattern.register_agent(agent)
        
        # Store documents
        print("\n2. Storing documents in vector store...")
        
        documents = [
            ("doc1", "Machine learning is a subset of artificial intelligence that enables "
                    "computers to learn from data without explicit programming.",
             {"category": "AI", "difficulty": "beginner"}),
            
            ("doc2", "Neural networks are computing systems inspired by biological neural networks. "
                    "They consist of layers of interconnected nodes that process information.",
             {"category": "AI", "difficulty": "intermediate"}),
            
            ("doc3", "Natural language processing (NLP) is a field of AI that focuses on enabling "
                    "computers to understand, interpret, and generate human language.",
             {"category": "AI", "difficulty": "intermediate"}),
            
            ("doc4", "Deep learning uses neural networks with multiple layers to learn hierarchical "
                    "representations of data, achieving state-of-the-art results in many domains.",
             {"category": "AI", "difficulty": "advanced"}),
            
            ("doc5", "Reinforcement learning is a type of machine learning where agents learn to make "
                    "decisions by interacting with an environment and receiving rewards or penalties.",
             {"category": "AI", "difficulty": "advanced"}),
            
            ("doc6", "Computer vision enables machines to interpret and understand visual information "
                    "from the world, including image recognition and object detection.",
             {"category": "AI", "difficulty": "intermediate"}),
        ]
        
        agent.store_batch(documents)
        
        # Semantic similarity search
        print("\n3. Performing semantic similarity searches...")
        
        queries = [
            "How do computers learn?",
            "What are artificial brains?",
            "Understanding human language with AI",
            "Learning through trial and error"
        ]
        
        for query in queries:
            print(f"\n   Query: '{query}'")
            results = agent.search(query, k=2)
            for result in results:
                print(f"   [{result.rank}] Similarity: {result.similarity_score:.3f}")
                print(f"       {result.document.content[:80]}...")
                print(f"       Category: {result.document.metadata.get('category')}, "
                      f"Difficulty: {result.document.metadata.get('difficulty')}")
        
        # Question answering with context
        print("\n4. Answering questions using retrieved context...")
        
        questions = [
            "What is machine learning?",
            "How do neural networks work?",
            "What's the difference between deep learning and machine learning?",
            "What can computer vision do?"
        ]
        
        for question in questions:
            print(f"\n   Q: {question}")
            answer = agent.answer_with_context(question, k=3)
            print(f"   A: {answer}")
        
        # Statistics
        print("\n5. Vector Store Statistics:")
        summary = pattern.run("AI Knowledge Base")
        print(f"   Total Documents: {summary['total_documents']}")
        print(f"   Total Searches: {summary['total_searches']}")
        
        # Search history analysis
        print("\n6. Search History:")
        for i, (query, results) in enumerate(agent.search_history[:3], 1):
            print(f"   {i}. '{query}' -> {len(results)} results")
            if results:
                best = results[0]
                print(f"      Best match: {best.document.doc_id} (similarity: {best.similarity_score:.3f})")
        
        print("\nāœ“ Vector store pattern enabled semantic search!")
    
        

    Agentic Architecture Pattern: Vector Store

    Pattern 69: 69 Vector Store – Line-by-Line Explanation

    Overview

    Pattern 69: Vector Store Pattern

    Agents store and retrieve information using vector embeddings and similarity search. Enables semantic search: finding similar content based on meaning, not just keywords.


    Code Structure Analysis

    File Information

    • Pattern Number: 69
    • Pattern Name: 69 Vector Store
    • File Path: patterns\memory_knowledge\69_vector_store.py
    • Total Lines: 301

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 69: Vector Store Pattern
    
    Agents store and retrieve information using vector embeddings and similarity search.
    Enables semantic search: finding similar content based on meaning, not just keywords.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 69 Vector Store pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Tuple
    from dataclasses import dataclass, field
    from datetime import datetime
    import numpy as np
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI, OpenAIEmbeddings
    from langchain_community.vectorstores import FAISS
    from langchain_core.documents import Document  # First 20 imports shown
    

    Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional, Tuple: Type hints for better code documentation – from dataclasses import dataclass, field: Data class decorators for clean data structures – from datetime import datetime: Date and time utilities – from langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI, OpenAIEmbeddings: LangChain framework integration – from langchain_community.vectorstores import FAISS: LangChain framework integration – from langchain_core.documents import Document: LangChain framework integration


    Classes

    VectorDocument (Line 19)

    Description: Document with vector embedding.

    SearchResult (Line 29)

    Description: Result from vector similarity search.

    VectorStore (Line 36)

    Description: Vector storage with similarity search.

    Methods:

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

    Purpose: No method docstring.

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

    add_document (Line 45)
    def add_document(self, doc):
        """Add document to vector store."""
    

    Purpose: Add document to vector store.

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

    add_documents_batch (Line 65)
    def add_documents_batch(self, docs):
        """Add multiple documents efficiently."""
    

    Purpose: Add multiple documents efficiently.

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

    similarity_search (Line 91)
    def similarity_search(self, query, k):
        """Search for similar documents."""
    

    Purpose: Search for similar documents.

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

    get_document (Line 111)
    def get_document(self, doc_id):
        """Get document by ID."""
    

    Purpose: Get document by ID.

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

    VectorStoreAgent (Line 116)

    Description: Agent with vector store for semantic search.

    Methods:

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

    Purpose: No method docstring.

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

    store_information (Line 125)
    def store_information(self, doc_id, content, metadata):
        """Store information in vector store."""
    

    Purpose: Store information in vector store.

    Parameters: – self: Instance reference – doc_id: Parameter for doc_id – content: Parameter for content – metadata: Parameter for metadata

    store_batch (Line 135)
    def store_batch(self, documents):
        """Store multiple documents at once."""
    

    Purpose: Store multiple documents at once.

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

    search (Line 144)
    def search(self, query, k):
        """Search for similar content."""
    

    Purpose: Search for similar content.

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

    answer_with_context (Line 152)
    def answer_with_context(self, question, k):
        """Answer question using retrieved context."""
    

    Purpose: Answer question using retrieved context.

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

    VectorStorePattern (Line 180)

    Description: Vector Store Pattern – Semantic search with embeddings.

    Agents store information as vector embeddings and retrieve similar content based on semantic meaning rather than keyword matching.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register_agent (Line 191)
    def register_agent(self, agent):
        """Register agent with vector store."""
    

    Purpose: Register agent with vector store.

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

    run (Line 195)
    def run(self, scenario):
        """Execute vector store pattern."""
    

    Purpose: Execute vector store pattern.

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


    Design Patterns Used

    • Strategy Pattern: Different execution strategies for various scenarios
    • State Pattern: Managing different states in the workflow
    • Chain of Responsibility: Sequential processing through workflow nodes
    • Observer Pattern: Tracking and monitoring pattern execution
    • Factory Pattern: Creating instances with proper configuration

    Usage Example

    # Initialize the pattern
    pattern = VectorDocument(name="example", model_name="gpt-4")
    
    # Configure and execute
    result = pattern.execute(data={"key": "value"})
    
    # Check results
    print(result)
    

    Key Concepts

    • LLM Integration: Uses LangChain/OpenAI for intelligent decision-making
    • Workflow Orchestration: LangGraph manages execution flow through nodes
    • State Management: TypedDict defines workflow state structure
    • Error Handling: Comprehensive error handling and fallback mechanisms
    • Extensibility: Designed for easy customization and extension

    Extension Points

    This pattern can be extended by: 1. Adding custom workflow nodes 2. Implementing additional validation logic 3. Integrating with external services 4. Customizing LLM prompts and responses 5. Adding monitoring and logging capabilities

  • Agentic Architecture Pattern: Graph Based Knowledge

    
        """
    Pattern 68: Graph-Based Knowledge Pattern
    
    Agents store knowledge as a graph with nodes (entities) and edges (relationships).
    Enables path finding, traversal, and graph-based reasoning.
    """
    
    from typing import Dict, Any, List, Optional, Set, Tuple
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class NodeType(Enum):
        """Type of knowledge graph node."""
        ENTITY = "entity"
        CONCEPT = "concept"
        EVENT = "event"
        ATTRIBUTE = "attribute"
    
    
    @dataclass
    class GraphNode:
        """Node in knowledge graph."""
        node_id: str
        node_type: NodeType
        label: str
        properties: Dict[str, Any] = field(default_factory=dict)
        created_at: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class GraphEdge:
        """Edge in knowledge graph."""
        edge_id: str
        source_id: str
        target_id: str
        relationship: str
        weight: float = 1.0
        properties: Dict[str, Any] = field(default_factory=dict)
        created_at: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class GraphPath:
        """Path through knowledge graph."""
        nodes: List[str]
        edges: List[str]
        total_weight: float
        path_length: int
    
    
    class KnowledgeGraph:
        """Graph-based knowledge storage with traversal."""
        
        def __init__(self):
            self.nodes: Dict[str, GraphNode] = {}
            self.edges: Dict[str, GraphEdge] = {}
            self.adjacency: Dict[str, Set[str]] = {}  # node_id -> {edge_ids}
        
        def add_node(self, node: GraphNode):
            """Add node to graph."""
            self.nodes[node.node_id] = node
            if node.node_id not in self.adjacency:
                self.adjacency[node.node_id] = set()
        
        def add_edge(self, edge: GraphEdge):
            """Add edge to graph."""
            self.edges[edge.edge_id] = edge
            
            # Update adjacency
            if edge.source_id not in self.adjacency:
                self.adjacency[edge.source_id] = set()
            self.adjacency[edge.source_id].add(edge.edge_id)
        
        def get_neighbors(self, node_id: str) -> List[Tuple[GraphNode, GraphEdge]]:
            """Get neighboring nodes and connecting edges."""
            neighbors = []
            
            if node_id not in self.adjacency:
                return neighbors
            
            for edge_id in self.adjacency[node_id]:
                edge = self.edges.get(edge_id)
                if edge:
                    target_node = self.nodes.get(edge.target_id)
                    if target_node:
                        neighbors.append((target_node, edge))
            
            return neighbors
        
        def find_path(self, start_id: str, end_id: str, 
                      max_depth: int = 5) -> Optional[GraphPath]:
            """Find path between two nodes using BFS."""
            if start_id not in self.nodes or end_id not in self.nodes:
                return None
            
            # BFS
            queue = [(start_id, [start_id], [], 0.0)]
            visited = {start_id}
            
            while queue:
                current_id, path_nodes, path_edges, total_weight = queue.pop(0)
                
                if current_id == end_id:
                    return GraphPath(
                        nodes=path_nodes,
                        edges=path_edges,
                        total_weight=total_weight,
                        path_length=len(path_nodes) - 1
                    )
                
                if len(path_nodes) >= max_depth:
                    continue
                
                # Explore neighbors
                for neighbor, edge in self.get_neighbors(current_id):
                    if neighbor.node_id not in visited:
                        visited.add(neighbor.node_id)
                        queue.append((
                            neighbor.node_id,
                            path_nodes + [neighbor.node_id],
                            path_edges + [edge.edge_id],
                            total_weight + edge.weight
                        ))
            
            return None
        
        def find_nodes_by_type(self, node_type: NodeType) -> List[GraphNode]:
            """Find all nodes of a specific type."""
            return [node for node in self.nodes.values() 
                    if node.node_type == node_type]
        
        def find_related(self, node_id: str, relationship: str) -> List[GraphNode]:
            """Find nodes related by specific relationship."""
            related = []
            
            if node_id not in self.adjacency:
                return related
            
            for edge_id in self.adjacency[node_id]:
                edge = self.edges.get(edge_id)
                if edge and edge.relationship == relationship:
                    target = self.nodes.get(edge.target_id)
                    if target:
                        related.append(target)
            
            return related
        
        def get_subgraph(self, node_id: str, depth: int = 2) -> Tuple[Set[str], Set[str]]:
            """Get subgraph around a node."""
            nodes = {node_id}
            edges = set()
            
            queue = [(node_id, 0)]
            visited = {node_id}
            
            while queue:
                current_id, current_depth = queue.pop(0)
                
                if current_depth >= depth:
                    continue
                
                for neighbor, edge in self.get_neighbors(current_id):
                    edges.add(edge.edge_id)
                    if neighbor.node_id not in visited:
                        visited.add(neighbor.node_id)
                        nodes.add(neighbor.node_id)
                        queue.append((neighbor.node_id, current_depth + 1))
            
            return nodes, edges
    
    
    class GraphKnowledgeAgent:
        """Agent with graph-based knowledge representation."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.3)
            self.graph = KnowledgeGraph()
        
        def learn_entity(self, entity_id: str, label: str, 
                         properties: Optional[Dict[str, Any]] = None):
            """Learn about an entity."""
            node = GraphNode(
                node_id=entity_id,
                node_type=NodeType.ENTITY,
                label=label,
                properties=properties or {}
            )
            self.graph.add_node(node)
            print(f"   šŸ”· {self.name} learned entity: {label}")
        
        def learn_relationship(self, source_id: str, target_id: str, 
                              relationship: str, weight: float = 1.0):
            """Learn a relationship between entities."""
            edge_id = f"{source_id}_{relationship}_{target_id}"
            edge = GraphEdge(
                edge_id=edge_id,
                source_id=source_id,
                target_id=target_id,
                relationship=relationship,
                weight=weight
            )
            self.graph.add_edge(edge)
            print(f"   šŸ”— {self.name} learned: {source_id} --{relationship}-> {target_id}")
        
        def query_relationship(self, entity_id: str, relationship: str) -> str:
            """Query relationships from an entity."""
            related = self.graph.find_related(entity_id, relationship)
            
            if not related:
                return f"No {relationship} relationships found for {entity_id}."
            
            entity = self.graph.nodes.get(entity_id)
            entity_label = entity.label if entity else entity_id
            
            related_labels = [node.label for node in related]
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name} with graph-based knowledge."),
                ("human", f"Entity: {entity_label}\n"
                         f"Relationship: {relationship}\n"
                         f"Related entities: {', '.join(related_labels)}\n\n"
                         f"Provide a natural language summary of this relationship. (1-2 sentences)")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content)[:200]
        
        def find_connection(self, entity1_id: str, entity2_id: str) -> str:
            """Find how two entities are connected."""
            path = self.graph.find_path(entity1_id, entity2_id)
            
            if not path:
                return f"No connection found between {entity1_id} and {entity2_id}."
            
            # Build path description
            path_desc = []
            for i in range(len(path.nodes) - 1):
                node1 = self.graph.nodes.get(path.nodes[i])
                node2 = self.graph.nodes.get(path.nodes[i + 1])
                edge = self.graph.edges.get(path.edges[i])
                
                if node1 and node2 and edge:
                    path_desc.append(f"{node1.label} --{edge.relationship}-> {node2.label}")
            
            return f"Path: {' → '.join(path_desc)} (length: {path.path_length}, weight: {path.total_weight:.1f})"
    
    
    class GraphBasedKnowledgePattern:
        """
        Graph-Based Knowledge Pattern - Knowledge as graph structures.
        
        Agents represent knowledge as nodes and edges, enabling graph
        traversal, path finding, and relationship-based reasoning.
        """
        
        def __init__(self):
            self.agents: Dict[str, GraphKnowledgeAgent] = {}
        
        def register_agent(self, agent: GraphKnowledgeAgent):
            """Register agent with graph knowledge."""
            self.agents[agent.name] = agent
        
        def run(self, domain: str) -> Dict[str, Any]:
            """Execute graph knowledge pattern."""
            total_nodes = sum(len(agent.graph.nodes) for agent in self.agents.values())
            total_edges = sum(len(agent.graph.edges) for agent in self.agents.values())
            
            return {
                "pattern": "GraphBasedKnowledge",
                "domain": domain,
                "total_agents": len(self.agents),
                "total_nodes": total_nodes,
                "total_edges": total_edges
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Graph-Based Knowledge Pattern Demo ===\n")
        
        # Create pattern
        pattern = GraphBasedKnowledgePattern()
        
        # Create agent with graph knowledge
        print("1. Creating agent with graph knowledge...")
        agent = GraphKnowledgeAgent("Scholar")
        pattern.register_agent(agent)
        
        # Build knowledge graph about a company
        print("\n2. Building knowledge graph...")
        
        # Entities
        agent.learn_entity("company", "TechCorp", {"type": "company", "founded": 2010})
        agent.learn_entity("ceo", "Alice Johnson", {"role": "CEO"})
        agent.learn_entity("cto", "Bob Smith", {"role": "CTO"})
        agent.learn_entity("product1", "CloudApp", {"category": "SaaS"})
        agent.learn_entity("product2", "DataPlatform", {"category": "Analytics"})
        agent.learn_entity("customer1", "Acme Corp", {"type": "enterprise"})
        agent.learn_entity("tech1", "Python", {"type": "language"})
        agent.learn_entity("tech2", "Kubernetes", {"type": "platform"})
        
        # Relationships
        print("\n3. Adding relationships...")
        agent.learn_relationship("ceo", "company", "leads", 1.0)
        agent.learn_relationship("cto", "company", "works_for", 1.0)
        agent.learn_relationship("cto", "ceo", "reports_to", 1.0)
        agent.learn_relationship("company", "product1", "develops", 1.0)
        agent.learn_relationship("company", "product2", "develops", 1.0)
        agent.learn_relationship("customer1", "product1", "uses", 1.0)
        agent.learn_relationship("product1", "tech1", "built_with", 1.0)
        agent.learn_relationship("product2", "tech1", "built_with", 1.0)
        agent.learn_relationship("product2", "tech2", "deployed_on", 1.0)
        
        # Query relationships
        print("\n4. Querying relationships...")
        summary = agent.query_relationship("company", "develops")
        print(f"   {summary}")
        
        summary = agent.query_relationship("product1", "built_with")
        print(f"   {summary}")
        
        # Find connections
        print("\n5. Finding connections between entities...")
        connections = [
            ("customer1", "tech1"),
            ("cto", "customer1"),
            ("tech2", "ceo")
        ]
        
        for entity1, entity2 in connections:
            print(f"\n   Connection: {entity1}  {entity2}")
            result = agent.find_connection(entity1, entity2)
            print(f"   {result}")
        
        # Explore subgraph
        print("\n6. Exploring subgraph around 'company'...")
        nodes, edges = agent.graph.get_subgraph("company", depth=2)
        print(f"   Nodes in subgraph: {len(nodes)}")
        print(f"   Edges in subgraph: {len(edges)}")
        
        node_labels = [agent.graph.nodes[nid].label for nid in nodes if nid in agent.graph.nodes]
        print(f"   Entities: {', '.join(node_labels)}")
        
        # Find by type
        print("\n7. Finding entities by type...")
        entities = agent.graph.find_nodes_by_type(NodeType.ENTITY)
        print(f"   Total entities: {len(entities)}")
        for entity in entities[:5]:
            print(f"   - {entity.label} ({entity.properties.get('type', 'N/A')})")
        
        # Statistics
        print("\n8. Graph Statistics:")
        summary = pattern.run("Company Knowledge")
        print(f"   Total Nodes: {summary['total_nodes']}")
        print(f"   Total Edges: {summary['total_edges']}")
        print(f"   Avg connections per node: {summary['total_edges'] / max(1, summary['total_nodes']):.1f}")
        
        # Analyze graph structure
        print("\n9. Graph Structure Analysis:")
        node_degrees = {}
        for node_id in agent.graph.nodes:
            degree = len(agent.graph.adjacency.get(node_id, set()))
            node_degrees[node_id] = degree
        
        if node_degrees:
            max_degree = max(node_degrees.values())
            central_nodes = [nid for nid, deg in node_degrees.items() if deg == max_degree]
            print(f"   Max node degree: {max_degree}")
            print(f"   Most connected: {[agent.graph.nodes[nid].label for nid in central_nodes]}")
        
        print("\nāœ“ Graph-based knowledge pattern enabled relationship reasoning!")
    
        

    Agentic Architecture Pattern: Graph Based Knowledge

    Pattern 68: 68 Graph Based Knowledge – Line-by-Line Explanation

    Overview

    Pattern 68: Graph-Based Knowledge Pattern

    Agents store knowledge as a graph with nodes (entities) and edges (relationships). Enables path finding, traversal, and graph-based reasoning.


    Code Structure Analysis

    File Information

    • Pattern Number: 68
    • Pattern Name: 68 Graph Based Knowledge
    • File Path: patterns\memory_knowledge\68_graph_based_knowledge.py
    • Total Lines: 379

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 68: Graph-Based Knowledge Pattern
    
    Agents store knowledge as a graph with nodes (entities) and edges (relationships).
    Enables path finding, traversal, and graph-based reasoning.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 68 Graph Based Knowledge pattern.


    Imports Section

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

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

    NodeType (Line 16)

    class NodeType(Enum):
        ENTITY
        CONCEPT
        EVENT
        ATTRIBUTE
    

    Purpose: Type of knowledge graph node.

    Values: – ENTITY: Represents entity – CONCEPT: Represents concept – EVENT: Represents event – ATTRIBUTE: Represents attribute


    Classes

    NodeType (Line 16)

    Description: Type of knowledge graph node.

    GraphNode (Line 25)

    Description: Node in knowledge graph.

    GraphEdge (Line 35)

    Description: Edge in knowledge graph.

    GraphPath (Line 47)

    Description: Path through knowledge graph.

    KnowledgeGraph (Line 55)

    Description: Graph-based knowledge storage with traversal.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    add_node (Line 63)
    def add_node(self, node):
        """Add node to graph."""
    

    Purpose: Add node to graph.

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

    add_edge (Line 69)
    def add_edge(self, edge):
        """Add edge to graph."""
    

    Purpose: Add edge to graph.

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

    get_neighbors (Line 78)
    def get_neighbors(self, node_id):
        """Get neighboring nodes and connecting edges."""
    

    Purpose: Get neighboring nodes and connecting edges.

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

    find_path (Line 94)
    def find_path(self, start_id, end_id, max_depth):
        """Find path between two nodes using BFS."""
    

    Purpose: Find path between two nodes using BFS.

    Parameters: – self: Instance reference – start_id: Parameter for start_id – end_id: Parameter for end_id – max_depth: Parameter for max_depth

    find_nodes_by_type (Line 131)
    def find_nodes_by_type(self, node_type):
        """Find all nodes of a specific type."""
    

    Purpose: Find all nodes of a specific type.

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

    find_related (Line 136)
    def find_related(self, node_id, relationship):
        """Find nodes related by specific relationship."""
    

    Purpose: Find nodes related by specific relationship.

    Parameters: – self: Instance reference – node_id: Parameter for node_id – relationship: Parameter for relationship

    get_subgraph (Line 152)
    def get_subgraph(self, node_id, depth):
        """Get subgraph around a node."""
    

    Purpose: Get subgraph around a node.

    Parameters: – self: Instance reference – node_id: Parameter for node_id – depth: Parameter for depth

    GraphKnowledgeAgent (Line 176)

    Description: Agent with graph-based knowledge representation.

    Methods:

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

    Purpose: No method docstring.

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

    learn_entity (Line 184)
    def learn_entity(self, entity_id, label, properties):
        """Learn about an entity."""
    

    Purpose: Learn about an entity.

    Parameters: – self: Instance reference – entity_id: Parameter for entity_id – label: Parameter for label – properties: Parameter for properties

    learn_relationship (Line 196)
    def learn_relationship(self, source_id, target_id, relationship, weight):
        """Learn a relationship between entities."""
    

    Purpose: Learn a relationship between entities.

    Parameters: – self: Instance reference – source_id: Parameter for source_id – target_id: Parameter for target_id – relationship: Parameter for relationship – weight: Parameter for weight

    query_relationship (Line 210)
    def query_relationship(self, entity_id, relationship):
        """Query relationships from an entity."""
    

    Purpose: Query relationships from an entity.

    Parameters: – self: Instance reference – entity_id: Parameter for entity_id – relationship: Parameter for relationship

    find_connection (Line 235)
    def find_connection(self, entity1_id, entity2_id):
        """Find how two entities are connected."""
    

    Purpose: Find how two entities are connected.

    Parameters: – self: Instance reference – entity1_id: Parameter for entity1_id – entity2_id: Parameter for entity2_id

    GraphBasedKnowledgePattern (Line 255)

    Description: Graph-Based Knowledge Pattern – Knowledge as graph structures.

    Agents represent knowledge as nodes and edges, enabling graph traversal, path finding, and relationship-based reasoning.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register_agent (Line 266)
    def register_agent(self, agent):
        """Register agent with graph knowledge."""
    

    Purpose: Register agent with graph knowledge.

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

    run (Line 270)
    def run(self, domain):
        """Execute graph knowledge pattern."""
    

    Purpose: Execute graph knowledge pattern.

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


    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 = NodeType(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: Ontology Based

    
        """
    Pattern 67: Ontology-Based Pattern
    
    Formal knowledge representation using ontologies with classes, properties, relationships,
    inheritance, and logical reasoning capabilities.
    """
    
    from typing import Dict, Any, List, Set, Optional, Tuple
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class PropertyType(Enum):
        """Types of ontology properties."""
        DATA_PROPERTY = "data_property"  # Property with literal value
        OBJECT_PROPERTY = "object_property"  # Property relating to another entity
        FUNCTIONAL = "functional"  # Has exactly one value
        TRANSITIVE = "transitive"  # If A->B and B->C then A->C
        SYMMETRIC = "symmetric"  # If A->B then B->A
    
    
    @dataclass
    class OntologyProperty:
        """A property definition in ontology."""
        name: str
        property_type: PropertyType
        domain: Optional[str] = None  # Which class it belongs to
        range: Optional[str] = None  # What type of value it has
        restrictions: Dict[str, Any] = field(default_factory=dict)
    
    
    @dataclass
    class OntologyClass:
        """A class in the ontology."""
        name: str
        parent: Optional[str] = None
        properties: Dict[str, OntologyProperty] = field(default_factory=dict)
        instances: Set[str] = field(default_factory=set)
        constraints: List[str] = field(default_factory=list)
        
        def get_all_properties(self, ontology: 'OntologyBasedPattern') -> Dict[str, OntologyProperty]:
            """Get all properties including inherited ones."""
            props = dict(self.properties)
            
            # Add parent properties
            if self.parent and self.parent in ontology.classes:
                parent_class = ontology.classes[self.parent]
                parent_props = parent_class.get_all_properties(ontology)
                # Parent properties come first (can be overridden)
                for name, prop in parent_props.items():
                    if name not in props:
                        props[name] = prop
            
            return props
    
    
    @dataclass
    class OntologyRelation:
        """A relationship between entities."""
        subject: str
        predicate: str
        object: str
        properties: Dict[str, Any] = field(default_factory=dict)
        timestamp: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class OntologyInstance:
        """An instance of an ontology class."""
        name: str
        class_name: str
        properties: Dict[str, Any] = field(default_factory=dict)
        relations: List[OntologyRelation] = field(default_factory=list)
    
    
    class OntologyReasoner:
        """Reasoning engine for ontology."""
        
        def __init__(self, ontology: 'OntologyBasedPattern'):
            self.ontology = ontology
            self.llm = ontology.llm
        
        def is_subclass_of(self, child: str, parent: str) -> bool:
            """Check if child is a subclass of parent."""
            if child == parent:
                return True
            
            if child not in self.ontology.classes:
                return False
            
            current = self.ontology.classes[child]
            while current.parent:
                if current.parent == parent:
                    return True
                if current.parent not in self.ontology.classes:
                    break
                current = self.ontology.classes[current.parent]
            
            return False
        
        def is_instance_of(self, instance_name: str, class_name: str) -> bool:
            """Check if instance is of given class (including subclasses)."""
            if instance_name not in self.ontology.instances:
                return False
            
            instance = self.ontology.instances[instance_name]
            return self.is_subclass_of(instance.class_name, class_name)
        
        def infer_transitive_relations(self, predicate: str) -> List[OntologyRelation]:
            """Infer transitive relations (if A->B and B->C then A->C)."""
            # Find property definition
            prop = None
            for onto_class in self.ontology.classes.values():
                if predicate in onto_class.properties:
                    prop = onto_class.properties[predicate]
                    break
            
            if not prop or prop.property_type != PropertyType.TRANSITIVE:
                return []
            
            # Build relation map
            relations_map: Dict[str, List[str]] = {}
            for rel in self.ontology.relations:
                if rel.predicate == predicate:
                    if rel.subject not in relations_map:
                        relations_map[rel.subject] = []
                    relations_map[rel.subject].append(rel.object)
            
            # Infer transitive closures
            inferred = []
            for start, targets in relations_map.items():
                visited = set()
                queue = list(targets)
                
                while queue:
                    current = queue.pop(0)
                    if current in visited:
                        continue
                    visited.add(current)
                    
                    # Add inferred relation
                    if current not in targets:  # Not direct relation
                        inferred.append(OntologyRelation(
                            subject=start,
                            predicate=predicate,
                            object=current,
                            properties={"inferred": True, "type": "transitive"}
                        ))
                    
                    # Add next level
                    if current in relations_map:
                        queue.extend(relations_map[current])
            
            return inferred
        
        def query_with_reasoning(self, query: str) -> str:
            """Answer query using ontology reasoning."""
            # Get ontology context
            context_parts = [
                "Ontology Classes:",
                *[f"- {name}: {cls.parent or 'root'}" for name, cls in self.ontology.classes.items()],
                "\nInstances:",
                *[f"- {inst.name} (type: {inst.class_name})" for inst in self.ontology.instances.values()],
                "\nRelations:",
                *[f"- {rel.subject} {rel.predicate} {rel.object}" for rel in self.ontology.relations[:20]]
            ]
            
            context = "\n".join(context_parts)
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", "You are an ontology reasoning expert. Use the ontology structure to answer questions."),
                ("human", f"Ontology:\n{context}\n\nQuery: {query}\n\nProvide a reasoned answer based on the ontology.")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content)
    
    
    class OntologyBasedPattern:
        """
        Ontology-Based Pattern - Formal knowledge representation with reasoning.
        
        Provides structured knowledge representation using classes, properties,
        instances, and relationships with inheritance and logical inference.
        """
        
        def __init__(self, model_name: str = "gpt-4"):
            self.llm = ChatOpenAI(model=model_name, temperature=0.2)
            self.classes: Dict[str, OntologyClass] = {}
            self.relations: List[OntologyRelation] = []
            self.instances: Dict[str, OntologyInstance] = {}
            self.reasoner = OntologyReasoner(self)
        
        def add_class(self, name: str, parent: Optional[str] = None, 
                      properties: Optional[Dict[str, OntologyProperty]] = None,
                      constraints: Optional[List[str]] = None):
            """Add a class to ontology."""
            onto_class = OntologyClass(
                name=name,
                parent=parent,
                properties=properties or {},
                constraints=constraints or []
            )
            self.classes[name] = onto_class
            print(f"šŸ“š Class added: {name}" + (f" (extends {parent})" if parent else ""))
        
        def add_instance(self, class_name: str, instance_name: str, properties: Optional[Dict[str, Any]] = None):
            """Add an instance of a class."""
            if class_name not in self.classes:
                raise ValueError(f"Class {class_name} not found in ontology")
            
            instance = OntologyInstance(
                name=instance_name,
                class_name=class_name,
                properties=properties or {}
            )
            
            self.classes[class_name].instances.add(instance_name)
            self.instances[instance_name] = instance
            print(f"āž• Instance added: {instance_name} of class {class_name}")
        
        def add_relation(self, subject: str, predicate: str, obj: str):
            """Add a relation between entities."""
            relation = OntologyRelation(subject, predicate, obj)
            self.relations.append(relation)
            print(f"šŸ”— Relation: {subject} {predicate} {obj}")
        
        def query(self, question: str) -> str:
            """Query the ontology using natural language."""
            ontology_desc = self._describe_ontology()
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", """You are an ontology reasoner. Use the ontology to answer questions.
    
    Ontology:
    {ontology}"""),
                ("human", "{question}")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({
                "ontology": ontology_desc,
                "question": question
            })
            
            return str(response.content)
        
        def _describe_ontology(self) -> str:
            """Describe the ontology structure."""
            desc = []
            desc.append("Classes:")
            for name, cls in self.classes.items():
                parent_info = f" extends {cls.parent}" if cls.parent else ""
                desc.append(f"  - {name}{parent_info}")
                if cls.properties:
                    desc.append(f"    Properties: {list(cls.properties.keys())}")
            
            desc.append("\nInstances:")
            for inst_name, inst_data in self.instances.items():
                desc.append(f"  - {inst_name}: {inst_data.class_name}")
            
            desc.append("\nRelations:")
            for rel in self.relations:
                desc.append(f"  - {rel.subject} {rel.predicate} {rel.object}")
            
            return "\n".join(desc)
        
        def run(self, queries: List[str]) -> Dict[str, Any]:
            """Run queries against the ontology."""
            results = []
            for query in queries:
                answer = self.query(query)
                results.append({"query": query, "answer": answer})
            
            return {
                "ontology_stats": {
                    "classes": len(self.classes),
                    "instances": len(self.instances),
                    "relations": len(self.relations)
                },
                "queries": results
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("\n=== Ontology-Based Pattern Example ===")
        
        onto = OntologyBasedPattern()
        
        # Build ontology
        onto.add_class("Animal")
        onto.add_class("Mammal", parent="Animal")
        onto.add_class("Bird", parent="Animal")
        onto.add_class("Dog", parent="Mammal")
        onto.add_class("Cat", parent="Mammal")
        
        # Add instances
        onto.add_instance("Dog", "Buddy", {"age": 5, "breed": "Golden Retriever"})
        onto.add_instance("Cat", "Whiskers", {"age": 3, "breed": "Siamese"})
        onto.add_instance("Bird", "Tweety", {"species": "Canary"})
        
        # Add relations
        onto.add_relation("Buddy", "likes", "playing fetch")
        onto.add_relation("Whiskers", "likes", "sleeping")
        onto.add_relation("Dog", "is_a", "Mammal")
        
        # Query
        queries = [
            "What animals are mammals?",
            "Tell me about Buddy",
            "What properties do mammals have?"
        ]
        
        result = onto.run(queries)
        
        print("\n=== Results ===")
        print(f"Ontology: {result['ontology_stats']}")
        print("\nQuery Results:")
        for q in result['queries']:
            print(f"\nQ: {q['query']}")
            print(f"A: {q['answer']}")
    
        

    Agentic Architecture Pattern: Ontology Based

    Pattern 67: 67 Ontology Based – Line-by-Line Explanation

    Overview

    Pattern 67: Ontology-Based Pattern

    Formal knowledge representation using ontologies with classes, properties, relationships, inheritance, and logical reasoning capabilities.


    Code Structure Analysis

    File Information

    • Pattern Number: 67
    • Pattern Name: 67 Ontology Based
    • File Path: patterns\memory_knowledge\67_ontology_based.py
    • Total Lines: 328

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 67: Ontology-Based Pattern
    
    Formal knowledge representation using ontologies with classes, properties, relationships,
    inheritance, and logical reasoning capabilities.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 67 Ontology Based pattern.


    Imports Section

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

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

    PropertyType (Line 16)

    class PropertyType(Enum):
        DATA_PROPERTY
        OBJECT_PROPERTY
        FUNCTIONAL
        TRANSITIVE
        SYMMETRIC
    

    Purpose: Types of ontology properties.

    Values: – DATA_PROPERTY: Represents data property – OBJECT_PROPERTY: Represents object property – FUNCTIONAL: Represents functional – TRANSITIVE: Represents transitive – SYMMETRIC: Represents symmetric


    Classes

    PropertyType (Line 16)

    Description: Types of ontology properties.

    OntologyProperty (Line 26)

    Description: A property definition in ontology.

    OntologyClass (Line 36)

    Description: A class in the ontology.

    Methods:

    get_all_properties (Line 44)
    def get_all_properties(self, ontology):
        """Get all properties including inherited ones."""
    

    Purpose: Get all properties including inherited ones.

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

    OntologyRelation (Line 61)

    Description: A relationship between entities.

    OntologyInstance (Line 71)

    Description: An instance of an ontology class.

    OntologyReasoner (Line 79)

    Description: Reasoning engine for ontology.

    Methods:

    __init__ (Line 82)
    def __init__(self, ontology):
        """No method docstring."""
    

    Purpose: No method docstring.

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

    is_subclass_of (Line 86)
    def is_subclass_of(self, child, parent):
        """Check if child is a subclass of parent."""
    

    Purpose: Check if child is a subclass of parent.

    Parameters: – self: Instance reference – child: Parameter for child – parent: Parameter for parent

    is_instance_of (Line 104)
    def is_instance_of(self, instance_name, class_name):
        """Check if instance is of given class (including subclasses)."""
    

    Purpose: Check if instance is of given class (including subclasses).

    Parameters: – self: Instance reference – instance_name: Parameter for instance_name – class_name: Parameter for class_name

    infer_transitive_relations (Line 112)
    def infer_transitive_relations(self, predicate):
        """Infer transitive relations (if A->B and B->C then A->C)."""
    

    Purpose: Infer transitive relations (if A->B and B->C then A->C).

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

    query_with_reasoning (Line 159)
    def query_with_reasoning(self, query):
        """Answer query using ontology reasoning."""
    

    Purpose: Answer query using ontology reasoning.

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

    OntologyBasedPattern (Line 184)

    Description: Ontology-Based Pattern – Formal knowledge representation with reasoning.

    Provides structured knowledge representation using classes, properties, instances, and relationships with inheritance and logical inference.

    Methods:

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

    Purpose: No method docstring.

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

    add_class (Line 199)
    def add_class(self, name, parent, properties, constraints):
        """Add a class to ontology."""
    

    Purpose: Add a class to ontology.

    Parameters: – self: Instance reference – name: Identifier or label – parent: Parameter for parent – properties: Parameter for properties – constraints: Parameter for constraints

    add_instance (Line 212)
    def add_instance(self, class_name, instance_name, properties):
        """Add an instance of a class."""
    

    Purpose: Add an instance of a class.

    Parameters: – self: Instance reference – class_name: Parameter for class_name – instance_name: Parameter for instance_name – properties: Parameter for properties

    add_relation (Line 227)
    def add_relation(self, subject, predicate, obj):
        """Add a relation between entities."""
    

    Purpose: Add a relation between entities.

    Parameters: – self: Instance reference – subject: Parameter for subject – predicate: Parameter for predicate – obj: Parameter for obj

    query (Line 233)
    def query(self, question):
        """Query the ontology using natural language."""
    

    Purpose: Query the ontology using natural language.

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

    _describe_ontology (Line 253)
    def _describe_ontology(self):
        """Describe the ontology structure."""
    

    Purpose: Describe the ontology structure.

    Parameters: – self: Instance reference

    run (Line 273)
    def run(self, queries):
        """Run queries against the ontology."""
    

    Purpose: Run queries against the ontology.

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


    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 = PropertyType(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: Knowledge Base

    
        """
    Pattern 66: Knowledge Base Pattern
    
    Agents maintain structured knowledge about the world, rules, facts, and relationships.
    Supports querying, inference, and reasoning over stored knowledge.
    """
    
    from typing import Dict, Any, List, Optional, Set
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class FactType(Enum):
        """Type of knowledge fact."""
        ENTITY = "entity"
        RELATION = "relation"
        RULE = "rule"
        CONCEPT = "concept"
        PROCEDURE = "procedure"
    
    
    class ConfidenceLevel(Enum):
        """Confidence in knowledge."""
        CERTAIN = 1.0
        HIGH = 0.8
        MEDIUM = 0.5
        LOW = 0.3
        UNCERTAIN = 0.1
    
    
    @dataclass
    class Fact:
        """Knowledge fact with metadata."""
        fact_id: str
        fact_type: FactType
        subject: str
        predicate: str
        object: str
        confidence: float = 1.0
        source: Optional[str] = None
        timestamp: datetime = field(default_factory=datetime.now)
        tags: List[str] = field(default_factory=list)
    
    
    @dataclass
    class Rule:
        """Logical rule for inference."""
        rule_id: str
        name: str
        conditions: List[str]  # IF conditions
        conclusion: str  # THEN conclusion
        confidence: float = 1.0
        description: Optional[str] = None
    
    
    @dataclass
    class Query:
        """Knowledge base query."""
        query_id: str
        question: str
        query_type: str  # "fact", "inference", "explanation"
        results: List[Fact] = field(default_factory=list)
        inferred_facts: List[Fact] = field(default_factory=list)
        explanation: Optional[str] = None
    
    
    class KnowledgeBase:
        """Structured knowledge storage with reasoning."""
        
        def __init__(self, name: str):
            self.name = name
            self.facts: Dict[str, Fact] = {}
            self.rules: Dict[str, Rule] = {}
            self.indexes: Dict[str, Set[str]] = {
                "subject": {},
                "predicate": {},
                "object": {}
            }
        
        def add_fact(self, fact: Fact):
            """Add fact to knowledge base."""
            self.facts[fact.fact_id] = fact
            
            # Update indexes
            for index_type in ["subject", "predicate", "object"]:
                value = getattr(fact, index_type)
                if value not in self.indexes[index_type]:
                    self.indexes[index_type][value] = set()
                self.indexes[index_type][value].add(fact.fact_id)
        
        def add_rule(self, rule: Rule):
            """Add inference rule."""
            self.rules[rule.rule_id] = rule
        
        def query_facts(self, subject: Optional[str] = None, 
                       predicate: Optional[str] = None,
                       object: Optional[str] = None) -> List[Fact]:
            """Query facts by subject, predicate, or object."""
            result_ids = None
            
            if subject:
                result_ids = self.indexes["subject"].get(subject, set())
            if predicate:
                pred_ids = self.indexes["predicate"].get(predicate, set())
                result_ids = result_ids & pred_ids if result_ids else pred_ids
            if object:
                obj_ids = self.indexes["object"].get(object, set())
                result_ids = result_ids & obj_ids if result_ids else obj_ids
            
            if result_ids is None:
                return list(self.facts.values())
            
            return [self.facts[fid] for fid in result_ids if fid in self.facts]
        
        def apply_rules(self) -> List[Fact]:
            """Apply inference rules to derive new facts."""
            inferred = []
            
            for rule in self.rules.values():
                # Simple rule matching (can be extended)
                conditions_met = True
                
                for condition in rule.conditions:
                    # Parse condition: "subject predicate object"
                    parts = condition.split()
                    if len(parts) >= 3:
                        matching_facts = self.query_facts(
                            subject=parts[0] if parts[0] != "?" else None,
                            predicate=parts[1] if parts[1] != "?" else None,
                            object=parts[2] if parts[2] != "?" else None
                        )
                        if not matching_facts:
                            conditions_met = False
                            break
                
                if conditions_met:
                    # Create inferred fact from conclusion
                    parts = rule.conclusion.split()
                    if len(parts) >= 3:
                        inferred_fact = Fact(
                            fact_id=f"inferred_{rule.rule_id}_{len(inferred)}",
                            fact_type=FactType.RELATION,
                            subject=parts[0],
                            predicate=parts[1],
                            object=parts[2],
                            confidence=rule.confidence,
                            source=f"rule:{rule.rule_id}"
                        )
                        inferred.append(inferred_fact)
            
            return inferred
    
    
    class KnowledgeAgent:
        """Agent with knowledge base and reasoning capabilities."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.3)
            self.kb = KnowledgeBase(f"{name}_kb")
            self.queries: List[Query] = []
        
        def learn_fact(self, subject: str, predicate: str, object: str, 
                       fact_type: FactType = FactType.RELATION,
                       confidence: float = 1.0):
            """Learn new fact."""
            fact = Fact(
                fact_id=f"fact_{len(self.kb.facts)}",
                fact_type=fact_type,
                subject=subject,
                predicate=predicate,
                object=object,
                confidence=confidence,
                source=self.name
            )
            self.kb.add_fact(fact)
            print(f"   šŸ“š {self.name} learned: {subject} {predicate} {object}")
        
        def answer_query(self, question: str) -> Query:
            """Answer question using knowledge base and LLM."""
            # First, try direct fact lookup
            facts_text = "\n".join([
                f"- {f.subject} {f.predicate} {f.object} (confidence: {f.confidence:.2f})"
                for f in self.kb.facts.values()
            ])
            
            # Apply inference rules
            inferred = self.kb.apply_rules()
            inferred_text = "\n".join([
                f"- {f.subject} {f.predicate} {f.object} (inferred, confidence: {f.confidence:.2f})"
                for f in inferred
            ]) if inferred else "None"
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, an AI agent with a knowledge base. "
                          f"Answer questions based on your knowledge and reasoning."),
                ("human", f"Known facts:\n{facts_text}\n\n"
                         f"Inferred facts:\n{inferred_text}\n\n"
                         f"Question: {question}\n\n"
                         f"Provide a clear answer based on the facts and inferences. "
                         f"If you need to infer something, explain your reasoning.")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            query = Query(
                query_id=f"q{len(self.queries)}",
                question=question,
                query_type="inference",
                inferred_facts=inferred,
                explanation=str(response.content)
            )
            
            self.queries.append(query)
            return query
    
    
    class KnowledgeBasePattern:
        """
        Knowledge Base Pattern - Structured knowledge with reasoning.
        
        Agents maintain facts, rules, and relationships, enabling them to
        answer questions through direct lookup and logical inference.
        """
        
        def __init__(self):
            self.agents: Dict[str, KnowledgeAgent] = {}
        
        def register_agent(self, agent: KnowledgeAgent):
            """Register agent with knowledge base."""
            self.agents[agent.name] = agent
        
        def share_knowledge(self, source_agent: str, target_agent: str, fact: Fact):
            """Share knowledge between agents."""
            if source_agent in self.agents and target_agent in self.agents:
                self.agents[target_agent].kb.add_fact(fact)
        
        def run(self, domain: str) -> Dict[str, Any]:
            """Execute knowledge base pattern."""
            total_facts = sum(len(agent.kb.facts) for agent in self.agents.values())
            total_rules = sum(len(agent.kb.rules) for agent in self.agents.values())
            total_queries = sum(len(agent.queries) for agent in self.agents.values())
            
            return {
                "pattern": "KnowledgeBase",
                "domain": domain,
                "total_agents": len(self.agents),
                "total_facts": total_facts,
                "total_rules": total_rules,
                "total_queries": total_queries
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Knowledge Base Pattern Demo ===\n")
        
        # Create pattern
        pattern = KnowledgeBasePattern()
        
        # Create agent with knowledge base
        print("1. Creating agent with knowledge base...")
        agent = KnowledgeAgent("Scholar")
        pattern.register_agent(agent)
        
        # Learn facts about programming languages
        print("\n2. Learning facts about programming...")
        agent.learn_fact("Python", "is_a", "programming_language", FactType.CONCEPT)
        agent.learn_fact("Python", "has_feature", "dynamic_typing", FactType.RELATION)
        agent.learn_fact("Python", "used_for", "data_science", FactType.RELATION)
        agent.learn_fact("Python", "used_for", "web_development", FactType.RELATION)
        agent.learn_fact("JavaScript", "is_a", "programming_language", FactType.CONCEPT)
        agent.learn_fact("JavaScript", "used_for", "web_development", FactType.RELATION)
        agent.learn_fact("TypeScript", "extends", "JavaScript", FactType.RELATION)
        agent.learn_fact("TypeScript", "has_feature", "static_typing", FactType.RELATION)
        
        # Add inference rules
        print("\n3. Adding inference rules...")
        rule1 = Rule(
            rule_id="rule1",
            name="Inheritance",
            conditions=["TypeScript extends JavaScript", "JavaScript used_for web_development"],
            conclusion="TypeScript used_for web_development",
            confidence=0.95,
            description="If A extends B, and B is used for X, then A is used for X"
        )
        agent.kb.add_rule(rule1)
        print(f"   āš™ļø Added rule: {rule1.name}")
        
        # Query knowledge base
        print("\n4. Querying knowledge base...")
        
        # Direct queries
        print("\n   Direct fact lookup:")
        python_facts = agent.kb.query_facts(subject="Python")
        for fact in python_facts:
            print(f"   - {fact.subject} {fact.predicate} {fact.object}")
        
        web_dev_facts = agent.kb.query_facts(predicate="used_for", object="web_development")
        print(f"\n   Languages used for web development: {len(web_dev_facts)}")
        for fact in web_dev_facts:
            print(f"   - {fact.subject}")
        
        # Natural language queries
        print("\n5. Answering natural language questions...")
        questions = [
            "What is Python used for?",
            "Which programming languages support web development?",
            "What are the differences between Python and TypeScript?",
            "Can TypeScript be used for web development?"
        ]
        
        for question in questions:
            print(f"\n   Q: {question}")
            query = agent.answer_query(question)
            print(f"   A: {query.explanation[:200]}...")
            if query.inferred_facts:
                print(f"   Inferred: {len(query.inferred_facts)} new facts")
        
        # Knowledge statistics
        print("\n6. Knowledge Base Statistics:")
        summary = pattern.run("Programming Languages")
        print(f"   Total Facts: {summary['total_facts']}")
        print(f"   Total Rules: {summary['total_rules']}")
        print(f"   Total Queries: {summary['total_queries']}")
        
        # Show knowledge graph structure
        print("\n7. Knowledge Graph:")
        subjects = set(f.subject for f in agent.kb.facts.values())
        predicates = set(f.predicate for f in agent.kb.facts.values())
        print(f"   Entities: {len(subjects)}")
        print(f"   Relation types: {len(predicates)}")
        print(f"   Predicates: {', '.join(sorted(predicates))}")
        
        print("\nāœ“ Knowledge base pattern enabled structured reasoning!")
    
        

    Agentic Architecture Pattern: Knowledge Base

    Pattern 66: 66 Knowledge Base – Line-by-Line Explanation

    Overview

    Pattern 66: Knowledge Base Pattern

    Agents maintain structured knowledge about the world, rules, facts, and relationships. Supports querying, inference, and reasoning over stored knowledge.


    Code Structure Analysis

    File Information

    • Pattern Number: 66
    • Pattern Name: 66 Knowledge Base
    • File Path: patterns\memory_knowledge\66_knowledge_base.py
    • Total Lines: 340

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 66: Knowledge Base Pattern
    
    Agents maintain structured knowledge about the world, rules, facts, and relationships.
    Supports querying, inference, and reasoning over stored knowledge.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 66 Knowledge Base pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Set
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI  # 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

    FactType (Line 16)

    class FactType(Enum):
        ENTITY
        RELATION
        RULE
        CONCEPT
        PROCEDURE
    

    Purpose: Type of knowledge fact.

    Values: – ENTITY: Represents entity – RELATION: Represents relation – RULE: Represents rule – CONCEPT: Represents concept – PROCEDURE: Represents procedure

    ConfidenceLevel (Line 25)

    class ConfidenceLevel(Enum):
        CERTAIN
        HIGH
        MEDIUM
        LOW
        UNCERTAIN
    

    Purpose: Confidence in knowledge.

    Values: – CERTAIN: Represents certain – HIGH: Represents high – MEDIUM: Represents medium – LOW: Represents low – UNCERTAIN: Represents uncertain


    Classes

    FactType (Line 16)

    Description: Type of knowledge fact.

    ConfidenceLevel (Line 25)

    Description: Confidence in knowledge.

    Fact (Line 35)

    Description: Knowledge fact with metadata.

    Rule (Line 49)

    Description: Logical rule for inference.

    Query (Line 60)

    Description: Knowledge base query.

    KnowledgeBase (Line 70)

    Description: Structured knowledge storage with reasoning.

    Methods:

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

    Purpose: No method docstring.

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

    add_fact (Line 83)
    def add_fact(self, fact):
        """Add fact to knowledge base."""
    

    Purpose: Add fact to knowledge base.

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

    add_rule (Line 94)
    def add_rule(self, rule):
        """Add inference rule."""
    

    Purpose: Add inference rule.

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

    query_facts (Line 98)
    def query_facts(self, subject, predicate, object):
        """Query facts by subject, predicate, or object."""
    

    Purpose: Query facts by subject, predicate, or object.

    Parameters: – self: Instance reference – subject: Parameter for subject – predicate: Parameter for predicate – object: Parameter for object

    apply_rules (Line 118)
    def apply_rules(self):
        """Apply inference rules to derive new facts."""
    

    Purpose: Apply inference rules to derive new facts.

    Parameters: – self: Instance reference

    KnowledgeAgent (Line 157)

    Description: Agent with knowledge base and reasoning capabilities.

    Methods:

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

    Purpose: No method docstring.

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

    learn_fact (Line 166)
    def learn_fact(self, subject, predicate, object, fact_type, confidence):
        """Learn new fact."""
    

    Purpose: Learn new fact.

    Parameters: – self: Instance reference – subject: Parameter for subject – predicate: Parameter for predicate – object: Parameter for object – fact_type: Parameter for fact_type – confidence: Parameter for confidence

    answer_query (Line 182)
    def answer_query(self, question):
        """Answer question using knowledge base and LLM."""
    

    Purpose: Answer question using knowledge base and LLM.

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

    KnowledgeBasePattern (Line 222)

    Description: Knowledge Base Pattern – Structured knowledge with reasoning.

    Agents maintain facts, rules, and relationships, enabling them to answer questions through direct lookup and logical inference.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register_agent (Line 233)
    def register_agent(self, agent):
        """Register agent with knowledge base."""
    

    Purpose: Register agent with knowledge base.

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

    share_knowledge (Line 237)
    def share_knowledge(self, source_agent, target_agent, fact):
        """Share knowledge between agents."""
    

    Purpose: Share knowledge between agents.

    Parameters: – self: Instance reference – source_agent: Parameter for source_agent – target_agent: Parameter for target_agent – fact: Parameter for fact

    run (Line 242)
    def run(self, domain):
        """Execute knowledge base pattern."""
    

    Purpose: Execute knowledge base pattern.

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


    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 = FactType(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: Short Term Memory

    
        """
    Pattern 65: Short-Term Memory Pattern
    
    Agents maintain temporary memory with rapid decay for immediate task context.
    Holds information briefly (seconds to minutes) for active use.
    """
    
    from typing import Dict, Any, List, Optional, Deque
    from dataclasses import dataclass, field
    from datetime import datetime, timedelta
    from collections import deque
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    @dataclass
    class ShortTermItem:
        """Item in short-term memory with automatic decay."""
        item_id: str
        content: Any
        created_at: datetime = field(default_factory=datetime.now)
        ttl_seconds: float = 30.0  # Time to live in seconds
        access_count: int = 0
        
        def is_expired(self) -> bool:
            """Check if item has expired."""
            age = (datetime.now() - self.created_at).total_seconds()
            return age > self.ttl_seconds
        
        def time_remaining(self) -> float:
            """Get remaining time before expiration."""
            age = (datetime.now() - self.created_at).total_seconds()
            return max(0, self.ttl_seconds - age)
    
    
    class ShortTermMemory:
        """
        Short-term memory with rapid decay and limited retention.
        """
        
        def __init__(self, capacity: int = 7, default_ttl: float = 30.0):
            self.capacity = capacity
            self.default_ttl = default_ttl
            self.items: Dict[str, ShortTermItem] = {}
            self.access_log: Deque[str] = deque(maxlen=100)
        
        def store(self, item_id: str, content: Any, ttl: Optional[float] = None):
            """Store item in short-term memory."""
            # Clean expired items first
            self._clean_expired()
            
            # Check capacity
            if len(self.items) >= self.capacity and item_id not in self.items:
                self._evict_oldest()
            
            # Store item
            item = ShortTermItem(
                item_id=item_id,
                content=content,
                ttl_seconds=ttl if ttl is not None else self.default_ttl
            )
            self.items[item_id] = item
            self.access_log.append(f"store:{item_id}")
        
        def retrieve(self, item_id: str) -> Optional[Any]:
            """Retrieve item from short-term memory."""
            # Clean expired items
            self._clean_expired()
            
            if item_id not in self.items:
                self.access_log.append(f"miss:{item_id}")
                return None
            
            item = self.items[item_id]
            
            if item.is_expired():
                del self.items[item_id]
                self.access_log.append(f"expired:{item_id}")
                return None
            
            item.access_count += 1
            self.access_log.append(f"hit:{item_id}")
            return item.content
        
        def _clean_expired(self):
            """Remove expired items."""
            expired = [iid for iid, item in self.items.items() if item.is_expired()]
            for iid in expired:
                del self.items[iid]
        
        def _evict_oldest(self):
            """Evict oldest item."""
            if not self.items:
                return
            
            oldest_id = min(self.items.keys(), 
                           key=lambda k: self.items[k].created_at)
            del self.items[oldest_id]
            self.access_log.append(f"evict:{oldest_id}")
        
        def get_active_items(self) -> List[ShortTermItem]:
            """Get all non-expired items."""
            self._clean_expired()
            return list(self.items.values())
        
        def clear(self):
            """Clear all short-term memory."""
            self.items.clear()
            self.access_log.append("clear:all")
    
    
    class ShortTermMemoryAgent:
        """Agent with short-term memory for immediate context."""
        
        def __init__(self, name: str, memory_capacity: int = 5, 
                     default_ttl: float = 30.0, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
            self.stm = ShortTermMemory(capacity=memory_capacity, default_ttl=default_ttl)
            self.conversation_buffer: Deque[str] = deque(maxlen=10)
        
        def note(self, key: str, value: Any, ttl: Optional[float] = None):
            """Quickly note something in short-term memory."""
            self.stm.store(key, value, ttl)
            print(f"   šŸ“ {self.name} noted: {key} (expires in {ttl or self.stm.default_ttl}s)")
        
        def remember(self, key: str) -> Optional[Any]:
            """Try to remember from short-term memory."""
            value = self.stm.retrieve(key)
            if value:
                item = self.stm.items.get(key)
                remaining = item.time_remaining() if item else 0
                print(f"   āœ“ {self.name} remembered: {key} ({remaining:.1f}s remaining)")
            else:
                print(f"   āœ— {self.name} forgot: {key} (expired or not found)")
            return value
        
        def process_immediate_context(self, input_text: str) -> str:
            """Process input with immediate short-term memory context."""
            # Store input in conversation buffer
            self.conversation_buffer.append(f"Input: {input_text}")
            
            # Get active memory items
            active_items = self.stm.get_active_items()
            
            if not active_items:
                context = "No immediate context in short-term memory."
            else:
                context = "\n".join([
                    f"- {item.item_id}: {item.content} ({item.time_remaining():.1f}s left)"
                    for item in sorted(active_items, 
                                      key=lambda x: x.time_remaining(), 
                                      reverse=True)
                ])
            
            # Recent conversation
            recent_conv = "\n".join(list(self.conversation_buffer)[-3:])
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}. You have short-term memory for immediate context. "
                          f"Memory items decay quickly (within seconds)."),
                ("human", f"Short-term memory:\n{context}\n\n"
                         f"Recent conversation:\n{recent_conv}\n\n"
                         f"Current input: {input_text}\n\n"
                         f"Respond briefly (1-2 sentences) using your short-term memory.")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            response_text = str(response.content)[:200]
            self.conversation_buffer.append(f"Response: {response_text}")
            
            return response_text
    
    
    class ShortTermMemoryPattern:
        """
        Short-Term Memory Pattern - Temporary rapid-decay memory.
        
        Agents hold information briefly for immediate use, with automatic
        expiration and capacity limits mimicking human short-term memory.
        """
        
        def __init__(self):
            self.agents: Dict[str, ShortTermMemoryAgent] = {}
        
        def register_agent(self, agent: ShortTermMemoryAgent):
            """Register agent with short-term memory."""
            self.agents[agent.name] = agent
        
        def run(self, scenario: str) -> Dict[str, Any]:
            """Execute short-term memory pattern."""
            total_items = sum(len(agent.stm.items) for agent in self.agents.values())
            total_accesses = sum(len(agent.stm.access_log) for agent in self.agents.values())
            
            return {
                "pattern": "ShortTermMemory",
                "scenario": scenario,
                "total_agents": len(self.agents),
                "active_items": total_items,
                "total_accesses": total_accesses
            }
    
    
    # Example usage
    if __name__ == "__main__":
        import time
        
        print("=== Short-Term Memory Pattern Demo ===\n")
        
        # Create pattern
        pattern = ShortTermMemoryPattern()
        
        # Create agent with short-term memory (30 second TTL)
        print("1. Creating agent with short-term memory...")
        agent = ShortTermMemoryAgent("Alice", memory_capacity=5, default_ttl=15.0)
        pattern.register_agent(agent)
        
        # Store items with different TTLs
        print("\n2. Storing items in short-term memory...")
        agent.note("customer_name", "John Doe", ttl=20.0)
        agent.note("order_number", "ORD-12345", ttl=15.0)
        agent.note("total_amount", "$125.50", ttl=10.0)
        agent.note("shipping_address", "123 Main St", ttl=15.0)
        
        # Immediate recall
        print("\n3. Immediate recall (should work)...")
        agent.remember("customer_name")
        agent.remember("order_number")
        
        # Check active items
        print("\n4. Active items in short-term memory:")
        active = agent.stm.get_active_items()
        for item in sorted(active, key=lambda x: x.time_remaining(), reverse=True):
            print(f"   - {item.item_id}: {item.time_remaining():.1f}s remaining")
        
        # Wait a bit
        print("\n5. Waiting 8 seconds...")
        time.sleep(8)
        
        # Try to recall again
        print("\n6. Recall after 8 seconds...")
        agent.remember("customer_name")  # Should still work (20s TTL)
        agent.remember("total_amount")  # May be expired (10s TTL)
        
        # Process with context
        print("\n7. Processing with short-term memory context...")
        queries = [
            "What's the customer's name?",
            "What's the order total?",
            "Where should we ship it?"
        ]
        
        for query in queries:
            print(f"\n   Q: {query}")
            response = agent.process_immediate_context(query)
            print(f"   A: {response}")
            time.sleep(2)  # Brief pause between queries
        
        # Wait for more expiration
        print("\n8. Waiting 10 more seconds for memory decay...")
        time.sleep(10)
        
        # Try to recall again
        print("\n9. Recall after total 18 seconds...")
        agent.remember("customer_name")  # May be expired
        agent.remember("order_number")  # Likely expired
        
        # Check what's left
        print("\n10. Remaining items in short-term memory:")
        remaining = agent.stm.get_active_items()
        if remaining:
            for item in remaining:
                print(f"   - {item.item_id}: {item.time_remaining():.1f}s remaining")
        else:
            print("   (No items remaining - all expired)")
        
        # Statistics
        print("\n11. Memory Statistics:")
        summary = pattern.run("Customer order processing")
        print(f"   Active items: {summary['active_items']}")
        print(f"   Total accesses: {summary['total_accesses']}")
        
        # Access log analysis
        log = list(agent.stm.access_log)
        hit_count = sum(1 for entry in log if entry.startswith("hit:"))
        miss_count = sum(1 for entry in log if entry.startswith("miss:"))
        expired_count = sum(1 for entry in log if entry.startswith("expired:"))
        
        print(f"\n12. Access Log Analysis:")
        print(f"   Hits: {hit_count}")
        print(f"   Misses: {miss_count}")
        print(f"   Expired: {expired_count}")
        if hit_count + miss_count > 0:
            hit_rate = hit_count / (hit_count + miss_count) * 100
            print(f"   Hit rate: {hit_rate:.1f}%")
        
        print("\nāœ“ Short-term memory pattern demonstrated rapid decay!")
    
        

    Agentic Architecture Pattern: Short Term Memory

    Pattern 65: 65 Short Term Memory – Line-by-Line Explanation

    Overview

    Pattern 65: Short-Term Memory Pattern

    Agents maintain temporary memory with rapid decay for immediate task context. Holds information briefly (seconds to minutes) for active use.


    Code Structure Analysis

    File Information

    • Pattern Number: 65
    • Pattern Name: 65 Short Term Memory
    • File Path: patterns\memory_knowledge\65_short_term_memory.py
    • Total Lines: 300

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 65: Short-Term Memory Pattern
    
    Agents maintain temporary memory with rapid decay for immediate task context.
    Holds information briefly (seconds to minutes) for active use.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 65 Short Term Memory pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Deque
    from dataclasses import dataclass, field
    from datetime import datetime, timedelta
    from collections import deque
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
        import time  # First 20 imports shown
    

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


    Classes

    ShortTermItem (Line 17)

    Description: Item in short-term memory with automatic decay.

    Methods:

    is_expired (Line 25)
    def is_expired(self):
        """Check if item has expired."""
    

    Purpose: Check if item has expired.

    Parameters: – self: Instance reference

    time_remaining (Line 30)
    def time_remaining(self):
        """Get remaining time before expiration."""
    

    Purpose: Get remaining time before expiration.

    Parameters: – self: Instance reference

    ShortTermMemory (Line 36)

    Description: Short-term memory with rapid decay and limited retention.

    Methods:

    __init__ (Line 41)
    def __init__(self, capacity, default_ttl):
        """No method docstring."""
    

    Purpose: No method docstring.

    Parameters: – self: Instance reference – capacity: Parameter for capacity – default_ttl: Parameter for default_ttl

    store (Line 47)
    def store(self, item_id, content, ttl):
        """Store item in short-term memory."""
    

    Purpose: Store item in short-term memory.

    Parameters: – self: Instance reference – item_id: Parameter for item_id – content: Parameter for content – ttl: Parameter for ttl

    retrieve (Line 65)
    def retrieve(self, item_id):
        """Retrieve item from short-term memory."""
    

    Purpose: Retrieve item from short-term memory.

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

    _clean_expired (Line 85)
    def _clean_expired(self):
        """Remove expired items."""
    

    Purpose: Remove expired items.

    Parameters: – self: Instance reference

    _evict_oldest (Line 91)
    def _evict_oldest(self):
        """Evict oldest item."""
    

    Purpose: Evict oldest item.

    Parameters: – self: Instance reference

    get_active_items (Line 101)
    def get_active_items(self):
        """Get all non-expired items."""
    

    Purpose: Get all non-expired items.

    Parameters: – self: Instance reference

    clear (Line 106)
    def clear(self):
        """Clear all short-term memory."""
    

    Purpose: Clear all short-term memory.

    Parameters: – self: Instance reference

    ShortTermMemoryAgent (Line 112)

    Description: Agent with short-term memory for immediate context.

    Methods:

    __init__ (Line 115)
    def __init__(self, name, memory_capacity, default_ttl, model_name):
        """No method docstring."""
    

    Purpose: No method docstring.

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

    note (Line 122)
    def note(self, key, value, ttl):
        """Quickly note something in short-term memory."""
    

    Purpose: Quickly note something in short-term memory.

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

    remember (Line 127)
    def remember(self, key):
        """Try to remember from short-term memory."""
    

    Purpose: Try to remember from short-term memory.

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

    process_immediate_context (Line 138)
    def process_immediate_context(self, input_text):
        """Process input with immediate short-term memory context."""
    

    Purpose: Process input with immediate short-term memory context.

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

    ShortTermMemoryPattern (Line 177)

    Description: Short-Term Memory Pattern – Temporary rapid-decay memory.

    Agents hold information briefly for immediate use, with automatic expiration and capacity limits mimicking human short-term memory.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register_agent (Line 188)
    def register_agent(self, agent):
        """Register agent with short-term memory."""
    

    Purpose: Register agent with short-term memory.

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

    run (Line 192)
    def run(self, scenario):
        """Execute short-term memory pattern."""
    

    Purpose: Execute short-term memory pattern.

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


    Design Patterns Used

    • Strategy Pattern: Different execution strategies for various scenarios
    • State Pattern: Managing different states in the workflow
    • Chain of Responsibility: Sequential processing through workflow nodes
    • Observer Pattern: Tracking and monitoring pattern execution
    • Factory Pattern: Creating instances with proper configuration

    Usage Example

    # Initialize the pattern
    pattern = ShortTermItem(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: Long Term Memory

    
        """
    Pattern 64: Long-Term Memory Pattern
    
    Agents maintain persistent memory across sessions with consolidation and retrieval.
    Combines episodic, semantic, and procedural memory for long-term storage.
    """
    
    from typing import Dict, Any, List, Optional, Set
    from dataclasses import dataclass, field
    from datetime import datetime, timedelta
    from enum import Enum
    import json
    from pathlib import Path
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class MemoryType(Enum):
        """Type of long-term memory."""
        EPISODIC = "episodic"  # Personal experiences
        SEMANTIC = "semantic"  # Facts and concepts
        PROCEDURAL = "procedural"  # Skills and procedures
        AUTOBIOGRAPHICAL = "autobiographical"  # Personal history
    
    
    class MemoryStrength(Enum):
        """Memory consolidation strength."""
        WEAK = 0.3
        MODERATE = 0.6
        STRONG = 0.9
        PERMANENT = 1.0
    
    
    @dataclass
    class LongTermMemoryEntry:
        """Entry in long-term memory."""
        memory_id: str
        memory_type: MemoryType
        content: Any
        context: Dict[str, Any]
        strength: float = 0.5  # Consolidation strength
        created_at: datetime = field(default_factory=datetime.now)
        last_accessed: datetime = field(default_factory=datetime.now)
        access_count: int = 0
        tags: Set[str] = field(default_factory=set)
        associations: Set[str] = field(default_factory=set)  # IDs of related memories
    
    
    @dataclass
    class MemoryConsolidation:
        """Record of memory consolidation process."""
        consolidation_id: str
        memories_consolidated: List[str]
        original_strength: float
        new_strength: float
        timestamp: datetime = field(default_factory=datetime.now)
        reason: str = ""
    
    
    class LongTermMemoryStore:
        """Persistent long-term memory storage."""
        
        def __init__(self, storage_path: Optional[Path] = None):
            self.storage_path = storage_path
            self.memories: Dict[str, LongTermMemoryEntry] = {}
            self.consolidation_history: List[MemoryConsolidation] = []
            self.indexes: Dict[str, Dict[Any, Set[str]]] = {
                "type": {},
                "tags": {},
                "date": {}
            }
        
        def store(self, memory: LongTermMemoryEntry):
            """Store memory in long-term storage."""
            self.memories[memory.memory_id] = memory
            
            # Update indexes
            mem_type = memory.memory_type.value
            if mem_type not in self.indexes["type"]:
                self.indexes["type"][mem_type] = set()
            self.indexes["type"][mem_type].add(memory.memory_id)
            
            # Tag index
            for tag in memory.tags:
                if tag not in self.indexes["tags"]:
                    self.indexes["tags"][tag] = set()
                self.indexes["tags"][tag].add(memory.memory_id)
            
            # Date index (by day)
            date_key = memory.created_at.date()
            if date_key not in self.indexes["date"]:
                self.indexes["date"][date_key] = set()
            self.indexes["date"][date_key].add(memory.memory_id)
        
        def retrieve(self, memory_id: str) -> Optional[LongTermMemoryEntry]:
            """Retrieve memory and update access metadata."""
            if memory_id not in self.memories:
                return None
            
            memory = self.memories[memory_id]
            memory.last_accessed = datetime.now()
            memory.access_count += 1
            
            # Strengthen memory through retrieval
            self._strengthen_memory(memory_id, 0.05)
            
            return memory
        
        def search_by_type(self, memory_type: MemoryType) -> List[LongTermMemoryEntry]:
            """Search memories by type."""
            memory_ids = self.indexes["type"].get(memory_type.value, set())
            return [self.memories[mid] for mid in memory_ids if mid in self.memories]
        
        def search_by_tags(self, tags: Set[str]) -> List[LongTermMemoryEntry]:
            """Search memories by tags."""
            result_ids = None
            for tag in tags:
                tag_ids = self.indexes["tags"].get(tag, set())
                if result_ids is None:
                    result_ids = tag_ids
                else:
                    result_ids = result_ids & tag_ids
            
            if result_ids is None:
                return []
            
            return [self.memories[mid] for mid in result_ids if mid in self.memories]
        
        def search_by_date_range(self, start: datetime, end: datetime) -> List[LongTermMemoryEntry]:
            """Search memories by date range."""
            results = []
            current_date = start.date()
            end_date = end.date()
            
            while current_date  7:  # Only decay after a week
                    decay = decay_rate * (days_since_access / 7)
                    memory.strength = max(0.1, memory.strength - decay)
    
    
    class LongTermMemoryAgent:
        """Agent with long-term persistent memory."""
        
        def __init__(self, name: str, storage_path: Optional[Path] = None, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.3)
            self.memory_store = LongTermMemoryStore(storage_path)
        
        def remember(self, memory_id: str, content: Any, memory_type: MemoryType,
                     context: Optional[Dict[str, Any]] = None, tags: Optional[Set[str]] = None):
            """Store in long-term memory."""
            memory = LongTermMemoryEntry(
                memory_id=memory_id,
                memory_type=memory_type,
                content=content,
                context=context or {},
                tags=tags or set(),
                strength=0.5
            )
            
            self.memory_store.store(memory)
            print(f"   šŸ’¾ {self.name} stored long-term memory: {memory_id} ({memory_type.value})")
        
        def recall(self, memory_id: str) -> Optional[Any]:
            """Recall from long-term memory."""
            memory = self.memory_store.retrieve(memory_id)
            if memory:
                print(f"   āœ“ {self.name} recalled: {memory_id} (strength: {memory.strength:.2f}, accessed {memory.access_count}x)")
                return memory.content
            else:
                print(f"   āœ— {self.name} couldn't recall: {memory_id}")
                return None
        
        def reflect_on_memories(self, memory_type: MemoryType, limit: int = 5) -> str:
            """Reflect on memories using LLM."""
            memories = self.memory_store.search_by_type(memory_type)[:limit]
            
            if not memories:
                return f"No {memory_type.value} memories to reflect on."
            
            memories_text = "\n".join([
                f"- [{m.memory_id}] {m.content} (strength: {m.strength:.2f}, accessed: {m.access_count}x)"
                for m in sorted(memories, key=lambda x: x.strength, reverse=True)
            ])
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name} reflecting on your long-term memories."),
                ("human", f"Your {memory_type.value} memories:\n{memories_text}\n\n"
                         f"Reflect on these memories. What patterns or insights do you notice? "
                         f"(2-3 sentences)")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content)[:300]
    
    
    class LongTermMemoryPattern:
        """
        Long-Term Memory Pattern - Persistent cross-session memory.
        
        Agents maintain memories across sessions with consolidation,
        strengthening through retrieval, and decay of unused memories.
        """
        
        def __init__(self):
            self.agents: Dict[str, LongTermMemoryAgent] = {}
        
        def register_agent(self, agent: LongTermMemoryAgent):
            """Register agent with long-term memory."""
            self.agents[agent.name] = agent
        
        def run(self, scenario: str) -> Dict[str, Any]:
            """Execute long-term memory pattern."""
            total_memories = sum(len(agent.memory_store.memories) for agent in self.agents.values())
            total_consolidations = sum(len(agent.memory_store.consolidation_history) for agent in self.agents.values())
            
            avg_strength = 0
            if total_memories > 0:
                all_strengths = [m.strength for agent in self.agents.values() 
                               for m in agent.memory_store.memories.values()]
                avg_strength = sum(all_strengths) / len(all_strengths)
            
            return {
                "pattern": "LongTermMemory",
                "scenario": scenario,
                "total_agents": len(self.agents),
                "total_memories": total_memories,
                "average_strength": avg_strength,
                "total_consolidations": total_consolidations
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Long-Term Memory Pattern Demo ===\n")
        
        # Create pattern
        pattern = LongTermMemoryPattern()
        
        # Create agent with long-term memory
        print("1. Creating agent with long-term memory...")
        agent = LongTermMemoryAgent("Sage")
        pattern.register_agent(agent)
        
        # Store various types of memories
        print("\n2. Storing long-term memories...")
        
        # Episodic memories
        agent.remember("first_project", "Led AI chatbot project in 2023", MemoryType.EPISODIC,
                       context={"year": 2023, "role": "lead"}, tags={"work", "project", "ai"})
        
        agent.remember("conference_talk", "Presented at AI Conference 2024", MemoryType.EPISODIC,
                       context={"year": 2024, "type": "presentation"}, tags={"conference", "public_speaking"})
        
        # Semantic memories
        agent.remember("python_knowledge", "Python is a high-level programming language", MemoryType.SEMANTIC,
                       tags={"programming", "knowledge"})
        
        agent.remember("ml_concept", "Machine learning enables computers to learn from data", MemoryType.SEMANTIC,
                       tags={"ai", "knowledge", "ml"})
        
        # Procedural memories
        agent.remember("debug_process", "Check logs, isolate issue, fix, test", MemoryType.PROCEDURAL,
                       tags={"programming", "skill"})
        
        # Recall memories
        print("\n3. Recalling memories...")
        agent.recall("first_project")
        agent.recall("python_knowledge")
        agent.recall("debug_process")
        agent.recall("first_project")  # Second recall strengthens
        
        # Search by type
        print("\n4. Searching memories by type...")
        episodic = agent.memory_store.search_by_type(MemoryType.EPISODIC)
        print(f"   Episodic memories: {len(episodic)}")
        for mem in episodic:
            print(f"   - {mem.memory_id}: {mem.content} (strength: {mem.strength:.2f})")
        
        # Search by tags
        print("\n5. Searching memories by tags...")
        ai_memories = agent.memory_store.search_by_tags({"ai"})
        print(f"   Memories tagged 'ai': {len(ai_memories)}")
        for mem in ai_memories:
            print(f"   - {mem.memory_id}: {mem.content}")
        
        # Consolidate important memories
        print("\n6. Consolidating memories...")
        important_ids = ["first_project", "ml_concept"]
        agent.memory_store.consolidate_memories(important_ids, reason="frequently accessed")
        print(f"   Consolidated {len(important_ids)} memories")
        
        # Check strength after consolidation
        for mid in important_ids:
            mem = agent.memory_store.memories.get(mid)
            if mem:
                print(f"   - {mid}: strength now {mem.strength:.2f}")
        
        # Reflection
        print("\n7. Reflecting on memories...")
        reflection = agent.reflect_on_memories(MemoryType.EPISODIC)
        print(f"   Reflection on episodic memories:")
        print(f"   {reflection}")
        
        # Statistics
        print("\n8. Memory Statistics:")
        summary = pattern.run("Personal knowledge and experience")
        print(f"   Total Memories: {summary['total_memories']}")
        print(f"   Average Strength: {summary['average_strength']:.2f}")
        print(f"   Consolidations: {summary['total_consolidations']}")
        
        # Memory distribution
        print("\n9. Memory Distribution:")
        for mem_type in MemoryType:
            count = len(agent.memory_store.search_by_type(mem_type))
            print(f"   {mem_type.value}: {count}")
        
        print("\nāœ“ Long-term memory pattern enabled persistent knowledge storage!")
    
        

    Agentic Architecture Pattern: Long Term Memory

    Pattern 64: 64 Long Term Memory – Line-by-Line Explanation

    Overview

    Pattern 64: Long-Term Memory Pattern

    Agents maintain persistent memory across sessions with consolidation and retrieval. Combines episodic, semantic, and procedural memory for long-term storage.


    Code Structure Analysis

    File Information

    • Pattern Number: 64
    • Pattern Name: 64 Long Term Memory
    • File Path: patterns\memory_knowledge\64_long_term_memory.py
    • Total Lines: 366

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 64: Long-Term Memory Pattern
    
    Agents maintain persistent memory across sessions with consolidation and retrieval.
    Combines episodic, semantic, and procedural memory for long-term storage.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 64 Long Term Memory pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Set
    from dataclasses import dataclass, field
    from datetime import datetime, timedelta
    from enum import Enum
    import json
    from pathlib import Path
    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, timedelta: Date and time utilities – from enum import Enum: Enumeration support for fixed sets of values – import json: JSON parsing and serialization – from langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration


    Enumerations

    MemoryType (Line 18)

    class MemoryType(Enum):
        EPISODIC
        SEMANTIC
        PROCEDURAL
        AUTOBIOGRAPHICAL
    

    Purpose: Type of long-term memory.

    Values: – EPISODIC: Represents episodic – SEMANTIC: Represents semantic – PROCEDURAL: Represents procedural – AUTOBIOGRAPHICAL: Represents autobiographical

    MemoryStrength (Line 26)

    class MemoryStrength(Enum):
        WEAK
        MODERATE
        STRONG
        PERMANENT
    

    Purpose: Memory consolidation strength.

    Values: – WEAK: Represents weak – MODERATE: Represents moderate – STRONG: Represents strong – PERMANENT: Represents permanent


    Classes

    MemoryType (Line 18)

    Description: Type of long-term memory.

    MemoryStrength (Line 26)

    Description: Memory consolidation strength.

    LongTermMemoryEntry (Line 35)

    Description: Entry in long-term memory.

    MemoryConsolidation (Line 50)

    Description: Record of memory consolidation process.

    LongTermMemoryStore (Line 60)

    Description: Persistent long-term memory storage.

    Methods:

    __init__ (Line 63)
    def __init__(self, storage_path):
        """No method docstring."""
    

    Purpose: No method docstring.

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

    store (Line 73)
    def store(self, memory):
        """Store memory in long-term storage."""
    

    Purpose: Store memory in long-term storage.

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

    retrieve (Line 95)
    def retrieve(self, memory_id):
        """Retrieve memory and update access metadata."""
    

    Purpose: Retrieve memory and update access metadata.

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

    search_by_type (Line 109)
    def search_by_type(self, memory_type):
        """Search memories by type."""
    

    Purpose: Search memories by type.

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

    search_by_tags (Line 114)
    def search_by_tags(self, tags):
        """Search memories by tags."""
    

    Purpose: Search memories by tags.

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

    search_by_date_range (Line 129)
    def search_by_date_range(self, start, end):
        """Search memories by date range."""
    

    Purpose: Search memories by date range.

    Parameters: – self: Instance reference – start: Parameter for start – end: Parameter for end

    consolidate_memories (Line 144)
    def consolidate_memories(self, memory_ids, reason):
        """Consolidate memories to strengthen retention."""
    

    Purpose: Consolidate memories to strengthen retention.

    Parameters: – self: Instance reference – memory_ids: Parameter for memory_ids – reason: Parameter for reason

    _strengthen_memory (Line 168)
    def _strengthen_memory(self, memory_id, amount):
        """Strengthen memory consolidation."""
    

    Purpose: Strengthen memory consolidation.

    Parameters: – self: Instance reference – memory_id: Parameter for memory_id – amount: Parameter for amount

    decay_memories (Line 174)
    def decay_memories(self, decay_rate):
        """Apply memory decay to unused memories."""
    

    Purpose: Apply memory decay to unused memories.

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

    LongTermMemoryAgent (Line 186)

    Description: Agent with long-term persistent memory.

    Methods:

    __init__ (Line 189)
    def __init__(self, name, storage_path, model_name):
        """No method docstring."""
    

    Purpose: No method docstring.

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

    remember (Line 194)
    def remember(self, memory_id, content, memory_type, context, tags):
        """Store in long-term memory."""
    

    Purpose: Store in long-term memory.

    Parameters: – self: Instance reference – memory_id: Parameter for memory_id – content: Parameter for content – memory_type: Parameter for memory_type – context: Parameter for context – tags: Parameter for tags

    recall (Line 209)
    def recall(self, memory_id):
        """Recall from long-term memory."""
    

    Purpose: Recall from long-term memory.

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

    reflect_on_memories (Line 219)
    def reflect_on_memories(self, memory_type, limit):
        """Reflect on memories using LLM."""
    

    Purpose: Reflect on memories using LLM.

    Parameters: – self: Instance reference – memory_type: Parameter for memory_type – limit: Parameter for limit

    LongTermMemoryPattern (Line 244)

    Description: Long-Term Memory Pattern – Persistent cross-session memory.

    Agents maintain memories across sessions with consolidation, strengthening through retrieval, and decay of unused memories.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register_agent (Line 255)
    def register_agent(self, agent):
        """Register agent with long-term memory."""
    

    Purpose: Register agent with long-term memory.

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

    run (Line 259)
    def run(self, scenario):
        """Execute long-term memory pattern."""
    

    Purpose: Execute long-term memory pattern.

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


    Design Patterns Used

    • Strategy Pattern: Different execution strategies for various scenarios
    • State Pattern: Managing different states in the workflow
    • Chain of Responsibility: Sequential processing through workflow nodes
    • Observer Pattern: Tracking and monitoring pattern execution
    • Factory Pattern: Creating instances with proper configuration

    Usage Example

    # Initialize the pattern
    pattern = MemoryType(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: Working Memory

    
        """
    Pattern 63: Working Memory Pattern
    
    Agents maintain temporary, limited-capacity memory for current task execution.
    Similar to human working memory: holds active information needed right now.
    """
    
    from typing import Dict, Any, List, Optional, Deque
    from dataclasses import dataclass, field
    from datetime import datetime, timedelta
    from collections import deque
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class ItemPriority(Enum):
        """Priority level for working memory items."""
        CRITICAL = 3
        HIGH = 2
        NORMAL = 1
        LOW = 0
    
    
    @dataclass
    class WorkingMemoryItem:
        """Item in working memory."""
        item_id: str
        content: Any
        priority: ItemPriority
        created_at: datetime = field(default_factory=datetime.now)
        last_accessed: datetime = field(default_factory=datetime.now)
        access_count: int = 0
        ttl: Optional[timedelta] = None  # Time to live
        context: Dict[str, Any] = field(default_factory=dict)
    
    
    @dataclass
    class MemoryOperation:
        """Record of memory operation."""
        operation_type: str  # "store", "retrieve", "update", "evict"
        item_id: str
        timestamp: datetime = field(default_factory=datetime.now)
        success: bool = True
    
    
    class WorkingMemory:
        """
        Limited-capacity working memory with eviction policies.
        """
        
        def __init__(self, capacity: int = 7):  # Miller's law: 7±2 items
            self.capacity = capacity
            self.items: Dict[str, WorkingMemoryItem] = {}
            self.access_queue: Deque[str] = deque()  # For LRU eviction
            self.operations: List[MemoryOperation] = []
        
        def store(self, item: WorkingMemoryItem) -> bool:
            """Store item in working memory."""
            # Check if we need to evict
            if len(self.items) >= self.capacity and item.item_id not in self.items:
                self._evict()
            
            # Store item
            self.items[item.item_id] = item
            
            # Update access queue
            if item.item_id in self.access_queue:
                self.access_queue.remove(item.item_id)
            self.access_queue.append(item.item_id)
            
            # Record operation
            self.operations.append(MemoryOperation("store", item.item_id))
            
            return True
        
        def retrieve(self, item_id: str) -> Optional[WorkingMemoryItem]:
            """Retrieve item from working memory."""
            if item_id not in self.items:
                self.operations.append(MemoryOperation("retrieve", item_id, success=False))
                return None
            
            item = self.items[item_id]
            
            # Check TTL
            if item.ttl and datetime.now() - item.created_at > item.ttl:
                self._remove(item_id)
                return None
            
            # Update access metadata
            item.last_accessed = datetime.now()
            item.access_count += 1
            
            # Update LRU queue
            if item_id in self.access_queue:
                self.access_queue.remove(item_id)
            self.access_queue.append(item_id)
            
            # Record operation
            self.operations.append(MemoryOperation("retrieve", item_id))
            
            return item
        
        def update(self, item_id: str, new_content: Any) -> bool:
            """Update item in working memory."""
            if item_id not in self.items:
                return False
            
            self.items[item_id].content = new_content
            self.items[item_id].last_accessed = datetime.now()
            
            self.operations.append(MemoryOperation("update", item_id))
            
            return True
        
        def _evict(self):
            """Evict item based on priority and recency."""
            if not self.items:
                return
            
            # Find lowest priority, least recently used item
            candidates = []
            for item_id in list(self.access_queue):
                if item_id in self.items:
                    item = self.items[item_id]
                    # Score: lower is better for eviction
                    score = item.priority.value * 100 + item.access_count
                    candidates.append((score, item_id))
            
            if candidates:
                candidates.sort()
                item_id_to_evict = candidates[0][1]
                self._remove(item_id_to_evict)
        
        def _remove(self, item_id: str):
            """Remove item from working memory."""
            if item_id in self.items:
                del self.items[item_id]
            if item_id in self.access_queue:
                self.access_queue.remove(item_id)
            
            self.operations.append(MemoryOperation("evict", item_id))
        
        def get_all(self) -> List[WorkingMemoryItem]:
            """Get all items in working memory."""
            return list(self.items.values())
        
        def clear(self):
            """Clear all working memory."""
            self.items.clear()
            self.access_queue.clear()
        
        def is_full(self) -> bool:
            """Check if working memory is at capacity."""
            return len(self.items) >= self.capacity
    
    
    class WorkingMemoryAgent:
        """Agent with working memory for current task execution."""
        
        def __init__(self, name: str, memory_capacity: int = 7, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
            self.working_memory = WorkingMemory(capacity=memory_capacity)
            self.task_context: Dict[str, Any] = {}
        
        def start_task(self, task_name: str, task_data: Dict[str, Any]):
            """Start new task, initializing working memory."""
            self.task_context = {"task": task_name, "data": task_data}
            
            # Store task info in working memory
            task_item = WorkingMemoryItem(
                "current_task",
                task_name,
                ItemPriority.CRITICAL,
                context=task_data
            )
            self.working_memory.store(task_item)
            
            print(f"   šŸŽÆ {self.name} started task: {task_name}")
        
        def remember(self, key: str, value: Any, priority: ItemPriority = ItemPriority.NORMAL,
                     ttl: Optional[timedelta] = None):
            """Store information in working memory."""
            item = WorkingMemoryItem(key, value, priority, ttl=ttl)
            self.working_memory.store(item)
            print(f"   šŸ’­ {self.name} remembered: {key} (priority: {priority.name})")
        
        def recall(self, key: str) -> Optional[Any]:
            """Recall information from working memory."""
            item = self.working_memory.retrieve(key)
            if item:
                print(f"   āœ“ {self.name} recalled: {key}")
                return item.content
            else:
                print(f"   āœ— {self.name} couldn't recall: {key}")
                return None
        
        def process_with_context(self, query: str) -> str:
            """Process query using working memory context."""
            # Get all working memory items
            items = self.working_memory.get_all()
            
            context_text = "\n".join([
                f"- {item.item_id}: {item.content} (priority: {item.priority.name}, accessed: {item.access_count})"
                for item in sorted(items, key=lambda x: x.priority.value, reverse=True)
            ])
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name} working on a task. "
                          f"Use your working memory to inform your response."),
                ("human", f"Current working memory:\n{context_text}\n\n"
                         f"Current task: {self.task_context.get('task', 'None')}\n\n"
                         f"Query: {query}\n\n"
                         f"Respond based on your working memory context. Be brief (2-3 sentences).")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content)[:300]
        
        def get_memory_status(self) -> Dict[str, Any]:
            """Get current working memory status."""
            items = self.working_memory.get_all()
            
            return {
                "capacity": self.working_memory.capacity,
                "used": len(items),
                "available": self.working_memory.capacity - len(items),
                "is_full": self.working_memory.is_full(),
                "items": [
                    {
                        "id": item.item_id,
                        "priority": item.priority.name,
                        "access_count": item.access_count
                    }
                    for item in sorted(items, key=lambda x: x.priority.value, reverse=True)
                ]
            }
    
    
    class WorkingMemoryPattern:
        """
        Working Memory Pattern - Temporary task-focused memory.
        
        Agents maintain limited-capacity memory for current task execution,
        with automatic eviction based on priority and recency.
        """
        
        def __init__(self):
            self.agents: Dict[str, WorkingMemoryAgent] = {}
        
        def register_agent(self, agent: WorkingMemoryAgent):
            """Register agent with working memory."""
            self.agents[agent.name] = agent
        
        def run(self, scenario: str) -> Dict[str, Any]:
            """Execute working memory pattern."""
            total_items = sum(len(agent.working_memory.items) for agent in self.agents.values())
            total_operations = sum(len(agent.working_memory.operations) for agent in self.agents.values())
            
            return {
                "pattern": "WorkingMemory",
                "scenario": scenario,
                "total_agents": len(self.agents),
                "total_items_in_memory": total_items,
                "total_operations": total_operations
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Working Memory Pattern Demo ===\n")
        
        # Create pattern
        pattern = WorkingMemoryPattern()
        
        # Create agent with limited working memory
        print("1. Creating agent with working memory (capacity: 5)...")
        agent = WorkingMemoryAgent("Worker", memory_capacity=5)
        pattern.register_agent(agent)
        
        # Start a task
        print("\n2. Starting task...")
        agent.start_task("Data Analysis", {"dataset": "sales_2024", "goal": "find trends"})
        
        # Store items in working memory
        print("\n3. Storing information in working memory...")
        agent.remember("total_records", 10000, ItemPriority.HIGH)
        agent.remember("date_range", "2024-01-01 to 2024-12-31", ItemPriority.NORMAL)
        agent.remember("primary_metric", "revenue", ItemPriority.HIGH)
        agent.remember("secondary_metric", "customer_count", ItemPriority.NORMAL)
        
        # Check memory status
        print("\n4. Working memory status:")
        status = agent.get_memory_status()
        print(f"   Capacity: {status['used']}/{status['capacity']}")
        print(f"   Items:")
        for item in status['items']:
            print(f"   - {item['id']} (priority: {item['priority']}, accessed: {item['access_count']}x)")
        
        # Store more items (will trigger eviction)
        print("\n5. Adding more items (triggers eviction)...")
        agent.remember("temp_calculation", 42, ItemPriority.LOW)
        agent.remember("current_filter", "region=North", ItemPriority.NORMAL)
        
        status = agent.get_memory_status()
        print(f"   Memory now: {status['used']}/{status['capacity']}")
        
        # Recall items
        print("\n6. Recalling items from working memory...")
        agent.recall("primary_metric")
        agent.recall("total_records")
        agent.recall("temp_calculation")  # May have been evicted
        
        # Process with context
        print("\n7. Processing queries with working memory context...")
        queries = [
            "What is the main goal of my current task?",
            "What metrics am I tracking?",
            "Summarize what I'm working on"
        ]
        
        for query in queries:
            print(f"\n   Q: {query}")
            response = agent.process_with_context(query)
            print(f"   A: {response}")
        
        # Memory operations statistics
        print("\n8. Memory operation statistics:")
        ops = agent.working_memory.operations
        op_counts = {}
        for op in ops:
            op_counts[op.operation_type] = op_counts.get(op.operation_type, 0) + 1
        
        print(f"   Total operations: {len(ops)}")
        for op_type, count in op_counts.items():
            print(f"   - {op_type}: {count}")
        
        # Summary
        print("\n9. Pattern Summary:")
        summary = pattern.run("Task-focused data analysis")
        print(f"   Total items in memory: {summary['total_items_in_memory']}")
        print(f"   Total operations: {summary['total_operations']}")
        
        print("\nāœ“ Working memory pattern enabled limited-capacity task execution!")
    
        

    Agentic Architecture Pattern: Working Memory

    Pattern 63: 63 Working Memory – Line-by-Line Explanation

    Overview

    Pattern 63: Working Memory Pattern

    Agents maintain temporary, limited-capacity memory for current task execution. Similar to human working memory: holds active information needed right now.


    Code Structure Analysis

    File Information

    • Pattern Number: 63
    • Pattern Name: 63 Working Memory
    • File Path: patterns\memory_knowledge\63_working_memory.py
    • Total Lines: 348

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 63: Working Memory Pattern
    
    Agents maintain temporary, limited-capacity memory for current task execution.
    Similar to human working memory: holds active information needed right now.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 63 Working Memory pattern.


    Imports Section

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

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


    Enumerations

    ItemPriority (Line 17)

    class ItemPriority(Enum):
        CRITICAL
        HIGH
        NORMAL
        LOW
    

    Purpose: Priority level for working memory items.

    Values: – CRITICAL: Represents critical – HIGH: Represents high – NORMAL: Represents normal – LOW: Represents low


    Classes

    ItemPriority (Line 17)

    Description: Priority level for working memory items.

    WorkingMemoryItem (Line 26)

    Description: Item in working memory.

    MemoryOperation (Line 39)

    Description: Record of memory operation.

    WorkingMemory (Line 47)

    Description: Limited-capacity working memory with eviction policies.

    Methods:

    __init__ (Line 52)
    def __init__(self, capacity):
        """No method docstring."""
    

    Purpose: No method docstring.

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

    store (Line 58)
    def store(self, item):
        """Store item in working memory."""
    

    Purpose: Store item in working memory.

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

    retrieve (Line 77)
    def retrieve(self, item_id):
        """Retrieve item from working memory."""
    

    Purpose: Retrieve item from working memory.

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

    update (Line 104)
    def update(self, item_id, new_content):
        """Update item in working memory."""
    

    Purpose: Update item in working memory.

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

    _evict (Line 116)
    def _evict(self):
        """Evict item based on priority and recency."""
    

    Purpose: Evict item based on priority and recency.

    Parameters: – self: Instance reference

    _remove (Line 135)
    def _remove(self, item_id):
        """Remove item from working memory."""
    

    Purpose: Remove item from working memory.

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

    get_all (Line 144)
    def get_all(self):
        """Get all items in working memory."""
    

    Purpose: Get all items in working memory.

    Parameters: – self: Instance reference

    clear (Line 148)
    def clear(self):
        """Clear all working memory."""
    

    Purpose: Clear all working memory.

    Parameters: – self: Instance reference

    is_full (Line 153)
    def is_full(self):
        """Check if working memory is at capacity."""
    

    Purpose: Check if working memory is at capacity.

    Parameters: – self: Instance reference

    WorkingMemoryAgent (Line 158)

    Description: Agent with working memory for current task execution.

    Methods:

    __init__ (Line 161)
    def __init__(self, name, memory_capacity, model_name):
        """No method docstring."""
    

    Purpose: No method docstring.

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

    start_task (Line 167)
    def start_task(self, task_name, task_data):
        """Start new task, initializing working memory."""
    

    Purpose: Start new task, initializing working memory.

    Parameters: – self: Instance reference – task_name: Parameter for task_name – task_data: Parameter for task_data

    remember (Line 182)
    def remember(self, key, value, priority, ttl):
        """Store information in working memory."""
    

    Purpose: Store information in working memory.

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

    recall (Line 189)
    def recall(self, key):
        """Recall information from working memory."""
    

    Purpose: Recall information from working memory.

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

    process_with_context (Line 199)
    def process_with_context(self, query):
        """Process query using working memory context."""
    

    Purpose: Process query using working memory context.

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

    get_memory_status (Line 223)
    def get_memory_status(self):
        """Get current working memory status."""
    

    Purpose: Get current working memory status.

    Parameters: – self: Instance reference

    WorkingMemoryPattern (Line 243)

    Description: Working Memory Pattern – Temporary task-focused memory.

    Agents maintain limited-capacity memory for current task execution, with automatic eviction based on priority and recency.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register_agent (Line 254)
    def register_agent(self, agent):
        """Register agent with working memory."""
    

    Purpose: Register agent with working memory.

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

    run (Line 258)
    def run(self, scenario):
        """Execute working memory pattern."""
    

    Purpose: Execute working memory pattern.

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


    Design Patterns Used

    • Strategy Pattern: Different execution strategies for various scenarios
    • State Pattern: Managing different states in the workflow
    • Chain of Responsibility: Sequential processing through workflow nodes
    • Observer Pattern: Tracking and monitoring pattern execution
    • Factory Pattern: Creating instances with proper configuration

    Usage Example

    # Initialize the pattern
    pattern = ItemPriority(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: Semantic Memory

    
        """
    Pattern 62: Semantic Memory Pattern
    
    Agents store general knowledge, concepts, and meanings independent of context.
    Unlike episodic memory (specific events), semantic memory contains abstract facts.
    """
    
    from typing import Dict, Any, List, Optional, Set
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    
    
    class ConceptType(Enum):
        """Type of semantic concept."""
        CATEGORY = "category"
        PROPERTY = "property"
        RELATIONSHIP = "relationship"
        PROCEDURE = "procedure"
        DEFINITION = "definition"
    
    
    @dataclass
    class Concept:
        """Semantic concept with properties."""
        concept_id: str
        name: str
        concept_type: ConceptType
        definition: str
        properties: Dict[str, Any] = field(default_factory=dict)
        related_concepts: Set[str] = field(default_factory=set)
        examples: List[str] = field(default_factory=list)
        confidence: float = 1.0
        learned_date: datetime = field(default_factory=datetime.now)
    
    
    @dataclass
    class Association:
        """Association between concepts."""
        from_concept: str
        to_concept: str
        relationship: str
        strength: float = 1.0  # 0 to 1
    
    
    @dataclass
    class ConceptQuery:
        """Query about semantic knowledge."""
        query: str
        matched_concepts: List[Concept]
        associations: List[Association]
        answer: str
    
    
    class SemanticMemory:
        """Semantic memory storage and retrieval."""
        
        def __init__(self):
            self.concepts: Dict[str, Concept] = {}
            self.associations: List[Association] = []
            self.categories: Dict[str, Set[str]] = {}
        
        def add_concept(self, concept: Concept):
            """Add concept to semantic memory."""
            self.concepts[concept.concept_id] = concept
            
            # Add to category index
            category_name = concept.concept_type.value
            if category_name not in self.categories:
                self.categories[category_name] = set()
            self.categories[category_name].add(concept.concept_id)
        
        def add_association(self, from_concept: str, to_concept: str, 
                           relationship: str, strength: float = 1.0):
            """Add association between concepts."""
            assoc = Association(from_concept, to_concept, relationship, strength)
            self.associations.append(assoc)
            
            # Update related concepts
            if from_concept in self.concepts:
                self.concepts[from_concept].related_concepts.add(to_concept)
            if to_concept in self.concepts:
                self.concepts[to_concept].related_concepts.add(from_concept)
        
        def find_concept(self, name: str) -> Optional[Concept]:
            """Find concept by name."""
            for concept in self.concepts.values():
                if concept.name.lower() == name.lower():
                    return concept
            return None
        
        def get_related_concepts(self, concept_id: str, max_depth: int = 2) -> List[Concept]:
            """Get concepts related to given concept."""
            if concept_id not in self.concepts:
                return []
            
            related_ids = set()
            to_explore = [(concept_id, 0)]
            explored = set()
            
            while to_explore:
                current_id, depth = to_explore.pop(0)
                if current_id in explored or depth > max_depth:
                    continue
                
                explored.add(current_id)
                if current_id != concept_id:
                    related_ids.add(current_id)
                
                # Add related concepts to explore
                if current_id in self.concepts:
                    for related_id in self.concepts[current_id].related_concepts:
                        if related_id not in explored:
                            to_explore.append((related_id, depth + 1))
            
            return [self.concepts[cid] for cid in related_ids if cid in self.concepts]
        
        def get_by_category(self, category: ConceptType) -> List[Concept]:
            """Get all concepts in a category."""
            concept_ids = self.categories.get(category.value, set())
            return [self.concepts[cid] for cid in concept_ids if cid in self.concepts]
    
    
    class SemanticMemoryAgent:
        """Agent with semantic memory capabilities."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.3)
            self.memory = SemanticMemory()
            self.queries: List[ConceptQuery] = []
        
        def learn_concept(self, concept: Concept):
            """Learn new concept."""
            self.memory.add_concept(concept)
            print(f"   🧠 {self.name} learned concept: {concept.name} ({concept.concept_type.value})")
        
        def associate_concepts(self, concept1: str, concept2: str, relationship: str, strength: float = 1.0):
            """Create association between concepts."""
            self.memory.add_association(concept1, concept2, relationship, strength)
            print(f"   šŸ”— {self.name} associated: {concept1} --{relationship}-> {concept2}")
        
        def explain_concept(self, concept_name: str) -> str:
            """Explain concept using LLM."""
            concept = self.memory.find_concept(concept_name)
            if not concept:
                return f"I don't have semantic knowledge about '{concept_name}'."
            
            # Get related concepts
            related = self.memory.get_related_concepts(concept.concept_id)
            related_names = [self.memory.concepts[rc.concept_id].name for rc in related if rc.concept_id in self.memory.concepts]
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name}, explaining concepts from your semantic memory."),
                ("human", f"Explain this concept:\n"
                         f"Name: {concept.name}\n"
                         f"Type: {concept.concept_type.value}\n"
                         f"Definition: {concept.definition}\n"
                         f"Properties: {concept.properties}\n"
                         f"Related concepts: {', '.join(related_names[:5])}\n\n"
                         f"Provide a clear, educational explanation (2-3 sentences).")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content)[:300]
        
        def query_knowledge(self, query: str) -> ConceptQuery:
            """Query semantic knowledge."""
            # Get all concepts as context
            concepts_text = "\n".join([
                f"- {c.name} ({c.concept_type.value}): {c.definition}"
                for c in self.memory.concepts.values()
            ])
            
            associations_text = "\n".join([
                f"- {a.from_concept} {a.relationship} {a.to_concept}"
                for a in self.memory.associations[:20]  # Limit for context
            ])
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name} with semantic memory. "
                          f"Answer questions using your general knowledge."),
                ("human", f"My semantic knowledge:\n{concepts_text}\n\n"
                         f"Associations:\n{associations_text}\n\n"
                         f"Question: {query}\n\n"
                         f"Answer based on the semantic knowledge above.")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            result = ConceptQuery(
                query=query,
                matched_concepts=list(self.memory.concepts.values())[:5],
                associations=self.memory.associations[:5],
                answer=str(response.content)
            )
            
            self.queries.append(result)
            return result
    
    
    class SemanticMemoryPattern:
        """
        Semantic Memory Pattern - Abstract knowledge storage.
        
        Agents maintain general facts, concepts, and meanings, enabling
        them to reason about abstract ideas and relationships.
        """
        
        def __init__(self):
            self.agents: Dict[str, SemanticMemoryAgent] = {}
        
        def register_agent(self, agent: SemanticMemoryAgent):
            """Register agent with semantic memory."""
            self.agents[agent.name] = agent
        
        def share_concept(self, source_agent: str, target_agent: str, concept_name: str):
            """Share concept between agents."""
            if source_agent in self.agents and target_agent in self.agents:
                source = self.agents[source_agent]
                target = self.agents[target_agent]
                
                concept = source.memory.find_concept(concept_name)
                if concept:
                    target.learn_concept(concept)
        
        def run(self, domain: str) -> Dict[str, Any]:
            """Execute semantic memory pattern."""
            total_concepts = sum(len(agent.memory.concepts) for agent in self.agents.values())
            total_associations = sum(len(agent.memory.associations) for agent in self.agents.values())
            total_queries = sum(len(agent.queries) for agent in self.agents.values())
            
            return {
                "pattern": "SemanticMemory",
                "domain": domain,
                "total_agents": len(self.agents),
                "total_concepts": total_concepts,
                "total_associations": total_associations,
                "total_queries": total_queries
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Semantic Memory Pattern Demo ===\n")
        
        # Create pattern
        pattern = SemanticMemoryPattern()
        
        # Create agent with semantic memory
        print("1. Creating agent with semantic memory...")
        agent = SemanticMemoryAgent("Sage")
        pattern.register_agent(agent)
        
        # Learn concepts
        print("\n2. Learning concepts...")
        
        concepts = [
            Concept("ml", "Machine Learning", ConceptType.CATEGORY,
                    "Field of AI focused on learning from data",
                    properties={"paradigm": "supervised/unsupervised", "goal": "prediction"},
                    examples=["classification", "regression", "clustering"]),
            
            Concept("nn", "Neural Network", ConceptType.CATEGORY,
                    "Computing system inspired by biological neural networks",
                    properties={"layers": "input, hidden, output", "learning": "backpropagation"},
                    examples=["CNN", "RNN", "Transformer"]),
            
            Concept("supervised", "Supervised Learning", ConceptType.PROCEDURE,
                    "Learning from labeled training data",
                    properties={"requires": "labeled data", "output": "prediction model"},
                    examples=["classification", "regression"]),
            
            Concept("unsupervised", "Unsupervised Learning", ConceptType.PROCEDURE,
                    "Learning patterns from unlabeled data",
                    properties={"requires": "unlabeled data", "output": "patterns, clusters"},
                    examples=["clustering", "dimensionality reduction"]),
            
            Concept("backprop", "Backpropagation", ConceptType.PROCEDURE,
                    "Algorithm for training neural networks using gradient descent",
                    properties={"technique": "gradient descent", "direction": "backward"},
                    examples=["SGD", "Adam optimizer"]),
        ]
        
        for concept in concepts:
            agent.learn_concept(concept)
        
        # Create associations
        print("\n3. Creating concept associations...")
        agent.associate_concepts("ml", "supervised", "includes", 0.9)
        agent.associate_concepts("ml", "unsupervised", "includes", 0.9)
        agent.associate_concepts("nn", "ml", "is_part_of", 0.95)
        agent.associate_concepts("nn", "backprop", "uses", 1.0)
        agent.associate_concepts("supervised", "nn", "can_use", 0.8)
        
        # Explain concepts
        print("\n4. Explaining concepts...")
        for concept_name in ["Machine Learning", "Neural Network", "Backpropagation"]:
            explanation = agent.explain_concept(concept_name)
            print(f"\n   {concept_name}:")
            print(f"   {explanation}")
        
        # Query semantic knowledge
        print("\n5. Querying semantic knowledge...")
        queries = [
            "What is the relationship between neural networks and machine learning?",
            "Explain the difference between supervised and unsupervised learning",
            "How does backpropagation work?"
        ]
        
        for query in queries:
            print(f"\n   Q: {query}")
            result = agent.query_knowledge(query)
            print(f"   A: {result.answer[:200]}...")
        
        # Explore concept network
        print("\n6. Exploring concept relationships...")
        ml_concept = agent.memory.find_concept("Machine Learning")
        if ml_concept:
            related = agent.memory.get_related_concepts(ml_concept.concept_id)
            print(f"   Concepts related to 'Machine Learning': {len(related)}")
            for rc in related:
                print(f"   - {rc.name} ({rc.concept_type.value})")
        
        # Statistics
        print("\n7. Semantic Memory Statistics:")
        summary = pattern.run("AI and Machine Learning")
        print(f"   Total Concepts: {summary['total_concepts']}")
        print(f"   Total Associations: {summary['total_associations']}")
        print(f"   Total Queries: {summary['total_queries']}")
        
        categories = agent.memory.categories
        print(f"\n   Concepts by category:")
        for category, concept_ids in categories.items():
            print(f"   - {category}: {len(concept_ids)}")
        
        print("\nāœ“ Semantic memory pattern enabled abstract knowledge reasoning!")
    
        

    Agentic Architecture Pattern: Semantic Memory

    Pattern 62: 62 Semantic Memory – Line-by-Line Explanation

    Overview

    Pattern 62: Semantic Memory Pattern

    Agents store general knowledge, concepts, and meanings independent of context. Unlike episodic memory (specific events), semantic memory contains abstract facts.


    Code Structure Analysis

    File Information

    • Pattern Number: 62
    • Pattern Name: 62 Semantic Memory
    • File Path: patterns\memory_knowledge\62_semantic_memory.py
    • Total Lines: 343

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 62: Semantic Memory Pattern
    
    Agents store general knowledge, concepts, and meanings independent of context.
    Unlike episodic memory (specific events), semantic memory contains abstract facts.
    """
    

    Explanation: This module docstring describes the purpose and key features of the 62 Semantic Memory pattern.


    Imports Section

    from typing import Dict, Any, List, Optional, Set
    from dataclasses import dataclass, field
    from datetime import datetime
    from enum import Enum
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI  # 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

    ConceptType (Line 16)

    class ConceptType(Enum):
        CATEGORY
        PROPERTY
        RELATIONSHIP
        PROCEDURE
        DEFINITION
    

    Purpose: Type of semantic concept.

    Values: – CATEGORY: Represents category – PROPERTY: Represents property – RELATIONSHIP: Represents relationship – PROCEDURE: Represents procedure – DEFINITION: Represents definition


    Classes

    ConceptType (Line 16)

    Description: Type of semantic concept.

    Concept (Line 26)

    Description: Semantic concept with properties.

    Association (Line 40)

    Description: Association between concepts.

    ConceptQuery (Line 49)

    Description: Query about semantic knowledge.

    SemanticMemory (Line 57)

    Description: Semantic memory storage and retrieval.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    add_concept (Line 65)
    def add_concept(self, concept):
        """Add concept to semantic memory."""
    

    Purpose: Add concept to semantic memory.

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

    add_association (Line 75)
    def add_association(self, from_concept, to_concept, relationship, strength):
        """Add association between concepts."""
    

    Purpose: Add association between concepts.

    Parameters: – self: Instance reference – from_concept: Parameter for from_concept – to_concept: Parameter for to_concept – relationship: Parameter for relationship – strength: Parameter for strength

    find_concept (Line 87)
    def find_concept(self, name):
        """Find concept by name."""
    

    Purpose: Find concept by name.

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

    get_related_concepts (Line 94)
    def get_related_concepts(self, concept_id, max_depth):
        """Get concepts related to given concept."""
    

    Purpose: Get concepts related to given concept.

    Parameters: – self: Instance reference – concept_id: Parameter for concept_id – max_depth: Parameter for max_depth

    get_by_category (Line 120)
    def get_by_category(self, category):
        """Get all concepts in a category."""
    

    Purpose: Get all concepts in a category.

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

    SemanticMemoryAgent (Line 126)

    Description: Agent with semantic memory capabilities.

    Methods:

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

    Purpose: No method docstring.

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

    learn_concept (Line 135)
    def learn_concept(self, concept):
        """Learn new concept."""
    

    Purpose: Learn new concept.

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

    associate_concepts (Line 140)
    def associate_concepts(self, concept1, concept2, relationship, strength):
        """Create association between concepts."""
    

    Purpose: Create association between concepts.

    Parameters: – self: Instance reference – concept1: Parameter for concept1 – concept2: Parameter for concept2 – relationship: Parameter for relationship – strength: Parameter for strength

    explain_concept (Line 145)
    def explain_concept(self, concept_name):
        """Explain concept using LLM."""
    

    Purpose: Explain concept using LLM.

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

    query_knowledge (Line 171)
    def query_knowledge(self, query):
        """Query semantic knowledge."""
    

    Purpose: Query semantic knowledge.

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

    SemanticMemoryPattern (Line 207)

    Description: Semantic Memory Pattern – Abstract knowledge storage.

    Agents maintain general facts, concepts, and meanings, enabling them to reason about abstract ideas and relationships.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register_agent (Line 218)
    def register_agent(self, agent):
        """Register agent with semantic memory."""
    

    Purpose: Register agent with semantic memory.

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

    share_concept (Line 222)
    def share_concept(self, source_agent, target_agent, concept_name):
        """Share concept between agents."""
    

    Purpose: Share concept between agents.

    Parameters: – self: Instance reference – source_agent: Parameter for source_agent – target_agent: Parameter for target_agent – concept_name: Parameter for concept_name

    run (Line 232)
    def run(self, domain):
        """Execute semantic memory pattern."""
    

    Purpose: Execute semantic memory pattern.

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


    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 = ConceptType(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: Episodic Memory

    
        """
    Pattern 61: Episodic Memory Pattern
    
    Agents store and recall specific experiences/episodes with temporal context.
    Like human episodic memory: "I remember when X happened at time Y."
    """
    
    from typing import Dict, Any, List, Optional
    from dataclasses import dataclass, field
    from datetime import datetime
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI
    from langchain_core.messages import HumanMessage, AIMessage
    
    
    @dataclass
    class Episode:
        """Single episode in memory."""
        episode_id: str
        description: str
        context: Dict[str, Any]
        participants: List[str]
        location: Optional[str] = None
        outcome: Optional[str] = None
        emotional_valence: float = 0.0  # -1 (negative) to +1 (positive)
        importance: float = 0.5  # 0 to 1
        timestamp: datetime = field(default_factory=datetime.now)
        tags: List[str] = field(default_factory=list)
    
    
    @dataclass
    class MemoryRecall:
        """Result of memory recall."""
        query: str
        recalled_episodes: List[Episode]
        relevance_scores: Dict[str, float]
        recall_time: datetime = field(default_factory=datetime.now)
    
    
    class EpisodicMemoryAgent:
        """Agent with episodic memory capabilities."""
        
        def __init__(self, name: str, model_name: str = "gpt-4"):
            self.name = name
            self.llm = ChatOpenAI(model=model_name, temperature=0.7)
            self.episodes: List[Episode] = []
            self.recall_history: List[MemoryRecall] = []
        
        def store_episode(self, episode: Episode):
            """Store new episode in memory."""
            self.episodes.append(episode)
            print(f"   šŸ“ {self.name} stored: {episode.description}")
        
        def recall_by_time(self, start_time: datetime, end_time: datetime) -> List[Episode]:
            """Recall episodes within time range."""
            return [ep for ep in self.episodes 
                    if start_time <= ep.timestamp  List[Episode]:
            """Recall episodes with specific context."""
            return [ep for ep in self.episodes 
                    if ep.context.get(context_key) == context_value]
        
        def recall_by_participant(self, participant: str) -> List[Episode]:
            """Recall episodes involving specific participant."""
            return [ep for ep in self.episodes 
                    if participant in ep.participants]
        
        def recall_similar(self, query: str, top_k: int = 5) -> MemoryRecall:
            """Recall episodes similar to query using LLM."""
            if not self.episodes:
                return MemoryRecall(query, [], {})
            
            # Create episode descriptions
            episodes_text = "\n".join([
                f"{i+1}. [{ep.timestamp.strftime('%Y-%m-%d %H:%M')}] {ep.description} "
                f"(Participants: {', '.join(ep.participants)})"
                for i, ep in enumerate(self.episodes)
            ])
            
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name} recalling past experiences. "
                          f"Review your episodic memories and identify which ones are most relevant to the query."),
                ("human", f"Your episodic memories:\n{episodes_text}\n\n"
                         f"Query: {query}\n\n"
                         f"List the episode numbers (1-{len(self.episodes)}) most relevant to this query, "
                         f"in order of relevance. Format: just the numbers separated by commas.")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            # Parse episode numbers
            content = str(response.content)
            try:
                import re
                numbers = re.findall(r'\d+', content)
                indices = [int(n) - 1 for n in numbers if 0 < int(n) <= len(self.episodes)][:top_k]
                
                recalled = [self.episodes[i] for i in indices if i  str:
            """Reflect on stored episode using LLM."""
            prompt = ChatPromptTemplate.from_messages([
                ("system", f"You are {self.name} reflecting on a past experience."),
                ("human", f"Experience: {episode.description}\n"
                         f"When: {episode.timestamp.strftime('%Y-%m-%d %H:%M')}\n"
                         f"Context: {episode.context}\n"
                         f"Outcome: {episode.outcome}\n\n"
                         f"What did you learn from this experience? (2-3 sentences)")
            ])
            
            chain = prompt | self.llm
            response = chain.invoke({})
            
            return str(response.content)[:200]
    
    
    class EpisodicMemoryPattern:
        """
        Episodic Memory Pattern - Experience-based memory system.
        
        Agents store specific experiences with temporal and contextual information,
        enabling recall of "what happened when" and learning from past experiences.
        """
        
        def __init__(self):
            self.agents: Dict[str, EpisodicMemoryAgent] = {}
        
        def register_agent(self, agent: EpisodicMemoryAgent):
            """Register agent with episodic memory."""
            self.agents[agent.name] = agent
        
        def create_shared_episode(self, episode: Episode):
            """Create episode shared by all agents."""
            for agent in self.agents.values():
                agent.store_episode(episode)
        
        def run(self, scenario: str) -> Dict[str, Any]:
            """Execute episodic memory pattern."""
            total_episodes = sum(len(agent.episodes) for agent in self.agents.values())
            total_recalls = sum(len(agent.recall_history) for agent in self.agents.values())
            
            return {
                "pattern": "EpisodicMemory",
                "total_agents": len(self.agents),
                "total_episodes": total_episodes,
                "total_recalls": total_recalls,
                "scenario": scenario
            }
    
    
    # Example usage
    if __name__ == "__main__":
        print("=== Episodic Memory Pattern Demo ===\n")
        
        # Create pattern
        pattern = EpisodicMemoryPattern()
        
        # Create agent with episodic memory
        print("1. Creating agent with episodic memory...")
        agent = EpisodicMemoryAgent("Alice")
        pattern.register_agent(agent)
        
        # Store episodes
        print("\n2. Storing episodic memories...")
        
        episodes = [
            Episode(
                "ep1",
                "First meeting with project team",
                context={"project": "AI Platform", "phase": "kickoff"},
                participants=["Alice", "Bob", "Carol"],
                location="Conference Room A",
                outcome="Agreed on project timeline",
                emotional_valence=0.8,
                importance=0.9,
                tags=["meeting", "project", "team"]
            ),
            Episode(
                "ep2",
                "Debugged critical production issue",
                context={"project": "AI Platform", "phase": "deployment"},
                participants=["Alice", "Dave"],
                location="Remote",
                outcome="Fixed database connection bug",
                emotional_valence=-0.3,
                importance=0.95,
                tags=["debugging", "production", "urgent"]
            ),
            Episode(
                "ep3",
                "Celebrated successful product launch",
                context={"project": "AI Platform", "phase": "launch"},
                participants=["Alice", "Bob", "Carol", "Dave", "Eve"],
                location="Office",
                outcome="Product launched successfully",
                emotional_valence=1.0,
                importance=1.0,
                tags=["celebration", "launch", "success"]
            ),
            Episode(
                "ep4",
                "Code review session with junior developer",
                context={"project": "AI Platform", "phase": "development"},
                participants=["Alice", "Frank"],
                location="Video call",
                outcome="Improved code quality and mentored junior dev",
                emotional_valence=0.6,
                importance=0.7,
                tags=["code_review", "mentoring", "learning"]
            ),
        ]
        
        for episode in episodes:
            agent.store_episode(episode)
        
        # Recall by different criteria
        print("\n3. Recalling memories by participant...")
        bob_episodes = agent.recall_by_participant("Bob")
        print(f"   Episodes with Bob: {len(bob_episodes)}")
        for ep in bob_episodes:
            print(f"   - {ep.description}")
        
        print("\n4. Recalling memories by context...")
        launch_episodes = agent.recall_by_context("phase", "launch")
        print(f"   Episodes in launch phase: {len(launch_episodes)}")
        for ep in launch_episodes:
            print(f"   - {ep.description}")
        
        print("\n5. Recalling similar memories (semantic search)...")
        queries = [
            "Tell me about times when we had problems",
            "What were our team celebrations?",
            "Experiences with code and development"
        ]
        
        for query in queries:
            print(f"\n   Query: {query}")
            recall = agent.recall_similar(query, top_k=2)
            for ep in recall.recalled_episodes:
                print(f"   - {ep.description} (relevance: {recall.relevance_scores.get(ep.episode_id, 0):.1f})")
        
        # Reflection
        print("\n6. Reflecting on experience...")
        important_ep = max(agent.episodes, key=lambda e: e.importance)
        reflection = agent.reflect_on_experience(important_ep)
        print(f"   Reflecting on: {important_ep.description}")
        print(f"   Reflection: {reflection}")
        
        # Summary
        print("\n7. Memory Statistics:")
        summary = pattern.run("Personal experience tracking")
        print(f"   Total Episodes: {summary['total_episodes']}")
        print(f"   Total Recalls: {summary['total_recalls']}")
        print(f"   Average importance: {sum(ep.importance for ep in agent.episodes) / len(agent.episodes):.2f}")
        print(f"   Average emotional valence: {sum(ep.emotional_valence for ep in agent.episodes) / len(agent.episodes):.2f}")
        
        print("\nāœ“ Episodic memory pattern enabled experience-based recall!")
    
        

    Agentic Architecture Pattern: Episodic Memory

    Pattern 61: 61 Episodic Memory – Line-by-Line Explanation

    Overview

    Pattern 61: Episodic Memory Pattern

    Agents store and recall specific experiences/episodes with temporal context. Like human episodic memory: “I remember when X happened at time Y.”


    Code Structure Analysis

    File Information

    • Pattern Number: 61
    • Pattern Name: 61 Episodic Memory
    • File Path: patterns\memory_knowledge\61_episodic_memory.py
    • Total Lines: 268

    Detailed Code Explanation

    Module Docstring

    """
    Pattern 61: Episodic Memory Pattern
    
    Agents store and recall specific experiences/episodes with temporal context.
    Like human episodic memory: "I remember when X happened at time Y."
    """
    

    Explanation: This module docstring describes the purpose and key features of the 61 Episodic Memory pattern.


    Imports Section

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

    Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional: Type hints for better code documentation – from dataclasses import dataclass, field: Data class decorators for clean data structures – from datetime import datetime: Date and time utilities – from langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration – from langchain_core.messages import HumanMessage, AIMessage: LangChain framework integration


    Classes

    Episode (Line 17)

    Description: Single episode in memory.

    MemoryRecall (Line 32)

    Description: Result of memory recall.

    EpisodicMemoryAgent (Line 40)

    Description: Agent with episodic memory capabilities.

    Methods:

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

    Purpose: No method docstring.

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

    store_episode (Line 49)
    def store_episode(self, episode):
        """Store new episode in memory."""
    

    Purpose: Store new episode in memory.

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

    recall_by_time (Line 54)
    def recall_by_time(self, start_time, end_time):
        """Recall episodes within time range."""
    

    Purpose: Recall episodes within time range.

    Parameters: – self: Instance reference – start_time: Parameter for start_time – end_time: Parameter for end_time

    recall_by_context (Line 59)
    def recall_by_context(self, context_key, context_value):
        """Recall episodes with specific context."""
    

    Purpose: Recall episodes with specific context.

    Parameters: – self: Instance reference – context_key: Parameter for context_key – context_value: Parameter for context_value

    recall_by_participant (Line 64)
    def recall_by_participant(self, participant):
        """Recall episodes involving specific participant."""
    

    Purpose: Recall episodes involving specific participant.

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

    recall_similar (Line 69)
    def recall_similar(self, query, top_k):
        """Recall episodes similar to query using LLM."""
    

    Purpose: Recall episodes similar to query using LLM.

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

    reflect_on_experience (Line 110)
    def reflect_on_experience(self, episode):
        """Reflect on stored episode using LLM."""
    

    Purpose: Reflect on stored episode using LLM.

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

    EpisodicMemoryPattern (Line 127)

    Description: Episodic Memory Pattern – Experience-based memory system.

    Agents store specific experiences with temporal and contextual information, enabling recall of “what happened when” and learning from past experiences.

    Methods:

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

    Purpose: No method docstring.

    Parameters: – self: Instance reference

    register_agent (Line 138)
    def register_agent(self, agent):
        """Register agent with episodic memory."""
    

    Purpose: Register agent with episodic memory.

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

    create_shared_episode (Line 142)
    def create_shared_episode(self, episode):
        """Create episode shared by all agents."""
    

    Purpose: Create episode shared by all agents.

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

    run (Line 147)
    def run(self, scenario):
        """Execute episodic memory pattern."""
    

    Purpose: Execute episodic memory pattern.

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


    Design Patterns Used

    • Strategy Pattern: Different execution strategies for various scenarios
    • State Pattern: Managing different states in the workflow
    • Chain of Responsibility: Sequential processing through workflow nodes
    • Observer Pattern: Tracking and monitoring pattern execution
    • Factory Pattern: Creating instances with proper configuration

    Usage Example

    # Initialize the pattern
    pattern = Episode(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