granite-decisions / tests /test_native.py
adampippert's picture
Publish Granite Decisions v0.1.0 training starter and evaluation evidence
577b44e verified
Raw History Blame Contribute Delete
4.78 kB
import copy
import unittest
import numpy as np
from granite_decisions.contracts import ContractError
from granite_decisions.llamacpp import BackendError, LlamaRuntime, NativeClient, PROMPT_VERSION, gpu_offload_evidence, props_fingerprint
class StubNative:
def __init__(self):
self.props = {"model_path": "/models/granite.gguf", "build_info": "test-build", "chat_template": "template", "total_slots": 1, "granite_decisions_grammar_probs": 1, "granite_decisions_pooling": 3,
"default_generation_settings": {"n_ctx": 4096}}
self.calls, self.partial, self.truncated = [], False, False
def request(self, path, body=None):
self.calls.append((path, body))
if path == "/props":
return self.props
if path == "/apply-template":
return {"prompt": "test template"}
if path == "/embedding":
return [{"index": 0, "embedding": [[.6, .8]]}]
if path == "/completion":
top = [{"id": 65, "prob": .25}, {"id": 66, "prob": .75}]
return {"truncated": self.truncated, "content": "irrelevant",
"completion_probabilities": [{"top_probs": top[:1] if self.partial else top}]}
raise AssertionError(path)
def tokens(self, text, **kwargs):
return [ord(text)] if len(text) == 1 else [1, 2, 3]
def runtime(client, mode):
return LlamaRuntime(client, {"format": 1, "mode": mode, "model_id": "ibm-granite/granite-4.1-3b", "prompt_version": PROMPT_VERSION,
"server_fingerprint": props_fingerprint(client.props), "max_tokens": 2048})
class Native(unittest.TestCase):
def test_gpu_device_listing_is_insufficient_offload_evidence(self):
for log in ("ROCm0: AMD GPU", "load_tensors: offloaded 0/41 layers to GPU",
"load_tensors: offloaded 42/41 layers to GPU"):
with self.assertRaises(BackendError):
gpu_offload_evidence(log)
self.assertEqual(gpu_offload_evidence("load_tensors: offloaded 41/41 layers to GPU")["offloaded_layers"], 41)
def test_loopback_only(self):
for url in ("http://hyde:8080", "http://1.2.3.4", "http://127.0.0.1/?key=x", "http://user:pass@127.0.0.1"):
with self.assertRaises(ContractError):
NativeClient(url)
def test_last_pool_embedding(self):
client = StubNative()
x = runtime(client, "embedding").encode([{"hello": "world"}])
np.testing.assert_allclose(x, [[.6, .8]])
self.assertEqual(sum(p == "/embedding" for p, _ in client.calls), 1)
def test_baseline_uses_all_candidate_probabilities_not_generated_text(self):
client = StubNative()
r = runtime(client, "baseline")
q = {"decision": {"type": "noul", "instructions": "True?"}}
result = r.baseline_logits({}, q)
np.testing.assert_allclose(np.exp(result["decision"]), [.25, .75])
payload = next(b for p, b in client.calls if p == "/completion")
self.assertEqual(payload["n_predict"], 1)
self.assertEqual(payload["temperature"], 1)
self.assertEqual(payload["samplers"], ["temperature"])
def test_missing_low_probability_candidate_rejected(self):
client = StubNative()
client.partial = True
with self.assertRaises(BackendError):
runtime(client, "baseline").baseline_logits({}, {"q": {"type": "noul", "instructions": "True?"}})
def test_context_truncation_rejected(self):
client = StubNative()
client.truncated = True
with self.assertRaises(BackendError):
runtime(client, "baseline").baseline_logits({}, {"q": {"type": "noul", "instructions": "True?"}})
def test_budget_exceeded_before_inference(self):
client = StubNative()
r = runtime(client, "embedding")
client.tokens = lambda *a, **k: list(range(3000))
with self.assertRaises(ContractError):
r.encode([{}])
self.assertFalse(any(p == "/embedding" for p, _ in client.calls))
def test_runtime_change_rejected(self):
client = StubNative()
r = runtime(client, "embedding")
client.props["build_info"] = "new-build"
with self.assertRaises(BackendError):
r.encode([{}])
def test_unpatched_baseline_rejected(self):
client = StubNative()
del client.props["granite_decisions_grammar_probs"]
with self.assertRaises(BackendError):
runtime(client, "baseline")
def test_wrong_pooling_rejected(self):
client = StubNative()
client.props["granite_decisions_pooling"] = 1
with self.assertRaises(BackendError):
runtime(client, "embedding")
if __name__ == "__main__":
unittest.main()