Run ML models in isolated subprocess environments with automatic dependency management
Project description
pymodelserve
Run ML models in isolated subprocess environments with automatic dependency management.
Define your model once, and the library handles virtual environment creation, dependency installation, and inter-process communication via named pipes. Supports TensorFlow, PyTorch, or any Python ML framework with optional Django integration.
Installation
pip install pymodelserve
For Django integration:
pip install pymodelserve[django]
Quick Start
1. Create a Model
Create a directory structure for your model:
models/my_classifier/
├── model.yaml # Configuration
├── model.py # Client implementation
├── requirements.txt # Dependencies
└── weights/ # Model files (optional)
model.yaml:
name: my_classifier
version: "1.0.0"
python: ">=3.11"
client:
module: model
class: MyClassifierClient
requirements: requirements.txt
handlers:
- name: classify
input:
image_path: string
output:
class: string
confidence: float
model.py:
from pymodelserve import ModelClient, handler
class MyClassifierClient(ModelClient):
def setup(self):
# Load your model here
import tensorflow as tf
self.model = tf.keras.models.load_model("weights/model.keras")
@handler("classify")
def classify(self, image_path: str) -> dict:
# Your classification logic
return {"class": "cat", "confidence": 0.95}
if __name__ == "__main__":
MyClassifierClient().run()
2. Use the Model
from pymodelserve import ModelManager
# Using context manager (recommended)
with ModelManager.from_yaml("./models/my_classifier/model.yaml") as model:
result = model.request("classify", {"image_path": "/path/to/image.jpg"})
print(result) # {"class": "cat", "confidence": 0.95}
# Or manual lifecycle
manager = ModelManager.from_yaml("./models/my_classifier/model.yaml")
manager.start()
result = manager.request("classify", {"image_path": "/path/to/image.jpg"})
manager.stop()
3. Serve Models (CLI)
# Serve a single model
pml serve ./models/my_classifier/
# Serve all models in a directory
pml serve ./models/ --all
# List discovered models
pml list ./models/
# Create a new model scaffold
pml init my_new_model --framework tensorflow
Features
- Isolated Environments: Each model runs in its own virtual environment with isolated dependencies
- Named Pipe IPC: Fast inter-process communication with no network overhead
- Auto-Discovery: Scan directories for models and register them automatically
- Health Monitoring: Periodic health checks with automatic restart on failure
- Django Integration: Optional Django app with views and management commands
- CLI Tools: Commands for serving, testing, and managing models
Model Registry
Manage multiple models with the registry:
from pymodelserve import ModelRegistry
registry = ModelRegistry()
registry.register("fruit", "./models/fruit_classifier/")
registry.register("sentiment", "./models/sentiment/")
# Start all models
registry.start_all()
# Use specific model
result = registry.get("fruit").request("classify", {"image_path": "..."})
# Get status
print(registry.status())
# Stop all
registry.stop_all()
Or use auto-discovery:
from pymodelserve import discover_models, ModelRegistry
# Discover all models
configs = discover_models("./models/")
# Create registry from discovered models
registry = ModelRegistry()
registry.register_from_dir("./models/")
Health Monitoring
from pymodelserve import ModelRegistry
from pymodelserve.health import HealthChecker
registry = ModelRegistry()
registry.register_from_dir("./models/")
registry.start_all()
# Start health monitoring with auto-restart
checker = HealthChecker(
registry=registry,
interval=30, # Check every 30 seconds
max_failures=3, # Restart after 3 failures
auto_restart=True,
)
checker.start()
# ... your application runs ...
checker.stop()
registry.stop_all()
Django Integration
settings.py:
INSTALLED_APPS = [
...
'pymodelserve.contrib.django',
]
MLSERVE = {
"models_dir": BASE_DIR / "ml_models",
"auto_start": True,
"health_check_interval": 30,
}
views.py:
from pymodelserve.contrib.django.views import ModelAPIView
class ClassifyImageView(ModelAPIView):
model_name = "fruit_classifier"
handler = "classify"
def get_handler_input(self, request):
image = request.FILES["image"]
path = save_uploaded_file(image)
return {"image_path": str(path)}
urls.py:
from django.urls import path
from pymodelserve.contrib.django.views import GenericModelView, ModelStatusView
urlpatterns = [
# Generic endpoint for any model/handler
path("api/models/<str:model_name>/<str:handler>/", GenericModelView.as_view()),
# Status endpoint
path("api/models/status/", ModelStatusView.as_view()),
]
Management command:
python manage.py serve_models
python manage.py serve_models --model fruit_classifier --model sentiment
Client Implementation
The ModelClient base class runs in the subprocess and handles IPC:
from pymodelserve import ModelClient, handler
class MyModelClient(ModelClient):
def setup(self):
"""Called once after IPC is established, before processing requests."""
self.model = load_my_model()
def teardown(self):
"""Called when shutting down."""
cleanup_resources()
@handler("predict")
def predict(self, x: float, y: float) -> dict:
"""Handler methods receive kwargs and return dicts."""
result = self.model.predict([[x, y]])
return {"prediction": float(result[0])}
# Alternative: use handle_* naming pattern
def handle_info(self, **kwargs) -> dict:
return {"version": "1.0", "status": "ready"}
Configuration Reference
model.yaml:
name: my_model # Required: unique model name
version: "1.0.0" # Model version
python: ">=3.11" # Python version requirement
client:
module: model # Python module name (model.py)
class: MyModelClient # Class name in module
requirements: requirements.txt # Dependencies file
handlers: # Optional: document handlers
- name: predict
input:
x: float
output:
result: float
health:
interval: 30 # Health check interval (seconds)
timeout: 5 # Health check timeout
max_failures: 3 # Failures before restart
resources: # Optional: resource limits
memory_limit: 4G
cpu_limit: 2
gpu_ids: [0, 1] # CUDA_VISIBLE_DEVICES
License
MIT License - see LICENSE for details.
Project details
Release history Release notifications | RSS feed
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 pymodelserve-0.1.0.tar.gz.
File metadata
- Download URL: pymodelserve-0.1.0.tar.gz
- Upload date:
- Size: 95.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cff413eb9e357ff52dea1854c608a4d271f3250af5a340d7af82660e13e51754
|
|
| MD5 |
1b1a2df90668f88785dd2554c1347e6e
|
|
| BLAKE2b-256 |
4c96c6c5c56c5d80f76530f94cb86e6aaa3e9e762a015da32d35579a77a9813d
|
File details
Details for the file pymodelserve-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pymodelserve-0.1.0-py3-none-any.whl
- Upload date:
- Size: 34.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
950da854e3bb903833a3a02aa7bb9d872dac4d3f22dc94b713e95a3c68cf2ba0
|
|
| MD5 |
330087b86abe2c42adb2ed0e282a1074
|
|
| BLAKE2b-256 |
279408d6665293dd4e20243fd68b7db28f19e1a0dd221212c2c3f83036c838e5
|