Views
No views yet
| Base model | Qwen/Qwen3.5-9B (Hybrid, Dense, 64K context) |
| SFT data | 9,662 examples across 6 industry domains |
| Preference data | 5,614 examiner-labelled pairs |
| Evaluation | 1,314 held-out examples, sliced 11 ways |
1git clone <your-repo-url> && cd claim-drafter
2make setup # .venv on Python 3.12 + dependencies
3cp .env.example .env # then add your TINKER_API_KEY
4make test # offline tests, no key or data needed
5make preflight # verifies everything incl. the API
6make all # SFT -> DPO -> GRPO -> graphsmake all hands each stage's
checkpoint to the next automatically, and prints a live progress line per stage:sft [############................] 43.2% 1037/2400 nll 0.8421 2.9s/it 50m12s<1h06m eval in 8m21smake sft, make dpo, make rl), and
make graphs redraws runs/graphs/ from whatever logs exist. See the
GitHub repository for the eval-cadence
reasoning.make help lists every target. The GitHub repository walks through
every step in order and what to watch while it runs.tinker SDK requires it.macOS note. Ifpipfails withSymbol not found: _XML_SetAllocTrackerActivationThreshold, your Homebrew Python has a brokenpyexpatlink and cannot install anything —venvfails too, becauseensurepiphits the same error.make setupsidesteps it by usinguv, which fetches its own standalone Python. To fix the underlying install instead:brew reinstall expat python@3.14.
claim_drafter/ importable library
config.py shared defaults, .env loading
domains.py IPC code -> one of six industry domains (99.96% coverage)
filters.py text cleaning, leakage, unlearnable-claim detection
patents.py Google Patents fetch/parse (granted B2 and as-filed A1)
rewards.py programmatic claim reward + production guardrail
rl_env.py RL environment (ProblemEnv subclass)
evaluator.py custom evaluator over the 11 validation slices
scripts/ data pipeline and checks
select_targets.py choose which patents to fetch, before making the calls
fetch_claims.py concurrent, resumable claim fetching
augment_thin_domains.py stream an extra HUPD year for under-represented domains
build_sft_dataset.py build the SFT dataset
build_dpo_pairs.py build examiner-labelled preference pairs
validate_dataset.py structural pre-flight on a built dataset
estimate_cost.py size the pipeline before running it
preflight.py verify the whole setup end to end
training/ train_sft.py -> train_dpo.py -> train_rl.py
deploy/ export_model.py, example_client.py
tests/ offline test suite (runs on a fresh clone)
manifests/ provenance for every example -- makes the data reproducible
samples/ a few rows of each dataset, so the format is visible
docs/ runbook, experiment plan, dataset card (in the GitHub repo)
data/ generated, gitignoredmanifests/ records the patent number, IPC class, domain, split and
token counts for every example. Combined with the scripts and a fixed seed, that
reproduces the datasets byte-identically:1make data # SFT dataset (~1 hour, mostly network)
2make dpo-data # preference pairssamples/ holds a handful of rows from each so you can see the format without
rebuilding anything. The tests run against those, so a fresh clone is testable
immediately.| Stage | Method | Teaches |
|---|---|---|
| 1 | SFT | claim format and USPTO register |
| 2 | DPO | allowable scope — what survives examination |
| 3 | GRPO | formal validity under the model's own distribution |
1make sft # stage 1
2make graphs # then LOOK at the results before starting stage 2
3make dpo # checkpoint resolves from runs/sft automatically
4make rl # checkpoint resolves from runs/dpo automatically1python3 deploy/export_model.py --checkpoint tinker://<run-id>/sampler_weights/final
2vllm serve Qwen/Qwen3.5-9B --lora-modules claim-drafter=./export/peft_adapter
3python3 deploy/example_client.py1from claim_drafter.rewards import claim_reward
2if claim_reward(generated) < 0.9:
3 ... # numbering or dependency defect: regenerate or route to reviewclaim_reward checks formal validity
only. Every output needs attorney review.--workers modest — it is a polite crawler with
backoff, and the service is not yours.Qwen/Qwen3.5-9B,
alongside the full training/data pipeline. The datasets it was trained on are
published separately as a dataset repo:
vishwr/claim_drafter.adapter_config.json,
adapter_model.safetensors) for one-line loading, and is also kept at
export/peft_adapter/ so the paths in the docs and the vllm command below
resolve unchanged.1from peft import PeftModel
2from transformers import AutoModelForCausalLM, AutoTokenizer
3
4base = "Qwen/Qwen3.5-9B"
5tok = AutoTokenizer.from_pretrained(base)
6model = AutoModelForCausalLM.from_pretrained(base, device_map="auto")
7model = PeftModel.from_pretrained(model, "vishwr/claim_drafter") # adapter at repo root1vllm serve Qwen/Qwen3.5-9B --enable-lora \
2 --lora-modules claim-drafter=vishwr/claim_drafterclaim_drafter/rewards.py) before showing it to a user — it checks numbering,
dependency validity and single-sentence form.