Instructions to use properexit/ArgParser-v4 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use properexit/ArgParser-v4 with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-1.5B-Instruct") model = PeftModel.from_pretrained(base_model, "properexit/ArgParser-v4") - Notebooks
- Google Colab
- Kaggle
ArgParser-v4
A Qwen-1.5B LoRA that extracts argument structure — claims, premises, citations, and support/attack relations — from political claims and argumentative prose. This is the fourth iteration of a distillation project, and the one that actually works well enough to plug into a real fact-checking pipeline.
Where this came from
I built an argument-aware retrieval pipeline for Politifact-style fact-checking. Given a claim like "Politician X said Y," it retrieves evidence using argument-role-targeted queries and returns a 6-way truth verdict. When the parser was reading gold argument annotations from the LIARArg dataset, this pipeline hit 0.422 6-way F1 versus 0.114 for a flat-RAG baseline. The 0.308 gap was the whole reason to build it.
But that gap only means something if a real parser can slot in at inference time. Gold annotations aren't available for actual incoming claims. So the question became: what parser closes that gap?
First cut, Phase 2-α, was gpt-oss-120b running zero-shot on Cerebras.
It closed about 45% of the gap (integration F1 0.254). Real, useful,
but calling a 120B cloud model per claim isn't practical for anything
resembling deployment.
Phase 2-β was the distillation project. Four iterations. Can a small local model preserve most of the gain?
The four iterations
v1 was Qwen-0.5B, full fine-tune on four argument-mining corpora (AbstRCT, Microtext, CDCP, PERSPECTRUM), 1,494 records, 3 epochs. The smallest reasonable baseline. In-domain comp-F1 averaged 0.108 across the four held-out test sets. High empty rates on some domains (PERSPECTRUM: 91% empty). The point was to get the pipeline plumbing right, not to publish a number.
v2 kept the same data but moved to Qwen-1.5B with LoRA r=16
(α=32, dropout 0.05, target q_proj,k_proj,v_proj,o_proj). 3 epochs.
In-domain comp-F1: 0.219, roughly double v1. Microtext premise F1
jumped from 0.000 to 0.680. AbstRCT empty rate 75% → 50%. Scale +
LoRA + longer training context are the dominant levers here.
v3 was v2's adapter continued for one more epoch after adding a fifth corpus (AAEC, 402 persuasive essays). Marginal in-domain improvement (0.229). PERSPECTRUM actually regressed slightly, which was the first sign that adding more of the same kind of extractive gold hits diminishing returns quickly. Then I tried v3 on the actual LIARArg parse and hit 83% empty rate on the first 64 rows. Killed that run. The lesson was clear: extractive gold from academic argument-mining corpora doesn't teach a small student to handle Politifact-style claims. The distribution gap is too wide.
v4 is this model. Two changes from v3:
- Fresh adapter, not continual. Clean A/B against v3.
- I generated 2,123 silver labels on LIARArg train articles using
gpt-oss-120bvia Cerebras. Both the extracted argument structure and the model's Chain-of-Thought reasoning came back (the CoT was inmessage.reasoning, which I captured almost by accident). The training code's target-formatter passes reasoning through as<think>...</think>{json}when present, so v4 accidentally became CoT-aware for LIARArg-style inputs — while staying purely extractive on the gold in-domain corpora (where reasoning was empty).
This wasn't planned. It just happened, and it turned out to be exactly what was missing.
Training details: 3,617 records total, 3 epochs, fresh LoRA adapter, fp16, Adafactor, gradient checkpointing. Batch 1, grad accum 32. About 29 hours on a single GTX 1080 Ti.
What v4 actually does
The load-bearing number is Phase 1 integration on LIARArg — the whole reason to build any of this:
| Metric | v4 | Phase 2-α teacher (120B) | Teacher retention |
|---|---|---|---|
| 6-way F1 | 0.217 | 0.254 | 85% |
| 3-way F1 | 0.457 | 0.461 | 99% |
| within-1 accuracy | 0.605 | 0.616 | 98% |
Flat-RAG baseline for reference: 0.114. v4 beats it by 0.103 and closes 33% of the gold-parser gap using a locally-runnable 1.5B model.
LIARArg parse empty rate went from v3's 83% down to 23%. Silver + CoT was the missing piece.
In-domain retention is modest — 0.192 comp-F1 averaged across the five training corpora, slightly regressed from v3's 0.229. That's the cost of a fresh 3-epoch run versus v3's effective 4 epochs. The trade was worth it for the cross-domain transfer.
OOD probes
To characterize where v4 stops transferring, I ran three unseen-domain probes:
AMPERSAND (Chakrabarty et al. 2019, Reddit ChangeMyView). Binary is-argumentative F1 = 0.819 with recall 0.970 on 150 balanced sentences. v4 catches essentially all argumentative content in Reddit debate. The 30% false-positive rate comes from over-flagging fragments and borderline sentences; some of those are arguably right and just disagree with the annotator.
PERSUADE 2.0 (Kaggle Feedback Prize, student argumentative essays). Component F1 macro = 0.193 with 45.7% extraction rate on 25 essays. Claim F1 = 0.351, premise F1 = 0.034. v4 finds about half of PERSUADE's argumentative spans and labels claim-like content reasonably. Premise F1 collapses because PERSUADE's Evidence and Rebuttal categories are much narrower than v4's premise concept.
ECHR (European Court of Human Rights case briefs). Component F1 = 0.074 with 9.7% extraction rate against a proxy gold derived from ECHR's agent labels. Legal reasoning is structurally distant from anything v4 saw in training.
Ordering (Reddit > essays > legal) tracks discourse-register proximity to v4's training data. Predictable, but useful to have quantified.
Usage
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch, re, json
base_id = "Qwen/Qwen2.5-1.5B-Instruct"
adapter_id = "properexit/ArgParser-v4"
tok = AutoTokenizer.from_pretrained(base_id)
base = AutoModelForCausalLM.from_pretrained(
base_id, torch_dtype=torch.float16, device_map="auto"
)
model = PeftModel.from_pretrained(base, adapter_id)
INSTR = ("Extract all argument components and relations from the text. "
"Output strict JSON with claim_components, premise_components, "
"citation_components, and relations.")
def parse(text, max_new_tokens=1024):
prompt = tok.apply_chat_template(
[{"role": "user", "content": f"{INSTR}\n\nTEXT:\n{text}"}],
tokenize=False, add_generation_prompt=True,
)
enc = tok(prompt, return_tensors="pt", truncation=True,
max_length=2048).to(model.device)
out = model.generate(**enc, max_new_tokens=max_new_tokens,
do_sample=False,
pad_token_id=tok.pad_token_id,
eos_token_id=tok.eos_token_id)
raw = tok.decode(out[0, enc["input_ids"].shape[-1]:],
skip_special_tokens=True)
cleaned = re.sub(r"<think>.*?</think>", "", raw, flags=re.DOTALL)
m = re.search(r"\{.*\}", cleaned, flags=re.DOTALL)
return (json.loads(m.group()) if m else None), raw
pred, raw = parse(
"The Obama administration is putting Border Patrol agents in a chokehold."
)
print(pred)
Things worth knowing before using this
The model emits <think>...</think> blocks on political and
opinionated inputs (that's where it saw CoT during training). On
formal or structured text — legal writing, some scientific abstracts
— it goes straight to JSON. Neither is a bug, it just needs handling
if you're stripping the raw generation.
Long inputs can trigger a relation-generation loop that leaves the JSON
unclosed. What happens: the model emits valid claim_components and
premise_components early, then gets stuck emitting
{"src": N, "tgt": M, "type": "support"} tuples in a repeating
pattern until it hits max_new_tokens. You never see the closing }
so strict JSON parsing rejects everything. The workaround is either
setting max_new_tokens conservatively, or using a lenient parser
that pulls each valid {...} object out of each section
independently and dedupes relations. I use the second approach in
the training repo.
v4 systematically over-predicts spans on OOD text — precision runs lower than recall in every probe. On borderline sentences it defaults to labeling as claim. Something to keep in mind if downstream consumers care about precision.
Fine-grained annotation schemas map imperfectly to v4's binary claim/premise split. PERSUADE's Evidence/Rebuttal distinction and ECHR's Court/Applicant/State agent labels don't translate directly. v4 knows a claim from a premise; it doesn't know PERSUADE's Evidence from PERSUADE's Rebuttal.
Training summary
- Base:
Qwen/Qwen2.5-1.5B-Instruct - LoRA: r=16, α=32, dropout 0.05, on
q_proj,k_proj,v_proj,o_proj - Training records: 3,617 (5 gold corpora + 2,123 LIARArg silver)
- Epochs: 3, fresh adapter
- Optimizer: Adafactor, fp16, gradient checkpointing
- Hardware: single NVIDIA GTX 1080 Ti
- Wall clock: ~29 h
License
Apache 2.0. Base model (Qwen 2.5) is also Apache 2.0. Use however you want, no warranty.
- Downloads last month
- 15