Agentic Design Pattern: Output Format

Written by

in


    """
Pattern 086: Output Format Specification Pattern

Description:
    The Output Format Specification pattern explicitly defines the structure, format,
    and schema of the LLM's response. This pattern is crucial for integrating LLM
    outputs with downstream systems, APIs, and applications that require consistent,
    parseable, and structured data. By specifying the exact format upfront, this
    pattern eliminates ambiguity and ensures reliable programmatic processing.

    Format specification is essential for:
    - API integration and data exchange
    - Structured data extraction
    - Multi-step workflows with defined interfaces
    - Database storage and retrieval
    - User interface rendering
    - Automated testing and validation

Components:
    1. Format Type
       - JSON (JavaScript Object Notation)
       - XML (Extensible Markup Language)
       - YAML (YAML Ain't Markup Language)
       - CSV (Comma-Separated Values)
       - Markdown (formatted text)
       - Custom formats (domain-specific)

    2. Schema Definition
       - Field names and types
       - Required vs optional fields
       - Value constraints and ranges
       - Nested structures
       - Array/list specifications

    3. Format Enforcement
       - Clear examples in prompts
       - Schema validation
       - Error handling for format violations
       - Retry mechanisms
       - Fallback strategies

    4. Parsing and Validation
       - Automated parsing
       - Schema compliance checking
       - Type validation
       - Constraint verification
       - Error reporting

Use Cases:
    1. Data Extraction
       - Entity extraction from text → JSON
       - Information retrieval → structured records
       - Document parsing → database entries
       - Web scraping → CSV data
       - Form filling → key-value pairs

    2. API Integration
       - API request generation → JSON payloads
       - Response formatting → standardized structures
       - Webhook payloads → event schemas
       - Configuration files → YAML/JSON
       - Data exchange → XML documents

    3. Report Generation
       - Business reports → Markdown tables
       - Data summaries → formatted text
       - Analytics → JSON metrics
       - Documentation → structured sections
       - Dashboards → visualization specs

    4. Code Generation
       - Function signatures → specific syntax
       - Configuration files → language-specific format
       - Test cases → structured test specs
       - API documentation → OpenAPI/Swagger
       - Database schemas → SQL/DDL

    5. Content Creation
       - Blog posts → Markdown with frontmatter
       - Product descriptions → structured fields
       - Email templates → HTML with placeholders
       - Social media → platform-specific formats
       - Translations → parallel text structures

LangChain Implementation:
    LangChain provides excellent format control through:
    - StructuredOutputParser for schema-based parsing
    - JsonOutputParser for JSON responses
    - PydanticOutputParser for type-safe outputs
    - Custom output parsers for specific formats
    - Output fixing parser for auto-correction

Key Features:
    1. Type Safety
       - Pydantic models for validation
       - Automatic type checking
       - Type coercion when possible
       - Clear error messages

    2. Schema Validation
       - JSON Schema compliance
       - Custom validation rules
       - Nested object validation
       - Array element validation

    3. Error Recovery
       - Automatic retry with corrections
       - Format fixing parsers
       - Fallback to alternative formats
       - Graceful degradation

    4. Multiple Format Support
       - JSON (most common)
       - XML for legacy systems
       - CSV for tabular data
       - Markdown for documents
       - Custom formats as needed

Best Practices:
    1. Clear Format Specification
       - Provide explicit format examples
       - Use schema definitions when possible
       - Show complete structure (not partial)
       - Include edge cases in examples

    2. Validation Strategy
       - Validate immediately after generation
       - Provide clear error messages
       - Implement retry logic
       - Log format violations

    3. Error Handling
       - Graceful fallbacks
       - User-friendly error messages
       - Automatic format correction when possible
       - Manual intervention for critical failures

    4. Documentation
       - Document expected formats
       - Provide format examples
       - Explain field meanings
       - Note format versions

Trade-offs:
    Advantages:
    - Reliable programmatic processing
    - Easy integration with systems
    - Reduced parsing errors
    - Type safety and validation
    - Better error detection
    - Automated testing possible

    Disadvantages:
    - More rigid (less flexibility)
    - Format violations require handling
    - Increases prompt complexity
    - May constrain natural language quality
    - Requires careful schema design
    - Parsing overhead

Production Considerations:
    1. Schema Evolution
       - Version format schemas
       - Backward compatibility
       - Migration strategies
       - Deprecation policies

    2. Performance
       - Parsing efficiency
       - Validation overhead
       - Caching strategies
       - Batch processing

    3. Reliability
       - Retry logic for format errors
       - Format fixing mechanisms
       - Fallback formats
       - Monitoring and alerting

    4. Maintenance
       - Schema documentation
       - Format validation tests
       - Breaking change detection
       - Client SDK generation

    5. Security
       - Input sanitization
       - Injection prevention
       - Size limits
       - Type validation
"""

import os
import json
from typing import List, Dict, Any, Optional
from dataclasses import dataclass
from enum import Enum
from dotenv import load_dotenv
from pydantic import BaseModel, Field

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import (
    StrOutputParser,
    JsonOutputParser,
    PydanticOutputParser
)
from langchain_openai import ChatOpenAI

load_dotenv()


class OutputFormat(Enum):
    """Supported output formats"""
    JSON = "json"
    XML = "xml"
    MARKDOWN = "markdown"
    CSV = "csv"
    YAML = "yaml"


# Pydantic models for structured outputs
class Person(BaseModel):
    """Person entity"""
    name: str = Field(description="Full name of the person")
    age: Optional[int] = Field(description="Age in years", ge=0, le=150)
    email: Optional[str] = Field(description="Email address")
    occupation: Optional[str] = Field(description="Job title or occupation")


class Product(BaseModel):
    """Product information"""
    name: str = Field(description="Product name")
    category: str = Field(description="Product category")
    price: float = Field(description="Price in USD", gt=0)
    in_stock: bool = Field(description="Availability status")
    rating: Optional[float] = Field(description="Average rating", ge=0, le=5)


class Article(BaseModel):
    """Article/content structure"""
    title: str = Field(description="Article title")
    author: str = Field(description="Author name")
    summary: str = Field(description="Brief summary")
    tags: List[str] = Field(description="Content tags")
    word_count: int = Field(description="Approximate word count", gt=0)


class SentimentAnalysis(BaseModel):
    """Sentiment analysis result"""
    text: str = Field(description="Analyzed text")
    sentiment: str = Field(description="Sentiment: positive, negative, or neutral")
    confidence: float = Field(description="Confidence score", ge=0, le=1)
    keywords: List[str] = Field(description="Key terms identified")


@dataclass
class FormatConfig:
    """Configuration for format specification"""
    format_type: OutputFormat = OutputFormat.JSON
    strict_mode: bool = True
    temperature: float = 0.1  # Lower for more consistent formatting
    model_name: str = "gpt-3.5-turbo"


class OutputFormatAgent:
    """
    Agent that enforces specific output formats.
    
    This agent demonstrates:
    1. JSON format specification
    2. Pydantic-based type-safe outputs
    3. Multiple format support
    4. Schema validation
    """
    
    def __init__(self, config: Optional[FormatConfig] = None):
        """
        Initialize output format agent.
        
        Args:
            config: Configuration for format handling
        """
        self.config = config or FormatConfig()
        self.llm = ChatOpenAI(
            model=self.config.model_name,
            temperature=self.config.temperature
        )
    
    def extract_as_json(
        self,
        text: str,
        schema_description: str
    ) -> Dict[str, Any]:
        """
        Extract information in JSON format.
        
        Args:
            text: Text to extract from
            schema_description: Description of desired JSON structure
            
        Returns:
            Extracted data as dictionary
        """
        json_parser = JsonOutputParser()
        
        prompt = ChatPromptTemplate.from_messages([
            ("system", """Extract information from the text in JSON format.

Format requirements:
- Valid JSON only
- Follow the schema described
- Use appropriate data types
- Include all requested fields

{format_instructions}"""),
            ("human", "Extract from this text: {text}\n\nSchema: {schema}")
        ])
        
        chain = prompt | self.llm | json_parser
        
        try:
            result = chain.invoke({
                "text": text,
                "schema": schema_description,
                "format_instructions": json_parser.get_format_instructions()
            })
            return result
        except Exception as e:
            return {"error": str(e), "raw_text": text}
    
    def extract_person_info(self, text: str) -> Person:
        """
        Extract person information with type safety.
        
        Args:
            text: Text containing person information
            
        Returns:
            Person object with validated fields
        """
        parser = PydanticOutputParser(pydantic_object=Person)
        
        prompt = ChatPromptTemplate.from_messages([
            ("system", """Extract person information from the text.

{format_instructions}

Provide valid data for all available fields."""),
            ("human", "{text}")
        ])
        
        chain = prompt | self.llm | parser
        
        result = chain.invoke({
            "text": text,
            "format_instructions": parser.get_format_instructions()
        })
        
        return result
    
    def extract_product_info(self, text: str) -> Product:
        """
        Extract product information with validation.
        
        Args:
            text: Text containing product information
            
        Returns:
            Product object with validated fields
        """
        parser = PydanticOutputParser(pydantic_object=Product)
        
        prompt = ChatPromptTemplate.from_messages([
            ("system", """Extract product information from the text.

{format_instructions}

Ensure all data types are correct and constraints are met."""),
            ("human", "{text}")
        ])
        
        chain = prompt | self.llm | parser
        
        result = chain.invoke({
            "text": text,
            "format_instructions": parser.get_format_instructions()
        })
        
        return result
    
    def analyze_sentiment_structured(self, text: str) -> SentimentAnalysis:
        """
        Perform sentiment analysis with structured output.
        
        Args:
            text: Text to analyze
            
        Returns:
            SentimentAnalysis object with validated fields
        """
        parser = PydanticOutputParser(pydantic_object=SentimentAnalysis)
        
        prompt = ChatPromptTemplate.from_messages([
            ("system", """Analyze the sentiment of the text and provide results in the specified format.

{format_instructions}

- Sentiment must be: positive, negative, or neutral
- Confidence must be between 0 and 1
- Extract 3-5 relevant keywords"""),
            ("human", "{text}")
        ])
        
        chain = prompt | self.llm | parser
        
        result = chain.invoke({
            "text": text,
            "format_instructions": parser.get_format_instructions()
        })
        
        return result
    
    def generate_markdown_report(
        self,
        topic: str,
        sections: List[str]
    ) -> str:
        """
        Generate report in markdown format.
        
        Args:
            topic: Report topic
            sections: List of section titles
            
        Returns:
            Markdown formatted report
        """
        sections_list = "\n".join([f"- {s}" for s in sections])
        
        prompt = ChatPromptTemplate.from_messages([
            ("system", """Generate a report in Markdown format.

Format requirements:
- Use # for main title
- Use ## for section headers
- Use **bold** for emphasis
- Use bullet points (- ) for lists
- Use code blocks (```) for code
- Maintain consistent formatting"""),
            ("human", """Create a report on: {topic}

Include these sections:
{sections}""")
        ])
        
        chain = prompt | self.llm | StrOutputParser()
        
        result = chain.invoke({
            "topic": topic,
            "sections": sections_list
        })
        
        return result
    
    def generate_csv_format(
        self,
        data_description: str,
        num_rows: int = 5
    ) -> str:
        """
        Generate data in CSV format.
        
        Args:
            data_description: Description of data to generate
            num_rows: Number of data rows
            
        Returns:
            CSV formatted data
        """
        prompt = ChatPromptTemplate.from_messages([
            ("system", """Generate data in CSV format.

Format requirements:
- First row: column headers
- Subsequent rows: data values
- Use commas as separators
- Quote strings containing commas
- No extra whitespace
- Valid CSV syntax"""),
            ("human", """Generate {num_rows} rows of CSV data for: {description}""")
        ])
        
        chain = prompt | self.llm | StrOutputParser()
        
        result = chain.invoke({
            "description": data_description,
            "num_rows": num_rows
        })
        
        return result
    
    def generate_xml_format(self, data_description: str) -> str:
        """
        Generate data in XML format.
        
        Args:
            data_description: Description of data structure
            
        Returns:
            XML formatted data
        """
        prompt = ChatPromptTemplate.from_messages([
            ("system", """Generate data in XML format.

Format requirements:
- Proper XML declaration
- Well-formed tags (open and close)
- Proper nesting
- Attribute syntax when appropriate
- Valid XML structure"""),
            ("human", "Generate XML for: {description}")
        ])
        
        chain = prompt | self.llm | StrOutputParser()
        
        result = chain.invoke({"description": data_description})
        
        return result
    
    def compare_formats(self, data: str) -> Dict[str, str]:
        """
        Generate same data in multiple formats for comparison.
        
        Args:
            data: Data description
            
        Returns:
            Dictionary with data in different formats
        """
        formats = {}
        
        # JSON format
        json_result = self.extract_as_json(
            data,
            "Extract as JSON with appropriate fields"
        )
        formats["json"] = json.dumps(json_result, indent=2)
        
        # XML format
        formats["xml"] = self.generate_xml_format(data)
        
        # CSV format (if tabular)
        formats["csv"] = self.generate_csv_format(data, num_rows=3)
        
        return formats


def demonstrate_output_format():
    """Demonstrate output format specification patterns"""
    print("=" * 80)
    print("OUTPUT FORMAT SPECIFICATION PATTERN DEMONSTRATION")
    print("=" * 80)
    
    agent = OutputFormatAgent()
    
    # Example 1: JSON Extraction
    print("\n" + "=" * 80)
    print("EXAMPLE 1: JSON Format Extraction")
    print("=" * 80)
    
    text = "Apple Inc. released the iPhone 15 Pro in September 2023 priced at $999."
    schema = "Extract product name, company, release date, and price"
    print(f"\nText: {text}")
    print(f"Schema: {schema}\n")
    
    json_result = agent.extract_as_json(text, schema)
    print("JSON Output:")
    print(json.dumps(json_result, indent=2))
    
    # Example 2: Type-Safe Person Extraction
    print("\n" + "=" * 80)
    print("EXAMPLE 2: Type-Safe Person Information (Pydantic)")
    print("=" * 80)
    
    person_text = "Dr. Sarah Johnson is a 45-year-old cardiologist at Mayo Clinic. Her email is sarah.j@mayo.edu"
    print(f"\nText: {person_text}\n")
    
    person = agent.extract_person_info(person_text)
    print("Extracted Person (Type-Safe):")
    print(f"  Name: {person.name}")
    print(f"  Age: {person.age}")
    print(f"  Occupation: {person.occupation}")
    print(f"  Email: {person.email}")
    print(f"\nObject type: {type(person)}")
    
    # Example 3: Product Information
    print("\n" + "=" * 80)
    print("EXAMPLE 3: Structured Product Information")
    print("=" * 80)
    
    product_text = "The UltraBook Pro laptop in the Electronics category costs $1,299. Currently in stock with 4.5 star rating."
    print(f"\nText: {product_text}\n")
    
    product = agent.extract_product_info(product_text)
    print("Extracted Product:")
    print(f"  Name: {product.name}")
    print(f"  Category: {product.category}")
    print(f"  Price: ${product.price}")
    print(f"  In Stock: {product.in_stock}")
    print(f"  Rating: {product.rating}")
    
    # Example 4: Sentiment Analysis with Structure
    print("\n" + "=" * 80)
    print("EXAMPLE 4: Structured Sentiment Analysis")
    print("=" * 80)
    
    review = "This product is absolutely amazing! Best purchase I've made this year. Highly recommended!"
    print(f"\nReview: {review}\n")
    
    sentiment = agent.analyze_sentiment_structured(review)
    print("Sentiment Analysis Result:")
    print(f"  Sentiment: {sentiment.sentiment}")
    print(f"  Confidence: {sentiment.confidence:.2f}")
    print(f"  Keywords: {', '.join(sentiment.keywords)}")
    
    # Example 5: Markdown Report
    print("\n" + "=" * 80)
    print("EXAMPLE 5: Markdown Formatted Report")
    print("=" * 80)
    
    topic = "Quarterly Sales Performance"
    sections = ["Executive Summary", "Key Metrics", "Regional Analysis", "Recommendations"]
    print(f"\nTopic: {topic}")
    print(f"Sections: {sections}\n")
    
    markdown_report = agent.generate_markdown_report(topic, sections)
    print("Markdown Output:")
    print(markdown_report)
    
    # Example 6: CSV Format
    print("\n" + "=" * 80)
    print("EXAMPLE 6: CSV Format Generation")
    print("=" * 80)
    
    data_desc = "Employee records with name, department, salary, and hire date"
    print(f"\nData: {data_desc}\n")
    
    csv_data = agent.generate_csv_format(data_desc, num_rows=5)
    print("CSV Output:")
    print(csv_data)
    
    # Example 7: XML Format
    print("\n" + "=" * 80)
    print("EXAMPLE 7: XML Format Generation")
    print("=" * 80)
    
    xml_desc = "Book catalog with title, author, ISBN, and publication year"
    print(f"\nData: {xml_desc}\n")
    
    xml_data = agent.generate_xml_format(xml_desc)
    print("XML Output:")
    print(xml_data)
    
    # Summary
    print("\n" + "=" * 80)
    print("OUTPUT FORMAT SPECIFICATION SUMMARY")
    print("=" * 80)
    print("""
Output Format Pattern Benefits:
1. Programmatic Processing: Easy to parse and use in code
2. Type Safety: Validation ensures correct data types
3. Integration Ready: Works seamlessly with APIs and systems
4. Error Detection: Schema validation catches issues early
5. Documentation: Format serves as documentation
6. Testing: Enables automated testing

Key Formats Demonstrated:
1. JSON: Most common, flexible, widely supported
2. Pydantic Models: Type-safe Python objects with validation
3. Markdown: Human-readable formatted documents
4. CSV: Tabular data for spreadsheets
5. XML: Structured data for legacy systems

Format Specification Techniques:
1. Explicit Examples: Show exact format in prompt
2. Schema Definition: Use JSON Schema or Pydantic
3. Format Instructions: Parser-generated instructions
4. Validation: Automatic type and constraint checking
5. Error Recovery: Retry and fix malformed outputs

Best Practices:
1. Choose appropriate format for use case
   - JSON: APIs, web apps, general data
   - CSV: Tabular data, spreadsheets
   - XML: Legacy systems, complex hierarchies
   - Markdown: Documentation, reports
   
2. Use type safety when possible (Pydantic)
   - Automatic validation
   - IDE support
   - Clear error messages
   
3. Provide clear format instructions
   - Show complete examples
   - Specify all fields
   - Define data types and constraints
   
4. Handle format errors gracefully
   - Retry with corrections
   - Fallback formats
   - Clear error messages
   
5. Validate outputs
   - Schema compliance
   - Type checking
   - Constraint verification

Production Considerations:
- Lower temperature (0.1-0.3) for consistent formatting
- Implement retry logic for format violations
- Cache format instructions to save tokens
- Version schemas for evolution
- Monitor parsing success rates
- Log format errors for debugging
- Test edge cases thoroughly

Format Selection Guide:
- JSON: Default choice for most applications
- Pydantic: When type safety is critical
- CSV: For tabular data and spreadsheet integration
- XML: For legacy system compatibility
- Markdown: For human-readable documents
- YAML: For configuration files

Common Pitfalls:
- Insufficient format examples in prompts
- No validation of generated outputs
- Overly complex schemas
- Missing error handling
- Temperature too high (inconsistent outputs)
- Not handling optional fields properly
""")
    
    print("\n" + "=" * 80)
    print("Pattern 086 (Output Format Specification) demonstration complete!")
    print("=" * 80)


if __name__ == "__main__":
    demonstrate_output_format()

    

Agentic Design Pattern: Output Format

Pattern 086: Output Format – Line-by-Line Explanation

Overview

This document provides a detailed line-by-line explanation of the Output Format pattern implementation.


Pattern Description

Pattern 086: Output Format Specification Pattern

Description: The Output Format Specification pattern explicitly defines the structure, format, and schema of the LLM’s response. This pattern is crucial for integrating LLM outputs with downstream systems, APIs, and applications that require consistent, parseable, and structured data. By specifying the exact format upfront, this pattern eliminates ambiguity and ensures reliable programmatic processing.

Format specification is essential for:
- API integration and data exchange
- Structured data extraction
- Multi-step workflows with defined interfaces
- Database storage and retrieval
- User interface rendering
- Automated testing and validation

Components: 1. Format Type – JSON (JavaScript Object Notation) – XML (Extensible Markup Language) – YAML (YAML Ain’t Markup Language) – CSV (Comma-Separated Values) – Markdown (formatted text) – Custom formats (domain-specific)

2. Schema Definition
   - Field names and types
   - Required vs optional fields
   - Value constraints and ranges
   - Nested structures
   - Array/list specifications

3. Format Enforcement
   - Clear examples in prompts
   - Schema validation
   - Error handling for format violations
   - Retry mechanisms
   - Fallback strategies

4. Parsing and Validation
   - Automated parsing
   - Schema compliance checking
   - Type validation
   - Constraint verification
   - Error reporting

Use Cases: 1. Data Extraction – Entity extraction from text → JSON – Information retrieval → structured records – Document parsing → database entries – Web scraping → CSV data – Form filling → key-value pairs

2. API Integration
   - API request generation → JSON payloads
   - Response formatting → standardized structures
   - Webhook payloads → event schemas
   - Configuration files → YAML/JSON
   - Data exchange → XML documents

3. Report Generation
   - Business reports → Markdown tables
   - Data summaries → formatted text
   - Analytics → JSON metrics
   - Documentation → structured sections
   - Dashboards → visualization specs

4. Code Generation
   - Function signatures → specific syntax
   - Configuration files → language-specific format
   - Test cases → structured test specs
   - API documentation → OpenAPI/Swagger
   - Database schemas → SQL/DDL

5. Content Creation
   - Blog posts → Markdown with frontmatter
   - Product descriptions → structured fields
   - Email templates → HTML with placeholders
   - Social media → platform-specific formats
   - Translations → parallel text structures

LangChain Implementation: LangChain provides excellent format control through: – StructuredOutputParser for schema-based parsing – JsonOutputParser for JSON responses – PydanticOutputParser for type-safe outputs – Custom output parsers for specific formats – Output fixing parser for auto-correction

Key Features: 1. Type Safety – Pydantic models for validation – Automatic type checking – Type coercion when possible – Clear error messages

2. Schema Validation
   - JSON Schema compliance
   - Custom validation rules
   - Nested object validation
   - Array element validation

3. Error Recovery
   - Automatic retry with corrections
   - Format fixing parsers
   - Fallback to alternative formats
   - Graceful degradation

4. Multiple Format Support
   - JSON (most common)
   - XML for legacy systems
   - CSV for tabular data
   - Markdown for documents
   - Custom formats as needed

Best Practices: 1. Clear Format Specification – Provide explicit format examples – Use schema definitions when possible – Show complete structure (not partial) – Include edge cases in examples

2. Validation Strategy
   - Validate immediately after generation
   - Provide clear error messages
   - Implement retry logic
   - Log format violations

3. Error Handling
   - Graceful fallbacks
   - User-friendly error messages
   - Automatic format correction when possible
   - Manual intervention for critical failures

4. Documentation
   - Document expected formats
   - Provide format examples
   - Explain field meanings
   - Note format versions

Trade-offs: Advantages: – Reliable programmatic processing – Easy integration with systems – Reduced parsing errors – Type safety and validation – Better error detection – Automated testing possible

Disadvantages:
- More rigid (less flexibility)
- Format violations require handling
- Increases prompt complexity
- May constrain natural language quality
- Requires careful schema design
- Parsing overhead

Production Considerations: 1. Schema Evolution – Version format schemas – Backward compatibility – Migration strategies – Deprecation policies

2. Performance
   - Parsing efficiency
   - Validation overhead
   - Caching strategies
   - Batch processing

3. Reliability
   - Retry logic for format errors
   - Format fixing mechanisms
   - Fallback formats
   - Monitoring and alerting

4. Maintenance
   - Schema documentation
   - Format validation tests
   - Breaking change detection
   - Client SDK generation

5. Security
   - Input sanitization
   - Injection prevention
   - Size limits
   - Type validation

File Statistics

  • Total Lines: 751
  • Classes: 7
  • Functions: 1
  • Constants: 0

Module Documentation

"""
Pattern 086: Output Format Specification Pattern

Description:
    The Output Format Specification pattern explicitly defines the structure, format,
    and schema of the LLM's response. This pattern is crucial for integrating LLM
    outputs with downstream systems, APIs, and applications that require consistent,
    parseable, and structured data. By specifying the exact format upfront, this
    pattern eliminates ambiguity and ensures reliable programmatic processing.

    Format specification is essential for:
    - API integration and data exchange
    - Structured data extraction
    - Multi-step workflows with defined interfaces
    - Database storage and retrieval
    - User interface rendering
    - Automated testing and validation

Components:
    1. Format Type
       - JSON (JavaScript Object Notation)
       - XML (Extensible Markup Language)
       - YAML (YAML Ain't Markup Language)
       - CSV (Comma-Separated Values)
       - Markdown (formatted text)
       - Custom formats (domain-specific)

    2. Schema Definition
       - Field names and types
       - Required vs optional fields
       - Value constraints and ranges
       - Nested structures
       - Array/list specifications

    3. Format Enforcement
       - Clear examples in prompts
       - Schema validation
       - Error handling for format violations
       - Retry mechanisms
       - Fallback strategies

    4. Parsing and Validation
       - Automated parsing
       - Schema compliance checking
       - Type validation
       - Constraint verification
       - Error reporting

Use Cases:
    1. Data Extraction
       - Entity extraction from text → JSON
       - Information retrieval → structured records
       - Document parsing → database entries
       - Web scraping → CSV data
       - Form filling → key-value pairs

    2. API Integration
       - API request generation → JSON payloads
       - Response formatting → standardized structures
       - Webhook payloads → event schemas
       - Configuration files → YAML/JSON
       - Data exchange → XML documents

    3. Report Generation
       - Business reports → Markdown tables
       - Data summaries → formatted text
       - Analytics → JSON metrics
       - Documentation → structured sections
       - Dashboards → visualization specs

    4. Code Generation
       - Function signatures → specific syntax
       - Configuration files → language-specific format
       - Test cases → structured test specs
       - API documentation → OpenAPI/Swagger
       - Database schemas → SQL/DDL

    5. Content Creation
       - Blog posts → Markdown with frontmatter
       - Product descriptions → structured fields
       - Email templates → HTML with placeholders
       - Social media → platform-specific formats
       - Translations → parallel text structures

LangChain Implementation:
    LangChain provides excellent format control through:
    - StructuredOutputParser for schema-based parsing
    - JsonOutputParser for JSON responses
    - PydanticOutputParser for type-safe outputs
    - Custom output parsers for specific formats
    - Output fixing parser for auto-correction

Key Features:
    1. Type Safety
       - Pydantic models for validation
       - Automatic type checking
       - Type coercion when possible
       - Clear error messages

    2. Schema Validation
       - JSON Schema compliance
       - Custom validation rules
       - Nested object validation
       - Array element validation

    3. Error Recovery
       - Automatic retry with corrections
       - Format fixing parsers
       - Fallback to alternative formats
       - Graceful degradation

    4. Multiple Format Support
       - JSON (most common)
       - XML for legacy systems
       - CSV for tabular data
       - Markdown for documents
       - Custom formats as needed

Best Practices:
    1. Clear Format Specification
       - Provide explicit format examples
       - Use schema definitions when possible
       - Show complete structure (not partial)
       - Include edge cases in examples

    2. Validation Strategy
       - Validate immediately after generation
       - Provide clear error messages
       - Implement retry logic
       - Log format violations

    3. Error Handling
       - Graceful fallbacks
       - User-friendly error messages
       - Automatic format correction when possible
       - Manual intervention for critical failures

    4. Documentation
       - Document expected formats
       - Provide format examples
       - Explain field meanings
       - Note format versions

Trade-offs:
    Advantages:
    - Reliable programmatic processing
    - Easy integration with systems
    - Reduced parsing errors
    - Type safety and validation
    - Better error detection
    - Automated testing possible

    Disadvantages:
    - More rigid (less flexibility)
    - Format violations require handling
    - Increases prompt complexity
    - May constrain natural language quality
    - Requires careful schema design
    - Parsing overhead

Production Considerations:
    1. Schema Evolution
       - Version format schemas
       - Backward compatibility
       - Migration strategies
       - Deprecation policies

    2. Performance
       - Parsing efficiency
       - Validation overhead
       - Caching strategies
       - Batch processing

    3. Reliability
       - Retry logic for format errors
       - Format fixing mechanisms
       - Fallback formats
       - Monitoring and alerting

    4. Maintenance
       - Schema documentation
       - Format validation tests
       - Breaking change detection
       - Client SDK generation

    5. Security
       - Input sanitization
       - Injection prevention
       - Size limits
       - Type validation
"""

Purpose: This module implements the Output Format pattern, providing a structured approach to agent design and implementation.


Import Statements

Standard Library Imports

import dataclasses.dataclass
import enum.Enum
import json
import langchain_core.output_parsers.JsonOutputParser
import langchain_core.output_parsers.PydanticOutputParser
import langchain_core.output_parsers.StrOutputParser
import langchain_core.prompts.ChatPromptTemplate
import os
import typing.Any
import typing.Dict
import typing.List
import typing.Optional

Purpose: Core Python functionality: – dataclasses.dataclass: Simplified class definitions with @dataclass – enum.Enum: Enumeration support – json: JSON serialization/deserialization – langchain_core.output_parsers.JsonOutputParser: Regular expression operations – langchain_core.output_parsers.PydanticOutputParser: Regular expression operations – langchain_core.output_parsers.StrOutputParser: Regular expression operations – langchain_core.prompts.ChatPromptTemplate: Regular expression operations – os: Environment variable access and system operations – typing.Any: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Dict: Type hints for better code documentation (List, Dict, Any, Optional) – typing.List: Type hints for better code documentation (List, Dict, Any, Optional) – typing.Optional: Type hints for better code documentation (List, Dict, Any, Optional)

LangChain Imports

from langchain_openai.ChatOpenAI

Purpose: LangChain framework components: – LLM Interface: Wrapper for OpenAI models – Chains: Composable building blocks for complex workflows

Other Imports

from dotenv.load_dotenv
from pydantic.BaseModel
from pydantic.Field

Purpose: Additional dependencies for specialized functionality.


Classes

Class: OutputFormat

Lines 212-218

Inherits from: Enum

Purpose:

Supported output formats

Class: Person

Lines 222-227

Inherits from: BaseModel

Purpose:

Person entity

Class: Product

Lines 230-236

Inherits from: BaseModel

Purpose:

Product information

Class: Article

Lines 239-245

Inherits from: BaseModel

Purpose:

Article/content structure

Class: SentimentAnalysis

Lines 248-253

Inherits from: BaseModel

Purpose:

Sentiment analysis result

Class: FormatConfig

Lines 257-262

Purpose:

Configuration for format specification

Class: OutputFormatAgent

Lines 265-555

Purpose:

Agent that enforces specific output formats.

This agent demonstrates:
1. JSON format specification
2. Pydantic-based type-safe outputs
3. Multiple format support
4. Schema validation

Methods:

__init__(self, config)

Lines 276-287

Purpose:

Initialize output format agent.

Args:
    config: Configuration for format handling

Parameters: – config: Config

extract_as_json(self, text, schema_description)

Lines 289-329

Purpose:

Extract information in JSON format.

Args:
    text: Text to extract from
    schema_description: Description of desired JSON structure

Returns:
    Extracted data as dictionary

Parameters: – text: Text – schema_description: Schema description

Returns: <ast.Subscript object at 0x000001A06D63E910>

extract_person_info(self, text)

Lines 331-359

Purpose:

Extract person information with type safety.

Args:
    text: Text containing person information

Returns:
    Person object with validated fields

Parameters: – text: Text

Returns: Person

extract_product_info(self, text)

Lines 361-389

Purpose:

Extract product information with validation.

Args:
    text: Text containing product information

Returns:
    Product object with validated fields

Parameters: – text: Text

Returns: Product

analyze_sentiment_structured(self, text)

Lines 391-421

Purpose:

Perform sentiment analysis with structured output.

Args:
    text: Text to analyze

Returns:
    SentimentAnalysis object with validated fields

Parameters: – text: Text

Returns: SentimentAnalysis

generate_markdown_report(self, topic, sections)

Lines 423-463

Purpose:

Generate report in markdown format.

Args:
    topic: Report topic
    sections: List of section titles

Returns:
    Markdown formatted report

Parameters: – topic: Topic – sections: Sections

Returns: str

generate_csv_format(self, data_description, num_rows)

Lines 465-500

Purpose:

Generate data in CSV format.

Args:
    data_description: Description of data to generate
    num_rows: Number of data rows

Returns:
    CSV formatted data

Parameters: – data_description: Data description – num_rows: Num rows

Returns: str

generate_xml_format(self, data_description)

Lines 502-528

Purpose:

Generate data in XML format.

Args:
    data_description: Description of data structure

Returns:
    XML formatted data

Parameters: – data_description: Data description

Returns: str

compare_formats(self, data)

Lines 530-555

Purpose:

Generate same data in multiple formats for comparison.

Args:
    data: Data description

Returns:
    Dictionary with data in different formats

Parameters: – data: Data

Returns: <ast.Subscript object at 0x000001A06D83C910>


Functions

demonstrate_output_format()

Lines 558-746

Purpose:

Demonstrate output format specification patterns

Key Concepts Summary

Pattern Overview

The Output Format pattern provides a structured approach to building AI agents with specific capabilities and behaviors. This implementation leverages LangChain’s composable components to create a robust and maintainable solution.

Core Components

  1. Agent Class: Main implementation of the pattern logic
  2. Prompt Engineering: Carefully crafted prompts to guide LLM behavior
  3. Tool Integration: Optional tools for extended functionality
  4. Memory Management: State handling across interactions
  5. Output Parsing: Structured response processing

When to Use

✅ Good for: – Scenarios requiring this specific pattern’s strengths – Applications needing structured agent behavior – Systems where explainability is important – Production environments requiring reliability

❌ Not ideal for: – Simple single-prompt tasks – Scenarios requiring different pattern characteristics – Resource-constrained environments (if computationally intensive)


Best Practices Demonstrated

1. Environment Configuration

  • ✅ Use .env files for API keys
  • ✅ Never hardcode credentials
  • ✅ Validate environment variables on startup

2. Error Handling

  • ✅ Graceful degradation on failures
  • ✅ Informative error messages
  • ✅ Logging for debugging

3. Prompt Engineering

  • ✅ Clear, specific instructions
  • ✅ Structured output formats
  • ✅ Few-shot examples when beneficial

4. Code Organization

  • ✅ Separation of concerns (class-based design)
  • ✅ Type hints for clarity
  • ✅ Docstrings for documentation

5. Performance Optimization

  • ✅ Appropriate temperature settings
  • ✅ Token budget management
  • ✅ Caching where applicable

LangChain Components Used

  • ChatOpenAI: OpenAI model interface
  • Chains: Sequential component composition

Why LangChain? – Composable abstractions for LLM applications – Rich ecosystem of integrations – Production-ready patterns – Active community and development


Execution Flow

1. Initialize agent with configuration
   ↓
2. Load environment and dependencies
   ↓
3. Prepare prompt with input data
   ↓
4. Invoke LLM through LangChain
   ↓
5. Parse and validate response
   ↓
6. Return formatted result

Key Decision Points: – Model selection (temperature, model type) – Prompt structure (few-shot vs zero-shot) – Error handling strategy – Output format validation


Performance Considerations

Computational Cost

  • LLM Calls: Primary cost factor (based on tokens)
  • Latency: Depends on model and input size
  • Memory: Minimal for most patterns

Optimization Strategies

  1. Prompt Optimization: Minimize tokens while maintaining clarity
  2. Caching: Cache repeated queries/responses
  3. Model Selection: Use smaller models when appropriate
  4. Batch Processing: Group similar requests
  5. Streaming: For long responses, stream tokens

Cost Estimates (Approximate)

  • GPT-3.5-turbo: ~$0.002 per request
  • GPT-4: ~$0.03 per request
  • GPT-4-turbo: ~$0.01 per request

Actual costs vary based on input/output token counts


Common Pitfalls to Avoid

1. Prompt Design Issues

❌ Vague or ambiguous instructions
✅ Clear, specific, testable prompts

2. Error Handling

❌ Ignoring API errors or rate limits
✅ Implement retry logic and graceful degradation

3. Token Management

❌ Exceeding model token limits
✅ Truncate inputs, chunk processing

4. Security

❌ Exposing API keys in code
✅ Use environment variables

5. Testing

❌ Only testing happy paths
✅ Test edge cases, failures, malformed inputs

6. Cost Management

❌ Unmonitored API usage
✅ Implement budgets, alerts, and monitoring


Further Improvements

Production Enhancements

  1. Monitoring: Add logging, metrics, tracing
  2. Validation: Input/output schema validation
  3. Rate Limiting: Implement request throttling
  4. Caching: Redis or in-memory cache for responses
  5. Async Support: Non-blocking operations for scalability

Feature Extensions

  1. Multi-Model Support: Switch between providers
  2. Fallback Models: Graceful degradation strategy
  3. Custom Tools: Domain-specific function calling
  4. Advanced Memory: Vector stores for long-term memory
  5. Evaluation: Automated testing and benchmarking

Code Quality

  1. Testing: Unit tests, integration tests
  2. Documentation: API docs, usage examples
  3. Type Safety: Stricter type hints
  4. Configuration: Externalized config files

Related Patterns

  • Pattern 085
  • Pattern 087

Pattern Families: – Reasoning Patterns (001-011) – Multi-Agent Patterns (012-019) – Tool Use Patterns (020-025) – Memory Patterns (026-031) – And many more…


Summary

The Output Format pattern provides a powerful approach to building AI agents with specific capabilities. This implementation demonstrates:

✅ Key Strengths: – Clean, maintainable code structure – LangChain integration for composability – Type hints and documentation – Production-ready patterns

🎯 Best Use Cases: – Applications requiring this pattern’s characteristics – Systems needing structured agent behavior – Production environments requiring reliability

📚 Learning Resources: – LangChain Documentation: https://python.langchain.com/ – Pattern Documentation: See related patterns – OpenAI API Reference: https://platform.openai.com/docs/


File: 086_output_format.py
Total Lines: 751
Pattern Category: AI Agent Design Pattern #086


Generated from actual implementation code
For educational and reference purposes

Comments

Leave a Reply

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