align / code /docs /KIMINA_SERVER_BACKEND.md
viai957's picture
Add files using upload-large-folder tool
d909bd8 verified
|
Raw History Blame Contribute Delete
6.61 kB

Kimina Lean server as an optional pre-filter (evaluation, 2026-10-19)

Verdict: built, pinned, safe by construction, and not worth adopting as a throughput layer on the P2 population. It cannot replace the strict verifier (compile-only: 40 of 54 code-bearing adversarial cases compile clean) and as a pre-filter in front of it the pipeline is ~52 % slower than the strict verifier alone. Code stays optional; nothing in align/verify/lean/ changed.

What was built (all under /apps/development/rlhf/toolchains/)

Server project-numina/kimina-lean-server @ fb2393de (server 2.0.0, Apache-2.0; its client package is MIT) in src/kimina/kimina-lean-server; venv kimina-venv (py3.11.13, fastapi 0.116.1, uvicorn 0.35.0, psutil 7.0.0, prisma client generated, no DB)
Lean / Mathlib the SAME install as our verifier: Lean 4.9.0-rc1, Mathlib d1d1e4b7 (/apps/development/rlhf/lean/workspace), selected with LEAN_SERVER_PROJECT_DIR; nothing rebuilt
REPL leanprover-community/repl@v4.9.0-rc1 (7df77c0) + cherry-pick 4fc1e6d (flush stdout per reply) in work/kimina-repl49, binary sha256 699eed80.... Our verifier's REPL (32412d14...) lacks that commit and relies on stdbuf; Kimina starts the REPL through lake env with plain pipes, so it needs the patch (Kimina's own setup.sh applies the same cherry-pick for Lean <= 4.9.0). The patch only flushes stdout.
Launch scripts/p2/kimina_server_start.sh: scrubbed env, loopback only, MAX_REPLS=4, under hostguard.py run --cores 4

Not pinnable / not built: Pantograph (leanprover/Pantograph, Apache-2.0): oldest tag v0.2.18 needs Lean 4.10.0-rc1, current 4.31; no release for 4.9.0-rc1. DeepSeek xinhjBrant/repl@deepseek is the REPL fork already used upstream of our pin (extra allTactics/ast/premises options we do not use); plain REPL variants are what we already run. Kimina was the only candidate that serves our pin unchanged.

Safety design (align/verify_backends/kimina_server.py)

  • PrefilterVerdict is reject | maybe | error; no accepted field; bool(verdict) raises.
  • GatedVerifier.verify reports an accept only from the wrapped StrictVerifier's own verdict on the same code. maybe and error (timeout, dead server, bad reply) always go to the strict verifier; only reject short-circuits, which can lose recall but never soundness. Server down means "strict only".
  • Loopback URLs only (the server has no sandbox, no axiom audit, no statement bridge, no lexical gate; it applies only RLIMIT_AS).
  • stdlib only (dependency firewall passes). tests/test_kimina_backend.py: 9 tests against a fake server, including "server says it compiles, strict rejects => reject" and "no accept expression in the module".

Measurements (scripts/p2/backend_agreement.py, report: docs/results/kimina_agreement_report.json)

741 items: 180 known-good (ceiling-test rows + restated), 61 adversarial, 500 random code-bearing records of gen_minif2f_c40960.jsonl (seed 20261019, population 7632; finish_reason=length and code-less records are excluded because both sides reject them without Lean). 4 workers/REPLs each, 180 s budget, phases run one at a time. Control: our own REPL pool, compile-only, to separate server overhead from strict-tier overhead.

Agreement (rows ours, columns Kimina pre-filter):

ours \ Kimina maybe reject error
accept (485) 485 0 0
reject (213) 40 173 0
undecided (43: timeout/crash/memory) 5 5 33

Known-good: ours accepts 177/180, Kimina passes 179/180. Adversarial: ours accepts 0/61, Kimina compile-only passes 40 (all 40 are rejected by our lexical/target/header/axiom layers: axiom, native_decide, statement changes, hole constructs, wrong names, banned constructs); gated accepts 0/61. Sample (500): 308 strict accepts all passed the pre-filter; 155 rejects agree; 0 strict-only rejects in the sample (the policy layers matter on adversarial text, not on this honest-policy population).

Disagreements: 0 pre-filter false rejects. 40 strict-only rejects, all adversarial (listed in the report with reasons). 43 undecided, all budget/limit effects: 33 where Kimina returned error (28 timeouts that ours also hit; the 3 bomb cases: ours timeout / crash / memory kill, Kimina a 30 s timeout for each; 2 sample proofs that ours memory-killed at ~21 s and Kimina answered HTTP 500 after ~129 s, i.e. its only memory defence is RLIMIT_AS); 5 proofs where our strict tier timed out at 180 s but Kimina decided maybe (81-152 s; incl. the known lean_workbook_51088, ..._plus_64037: the strict reference-env/audit layering slows borderline nlinarith, see LEAN_VERIFIER.md 5.1); 5 where strict timed out and Kimina found a compile error. Control: our compile-only vs Kimina agree on 648/650 jointly-decided items; the 2 diffs are instant crash records in the control pool (0.2 s, harness artifact, both strict-accepted).

Throughput (same 680 kg+sample items, per-worker busy time, 4 cores):

engine proofs/s/core total busy s
our strict verifier 0.0491 13862
our REPL, compile-only 0.0585 11626
Kimina server, compile-only 0.0602 11300

Kimina is 2.8 % faster than our own REPL doing the same compile-only job (same Lean engine; Lean elaboration is the cost, not the front end) and 18 % faster than the strict verifier, which includes reference env + audit. Pipeline "Kimina then strict on survivors": 11300 + 9762 = 21061 s vs 13862 s strict alone (+52 %). It rejects 160/680 (23.5 %) and saves 4100 s of strict work, but pays 11300 s up front. A pre-filter only pays when its cost on rejects is far below the strict cost on rejects, which a same-engine compile cannot be (mean per reject: Kimina 16.6 s vs strict 20.5 s; accepts, 76 % of survivors, are compiled twice).

Recommendation

  1. Do not put Kimina in the reward path as a pre-filter for P2-like populations (accept rate ~60 %).
  2. It could only help if the survivor rate were very low (<~20 %) and a cheap budget (e.g. 10-20 s) were used to reject; that is not the regime measured here, and a short budget turns slow valid proofs into losses.
  3. Where it is useful: a loopback-only compile-feedback service (error positions for correction rounds) and as an independent second implementation of "does it compile" for sanity checks.
  4. The real strict-tier throughput lever is not the server: it is the per-proof REPL work (reference env, audit prelude) and the heavy nlinarith tail (p90 92 s on the sample).