Instructions to use vishwr/claim_drafter with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use vishwr/claim_drafter with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3.5-9B") model = PeftModel.from_pretrained(base_model, "vishwr/claim_drafter") - Notebooks
- Google Colab
- Kaggle
| #!/usr/bin/env python3 | |
| """Choose which patents to fetch claims for, before spending network calls. | |
| Two modes. | |
| Granted-claim targets (default) — walk a directory of HUPD application JSONs and | |
| emit the patent numbers worth fetching: granted, in a target domain, and with | |
| enough Background/Abstract text to survive the dataset filters. Pre-filtering | |
| here avoids thousands of fetches for applications the builder would discard. | |
| python3 scripts/select_targets.py --hupd hupd/sample/2016 \\ | |
| --output data/cache/targets_granted.txt | |
| Publication targets (--publications) — emit "<application>\\t<publication>" pairs | |
| for the SFT training split, so the as-filed (A1) claims can be fetched to build | |
| DPO preference pairs. Restricted to the training split so the held-out evaluation | |
| pool is never touched. | |
| python3 scripts/select_targets.py --hupd hupd/sample/2016 --publications \\ | |
| --manifest data/sft/manifest.jsonl --output data/cache/targets_pubs.tsv | |
| """ | |
| import argparse | |
| import glob | |
| import json | |
| import os | |
| import random | |
| import sys | |
| from collections import Counter | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| from claim_drafter.domains import classify | |
| from claim_drafter.filters import clean_section | |
| MIN_BACKGROUND_CHARS = 400 | |
| MIN_ABSTRACT_CHARS = 150 | |
| def iter_applications(hupd_dirs): | |
| for d in hupd_dirs: | |
| for path in sorted(glob.glob(os.path.join(d, "*.json"))): | |
| try: | |
| with open(path) as f: | |
| yield json.load(f) | |
| except ValueError: | |
| continue | |
| def already_fetched(path, key): | |
| done = set() | |
| if path and os.path.exists(path): | |
| with open(path) as f: | |
| for line in f: | |
| try: | |
| done.add(json.loads(line)[key]) | |
| except Exception: | |
| pass | |
| return done | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--hupd", nargs="+", required=True, help="directories of HUPD JSONs") | |
| ap.add_argument("--output", required=True) | |
| ap.add_argument("--publications", action="store_true", | |
| help="emit application/publication pairs for as-filed claims") | |
| ap.add_argument("--manifest", help="restrict to the train split of this manifest") | |
| ap.add_argument("--domains", help="comma-separated domain allowlist") | |
| ap.add_argument("--skip-cached", help="JSONL of already-fetched records") | |
| ap.add_argument("--per-domain-cap", type=int, default=0, | |
| help="cap per domain, for augmentation runs") | |
| ap.add_argument("--seed", type=int, default=42) | |
| args = ap.parse_args() | |
| allow = set(args.domains.split(",")) if args.domains else None | |
| restrict = None | |
| if args.manifest: | |
| restrict = set() | |
| with open(args.manifest) as f: | |
| for line in f: | |
| r = json.loads(line) | |
| if r.get("split") == "train": | |
| restrict.add(r["application_number"]) | |
| stats = Counter() | |
| by_domain = {} | |
| rows = [] | |
| if args.publications: | |
| done = already_fetched(args.skip_cached, "application_number") | |
| for d in iter_applications(args.hupd): | |
| app = d.get("application_number") or "" | |
| if restrict is not None and app not in restrict: | |
| continue | |
| if app in done: | |
| stats["already_cached"] += 1 | |
| continue | |
| pub = (d.get("publication_number") or "").split("-")[0] | |
| if not pub.startswith("US"): | |
| stats["no_publication"] += 1 | |
| continue | |
| rows.append("%s\t%s" % (app, pub)) | |
| else: | |
| done = already_fetched(args.skip_cached, "patent_number") | |
| for d in iter_applications(args.hupd): | |
| if d.get("decision") != "ACCEPTED": | |
| stats["not_granted"] += 1 | |
| continue | |
| domain = classify(d.get("main_ipcr_label")) | |
| if not domain or (allow and domain not in allow): | |
| stats["off_domain"] += 1 | |
| continue | |
| patent = d.get("patent_number") or "" | |
| if not patent.isdigit(): | |
| stats["no_patent_number"] += 1 | |
| continue | |
| if patent in done: | |
| stats["already_cached"] += 1 | |
| continue | |
| if len(clean_section(d.get("background"))) < MIN_BACKGROUND_CHARS: | |
| stats["thin_background"] += 1 | |
| continue | |
| if len(clean_section(d.get("abstract"))) < MIN_ABSTRACT_CHARS: | |
| stats["thin_abstract"] += 1 | |
| continue | |
| by_domain.setdefault(domain, []).append(patent) | |
| rng = random.Random(args.seed) | |
| for domain, patents in sorted(by_domain.items()): | |
| patents = sorted(set(patents)) | |
| rng.shuffle(patents) | |
| if args.per_domain_cap: | |
| patents = patents[: args.per_domain_cap] | |
| print(" %-26s %5d" % (domain, len(patents))) | |
| rows.extend(patents) | |
| rows = list(dict.fromkeys(rows)) | |
| os.makedirs(os.path.dirname(os.path.abspath(args.output)), exist_ok=True) | |
| with open(args.output, "w") as f: | |
| f.write("\n".join(rows) + ("\n" if rows else "")) | |
| print("\nskipped: %s" % (" ".join("%s=%d" % kv for kv in sorted(stats.items())) or "none")) | |
| print("wrote %d targets -> %s" % (len(rows), args.output)) | |
| if __name__ == "__main__": | |
| main() | |