Text Classification
Transformers
Safetensors
English
French
qwen3
feature-extraction
ai-text-detection
ai-generated-text
token-classification
authorship
lora
text-embeddings-inference
Instructions to use Jour/ouroboros-detector with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Jour/ouroboros-detector with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="Jour/ouroboros-detector")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModel tokenizer = AutoTokenizer.from_pretrained("Jour/ouroboros-detector") model = AutoModel.from_pretrained("Jour/ouroboros-detector", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Ouroboros detector v7: merged backbone, heads, calibrator, model card
Browse files- .gitattributes +5 -0
- README.md +114 -0
- assets/architecture.png +3 -0
- assets/banner.png +0 -0
- assets/benchmarks.png +3 -0
- assets/biases.png +0 -0
- assets/generators.png +3 -0
- assets/interpretability.png +3 -0
- calibrator.json +41 -0
- chat_template.jinja +85 -0
- config.json +63 -0
- heads.pt +3 -0
- model.safetensors +3 -0
- ouroboros_config.yaml +52 -0
- tokenizer.json +3 -0
- tokenizer_config.json +30 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,8 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
assets/architecture.png filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
assets/benchmarks.png filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
assets/generators.png filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
assets/interpretability.png filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
tokenizer.json filter=lfs diff=lfs merge=lfs -text
|
README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
language:
|
| 4 |
+
- en
|
| 5 |
+
- fr
|
| 6 |
+
library_name: transformers
|
| 7 |
+
base_model: Qwen/Qwen3-1.7B-Base
|
| 8 |
+
pipeline_tag: text-classification
|
| 9 |
+
tags:
|
| 10 |
+
- ai-text-detection
|
| 11 |
+
- ai-generated-text
|
| 12 |
+
- token-classification
|
| 13 |
+
- authorship
|
| 14 |
+
- lora
|
| 15 |
+
- qwen3
|
| 16 |
+
---
|
| 17 |
+
|
| 18 |
+
<div align="center">
|
| 19 |
+
<img src="assets/banner.png" alt="Ouroboros" width="100%">
|
| 20 |
+
</div>
|
| 21 |
+
|
| 22 |
+
# Ouroboros detector (v7)
|
| 23 |
+
|
| 24 |
+
An open, **token-level detector of AI-written text**. For a document it returns character-aligned segments labelled `human`, `ai-assisted` or `ai-generated` with confidences, a weighted AI fraction, a `human` / `mixed` / `ai` verdict, and a 4-way "was this humanized?" probability (`human`, `ai-generated`, `humanized-ai`, `mixed-authorship`).
|
| 25 |
+
|
| 26 |
+
> **Unofficial.** This is an independent, open reimplementation of the method of the *Pangram 4* technical report ([arXiv:2607.27183](https://arxiv.org/abs/2607.27183)). It is not affiliated with or endorsed by Pangram, and it is not their model, weights or data.
|
| 27 |
+
|
| 28 |
+
> **Built end to end by Claude Opus 5.5.** The architecture implementation, data pipeline, training, evaluation, interpretability study, bias audit and this model card were designed, written and run end to end by Claude Opus 5.5 (Anthropic) as an autonomous coding agent, at the direction of the author, who set the goals and reviewed the results.
|
| 29 |
+
|
| 30 |
+
- **Code, training pipeline, dataset builder, demo:** https://github.com/Jourdelune/ouroboros-detector
|
| 31 |
+
- **Backbone:** [Qwen3-1.7B-Base](https://huggingface.co/Qwen/Qwen3-1.7B-Base) with a LoRA adapter (r = 32) **merged into the weights** (bf16, 3.4 GB), plus four single-layer heads.
|
| 32 |
+
- **Languages:** evaluated on English and French; other languages appear in the training data but are not benchmarked.
|
| 33 |
+
|
| 34 |
+
## Use
|
| 35 |
+
|
| 36 |
+
```bash
|
| 37 |
+
pip install "git+https://github.com/Jourdelune/ouroboros-detector.git"
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
```python
|
| 41 |
+
from ouroboros.infer.predict import Predictor
|
| 42 |
+
|
| 43 |
+
detector = Predictor.from_pretrained("Jour/ouroboros-detector")
|
| 44 |
+
result = detector.predict(text) # texts of at least ~50 words
|
| 45 |
+
print(result.document_label, result.weighted_ai_fraction)
|
| 46 |
+
for seg in result.segments:
|
| 47 |
+
print(seg.start, seg.end, seg.label_name, seg.confidence)
|
| 48 |
+
print(detector.humanizer(text))
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
The model needs the `ouroboros` package: it implements Repeat2 inputs, the four heads, sliding windows, calibration and CRF decoding. `AutoModel.from_pretrained` alone loads only the backbone.
|
| 52 |
+
|
| 53 |
+
## Architecture
|
| 54 |
+
|
| 55 |
+
One causal backbone fed the window twice (**Repeat2**, so every supervised token has seen the whole window) and four heads: segment (`D→15`, weighted AI fraction), tokenwise provenance (`D→3`), mixed-authorship (`D→2`), humanizer probe (`D→4`, stop-gradient). Windows of 512 tokens with stride 256, then calibration and a linear-chain CRF.
|
| 56 |
+
|
| 57 |
+
<img src="assets/architecture.png" alt="Architecture" width="100%">
|
| 58 |
+
|
| 59 |
+
## Evaluation
|
| 60 |
+
|
| 61 |
+
Held-out test split of the project's corpus: 12,000 documents (4,531 human, 6,821 AI, 648 mixed), split by source document. Operating point chosen on a separate calibration split for a 0.5 % false-positive target.
|
| 62 |
+
|
| 63 |
+
| metric | v7 |
|
| 64 |
+
|---|---:|
|
| 65 |
+
| False-positive rate | 1.35 % |
|
| 66 |
+
| False-negative rate (AI or mixed missed) | 0.94 % |
|
| 67 |
+
| AUROC | 0.9915 |
|
| 68 |
+
| TPR @ 1 % FPR | 98.9 % |
|
| 69 |
+
| Token accuracy | 98.4 % |
|
| 70 |
+
| Token F1 — human / AI-assisted / AI-generated | 0.986 / 0.714 / 0.988 |
|
| 71 |
+
| Mixed-document accuracy | 77.2 % |
|
| 72 |
+
| 4-way humanizer head accuracy / recall on `humanized-ai` | 95.0 % / 56.8 % |
|
| 73 |
+
|
| 74 |
+
<img src="assets/benchmarks.png" alt="Benchmarks" width="100%">
|
| 75 |
+
|
| 76 |
+
These numbers are **in-distribution** (same corpus families as training) and **not comparable** to the Pangram report's, which uses a different, proprietary corpus and backbone.
|
| 77 |
+
|
| 78 |
+
## Known limitations and biases
|
| 79 |
+
|
| 80 |
+
<img src="assets/biases.png" alt="Known biases" width="75%">
|
| 81 |
+
|
| 82 |
+
- **Higher false-positive rate** on French human text (7.0 % vs 1.0 % in English), on very short text (< 80 words: 6.5 %), and on human text formatted like an assistant answer (bullets / bold / headers: 8.8 %).
|
| 83 |
+
- **Format and encoding shortcuts:** human text split into paragraphs is flagged 14.5 % of the time; inserting four Cyrillic look-alike letters into a human text makes it read as AI in 86 % of cases. Normalise confusable characters before inference.
|
| 84 |
+
- **Not robust to adaptive adversaries:** a rewriting loop with access to the detector's score made 70–88 % of a small held-out set (50 French + 50 English passages) read as human while passing automatic fidelity checks.
|
| 85 |
+
- Not supported: texts under ~50 words. `ai-assisted` is the weakest class (F1 0.71).
|
| 86 |
+
- **Do not use a verdict as the sole basis for a decision about a person.** AI-text detectors can wrongly flag non-native writers and formal prose.
|
| 87 |
+
|
| 88 |
+
## What it looks at (interpretability)
|
| 89 |
+
|
| 90 |
+
Measured on held-out passages with 95 % intervals: a linear probe on the *untrained* Qwen3-1.7B-Base already separates classes at 95 %; fine-tuning raises it to 98.5 % and makes it language-independent (French→English transfer 99.5 % vs 91.5 %). The verdict is written in layers 18–27, mostly by two attention heads and the last MLP; sentence-final periods (2.4 % of tokens) carry 28 % of the evidence and paragraph breaks (0.8 %) 21 %; shuffling words inside sentences removes most of the signal while surface edits barely move it; the score is uncorrelated with a base language model's surprisal.
|
| 91 |
+
|
| 92 |
+
<img src="assets/interpretability.png" alt="Interpretability" width="100%">
|
| 93 |
+
|
| 94 |
+
## Training data
|
| 95 |
+
|
| 96 |
+
Public sources only: RAID, MAGE, COLING-2025 MGT, ai-text-detection-pile, `dmitva/human_ai_generated_text`, Cosmopedia, WildChat, UltraChat, OpenHermes-2.5, arena preference sets, Amazon/Yelp/IMDB reviews, arXiv abstracts, FineWeb-2 (French) and FineWeb-Edu, Aya, Wikipedia, French instruction sets and several public distillation sets from recent frontier models (≈ 1.09 M training documents including augmentations). The dataset builder is in the GitHub repository.
|
| 97 |
+
|
| 98 |
+
> **Licences.** The weights are released under Apache-2.0 and the backbone is Apache-2.0, but the training data comes from many datasets with their own terms (some research-only or non-commercial). Check them before any commercial use. No dataset is redistributed here.
|
| 99 |
+
|
| 100 |
+
## Files
|
| 101 |
+
|
| 102 |
+
`model.safetensors`, `config.json` (merged backbone) · `heads.pt` (the four heads) · `calibrator.json` (decoder calibration, 0.5 % FPR target) · `ouroboros_config.yaml` (inference settings) · tokenizer files.
|
| 103 |
+
|
| 104 |
+
## Citation
|
| 105 |
+
|
| 106 |
+
```bibtex
|
| 107 |
+
@software{ouroboros_detector,
|
| 108 |
+
title = {Ouroboros: an open token-level AI-text detector},
|
| 109 |
+
author = {Jourdelune},
|
| 110 |
+
year = {2026},
|
| 111 |
+
note = {Unofficial reimplementation of the Pangram 4 technical report (arXiv:2607.27183); built end to end with Claude Opus 5.5},
|
| 112 |
+
url = {https://github.com/Jourdelune/ouroboros-detector}
|
| 113 |
+
}
|
| 114 |
+
```
|
assets/architecture.png
ADDED
|
Git LFS Details
|
assets/banner.png
ADDED
|
assets/benchmarks.png
ADDED
|
Git LFS Details
|
assets/biases.png
ADDED
|
assets/generators.png
ADDED
|
Git LFS Details
|
assets/interpretability.png
ADDED
|
Git LFS Details
|
calibrator.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"intercepts": [
|
| 3 |
+
-0.13786710811109545,
|
| 4 |
+
0.1736658319082379,
|
| 5 |
+
-0.03579872379724635
|
| 6 |
+
],
|
| 7 |
+
"weights": [
|
| 8 |
+
[
|
| 9 |
+
0.6090387031621195,
|
| 10 |
+
-0.2203546534333896,
|
| 11 |
+
0.05042216278611674,
|
| 12 |
+
-0.043796612923324964,
|
| 13 |
+
-0.16172733427658842,
|
| 14 |
+
-0.07141518106119561
|
| 15 |
+
],
|
| 16 |
+
[
|
| 17 |
+
-0.47584707836701884,
|
| 18 |
+
0.44584154734933923,
|
| 19 |
+
-0.53091849183712,
|
| 20 |
+
0.18571772229692793,
|
| 21 |
+
0.344271744390476,
|
| 22 |
+
0.030821937669911974
|
| 23 |
+
],
|
| 24 |
+
[
|
| 25 |
+
-0.13319162479510294,
|
| 26 |
+
-0.22548689391594745,
|
| 27 |
+
0.4804963290510028,
|
| 28 |
+
-0.1419211093736046,
|
| 29 |
+
-0.18254441011389036,
|
| 30 |
+
0.040593243391284464
|
| 31 |
+
]
|
| 32 |
+
],
|
| 33 |
+
"deltas": [
|
| 34 |
+
1.5,
|
| 35 |
+
0.0,
|
| 36 |
+
0.0
|
| 37 |
+
],
|
| 38 |
+
"smoothness_lambda": 4.0,
|
| 39 |
+
"mixed_gamma": 0.25,
|
| 40 |
+
"identity": false
|
| 41 |
+
}
|
chat_template.jinja
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{%- if tools %}
|
| 2 |
+
{{- '<|im_start|>system\n' }}
|
| 3 |
+
{%- if messages[0].role == 'system' %}
|
| 4 |
+
{{- messages[0].content + '\n\n' }}
|
| 5 |
+
{%- endif %}
|
| 6 |
+
{{- "# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
|
| 7 |
+
{%- for tool in tools %}
|
| 8 |
+
{{- "\n" }}
|
| 9 |
+
{{- tool | tojson }}
|
| 10 |
+
{%- endfor %}
|
| 11 |
+
{{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
|
| 12 |
+
{%- else %}
|
| 13 |
+
{%- if messages[0].role == 'system' %}
|
| 14 |
+
{{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }}
|
| 15 |
+
{%- endif %}
|
| 16 |
+
{%- endif %}
|
| 17 |
+
{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
|
| 18 |
+
{%- for message in messages[::-1] %}
|
| 19 |
+
{%- set index = (messages|length - 1) - loop.index0 %}
|
| 20 |
+
{%- if ns.multi_step_tool and message.role == "user" and not(message.content.startswith('<tool_response>') and message.content.endswith('</tool_response>')) %}
|
| 21 |
+
{%- set ns.multi_step_tool = false %}
|
| 22 |
+
{%- set ns.last_query_index = index %}
|
| 23 |
+
{%- endif %}
|
| 24 |
+
{%- endfor %}
|
| 25 |
+
{%- for message in messages %}
|
| 26 |
+
{%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
|
| 27 |
+
{{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }}
|
| 28 |
+
{%- elif message.role == "assistant" %}
|
| 29 |
+
{%- set content = message.content %}
|
| 30 |
+
{%- set reasoning_content = '' %}
|
| 31 |
+
{%- if message.reasoning_content is defined and message.reasoning_content is not none %}
|
| 32 |
+
{%- set reasoning_content = message.reasoning_content %}
|
| 33 |
+
{%- else %}
|
| 34 |
+
{%- if '</think>' in message.content %}
|
| 35 |
+
{%- set content = message.content.split('</think>')[-1].lstrip('\n') %}
|
| 36 |
+
{%- set reasoning_content = message.content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
|
| 37 |
+
{%- endif %}
|
| 38 |
+
{%- endif %}
|
| 39 |
+
{%- if loop.index0 > ns.last_query_index %}
|
| 40 |
+
{%- if loop.last or (not loop.last and reasoning_content) %}
|
| 41 |
+
{{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content.strip('\n') + '\n</think>\n\n' + content.lstrip('\n') }}
|
| 42 |
+
{%- else %}
|
| 43 |
+
{{- '<|im_start|>' + message.role + '\n' + content }}
|
| 44 |
+
{%- endif %}
|
| 45 |
+
{%- else %}
|
| 46 |
+
{{- '<|im_start|>' + message.role + '\n' + content }}
|
| 47 |
+
{%- endif %}
|
| 48 |
+
{%- if message.tool_calls %}
|
| 49 |
+
{%- for tool_call in message.tool_calls %}
|
| 50 |
+
{%- if (loop.first and content) or (not loop.first) %}
|
| 51 |
+
{{- '\n' }}
|
| 52 |
+
{%- endif %}
|
| 53 |
+
{%- if tool_call.function %}
|
| 54 |
+
{%- set tool_call = tool_call.function %}
|
| 55 |
+
{%- endif %}
|
| 56 |
+
{{- '<tool_call>\n{"name": "' }}
|
| 57 |
+
{{- tool_call.name }}
|
| 58 |
+
{{- '", "arguments": ' }}
|
| 59 |
+
{%- if tool_call.arguments is string %}
|
| 60 |
+
{{- tool_call.arguments }}
|
| 61 |
+
{%- else %}
|
| 62 |
+
{{- tool_call.arguments | tojson }}
|
| 63 |
+
{%- endif %}
|
| 64 |
+
{{- '}\n</tool_call>' }}
|
| 65 |
+
{%- endfor %}
|
| 66 |
+
{%- endif %}
|
| 67 |
+
{{- '<|im_end|>\n' }}
|
| 68 |
+
{%- elif message.role == "tool" %}
|
| 69 |
+
{%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
|
| 70 |
+
{{- '<|im_start|>user' }}
|
| 71 |
+
{%- endif %}
|
| 72 |
+
{{- '\n<tool_response>\n' }}
|
| 73 |
+
{{- message.content }}
|
| 74 |
+
{{- '\n</tool_response>' }}
|
| 75 |
+
{%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
|
| 76 |
+
{{- '<|im_end|>\n' }}
|
| 77 |
+
{%- endif %}
|
| 78 |
+
{%- endif %}
|
| 79 |
+
{%- endfor %}
|
| 80 |
+
{%- if add_generation_prompt %}
|
| 81 |
+
{{- '<|im_start|>assistant\n' }}
|
| 82 |
+
{%- if enable_thinking is defined and enable_thinking is false %}
|
| 83 |
+
{{- '<think>\n\n</think>\n\n' }}
|
| 84 |
+
{%- endif %}
|
| 85 |
+
{%- endif %}
|
config.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"Qwen3Model"
|
| 4 |
+
],
|
| 5 |
+
"attention_bias": false,
|
| 6 |
+
"attention_dropout": 0.0,
|
| 7 |
+
"bos_token_id": 151643,
|
| 8 |
+
"dtype": "bfloat16",
|
| 9 |
+
"eos_token_id": 151643,
|
| 10 |
+
"head_dim": 128,
|
| 11 |
+
"hidden_act": "silu",
|
| 12 |
+
"hidden_size": 2048,
|
| 13 |
+
"initializer_range": 0.02,
|
| 14 |
+
"intermediate_size": 6144,
|
| 15 |
+
"layer_types": [
|
| 16 |
+
"full_attention",
|
| 17 |
+
"full_attention",
|
| 18 |
+
"full_attention",
|
| 19 |
+
"full_attention",
|
| 20 |
+
"full_attention",
|
| 21 |
+
"full_attention",
|
| 22 |
+
"full_attention",
|
| 23 |
+
"full_attention",
|
| 24 |
+
"full_attention",
|
| 25 |
+
"full_attention",
|
| 26 |
+
"full_attention",
|
| 27 |
+
"full_attention",
|
| 28 |
+
"full_attention",
|
| 29 |
+
"full_attention",
|
| 30 |
+
"full_attention",
|
| 31 |
+
"full_attention",
|
| 32 |
+
"full_attention",
|
| 33 |
+
"full_attention",
|
| 34 |
+
"full_attention",
|
| 35 |
+
"full_attention",
|
| 36 |
+
"full_attention",
|
| 37 |
+
"full_attention",
|
| 38 |
+
"full_attention",
|
| 39 |
+
"full_attention",
|
| 40 |
+
"full_attention",
|
| 41 |
+
"full_attention",
|
| 42 |
+
"full_attention",
|
| 43 |
+
"full_attention"
|
| 44 |
+
],
|
| 45 |
+
"max_position_embeddings": 32768,
|
| 46 |
+
"max_window_layers": 28,
|
| 47 |
+
"model_type": "qwen3",
|
| 48 |
+
"num_attention_heads": 16,
|
| 49 |
+
"num_hidden_layers": 28,
|
| 50 |
+
"num_key_value_heads": 8,
|
| 51 |
+
"pad_token_id": null,
|
| 52 |
+
"rms_norm_eps": 1e-06,
|
| 53 |
+
"rope_parameters": {
|
| 54 |
+
"rope_theta": 1000000,
|
| 55 |
+
"rope_type": "default"
|
| 56 |
+
},
|
| 57 |
+
"sliding_window": null,
|
| 58 |
+
"tie_word_embeddings": true,
|
| 59 |
+
"transformers_version": "5.17.0",
|
| 60 |
+
"use_cache": true,
|
| 61 |
+
"use_sliding_window": false,
|
| 62 |
+
"vocab_size": 151936
|
| 63 |
+
}
|
heads.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f1caa1bcf98884af6aa6edb40e370b767390c4768220ea0e5112a5490ee94df2
|
| 3 |
+
size 199985
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9becd7103e67152a8c8054eabec1dd3a817f6515c4a12dee4576389ec764f8f4
|
| 3 |
+
size 3441183752
|
ouroboros_config.yaml
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Inference / training settings of the released model (Ouroboros v7, stage 2). `backbone.name` is replaced by the
|
| 2 |
+
# directory this file lives in when the model is loaded.
|
| 3 |
+
backbone:
|
| 4 |
+
name: .
|
| 5 |
+
dtype: bfloat16
|
| 6 |
+
attn_implementation: sdpa
|
| 7 |
+
gradient_checkpointing: true
|
| 8 |
+
trust_remote_code: false
|
| 9 |
+
lora:
|
| 10 |
+
r: 32
|
| 11 |
+
alpha: 64
|
| 12 |
+
dropout: 0.05
|
| 13 |
+
target_modules: [q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj]
|
| 14 |
+
target_routed_experts: false
|
| 15 |
+
data:
|
| 16 |
+
train_shards: [data/corpus/train.jsonl]
|
| 17 |
+
eval_shards: [data/corpus/eval.jsonl]
|
| 18 |
+
calibration_shards: [data/corpus/calibration.jsonl]
|
| 19 |
+
test_shards: [data/corpus/test.jsonl]
|
| 20 |
+
window_tokens: 512
|
| 21 |
+
stride_tokens: 256
|
| 22 |
+
min_words: 50
|
| 23 |
+
max_windows_per_doc: 2
|
| 24 |
+
mixed_threshold: 0.15
|
| 25 |
+
soft_bucket_sharpness: 1.0
|
| 26 |
+
seed: 0
|
| 27 |
+
train:
|
| 28 |
+
output_dir: runs/ouroboros
|
| 29 |
+
stage: 2
|
| 30 |
+
steps: 6000
|
| 31 |
+
batch_size: 4
|
| 32 |
+
grad_accum: 4
|
| 33 |
+
lr: 5.0e-05
|
| 34 |
+
head_lr: 0.0005
|
| 35 |
+
weight_decay: 0.01
|
| 36 |
+
warmup_ratio: 0.03
|
| 37 |
+
max_grad_norm: 1.0
|
| 38 |
+
log_every: 25
|
| 39 |
+
eval_every: 500
|
| 40 |
+
save_every: 500
|
| 41 |
+
seed: 0
|
| 42 |
+
w_segment: 1.0
|
| 43 |
+
w_token: 1.0
|
| 44 |
+
w_mixed: 0.5
|
| 45 |
+
w_humanizer: 0.25
|
| 46 |
+
postprocess:
|
| 47 |
+
smoothness_lambda: 4.0
|
| 48 |
+
mixed_gamma: 0.5
|
| 49 |
+
class_prior_delta: [0.0, 0.0, 0.0]
|
| 50 |
+
min_segment_tokens: 32
|
| 51 |
+
human_fraction_threshold: 0.9
|
| 52 |
+
ai_fraction_threshold: 0.8
|
tokenizer.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:be75606093db2094d7cd20f3c2f385c212750648bd6ea4fb2bf507a6a4c55506
|
| 3 |
+
size 11422650
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": false,
|
| 3 |
+
"backend": "tokenizers",
|
| 4 |
+
"bos_token": null,
|
| 5 |
+
"clean_up_tokenization_spaces": false,
|
| 6 |
+
"eos_token": "<|endoftext|>",
|
| 7 |
+
"errors": "replace",
|
| 8 |
+
"extra_special_tokens": [
|
| 9 |
+
"<|im_start|>",
|
| 10 |
+
"<|im_end|>",
|
| 11 |
+
"<|object_ref_start|>",
|
| 12 |
+
"<|object_ref_end|>",
|
| 13 |
+
"<|box_start|>",
|
| 14 |
+
"<|box_end|>",
|
| 15 |
+
"<|quad_start|>",
|
| 16 |
+
"<|quad_end|>",
|
| 17 |
+
"<|vision_start|>",
|
| 18 |
+
"<|vision_end|>",
|
| 19 |
+
"<|vision_pad|>",
|
| 20 |
+
"<|image_pad|>",
|
| 21 |
+
"<|video_pad|>"
|
| 22 |
+
],
|
| 23 |
+
"is_local": true,
|
| 24 |
+
"local_files_only": false,
|
| 25 |
+
"model_max_length": 131072,
|
| 26 |
+
"pad_token": "<|endoftext|>",
|
| 27 |
+
"split_special_tokens": false,
|
| 28 |
+
"tokenizer_class": "Qwen2Tokenizer",
|
| 29 |
+
"unk_token": null
|
| 30 |
+
}
|