diff --git a/blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md b/blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md
index 0079bcf90..c82b42c6d 100644
--- a/blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md
+++ b/blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md
@@ -68,12 +68,10 @@ graph TD
POD --> SCHED --> INJECT --> WEBHOOK --> CONTAINER --> ENFORCE
DAEMON -. "loads libvgpu.so" .-> CONTAINER
- style SCHED fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937
- style INJECT fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937
- style WEBHOOK fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937
- style DAEMON fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937
- style CONTAINER fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#1f2937
- style ENFORCE fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937
+ class SCHED,INJECT kai
+ class WEBHOOK,DAEMON info
+ class CONTAINER run
+ class ENFORCE ok
```
The workflow has four phases:
@@ -93,8 +91,8 @@ graph TD
B2 --> B3["Cannot oversubscribe
hard isolation"]
A3 ~~~ B1
- style A3 fill:#fee2e2,stroke:#b3261e,stroke-width:2px,color:#1f2937
- style B3 fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937
+ class A3 bad
+ class B3 ok
```
### Deploy
@@ -200,8 +198,8 @@ graph TD
HAMI --> Kueue
HAMI --> Koordinator
- style HAMI fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937
- style KAI fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937
+ class HAMI info
+ class KAI kai
```
### It creates real value for users
diff --git a/blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md b/blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md
index 62b1b04f3..2a90ac255 100644
--- a/blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md
+++ b/blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md
@@ -41,12 +41,10 @@ graph TD
LIB -. "provides libvgpu.so" .-> RUN
RUN -. "writes node-local cache" .-> MON
- style KAI fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937
- style WEBHOOK fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937
- style LIB fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937
- style RUN fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#1f2937
- style ENF fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937
- style MON fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937
+ class KAI kai
+ class WEBHOOK,LIB,MON info
+ class RUN run
+ class ENF ok
```
`CUDA_DEVICE_MEMORY_LIMIT` is the contract between scheduling and enforcement. KAI does not need to know how CUDA calls are intercepted, and HAMi-core does not need to know how the quota was calculated. KAI retains its own scheduling logic; it integrates with HAMi-core rather than replacing its scheduler with the full HAMi platform.
diff --git a/docusaurus.config.js b/docusaurus.config.js
index 916b51f8a..73fb7419c 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -314,6 +314,9 @@ module.exports = {
defaultMode: "dark",
respectPrefersColorScheme: false,
},
+ mermaid: {
+ theme: { light: "default", dark: "dark" },
+ },
announcementBar,
navbar: {
title: "HAMi",
diff --git a/i18n/zh/docusaurus-plugin-content-blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md b/i18n/zh/docusaurus-plugin-content-blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md
index da06580dc..0547fc86c 100644
--- a/i18n/zh/docusaurus-plugin-content-blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md
+++ b/i18n/zh/docusaurus-plugin-content-blog/hami-core-adopted-by-nvidia-kai-scheduler/index.md
@@ -67,12 +67,10 @@ graph TD
POD --> SCHED --> INJECT --> WEBHOOK --> CONTAINER --> ENFORCE
DAEMON -. "加载 libvgpu.so" .-> CONTAINER
- style SCHED fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937
- style INJECT fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937
- style WEBHOOK fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937
- style DAEMON fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937
- style CONTAINER fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#1f2937
- style ENFORCE fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937
+ class SCHED,INJECT kai
+ class WEBHOOK,DAEMON info
+ class CONTAINER run
+ class ENFORCE ok
```
工作流程分为四个阶段:
@@ -92,8 +90,8 @@ graph TD
B2 --> B3["无法超额
硬隔离"]
A3 ~~~ B1
- style A3 fill:#fee2e2,stroke:#b3261e,stroke-width:2px,color:#1f2937
- style B3 fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937
+ class A3 bad
+ class B3 ok
```
### 部署方式
@@ -199,8 +197,8 @@ graph TD
HAMI --> Kueue
HAMI --> Koordinator
- style HAMI fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937
- style KAI fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937
+ class HAMI info
+ class KAI kai
```
### 为用户创造实际价值
diff --git a/i18n/zh/docusaurus-plugin-content-blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md b/i18n/zh/docusaurus-plugin-content-blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md
index 35d4ec23e..9d0ad24b5 100644
--- a/i18n/zh/docusaurus-plugin-content-blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md
+++ b/i18n/zh/docusaurus-plugin-content-blog/kai-scheduler-hami-gpu-memory-hard-isolation/index.md
@@ -41,12 +41,10 @@ graph TD
LIB -. "提供 libvgpu.so" .-> RUN
RUN -. "写入节点本地缓存" .-> MON
- style KAI fill:#d9f99d,stroke:#4f7d00,stroke-width:2px,color:#1f2937
- style WEBHOOK fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937
- style LIB fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937
- style RUN fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#1f2937
- style ENF fill:#dcfce7,stroke:#0b6b3c,stroke-width:2px,color:#1f2937
- style MON fill:#dbeafe,stroke:#1a5fb4,stroke-width:2px,color:#1f2937
+ class KAI kai
+ class WEBHOOK,LIB,MON info
+ class RUN run
+ class ENF ok
```
`CUDA_DEVICE_MEMORY_LIMIT` 是调度层与隔离层之间的契约。KAI 不需要知道 CUDA 调用如何被拦截,HAMi-core 也不需要知道配额如何计算。KAI 保留自己的调度逻辑;它集成的是 HAMi-core,而不是用完整的 HAMi 平台替换自身调度器。
diff --git a/src/css/custom.css b/src/css/custom.css
index d1a1ad269..dfb4bcb1b 100644
--- a/src/css/custom.css
+++ b/src/css/custom.css
@@ -145,6 +145,23 @@
rgba(241, 246, 250, 0.95)
);
--hami-diagram-outcome-bg: rgba(255, 255, 255, 0.62);
+
+ /* mermaid class roles: kai, info, run, ok, bad */
+ --hami-mermaid-kai-fill: #d9f99d;
+ --hami-mermaid-kai-stroke: #4f7d00;
+ --hami-mermaid-kai-text: #1f2937;
+ --hami-mermaid-info-fill: #dbeafe;
+ --hami-mermaid-info-stroke: #1a5fb4;
+ --hami-mermaid-info-text: #1f2937;
+ --hami-mermaid-run-fill: #fef3c7;
+ --hami-mermaid-run-stroke: #b45309;
+ --hami-mermaid-run-text: #1f2937;
+ --hami-mermaid-ok-fill: #dcfce7;
+ --hami-mermaid-ok-stroke: #0b6b3c;
+ --hami-mermaid-ok-text: #1f2937;
+ --hami-mermaid-bad-fill: #fee2e2;
+ --hami-mermaid-bad-stroke: #b3261e;
+ --hami-mermaid-bad-text: #1f2937;
}
:root[data-theme="dark"] {
@@ -247,6 +264,22 @@
);
--hami-diagram-outcome-bg: rgba(255, 255, 255, 0.04);
+ --hami-mermaid-kai-fill: #365314;
+ --hami-mermaid-kai-stroke: #a3e635;
+ --hami-mermaid-kai-text: #ecfccb;
+ --hami-mermaid-info-fill: #1e3a5f;
+ --hami-mermaid-info-stroke: #60a5fa;
+ --hami-mermaid-info-text: #dbeafe;
+ --hami-mermaid-run-fill: #78350f;
+ --hami-mermaid-run-stroke: #fbbf24;
+ --hami-mermaid-run-text: #fef3c7;
+ --hami-mermaid-ok-fill: #14532d;
+ --hami-mermaid-ok-stroke: #4ade80;
+ --hami-mermaid-ok-text: #dcfce7;
+ --hami-mermaid-bad-fill: #7f1d1d;
+ --hami-mermaid-bad-stroke: #f87171;
+ --hami-mermaid-bad-text: #fee2e2;
+
--ifm-navbar-search-input-icon: url("data:image/svg+xml;utf8,");
}
@@ -426,6 +459,78 @@ html[data-theme="dark"] .hami-lightbox__svg {
text-align: center;
}
+.docusaurus-mermaid-container svg {
+ background: transparent !important;
+}
+
+/* mermaid leaves subgraph titles / edge labels dark even on the dark theme */
+.docusaurus-mermaid-container .cluster-label,
+.docusaurus-mermaid-container .cluster-label span,
+.docusaurus-mermaid-container .cluster span,
+.docusaurus-mermaid-container .edgeLabel,
+.docusaurus-mermaid-container .edgeLabel span,
+.docusaurus-mermaid-container .edgeLabel p {
+ color: var(--ifm-font-color-base) !important;
+}
+
+.docusaurus-mermaid-container .cluster-label text,
+.docusaurus-mermaid-container .edgeLabel text {
+ fill: var(--ifm-font-color-base) !important;
+}
+
+.docusaurus-mermaid-container .edgeLabel,
+.docusaurus-mermaid-container .edgeLabel p,
+.docusaurus-mermaid-container .labelBkg {
+ background-color: var(--ifm-background-color) !important;
+}
+
+.docusaurus-mermaid-container .edgeLabel rect {
+ background-color: var(--ifm-background-color) !important;
+ fill: var(--ifm-background-color) !important;
+}
+
+.docusaurus-mermaid-container .kai {
+ --hami-mermaid-node-fill: var(--hami-mermaid-kai-fill);
+ --hami-mermaid-node-stroke: var(--hami-mermaid-kai-stroke);
+ --hami-mermaid-node-text: var(--hami-mermaid-kai-text);
+}
+
+.docusaurus-mermaid-container .info {
+ --hami-mermaid-node-fill: var(--hami-mermaid-info-fill);
+ --hami-mermaid-node-stroke: var(--hami-mermaid-info-stroke);
+ --hami-mermaid-node-text: var(--hami-mermaid-info-text);
+}
+
+.docusaurus-mermaid-container .run {
+ --hami-mermaid-node-fill: var(--hami-mermaid-run-fill);
+ --hami-mermaid-node-stroke: var(--hami-mermaid-run-stroke);
+ --hami-mermaid-node-text: var(--hami-mermaid-run-text);
+}
+
+.docusaurus-mermaid-container .ok {
+ --hami-mermaid-node-fill: var(--hami-mermaid-ok-fill);
+ --hami-mermaid-node-stroke: var(--hami-mermaid-ok-stroke);
+ --hami-mermaid-node-text: var(--hami-mermaid-ok-text);
+}
+
+.docusaurus-mermaid-container .bad {
+ --hami-mermaid-node-fill: var(--hami-mermaid-bad-fill);
+ --hami-mermaid-node-stroke: var(--hami-mermaid-bad-stroke);
+ --hami-mermaid-node-text: var(--hami-mermaid-bad-text);
+}
+
+.docusaurus-mermaid-container
+ :is(.kai, .info, .run, .ok, .bad)
+ > :is(rect, polygon, circle, ellipse, path) {
+ fill: var(--hami-mermaid-node-fill) !important;
+ stroke: var(--hami-mermaid-node-stroke) !important;
+ stroke-width: 2px !important;
+}
+
+.docusaurus-mermaid-container :is(.kai, .info, .run, .ok, .bad) :is(.nodeLabel, span) {
+ color: var(--hami-mermaid-node-text) !important;
+}
+
.mermaid-figure {
margin: 0 0 1.5rem;
text-align: center;