Agentic Architecture Pattern: Zero Shot Learning

Written by

in


    """
Pattern 193: Zero-Shot Learning Pattern

LLM performs tasks without any training examples, relying solely on pre-trained knowledge.
Demonstrates ability to generalize to new tasks using instructions alone.
"""

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_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI


class TaskCategory(Enum):
    """Categories of zero-shot tasks."""
    CLASSIFICATION = "classification"
    GENERATION = "generation"
    TRANSLATION = "translation"
    SUMMARIZATION = "summarization"
    QUESTION_ANSWERING = "question_answering"
    REASONING = "reasoning"
    EXTRACTION = "extraction"


@dataclass
class ZeroShotTask:
    """A task to be performed without examples."""
    task_name: str
    category: TaskCategory
    instruction: str
    expected_output_format: Optional[str] = None
    constraints: List[str] = field(default_factory=list)


@dataclass
class ZeroShotResult:
    """Result from zero-shot execution."""
    task_name: str
    category: TaskCategory
    input: str
    output: str
    instruction_used: str
    confidence_estimate: Optional[float] = None
    timestamp: datetime = field(default_factory=datetime.now)


class ZeroShotAgent:
    """Agent that performs tasks without examples."""
    
    def __init__(self, name: str, model_name: str = "gpt-4", temperature: float = 0.7):
        self.name = name
        self.llm = ChatOpenAI(model=model_name, temperature=temperature)
        self.task_registry: Dict[str, ZeroShotTask] = {}
        self.results: List[ZeroShotResult] = []
    
    def register_task(self, task: ZeroShotTask):
        """Register a task the agent can perform."""
        self.task_registry[task.task_name] = task
        print(f"šŸ“‹ {self.name} registered task: {task.task_name} ({task.category.value})")
    
    def create_zero_shot_prompt(self, task: ZeroShotTask, input_text: str) -> str:
        """Create prompt for zero-shot execution."""
        prompt_parts = []
        
        # Task instruction
        prompt_parts.append(f"Task: {task.instruction}")
        
        # Output format if specified
        if task.expected_output_format:
            prompt_parts.append(f"\nExpected Output Format: {task.expected_output_format}")
        
        # Constraints if any
        if task.constraints:
            prompt_parts.append("\nConstraints:")
            for constraint in task.constraints:
                prompt_parts.append(f"- {constraint}")
        
        # The actual input
        prompt_parts.append(f"\nInput: {input_text}")
        prompt_parts.append("\nOutput:")
        
        return "\n".join(prompt_parts)
    
    def execute_task(self, task_name: str, input_text: str) -> ZeroShotResult:
        """Execute a registered task on input."""
        if task_name not in self.task_registry:
            raise ValueError(f"Task '{task_name}' not registered")
        
        task = self.task_registry[task_name]
        prompt_text = self.create_zero_shot_prompt(task, input_text)
        
        # Execute with LLM
        prompt = ChatPromptTemplate.from_messages([
            ("system", f"You are {self.name}, a capable AI assistant. "
                      f"Follow the instructions precisely and provide high-quality output."),
            ("human", "{prompt}")
        ])
        
        chain = prompt | self.llm | StrOutputParser()
        output = chain.invoke({"prompt": prompt_text})
        
        result = ZeroShotResult(
            task_name=task_name,
            category=task.category,
            input=input_text,
            output=output,
            instruction_used=task.instruction
        )
        
        self.results.append(result)
        return result
    
    def execute_adhoc(self, instruction: str, input_text: str, 
                     category: TaskCategory = TaskCategory.GENERATION) -> ZeroShotResult:
        """Execute an ad-hoc task without prior registration."""
        adhoc_task = ZeroShotTask(
            task_name=f"adhoc_{len(self.results)}",
            category=category,
            instruction=instruction
        )
        
        prompt_text = self.create_zero_shot_prompt(adhoc_task, input_text)
        
        prompt = ChatPromptTemplate.from_messages([
            ("system", f"You are {self.name}. Follow instructions and provide quality output."),
            ("human", "{prompt}")
        ])
        
        chain = prompt | self.llm | StrOutputParser()
        output = chain.invoke({"prompt": prompt_text})
        
        result = ZeroShotResult(
            task_name=adhoc_task.task_name,
            category=category,
            input=input_text,
            output=output,
            instruction_used=instruction
        )
        
        self.results.append(result)
        return result
    
    def get_statistics(self) -> Dict[str, Any]:
        """Get agent statistics."""
        category_counts = {}
        for result in self.results:
            cat = result.category.value
            category_counts[cat] = category_counts.get(cat, 0) + 1
        
        return {
            "name": self.name,
            "registered_tasks": len(self.task_registry),
            "total_executions": len(self.results),
            "tasks_by_category": category_counts
        }


class ZeroShotLearningPattern:
    """
    Zero-Shot Learning Pattern - Task execution without training examples.
    
    Leverages LLM's pre-trained knowledge to perform tasks based solely
    on natural language instructions, without any demonstration examples.
    """
    
    def __init__(self, model_name: str = "gpt-4"):
        self.model_name = model_name
        self.agents: Dict[str, ZeroShotAgent] = {}
        self.task_library: Dict[str, ZeroShotTask] = {}
    
    def create_agent(self, name: str) -> ZeroShotAgent:
        """Create a zero-shot capable agent."""
        agent = ZeroShotAgent(name, self.model_name)
        self.agents[name] = agent
        return agent
    
    def register_task_template(self, task: ZeroShotTask):
        """Register a task template in the library."""
        self.task_library[task.task_name] = task
        print(f"šŸ“š Task template registered: {task.task_name}")
    
    def create_task(self, task_name: str, category: TaskCategory, 
                   instruction: str, **kwargs) -> ZeroShotTask:
        """Create and register a task template."""
        task = ZeroShotTask(
            task_name=task_name,
            category=category,
            instruction=instruction,
            expected_output_format=kwargs.get('expected_output_format'),
            constraints=kwargs.get('constraints', [])
        )
        self.register_task_template(task)
        return task
    
    def assign_task_to_agent(self, agent_name: str, task_name: str):
        """Assign a task from library to an agent."""
        if agent_name not in self.agents:
            raise ValueError(f"Agent '{agent_name}' not found")
        if task_name not in self.task_library:
            raise ValueError(f"Task '{task_name}' not in library")
        
        agent = self.agents[agent_name]
        task = self.task_library[task_name]
        agent.register_task(task)
    
    def get_statistics(self) -> Dict[str, Any]:
        """Get pattern statistics."""
        return {
            "total_agents": len(self.agents),
            "task_templates": len(self.task_library),
            "agents": {name: agent.get_statistics() for name, agent in self.agents.items()}
        }


# Example usage
if __name__ == "__main__":
    print("=== Zero-Shot Learning Pattern Demo ===\n")
    
    # Create pattern
    print("1. Creating zero-shot learning pattern...")
    pattern = ZeroShotLearningPattern()
    
    # Create agent
    agent = pattern.create_agent("ZeroShotMaster")
    
    # Task 1: Text Classification
    print(f"\n{'='*70}")
    print("šŸ“ Task 1: Text Classification (Zero-Shot)")
    print(f"{'='*70}\n")
    
    classification_task = pattern.create_task(
        task_name="sentiment_classification",
        category=TaskCategory.CLASSIFICATION,
        instruction="Classify the sentiment of the given text as Positive, Negative, or Neutral.",
        expected_output_format="Single word: Positive, Negative, or Neutral",
        constraints=["Provide only the classification", "No explanation needed"]
    )
    
    pattern.assign_task_to_agent("ZeroShotMaster", "sentiment_classification")
    
    test_texts = [
        "This is absolutely fantastic! Best purchase ever!",
        "Completely disappointed. Waste of money.",
        "It's okay, does what it's supposed to do."
    ]
    
    print("Testing zero-shot classification:\n")
    for text in test_texts:
        result = agent.execute_task("sentiment_classification", text)
        print(f"Text: {result.input}")
        print(f"Classification: {result.output.strip()}\n")
    
    # Task 2: Question Answering
    print(f"\n{'='*70}")
    print("ā“ Task 2: Question Answering (Zero-Shot)")
    print(f"{'='*70}\n")
    
    qa_task = pattern.create_task(
        task_name="question_answering",
        category=TaskCategory.QUESTION_ANSWERING,
        instruction="Answer the question concisely based on general knowledge.",
        expected_output_format="2-3 sentences maximum",
        constraints=["Be factual and accurate", "Cite key points only"]
    )
    
    pattern.assign_task_to_agent("ZeroShotMaster", "question_answering")
    
    questions = [
        "What is the capital of France?",
        "How does photosynthesis work?",
        "Who wrote Romeo and Juliet?"
    ]
    
    print("Testing zero-shot Q&A:\n")
    for question in questions:
        result = agent.execute_task("question_answering", question)
        print(f"Q: {result.input}")
        print(f"A: {result.output.strip()}\n")
    
    # Task 3: Ad-hoc Execution (no prior registration)
    print(f"\n{'='*70}")
    print("šŸš€ Task 3: Ad-hoc Execution (Zero-Shot)")
    print(f"{'='*70}\n")
    
    adhoc_result = agent.execute_adhoc(
        instruction="Extract all email addresses from the text",
        input_text="Contact us at support@example.com or sales@company.org for more info.",
        category=TaskCategory.EXTRACTION
    )
    
    print(f"Instruction: {adhoc_result.instruction_used}")
    print(f"Input: {adhoc_result.input}")
    print(f"Extracted: {adhoc_result.output.strip()}\n")
    
    # Task 4: Translation
    print(f"\n{'='*70}")
    print("šŸŒ Task 4: Translation (Zero-Shot)")
    print(f"{'='*70}\n")
    
    translation_task = pattern.create_task(
        task_name="english_to_spanish",
        category=TaskCategory.TRANSLATION,
        instruction="Translate the English text to Spanish.",
        expected_output_format="Spanish translation only"
    )
    
    pattern.assign_task_to_agent("ZeroShotMaster", "english_to_spanish")
    
    translate_texts = [
        "Hello, how are you?",
        "The weather is beautiful today.",
        "I love learning new things."
    ]
    
    print("Testing zero-shot translation:\n")
    for text in translate_texts:
        result = agent.execute_task("english_to_spanish", text)
        print(f"English: {result.input}")
        print(f"Spanish: {result.output.strip()}\n")
    
    # Statistics
    print(f"\n{'='*70}")
    print("šŸ“Š Zero-Shot Learning Statistics")
    print(f"{'='*70}")
    
    stats = pattern.get_statistics()
    
    print(f"   Total agents: {stats['total_agents']}")
    print(f"   Task templates: {stats['task_templates']}")
    
    for agent_name, agent_stats in stats['agents'].items():
        print(f"\n   Agent: {agent_name}")
        print(f"   - Registered tasks: {agent_stats['registered_tasks']}")
        print(f"   - Total executions: {agent_stats['total_executions']}")
        print(f"   - Tasks by category:")
        for category, count in agent_stats['tasks_by_category'].items():
            print(f"     * {category}: {count}")
    
    print("\nāœ“ Zero-shot learning enabled task execution without examples!")

    

Agentic Architecture Pattern: Zero Shot Learning

Pattern 193: 193 Zero Shot Learning Pattern – Line-by-Line Explanation

Overview

Pattern 193: Zero-Shot Learning Pattern

LLM performs tasks without any training examples, relying solely on pre-trained knowledge. Demonstrates ability to generalize to new tasks using instructions alone.


Code Structure Analysis

File Information

  • Pattern Number: 193
  • Pattern Name: 193 Zero Shot Learning Pattern
  • File Path: patterns\llm_specific\193_zero_shot_learning_pattern.py
  • Total Lines: 343

Detailed Code Explanation

Module Docstring

"""
Pattern 193: Zero-Shot Learning Pattern

LLM performs tasks without any training examples, relying solely on pre-trained knowledge.
Demonstrates ability to generalize to new tasks using instructions alone.
"""

Explanation: This module docstring describes the purpose and key features of the 193 Zero Shot Learning Pattern 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_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI  # First 20 imports shown

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


Enumerations

TaskCategory (Line 17)

class TaskCategory(Enum):
    CLASSIFICATION
    GENERATION
    TRANSLATION
    SUMMARIZATION
    QUESTION_ANSWERING
    REASONING
    EXTRACTION

Purpose: Categories of zero-shot tasks.

Values: – CLASSIFICATION: Represents classification – GENERATION: Represents generation – TRANSLATION: Represents translation – SUMMARIZATION: Represents summarization – QUESTION_ANSWERING: Represents question answering – REASONING: Represents reasoning – EXTRACTION: Represents extraction


Classes

TaskCategory (Line 17)

Description: Categories of zero-shot tasks.

ZeroShotTask (Line 29)

Description: A task to be performed without examples.

ZeroShotResult (Line 39)

Description: Result from zero-shot execution.

ZeroShotAgent (Line 50)

Description: Agent that performs tasks without examples.

Methods:

__init__ (Line 53)
def __init__(self, name, model_name, temperature):
    """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”) – temperature: Randomness in LLM responses (0.0-1.0)

register_task (Line 59)
def register_task(self, task):
    """Register a task the agent can perform."""

Purpose: Register a task the agent can perform.

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

create_zero_shot_prompt (Line 64)
def create_zero_shot_prompt(self, task, input_text):
    """Create prompt for zero-shot execution."""

Purpose: Create prompt for zero-shot execution.

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

execute_task (Line 87)
def execute_task(self, task_name, input_text):
    """Execute a registered task on input."""

Purpose: Execute a registered task on input.

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

execute_adhoc (Line 116)
def execute_adhoc(self, instruction, input_text, category):
    """Execute an ad-hoc task without prior registration."""

Purpose: Execute an ad-hoc task without prior registration.

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

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

Purpose: Get agent statistics.

Parameters: – self: Instance reference

ZeroShotLearningPattern (Line 161)

Description: Zero-Shot Learning Pattern – Task execution without training examples.

Leverages LLM’s pre-trained knowledge to perform tasks based solely on natural language instructions, without any demonstration examples.

Methods:

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

create_agent (Line 174)
def create_agent(self, name):
    """Create a zero-shot capable agent."""

Purpose: Create a zero-shot capable agent.

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

register_task_template (Line 180)
def register_task_template(self, task):
    """Register a task template in the library."""

Purpose: Register a task template in the library.

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

create_task (Line 185)
def create_task(self, task_name, category, instruction):
    """Create and register a task template."""

Purpose: Create and register a task template.

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

assign_task_to_agent (Line 198)
def assign_task_to_agent(self, agent_name, task_name):
    """Assign a task from library to an agent."""

Purpose: Assign a task from library to an agent.

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

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

Purpose: Get pattern statistics.

Parameters: – self: Instance reference


Design Patterns Used

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

Usage Example

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

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *