iints-sdk-python35 1.1.2__tar.gz → 1.2.0__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.2/src/iints_sdk_python35.egg-info → iints_sdk_python35-1.2.0}/PKG-INFO +83 -2
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/README.md +82 -1
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/pyproject.toml +1 -1
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/__init__.py +13 -1
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/ai/backends/ollama.py +84 -1
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/ai/cli.py +16 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/ai/prompts.py +16 -15
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/__init__.py +4 -0
- iints_sdk_python35-1.2.0/src/iints/analysis/carelink_workbench.py +733 -0
- iints_sdk_python35-1.2.0/src/iints/analysis/poster.py +289 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/cli/cli.py +219 -1
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/__init__.py +8 -0
- iints_sdk_python35-1.2.0/src/iints/data/importer.py +602 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0/src/iints_sdk_python35.egg-info}/PKG-INFO +83 -2
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints_sdk_python35.egg-info/SOURCES.txt +4 -0
- iints_sdk_python35-1.2.0/tests/test_cli_carelink_workbench.py +46 -0
- iints_sdk_python35-1.2.0/tests/test_cli_poster.py +61 -0
- iints_sdk_python35-1.1.2/src/iints/data/importer.py +0 -275
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/LICENSE +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/setup.cfg +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/ai/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/ai/assistant.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/ai/backends/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/ai/backends/base.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/ai/backends/mistral_api.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/ai/mdmp_guard.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/ai/model_catalog.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/ai/prepare.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/algorithm_xray.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/baseline.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/clinical_benchmark.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/clinical_metrics.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/clinical_tir_analyzer.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/diabetes_metrics.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/edge_efficiency.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/edge_performance_monitor.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/explainability.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/explainable_ai.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/hardware_benchmark.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/metrics.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/population_report.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/reporting.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/safety_index.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/sensor_filtering.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/analysis/validator.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/api/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/api/base_algorithm.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/api/registry.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/api/template_algorithm.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/assets/iints_logo.png +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/cli/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/algorithms/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/algorithms/battle_runner.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/algorithms/correction_bolus.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/algorithms/discovery.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/algorithms/fixed_basal_bolus.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/algorithms/hybrid_algorithm.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/algorithms/lstm_algorithm.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/algorithms/mock_algorithms.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/algorithms/pid_controller.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/algorithms/standard_pump_algo.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/device.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/device_manager.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/devices/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/devices/models.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/patient/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/patient/bergman_model.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/patient/models.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/patient/patient_factory.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/patient/profile.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/safety/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/safety/config.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/safety/input_validator.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/safety/supervisor.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/simulation/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/simulation/scenario_parser.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/simulator.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/core/supervisor.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/adapter.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/column_mapper.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/contracts.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/datasets.json +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/demo/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/demo/demo_cgm.csv +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/guardians.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/ingestor.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/mdmp_visualizer.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/nightscout.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/quality_checker.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/registry.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/runner.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/synthetic_mirror.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/tidepool.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/universal_parser.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/virtual_patients/clinic_safe_baseline.yaml +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/virtual_patients/clinic_safe_hyper_challenge.yaml +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/virtual_patients/clinic_safe_hypo_prone.yaml +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/virtual_patients/clinic_safe_midnight.yaml +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/virtual_patients/clinic_safe_pizza.yaml +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/virtual_patients/clinic_safe_stress_meal.yaml +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/virtual_patients/default_patient.yaml +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/data/virtual_patients/patient_559_config.yaml +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/emulation/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/emulation/legacy_base.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/emulation/medtronic_780g.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/emulation/omnipod_5.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/emulation/tandem_controliq.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/highlevel.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/learning/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/learning/autonomous_optimizer.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/learning/learning_system.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/mdmp/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/mdmp/backend.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/metrics.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/population/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/population/generator.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/population/runner.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/presets/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/presets/evidence_sources.yaml +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/presets/forecast_calibration_profiles.yaml +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/presets/golden_benchmark.yaml +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/presets/presets.json +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/presets/safety_contract_default.yaml +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/presets/validation_profiles.yaml +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/research/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/research/audit.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/research/calibration_gate.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/research/config.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/research/dataset.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/research/evaluation.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/research/losses.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/research/metrics.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/research/model_registry.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/research/predictor.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/scenarios/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/scenarios/generator.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/templates/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/templates/default_algorithm.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/templates/scenarios/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/templates/scenarios/chaos_insulin_stacking.json +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/templates/scenarios/chaos_runaway_ai.json +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/templates/scenarios/example_scenario.json +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/templates/scenarios/exercise_stress.json +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/utils/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/utils/plotting.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/utils/run_io.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/validation/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/validation/golden.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/validation/replay.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/validation/run_validation.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/validation/safety_contract.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/validation/schemas.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/visualization/__init__.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/visualization/cockpit.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints/visualization/uncertainty_cloud.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints_sdk_python35.egg-info/dependency_links.txt +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints_sdk_python35.egg-info/entry_points.txt +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints_sdk_python35.egg-info/requires.txt +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/src/iints_sdk_python35.egg-info/top_level.txt +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/tests/test_bergman.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/tests/test_install_doctor.py +0 -0
- {iints_sdk_python35-1.1.2 → iints_sdk_python35-1.2.0}/tests/test_population.py +0 -0
{iints_sdk_python35-1.1.2/src/iints_sdk_python35.egg-info → iints_sdk_python35-1.2.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iints-sdk-python35
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
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
|
|
@@ -81,6 +81,47 @@ cd iints_quickstart
|
|
|
81
81
|
iints presets run --name baseline_t1d --algo algorithms/example_algorithm.py
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
+
## CareLink Import
|
|
85
|
+
|
|
86
|
+
The SDK can now ingest Medtronic CareLink / MiniMed CSV exports and convert them into the standard IINTS schema:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
iints import-carelink \
|
|
90
|
+
--input-csv "/path/to/CareLink export.csv" \
|
|
91
|
+
--output-dir results/imported_carelink
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
This writes:
|
|
95
|
+
- `cgm_standard.csv`
|
|
96
|
+
- `scenario.json`
|
|
97
|
+
- `carelink_summary.json`
|
|
98
|
+
|
|
99
|
+
It extracts glucose, carb, and insulin events from the CareLink event log and aligns them onto an IINTS-ready timeline.
|
|
100
|
+
|
|
101
|
+
If you want a reusable personal-data workspace in one command, build a CareLink workbench:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
iints carelink-workbench \
|
|
105
|
+
--input-csv "/path/to/CareLink export.csv" \
|
|
106
|
+
--output-dir results/personal_carelink
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
This adds:
|
|
110
|
+
- `carelink_timeline.csv`
|
|
111
|
+
- `carelink_metrics.json`
|
|
112
|
+
- `carelink_dashboard.png`
|
|
113
|
+
- `carelink_poster.png`
|
|
114
|
+
- `carelink_dashboard.html`
|
|
115
|
+
- `ai/report_payload.json`
|
|
116
|
+
- `ai/trends_payload.json`
|
|
117
|
+
- `ai/anomalies_payload.json`
|
|
118
|
+
- `ai/step_riskiest.json`
|
|
119
|
+
|
|
120
|
+
That workbench is designed for three things:
|
|
121
|
+
- inspect your own data visually
|
|
122
|
+
- reuse the generated `scenario.json` inside IINTS experiments
|
|
123
|
+
- let the local AI assistant explain what the imported patterns mean
|
|
124
|
+
|
|
84
125
|
## AI Assistant (Ministral 3 Open-Weight via Ollama)
|
|
85
126
|
|
|
86
127
|
The SDK now includes a research-only AI assistant layer for explanations and run summaries.
|
|
@@ -110,6 +151,8 @@ ollama pull ministral-3:8b
|
|
|
110
151
|
iints ai local-check --model ministral-3:8b
|
|
111
152
|
```
|
|
112
153
|
|
|
154
|
+
`local-check` now performs a tiny generation smoke-test by default, so it verifies both model presence and real inference readiness.
|
|
155
|
+
|
|
113
156
|
Recommended flow:
|
|
114
157
|
|
|
115
158
|
```bash
|
|
@@ -120,6 +163,18 @@ iints ai prepare results/<run_id>
|
|
|
120
163
|
iints ai report results/<run_id>
|
|
121
164
|
```
|
|
122
165
|
|
|
166
|
+
For imported CareLink data, the matching flow is:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
iints carelink-workbench \
|
|
170
|
+
--input-csv "/path/to/CareLink export.csv" \
|
|
171
|
+
--output-dir results/personal_carelink
|
|
172
|
+
|
|
173
|
+
iints ai report results/personal_carelink --model ministral-3:3b
|
|
174
|
+
iints ai trends results/personal_carelink --model ministral-3:3b
|
|
175
|
+
iints ai explain results/personal_carelink --model ministral-3:3b
|
|
176
|
+
```
|
|
177
|
+
|
|
123
178
|
Direct JSON mode still works if you already have your own payloads and signed MDMP artifact:
|
|
124
179
|
|
|
125
180
|
```bash
|
|
@@ -134,9 +189,35 @@ Notes:
|
|
|
134
189
|
- Users can choose a larger or smaller local Mistral-family model with `--model ...`.
|
|
135
190
|
- Large JSON payloads are clipped automatically before prompt generation to keep local inference stable.
|
|
136
191
|
- `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/`.
|
|
192
|
+
- `iints carelink-workbench` now does the same kind of AI preparation for imported personal CareLink data and also generates a dashboard PNG/HTML pair.
|
|
193
|
+
- 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.
|
|
137
194
|
- After `iints ai prepare`, you can point `iints ai explain|trends|anomalies|report` directly at the run directory.
|
|
195
|
+
- After `iints carelink-workbench`, you can point those same AI commands directly at the generated CareLink workspace directory.
|
|
138
196
|
- Output is research-only and not medical advice.
|
|
139
197
|
|
|
198
|
+
## Jury Poster / Demo Graphic
|
|
199
|
+
|
|
200
|
+
You can now generate a poster-style PNG directly from one to three real run bundles:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
iints poster \
|
|
204
|
+
--run-dir results/normal_run \
|
|
205
|
+
--run-dir results/meal_stress \
|
|
206
|
+
--run-dir results/supervisor_override \
|
|
207
|
+
--label "Normal Run" \
|
|
208
|
+
--label "Meal Stress Test" \
|
|
209
|
+
--label "Supervisor Override" \
|
|
210
|
+
--output-path results/posters/iints_results_poster.png
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The poster shows:
|
|
214
|
+
- glucose curves with the target range highlighted
|
|
215
|
+
- meal events
|
|
216
|
+
- supervisor interventions
|
|
217
|
+
- panel summaries with TIR, hypo time, meal count, and intervention count
|
|
218
|
+
|
|
219
|
+
If you omit `--run-dir`, the CLI auto-discovers the latest run bundles under `./results`.
|
|
220
|
+
|
|
140
221
|
Troubleshooting:
|
|
141
222
|
- If `iints ai ...` says `No such command 'ai'`, your environment usually still has a legacy `iints` package installed alongside `iints-sdk-python35`.
|
|
142
223
|
- Run `iints-sdk-doctor` first.
|
|
@@ -144,7 +225,7 @@ Troubleshooting:
|
|
|
144
225
|
|
|
145
226
|
```bash
|
|
146
227
|
python -m pip uninstall -y iints iints-sdk-python35
|
|
147
|
-
python -m pip install -U "iints-sdk-python35[mdmp]==1.
|
|
228
|
+
python -m pip install -U "iints-sdk-python35[mdmp]==1.2.0"
|
|
148
229
|
hash -r
|
|
149
230
|
```
|
|
150
231
|
|
|
@@ -30,6 +30,47 @@ cd iints_quickstart
|
|
|
30
30
|
iints presets run --name baseline_t1d --algo algorithms/example_algorithm.py
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
## CareLink Import
|
|
34
|
+
|
|
35
|
+
The SDK can now ingest Medtronic CareLink / MiniMed CSV exports and convert them into the standard IINTS schema:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
iints import-carelink \
|
|
39
|
+
--input-csv "/path/to/CareLink export.csv" \
|
|
40
|
+
--output-dir results/imported_carelink
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This writes:
|
|
44
|
+
- `cgm_standard.csv`
|
|
45
|
+
- `scenario.json`
|
|
46
|
+
- `carelink_summary.json`
|
|
47
|
+
|
|
48
|
+
It extracts glucose, carb, and insulin events from the CareLink event log and aligns them onto an IINTS-ready timeline.
|
|
49
|
+
|
|
50
|
+
If you want a reusable personal-data workspace in one command, build a CareLink workbench:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
iints carelink-workbench \
|
|
54
|
+
--input-csv "/path/to/CareLink export.csv" \
|
|
55
|
+
--output-dir results/personal_carelink
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This adds:
|
|
59
|
+
- `carelink_timeline.csv`
|
|
60
|
+
- `carelink_metrics.json`
|
|
61
|
+
- `carelink_dashboard.png`
|
|
62
|
+
- `carelink_poster.png`
|
|
63
|
+
- `carelink_dashboard.html`
|
|
64
|
+
- `ai/report_payload.json`
|
|
65
|
+
- `ai/trends_payload.json`
|
|
66
|
+
- `ai/anomalies_payload.json`
|
|
67
|
+
- `ai/step_riskiest.json`
|
|
68
|
+
|
|
69
|
+
That workbench is designed for three things:
|
|
70
|
+
- inspect your own data visually
|
|
71
|
+
- reuse the generated `scenario.json` inside IINTS experiments
|
|
72
|
+
- let the local AI assistant explain what the imported patterns mean
|
|
73
|
+
|
|
33
74
|
## AI Assistant (Ministral 3 Open-Weight via Ollama)
|
|
34
75
|
|
|
35
76
|
The SDK now includes a research-only AI assistant layer for explanations and run summaries.
|
|
@@ -59,6 +100,8 @@ ollama pull ministral-3:8b
|
|
|
59
100
|
iints ai local-check --model ministral-3:8b
|
|
60
101
|
```
|
|
61
102
|
|
|
103
|
+
`local-check` now performs a tiny generation smoke-test by default, so it verifies both model presence and real inference readiness.
|
|
104
|
+
|
|
62
105
|
Recommended flow:
|
|
63
106
|
|
|
64
107
|
```bash
|
|
@@ -69,6 +112,18 @@ iints ai prepare results/<run_id>
|
|
|
69
112
|
iints ai report results/<run_id>
|
|
70
113
|
```
|
|
71
114
|
|
|
115
|
+
For imported CareLink data, the matching flow is:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
iints carelink-workbench \
|
|
119
|
+
--input-csv "/path/to/CareLink export.csv" \
|
|
120
|
+
--output-dir results/personal_carelink
|
|
121
|
+
|
|
122
|
+
iints ai report results/personal_carelink --model ministral-3:3b
|
|
123
|
+
iints ai trends results/personal_carelink --model ministral-3:3b
|
|
124
|
+
iints ai explain results/personal_carelink --model ministral-3:3b
|
|
125
|
+
```
|
|
126
|
+
|
|
72
127
|
Direct JSON mode still works if you already have your own payloads and signed MDMP artifact:
|
|
73
128
|
|
|
74
129
|
```bash
|
|
@@ -83,9 +138,35 @@ Notes:
|
|
|
83
138
|
- Users can choose a larger or smaller local Mistral-family model with `--model ...`.
|
|
84
139
|
- Large JSON payloads are clipped automatically before prompt generation to keep local inference stable.
|
|
85
140
|
- `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/`.
|
|
141
|
+
- `iints carelink-workbench` now does the same kind of AI preparation for imported personal CareLink data and also generates a dashboard PNG/HTML pair.
|
|
142
|
+
- 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.
|
|
86
143
|
- After `iints ai prepare`, you can point `iints ai explain|trends|anomalies|report` directly at the run directory.
|
|
144
|
+
- After `iints carelink-workbench`, you can point those same AI commands directly at the generated CareLink workspace directory.
|
|
87
145
|
- Output is research-only and not medical advice.
|
|
88
146
|
|
|
147
|
+
## Jury Poster / Demo Graphic
|
|
148
|
+
|
|
149
|
+
You can now generate a poster-style PNG directly from one to three real run bundles:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
iints poster \
|
|
153
|
+
--run-dir results/normal_run \
|
|
154
|
+
--run-dir results/meal_stress \
|
|
155
|
+
--run-dir results/supervisor_override \
|
|
156
|
+
--label "Normal Run" \
|
|
157
|
+
--label "Meal Stress Test" \
|
|
158
|
+
--label "Supervisor Override" \
|
|
159
|
+
--output-path results/posters/iints_results_poster.png
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The poster shows:
|
|
163
|
+
- glucose curves with the target range highlighted
|
|
164
|
+
- meal events
|
|
165
|
+
- supervisor interventions
|
|
166
|
+
- panel summaries with TIR, hypo time, meal count, and intervention count
|
|
167
|
+
|
|
168
|
+
If you omit `--run-dir`, the CLI auto-discovers the latest run bundles under `./results`.
|
|
169
|
+
|
|
89
170
|
Troubleshooting:
|
|
90
171
|
- If `iints ai ...` says `No such command 'ai'`, your environment usually still has a legacy `iints` package installed alongside `iints-sdk-python35`.
|
|
91
172
|
- Run `iints-sdk-doctor` first.
|
|
@@ -93,7 +174,7 @@ Troubleshooting:
|
|
|
93
174
|
|
|
94
175
|
```bash
|
|
95
176
|
python -m pip uninstall -y iints iints-sdk-python35
|
|
96
|
-
python -m pip install -U "iints-sdk-python35[mdmp]==1.
|
|
177
|
+
python -m pip install -U "iints-sdk-python35[mdmp]==1.2.0"
|
|
97
178
|
hash -r
|
|
98
179
|
```
|
|
99
180
|
|
|
@@ -11,7 +11,7 @@ except ImportError: # pragma: no cover - Python < 3.8 fallback
|
|
|
11
11
|
try:
|
|
12
12
|
__version__ = version("iints-sdk-python35")
|
|
13
13
|
except PackageNotFoundError: # pragma: no cover - source tree fallback
|
|
14
|
-
__version__ = "1.
|
|
14
|
+
__version__ = "1.2.0"
|
|
15
15
|
|
|
16
16
|
# Note to developers: this SDK is currently maintained by a single author.
|
|
17
17
|
# Please report bugs via GitHub issues and feel free to contribute fixes via PRs.
|
|
@@ -56,17 +56,23 @@ from .data.importer import (
|
|
|
56
56
|
export_demo_csv,
|
|
57
57
|
export_standard_csv,
|
|
58
58
|
guess_column_mapping,
|
|
59
|
+
import_carelink_csv,
|
|
60
|
+
import_carelink_timeline,
|
|
59
61
|
import_cgm_csv,
|
|
60
62
|
import_cgm_dataframe,
|
|
63
|
+
load_carelink_event_log,
|
|
61
64
|
load_demo_dataframe,
|
|
62
65
|
scenario_from_csv,
|
|
63
66
|
scenario_from_dataframe,
|
|
67
|
+
summarize_carelink_csv,
|
|
64
68
|
)
|
|
65
69
|
from .data.nightscout import NightscoutConfig, import_nightscout
|
|
66
70
|
from .data.tidepool import TidepoolClient, load_openapi_spec
|
|
67
71
|
from .data.guardians import mdmp_gate, MDMPGateError
|
|
68
72
|
from .data.synthetic_mirror import generate_synthetic_mirror, SyntheticMirrorArtifact
|
|
69
73
|
from .analysis.metrics import generate_benchmark_metrics # Added for benchmark
|
|
74
|
+
from .analysis.carelink_workbench import build_carelink_workbench
|
|
75
|
+
from .analysis.poster import generate_results_poster
|
|
70
76
|
from .analysis.reporting import ClinicalReportGenerator
|
|
71
77
|
from .analysis.edge_efficiency import EnergyEstimate, estimate_energy_per_decision
|
|
72
78
|
from .ai import AIResponse, IINTSAssistant, MDMPGuard
|
|
@@ -160,11 +166,15 @@ __all__ = [
|
|
|
160
166
|
"export_demo_csv",
|
|
161
167
|
"export_standard_csv",
|
|
162
168
|
"guess_column_mapping",
|
|
169
|
+
"import_carelink_csv",
|
|
170
|
+
"import_carelink_timeline",
|
|
163
171
|
"import_cgm_csv",
|
|
164
172
|
"import_cgm_dataframe",
|
|
173
|
+
"load_carelink_event_log",
|
|
165
174
|
"load_demo_dataframe",
|
|
166
175
|
"scenario_from_csv",
|
|
167
176
|
"scenario_from_dataframe",
|
|
177
|
+
"summarize_carelink_csv",
|
|
168
178
|
"NightscoutConfig",
|
|
169
179
|
"import_nightscout",
|
|
170
180
|
"TidepoolClient",
|
|
@@ -175,6 +185,7 @@ __all__ = [
|
|
|
175
185
|
"SyntheticMirrorArtifact",
|
|
176
186
|
# Analysis Metrics
|
|
177
187
|
"generate_benchmark_metrics",
|
|
188
|
+
"build_carelink_workbench",
|
|
178
189
|
"ClinicalReportGenerator",
|
|
179
190
|
"EnergyEstimate",
|
|
180
191
|
"estimate_energy_per_decision",
|
|
@@ -185,6 +196,7 @@ __all__ = [
|
|
|
185
196
|
"generate_report",
|
|
186
197
|
"generate_quickstart_report",
|
|
187
198
|
"generate_demo_report",
|
|
199
|
+
"generate_results_poster",
|
|
188
200
|
# High-level API
|
|
189
201
|
"run_simulation",
|
|
190
202
|
"run_full",
|
|
@@ -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.")
|
|
@@ -111,6 +111,7 @@ def _render_local_check(console: Console, status: dict[str, object]) -> None:
|
|
|
111
111
|
installed_text = ", ".join(str(item) for item in installed) if isinstance(installed, list) and installed else "none"
|
|
112
112
|
ready = bool(status.get("ready"))
|
|
113
113
|
resolved_model = status.get("resolved_model") or "not found"
|
|
114
|
+
smoke_text = status.get("smoke_test") or "not run"
|
|
114
115
|
console.print(
|
|
115
116
|
Panel(
|
|
116
117
|
"\n".join(
|
|
@@ -126,6 +127,7 @@ def _render_local_check(console: Console, status: dict[str, object]) -> None:
|
|
|
126
127
|
if status.get("pull_command")
|
|
127
128
|
else "Pull command: not needed"
|
|
128
129
|
),
|
|
130
|
+
f"Generate smoke-test: {smoke_text}",
|
|
129
131
|
]
|
|
130
132
|
),
|
|
131
133
|
title="IINTS AI Local Check",
|
|
@@ -239,6 +241,13 @@ def local_check(
|
|
|
239
241
|
model: Annotated[str, typer.Option(help="Ollama model name to validate locally.")] = DEFAULT_MINISTRAL_MODEL,
|
|
240
242
|
ollama_host: Annotated[Optional[str], typer.Option(help="Override the Ollama base URL.")] = None,
|
|
241
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,
|
|
242
251
|
) -> None:
|
|
243
252
|
console = Console()
|
|
244
253
|
backend = OllamaBackend(model_name=model, base_url=ollama_host, timeout_seconds=timeout_seconds)
|
|
@@ -250,6 +259,13 @@ def local_check(
|
|
|
250
259
|
)
|
|
251
260
|
raise typer.Exit(code=1)
|
|
252
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"
|
|
253
269
|
_render_local_check(console, status)
|
|
254
270
|
if not bool(status.get("ready")):
|
|
255
271
|
raise typer.Exit(code=1)
|
|
@@ -8,8 +8,9 @@ TaskName = Literal["explain_decision", "analyze_trends", "detect_anomalies", "ge
|
|
|
8
8
|
MAX_PROMPT_PAYLOAD_CHARS = 12000
|
|
9
9
|
|
|
10
10
|
SYSTEM_PROMPT = (
|
|
11
|
-
"You are the IINTS-AF research assistant for closed-loop insulin delivery simulations
|
|
12
|
-
"
|
|
11
|
+
"You are the IINTS-AF research assistant for closed-loop insulin delivery simulations "
|
|
12
|
+
"and imported glucose datasets. "
|
|
13
|
+
"Explain glycemic behavior clearly, conservatively, and in plain language. "
|
|
13
14
|
"Do not give medical advice, treatment instructions, or patient-specific recommendations. "
|
|
14
15
|
"State uncertainty when the input is incomplete. "
|
|
15
16
|
"For research use only."
|
|
@@ -17,39 +18,39 @@ SYSTEM_PROMPT = (
|
|
|
17
18
|
|
|
18
19
|
TASK_TEMPLATES: dict[TaskName, str] = {
|
|
19
20
|
"explain_decision": (
|
|
20
|
-
"Given this single
|
|
21
|
-
"1. What the
|
|
22
|
-
"2. Whether
|
|
23
|
-
"3.
|
|
21
|
+
"Given this single decision step or noteworthy glucose snapshot, explain:\n"
|
|
22
|
+
"1. What is happening in the data and why it stands out\n"
|
|
23
|
+
"2. Whether there are safety signals, supervision, or notable context clues\n"
|
|
24
|
+
"3. What a research user should pay attention to next\n\n"
|
|
24
25
|
"Respond in 3 short paragraphs.\n\n"
|
|
25
|
-
"
|
|
26
|
+
"Input JSON:\n{data}"
|
|
26
27
|
),
|
|
27
28
|
"analyze_trends": (
|
|
28
|
-
"Review this glucose-oriented
|
|
29
|
+
"Review this glucose-oriented payload and summarize the main glycemic trends.\n"
|
|
29
30
|
"Focus on direction, stability, excursions, and likely triggers.\n"
|
|
30
31
|
"Respond with:\n"
|
|
31
32
|
"- Trend summary\n"
|
|
32
33
|
"- Main risk signals\n"
|
|
33
34
|
"- Short operational takeaway\n\n"
|
|
34
|
-
"
|
|
35
|
+
"Payload JSON:\n{data}"
|
|
35
36
|
),
|
|
36
37
|
"detect_anomalies": (
|
|
37
|
-
"Inspect this run summary and identify unusual patterns, inconsistent values, or clinically relevant anomalies.\n"
|
|
38
|
+
"Inspect this run or imported-data summary and identify unusual patterns, inconsistent values, or clinically relevant anomalies.\n"
|
|
38
39
|
"Respond with:\n"
|
|
39
40
|
"- Detected anomalies\n"
|
|
40
41
|
"- Why each anomaly matters\n"
|
|
41
42
|
"- Whether follow-up validation is recommended\n\n"
|
|
42
|
-
"
|
|
43
|
+
"Summary JSON:\n{data}"
|
|
43
44
|
),
|
|
44
45
|
"generate_report": (
|
|
45
|
-
"Write a concise markdown report for this IINTS-AF simulation run.\n"
|
|
46
|
+
"Write a concise markdown report for this IINTS-AF simulation run or imported personal glucose dataset.\n"
|
|
46
47
|
"Include sections:\n"
|
|
47
48
|
"1. Executive summary\n"
|
|
48
49
|
"2. Glycemic behavior\n"
|
|
49
|
-
"3. Safety
|
|
50
|
-
"4. Notable events or anomalies\n"
|
|
50
|
+
"3. Safety, supervision, or device behavior\n"
|
|
51
|
+
"4. Notable events, patterns, or anomalies\n"
|
|
51
52
|
"5. Research-only conclusion\n\n"
|
|
52
|
-
"
|
|
53
|
+
"Input JSON:\n{data}"
|
|
53
54
|
),
|
|
54
55
|
}
|
|
55
56
|
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
from .clinical_metrics import ClinicalMetricsCalculator, ClinicalMetricsResult
|
|
2
2
|
from .baseline import compute_metrics, run_baseline_comparison, write_baseline_comparison
|
|
3
|
+
from .carelink_workbench import build_carelink_workbench
|
|
4
|
+
from .poster import generate_results_poster
|
|
3
5
|
from .reporting import ClinicalReportGenerator
|
|
4
6
|
|
|
5
7
|
__all__ = [
|
|
8
|
+
"build_carelink_workbench",
|
|
6
9
|
"ClinicalMetricsCalculator",
|
|
7
10
|
"ClinicalMetricsResult",
|
|
8
11
|
"ClinicalReportGenerator",
|
|
9
12
|
"compute_metrics",
|
|
13
|
+
"generate_results_poster",
|
|
10
14
|
"run_baseline_comparison",
|
|
11
15
|
"write_baseline_comparison",
|
|
12
16
|
]
|