#000049 §7 #22: speedup (batch + cuda auto-detect + ONNX-int8 export) + the gate-item-4 verdict at proper n
Speedup (§3 plan): ShadowNLI._nli_batch batches forwards (ARBORIST_NLI_BATCH=64); device auto-detect (ARBORIST_NLI_DEVICE, else cuda-if-available); auto-prefer an ONNX export — bench/scripts/export_nli_onnx.py / make export-nli-onnx exports + int8-dynamic-quantizes the pinned checkpoint into ~/.arborist/models/nli/<ver>/onnx/ (operator state, NOT committed), _ensure_loaded loads model_quantized.onnx via optimum.onnxruntime (backend onnx-int8), falls back to torch silently. torch-cpu-batch1 ~120ms/pair → onnx-int8-cpu-batched ~32ms/pair (~4x); seconds on a 4090. optimum[onnxruntime] added to the [nli] extra; 24 tests. Gate-item-4 verdict at proper n: ARBORIST_NLI_SHADOW=1 make bench-qa BENCH_QA_N=1 → 223 cells (89 STRICT / 90 HYBRID / 44 UNGROUNDED; also surfaced + fixed a lone-surrogate bug). Shadow sweep over those: NLI-as- runtime-veto on STRICT has ~26% FP at θc 0.5, ~8% at θc 0.90, ~0% only at θc 0.99 — and θc 0.99 gives up most recombination recall (hard synthetic recombinations bottom out ~0.76). FAILS the §7 #12 gate on this design. Only untried path that might pass: a Phase-3 runtime hook running NLI on the verifier's actual matched clauses (1-3), not top-6-by-overlap. Until then: runtime NLI demotion stays off; the 2 fixtures stay permanent boundary markers; θc stays 0.5. Production verifier unchanged; falsification-hard stays 10/12.
This commit is contained in:
parent
96ff586da1
commit
87d9db15c7
8 changed files with 4587 additions and 30 deletions
|
|
@ -136,6 +136,36 @@ def test_shadownli_construction_never_raises_and_starts_unavailable():
|
|||
assert nli.available is False # not loaded until first check
|
||||
assert nli.model_version == load_manifest()["nli_model_version"]
|
||||
assert nli.theta_contra == 0.5 and nli.theta_entail == 0.9
|
||||
assert nli.device_pref in ("auto", "cpu", "cuda") # default 'auto'
|
||||
assert nli.batch_size >= 1
|
||||
assert nli.backend is None # set at load → "torch" / "onnx" / "onnx-int8"
|
||||
assert nli._onnx_dir().name == "onnx" # conventional export location
|
||||
|
||||
|
||||
def test_shadownli_device_and_onnx_dir_env_overrides(monkeypatch, tmp_path):
|
||||
monkeypatch.setenv("ARBORIST_NLI_DEVICE", "cpu")
|
||||
monkeypatch.setenv("ARBORIST_NLI_ONNX_DIR", str(tmp_path / "x"))
|
||||
monkeypatch.setenv("ARBORIST_NLI_BATCH", "8")
|
||||
nli = ShadowNLI()
|
||||
assert nli.device_pref == "cpu" and nli.batch_size == 8
|
||||
assert nli._onnx_dir() == tmp_path / "x"
|
||||
|
||||
|
||||
def test_nli_batch_matches_single_when_available():
|
||||
nli = ShadowNLI()
|
||||
nli._ensure_loaded()
|
||||
if not nli.available:
|
||||
pytest.skip("[nli] extra not installed")
|
||||
pairs = [("Jupiter is the largest planet.", "Mercury is the largest planet."),
|
||||
("Paris is the capital of France.", "Paris is the capital of France.")]
|
||||
batched = nli._nli_batch(pairs)
|
||||
singles = [nli._nli(p, h) for p, h in pairs]
|
||||
for b, s in zip(batched, singles):
|
||||
# batching pads the shorter sequence; with attention masking that's
|
||||
# ~a no-op for fp32, and within quantization noise for int8 ONNX —
|
||||
# the operative thing (argmax label, gate decision) must not move.
|
||||
assert max(range(3), key=lambda i: b[i]) == max(range(3), key=lambda i: s[i])
|
||||
assert all(abs(x - y) < 0.05 for x, y in zip(b, s))
|
||||
|
||||
|
||||
def test_check_returns_shadowresult_and_degrades_gracefully():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue