Instructions to use brandonmusic/GLM-5.2-EXL3-TR3v4-3.5bpw-MTP78 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Trellis
How to use brandonmusic/GLM-5.2-EXL3-TR3v4-3.5bpw-MTP78 with Trellis:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
Shakeout fixes: CUDA-free platform probe, 16-way parallel verify, sharded forward w/ replica parity, transformers==5.12.1 pin, torchvision removal
Browse files- r7_encoder/inventory.py +19 -2
- r7_encoder/transformers_runtime.py +132 -28
- run_scripts/setup_box.sh +7 -1
r7_encoder/inventory.py
CHANGED
|
@@ -248,11 +248,22 @@ def verify_checkpoint_inventory(
|
|
| 248 |
raw_shards = payload.get("shards")
|
| 249 |
if not isinstance(raw_shards, dict):
|
| 250 |
raise ValueError("checkpoint inventory lacks shard map")
|
| 251 |
-
|
|
|
|
| 252 |
if not isinstance(record, dict) or sha256_file(root / shard_name) != record.get(
|
| 253 |
"file_sha256"
|
| 254 |
):
|
| 255 |
raise ValueError(f"checkpoint shard changed after inventory: {shard_name}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 256 |
auxiliary = payload.get("auxiliary_files_sha256")
|
| 257 |
if not isinstance(auxiliary, dict) or not auxiliary:
|
| 258 |
raise ValueError("checkpoint inventory lacks auxiliary/tokenizer assets")
|
|
@@ -396,7 +407,13 @@ def _collect_execution_platform(
|
|
| 396 |
"torch_version": str(torch.__version__),
|
| 397 |
"torch_git_version": str(getattr(torch.version, "git_version", "UNKNOWN")),
|
| 398 |
"torch_cuda_build": str(torch.version.cuda),
|
| 399 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 400 |
"device": _nvidia_device_record(device),
|
| 401 |
"torch_numerical_binaries_sha256": torch_binaries,
|
| 402 |
"dynamic_dependency_closure_sha256": _dynamic_library_closure(dynamic_roots),
|
|
|
|
| 248 |
raw_shards = payload.get("shards")
|
| 249 |
if not isinstance(raw_shards, dict):
|
| 250 |
raise ValueError("checkpoint inventory lacks shard map")
|
| 251 |
+
def _check_shard(item):
|
| 252 |
+
shard_name, record = item
|
| 253 |
if not isinstance(record, dict) or sha256_file(root / shard_name) != record.get(
|
| 254 |
"file_sha256"
|
| 255 |
):
|
| 256 |
raise ValueError(f"checkpoint shard changed after inventory: {shard_name}")
|
| 257 |
+
|
| 258 |
+
# Hash shards in parallel; identical failure semantics (any mismatch
|
| 259 |
+
# raises), deterministic because each check is independent and the full
|
| 260 |
+
# set must pass. Turns a ~25-minute single-thread startup verify into a
|
| 261 |
+
# few minutes on every launch and resume.
|
| 262 |
+
from concurrent.futures import ThreadPoolExecutor
|
| 263 |
+
|
| 264 |
+
with ThreadPoolExecutor(max_workers=16) as _pool:
|
| 265 |
+
for _ in _pool.map(_check_shard, sorted(raw_shards.items())):
|
| 266 |
+
pass
|
| 267 |
auxiliary = payload.get("auxiliary_files_sha256")
|
| 268 |
if not isinstance(auxiliary, dict) or not auxiliary:
|
| 269 |
raise ValueError("checkpoint inventory lacks auxiliary/tokenizer assets")
|
|
|
|
| 407 |
"torch_version": str(torch.__version__),
|
| 408 |
"torch_git_version": str(getattr(torch.version, "git_version", "UNKNOWN")),
|
| 409 |
"torch_cuda_build": str(torch.version.cuda),
|
| 410 |
+
# cuDNN build parsed from static build info: torch.backends.cudnn
|
| 411 |
+
# .version() initializes CUDA, which would trip the runtime's
|
| 412 |
+
# CUDA-purity gate 26 minutes later at walk startup.
|
| 413 |
+
"torch_cudnn_build": (
|
| 414 |
+
(re.search(r"CuDNN[^\n]*?([\d.]+)", torch.__config__.show())
|
| 415 |
+
or [None, "UNKNOWN"])[1]
|
| 416 |
+
),
|
| 417 |
"device": _nvidia_device_record(device),
|
| 418 |
"torch_numerical_binaries_sha256": torch_binaries,
|
| 419 |
"dynamic_dependency_closure_sha256": _dynamic_library_closure(dynamic_roots),
|
r7_encoder/transformers_runtime.py
CHANGED
|
@@ -220,6 +220,12 @@ class TransformersSequentialRuntime(GLM52Runtime):
|
|
| 220 |
)
|
| 221 |
|
| 222 |
self.device = torch.device(config.device)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
if self.device.type != "cuda":
|
| 224 |
raise ValueError(
|
| 225 |
"the owner-run GLM reference runtime requires one CUDA device"
|
|
@@ -506,7 +512,8 @@ class TransformersSequentialRuntime(GLM52Runtime):
|
|
| 506 |
"auxiliary": "prev_topk_indices-int32",
|
| 507 |
}
|
| 508 |
|
| 509 |
-
def _context(self, hidden, metadata: Mapping[str, object]):
|
|
|
|
| 510 |
import torch
|
| 511 |
|
| 512 |
tokens = int(metadata["tokens"])
|
|
@@ -517,21 +524,21 @@ class TransformersSequentialRuntime(GLM52Runtime):
|
|
| 517 |
):
|
| 518 |
raise ValueError("state metadata is not the pinned one-prompt DSA schema")
|
| 519 |
x = (
|
| 520 |
-
torch.as_tensor(hidden, device=
|
| 521 |
.reshape(1, tokens, HIDDEN_SIZE)
|
| 522 |
.to(torch.bfloat16)
|
| 523 |
)
|
| 524 |
-
position_ids = torch.arange(tokens, device=
|
| 525 |
minimum = torch.finfo(x.dtype).min
|
| 526 |
causal = torch.full(
|
| 527 |
-
(tokens, tokens), minimum, device=
|
| 528 |
).triu(diagonal=1)
|
| 529 |
attention_mask = causal.unsqueeze(0).unsqueeze(0)
|
| 530 |
position_embeddings = self.rotary(x, position_ids)
|
| 531 |
previous = metadata.get("prev_topk_indices")
|
| 532 |
if previous is not None:
|
| 533 |
previous = torch.as_tensor(
|
| 534 |
-
previous, device=
|
| 535 |
).unsqueeze(0)
|
| 536 |
return x, attention_mask, position_ids, position_embeddings, previous
|
| 537 |
|
|
@@ -562,12 +569,12 @@ class TransformersSequentialRuntime(GLM52Runtime):
|
|
| 562 |
gate_up = torch.empty(
|
| 563 |
(NUM_EXPERTS, 2 * INTERMEDIATE_SIZE, HIDDEN_SIZE),
|
| 564 |
dtype=torch.bfloat16,
|
| 565 |
-
device=
|
| 566 |
)
|
| 567 |
down = torch.empty(
|
| 568 |
(NUM_EXPERTS, HIDDEN_SIZE, INTERMEDIATE_SIZE),
|
| 569 |
dtype=torch.bfloat16,
|
| 570 |
-
device=
|
| 571 |
)
|
| 572 |
for expert in range(NUM_EXPERTS):
|
| 573 |
gate_up[expert, :INTERMEDIATE_SIZE] = installed[expert][
|
|
@@ -594,8 +601,8 @@ class TransformersSequentialRuntime(GLM52Runtime):
|
|
| 594 |
module.eval()
|
| 595 |
return module
|
| 596 |
|
| 597 |
-
def _advance(self, module, hidden, metadata):
|
| 598 |
-
context = self._context(hidden, metadata)
|
| 599 |
x, mask, positions, rotary, previous = context
|
| 600 |
with __import__("torch").inference_mode():
|
| 601 |
output, topk = module(
|
|
@@ -1360,22 +1367,25 @@ class TransformersSequentialRuntime(GLM52Runtime):
|
|
| 1360 |
}
|
| 1361 |
carrier_audit = sha256_bytes(canonical_json_bytes(layer_records))
|
| 1362 |
first_shard_id = input_values[0].shard_id
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1363 |
try:
|
| 1364 |
-
|
| 1365 |
-
if shard.shard_id in completed_shard_ids:
|
| 1366 |
-
continue
|
| 1367 |
reader = SafeTensorReader(shard.hidden_path)
|
| 1368 |
hidden = read_torch_tensor(reader, "hidden")
|
| 1369 |
previous = read_torch_tensor(reader, "prev_topk_indices")
|
| 1370 |
metadata = read_json(shard.metadata_path)
|
| 1371 |
metadata["prev_topk_indices"] = previous
|
| 1372 |
-
|
| 1373 |
-
|
| 1374 |
-
|
| 1375 |
-
)
|
| 1376 |
-
else:
|
| 1377 |
-
output, topk = self._advance(module, hidden, metadata)
|
| 1378 |
-
repeat_audit = None
|
| 1379 |
successor = dict(metadata)
|
| 1380 |
successor.pop("prev_topk_indices", None)
|
| 1381 |
successor["producer"] = f"round7-installed-layer-{layer:03d}"
|
|
@@ -1383,18 +1393,112 @@ class TransformersSequentialRuntime(GLM52Runtime):
|
|
| 1383 |
successor["carrier_decode_audit_sha256"] = carrier_audit
|
| 1384 |
if repeat_audit is not None:
|
| 1385 |
successor["official_repeat_audit"] = repeat_audit
|
| 1386 |
-
|
| 1387 |
-
|
| 1388 |
-
|
| 1389 |
-
|
| 1390 |
-
|
| 1391 |
-
|
| 1392 |
-
|
| 1393 |
-
|
| 1394 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1395 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1396 |
finally:
|
| 1397 |
del module
|
|
|
|
|
|
|
|
|
|
| 1398 |
self._installed.pop(layer, None)
|
| 1399 |
torch.cuda.empty_cache()
|
| 1400 |
|
|
|
|
| 220 |
)
|
| 221 |
|
| 222 |
self.device = torch.device(config.device)
|
| 223 |
+
# Optional device pool for the sharded successor forward. Pool of one
|
| 224 |
+
# (the default) is byte-identical to the original sequential flow.
|
| 225 |
+
_pool = tuple(getattr(config, "devices", ()) or ()) or (config.device,)
|
| 226 |
+
if _pool[0] != config.device:
|
| 227 |
+
raise ValueError("forward device pool must start with the primary device")
|
| 228 |
+
self.forward_devices = tuple(torch.device(item) for item in _pool)
|
| 229 |
if self.device.type != "cuda":
|
| 230 |
raise ValueError(
|
| 231 |
"the owner-run GLM reference runtime requires one CUDA device"
|
|
|
|
| 512 |
"auxiliary": "prev_topk_indices-int32",
|
| 513 |
}
|
| 514 |
|
| 515 |
+
def _context(self, hidden, metadata: Mapping[str, object], device=None):
|
| 516 |
+
device = self.device if device is None else device
|
| 517 |
import torch
|
| 518 |
|
| 519 |
tokens = int(metadata["tokens"])
|
|
|
|
| 524 |
):
|
| 525 |
raise ValueError("state metadata is not the pinned one-prompt DSA schema")
|
| 526 |
x = (
|
| 527 |
+
torch.as_tensor(hidden, device=device)
|
| 528 |
.reshape(1, tokens, HIDDEN_SIZE)
|
| 529 |
.to(torch.bfloat16)
|
| 530 |
)
|
| 531 |
+
position_ids = torch.arange(tokens, device=device).unsqueeze(0)
|
| 532 |
minimum = torch.finfo(x.dtype).min
|
| 533 |
causal = torch.full(
|
| 534 |
+
(tokens, tokens), minimum, device=device, dtype=x.dtype
|
| 535 |
).triu(diagonal=1)
|
| 536 |
attention_mask = causal.unsqueeze(0).unsqueeze(0)
|
| 537 |
position_embeddings = self.rotary(x, position_ids)
|
| 538 |
previous = metadata.get("prev_topk_indices")
|
| 539 |
if previous is not None:
|
| 540 |
previous = torch.as_tensor(
|
| 541 |
+
previous, device=device, dtype=torch.int32
|
| 542 |
).unsqueeze(0)
|
| 543 |
return x, attention_mask, position_ids, position_embeddings, previous
|
| 544 |
|
|
|
|
| 569 |
gate_up = torch.empty(
|
| 570 |
(NUM_EXPERTS, 2 * INTERMEDIATE_SIZE, HIDDEN_SIZE),
|
| 571 |
dtype=torch.bfloat16,
|
| 572 |
+
device=device,
|
| 573 |
)
|
| 574 |
down = torch.empty(
|
| 575 |
(NUM_EXPERTS, HIDDEN_SIZE, INTERMEDIATE_SIZE),
|
| 576 |
dtype=torch.bfloat16,
|
| 577 |
+
device=device,
|
| 578 |
)
|
| 579 |
for expert in range(NUM_EXPERTS):
|
| 580 |
gate_up[expert, :INTERMEDIATE_SIZE] = installed[expert][
|
|
|
|
| 601 |
module.eval()
|
| 602 |
return module
|
| 603 |
|
| 604 |
+
def _advance(self, module, hidden, metadata, device=None):
|
| 605 |
+
context = self._context(hidden, metadata, device=device)
|
| 606 |
x, mask, positions, rotary, previous = context
|
| 607 |
with __import__("torch").inference_mode():
|
| 608 |
output, topk = module(
|
|
|
|
| 1367 |
}
|
| 1368 |
carrier_audit = sha256_bytes(canonical_json_bytes(layer_records))
|
| 1369 |
first_shard_id = input_values[0].shard_id
|
| 1370 |
+
devices = getattr(self, "forward_devices", None) or (
|
| 1371 |
+
getattr(self, "device", None),
|
| 1372 |
+
)
|
| 1373 |
+
pending = [
|
| 1374 |
+
shard
|
| 1375 |
+
for shard in input_values
|
| 1376 |
+
if shard.shard_id not in completed_shard_ids
|
| 1377 |
+
]
|
| 1378 |
+
replicas: list = []
|
| 1379 |
try:
|
| 1380 |
+
def _load_shard(shard):
|
|
|
|
|
|
|
| 1381 |
reader = SafeTensorReader(shard.hidden_path)
|
| 1382 |
hidden = read_torch_tensor(reader, "hidden")
|
| 1383 |
previous = read_torch_tensor(reader, "prev_topk_indices")
|
| 1384 |
metadata = read_json(shard.metadata_path)
|
| 1385 |
metadata["prev_topk_indices"] = previous
|
| 1386 |
+
return hidden, metadata
|
| 1387 |
+
|
| 1388 |
+
def _successor(shard, metadata, repeat_audit, parity_audit):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1389 |
successor = dict(metadata)
|
| 1390 |
successor.pop("prev_topk_indices", None)
|
| 1391 |
successor["producer"] = f"round7-installed-layer-{layer:03d}"
|
|
|
|
| 1393 |
successor["carrier_decode_audit_sha256"] = carrier_audit
|
| 1394 |
if repeat_audit is not None:
|
| 1395 |
successor["official_repeat_audit"] = repeat_audit
|
| 1396 |
+
if parity_audit is not None:
|
| 1397 |
+
successor["replica_parity_audit"] = parity_audit
|
| 1398 |
+
return successor
|
| 1399 |
+
|
| 1400 |
+
sequential = (
|
| 1401 |
+
len(devices) <= 1
|
| 1402 |
+
or len(pending) <= 1
|
| 1403 |
+
# Mid-layer resume: the oracle prompt is already sealed, so
|
| 1404 |
+
# the parity check has no reference. Sequential handles it.
|
| 1405 |
+
or pending[0].shard_id != first_shard_id
|
| 1406 |
+
)
|
| 1407 |
+
if sequential:
|
| 1408 |
+
# Original sequential flow, byte-identical.
|
| 1409 |
+
for shard in pending:
|
| 1410 |
+
hidden, metadata = _load_shard(shard)
|
| 1411 |
+
if shard.shard_id == first_shard_id:
|
| 1412 |
+
output, topk, repeat_audit = self._advance_repeat_oracle(
|
| 1413 |
+
module, hidden, metadata
|
| 1414 |
+
)
|
| 1415 |
+
else:
|
| 1416 |
+
output, topk = self._advance(module, hidden, metadata)
|
| 1417 |
+
repeat_audit = None
|
| 1418 |
+
# Yield immediately: the walk seals this prompt in
|
| 1419 |
+
# PARTIAL.json before the next expensive prompt starts.
|
| 1420 |
+
yield self._write_state(
|
| 1421 |
+
output_partial=output_partial,
|
| 1422 |
+
layer_input=layer + 1,
|
| 1423 |
+
shard_id=shard.shard_id,
|
| 1424 |
+
hidden=output,
|
| 1425 |
+
previous_topk=topk,
|
| 1426 |
+
metadata=_successor(shard, metadata, repeat_audit, None),
|
| 1427 |
+
)
|
| 1428 |
+
return
|
| 1429 |
+
|
| 1430 |
+
# Sharded successor forward across the device pool. Compute fans
|
| 1431 |
+
# out to worker replicas; every state write and yield stays on
|
| 1432 |
+
# THIS thread in canonical shard order, so PARTIAL.json sealing,
|
| 1433 |
+
# resume semantics, and state hashing are unchanged.
|
| 1434 |
+
import copy
|
| 1435 |
+
from concurrent.futures import ThreadPoolExecutor
|
| 1436 |
+
|
| 1437 |
+
first_shard = pending[0]
|
| 1438 |
+
first_hidden, first_metadata = _load_shard(first_shard)
|
| 1439 |
+
output, topk, repeat_audit = self._advance_repeat_oracle(
|
| 1440 |
+
module, first_hidden, first_metadata
|
| 1441 |
+
)
|
| 1442 |
+
# Replicate only after the primary oracle passes, and prove every
|
| 1443 |
+
# replica reproduces the primary bytes before trusting it with
|
| 1444 |
+
# calibration state.
|
| 1445 |
+
replica_parity = {
|
| 1446 |
+
"schema": "r7-replica-parity-v1",
|
| 1447 |
+
"devices": [str(item) for item in devices],
|
| 1448 |
+
}
|
| 1449 |
+
modules = [module]
|
| 1450 |
+
for extra in devices[1:]:
|
| 1451 |
+
replica = copy.deepcopy(module).to(extra)
|
| 1452 |
+
r_out, r_topk = self._advance(
|
| 1453 |
+
replica, first_hidden, first_metadata, device=extra
|
| 1454 |
)
|
| 1455 |
+
if not torch.equal(r_out, output) or not torch.equal(
|
| 1456 |
+
r_topk, topk
|
| 1457 |
+
):
|
| 1458 |
+
raise RuntimeError(
|
| 1459 |
+
f"replica on {extra} diverged from the primary "
|
| 1460 |
+
"successor forward; refusing sharded execution"
|
| 1461 |
+
)
|
| 1462 |
+
replicas.append(replica)
|
| 1463 |
+
modules.append(replica)
|
| 1464 |
+
replica_parity["passed"] = True
|
| 1465 |
+
yield self._write_state(
|
| 1466 |
+
output_partial=output_partial,
|
| 1467 |
+
layer_input=layer + 1,
|
| 1468 |
+
shard_id=first_shard.shard_id,
|
| 1469 |
+
hidden=output,
|
| 1470 |
+
previous_topk=topk,
|
| 1471 |
+
metadata=_successor(
|
| 1472 |
+
first_shard, first_metadata, repeat_audit, replica_parity
|
| 1473 |
+
),
|
| 1474 |
+
)
|
| 1475 |
+
|
| 1476 |
+
def _compute(index_shard):
|
| 1477 |
+
index, shard = index_shard
|
| 1478 |
+
worker = index % len(modules)
|
| 1479 |
+
hidden, metadata = _load_shard(shard)
|
| 1480 |
+
out, tk = self._advance(
|
| 1481 |
+
modules[worker], hidden, metadata, device=devices[worker]
|
| 1482 |
+
)
|
| 1483 |
+
return shard, metadata, out, tk
|
| 1484 |
+
|
| 1485 |
+
with ThreadPoolExecutor(max_workers=len(modules)) as pool:
|
| 1486 |
+
for shard, metadata, out, tk in pool.map(
|
| 1487 |
+
_compute, enumerate(pending[1:])
|
| 1488 |
+
):
|
| 1489 |
+
yield self._write_state(
|
| 1490 |
+
output_partial=output_partial,
|
| 1491 |
+
layer_input=layer + 1,
|
| 1492 |
+
shard_id=shard.shard_id,
|
| 1493 |
+
hidden=out,
|
| 1494 |
+
previous_topk=tk,
|
| 1495 |
+
metadata=_successor(shard, metadata, None, None),
|
| 1496 |
+
)
|
| 1497 |
finally:
|
| 1498 |
del module
|
| 1499 |
+
for replica in replicas:
|
| 1500 |
+
del replica
|
| 1501 |
+
replicas.clear()
|
| 1502 |
self._installed.pop(layer, None)
|
| 1503 |
torch.cuda.empty_cache()
|
| 1504 |
|
run_scripts/setup_box.sh
CHANGED
|
@@ -5,7 +5,13 @@
|
|
| 5 |
# plus the encoder oracles validate the rebuilt extension on behavior.
|
| 6 |
set -e
|
| 7 |
python3 -m pip install --break-system-packages -q torch==2.12.1+cu132 --index-url https://download.pytorch.org/whl/cu132
|
| 8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
tar xzf exl3_v0043_src.tgz -C exl3src
|
| 10 |
cd exl3src && TORCH_CUDA_ARCH_LIST=10.0 MAX_JOBS=64 python3 -m pip install --break-system-packages --no-deps --no-build-isolation .
|
| 11 |
python3 -c "import torch, exllamav3_ext; print('ext OK on torch', torch.__version__)"
|
|
|
|
| 5 |
# plus the encoder oracles validate the rebuilt extension on behavior.
|
| 6 |
set -e
|
| 7 |
python3 -m pip install --break-system-packages -q torch==2.12.1+cu132 --index-url https://download.pytorch.org/whl/cu132
|
| 8 |
+
# transformers PINNED: the runtime is authored against 5.12.1
|
| 9 |
+
# (GlmMoeDsaNaiveMoe was refactored away in later versions).
|
| 10 |
+
python3 -m pip install --break-system-packages -q "transformers==5.12.1" safetensors pytest ninja setuptools wheel "huggingface_hub[hf_transfer]"
|
| 11 |
+
# remove image-bundled torchvision/torchaudio: built against older torch,
|
| 12 |
+
# their ABI-mismatched op registration explodes inside transformers imports
|
| 13 |
+
python3 -m pip uninstall -y --break-system-packages torchvision torchaudio 2>/dev/null || true
|
| 14 |
+
python3 -c "import importlib.util; assert importlib.util.find_spec('torchvision') is None, 'torchvision still present'"
|
| 15 |
tar xzf exl3_v0043_src.tgz -C exl3src
|
| 16 |
cd exl3src && TORCH_CUDA_ARCH_LIST=10.0 MAX_JOBS=64 python3 -m pip install --break-system-packages --no-deps --no-build-isolation .
|
| 17 |
python3 -c "import torch, exllamav3_ext; print('ext OK on torch', torch.__version__)"
|