mirror of
https://github.com/TheTom/turboquant_plus.git
synced 2026-10-22 11:02:42 -05:00
v0.1.3 ships no new functional axes — only the test coverage, fail-loud guards, and corpus-identity machinery needed to stop the v0.1.x patch-round-after-matrix-run cycle. Code fixes: - axes/gtm.py: tokenizer-failure fallback now RAISES instead of silently using whitespace (was producing wrong-unit scores with no detection). - axes/gtm.py: GTM score now normalizes by mean_cand_length instead of n_predict (fixes gemma-31B 2.87× retokenize inflation that re-clipped the score to 100 in v0.1.2). - cli.py: --measure-floor additionally asserts mean_prefix == mean_cand on ref-vs-ref greedy (KLD ref-vs-ref is bit-exact zero on Metal so the composite floor passes even when GTM is broken). - runner.py: _TOPP_RE regex now tolerates 'Same top p' (space) form (test surfaced that v0.1.2 only matched the dashed form). - runner.py: new corpus_identity / sidecar machinery; KLDResult includes corpus path/size/SHA; refuses to score against a base built from a different corpus. New tests (30 across 6 files; all pass in <0.05s, no subprocess): - test_strip_noise.py: 5 — pins runner._strip_noise (banner / backspace / block-char regressions from v0.1.1). - test_command_construction.py: 4 — pins --single-turn presence, --no-conversation absence, --kl-divergence-base, errors='replace'. - test_tokenize_to_ids.py: 5 — parser + raise-on-error contract. - test_kld_regex.py: 6 — perplexity output regexes incl. gemma Same-top-p missing case (this test caught the regex bug). - test_report_json_layout.py: 5 — pins schema + composite-is-scalar. - test_corpus_identity.py: 5 — sidecar machinery. - test_validation.py: +4 GTM assertions (full_match_rate < 1.0, mean_prefix > 0, ≥3 distinct refs, ratio == 1.0 on ref-vs-ref). Total: 14 → 44 unit tests + 1 strengthened integration test. Docs: - LIMITATIONS.md: NEW — documents the limitations we ship with (detokenize→retokenize gap, corpus-anchored KLD, provisional bands, single-platform tested, GTM/EOS conflation, v0.1.3 fail-loud removal). - README.md: GTM scoring formula updated; new test files listed; points at LIMITATIONS.md. - axes/gtm.py module docstring: refreshed to reflect v0.1.2 + v0.1.3. - CHANGELOG.md: v0.1.3 entry at top with the v0.1.2 matrix table and the file-by-file change summary. - report.py: schema bumped refract.report.v0.1.1 → v0.1.3. - __init__.py: __version__ = "0.1.3". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-Authored-By: tturney <tturney1@gmail.com>
104 lines
3.7 KiB
Python
104 lines
3.7 KiB
Python
"""v0.1.3 regression tests for the llama.cpp command lines we construct.
|
|
|
|
These pin the v0.1.1 + v0.1.2 fixes:
|
|
|
|
- run_completion must pass --single-turn but NOT --no-conversation
|
|
(this fork rejects --no-conversation and prints help; v0.1 captured
|
|
the help text as the "completion").
|
|
- run_perplexity_kld_base passes --kl-divergence-base.
|
|
- run_perplexity_kld passes BOTH --kl-divergence and --kl-divergence-base.
|
|
- All three pass errors='replace' to subprocess.run (Mistral-Small-24B
|
|
crashed in v0.1.1 on a strict utf-8 decode of stderr).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import subprocess
|
|
from pathlib import Path
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from refract import runner
|
|
from refract.runner import (
|
|
KVConfig,
|
|
run_completion,
|
|
run_perplexity_kld,
|
|
run_perplexity_kld_base,
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def captured(monkeypatch, tmp_path):
|
|
"""Patch subprocess.run + _bin so the wrappers run without llama.cpp.
|
|
|
|
Returns a list captured[0] = SimpleNamespace(cmd, kwargs) per call.
|
|
"""
|
|
calls: list = []
|
|
|
|
def fake_run(cmd, **kwargs):
|
|
calls.append(SimpleNamespace(cmd=cmd, kwargs=kwargs))
|
|
# Return enough fields for the wrappers to parse without raising.
|
|
# KLD parser needs a Mean KLD line; perplexity-base just needs rc=0.
|
|
stdout = "Mean KLD: 0.000000\nFinal estimate: PPL = 6.0\n"
|
|
return SimpleNamespace(returncode=0, stdout=stdout, stderr="")
|
|
|
|
monkeypatch.setattr(subprocess, "run", fake_run)
|
|
# _bin checks file existence — bypass with a temp dummy file.
|
|
fake_bin = tmp_path / "fake-bin"
|
|
fake_bin.touch()
|
|
monkeypatch.setattr(runner, "_bin", lambda name: fake_bin)
|
|
return calls
|
|
|
|
|
|
def test_run_completion_has_single_turn_no_no_conversation(captured, tmp_path):
|
|
model = tmp_path / "m.gguf"
|
|
model.touch()
|
|
run_completion(model=model, prompt="hi", kv=KVConfig(), n_predict=4)
|
|
assert len(captured) == 1
|
|
cmd = captured[0].cmd
|
|
assert "--single-turn" in cmd
|
|
# Regression: --no-conversation must NOT be in the args. This fork
|
|
# rejects it with "please use llama-completion instead" and prints help,
|
|
# which v0.1 silently captured as the model's completion.
|
|
assert "--no-conversation" not in cmd
|
|
|
|
|
|
def test_run_completion_passes_errors_replace(captured, tmp_path):
|
|
model = tmp_path / "m.gguf"
|
|
model.touch()
|
|
run_completion(model=model, prompt="hi", kv=KVConfig(), n_predict=4)
|
|
# Regression: Mistral-Small-24B crashed in v0.1.1 on UnicodeDecodeError
|
|
# because subprocess.run(text=True) strict-decodes stderr. errors='replace'
|
|
# keeps the stream usable when llama-cli emits non-utf-8 bytes.
|
|
assert captured[0].kwargs.get("errors") == "replace"
|
|
assert captured[0].kwargs.get("text") is True
|
|
|
|
|
|
def test_run_perplexity_kld_base_has_base_flag(captured, tmp_path):
|
|
model = tmp_path / "m.gguf"
|
|
model.touch()
|
|
corpus = tmp_path / "wiki.raw"
|
|
corpus.write_text("hello world")
|
|
base = tmp_path / "base.bin"
|
|
run_perplexity_kld_base(model=model, corpus=corpus, kv=KVConfig(),
|
|
base_path=base, chunks=4)
|
|
cmd = captured[0].cmd
|
|
assert "--kl-divergence-base" in cmd
|
|
assert str(base) in cmd
|
|
assert captured[0].kwargs.get("errors") == "replace"
|
|
|
|
|
|
def test_run_perplexity_kld_has_both_flags(captured, tmp_path):
|
|
model = tmp_path / "m.gguf"
|
|
model.touch()
|
|
corpus = tmp_path / "wiki.raw"
|
|
corpus.write_text("hello world")
|
|
base = tmp_path / "base.bin"
|
|
run_perplexity_kld(model=model, corpus=corpus, kv=KVConfig(),
|
|
base_path=base, chunks=4)
|
|
cmd = captured[0].cmd
|
|
assert "--kl-divergence" in cmd
|
|
assert "--kl-divergence-base" in cmd
|
|
assert captured[0].kwargs.get("errors") == "replace"
|