Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 6 additions & 15 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Dashboard
name: Documentation

on:
push:
Expand All @@ -19,7 +19,7 @@ concurrency:

jobs:
build:
name: Generate Dashboard
name: Build Documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
Expand All @@ -33,9 +33,9 @@ jobs:
uses: actions/cache@v5
with:
path: ~/.cache/pip
key: pip-dashboard-${{ hashFiles('pyproject.toml') }}
key: pip-docs-${{ hashFiles('pyproject.toml') }}
restore-keys: |
pip-dashboard-
pip-docs-

- name: Install PyTorch CPU
run: pip install torch --index-url https://download.pytorch.org/whl/cpu
Expand All @@ -46,17 +46,8 @@ jobs:
pip install -r docs/requirements.txt
pip install -e '.[testing]'

- name: Generate dashboard
run: |
mkdir -p _site
python scripts/generate_dashboard.py \
--output _site/index.html \
--commit $(git rev-parse --short HEAD)

- name: Build Sphinx docs
run: |
python docs/_generate_models.py
sphinx-build docs _site/docs
- name: Build documentation
run: sphinx-build docs _site

- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v4
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,4 @@ cache_dir/**
.flightdeck/shared/**
.worktrees/
dashboard_preview.html
docs/feature-flags.md
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Supports building ONNX models from HuggingFace model IDs with automatic weight
downloading, dtype casting (including bfloat16 via `ir.LazyTensor`), and
multi-component export for pipelines.

📖 **[Documentation](https://onnxruntime.github.io/mobius/docs/)** · 📦 **[Supported Models](https://onnxruntime.github.io/mobius/docs/models/index.html)**
📖 **[Documentation](https://onnxruntime.github.io/mobius/)** · 📦 **[Supported Models](https://onnxruntime.github.io/mobius/models/index.html)**

## Highlighted Models

Expand All @@ -34,7 +34,7 @@ multi-component export for pipelines.
Supports **130 Transformers model types** and **5 Diffusers component types**
across **14 task types** and **56+ reusable components**.

See the [model documentation](https://onnxruntime.github.io/mobius/docs/models/index.html) for the complete list.
See the [model documentation](https://onnxruntime.github.io/mobius/models/index.html) for the complete list.

## Installation

Expand Down Expand Up @@ -79,7 +79,7 @@ mobius build --model openai/whisper-tiny output_dir/
mobius build --model meta-llama/Llama-3.2-1B output_dir/ --dtype f16
```

See the [CLI reference](https://onnxruntime.github.io/mobius/docs/cli.html) for all options.
See the [CLI reference](https://onnxruntime.github.io/mobius/cli.html) for all options.

### Examples

Expand Down Expand Up @@ -113,7 +113,7 @@ The package is organised into four layers:
- **Tasks** — Define the ONNX graph I/O contract (inputs, outputs, KV cache)
- **Registry** — Maps HuggingFace `model_type` strings to model classes

See the [design document](https://onnxruntime.github.io/mobius/docs/design.html) for details.
See the [design document](https://onnxruntime.github.io/mobius/design.html) for details.

## Development

Expand All @@ -133,7 +133,7 @@ lintrunner f --all-files

### Adding a new model

See the [AI-assisted model support strategy](https://onnxruntime.github.io/mobius/docs/ai-model-support-strategy.html)
See the [AI-assisted model support strategy](https://onnxruntime.github.io/mobius/ai-model-support-strategy.html)
and the developer skills in `.github/skills/`:

| Skill | Use when |
Expand Down
97 changes: 97 additions & 0 deletions docs/_ext/dashboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
"""Sphinx extension: generate the confidence dashboard after build.

Hooks into ``build-finished`` to run ``scripts/generate_dashboard.py``
and place the output in the build directory under ``/dashboard/``.
Also creates a redirect from the old ``/docs/`` path to the new root.
"""

from __future__ import annotations

import logging
import subprocess
import sys
from pathlib import Path
from typing import Any

from sphinx.application import Sphinx

logger = logging.getLogger(__name__)

_REDIRECT_HTML = """\
<!DOCTYPE html>
<html><head>\
<meta http-equiv="refresh" content="0; url=../">\
<title>Redirecting...</title></head>
<body><a href="../">Click here</a></body></html>
"""


def generate_dashboard(app: Sphinx, exception: Exception | None) -> None:
"""Generate dashboard HTML into the build output directory."""
if exception is not None:
# Don't generate dashboard if Sphinx build failed
return

repo_root = Path(app.srcdir).parent
script = repo_root / "scripts" / "generate_dashboard.py"

if not script.exists():
logger.warning("Dashboard script not found: %s", script)
return

outdir = Path(app.outdir)
dashboard_dir = outdir / "dashboard"
dashboard_dir.mkdir(parents=True, exist_ok=True)

# Determine current git commit for display in the dashboard
commit = _git_short_hash(repo_root)

result = subprocess.run(
[
sys.executable,
str(script),
"--output",
str(dashboard_dir / "index.html"),
"--commit",
commit,
],
cwd=str(repo_root),
capture_output=True,
text=True,
check=False,
)

if result.returncode != 0:
raise RuntimeError(f"Dashboard generation failed:\n{result.stderr}")

if result.stdout:
logger.info(result.stdout.strip())

# Add redirect from old /docs/ path to root
docs_redirect_dir = outdir / "docs"
docs_redirect_dir.mkdir(parents=True, exist_ok=True)
(docs_redirect_dir / "index.html").write_text(_REDIRECT_HTML)


def _git_short_hash(repo_root: Path) -> str:
"""Return the short git commit hash, or 'unknown' on failure."""
try:
result = subprocess.run(
["git", "rev-parse", "--short", "HEAD"],
cwd=str(repo_root),
capture_output=True,
text=True,
check=True,
)
return result.stdout.strip()
except (subprocess.CalledProcessError, FileNotFoundError):
return "unknown"


def setup(app: Sphinx) -> dict[str, Any]:
app.connect("build-finished", generate_dashboard)
return {
"version": "0.1",
"parallel_read_safe": True,
"parallel_write_safe": True,
}
58 changes: 58 additions & 0 deletions docs/_ext/flags_gen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""Sphinx extension: generate feature flags documentation at build time.

Hooks into ``builder-inited`` to generate ``docs/feature-flags.md`` from
the ``_Flags`` dataclass. This extension is conditional — it only runs
when the flags module exists (the feature-flags script lives on a
separate PR branch and may not be merged yet).
"""

from __future__ import annotations

import logging
import subprocess
import sys
from pathlib import Path
from typing import Any

from sphinx.application import Sphinx

logger = logging.getLogger(__name__)


def generate_flags_docs(app: Sphinx) -> None:
"""Generate feature-flags.md if the generator script exists."""
docs_dir = Path(app.srcdir)

# Check both possible locations for the script
script = docs_dir / "_generate_flags_docs.py"
if not script.exists():
# Fallback to the scripts/ directory (legacy location)
script = docs_dir.parent / "scripts" / "generate_flags_docs.py"

if not script.exists():
# Not an error — feature-flags PR may not be merged yet
logger.debug("Flags docs generator not found; skipping")
return

result = subprocess.run(
[sys.executable, str(script)],
cwd=str(docs_dir.parent),
capture_output=True,
text=True,
check=False,
)

if result.returncode != 0:
raise RuntimeError(f"Feature flags doc generation failed:\n{result.stderr}")

if result.stdout:
logger.info(result.stdout.strip())


def setup(app: Sphinx) -> dict[str, Any]:
app.connect("builder-inited", generate_flags_docs)
return {
"version": "0.1",
"parallel_read_safe": True,
"parallel_write_safe": True,
}
52 changes: 52 additions & 0 deletions docs/_ext/models_gen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Sphinx extension: generate model documentation pages at build time.

Hooks into ``builder-inited`` to run the existing model page generator
(``docs/_generate_models.py``) before Sphinx processes source files.
"""

from __future__ import annotations

import logging
import subprocess
import sys
from pathlib import Path
from typing import Any

from sphinx.application import Sphinx

logger = logging.getLogger(__name__)


def generate_model_pages(app: Sphinx) -> None:
"""Generate model .md pages from the registry."""
docs_dir = Path(app.srcdir)
script = docs_dir / "_generate_models.py"

if not script.exists():
logger.warning("Model generation script not found: %s", script)
return

# Run as subprocess to avoid polluting Sphinx's import state.
# The script handles its own sys.path manipulation.
result = subprocess.run(
[sys.executable, str(script)],
cwd=str(docs_dir.parent),
capture_output=True,
text=True,
check=False,
)

if result.returncode != 0:
raise RuntimeError(f"Model page generation failed:\n{result.stderr}")

if result.stdout:
logger.info(result.stdout.strip())


def setup(app: Sphinx) -> dict[str, Any]:
app.connect("builder-inited", generate_model_pages)
return {
"version": "0.1",
"parallel_read_safe": True,
"parallel_write_safe": True,
}
Loading
Loading