From 25940a7e869e2a7b5c3c77df4200caed36b27701 Mon Sep 17 00:00:00 2001 From: Aryan Kumar <156166681+aryan5v@users.noreply.github.com> Date: Fri, 16 Oct 2026 17:26:51 -0700 Subject: [PATCH] [docs] Unify cookbook model editors and launch commands (#1970) Co-authored-by: Aryan Kumar --- .../components/cookbook/HardwarePicker.tsx | 9 +- .../components/cookbook/ModelRelease.tsx | 43 -- .../cookbook/minimax-h3/fasth3-trim.mdx | 7 + docs-site/cookbook-components-preview.png | Bin 53259 -> 124121 bytes docs-site/islands/Cookbook.tsx | 227 +++++-- docs-site/islands/SourceRecipe.tsx | 560 ++++++++++++++---- docs-site/lib/cookbook-commands.ts | 71 +++ docs-site/lib/cookbook-pages.ts | 41 +- docs-site/lib/cookbook.ts | 11 + docs-site/navigation.json | 4 + docs-site/package.json | 2 +- docs-site/scripts/prepare-content.mjs | 3 + docs-site/scripts/prepare-python-docs.py | 85 +++ docs-site/tests/commands.test.mjs | 100 ++++ docs-site/tests/cookbook.spec.ts | 118 +++- docs-site/tests/test_python_reference.py | 19 + docs-site/theme.css | 24 + docs/assets/cookbook-recipes.json | 27 +- docs/contributing/cookbook_configuration.md | 26 +- docs/cookbook/design.md | 8 +- docs/cookbook/recipes/fasth3-trim.yaml | 51 ++ docs/js/cookbook-config.mjs | 7 +- docs/tests/cookbook-config.test.mjs | 9 + .../serving/openai_fasth3_trim_spark.yaml | 55 ++ 24 files changed, 1274 insertions(+), 233 deletions(-) delete mode 100644 docs-site/components/cookbook/ModelRelease.tsx create mode 100644 docs-site/content/cookbook/minimax-h3/fasth3-trim.mdx create mode 100644 docs-site/lib/cookbook-commands.ts create mode 100644 docs-site/tests/commands.test.mjs create mode 100644 docs/cookbook/recipes/fasth3-trim.yaml create mode 100644 examples/serving/openai_fasth3_trim_spark.yaml diff --git a/docs-site/components/cookbook/HardwarePicker.tsx b/docs-site/components/cookbook/HardwarePicker.tsx index 927fc2b84..e012d0489 100644 --- a/docs-site/components/cookbook/HardwarePicker.tsx +++ b/docs-site/components/cookbook/HardwarePicker.tsx @@ -1,4 +1,4 @@ -import { useId, useState } from "react"; +import { useEffect, useId, useState } from "react"; import { Input } from "@/components/ui/input"; export default function HardwarePicker({ @@ -14,10 +14,11 @@ export default function HardwarePicker({ }) { const [search, setSearch] = useState(""); const [adding, setAdding] = useState(false); - const [custom, setCustom] = useState(() => { + const [custom, setCustom] = useState(""); + useEffect(() => { const requested = new URL(window.location.href).searchParams.get("hardware"); - return requested?.startsWith("custom:") ? requested.slice(7) : ""; - }); + setCustom(requested?.startsWith("custom:") ? requested.slice(7) : ""); + }, []); const id = useId(); const known = options.filter((option) => option.join(" ").toLowerCase().includes(search.toLowerCase())); function add() { diff --git a/docs-site/components/cookbook/ModelRelease.tsx b/docs-site/components/cookbook/ModelRelease.tsx deleted file mode 100644 index 63299bb2e..000000000 --- a/docs-site/components/cookbook/ModelRelease.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import ModelHeader from "./ModelHeader"; -import ComponentPlan from "./ComponentPlan"; -import { sitePath, type DirectoryModel } from "@/lib/cookbook-pages"; - -export default function ModelRelease({ model }: { model: DirectoryModel }) { - return ( -
- -
-

FastH3 Trim is the smaller FastH3 model, previously called CompactH3.

-

A maintained serving recipe is being prepared. Use the published checkpoint instructions for setup.

-
-
-
-

Weights

-
-
- {[ - ["BF16", "FastVideo-FastH3-Trim-8-Step"], - ["FP8", "FastVideo-FastH3-Trim-8-Step-FP8"], - ["NVFP4", "FastVideo-FastH3-Trim-8-Step-NVFP4"], - ].map(([name, repo]) => ( - - {name} ↗ - - ))} -
-
-
-
-

Components

-
- -
-
-
-
- FastH3 checkpoint guide → - Release collection ↗ -
-
- ); -} diff --git a/docs-site/content/cookbook/minimax-h3/fasth3-trim.mdx b/docs-site/content/cookbook/minimax-h3/fasth3-trim.mdx new file mode 100644 index 000000000..41be59320 --- /dev/null +++ b/docs-site/content/cookbook/minimax-h3/fasth3-trim.mdx @@ -0,0 +1,7 @@ +--- +title: FastH3 Trim +description: Configure FastH3 Trim NVFP4 and copy inference or serving commands. +mode: frame +--- + + diff --git a/docs-site/cookbook-components-preview.png b/docs-site/cookbook-components-preview.png index a687792a79e5cec226431ec282a5ff2f52bfae78..e68d07b781102e10c3d4eac830e73b72d1b54f44 100644 GIT binary patch literal 124121 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 z zuR97tiDz$fXvrRL!JA~~GHhm=X;BwCl*=DWDxSXQuq$$%)c8bX)MWX&TI;xL{G5)* zOgHO(s6b!^eYNxHB2o~gv*(;U7V=VN=72b-$>E`?GI*WUcI+HGG-o9-G4!)qU0a*g z_71Yhw44&pG_xxh`}Qqvm4-$gAt!R&Qu^xgt>=x6BAqQg4t~qIo-4zw&ubow{ z2QfKOC2O(SuR3lHq;w(UI|+Y9rhTTohVv4Jk>f=s!7lRrUuL7@=eU@eOb<6DYiCWi zgnG*?RKxzT95Oqftma9`*9c*4#*^EteHZkyn|GUi>ou!WuF# z1evQ2-QqOItwBMbtIe*VD@Gl)9LDZzE}nUzq?9qXRKRKHqv?_NebARS+8xb5nd;$u zuh6*G&%uDUjspx9v03i@|7h*IQQg5kja- zv}EtBXo`vu?lMbDWfU4lDIuNbr@r_3opT=N{Bs^ZkNcmyyBpW%^B%9)bG;&9U<_d! zM?vfVqK@qi_{YxXo^?3~Vi=au|E}fEr@ z<|h{}HqZ^A0p=4Kv)jy<+6KW8Qt?f;)(!UiTh@WhMWd2`GW6{|`XjWC@@m!rJ~!`C z*OQ`zvKNGVnmaDD6T~neTHo7M(w@9^gRzsXW3@t}Vq!W7IYKX$YZ>X88yDrN>f9(P zfYE|mi`*J`upiKADZgOHdfgE+Rgabs(mL1UAJ!B7+5BR8a zFMOF^ZO7^80B&c4-_hT%5BIseiHj^7`VpUc`&C9^=<3TmbDv*cj^m^~_wsP-U_Ejz z?@O_h0nO8_C6{KUG@TUl!}+eWoSNDWXN9XwO4t5rZ=tPj_&i7wzdSX_J7_i`d1kfW zl+V%U5iQTsY>tZw4o?ot!`RvRz-<5fY}VLH>mw)RY&x26qy?;4v0|n?`P-d{-^)L| z{0jg8_|trQRHkQUPyi&iSHrlo{l7?--r~yQ=m2)z!zh;ulPf6stx#&tY@|)rJPi&3 z3O{{AFJc+2SSVVod1YF(hNso|1IYWuVEeC%G`+na^))xBmpr#TX!0ZiE`c4PVA?x$97QXh-SHqv59qb)6Iy8 z@JqRP>-_&p(`0%a`JXgR-@<{9z&xHZer;KRgEj(jF_S?C#rp~T9d^{WW4?ddcMFeJ z+3qPJ#MO;28fnjke|^uT)n&eiQT;DPqq$D5ii?ZuGTLpBJ;0NCudFH*KC_5E)&pZ{Fa`6Ft^AANbqu0i}aLS1VA$MkIR z3}z=BGt4Y3O&I2;tGkPr;)_nu&)wbK&kq&;faLMiO@BSky*{|_0Yd}^29`V2D zo$w#nQgAIVFApw3WPt!ce~H=@U2ejqlmCGdo&h)m-3U%xK4Cnpd(&uM^iUoF73=8S z0xLl>Cv>y;D#*89G+j7K(52s^08l}AIr90lYJlK>ezqxqe*A3r1%(A~Jb7f0P@(^7 z*ZCLf2swWIDV*xOJ*y4{2I4X<`mg^4OE6efcG3dlJpa3L`2cQ0+>NgzJt*nGU^DTB zF+fiZ^?Q2YUjul$+Nsm0->*zf(C2G3(fRoFxgO(%zaY>5-TAG@0@>X7Sv`a!K^zO; z1cgG0u4RD{d)u~7JdT^UZ$q}1_xsOx4{HF_@a_$|IQSXA`szMs(Un7eF$YEd+qW)I zYeF1W@PNRd6ZCu0IsDVr1)tCOr%zqqE?#vBbje@q+uz>O!gz5DFNIrBN@@r}W}m#E z^jVcq7fU?#argO!1!$V>s+{&(ueZ-PqYtYO*FO+JOI{xy!ouFuHa$B# z{IgJpVf|SE5i)s~TAQ2QQ8k=Ac`{l*39diFFFtzgkF{M|4wA58gX)7w%K{Lbp|*Dyujf7B`>@TU%k=T|RQU7l&gGwy z={UN&+~qCg&L#SJV=4jll85+I{!dTY?t0H&CJ=k(SDxZ8;&Z9~S+^E9Jhw8<;~_%# zkl9?4%_F|nBJ=`SlDyr+XqXI^remUvxJ!1~u8*?n1VW4$?I=z?-+uDbDB^$%I0u@F z9g{DC6LDM}+g?hC4RvnG3WapbDndy({Wc260Z@F#o_Hvv^;*7lM*fQh1XpKg4}p#O z>*y?O{pX*n-~>oFI%&SXkT!woK6gJ6?g}?Ix3y+&oUNVjMn^}n@{luHhv!a&l&*Bh zK5t3m1JVwO`n({VvK*uZGTz0u-;V=fJQ?@0`Tp`$Nl6LSUywEl-)6!5d@xS1T#0E# z(Xs>{LS77t_1z{yi}6jic3ILz{w2J+05r+&3=9k;IXO)yeOz1(RaO4bA#(_=?nka4 z#PY4LFV@oFhsdi;@NPG6_jZ5*v@HcqL7MLMBh8=g=!1gjqsuHIW*4v4x3G#)9SL6b20;tO>9enWup!))* zTG~bsqGcoP!yp)DvSIh@X=`JVgMEGa5bDB!3jl;5-9s9&k^5s9aCai;YI+w7OFX<% z>pgj9S?;g53qOFjedPW=u6yGzc8^w0JheBgeVZO!Dq@-or7|H=@AB1 z1@WWS-8$a^_OKyu1GYR)zz-47vh=Bs?E#T~3zsAo7d+!IP{e5_*gT_Z=2p5S#9rQlF6J|W!v^cPobBU(Su?Jez=+$$4t!aAP6>Q zu8({+R=)>!er99BBi@79=&72MU%!3*`VmqcuecwfSU0Gl_f)$?;iSpqT&xhG8DD!3 zLdr&p^w03lH}~$n1^Q@S?gv5M_#?1SstA4ye;YUX_5+I4ymTt?)!)1Ku82X6sR{$t zRdPuE!Mq~`xaTQ6#F7=Dh6-e-P)jZ$KUG6HxLje=2m{GI)Wy)??xZEa*q!KB)m0-t zee~WdjYzuWN$Ce`8Wl^`SouCe(tt+@qlb#3VaRvDfeE`U9(KG+yV4_MfqbfAr2k1{QY40d+5_l&CK3^ zTf7U=(OaGtx@C{0v|R2bMB?Y{061*3^r*I&4ucaSZ;XS=nlIceCjI)@yvS=t@Rbm) z7qlJ_h4!(exH#T&zmJa(*r%oB)tg#7ciZRe7JJFiBc7DD>TvG&)7gA2UJXBq!r>{) zOO7xyx#>5AN?_n^-X}}>?hlfalUw>U`SBxcA9;JWF48+pj6UtQR~RTpF|&x6ciAs_ z49V*+1=t8M+YH5bJbJ`t@G_db0yR55?PSvl*166^5hj+Wa>S} z@vVE6DfbFrsY8)-DV8h&JaT04enEiJ+izeO3*5fBkizAjx;5Yqy>{)|85h26P39F@ zwFGf5FC6ttr&W$?*tu|0dDXqFSN)xdPRvWaxmu}o$q}n8FBIs-IdAfGcWuV42F1m$ z@ssybeV{yD`##1p@>SCODYogVPn~pvX}IEl09VV=4#D*_ZbB$-7i6X-bP=rx5;gx! za-$awcV0dvTpbDWlb;70J1%K%ZupS!iV!%_?s(?!X2)X~z>P9)K%UG?5aH!L1nLsU z)ZHI>=2-HZnVtYj(o`B?Lqc@w1AhmHLEN^=)Dmmrq;F}Vio_mDiY!~+<*_T5{q9ye zZg%zuG;q@_y@F0jw-t_GHcORCNlWH0oHd3+E#$U(t9x!ou(Gmp7yUb~qwZsROgfP> zBoU)pg4rI@74(@YeiX!S&6&v(h4TvG^+TeDW7lz7pwff8C#>VAC`88liC`8ycG+5p zDaAHDNa!{`s-Ldc+R@X)XX;Y$9N2!|_aswyzHxhk%dXYJB{8{EWpfjA*$*g@ho6%Q z{JPgRTMg^FwRgM}~(H$@Zp%A{ToeNJD`x z7kdM%F&Y^R*ic|k?NCUtRfEmQW_EZxd%ypTx?6@8^WAe0khkwGu_IM;N$C-z{DjL& zl4tX^!~&|4LoNCzAK9B3(V{h_JsU!E`S}7_`X8m6QrOG|=p!yv#ILATo4i}{bYXE3 zOv6c7)dElzR10~$iDf>bxr7NOxUcaX7P0Qj_b8MDdh4J&t{_E>Fie}q^hjbF+;bw^ z#eqeKe(1p5x1=B`(-Gs<(H3nvC)5aaf6uCWnXJwVe=A#0XWSi^2?3;%E%LD!AvXE8 z3K?m9{GV{L!=1hcSN>f2M`df0KJ32e?7;k0hMzX{zWXDVIu_q?BZm3)wKSdTesK-PDFEQBPRnuM~;1JZ9{8lcT?nNWvc&C zP&w9X&t=XEmr0P@=|h>jm7^M&1%G08O5~+vuH5kMdS>c9jon9%brJo}geaT|)SwI# z+TnR2TZ3Z7MRz(yQpXp_4`OdCcO0469z%!zgMWLBlS9aaOM&AI8^>xKjL6>dby=qP3Rz__3X# zQd6VZihaH^idU%yh@i#e64RthJQV2~h;%AvzgTw&k+30~(9;_j80=Rsa7K=wpo^uY zCG=|{u#LmY_A?s;xOv87?wyDZsMLCb{-0z3w+3_JJOH4)t?E^}%)x}~6B?o1lTDtT z!g6x?peAK@5E`rl5mT~b4g%jca*D4V2Tc-fu@7ytwr{^h_8lV=X+ru362@rJXjJm} zWK)F+?b`fb+f|27=&vP?7atmu&NlrhGC>cWa7amAW(i0kV*{Y%azHqg*a zW9;fN#(VZ&iv6y4{M$HKCe**Ys8-X$d)ihn-ZY>Ra?2h&^o8UT$EQ?7`feN8mQ841 zof$WHY&7wsFRa6LX!1skeQ|nt+@zqnk;w%7eu4{A0Amo;GOb`d#b3o?NfSQe8jtQS zJ|0?Yv3lo_l+;UcMAt~(hvIX0S!S|g9;Y!|IVfOM#|VM|1tZ2C;zk(1jV9TwykSixUI{>E~eLWF@}-8v@Y^htUT_>pQ~tI&TO){vU62 zLV{KlO02w3#JDBU!{yew3@10~>ESBJaHz<4@FcMOUhmT@fB6|Ujvv;y&n5{Gkq;9S z6Yt-jdu)qsge$9!$6zUK70==pgI+KnP}d)DnQnUX9JLiV+j&5k$hbLs`SMDe!!R8; zf>1)614J337a;9& z&4?xzx2!T;K-z)vf|Zzr1R;-}_>uo}eqQF+@TN;ZA0deBxfpp{t##vu4RA{yhAjpv z3f%4<#>Nj|&ntQHN<^~ZHVlK>3GBJKb}Z4@UUeh<#31|XO1knOQ!f$2JBH+4 zCUZFV>{)^3*XUZ&7Q@aw2*_*u_fGXDms-4FP?6Nf^mDC96`Y%TBdv1`OgnPxvvTl6 zO0-GdgkKm4P8%t$PlKS!utv(4`%!PFznSjGF#sFb0WYtoXo7G`A_>LK5)AP?+ASa& zuA7(&4c` z1W5krvQ>pUiIs<^tsSSV%q`qj2XT-@+r(sZgnU;Y{sN6(jj6S&`Gh`HpU@WZXhuPx z)>_iUzL!6^d`x4=RZozB-t5lX(VNLl;JP30TJGNFm=`3eaGH7rhAYqQ+mqWx>olB} zSibfLuZIt2jC*YO60}5Mx_@IAjBc(|q>N);?5TM}1os4Ag-4T_aaXKUfvx-?mWjJV zcEks=%fDCvU9xxuB+!?bl{k3fR;w$iw{Y{S-~VEf9kdIP{7?Y7v&>;>LgGh0>-y#< z`iJDU7T9Y`zf@+(usD?HDchZXC-z{%u-5bg6EjX6ZMbbgmN`zCJ~2hGCV<0bl*sKL z&zEi<*r_8a{#tVDI>ORgXS(>0NI!2lHVqy;G}MGn18oQlp%@Q@_P(I7sGd? zf#U8XUuS3e#bVA4L+%@He}2PZ(hKPlD*5gNbTLr6WNeWrkJoXpKXBl{%ru%W_)Z|+ zIu~CamPX)5*Bio^_0-j8ID_7hUcOOfPtZjdeqS| zNqAd=kvA7RfUN>_j_U-aur47?W@`(pJL|w~k-1X&=`0=LD0&rcj*P`E$E)zcq3*Lf z_F`DXJp0yFefsd@Hs57(>JXLSxs;HTDV*_>w)-4Dwto6|o+vz4?eK>56WH2GSEkWx z!jOCrPNLvRyddxWN-Ps$%mm6($nZ}1b1ER0T(((sOt}eB$62Fm^m;id&-?q2Krb+> zfUpq+rH7*JYKiwl!+`uC8>!6}jtcVfjA3FH+|gtf<8P*7)>>?=2aBG~-Mr0bPeRn7)_Drg9tpcjkiml$I@H8ysERy?X2 z5?dB|3*8AoP`PmT+=>M+YrMFc8bBm8bEc`{SBFY&V9bb!{|2*Tn6@`!2W^%b(Nr61 z8li6KPM1v>zh)Sefg+{dW_%w+E0BaC=Ii{oI;YAO^&o6M>}f^m*0wfyMuh*_z_=qK zB4TOO{de>k74ZYakP-OUQI2R5>A}DkT^4Y}Io&)&lSA+8%l3QC@2Lwp!)gjt&jd0g8(M&%Z7KOgO*k$e}} z(a&xtqudo-Cb_;$d8P5(Cv?ugT9p@2i%LlF1}^lCf+s*sr@(E9LMiJ#gr#Je&W~+$ zzUn1x`IRTlJAHo&Dxg`; z-AmJQzuf2^^*w)n3s@28BShMK_ge+G>dxrw3#V`rs&=gva^i*)L_kK zcfN#LFu*3?9#%mA5o-~GuJT8vD5 zKJtF<5=x|s%I@UmTXhxf>!#Zh!s<>Hm+Z}HelFT)?tfEWWpC9q-1Ie=eq>$kIkN>O zm4uK_Bca|4LS^Ta-yFz$(hS6oUbK*--)Hpd+wK)vlQi^S;Zq@@S6GEEV~o>|P{FnK z5Cq1A{{|hK9tPzyynW#qqBh{*Nz1~@pPV(*en$w+h zQnwm8Hr6Yj1tHMuQ_N^jPeKxFyw-ZTdPrOZOQ4&GU5F5kIrb2P5@O3#l3nxyMlIy`38qPJIxZ+I zY!5LW?NI-n8ld|%SP{sS@z_s0cKg`pQ_Q32cN-Tb%W;jnuhf8et|-@Vcx)^#ojiJQ zu$o?I@7m-HEzU`WEH?WUDIXvQ@!lgxmn2~juE(5h5OI27^P-~@V|s#3Z#a{vE5Dd% z2w~>6xJq<7&eSqnx70w$(Qt6SOFA`mt>J^bgM$M(ig%sOr!&+UlE3o?B7ExnaYG z0)cB2eXe~uTT`W(kIWG14|%_-a7)3dff7|+S!StFS>mZ{Z zrY-gOo#0e7F1PZj&D*15bvY>|#Wd9P7xUfE!9PJV3}gX|hK z&QtgfYpOi)O>fi4Kb%A_KMGz#=~=|yyT{kDZ%gPX`7_^iAW)RAr>Dg1-g_pF#NKqr z56m(zG60}~aUiA^U}E2BPt)Ym(ozu?FywWy9gUAtGfQa01Dg->T|NeVt;p{w@l(HlXc&)umo=U-ktBByjcGI|B6d>hg=dRz?2cftKkDwG87X$a;^7s_x5+11!kw0GAv<9E-7 zhNQ-xqazqr=$PNR8l8ptyAK#1agYDaiC-%lBzr_YM%u9Nx@COy1Vw&dojm12IF2w} z=eF5~@%C!H{)0^6UAg010Z0onPw{G8F z{Vd6*X(g#~AS+exy$|oIyq+7I38%c@GzDBx=d;W5#Y$> z{UY~^jTsYHCya#o_fNLQ1Z?a=RZ`rb?p4c9s#ypdq0KVyiWJjZa%kK$@;(r5qF1qH zn_?m;73Usipg!>1b4{FU1iwwbq3Xr_h1F>H^2gXUZ2YLye)QMf9C1@+NC8D%pDy)v ztaBCh!!I{I2G#H4gBNqOIRr+wo#tLYHtmu-ner0t1!_tM2T><%#KWQQ1~Q|wRRN6P zYLV)myD=rzRAQ5}T;x~XZj^}o$Gkpeu?xK)T@I#3^RtoDWFu~1Eb6cI- zcm0Z+7wG1@iQ&8HMvB(+EU@Mzt3xvqI7fuzG-ngM1tt`$7 zlEzS=4uogP7|eiXX4Z^5LPoEpq;M&2mSssXoJ*>PgI3^xamZC$$Lkp&f@jVU&=%Jj zV1MMpA_{p#DW@2m+qx?^H2S)xc(3>R#rgU6xLvz;xmm(mj_khZnaOACOkR(Jet}LP zKfpa5J&`XpHNhhHSCR{tn3e~ME`0J9ZAqPKAcuh8GOV!k{n1JR%Yo>Gq46G8Su>q( zi3XSM5KSlNcydYdjt#jlm;g{%xbv~r;G{+@-3Z{)j*pYmMAS#wUFP>h?0X1D zAy4$qtI$vr)|cep!%6DX#gArCn>EjabaP8hJawewqVl&-&jke39jfUTtB`u&W<{%I zN!OAn`vNXvB#cl3kP8V6`Is*1>AF>*obhk*7r4qAMRlNFVcY@gA*9N3ts4Sx_(etM z;mf-2-NVpK6hX#j6&cq8jvl>i5TUO{P)$8VTFYAGN4!mMJ4z^R&XsGNzj=GV`tl`yr-KC~EyrEvj`@{IX;&U^CH;b} zz%6rif)@SMic2HjGy3;vV_E^yE**-&(r;gxB>kX2H+uByT4Oo0JhtMY)@?TFEVB72 zW#P%14^(|s#{;cGdf)uEpC8*sHPTS-KMNpv0f1{>uiWxRn(o!Frv@at*ac5$p4oXe zcaIFhcwSV|Z5vc7IO-=oryi)gk}8&1f8}a~GSuC+DPJZzsekBC&us}gN*8IOrIdHp zO|151`vyswMcbPW0i*z$ASa9UMN@ZnDst8d)1|EUL}7523-SbUuQfR9Qf1Xo_;NJg1lem`uE~hza0@y8)%CrlV&B zdM|WS(E&`KjO&kvjbIBR%q8KKABubQ9YQAGej}%lv=Ew{!Z|W5uswOruMVbfVuI>U zOE_7;h)36I?=J%0&fXz3JR*SPnim8!fPDw+gl2^?vSjpuJIo$CP2&($vSG|9!4GEd zXsyJIys5poBLQ;Fu(A2MoCp8dgE zxS!$T3JJmy3-JerkMq)$T|S5jt#set662jPJ~D#)Hn8)C_tpoaFBc=h`A>HIx0=7d0jT!f5+5TojY2Gw zLsIMZ4~nikKfy4{vWzpBdey1A11-edrMVq|rRo zP*X>C@oul&Oj?kCm566>@aNa_A0Fi+ZRjS_hLHF}i$h>mp(46){){(SqQH_qtzqKp zDMs2Zse|FYmltyGtDNHE8o9MK*K28XYinusemERvVzL^o%VF}OqCChKKh;3?8pEOB;CYS;1d4bwnDZm@`tYT5_WO!MxQM{5=%ZtX z6de#hk)sQ}-We;%3BO`-PBbk6q{pdZIai7bDdr`w_ zTy{V3&tEYD-`I9$Bj4~%h%u$8DfEsaaZf}f6D?li6Q;RQB#=Q0 zGKwP&h_|40XG;rV?zZQhZ@T(!C_;sX@bx(fPWTL zf~Xz_p#}ziMPDHaXCiK1QNp|pJ2LJ39&kXg2jJCPTt#!aRzt($77e!r>D6#O&g*h~ z*D~dp;{ga8fZc&WKxjn($j9c9%R&;Y$EXE;lSj9KerItuqd43YFq#0^r}j9JS>c!~ z_zD0Ba&KKWXlP8sEkZVb`Qioa5xc{*I_yCT!2+a%!WyLA-^YL3axvZz)Xe1#hllaT zuoHv5@db}k6fiy=P|_H(aM8cfh?k3}qp!V5H)=3Q?V+EH$%$ z5+uHrct-Y>dlJW!9I>rgeZE7XS6a!*-h`;%2ka<%F_w3)SgJ-vxUMGqLj+%n!d2D0 z%W>B(;P`cb_Dj6V)v3#-q7F4~Oj5Dfq>% z!F~(x2>|O$#0f#OH2JJ5m6kMvXsETCnnte&zy|Yt{`{H3a{b!1=0lLlKfYoxH8LWX z3WxYy^h|)YF%moF2>MX)s<)sEBk`(xS{$ z#2@PZk?5tX^`Y6A5D^OoP=yk}#Ci|Jc!=?^xy*m`ElP?{$W8d!0>iYOqt4KS2gXIt zWU#(k$pK1U#9&g^M|YNE;sMDieE`N~hbc2Aj{W=L_m46yI2z^?hf4#z)eQenje))l zzB0%)62B=+W00Nh+O>io<;c6w)F0p92W<7g>mUi-}?@b)_O9CFS8##sv-IfR2I-mo6pKEdjWKmzg4#NIC?7 z#^eRE4+oxT?+E!)Q+s5tiCS_ntH3G0=+g>mRq#BaQm>FgNE}yu6B??>&o;)+gf3xY z$fY%qy^v1GNc%Fr#g<3C%`L6JM}G;w8Lb$~=9Hi9dWjcQopwWSHTO(+<3<($ika2M zzIIjxXHrvn-md|wKK5WIDtg_ZFOp7i)+y!Xd_zH3s z#@;v-ZWUs5(Tg)+jCc$3*!NkbDtY${fNOuXIo{*ENB~G_7vld@lu(3wmSwv^SUtx{ ziVit_Kc6RI#l^6cpHv)0Xx24ANU;eh_WyNhiXum_ZSCxLWB#%>)=Kh_+f6vfadP!K z#OCLZAjBC3?H#Nf$gqG?DG#`?ajC@a7R(zkfB)o)bh-nxyUH)@00%Kdn*ntRQB}(= z`+@t|8PgX~^fweP*Wf z+YNF>yhwId)_avozeMu158-Mc*qiS4pLSqgV;}Ivx%9zbSO)tV7J0L@k%0AwOxqnawR?q#9V*6ZmaxwulROMKOo;g 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%0AR!Y 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%0Ak+2lMF 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 diff --git a/docs-site/islands/Cookbook.tsx b/docs-site/islands/Cookbook.tsx index 06b77e720..92ef9f2a4 100644 --- a/docs-site/islands/Cookbook.tsx +++ b/docs-site/islands/Cookbook.tsx @@ -8,8 +8,8 @@ import { Textarea } from "@/components/ui/textarea"; import SourceRecipe from "./SourceRecipe"; import ComponentPlan from "@/components/cookbook/ComponentPlan"; import HardwarePicker from "@/components/cookbook/HardwarePicker"; -import ModelRelease from "@/components/cookbook/ModelRelease"; import ModelHeader from "@/components/cookbook/ModelHeader"; +import { configAndLaunch, inferenceOutput, sdkCommand } from "@/lib/cookbook-commands"; import { api, guideUrl, @@ -194,14 +194,23 @@ function Editor({ }) { const [advanced, setAdvanced] = useState(false); const [componentDraft, setComponentDraft] = useState(false); + const [runMode, setRunMode] = useState("serving"); + const [sourceImage, setSourceImage] = useState(""); + const sourceImageId = useId(); + const [showEnv, setShowEnv] = useState(false); + const [showClient, setShowClient] = useState(false); + const [outputTab, setOutputTab] = useState("commands"); const [hardware, setHardware] = useState( - () => new URL(window.location.href).searchParams.get("hardware") ?? "unspecified", + () => + new URL(window.location.href).searchParams.get("hardware") ?? + (catalog.id.startsWith("fasth3-trim/") ? "spark" : "unspecified"), ); const [edits, setEdits] = useState>({}); const [parseErrors, setParseErrors] = useState>({}); const [reset, setReset] = useState(0); const [notice, setNotice] = useState(""); let result: Result | undefined; + let output: ReturnType | undefined; let failure = ""; let failedPath: string | undefined; try { @@ -209,11 +218,18 @@ function Editor({ throw new Error("Component preview selected. A compatible serving recipe is needed before generating YAML."); if (Object.keys(parseErrors).length) throw new Error("Correct the highlighted fields to generate a configuration."); result = api.resolveConfig(catalog, edits); + output = + runMode === "serving" ? result : inferenceOutput(result, catalog.workload === "i2v" ? sourceImage : undefined); } catch (error) { failure = errorText(error); failedPath = (error as { path?: string }).path; } const fields = api.getOptions(catalog, catalog.base_config, edits); + const launchCommand = + output && + (runMode === "sdk" + ? output.command.replace(/fastvideo generate --config config\.yaml$/, sdkCommand) + : output.command); const groups = [...new Set(fields.map((field) => field.path.split(".").slice(0, -1).join(".")))]; function update(path: string, raw: string | undefined, field: Field) { setNotice(""); @@ -240,8 +256,8 @@ function Editor({ } } function download() { - if (!result) return; - const url = URL.createObjectURL(new Blob([result.yaml], { type: "application/yaml" })); + if (!output) return; + const url = URL.createObjectURL(new Blob([output.yaml], { type: "application/yaml" })); const link = document.createElement("a"); link.href = url; link.download = "config.yaml"; @@ -250,16 +266,20 @@ function Editor({ setNotice("Downloaded config.yaml."); } const mlx = catalog.runtime.backend === "mlx"; - const hardwareOptions = mlx - ? [["apple", "Apple Silicon", "Unified memory"]] - : [ - ["b200", "B200", "Data center"], - ["gb200", "GB200", "Data center"], - ["h100", "H100", "Data center"], - ["rtx5090", "RTX 5090", "GeForce"], - ["rtx", "RTX PRO 6000", "Workstation"], - ["spark", "DGX Spark", "GB10"], - ]; + const generator = catalog.base_config.generator as { engine?: { quantization?: { transformer_quant?: string } } }; + const nvfp4 = generator?.engine?.quantization?.transformer_quant === "NVFP4"; + const hardwareOptions = ( + mlx + ? [["apple", "Apple Silicon", "Unified memory"]] + : [ + ["b200", "B200", "Data center"], + ["gb200", "GB200", "Data center"], + ["h100", "H100", "Data center"], + ["rtx5090", "RTX 5090", "GeForce"], + ["rtx", "RTX PRO 6000", "Workstation"], + ["spark", "DGX Spark", "GB10"], + ] + ).filter(([id]) => !nvfp4 || id !== "h100"); const selectedHardware = hardwareOptions.find(([value]) => value === hardware) ?? hardwareOptions[0]; const model = modelDirectory.find((model) => model.id === catalog.id.split("/")[0])!; const renderField = (field: Field) => ( @@ -289,24 +309,78 @@ function Editor({ model={model} actions={ <> - - } /> + { +

+ {(mlx ? ["serving"] : ["sdk", "inference", "serving"]).map((mode) => ( + + ))} +
+ }
- +
Unverified recipe +
+ + {runMode === "serving" && ( + + )} + {Object.keys(catalog.env).length > 0 && ( + + )} +
Commands config.yaml
+ {showEnv && ( +
+              
+                {Object.entries(catalog.env)
+                  .map(([name, value]) => `${name}=${value}`)
+                  .join("\n")}
+              
+            
+ )} {failure && (

{failure}

@@ -316,38 +390,50 @@ function Editor({
)} - {result && ( + {result && output && ( <>
- Serve - + {runMode === "sdk" ? "Python SDK" : runMode === "inference" ? "Generate" : "Serve"}
-
-                  {result.command}
+                
+                  {launchCommand}
                 
-
- {result.websocketUrl ? "Health check and WebSocket" : "Example request"} - -
-                    {result.clientCommand}
-                  
- {result.websocketUrl && ( -

- WebSocket URL: {result.websocketUrl} -

- )} -
+

+ Includes your settings and writes config.yaml. Run from an installed FastVideo checkout. +

+ {runMode === "serving" && ( +
setShowClient(event.currentTarget.open)} + > + {result.websocketUrl ? "Health check and WebSocket" : "Example request"} + +
+                      {result.clientCommand}
+                    
+ {result.websocketUrl && ( +

+ WebSocket URL: {result.websocketUrl} +

+ )} +
+ )} )} - {result && ( + {output && (
-                {result.yaml}
+                {output.yaml}
               
)}
@@ -358,7 +444,7 @@ function Editor({
- Installation {catalog.runtime.label} + Installation {catalog.runtime.label.replace(/\s*REST/gi, "")} {catalog.requirements?.length ? (
    @@ -385,7 +471,7 @@ function Editor({ if (catalog.id !== deployment.id) selectRuntime(deployment.id); }} > - {deployment.runtime.includes("mlx") ? "MLX" : "NVIDIA"} + {deployment.runtime.includes("mlx") ? "MLX" : "CUDA"} ))} @@ -415,8 +501,43 @@ function Editor({

    Hardware fit has not been verified. GPU count updates the YAML.

    + {catalog.workload === "i2v" && runMode !== "serving" && ( + +
    + + { + setSourceImage(event.target.value); + setNotice(""); + }} + /> +

    + Path to an image on the machine running FastVideo. Included as request.inputs.image_path. +

    +
    +
    + )} {model.family === "FastH3" && ( + {model.id === "fasth3-trim" && ( +
    + {["NVFP4 transformer", "50-layer NVFP4 encoder", "Lightweight video VAE", "H3 audio VAE"].map( + (name) => ( + + {name} + + ), + )} +
    + )}
    )} @@ -461,11 +582,12 @@ function Editor({
- Save config.yaml before running the server. + Copy config and launch together, or download config.yaml first. ))}
diff --git a/docs-site/islands/SourceRecipe.tsx b/docs-site/islands/SourceRecipe.tsx index 9a3c35175..f9e3411d9 100644 --- a/docs-site/islands/SourceRecipe.tsx +++ b/docs-site/islands/SourceRecipe.tsx @@ -1,35 +1,124 @@ import { useEffect, useState } from "react"; +import { Tabs } from "radix-ui"; +import { parse, stringify } from "yaml"; import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; import ModelHeader from "@/components/cookbook/ModelHeader"; +import HardwarePicker from "@/components/cookbook/HardwarePicker"; +import { configAndLaunch, fileAndLaunch, sdkCommand, pythonSource } from "@/lib/cookbook-commands"; import { sitePath, type DirectoryModel } from "@/lib/cookbook-pages"; +import { api } from "@/lib/cookbook"; -/** Existing inference recipes stay runnable while editable serving catalogs are added. */ +interface Control { + name: string; + label: string; + value: string | number | boolean; + spans?: number[][]; + path?: string[]; + flag?: string; + integer?: boolean; + booleanOptional?: boolean; + choices?: (string | number | { value: string | number; label: string })[]; +} +interface Example { + source: string; + controls: Control[]; +} +const labels: Record = { + prompt: "Prompt", + num_gpus: "GPU count", + height: "Height", + width: "Width", + num_frames: "Frames", + seed: "Seed", + num_inference_steps: "Inference steps", + guidance_scale: "Guidance scale", + fps: "FPS", + host: "Host", + port: "Port", + served_model_name: "Served model name", +}; + +/** Every source page uses the model editor; settings modify the maintained example itself. */ export default function SourceRecipe({ model }: { model: DirectoryModel }) { const [selected, setSelected] = useState(model.recipes[0].id); - const [mode, setMode] = useState("inference"); - const [yaml, setYaml] = useState(""); + const [mode, setMode] = useState("sdk"); + const [loaded, setLoaded] = useState<{ url: string; example: Example }>(); const [notice, setNotice] = useState(""); + const [showEnv, setShowEnv] = useState(false); + const [showClient, setShowClient] = useState(false); + const [outputTab, setOutputTab] = useState("commands"); const [error, setError] = useState(""); + const [edits, setEdits] = useState>({}); + const [hardware, setHardware] = useState("unspecified"); + useEffect(() => { + setHardware(new URL(window.location.href).searchParams.get("hardware") ?? "unspecified"); + }, []); const recipe = model.recipes.find((recipe) => recipe.id === selected)!; const yamlSource = mode === "serving" ? recipe.serving?.source : /\.ya?ml$/.test(recipe.source) ? recipe.source : undefined; - const sourceUrl = sitePath(`/assets/cookbook-sources/${recipe.id}-${mode}.yaml`); + const sourceUrl = sitePath( + yamlSource + ? `/assets/cookbook-sources/${recipe.id}-${mode === "serving" ? "serving" : "inference"}.yaml` + : `/assets/cookbook-examples/${recipe.id}.json`, + ); + const example = loaded?.url === sourceUrl ? loaded.example : undefined; useEffect(() => { const controller = new AbortController(); - setYaml(""); setError(""); - if (yamlSource) - fetch(sourceUrl, { signal: controller.signal }) - .then(async (response) => { - if (!response.ok) throw new Error(`YAML could not be loaded: HTTP ${response.status}.`); - const text = await response.text(); - if (!controller.signal.aborted) setYaml(text); - }) - .catch((error) => { - if (!controller.signal.aborted) setError(error.message); - }); + fetch(sourceUrl, { signal: controller.signal }) + .then(async (response) => { + if (!response.ok) throw new Error(`Example could not be loaded: HTTP ${response.status}.`); + let data: Example; + if (!yamlSource) data = await response.json(); + else { + const source = await response.text(); + const config = parse(source); + const controls: Control[] = []; + function visit(value: Record, path: string[] = []) { + for (const [name, item] of Object.entries(value)) { + if (item && typeof item === "object" && !Array.isArray(item)) + visit(item as Record, [...path, name]); + else if (labels[name] && ["string", "number", "boolean"].includes(typeof item)) + controls.push({ + name, + label: labels[name], + value: item as Control["value"], + integer: !["guidance_scale", "audio_end_in_s"].includes(name), + path: [...path, name], + }); + } + } + visit(config); + data = { source, controls }; + } + if (!yamlSource) { + for (const knob of recipe.knobs ?? []) { + const field = data.controls.find((field) => field.name === knob.key); + if (field) field.choices = knob.options; + else + data.controls.push({ + name: knob.key, + label: labels[knob.key] ?? knob.label, + value: knob.default, + flag: knob.flag, + spans: [], + choices: knob.options, + }); + } + } + if (!controller.signal.aborted) setLoaded({ url: sourceUrl, example: data }); + }) + .catch((error) => { + if (!controller.signal.aborted) setError(error.message); + }); return () => controller.abort(); - }, [sourceUrl, yamlSource]); + }, [sourceUrl, yamlSource, recipe]); + function selectMode(next: string) { + setMode(next); + if ((next === "serving") !== (mode === "serving")) setEdits({}); + setNotice(""); + } async function copy(value: string) { try { await navigator.clipboard.writeText(value); @@ -38,140 +127,399 @@ export default function SourceRecipe({ model }: { model: DirectoryModel }) { setNotice("Copy failed. Select and copy the text below."); } } - const command = + let source = example?.source ?? ""; + let failure = ""; + for (const [key, value] of Object.entries(edits)) { + const field = example?.controls[Number(key)]; + if ( + field && + typeof field.value === "number" && + (!Number.isFinite(value) || + ((field.integer ?? Number.isInteger(field.value)) && !Number.isInteger(value)) || + (field.name === "num_gpus" && Number(value) < 1)) + ) + failure = "Enter valid numeric settings before copying the example."; + } + if (example && yamlSource) { + const config = parse(source); + for (const [key, value] of Object.entries(edits)) { + const path = example.controls[Number(key)].path!; + const parent = path.slice(0, -1).reduce((item, name) => item[name], config); + parent[path.at(-1)!] = value; + } + source = stringify(config); + } else if (example) { + source = pythonSource(source, example.controls, edits); + } + const baselineCommand = mode === "serving" && recipe.serving ? `${recipe.serving.env ? `${recipe.serving.env} ` : ""}fastvideo serve --config ${recipe.serving.source}` : recipe.command; + const localFile = recipe.source.replace(/[^/]+$/, `cookbook_${recipe.id.replaceAll("-", "_")}.py`); + const command = yamlSource + ? baselineCommand.replace(/--config\s+\S+/, "--config config.yaml") + : baselineCommand.replace(recipe.source, localFile) + + Object.entries(edits) + .filter(([key]) => example?.controls[Number(key)].flag) + .map(([key, value]) => { + const field = example!.controls[Number(key)]; + return typeof value === "boolean" && field.booleanOptional + ? ` ${value ? field.flag : field.flag!.replace(/^--/, "--no-")}` + : ` ${field.flag} '${String(value).replaceAll("'", "'\"'\"'")}'`; + }) + .join(""); + const sdk = mode === "sdk" && !!yamlSource; + const config = sdk && source ? parse(source) : undefined; + const displayedSource = config + ? stringify({ generator: config.generator, request: config.request ?? config.default_request }) + : source; + const launch = sdk ? command.replace(/fastvideo generate --config config\.yaml$/, sdkCommand) : command; + const ready = !!example && !failure; + const clientCommand = + mode === "serving" && ready + ? api.sampleRequest( + { + runtime: { interface: "rest", server_defaults: { host: "127.0.0.1", port: 8000 } }, + model: { id: model.model }, + workload: "t2v", + }, + parse(source), + ).command + : undefined; + const launchScript = yamlSource + ? configAndLaunch(displayedSource, launch) + : fileAndLaunch(localFile, displayedSource, launch); + const environment = [...baselineCommand.matchAll(/(?:^|\s)([A-Z][A-Z0-9_]*=(?:'[^']*'|"[^"]*"|[^\s]+))/g)] + .map((match) => match[1]) + .join("\n"); + const mlx = recipe.gpu_types.includes("Apple Silicon"); + const devices = mlx + ? [["apple", "Apple Silicon", "Unified memory"]] + : [ + ["b200", "B200", "Data center"], + ["h100", "H100", "Data center"], + ["rtx5090", "RTX 5090", "GeForce"], + ["rtx", "RTX PRO 6000", "Workstation"], + ["spark", "DGX Spark", "GB10"], + ]; + const chooseHardware = (value: string) => { + setHardware(value); + const url = new URL(window.location.href); + url.searchParams.set("hardware", value); + window.history.replaceState(null, "", url); + }; + const control = (field: Control, index: number) => { + const value = Object.hasOwn(edits, index) ? edits[index] : field.value; + return ( +
+ {field.choices || typeof value === "boolean" ? ( + {field.label} + ) : ( + + )} + {field.choices ? ( +
+ {field.choices.map((option) => { + const choice = typeof option === "object" ? option.value : option; + return ( + + ); + })} +
+ ) : typeof value === "boolean" ? ( +
+ {[true, false].map((choice) => ( + + ))} +
+ ) : ( + + setEdits({ + ...edits, + [index]: + typeof field.value === "number" + ? event.target.value === "" + ? NaN + : Number(event.target.value) + : event.target.value, + }) + } + /> + )} +
+ ); + }; return (
- {yamlSource ? ( - <> - - - - ) : ( - - )} + + } /> -
-
- Unverified recipe - -
-
-
-            {command}
-          
- {yamlSource && ( -
- View source YAML - {error ? ( -

{error}

- ) : ( -
-                  {yaml || "Loading YAML…"}
-                
+ ))} +
+
+ +
+ Unverified recipe +
+ + {mode === "serving" && ( + )} - + {environment && ( + + )} +
+ + Commands + {yamlSource ? "config.yaml" : "Python example"} + +
+ {showEnv && ( +
+              {environment}
+            
)} -
+ {(error || failure) && ( +

+ {error || failure} +

+ )} + +
+ {mode === "serving" ? "Serve" : mode === "sdk" ? "Python SDK" : "Generate"} +
+
+              {launch}
+            
+

Includes your settings. Run from an installed FastVideo checkout.

+ {clientCommand && ( +
setShowClient(event.currentTarget.open)} + > + Example request + +
+                  {clientCommand}
+                
+
+ )} +
+ +
+              {displayedSource || "Loading example…"}
+            
+
+

{notice}

- Installation and setup + + Installation and setup {mlx ? "MLX" : "CUDA"} + {mode === "serving" && recipe.serving && (
             {recipe.serving.install}
           
)} + {mode === "serving" && recipe.serving?.prepare && ( + <> +
+              {recipe.serving.prepare}
+            
+ + + )} Model setup guide ↗
-
-
-

Recipe

-
-
- {model.recipes.map((entry) => ( - - ))} -
-
-
+

Hardware

-
- {recipe.gpu_types.map((platform) => ( - - {platform === "Apple Silicon" ? "MLX" : platform} - +
+ {[ + ...new Set(model.recipes.map((entry) => (entry.gpu_types.includes("Apple Silicon") ? "MLX" : "CUDA"))), + ].map((platform) => ( + ))}
+
+ id === hardware)?.[0] ?? devices[0][0]) + } + onChange={chooseHardware} + /> +
+ Resources + {example?.controls.map((field, i) => (field.name === "num_gpus" ? control(field, i) : null))} + {!example?.controls.some((field) => field.name === "num_gpus") && ( +

{mlx ? "1 Apple Silicon host" : `${recipe.hardware?.gpu_count ?? 1} GPU in the source example`}

+ )} +
+

- {recipe.hardware?.accelerator ?? - (recipe.hardware?.gpu_count - ? `${recipe.hardware.gpu_count} GPU${recipe.hardware.gpu_count === 1 ? "" : "s"} in the source recipe` - : "See the model guide for resources")} + Hardware fit has not been verified. Settings edit the source example; device choice is a preference.

-
-

Run mode

-
-
- - {recipe.serving && ( - - )} + {model.recipes.filter((entry) => entry.gpu_types.includes(mlx ? "Apple Silicon" : "NVIDIA")).length > 1 && ( +
+

Recipe

+
+ {model.recipes + .filter((entry) => entry.gpu_types.includes(mlx ? "Apple Silicon" : "NVIDIA")) + .map((entry) => ( + + ))}
+ )} +
+

Generation settings

+
+
+ {example?.controls.map((field, i) => + field.name !== "num_gpus" && field.path?.[0] !== "server" ? control(field, i) : null, + )} +
+ {example && !example.controls.length && ( +

+ This example uses its model defaults. Open the Python example to customize its pipeline. +

+ )} +
+ {example?.controls.some((field) => field.path?.[0] === "server") && ( +
+ + Advanced Server settings + +
+

Server

+
+ {example.controls.map((field, i) => (field.path?.[0] === "server" ? control(field, i) : null))} +
+
+
+ )}
-
- Model guide → +
- View source ↗ + View original example ↗ - - Run from the FastVideo checkout. Source recipe. Interactive YAML configuration is not available for this model - yet. - +
); diff --git a/docs-site/lib/cookbook-commands.ts b/docs-site/lib/cookbook-commands.ts new file mode 100644 index 000000000..25e43e695 --- /dev/null +++ b/docs-site/lib/cookbook-commands.ts @@ -0,0 +1,71 @@ +import { stringify } from "yaml"; +import type { Result, Value } from "./cookbook"; + +export function pythonSource( + source: string, + controls: { value: string | number | boolean; spans?: number[][] }[], + edits: Record = {}, +) { + const replacements = controls.flatMap((field, index) => + (field.spans ?? []).map(([start, end]) => { + const value = Object.hasOwn(edits, index) ? edits[index] : field.value; + return { start, end, text: typeof value === "boolean" ? (value ? "True" : "False") : JSON.stringify(value) }; + }), + ); + for (const replacement of replacements.sort((a, b) => b.start - a.start)) + source = source.slice(0, replacement.start) + replacement.text + source.slice(replacement.end); + return source; +} + +/** Quoted heredocs preserve prompts literally, including shell substitutions. */ +export function configAndLaunch(yaml: string, command: string) { + return fileAndLaunch("config.yaml", yaml, command); +} + +export function fileAndLaunch(filename: string, content: string, command: string) { + let delimiter = "FASTVIDEO_CONFIG"; + while (content.split("\n").includes(delimiter)) delimiter += "_"; + return `(\nset -e\ncat > ${filename} <<'${delimiter}'\n${content.trimEnd()}\n${delimiter}\n${command}\n)`; +} + +export const sdkCommand = `python - <<'FASTVIDEO_SDK' +import yaml +from fastvideo import VideoGenerator + +with open("config.yaml") as file: + config = yaml.safe_load(file) +generator = VideoGenerator.from_config(config["generator"]) +try: + generator.generate(config["request"]) +finally: + generator.shutdown() +FASTVIDEO_SDK`; + +/** The CUDA CLI uses the same generator with request instead of server defaults. */ +export function inferenceOutput(result: Result, imagePath?: string) { + const defaults = (result.config.default_request ?? {}) as Record; + const output = (defaults.output ?? {}) as Record; + const generator = result.config.generator as Record; + const pipeline = generator.pipeline as Record | undefined; + const inputs = { ...((defaults.inputs ?? {}) as Record) }; + if (imagePath !== undefined) inputs.image_path = imagePath.trim(); + const images = Array.isArray(inputs.image_path) ? inputs.image_path : [inputs.image_path]; + if (pipeline?.workload_type === "i2v" && !images.some((image) => typeof image === "string" && image.trim())) { + throw new Error("Enter a source image path before copying a CLI or Python SDK example."); + } + return { + yaml: stringify({ + generator: result.config.generator, + request: { + ...defaults, + ...(Object.keys(inputs).length ? { inputs } : {}), + prompt: defaults.prompt ?? "A river flowing through a peaceful forest", + output: { ...output, save_video: true, return_frames: false, output_path: "outputs/cookbook/" }, + }, + }), + command: result.command.replace( + /\bfastvideo serve --config config\.yaml$/, + "fastvideo generate --config config.yaml", + ), + }; +} diff --git a/docs-site/lib/cookbook-pages.ts b/docs-site/lib/cookbook-pages.ts index bf15c36f0..041ea9761 100644 --- a/docs-site/lib/cookbook-pages.ts +++ b/docs-site/lib/cookbook-pages.ts @@ -12,6 +12,15 @@ export const recipePages = [ tags: ["Text to video", "Audio", "8-step"], featured: true, }, + { + id: "fasth3-trim", + family: "FastH3", + title: "FastH3 Trim", + mark: "H3", + path: "/cookbook/minimax-h3/fasth3-trim", + description: "The smaller FastH3 model for eight-step video generation with synchronized audio.", + tags: ["Text to video", "Audio", "NVFP4", "8-step"], + }, { id: "fastwan21", family: "Wan", @@ -56,7 +65,15 @@ export interface SourceRecipe { command: string; gpu_types: string[]; hardware?: { gpu_count?: number; platform?: string; accelerator?: string }; - serving?: { source: string; install: string; env?: string }; + serving?: { source: string; install: string; env?: string; prepare?: string }; + knobs?: { + key: string; + label: string; + hint?: string; + flag: string; + default: string | number; + options: (string | number | { value: string | number; label: string })[]; + }[]; } export const sourceRecipes = sourceCatalog.recipes as SourceRecipe[]; const familyInfo: Record = { @@ -75,6 +92,7 @@ const familyInfo: Record = { "FastVideo/FastVideo-FastH3-8-Step-V2": "fasth3-8step", + "FastVideo/FastVideo-FastH3-Trim-8-Step-NVFP4": "fasth3-trim", "FastVideo/FastWan2.1-T2V-1.3B-Diffusers": "fastwan21", "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers": "wan21-i2v", "FastVideo/LTX2-Distilled-Diffusers": "ltx2-distilled", @@ -116,7 +134,6 @@ export const modelDirectory = [...new Set(sourceRecipes.map((recipe) => recipe.m path: backend?.path ?? `/cookbook/${family.path}/models/${first.id}`, logo, provider: providers[logo], - releaseOnly: false, category: family.category, description: backend?.description ?? first.summary, tags: backend?.tags ?? [...new Set(recipes.map((recipe) => recipe.task))], @@ -125,26 +142,6 @@ export const modelDirectory = [...new Set(sourceRecipes.map((recipe) => recipe.m featured: backend?.featured ?? false, }; }) - .concat([ - { - id: "fasth3-trim", - model: "FastVideo/FastVideo-FastH3-Trim-8-Step", - recipes: [] as SourceRecipe[], - title: "FastH3 Trim", - family: "FastH3", - familyPath: "/cookbook/minimax-h3", - path: "/cookbook/minimax-h3/fasth3-trim", - logo: "fastvideo", - provider: "FastVideo", - releaseOnly: true, - category: "Video", - description: "The smaller FastH3 release, previously called CompactH3.", - tags: ["Text to video", "Audio", "8-step"], - platforms: ["NVIDIA", "Apple Silicon"], - configurable: false, - featured: false, - }, - ]) .sort( (a, b) => Number(b.featured) - Number(a.featured) || diff --git a/docs-site/lib/cookbook.ts b/docs-site/lib/cookbook.ts index fd066d26f..54ae851f4 100644 --- a/docs-site/lib/cookbook.ts +++ b/docs-site/lib/cookbook.ts @@ -36,6 +36,8 @@ export interface Catalog { id: string; title: string; summary?: string; + workload: string; + env: Record; base_config: Record; runtime: { label: string; @@ -48,12 +50,21 @@ export interface Catalog { guide?: { url: string; label?: string }; } export interface Result { + config: Record; yaml: string; command: string; clientCommand: string; websocketUrl?: string; } interface Api { + sampleRequest( + catalog: { + runtime: { interface: string; server_defaults: { host: string; port: number } }; + model: { id: string }; + workload: string; + }, + config: Record, + ): { command: string }; loadIndex(url: string, options?: { signal?: AbortSignal }): Promise; loadDeployment(index: Index, id: string, options?: { signal?: AbortSignal }): Promise; getOptions(catalog: Catalog, config?: Catalog["base_config"], edits?: Record): Field[]; diff --git a/docs-site/navigation.json b/docs-site/navigation.json index 41b88323b..06ba8f7cc 100644 --- a/docs-site/navigation.json +++ b/docs-site/navigation.json @@ -142,6 +142,10 @@ "label": "FastH3 8-Step V2", "href": "/cookbook/minimax-h3/fasth3-8step" }, + { + "label": "FastH3 Trim", + "href": "/cookbook/minimax-h3/fasth3-trim" + }, { "label": "Recipes and setup", "href": "/cookbook/minimax-h3" diff --git a/docs-site/package.json b/docs-site/package.json index e3a5ea717..b6eb4d4fa 100644 --- a/docs-site/package.json +++ b/docs-site/package.json @@ -15,7 +15,7 @@ "test": "playwright test", "format": "prettier --write .", "format:check": "prettier --check .", - "test:content": "node --test tests/content.test.mjs" + "test:content": "node --test tests/content.test.mjs tests/commands.test.mjs" }, "dependencies": { "blume": "2.2.3", diff --git a/docs-site/scripts/prepare-content.mjs b/docs-site/scripts/prepare-content.mjs index d9b7042fd..7fd24cc1c 100644 --- a/docs-site/scripts/prepare-content.mjs +++ b/docs-site/scripts/prepare-content.mjs @@ -22,6 +22,9 @@ await cp(new URL("docs/assets/cookbook-config/", repo), destination, { await cp(new URL("docs/assets/logos/icon_simple.svg", repo), new URL("icon.svg", publicDir)); await cp(new URL("../assets/hao-ai-lab.png", import.meta.url), new URL("assets/hao-ai-lab.png", publicDir)); +await cp(new URL("../.generated/source-examples/", import.meta.url), new URL("assets/cookbook-examples/", publicDir), { + recursive: true, +}); // Publish exact checked-in YAML for inference-only model pages. No settings are synthesized. const sourceDir = new URL("assets/cookbook-sources/", publicDir); diff --git a/docs-site/scripts/prepare-python-docs.py b/docs-site/scripts/prepare-python-docs.py index 11b82ba1c..3f86b69a9 100644 --- a/docs-site/scripts/prepare-python-docs.py +++ b/docs-site/scripts/prepare-python-docs.py @@ -2,10 +2,12 @@ from __future__ import annotations import html +import ast import json import re import runpy import shutil +import shlex from pathlib import Path from urllib.parse import urljoin, urlsplit, urlunsplit @@ -18,6 +20,68 @@ SITE = ROOT / "docs-site" GENERATED = SITE / ".generated" +def source_controls(source: str) -> list[dict]: + """Expose literal settings in maintained examples without importing them.""" + labels = { + "prompt": "Prompt", "num_gpus": "GPU count", "height": "Height", "width": "Width", + "num_frames": "Frames", "seed": "Seed", "num_inference_steps": "Inference steps", + "guidance_scale": "Guidance scale", "fps": "FPS", "audio_end_in_s": "Audio duration", + "text_encoder_cpu_offload": "Offload text encoder", "vae_cpu_offload": "Offload VAE", + "dit_cpu_offload": "Offload transformer", "inference_torch_compile": "Compile transformer", + "video_decode_backend": "Video decoder", + } + lines = source.splitlines(keepends=True) + offsets = [0] + for line in lines: + offsets.append(offsets[-1] + len(line)) + + def position(line, column): + prefix = source[:offsets[line - 1]] + lines[line - 1].encode()[:column].decode() + return len(prefix.encode("utf-16-le")) // 2 + + settings = {} + + def add(name, value): + if name not in labels or not isinstance(value, ast.Constant) or type(value.value) not in (str, int, float, bool): + return + key = json.dumps([name, value.value]) + entry = settings.setdefault(key, {"name": name, "label": labels[name], "value": value.value, + "integer": type(value.value) is int, "spans": []}) + entry["spans"].append([position(value.lineno, value.col_offset), position(value.end_lineno, value.end_col_offset)]) + + for node in ast.walk(ast.parse(source)): + if isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute): + if node.func.attr in {"from_pretrained", "generate_video"}: + for keyword in node.keywords: + add(keyword.arg, keyword.value) + elif node.func.attr == "add_argument": + flags = [arg.value for arg in node.args if isinstance(arg, ast.Constant) and isinstance(arg.value, str)] + flag = next((flag for flag in flags if flag.startswith("--")), "") + for keyword in node.keywords: + if keyword.arg == "default": + add(flag.removeprefix("--").replace("-", "_"), keyword.value) + key = json.dumps([flag.removeprefix("--").replace("-", "_"), getattr(keyword.value, "value", None)]) + if key in settings: + settings[key]["flag"] = flag + if any(item.arg == "type" and isinstance(item.value, ast.Name) and item.value.id == "float" + for item in node.keywords): + settings[key]["integer"] = False + settings[key]["booleanOptional"] = any( + item.arg == "action" and isinstance(item.value, ast.Attribute) and item.value.attr == "BooleanOptionalAction" + for item in node.keywords) + elif isinstance(node, ast.Assign): + for target in node.targets: + if isinstance(target, ast.Name) and target.id.isupper(): + add(target.id.lower(), node.value) + result = list(settings.values()) + seen = {} + for field in result: + seen[field["label"]] = seen.get(field["label"], 0) + 1 + if seen[field["label"]] > 1: + field["label"] += f' ({seen[field["label"]]})' + return result + + def signature(obj) -> str: """Preserve parameter kinds, annotations, defaults, and return annotations.""" if obj.is_attribute: @@ -159,6 +223,27 @@ def prepare() -> None: examples = runpy.run_path(str(ROOT / "docs/generate_examples.py")) examples["validate_cookbook"]() examples["generate_examples"](generate_main_index=True) + source_dir = GENERATED / "source-examples" + shutil.rmtree(source_dir, ignore_errors=True) + source_dir.mkdir() + for recipe in json.loads((ROOT / "docs/assets/cookbook-recipes.json").read_text())["recipes"]: + path = ROOT / recipe["source"] + if path.suffix == ".py": + source = path.read_text() + controls = source_controls(source) + argv = shlex.split(recipe["command"]) + for field in controls: + flag = field.get("flag") + positions = [i for i, argument in enumerate(argv[:-1]) if argument == flag] + if positions and type(field["value"]) is not bool: + converter = float if isinstance(field["value"], (int, float)) and not field["integer"] else type(field["value"]) + field["value"] = converter(argv[positions[-1] + 1]) + elif field.get("booleanOptional"): + if flag in argv: + field["value"] = True + elif flag.replace("--", "--no-", 1) in argv: + field["value"] = False + (source_dir / f'{recipe["id"]}.json').write_text(json.dumps({"source": source, "controls": controls})) anchors = json.loads((SITE / "migration-anchors.json").read_text()) shutil.rmtree(GENERATED / "python-reference", ignore_errors=True) package = griffe.load("fastvideo", search_paths=[ROOT], allow_inspection=False, resolve_aliases=True, diff --git a/docs-site/tests/commands.test.mjs b/docs-site/tests/commands.test.mjs new file mode 100644 index 000000000..91e00f075 --- /dev/null +++ b/docs-site/tests/commands.test.mjs @@ -0,0 +1,100 @@ +import assert from "node:assert/strict"; +import { execFileSync } from "node:child_process"; +import { mkdtempSync, readFileSync, readdirSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { test } from "node:test"; +import { parse } from "yaml"; +import { configAndLaunch, inferenceOutput, pythonSource, sdkCommand } from "../lib/cookbook-commands.ts"; + +test("every generated Python example remains valid after its source-backed settings are applied", () => { + const directory = new URL("../.generated/source-examples/", import.meta.url); + const examples = readdirSync(directory) + .filter((name) => name.endsWith(".json")) + .map((name) => { + const data = JSON.parse(readFileSync(new URL(name, directory), "utf8")); + const edits = Object.fromEntries( + data.controls.map((field, i) => [ + i, + typeof field.value === "number" + ? 2 + : typeof field.value === "boolean" + ? false + : "A bowl 🥣 with 'quotes' and $(literal text)", + ]), + ); + return { + name, + baseline: pythonSource(data.source, data.controls), + edited: pythonSource(data.source, data.controls, edits), + }; + }); + assert.ok(examples.length > 25); + execFileSync( + "python3", + [ + "-c", + "import ast,json,sys\nfor example in json.load(sys.stdin):\n for key in ('baseline', 'edited'):\n ast.parse(example[key], filename=example['name'])", + ], + { input: JSON.stringify(examples) }, + ); +}); + +test("SDK launch commands have valid shell syntax without executing model code", () => { + execFileSync("bash", ["-n"], { + input: configAndLaunch("generator: {}\nrequest: {}\n", `FASTVIDEO_FA4=0 ${sdkCommand}`), + }); +}); + +test("copy-and-launch writes literal YAML before invoking the command", () => { + const root = mkdtempSync(join(tmpdir(), "fastvideo-copy-command-")); + try { + const yaml = 'prompt: "$(touch injected) `touch injected2`"\nFASTVIDEO_CONFIG\n'; + execFileSync("bash", ["-c", configAndLaunch(yaml, "cp config.yaml received.yaml")], { cwd: root }); + assert.equal(readFileSync(join(root, "received.yaml"), "utf8"), yaml); + assert.throws(() => readFileSync(join(root, "injected"))); + assert.throws(() => readFileSync(join(root, "injected2"))); + } finally { + rmSync(root, { recursive: true, force: true }); + } +}); + +test("inference output preserves edited settings and hidden generator fields", () => { + const config = { + generator: { + model_path: "FastVideo/Trim", + engine: { num_gpus: 2 }, + pipeline: { experimental: { VSA_sparsity: 0.8 } }, + }, + server: { port: 9000 }, + default_request: { prompt: "A ceramic bowl", sampling: { num_frames: 243, seed: 0 } }, + }; + const result = inferenceOutput({ config, command: "FASTVIDEO_FA4=0 fastvideo serve --config config.yaml" }); + const saved = parse(result.yaml); + assert.deepEqual(saved.generator, config.generator); + assert.deepEqual(saved.request.sampling, config.default_request.sampling); + assert.equal(saved.request.prompt, "A ceramic bowl"); + assert.equal(saved.request.output.save_video, true); + assert.equal(saved.server, undefined); + assert.equal(result.command, "FASTVIDEO_FA4=0 fastvideo generate --config config.yaml"); + assert.ok(config.server); +}); + +test("Wan I2V inference requires a source image and preserves the serving baseline", () => { + const config = parse( + readFileSync(new URL("../../examples/serving/openai_wan21_i2v_14b.yaml", import.meta.url), "utf8"), + ); + const baseline = structuredClone(config); + const result = { config, command: "fastvideo serve --config config.yaml" }; + assert.throws(() => inferenceOutput(result), /source image path/); + assert.throws(() => inferenceOutput(result, " "), /source image path/); + const saved = parse(inferenceOutput(result, " /data/first-frame.png ").yaml); + assert.equal(saved.request.inputs.image_path, "/data/first-frame.png"); + assert.deepEqual(saved.request.sampling, config.default_request.sampling); + assert.deepEqual(config, baseline); + assert.equal(config.default_request.inputs, undefined); + const withDefaults = structuredClone(config); + withDefaults.default_request.inputs = { image_path: "/data/existing.png", video_path: "/data/reference.mp4" }; + const existing = parse(inferenceOutput({ ...result, config: withDefaults }).yaml); + assert.deepEqual(existing.request.inputs, withDefaults.default_request.inputs); +}); diff --git a/docs-site/tests/cookbook.spec.ts b/docs-site/tests/cookbook.spec.ts index 9f44fe642..73a7a77e3 100644 --- a/docs-site/tests/cookbook.spec.ts +++ b/docs-site/tests/cookbook.spec.ts @@ -117,12 +117,12 @@ test("an obsolete deployment response cannot replace the selected deployment", a await output(page, "config.yaml"); await expect(page.getByLabel("Generated YAML", { exact: true })).toBeVisible(); await backend(page, "MLX"); - await backend(page, "NVIDIA"); + await backend(page, "CUDA"); release(); await output(page, "config.yaml"); await expect(page.getByLabel("Generated YAML", { exact: true })).toContainText("FastVideo-FastH3-8-Step-V2"); await expect( - page.getByRole("group", { name: "Hardware backend" }).getByRole("button", { name: "NVIDIA", exact: true }), + page.getByRole("group", { name: "Hardware backend" }).getByRole("button", { name: "CUDA", exact: true }), ).toHaveAttribute("aria-pressed", "true"); }); @@ -245,10 +245,18 @@ test("image and audio models have logos and dedicated source recipe pages", asyn await card.click(); await expect(page.getByRole("heading", { level: 1 })).toHaveText("FLUX.2 Klein 4B"); await expect(page.getByLabel("Inference command")).toContainText("flux"); - await expect(page.getByText(/Interactive YAML configuration is not available for this model yet/)).toBeVisible(); + await expect( + page.getByRole("group", { name: "Run mode" }).getByRole("button", { name: "Python SDK", exact: true }), + ).toHaveAttribute("aria-pressed", "true"); + await expect(page.getByRole("button", { name: "Serving", exact: true })).toHaveCount(0); + await page.getByLabel("Seed", { exact: true }).fill("0"); + await expect(page.getByRole("button", { name: "Copy", exact: true })).toBeEnabled(); await page.goto("/FastVideo/cookbook"); await page.getByRole("button", { name: "Audio", exact: true }).click(); await expect(page.locator(".recipe-card")).toHaveCount(3); + await page.locator(".recipe-card").first().click(); + await page.getByLabel("Audio duration", { exact: true }).fill("1.5"); + await expect(page.getByRole("button", { name: "Copy", exact: true })).toBeEnabled(); }); test("provider labels match FastVideo logos and CompactH3 is replaced by FastH3 Trim", async ({ page }) => { @@ -259,10 +267,112 @@ test("provider labels match FastVideo logos and CompactH3 is replaced by FastH3 await expect(page.locator(".recipe-card")).toHaveCount(1); await page.locator(".recipe-card").click(); await expect(page.getByRole("heading", { level: 1 })).toHaveText("FastH3 Trim"); - await expect(page.getByRole("link", { name: "NVFP4 ↗", exact: true })).toHaveAttribute( + await expect(page.getByRole("link", { name: "View on Hugging Face ↗", exact: true })).toHaveAttribute( "href", /FastVideo-FastH3-Trim-8-Step-NVFP4/, ); + await expect(page.getByRole("button", { name: "Copy YAML", exact: true })).toBeEnabled(); +}); + +test("FastH3 Trim edits drive inference, serving, and complete copyable launch scripts", async ({ page }) => { + await page.addInitScript(() => { + Object.defineProperty(navigator, "clipboard", { + value: { + writeText: async (text: string) => { + (window as Window & { copiedCommand?: string }).copiedCommand = text; + }, + }, + }); + }); + await page.goto("/FastVideo/cookbook/minimax-h3/fasth3-trim"); + await expect(page.getByRole("radio", { name: "DGX Spark GB10", exact: true })).toBeChecked(); + await expect(page.getByRole("radio", { name: "H100 Data center", exact: true })).toHaveCount(0); + await page.getByLabel("Prompt", { exact: true }).fill("A potter finishes a blue bowl."); + await page.getByLabel("Seed", { exact: true }).fill("0"); + await page.getByRole("button", { name: "Copy", exact: true }).click(); + const script = await page.evaluate(() => (window as Window & { copiedCommand?: string }).copiedCommand); + expect(script).toContain("cat > config.yaml <<'FASTVIDEO_CONFIG'"); + expect(script).toContain("FastVideo-FastH3-Trim-8-Step-NVFP4"); + expect(script).toContain('"seed": 0'); + expect(script).toContain("FASTVIDEO_VSA_TRITON=1"); + expect(script).toContain("fastvideo serve --config config.yaml"); + await page.locator(".recipe-request-code summary").click(); + await expect(page.getByLabel("Client command", { exact: true })).toContainText("A potter finishes a blue bowl."); + await chip(page, "Run mode", "CLI"); + await expect(page.getByLabel("Inference command", { exact: true })).toContainText("fastvideo generate"); + await output(page, "config.yaml"); + await expect(page.getByLabel("Generated YAML", { exact: true })).toContainText("request:"); + await expect(page.getByLabel("Generated YAML", { exact: true })).not.toContainText("server:"); + await expect(page.getByLabel("Generated YAML", { exact: true })).toContainText("num_inference_steps: 9"); + await chip(page, "Run mode", "Python SDK"); + await output(page, "Commands"); + await expect(page.getByLabel("SDK command", { exact: true })).toContainText("VideoGenerator.from_config"); + await page.setViewportSize({ width: 390, height: 844 }); + expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true); +}); + +test("source-backed controls update the copied command without changing models", async ({ page }) => { + await page.goto("/FastVideo/cookbook/minimax-h3/models/minimax-h3-t2v"); + await chip(page, "GPU count", "2"); + await expect(page.getByLabel("Inference command", { exact: true })).toContainText("--num-gpus '2'"); +}); + +test("Wan I2V requires an image for CLI and SDK examples without changing server defaults", async ({ page }) => { + await page.goto("/FastVideo/cookbook/wan/wan21-i2v"); + await chip(page, "Run mode", "CLI"); + await expect(page.getByRole("alert")).toContainText("Enter a source image path"); + await expect(page.getByRole("button", { name: "Copy", exact: true })).toBeDisabled(); + await expect(page.getByRole("button", { name: "Download YAML", exact: true })).toBeDisabled(); + await page.getByLabel("Source image path", { exact: true }).fill("/data/first-frame.png"); + await output(page, "config.yaml"); + await expect(page.getByLabel("Generated YAML", { exact: true })).toContainText("image_path: /data/first-frame.png"); + await expect(page.getByRole("button", { name: "Copy", exact: true })).toBeEnabled(); + await chip(page, "Run mode", "Python SDK"); + await expect(page.getByLabel("Generated YAML", { exact: true })).toContainText("image_path: /data/first-frame.png"); + await page.getByLabel("Source image path", { exact: true }).fill(""); + await expect(page.getByRole("button", { name: "Copy YAML", exact: true })).toBeDisabled(); + await expect(page.getByLabel("Generated YAML", { exact: true })).toHaveCount(0); + await chip(page, "Run mode", "Serving"); + await expect(page.getByRole("button", { name: "Copy", exact: true })).toBeEnabled(); + await expect(page.getByLabel("Generated YAML", { exact: true })).not.toContainText("image_path"); +}); + +test("source editors retain required model flags and preparation commands", async ({ page }) => { + await page.goto("/FastVideo/cookbook/wan/models/fastmetal-1-3b-mlx"); + await expect(page.getByLabel("Height", { exact: true })).toHaveValue("480"); + await expect(page.getByLabel("Inference command", { exact: true })).toContainText( + "hf download FastVideo/FastMetal-1.3B-QAD", + ); + await expect(page.getByLabel("Inference command", { exact: true })).toContainText( + "--model-root ./FastMetal-1.3B-QAD", + ); + await page.getByLabel("Seed", { exact: true }).fill("0"); + await expect(page.getByLabel("Inference command", { exact: true })).toContainText("--seed '0'"); + await page.getByRole("tab", { name: "Python example", exact: true }).click(); + await expect(page.getByLabel("Source example", { exact: true })).toContainText("default=480"); +}); + +test("source-backed serving pages expose their actual server settings", async ({ page }) => { + await page.goto("/FastVideo/cookbook/wan/models/wan22-t2v"); + await chip(page, "Run mode", "Serving"); + await page.locator(".matrix-advanced > summary").click(); + await page.getByLabel("Port", { exact: true }).fill("9005"); + await page.getByRole("button", { name: "cURL", exact: true }).click(); + await expect(page.getByLabel("Client command", { exact: true })).toContainText(":9005/v1/videos/sync"); + await page.getByRole("tab", { name: "config.yaml", exact: true }).click(); + await expect(page.getByLabel("Source example", { exact: true })).toContainText("port: 9005"); + await expect(page.getByLabel("Source example", { exact: true })).toContainText("Wan2.2-T2V-A14B"); + await expect(page.getByRole("button", { name: "Copy", exact: true })).toBeEnabled(); +}); + +test("source model hardware preferences survive hydration and reload", async ({ page }) => { + const errors: string[] = []; + page.on("pageerror", (error) => errors.push(error.message)); + await page.goto("/FastVideo/cookbook/flux/models/flux2-klein-t2i?hardware=custom%3ARTX%204090"); + await expect(page.getByRole("radio", { name: "RTX 4090 Custom device", exact: true })).toBeChecked(); + await page.reload(); + await expect(page.getByRole("radio", { name: "RTX 4090 Custom device", exact: true })).toBeChecked(); + expect(errors).toEqual([]); }); test("custom devices persist and component previews cannot silently generate incompatible YAML", async ({ page }) => { diff --git a/docs-site/tests/test_python_reference.py b/docs-site/tests/test_python_reference.py index ac9d82db8..173b7be32 100644 --- a/docs-site/tests/test_python_reference.py +++ b/docs-site/tests/test_python_reference.py @@ -1,4 +1,5 @@ """Regression checks for source-only API rendering, without importing model code.""" +import ast import importlib.util from pathlib import Path import tempfile @@ -69,6 +70,24 @@ class Empty: self.assertNotIn('[]', rendered) self.assertIn("[", rendered) + def test_example_controls_edit_literals_without_imports_and_use_javascript_offsets(self): + source = '''raise RuntimeError("Never execute this example 🥣") +PROMPT = "A bowl" +generator = VideoGenerator.from_pretrained("Example/Model", num_gpus=1) +parser.add_argument("--num-frames", type=int, default=124) +parser.add_argument("--fps", type=float, default=24) +generator.generate_video(height=480, prompt=PROMPT) +''' + controls = renderer.source_controls(source) + self.assertEqual({item["name"] for item in controls}, {"prompt", "num_gpus", "num_frames", "height", "fps"}) + self.assertFalse(next(item for item in controls if item["name"] == "fps")["integer"]) + frames = next(item for item in controls if item["name"] == "num_frames") + self.assertEqual(frames["flag"], "--num-frames") + for item in controls: + for start, end in item["spans"]: + literal = source.encode("utf-16-le")[start * 2:end * 2].decode("utf-16-le") + self.assertEqual(ast.literal_eval(literal), item["value"]) + def test_class_includes_constructor_documentation_without_a_separate_method(self): for obj, path in [(self.module["Generator"], "sample.Generator"), (self.public["Generator"], "public.Generator")]: diff --git a/docs-site/theme.css b/docs-site/theme.css index 84888b1e5..6cf0794c8 100644 --- a/docs-site/theme.css +++ b/docs-site/theme.css @@ -687,6 +687,30 @@ margin-block-end: 1rem; overflow: clip; } +.recipe-run-modes { + margin-block-end: 1rem; +} +.recipe-command-tools { + display: flex; + flex-wrap: wrap; + gap: 0.375rem; + order: 3; +} +.recipe-command-tools button { + min-block-size: 1.75rem; + padding: 0.25rem 0.625rem; + border: 1px solid var(--recipe-line); + border-radius: 0.375rem; + color: var(--blume-foreground); + background: var(--blume-background); +} +.recipe-command-tools button[aria-pressed="true"] { + border-color: currentColor; +} +.recipe-environment { + padding: 1rem; + border-block-end: 1px solid var(--recipe-line); +} .recipe-command-toolbar { display: flex; flex-wrap: wrap; diff --git a/docs/assets/cookbook-recipes.json b/docs/assets/cookbook-recipes.json index 8b26bf97c..0038beda5 100644 --- a/docs/assets/cookbook-recipes.json +++ b/docs/assets/cookbook-recipes.json @@ -1,5 +1,5 @@ { - "version": 16, + "version": 17, "recipes": [ { "id": "fastwan21-t2v", @@ -832,6 +832,31 @@ "evidence": "Source-backed", "expected_artifact": "MP4 videos under video_samples_matrixgame3/", "related": ["matrix-game-2"] + }, + { + "id": "fasth3-trim-spark", + "family": "minimax_h3", + "stage": "inference", + "task": "Text to video with audio", + "label": "FastH3 Trim", + "summary": "Eight-step video and synchronized audio with the released NVFP4 transformer, text encoder, and lightweight VAE.", + "model": "FastVideo/FastVideo-FastH3-Trim-8-Step-NVFP4", + "source": "examples/inference/basic/basic_fasth3_spark_pruned_nvfp4.yaml", + "command": "FASTVIDEO_MINIMAX_H3_FUSIONS=all FASTVIDEO_NVFP4_MM_BACKEND=cutlass FASTVIDEO_H3_VAE_TILE_BATCH=1 FASTVIDEO_VSA_TRITON=1 FASTVIDEO_VSA_SM100A=0 FASTVIDEO_FA4=0 FASTVIDEO_ATTENTION_BACKEND=VIDEO_SPARSE_ATTN_H3 FASTVIDEO_STAGE_LOGGING=1 fastvideo generate --config examples/inference/basic/basic_fasth3_spark_pruned_nvfp4.yaml", + "gpu_types": [ + "NVIDIA" + ], + "hardware": { + "platform": "cuda", + "gpu_count": 1, + "device": "spark", + "evidence": "source-configured" + }, + "evidence": "Source-backed", + "serving": { + "source": "examples/serving/openai_fasth3_trim_spark.yaml", + "install": "Install FastVideo following the DGX Spark installation guide." + } } ] } diff --git a/docs/contributing/cookbook_configuration.md b/docs/contributing/cookbook_configuration.md index f2f746ada..41d38d127 100644 --- a/docs/contributing/cookbook_configuration.md +++ b/docs/contributing/cookbook_configuration.md @@ -328,8 +328,13 @@ sidebar family group. `docs-site/lib/cookbook-pages.ts` derives the inventory from `docs/assets/cookbook-recipes.json`. Recipes sharing a checkpoint become variants on one model page. `transfer-docs.mjs` generates source-recipe pages and sidebar -entries. Preparation publishes exact checked-in YAML under -`assets/cookbook-sources/`; it does not synthesize settings for these pages. +entries. Preparation publishes checked-in YAML under `assets/cookbook-sources/` +and Python examples with source locations for editable literals under +`assets/cookbook-examples/`. Python examples are parsed with AST, never imported. +Explicit values in the maintained launch command take priority over argparse +defaults. The editor rewrites those literals and preserves required launch flags +and preparation commands. Controls inherited from a helper may use an explicitly +declared cookbook knob. Settings without a source binding stay hidden. For a model with an editable serving catalog, add its display metadata to `recipePages`, map the checkpoint in `backendModels`, and add an MDX overlay with @@ -351,7 +356,22 @@ Old `/cookbook?deployment=` links open the corresponding model page. Provider labels follow the displayed logo. FastVideo-owned releases and converted checkpoints using its mark display `FastVideo` as provider. FastH3 Trim replaces -the obsolete CompactH3 catalog entry; do not restore its local assembly recipes. +the obsolete CompactH3 catalog entry. Its editable NVFP4 deployment uses the +released checkpoint and the maintained one-Spark inference configuration, with +a serving adaptation under `examples/serving/`. Do not restore the old local +assembly recipes or their four-forward sampling settings. + +Every model uses the same header, run modes, command toolbar, hardware matrix, +settings, and reset controls. The top choices are Python SDK, CLI, and Serving, +limited to supported routes. Hardware backends display CUDA or MLX. Serving +appears only where a native server baseline exists. + +The toolbar's Copy action writes the edited YAML or Python example with a quoted +heredoc, then runs the matching command. CUDA catalog pages use the same generator +settings for SDK, CLI, and serving. Inference uses `request`; serving uses `server` +and `default_request`. These commands assume the platform's installation guide +has already been followed. cURL and environment tools appear where the recipe +provides them. Do not invent CLI flags, serving support, or container commands. Custom hardware names can be added through the matrix and persist in the page URL. This is a device preference, not a memory lookup or compatibility result. diff --git a/docs/cookbook/design.md b/docs/cookbook/design.md index ffe770489..3eae75275 100644 --- a/docs/cookbook/design.md +++ b/docs/cookbook/design.md @@ -74,7 +74,7 @@ to documentation, not embedded HTML. ## Shared JavaScript API -`docs/js/cookbook-config.mjs` exports the four functions below. The generated +`docs/js/cookbook-config.mjs` exports the five functions below. The generated `assets/cookbook-config/cookbook-config.js` bundles them with Ajv and exposes the browser global `FastVideoConfigCookbook` and CommonJS exports: @@ -84,6 +84,12 @@ the browser global `FastVideoConfigCookbook` and CommonJS exports: | `loadDeployment(index, id, {signal, fetcher} = {})` | Promise of the selected complete catalog | | `getOptions(catalog, config = catalog.base_config, edits = {})` | `[{path, schema, value}]`, including GPU-dependent degree limits | | `resolveConfig(catalog, edits = {})` | `config`, `yaml`, `argv`, `command`, `clientRequest`, `clientCommand`, optional `websocketUrl` | +| `sampleRequest(metadata, config)` | `{body, command}` and optional `websocketUrl` for a native serving baseline | + +`sampleRequest()` is also used by model pages backed by a checked-in serving +YAML rather than a full editable catalog. Its metadata supplies `model.id`, +`workload`, and `runtime.interface`/`runtime.server_defaults`. It builds client +instructions only; it does not validate the configuration or run a request. For WebSocket deployments, `clientRequest` is `null` and `websocketUrl` is present. REST deployments return a request object and omit `websocketUrl`. diff --git a/docs/cookbook/recipes/fasth3-trim.yaml b/docs/cookbook/recipes/fasth3-trim.yaml new file mode 100644 index 000000000..62b68c69c --- /dev/null +++ b/docs/cookbook/recipes/fasth3-trim.yaml @@ -0,0 +1,51 @@ +title: FastH3 Trim +summary: Eight-step video and audio from the released NVFP4 checkpoint. +guide: docs/getting_started/installation/spark_performance.md +deployments: + spark-rest: + label: DGX Spark REST + runtime: fastvideo-cuda-rest + workload: t2v + defaults: examples/serving/openai_fasth3_trim_spark.yaml + env: + FASTVIDEO_MINIMAX_H3_FUSIONS: all + FASTVIDEO_NVFP4_MM_BACKEND: cutlass + FASTVIDEO_H3_VAE_TILE_BATCH: "1" + FASTVIDEO_VSA_TRITON: "1" + FASTVIDEO_VSA_SM100A: "0" + FASTVIDEO_FA4: "0" + FASTVIDEO_ATTENTION_BACKEND: VIDEO_SPARSE_ATTN_H3 + FASTVIDEO_STAGE_LOGGING: "1" + requirements: + - Install FastVideo using the DGX Spark guide before running these commands. + - Based on the released one-Spark inference recipe. This serving adaptation and edited hardware combinations have not been GPU-validated. + - The checkpoint includes NVFP4 weights and encoder, a lightweight video VAE, and its trained eight-forward schedule. No local CompactH3 assembly is needed. + options: + - server.* + - generator.engine.num_gpus + - generator.engine.parallelism.tp_size + - generator.engine.parallelism.sp_size + - generator.engine.offload.text_encoder + - generator.engine.offload.vae + - default_request.prompt + - default_request.sampling.num_frames + - default_request.sampling.height + - default_request.sampling.width + - default_request.sampling.seed + overrides: + default_request.prompt: + title: Prompt + type: string + minLength: 1 + default_request.sampling.num_frames: + enum: [124, 243, 345] + default: 124 + description: Native H3 frame counts. Hardware fit has not been verified. + default_request.sampling.height: + minimum: 32 + multipleOf: 32 + default: 480 + default_request.sampling.width: + minimum: 32 + multipleOf: 32 + default: 832 diff --git a/docs/js/cookbook-config.mjs b/docs/js/cookbook-config.mjs index 48742382e..867c0c129 100644 --- a/docs/js/cookbook-config.mjs +++ b/docs/js/cookbook-config.mjs @@ -336,7 +336,7 @@ function toYaml(value, depth = 0) { } /** Build same-machine client instructions; a bind-all address is not a client destination. */ -function sampleRequest(catalog, config) { +export function sampleRequest(catalog, config) { const server = { ...catalog.runtime.server_defaults, ...config.server }; let host = server.host; if (host === "0.0.0.0") host = "127.0.0.1"; @@ -351,7 +351,10 @@ function sampleRequest(catalog, config) { } const components = config.generator?.pipeline?.components; const model = components?.lora_path ? components.lora_nickname : server.served_model_name || catalog.model.id; - const body = { ...(model === undefined ? {} : { model }), prompt: "A river flowing through a peaceful forest" }; + const body = { + ...(model === undefined ? {} : { model }), + prompt: config.default_request?.prompt ?? "A river flowing through a peaceful forest", + }; if (catalog.workload === "i2v") body.input_reference = "/absolute/path/to/first-frame.png"; const argv = [ "curl", diff --git a/docs/tests/cookbook-config.test.mjs b/docs/tests/cookbook-config.test.mjs index bb7f2cb03..703a795ae 100644 --- a/docs/tests/cookbook-config.test.mjs +++ b/docs/tests/cookbook-config.test.mjs @@ -103,6 +103,7 @@ test("browser bundle exposes reusable methods and its error class with no DOM or "loadDeployment", "loadIndex", "resolveConfig", + "sampleRequest", ]); const api = context.FastVideoConfigCookbook; assert.equal(api.resolveConfig(catalog(), { "server.port": 9000 }).config.server.port, 9000); @@ -485,6 +486,14 @@ test("LoRA sample requests use the startup adapter instead of an edited server a assert.equal(resolveConfig(data, edits).clientRequest.model, "different-server-name"); }); +test("sample requests honor an explicitly configured prompt", () => { + const data = catalog(); + data.controls.push({ path: "default_request.prompt", schema: { type: "string" } }); + const result = resolveConfig(data, { "default_request.prompt": "A potter finishes a blue bowl." }); + assert.equal(result.clientRequest.prompt, "A potter finishes a blue bowl."); + assert.match(result.clientCommand, /A potter finishes a blue bowl/); +}); + test("environment variables are present and shell quoted without evaluation", () => { const data = catalog(); data.env = { BACKEND: "it's literal $(touch /never-run)" }; diff --git a/examples/serving/openai_fasth3_trim_spark.yaml b/examples/serving/openai_fasth3_trim_spark.yaml new file mode 100644 index 000000000..c517873f8 --- /dev/null +++ b/examples/serving/openai_fasth3_trim_spark.yaml @@ -0,0 +1,55 @@ +# FastH3 Trim NVFP4. Generator and sampling defaults follow the released +# one-Spark recipe: examples/inference/basic/basic_fasth3_spark_pruned_nvfp4.yaml. +# Install with the DGX Spark guide. This serving adaptation is not GPU-validated. +generator: + model_path: FastVideo/FastVideo-FastH3-Trim-8-Step-NVFP4 + engine: + num_gpus: 1 + use_fsdp_inference: false + quantization: + transformer_quant: NVFP4 + layer_profile: h3_dit_vsa + parallelism: + tp_size: 1 + sp_size: 1 + offload: + dit: false + dit_layerwise: false + text_encoder: false + image_encoder: false + vae: false + pin_cpu_memory: false + lazy_module_load: false + compile: + enabled: false + vae_enabled: false + pipeline: + workload_type: t2v + vae_tiling: true + experimental: + attention_backend: VIDEO_SPARSE_ATTN_H3 + VSA_sparsity: 0.8 + VSA_tile_size: 64 + h3_sequential_load: false + inference_torch_compile: false + vae_parallel_decode: false + video_decode_backend: h3-vae +server: + host: 127.0.0.1 + port: 8000 + output_dir: outputs/fasth3_trim_server + served_model_name: fasth3-trim +default_request: + prompt: A quiet pottery studio with a potter finishing a bowl at the wheel. + negative_prompt: '' + sampling: + seed: 1234 + height: 480 + width: 832 + num_frames: 124 + fps: 24 + num_inference_steps: 9 + guidance_scale: 1.0 + batch_cfg: false + output: + return_frames: false