diff --git a/.github/workflows/infra-docs.yml b/.github/workflows/infra-docs.yml index 502b72184..69aba4c84 100644 --- a/.github/workflows/infra-docs.yml +++ b/.github/workflows/infra-docs.yml @@ -6,7 +6,7 @@ on: paths: - 'docs/**' - 'examples/**' - - 'consumer-guide/**' + - 'scripts/inference/**' - 'mkdocs.yml' - 'requirements-mkdocs.in' - 'requirements-mkdocs.txt' @@ -17,7 +17,7 @@ on: paths: - 'docs/**' - 'examples/**' - - 'consumer-guide/**' + - 'scripts/inference/**' - 'mkdocs.yml' - 'requirements-mkdocs.in' - 'requirements-mkdocs.txt' @@ -54,7 +54,6 @@ jobs: run: uv pip install --system -r requirements-mkdocs.txt - name: Setup Pages - id: pages uses: actions/configure-pages@v4 - name: Build documentation @@ -63,33 +62,6 @@ jobs: - name: Check docs links run: python scripts/check_docs_links.py - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: '24' - - - name: Enable pnpm - run: corepack enable - - - name: Install config generator dependencies - working-directory: consumer-guide - run: pnpm install --frozen-lockfile - - - name: Build config generator - working-directory: consumer-guide - env: - NEXT_BASE_PATH: ${{ steps.pages.outputs.base_path }}/config-generator - NEXT_TELEMETRY_DISABLED: '1' - run: pnpm build - - - name: Copy config generator into docs site - run: | - mkdir -p site/config-generator - cp -R consumer-guide/out/. site/config-generator/ - - - name: Verify config generator asset paths - run: grep -Fq "${{ steps.pages.outputs.base_path }}/config-generator/_next/" site/config-generator/index.html - - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: diff --git a/.gitignore b/.gitignore index 4028ab217..e003506b7 100644 --- a/.gitignore +++ b/.gitignore @@ -22,8 +22,6 @@ samples/ Miniconda3-latest-Linux-x86_64.sh *validation/ data/ -!consumer-guide/data/ -!consumer-guide/data/**/*.json outputs/ outputs_video checkpoints/ diff --git a/consumer-guide/.gitignore b/consumer-guide/.gitignore deleted file mode 100644 index 0e77bb80e..000000000 --- a/consumer-guide/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# Dependencies -node_modules - -# Next.js build output / generated files -.next/ -out/ -next-env.d.ts -tsconfig.tsbuildinfo - -# Local env files -.env*.local - -# Misc -.DS_Store diff --git a/consumer-guide/README.md b/consumer-guide/README.md deleted file mode 100644 index 5fdca2f5d..000000000 --- a/consumer-guide/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# FastVideo Config Generator - -A standalone Next.js app that turns maintained FastVideo inference recipes into -executable YAML or Python. The docs build exports it beneath the GitHub Pages -base path at `config-generator/`. - -Two pages are available: - -- **Quick Start** (`/config-generator/`) — choose a task, model profile, and GPU - count. -- **Advanced Tuning** (`/config-generator/tuning/`) — start from an exact model - recipe and adjust supported configuration fields. - -## Run locally - -```bash -pnpm install -pnpm dev -``` - -Open . - -## Build - -```bash -pnpm build -``` - -The build first runs `scripts/validate-data.mjs`, then writes a static export to -`out/`. - -## Recipe data - -`data/tuning.json` is the app's recipe source. Its `source` block pins the exact -FastVideo revision and repository paths used to transcribe model defaults, -pipeline settings, examples, and verified attention compatibility. - -`data/quickstart.json` contains only the curated task/profile choices and engine -offload settings. Each profile references a model from `tuning.json`; the build -fails on missing models, task mismatches, duplicate profiles, unknown attention -backends, or unsupported performance fields. - -The guide intentionally publishes no latency, VRAM, RAM, or speedup claims. -Add those only when a reproducible benchmark record includes the FastVideo and -model revisions, GPU type/count, complete resolved recipe, software environment, -prompt/seed, warmup/sample protocol, latency statistic, and peak memory. - -## Updating a recipe - -1. Check the current registry, model-family preset, pipeline config, maintained - example, and support matrix. -2. Update the model entry in `data/tuning.json` and advance - `source.fastvideoCommit` to the inspected revision. -3. Update `data/quickstart.json` only if the curated profile selection changes. -4. Run `pnpm build`. - -The UI reads the JSON directly; model defaults do not belong in the `.tsx` -components. diff --git a/consumer-guide/app/basic_page.tsx b/consumer-guide/app/basic_page.tsx deleted file mode 100644 index dafce98cf..000000000 --- a/consumer-guide/app/basic_page.tsx +++ /dev/null @@ -1,442 +0,0 @@ -"use client" - -import { useEffect, useState, useMemo } from "react" -import { Layers, Copy, Check, Film, Image, Sparkles, Gamepad2 } from "lucide-react" -import quickstartData from "@/data/quickstart.json" -import tuningData from "@/data/tuning.json" - -type IconName = "Film" | "Image" | "Sparkles" | "Gamepad2" - -interface Recipe { - height: number - width: number - numFrames: number - fps: number - numInferenceSteps: number - guidanceScale: number - guidanceScale2: number | null - embeddedCfgScale: number - boundaryRatio: number | null - dmdDenoisingSteps: number[] | null - attentionBackends: string[] - defaultAttentionBackend: string - vsaSparsity: number -} - -interface TaskOption { - id: string - label: string - sub: string - icon: string -} - -interface ModelOption { - id: string - name: string - workload: string - keyboardDim?: number - usesMouse?: boolean - recipe: Recipe -} - -interface TierOption { - id: string - name: string - desc: string - badge?: string -} - -interface Profile { - task: string - tier: string - model: string - ditCpuOffload: boolean - ditLayerwiseOffload: boolean - vaeCpuOffload: boolean - textEncoderCpuOffload: boolean - imageEncoderCpuOffload: boolean - pinCpuMemory: boolean - useFsdpInference: boolean -} - -interface QuickstartDefaults { - task: string - tier: string - numGpus: number -} - -const ICONS: Record = { - Film, - Image, - Sparkles, - Gamepad2, -} - -const DEFAULTS = quickstartData.defaults as QuickstartDefaults -const GPU_COUNT_OPTIONS = quickstartData.gpuCountOptions as number[] -const PROFILES = quickstartData.profiles as Profile[] -const TASKS = quickstartData.tasks as TaskOption[] -const TIERS = quickstartData.tiers as TierOption[] -const MODELS = tuningData.models as ModelOption[] -const MODEL_BY_ID = Object.fromEntries(MODELS.map((model) => [model.id, model])) as Record - -function getProfile(task: string, tier: string): Profile | undefined { - return PROFILES.find((profile) => profile.task === task && profile.tier === tier) -} - -export default function FastVideoConfigSelector() { - const [task, setTask] = useState(DEFAULTS.task) - const [tier, setTier] = useState(DEFAULTS.tier) - const [ngpu, setNgpu] = useState(DEFAULTS.numGpus) - const [copied, setCopied] = useState(false) - - const profile = getProfile(task, tier) - const selectedModel = profile ? MODEL_BY_ID[profile.model] : undefined - const config = profile && selectedModel ? { ...profile, ...selectedModel.recipe, ...selectedModel } : undefined - - // Report content height to the parent docs page so the embedding iframe can - // auto-resize — same mechanism as the Advanced Tuning guide. - useEffect(() => { - if (typeof window === "undefined" || window.parent === window) return - const root = document.getElementById("config-generator-root") - if (!root) return - - let frame = 0 - const sendHeight = () => { - window.cancelAnimationFrame(frame) - frame = window.requestAnimationFrame(() => { - window.parent.postMessage( - { type: "fastvideo-config-generator:resize", height: Math.ceil(root.getBoundingClientRect().height) }, - window.location.origin, - ) - }) - } - - const ro = new ResizeObserver(sendHeight) - ro.observe(root) - sendHeight() - - return () => { - window.cancelAnimationFrame(frame) - ro.disconnect() - } - }, []) - - const command = useMemo(() => { - if (!config) return "" - - const workloadType = task === "ti2v" ? "i2v" : task - const pythonBoolean = (value: boolean) => value ? "True" : "False" - const presetOverrideEntries = [ - task === "game" ? null : `["embedded_cfg_scale", ${config.embeddedCfgScale}]`, - config.dmdDenoisingSteps === null - ? null - : `["dmd_denoising_steps", [${config.dmdDenoisingSteps.join(", ")}]]`, - ].filter((entry): entry is string => Boolean(entry)) - - if (task === "game") { - const keyboardDim = config.keyboardDim ?? 4 - const inputLines = [ - ' "image_path": "./input.png",', - config.usesMouse === false ? null : ' "mouse_cond": actions["mouse"].unsqueeze(0),', - ' "keyboard_cond": actions["keyboard"].unsqueeze(0),', - ' "grid_sizes": grid_sizes,', - ].filter((line): line is string => Boolean(line)) - return [ - "# Game control uses the Python API because mouse/keyboard", - "# conditions are tensors, not simple CLI fields.", - "", - "# Install once:", - "# pip install fastvideo", - "", - "# Save this file as run.py and run:", - "# python run.py", - "import os", - "import torch", - "from fastvideo import VideoGenerator", - "from fastvideo.models.dits.matrixgame2.utils import create_action_presets", - "", - `os.environ["FASTVIDEO_ATTENTION_BACKEND"] = "${config.defaultAttentionBackend}"`, - "", - "generator = VideoGenerator.from_config({", - ` "model_path": "${config.model}",`, - " \"engine\": {", - ` "num_gpus": ${ngpu},`, - ` "use_fsdp_inference": ${pythonBoolean(config.useFsdpInference)},`, - " \"offload\": {", - ` "dit": ${pythonBoolean(config.ditCpuOffload)},`, - ` "dit_layerwise": ${pythonBoolean(config.ditLayerwiseOffload)},`, - ` "text_encoder": ${pythonBoolean(config.textEncoderCpuOffload)},`, - ` "image_encoder": ${pythonBoolean(config.imageEncoderCpuOffload)},`, - ` "vae": ${pythonBoolean(config.vaeCpuOffload)},`, - ` "pin_cpu_memory": ${pythonBoolean(config.pinCpuMemory)},`, - " },", - " },", - " \"pipeline\": {", - " \"workload_type\": \"i2v\",", - " \"preset_overrides\": dict([", - ...presetOverrideEntries.map((entry) => ` ${entry},`), - " ]),", - " },", - "})", - "", - `num_frames = ${config.numFrames}`, - `actions = create_action_presets(num_frames, keyboard_dim=${keyboardDim}, seed=1024)`, - `grid_sizes = torch.tensor([${Math.floor((config.numFrames - 1) / 4) + 1}, ${Math.floor(config.height / 8)}, ${Math.floor(config.width / 8)}])`, - "", - "generator.generate({", - ' "prompt": "",', - " \"inputs\": {", - ...inputLines, - " },", - " \"sampling\": {", - ` "height": ${config.height},`, - ` "width": ${config.width},`, - ` "fps": ${config.fps},`, - " \"seed\": 1024,", - ` "num_frames": ${config.numFrames},`, - ` "num_inference_steps": ${config.numInferenceSteps},`, - ...(config.dmdDenoisingSteps === null ? [` "guidance_scale": ${config.guidanceScale},`] : []), - ...(config.boundaryRatio === null ? [] : [` "boundary_ratio": ${config.boundaryRatio},`]), - " },", - ' "output": {"output_path": "outputs/", "save_video": True},', - "})", - ].join("\n") - } - - const offloadYaml = [ - ` dit: ${config.ditCpuOffload}`, - ` dit_layerwise: ${config.ditLayerwiseOffload}`, - ` text_encoder: ${config.textEncoderCpuOffload}`, - ` image_encoder: ${config.imageEncoderCpuOffload}`, - ` vae: ${config.vaeCpuOffload}`, - ` pin_cpu_memory: ${config.pinCpuMemory}`, - ] - const inputsYaml = task === "i2v" || task === "ti2v" - ? [ - " inputs:", - " image_path: ./input.png", - ] - : [] - const presetOverridesYaml = [ - " preset_overrides:", - ` embedded_cfg_scale: ${config.embeddedCfgScale}`, - ...(config.dmdDenoisingSteps === null - ? [] - : [` dmd_denoising_steps: [${config.dmdDenoisingSteps.join(", ")}]`]), - ] - const experimentalYaml = config.defaultAttentionBackend === "VIDEO_SPARSE_ATTN" - ? [" experimental:", ` VSA_sparsity: ${config.vsaSparsity}`] - : [] - - return [ - "# Install once:", - "# pip install fastvideo", - "", - "cat > fastvideo-generate.yaml <<'YAML'", - "generator:", - ` model_path: ${config.model}`, - " engine:", - ` num_gpus: ${ngpu}`, - ` use_fsdp_inference: ${config.useFsdpInference}`, - " offload:", - ...offloadYaml, - " pipeline:", - ` workload_type: ${workloadType}`, - ...presetOverridesYaml, - ...experimentalYaml, - "", - "request:", - ' prompt: "your prompt here"', - ...inputsYaml, - " sampling:", - ` height: ${config.height}`, - ` width: ${config.width}`, - ` fps: ${config.fps}`, - " seed: 1024", - ` num_frames: ${config.numFrames}`, - ` num_inference_steps: ${config.numInferenceSteps}`, - ...(config.dmdDenoisingSteps === null ? [` guidance_scale: ${config.guidanceScale}`] : []), - ...(config.guidanceScale2 === null ? [] : [` guidance_scale_2: ${config.guidanceScale2}`]), - ...(config.boundaryRatio === null ? [] : [` boundary_ratio: ${config.boundaryRatio}`]), - " output:", - " output_path: outputs/", - " save_video: true", - "YAML", - "", - `FASTVIDEO_ATTENTION_BACKEND=${config.defaultAttentionBackend} \\`, - " fastvideo generate --config fastvideo-generate.yaml", - ].join("\n") - }, [config, ngpu, task]) - - const copyCommand = async () => { - if (!command) return - await navigator.clipboard.writeText(command) - setCopied(true) - setTimeout(() => setCopied(false), 2000) - } - - return ( -
-
- {/* Step 1: Task Selection */} -
-
- 1 -

What do you want to make?

-
-
- {TASKS.map(({ id, label, sub, icon }) => { - const Icon = ICONS[icon as IconName] ?? Film - return ( - - ) - })} -
-
- - {/* Step 2: Parallelism */} -
-
- 2 -

Parallelism

-
-
- - -
-
- - {/* Step 3: Model profile */} -
-
- 3 -

Model profile

-
-
- {TIERS.map(({ id, name, desc, badge }) => { - const tierConfig = getProfile(task, id) - const tierModel = tierConfig ? MODEL_BY_ID[tierConfig.model] : undefined - return ( - - ) - })} -
-
- - {/* Output Configuration */} -
-
- - - -

Your configuration

-
-
- {/* Meta Cards */} -
-
-
Model
-
{config?.name ?? "Unavailable"}
-
-
-
Resolution
-
{config ? `${config.width}×${config.height}` : "Unavailable"}
-
-
-
Denoising
-
{config ? `${config.numInferenceSteps} steps` : "Unavailable"}
-
-
- {/* Command Block */} -
- {command && ( - - )} - {command ? ( -
-                  {command}
-                
- ) : ( -
- No maintained profile is available for this task and model choice. -
- )} -
-
-
-
-
- ) -} diff --git a/consumer-guide/app/globals.css b/consumer-guide/app/globals.css deleted file mode 100644 index 09c52ed18..000000000 --- a/consumer-guide/app/globals.css +++ /dev/null @@ -1,125 +0,0 @@ -@import 'tailwindcss'; -@import 'tw-animate-css'; - -@custom-variant dark (&:is(.dark *)); - -:root { - --background: oklch(0.985 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.58 0.22 264); - --primary-foreground: oklch(1 0 0); - --secondary: oklch(0.94 0.03 264); - --secondary-foreground: oklch(0.38 0.16 264); - --muted: oklch(0.96 0.01 264); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.93 0.04 264); - --accent-foreground: oklch(0.38 0.16 264); - --destructive: oklch(0.577 0.245 27.325); - --destructive-foreground: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.58 0.22 264); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --radius: 0.625rem; - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.58 0.22 264); - --sidebar-primary-foreground: oklch(1 0 0); - --sidebar-accent: oklch(0.93 0.04 264); - --sidebar-accent-foreground: oklch(0.38 0.16 264); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); -} - -.dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.145 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.145 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.985 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.396 0.141 25.723); - --destructive-foreground: oklch(0.637 0.237 25.331); - --border: oklch(0.269 0 0); - --input: oklch(0.269 0 0); - --ring: oklch(0.439 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(0.269 0 0); - --sidebar-ring: oklch(0.439 0 0); -} - -@theme inline { - --font-sans: ui-sans-serif, system-ui, sans-serif; - --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; - --color-background: var(--background); - --color-foreground: var(--foreground); - --color-card: var(--card); - --color-card-foreground: var(--card-foreground); - --color-popover: var(--popover); - --color-popover-foreground: var(--popover-foreground); - --color-primary: var(--primary); - --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); - --color-secondary-foreground: var(--secondary-foreground); - --color-muted: var(--muted); - --color-muted-foreground: var(--muted-foreground); - --color-accent: var(--accent); - --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); - --color-destructive-foreground: var(--destructive-foreground); - --color-border: var(--border); - --color-input: var(--input); - --color-ring: var(--ring); - --color-chart-1: var(--chart-1); - --color-chart-2: var(--chart-2); - --color-chart-3: var(--chart-3); - --color-chart-4: var(--chart-4); - --color-chart-5: var(--chart-5); - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); - --color-sidebar: var(--sidebar); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-ring: var(--sidebar-ring); -} - -@layer base { - * { - @apply border-border outline-ring/50; - } - body { - @apply bg-white text-foreground; - } -} diff --git a/consumer-guide/app/layout.tsx b/consumer-guide/app/layout.tsx deleted file mode 100644 index 734dfa378..000000000 --- a/consumer-guide/app/layout.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import type { Metadata } from 'next' -import './globals.css' - -export const metadata: Metadata = { - title: 'FastVideo Config Generator', - description: 'Choose a maintained FastVideo recipe and generate an executable configuration', -} - -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode -}>) { - return ( - - - {children} - - - ) -} diff --git a/consumer-guide/app/page.tsx b/consumer-guide/app/page.tsx deleted file mode 100644 index bf391b925..000000000 --- a/consumer-guide/app/page.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./basic_page" diff --git a/consumer-guide/app/tuning/adv_page.tsx b/consumer-guide/app/tuning/adv_page.tsx deleted file mode 100644 index 9c2c578ec..000000000 --- a/consumer-guide/app/tuning/adv_page.tsx +++ /dev/null @@ -1,679 +0,0 @@ -"use client" - -import { useEffect, useId, useMemo, useState, type ElementType, type ReactNode } from "react" -import { - BarChart3, - Check, - ChevronDown, - ChevronUp, - Copy, - Film, - HardDrive, - Image, - Info, - Layers, - Settings2, - Sparkles, - Zap, -} from "lucide-react" -import tuningData from "@/data/tuning.json" - -interface Recipe { - height: number - width: number - numFrames: number - fps: number - numInferenceSteps: number - guidanceScale: number - guidanceScale2: number | null - embeddedCfgScale: number - boundaryRatio: number | null - dmdDenoisingSteps: number[] | null - attentionBackends: string[] - defaultAttentionBackend: string - vsaSparsity: number -} - -interface ModelOption { - id: string - name: string - size: string - workload: string - keyboardDim?: number - usesMouse?: boolean - recipe: Recipe -} - -interface WorkloadOption { - id: string - name: string - icon: string -} - -interface AttentionBackend { - id: string - name: string - shortName: string - desc: string -} - -interface Defaults { - model_id: string - workload_type: string - num_gpus: number - seed: number - dit_cpu_offload: boolean - dit_layerwise_offload: boolean - vae_cpu_offload: boolean - text_encoder_cpu_offload: boolean - image_encoder_cpu_offload: boolean - pin_cpu_memory: boolean - use_fsdp_inference: boolean -} - -interface Config extends Defaults { - height: number - width: number - num_frames: number - fps: number - num_inference_steps: number - guidance_scale: number - guidance_scale_2: number | null - embedded_cfg_scale: number - boundary_ratio: number | null - dmd_denoising_steps: number[] | null - attention_backend: string - VSA_sparsity: number -} - -const DEFAULTS = tuningData.defaults as Defaults -const MODELS = tuningData.models as ModelOption[] -const WORKLOADS = tuningData.workloads as WorkloadOption[] -const ATTENTION_BACKENDS = tuningData.attentionBackends as AttentionBackend[] -const MODEL_BY_ID = Object.fromEntries(MODELS.map((model) => [model.id, model])) as Record -const ATTENTION_BY_ID = Object.fromEntries(ATTENTION_BACKENDS.map((backend) => [backend.id, backend])) as Record -const DEFAULT_MODEL = MODEL_BY_ID[DEFAULTS.model_id] ?? MODELS[0] -const SOURCE = tuningData.source - -const WORKLOAD_ICONS: Record = { - t2v: Film, - i2v: Image, - ti2v: Layers, - game: Zap, -} - -function withModel(base: Defaults | Config, model: ModelOption): Config { - const recipe = model.recipe - return { - ...base, - model_id: model.id, - workload_type: model.workload, - height: recipe.height, - width: recipe.width, - num_frames: recipe.numFrames, - fps: recipe.fps, - num_inference_steps: recipe.numInferenceSteps, - guidance_scale: recipe.guidanceScale, - guidance_scale_2: recipe.guidanceScale2, - embedded_cfg_scale: recipe.embeddedCfgScale, - boundary_ratio: recipe.boundaryRatio, - dmd_denoising_steps: recipe.dmdDenoisingSteps ? [...recipe.dmdDenoisingSteps] : null, - attention_backend: recipe.defaultAttentionBackend, - VSA_sparsity: recipe.vsaSparsity, - } -} - -function Help({ text }: { text: string }) { - return ( - - - ) -} - -function Section({ - title, - icon: Icon, - children, -}: { - title: string - icon: ElementType - children: ReactNode -}) { - const [open, setOpen] = useState(true) - const contentId = useId() - return ( -
- - {open &&
{children}
} -
- ) -} - -function NumberInput({ - label, - value, - onChange, - min, - max, - step = 1, - help, - disabled = false, -}: { - label: string - value: number - onChange: (value: number) => void - min?: number - max?: number - step?: number - help?: string - disabled?: boolean -}) { - const id = useId() - return ( -
- - { - let next = event.currentTarget.valueAsNumber - if (!Number.isFinite(next)) return - if (Number.isInteger(step)) { - next = (min ?? 0) + Math.round((next - (min ?? 0)) / step) * step - } - if (min !== undefined) next = Math.max(min, next) - if (max !== undefined) next = Math.min(max, next) - onChange(next) - }} - className="w-full rounded-lg border border-slate-300 bg-white px-3 py-2.5 text-sm text-slate-900 disabled:cursor-not-allowed disabled:bg-slate-100" - /> -
- ) -} - -function SelectInput({ - label, - value, - onChange, - options, - help, -}: { - label: string - value: string - onChange: (value: string) => void - options: { id: string; name: string }[] - help?: string -}) { - const id = useId() - return ( -
- - -
- ) -} - -function Toggle({ - label, - checked, - onChange, - help, - disabled = false, -}: { - label: string - checked: boolean - onChange: (value: boolean) => void - help?: string - disabled?: boolean -}) { - return ( -
- - {label} - {help && } - - -
- ) -} - -export default function AdvancedTuningPage() { - const [config, setConfig] = useState(() => withModel(DEFAULTS, DEFAULT_MODEL)) - const [copied, setCopied] = useState(false) - - const selectedModel = MODEL_BY_ID[config.model_id] ?? DEFAULT_MODEL - const availableModels = useMemo( - () => MODELS.filter((model) => model.workload === config.workload_type), - [config.workload_type], - ) - const availableBackends = selectedModel.recipe.attentionBackends - .map((id) => ATTENTION_BY_ID[id]) - .filter((backend): backend is AttentionBackend => Boolean(backend)) - - const updateConfig = (key: K, value: Config[K]) => { - setConfig((current) => ({ ...current, [key]: value })) - } - - const selectWorkload = (workload: string) => { - const model = MODELS.find((candidate) => candidate.workload === workload) - if (model) setConfig((current) => withModel(current, model)) - } - - const selectModel = (modelId: string) => { - const model = MODEL_BY_ID[modelId] - if (model) setConfig((current) => withModel(current, model)) - } - - const recipeChanged = useMemo(() => { - const recipe = selectedModel.recipe - return config.height !== recipe.height || - config.width !== recipe.width || - config.num_frames !== recipe.numFrames || - config.fps !== recipe.fps || - config.num_inference_steps !== recipe.numInferenceSteps || - config.guidance_scale !== recipe.guidanceScale || - config.guidance_scale_2 !== recipe.guidanceScale2 || - config.embedded_cfg_scale !== recipe.embeddedCfgScale || - config.boundary_ratio !== recipe.boundaryRatio || - config.attention_backend !== recipe.defaultAttentionBackend || - config.VSA_sparsity !== recipe.vsaSparsity - }, [config, selectedModel]) - - const videoLength = (config.num_frames / config.fps).toFixed(1) - const totalPixels = config.height * config.width * config.num_frames - const latentTokens = (Math.floor((config.num_frames - 1) / 4) + 1) * - Math.floor(config.height / 8) * Math.floor(config.width / 8) - - useEffect(() => { - if (window.parent === window) return - const root = document.getElementById("config-generator-root") - if (!root) return - - let frame = 0 - const sendHeight = () => { - window.cancelAnimationFrame(frame) - frame = window.requestAnimationFrame(() => { - window.parent.postMessage( - { type: "fastvideo-config-generator:resize", height: Math.ceil(root.getBoundingClientRect().height) }, - window.location.origin, - ) - }) - } - const observer = new ResizeObserver(sendHeight) - observer.observe(root) - sendHeight() - return () => { - window.cancelAnimationFrame(frame) - observer.disconnect() - } - }, []) - - const command = useMemo(() => { - const isGame = config.workload_type === "game" - const needsImage = isGame || config.workload_type === "i2v" || config.workload_type === "ti2v" - const workloadType = config.workload_type === "ti2v" || isGame ? "i2v" : config.workload_type - const overrideYaml = [ - " preset_overrides:", - ` embedded_cfg_scale: ${config.embedded_cfg_scale}`, - ...(config.dmd_denoising_steps === null - ? [] - : [` dmd_denoising_steps: [${config.dmd_denoising_steps.join(", ")}]`]), - ] - - if (isGame) { - const pythonBoolean = (value: boolean) => value ? "True" : "False" - const pythonOverrides = [ - ...(config.dmd_denoising_steps === null - ? [] - : [` "dmd_denoising_steps": [${config.dmd_denoising_steps.join(", ")}],`]), - ] - const inputLines = [ - ' "image_path": "./input.png",', - selectedModel.usesMouse === false ? null : ' "mouse_cond": actions["mouse"].unsqueeze(0),', - ' "keyboard_cond": actions["keyboard"].unsqueeze(0),', - ' "grid_sizes": grid_sizes,', - ].filter((line): line is string => Boolean(line)) - const keyboardDim = selectedModel.keyboardDim ?? 4 - return [ - "# Save as run.py, then run: python run.py", - "import os", - "import torch", - "from fastvideo import VideoGenerator", - "from fastvideo.models.dits.matrixgame2.utils import create_action_presets", - "", - `os.environ["FASTVIDEO_ATTENTION_BACKEND"] = "${config.attention_backend}"`, - "generator = VideoGenerator.from_config({", - ` "model_path": "${config.model_id}",`, - " \"engine\": {", - ` "num_gpus": ${config.num_gpus},`, - ` "use_fsdp_inference": ${pythonBoolean(config.use_fsdp_inference)},`, - " \"offload\": {", - ` "dit": ${pythonBoolean(config.dit_cpu_offload)},`, - ` "dit_layerwise": ${pythonBoolean(config.dit_layerwise_offload)},`, - ` "text_encoder": ${pythonBoolean(config.text_encoder_cpu_offload)},`, - ` "image_encoder": ${pythonBoolean(config.image_encoder_cpu_offload)},`, - ` "vae": ${pythonBoolean(config.vae_cpu_offload)},`, - ` "pin_cpu_memory": ${pythonBoolean(config.pin_cpu_memory)},`, - " },", - " },", - " \"pipeline\": {", - " \"workload_type\": \"i2v\",", - " \"preset_overrides\": {", - ...pythonOverrides, - " },", - " },", - "})", - "", - `num_frames = ${config.num_frames}`, - `actions = create_action_presets(num_frames, keyboard_dim=${keyboardDim}, seed=${config.seed < 0 ? "None" : config.seed})`, - `grid_sizes = torch.tensor([${Math.floor((config.num_frames - 1) / 4) + 1}, ${Math.floor(config.height / 8)}, ${Math.floor(config.width / 8)}])`, - "generator.generate({", - ' "prompt": "",', - " \"inputs\": {", - ...inputLines, - " },", - " \"sampling\": {", - ` "height": ${config.height},`, - ` "width": ${config.width},`, - ` "num_frames": ${config.num_frames},`, - ` "fps": ${config.fps},`, - ` "num_inference_steps": ${config.num_inference_steps},`, - ...(config.dmd_denoising_steps === null ? [` "guidance_scale": ${config.guidance_scale},`] : []), - ...(config.boundary_ratio === null ? [] : [` "boundary_ratio": ${config.boundary_ratio},`]), - ` "seed": ${config.seed},`, - " },", - ' "output": {"output_path": "outputs/", "save_video": True},', - "})", - ].join("\n") - } - - const experimentalYaml = config.attention_backend === "VIDEO_SPARSE_ATTN" - ? [" experimental:", ` VSA_sparsity: ${config.VSA_sparsity}`] - : [] - const inputYaml = needsImage ? [" inputs:", " image_path: ./input.png"] : [] - - return [ - "cat > fastvideo-generate.yaml <<'YAML'", - "generator:", - ` model_path: ${config.model_id}`, - " engine:", - ` num_gpus: ${config.num_gpus}`, - ` use_fsdp_inference: ${config.use_fsdp_inference}`, - " offload:", - ` dit: ${config.dit_cpu_offload}`, - ` dit_layerwise: ${config.dit_layerwise_offload}`, - ` text_encoder: ${config.text_encoder_cpu_offload}`, - ` image_encoder: ${config.image_encoder_cpu_offload}`, - ` vae: ${config.vae_cpu_offload}`, - ` pin_cpu_memory: ${config.pin_cpu_memory}`, - " pipeline:", - ` workload_type: ${workloadType}`, - ...overrideYaml, - ...experimentalYaml, - "", - "request:", - ' prompt: "your prompt here"', - ...inputYaml, - " sampling:", - ` height: ${config.height}`, - ` width: ${config.width}`, - ` num_frames: ${config.num_frames}`, - ` fps: ${config.fps}`, - ` num_inference_steps: ${config.num_inference_steps}`, - ...(config.dmd_denoising_steps === null ? [` guidance_scale: ${config.guidance_scale}`] : []), - ...(config.guidance_scale_2 === null ? [] : [` guidance_scale_2: ${config.guidance_scale_2}`]), - ...(config.boundary_ratio === null ? [] : [` boundary_ratio: ${config.boundary_ratio}`]), - ` seed: ${config.seed}`, - " output:", - " output_path: outputs/", - " save_video: true", - "YAML", - "", - `FASTVIDEO_ATTENTION_BACKEND=${config.attention_backend} \\`, - " fastvideo generate --config fastvideo-generate.yaml", - ].join("\n") - }, [config, selectedModel]) - - const copyCommand = async () => { - await navigator.clipboard.writeText(command) - setCopied(true) - window.setTimeout(() => setCopied(false), 2000) - } - - const isImageWorkload = config.workload_type === "i2v" || config.workload_type === "ti2v" || config.workload_type === "game" - - return ( -
-
-
-

Advanced Tuning Guide

-

- Start from a maintained FastVideo recipe, then copy an executable config. Runtime and memory estimates are intentionally omitted until reproducible benchmark records are published. -

-
- -
-
Video length
{videoLength}s
-
Total pixels
{(totalPixels / 1_000_000).toFixed(1)}M
-
Latent tokens
{latentTokens.toLocaleString()}
-
- -
-
-
-
-
-
Workload
-
- {WORKLOADS.map((workload) => { - const Icon = WORKLOAD_ICONS[workload.id] ?? Film - return ( - - ) - })} -
-
-
- ({ id: model.id, name: `${model.name} (${model.size})` }))} - help="Models registered for the selected workload." - /> - setConfig((current) => ({ - ...current, - num_gpus: value, - use_fsdp_inference: value > 1 && current.use_fsdp_inference, - }))} - min={1} - max={8} - /> -
-

- Recipe source: FastVideo {SOURCE.fastvideoCommit.slice(0, 8)}. Hardware fit is not inferred. -

-
-
- -
-
- updateConfig("height", value)} min={256} max={2160} step={8} /> - updateConfig("width", value)} min={256} max={3840} step={8} /> - updateConfig("num_frames", value)} - min={config.workload_type === "game" ? 9 : 1} - max={config.workload_type === "game" ? 1197 : 1200} - step={config.workload_type === "game" ? 12 : 1} - help={config.workload_type === "game" ? "Matrix Game requires 9 + 12k frames." : undefined} - /> - updateConfig("fps", value)} min={1} max={60} /> -
- {recipeChanged &&

Custom values differ from the maintained recipe and may be unsupported.

} -
- -
-
- updateConfig("num_inference_steps", value)} - min={1} - max={100} - disabled={config.dmd_denoising_steps !== null} - help={config.dmd_denoising_steps ? "This model uses the fixed schedule shown below." : "Number of denoising iterations."} - /> - {config.workload_type !== "game" && ( - updateConfig("guidance_scale", value)} - min={0.5} - max={20} - step={0.5} - disabled={config.dmd_denoising_steps !== null} - help={config.dmd_denoising_steps ? "DMD uses the embedded CFG scale instead." : "Values above 1 may add an unconditional forward pass."} - /> - )} - {config.guidance_scale_2 !== null && updateConfig("guidance_scale_2", value)} min={0.5} max={20} step={0.5} />} - {config.workload_type !== "game" && updateConfig("embedded_cfg_scale", value)} min={0} max={20} step={0.5} />} - {config.boundary_ratio !== null && updateConfig("boundary_ratio", value)} min={0} max={1} step={0.025} />} - updateConfig("seed", value)} min={0} /> -
- {config.dmd_denoising_steps && ( -
- Fixed denoising schedule: {config.dmd_denoising_steps.join(", ")} -
- )} -
- -
-
- {availableBackends.map((backend) => ( - - ))} -
- {config.attention_backend === "VIDEO_SPARSE_ATTN" && ( -
- updateConfig("VSA_sparsity", value)} min={0} max={1} step={0.1} /> -
- )} -
- -
- setConfig((current) => ({ ...current, dit_cpu_offload: value, dit_layerwise_offload: value ? false : current.dit_layerwise_offload }))} - /> - setConfig((current) => ({ ...current, dit_layerwise_offload: value, dit_cpu_offload: value ? false : current.dit_cpu_offload, use_fsdp_inference: value ? false : current.use_fsdp_inference }))} - help="Mutually exclusive with whole-DiT offload and FSDP." - /> - updateConfig("vae_cpu_offload", value)} /> - updateConfig("text_encoder_cpu_offload", value)} /> - updateConfig("image_encoder_cpu_offload", value)} disabled={!isImageWorkload} /> - updateConfig("pin_cpu_memory", value)} /> - updateConfig("use_fsdp_inference", value)} disabled={config.num_gpus <= 1 || config.dit_layerwise_offload} /> -
-
- - -
-
-
- ) -} diff --git a/consumer-guide/app/tuning/page.tsx b/consumer-guide/app/tuning/page.tsx deleted file mode 100644 index 7f9c05dde..000000000 --- a/consumer-guide/app/tuning/page.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./adv_page" diff --git a/consumer-guide/data/quickstart.json b/consumer-guide/data/quickstart.json deleted file mode 100644 index fe1acc0d9..000000000 --- a/consumer-guide/data/quickstart.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "defaults": { - "task": "t2v", - "tier": "quick", - "numGpus": 1 - }, - "gpuCountOptions": [1, 2, 4], - "tasks": [ - { "id": "t2v", "label": "Text to Video", "sub": "T2V", "icon": "Film" }, - { "id": "i2v", "label": "Image to Video", "sub": "I2V", "icon": "Image" }, - { "id": "ti2v", "label": "Text + Image", "sub": "TI2V", "icon": "Sparkles" }, - { "id": "game", "label": "Game", "sub": "Matrix Game", "icon": "Gamepad2" } - ], - "tiers": [ - { - "id": "quick", - "name": "Recommended", - "desc": "The maintained FastVideo example for this task.", - "badge": "Start here" - }, - { - "id": "best", - "name": "Alternative", - "desc": "Another maintained model or task variant." - } - ], - "profiles": [ - { - "task": "t2v", - "tier": "quick", - "model": "FastVideo/FastWan2.1-T2V-1.3B-Diffusers", - "ditCpuOffload": false, - "ditLayerwiseOffload": false, - "vaeCpuOffload": false, - "textEncoderCpuOffload": true, - "imageEncoderCpuOffload": false, - "pinCpuMemory": true, - "useFsdpInference": false - }, - { - "task": "t2v", - "tier": "best", - "model": "Wan-AI/Wan2.1-T2V-14B-Diffusers", - "ditCpuOffload": true, - "ditLayerwiseOffload": false, - "vaeCpuOffload": false, - "textEncoderCpuOffload": true, - "imageEncoderCpuOffload": false, - "pinCpuMemory": true, - "useFsdpInference": false - }, - { - "task": "i2v", - "tier": "quick", - "model": "loayrashid/TurboWan2.2-I2V-A14B-Diffusers", - "ditCpuOffload": true, - "ditLayerwiseOffload": false, - "vaeCpuOffload": false, - "textEncoderCpuOffload": true, - "imageEncoderCpuOffload": true, - "pinCpuMemory": true, - "useFsdpInference": false - }, - { - "task": "i2v", - "tier": "best", - "model": "Wan-AI/Wan2.1-I2V-14B-720P-Diffusers", - "ditCpuOffload": true, - "ditLayerwiseOffload": false, - "vaeCpuOffload": false, - "textEncoderCpuOffload": true, - "imageEncoderCpuOffload": true, - "pinCpuMemory": true, - "useFsdpInference": false - }, - { - "task": "ti2v", - "tier": "quick", - "model": "FastVideo/FastWan2.2-TI2V-5B-FullAttn-Diffusers", - "ditCpuOffload": true, - "ditLayerwiseOffload": false, - "vaeCpuOffload": false, - "textEncoderCpuOffload": true, - "imageEncoderCpuOffload": true, - "pinCpuMemory": true, - "useFsdpInference": false - }, - { - "task": "ti2v", - "tier": "best", - "model": "Wan-AI/Wan2.2-TI2V-5B-Diffusers", - "ditCpuOffload": true, - "ditLayerwiseOffload": false, - "vaeCpuOffload": false, - "textEncoderCpuOffload": true, - "imageEncoderCpuOffload": true, - "pinCpuMemory": true, - "useFsdpInference": false - }, - { - "task": "game", - "tier": "quick", - "model": "FastVideo/Matrix-Game-2.0-Base-Distilled-Diffusers", - "ditCpuOffload": true, - "ditLayerwiseOffload": false, - "vaeCpuOffload": false, - "textEncoderCpuOffload": true, - "imageEncoderCpuOffload": true, - "pinCpuMemory": true, - "useFsdpInference": false - }, - { - "task": "game", - "tier": "best", - "model": "FastVideo/Matrix-Game-2.0-GTA-Distilled-Diffusers", - "ditCpuOffload": true, - "ditLayerwiseOffload": false, - "vaeCpuOffload": false, - "textEncoderCpuOffload": true, - "imageEncoderCpuOffload": true, - "pinCpuMemory": true, - "useFsdpInference": false - } - ] -} diff --git a/consumer-guide/data/tuning.json b/consumer-guide/data/tuning.json deleted file mode 100644 index b2bd30d73..000000000 --- a/consumer-guide/data/tuning.json +++ /dev/null @@ -1,170 +0,0 @@ -{ - "source": { - "fastvideoCommit": "a2bfc7cdb2a1de2b138258412e42d183444ffe09", - "description": "Defaults transcribed from FastVideo's registered inference presets, pipeline configs, maintained examples, and support matrix at this commit.", - "paths": [ - "fastvideo/registry.py", - "fastvideo/pipelines/basic/*/presets.py", - "fastvideo/configs/pipelines/*.py", - "examples/inference/basic/*.py", - "docs/inference/support_matrix.md" - ] - }, - "defaults": { - "model_id": "FastVideo/FastWan2.1-T2V-1.3B-Diffusers", - "workload_type": "t2v", - "num_gpus": 1, - "seed": 1024, - "dit_cpu_offload": false, - "dit_layerwise_offload": false, - "vae_cpu_offload": false, - "text_encoder_cpu_offload": true, - "image_encoder_cpu_offload": false, - "pin_cpu_memory": true, - "use_fsdp_inference": false - }, - "workloads": [ - { "id": "t2v", "name": "Text to Video", "icon": "Film" }, - { "id": "i2v", "name": "Image to Video", "icon": "Sparkles" }, - { "id": "ti2v", "name": "Text + Image to Video", "icon": "Layers" }, - { "id": "game", "name": "Game", "icon": "Zap" } - ], - "attentionBackends": [ - { "id": "FLASH_ATTN", "name": "Flash Attention", "shortName": "Flash", "desc": "Default dense attention backend." }, - { "id": "VIDEO_SPARSE_ATTN", "name": "Video Sparse Attention", "shortName": "VSA", "desc": "Use only with models marked VSA-compatible." }, - { "id": "SAGE_ATTN", "name": "Sage Attention", "shortName": "SAGE", "desc": "Quantized attention for models marked Sage-compatible." }, - { "id": "SLA_ATTN", "name": "Sparse-Linear Attention", "shortName": "SLA", "desc": "Required by TurboDiffusion checkpoints." } - ], - "models": [ - { - "id": "FastVideo/FastWan2.1-T2V-1.3B-Diffusers", - "name": "FastWan2.1 T2V", - "size": "1.3B", - "workload": "t2v", - "recipe": { "height": 448, "width": 832, "numFrames": 61, "fps": 16, "numInferenceSteps": 3, "guidanceScale": 3, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 8, "boundaryRatio": null, "dmdDenoisingSteps": [1000, 757, 522], "attentionBackends": ["VIDEO_SPARSE_ATTN", "FLASH_ATTN"], "defaultAttentionBackend": "VIDEO_SPARSE_ATTN", "vsaSparsity": 0.8 } - }, - { - "id": "FastVideo/FastWan2.2-TI2V-5B-FullAttn-Diffusers", - "name": "FastWan2.2 TI2V FullAttn", - "size": "5B", - "workload": "ti2v", - "recipe": { "height": 704, "width": 1280, "numFrames": 121, "fps": 24, "numInferenceSteps": 3, "guidanceScale": 5, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": [1000, 757, 522], "attentionBackends": ["FLASH_ATTN", "VIDEO_SPARSE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - }, - { - "id": "Wan-AI/Wan2.2-TI2V-5B-Diffusers", - "name": "Wan2.2 TI2V", - "size": "5B", - "workload": "ti2v", - "recipe": { "height": 704, "width": 1280, "numFrames": 121, "fps": 24, "numInferenceSteps": 50, "guidanceScale": 5, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - }, - { - "id": "Wan-AI/Wan2.2-T2V-A14B-Diffusers", - "name": "Wan2.2 T2V", - "size": "A14B", - "workload": "t2v", - "recipe": { "height": 720, "width": 1280, "numFrames": 81, "fps": 16, "numInferenceSteps": 40, "guidanceScale": 4, "guidanceScale2": 3, "embeddedCfgScale": 6, "flowShift": 12, "boundaryRatio": 0.875, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - }, - { - "id": "Wan-AI/Wan2.2-I2V-A14B-Diffusers", - "name": "Wan2.2 I2V", - "size": "A14B", - "workload": "i2v", - "recipe": { "height": 832, "width": 480, "numFrames": 81, "fps": 16, "numInferenceSteps": 40, "guidanceScale": 3.5, "guidanceScale2": 3.5, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": 0.9, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - }, - { - "id": "hunyuanvideo-community/HunyuanVideo", - "name": "HunyuanVideo", - "size": "13B", - "workload": "t2v", - "recipe": { "height": 720, "width": 1280, "numFrames": 125, "fps": 24, "numInferenceSteps": 50, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 7, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - }, - { - "id": "FastVideo/FastHunyuan-diffusers", - "name": "FastHunyuan", - "size": "13B", - "workload": "t2v", - "recipe": { "height": 720, "width": 1280, "numFrames": 125, "fps": 24, "numInferenceSteps": 6, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 17, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - }, - { - "id": "Wan-AI/Wan2.1-T2V-1.3B-Diffusers", - "name": "Wan2.1 T2V", - "size": "1.3B", - "workload": "t2v", - "recipe": { "height": 480, "width": 832, "numFrames": 81, "fps": 16, "numInferenceSteps": 50, "guidanceScale": 3, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 3, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - }, - { - "id": "Wan-AI/Wan2.1-T2V-14B-Diffusers", - "name": "Wan2.1 T2V", - "size": "14B", - "workload": "t2v", - "recipe": { "height": 720, "width": 1280, "numFrames": 81, "fps": 16, "numInferenceSteps": 50, "guidanceScale": 5, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - }, - { - "id": "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers", - "name": "Wan2.1 I2V 480P", - "size": "14B", - "workload": "i2v", - "recipe": { "height": 480, "width": 832, "numFrames": 81, "fps": 16, "numInferenceSteps": 40, "guidanceScale": 5, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 3, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - }, - { - "id": "Wan-AI/Wan2.1-I2V-14B-720P-Diffusers", - "name": "Wan2.1 I2V 720P", - "size": "14B", - "workload": "i2v", - "recipe": { "height": 720, "width": 1280, "numFrames": 81, "fps": 16, "numInferenceSteps": 40, "guidanceScale": 5, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - }, - { - "id": "loayrashid/TurboWan2.1-T2V-1.3B-Diffusers", - "name": "TurboWan2.1 T2V", - "size": "1.3B", - "workload": "t2v", - "recipe": { "height": 480, "width": 832, "numFrames": 81, "fps": 16, "numInferenceSteps": 4, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 3, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["SLA_ATTN"], "defaultAttentionBackend": "SLA_ATTN", "vsaSparsity": 0 } - }, - { - "id": "loayrashid/TurboWan2.1-T2V-14B-Diffusers", - "name": "TurboWan2.1 T2V", - "size": "14B", - "workload": "t2v", - "recipe": { "height": 720, "width": 1280, "numFrames": 81, "fps": 16, "numInferenceSteps": 4, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["SLA_ATTN"], "defaultAttentionBackend": "SLA_ATTN", "vsaSparsity": 0 } - }, - { - "id": "loayrashid/TurboWan2.2-I2V-A14B-Diffusers", - "name": "TurboWan2.2 I2V", - "size": "A14B", - "workload": "i2v", - "recipe": { "height": 720, "width": 1280, "numFrames": 81, "fps": 16, "numInferenceSteps": 4, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": 0.9, "dmdDenoisingSteps": null, "attentionBackends": ["SLA_ATTN"], "defaultAttentionBackend": "SLA_ATTN", "vsaSparsity": 0 } - }, - { - "id": "FastVideo/LongCat-Video-T2V-Diffusers", - "name": "LongCat T2V", - "size": "13.6B", - "workload": "t2v", - "recipe": { "height": 480, "width": 848, "numFrames": 121, "fps": 24, "numInferenceSteps": 50, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": null, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - }, - { - "id": "FastVideo/Matrix-Game-2.0-Base-Distilled-Diffusers", - "name": "Matrix Game 2.0 Base", - "size": "1.3B", - "workload": "game", - "keyboardDim": 4, - "recipe": { "height": 352, "width": 640, "numFrames": 57, "fps": 25, "numInferenceSteps": 3, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": [1000, 666, 333], "attentionBackends": ["FLASH_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - }, - { - "id": "FastVideo/Matrix-Game-2.0-GTA-Distilled-Diffusers", - "name": "Matrix Game 2.0 GTA", - "size": "1.3B", - "workload": "game", - "keyboardDim": 2, - "recipe": { "height": 352, "width": 640, "numFrames": 57, "fps": 25, "numInferenceSteps": 3, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": [1000, 666, 333], "attentionBackends": ["FLASH_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - }, - { - "id": "FastVideo/Matrix-Game-2.0-TempleRun-Distilled-Diffusers", - "name": "Matrix Game 2.0 TempleRun", - "size": "1.3B", - "workload": "game", - "keyboardDim": 7, - "usesMouse": false, - "recipe": { "height": 352, "width": 640, "numFrames": 57, "fps": 25, "numInferenceSteps": 3, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": [1000, 666, 333], "attentionBackends": ["FLASH_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 } - } - ] -} diff --git a/consumer-guide/next.config.mjs b/consumer-guide/next.config.mjs deleted file mode 100644 index 47f039e89..000000000 --- a/consumer-guide/next.config.mjs +++ /dev/null @@ -1,16 +0,0 @@ -/** @type {import('next').NextConfig} */ -const basePath = process.env.NEXT_BASE_PATH || "/config-generator" - -const nextConfig = { - output: "export", - trailingSlash: true, - basePath, - typescript: { - ignoreBuildErrors: false, - }, - images: { - unoptimized: true, - }, -} - -export default nextConfig diff --git a/consumer-guide/package.json b/consumer-guide/package.json deleted file mode 100644 index 9b39db0b4..000000000 --- a/consumer-guide/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "fastvideo-config-generator", - "version": "0.1.0", - "private": true, - "packageManager": "pnpm@10.28.0", - "scripts": { - "dev": "next dev -p 3003", - "build": "node scripts/validate-data.mjs && next build" - }, - "dependencies": { - "lucide-react": "^0.564.0", - "next": "16.2.4", - "react": "^19", - "react-dom": "^19" - }, - "devDependencies": { - "@tailwindcss/postcss": "^4.2.0", - "@types/node": "^22", - "@types/react": "^19", - "@types/react-dom": "^19", - "postcss": "^8.5", - "tailwindcss": "^4.2.0", - "tw-animate-css": "1.3.3", - "typescript": "5.7.3" - } -} diff --git a/consumer-guide/pnpm-lock.yaml b/consumer-guide/pnpm-lock.yaml deleted file mode 100644 index ae07e8cdb..000000000 --- a/consumer-guide/pnpm-lock.yaml +++ /dev/null @@ -1,979 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - lucide-react: - specifier: ^0.564.0 - version: 0.564.0(react@19.2.4) - next: - specifier: 16.2.4 - version: 16.2.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: - specifier: ^19 - version: 19.2.4 - react-dom: - specifier: ^19 - version: 19.2.4(react@19.2.4) - devDependencies: - '@tailwindcss/postcss': - specifier: ^4.2.0 - version: 4.2.0 - '@types/node': - specifier: ^22 - version: 22.19.11 - '@types/react': - specifier: ^19 - version: 19.2.14 - '@types/react-dom': - specifier: ^19 - version: 19.2.3(@types/react@19.2.14) - postcss: - specifier: ^8.5 - version: 8.5.6 - tailwindcss: - specifier: ^4.2.0 - version: 4.2.0 - tw-animate-css: - specifier: 1.3.3 - version: 1.3.3 - typescript: - specifier: 5.7.3 - version: 5.7.3 - -packages: - - '@alloc/quick-lru@5.2.0': - resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} - engines: {node: '>=10'} - - '@emnapi/runtime@1.8.1': - resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} - - '@img/colour@1.0.0': - resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} - engines: {node: '>=18'} - - '@img/sharp-darwin-arm64@0.34.5': - resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [darwin] - - '@img/sharp-darwin-x64@0.34.5': - resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [darwin] - - '@img/sharp-libvips-darwin-arm64@1.2.4': - resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} - cpu: [arm64] - os: [darwin] - - '@img/sharp-libvips-darwin-x64@1.2.4': - resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} - cpu: [x64] - os: [darwin] - - '@img/sharp-libvips-linux-arm64@1.2.4': - resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} - cpu: [arm64] - os: [linux] - - '@img/sharp-libvips-linux-arm@1.2.4': - resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} - cpu: [arm] - os: [linux] - - '@img/sharp-libvips-linux-ppc64@1.2.4': - resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} - cpu: [ppc64] - os: [linux] - - '@img/sharp-libvips-linux-riscv64@1.2.4': - resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} - cpu: [riscv64] - os: [linux] - - '@img/sharp-libvips-linux-s390x@1.2.4': - resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} - cpu: [s390x] - os: [linux] - - '@img/sharp-libvips-linux-x64@1.2.4': - resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} - cpu: [x64] - os: [linux] - - '@img/sharp-libvips-linuxmusl-arm64@1.2.4': - resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} - cpu: [arm64] - os: [linux] - - '@img/sharp-libvips-linuxmusl-x64@1.2.4': - resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} - cpu: [x64] - os: [linux] - - '@img/sharp-linux-arm64@0.34.5': - resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - - '@img/sharp-linux-arm@0.34.5': - resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm] - os: [linux] - - '@img/sharp-linux-ppc64@0.34.5': - resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [ppc64] - os: [linux] - - '@img/sharp-linux-riscv64@0.34.5': - resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [riscv64] - os: [linux] - - '@img/sharp-linux-s390x@0.34.5': - resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [s390x] - os: [linux] - - '@img/sharp-linux-x64@0.34.5': - resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - - '@img/sharp-linuxmusl-arm64@0.34.5': - resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - - '@img/sharp-linuxmusl-x64@0.34.5': - resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - - '@img/sharp-wasm32@0.34.5': - resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [wasm32] - - '@img/sharp-win32-arm64@0.34.5': - resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [win32] - - '@img/sharp-win32-ia32@0.34.5': - resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [ia32] - os: [win32] - - '@img/sharp-win32-x64@0.34.5': - resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [win32] - - '@jridgewell/gen-mapping@0.3.13': - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - - '@jridgewell/remapping@2.3.5': - resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - - '@jridgewell/trace-mapping@0.3.31': - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - - '@next/env@16.2.4': - resolution: {integrity: sha512-dKkkOzOSwFYe5RX6y26fZgkSpVAlIOJKQHIiydQcrWH6y/97+RceSOAdjZ14Qa3zLduVUy0TXcn+EiM6t4rPgw==} - - '@next/swc-darwin-arm64@16.2.4': - resolution: {integrity: sha512-OXTFFox5EKN1Ym08vfrz+OXxmCcEjT4SFMbNRsWZE99dMqt2Kcusl5MqPXcW232RYkMLQTy0hqgAMEsfEd/l2A==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@next/swc-darwin-x64@16.2.4': - resolution: {integrity: sha512-XhpVnUfmYWvD3YrXu55XdcAkQtOnvaI6wtQa8fuF5fGoKoxIUZ0kWPtcOfqJEWngFF/lOS9l3+O9CcownhiQxQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@next/swc-linux-arm64-gnu@16.2.4': - resolution: {integrity: sha512-Mx/tjlNA3G8kg14QvuGAJ4xBwPk1tUHq56JxZ8CXnZwz1Etz714soCEzGQQzVMz4bEnGPowzkV6Xrp6wAkEWOQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-arm64-musl@16.2.4': - resolution: {integrity: sha512-iVMMp14514u7Nup2umQS03nT/bN9HurK8ufylC3FZNykrwjtx7V1A7+4kvhbDSCeonTVqV3Txnv0Lu+m2oDXNg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-x64-gnu@16.2.4': - resolution: {integrity: sha512-EZOvm1aQWgnI/N/xcWOlnS3RQBk0VtVav5Zo7n4p0A7UKyTDx047k8opDbXgBpHl4CulRqRfbw3QrX2w5UOXMQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-linux-x64-musl@16.2.4': - resolution: {integrity: sha512-h9FxsngCm9cTBf71AR4fGznDEDx1hS7+kSEiIRjq5kO1oXWm07DxVGZjCvk0SGx7TSjlUqhI8oOyz7NfwAdPoA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-win32-arm64-msvc@16.2.4': - resolution: {integrity: sha512-3NdJV5OXMSOeJYijX+bjaLge3mJBlh4ybydbT4GFoB/2hAojWHtMhl3CYlYoMrjPuodp0nzFVi4Tj2+WaMg+Ow==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@next/swc-win32-x64-msvc@16.2.4': - resolution: {integrity: sha512-kMVGgsqhO5YTYODD9IPGGhA6iprWidQckK3LmPeW08PIFENRmgfb4MjXHO+p//d+ts2rpjvK5gXWzXSMrPl9cw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - - '@swc/helpers@0.5.15': - resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - - '@tailwindcss/node@4.2.0': - resolution: {integrity: sha512-Yv+fn/o2OmL5fh/Ir62VXItdShnUxfpkMA4Y7jdeC8O81WPB8Kf6TT6GSHvnqgSwDzlB5iT7kDpeXxLsUS0T6Q==} - - '@tailwindcss/oxide-android-arm64@4.2.0': - resolution: {integrity: sha512-F0QkHAVaW/JNBWl4CEKWdZ9PMb0khw5DCELAOnu+RtjAfx5Zgw+gqCHFvqg3AirU1IAd181fwOtJQ5I8Yx5wtw==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [android] - - '@tailwindcss/oxide-darwin-arm64@4.2.0': - resolution: {integrity: sha512-I0QylkXsBsJMZ4nkUNSR04p6+UptjcwhcVo3Zu828ikiEqHjVmQL9RuQ6uT/cVIiKpvtVA25msu/eRV97JeNSA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [darwin] - - '@tailwindcss/oxide-darwin-x64@4.2.0': - resolution: {integrity: sha512-6TmQIn4p09PBrmnkvbYQ0wbZhLtbaksCDx7Y7R3FYYx0yxNA7xg5KP7dowmQ3d2JVdabIHvs3Hx4K3d5uCf8xg==} - engines: {node: '>= 20'} - cpu: [x64] - os: [darwin] - - '@tailwindcss/oxide-freebsd-x64@4.2.0': - resolution: {integrity: sha512-qBudxDvAa2QwGlq9y7VIzhTvp2mLJ6nD/G8/tI70DCDoneaUeLWBJaPcbfzqRIWraj+o969aDQKvKW9dvkUizw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [freebsd] - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.0': - resolution: {integrity: sha512-7XKkitpy5NIjFZNUQPeUyNJNJn1CJeV7rmMR+exHfTuOsg8rxIO9eNV5TSEnqRcaOK77zQpsyUkBWmPy8FgdSg==} - engines: {node: '>= 20'} - cpu: [arm] - os: [linux] - - '@tailwindcss/oxide-linux-arm64-gnu@4.2.0': - resolution: {integrity: sha512-Mff5a5Q3WoQR01pGU1gr29hHM1N93xYrKkGXfPw/aRtK4bOc331Ho4Tgfsm5WDGvpevqMpdlkCojT3qlCQbCpA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - - '@tailwindcss/oxide-linux-arm64-musl@4.2.0': - resolution: {integrity: sha512-XKcSStleEVnbH6W/9DHzZv1YhjE4eSS6zOu2eRtYAIh7aV4o3vIBs+t/B15xlqoxt6ef/0uiqJVB6hkHjWD/0A==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - - '@tailwindcss/oxide-linux-x64-gnu@4.2.0': - resolution: {integrity: sha512-/hlXCBqn9K6fi7eAM0RsobHwJYa5V/xzWspVTzxnX+Ft9v6n+30Pz8+RxCn7sQL/vRHHLS30iQPrHQunu6/vJA==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - - '@tailwindcss/oxide-linux-x64-musl@4.2.0': - resolution: {integrity: sha512-lKUaygq4G7sWkhQbfdRRBkaq4LY39IriqBQ+Gk6l5nKq6Ay2M2ZZb1tlIyRNgZKS8cbErTwuYSor0IIULC0SHw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - - '@tailwindcss/oxide-wasm32-wasi@4.2.0': - resolution: {integrity: sha512-xuDjhAsFdUuFP5W9Ze4k/o4AskUtI8bcAGU4puTYprr89QaYFmhYOPfP+d1pH+k9ets6RoE23BXZM1X1jJqoyw==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - bundledDependencies: - - '@napi-rs/wasm-runtime' - - '@emnapi/core' - - '@emnapi/runtime' - - '@tybys/wasm-util' - - '@emnapi/wasi-threads' - - tslib - - '@tailwindcss/oxide-win32-arm64-msvc@4.2.0': - resolution: {integrity: sha512-2UU/15y1sWDEDNJXxEIrfWKC2Yb4YgIW5Xz2fKFqGzFWfoMHWFlfa1EJlGO2Xzjkq/tvSarh9ZTjvbxqWvLLXA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [win32] - - '@tailwindcss/oxide-win32-x64-msvc@4.2.0': - resolution: {integrity: sha512-CrFadmFoc+z76EV6LPG1jx6XceDsaCG3lFhyLNo/bV9ByPrE+FnBPckXQVP4XRkN76h3Fjt/a+5Er/oA/nCBvQ==} - engines: {node: '>= 20'} - cpu: [x64] - os: [win32] - - '@tailwindcss/oxide@4.2.0': - resolution: {integrity: sha512-AZqQzADaj742oqn2xjl5JbIOzZB/DGCYF/7bpvhA8KvjUj9HJkag6bBuwZvH1ps6dfgxNHyuJVlzSr2VpMgdTQ==} - engines: {node: '>= 20'} - - '@tailwindcss/postcss@4.2.0': - resolution: {integrity: sha512-u6YBacGpOm/ixPfKqfgrJEjMfrYmPD7gEFRoygS/hnQaRtV0VCBdpkx5Ouw9pnaLRwwlgGCuJw8xLpaR0hOrQg==} - - '@types/node@22.19.11': - resolution: {integrity: sha512-BH7YwL6rA93ReqeQS1c4bsPpcfOmJasG+Fkr6Y59q83f9M1WcBRHR2vM+P9eOisYRcN3ujQoiZY8uk5W+1WL8w==} - - '@types/react-dom@19.2.3': - resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} - peerDependencies: - '@types/react': ^19.2.0 - - '@types/react@19.2.14': - resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} - - baseline-browser-mapping@2.9.19: - resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} - hasBin: true - - caniuse-lite@1.0.30001769: - resolution: {integrity: sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==} - - client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - - csstype@3.2.3: - resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - - detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} - - enhanced-resolve@5.19.0: - resolution: {integrity: sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==} - engines: {node: '>=10.13.0'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - jiti@2.6.1: - resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} - hasBin: true - - lightningcss-android-arm64@1.31.1: - resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [android] - - lightningcss-darwin-arm64@1.31.1: - resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [darwin] - - lightningcss-darwin-x64@1.31.1: - resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [darwin] - - lightningcss-freebsd-x64@1.31.1: - resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [freebsd] - - lightningcss-linux-arm-gnueabihf@1.31.1: - resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==} - engines: {node: '>= 12.0.0'} - cpu: [arm] - os: [linux] - - lightningcss-linux-arm64-gnu@1.31.1: - resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - - lightningcss-linux-arm64-musl@1.31.1: - resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - - lightningcss-linux-x64-gnu@1.31.1: - resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - - lightningcss-linux-x64-musl@1.31.1: - resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - - lightningcss-win32-arm64-msvc@1.31.1: - resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [win32] - - lightningcss-win32-x64-msvc@1.31.1: - resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [win32] - - lightningcss@1.31.1: - resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==} - engines: {node: '>= 12.0.0'} - - lucide-react@0.564.0: - resolution: {integrity: sha512-JJ8GVTQqFwuliifD48U6+h7DXEHdkhJ/E87kksGByII3qHxtPciVb8T8woQONHBQgHVOl7rSMrrip3SeVNy7Fg==} - peerDependencies: - react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 - - magic-string@0.30.21: - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - next@16.2.4: - resolution: {integrity: sha512-kPvz56wF5frc+FxlHI5qnklCzbq53HTwORaWBGdT0vNoKh1Aya9XC8aPauH4NJxqtzbWsS5mAbctm4cr+EkQ2Q==} - engines: {node: '>=20.9.0'} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.51.1 - babel-plugin-react-compiler: '*' - react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@playwright/test': - optional: true - babel-plugin-react-compiler: - optional: true - sass: - optional: true - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} - engines: {node: ^10 || ^12 || >=14} - - react-dom@19.2.4: - resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} - peerDependencies: - react: ^19.2.4 - - react@19.2.4: - resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} - engines: {node: '>=0.10.0'} - - scheduler@0.27.0: - resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} - - semver@7.7.4: - resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} - engines: {node: '>=10'} - hasBin: true - - sharp@0.34.5: - resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - styled-jsx@5.1.6: - resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - - tailwindcss@4.2.0: - resolution: {integrity: sha512-yYzTZ4++b7fNYxFfpnberEEKu43w44aqDMNM9MHMmcKuCH7lL8jJ4yJ7LGHv7rSwiqM0nkiobF9I6cLlpS2P7Q==} - - tapable@2.3.0: - resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} - engines: {node: '>=6'} - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - tw-animate-css@1.3.3: - resolution: {integrity: sha512-tXE2TRWrskc4TU3RDd7T8n8Np/wCfoeH9gz22c7PzYqNPQ9FBGFbWWzwL0JyHcFp+jHozmF76tbHfPAx22ua2Q==} - - typescript@5.7.3: - resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} - engines: {node: '>=14.17'} - hasBin: true - - undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - -snapshots: - - '@alloc/quick-lru@5.2.0': {} - - '@emnapi/runtime@1.8.1': - dependencies: - tslib: 2.8.1 - optional: true - - '@img/colour@1.0.0': - optional: true - - '@img/sharp-darwin-arm64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.2.4 - optional: true - - '@img/sharp-darwin-x64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.2.4 - optional: true - - '@img/sharp-libvips-darwin-arm64@1.2.4': - optional: true - - '@img/sharp-libvips-darwin-x64@1.2.4': - optional: true - - '@img/sharp-libvips-linux-arm64@1.2.4': - optional: true - - '@img/sharp-libvips-linux-arm@1.2.4': - optional: true - - '@img/sharp-libvips-linux-ppc64@1.2.4': - optional: true - - '@img/sharp-libvips-linux-riscv64@1.2.4': - optional: true - - '@img/sharp-libvips-linux-s390x@1.2.4': - optional: true - - '@img/sharp-libvips-linux-x64@1.2.4': - optional: true - - '@img/sharp-libvips-linuxmusl-arm64@1.2.4': - optional: true - - '@img/sharp-libvips-linuxmusl-x64@1.2.4': - optional: true - - '@img/sharp-linux-arm64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.2.4 - optional: true - - '@img/sharp-linux-arm@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.2.4 - optional: true - - '@img/sharp-linux-ppc64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-ppc64': 1.2.4 - optional: true - - '@img/sharp-linux-riscv64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-riscv64': 1.2.4 - optional: true - - '@img/sharp-linux-s390x@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.2.4 - optional: true - - '@img/sharp-linux-x64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.2.4 - optional: true - - '@img/sharp-linuxmusl-arm64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 - optional: true - - '@img/sharp-linuxmusl-x64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.2.4 - optional: true - - '@img/sharp-wasm32@0.34.5': - dependencies: - '@emnapi/runtime': 1.8.1 - optional: true - - '@img/sharp-win32-arm64@0.34.5': - optional: true - - '@img/sharp-win32-ia32@0.34.5': - optional: true - - '@img/sharp-win32-x64@0.34.5': - optional: true - - '@jridgewell/gen-mapping@0.3.13': - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/remapping@2.3.5': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/sourcemap-codec@1.5.5': {} - - '@jridgewell/trace-mapping@0.3.31': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - - '@next/env@16.2.4': {} - - '@next/swc-darwin-arm64@16.2.4': - optional: true - - '@next/swc-darwin-x64@16.2.4': - optional: true - - '@next/swc-linux-arm64-gnu@16.2.4': - optional: true - - '@next/swc-linux-arm64-musl@16.2.4': - optional: true - - '@next/swc-linux-x64-gnu@16.2.4': - optional: true - - '@next/swc-linux-x64-musl@16.2.4': - optional: true - - '@next/swc-win32-arm64-msvc@16.2.4': - optional: true - - '@next/swc-win32-x64-msvc@16.2.4': - optional: true - - '@swc/helpers@0.5.15': - dependencies: - tslib: 2.8.1 - - '@tailwindcss/node@4.2.0': - dependencies: - '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.19.0 - jiti: 2.6.1 - lightningcss: 1.31.1 - magic-string: 0.30.21 - source-map-js: 1.2.1 - tailwindcss: 4.2.0 - - '@tailwindcss/oxide-android-arm64@4.2.0': - optional: true - - '@tailwindcss/oxide-darwin-arm64@4.2.0': - optional: true - - '@tailwindcss/oxide-darwin-x64@4.2.0': - optional: true - - '@tailwindcss/oxide-freebsd-x64@4.2.0': - optional: true - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.0': - optional: true - - '@tailwindcss/oxide-linux-arm64-gnu@4.2.0': - optional: true - - '@tailwindcss/oxide-linux-arm64-musl@4.2.0': - optional: true - - '@tailwindcss/oxide-linux-x64-gnu@4.2.0': - optional: true - - '@tailwindcss/oxide-linux-x64-musl@4.2.0': - optional: true - - '@tailwindcss/oxide-wasm32-wasi@4.2.0': - optional: true - - '@tailwindcss/oxide-win32-arm64-msvc@4.2.0': - optional: true - - '@tailwindcss/oxide-win32-x64-msvc@4.2.0': - optional: true - - '@tailwindcss/oxide@4.2.0': - optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.2.0 - '@tailwindcss/oxide-darwin-arm64': 4.2.0 - '@tailwindcss/oxide-darwin-x64': 4.2.0 - '@tailwindcss/oxide-freebsd-x64': 4.2.0 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.0 - '@tailwindcss/oxide-linux-arm64-gnu': 4.2.0 - '@tailwindcss/oxide-linux-arm64-musl': 4.2.0 - '@tailwindcss/oxide-linux-x64-gnu': 4.2.0 - '@tailwindcss/oxide-linux-x64-musl': 4.2.0 - '@tailwindcss/oxide-wasm32-wasi': 4.2.0 - '@tailwindcss/oxide-win32-arm64-msvc': 4.2.0 - '@tailwindcss/oxide-win32-x64-msvc': 4.2.0 - - '@tailwindcss/postcss@4.2.0': - dependencies: - '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.2.0 - '@tailwindcss/oxide': 4.2.0 - postcss: 8.5.6 - tailwindcss: 4.2.0 - - '@types/node@22.19.11': - dependencies: - undici-types: 6.21.0 - - '@types/react-dom@19.2.3(@types/react@19.2.14)': - dependencies: - '@types/react': 19.2.14 - - '@types/react@19.2.14': - dependencies: - csstype: 3.2.3 - - baseline-browser-mapping@2.9.19: {} - - caniuse-lite@1.0.30001769: {} - - client-only@0.0.1: {} - - csstype@3.2.3: {} - - detect-libc@2.1.2: {} - - enhanced-resolve@5.19.0: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.3.0 - - graceful-fs@4.2.11: {} - - jiti@2.6.1: {} - - lightningcss-android-arm64@1.31.1: - optional: true - - lightningcss-darwin-arm64@1.31.1: - optional: true - - lightningcss-darwin-x64@1.31.1: - optional: true - - lightningcss-freebsd-x64@1.31.1: - optional: true - - lightningcss-linux-arm-gnueabihf@1.31.1: - optional: true - - lightningcss-linux-arm64-gnu@1.31.1: - optional: true - - lightningcss-linux-arm64-musl@1.31.1: - optional: true - - lightningcss-linux-x64-gnu@1.31.1: - optional: true - - lightningcss-linux-x64-musl@1.31.1: - optional: true - - lightningcss-win32-arm64-msvc@1.31.1: - optional: true - - lightningcss-win32-x64-msvc@1.31.1: - optional: true - - lightningcss@1.31.1: - dependencies: - detect-libc: 2.1.2 - optionalDependencies: - lightningcss-android-arm64: 1.31.1 - lightningcss-darwin-arm64: 1.31.1 - lightningcss-darwin-x64: 1.31.1 - lightningcss-freebsd-x64: 1.31.1 - lightningcss-linux-arm-gnueabihf: 1.31.1 - lightningcss-linux-arm64-gnu: 1.31.1 - lightningcss-linux-arm64-musl: 1.31.1 - lightningcss-linux-x64-gnu: 1.31.1 - lightningcss-linux-x64-musl: 1.31.1 - lightningcss-win32-arm64-msvc: 1.31.1 - lightningcss-win32-x64-msvc: 1.31.1 - - lucide-react@0.564.0(react@19.2.4): - dependencies: - react: 19.2.4 - - magic-string@0.30.21: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - - nanoid@3.3.11: {} - - next@16.2.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - '@next/env': 16.2.4 - '@swc/helpers': 0.5.15 - baseline-browser-mapping: 2.9.19 - caniuse-lite: 1.0.30001769 - postcss: 8.4.31 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - styled-jsx: 5.1.6(react@19.2.4) - optionalDependencies: - '@next/swc-darwin-arm64': 16.2.4 - '@next/swc-darwin-x64': 16.2.4 - '@next/swc-linux-arm64-gnu': 16.2.4 - '@next/swc-linux-arm64-musl': 16.2.4 - '@next/swc-linux-x64-gnu': 16.2.4 - '@next/swc-linux-x64-musl': 16.2.4 - '@next/swc-win32-arm64-msvc': 16.2.4 - '@next/swc-win32-x64-msvc': 16.2.4 - sharp: 0.34.5 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - - picocolors@1.1.1: {} - - postcss@8.4.31: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - postcss@8.5.6: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - react-dom@19.2.4(react@19.2.4): - dependencies: - react: 19.2.4 - scheduler: 0.27.0 - - react@19.2.4: {} - - scheduler@0.27.0: {} - - semver@7.7.4: - optional: true - - sharp@0.34.5: - dependencies: - '@img/colour': 1.0.0 - detect-libc: 2.1.2 - semver: 7.7.4 - optionalDependencies: - '@img/sharp-darwin-arm64': 0.34.5 - '@img/sharp-darwin-x64': 0.34.5 - '@img/sharp-libvips-darwin-arm64': 1.2.4 - '@img/sharp-libvips-darwin-x64': 1.2.4 - '@img/sharp-libvips-linux-arm': 1.2.4 - '@img/sharp-libvips-linux-arm64': 1.2.4 - '@img/sharp-libvips-linux-ppc64': 1.2.4 - '@img/sharp-libvips-linux-riscv64': 1.2.4 - '@img/sharp-libvips-linux-s390x': 1.2.4 - '@img/sharp-libvips-linux-x64': 1.2.4 - '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 - '@img/sharp-libvips-linuxmusl-x64': 1.2.4 - '@img/sharp-linux-arm': 0.34.5 - '@img/sharp-linux-arm64': 0.34.5 - '@img/sharp-linux-ppc64': 0.34.5 - '@img/sharp-linux-riscv64': 0.34.5 - '@img/sharp-linux-s390x': 0.34.5 - '@img/sharp-linux-x64': 0.34.5 - '@img/sharp-linuxmusl-arm64': 0.34.5 - '@img/sharp-linuxmusl-x64': 0.34.5 - '@img/sharp-wasm32': 0.34.5 - '@img/sharp-win32-arm64': 0.34.5 - '@img/sharp-win32-ia32': 0.34.5 - '@img/sharp-win32-x64': 0.34.5 - optional: true - - source-map-js@1.2.1: {} - - styled-jsx@5.1.6(react@19.2.4): - dependencies: - client-only: 0.0.1 - react: 19.2.4 - - tailwindcss@4.2.0: {} - - tapable@2.3.0: {} - - tslib@2.8.1: {} - - tw-animate-css@1.3.3: {} - - typescript@5.7.3: {} - - undici-types@6.21.0: {} diff --git a/consumer-guide/postcss.config.mjs b/consumer-guide/postcss.config.mjs deleted file mode 100644 index a869506ee..000000000 --- a/consumer-guide/postcss.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -/** @type {import('postcss-load-config').Config} */ -const config = { - plugins: { - '@tailwindcss/postcss': {}, - }, -} - -export default config diff --git a/consumer-guide/scripts/validate-data.mjs b/consumer-guide/scripts/validate-data.mjs deleted file mode 100644 index 26e26543f..000000000 --- a/consumer-guide/scripts/validate-data.mjs +++ /dev/null @@ -1,52 +0,0 @@ -import assert from "node:assert/strict" -import { readFile } from "node:fs/promises" - -const load = async (name) => JSON.parse(await readFile(new URL(`../data/${name}`, import.meta.url), "utf8")) -const [quickstart, tuning] = await Promise.all([load("quickstart.json"), load("tuning.json")]) - -assert.match(tuning.source.fastvideoCommit, /^[0-9a-f]{40}$/) - -const backendIds = new Set(tuning.attentionBackends.map(({ id }) => id)) -const workloadIds = new Set(tuning.workloads.map(({ id }) => id)) -const modelIds = new Set() -for (const model of tuning.models) { - assert(!modelIds.has(model.id), `duplicate model: ${model.id}`) - modelIds.add(model.id) - assert(workloadIds.has(model.workload), `${model.id}: unknown workload ${model.workload}`) - - const { recipe } = model - for (const key of ["height", "width", "numFrames", "fps", "numInferenceSteps"]) { - assert(Number.isInteger(recipe[key]) && recipe[key] > 0, `${model.id}: invalid ${key}`) - } - if (model.workload === "game") { - assert(recipe.numFrames % 12 === 9, `${model.id}: Matrix frames must be 9 + 12k`) - } - assert(recipe.guidanceScale > 0, `${model.id}: guidance must be positive`) - assert(recipe.vsaSparsity >= 0 && recipe.vsaSparsity <= 1, `${model.id}: invalid VSA sparsity`) - if (recipe.dmdDenoisingSteps !== null) { - assert(recipe.dmdDenoisingSteps.length > 0 && - recipe.dmdDenoisingSteps.every((step) => Number.isInteger(step) && step > 0), - `${model.id}: invalid DMD schedule`) - } - assert(recipe.attentionBackends.length > 0, `${model.id}: no attention backend`) - assert(recipe.attentionBackends.includes(recipe.defaultAttentionBackend), `${model.id}: invalid default backend`) - for (const backend of recipe.attentionBackends) { - assert(backendIds.has(backend), `${model.id}: unknown backend ${backend}`) - } -} - -assert(modelIds.has(tuning.defaults.model_id), "unknown default model") -const profileKeys = new Set() -for (const profile of quickstart.profiles) { - assert(modelIds.has(profile.model), `quick-start profile uses unknown model: ${profile.model}`) - assert(tuning.models.find(({ id }) => id === profile.model).workload === profile.task, - `${profile.model}: quick-start task does not match recipe workload`) - const key = `${profile.task}:${profile.tier}` - assert(!profileKeys.has(key), `duplicate quick-start profile: ${key}`) - profileKeys.add(key) -} - -const unsupportedClaims = /"(?:generationSeconds|runtimeSeconds|timeSec|firstRunSec|vramMin|ramMin)"/ -assert(!unsupportedClaims.test(JSON.stringify({ quickstart, tuning })), "unproven performance claim in recipe data") - -console.log(`Validated ${tuning.models.length} recipes and ${quickstart.profiles.length} quick-start profiles.`) diff --git a/consumer-guide/tsconfig.json b/consumer-guide/tsconfig.json deleted file mode 100644 index 48d6d8209..000000000 --- a/consumer-guide/tsconfig.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "compilerOptions": { - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "allowJs": true, - "target": "ES6", - "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "react-jsx", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], - "paths": { - "@/*": [ - "./*" - ] - } - }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - ".next/types/**/*.ts", - ".next/dev/types/**/*.ts" - ], - "exclude": [ - "node_modules" - ] -} diff --git a/docs/README.md b/docs/README.md index f804502fb..134d9270e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,12 +2,6 @@ This directory contains the FastVideo documentation built with MkDocs. -The Quick Start and Advanced Tuning pages embed an interactive **config -generator** — a separate Next.js app documented in -[`consumer-guide/README.md`](../consumer-guide/README.md). It is built -independently and copied into the docs artifact under `config-generator/`. Its -asset URLs use the GitHub Pages base path reported by `actions/configure-pages`. - ## Build the docs locally ```bash @@ -31,29 +25,10 @@ mkdocs serve Then open your browser to: http://127.0.0.1:8000 -> **Note:** `mkdocs serve` only builds the docs. The embedded config generator -> is **not** built, so its iframe on the Quick Start / Advanced Tuning pages -> shows a 404. This is expected — use "Full local preview" below to see it. - -### Full local preview (docs + config generator) - -To preview exactly what gets deployed, replicate the CI build: +### Static build ```bash -# 1. Build the docs mkdocs build - -# 2. Build the config generator -cd consumer-guide -pnpm install -NEXT_BASE_PATH=/config-generator pnpm build -cd .. - -# 3. Copy it into the docs site -mkdir -p site/config-generator -cp -R consumer-guide/out/. site/config-generator/ - -# 4. Serve the merged site python -m http.server -d site/ ``` @@ -61,10 +36,7 @@ Then open your browser to: http://localhost:8000 ## Automatic Deployment -Documentation is automatically built and deployed to GitHub Pages when changes -are pushed to the `main` branch via the `.github/workflows/infra-docs.yml` -workflow. The same workflow also builds the config generator and copies it into -the deployed site. +Documentation is automatically built and deployed to GitHub Pages when changes are pushed to the `main` branch via the `.github/workflows/infra-docs.yml` workflow. ## Update documentation dependencies diff --git a/docs/assets/config-generator.js b/docs/assets/config-generator.js deleted file mode 100644 index 56aa62b7d..000000000 --- a/docs/assets/config-generator.js +++ /dev/null @@ -1,15 +0,0 @@ -(() => { - const resizeType = "fastvideo-config-generator:resize"; - - window.addEventListener("message", (event) => { - if (event.origin !== window.location.origin) return; - if (!event.data || typeof event.data !== "object" || event.data.type !== resizeType) return; - - const frame = Array.from(document.querySelectorAll("iframe[data-config-generator]")) - .find((candidate) => candidate.contentWindow === event.source); - const height = Number(event.data.height); - if (!frame || !Number.isFinite(height) || height < 320 || height > 20000) return; - - frame.style.height = `${Math.ceil(height)}px`; - }); -})(); diff --git a/docs/assets/cookbook-recipes.json b/docs/assets/cookbook-recipes.json new file mode 100644 index 000000000..eadeee535 --- /dev/null +++ b/docs/assets/cookbook-recipes.json @@ -0,0 +1,52 @@ +{ + "recipes": [ + { + "id": "fastwan21-t2v", + "task": "Text to video", + "label": "FastWan2.1 1.3B (distilled + VSA)", + "model": "FastVideo/FastWan2.1-T2V-1.3B-Diffusers", + "source": "scripts/inference/inference_wan_VSA_DMD_1_3B.yaml", + "command": "FASTVIDEO_ATTENTION_BACKEND=VIDEO_SPARSE_ATTN fastvideo generate --config scripts/inference/inference_wan_VSA_DMD_1_3B.yaml" + }, + { + "id": "wan22-t2v", + "task": "Text to video", + "label": "Wan2.2 A14B", + "model": "Wan-AI/Wan2.2-T2V-A14B-Diffusers", + "source": "examples/inference/basic/basic_wan2_2.py", + "command": "python examples/inference/basic/basic_wan2_2.py" + }, + { + "id": "wan21-i2v", + "task": "Image to video", + "label": "Wan2.1 14B 480P", + "model": "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers", + "source": "scripts/inference/inference_wan_i2v.yaml", + "command": "fastvideo generate --config scripts/inference/inference_wan_i2v.yaml" + }, + { + "id": "turbowan22-i2v", + "task": "Image to video", + "label": "TurboWan2.2 A14B", + "model": "loayrashid/TurboWan2.2-I2V-A14B-Diffusers", + "source": "examples/inference/basic/basic_turbodiffusion_i2v.py", + "command": "python examples/inference/basic/basic_turbodiffusion_i2v.py" + }, + { + "id": "wan22-ti2v", + "task": "Text or image to video", + "label": "Wan2.2 TI2V 5B", + "model": "Wan-AI/Wan2.2-TI2V-5B-Diffusers", + "source": "examples/inference/basic/basic_wan2_2_ti2v.py", + "command": "python examples/inference/basic/basic_wan2_2_ti2v.py" + }, + { + "id": "matrix-game-2", + "task": "Interactive world", + "label": "Matrix Game 2.0", + "model": "FastVideo/Matrix-Game-2.0-Base-Distilled-Diffusers", + "source": "examples/inference/basic/basic_matrixgame2.py", + "command": "python examples/inference/basic/basic_matrixgame2.py" + } + ] +} diff --git a/docs/assets/cookbook.js b/docs/assets/cookbook.js new file mode 100644 index 000000000..1b985bc4e --- /dev/null +++ b/docs/assets/cookbook.js @@ -0,0 +1,60 @@ +(() => { + let recipesPromise; + + const loadRecipes = (url) => { + recipesPromise ||= fetch(url).then((response) => { + if (!response.ok) throw new Error(`HTTP ${response.status}`); + return response.json(); + }); + return recipesPromise; + }; + + const init = () => { + document.querySelectorAll("[data-cookbook]").forEach(async (root) => { + if (root.dataset.initialized) return; + root.dataset.initialized = "true"; + + const select = root.querySelector("[data-cookbook-recipe]"); + const model = root.querySelector("[data-cookbook-model]"); + const source = root.querySelector("[data-cookbook-source]"); + const command = root.querySelector("[data-cookbook-command]"); + const status = root.querySelector("[data-cookbook-status]"); + + try { + const { recipes } = await loadRecipes(root.dataset.recipes); + const byId = new Map(recipes.map((recipe) => [recipe.id, recipe])); + const groups = new Map(); + + select.replaceChildren(); + recipes.forEach((recipe) => { + if (!groups.has(recipe.task)) { + const group = document.createElement("optgroup"); + group.label = recipe.task; + groups.set(recipe.task, group); + select.append(group); + } + groups.get(recipe.task).append(new Option(recipe.label, recipe.id)); + }); + + const render = () => { + const recipe = byId.get(select.value); + model.textContent = recipe.model; + source.textContent = recipe.source; + source.href = `https://github.com/hao-ai-lab/FastVideo/blob/main/${recipe.source}`; + command.textContent = recipe.command; + status.textContent = `${recipe.label} selected.`; + }; + + select.addEventListener("change", render); + select.disabled = false; + render(); + } catch (error) { + status.textContent = "Recipes could not be loaded. Use the examples link below."; + console.error("Failed to load FastVideo cookbook recipes", error); + } + }); + }; + + if (window.document$) window.document$.subscribe(init); + else document.addEventListener("DOMContentLoaded", init); +})(); diff --git a/docs/assets/custom.css b/docs/assets/custom.css index 6c9b5ad8b..b87ef67c8 100644 --- a/docs/assets/custom.css +++ b/docs/assets/custom.css @@ -42,55 +42,44 @@ img { margin: 0 auto; } -/* ===== Advanced Tuning Guide (standalone, full-bleed page) ===== */ -.md-content__inner:has(.adv-tuning-guide-wrap) > h1 { - display: none; +.cookbook-picker { + padding: 1rem; + border: 0.05rem solid var(--md-default-fg-color--lightest); + border-radius: 0.2rem; } -.md-content:has(.adv-tuning-guide-wrap) ~ .md-sidebar--secondary { - display: none; +.cookbook-picker select { + width: 100%; + padding: 0.6rem; + color: var(--md-default-fg-color); + background: var(--md-default-bg-color); + border: 0.05rem solid var(--md-default-fg-color--lighter); + border-radius: 0.2rem; } -.md-content:has(.adv-tuning-guide-wrap) { - max-width: none; +.cookbook-picker dl { + display: grid; + grid-template-columns: max-content 1fr; + gap: 0.25rem 1rem; } -.md-content__inner:has(.adv-tuning-guide-wrap) { - max-width: none; - margin: 0; - padding: 0; +.cookbook-picker dt { + font-weight: 700; } -.adv-tuning-guide-wrap { - width: 100%; - max-width: none; - overflow: hidden; - background: #fff; - margin-right: 0; +.cookbook-picker dd { + margin: 0; + min-width: 0; + overflow-wrap: anywhere; } -.adv-tuning-guide-frame { - width: 100%; - height: 1250px; /* fallback before postMessage adjusts to actual content height */ - border: 0; - display: block; - background: #fff; -} - -/* ===== Quick Start embedded guide ===== */ -.quick-start-guide-wrap { - width: 100%; - max-width: 100%; - overflow: hidden; - background: #fff; -} - -.quick-start-guide-frame { - width: 100%; - height: 1205px; /* fallback before postMessage adjusts to actual content height */ - border: 0; - display: block; - background: #fff; +.cookbook-picker__status { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; } .md-typeset .copy-page-button.md-button { diff --git a/docs/cookbook/index.md b/docs/cookbook/index.md new file mode 100644 index 000000000..b5d408f6c --- /dev/null +++ b/docs/cookbook/index.md @@ -0,0 +1,44 @@ +# Inference Cookbook + +Choose a complete recipe maintained in the FastVideo repository. Each command +runs its checked-in source directly, so coupled model, GPU, offload, and +attention settings do not drift into unsupported combinations. + +The commands expect a local clone: + +```bash +git clone https://github.com/hao-ai-lab/FastVideo.git +cd FastVideo +``` + +
+ + +
+
Model
+
Loading…
+
Source
+
Browse maintained examples
+
+
Loading…
+

+ +
+ +## Customize a recipe + +Start from the checked-in source, then change only the settings your model +supports: + +- [Configuration](../inference/configuration.md) covers the Python and CLI + config surfaces. +- [Optimizations](../inference/optimizations.md) covers attention backends, + compilation, and memory tradeoffs. +- [Support matrix](../inference/support_matrix.md) lists supported models and + optimizations. diff --git a/docs/generate_examples.py b/docs/generate_examples.py index 6a57397a7..1e85d5d4a 100644 --- a/docs/generate_examples.py +++ b/docs/generate_examples.py @@ -2,6 +2,7 @@ # adapted from vllm: https://github.com/vllm-project/vllm/blob/v0.7.3/docs/source/generate_examples.py import itertools +import json import os import re from dataclasses import dataclass, field @@ -19,6 +20,40 @@ GENERATED_DOC_PREFIXES = ( "training/examples/", "distillation/examples/", ) +COOKBOOK_DATA = ROOT_DIR / "docs/assets/cookbook-recipes.json" +COOKBOOK_SOURCE_ROOTS = ( + ROOT_DIR / "examples/inference", + ROOT_DIR / "scripts/inference", +) + + +def validate_cookbook() -> None: + """Keep cookbook entries tied to checked-in runnable sources.""" + recipes = json.loads(COOKBOOK_DATA.read_text(encoding="utf-8")).get("recipes") + if not isinstance(recipes, list) or not recipes: + raise ValueError(f"{COOKBOOK_DATA}: recipes must be a non-empty list") + + seen: set[str] = set() + for recipe in recipes: + required = ("id", "task", "label", "model", "source", "command") + missing = {key for key in required if not recipe.get(key)} + if missing: + raise ValueError(f"Cookbook recipe is missing: {', '.join(sorted(missing))}") + if recipe["id"] in seen: + raise ValueError(f"Duplicate cookbook recipe id: {recipe['id']}") + seen.add(recipe["id"]) + + source = (ROOT_DIR / recipe["source"]).resolve() + if not any(source.is_relative_to(root.resolve()) for root in COOKBOOK_SOURCE_ROOTS): + raise ValueError(f"Cookbook source is outside an approved directory: {recipe['source']}") + if not source.is_file(): + raise ValueError(f"Cookbook source does not exist: {recipe['source']}") + + source_text = source.read_text(encoding="utf-8") + if recipe["model"] not in source_text: + raise ValueError(f"Cookbook model is not present in {recipe['source']}: {recipe['model']}") + if recipe["source"] not in recipe["command"]: + raise ValueError(f"Cookbook command does not invoke its source: {recipe['id']}") def fix_case(text: str) -> str: @@ -536,6 +571,7 @@ def on_pre_build(config, **kwargs): MkDocs hook to generate examples before building the documentation. This function is called automatically by MkDocs' native hook system. """ + validate_cookbook() print("Generating example documentation...") generate_examples(generate_main_index=True) print("Example documentation generated successfully!") @@ -549,6 +585,7 @@ def on_page_context(context, page, **kwargs): if __name__ == "__main__": + validate_cookbook() print("Generating example documentation...") generate_examples(generate_main_index=True) print("Example documentation generated successfully!") diff --git a/docs/getting_started/advanced_tuning_guide.md b/docs/getting_started/advanced_tuning_guide.md deleted file mode 100644 index 1f5ecd7b2..000000000 --- a/docs/getting_started/advanced_tuning_guide.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -hide: -- toc ---- - -
- -
diff --git a/docs/getting_started/installation.md b/docs/getting_started/installation.md index 4464afa47..6d5c29639 100644 --- a/docs/getting_started/installation.md +++ b/docs/getting_started/installation.md @@ -65,8 +65,7 @@ uv pip install flash-attn --no-build-isolation -v ## Next Steps -Now that FastVideo is installed, head to the [Quick Start](quick_start.md) to generate your first video. - -!!! tip "Not sure which command to run?" - - The [Quick Start](quick_start.md) page has an interactive Config Generator. Select your task, maintained model profile, and GPU count to get a ready-to-copy `fastvideo generate` command. - - For fine-grained control over all parameters, use the [Advanced Tuning Guide](advanced_tuning_guide.md). +- [Quick Start](quick_start.md) - Generate your first video +- [Inference Cookbook](../cookbook/index.md) - Choose a maintained recipe +- [Configuration](../inference/configuration.md) - Learn about configuration options +- [Examples](../inference/examples/examples_inference_index.md) - Explore scripts and notebooks diff --git a/docs/getting_started/quick_start.md b/docs/getting_started/quick_start.md index bdc22e2bc..34701f3c8 100644 --- a/docs/getting_started/quick_start.md +++ b/docs/getting_started/quick_start.md @@ -23,26 +23,21 @@ Also optionally install flash-attn: uv pip install flash-attn --no-build-isolation -v ``` -## ⚡ Generate Your Command +## Choose a maintained recipe -Select your task, model profile, and GPU count to get a ready-to-run command: +The cookbook selects complete, checked-in recipes instead of mixing model, +parallelism, offload, and attention settings independently. -
- -
+[Open the inference cookbook](../cookbook/index.md){ .md-button .md-button--primary } !!! tip "Need more control?" - Use the [Advanced Tuning Guide](advanced_tuning_guide.md) to tune all parameters — resolution, attention backend, memory offloading, and more. + Start from a maintained recipe, then use the + [configuration](../inference/configuration.md) and + [optimization](../inference/optimizations.md) guides for supported changes. ## Next Steps -- [Advanced Tuning Guide](advanced_tuning_guide.md) - Fine-grained parameter tuning +- [Inference Cookbook](../cookbook/index.md) - Choose a maintained recipe - [Installation Guide](installation.md) - Detailed installation instructions - [Configuration](../inference/configuration.md) - Learn about configuration options - [Examples](../inference/examples/examples_inference_index.md) - Explore more diff --git a/mkdocs.yml b/mkdocs.yml index 70db2fd8b..02956aab3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -78,7 +78,7 @@ plugins: minify_js: true minify_css: true cache_safe: true - js_files: [assets/copy-page.js, assets/config-generator.js] + js_files: [assets/copy-page.js, assets/cookbook.js] css_files: [assets/custom.css] - api-autonav: modules: ["fastvideo"] @@ -153,7 +153,7 @@ nav: - Installation: getting_started/installation.md - Quick Start: getting_started/quick_start.md - V1 API: getting_started/v1_api.md - - Advanced Tuning Guide: getting_started/advanced_tuning_guide.md + - Cookbook: cookbook/index.md - Inference: - Quick Start: inference/inference_quick_start.md - Configuration: inference/configuration.md @@ -238,4 +238,4 @@ extra_css: # Custom JavaScript extra_javascript: - assets/copy-page.js - - assets/config-generator.js + - assets/cookbook.js