code wiki / (root) / nx_gen_zoo.nx

nx_gen_zoo.nx source

↩ module page · 195 lines · 7056 B

1// nx_gen_zoo.nx -- walk a model directory, identify every file, and report which PIPELINES are 2// runnable. ComfyUI's capability without ComfyUI's interface. 3// 4// You should not have to know what you downloaded. Point this at a models tree and it answers the 5// only questions that matter: what is each file, and can I generate an image with what I have? 6// 7// It calls nx_genrole for every classification -- genuinely, not as a claim. This header used 8// to assert that reuse while zo_classify re-derived every probe, and the two copies had already 9// drifted apart. See nx_genrole.nx. 10// 11// Usage: nx_gen_zoo <dir> [dir2] [dir3] ... 12// 13// A pipeline is reported RUNNABLE only when every required role is present AND runnable for the 14// same family. Missing pieces are named, so the answer is actionable rather than a verdict. 15// license_tier: ORIGINAL 16 17import "nx_syscalls.nx" 18import "nx_le.nx" 19import "nx_f32.nx" 20import "nx_f32_div.nx" 21import "nx_f32_cvt.nx" 22import "nx_f16.nx" 23import "nx_strconv.nx" 24import "nx_genver.nx" 25import "nx_genweights.nx" 26import "nx_genarch.nx" 27import "nx_genrole.nx" 28const ZOO_MAGIC_65536: i64 = 65536 29const ZOO_MAGIC_1024: i64 = 1024 30 31const ZOO_MAX: i64 = 256 32 33func zo_puts(s: *u8) -> i64 { 34 var n: i64 = 0 35 while s[n] != (0 as u8) { n = n + 1 } 36 return sys_write(1, s, n) 37} 38func zo_len(s: *u8) -> i64 { 39 var n: i64 = 0 40 while s[n] != (0 as u8) { n = n + 1 } 41 return n 42} 43func zo_pad(s: *u8, w: i64) -> i64 { 44 let n: i64 = zo_len(s) 45 sys_write(1, s, n) 46 var i: i64 = n 47 while i < w { sys_write(1, " " as *u8, 1); i = i + 1 } 48 return 0 49} 50func zo_has(gw: *i64, name: *u8) -> i64 { 51 if nx_gw_find(gw, name, zo_len(name)) < 0 { return 0 } 52 return 1 53} 54func zo_join(out: *u8, dir: *u8, name: *u8) -> *u8 { 55 var o: i64 = 0 56 var i: i64 = 0 57 while dir[i] != (0 as u8) { out[o] = dir[i]; o = o + 1; i = i + 1 } 58 if o > 0 { if out[o - 1] != (0x2F as u8) { out[o] = 0x2F; o = o + 1 } } 59 i = 0 60 while name[i] != (0 as u8) { out[o] = name[i]; o = o + 1; i = i + 1 } 61 out[o] = 0 62 return out 63} 64 65static g_have_dit: i64 66static g_have_vae: i64 67static g_have_te: i64 68static g_n_adapter: i64 69static g_n_unknown: i64 70 71// Classification now lives in nx_genrole -- ONE copy, three consumers. It used to live here too, 72// and the two copies had ALREADY drifted: this one printed "adapter-lora(peft)" with no family 73// while nx_gen_modelid resolved the target family from the same bytes. 74// ★★★★★ A COMMENT ASSERTING DRY IS NOT DRY -- this function's header claimed it reused modelid's 75// probes while re-deriving every one of them. 76func zo_classify(path: *u8, label: *u8) -> i64 { 77 let gw: *i64 = nx_gw_open(path) 78 zo_pad(label, 44) 79 if (gw as i64) == 0 { 80 zo_puts("unreadable (not gguf/safetensors)\n" as *u8) 81 g_n_unknown = g_n_unknown + 1 82 return 0 83 } 84 let rl: *i64 = sys_mmap(RL_SLOTS * 8 + 64) as *i64 85 let role: i64 = nx_role_probe(gw, rl) 86 zo_pad(nx_family_name(rl[RL_FAMILY]), 10) 87 zo_pad(nx_role_name(role), 13) 88 if role == ROLE_ADAPTER { zo_pad(nx_adkind_name(rl[RL_ADKIND]), 13) } 89 else { zo_pad("" as *u8, 13) } 90 91 if rl[RL_RUNNABLE] == 1 { 92 if role == ROLE_DIT { 93 let arch: *i64 = sys_mmap(NX_ARCH_SLOTS * 8 + 64) as *i64 94 if nx_arch_probe(gw, arch) == 0 { 95 let b: *u8 = sys_mmap(32) 96 zo_puts("layers=" as *u8) 97 sys_write(1, b, nx_strconv_format_i64(arch[NX_ARCH_N_LAYERS], b)) 98 zo_puts(" heads=" as *u8) 99 sys_write(1, b, nx_strconv_format_i64(arch[NX_ARCH_N_HEADS], b)) 100 zo_puts(" " as *u8) 101 } 102 } 103 zo_puts("RUNNABLE\n" as *u8) 104 } else { 105 zo_puts("blocked: " as *u8) 106 zo_puts(nx_role_blocker(rl)) 107 zo_puts("\n" as *u8) 108 } 109 110 if role == ROLE_ADAPTER { g_n_adapter = g_n_adapter + 1; return role } 111 if role == ROLE_UNKNOWN { g_n_unknown = g_n_unknown + 1; return role } 112 // Only a RUNNABLE part counts toward the pipeline verdict: an sd-vae we cannot decode must not 113 // make the zoo report that a vae decoder is present. 114 if rl[RL_RUNNABLE] == 1 { 115 if role == ROLE_DIT { g_have_dit = g_have_dit + 1 } 116 if role == ROLE_VAE_DEC { g_have_vae = g_have_vae + 1 } 117 if role == ROLE_TEXTENC { g_have_te = g_have_te + 1 } 118 } 119 return role 120} 121 122func zo_walk(dir: *u8) -> i64 { 123 let fd: i64 = sys_openat_rd(dir) 124 if fd < 0 { zo_puts(" (cannot open dir)\n" as *u8); return 0 - 1 } 125 let buf: *u8 = sys_mmap(ZOO_MAGIC_65536) 126 let path: *u8 = sys_mmap(ZOO_MAGIC_1024) 127 var go: i64 = 1 128 while go == 1 { 129 let n: i64 = sys_getdents64(fd, buf, ZOO_MAGIC_65536) 130 if n <= 0 { go = 0 } 131 else { 132 var off: i64 = 0 133 while off < n { 134 let ent: *u8 = ((buf as i64) + off) as *u8 135 let rl: i64 = dirent_reclen(ent) 136 let ty: i64 = dirent_type(ent) 137 let nm: *u8 = dirent_name(ent) 138 // 8 = DT_REG. Skip dot entries; a name starting '.' is never a model here. 139 if ty == 8 { 140 if nm[0] != (0x2E as u8) { 141 zo_classify(zo_join(path, dir, nm), nm) 142 } 143 } 144 if rl <= 0 { off = n } else { off = off + rl } 145 } 146 } 147 } 148 sys_close(fd) 149 return 0 150} 151 152func main(argc: i64, argv: *i64) -> i64 { 153 if argc < 2 { 154 zo_puts("usage: nx_gen_zoo <dir> [dir2 ...]\n" as *u8) 155 return 2 156 } 157 g_have_dit = 0 158 g_have_vae = 0 159 g_have_te = 0 160 g_n_adapter = 0 161 g_n_unknown = 0 162 163 zo_puts("=== NISHI GEN ZOO ===\n" as *u8) 164 var a: i64 = 1 165 while a < argc { 166 zo_puts("-- " as *u8) 167 zo_puts(argv[a] as *u8) 168 zo_puts("\n" as *u8) 169 zo_walk(argv[a] as *u8) 170 a = a + 1 171 } 172 173 zo_puts("=== PIPELINE ===\n" as *u8) 174 nx_genver_emit("runnable_dits" as *u8, g_have_dit) 175 nx_genver_emit("runnable_vae_decoders" as *u8, g_have_vae) 176 nx_genver_emit("text_encoders" as *u8, g_have_te) 177 nx_genver_emit("adapters" as *u8, g_n_adapter) 178 nx_genver_emit("unidentified" as *u8, g_n_unknown) 179 180 // Report what is MISSING by name, not just a verdict -- a bare NO is not actionable. 181 if g_have_dit > 0 { 182 if g_have_vae > 0 { 183 if g_have_te > 0 { 184 zo_puts("VERDICT: image generation RUNNABLE (dit + vae-decoder present; text encoder is third-party)\n" as *u8) 185 return 0 186 } 187 zo_puts("VERDICT: blocked -- no text encoder found\n" as *u8) 188 return 1 189 } 190 zo_puts("VERDICT: blocked -- no RUNNABLE vae decoder (taesd) found\n" as *u8) 191 return 1 192 } 193 zo_puts("VERDICT: blocked -- no runnable DiT found\n" as *u8) 194 return 1 195}