G-reen / model-family-detector

huggingface.co
Total runs: 0
24-hour runs: 0
7-day runs: 0
30-day runs: 0
Model's Last Updated: October 12 2026
text-classification

Introduction of model-family-detector

Model Details of model-family-detector

model-family-detector (final-t001)

A classifier that reads a piece of long-form English writing (essay, article, review, story, blog post) and predicts which LLM family wrote it — OpenAI, Anthropic, Gemini or Other — with an auxiliary AI-vs-human output. It is a LoRA adapter on Gemma-3-4B-it with a small two-task head. It is the first complete model of this project ( final-t001 , trained 2026-10-10/11); it is useful, but the Results and Known issues sections below describe real weaknesses on the newest model generations, and you should read them before relying on it.

TL;DR of the numbers (top-1 accuracy on AI-written text, canonical normalisation): 93% on held-in sources, 63% on sources never seen in training (4 classes) , 54% on the LEDE benchmark 4-way / 74% on LEDE when forced to choose among the three real families , 89% on the IntelLabs peer-review benchmark. AI-vs-human AUROC 0.999 on every validation set — but the AI head calls ~50–60% of GPT-5-family long-form text "human" on LEDE. Details below.

Contents of this repo
path what
adapter/ PEFT LoRA adapter (r = 32 on q/k/v/o/gate/up/down of all 34 text layers) plus the classification head ( score , saved through modules_to_save ). 241 MB.
inference.py Stand-alone inference ( load() , predict() , CLI). Depends only on transformers , peft , torch , huggingface_hub , and regularizer.py from this repo.
regularizer.py The training-time formatting regularizer and the canonical() normaliser used at evaluation and inference.
training_config.json The exact Config the adapter was trained with (hyper-parameters, data settings).
eval_summary.json Every metric of the final evaluation (validation, leave-sources-out validation, three test sets; raw and canonical; per source / era / slice / class).
training_code/ The training stack: build_step4.py (splits + sample weights), data.py , model.py , regularizer.py , trainer.py , train.py , sweep.py , report_sweep.py , predict.py , and the Slurm launchers.
How to use
pip install "transformers>=4.57" "peft>=0.17" torch huggingface_hub
# request access to this repo on the Hub first (manual gating), then:
python inference.py --repo G-reen/model-family-detector \
  --text "The quarterly numbers tell a simple story: revenue is up, margins are flat, and the board is nervous."
# p_ai=0.952 family=Other 3way=Gemini OpenAI=0.10 Anthropic=0.12 Gemini=0.14 Other=0.64 | 'The quarterly numbers ...'
# (a one-sentence input like this is far below the >=150-word texts the model was trained on; the family
#  distribution is close to flat and lands on Other. Give it a full article or essay.)
python inference.py --repo G-reen/model-family-detector --jsonl texts.jsonl --out preds.jsonl   # {"text": ...} per line
import inference                                  # from this repo
model, tok, max_len = inference.load("G-reen/model-family-detector")      # needs a GPU with ~10 GB; bf16
preds = inference.predict(model, tok, ["...text 1...", "...text 2..."], max_len)
# each pred: {"p_ai": <float>, "p_family": {"OpenAI": ., "Anthropic": ., "Gemini": ., "Other": .},
#             "family": <argmax of p_family>, "family_3way": <argmax over the three real families>}

The base model ( unsloth/gemma-3-4b-it , a re-upload of Google's Gemma 3 4B IT) is downloaded automatically; its vision tower is loaded but unused. Inputs are truncated to 768 tokens (the training length); the model reads the first ~550 words of a text. Texts shorter than ~150 words are outside the training distribution.

Reading the outputs

The head emits 5 logits from one linear layer , read as two independent quantities:

  • p_ai = sigmoid(logit 4) — probability the text is AI-written. Trained on all rows (human rows included).
  • p_family = softmax(logits 0..3) — P(family | the text is AI-written) . Trained only on AI rows ; human rows are masked out of this loss. It always sums to 1 and says nothing about human-vs-AI; on a human text it is meaningless.

So: read p_ai first; if it says AI, read the family. The joint probability of "AI and written by family k " is p_ai * p_family[k] .

family_3way is the argmax over OpenAI/Anthropic/Gemini only. The Other class absorbs most of the model's uncertainty on unfamiliar text (see Results); on the LEDE benchmark the forced 3-way reading is right 74% of the time where the 4-way reading is right 61%. Use it when you know the text came from one of the three big labs.

By default inference.py passes the text through regularizer.canonical() (curly quotes → straight, dashes → ASCII, markdown emphasis/headers/bullets stripped, rule lines removed, whitespace normalised). The model was selected on canonical text and its raw-vs-canonical scores are within a point of each other, so either is fine; --raw skips it.

Classes
class id what is in it
OpenAI 0 GPT-3.5, GPT-4, 4-turbo, 4o, 4.1, GPT-5 family, o1/o3 (chatgpt-4o-latest, gpt-5-chat, gpt-5.4, gpt-5.6 in training)
Anthropic 1 Claude 1/2/3/3.5/3.7/4/4.5/4.6 (training is heaviest on Claude 3 Opus, 3.5 Sonnet, Sonnet 4, Sonnet 4.6, Haiku 4.5)
Gemini 2 Gemini 1.0/1.5/2.0/2.5/3 (training is heaviest on gemini-3-flash, 2.5-flash, 1.5-flash, 1.0-pro)
Other 3 everything else: Llama, Mistral, Qwen, DeepSeek, Kimi, Granite, Command-R, Reka, Yi, Phi, Nemotron, and Gemma (see the Gemma note)
(Human) — not a family class; only the p_ai output is trained on human text

Gemma note. This adapter was trained with Gemma mapped to Other (a decision taken 2026-10-04). Evaluation showed that is the wrong label: the model calls gemma-3-27b-it "Gemini" 65–67% of the time and gemma-2 66–72%, because Gemma writes with the Gemini fingerprint. The project switched to Gemma = Gemini on 2026-10-11; the published step-1/step-23 datasets and this adapter still reflect the old labelling. If your Gemma text comes back as Gemini, the model is right and the label was wrong.

Architecture
  • Backbone : Gemma-3-4B-it (4.3 B params), frozen, bf16, SDPA attention. Sequence representation = hidden state of the last non-pad token (HF Gemma3ForSequenceClassification pooling).
  • LoRA : r = 32, α = 32, dropout 0.1, rsLoRA, on q_proj k_proj v_proj o_proj gate_proj up_proj down_proj of every text layer (vision tower and projector excluded). 60.3 M trainable parameters incl. the head.
  • Head : Linear(2560→256) → GELU → Dropout(0.1) → Linear(256→5, no bias) , fp32. No LayerNorm in this configuration.
  • Loss : 0.3 · CE(logits[0:4], family) on AI rows only + 0.7 · BCE(logit[4], is_ai) on all rows. The 0.3 family weight is a project decision (the AI/human task was meant as regularisation, not the product).
Data

Everything is built from public datasets plus the project's own G-reen/fastdetector-train-stat-train (no API generation was done). The pipeline is documented in detail in the dataset cards; the short version:

  1. Step 1 — unify ( G-reen/model-family-step1-train / -test ): 36 loaders, 3,472,346 rows, one schema ( text, model_family, model_id, metadata with 19 identical metadata keys). Gemma → Other; AI-edited text kept unless it is a near copy of its human source (cosine distance < 0.1 to the original removed, matching the fastdetector filter).
  2. Step 2 — keep writing only : a rule pre-filter (length, structure) then a gemma-4-E4B-it judge that keeps only standalone long-form writing (essays, articles, stories, reviews, letters, blog posts); chat answers, code, math, lists, Q&A, dialogue scripts, forum threads and templated bot output were removed. For chat-derived sources a second judge also saw the user prompt and dropped rows where the user had not asked for a piece of writing.
  3. Step 3 — clean : mojibake repair, chat-template tokens, HTML/markdown wrappers, acknowledgement openers ("Sure, here is…"), bylines, "THE END"/word-count footers, refusals, placeholders, self-references ("as an AI language model"), degenerate repetition, near-duplicates (MinHash), AI rows that copy their human original's structure, unsafe content. Titles, closing offers and typography were deliberately not removed — they are handled by the training-time regularizer so the model does not learn them as shortcuts. Two independent audits (reports in the project) drove versions 2 and 3. Result ( G-reen/model-family-step23-train , v3, 2026-10-08): 730,625 rows — Human 303k (aux head only), Other 200k, OpenAI 119k, Anthropic 76k, Gemini 32k, across 24 source configs.
  4. Step 4 — splits and balancing ( training_code/build_step4.py ): three whole sources are held out as leave-sources-out validation ( val_loco : imbue_demo, lmarena_100k, ghostbuster_news — 12,500 rows, 2,500 per class incl. Human); a 5% grouped in-distribution validation split ( val_id , 11,255 rows; grouped by prompt/source key so paraphrase pairs never straddle the split); the rest is train: 650,541 rows (OpenAI 101,680 / Anthropic 64,694 / Gemini 23,164 / Other 186,952 / Human 274,051). Balancing is done by sampling weights, not by dropping rows: AI rows are weighted n_cell^-0.6 · N_family^-0.5 (cell = source × family), and 35% of every batch is Human text (for the AI head only).

Train rows by source (step-4 train split):

source rows families upstream / licence
fastdetector_train_stat 378,185 Human 255k, Other 119k (gemma-4-31b, llama-3.3, mistral-small, qwen3.8, …), OpenAI 2.9k, Anthropic 1.6k own data (Common Crawl upstream, ODC-By)
wildchat 48,082 OpenAI (GPT-3.5/4) allenai/WildChat-4.8M, ODC-BY
storyscope 47,260 OpenAI (gpt-5.4), Anthropic (claude-sonnet-4-6), Gemini (gemini-3-flash), Other — long fiction MIT (prompts derived from Books3)
editlens_iclr 39,703 Human, Anthropic, OpenAI, Gemini, Other gated, non-commercial terms
gsingh_train (Defactify-4) 31,679 Other (gemma-2-9b, …), Human, OpenAI none stated; NYT content
biscope 18,821 OpenAI, Anthropic, Gemini, Human cc-by-nc-nd-4.0
norquinal_claude 13,096 Anthropic (Claude 1/2) none stated
lmsys_chat_1m 11,662 Other, Anthropic, OpenAI LMSYS-Chat-1M licence (no redistribution)
gryphe_opus_wp / gryphe_gpt4o_wp 8,502 / 3,544 Anthropic (Opus 3) + OpenAI (gpt-4o) WritingPrompts none stated
lmsys_gpt5 8,115 OpenAI (gpt-5-chat) cc-by-4.0 (prompts: LMSYS)
ghostbuster_essay / _stories 5,932 / 6,083 OpenAI, Anthropic, Human cc-by-3.0 (human text: IvyPanda / r/WritingPrompts)
opus_storygen, claude_opus_instruct, gsingh_claude_sonnet 5,358 / 5,317 / 4,296 Anthropic none stated / apache-2.0 / NYT content
lmarena_55k / lmarena_140k 4,540 / 2,777 all four apache-2.0 / cc-by-4.0 prompts, outputs under provider ToS
gsingh_gemini_flash 3,238 Gemini (1.5-flash) none stated; NYT content
gradtex 3,043 Other (gemma-4-31b) cc-by-4.0 over MAGE
anthropic_persuasion 1,308 Anthropic, Human cc-by-nc-sa-4.0

Held-out (never trained on): imbue_demo (claude-sonnet-4-6, gemini-3-flash-preview, gpt-5.3-chat-latest and human text in reviews/news/essays/stories; cc-by-nc-sa-4.0), lmarena_100k (40+ open and closed 2024 models), ghostbuster_news (gpt-3.5-turbo, Claude 2023, Reuters human text).

Test sets ( G-reen/model-family-step23-test ): LEDE (146,820 rows: 24 models of 2024–2026 in the generated and we = writing-enhancement slices; OpenAI 63.5k, Anthropic 42.2k, Gemini 34.6k, Other = gemma-3-27b-it 6.6k), IntelLabs peer-review benchmark (39,800 rows; GPT-4o, Claude, gemini-1.5-pro-002, llama-3.1-70b, qwen2.5-72b, human reviews; OOD genre, not uploadable), tell-human-detectors (300 rows: plain / paraphrased / humanized GPT-4o and Claude text, human). Test sets were evaluated once , on the finished model, with a cap of 7,500 rows per class.

Training process
  • Regularizer ( regularizer.py ): at training time each example independently gets, with probability scaled by reg_strength = 0.5 , any of 20 transformations — quote/dash/ellipsis normalisation, markdown and header stripping, bullet and rule-line removal, title line removal/insertion, closing-offer removal, paragraph re-flow, double spaces, case changes, unicode hyphens — so that typography and boilerplate cannot be used as family shortcuts. Random chunking ( chunk_p ) was searched but the chosen configuration has it off.
  • Stage-1 sweep ( mf-broad-1 , 84 Optuna trials, TPE + Hyperband, 12k rows each, objective = leave-sources-out canonical macro-F1): learning rate, batch, LoRA rank/α/dropout/rsLoRA, head norm/bottleneck, weight decay, warm-up, scheduler, max length {512, 768}, regularizer strength, chunking, balancing exponents, human share, base {pt, it}. Best 0.584.
  • Stage-2 sweep ( mf-narrow-1 , 21 trials, 120k rows each, narrowed space): three trials completed at 0.58–0.59; the held-out score plateaued from ~40k rows while in-distribution kept rising (0.84 → 0.96) — more rows of the same sources teach source style, not family style. Trial t001 was chosen for the best score on the imbue_demo source (0.66) and the most balanced per-class recall.
  • Final run ( final-t001 ): t001's configuration — lr 3.66e-5 constant with 3% warm-up, effective batch 16, weight decay 0.1, 768 tokens, bf16, gradient checkpointing — on 300,000 weighted samples drawn from the 650k train rows (≈ one pass), 4 × A6000 with torchrun DDP, ≈ 10 h wall (≈ 40 GPU-hours). Evaluation every 25k rows on 1,000 rows per class; the end-of-training checkpoint is the released one (no checkpoint selection: the held-out curve is flat within noise after 100k rows). Provenance note : the run was interrupted once by a cluster hand-over and resumed from its 125k-row checkpoint; a duplicate resume later replayed rows 250k–300k from the same checkpoint with the same data order. The released weights are one coherent 300k-row trajectory.
Results

All numbers are top-1 accuracy on AI-written rows unless stated; "canon" = text passed through canonical() , "raw" = as published. Validation rows: 1,500 per class.

set 4-way acc canon 4-way acc raw macro-F1 canon AI-vs-human AUROC
val_id (held-in sources) 0.933 0.940 0.933 0.9992
val_loco (held-out sources) 0.630 0.623 0.628 0.9987
↳ ghostbuster_news / imbue_demo / lmarena_100k 0.84 / 0.69 / 0.43
test LEDE (7.5k/class) 0.536 0.569 0.517 n/a (no human rows)
↳ generated / writing-enhancement slice 0.547 / 0.505 0.580 / 0.537
test Intel peer review (OOD) 0.889 0.905 0.841 1.000
test tell (150 AI rows) 0.700 0.740 1.000

LEDE confusion, canonical (rows = true class, 7,500 per class; Other = gemma-3-27b-it, 6,583):

            OpenAI  Anthropic  Gemini  Other
OpenAI        3170       443    1105   2782
Anthropic      179      6031     781    509
Gemini         341       313    5362   1484
Other(Gemma)   356       956    4250   1021

Per-model accuracy on a 24k-row random LEDE sample (canonical; →Other = share sent to Other; P(AI)<.5 = share the AI head calls human):

model n 4-way forced 3-way →Other P(AI)<.5
claude-opus-4 778 0.995 0.996 0.00 0.01
claude-opus-4-1 1091 0.977 0.977 0.00 0.01
claude-3-5-haiku 1009 0.929 0.931 0.00 0.01
claude-sonnet-4 / 4-5 1048 / 953 0.901 / 0.902 0.949 / 0.920 0.08 / 0.03 0.17 / 0.02
claude-sonnet-4-6 1019 0.526 0.605 0.12 0.09
claude-opus-4-6 927 0.424 0.552 0.21 0.04
gemini-2.5-flash 2222 0.913 0.923 0.02 0.04
gemini-2.5-pro 1011 0.812 0.867 0.08 0.03
gemini-3.1-pro 1189 0.802 0.876 0.14 0.13
gemini-3.1-flash 1170 0.194 0.363 0.69 0.01
o1 1099 0.605 0.684 0.16 0.21
gpt-4.1 1366 0.568 0.643 0.10 0.10
gpt-5.4 1303 0.500 0.744 0.45 0.49
o3 1078 0.466 0.761 0.38 0.34
gpt-4o 1407 0.437 0.509 0.14 0.05
gpt-5.4-pro 435 0.345 0.641 0.56 0.64
gpt-5.4-nano 1355 0.308 0.710 0.63 0.49
gpt-5 1068 0.270 0.624 0.55 0.62
gpt-5-nano 1383 0.221 0.587 0.61 0.56
gemma-3-27b-it (labelled Other) 1089 0.151 — (→Gemini 0.67) 0.15 0.24

On the 22,500 OpenAI/Anthropic/Gemini LEDE rows: 4-way 0.607, forced 3-way 0.743 canonical / ≈0.80 raw ; when the model names a real family rather than Other it is right 80% of the time at 76% coverage. Raw text helps OpenAI most (gpt-5.4-nano forced 3-way 0.94 raw).

Sanity checks on shortcuts: a gradient-boosted classifier on 28 surface statistics (lengths, punctuation rates, markdown counts, type-token ratio) reaches 0.94 AUROC for AI-vs-human on the held-out sources but only 0.35 macro-F1 for the family task (vs 0.63 for this model), so the family signal is not punctuation and length. In-distribution scores are inflated by single-family sources (wildchat = OpenAI only, norquinal = Anthropic only, …); the held-out numbers are the honest ones.

Known issues (read before using)
  1. The AI head misses GPT-5-family long-form text. On LEDE, 19.5% of AI texts get p_ai < 0.5 ; gpt-5 / 5-nano / 5.4 / 5.4-nano / 5.4-pro are called human 49–64% of the time, o3 34%, o1 21%; Claude and Gemini 1–4%. On LEDE's writing-enhancement slice, 69% of OpenAI rows are called human. The validation sets did not contain these models and reported AUROC 0.999. Do not gate long-form text on p_ai for OpenAI-2025 models.
  2. The newest frontier generations are under-covered outside fiction. claude-opus-4-6 (0.42), claude-sonnet-4-6 (0.53), gemini-3.1-flash (0.19) and the GPT-5 family are the weak cells; in training these generations come almost entirely from storyscope (fiction). The model's reaction to "unfamiliar" text is Other (and, for OpenAI, human).
  3. Other is learned as "Llama-like", not "none of the above." Held-out Llama variants are Other 65–72% of the time, but Reka, Yi, Athene, Command-R go to OpenAI 67–70% and DeepSeek 53%.
  4. Gemma is labelled Other in this adapter but behaves as Gemini (see Classes).
  5. Scores are for English, ≥150-word prose, truncated at 768 tokens; chat answers, code, lists and very short texts were filtered out of training and are untested.
  6. Human text in the validation data (news, essays, Wikipedia-style, Common-Crawl prose) is much easier than modern edited human writing; expect a higher false-AI rate on polished human Substack-style text than the 0.2% measured here.
Data and licensing

The adapter is a derivative of Gemma 3 and is subject to the Gemma Terms of Use . The training data mixes licences from permissive (MIT, apache-2.0, cc-by, ODC-BY) to non-commercial (cc-by-nc-sa, cc-by-nc-nd, editlens access terms) and no-redistribution (LMSYS-Chat-1M); NYT-derived and Books3-derived prompts appear upstream of several sources. The weights are therefore released for research use only , behind manual gating, like the datasets. The IntelLabs peer-review benchmark is used for evaluation only and is not redistributed.

Reproducing
python -m training_code.build_step4            # step-23 parquet -> step-4 splits (set MD_STEP23V3_DIR / MD_STEP4_DIR)
python -m training_code.sweep --stage broad --study mf-broad-1 --trials 6     # per GPU worker; see sweep.sbatch
python -m training_code.sweep --stage narrow --study mf-narrow-1 --trials 2 --inherit narrow.json
torchrun --nproc_per_node=4 -m training_code.train $(cat launch args in launch_final.sh)
python -m training_code.predict --run <run dir> --split test_lede --limit 24000 --out preds.parquet

The code expects the fastdetector package on PYTHONPATH for the Optuna study helper only; everything else is in training_code/ .

Changelog
  • 2026-10-11 — final-t001 released. Known: Gemma labelled Other; GPT-5-family AI-head miss. Next planned: retrain with Gemma = Gemini ( step4_gemma data), non-fiction coverage of 2025 models.

Runs of G-reen model-family-detector on huggingface.co

0
Total runs
0
24-hour runs
0
3-day runs
0
7-day runs
0
30-day runs

More Information About model-family-detector huggingface.co Model

model-family-detector huggingface.co

model-family-detector huggingface.co is an AI model on huggingface.co that provides model-family-detector's model effect (), which can be used instantly with this G-reen model-family-detector model. huggingface.co supports a free trial of the model-family-detector model, and also provides paid use of the model-family-detector. Support call model-family-detector model through api, including Node.js, Python, http.

model-family-detector huggingface.co Url

https://huggingface.co/G-reen/model-family-detector

G-reen model-family-detector online free

model-family-detector huggingface.co is an online trial and call api platform, which integrates model-family-detector's modeling effects, including api services, and provides a free online trial of model-family-detector, you can try model-family-detector online for free by clicking the link below.

G-reen model-family-detector online free url in huggingface.co:

https://huggingface.co/G-reen/model-family-detector

model-family-detector install

model-family-detector is an open source model from GitHub that offers a free installation service, and any user can find model-family-detector on GitHub to install. At the same time, huggingface.co provides the effect of model-family-detector install, users can directly use model-family-detector installed effect in huggingface.co for debugging and trial. It also supports api for free installation.

model-family-detector install url in huggingface.co:

https://huggingface.co/G-reen/model-family-detector

Url of model-family-detector

model-family-detector huggingface.co Url

Provider of model-family-detector huggingface.co

G-reen
ORGANIZATIONS

Other API from G-reen

huggingface.co

Total runs: 15
Run Growth: 0
Growth Rate: 0.00%
Updated:September 04 2024
huggingface.co

Total runs: 8
Run Growth: 0
Growth Rate: 0.00%
Updated:June 02 2024
huggingface.co

Total runs: 0
Run Growth: 0
Growth Rate: 0.00%
Updated:August 26 2024