ζ΅ Β· to flow, to stream
Current version: v0.29.0
A curated map of the next two quarters of work, gathered from internal
priorities + outside-in survey of regulated-AI evaluation tooling. Items
are scoped by both impact (how much it unlocks for paying users) and
complexity (engineering hours + ongoing maintenance). Every P1 item
has shipped in v0.15.0 β the four π΄ rows below are now DONE.
- Score distributions + percentile benchmarks (DONE β v0.15.0)
Each criterion now carries a reference distribution built from a
deterministic 1000-pair synthetic corpus.
GET /benchmarks/{criterion}returnsp25/p50/p75/p90/p99/mean/stdevplus a 20-bucket histogram for violin / sparkline rendering. Every/evaluateresponse includes abenchmarksblock mapping each criterion to{you, rank, p25, p50, p75}. - A/B statistical significance testing (DONE β v0.15.0)
POST /comparenow returns asignificanceblock with the paired t-test result over per-criterion differences:n, mean_diff, stdev_diff, t_stat, df, p_value, effect_size, effect_label, confidence_interval, winner. Astatistical_winnerfield overrides the heuristic winner to"tie"wheneverp > 0.05or|Cohen's d| < 0.2. Pure stdlib β Student's t CDF via Simpson's rule numerical integration of the PDF. - Immutable audit log (DONE β v0.15.0)
Append-only SQLite at
KAIRU_AUDIT_DB(default:memory:). Schema-level triggersRAISE(ABORT, β¦)on UPDATE / DELETE. Every/evaluateand/comparecall records{timestamp_utc, input_hash, rubric_name, rubric_version, judge_model, endpoint, scores, reasoning}and returns the row id in the response.GET /audit?start=&end=&...paginated,GET /audit.csvflat export. WAL journaling β dashboards read while the API writes. - Rubric versioning (DONE β v0.15.0)
Every
Rubriccarries a SemVerversion(default1.0.0).RUBRIC_REGISTRY[name][version]keeps every version ever served so audit-log rows resolve back to the exact rubric that produced them.POST /rubricscreates a new version (patch-bumps when no version is supplied).GET /rubricsnow lists every active version.
-
Judge bias correction + multi-judge ensembles (DONE β v0.16.0)
JudgeConfigcarries (rubric, criteria, weights, seed, noise). Median aggregation per criterion (robust to one outlier), per-criterion stdev as the disagreement metric,disagreement_flag = max_stdev > 0.2(default; tunable).POST /evaluate/ensembleandPOST /compare/ensembleacceptjudges: [JudgeConfig...]. Deterministic seeded Gaussian noise simulates inter-judge variance authentically while keeping CI reproducible. Real LLM judges plug in behind the sameJudgeConfigcontract later. -
Production traffic β auto-eval pipeline (DONE β v0.16.0)
POST /eval_from_logaccepts{input, output, metadata?}records, scores them through a named rubric, and returns aLogEvalReportwith mean/median/min/max/stdev aggregates, per-criterion mean and min, and per-item pass/fail flags.passed: boolkeys onmean_aggregate >= thresholdβ CI uses it as the exit-code gate. Metadata passes through untouched for downstream slicing by request id / region / model tag. -
CI regression gating (DONE β v0.16.0 β bonus item)
POST /ci/baselinesnapshots a golden corpus withBaselineSnapshot(input-hash + per-item scores).POST /ci/checkcompares a candidate run against the snapshot; a criterion regression is any per-item dropthreshold(default 0.05). Unmatched-input drift surfaces in the report.FileBaselineStorepersists snapshots toKAIRU_CI_DIRas JSON (atomic write via tempfile + rename). Designed for use as a deploy gate. -
Constitutional evals from policy docs (DONE β v0.17.0)
POST /rubrics/generateaccepts plain-text policy documents and returns auto-generated rubric criteria with weights. NLP extraction of "must", "shall not", "required" clauses β rubric items. The generated rubric registers as a new versioned entry in RUBRIC_REGISTRY. -
Agentic trajectory scoring (DONE β v0.17.0)
POST /eval/trajectoryaccepts a sequence of{step, tool_call, observation, response}records. Scores: tool selection correctness, error recovery, goal progress/completion, efficiency (steps taken vs. optimal). Returns a per-step breakdown plus an overall trajectory grade.
kairu/conformal.pyβ split conformal prediction (Sheng et al., EMNLP 2025, arXiv:2509.18658) adds a distribution-free coverage guarantee to the judge-eval stack, complementing the distribution-parametric reliability metrics.conformal_quantile(finite-sample rank,+infwhen undersized),calibrate_intervalβConformalInterval(ordinal boundary clamp + lower-bias midpoint),conformal_from_ensemblebridge.reliability.py/EnsembleResultuntouched β purely additive.- 17 new tests incl. an empirical-coverage check; module 100% coverage.
- First sprint of a new Discovery cycle (researcher sweep surfaced it as High-impact/Low-complexity; rebalances toward eval after two inference sprints). Backlog from the same sweep: IRT judge discrimination, entropy-driven adaptive Ξ³, dark-current datasheet, radix-tree KV dedup.
kairu/speed_bench.pyβrun_speed_benchβSpeedBenchReportruns the benchmark across six semantic task splits (TaskSplit/DEFAULT_SPLITS: translation, summarization, qa, code, dialogue, math) and reports per-split throughput + a throughput coefficient of variation quantifying task-dependence (SPEED-Bench methodology).BenchmarkRunnergained an optionalpromptarg to drive distinct splits.kairu/auto_profile.pyβDecoderProfile.warnings+recommend(quant=, draft_kind=)flag 4-bit draft and tree-draft speculative configs that erode acceptance/speedup (empty unless the hints are supplied).- 14 new tests; new
tests/test_speed_bench.pyat 100% module coverage. - Closes this session's Discovery sweep β both the eval track (CyclicJudge, reliability) and the inference-optimizer track (KV eviction/quant, adaptive early exit, SPEED-Bench) are complete.
kairu/early_exit.pyβ CALM-style (Schuster et al. 2022) per-token adaptive confidence threshold, opt-in viaadaptive=True(static path unchanged). The bar decays geometrically fromconfidence_thresholdtowardmin_confidenceover decoding steps viaeffective_confidence(step); early tokens need high confidence, later tokens exit more readily. Constructor now validates inputs; stats gainadaptive+final_confidence_threshold.kairu/auto_profile.pyβ_early_exit_suitablegates early exit out of encoder-style architectures (BERT/RoBERTa/T5/β¦) and sub-6-layer models, falling back tovanillawith an explanatory rationale.kairu/wrapper.pyβadaptive_early_exitflag (parallel toadaptive_gamma) forwards to the decoder from the public entry point.- 17 new tests; new
tests/test_early_exit.pytakes the module 21% β 100%.
kairu/kv_cache.pyβ upgradesLogitsCachefrom plain-recency LRU with two opt-in strategies (defaults unchanged, prior path bit-exact):eviction="attention"β H2O heavy-hitter eviction (Zhang et al. 2023): evict the least-accumulated-attention entry, not the oldest. Hits accrue attention;add_attention(key, weight)injects external rollups; ties break on the oldest entry (graceful LRU degradation).quant="int8" | "int4"β affine min-max quantised storage tier, ~4Γ/~8Γ footprint reduction at β€ half-step precision loss; int4 packed two-per-byte. New frozenQuantizedArraytype;stats()exposeseviction/quant/memory_bytes.
CachedModelforwards both knobs.kairu/__init__.pyexportsQuantizedArray.- 18 new tests;
tests/test_kv_cache.pyat 100% module coverage, all grade A.
kairu/reliability.pyβcronbach_alpha(internal consistency across criteria),intraclass_correlation(ICC(2,1) inter-judge agreement on continuous scores),fleiss_kappa(chance-corrected agreement on pass/fail binarisation),compute_reliabilityβReliabilityReportwith standard interpretation bands,reliability_from_ensemble. Pure stdlib; each metric returnsNonewhen undefined rather than fabricating a number. Grounded in Autorubric (arXiv:2603.00077).- API:
/evaluate/ensembleresponses gain areliabilityblock; newPOST /evaluate/reliabilitycomputes from a raw judges Γ criteria matrix. - 25 new tests; suite: 802 passed, 4 HF-gated skipped.
kairu/cyclic_judge.pyβcyclic_allocate(round-robin judge assignment, CyclicJudge / arXiv:2603.01865),cyclic_evaluateβCyclicEvalReport(one rotating judge per item at single-judge cost + load-balance diagnostic),batch_mean_intervalβMeanInterval(Student-t CI over independent per-item aggregates β the coverage-correct sampling unit; cf. CJE / arXiv:2512.11150, which shows criterion-level CIs have ~0% coverage),variance_componentsβVarianceComponents(two-way ANOVA judge/item/residual split),full_grid_scores(NΒ·K reference run).POST /evaluate/cyclicβ boundary-validated round-robin batch endpoint.- Housekeeping: reconciled the 0.20.0β0.24.0 version-stamp drift across
pyproject.toml+kairu/__init__.py; fixed thewatermark.pydocstringDeprecationWarning. - 41 new tests; suite: 777 passed, 4 HF-gated skipped.
kairu/marketplace.pyβMarketplaceEntry,MarketplaceStore(SQLite+WAL),compute_signature,open_default_marketplace_store,seed_community_rubricsapi/marketplace_router.pyβGET/POST /marketplace,GET /marketplace/domains,GET /marketplace/{name},POST /marketplace/{name}/import- 4 community rubrics seeded at startup:
medical_qa,legal_analysis,creative_writing,code_review - Marketplace tab (18th tab) β domain chips, search, animated rubric cards, one-click import, publish form
- 26 new tests; suite: 640 passed, 4 HF-gated skipped
- Visual overhaul β animated mesh bg, glassmorphism cards, slide/fade tab transitions, neon glow, sparklines, animated histogram
- Audit tab β live eval history query (
GET /audit), CSV export, color-coded scores - Rubric Lab tab β constitutional rubric generator (
POST /rubrics/generate) + rubric browser - Batch tab β multi-pair batch eval (
POST /batch) with animated progress bar - Human Feedback β
kairu/human_feedback.py(FeedbackStore, SQLite),POST /eval/{id}/feedbackendpoint, π/π UI in Evaluate tab - Generate tab β Prompt Library drawer backed by
/promptsAPI - Leaderboard β sparkline graphs + rank badge glow
- 604 tests passing, all CI gates green
- Engine tab β Speculative Decoder (animated token bubbles), Layerwise Early Exit (depth bars), KV Cache Monitor (hit/miss/evict timeline) β all live via
/api/kv-cache-sim,/api/early-exit-sim - Speed-Up tab β interactive 10Γ8 speedup heatmap + AutoProfile strategy card via
/api/recommend - Watermark tab β Kirchenbauer token pills + z-score glow display via
/api/watermark-demo - Prism beam animation fixed β
stroke-dashoffsetproportional to rubric scores (was no-op) - Decoder hint in Generate tab β calls
/api/recommendinline after streaming completes - 517 tests passing, all gates green
kairu/leaderboard.pyβ SQLite-backed score history;rank()with delta/trend/percentileskairu/analytics.pyβ histogram, nearest-rank percentiles, z-score anomalies (pure stdlib)kairu/prompts.pyβ saved prompt library with tag normalization- Live leaderboard + analytics in demo UI; "synthesised view" badges removed
- 590 tests passing
- Evaluation templates (DONE β v0.19.0)
POST /templatessaves a named rubric+criteria+weights+judges bundle to SQLite (KAIRU_TEMPLATE_DB).GET /templates,GET /templates/{name},DELETE /templates/{name}for CRUD. Apply viaPOST /evaluate/template/{name}β single-mode when no judges are present, ensemble-mode when they are. Eliminates copy-paste of repeated configurations across CI pipelines. - Adversarial prompt + response detection (DONE β v0.19.0)
POST /evaluate/adversarial_checkreturns{is_adversarial, confidence, risk_level, patterns_found, categories}. 18 default heuristics across five categories (prompt_injection, jailbreak, override, exfiltration, compliance); each pattern has a calibrated weight and targets the prompt, the response, or both. Detects classic DAN/developer-mode/ignore-previous injection attempts, system-prompt leaks, raw secret / PII / private-key exfiltration, and compliance markers (response openly states it dropped its rules). Pure stdlib regex β no ML dependency. - Multi-model tournament (DONE β v0.19.0)
POST /tournamentruns round-robin pairwiseensemble_compareacross every (model, prompt) cell of a pre-computed response grid. Returns Elo-style ratings (start 1500, K=32, total Elo conserved), win matrix, per-criterion dominance counts, and a ranked leaderboard. Tournaments persist in memory;GET /tournaments/{id}andGET /tournaments.
- Human feedback integration (DONE β v0.21.0)
POST /eval/{id}/feedbackrecords human overrides on individual audit rows.FeedbackStore(SQLite) accumulates votes per criterion. - Cross-model regression testing (DONE β v0.22.0)
GET /regression?model_a=&model_b=flags regressions >2% per criterion. Collapsible panel in Leaderboard tab β pick two models, see the diff. - Rubric marketplace (DONE β v0.23.0)
kairu/marketplace.py+api/marketplace_router.py. 4 community rubrics seeded at startup (medical, legal, creative_writing, code_review). Domain filter chips, keyword search, card grid, one-click import, publish form. 18-tab demo UI fully wired to the eval API.
Ship Gate: 31 Python tests passing.
Deliverables:
ModelInterfaceabstract base β zero-dependency contract for any model backendMockModelβ deterministic LCG-seeded mock; enables full test coverage without ML frameworksSpeculativeDecoderβ draft-model lookahead with acceptance-ratio rejection sampling (Chen et al. 2023)EarlyExitDecoderβ confidence-threshold + entropy-floor haltingTokenBudgetβ hard prompt+generation cap withconsume(),remaining,utilization()GenerationMetricsβ wall-clock timing, tok/s, mean latency, acceptance rateKairuDashboardβ Rich live panel for real-time metric displayModelWrapper+wrap_model()β unified entry point wiring all layers togetherHuggingFaceModel/_hf_backend.pyβ optional HF integration (behindkairu[hf])pyproject.tomlwithhatchlingbuild,dev+hfextras- GitHub Actions CI β Python 3.11,
pytest -v
Ship Gate: 51 Python tests passing (4 gated HF integration tests skipped without KAIRU_TEST_HF=1).
Deliverables:
kairu/tokenizer.pyβTokenizerBaseABC,MockTokenizer(deterministic, no deps),HFTokenizer(wraps HFAutoTokenizer)kairu/streaming.pyβStreamingDecoder: greedy/temperature-sampled token-by-token iterator using only NumPy +ModelInterface;stream()yields IDs,generate()collects to list; stop-token supportkairu/_hf_backend.pyβ full rewrite:HuggingFaceModelwithencode(),decode(),stream_generate()(HFTextIteratorStreamer+ threading); all heavy imports deferred to__init__so the module is importable without ML libskairu/__init__.pyβ exportsStreamingDecoder,MockTokenizer,TokenizerBase; guarded import ofHFTokenizer; version bumped to0.2.0- 8 tokenizer tests (
tests/test_tokenizer.py) β fully offline - 8 streaming tests (
tests/test_streaming.py) β usesMockModel, no HF - 8 HF backend tests (
tests/test_hf_backend.py) β 4 structural (offline), 4 integration gated behindKAIRU_TEST_HF=1
Ship Gate: 59 Python tests passing (4 gated HF integration tests skipped without KAIRU_TEST_HF=1).
Deliverables:
kairu/bench.pyβBenchmarkRunnerdriving N generation runs against anyModelInterface;build_parser()+main()CLI entry; p50/p95/p99/stddev via purestatistics+ sorted-list percentile (no scipy)kairu/bench.BenchmarkResultβ dataclass withlatencies_s,p50,p95,p99,mean,stddev,tokens_per_s_mean,hardware,timestamp;to_json()+save()(never overwrites)kairu/bench._collect_hardware()β hostname, OS, machine, CPU model (sysctl//proc/cpuinfo), total RAM (psutil/sysctl hw.memsize//proc/meminfo), Python versionkairu/__main__bench.pyβ thin re-export shim forbuild_parser,main,_collect_hardwarepython -m kairu.bench --model mock --tokens 100 --runs 50 --warmup 5exits 0 with no ML deps- 8 benchmark tests in
tests/test_bench.pyβ shape, percentile ordering, JSON round-trip, file save, hardware keys, CLI exit 0, CLI --help, filename contains timestamp+name kairu/__init__.pyexportsBenchmarkRunner,BenchmarkResult; version bumped0.2.0 β 0.3.0
Ship Gate: 73 Python tests passing (4 gated HF integration tests skipped without KAIRU_TEST_HF=1).
Deliverables:
kairu/server.pyβcreate_app(model?, tokenizer?, config?)FastAPI factory;POST /generateSSE endpoint,GET /health; OpenAI-compatiblechat.completion.chunkframes +kairuextension carrying per-tokentoken_id/index/latency_ms/tokens_per_s; final frame'sfinish_reason β {length, stop, timeout}; trailingdata: [DONE]\n\nsentinelkairu.server.ServerConfigβmax_prompt_chars,max_tokens_cap,request_timeout_s,rate_limit_requests,rate_limit_window_s; every limit enforced at the API boundary before the tokenizer is touchedkairu.server.RateLimiterβ pure-stdlib sliding-window per-key limiter,asyncio.Lock-guarded- Boundary validation: empty/oversized prompts, control characters, max-tokens cap, temperature β [0, 2], non-positive
stop_token_id - SHA-256-only prompt logging (raw content never logged)
- 14 server tests in
tests/test_server.pyβ health, OpenAI chunk shape,[DONE]sentinel, all validation paths, 429 rate limiting, request timeout, sliding-window unit tests, total_s monotonicity pyproject.tomlβ newserverextras (fastapi,uvicorn,pydantic);devextras gainpytest-asyncioandhttpx;asyncio_mode = "auto"kairu/__init__.pyβ guarded re-export ofcreate_app,ServerConfig,RateLimiter; version0.3.0 β 0.4.0
Ship Gate: 112 Python tests passing (4 gated HF integration tests skipped without KAIRU_TEST_HF=1).
Deliverables:
kairu/layered.pyβLayeredModelInterfaceextension;MockLayeredModelwith depth-monotonic confidence;LayerwiseEarlyExitDecoderreporting per-token exit layers andcompute_savedkairu/kv_cache.pyβLogitsCache(bounded LRU, O(1) get/put, hit/miss/evict stats);CachedModelwrapper memoizingnext_token_logitskeyed by prefix tuplekairu/gamma_scheduler.pyβDynamicGammaScheduler(AIMD over Ξ³, configurable bounds/thresholds/window/rates)kairu/auto_profile.pyβAutoProfile.recommend(model, name_hint?, has_draft=False)β frozenDecoderProfile{strategy, gamma, threshold, temperature, use_cache, cache_capacity, rationale}kairu/speculative.pyβ optionalschedulerkwarg; per-roundscheduler.update; stats now includefinal_gammaandgamma_adjustmentskairu/wrapper.pyβ new flagscache_capacity(transparently wraps target+draft inCachedModel) andadaptive_gamma(auto-attaches scheduler)- 39 new tests across
tests/test_layered.py,tests/test_kv_cache.py,tests/test_gamma_scheduler.py,tests/test_auto_profile.py kairu/__init__.pyβ exports new types; version0.4.0 β 0.5.0
Ship Gate: 139 Python tests passing (4 gated HF integration tests skipped without KAIRU_TEST_HF=1).
Deliverables:
kairu/rate_limit.pyβRateLimiterBackendprotocol;InMemoryBackend(default, BC-preserving) +RedisBackend(atomicMULTIpipeline with speculative-add rollback).kairu.create_app(..., rate_limit_backend=...)accepts any backend.kairu/metrics_export.pyβ pure-stdlib Prometheus exposition;Counter/Gauge/Histogram(canonical Prometheus latency buckets, O(log buckets)observe).MetricsCollectorexposes the named series the dashboard contract depends on.GET /metricsendpoint on the SSE server, instrumenting/health,/generatesuccess/422/429/500, and the active-streams gauge with propertry/finally.kairu/cli.pyβkairu serve | bench | versionconsole script.servecovers everyServerConfigfield plus--cache-capacity,--adaptive-gamma,--redis URL.kairu/_hf_backend.pyβ newHuggingFaceKVCachedModel; persistentpast_key_valueskeyed by longest-common-prefix between successive calls;kv_cache_statsandreset_cache()exposed.Dockerfile(multi-stage slim, non-root uid 1001, healthcheck) +.dockerignore..github/workflows/docker.ymlβ multi-arch (amd64/arm64) GHCR publish onmainpush andv*.*.*tags. Buildx + QEMU + GHA cache. Forks safe.- 27 new tests across
tests/test_rate_limit.py(12),tests/test_metrics_export.py(8),tests/test_cli.py(7); plus 2 server-side/metricstests. kairu/__init__.pyβ exportsMetricsCollector,InMemoryBackend,RedisBackend,RateLimiterBackend; version0.5.0 β 0.6.0.pyproject.tomladdsredisextra andkairuconsole script.
Ship Gate: 191 Python tests passing (4 gated HF integration tests skipped without KAIRU_TEST_HF=1).
Deliverables:
kairu/tracing.pyβKairuTracer(OTel API facade + automatic_NoOpTracerfallback whenopentelemetry-apiis absent). W3Ctraceparent/tracestateextraction viaextract_trace_context(headers). Per-tokenadd_eventannotations on thekairu.generateroot span (not child spans β avoids trace store bloat).record_generation_complete()/record_error()helpers.headers_from_request()normalises ASGI headers for propagation.kairu/cluster_budget.pyβClusterTokenBudget(RedisINCRBY/DECRBY/EXPIREwith speculative-rollback on cap overflow) +LocalClusterBudget(in-process,asyncio.Lock-guarded, window-resetting). Both implement theClusterBudgetBackendprotocol. Configurable scope string for multi-tenant isolation.kairu/server.pyβ JSONL streaming fallback: when the client setsAccept: application/x-ndjsonthe server emits the same frame objects as newline-delimited JSON (nodata:prefix, no[DONE]sentinel). OTel tracing wired into the_token_loopshared generator β SSE and JSONL paths both get per-token span events.create_app()now accepts an optionaltracer: KairuTracerkwarg. Serverversionbumped to0.7.0.benchmarks/run_corpus.pyβCorpusBenchmarkRunnerdriving the full 100-prompt corpus (instruction-following, Q&A, coding, summarisation, free-form) against anyModelInterface.--model mockruns fully offline. Results saved viaBenchmarkResult.save()tobenchmarks/results/(never overwrites). Standalone CLI:python benchmarks/run_corpus.py --model mock --tokens 64 --runs 100.helm/kairu/β Helm chart v0.7.0:Chart.yaml,values.yaml(image, replicas, resources, probes, autoscaling, Redis, OTel, ServiceMonitor, PDB toggles), templates (deployment.yaml,service.yaml,configmap.yaml,hpa.yaml,ingress.yaml,servicemonitor.yaml,pdb.yaml,_helpers.tpl).kustomize/β Kustomize base (Deployment + Service) + overlays:production(4 replicas, doubled resources) andstaging(1 replica).- 52 new tests:
tests/test_tracing.py(13),tests/test_cluster_budget.py(19),tests/test_jsonl_stream.py(10),tests/test_corpus_bench.py(10). All run offline withMockModel. kairu/__init__.pyβ exportsKairuTracer,extract_trace_context,ClusterTokenBudget,LocalClusterBudget; version0.6.0 β 0.7.0.pyproject.tomlβ version0.6.0 β 0.7.0; newoteloptional extra (opentelemetry-api,opentelemetry-sdk,opentelemetry-exporter-otlp-proto-grpc).
Ship Gate: 221 Python tests passing (4 gated HF integration tests skipped without KAIRU_TEST_HF=1).
Deliverables:
kairu/router.pyβDecoderRouter: given prompt token IDs and runtime signals (prompt length, draft-model availability, latency budget), deterministically selects the optimal decoding strategy (streaming/speculative/early_exit). Routing rules: tight budget (< 200 ms) β streaming; short prompt (< threshold) β streaming; draft available β speculative; otherwise β early_exit. EWMA latency tracking per strategy viarecord_outcome(decision, metrics).kairu/feedback.pyβFeedbackLoop: ingestsBenchmarkResultobjects, buffers untilmin_resultsreached, then computes mean acceptance rate and drivesDynamicGammaSchedulerup (high AR > 0.75) or down (low AR < 0.40) via 100 %/0 % synthetic update rounds. EmitsFeedbackSummaryon each flush cycle.RouterDecisiondataclass β carriesstrategy,profile(aDecoderProfilewith strategy overridden to match routing),confidence,rationale,latency_budget_ms.RoutingStatsdataclass β per-strategy decision counts, per-strategy EWMA latency, total routed.FeedbackSummarydataclass βn_results,mean_acceptance_rate,gamma_adjusted,new_gamma,recommendation.- 16 router tests in
tests/test_router.pyβ construction, all routing branches, budget override, stats accumulation, EWMA update, profile strategy alignment. - 14 feedback tests in
tests/test_feedback.pyβ flush threshold, buffer clearing, gamma direction, summary fields, multi-cycle operation. kairu/__init__.pyβ exportsDecoderRouter,RouterDecision,RoutingStats,FeedbackLoop,FeedbackSummary; version0.7.0 β 0.8.0.
Ship Gate: 239 Python tests passing (4 gated HF integration tests skipped without KAIRU_TEST_HF=1).
Deliverables:
kairu/watermark.pyβ Kirchenbauer et al. (2023) green/red list watermarking scheme implemented with pure NumPy + stdlib (hashlib,math,struct). No ML framework dependency.WatermarkLogitsProcessorβ at each decoding step, hash-seeds a green/red partition of the vocabulary using the preceding token (or a context window) then adds a scalar biasΞ΄to all green-list logits before softmax. Supportsseeding_scheme β {"single", "context"}. Never mutates the input logits array.WatermarkDetectorβ given a token sequence + optional prompt prefix, reconstructs the per-step green lists (identical seeding parameters) and counts green tokens. Computes z-score against the Binomial(T, 0.5) null (well-approximated by N for T β₯ 20) and one-sided p-value viamath.erfc(no scipy). Returns a frozenWatermarkResultdataclass.WatermarkResultβ frozen dataclass carryingnum_tokens,num_green,green_fraction,z_score,p_value,decision,threshold._norm_sf(z)β exact normal survival function viamath.erfc; no scipy dependency.
kairu/streaming.pyβStreamingDecodergains optionalwatermark: WatermarkLogitsProcessor | Noneconstructor kwarg. When set,process()is called on every logit array before sampling; when None the code path is identical to v0.8.0 (zero overhead).- 18 new tests in
tests/test_watermark.pyβ covering: seed determinism, seed uniqueness, green-list shape/fraction/reproducibility, processor construction validation, logit bias correctness, immutability of input, shape-mismatch error, empty context, scheme divergence, detector construction, empty sequence error, result fields, watermarked-sequence z-score direction, unwatermarked no false positive, frozen result mutation,_norm_sfedge cases and monotonicity. kairu/__init__.pyβ exportsWatermarkLogitsProcessor,WatermarkDetector,WatermarkResult; version0.8.0 β 0.9.0.pyproject.tomlβ version0.8.0 β 0.9.0; description updated.
Ship Gate: 286 Python tests passing (4 gated HF integration tests skipped without KAIRU_TEST_HF=1).
Deliverables:
kairu/squish_eval.pyβ pure-stdlib quality rubric for evaluating LLM outputs across quantization tiers (FP16 baseline vs INT8/INT4/INT2 quantized).- 5-criterion
SquishEvaluator(correctness, fluency, faithfulness, completeness, safety) β every score in[0, 1], aggregate is unweighted mean. quality_degradation_report(...)β per-criterion delta + retention% per tier; tiers ordered by descending bit-width.recommended_quant_tier(report, tolerance)β returns the deepest tier still within(1 - tolerance) * 100% retention.- All result types are frozen dataclasses with
as_dict()for JSON transport.
- 5-criterion
POST /compare/quantizationinkairu/server.pyβ Pydantic-validated, rate-limited, pure-CPU endpoint that wraps the module-level functions and returns{report, recommended_tier, tolerance}.demo/sample_comparisons/04_quantization_comparison.jsonβ realistic GPT-4 vs INT8/INT4/INT2 sample over 5 prompts with verified retention numbers and ready-to-POST request body.- 20 new tests (
tests/test_squish_eval.py+tests/test_server.py) covering identical/degraded/garbage tiers, empty inputs, length mismatches, recommendation thresholds, frozen-dataclass invariants, JSON round-trip, and HTTP-level integration. kairu/__init__.pyandpyproject.toml: version0.9.0 β 0.10.0; description updated.
Ship Gate: 294 Python tests passing, 4 skipped HF-gated (32 evaluation + 16 HTTP-boundary tests added).
Deliverables:
kairu/evaluation.pyβ seven heuristic scorers (relevance F1, coherence trigram-uniqueness, conciseness Gaussian, safety regex categories, fluency sentence-length + TTR, specificity entity density, completeness recall). All deterministic, pure-stdlib, bounded to [0, 1].- Five built-in rubrics:
default,helpfulness,safety_focused,concise_qa,creativeβ composable withweights={β¦}overrides per call. compare()returnsComparisonwith absolute margin and per-criterion winner using aTIE_EPSILON = 0.005noise floor.evaluate_batch()+to_csv()β batch driver returning JSON or CSV-ready rows.api/main.pyβ FastAPI app exposingPOST /evaluate,POST /compare,GET /rubrics,POST /batch,GET /health; pydantic v2 models, 413 on oversize, 422 on bad rubric/criterion.api/Dockerfile(slim, non-root,$PORT-aware),api/requirements.txt,render.yamlβ deployable to Render / Fly / GKE.demo/sample_comparisons/β 3 runnable A/B fixtures withexpected_winnerfor regression validation.kairu/__init__.pyβ re-exportsevaluate,compare,evaluate_batch,to_csv,Evaluation,Comparison,Rubric,CRITERIA,RUBRICS; version0.10.0 β 0.11.0.
Ship Gate: 313 tests passing, 4 HF-gated skipped (13 rubric + 6 API-route tests added).
Deliverables:
kairu/rubrics.pyβRUBRIC_DEFS: eight named rubrics (helpfulness, accuracy, safety, coherence, conciseness, creativity, groundedness, tone) with curated weights + canonical hex color per rubric.kairu/evaluation.RUBRICSauto-materialises fromRUBRIC_DEFS.- API:
GET /rubrics/{name}+POST /evaluate/rubric/{name}(path-param routing). demo/server.pyβPOST /api/prismruns all eight rubrics on one (prompt, response[, response_b]); pure stdlib, 16 KB input cap.demo/index.htmlβ full rebuild as the prism UI: pure dark#06060f, idly-rotating SVG triangular prism, eight color-coded beams, A/B mode with offset dashed beams, click-to-evaluate, hover tooltips, kbd shortcut.- 19 new tests across
tests/test_rubrics.pyandapi/test_api.py.
Ship Gate: 336 Python tests passing, 4 HF-gated skipped (25 new shield tests added).
Deliverables:
-
kairu/shield.pyβPromptShield,ShieldVerdict(StrEnum: ALLOWED/FLAGGED/BLOCKED),ShieldResult(frozen dataclass),ShieldRule,ShieldConfig,get_default_shield()singleton - 12 default rules: prompt injection (ignore/disregard/forget/override), jailbreak (DAN mode, developer mode, you-are-now, pretend-no-restrictions), roleplay bypass, prompt manipulation
- PII detection: email, SSN (NNN-NN-NNNN), credit card (16-digit), phone β configurable FLAGGED or BLOCKED
- Fail-open design: shield exceptions log a warning and return ALLOWED (never crash callers)
- Patterns compiled at class construction, not per-call
- Server integration:
create_app(shield=...)β shield runs before rate limiting; BLOCKED β HTTP 400{"error":"blocked","reason":...}; FLAGGED βX-Shield-Warningheader, request continues - CLI:
kairu shield "<prompt>" [--json]β usesget_default_shield() -
kairu/__init__.pyexports:PromptShield,ShieldConfig,ShieldResult,ShieldVerdict,ShieldRule,get_default_shield - 25 tests in
tests/test_shield.pyβ all offline except 2 server integration tests (TestClient)
Ship Gate: 356 Python tests passing, 4 HF-gated skipped (20 new streaming-API tests added).
Deliverables:
-
kairu/streaming_api.pyβStreamingConfig(dataclass: max_tokens, temperature, stop_sequences, seed, stream_chunk_delay_ms),StreamChunk(frozen dataclass: id, content, finish_reason, index;to_sse_line(),to_dict()),TokenStreamer(wrapsStreamingDecoder; stop-sequence detection; max-tokens cap; never raises β exceptions yieldfinish_reason="error") -
POST /generate/streamendpoint inkairu/server.pyβStreamRequestPydantic model; shield runs synchronously before streaming begins; BLOCKED β HTTP 400 JSON; FLAGGED βX-Shield-Warningheader + stream continues; rate-limited;StreamingResponsewithmedia_type="text/event-stream" - SSE format:
data: {chunk_json}\n\nper token,data: [DONE]\n\nsentinel at end; OpenAI-compatiblechoices[0].delta.content+finish_reason - Seeded determinism via
StreamingConfig.seedβ same seed always yields same token sequence -
kairu/__init__.pyexportsStreamingConfig,StreamChunk,TokenStreamer; version0.13.0 β 0.14.0 -
pyproject.tomlversion0.13.0 β 0.14.0 - 20 tests in
tests/test_streaming_api.pyβ unit tests for StreamChunk + TokenStreamer, API endpoint tests (200, content-type, data lines, [DONE], JSON validity, choices field, shared id, shield block, shield flag header, max-tokens enforcement)
Ship Gate: 438 Python tests passing, 4 HF-gated skipped (90 new tests across tests/test_ensemble.py [18], tests/test_ci_regression.py [15], tests/test_log_eval.py [11], and 14 HTTP endpoint tests in api/test_api.py).
Deliverables:
-
kairu/ensemble.pyβJudgeConfig(name, rubric, criteria, weights, seed, noise),JudgeScore,EnsembleResult(median_scores, stdev_scores, median_aggregate, max_disagreement, disagreement_flag),EnsembleComparison. Aggregation uses median per criterion (robust to one outlier) and reports per-criterion stdev as the disagreement metric. Deterministic seeded Gaussian noise simulates inter-judge variance without sacrificing test reproducibility. Real LLM judges plug in behind the sameJudgeConfigcontract. -
kairu/ci_regression.pyβBaselineSnapshot(immutable, JSON-round-trippable),BaselineItem,CriterionRegression,RegressionReport.snapshot_baseline()scores a golden corpus and freezes it.check_against_baseline()matches items by input-hash, flags any per-criterion drop >threshold(default 0.05), reports unmatched-input drift in both directions.BaselineStore(in-memory) +FileBaselineStore(atomic write via tempfile + rename, auto-loads fromKAIRU_CI_DIR). -
kairu/log_eval.pyβLogItemResult,LogEvalReport.evaluate_log()batch-evaluates{input, output, metadata?}records through a named rubric; returnsmean/median/min/max/stdevaggregates, per-criterion mean and min, per-item pass flags, andpassed: boolkeyed onmean_aggregate >= threshold(default 0.5). Metadata passes through untouched for downstream slicing by request id / region / model tag. - HTTP endpoints in
api/main.py:POST /evaluate/ensembleβ single (prompt, response) through N judgesPOST /compare/ensembleβ A/B through N judges with winner + per-criterion breakdownPOST /ci/baselineβ freeze a golden snapshot; returnssnapshot_idPOST /ci/checkβ score a candidate run against a snapshot; returnsRegressionReportwithpassed: boolGET /ci/baselinesandGET /ci/baselines/{snapshot_id}β list / inspect snapshotsPOST /eval_from_logβ production-log batch eval gate
-
app.state.baselineswires aBaselineStoreintocreate_app(resolvable viaKAIRU_CI_DIRenv) -
kairu/__init__.pyexports:JudgeConfig,JudgeScore,EnsembleResult,EnsembleComparison,ensemble_evaluate,ensemble_compare,judge_evaluate,DEFAULT_DISAGREEMENT_THRESHOLD,BaselineSnapshot,BaselineItem,BaselineStore,FileBaselineStore,CriterionRegression,RegressionReport,snapshot_baseline,check_against_baseline,open_default_store,DEFAULT_REGRESSION_THRESHOLD,LogEvalReport,LogItemResult,evaluate_log,DEFAULT_LOG_THRESHOLD; version0.15.0 β 0.16.0. -
pyproject.tomlversion0.15.0 β 0.16.0; description extended.
Phase 19 β Evaluation Templates + Adversarial Detection + Multi-Model Tournament (v0.19.0) β COMPLETE
Ship Gate: 544 Python tests passing, 4 HF-gated skipped (β₯60 new test outcomes across tests/test_templates.py [11], tests/test_adversarial.py [17], tests/test_tournament.py [15], and 15 HTTP endpoint tests in api/test_api.py).
Deliverables:
-
kairu/templates.pyβEvaluationTemplatefrozen dataclass +TemplateStore(SQLite, INSERT OR REPLACE semantics,created_utcpreserved across updates). Materialises judge configs from stored JSON for ensemble templates.KAIRU_TEMPLATE_DBenv resolves the file path (defaults to:memory:). -
kairu/adversarial.pyβAdversarialPattern(named regex + category + weight + target), 18 default patterns spanning prompt_injection, jailbreak, override, exfiltration, compliance.check_adversarial(prompt, response)returnsAdversarialReport(is_adversarial, confidence β [0,1], risk_level, patterns_found, categories, n_prompt_matches, n_response_matches). Confidence ismin(1.0, Ξ£ matched_weight / 2.0); risk-level bands at 0.3 / 0.6. -
kairu/tournament.pyβrun_tournament(models, prompts, judges)runs every pair Γ every prompt throughensemble_compare, tracks wins/losses/ties + per-criterion dominance, applies standard chess Elo (start 1500, K=32).TournamentResultcarries the win matrix, Elo dict, sortedModelRankinglist. In-memoryTournamentStorefor retrieval. - HTTP endpoints in
api/main.py:POST /templates,GET /templates,GET /templates/{name},DELETE /templates/{name}POST /evaluate/template/{name}β applies a saved template (single or ensemble)POST /evaluate/adversarial_checkPOST /tournament,GET /tournaments,GET /tournaments/{tournament_id}
-
kairu/__init__.pyexports:EvaluationTemplate,TemplateStore,open_default_template_store,AdversarialPattern,AdversarialMatch,AdversarialReport,ADVERSARIAL_DEFAULT_PATTERNS,check_adversarial,TournamentMatch,ModelRanking,TournamentResult,TournamentStore,run_tournament,DEFAULT_ELO_K,DEFAULT_ELO_START. Version0.18.0 β 0.19.0. -
pyproject.tomlversion0.18.0 β 0.19.0.