Live · Qwen3.5-2B + LoRA · trained on CUAD
Upload a contract, see the risky clauses highlighted.
A 2B-parameter model fine-tuned to find 41 kinds of clauses lawyers look for, from uncapped liability to change of control. It lifts held-out span F1 from 0.02 to 0.49 over the same model untuned.
Live scans paused
01— ScanPDF, DOCX or text
Or try a demo contract
02— Ask this contractanswers cite sections
Ask a question, get an answer that points at the text.
03— How it workseval, pipeline, privacy, cost
A small model, measured before and after fine-tuning.
Held-out results · 97 CUAD contracts
| Metric | Zero-shot | + LoRA r8 |
|---|---|---|
| Span F1 (IoU ≥ 0.5) | 0.023 | 0.492 |
| Clause presence F1 | 0.387 | 0.833 |
| Unparseable outputs | 58.6% | 4.1% |
| Output tokens | 709k | 175k |
Pipeline
- In your browser: pdf.js or mammoth extracts the text and splits it into overlapping sections of about 1,500 tokens, with the same chunker the model was trained on.
- Cloudflare Worker: builds the fixed prompt and checks the daily budget.
- Modal GPU (L4): vLLM runs Qwen3.5-2B with the LoRA merged in. It returns each clause's type and its first and last words.
- Back in the Worker: those anchors are matched to exact character offsets, so highlights land on the real text.
- Ask embeds sections with bge-m3 and answers with Qwen3-30B-A3B on Workers AI, citing only sections it was given.
How your contract is handled
- Your file
- Read in your browser. The file itself is never uploaded.
- Its text
- Sent in sections to a Cloudflare Worker, then to a GPU on Modal (may run in the US) and, for Ask, to Workers AI. Processed in memory and not stored. Modal doesn't store the requests this app sends, and Cloudflare doesn't train on them.
- Logs
- One line per request: timings, counts, lengths and a keyed fingerprint. Never the text or your questions.
- Your IP
- Turned into a pseudonymous id, salted afresh each day, to enforce a fair daily quota. Deleted after the day.
- Tip
- Remove personal details before scanning a real contract.