Text Generation
Transformers
Safetensors
MLX
qwen3
lora
on-device
legal
consumer-contracts
red-flag-detection
flowx
conversational
text-generation-inference
Instructions to use flowxai/caveat with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use flowxai/caveat with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="flowxai/caveat") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("flowxai/caveat") model = AutoModelForCausalLM.from_pretrained("flowxai/caveat", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - MLX
How to use flowxai/caveat with MLX:
# Make sure mlx-lm is installed # pip install --upgrade mlx-lm # Generate text with mlx-lm from mlx_lm import load, generate model, tokenizer = load("flowxai/caveat") prompt = "Write a story about Einstein" messages = [{"role": "user", "content": prompt}] prompt = tokenizer.apply_chat_template( messages, add_generation_prompt=True ) text = generate(model, tokenizer, prompt=prompt, verbose=True) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- vLLM
How to use flowxai/caveat with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "flowxai/caveat" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "flowxai/caveat", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/flowxai/caveat
- SGLang
How to use flowxai/caveat with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "flowxai/caveat" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "flowxai/caveat", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "flowxai/caveat" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "flowxai/caveat", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Pi
How to use flowxai/caveat with Pi:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "flowxai/caveat"
Configure the model in Pi
# Install Pi: npm install -g @mariozechner/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "mlx-lm": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "flowxai/caveat" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Hermes Agent new
How to use flowxai/caveat with Hermes Agent:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "flowxai/caveat"
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default flowxai/caveat
Run Hermes
hermes
- OpenClaw new
How to use flowxai/caveat with OpenClaw:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "flowxai/caveat"
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "flowxai/caveat" \ --custom-provider-id mlx-lm \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
- MLX LM
How to use flowxai/caveat with MLX LM:
Generate or start a chat session
# Install MLX LM uv tool install mlx-lm # Interactive chat REPL mlx_lm.chat --model "flowxai/caveat"
Run an OpenAI-compatible server
# Install MLX LM uv tool install mlx-lm # Start the server mlx_lm.server --model "flowxai/caveat" # Calling the OpenAI-compatible server with curl curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "flowxai/caveat", "messages": [ {"role": "user", "content": "Hello"} ] }' - Docker Model Runner
How to use flowxai/caveat with Docker Model Runner:
docker model run hf.co/flowxai/caveat
Add model card (README)
Browse files
README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
language:
|
| 4 |
+
- en
|
| 5 |
+
- ro
|
| 6 |
+
- pl
|
| 7 |
+
- hu
|
| 8 |
+
base_model: Qwen/Qwen3-4B
|
| 9 |
+
library_name: transformers
|
| 10 |
+
pipeline_tag: text-generation
|
| 11 |
+
tags:
|
| 12 |
+
- lora
|
| 13 |
+
- on-device
|
| 14 |
+
- mlx
|
| 15 |
+
- legal
|
| 16 |
+
- consumer-contracts
|
| 17 |
+
- red-flag-detection
|
| 18 |
+
- flowx
|
| 19 |
+
---
|
| 20 |
+
|
| 21 |
+
# caveat
|
| 22 |
+
|
| 23 |
+
**caveat** is a small, on-device model that reads a consumer contract and flags the
|
| 24 |
+
clauses worth reading twice: auto-renewal traps, punitive early-termination, liability
|
| 25 |
+
exclusions, data-selling, arbitration / class-action waivers, and the rest of a 34-type
|
| 26 |
+
taxonomy. It runs **privately on-device** (no API, no data leaves the machine) in
|
| 27 |
+
**English, Romanian, Polish and Hungarian**, and returns structured JSON, not prose.
|
| 28 |
+
|
| 29 |
+
> **caveat explains consequences. It is NOT legal advice and does not tell you whether to
|
| 30 |
+
> sign.** A no-advice contract is enforced at generation time (the model is scanned for
|
| 31 |
+
> advice language; violations are rejected).
|
| 32 |
+
|
| 33 |
+
- **Base model:** [Qwen/Qwen3-4B](https://huggingface.co/Qwen/Qwen3-4B) (Apache-2.0), LoRA fine-tuned.
|
| 34 |
+
- **Deployment:** on-device. Ship artifact is **MLX int4** (`mlx-int4/`, ~2 GB, Apple Silicon);
|
| 35 |
+
MLX int8 (`mlx-int8/`) and the standard fp16 merged model (repo root) are also provided.
|
| 36 |
+
- **Full model card:** see [`caveat_model_card.pdf`](./caveat_model_card.pdf).
|
| 37 |
+
|
| 38 |
+
## What it does
|
| 39 |
+
|
| 40 |
+
Input: one contract chunk + a document-type hint. Output: a JSON `ChunkResult`:
|
| 41 |
+
|
| 42 |
+
```json
|
| 43 |
+
{
|
| 44 |
+
"summary": "<one plain-language sentence>",
|
| 45 |
+
"red_flags": [
|
| 46 |
+
{"clause_type": "auto_renewal", "severity": "warning",
|
| 47 |
+
"span_text": "<verbatim clause text>", "explanation": "<consequence, no advice>",
|
| 48 |
+
"truncated": false}
|
| 49 |
+
]
|
| 50 |
+
}
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
`clause_type` is one of 34 taxonomy ids across 6 categories (money, rights-waived,
|
| 54 |
+
time/renewal, lease, insurance, data); `severity` is `info | caution | warning`.
|
| 55 |
+
|
| 56 |
+
### Recommended inference: two passes, unioned
|
| 57 |
+
|
| 58 |
+
Real contracts pack many red flags into few paragraphs, and a whole-document pass and a
|
| 59 |
+
per-paragraph pass surface **different** clauses (insurance detects better with full-document
|
| 60 |
+
context; lease/loan clauses detect better isolated). Run both and union the results
|
| 61 |
+
(de-duplicate by clause type + span). This roughly doubles real-world recall versus a single
|
| 62 |
+
whole-document pass. See `demo/explain.py` in the project repo for a reference implementation.
|
| 63 |
+
|
| 64 |
+
## Intended use
|
| 65 |
+
|
| 66 |
+
**In scope:** consumer-facing contracts (subscriptions / terms of service, insurance
|
| 67 |
+
policies, loan / credit agreements, residential leases, utility / telecom) in EN/RO/PL/HU,
|
| 68 |
+
as a **triage aid** that points a human to clauses worth a closer look.
|
| 69 |
+
|
| 70 |
+
**Out of scope:** legal advice or a decision on whether to sign; B2B / M&A / commercial
|
| 71 |
+
contracts; jurisdictions or languages outside those trained; any use where a missed clause
|
| 72 |
+
carries safety or legal risk without human review. Recall is partial (see Limitations).
|
| 73 |
+
|
| 74 |
+
## Evaluation
|
| 75 |
+
|
| 76 |
+
**Real-world recall (the headline).** On five held-out real consumer contracts (gym EN,
|
| 77 |
+
home-insurance EN, personal-loan RO, apartment-lease PL, mobile HU), scored with the
|
| 78 |
+
two-pass inference, caveat detects **13 distinct red flags**, up from 9 for a prior 4B and 7
|
| 79 |
+
for a 1.7B baseline, and it is the first version to catch flags on **all five** documents
|
| 80 |
+
(the RO loan and PL lease were previously undetected).
|
| 81 |
+
|
| 82 |
+
**Synthetic benchmark (RedFlag-Bench v0.1, 597 frozen held-out chunks).** Overall
|
| 83 |
+
clause-type F1 **0.275** (+54% over the pre-coverage-fix 4B); by category: lease 0.33,
|
| 84 |
+
money 0.32, data 0.32, rights-waived 0.23, time/renewal 0.20, insurance 0.00\*; by language:
|
| 85 |
+
EN 0.35, HU 0.29, PL 0.24, RO 0.14. Faithfulness: 2.6 span-verification failures per 100
|
| 86 |
+
flags; JSON validity 1.00; advice hits 0. *(\*The insurance bench F1 is a small-sample
|
| 87 |
+
artifact of the frozen set; real-document insurance detection works, e.g. waiting-periods and
|
| 88 |
+
buried-exclusions on the home-insurance doc.)* The synthetic bench shares a generator family
|
| 89 |
+
with the training data, so read it as a format-adherence / faithfulness ceiling, not a
|
| 90 |
+
real-world recall measure.
|
| 91 |
+
|
| 92 |
+
**Versus a frontier model (like-for-like slice).** On a seeded 100-chunk slice, a frontier
|
| 93 |
+
model (Claude Opus) leads the overall synthetic F1 (0.385 vs caveat 0.233); caveat wins
|
| 94 |
+
specific cells (lease 0.80 vs 0.30, English 0.63 vs 0.27, severity agreement 0.43 vs 0.33).
|
| 95 |
+
caveat's value is real-document recall and running **privately, on-device, at no inference
|
| 96 |
+
cost**, not beating a frontier model on the synthetic benchmark.
|
| 97 |
+
|
| 98 |
+
## Training
|
| 99 |
+
|
| 100 |
+
LoRA (rank 16 / alpha 32 / dropout 0.05, all-linear target modules), 2 epochs, cosine LR
|
| 101 |
+
2e-5 -> 2e-6, effective batch 4, max sequence length 2048, bf16, on an NVIDIA L4. Training
|
| 102 |
+
data (5,263 train / 1,367 validation chunks, split by document): synthetic consumer contracts
|
| 103 |
+
generated across five drafting registers with flag-dense examples, targeted insurance- and
|
| 104 |
+
lease-coverage batches, and **450 real English clause spans from CUAD** (train-only).
|
| 105 |
+
|
| 106 |
+
### Attribution & licenses
|
| 107 |
+
|
| 108 |
+
- Model weights released under **Apache-2.0** (inherited from the Qwen3-4B base).
|
| 109 |
+
- Training used the **Contract Understanding Atticus Dataset (CUAD) v1**, The Atticus
|
| 110 |
+
Project, Inc. (CC-BY-4.0) — Hendrycks et al., *CUAD: An Expert-Annotated NLP Dataset for
|
| 111 |
+
Legal Contract Review*, arXiv:[2103.06268](https://arxiv.org/abs/2103.06268). CUAD clause
|
| 112 |
+
spans were used train-only for clause shapes.
|
| 113 |
+
|
| 114 |
+
## Limitations & responsible use
|
| 115 |
+
|
| 116 |
+
- **Not legal advice.** A triage aid only; always have important contracts reviewed by a
|
| 117 |
+
qualified professional.
|
| 118 |
+
- **Partial recall.** caveat surfaces many but not all red flags (~13 of 20+ on the real set);
|
| 119 |
+
a clean result is not a guarantee the contract is safe.
|
| 120 |
+
- **Uneven coverage.** English is strongest; Romanian and Polish are weaker; insurance and
|
| 121 |
+
lease phrasing vary in reliability. Use the two-pass inference for best recall.
|
| 122 |
+
- **Small real-world eval.** The real-document evidence is five contracts; treat the numbers
|
| 123 |
+
as directional.
|
| 124 |
+
|
| 125 |
+
## Citation
|
| 126 |
+
|
| 127 |
+
```bibtex
|
| 128 |
+
@misc{flowx_caveat_2026,
|
| 129 |
+
title = {caveat: on-device consumer-contract red-flag detection},
|
| 130 |
+
author = {R\u{a}du\c{t}\u{a}, Bogdan},
|
| 131 |
+
year = {2026},
|
| 132 |
+
note = {FlowX.AI. LoRA fine-tune of Qwen3-4B.}
|
| 133 |
+
}
|
| 134 |
+
```
|
| 135 |
+
|
| 136 |
+
_Author: Bogdan Răduță, Head of Research, FlowX.AI._
|