A type-safe graph execution framework built on top of OpenLit for LLM pipelines
Project description
Hapax: Type-Safe Graph Execution Framework
Hapax is a powerful Python framework for building type-safe, observable data processing pipelines. Built on top of OpenLit, it provides multi-stage type checking, rich error messages, and comprehensive monitoring out of the box.
Features
✨ Multi-Stage Type Safety
- Import-time type validation through
@opsdecorator - Definition-time type checking when building graphs
- Runtime type validation during execution
- Rich error messages that pinpoint issues
🔍 Static Analysis
- Graph structure validation
- Cycle detection
- Type compatibility verification
- Configuration and metadata checks
📊 OpenLit Integration
- Automatic monitoring and observability
- Execution time tracking
- Success/failure rates
- Graph visualization
🎮 Intuitive API
- Fluent interface for building pipelines
- Type-safe operation composition using
>> - Rich control flow (branch, merge, condition, loop)
Quick Start
- Install Hapax:
pip install hapax
- Create your first pipeline:
from hapax import ops, graph
import openlit
from typing import List, Dict
# Initialize OpenLit (optional but recommended)
openlit.init(otlp_endpoint="http://127.0.0.1:4318")
# Define operations - type checked at import time
@ops(name="clean_text")
def clean_text(text: str) -> str:
return text.lower().strip()
@ops(name="tokenize")
def tokenize(text: str) -> List[str]:
return text.split()
@ops(name="analyze")
def analyze(tokens: List[str]) -> Dict[str, int]:
from collections import Counter
return dict(Counter(tokens))
# Build pipeline - type compatibility checked at definition time
pipeline = (
Graph("text_processing")
.then(clean_text) # str -> str
.then(tokenize) # str -> List[str]
.then(analyze) # List[str] -> Dict[str, int]
)
# Execute pipeline - types checked at runtime
result = pipeline.execute("Hello World! Hello Hapax!")
Core Concepts
1. Operations
Operations are pure functions with multi-stage type checking:
@ops(name="summarize", tags=["nlp"])
def summarize(text: str) -> str:
"""Generate a concise summary."""
return summary
# Type checking happens at:
# 1. Import time - through @ops decorator
# 2. Definition time - when used in a graph
# 3. Runtime - during execution
result = summarize(42) # Runtime TypeError: Expected str, got int
2. Graph Building
Build complex pipelines with immediate type validation:
# Using the fluent API - type compatibility checked at definition time
pipeline = (
Graph("text_analysis")
.then(clean_text) # str -> str
.branch(
summarize, # str -> str
sentiment_analysis # str -> float
)
.merge(combine_results)
)
# Or using the >> operator for composition
pipeline = clean_text >> tokenize >> analyze # Type compatibility checked immediately
3. Control Flow
Rich control flow operations with type safety:
# Parallel Processing
pipeline = (
Graph("parallel_nlp")
.branch(
summarize, # Branch 1: str -> str
extract_entities, # Branch 2: str -> List[str]
analyze_sentiment # Branch 3: str -> float
)
.merge(lambda results: {
"summary": results[0],
"entities": results[1],
"sentiment": results[2]
})
)
# Conditional Logic
pipeline = (
Graph("smart_translate")
.then(detect_language)
.condition(
lambda lang: lang != "en",
translate_to_english, # If true
lambda x: x # If false (pass through)
)
)
OpenLit Integration
Hapax is built on OpenLit for automatic monitoring:
# 1. Basic Setup
import openlit
openlit.init(otlp_endpoint="http://localhost:4318")
# 2. Operation-Level Monitoring
@ops(
name="tokenize",
tags=["nlp"],
openlit_config={
"trace_content": True,
"disable_metrics": False
}
)
def tokenize(text: str) -> List[str]:
return text.split()
# 3. Graph-Level Monitoring
@graph(
name="nlp_pipeline",
description="Process text using NLP"
)
def process_text(text: str) -> Dict[str, Any]:
return clean >> analyze
Error Handling
Hapax provides clear error messages:
# Type Mismatch
TypeError: Cannot compose operations: output type List[str] does not match input type Dict[str, Any]
# Structural Issues
GraphValidationError: Graph contains cycles: [['op1', 'op2', 'op1']]
# Runtime Errors
BranchError: Errors in branches: [('sentiment', ValueError('Invalid input'))]
Best Practices
-
Type Safety
- Always specify input and output types
- Let Hapax handle type validation
- Use mypy for additional static checking
-
Operation Design
- Keep operations pure and focused
- Use meaningful names
- Add proper documentation
-
Monitoring
- Initialize OpenLit early
- Add meaningful tags
- Use trace_content for debugging
-
Error Handling
- Handle branch errors appropriately
- Check partial results in case of failures
- Use the rich error information
Documentation
For more detailed information, check out:
License
MIT License - see LICENSE for details.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hapax-0.1.4.tar.gz.
File metadata
- Download URL: hapax-0.1.4.tar.gz
- Upload date:
- Size: 23.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.29
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6bdf25da0c8687a3f9508ee92c3489b16743b820d28044c5993e68cd543b2a8
|
|
| MD5 |
17909287f4e1f6f2d581eaf3e180ac6b
|
|
| BLAKE2b-256 |
b968a319ce8b7e971330f1bd166ae9b2a1ca3e139c79c7c712bfc5758908d009
|
File details
Details for the file hapax-0.1.4-py3-none-any.whl.
File metadata
- Download URL: hapax-0.1.4-py3-none-any.whl
- Upload date:
- Size: 24.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.29
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a90c4985f9fd9a57c76399e0b535b6b1fbe8179fd6043559b88c4b07db166f98
|
|
| MD5 |
42ad2e1d1741004086ff00f88e7b646f
|
|
| BLAKE2b-256 |
6ca8cd8b435a42cd323f0766b4ff46710f263dd120328196588e19c151961a48
|