@tuned-tensor/cli 0.24.0 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +178 -18
- package/dist/chunk-4BHDPRYD.js +2813 -0
- package/dist/chunk-4BHDPRYD.js.map +1 -0
- package/dist/{chunk-RPWOCVIL.js → chunk-FLRRDP3M.js} +2899 -3871
- package/dist/chunk-FLRRDP3M.js.map +1 -0
- package/dist/index.js +2902 -1869
- package/dist/index.js.map +1 -1
- package/dist/local-runtime.js +228 -72
- package/dist/local-runtime.js.map +1 -1
- package/dist/prefetch-DH365HNN.js +18 -0
- package/dist/prefetch-DH365HNN.js.map +1 -0
- package/docs/local-runtime/architecture.md +52 -1
- package/docs/local-runtime/aws-gpu.md +15 -0
- package/docs/local-runtime/background-runs.md +77 -0
- package/docs/local-runtime/decision.md +5 -0
- package/docs/local-runtime/serving.md +11 -2
- package/docs/spec-workflow.md +89 -5
- package/package.json +6 -2
- package/training/adapter/src/evaluate.py +127 -34
- package/training/adapter/src/model_contract.py +13 -0
- package/training/adapter/src/prefetch.py +11 -5
- package/training/adapter/src/serve.py +30 -0
- package/training/adapter/src/train.py +5 -1
- package/dist/chunk-RPWOCVIL.js.map +0 -1
|
@@ -137,6 +137,16 @@ def verify_snapshot(snapshot: Path, expected_model_id: str | None = None) -> tup
|
|
|
137
137
|
return files, verified_blobs
|
|
138
138
|
|
|
139
139
|
|
|
140
|
+
def check_requested_revision(base_model: str, revision: str | None, resolve_latest: bool) -> None:
|
|
141
|
+
"""Certified models keep their reviewed revision. An uncertified model needs
|
|
142
|
+
a pinned commit, except for a direct download that resolves its latest
|
|
143
|
+
commit (`tt models prefetch --repo`); the resolved SHA is reported so the
|
|
144
|
+
spec can pin it."""
|
|
145
|
+
if resolve_latest and revision is None and not is_certified_base_model(base_model):
|
|
146
|
+
return
|
|
147
|
+
assert_certified_base_model_revision(base_model, revision, "Prefetch base model revision")
|
|
148
|
+
|
|
149
|
+
|
|
140
150
|
def main() -> None:
|
|
141
151
|
parser = argparse.ArgumentParser(description="Prefetch a TT Hugging Face base model for local use.")
|
|
142
152
|
parser.add_argument("--input", required=True)
|
|
@@ -147,11 +157,7 @@ def main() -> None:
|
|
|
147
157
|
base_model = str(payload["base_model"])
|
|
148
158
|
assert_certified_base_model(base_model, "Prefetch base model")
|
|
149
159
|
requested_revision = payload.get("revision")
|
|
150
|
-
|
|
151
|
-
base_model,
|
|
152
|
-
requested_revision,
|
|
153
|
-
"Prefetch base model revision",
|
|
154
|
-
)
|
|
160
|
+
check_requested_revision(base_model, requested_revision, bool(payload.get("resolve_latest")))
|
|
155
161
|
cache_dir = payload.get("model_cache")
|
|
156
162
|
configure_hugging_face_cache(cache_dir)
|
|
157
163
|
|
|
@@ -63,6 +63,35 @@ def pin_native_content_format(args: list[str], model_source: str) -> None:
|
|
|
63
63
|
args += ["--chat-template-content-format", content_format]
|
|
64
64
|
|
|
65
65
|
|
|
66
|
+
def prepare_serving_adapter(adapter_path: str, temp_dir: Path) -> str:
|
|
67
|
+
# Transformers trains Qwen's text-only model, but vLLM loads the repository's
|
|
68
|
+
# conditional architecture, even with --language-model-only. Its LoRA mapper
|
|
69
|
+
# expects the language_model prefix; otherwise it silently misses our layers.
|
|
70
|
+
if os.environ.get("TT_BASE_MODEL") != "Qwen/Qwen3.5-2B":
|
|
71
|
+
return adapter_path
|
|
72
|
+
from safetensors import safe_open
|
|
73
|
+
from safetensors.torch import save_file
|
|
74
|
+
|
|
75
|
+
source = Path(adapter_path)
|
|
76
|
+
old = "base_model.model.model.layers."
|
|
77
|
+
new = "base_model.model.model.language_model.layers."
|
|
78
|
+
with safe_open(str(source / "adapter_model.safetensors"), framework="pt", device="cpu") as weights:
|
|
79
|
+
if not any(key.startswith(old) for key in weights.keys()):
|
|
80
|
+
return adapter_path
|
|
81
|
+
tensors = {}
|
|
82
|
+
for key in weights.keys():
|
|
83
|
+
mapped = new + key[len(old):] if key.startswith(old) else key
|
|
84
|
+
if mapped in tensors:
|
|
85
|
+
raise ValueError("Adapter contains conflicting text and conditional layer names.")
|
|
86
|
+
tensors[mapped] = weights.get_tensor(key)
|
|
87
|
+
destination = temp_dir / "serving-adapter"
|
|
88
|
+
destination.mkdir()
|
|
89
|
+
save_file(tensors, str(destination / "adapter_model.safetensors"), metadata=weights.metadata())
|
|
90
|
+
# Keep the verified archive and extracted training layout unchanged.
|
|
91
|
+
(destination / "adapter_config.json").write_bytes((source / "adapter_config.json").read_bytes())
|
|
92
|
+
return str(destination)
|
|
93
|
+
|
|
94
|
+
|
|
66
95
|
def build_vllm_args(model_source: str, adapter_path: str | None, temp_dir: Path) -> list[str]:
|
|
67
96
|
args = [
|
|
68
97
|
"serve", model_source,
|
|
@@ -101,6 +130,7 @@ def build_vllm_args(model_source: str, adapter_path: str | None, temp_dir: Path)
|
|
|
101
130
|
adapter_base = config.get("base_model_name_or_path")
|
|
102
131
|
if adapter_base not in {os.environ["TT_BASE_MODEL"], model_source}:
|
|
103
132
|
raise ValueError("The adapter base does not match the verified serving model.")
|
|
133
|
+
adapter_path = prepare_serving_adapter(adapter_path, temp_dir)
|
|
104
134
|
base_name = "base:" + os.environ["TT_BASE_MODEL"]
|
|
105
135
|
args[args.index("--served-model-name") + 1] = base_name
|
|
106
136
|
args += ["--enable-lora", "--max-lora-rank", str(max(8, int(config["r"]))),
|
|
@@ -26,6 +26,7 @@ from model_contract import (
|
|
|
26
26
|
assert_certified_base_model_revision,
|
|
27
27
|
assert_certified_model_config,
|
|
28
28
|
chat_template_kwargs,
|
|
29
|
+
cuda_model_load_device_map,
|
|
29
30
|
parse_lora_target_modules,
|
|
30
31
|
uncertified_load_kwargs,
|
|
31
32
|
)
|
|
@@ -216,13 +217,16 @@ def create_model_and_tokenizer(model_source: str) -> tuple[Any, Any, torch.dtype
|
|
|
216
217
|
if hp("model_loader", "causal_lm") == "image_text_to_text"
|
|
217
218
|
else AutoModelForCausalLM
|
|
218
219
|
)
|
|
220
|
+
load_device_map = cuda_model_load_device_map(torch)
|
|
219
221
|
model = model_class.from_pretrained(
|
|
220
222
|
model_source,
|
|
221
223
|
**source_kwargs,
|
|
222
224
|
**uncertified_load_kwargs(str(hp("base_model", CERTIFIED_BASE_MODEL))),
|
|
223
225
|
dtype=dtype,
|
|
224
|
-
device_map=
|
|
226
|
+
device_map=load_device_map,
|
|
225
227
|
)
|
|
228
|
+
if load_device_map is None:
|
|
229
|
+
model = model.to("cuda")
|
|
226
230
|
assert_certified_model_config(
|
|
227
231
|
model.config,
|
|
228
232
|
expected_model_id=str(hp("base_model", CERTIFIED_BASE_MODEL)),
|