iints-sdk-python35 1.1.1__tar.gz → 1.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {iints_sdk_python35-1.1.1/src/iints_sdk_python35.egg-info → iints_sdk_python35-1.1.3}/PKG-INFO +28 -6
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/README.md +27 -5
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/pyproject.toml +2 -1
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/__init__.py +9 -1
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/ai/__init__.py +2 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/ai/backends/ollama.py +84 -1
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/ai/cli.py +157 -20
- iints_sdk_python35-1.1.3/src/iints/ai/prepare.py +342 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/cli/cli.py +29 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3/src/iints_sdk_python35.egg-info}/PKG-INFO +28 -6
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints_sdk_python35.egg-info/SOURCES.txt +2 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints_sdk_python35.egg-info/entry_points.txt +1 -0
- iints_sdk_python35-1.1.3/tests/test_install_doctor.py +32 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/LICENSE +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/setup.cfg +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/ai/assistant.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/ai/backends/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/ai/backends/base.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/ai/backends/mistral_api.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/ai/mdmp_guard.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/ai/model_catalog.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/ai/prompts.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/algorithm_xray.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/baseline.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/clinical_benchmark.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/clinical_metrics.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/clinical_tir_analyzer.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/diabetes_metrics.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/edge_efficiency.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/edge_performance_monitor.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/explainability.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/explainable_ai.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/hardware_benchmark.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/metrics.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/population_report.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/reporting.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/safety_index.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/sensor_filtering.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/analysis/validator.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/api/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/api/base_algorithm.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/api/registry.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/api/template_algorithm.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/assets/iints_logo.png +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/cli/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/algorithms/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/algorithms/battle_runner.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/algorithms/correction_bolus.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/algorithms/discovery.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/algorithms/fixed_basal_bolus.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/algorithms/hybrid_algorithm.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/algorithms/lstm_algorithm.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/algorithms/mock_algorithms.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/algorithms/pid_controller.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/algorithms/standard_pump_algo.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/device.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/device_manager.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/devices/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/devices/models.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/patient/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/patient/bergman_model.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/patient/models.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/patient/patient_factory.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/patient/profile.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/safety/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/safety/config.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/safety/input_validator.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/safety/supervisor.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/simulation/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/simulation/scenario_parser.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/simulator.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/core/supervisor.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/adapter.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/column_mapper.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/contracts.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/datasets.json +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/demo/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/demo/demo_cgm.csv +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/guardians.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/importer.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/ingestor.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/mdmp_visualizer.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/nightscout.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/quality_checker.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/registry.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/runner.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/synthetic_mirror.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/tidepool.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/universal_parser.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/virtual_patients/clinic_safe_baseline.yaml +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/virtual_patients/clinic_safe_hyper_challenge.yaml +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/virtual_patients/clinic_safe_hypo_prone.yaml +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/virtual_patients/clinic_safe_midnight.yaml +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/virtual_patients/clinic_safe_pizza.yaml +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/virtual_patients/clinic_safe_stress_meal.yaml +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/virtual_patients/default_patient.yaml +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/data/virtual_patients/patient_559_config.yaml +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/emulation/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/emulation/legacy_base.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/emulation/medtronic_780g.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/emulation/omnipod_5.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/emulation/tandem_controliq.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/highlevel.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/learning/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/learning/autonomous_optimizer.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/learning/learning_system.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/mdmp/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/mdmp/backend.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/metrics.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/population/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/population/generator.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/population/runner.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/presets/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/presets/evidence_sources.yaml +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/presets/forecast_calibration_profiles.yaml +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/presets/golden_benchmark.yaml +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/presets/presets.json +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/presets/safety_contract_default.yaml +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/presets/validation_profiles.yaml +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/research/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/research/audit.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/research/calibration_gate.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/research/config.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/research/dataset.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/research/evaluation.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/research/losses.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/research/metrics.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/research/model_registry.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/research/predictor.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/scenarios/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/scenarios/generator.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/templates/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/templates/default_algorithm.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/templates/scenarios/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/templates/scenarios/chaos_insulin_stacking.json +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/templates/scenarios/chaos_runaway_ai.json +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/templates/scenarios/example_scenario.json +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/templates/scenarios/exercise_stress.json +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/utils/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/utils/plotting.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/utils/run_io.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/validation/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/validation/golden.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/validation/replay.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/validation/run_validation.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/validation/safety_contract.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/validation/schemas.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/visualization/__init__.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/visualization/cockpit.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints/visualization/uncertainty_cloud.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints_sdk_python35.egg-info/dependency_links.txt +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints_sdk_python35.egg-info/requires.txt +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/src/iints_sdk_python35.egg-info/top_level.txt +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/tests/test_bergman.py +0 -0
- {iints_sdk_python35-1.1.1 → iints_sdk_python35-1.1.3}/tests/test_population.py +0 -0
{iints_sdk_python35-1.1.1/src/iints_sdk_python35.egg-info → iints_sdk_python35-1.1.3}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iints-sdk-python35
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.3
|
|
4
4
|
Summary: A pre-clinical Edge-AI SDK for diabetes management validation.
|
|
5
5
|
Author-email: Rune Bobbaers <rune.bobbaers@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/python35/IINTS-SDK
|
|
@@ -110,15 +110,23 @@ ollama pull ministral-3:8b
|
|
|
110
110
|
iints ai local-check --model ministral-3:8b
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
`local-check` now performs a tiny generation smoke-test by default, so it verifies both model presence and real inference readiness.
|
|
114
|
+
|
|
115
|
+
Recommended flow:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
iints quickstart --project-name iints_quickstart
|
|
119
|
+
cd iints_quickstart
|
|
120
|
+
iints presets run --name baseline_t1d --algo algorithms/example_algorithm.py
|
|
121
|
+
iints ai prepare results/<run_id>
|
|
122
|
+
iints ai report results/<run_id>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Direct JSON mode still works if you already have your own payloads and signed MDMP artifact:
|
|
114
126
|
|
|
115
127
|
```bash
|
|
116
128
|
iints ai explain results/step.json \
|
|
117
129
|
--mdmp-cert results/report.signed.mdmp
|
|
118
|
-
|
|
119
|
-
iints ai report results/simulation_run.json \
|
|
120
|
-
--mdmp-cert results/report.signed.mdmp \
|
|
121
|
-
--output results/ai_report.md
|
|
122
130
|
```
|
|
123
131
|
|
|
124
132
|
Notes:
|
|
@@ -127,8 +135,22 @@ Notes:
|
|
|
127
135
|
- The SDK now targets the open local `Ministral 3` Ollama model by default.
|
|
128
136
|
- Users can choose a larger or smaller local Mistral-family model with `--model ...`.
|
|
129
137
|
- Large JSON payloads are clipped automatically before prompt generation to keep local inference stable.
|
|
138
|
+
- `iints ai prepare <run_dir>` now creates AI-ready JSON payloads and, when MDMP is installed, a local development certificate plus keypair in `<run_dir>/ai/`.
|
|
139
|
+
- If Ollama closes the connection during generation, the SDK now surfaces an explicit recovery hint and points users toward `ministral-3:3b` for lower-memory systems.
|
|
140
|
+
- After `iints ai prepare`, you can point `iints ai explain|trends|anomalies|report` directly at the run directory.
|
|
130
141
|
- Output is research-only and not medical advice.
|
|
131
142
|
|
|
143
|
+
Troubleshooting:
|
|
144
|
+
- If `iints ai ...` says `No such command 'ai'`, your environment usually still has a legacy `iints` package installed alongside `iints-sdk-python35`.
|
|
145
|
+
- Run `iints-sdk-doctor` first.
|
|
146
|
+
- If it reports a conflict, repair the environment with:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
python -m pip uninstall -y iints iints-sdk-python35
|
|
150
|
+
python -m pip install -U "iints-sdk-python35[mdmp]==1.1.3"
|
|
151
|
+
hash -r
|
|
152
|
+
```
|
|
153
|
+
|
|
132
154
|
## MDMP (Short)
|
|
133
155
|
MDMP is the data-quality protocol used by IINTS.
|
|
134
156
|
|
|
@@ -59,15 +59,23 @@ ollama pull ministral-3:8b
|
|
|
59
59
|
iints ai local-check --model ministral-3:8b
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
`local-check` now performs a tiny generation smoke-test by default, so it verifies both model presence and real inference readiness.
|
|
63
|
+
|
|
64
|
+
Recommended flow:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
iints quickstart --project-name iints_quickstart
|
|
68
|
+
cd iints_quickstart
|
|
69
|
+
iints presets run --name baseline_t1d --algo algorithms/example_algorithm.py
|
|
70
|
+
iints ai prepare results/<run_id>
|
|
71
|
+
iints ai report results/<run_id>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Direct JSON mode still works if you already have your own payloads and signed MDMP artifact:
|
|
63
75
|
|
|
64
76
|
```bash
|
|
65
77
|
iints ai explain results/step.json \
|
|
66
78
|
--mdmp-cert results/report.signed.mdmp
|
|
67
|
-
|
|
68
|
-
iints ai report results/simulation_run.json \
|
|
69
|
-
--mdmp-cert results/report.signed.mdmp \
|
|
70
|
-
--output results/ai_report.md
|
|
71
79
|
```
|
|
72
80
|
|
|
73
81
|
Notes:
|
|
@@ -76,8 +84,22 @@ Notes:
|
|
|
76
84
|
- The SDK now targets the open local `Ministral 3` Ollama model by default.
|
|
77
85
|
- Users can choose a larger or smaller local Mistral-family model with `--model ...`.
|
|
78
86
|
- Large JSON payloads are clipped automatically before prompt generation to keep local inference stable.
|
|
87
|
+
- `iints ai prepare <run_dir>` now creates AI-ready JSON payloads and, when MDMP is installed, a local development certificate plus keypair in `<run_dir>/ai/`.
|
|
88
|
+
- If Ollama closes the connection during generation, the SDK now surfaces an explicit recovery hint and points users toward `ministral-3:3b` for lower-memory systems.
|
|
89
|
+
- After `iints ai prepare`, you can point `iints ai explain|trends|anomalies|report` directly at the run directory.
|
|
79
90
|
- Output is research-only and not medical advice.
|
|
80
91
|
|
|
92
|
+
Troubleshooting:
|
|
93
|
+
- If `iints ai ...` says `No such command 'ai'`, your environment usually still has a legacy `iints` package installed alongside `iints-sdk-python35`.
|
|
94
|
+
- Run `iints-sdk-doctor` first.
|
|
95
|
+
- If it reports a conflict, repair the environment with:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
python -m pip uninstall -y iints iints-sdk-python35
|
|
99
|
+
python -m pip install -U "iints-sdk-python35[mdmp]==1.1.3"
|
|
100
|
+
hash -r
|
|
101
|
+
```
|
|
102
|
+
|
|
81
103
|
## MDMP (Short)
|
|
82
104
|
MDMP is the data-quality protocol used by IINTS.
|
|
83
105
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "iints-sdk-python35"
|
|
7
|
-
version = "1.1.
|
|
7
|
+
version = "1.1.3"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Rune Bobbaers", email="rune.bobbaers@gmail.com" },
|
|
10
10
|
]
|
|
@@ -65,6 +65,7 @@ mdmp = [
|
|
|
65
65
|
|
|
66
66
|
[project.scripts]
|
|
67
67
|
iints = "iints.cli.cli:app"
|
|
68
|
+
iints-sdk-doctor = "iints_sdk_python35_doctor:main"
|
|
68
69
|
|
|
69
70
|
[project.entry-points."iints.algorithms"]
|
|
70
71
|
"PID Controller" = "iints.core.algorithms.pid_controller:PIDController"
|
|
@@ -3,7 +3,15 @@
|
|
|
3
3
|
import pandas as pd # Required for type hints like pd.DataFrame
|
|
4
4
|
from typing import Optional
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
try:
|
|
7
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
8
|
+
except ImportError: # pragma: no cover - Python < 3.8 fallback
|
|
9
|
+
from importlib_metadata import PackageNotFoundError, version # type: ignore
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
__version__ = version("iints-sdk-python35")
|
|
13
|
+
except PackageNotFoundError: # pragma: no cover - source tree fallback
|
|
14
|
+
__version__ = "1.1.3"
|
|
7
15
|
|
|
8
16
|
# Note to developers: this SDK is currently maintained by a single author.
|
|
9
17
|
# Please report bugs via GitHub issues and feel free to contribute fixes via PRs.
|
|
@@ -2,6 +2,7 @@ from .assistant import AIResponse, IINTSAssistant
|
|
|
2
2
|
from .backends import DEFAULT_MINISTRAL_MODEL, DEFAULT_OLLAMA_HOST, OllamaBackend
|
|
3
3
|
from .mdmp_guard import GuardResult, MDMPGuard
|
|
4
4
|
from .model_catalog import LocalMistralModelProfile, list_local_mistral_models
|
|
5
|
+
from .prepare import prepare_ai_ready_artifacts
|
|
5
6
|
|
|
6
7
|
__all__ = [
|
|
7
8
|
"AIResponse",
|
|
@@ -13,4 +14,5 @@ __all__ = [
|
|
|
13
14
|
"MDMPGuard",
|
|
14
15
|
"LocalMistralModelProfile",
|
|
15
16
|
"list_local_mistral_models",
|
|
17
|
+
"prepare_ai_ready_artifacts",
|
|
16
18
|
]
|
|
@@ -2,6 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
|
+
from http.client import IncompleteRead, RemoteDisconnected
|
|
6
|
+
from time import sleep
|
|
5
7
|
from urllib import error, request
|
|
6
8
|
|
|
7
9
|
|
|
@@ -40,6 +42,20 @@ class OllamaBackend:
|
|
|
40
42
|
def _pull_hint(self) -> str:
|
|
41
43
|
return f"ollama pull {self.model_name}"
|
|
42
44
|
|
|
45
|
+
def _generation_failure_hint(self) -> str:
|
|
46
|
+
resolved = self.resolved_model_name or self.model_name
|
|
47
|
+
return (
|
|
48
|
+
"Ollama closed the generation connection before returning a response.\n"
|
|
49
|
+
f"Endpoint: {self.base_url}\n"
|
|
50
|
+
f"Model: {resolved}\n"
|
|
51
|
+
"This usually means the model crashed while loading, the daemon restarted, "
|
|
52
|
+
"or the machine ran out of memory.\n"
|
|
53
|
+
"Try one of these:\n"
|
|
54
|
+
f" 1. Run `ollama run {resolved} \"Reply with OK.\"` to confirm direct inference works.\n"
|
|
55
|
+
" 2. Run `iints ai local-check --smoke-test` to validate a real generation path.\n"
|
|
56
|
+
" 3. Switch to a smaller local model such as `ministral-3:3b` if memory is tight."
|
|
57
|
+
)
|
|
58
|
+
|
|
43
59
|
def _requires_ministral_3_runtime(self) -> bool:
|
|
44
60
|
requested = self.model_name.strip().lower()
|
|
45
61
|
return requested.startswith("ministral-3") or requested == "ministral"
|
|
@@ -68,6 +84,15 @@ class OllamaBackend:
|
|
|
68
84
|
payload: dict[str, object] | None = None,
|
|
69
85
|
*,
|
|
70
86
|
method: str = "POST",
|
|
87
|
+
) -> dict[str, object]:
|
|
88
|
+
return self._request_json_once(path, payload, method=method)
|
|
89
|
+
|
|
90
|
+
def _request_json_once(
|
|
91
|
+
self,
|
|
92
|
+
path: str,
|
|
93
|
+
payload: dict[str, object] | None = None,
|
|
94
|
+
*,
|
|
95
|
+
method: str = "POST",
|
|
71
96
|
) -> dict[str, object]:
|
|
72
97
|
url = f"{self.base_url}{path}"
|
|
73
98
|
body = None
|
|
@@ -92,6 +117,12 @@ class OllamaBackend:
|
|
|
92
117
|
f"Could not reach Ollama at {self.base_url}. "
|
|
93
118
|
"Start Ollama or set OLLAMA_HOST to the correct endpoint."
|
|
94
119
|
) from exc
|
|
120
|
+
except (RemoteDisconnected, ConnectionResetError, IncompleteRead) as exc:
|
|
121
|
+
if path == "/api/generate":
|
|
122
|
+
raise RuntimeError(self._generation_failure_hint()) from exc
|
|
123
|
+
raise RuntimeError(
|
|
124
|
+
f"Ollama connection closed unexpectedly while calling {path} at {self.base_url}."
|
|
125
|
+
) from exc
|
|
95
126
|
|
|
96
127
|
try:
|
|
97
128
|
payload_json = json.loads(text)
|
|
@@ -223,6 +254,43 @@ class OllamaBackend:
|
|
|
223
254
|
"version_ok": version_ok,
|
|
224
255
|
}
|
|
225
256
|
|
|
257
|
+
def smoke_test(self) -> dict[str, object]:
|
|
258
|
+
resolved_model = self.ensure_model_ready()
|
|
259
|
+
payload = {
|
|
260
|
+
"model": resolved_model,
|
|
261
|
+
"system": "You are a health check. Reply with exactly: OK",
|
|
262
|
+
"prompt": "Reply with exactly: OK",
|
|
263
|
+
"stream": False,
|
|
264
|
+
"options": {
|
|
265
|
+
"temperature": 0,
|
|
266
|
+
"num_predict": 8,
|
|
267
|
+
},
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
last_error: Exception | None = None
|
|
271
|
+
for attempt in range(2):
|
|
272
|
+
try:
|
|
273
|
+
response = self._request_json_once("/api/generate", payload)
|
|
274
|
+
text = response.get("response")
|
|
275
|
+
if not isinstance(text, str) or not text.strip():
|
|
276
|
+
raise RuntimeError("Ollama returned an empty smoke-test completion.")
|
|
277
|
+
return {
|
|
278
|
+
"ok": True,
|
|
279
|
+
"response": text.strip(),
|
|
280
|
+
"attempts": attempt + 1,
|
|
281
|
+
}
|
|
282
|
+
except (RuntimeError, RemoteDisconnected, ConnectionResetError, IncompleteRead) as exc:
|
|
283
|
+
if not isinstance(exc, RuntimeError):
|
|
284
|
+
exc = RuntimeError(self._generation_failure_hint())
|
|
285
|
+
last_error = exc
|
|
286
|
+
if attempt == 0:
|
|
287
|
+
sleep(1.0)
|
|
288
|
+
continue
|
|
289
|
+
break
|
|
290
|
+
|
|
291
|
+
assert last_error is not None
|
|
292
|
+
raise last_error
|
|
293
|
+
|
|
226
294
|
def complete(self, *, system_prompt: str, user_prompt: str) -> str:
|
|
227
295
|
resolved_model = self.ensure_model_ready()
|
|
228
296
|
payload = {
|
|
@@ -231,7 +299,22 @@ class OllamaBackend:
|
|
|
231
299
|
"prompt": user_prompt,
|
|
232
300
|
"stream": False,
|
|
233
301
|
}
|
|
234
|
-
|
|
302
|
+
last_error: Exception | None = None
|
|
303
|
+
for attempt in range(2):
|
|
304
|
+
try:
|
|
305
|
+
response = self._request_json_once("/api/generate", payload)
|
|
306
|
+
break
|
|
307
|
+
except (RuntimeError, RemoteDisconnected, ConnectionResetError, IncompleteRead) as exc:
|
|
308
|
+
if not isinstance(exc, RuntimeError):
|
|
309
|
+
exc = RuntimeError(self._generation_failure_hint())
|
|
310
|
+
last_error = exc
|
|
311
|
+
if attempt == 0:
|
|
312
|
+
sleep(1.0)
|
|
313
|
+
continue
|
|
314
|
+
raise exc
|
|
315
|
+
else:
|
|
316
|
+
assert last_error is not None
|
|
317
|
+
raise last_error
|
|
235
318
|
text = response.get("response")
|
|
236
319
|
if not isinstance(text, str) or not text.strip():
|
|
237
320
|
raise RuntimeError("Ollama returned an empty completion.")
|
|
@@ -13,6 +13,7 @@ from typing_extensions import Annotated
|
|
|
13
13
|
from .assistant import AIResponse, IINTSAssistant
|
|
14
14
|
from .backends import DEFAULT_MINISTRAL_MODEL, OllamaBackend
|
|
15
15
|
from .model_catalog import list_local_mistral_models
|
|
16
|
+
from .prepare import prepare_ai_ready_artifacts
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
app = typer.Typer(help="Research-only AI assistant commands gated by MDMP certification.")
|
|
@@ -36,6 +37,57 @@ def _load_json_payload(path: Path, label: str) -> Any:
|
|
|
36
37
|
return payload
|
|
37
38
|
|
|
38
39
|
|
|
40
|
+
def _default_prepared_payload(task: str, ai_dir: Path) -> Path:
|
|
41
|
+
candidates = {
|
|
42
|
+
"explain": ["step_riskiest.json", "step_latest.json"],
|
|
43
|
+
"trends": ["trends_payload.json"],
|
|
44
|
+
"anomalies": ["anomalies_payload.json"],
|
|
45
|
+
"report": ["report_payload.json"],
|
|
46
|
+
}.get(task, [])
|
|
47
|
+
for filename in candidates:
|
|
48
|
+
candidate = ai_dir / filename
|
|
49
|
+
if candidate.is_file():
|
|
50
|
+
return candidate
|
|
51
|
+
expected = ", ".join(candidates) if candidates else "prepared payload"
|
|
52
|
+
raise typer.BadParameter(
|
|
53
|
+
f"No prepared AI payload found in {ai_dir}. Expected one of: {expected}. "
|
|
54
|
+
"Run `iints ai prepare <run_dir>` first."
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _resolve_cli_inputs(
|
|
59
|
+
*,
|
|
60
|
+
task: str,
|
|
61
|
+
input_path: Path,
|
|
62
|
+
mdmp_cert: Path | None,
|
|
63
|
+
public_key: Path | None,
|
|
64
|
+
trust_store: Path | None,
|
|
65
|
+
) -> tuple[Path, Path, Path | None]:
|
|
66
|
+
resolved_input = input_path
|
|
67
|
+
resolved_cert = mdmp_cert
|
|
68
|
+
resolved_public_key = public_key
|
|
69
|
+
|
|
70
|
+
if input_path.is_dir():
|
|
71
|
+
ai_dir = input_path / "ai"
|
|
72
|
+
resolved_input = _default_prepared_payload(task, ai_dir)
|
|
73
|
+
if resolved_cert is None:
|
|
74
|
+
candidate_cert = ai_dir / "report.signed.mdmp"
|
|
75
|
+
if candidate_cert.is_file():
|
|
76
|
+
resolved_cert = candidate_cert
|
|
77
|
+
if resolved_public_key is None and trust_store is None:
|
|
78
|
+
candidate_public_key = ai_dir / "keys" / "mdmp_pub_v1.pem"
|
|
79
|
+
if candidate_public_key.is_file():
|
|
80
|
+
resolved_public_key = candidate_public_key
|
|
81
|
+
|
|
82
|
+
if resolved_cert is None:
|
|
83
|
+
raise typer.BadParameter(
|
|
84
|
+
"No MDMP certificate provided. Pass --mdmp-cert or run "
|
|
85
|
+
"`iints ai prepare <run_dir>` to generate a local development certificate."
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
return resolved_input, resolved_cert, resolved_public_key
|
|
89
|
+
|
|
90
|
+
|
|
39
91
|
def _write_output(path: Path | None, response: AIResponse) -> None:
|
|
40
92
|
if path is None:
|
|
41
93
|
return
|
|
@@ -59,6 +111,7 @@ def _render_local_check(console: Console, status: dict[str, object]) -> None:
|
|
|
59
111
|
installed_text = ", ".join(str(item) for item in installed) if isinstance(installed, list) and installed else "none"
|
|
60
112
|
ready = bool(status.get("ready"))
|
|
61
113
|
resolved_model = status.get("resolved_model") or "not found"
|
|
114
|
+
smoke_text = status.get("smoke_test") or "not run"
|
|
62
115
|
console.print(
|
|
63
116
|
Panel(
|
|
64
117
|
"\n".join(
|
|
@@ -74,6 +127,7 @@ def _render_local_check(console: Console, status: dict[str, object]) -> None:
|
|
|
74
127
|
if status.get("pull_command")
|
|
75
128
|
else "Pull command: not needed"
|
|
76
129
|
),
|
|
130
|
+
f"Generate smoke-test: {smoke_text}",
|
|
77
131
|
]
|
|
78
132
|
),
|
|
79
133
|
title="IINTS AI Local Check",
|
|
@@ -117,6 +171,47 @@ def models() -> None:
|
|
|
117
171
|
)
|
|
118
172
|
|
|
119
173
|
|
|
174
|
+
@app.command("prepare")
|
|
175
|
+
def prepare(
|
|
176
|
+
run_dir: Annotated[Path, typer.Argument(help="Run output directory containing results.csv and run_metadata.json.")],
|
|
177
|
+
create_dev_mdmp_cert: Annotated[
|
|
178
|
+
bool,
|
|
179
|
+
typer.Option(
|
|
180
|
+
"--create-dev-mdmp-cert/--no-create-dev-mdmp-cert",
|
|
181
|
+
help="Generate a local development MDMP certificate and keypair for AI commands.",
|
|
182
|
+
),
|
|
183
|
+
] = True,
|
|
184
|
+
grade: Annotated[str, typer.Option(help="Grade to embed in the local development MDMP certificate.")] = "research_grade",
|
|
185
|
+
expires_days: Annotated[int, typer.Option(help="Certificate expiry window in days for local development certs.")] = 30,
|
|
186
|
+
key_dir: Annotated[Optional[Path], typer.Option(help="Optional directory to store the generated local MDMP keypair.")] = None,
|
|
187
|
+
) -> None:
|
|
188
|
+
console = Console()
|
|
189
|
+
try:
|
|
190
|
+
outputs = prepare_ai_ready_artifacts(
|
|
191
|
+
run_dir,
|
|
192
|
+
create_dev_mdmp_cert=create_dev_mdmp_cert,
|
|
193
|
+
grade=grade,
|
|
194
|
+
expires_days=expires_days,
|
|
195
|
+
key_dir=key_dir,
|
|
196
|
+
)
|
|
197
|
+
except Exception as exc:
|
|
198
|
+
console.print(f"[bold red]Error:[/bold red] {exc}")
|
|
199
|
+
raise typer.Exit(code=1)
|
|
200
|
+
|
|
201
|
+
table = Table(title="IINTS AI Prepared Artifacts")
|
|
202
|
+
table.add_column("Artifact", style="cyan")
|
|
203
|
+
table.add_column("Path", overflow="fold")
|
|
204
|
+
for key, value in outputs.items():
|
|
205
|
+
table.add_row(key, value)
|
|
206
|
+
console.print(table)
|
|
207
|
+
console.print("[green]Prepared AI payloads are ready.[/green]")
|
|
208
|
+
if "mdmp_cert" in outputs:
|
|
209
|
+
console.print(
|
|
210
|
+
"[green]You can now run:[/green] "
|
|
211
|
+
f"`iints ai report {run_dir}` or `iints ai explain {run_dir}`"
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
|
|
120
215
|
def _build_assistant(
|
|
121
216
|
*,
|
|
122
217
|
mdmp_cert: Path,
|
|
@@ -146,6 +241,13 @@ def local_check(
|
|
|
146
241
|
model: Annotated[str, typer.Option(help="Ollama model name to validate locally.")] = DEFAULT_MINISTRAL_MODEL,
|
|
147
242
|
ollama_host: Annotated[Optional[str], typer.Option(help="Override the Ollama base URL.")] = None,
|
|
148
243
|
timeout_seconds: Annotated[float, typer.Option(help="HTTP timeout for Ollama health checks.")] = 120.0,
|
|
244
|
+
smoke_test: Annotated[
|
|
245
|
+
bool,
|
|
246
|
+
typer.Option(
|
|
247
|
+
"--smoke-test/--no-smoke-test",
|
|
248
|
+
help="Run a tiny generation request after health checks to prove the model can actually answer.",
|
|
249
|
+
),
|
|
250
|
+
] = True,
|
|
149
251
|
) -> None:
|
|
150
252
|
console = Console()
|
|
151
253
|
backend = OllamaBackend(model_name=model, base_url=ollama_host, timeout_seconds=timeout_seconds)
|
|
@@ -157,6 +259,13 @@ def local_check(
|
|
|
157
259
|
)
|
|
158
260
|
raise typer.Exit(code=1)
|
|
159
261
|
status = backend.healthcheck()
|
|
262
|
+
if smoke_test and bool(status.get("ready")):
|
|
263
|
+
smoke = backend.smoke_test()
|
|
264
|
+
status["smoke_test"] = f"OK ({smoke.get('response')})"
|
|
265
|
+
elif smoke_test:
|
|
266
|
+
status["smoke_test"] = "skipped (model not ready)"
|
|
267
|
+
else:
|
|
268
|
+
status["smoke_test"] = "disabled"
|
|
160
269
|
_render_local_check(console, status)
|
|
161
270
|
if not bool(status.get("ready")):
|
|
162
271
|
raise typer.Exit(code=1)
|
|
@@ -169,8 +278,8 @@ def local_check(
|
|
|
169
278
|
|
|
170
279
|
@app.command("explain")
|
|
171
280
|
def explain(
|
|
172
|
-
input_json: Annotated[Path, typer.Argument(help="JSON file with a single simulation step or decision context.")],
|
|
173
|
-
mdmp_cert: Annotated[Path, typer.Option(help="Signed MDMP artifact required before AI analysis can run.")],
|
|
281
|
+
input_json: Annotated[Path, typer.Argument(help="Prepared run directory or JSON file with a single simulation step or decision context.")],
|
|
282
|
+
mdmp_cert: Annotated[Optional[Path], typer.Option(help="Signed MDMP artifact required before AI analysis can run.")] = None,
|
|
174
283
|
mode: Annotated[str, typer.Option(help="AI backend mode. Use 'local' for Ollama/Ministral.")] = "auto",
|
|
175
284
|
model: Annotated[str, typer.Option(help="Ollama model name to use.")] = DEFAULT_MINISTRAL_MODEL,
|
|
176
285
|
minimum_grade: Annotated[str, typer.Option(help="Minimum MDMP grade required to allow analysis.")] = "research_grade",
|
|
@@ -182,13 +291,20 @@ def explain(
|
|
|
182
291
|
) -> None:
|
|
183
292
|
console = Console()
|
|
184
293
|
try:
|
|
185
|
-
|
|
186
|
-
|
|
294
|
+
resolved_input, resolved_cert, resolved_public_key = _resolve_cli_inputs(
|
|
295
|
+
task="explain",
|
|
296
|
+
input_path=input_json,
|
|
187
297
|
mdmp_cert=mdmp_cert,
|
|
298
|
+
public_key=public_key,
|
|
299
|
+
trust_store=trust_store,
|
|
300
|
+
)
|
|
301
|
+
payload = _load_json_payload(resolved_input, "Input JSON")
|
|
302
|
+
assistant = _build_assistant(
|
|
303
|
+
mdmp_cert=resolved_cert,
|
|
188
304
|
mode=mode,
|
|
189
305
|
model=model,
|
|
190
306
|
minimum_grade=minimum_grade,
|
|
191
|
-
public_key=
|
|
307
|
+
public_key=resolved_public_key,
|
|
192
308
|
trust_store=trust_store,
|
|
193
309
|
ollama_host=ollama_host,
|
|
194
310
|
timeout_seconds=timeout_seconds,
|
|
@@ -203,8 +319,8 @@ def explain(
|
|
|
203
319
|
|
|
204
320
|
@app.command("trends")
|
|
205
321
|
def trends(
|
|
206
|
-
input_json: Annotated[Path, typer.Argument(help="JSON file with glucose trace data or a run payload.")],
|
|
207
|
-
mdmp_cert: Annotated[Path, typer.Option(help="Signed MDMP artifact required before AI analysis can run.")],
|
|
322
|
+
input_json: Annotated[Path, typer.Argument(help="Prepared run directory or JSON file with glucose trace data or a run payload.")],
|
|
323
|
+
mdmp_cert: Annotated[Optional[Path], typer.Option(help="Signed MDMP artifact required before AI analysis can run.")] = None,
|
|
208
324
|
mode: Annotated[str, typer.Option(help="AI backend mode. Use 'local' for Ollama/Ministral.")] = "auto",
|
|
209
325
|
model: Annotated[str, typer.Option(help="Ollama model name to use.")] = DEFAULT_MINISTRAL_MODEL,
|
|
210
326
|
minimum_grade: Annotated[str, typer.Option(help="Minimum MDMP grade required to allow analysis.")] = "research_grade",
|
|
@@ -216,13 +332,20 @@ def trends(
|
|
|
216
332
|
) -> None:
|
|
217
333
|
console = Console()
|
|
218
334
|
try:
|
|
219
|
-
|
|
220
|
-
|
|
335
|
+
resolved_input, resolved_cert, resolved_public_key = _resolve_cli_inputs(
|
|
336
|
+
task="trends",
|
|
337
|
+
input_path=input_json,
|
|
221
338
|
mdmp_cert=mdmp_cert,
|
|
339
|
+
public_key=public_key,
|
|
340
|
+
trust_store=trust_store,
|
|
341
|
+
)
|
|
342
|
+
payload = _load_json_payload(resolved_input, "Input JSON")
|
|
343
|
+
assistant = _build_assistant(
|
|
344
|
+
mdmp_cert=resolved_cert,
|
|
222
345
|
mode=mode,
|
|
223
346
|
model=model,
|
|
224
347
|
minimum_grade=minimum_grade,
|
|
225
|
-
public_key=
|
|
348
|
+
public_key=resolved_public_key,
|
|
226
349
|
trust_store=trust_store,
|
|
227
350
|
ollama_host=ollama_host,
|
|
228
351
|
timeout_seconds=timeout_seconds,
|
|
@@ -237,8 +360,8 @@ def trends(
|
|
|
237
360
|
|
|
238
361
|
@app.command("anomalies")
|
|
239
362
|
def anomalies(
|
|
240
|
-
input_json: Annotated[Path, typer.Argument(help="JSON file with simulation results or run summary.")],
|
|
241
|
-
mdmp_cert: Annotated[Path, typer.Option(help="Signed MDMP artifact required before AI analysis can run.")],
|
|
363
|
+
input_json: Annotated[Path, typer.Argument(help="Prepared run directory or JSON file with simulation results or run summary.")],
|
|
364
|
+
mdmp_cert: Annotated[Optional[Path], typer.Option(help="Signed MDMP artifact required before AI analysis can run.")] = None,
|
|
242
365
|
mode: Annotated[str, typer.Option(help="AI backend mode. Use 'local' for Ollama/Ministral.")] = "auto",
|
|
243
366
|
model: Annotated[str, typer.Option(help="Ollama model name to use.")] = DEFAULT_MINISTRAL_MODEL,
|
|
244
367
|
minimum_grade: Annotated[str, typer.Option(help="Minimum MDMP grade required to allow analysis.")] = "research_grade",
|
|
@@ -250,13 +373,20 @@ def anomalies(
|
|
|
250
373
|
) -> None:
|
|
251
374
|
console = Console()
|
|
252
375
|
try:
|
|
253
|
-
|
|
254
|
-
|
|
376
|
+
resolved_input, resolved_cert, resolved_public_key = _resolve_cli_inputs(
|
|
377
|
+
task="anomalies",
|
|
378
|
+
input_path=input_json,
|
|
255
379
|
mdmp_cert=mdmp_cert,
|
|
380
|
+
public_key=public_key,
|
|
381
|
+
trust_store=trust_store,
|
|
382
|
+
)
|
|
383
|
+
payload = _load_json_payload(resolved_input, "Input JSON")
|
|
384
|
+
assistant = _build_assistant(
|
|
385
|
+
mdmp_cert=resolved_cert,
|
|
256
386
|
mode=mode,
|
|
257
387
|
model=model,
|
|
258
388
|
minimum_grade=minimum_grade,
|
|
259
|
-
public_key=
|
|
389
|
+
public_key=resolved_public_key,
|
|
260
390
|
trust_store=trust_store,
|
|
261
391
|
ollama_host=ollama_host,
|
|
262
392
|
timeout_seconds=timeout_seconds,
|
|
@@ -271,8 +401,8 @@ def anomalies(
|
|
|
271
401
|
|
|
272
402
|
@app.command("report")
|
|
273
403
|
def report(
|
|
274
|
-
input_json: Annotated[Path, typer.Argument(help="JSON file with run-level simulation outputs.")],
|
|
275
|
-
mdmp_cert: Annotated[Path, typer.Option(help="Signed MDMP artifact required before AI analysis can run.")],
|
|
404
|
+
input_json: Annotated[Path, typer.Argument(help="Prepared run directory or JSON file with run-level simulation outputs.")],
|
|
405
|
+
mdmp_cert: Annotated[Optional[Path], typer.Option(help="Signed MDMP artifact required before AI analysis can run.")] = None,
|
|
276
406
|
mode: Annotated[str, typer.Option(help="AI backend mode. Use 'local' for Ollama/Ministral.")] = "auto",
|
|
277
407
|
model: Annotated[str, typer.Option(help="Ollama model name to use.")] = DEFAULT_MINISTRAL_MODEL,
|
|
278
408
|
minimum_grade: Annotated[str, typer.Option(help="Minimum MDMP grade required to allow analysis.")] = "research_grade",
|
|
@@ -284,13 +414,20 @@ def report(
|
|
|
284
414
|
) -> None:
|
|
285
415
|
console = Console()
|
|
286
416
|
try:
|
|
287
|
-
|
|
288
|
-
|
|
417
|
+
resolved_input, resolved_cert, resolved_public_key = _resolve_cli_inputs(
|
|
418
|
+
task="report",
|
|
419
|
+
input_path=input_json,
|
|
289
420
|
mdmp_cert=mdmp_cert,
|
|
421
|
+
public_key=public_key,
|
|
422
|
+
trust_store=trust_store,
|
|
423
|
+
)
|
|
424
|
+
payload = _load_json_payload(resolved_input, "Input JSON")
|
|
425
|
+
assistant = _build_assistant(
|
|
426
|
+
mdmp_cert=resolved_cert,
|
|
290
427
|
mode=mode,
|
|
291
428
|
model=model,
|
|
292
429
|
minimum_grade=minimum_grade,
|
|
293
|
-
public_key=
|
|
430
|
+
public_key=resolved_public_key,
|
|
294
431
|
trust_store=trust_store,
|
|
295
432
|
ollama_host=ollama_host,
|
|
296
433
|
timeout_seconds=timeout_seconds,
|