mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
121 lines
3.4 KiB
Python
121 lines
3.4 KiB
Python
"""roboco.models.llm coverage — TOON config and metrics dataclasses.
|
|
|
|
Covers ToonConfig defaults, EncodedBlock __str__, LLMUsage totals, and
|
|
ToonMetrics record/reset/savings/fallback rate computations.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime
|
|
|
|
from roboco.models.llm import (
|
|
EncodedBlock,
|
|
LLMUsage,
|
|
ToonConfig,
|
|
ToonMetrics,
|
|
)
|
|
|
|
_BIG_JSON = 100
|
|
_BIG_TOON = 60
|
|
_INPUT = 100
|
|
_OUTPUT = 50
|
|
_CACHE_CREATE = 10
|
|
_CACHE_READ = 20
|
|
_FALLBACK_PERCENT_HALF = 50.0
|
|
_TWO_DECODES = 2
|
|
|
|
|
|
def test_toon_config_defaults() -> None:
|
|
cfg = ToonConfig()
|
|
assert cfg.delimiter == ","
|
|
assert cfg.indent > 0
|
|
assert cfg.include_length is True
|
|
|
|
|
|
def test_encoded_block_str_includes_label_and_content() -> None:
|
|
blk = EncodedBlock(content="data", label="Section")
|
|
s = str(blk)
|
|
assert "Section" in s
|
|
assert "data" in s
|
|
|
|
|
|
def test_llm_usage_total_tokens() -> None:
|
|
usage = LLMUsage(input_tokens=_INPUT, output_tokens=_OUTPUT)
|
|
assert usage.total_tokens == _INPUT + _OUTPUT
|
|
|
|
|
|
def test_llm_usage_total_input_with_cache() -> None:
|
|
usage = LLMUsage(
|
|
input_tokens=_INPUT,
|
|
cache_creation_input_tokens=_CACHE_CREATE,
|
|
cache_read_input_tokens=_CACHE_READ,
|
|
)
|
|
assert usage.total_input_with_cache == _INPUT + _CACHE_CREATE + _CACHE_READ
|
|
|
|
|
|
def test_toon_metrics_initial_state() -> None:
|
|
m = ToonMetrics()
|
|
assert m.json_chars == 0
|
|
assert m.toon_chars == 0
|
|
assert m.encode_count == 0
|
|
assert m.decode_count == 0
|
|
assert m.savings_percent == 0.0 # zero json_chars guard
|
|
assert m.fallback_rate == 0.0 # zero decode_count guard
|
|
|
|
|
|
def test_toon_metrics_record_encode() -> None:
|
|
m = ToonMetrics()
|
|
m.record_encode(json_chars=_BIG_JSON, toon_chars=_BIG_TOON)
|
|
assert m.json_chars == _BIG_JSON
|
|
assert m.toon_chars == _BIG_TOON
|
|
assert m.encode_count == 1
|
|
# 40% reduction from 100 -> 60.
|
|
expected_savings = (1 - _BIG_TOON / _BIG_JSON) * 100
|
|
assert m.savings_percent == expected_savings
|
|
|
|
|
|
def test_toon_metrics_record_decode_no_fallback() -> None:
|
|
m = ToonMetrics()
|
|
m.record_decode(used_fallback=False)
|
|
assert m.decode_count == 1
|
|
assert m.decode_fallback_count == 0
|
|
assert m.fallback_rate == 0.0
|
|
|
|
|
|
def test_toon_metrics_record_decode_with_fallback() -> None:
|
|
m = ToonMetrics()
|
|
m.record_decode(used_fallback=False)
|
|
m.record_decode(used_fallback=True)
|
|
assert m.decode_count == _TWO_DECODES
|
|
assert m.decode_fallback_count == 1
|
|
assert m.fallback_rate == _FALLBACK_PERCENT_HALF
|
|
|
|
|
|
def test_toon_metrics_to_dict_shape() -> None:
|
|
m = ToonMetrics()
|
|
m.record_encode(_BIG_JSON, _BIG_TOON)
|
|
m.record_decode(used_fallback=True)
|
|
out = m.to_dict()
|
|
assert out["json_chars"] == _BIG_JSON
|
|
assert out["toon_chars"] == _BIG_TOON
|
|
assert out["encode_count"] == 1
|
|
assert out["decode_count"] == 1
|
|
assert "started_at" in out
|
|
|
|
|
|
def test_toon_metrics_reset_clears_counters() -> None:
|
|
m = ToonMetrics()
|
|
m.record_encode(_BIG_JSON, _BIG_TOON)
|
|
m.record_decode(used_fallback=True)
|
|
before_reset = m.started_at
|
|
m.reset()
|
|
assert m.json_chars == 0
|
|
assert m.toon_chars == 0
|
|
assert m.encode_count == 0
|
|
assert m.decode_count == 0
|
|
assert m.decode_fallback_count == 0
|
|
# started_at is refreshed after reset.
|
|
assert isinstance(m.started_at, datetime)
|
|
assert m.started_at >= before_reset
|
|
assert m.started_at.tzinfo == UTC
|