openjev-server / tests /test_readout.py
abhishekgahlot's picture
openjev-server 0.2.0 with demos
0a2e8cf verified
Raw History Blame Contribute Delete
2.78 kB
import asyncio
import pytest
from openjev_server.profile import Profile
from openjev_server.readout import BadQuestion, Readout, choice_confidence, compose_chunks, score_confidence, softmax
def test_confidence_formulas():
assert choice_confidence([1.0]) == 1.0
assert choice_confidence([0.25] * 4) == 0.0
assert abs(choice_confidence([0.7, 0.1, 0.1, 0.1]) - (0.7 - 0.25) / 0.75) < 1e-12
assert score_confidence([0.0, 0.0, 1.0]) == 1.0
assert 0.0 <= score_confidence([0.5, 0.0, 0.5]) <= 1.0
def test_compose_chunks_is_a_distribution_and_order_free():
parts = [([0.7, 0.2, 0.1], 0), ([0.1, 0.6, 0.3], 1)]
p = compose_chunks(parts, [0.4, 0.6])
assert abs(sum(p) - 1) < 1e-12 and all(x > 0 for x in p)
assert abs(p[0] / p[4] - (0.4 * 0.7 / 0.7) / (0.6 * 0.6 / 0.6)) < 1e-12 # winners keep the final ratio
def test_softmax():
p = softmax([0.0, 0.0])
assert abs(p[0] - 0.5) < 1e-12
def test_bad_questions(fake_backend):
ro = Readout(fake_backend, Profile())
with pytest.raises(BadQuestion):
asyncio.run(ro.answer_all("s", {"q": {"type": "choice", "instructions": "x", "criteria": {}}}))
with pytest.raises(BadQuestion):
asyncio.run(ro.answer_all("s", {"q": {"type": "score", "instructions": "x", "criteria": ["one"]}}))
with pytest.raises(BadQuestion):
asyncio.run(ro.answer_all("s", {"q": {"type": "choice", "criteria": {"a": None}}}))
with pytest.raises(BadQuestion):
asyncio.run(ro.answer_all("s", {"q": {"type": "essay"}}))
def test_many_options_sum_to_one_and_use_two_stages(fake_backend):
ro = Readout(fake_backend, Profile())
ans, _ = asyncio.run(ro.answer_all("s", {"q": {"type": "choice", "instructions": "pick", "criteria": {f"o{i}": None for i in range(130)}}}))
p = ans["q"]["probabilities"]
assert len(p) == 130 and abs(sum(p.values()) - 1) < 0.01 and ans["q"]["choice"] in p
assert len(fake_backend.prompts) == 4 # 3 chunks of <= 52 + 1 over the winners
def test_stagger_runs_first_question_alone(fake_backend):
ro = Readout(fake_backend, Profile(stagger=True, stagger_min_chars=10))
ans, toks = asyncio.run(ro.answer_all("x" * 100, {"a": {"type": "noul", "instructions": "yes?"}, "b": {"type": "noul", "instructions": "no?"}}))
assert set(ans) == {"a", "b"} and toks > 0 and 0 <= ans["a"]["noul"] <= 1
def test_noul_calibration_direction(fake_backend):
ro = Readout(fake_backend, Profile(noul_t=1.0, noul_bias=0.0))
ans, _ = asyncio.run(ro.answer_all("s", {"q": {"type": "noul", "instructions": "?"}}))
ro2 = Readout(fake_backend, Profile(noul_t=1.0, noul_bias=3.0))
ans2, _ = asyncio.run(ro2.answer_all("s", {"q": {"type": "noul", "instructions": "?"}}))
assert ans2["q"]["noul"] > ans["q"]["noul"]