mikon 0.0.1__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 (92) hide show
  1. mikon-0.0.1/.gitignore +16 -0
  2. mikon-0.0.1/LICENSE +21 -0
  3. mikon-0.0.1/PKG-INFO +138 -0
  4. mikon-0.0.1/README-ja.md +98 -0
  5. mikon-0.0.1/README.md +98 -0
  6. mikon-0.0.1/mikon/__init__.py +8 -0
  7. mikon-0.0.1/mikon/_runner.py +146 -0
  8. mikon-0.0.1/mikon/cli.py +220 -0
  9. mikon-0.0.1/mikon/sdk/__init__.py +40 -0
  10. mikon-0.0.1/mikon/sdk/config.py +7 -0
  11. mikon-0.0.1/mikon/sdk/context.py +163 -0
  12. mikon-0.0.1/mikon/sdk/datasets.py +177 -0
  13. mikon-0.0.1/mikon/sdk/job.py +94 -0
  14. mikon-0.0.1/mikon/sdk/module.py +325 -0
  15. mikon-0.0.1/mikon/server/__init__.py +1 -0
  16. mikon-0.0.1/mikon/server/api.py +450 -0
  17. mikon-0.0.1/mikon/server/app.py +131 -0
  18. mikon-0.0.1/mikon/server/discovery.py +412 -0
  19. mikon-0.0.1/mikon/server/docs.py +536 -0
  20. mikon-0.0.1/mikon/server/models.py +361 -0
  21. mikon-0.0.1/mikon/server/problems.py +32 -0
  22. mikon-0.0.1/mikon/server/registry.py +96 -0
  23. mikon-0.0.1/mikon/server/resources.py +709 -0
  24. mikon-0.0.1/mikon/server/runner.py +284 -0
  25. mikon-0.0.1/mikon/server/schema.py +51 -0
  26. mikon-0.0.1/mikon/server/settings.py +43 -0
  27. mikon-0.0.1/mikon/server/store.py +1050 -0
  28. mikon-0.0.1/mikon/templates/docs/USAGE-ja.md +924 -0
  29. mikon-0.0.1/mikon/templates/docs/USAGE.md +924 -0
  30. mikon-0.0.1/mikon/web/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  31. mikon-0.0.1/mikon/web/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  32. mikon-0.0.1/mikon/web/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  33. mikon-0.0.1/mikon/web/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  34. mikon-0.0.1/mikon/web/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  35. mikon-0.0.1/mikon/web/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  36. mikon-0.0.1/mikon/web/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  37. mikon-0.0.1/mikon/web/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  38. mikon-0.0.1/mikon/web/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  39. mikon-0.0.1/mikon/web/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  40. mikon-0.0.1/mikon/web/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  41. mikon-0.0.1/mikon/web/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  42. mikon-0.0.1/mikon/web/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  43. mikon-0.0.1/mikon/web/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  44. mikon-0.0.1/mikon/web/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  45. mikon-0.0.1/mikon/web/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  46. mikon-0.0.1/mikon/web/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  47. mikon-0.0.1/mikon/web/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  48. mikon-0.0.1/mikon/web/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  49. mikon-0.0.1/mikon/web/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  50. mikon-0.0.1/mikon/web/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  51. mikon-0.0.1/mikon/web/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  52. mikon-0.0.1/mikon/web/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  53. mikon-0.0.1/mikon/web/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  54. mikon-0.0.1/mikon/web/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  55. mikon-0.0.1/mikon/web/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  56. mikon-0.0.1/mikon/web/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  57. mikon-0.0.1/mikon/web/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  58. mikon-0.0.1/mikon/web/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  59. mikon-0.0.1/mikon/web/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  60. mikon-0.0.1/mikon/web/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  61. mikon-0.0.1/mikon/web/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  62. mikon-0.0.1/mikon/web/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  63. mikon-0.0.1/mikon/web/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  64. mikon-0.0.1/mikon/web/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  65. mikon-0.0.1/mikon/web/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  66. mikon-0.0.1/mikon/web/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  67. mikon-0.0.1/mikon/web/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  68. mikon-0.0.1/mikon/web/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  69. mikon-0.0.1/mikon/web/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  70. mikon-0.0.1/mikon/web/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  71. mikon-0.0.1/mikon/web/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  72. mikon-0.0.1/mikon/web/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  73. mikon-0.0.1/mikon/web/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  74. mikon-0.0.1/mikon/web/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  75. mikon-0.0.1/mikon/web/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  76. mikon-0.0.1/mikon/web/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  77. mikon-0.0.1/mikon/web/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  78. mikon-0.0.1/mikon/web/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  79. mikon-0.0.1/mikon/web/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  80. mikon-0.0.1/mikon/web/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  81. mikon-0.0.1/mikon/web/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  82. mikon-0.0.1/mikon/web/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  83. mikon-0.0.1/mikon/web/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  84. mikon-0.0.1/mikon/web/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  85. mikon-0.0.1/mikon/web/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  86. mikon-0.0.1/mikon/web/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  87. mikon-0.0.1/mikon/web/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  88. mikon-0.0.1/mikon/web/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  89. mikon-0.0.1/mikon/web/assets/index-DVrEHM_2.css +2 -0
  90. mikon-0.0.1/mikon/web/assets/index-WIx9l7H5.js +372 -0
  91. mikon-0.0.1/mikon/web/index.html +13 -0
  92. mikon-0.0.1/pyproject.toml +88 -0
mikon-0.0.1/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ documents
2
+ .mikon/
3
+ .venv/
4
+ venv/
5
+ __pycache__/
6
+ *.py[cod]
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+ dist/
10
+ build/
11
+ *.egg-info/
12
+ node_modules/
13
+ frontend/dist/
14
+ frontend/node_modules/
15
+ mikon/web/index.html
16
+ mikon/web/assets/
mikon-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 miko-misa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
mikon-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,138 @@
1
+ Metadata-Version: 2.4
2
+ Name: mikon
3
+ Version: 0.0.1
4
+ Summary: Self-hosted AI development manager for GPU job execution on your own servers
5
+ Project-URL: Homepage, https://github.com/miko-misa/mikon
6
+ Project-URL: Repository, https://github.com/miko-misa/mikon
7
+ Project-URL: Issues, https://github.com/miko-misa/mikon/issues
8
+ Project-URL: Changelog, https://github.com/miko-misa/mikon/releases
9
+ Author-email: miko-misa <hacnosuke@gmail.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: amd,deep-learning,experiment-tracking,gpu,job-management,machine-learning,mlops,nvidia
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Topic :: System :: Monitoring
25
+ Requires-Python: >=3.11
26
+ Requires-Dist: bleach<7,>=6.1
27
+ Requires-Dist: fastapi<1,>=0.115
28
+ Requires-Dist: httpx<1,>=0.27
29
+ Requires-Dist: markdown<4,>=3.6
30
+ Requires-Dist: nvidia-ml-py<13,>=12.550
31
+ Requires-Dist: psutil<8,>=5.9
32
+ Requires-Dist: pydantic<3,>=2.8
33
+ Requires-Dist: pygments<3,>=2.18
34
+ Requires-Dist: pymdown-extensions<11,>=10.11
35
+ Requires-Dist: sse-starlette<4,>=2.1
36
+ Requires-Dist: typer<1,>=0.12
37
+ Requires-Dist: uvicorn[standard]<1,>=0.30
38
+ Requires-Dist: watchfiles<2,>=0.22
39
+ Description-Content-Type: text/markdown
40
+
41
+ # mikon
42
+
43
+ > 日本語版: [README-ja.md](README-ja.md)
44
+
45
+ A self-hosted tool for managing AI development (training and evaluation jobs) on GPU servers from a browser.
46
+
47
+ **Write Python the way you normally would, and just add a decorator to your functions.** mikon automatically discovers your jobs, generates config forms, allocates GPUs, launches runs, and displays metrics, logs, and artifacts in real time.
48
+
49
+ ---
50
+
51
+ ## Features
52
+
53
+ - **Decorator-only discovery** — Just add `@mikon.job`. No registration step, no code changes required.
54
+ - **Auto-generated config UI** — Pydantic fields on `class Config(mikon.Config)` become form widgets automatically (sliders, selects, checkboxes, etc.)
55
+ - **NVIDIA and AMD support** — Specify GPUs in unified `nvidia:0` / `amd:0` format. `CUDA_VISIBLE_DEVICES` / `ROCR_VISIBLE_DEVICES` are set automatically.
56
+ - **Live monitoring** — Metric charts and log streams update every few seconds via SSE.
57
+ - **Artifact management** — Call `ctx.log_artifact()` to make files downloadable from the browser.
58
+ - **Lineage tracking** — `ctx.use_dataset()` / `ctx.use_artifact()` automatically build an upstream/downstream graph.
59
+ - **Module system** — Register swappable components with `@mikon.module`; the UI generates a module-selection form automatically.
60
+ - **Dataset management** — Register existing paths or create datasets with a builder function.
61
+ - **Document viewer** — Markdown, Typst, and TypMark files placed in `docs/` are viewable in the dashboard.
62
+ - **File-based persistence** — No SQL database required. Everything is stored as text files under `.mikon/`.
63
+ - **Independent processes** — Jobs keep running even if the dashboard is restarted.
64
+
65
+ ---
66
+
67
+ ## Requirements
68
+
69
+ - Python 3.11+
70
+ - GPU server with NVIDIA drivers or AMD ROCm installed
71
+ - `typst` CLI (optional, for Typst document rendering)
72
+ - `typmark-cli` CLI (optional, for TypMark document rendering)
73
+
74
+ ---
75
+
76
+ ## Quick Start
77
+
78
+ ```bash
79
+ # Install
80
+ uv add mikon # or: pip install mikon
81
+
82
+ # Initialize project
83
+ mikon init
84
+ ```
85
+
86
+ ```python
87
+ # src/train.py
88
+ import mikon
89
+ from mikon import Config, RunContext
90
+ from pydantic import Field
91
+ from typing import Literal
92
+
93
+ class TrainConfig(Config):
94
+ lr: float = Field(1e-3, gt=0, le=1)
95
+ epochs: int = Field(10, ge=1, le=1000)
96
+ optimizer: Literal["adam", "sgd"] = "adam"
97
+
98
+ @mikon.job
99
+ def train(config: TrainConfig, ctx: RunContext) -> None:
100
+ for epoch in range(config.epochs):
101
+ loss = 1.0 / (epoch + 1)
102
+ ctx.log_metric("loss", loss, step=epoch)
103
+ ```
104
+
105
+ ```bash
106
+ # Start the server on the GPU machine
107
+ mikon serve
108
+
109
+ # Launch a job from the CLI
110
+ mikon run train --gpu nvidia:0
111
+
112
+ # Access the dashboard from your local machine via SSH port forwarding
113
+ ssh -L 8000:localhost:8000 you@gpu-server
114
+ # → Open http://localhost:8000 in your browser
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Installation
120
+
121
+ ```bash
122
+ uv add mikon # recommended
123
+ pip install mikon
124
+ ```
125
+
126
+ Dependencies (`pynvml`, `psutil`, `watchfiles`, `fastapi`, etc.) are installed automatically.
127
+
128
+ ---
129
+
130
+ ## Documentation
131
+
132
+ For the full usage guide, SDK reference, CLI options, and API error model, see [USAGE.md](USAGE.md).
133
+
134
+ ---
135
+
136
+ ## License
137
+
138
+ MIT
@@ -0,0 +1,98 @@
1
+ # mikon
2
+
3
+ > English: [README.md](README.md)
4
+
5
+ GPUサーバー上のAI開発(学習・評価ジョブ)をブラウザで管理するセルフホスト型ツール。
6
+
7
+ **あなたは普段どおりPythonでコードを書き、関数にデコレータを付けるだけ。** ツールが自動でジョブを認識し、コンフィグのフォームを生成し、GPUを割り当てて起動し、メトリクス・ログ・成果物をリアルタイムで表示します。
8
+
9
+ ---
10
+
11
+ ## 特徴
12
+
13
+ - **デコレータだけで認識** — `@mikon.job` を付けるだけ。登録作業やコード変更は不要
14
+ - **コンフィグUIの自動生成** — `class Config(mikon.Config)` の Pydantic フィールドがそのままフォームになる(スライダ・セレクト・チェックボックスなど)
15
+ - **NVIDIA / AMD 両対応** — `nvidia:0` / `amd:0` の統一形式でGPUを指定。`CUDA_VISIBLE_DEVICES` / `ROCR_VISIBLE_DEVICES` を自動設定
16
+ - **ライブモニタリング** — メトリクスチャート・ログストリームが数秒更新(SSE)
17
+ - **成果物管理** — `ctx.log_artifact()` でブラウザからダウンロード可能
18
+ - **リネージュ追跡** — `ctx.use_dataset()` / `ctx.use_artifact()` で上流/下流グラフを自動構築
19
+ - **モジュールシステム** — 差し替え可能なコンポーネントを `@mikon.module` で登録、UIでモジュール選択フォームが自動生成
20
+ - **データセット管理** — 既存パスの登録、ビルダーによる自動作成
21
+ - **ドキュメント閲覧** — `docs/` に置いた Markdown / Typst / TypMark をダッシュボードで表示
22
+ - **ファイルベース永続化** — SQLデータベース不要。すべて `.mikon/` 以下のテキストファイルに保存
23
+ - **独立プロセス** — ダッシュボードを再起動してもジョブは生き続ける
24
+
25
+ ---
26
+
27
+ ## 要件
28
+
29
+ - Python 3.11+
30
+ - GPUサーバー(NVIDIA ドライバ or AMD ROCm 導入済み)
31
+ - Typst ドキュメントを使う場合は `typst` CLI(任意)
32
+ - TypMark ドキュメントを使う場合は `typmark-cli` CLI(任意)
33
+
34
+ ---
35
+
36
+ ## クイックスタート
37
+
38
+ ```bash
39
+ # インストール
40
+ uv add mikon # または pip install mikon
41
+
42
+ # プロジェクト初期化
43
+ mikon init
44
+ ```
45
+
46
+ ```python
47
+ # src/train.py
48
+ import mikon
49
+ from mikon import Config, RunContext
50
+ from pydantic import Field
51
+ from typing import Literal
52
+
53
+ class TrainConfig(Config):
54
+ lr: float = Field(1e-3, gt=0, le=1)
55
+ epochs: int = Field(10, ge=1, le=1000)
56
+ optimizer: Literal["adam", "sgd"] = "adam"
57
+
58
+ @mikon.job
59
+ def train(config: TrainConfig, ctx: RunContext) -> None:
60
+ for epoch in range(config.epochs):
61
+ loss = 1.0 / (epoch + 1)
62
+ ctx.log_metric("loss", loss, step=epoch)
63
+ ```
64
+
65
+ ```bash
66
+ # サーバー起動(GPUサーバー上で)
67
+ mikon serve
68
+
69
+ # CLIから起動
70
+ mikon run train --gpu nvidia:0
71
+
72
+ # 手元PCからはSSHポートフォワードで
73
+ ssh -L 8000:localhost:8000 you@gpu-server
74
+ # → ブラウザで http://localhost:8000
75
+ ```
76
+
77
+ ---
78
+
79
+ ## インストール
80
+
81
+ ```bash
82
+ uv add mikon # 推奨
83
+ pip install mikon
84
+ ```
85
+
86
+ 依存ライブラリ(`pynvml`・`psutil`・`watchfiles`・`fastapi` など)は自動でインストールされます。
87
+
88
+ ---
89
+
90
+ ## ドキュメント
91
+
92
+ 詳細な使い方・SDK リファレンス・CLI オプション・API エラーモデルは [USAGE-ja.md](USAGE-ja.md) を参照してください。
93
+
94
+ ---
95
+
96
+ ## ライセンス
97
+
98
+ MIT
mikon-0.0.1/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # mikon
2
+
3
+ > 日本語版: [README-ja.md](README-ja.md)
4
+
5
+ A self-hosted tool for managing AI development (training and evaluation jobs) on GPU servers from a browser.
6
+
7
+ **Write Python the way you normally would, and just add a decorator to your functions.** mikon automatically discovers your jobs, generates config forms, allocates GPUs, launches runs, and displays metrics, logs, and artifacts in real time.
8
+
9
+ ---
10
+
11
+ ## Features
12
+
13
+ - **Decorator-only discovery** — Just add `@mikon.job`. No registration step, no code changes required.
14
+ - **Auto-generated config UI** — Pydantic fields on `class Config(mikon.Config)` become form widgets automatically (sliders, selects, checkboxes, etc.)
15
+ - **NVIDIA and AMD support** — Specify GPUs in unified `nvidia:0` / `amd:0` format. `CUDA_VISIBLE_DEVICES` / `ROCR_VISIBLE_DEVICES` are set automatically.
16
+ - **Live monitoring** — Metric charts and log streams update every few seconds via SSE.
17
+ - **Artifact management** — Call `ctx.log_artifact()` to make files downloadable from the browser.
18
+ - **Lineage tracking** — `ctx.use_dataset()` / `ctx.use_artifact()` automatically build an upstream/downstream graph.
19
+ - **Module system** — Register swappable components with `@mikon.module`; the UI generates a module-selection form automatically.
20
+ - **Dataset management** — Register existing paths or create datasets with a builder function.
21
+ - **Document viewer** — Markdown, Typst, and TypMark files placed in `docs/` are viewable in the dashboard.
22
+ - **File-based persistence** — No SQL database required. Everything is stored as text files under `.mikon/`.
23
+ - **Independent processes** — Jobs keep running even if the dashboard is restarted.
24
+
25
+ ---
26
+
27
+ ## Requirements
28
+
29
+ - Python 3.11+
30
+ - GPU server with NVIDIA drivers or AMD ROCm installed
31
+ - `typst` CLI (optional, for Typst document rendering)
32
+ - `typmark-cli` CLI (optional, for TypMark document rendering)
33
+
34
+ ---
35
+
36
+ ## Quick Start
37
+
38
+ ```bash
39
+ # Install
40
+ uv add mikon # or: pip install mikon
41
+
42
+ # Initialize project
43
+ mikon init
44
+ ```
45
+
46
+ ```python
47
+ # src/train.py
48
+ import mikon
49
+ from mikon import Config, RunContext
50
+ from pydantic import Field
51
+ from typing import Literal
52
+
53
+ class TrainConfig(Config):
54
+ lr: float = Field(1e-3, gt=0, le=1)
55
+ epochs: int = Field(10, ge=1, le=1000)
56
+ optimizer: Literal["adam", "sgd"] = "adam"
57
+
58
+ @mikon.job
59
+ def train(config: TrainConfig, ctx: RunContext) -> None:
60
+ for epoch in range(config.epochs):
61
+ loss = 1.0 / (epoch + 1)
62
+ ctx.log_metric("loss", loss, step=epoch)
63
+ ```
64
+
65
+ ```bash
66
+ # Start the server on the GPU machine
67
+ mikon serve
68
+
69
+ # Launch a job from the CLI
70
+ mikon run train --gpu nvidia:0
71
+
72
+ # Access the dashboard from your local machine via SSH port forwarding
73
+ ssh -L 8000:localhost:8000 you@gpu-server
74
+ # → Open http://localhost:8000 in your browser
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Installation
80
+
81
+ ```bash
82
+ uv add mikon # recommended
83
+ pip install mikon
84
+ ```
85
+
86
+ Dependencies (`pynvml`, `psutil`, `watchfiles`, `fastapi`, etc.) are installed automatically.
87
+
88
+ ---
89
+
90
+ ## Documentation
91
+
92
+ For the full usage guide, SDK reference, CLI options, and API error model, see [USAGE.md](USAGE.md).
93
+
94
+ ---
95
+
96
+ ## License
97
+
98
+ MIT
@@ -0,0 +1,8 @@
1
+ from mikon.sdk.config import Config
2
+ from mikon.sdk.context import RunContext
3
+ from mikon.sdk import datasets
4
+ from mikon.sdk.datasets import DatasetContext, dataset
5
+ from mikon.sdk.job import job
6
+ from mikon.sdk.module import ModuleFactory, ModuleRef, module
7
+
8
+ __all__ = ["Config", "DatasetContext", "ModuleFactory", "ModuleRef", "RunContext", "dataset", "datasets", "job", "module"]
@@ -0,0 +1,146 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ import signal
6
+ import sys
7
+ import threading
8
+ import time
9
+ import traceback
10
+ from pathlib import Path
11
+ from typing import TextIO
12
+
13
+ from mikon.sdk.datasets import DatasetContext, get_dataset_registry
14
+ from mikon.sdk.context import RunContext
15
+ from mikon.sdk.job import get_registry
16
+ from mikon.sdk.module import instantiate_config_modules, validate_module_nest_depth
17
+ from mikon.server.discovery import import_project
18
+ from mikon.server.models import RunStatus
19
+ from mikon.server.settings import load_settings
20
+ from mikon.server.store import Store
21
+
22
+
23
+ def main(argv: list[str] | None = None) -> int:
24
+ parser = argparse.ArgumentParser()
25
+ parser.add_argument("--run-dir", required=True)
26
+ args = parser.parse_args(argv)
27
+ run_dir = Path(args.run_dir).resolve()
28
+ store = Store(run_dir.parents[1])
29
+ meta = store.read_json(run_dir / "meta.json")
30
+ run_id = meta["run_id"]
31
+
32
+ stop_event = threading.Event()
33
+ heartbeat = threading.Thread(
34
+ target=_heartbeat_loop, args=(run_dir, stop_event), name="mikon-heartbeat", daemon=True
35
+ )
36
+ heartbeat.start()
37
+
38
+ def _handle_signal(signum: int, frame: object) -> None:
39
+ raise KeyboardInterrupt(f"received signal {signum}")
40
+
41
+ signal.signal(signal.SIGTERM, _handle_signal)
42
+ signal.signal(signal.SIGINT, _handle_signal)
43
+
44
+ status = RunStatus.completed
45
+ exit_code = 0
46
+ error: str | None = None
47
+ event_logger = _LogEventWriter(run_dir / "logs" / "events.jsonl")
48
+ original_stdout = sys.stdout
49
+ original_stderr = sys.stderr
50
+ sys.stdout = _TeeLineWriter(original_stdout, event_logger, "stdout")
51
+ sys.stderr = _TeeLineWriter(original_stderr, event_logger, "stderr")
52
+ try:
53
+ project_root = Path(meta["project_root"]).resolve()
54
+ watch_paths = [Path(item).resolve() for item in meta["watch"]]
55
+ import_project(project_root, watch_paths)
56
+ kind = meta.get("kind", "job")
57
+ if kind == "dataset":
58
+ definition = get_dataset_registry().get(meta["job"])
59
+ else:
60
+ definition = get_registry().get(meta["job"])
61
+ if definition is None:
62
+ raise RuntimeError(f"{kind} not found during run: {meta['job']}")
63
+ config_data = store.read_json(run_dir / "config.json")
64
+ settings = load_settings(project_root)
65
+ validate_module_nest_depth(config_data, settings.max_module_nest_depth)
66
+ config = definition.config_type.model_validate(config_data)
67
+ validate_module_nest_depth(config.model_dump(mode="json"), settings.max_module_nest_depth)
68
+ instantiate_config_modules(config, max_depth=settings.max_module_nest_depth)
69
+ ctx = DatasetContext(run_dir, meta["job"]) if kind == "dataset" else RunContext(run_dir)
70
+ definition.func(config, ctx)
71
+ except KeyboardInterrupt as exc:
72
+ status = RunStatus.stopped
73
+ exit_code = 143
74
+ error = str(exc)
75
+ except BaseException:
76
+ status = RunStatus.failed
77
+ exit_code = 1
78
+ error = traceback.format_exc()
79
+ finally:
80
+ sys.stdout = original_stdout
81
+ sys.stderr = original_stderr
82
+ event_logger.flush()
83
+ stop_event.set()
84
+ heartbeat.join(timeout=1)
85
+ store.write_status(run_id, status, exit_code, error)
86
+ return exit_code
87
+
88
+
89
+ def _heartbeat_loop(run_dir: Path, stop_event: threading.Event) -> None:
90
+ heartbeat = run_dir / "heartbeat"
91
+ while not stop_event.is_set():
92
+ heartbeat.write_text(str(time.time()), encoding="utf-8")
93
+ stop_event.wait(2)
94
+
95
+
96
+ class _LogEventWriter:
97
+ def __init__(self, path: Path) -> None:
98
+ self.path = path
99
+ self.path.parent.mkdir(parents=True, exist_ok=True)
100
+ self._lock = threading.Lock()
101
+ self._seq = 0
102
+
103
+ def write_line(self, stream: str, line: str) -> None:
104
+ with self._lock:
105
+ record = {"seq": self._seq, "t": time.time(), "stream": stream, "line": line}
106
+ self._seq += 1
107
+ with self.path.open("a", encoding="utf-8") as fp:
108
+ fp.write(json.dumps(record, separators=(",", ":"), allow_nan=False) + "\n")
109
+ fp.flush()
110
+
111
+ def flush(self) -> None:
112
+ return
113
+
114
+
115
+ class _TeeLineWriter:
116
+ def __init__(self, target: TextIO, event_logger: _LogEventWriter, stream: str) -> None:
117
+ self.target = target
118
+ self.event_logger = event_logger
119
+ self.stream = stream
120
+ self._buffer = ""
121
+
122
+ def write(self, text: str) -> int:
123
+ written = self.target.write(text)
124
+ self.target.flush()
125
+ self._buffer += text
126
+ while "\n" in self._buffer:
127
+ line, self._buffer = self._buffer.split("\n", 1)
128
+ self.event_logger.write_line(self.stream, line)
129
+ return written
130
+
131
+ def flush(self) -> None:
132
+ self.target.flush()
133
+ if self._buffer:
134
+ self.event_logger.write_line(self.stream, self._buffer)
135
+ self._buffer = ""
136
+
137
+ def isatty(self) -> bool:
138
+ return self.target.isatty()
139
+
140
+ @property
141
+ def encoding(self) -> str | None:
142
+ return self.target.encoding
143
+
144
+
145
+ if __name__ == "__main__":
146
+ raise SystemExit(main())