04 Production Ready
This guide assumes you completed the earlier tutorials and are working with AdaptShot v0.1.1. Focus: robustness, debugging, efficiency, and measuring energy.
1. Handling Real-World Errors
When calling AdaptShot APIs, handle runtime and validation exceptions from src/adaptshot/utils/exceptions.py:
AdaptShotError(base class)InvalidImageError(image path/format/dimensionality problems)ConfigValidationError(bad configuration values)CalibrationNotReadyError(calibration window needs more examples)BufferCapacityError(buffer/pruning issues)
Use explicit try/except patterns so your service degrades gracefully. Example:
from adaptshot.core.learner import FewShotLearner
from adaptshot.utils.exceptions import AdaptShotError, InvalidImageError, CalibrationNotReadyError
learner = FewShotLearner()
try:
learner.load_support_images([], [])
except AdaptShotError as exc:
# Print exact message shown by the library for diagnostics
print("AdaptShotError:", str(exc))
except Exception as exc:
print("Unexpected error:", exc)
# Typical exact messages you may see:
# "Support set cannot be empty. Provide at least one RGB image path and label. See docs/getting-started/quickstart.md."
# "Image file not found: '<path>'. Verify the path and try again."
# "Expected 3-channel RGB image, got <n>-channel mode '<mode>' from '<source>'. Convert before loading. See docs/getting-started/quickstart.md."
# Calibration-specific message template:
# "Calibration window is not ready. Need at least {min_samples} observations, got {observed}. Continue collecting feedback with correct()."
Table: Common exceptions and exact messages
| Exception | Example exact message (what you'll see) |
|---|---|
ConfigValidationError |
"n_way and k_shot must be positive integers." (from src/adaptshot/config/settings.py) |
InvalidImageError |
"Image file not found: '_load_rgb_image_from_path in src/adaptshot/core/learner.py) |
InvalidImageError |
"Expected 3-channel RGB image, got 1-channel grayscale array. Convert before loading. See docs/getting-started/quickstart.md." (see _normalize_predict_image) |
AdaptShotError |
"State file not found: 'FewShotLearner.load) |
AdaptShotError |
"Checkpoint integrity check failed. The checkpoint may be corrupted or tampered with." (see _load_state_payload) |
CalibrationNotReadyError |
"Calibration window is not ready. Need at least {min_samples} observations, got {observed}. Continue collecting feedback with correct()." (see _calibrate_or_raise) |
Try/Except patterns for production
- Validation errors (bad config or inputs): return HTTP 400 with the message.
- Missing files or corrupted checkpoints: return HTTP 500 and alert operator; include exact message to logs.
- Calibration not ready: accept predictions but flag for human review; surface message to UI so users can provide corrections.
Example: robust prediction endpoint (Flask-style, simplified)
from flask import Flask, jsonify, request
from adaptshot.core.learner import FewShotLearner
from adaptshot.utils.exceptions import AdaptShotError
app = Flask(__name__)
learner = FewShotLearner()
@app.route('/predict', methods=['POST'])
def predict():
try:
image_path = request.json['path']
res = learner.predict(image_path)
return jsonify({'prediction': str(res.prediction), 'confidence': res.calibrated_confidence})
except AdaptShotError as exc:
app.logger.error(str(exc))
return jsonify({'error': str(exc)}), 400
except Exception as exc:
app.logger.exception('Unhandled error')
return jsonify({'error': 'internal server error'}), 500
# Expected errors in logs: exact strings from exceptions in the repo
2. Optimizing for Low-Power Devices
Key knobs in src/adaptshot/config/settings.py:
eco_mode(bool): enable cheaper preview checks and early exits.early_exit_threshold(float): threshold between 0.5 and 1.0 (default 0.95) controlling early-exit aggressiveness.backbone("resnet18" | "mobilenet_v3_small"): choosemobilenet_v3_smallto reduce compute at some accuracy tradeoff.
Tradeoffs:
| Goal | Setting |
|---|---|
| Minimize energy & latency | eco_mode=True, backbone="mobilenet_v3_small", lower early_exit_threshold (e.g., 0.9) |
| Maximize accuracy | eco_mode=False, backbone="resnet18", keep early_exit_threshold high (0.98+) |
Runnable example: enable eco-mode and run the energy smoke test
python -m benchmarks.energy_profile --smoke-test --seed 42 --eco-mode --early-exit-threshold 0.9
# Expected: JSON printed with keys including "joules_estimate", "co2_g_estimate", "latency_avg_s", and "eco_mode": true
Notes:
- Default backbone is
resnet18. Switch tomobilenet_v3_smallinAdaptShotConfig(backbone="mobilenet_v3_small")for lower compute. Seesrc/adaptshot/config/settings.py. early_exit_thresholdmust be within [0.5, 1.0] orAdaptShotConfig.__post_init__will raise: "early_exit_threshold must be within [0.5, 1.0]."
3. Measuring Energy & Carbon
Use benchmarks/energy_profile.py to run a deterministic smoke test and estimate energy and CO₂. Key output fields (exact keys in output JSON):
latency_avg_s— average per-query latency (seconds)latency_p95_s— 95th percentile latency (seconds)joules_estimate— rough energy estimate (Joules)co2_g_estimate— estimated CO₂ equivalent (grams)accuracy— deterministic accuracy on synthetic dataeco_mode— whether eco-mode was enabled
Run the smoke test (repository root):
python -m benchmarks.energy_profile --smoke-test --seed 42
# Output: printed JSON with baseline and eco variants and fields above
Interpreting results:
- Joules → energy consumed; high values mean more power draw. Use
joules_estimatefor rough comparisons across backbones andeco_modesettings. - CO₂ → multiply by local grid intensity to estimate local footprint; the benchmark uses a conservative default. See
GRID_INTENSITY_CO2_PER_JOULEinbenchmarks/energy_profile.py. - Optimize when energy per prediction matters (edge devices, battery-powered). Prioritize accuracy when errors are costly.
4. Debugging Like a Pro
Logging setup (recommended)
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('adaptshot')
logger.setLevel(logging.DEBUG) # in staging only
Symptoms → root cause → fix (table)
| Symptom | Likely root cause | Fix |
|---|---|---|
Image file not found error |
Wrong path or missing upload | Verify file path, permissions; log full path; return 400 to client |
Expected 3-channel RGB image |
Grayscale or wrong image format | Convert images to RGB before sending; validate on upload |
Support set cannot be empty |
Initialization order bug | Ensure load_support_images() is called before predict(); fail fast with 400 |
Checkpoint integrity check failed |
Corrupted or tampered checkpoint | Recreate checkpoint via save() or restore from backup; log checksum mismatch |
| Slow predictions / high latency | Using heavy backbone or high-resolution images | Switch to mobilenet_v3_small, enable eco_mode, or downscale images |
Mermaid troubleshooting flowchart (copy into MkDocs with mermaid enabled):
flowchart TD
A[Prediction Error] --> B{Is it file-related?}
B -- Yes --> C[Check file path & permissions]
B -- No --> D{Is it model/config?}
D -- Config --> E[Check AdaptShotConfig values]
D -- Model --> F[Check checkpoints & integrity]
E --> G[Fix config, restart service]
F --> H[Recreate checkpoint or restore backup]
Determinism checks
- Use
src/adaptshot/utils/determinism.pyhelpers called inbenchmarks/energy_profile.pyto verify deterministic behavior across runs. Determinism helps reproducible profiling.
5. Deployment Checklist
Use this checklist before rolling to production:
- [ ] Confirm
AdaptShotConfig(device='cpu')andtorchfalls back to CPU. - [ ] Set
max_buffer_sizeto an appropriate value (>=10) to avoidValueError("max_buffer_size must be >= 10 for meaningful few-shot operation.")fromAdaptShotConfig. - [ ] Validate checkpoint integrity:
FewShotLearner.load()will raise: "Checkpoint integrity check failed. The checkpoint may be corrupted or tampered with." if mismatch. - [ ] Run
benchmarks/energy_profile.py --smoke-testand recordjoules_estimateandco2_g_estimate. - [ ] Enable logging and monitor
adaptshotlogs forAdaptShotErroroccurrences. - [ ] Add human-in-the-loop corrections in UI; ensure
learner.correct()is reachable andconfidence_weightis captured (0.0 -> 1.0).
Exact runtime checks (commands)
# Run smoke benchmark
python -m benchmarks.energy_profile --smoke-test --seed 42 --output results/energy_profile.json
# Quick import test
python -c "import sys, os; sys.path.insert(0, os.path.join(os.getcwd(),'src')); from adaptshot.core.learner import FewShotLearner; print('OK')"
6. Best Practices Summary
- Prefer
device='cpu'and validate it in staging to match production constraints. - Use
eco_mode+mobilenet_v3_smallfor energy-sensitive deployments; measure impact withbenchmarks/energy_profile.py. - Surface clear error messages from
src/adaptshot/utils/exceptions.pyto users and logs. - Keep checkpoints small and verify integrity at load time; automate backups.
- Add a simple human feedback loop to collect corrections — this improves calibration and reduces costly mistakes.
7. Verification Checklist
- [ ] My service catches and logs
AdaptShotErrorsubclasses and returns user-friendly errors. - [ ] I can enable
eco_modeand observe reducedlatency_avg_sin the benchmark output. - [ ] I can run
benchmarks/energy_profile.py --smoke-testand readjoules_estimateandco2_g_estimatefrom the results JSON. - [ ] I can reproduce a
Checkpoint integrity check failed.error by corrupting a checkpoint and seeing the exact message in logs. - [ ] My deployment enforces
device='cpu',max_buffer_size>=10, and has a human correction route callinglearner.correct().
Created by Johnson Christopher Hassan
Connect on LinkedIn
Project: github.com/johnson2006christopher/adaptshot