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
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 defaultsconstructor_configuration()- Custom configuration setupglobal_defaults_configuration()- Setting application-wide defaultsprovider_specific_configurations()- Provider-specific examples
Usage Patterns¶
Master direct validation and fluent interface patterns.
Download: 02_usage_patterns.py
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 usagefluent_interface()- Chaining multiple validationsstrict_vs_non_strict()- Error handling modeserror_handling()- Exception management
Production Use Cases¶
Real-world scenarios and pipeline integration examples.
Download: 03_production_use_cases.py
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 filteringapi_response_validation()- LLM response validationci_cd_integration()- Automated testing integrationbatch_processing()- High-volume processingquality_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
TokenValidatorBaseImplement
count(text: str) -> intmethodUse singleton pattern with thread-safe
get_instance()Register with
TokenValidatorFactory.register_token_validator()
Semantic Validators:
Extend
SemanticValidatorBaseImplement
validate(text1: str, text2: str, threshold: float) -> ResultmethodUse 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}")