Voice / vlib /pack.py
Wiself's picture
V 3
90f10d2
Raw History Blame Contribute Delete
3.25 kB
"""Head-only voice-pack preset (unused by the CLI)."""
import argparse
import json
import urllib.error
from pathlib import Path
from vlib import ctx
from vlib.fetch import _fetch_pack, _resolve_output_name, _source_arch
from vlib.sources import (_family, _hf_config, _public_source,
_slugify_voice_name, open_source)
from vlib.tensors import write_safetensors
from vlib.ui import _fail, _note, _now_iso, _say, _step
def _resolve_pack_tensors(source, repo, config, names):
"""Head-only voice-pack preset. Embed/norm/blocks stay manual
(voice get <repo> <tensors...>).
Config is the source config with _hf_config fallback. Miss fails loud."""
if config is None and getattr(source, "repo", None):
config = _hf_config(source.repo)
head = _resolve_output_name(source, config, names)
if head is None:
_fail(f" ✗ pack: no output head found in '{repo}'.")
return [head]
def cmd_pack(args):
repo = args.repo.strip().rstrip("/")
if not repo:
_fail(" ✗ Enter a model name — for example: voice pack google/gemma-3-1b")
_step(f"Finding the voice pack in {repo}…")
try:
source = open_source(repo)
names = source.names()
if not names:
_fail(f" ✗ No tensors found in '{repo}'.")
arch, config = _source_arch(source)
except urllib.error.HTTPError as e:
_fail(f" ✗ Model '{repo}' was not found or is not accessible ({e.code}).")
except Exception as e:
if ctx.VERBOSE:
import traceback
_say(traceback.format_exc())
_fail(f" ✗ Could not reach the model. Check your connection ({type(e).__name__}).")
_step("Resolving voice-pack tensors…")
resolved = _resolve_pack_tensors(source, repo, config, names)
for tname in resolved:
_note(f" {tname}")
# Fetch via the same multi path as get --multi, then save flat in the
# registry through the existing add machinery (no new storage format).
pack = _fetch_pack(source, repo, resolved)
slug = _slugify_voice_name(repo.split("/")[-1].split("@")[0].split(":")[0].replace(".gguf", "").replace(".safetensors", ""))
name = f"pack-{slug}"
import tempfile, shutil
stage = Path(tempfile.mkdtemp(prefix="voicepack-stage-"))
try:
st_path = stage / "voice.safetensors"
write_safetensors(pack, str(st_path))
js_path = stage / "voice.json"
js_path.write_text(json.dumps({
"name": name,
"source": _public_source(repo),
"source_format": source.kind,
"tensors": [{"name": n, "shape": [int(x) for x in pack[n][2]], "dtype": pack[n][1]}
for n in resolved if n in pack],
"architecture": arch,
"family": _family(arch),
"downloaded_at": _now_iso(),
}, indent=2) + "\n")
from vlib.cmds_voices import cmd_add
cmd_add(argparse.Namespace(safetensors=str(st_path), json=str(js_path), name=name,
yes=getattr(args, "yes", False),
non_interactive=getattr(args, "non_interactive", False)))
finally:
shutil.rmtree(stage, ignore_errors=True)