EvoX Genesis
EvoX Genesis는 고수준 목표를 재귀적 소프트웨어 세계로 전환해, 유한 에이전트가 개발하고 승인된 결과만 유지됩니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Local, Apple Silicon (MLX) test for hidden position bias in LLM-as-a-judge models.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A small, local, reproducible harness for measuring position-swap inconsistency in
LLM-as-a-judge models — the bias where a judge's verdict changes just because two answers
swap places. It runs offline on Apple Silicon (Apple MLX), writes one JSONL record per judge
call, and reports a single dark_current_score.
Status: first real runs complete. Three open-weight judges evaluated locally on a 12-item mini-slice (see Results); per-call records committed under
results/. A paper-aligned benchmark slice is the next milestone. This is independent work, not an official reproduction (see Scope).
Evaluating open-source judges usually drifts toward paid API baselines or GPU-heavy pipelines. This harness keeps the first pass local, deterministic, and auditable on a laptop:
[[A]] / [[B]] / [[Tie]] verdicts from the judge's free text;A → B, flips B → A, and keeps Tie → Tie;dark_current_score = fraction of items where the judge was not
order-invariant (strict: an item with an unparseable verdict counts too, so the Results
below report order-dependent and unparseable items separately).Three open-weight judges, fully local (MacBook M3 Pro 18 GB, mlx-lm 0.31.3), greedy decoding
(temperature=0.0, seed=42, max_tokens=512). The mini-slice
(data/minislice_v0.jsonl) has 12 hand-written pairwise items in
three conditions: clear_gap (one answer plainly better, better side balanced 2/2),
identical (byte-identical answers — any A/B pick is pure position signal), paraphrase
(same content, different wording). 12 items × 2 orders = 24 judge calls per model.
| Judge (4-bit MLX) | clear_gap | identical | paraphrase | order-dependent | unparseable | strict score | gen tokens | wall |
|---|---|---|---|---|---|---|---|---|
| Meta-Llama-3-8B-Instruct | 0/4 | 1/4 | 2/4 | 3/12 (0.250) | 1 | 0.333 | 4,459 | 170 s |
| Mistral-7B-Instruct-v0.3 | 0/4 | 0/4 | 3/4 | 3/12 (0.250) | 1 | 0.333 | 2,725 | 106 s |
| Qwen2-7B-Instruct | 0/4 | 2/4 | 3/4 | 5/12 (0.417) | 0 | 0.417 | 1,508 | 71 s |
Condition cells count order-dependent items: both verdicts parsed, and the verdict changed
with the A/B order. Unparseable items have one call without the strict marker, and neither
call was truncated: Llama-3 answered a clear_gap item correctly in prose but skipped [[B]];
Mistral wrote [Tie] with single brackets on a paraphrase item it had called a tie in the other
order. The strict score is the dark_current_score the CLI summary reports, which counts
unparseable items as not order-invariant (it was this README's headline number until
2026-10-24).
What the aggregate score hides:
clear_gap item, and
the parsed clear_gap verdicts picked the objectively better answer in both orders 11/12
times (the twelfth is Llama-3's unparseable call).Reproduce the breakdown (order-invariant / order-dependent / unparseable per condition, plus
the strict score): python3 scripts/category_breakdown.py results/*_minislice_v0.jsonl.
Full per-call records (hardware metadata, generation config, usage stats, raw generations,
parsed verdicts) are committed under results/.
Budget note. The runner aligns the tokenizer-declared chat eos token with the
mlx-lmstop set (Llama-3 declares<|eot_id|>, whose id is missing from the wrapper's stop ids). Before the fix every call burned the full 512-token budget with identical verdicts: 12,288 vs 4,459 generated tokens and 435 s vs 170 s. Per-callusagerecords token counts, tps, peak memory, andfinish_reason; summaries aggregate them inusage_totals.
Two deterministic mock judges validate the metric end-to-end — no model download, no network.
A purely position-biased judge should score 1.0 (maximally inconsistent); an order-invariant
judge should score 0.0. Both hold:
| Mock judge baseline | Items | Swap-consistent | dark_current_score |
|---|---|---|---|
position (always picks slot A) | 2 | 0 | 1.00 |
tie (always [[Tie]]) | 2 | 2 | 0.00 |
$ python3 -m unittest discover -s tests → Ran 8 tests ... OK (~0.02s)
These mocks are sanity baselines, not real judges: they prove the pipeline, parser, and
metric behave correctly before any model is loaded. Plugging in a real MLX judge is a
one-flag change (--runner mlx --model ...).
Validates dataset loading, prompt rendering, JSONL output, and the metric:
python3 eval_pipeline.py --runner mock --input data/sample_pairwise.jsonl
# writes results/run.jsonl and results/summary.json, prints the summary
PYTHONPATH=src python3 -m unittest discover -s tests
uv venv && source .venv/bin/activate
uv pip install -e ".[mlx]"
python3 eval_pipeline.py \
--runner mlx \
--model mlx-community/Meta-Llama-3-8B-Instruct-4bit \
--input data/minislice_v0.jsonl \
--output results/llama3_8b_4bit_minislice_v0.jsonl \
--report results/llama3_8b_4bit_minislice_v0_summary.json
Input is JSONL, one pairwise item per line:
{"item_id": "sample_fibonacci", "instruction": "Write a Python function for Fibonacci numbers.", "response_a": "...", "response_b": "...", "model_a_id": "toy_recursive", "model_b_id": "toy_iterative", "metadata": {"source": "local_sample"}}
Legacy prototype field names (id, model_a_response, model_b_response) are also accepted,
so older data files still load. Use --input builtin for an in-memory two-item smoke set.
One JSONL record per judge call (order is ab or ba); see schema.json:
{
"eval_id": "uuid shared across the run",
"item_id": "sample_fibonacci",
"judge_model": "mlx-community/Meta-Llama-3-8B-Instruct-4bit",
"hardware_env": {"platform": "macOS-...-arm64", "machine": "arm64", "python_version": "3.x"},
"generation_config": {"max_tokens": 256, "temperature": 0.0, "seed": 42},
"prompt_template_id": "pairwise_judge_v1",
"order": "ab",
"inputs": {"model_a_id": "...", "model_b_id": "...", "instruction": "...", "response_a": "...", "response_b": "...", "metadata": {}},
"outputs": {"raw_generation": "... [[A]]", "parsed_position_winner": "A", "parsed_original_winner": "model_a"},
"timing": {"latency_s": 0.0},
"usage": {"prompt_tokens": 310, "generation_tokens": 142, "prompt_tps": 250.0, "generation_tps": 28.5, "peak_memory_gb": 5.1, "finish_reason": "stop"}
}
parsed_position_winner is which slot won (A/B/tie); parsed_original_winner maps that back
to the original model id, so a swap-inconsistent judge is visible at the item level.
src/dark_current_mlx/
cli.py # argparse CLI (entry point: dark-current-mlx)
pipeline.py # A/B + B/A runs, JSONL writer, summary metrics + usage totals
runners.py # MockRunner (offline) + lazy MlxRunner (sampler API, eos alignment, usage stats)
verdicts.py # strict [[A]]/[[B]]/[[Tie]] parser + swap-consistency logic
models.py # PairwiseItem / Verdict / GenerationConfig dataclasses
prompts.py # pairwise_judge_v1 template + A/B-swap renderer
dataset.py # JSONL loader (+ legacy schema) and builtin sample
eval_pipeline.py # backward-compatible entry point (no install needed)
data/sample_pairwise.jsonl # 2-item dry-run sample
data/minislice_v0.jsonl # 12-item mini-slice (clear_gap / identical / paraphrase)
scripts/category_breakdown.py # per-condition order-dependent / unparseable split from run JSONL
schema.json # output record shape
tests/ # 8 offline unit tests (no network / no MLX / no downloads)
docs/ # results-note template + drafts
results/ # committed: the three mini-slice v0 runs (records + summaries)
The MlxRunner imports mlx-lm lazily, so the tests and the mock runner never touch MLX —
that is why the whole suite runs in well under a second with zero downloads.
| Area | State |
|---|---|
Package + CLI (mock / mlx runners) | ✅ done |
| Strict verdict parser + swap-consistency metric | ✅ done |
| JSONL output + reproducibility metadata + summary | ✅ done |
| Offline test suite (8 tests) | ✅ done |
| Real MLX judge run on a mini-slice (3 open judges, fixed seed) | ✅ done (see Results) |
| Budget-aware usage fields (tokens, tps, peak memory, finish reason) | ✅ done (scaffold/routing dimensions planned) |
| Order-dependent vs unparseable split | ✅ in scripts/category_breakdown.py; 🔜 in the CLI summary |
| Compact results note for the paper authors | ✅ sent 2026-07-03 (draft in docs/) |
| Paper-aligned benchmark adapter (MT-Bench / AlpacaEval-style) | 🔜 planned |
Inspired by "LLM Judges Have Dark Current: A Psychometric Datasheet for LLM-as-a-Judge
Evaluation" (Usami et al.). This is an independent pilot exploring local reproducibility
on Apple Silicon. It is not endorsed by the authors and does not reproduce the paper's
full results. The authors acknowledge it in the README of their revised repository,
dark-current-v2-review. No
proprietary API calls are used anywhere in the pipeline.
MIT — see LICENSE.