Examples

This section provides comprehensive examples demonstrating Aisert usage patterns from basic configuration to production deployment.

Configuration Examples

Learn different ways to configure Aisert for various providers and use cases.

Download: 01_configuration_examples.py

Configuration Options and Patterns
  1"""
  2Configuration Examples - Different ways to configure Aisert
  3
  4Shows all configuration options and patterns.
  5"""
  6
  7import sys
  8import os
  9sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 10
 11from aisert import AisertConfig
 12
 13
 14def default_configuration():
 15    """Using default configuration - no setup required."""
 16    print("=== Default Configuration ===")
 17    
 18    config = AisertConfig.get_default_config()
 19    print(f"Result: {config}")
 20    # Expected: AisertConfig(token(openai, gpt-3.5-turbo), semantic(openai, text-embedding-3-small))
 21
 22
 23def constructor_configuration():
 24    """Using constructor parameters for custom configuration."""
 25    print("\n=== Constructor Configuration ===")
 26    
 27    # Token counting only
 28    config1 = AisertConfig(token_provider="openai", token_model="gpt-4")
 29    print(f"Token only: {config1}")
 30    # Expected: AisertConfig(token(openai, gpt-4))
 31    
 32    # Semantic validation only
 33    config2 = AisertConfig(semantic_provider="sentence_transformers", semantic_model="all-MiniLM-L6-v2")
 34    print(f"Semantic only: {config2}")
 35    # Expected: AisertConfig(semantic(sentence_transformers, all-MiniLM-L6-v2))
 36    
 37    # Full configuration
 38    config3 = AisertConfig(
 39        token_provider="anthropic",
 40        token_model="claude-3",
 41        semantic_provider="tfidf"
 42    )
 43    print(f"Full config: {config3}")
 44    # Expected: AisertConfig(token(anthropic, claude-3), semantic(tfidf, None))
 45
 46
 47def global_defaults_configuration():
 48    """Setting global defaults for all future configurations."""
 49    print("\n=== Global Defaults Configuration ===")
 50    
 51    # Set custom global defaults
 52    AisertConfig.set_defaults(
 53        token_provider="anthropic",
 54        token_model="claude-3",
 55        semantic_provider="tfidf"
 56    )
 57    
 58    config = AisertConfig.get_default_config()
 59    print(f"Custom defaults: {config}")
 60    # Expected: AisertConfig(token(anthropic, claude-3), semantic(tfidf, text-embedding-3-small))
 61    
 62    # Reset to original defaults
 63    AisertConfig.set_defaults(
 64        token_provider="openai",
 65        token_model="gpt-3.5-turbo",
 66        semantic_provider="openai",
 67        semantic_model="text-embedding-3-small"
 68    )
 69
 70
 71def provider_specific_configurations():
 72    """Examples for different AI providers."""
 73    print("\n=== Provider-Specific Configurations ===")
 74    
 75    # OpenAI configuration
 76    openai_config = AisertConfig(
 77        token_provider="openai",
 78        token_model="gpt-4",
 79        token_encoding="cl100k_base",
 80        semantic_provider="openai",
 81        semantic_model="text-embedding-3-large"
 82    )
 83    print(f"OpenAI: {openai_config}")
 84    
 85    # Anthropic configuration
 86    anthropic_config = AisertConfig(
 87        token_provider="anthropic",
 88        token_model="claude-3-sonnet",
 89        semantic_provider="sentence_transformers",
 90        semantic_model="all-MiniLM-L6-v2"
 91    )
 92    print(f"Anthropic: {anthropic_config}")
 93    
 94    # Lightweight configuration (no heavy dependencies)
 95    lightweight_config = AisertConfig(
 96        semantic_provider="tfidf"  # No torch/transformers needed
 97    )
 98    print(f"Lightweight: {lightweight_config}")
 99
100
101if __name__ == "__main__":
102    print("🔧 Aisert Configuration Examples")
103    print("=" * 50)
104    
105    default_configuration()
106    constructor_configuration()
107    global_defaults_configuration()
108    provider_specific_configurations()
109    
110    print("\n✨ Configuration examples completed!")

Key topics covered:

  • Default configuration usage

  • Constructor-based configuration

  • Global defaults management

  • Provider-specific configurations

  • Lightweight vs full-featured setups

Functions in this example:

  • default_configuration() - Using built-in defaults

  • constructor_configuration() - Custom configuration setup

  • global_defaults_configuration() - Setting application-wide defaults

  • provider_specific_configurations() - Provider-specific examples

Usage Patterns

Master direct validation and fluent interface patterns.

Download: 02_usage_patterns.py

Direct Usage and Fluent Interface
  1"""
  2Usage Patterns - Direct validation and fluent interface examples
  3
  4Shows different ways to use Aisert for validation.
  5"""
  6
  7import sys
  8import os
  9sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 10
 11from aisert import Aisert, AisertConfig
 12from pydantic import BaseModel
 13
 14
 15class UserModel(BaseModel):
 16    name: str
 17    age: int
 18
 19
 20def direct_validation():
 21    """Direct validation - single validator per call."""
 22    print("=== Direct Validation ===")
 23    
 24    content = "Hello world, this is a test message."
 25    
 26    # Content validation
 27    result1 = Aisert(content).assert_contains(["Hello", "test"]).collect()
 28    print(f"Contains validation: {result1.status}")
 29    # Expected: True
 30    
 31    # Schema validation
 32    json_content = '{"name": "John", "age": 30}'
 33    result2 = Aisert(json_content).assert_schema(UserModel).collect()
 34    print(f"Schema validation: {result2.status}")
 35    # Expected: True
 36    
 37    # Token validation (requires config)
 38    config = AisertConfig(token_provider="openai", token_model="gpt-3.5-turbo")
 39    result3 = Aisert(content, config).assert_tokens(max_tokens=20).collect()
 40    print(f"Token validation: {result3.status}")
 41    # Expected: True (content is under 20 tokens)
 42
 43
 44def fluent_interface():
 45    """Fluent interface - chain multiple validations."""
 46    print("\n=== Fluent Interface ===")
 47    
 48    content = "AI and machine learning are transforming technology."
 49    config = AisertConfig(
 50        token_provider="openai",
 51        token_model="gpt-3.5-turbo",
 52        semantic_provider="openai",
 53        semantic_model="text-embedding-3-small"
 54    )
 55    
 56    # Chain multiple validations
 57    result = (Aisert(content, config)
 58             .assert_contains(["AI", "technology"])
 59             .assert_not_contains(["spam", "inappropriate"])
 60             .assert_tokens(max_tokens=50)
 61             .assert_semantic_matches("artificial intelligence technology", threshold=0.6)
 62             .collect())
 63    
 64    print(f"Chained validation: {result.status}")
 65    print(f"Validation count: {len(result.rules)}")
 66    # Expected: True, 4 validations
 67
 68
 69def strict_vs_non_strict():
 70    """Strict mode vs non-strict mode behavior."""
 71    print("\n=== Strict vs Non-Strict Modes ===")
 72    
 73    content = "Hello world"
 74    
 75    # Non-strict mode - collects all errors
 76    result = (Aisert(content)
 77             .assert_contains(["Hello"], strict=False)  # Pass
 78             .assert_contains(["missing"], strict=False)  # Fail but continue
 79             .assert_not_contains(["world"], strict=False)  # Fail but continue
 80             .collect())
 81    
 82    print(f"Non-strict mode - Overall: {result.status}")
 83    print(f"Individual results: {[v['status'] for v in result.rules.values()]}")
 84    # Expected: False, [True, False, False]
 85    
 86    # Strict mode - stops at first error
 87    try:
 88        result = (Aisert(content)
 89                 .assert_contains(["Hello"])  # Pass
 90                 .assert_contains(["missing"])  # Fail and raise exception
 91                 .collect())
 92        print("Strict mode completed")
 93    except Exception as e:
 94        print(f"Strict mode exception: {type(e).__name__}")
 95        # Expected: ContainsValidationError
 96
 97
 98def error_handling():
 99    """Proper error handling patterns."""
100    print("\n=== Error Handling ===")
101    
102    from aisert.exception import AisertError, ContainsValidationError
103    
104    content = "Test content"
105    
106    # Specific exception handling
107    try:
108        Aisert(content).assert_contains(["missing"]).collect()
109    except ContainsValidationError as e:
110        print(f"Caught specific error: {type(e).__name__}")
111        # Expected: ContainsValidationError
112    
113    # General exception handling
114    try:
115        Aisert("invalid json").assert_schema(UserModel).collect()
116    except AisertError as e:
117        print(f"Caught general error: {type(e).__name__}")
118        # Expected: SchemaValidationError
119    
120    # Graceful handling with non-strict mode
121    result = (Aisert(content)
122             .assert_contains(["Test"], strict=False)
123             .assert_contains(["missing"], strict=False)
124             .collect())
125    
126    if result.status:
127        print("All validations passed")
128    else:
129        failed = [v for v in result.rules.values() if not v['status']]
130        print(f"Failed validations: {len(failed)}")
131        # Expected: 1 failed validation
132
133
134if __name__ == "__main__":
135    print("🚀 Aisert Usage Patterns")
136    print("=" * 50)
137    
138    direct_validation()
139    fluent_interface()
140    strict_vs_non_strict()
141    error_handling()
142    
143    print("\n✨ Usage patterns completed!")

Key topics covered:

  • Direct validation (single validators)

  • Fluent interface (chained validations)

  • Strict vs non-strict modes

  • Error handling patterns

  • Exception hierarchy usage

Functions in this example:

  • direct_validation() - Single validator usage

  • fluent_interface() - Chaining multiple validations

  • strict_vs_non_strict() - Error handling modes

  • error_handling() - Exception management

Production Use Cases

Real-world scenarios and pipeline integration examples.

Download: 03_production_use_cases.py

Real-World Production Scenarios
  1"""
  2Production Use Cases - Real-world scenarios and pipeline integration
  3
  4Shows practical applications in production environments.
  5"""
  6
  7import sys
  8import os
  9sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 10
 11from aisert import Aisert, AisertConfig
 12from typing import List, Dict, Any
 13
 14
 15def content_moderation_pipeline():
 16    """Content moderation for user-generated content."""
 17    print("=== Content Moderation Pipeline ===")
 18    
 19    user_comments = [
 20        "Great product, really helpful!",
 21        "This spam content contains inappropriate language",
 22        "Excellent customer service, highly recommend!"
 23    ]
 24    
 25    flagged_terms = ["spam", "inappropriate", "offensive", "scam"]
 26    approved_count = 0
 27    
 28    for i, comment in enumerate(user_comments, 1):
 29        result = (Aisert(comment)
 30                 .assert_not_contains(flagged_terms, strict=False)
 31                 .collect())
 32        
 33        if result.status:
 34            print(f"Comment {i}: ✅ APPROVED")
 35            approved_count += 1
 36        else:
 37            print(f"Comment {i}: ❌ FLAGGED - {result.rules[1]['reason']}")
 38    
 39    print(f"Approval rate: {approved_count}/{len(user_comments)} ({approved_count/len(user_comments)*100:.1f}%)")
 40    # Expected: 2/3 approved (66.7%)
 41
 42
 43def api_response_validation():
 44    """Validate LLM API responses in production."""
 45    print("\n=== API Response Validation ===")
 46    
 47    config = AisertConfig(
 48        token_provider="openai",
 49        token_model="gpt-4",
 50        semantic_provider="openai",
 51        semantic_model="text-embedding-3-small"
 52    )
 53    
 54    # Simulate LLM responses
 55    responses = [
 56        "Thank you for your inquiry. I can help you with account setup.",
 57        "I cannot process this request due to insufficient information.",
 58        "Here's a comprehensive guide to getting started with our platform."
 59    ]
 60    
 61    valid_responses = 0
 62    for i, response in enumerate(responses, 1):
 63        result = (Aisert(response, config)
 64                 .assert_contains(["help", "information", "guide"], strict=False)  # Helpful content
 65                 .assert_not_contains(["error", "failed", "unavailable"], strict=False)  # No errors
 66                 .assert_tokens(max_tokens=100, strict=False)  # Reasonable length
 67                 .assert_semantic_matches("helpful customer service", threshold=0.6, strict=False)
 68                 .collect())
 69        
 70        if result.status:
 71            print(f"Response {i}: ✅ VALID")
 72            valid_responses += 1
 73        else:
 74            failed_checks = sum(1 for v in result.rules.values() if not v['status'])
 75            print(f"Response {i}: ❌ INVALID ({failed_checks} failed checks)")
 76    
 77    print(f"Valid responses: {valid_responses}/{len(responses)}")
 78    # Expected: Varies based on semantic similarity
 79
 80
 81def ci_cd_integration():
 82    """Integration with CI/CD pipelines for automated testing."""
 83    print("\n=== CI/CD Integration ===")
 84    
 85    def validate_generated_docs(content: str) -> bool:
 86        """Validate auto-generated documentation."""
 87        result = (Aisert(content)
 88                 .assert_contains(["API", "endpoint", "parameter"], strict=False)
 89                 .assert_not_contains(["TODO", "FIXME", "placeholder"], strict=False)
 90                 .assert_tokens(max_tokens=500, strict=False)
 91                 .collect())
 92        return result.status
 93    
 94    # Test documentation samples
 95    docs = [
 96        "API endpoint /users accepts GET requests with optional id parameter",
 97        "TODO: Add documentation for this endpoint",
 98        "This endpoint returns user data in JSON format with id, name, and email fields"
 99    ]
100    
101    passed_tests = 0
102    for i, doc in enumerate(docs, 1):
103        if validate_generated_docs(doc):
104            print(f"Doc {i}: ✅ PASS")
105            passed_tests += 1
106        else:
107            print(f"Doc {i}: ❌ FAIL")
108    
109    print(f"CI/CD Result: {passed_tests}/{len(docs)} tests passed")
110    # Expected: 2/3 tests pass (doc with TODO fails)
111    
112    # Simulate CI/CD exit code
113    exit_code = 0 if passed_tests == len(docs) else 1
114    print(f"Exit code: {exit_code}")
115
116
117def batch_processing():
118    """High-volume batch processing with performance optimization."""
119    print("\n=== Batch Processing ===")
120    
121    # Lightweight config for high-volume processing
122    config = AisertConfig(semantic_provider="tfidf")  # Fast, no model loading
123    
124    # Simulate large batch of content
125    batch_size = 100
126    content_batch = [f"User message {i} with some content to validate" for i in range(batch_size)]
127    
128    import time
129    start_time = time.time()
130    
131    processed = 0
132    valid_count = 0
133    
134    for content in content_batch:
135        result = (Aisert(content, config)
136                 .assert_not_contains(["spam", "inappropriate"], strict=False)
137                 .assert_semantic_matches("user message", threshold=0.3, strict=False)
138                 .collect())
139        
140        processed += 1
141        if result.status:
142            valid_count += 1
143    
144    processing_time = time.time() - start_time
145    
146    print(f"Processed: {processed} items")
147    print(f"Valid: {valid_count} ({valid_count/processed*100:.1f}%)")
148    print(f"Time: {processing_time:.2f}s ({processing_time/processed*1000:.1f}ms per item)")
149    print(f"Throughput: {processed/processing_time:.1f} items/second")
150    # Expected: High throughput with TFIDF (no model loading)
151
152
153def quality_monitoring():
154    """Monitor content quality in production with metrics."""
155    print("\n=== Quality Monitoring ===")
156    
157    class QualityMonitor:
158        def __init__(self):
159            self.metrics = {"total": 0, "passed": 0, "failed": 0}
160            self.config = AisertConfig(
161                token_provider="openai",
162                token_model="gpt-3.5-turbo"
163            )
164        
165        def validate_content(self, content: str, requirements: Dict[str, Any]) -> bool:
166            self.metrics["total"] += 1
167            
168            aisert = Aisert(content, self.config)
169            
170            if "required_terms" in requirements:
171                aisert.assert_contains(requirements["required_terms"], strict=False)
172            
173            if "forbidden_terms" in requirements:
174                aisert.assert_not_contains(requirements["forbidden_terms"], strict=False)
175            
176            if "max_tokens" in requirements:
177                aisert.assert_tokens(requirements["max_tokens"], strict=False)
178            
179            result = aisert.collect()
180            
181            if result.status:
182                self.metrics["passed"] += 1
183                return True
184            else:
185                self.metrics["failed"] += 1
186                return False
187        
188        def get_quality_score(self) -> float:
189            if self.metrics["total"] == 0:
190                return 0.0
191            return self.metrics["passed"] / self.metrics["total"]
192    
193    # Usage example
194    monitor = QualityMonitor()
195    
196    # Validate different content types
197    test_cases = [
198        ("Customer service response with helpful information", {"required_terms": ["helpful"], "max_tokens": 50}),
199        ("Product description with spam content", {"forbidden_terms": ["spam"], "max_tokens": 100}),
200        ("Technical documentation explaining the API", {"required_terms": ["API"], "max_tokens": 200})
201    ]
202    
203    for content, requirements in test_cases:
204        is_valid = monitor.validate_content(content, requirements)
205        print(f"Content valid: {is_valid}")
206    
207    quality_score = monitor.get_quality_score()
208    print(f"Overall quality score: {quality_score:.2f} ({quality_score*100:.1f}%)")
209    print(f"Metrics: {monitor.metrics}")
210    # Expected: Quality score based on validation results
211
212
213if __name__ == "__main__":
214    print("🏭 Aisert Production Use Cases")
215    print("=" * 50)
216    
217    content_moderation_pipeline()
218    api_response_validation()
219    ci_cd_integration()
220    batch_processing()
221    quality_monitoring()
222    
223    print("\n✨ Production use cases completed!")
224    print("💡 These patterns can be adapted for your specific production needs.")

Key topics covered:

  • Content moderation pipelines

  • API response validation

  • CI/CD integration

  • Batch processing optimization

  • Quality monitoring with metrics

Functions in this example:

  • content_moderation_pipeline() - User content filtering

  • api_response_validation() - LLM response validation

  • ci_cd_integration() - Automated testing integration

  • batch_processing() - High-volume processing

  • quality_monitoring() - Production metrics

Running Examples

To run these examples locally:

# Install Aisert with optional dependencies
pip install aisert[all]

# Set environment variables (for API-based validation)
export OPENAI_API_KEY="your-openai-key"
export ANTHROPIC_API_KEY="your-anthropic-key"

# Run examples in order
python examples/01_configuration_examples.py
python examples/02_usage_patterns.py
python examples/03_production_use_cases.py

Prerequisites (for running examples)

Basic Installation:

pip install aisert

Optional Dependencies:

# For semantic validation with sentence-transformers
pip install aisert[sentence-transformers]

# For HuggingFace models
pip install aisert[huggingface]

# For all features
pip install aisert[all]

Custom Validators

Aisert supports bringing your own token and semantic validators by extending the base classes.

Custom Token Validator

Create custom token validators by extending TokenValidatorBase:

from aisert.validators.token_validator.token_validator_base import TokenValidatorBase
from aisert.validators.token_validator.token_validator_factory import TokenValidatorFactory
from aisert.exception import TokenValidationError
import threading

class CustomTokenValidator(TokenValidatorBase):
    """Custom token validator example."""
    _instances = {}
    _lock = threading.RLock()

    def __init__(self, model_name: str):
        super().__init__(model_provider="custom")
        self.model_name = model_name

    @classmethod
    def get_instance(cls, token_model: str = None, **kwargs):
        with cls._lock:
            if token_model not in cls._instances:
                cls._instances[token_model] = cls(token_model)
            return cls._instances[token_model]

    def count(self, text: str) -> int:
        """Implement your custom token counting logic."""
        # Example: simple word count
        return len(text.split())

# Register the custom validator
TokenValidatorFactory.register_token_validator("custom", CustomTokenValidator)

# Usage
config = AisertConfig(token_provider="custom", token_model="my-model")
result = Aisert("Hello world", config).assert_tokens(max_tokens=5).collect()

Custom Semantic Validator

Create custom semantic validators by extending SemanticValidatorBase:

from aisert.validators.semantic_validator.semantic_validator_base import SemanticValidatorBase
from aisert.validators.semantic_validator.semantic_validator_factory import SemanticValidatorFactory
from aisert.exception import SemanticValidationError
from aisert.models.result import Result
import threading

class CustomSemanticValidator(SemanticValidatorBase):
    """Custom semantic validator example."""
    _instances = {}
    _lock = threading.RLock()

    def __init__(self, model_name: str = None):
        super().__init__()
        self.model_name = model_name or "custom-model"

    @classmethod
    def get_instance(cls, model_name: str = None, **kwargs):
        key = model_name or "default"
        with cls._lock:
            if key not in cls._instances:
                cls._instances[key] = cls(model_name)
            return cls._instances[key]

    def validate(self, text1: str, text2: str, threshold: float = 0.8) -> Result:
        """Implement your custom semantic similarity logic."""
        if not (0 <= threshold <= 1):
            raise SemanticValidationError("Threshold must be between 0 and 1")

        # Example: simple keyword overlap similarity
        words1 = set(text1.lower().split())
        words2 = set(text2.lower().split())
        similarity = len(words1 & words2) / len(words1 | words2) if words1 | words2 else 0

        if similarity < threshold:
            raise SemanticValidationError(
                f"Custom similarity score: {similarity:.3f} is less than threshold: {threshold}"
            )

        return Result(self.validator_name, True,
                     f"Custom similarity score: {similarity:.3f}, Threshold: {threshold}")

# Register the custom validator
SemanticValidatorFactory.register_semantic_validator("custom", CustomSemanticValidator)

# Usage
config = AisertConfig(semantic_provider="custom", semantic_model="my-model")
result = Aisert("Hello world", config).assert_semantic_matches("Hi world", 0.5).collect()

Key Implementation Points

Token Validators:

  • Extend TokenValidatorBase

  • Implement count(text: str) -> int method

  • Use singleton pattern with thread-safe get_instance()

  • Register with TokenValidatorFactory.register_token_validator()

Semantic Validators:

  • Extend SemanticValidatorBase

  • Implement validate(text1: str, text2: str, threshold: float) -> Result method

  • Use singleton pattern with thread-safe get_instance()

  • Register with SemanticValidatorFactory.register_semantic_validator()

Best Practices:

  • Use thread-safe singleton pattern for performance

  • Handle errors gracefully with appropriate exceptions

  • Validate input parameters (e.g., threshold range)

  • Return descriptive error messages

  • Cache expensive operations (models, connections)

Complete Custom Validator Example

Download: custom_validators_example.py

# Complete working example
from aisert import Aisert, AisertConfig
from aisert.validators.token_validator.token_validator_base import TokenValidatorBase
from aisert.validators.token_validator.token_validator_factory import TokenValidatorFactory
from aisert.validators.semantic_validator.semantic_validator_base import SemanticValidatorBase
from aisert.validators.semantic_validator.semantic_validator_factory import SemanticValidatorFactory
from aisert.models.result import Result
import threading

# Custom implementations here...
# (See full example in downloadable file)

if __name__ == "__main__":
    # Test custom validators
    config = AisertConfig(
        token_provider="custom",
        token_model="word-counter",
        semantic_provider="custom",
        semantic_model="keyword-overlap"
    )

    result = (
        Aisert("Hello world from custom validators", config)
        .assert_tokens(max_tokens=10)
        .assert_semantic_matches("Hi world custom", threshold=0.3)
        .collect()
    )

    print(f"Custom validation result: {result.status}")