Skip to content
EnvLoopPublic

About

Pev: a calibrated fast-decision model for personal agents — Pev-Bench benchmark, evaluation harness, LoRA on Qwen3.8-27B, tech report

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

Repository files navigation

Pev

A calibrated fast-decision model for personal agents with long-term memory, and the pre-registered benchmark it was evaluated on.

Paper page · Paper (PDF) · Model · Dataset · Leaderboard · Leaderboard Space · Collection · License

Tests Code: Apache-2.0 Model and data: CC BY-NC 4.0, gated

Personalized agents (assistants that remember one user and act for them across shopping, travel, email and calendar) are becoming a mainstream direction. Their hard part is not generating text but personal judgement: doing what this user would want. Asked to "re-order the dog food", an agent has to know that the user switched brands after an allergy, that the new $54 bag now exceeds the user's $50 approval rule, that an address the user asked it to forget must not be reused, and whether the request is worth interrupting the user for. An agent that asks about everything is useless; one that acts on a wrong guess is unsafe.

Pev-27B answers these personal decisions as typed questions in a single forward pass with calibrated probabilities, so an agent can automate the confident ones under an error budget and ask about the rest. It is a LoRA adapter on Qwen3.8-27B, evaluated on Pev-Bench, a pre-registered benchmark built from real public user behaviour. On a public test set of 720 new users it reaches 0.915 family-macro accuracy, ahead of gpt-6-astra (0.873), Kev-27B (0.823), Jev (0.788) and its base model (0.762).

Highlights

  • Benchmark from real public behaviour. Users' histories come from Amazon Reviews 2023 and Google Local 2021; personal rules (approvals, privacy, contacts, notifications, forget requests) are synthetic and seeded per user. Labels are computed from a knowledge base, never by an LLM; an LLM only renders the state into natural text, and the evidence for every label must appear verbatim.
  • Pre-registered evaluation. The pre-registration was written before any evaluation data existed and was only extended by dated amendments. The model was selected on DEV, passed a one-shot HIDDEN gate, and was then compared once with five other models on a TEST set built after it was frozen and committed by hash (docs/TEST_COMMITMENT.json).
  • Simple method. Supervised fine-tuning on the single option-label token; prediction is a temperature-scaled softmax over the label tokens' log-probabilities.
  • Results. Family-macro accuracy 0.915 on TEST, ahead of every compared model in both renderer halves, with automation coverage 0.94 at a 5% error budget.

Task

Each record is one state (what the agent remembers, the current request and candidate actions, sometimes with thousands of tokens of distractor text) with one to three typed questions:

Family Type Question
apply_memory yes/no Is this remembered fact relevant to the request (or would using it over-personalise)?
forgotten_violation yes/no Does the action rely on something the user asked to forget?
needs_approval yes/no Must the agent ask before acting (spend threshold, new recipient, irreversible action)?
share_ok yes/no May this memory be shared with this recipient under the user's privacy settings?
route choice Which connected service handles this, or should the agent ask the user?
notify_level score 0–3 Silent, digest, notify or interrupt, given urgency, quiet hours, meetings and VIPs
pick_option choice Which option will this user actually choose and rate highly? (labels from real later behaviour)

Results

TEST (public; 720 new users, 980 states, 2,156 scorable questions; half A rendered by gpt-6-astra, half B by Claude Opus 5.5; pseudonymized before any model was scored; every model run once). Family-macro accuracy and Pev-27B's paired lead in points with a 95% state-clustered bootstrap CI (Holm-adjusted p = 5 × 10⁻⁴ for all five comparisons):

Model All A half (gpt-6-astra) B half (Claude Opus 5.5) Pev-27B − model, all
Qwen3.5-4B (zero-shot) 0.652 0.627 0.677 +26.3 [+24.1, +28.4]
Qwen3.8-27B (base, zero-shot, same prompt) 0.762 0.759 0.766 +15.2 [+13.6, +16.8]
Jev (jev-1.13.0) 0.788 0.779 0.797 +12.7 [+11.2, +14.1]
Kev-27B 0.823 0.825 0.821 +9.2 [+7.8, +10.5]
gpt-6-astra 0.873 0.876 0.871 +4.1 [+2.8, +5.5]
Pev-27B 0.915 0.913 0.917 —

The pre-registered sensitivity analysis without pick_option (amendment 7) agrees in every comparison and half (Pev-27B 0.987 on the other six families). pick_option stays hard for every model (0.41–0.48, against a "priciest" shortcut of 0.347 and chance 0.276), so no progress is claimed there. Safety false negatives (forgotten_violation / needs_approval / share_ok): Pev-27B 0% / 1.3% / 2.0%, gpt-6-astra 0.7% / 0% / 0%. Full tables: docs/RESULTS.md and docs/TEST_RESULTS.json.

TEST family-macro accuracy per model, overall and per renderer half

TEST family-macro accuracy per model, overall and per renderer half (A: gpt-6-astra, B: Claude Opus 5.5).

Pev-27B minus each model on TEST with paired 95% CIs

Pev-27B minus each model on TEST, family-macro accuracy with paired 95% CIs, overall and per half.

HIDDEN (one-shot pre-registered gate; 960 states from 720 users, 2,106 scorable questions, half in rendering styles never seen in training; not released): family-macro accuracy 0.754 → 0.905 (+15.1 points, 95% CI [+13.5, +16.8], one-sided p = 1 × 10⁻⁴); all seven pre-registered checks pass. Automation coverage at a 5% error budget rises from 0.54 to 0.93. pick_option does not improve significantly (0.40 → 0.43) and should remain "ask the user" in deployment.

Per-family accuracy on HIDDEN for the base model and Pev-27B

Per-family accuracy on HIDDEN for the base model (orange) and Pev-27B (blue), with chance marks.

DEV (630 states, 1,409 scorable questions; the model-selection set): Qwen3.5-4B 0.638, Qwen3.8-27B (base) 0.766, Jev 0.785, Kev-27B 0.824, gpt-6-astra 0.881, Pev-27B 0.907. DEV and VAL numbers were computed on the pre-pseudonymization text; the released VAL and DEV are pseudonymized (options and labels unchanged), so re-running on them may differ slightly. TEST was pseudonymized before scoring (released TEST = scored TEST).

Quick start

Requirements: uv, Python 3.12, and one 80 GB GPU (H100/H200 class) for the model. The model and the dataset are gated: accept their terms on the Hugging Face Hub first.

git clone https://github.com/EnvLoop/Pev && cd Pev
uv sync --project packages/decision-eval --extra fast          # --extra fast: Linux/CUDA kernels for Qwen3.8
alias hf="uv run --project packages/decision-eval hf"           # the Hugging Face CLI from the same environment
hf auth login
hf download EnvLoop/Pev-27B-LoRA --local-dir adapter
hf download EnvLoop/Pev-Bench --repo-type dataset --local-dir data

Load the model and score one record (run with uv run --project packages/decision-eval python; the same code as usage_example.py on the Hub):

import json, torch
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
from decision_eval.conventions import question_keys
from decision_eval.prompts import MODEL, REVISION, render_prompt, verify_labels   # Qwen/Qwen3.8-27B @ 1d4bf0f2

tok = AutoTokenizer.from_pretrained(MODEL, revision=REVISION)
base = AutoModelForCausalLM.from_pretrained(MODEL, revision=REVISION, dtype=torch.bfloat16, device_map={"": "cuda"})
model = PeftModel.from_pretrained(base, "adapter", is_trainable=False).eval()
T = json.load(open("adapter/temperature.json"))["temperature"]               # 2.772, fitted on VAL

record = json.loads(open("data/test_a.jsonl").readline())
for qid, q in record["questions"].items():
    prompt, labels = render_prompt(record, qid, "direct", tok)               # frozen template, thinking disabled
    ids = tok(prompt, add_special_tokens=False, return_tensors="pt").input_ids.to(model.device)
    with torch.no_grad():
        logits = model(input_ids=ids, logits_to_keep=1).logits[0, -1].float()
    probs = torch.softmax(torch.log_softmax(logits, -1)[verify_labels(tok, labels)] / T, -1)
    print(qid, dict(zip(question_keys(q["type"], q.get("criteria")), probs.tolist())), "label:", q.get("label"))

Evaluate the adapter against its base model on TEST (calibration and thresholds are refit on the released VAL; roughly 20–30 minutes per predictor pass with --extra fast):

cat data/test_a.jsonl data/test_b.jsonl > data/test.jsonl     # byte-identical to the scored TEST file
uv run --project packages/decision-eval python training/evaluate_adapter.py \
    --adapter adapter --val data/val.jsonl --data data/test.jsonl --out eval/test

Retrain (the released TRAIN holds only Pev-Bench records; see below for the general mix):

uv run --project packages/decision-eval to-sft --data data/train.jsonl --template direct --out rows/train.jsonl
uv run --project packages/decision-eval python training/train_text_choice.py \
    --config training/configs/qwen3.8-27b-r2-mix-s20260930.json --train rows/train.jsonl --out runs/pev

The released adapter was also trained on 1,860 general decision questions from Kev's evals/decision-v2/train.jsonl, which are not redistributed (third-party licences). scripts/general_mix.py rebuilds that mix from Kev at the pinned commit (clone Kev into work/upstream/kev, then uv run --project packages/decision-eval python scripts/general_mix.py), and the dataset's general_mix_ids.jsonl lists the selected rows to check a rebuild against. evaluate_adapter.py refits the temperature and thresholds on the released (pseudonymized) VAL, so they can differ slightly from the shipped values (T = 2.772, threshold 0.369).

Rebuilding the data from the public sources

python scripts/acquire/download.py && python scripts/acquire/{amazon,google_local,openflights,enron,finalize}.py
cd packages/personal-decisions
uv run personal-decisions population ... && uv run personal-decisions build ... && uv run personal-decisions split ...
uv run personal-decisions generate --shard ... --renderer astra ...      # needs API access to gpt-6-astra
uv run personal-decisions export-release --records F.jsonl --out F.release.jsonl \
    --items SHARD/items.jsonl --key-file ../../release/pseudonym_key.txt

export-release is a consistent, reversible pseudonymization, not anonymization: the key is published (release/pseudonym_key.txt) so the export is exactly reproducible from the public source datasets. See docs/DATA.md and the package READMEs for every command.

Repository structure

Path Contents
packages/personal-decisions/ Knowledge base from public data, user-disjoint splits, the 7 question families, LLM rendering with verbatim anchor checks, privacy scan and release export
packages/decision-eval/ Base / adapter / reference predictors, VAL calibration and thresholds, paired scoring with a state-clustered bootstrap, gates, validity checks, TEST comparison
training/ Standalone LoRA trainer (transformers + PEFT), the training config and the evaluation entry point
scripts/ Source acquisition, Kev general-mix rebuild, TEST reproduction helpers
docs/ Pre-registration, results, data notes, dependency versions, TEST commitment and results
docs/tech-report/ Technical report (Markdown, PDF, LaTeX source), figures, data snapshots and the scripts that generate them
cards/ Model and dataset cards and their licences (copies of the Hugging Face READMEs)
release/ The published pseudonymization key

Development: see CONTRIBUTING.md. Both packages' unit tests run in CI (.github/workflows/tests.yml).

Data and licensing

  • Pev-Bench quotes real public product and restaurant reviews (Amazon Reviews 2023, Google Local 2021) and Enron emails as distractor text; everything about a user other than their reviews is synthetic. Names and user ids are pseudonymized with a published key. Do not attempt to identify the people behind reviews or emails.
  • The B half of TEST (test_b.jsonl, rendered by Claude Opus 5.5) is for evaluation only and must not be used for training.
  • Removal requests and questions: research@envloop.ai.

License

Citation

@techreport{envloop_pev,
  title       = {Pev: A Calibrated Fast-Decision Model for Personal Agents},
  author      = {{EnvLoop Research}},
  institution = {EnvLoop},
  url         = {https://github.com/EnvLoop/Pev}
}

Please also cite the data sources and models below (CITATION.cff lists them).

References

About

Pev: a calibrated fast-decision model for personal agents — Pev-Bench benchmark, evaluation harness, LoRA on Qwen3.8-27B, tech report

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages