/* SPDX-License-Identifier: AGPL-3.0-or-later */ /* Copyright (C) 2026 David (Corey) Herrera */ /* * ternarize-merge: Assemble final safetensors with packed ternary weights + scales. * * Usage: * ternarize-merge --workdir ./work --output ternary-model.safetensors */ #include "../ternarize/ternarize.h" #include #include #include static void usage(const char *prog) { fprintf(stderr, "Usage: %s --workdir --output \n", prog); fprintf(stderr, "\nOptions:\n"); fprintf(stderr, " --workdir Work directory (with completed flip layers)\n"); fprintf(stderr, " --output Output safetensors file path\n"); fprintf(stderr, " --config Path to config.json (re-parse architecture)\n"); } int main(int argc, char **argv) { ft_config cfg = ft_config_defaults(); const char *workdir = NULL; const char *output = NULL; const char *config_path = NULL; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--workdir") == 0 && i + 1 < argc) { workdir = argv[++i]; } else if (strcmp(argv[i], "--output") == 0 && i + 1 < argc) { output = argv[++i]; } else if (strcmp(argv[i], "--config") == 0 && i + 1 < argc) { config_path = argv[++i]; } else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { usage(argv[0]); return 0; } else { fprintf(stderr, "Unknown option: %s\n", argv[i]); usage(argv[0]); return 1; } } if (!workdir || !output) { usage(argv[0]); return 1; } if (config_path) { if (!ft_config_from_json(&cfg, config_path)) { fprintf(stderr, "ERROR: failed to parse %s\n", config_path); return 1; } } snprintf(cfg.workdir, sizeof(cfg.workdir), "%s", workdir); /* Read status to get n_layers if needed */ if (cfg.n_layers == 0) { ft_status st = ft_status_read(&cfg); cfg.n_layers = st.n_layers; } fprintf(stderr, "ternarize-merge\n"); fprintf(stderr, " Workdir: %s\n", workdir); fprintf(stderr, " Output: %s\n", output); fprintf(stderr, " Layers: %d\n", cfg.n_layers); if (!ft_merge(&cfg, output)) { fprintf(stderr, "ERROR: merge failed\n"); return 1; } return 0; }