--- license: mit language: - en library_name: graf tags: - graf - paragraph-segmentation - token-classification - news - encoder - modernbert - on-device pipeline_tag: token-classification base_model: jhu-clsp/ettin-encoder-17m metrics: - f1 --- # Graf Paragraphs will be stacked until morale improves. A small encoder that recovers paragraph breaks in flattened news text. | | | | --- | --- | | **Task** | Paragraph break recovery (token classification) | | **Size** | ~19 MB weights (trimmed vocab, int8 embeddings, fp16 rest) | | **Runtime** | CPU/GPU (PyTorch); browser (ONNX Runtime WASM) | | **Weights** | [`main`](https://huggingface.co/localangle/graf/tree/main) · [`web/`](https://huggingface.co/localangle/graf/tree/main/web) for WASM | | **Demo** | [localangle/graf-demo](https://huggingface.co/spaces/localangle/graf-demo) (in-browser) | Graf does **not** rewrite the article. It scores eligible token ends as `BREAK` / `NO_BREAK`, then splits the flattened string at predicted breaks. > Flattened: *City council approved a library renovation… Construction starts in March…* > → Graf inserts breaks between the recovered paragraphs. ## Try it - **Live demo:** [localangle/graf-demo](https://huggingface.co/spaces/localangle/graf-demo) — paste flattened news, paragraphize in the browser. - **Local UI:** from the [graf](https://github.com/cjdd3b/graf) repo, `graf-web --web-package checkpoints/graf-web`. ## Install ```bash pip install "graf @ git+https://github.com/cjdd3b/graf.git" # or, from a checkout: pip install -e . ``` Python ≥ 3.11. Needs `torch`, `transformers`, `safetensors`, `huggingface_hub`. ## Usage ```python from graf.infer import GrafParagraphizer graf = GrafParagraphizer("localangle/graf") # thr from graf.json (0.41) result = graf.paragraphize( "City council approved a library renovation after public comment. " "Paulsen and Chen voted against the measure. Construction starts in March." ) print("\n\n".join(result.paragraphs)) ``` Load a local package folder the same way: ```python graf = GrafParagraphizer("checkpoints/graf") ``` ## Files | File | Contents | | --- | --- | | `graf.json` | Format, threshold, kept vocabulary, source metadata | | `weights.safetensors` | Trimmed encoder + head (int8 token embeddings, fp16 elsewhere) | | `encoder/` | Ettin/ModernBERT config for the trimmed vocabulary | | `tokenizer/` | Full tokenizer (ids remapped at inference via `vocab_map`) | | `web/` | Browser package: `model.onnx` (~17 MB int8), `vocab_map.bin`, `graf-web.json`, `tokenizer/` | PyTorch weights expand to fp32 at load; only storage is compressed. The `web/` ONNX graph is what the static demo runs in WASM (soft cap 2048 tokens). ## Accuracy Held-out Extra structure v0.2 test set (publisher-disjoint), package threshold 0.41 (student before compression; packaging keeps break agreement ≈ Jaccard 0.98): | Metric | Value | | --- | --- | | Boundary F1 | 0.871 | | Precision / Recall | 0.845 / 0.900 | | PR-AUC | 0.948 | | Body–body precision / recall | 0.829 / 0.894 | | Median \|Δ block count\| | 2.0 | ## How it works Flattened article text is packed into overlapping 2048-token windows. Eligible token ends (positions that can host a paragraph boundary) are scored for `BREAK`. Probabilities are averaged across windows, thresholded, and used to reconstruct paragraph blocks. The published package is a compressed [Ettin](https://huggingface.co/jhu-clsp/ettin-encoder-17m) student (~17M) distilled for on-device / in-browser use. ## Limitations - English news-style prose; other domains are unmeasured. - Training text / Extra labels are not redistributed here. - Exact full-article reconstruction is intentionally hard; treat boundary F1 / body–body metrics as the primary quality signal. - Browser int8 ONNX drifts slightly vs the PyTorch package; the web meta threshold is nudged for recall (see `web/graf-web.json`). ## Built on - [Ettin encoder 17M](https://huggingface.co/jhu-clsp/ettin-encoder-17m) (MIT) by JHU CLSP. Fine-tuned and compressed for Graf; see `THIRD_PARTY_NOTICES.md`. ## License MIT for the Graf code and this package's weights, subject to the Ettin MIT notice above. ## Citation ```bibtex @software{graf_2026, title = {Graf: Paragraph break recovery for flattened news}, author = {Local Angle}, year = {2026}, url = {https://huggingface.co/localangle/graf}, } ```