infer-stack 0.6.0__tar.gz → 0.7.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.
Files changed (116) hide show
  1. infer_stack-0.7.0/LICENSE +13 -0
  2. {infer_stack-0.6.0/infer_stack.egg-info → infer_stack-0.7.0}/PKG-INFO +41 -2
  3. infer_stack-0.6.0/PKG-INFO → infer_stack-0.7.0/README.md +32 -29
  4. infer_stack-0.7.0/infer_stack/__init__.py +2 -0
  5. infer_stack-0.7.0/infer_stack/__main__.py +6 -0
  6. infer_stack-0.7.0/infer_stack/_log.py +51 -0
  7. infer_stack-0.7.0/infer_stack/backends/__init__.py +4 -0
  8. infer_stack-0.7.0/infer_stack/backends/kubeai.py +535 -0
  9. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack/backends/kubeai_renderer.py +3 -1
  10. infer_stack-0.7.0/infer_stack/cli/__init__.py +171 -0
  11. infer_stack-0.7.0/infer_stack/cli/commands_catalog.py +854 -0
  12. infer_stack-0.7.0/infer_stack/cli/commands_leasing.py +2314 -0
  13. infer_stack-0.7.0/infer_stack/cli/commands_meta.py +594 -0
  14. infer_stack-0.7.0/infer_stack/cli/commands_mock.py +171 -0
  15. infer_stack-0.7.0/infer_stack/cli/commands_runtime.py +627 -0
  16. infer_stack-0.7.0/infer_stack/cli/context.py +102 -0
  17. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack/cli/options.py +18 -4
  18. infer_stack-0.7.0/infer_stack/config.py +248 -0
  19. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack/diff_prompt.py +37 -1
  20. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack/docker_utils.py +65 -0
  21. infer_stack-0.7.0/infer_stack/gpu_doctor.py +240 -0
  22. infer_stack-0.7.0/infer_stack/hardware.py +145 -0
  23. infer_stack-0.7.0/infer_stack/leasing/__init__.py +103 -0
  24. infer_stack-0.7.0/infer_stack/leasing/backend.py +309 -0
  25. infer_stack-0.7.0/infer_stack/leasing/catalog.py +515 -0
  26. infer_stack-0.7.0/infer_stack/leasing/compose.py +2359 -0
  27. infer_stack-0.7.0/infer_stack/leasing/controller.py +840 -0
  28. infer_stack-0.7.0/infer_stack/leasing/envfile.py +137 -0
  29. infer_stack-0.7.0/infer_stack/leasing/ledger.py +380 -0
  30. infer_stack-0.7.0/infer_stack/leasing/models.py +354 -0
  31. infer_stack-0.7.0/infer_stack/leasing/placement.py +398 -0
  32. infer_stack-0.7.0/infer_stack/leasing/store.py +484 -0
  33. infer_stack-0.7.0/infer_stack/leasing/suggest.py +274 -0
  34. infer_stack-0.7.0/infer_stack/leasing/vram.py +285 -0
  35. infer_stack-0.7.0/infer_stack/mockserver/__init__.py +38 -0
  36. infer_stack-0.7.0/infer_stack/mockserver/data/oracle_questions.yaml +51 -0
  37. infer_stack-0.7.0/infer_stack/mockserver/modes.py +252 -0
  38. infer_stack-0.7.0/infer_stack/mockserver/server.py +465 -0
  39. infer_stack-0.7.0/infer_stack/mockserver/simulator.py +515 -0
  40. infer_stack-0.7.0/infer_stack/mockserver/vllm_serve.py +193 -0
  41. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack/paths.py +81 -0
  42. infer_stack-0.6.0/infer_stack/cli/probes.py → infer_stack-0.7.0/infer_stack/probe.py +48 -85
  43. infer_stack-0.7.0/infer_stack/profile_runtime.py +167 -0
  44. infer_stack-0.7.0/infer_stack/templates/suggestion-pool.yaml +377 -0
  45. infer_stack-0.7.0/infer_stack/tui.py +2574 -0
  46. infer_stack-0.6.0/README.md → infer_stack-0.7.0/infer_stack.egg-info/PKG-INFO +68 -1
  47. infer_stack-0.7.0/infer_stack.egg-info/SOURCES.txt +82 -0
  48. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack.egg-info/requires.txt +6 -0
  49. {infer_stack-0.6.0 → infer_stack-0.7.0}/pyproject.toml +17 -5
  50. infer_stack-0.7.0/tests/test_cli_catalog.py +305 -0
  51. infer_stack-0.7.0/tests/test_cli_config.py +154 -0
  52. infer_stack-0.7.0/tests/test_cli_leasing.py +890 -0
  53. infer_stack-0.7.0/tests/test_cli_meta.py +153 -0
  54. infer_stack-0.7.0/tests/test_gpu_doctor.py +113 -0
  55. infer_stack-0.7.0/tests/test_leasing_catalog.py +307 -0
  56. infer_stack-0.7.0/tests/test_leasing_coalesced_apply.py +405 -0
  57. infer_stack-0.7.0/tests/test_leasing_compose.py +1583 -0
  58. infer_stack-0.7.0/tests/test_leasing_controller.py +233 -0
  59. infer_stack-0.7.0/tests/test_leasing_controller_lock.py +258 -0
  60. infer_stack-0.7.0/tests/test_leasing_controller_queue.py +365 -0
  61. infer_stack-0.7.0/tests/test_leasing_dynamic_routing.py +388 -0
  62. infer_stack-0.7.0/tests/test_leasing_kubeai.py +518 -0
  63. infer_stack-0.7.0/tests/test_leasing_ledger.py +328 -0
  64. infer_stack-0.7.0/tests/test_leasing_placement.py +391 -0
  65. infer_stack-0.7.0/tests/test_leasing_reservation.py +211 -0
  66. infer_stack-0.7.0/tests/test_leasing_route_registry.py +427 -0
  67. infer_stack-0.7.0/tests/test_leasing_suggest.py +132 -0
  68. infer_stack-0.7.0/tests/test_leasing_vram.py +154 -0
  69. infer_stack-0.7.0/tests/test_mock_vllm_serve.py +288 -0
  70. infer_stack-0.7.0/tests/test_mockserver.py +741 -0
  71. infer_stack-0.7.0/tests/test_reservation_gpu_frame_e2e.py +150 -0
  72. infer_stack-0.7.0/tests/test_simulator_runtime.py +144 -0
  73. infer_stack-0.7.0/tests/test_tui.py +1513 -0
  74. infer_stack-0.6.0/infer_stack/__init__.py +0 -2
  75. infer_stack-0.6.0/infer_stack/backends/__init__.py +0 -7
  76. infer_stack-0.6.0/infer_stack/backends/compose_renderer.py +0 -243
  77. infer_stack-0.6.0/infer_stack/benchmark.py +0 -38
  78. infer_stack-0.6.0/infer_stack/catalog.py +0 -438
  79. infer_stack-0.6.0/infer_stack/cli/__init__.py +0 -169
  80. infer_stack-0.6.0/infer_stack/cli/commands_profile.py +0 -467
  81. infer_stack-0.6.0/infer_stack/cli/commands_runtime.py +0 -719
  82. infer_stack-0.6.0/infer_stack/cli/commands_smoke.py +0 -691
  83. infer_stack-0.6.0/infer_stack/cli/compose.py +0 -755
  84. infer_stack-0.6.0/infer_stack/cli/context.py +0 -471
  85. infer_stack-0.6.0/infer_stack/config.py +0 -450
  86. infer_stack-0.6.0/infer_stack/contracts.py +0 -223
  87. infer_stack-0.6.0/infer_stack/hardware.py +0 -70
  88. infer_stack-0.6.0/infer_stack/profile_runtime.py +0 -46
  89. infer_stack-0.6.0/infer_stack/renderer.py +0 -19
  90. infer_stack-0.6.0/infer_stack/resolver.py +0 -1092
  91. infer_stack-0.6.0/infer_stack/templates/default-models.yaml +0 -674
  92. infer_stack-0.6.0/infer_stack/templates/default-ollama-models.yaml +0 -31
  93. infer_stack-0.6.0/infer_stack/templates/default-profiles.yaml +0 -1731
  94. infer_stack-0.6.0/infer_stack/templates/default-vllm-models.yaml +0 -714
  95. infer_stack-0.6.0/infer_stack/templates/docker-compose.yml.j2 +0 -430
  96. infer_stack-0.6.0/infer_stack/templates/litellm_config.yaml.j2 +0 -44
  97. infer_stack-0.6.0/infer_stack/templates/nginx.conf.j2 +0 -84
  98. infer_stack-0.6.0/infer_stack/tuning.py +0 -3
  99. infer_stack-0.6.0/infer_stack/validator.py +0 -314
  100. infer_stack-0.6.0/infer_stack/verification.py +0 -46
  101. infer_stack-0.6.0/infer_stack.egg-info/SOURCES.txt +0 -52
  102. infer_stack-0.6.0/tests/test_cli_setup.py +0 -723
  103. infer_stack-0.6.0/tests/test_ollama_stack_graph.py +0 -262
  104. infer_stack-0.6.0/tests/test_reverse_proxy_ldap.py +0 -392
  105. infer_stack-0.6.0/tests/test_serving_profiles.py +0 -1152
  106. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack/cli/__main__.py +0 -0
  107. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack/env_utils.py +0 -0
  108. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack/experimental/model_catalog_discover.py +0 -0
  109. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack/experimental/model_memory_estimator.py +0 -0
  110. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack/experimental/stress_test_long_context.py +0 -0
  111. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack/kubeai_ops.py +0 -0
  112. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack.egg-info/dependency_links.txt +0 -0
  113. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack.egg-info/entry_points.txt +0 -0
  114. {infer_stack-0.6.0 → infer_stack-0.7.0}/infer_stack.egg-info/top_level.txt +0 -0
  115. {infer_stack-0.6.0 → infer_stack-0.7.0}/setup.cfg +0 -0
  116. {infer_stack-0.6.0 → infer_stack-0.7.0}/tests/test_import.py +0 -0
@@ -0,0 +1,13 @@
1
+ Copyright 2026 Kitware Inc
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: infer-stack
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: Profile-driven compose and KubeAI deployment compiler for inference stacks
5
5
  Author-email: "jon.crall" <jon.crall@kitware.com>
6
6
  License-Expression: Apache-2.0
@@ -12,11 +12,14 @@ Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
13
  Classifier: Programming Language :: Python :: 3.13
14
14
  Classifier: Programming Language :: Python :: 3.14
15
+ Classifier: Programming Language :: Python :: 3.15
15
16
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
17
  Classifier: Topic :: Utilities
17
18
  Requires-Python: >=3.10
18
19
  Description-Content-Type: text/markdown
20
+ License-File: LICENSE
19
21
  Requires-Dist: jinja2>=3.1
22
+ Requires-Dist: loguru>=0.7
20
23
  Requires-Dist: pyyaml>=6.0
21
24
  Requires-Dist: requests>=2.31
22
25
  Requires-Dist: rich>=13.0
@@ -25,9 +28,37 @@ Requires-Dist: ubelt>=1.3
25
28
  Provides-Extra: tests
26
29
  Requires-Dist: pytest>=7.0; extra == "tests"
27
30
  Requires-Dist: pytest-codeblocks>=0.17; extra == "tests"
31
+ Requires-Dist: pytest-cov>=3.0; extra == "tests"
32
+ Requires-Dist: xdoctest>=1.1.5; extra == "tests"
33
+ Provides-Extra: tui
34
+ Requires-Dist: textual>=0.50; extra == "tui"
35
+ Dynamic: license-file
28
36
 
29
37
  # Infer Stack
30
38
 
39
+ [![PyPI version](https://img.shields.io/pypi/v/infer-stack.svg)](https://pypi.org/project/infer-stack/)
40
+ [![Python versions](https://img.shields.io/pypi/pyversions/infer-stack.svg)](https://pypi.org/project/infer-stack/)
41
+ [![License](https://img.shields.io/pypi/l/infer-stack.svg)](https://github.com/AIQ-Kitware/infer_stack/blob/main/LICENSE)
42
+
43
+ > **Heads up — the leasing model is now the primary workflow.** Declare models
44
+ > in a catalog (`infer-stack catalog …`) and `acquire`/`run` endpoints
45
+ > on demand; see `docs/source/manual/` (the Ollama + Open WebUI tutorial and the
46
+ > leasing demo) and `infer-stack help tree`. The
47
+ > **named stack profiles** documented below (`setup`/`render`/`up`/`switch`/…)
48
+ > are the pre-leasing model and now live under **`infer-stack legacy <command>`**
49
+ > (e.g. `infer-stack legacy render`). This README still describes that legacy
50
+ > flow; a leasing-oriented rewrite is pending.
51
+
52
+ ## Supported platform
53
+
54
+ `infer-stack` supports **Linux hosts only**. Its process locking, container
55
+ runtime integration, GPU discovery, and deployment workflows are intentionally
56
+ Linux-oriented. Windows is not a supported or tested execution platform.
57
+
58
+ Operational and security constraints that are accepted during the current
59
+ planning-stage release are tracked in
60
+ [docs/planning/known-limitations.md](docs/planning/known-limitations.md).
61
+
31
62
  `infer_stack` manages **named stack profiles** for local and Kubernetes-backed inference.
32
63
 
33
64
  A stack profile is a small graph made from:
@@ -58,6 +89,8 @@ infer-stack deploy
58
89
  infer-stack switch <profile> --apply # re-render and converge; no separate up needed
59
90
  infer-stack status
60
91
  infer-stack smoke-test
92
+ infer-stack version # print the installed version
93
+ infer-stack config paths # show where config / artifacts / caches live
61
94
  ```
62
95
 
63
96
  The CLI is built on [`scriptconfig`](https://gitlab.kitware.com/utils/scriptconfig),
@@ -164,7 +197,13 @@ There are exactly two path roots:
164
197
  | **Everything generated** — `generated/` (docker-compose.yml, .env, plan.yaml, kubeai/*) **and** `state/` (hf-cache, postgres volumes, Ollama store, runtime bind mounts) | `~/.local/share/infer_stack/` (resp. `$XDG_DATA_HOME`) | `--data-dir` (or `INFER_STACK_DATA_DIR`) |
165
198
 
166
199
  `--data-dir` is the single knob for "put everything I generate in one
167
- directory." Set it once at `setup`; it is baked into the absolute
200
+ directory." It **relocates the one infer-stack installation controlling a
201
+ host/backend; it does not create an isolated second installation**. Do not run
202
+ controllers from multiple config/data roots against the same Docker host or
203
+ Kubernetes namespace. See the
204
+ [single-owner limitation](docs/planning/known-limitations.md#one-control-plane-per-host-or-backend-namespace).
205
+
206
+ Set it once at `setup`; it is baked into the absolute
168
207
  `state.*` and `output.generated_dir` paths written to `config.yaml`, so
169
208
  later commands don't need it again:
170
209
 
@@ -1,33 +1,28 @@
1
- Metadata-Version: 2.4
2
- Name: infer-stack
3
- Version: 0.6.0
4
- Summary: Profile-driven compose and KubeAI deployment compiler for inference stacks
5
- Author-email: "jon.crall" <jon.crall@kitware.com>
6
- License-Expression: Apache-2.0
7
- Project-URL: Homepage, https://github.com/AIQ-Kitware/infer_stack
8
- Classifier: Development Status :: 1 - Planning
9
- Classifier: Intended Audience :: Developers
10
- Classifier: Programming Language :: Python :: 3.10
11
- Classifier: Programming Language :: Python :: 3.11
12
- Classifier: Programming Language :: Python :: 3.12
13
- Classifier: Programming Language :: Python :: 3.13
14
- Classifier: Programming Language :: Python :: 3.14
15
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
- Classifier: Topic :: Utilities
17
- Requires-Python: >=3.10
18
- Description-Content-Type: text/markdown
19
- Requires-Dist: jinja2>=3.1
20
- Requires-Dist: pyyaml>=6.0
21
- Requires-Dist: requests>=2.31
22
- Requires-Dist: rich>=13.0
23
- Requires-Dist: scriptconfig>=0.9
24
- Requires-Dist: ubelt>=1.3
25
- Provides-Extra: tests
26
- Requires-Dist: pytest>=7.0; extra == "tests"
27
- Requires-Dist: pytest-codeblocks>=0.17; extra == "tests"
28
-
29
1
  # Infer Stack
30
2
 
3
+ [![PyPI version](https://img.shields.io/pypi/v/infer-stack.svg)](https://pypi.org/project/infer-stack/)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/infer-stack.svg)](https://pypi.org/project/infer-stack/)
5
+ [![License](https://img.shields.io/pypi/l/infer-stack.svg)](https://github.com/AIQ-Kitware/infer_stack/blob/main/LICENSE)
6
+
7
+ > **Heads up — the leasing model is now the primary workflow.** Declare models
8
+ > in a catalog (`infer-stack catalog …`) and `acquire`/`run` endpoints
9
+ > on demand; see `docs/source/manual/` (the Ollama + Open WebUI tutorial and the
10
+ > leasing demo) and `infer-stack help tree`. The
11
+ > **named stack profiles** documented below (`setup`/`render`/`up`/`switch`/…)
12
+ > are the pre-leasing model and now live under **`infer-stack legacy <command>`**
13
+ > (e.g. `infer-stack legacy render`). This README still describes that legacy
14
+ > flow; a leasing-oriented rewrite is pending.
15
+
16
+ ## Supported platform
17
+
18
+ `infer-stack` supports **Linux hosts only**. Its process locking, container
19
+ runtime integration, GPU discovery, and deployment workflows are intentionally
20
+ Linux-oriented. Windows is not a supported or tested execution platform.
21
+
22
+ Operational and security constraints that are accepted during the current
23
+ planning-stage release are tracked in
24
+ [docs/planning/known-limitations.md](docs/planning/known-limitations.md).
25
+
31
26
  `infer_stack` manages **named stack profiles** for local and Kubernetes-backed inference.
32
27
 
33
28
  A stack profile is a small graph made from:
@@ -58,6 +53,8 @@ infer-stack deploy
58
53
  infer-stack switch <profile> --apply # re-render and converge; no separate up needed
59
54
  infer-stack status
60
55
  infer-stack smoke-test
56
+ infer-stack version # print the installed version
57
+ infer-stack config paths # show where config / artifacts / caches live
61
58
  ```
62
59
 
63
60
  The CLI is built on [`scriptconfig`](https://gitlab.kitware.com/utils/scriptconfig),
@@ -164,7 +161,13 @@ There are exactly two path roots:
164
161
  | **Everything generated** — `generated/` (docker-compose.yml, .env, plan.yaml, kubeai/*) **and** `state/` (hf-cache, postgres volumes, Ollama store, runtime bind mounts) | `~/.local/share/infer_stack/` (resp. `$XDG_DATA_HOME`) | `--data-dir` (or `INFER_STACK_DATA_DIR`) |
165
162
 
166
163
  `--data-dir` is the single knob for "put everything I generate in one
167
- directory." Set it once at `setup`; it is baked into the absolute
164
+ directory." It **relocates the one infer-stack installation controlling a
165
+ host/backend; it does not create an isolated second installation**. Do not run
166
+ controllers from multiple config/data roots against the same Docker host or
167
+ Kubernetes namespace. See the
168
+ [single-owner limitation](docs/planning/known-limitations.md#one-control-plane-per-host-or-backend-namespace).
169
+
170
+ Set it once at `setup`; it is baked into the absolute
168
171
  `state.*` and `output.generated_dir` paths written to `config.yaml`, so
169
172
  later commands don't need it again:
170
173
 
@@ -0,0 +1,2 @@
1
+ __all__ = []
2
+ __version__ = '0.7.0'
@@ -0,0 +1,6 @@
1
+ """Enable ``python -m infer_stack`` to run the CLI."""
2
+
3
+ from .cli import main
4
+
5
+ if __name__ == '__main__':
6
+ raise SystemExit(main())
@@ -0,0 +1,51 @@
1
+ """loguru-based "behind the scenes" feedback for the leasing CLI.
2
+
3
+ This is deliberately kept off the ``--help`` import path (loguru is ~50ms to
4
+ import): nothing at module scope in the CLI imports this. It is pulled in only
5
+ at runtime by the leasing verbs (``configure_logging``) and the converge/
6
+ reconcile code that narrates what it is doing.
7
+
8
+ The ``infer_stack`` package is ``disable``d here on import, so importing the
9
+ library (or running the test suite, which calls subcommands directly) stays
10
+ silent until the CLI explicitly calls :func:`configure_logging`.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import os
16
+ import sys
17
+
18
+ from loguru import logger
19
+
20
+ __all__ = ['logger', 'configure_logging']
21
+
22
+ # Silent by default; the CLI entry points re-enable via configure_logging().
23
+ logger.disable('infer_stack')
24
+ _CONFIGURED = False
25
+
26
+
27
+ def configure_logging(level: str | None = None, *, force: bool = False):
28
+ """Route infer-stack's narration to stderr (idempotent).
29
+
30
+ Level resolves to ``level`` arg > ``$INFER_STACK_LOG_LEVEL`` > ``INFO``.
31
+ Narration goes to stderr so it never pollutes a command's stdout (JSON,
32
+ ``$(infer-stack env KEY)``, etc.). Colorized only on a real terminal.
33
+ """
34
+ global _CONFIGURED
35
+ logger.enable('infer_stack')
36
+ if _CONFIGURED and not force:
37
+ return logger
38
+ level = (level or os.environ.get('INFER_STACK_LOG_LEVEL') or 'INFO').upper()
39
+ colorize = sys.stderr.isatty() and os.environ.get('NO_COLOR') is None
40
+ logger.remove()
41
+ logger.add(
42
+ sys.stderr,
43
+ level=level,
44
+ colorize=colorize,
45
+ format=(
46
+ '<dim>{time:HH:mm:ss}</dim> '
47
+ '<level>{level: <7}</level> {message}'
48
+ ),
49
+ )
50
+ _CONFIGURED = True
51
+ return logger
@@ -0,0 +1,4 @@
1
+ from .kubeai import KubeaiBackend
2
+ from .kubeai_renderer import render_kubeai_artifacts # legacy profile-era path
3
+
4
+ __all__ = ['KubeaiBackend', 'render_kubeai_artifacts']