Configuration Parsing Warning:In adapter_config.json: "peft.base_model_name_or_path" must be a string

D1A avatar: an anime girl with silver-white and dark purple hair, round glasses and headphones on a round #D1A badge

D1A-E2B-it QAT Β· PyTorch

What it does: decisions (/v1/systemone), chat (OpenAI-format /v1/chat/completions, streaming and tool calls), and photos, voice clips and video (python -m d1a.serving.media). For NVIDIA, CPU, or a Mac without MLX. On Apple Silicon use the MLX build, JohnP1/d1a-e2b-it-qat-mlx-q4: the same adapter, faster.

A small decision model: give it a document and a few questions, and it picks the answers. Each question is yes/no, multiple choice or a score; D1A returns a calibrated probability for every option in one forward pass. With its adapter switched off the same model is Gemma 4 E2B-it QAT and chats.

Versions

version date what changed load it with
v0.7 (main) 2026-10-30 (PyTorch files 2026-11-10) fine-tuned on English and Japanese dialogue acts and intents: better at "did they agree?", "is that just thanks, or a request?" and "a command or just talk?" JohnP1/d1a-e2b-it-qat
v0.6 2026-10-25 the D1A adapter retrained on Google's QAT int4 trunk; replaced D1A-E2B-it v0.6 by the owner's decision of 2026-10-25 JohnP1/d1a-e2b-it-qat@v0.6

Only the adapter, the pointer head and the calibration temperature (1.55 β†’ 1.91) differ between the two. What v0.7 is better at, and what it is not, is measured on the MLX build's card: dialogue acts +15.9 points [+12.2, +19.7] on 498 held-out questions; intent classification unchanged; every other D1A suite pooled βˆ’0.38 (not significant); calibration a little worse on some suites. The v0.6 card has v0.6's checks. The PyTorch v0.7 files were published with four of their eleven checks missed, by the owner's decision (Checks).

What's inside

  • The D1A LoRA adapter (rank 16) and pointer head of v0.7, trained on Google's quantization-aware-trained int4 trunk google/gemma-4-E2B-it-qat-w4a16-ct (revision 971342c0): v0.6's adapter fine-tuned for one epoch on English and Japanese intents and dialogue acts, with every earlier D1A training source replayed. The same files as the MLX build's adapter/ and head.safetensors, byte for byte.
  • base_ct in d1a_config.json names that checkpoint. d1a rebuilds the trunk from it when it loads this adapter, every int4 weight written as scale Γ— integer, so the adapter runs on the weights it was trained on. Exact in fp32 (D1A_DTYPE=fp32), rounded in bf16.
  • Calibration temperature 1.91, fitted on the MLX build's answers (decision-v7 calibration + PR-label development), v0.6's recipe.
  • Routing temperature 1.59 for requests that send "use_case": "routing" (jonpol01/d1a#385): fitted on the MLX build's answers to 315 routing questions (270 generic development, 45 hand-labelled). On the 640 factory development questions, not used for the fit but from the same corpus as the training data, calibration error 0.027 β†’ 0.018 and confident errors 0.022 β†’ 0.011, accuracy unchanged (0.933). On the fit rows themselves the gain is within noise (90% interval for the temperature 1.05 to 1.91). Not checked on this PyTorch build. Every other request uses 1.91.
  • Loading downloads Gemma 4 E2B-it (about 10 GB) and the QAT checkpoint (about 8 GB).

Run it

pip install "d1a[serve,media] @ git+https://github.com/jonpol01/d1a"
D1A_MERGE=0 python -m d1a.serving.serve --run JohnP1/d1a-e2b-it-qat --port 8009

v0.6 instead: --run JohnP1/d1a-e2b-it-qat@v0.6. Decisions and chat come from that one server: D1A_MERGE=0 keeps the adapter separate, so chat switches it off and talks as Gemma 4 E2B-it QAT itself. Photos, voice and video come from the media server, which loads the full model with its encoders (the QAT checkpoint's own, the vision projection QAT retrained included):

python -m d1a.serving.media --run JohnP1/d1a-e2b-it-qat --port 8010

A decision:

curl -s localhost:8009/v1/systemone -H 'content-type: application/json' -d '{
  "state": "Assistant: Shall I cancel the 3 pm meeting?\nUser: is that the one with the client?",
  "questions": {"answer": {"type": "choice", "instructions": "Did the user agree to the assistant'"'"'s question?",
                           "criteria": {"yes": "Agrees: go ahead", "no": "Refuses, wants to wait, or corrects it",
                                        "unclear": "Neither: a counter-question, a hedge, or something unrelated"}}}
}'

It answers unclear 0.59 (no 0.34, yes 0.07). With "not yet, I need to check first" it answers no 0.97, and with "sure, why not" yes 0.99: the MLX build's card gives 0.62, 0.96 and 0.99.

Checks

Published with four checks missed (the owner's decision of 2026-11-10). Before the checks ran, a limit was set for each; four were missed, and they are stated below. On a CUDA GPU (TF32 off), with this repository's adapter and head as published and its d1a_config.json before the routing temperature was added (no check sends use_case), d1a at 178e37d, torch 2.13, on 2026-11-10.

Check Limit (set before the check) Result
The files are v0.7's adapter and head byte-identical to the MLX v0.7 build's; temperature 1.91; the QAT trunk and encoders written in on load βœ…
The answers are v0.7's, not v0.6's mean change from MLX v0.7 at most half that from the Core ML v0.6 build's answers βœ… 0.009 against 0.047
Decisions (the 28 requests of the Core ML check, 42 answers): bf16 against fp32 no top answer with a margin β‰₯ 0.05 different; largest change ≀ 0.05 missed: largest change 0.0503, on one answer whose top option stays the same; mean 0.006; no top answer different
Decisions: bf16 against the MLX v0.7 build the same, and mean change ≀ 0.008 missed: largest change 0.064, mean 0.009. On that answer the MLX build is 0.051 from fp32 and this build 0.013. One top answer is different, a near tie (0.319 against 0.318 in fp32), where this build agrees with fp32
The dialogue-act example above, through the server the MLX card's top answers, within 0.05 βœ… unclear 0.59, no 0.97, yes 0.99
Chat through the server (the adapter off) the same greedy text and token count as v0.6 βœ… identical text (64 tokens, the cap); streams
Photos, voice clips and video: the playground's 14 media requests (28 answers) through the media server, bf16 against fp32 as for decisions βœ… largest change 0.034, mean 0.006, no top answer different
The media server on the 28 decision requests (fp32) against the decision server (fp32) largest change ≀ 0.01 βœ… 0.008
The photo, voice and video encoders (fp32) against an fp32 reference per-token cosine β‰₯ 0.999 missed. The reference first used had rounded its inputs to bf16, so its result (as low as 0.81) does not measure the encoders. Re-run afterwards against an independent fp32 run of the same encoders on the CPU: β‰₯ 0.9993 on 13 of the 14 clips, 0.9969 on one photo, below the limit; mean β‰₯ 0.99998 on every clip
Photos, voice clips and video against the MLX v0.7 build (26 answers; one voice clip left out before the run, jonpol01/d1a#384) as for decisions missed: largest change 0.143; no top answer with a margin β‰₯ 0.05 different (2 near ties). The MLX build is the side far from fp32 (below)
fp32 on the CPU against fp32 on the GPU (5 requests) largest change ≀ 0.001 βœ… 0.0

Against the full-precision model (this model in fp32 on the GPU, Google's QAT trunk exact, the same adapter; the QAT encoders fed fp32 inputs):

decisions (the 28 requests, 42 answers): largest change, mean photos, voice and video (14 requests, 28 answers): largest change, mean, top answers different
this build (bf16) 0.050, 0.006 0.034, 0.006, 0
MLX v0.7 0.051, 0.008 0.140, 0.034, 2
Core ML v0.7 0.048, 0.006 0.117, 0.029, 1

On decisions the three builds are level. On photos, voice and video this build stays within 0.034 of full precision, which is expected: the reference is this same PyTorch model run in fp32. The two Mac builds share a gap there whose cause is not found yet (jonpol01/d1a#386). These are 14 clips and 28 answers; they show how close each build is to this reference, not how accurate it is.

The suites were measured on the MLX build of this adapter (its card has the scorecard).

Limits

  • Act on a "yes" only above a confidence threshold (v0.7): in dialogue-act tests it still reads some refusals and hedges as agreement; an app that acts on the answer should confirm when the top probability is below about 0.6.
  • Intent classification did not improve, and calibration is a little worse on some suites (the MLX card has the numbers).
  • Release exception carried from v0.6: transfer-v4 βˆ’5.2 points against D1A-E2B-it v0.6 (task types outside training). Pin JohnP1/d1a-e2b-it@v0.6 where those matter.
  • PyTorch on a Mac's GPU (MPS) needs d1a with jonpol01/d1a#354, or torch 2.14 or later. Before it, PyTorch's MPS embedding kernel read part of Gemma 4's per-layer embedding table as zeros: for E2B, token ids from 239,675 (tabs, some CJK, emoji, and the image start and end tokens; jonpol01/d1a#353, pytorch/pytorch#188756). NVIDIA, the CPU and the MLX build were never affected. v0.7 was checked on a CUDA GPU and the CPU, not re-checked on a Mac's GPU.
  • <bos>: trained with id 2 at the start of every record; d1a adds it.
  • Questions are in English; the documents can be English or Japanese.

License and data

Apache-2.0. Base model: Gemma 4 by Google (Apache-2.0). Code: github.com/jonpol01/d1a, built on Kev by Jared Palmer (Apache-2.0). Intent data from MASSIVE 1.1 by Amazon (FitzGerald et al., 2022; CC BY 4.0), English and Japanese. Japanese decision data derived from JGLUE by Yahoo Japan Corporation and Waseda University (CC BY-SA 4.0). Pull-request data from NousResearch/hermes-agent (MIT); the labelled PR dataset itself, including the recent PRs, is private.

Downloads last month
57
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Model tree for JohnP1/d1a-e2b-it-qat

Adapter
(223)
this model

Dataset used to train JohnP1/d1a-e2b-it-qat

Collection including JohnP1/d1a-e2b-it-qat