--- license: apache-2.0 library_name: numpy tags: - argument-mining - argument-graph - robustness - interpretability - nli - heuristic - cpu pipeline_tag: text-classification --- # hv-core **Sensitivity-annotated argument graph.** Given a text, output what it claims, how much each claim carries, and the single cheapest edit that would break it. ## The claim in one sentence `hv-core` produces the sensitivity-annotated argument graph: G = (V, E, d, Φ) V = claims E = inference relations d = per-claim information density Φ = flip sets (which edits change the conclusion) ## What it produces A `CoreReport` containing: - **graph** — nodes (claims) and edges (inference relations) - **density** — per-claim information weight - **critical_path** — highest-density path from premises to conclusion - **redundant_claims** — claims removable without changing the conclusion - **low_density_spans** — filler claims - **gaps** — structural inferences that should exist but don't - **flip_set** — the minimal cut: the set of edges whose simultaneous removal flips the conclusion - **min_flip_cost** — total cost of the cheapest cut - **robustness** — the scalar `R` (total cost of the min-cut) - **robustness_tier** — `weak` / `medium` / `strong` / `trivial` - **load_bearing_claim** — the densest claim on the critical path - **redundancy_index** — fraction of removable claims ### Robustness tier Tier is assigned by **cut size** (structural robustness), not by raw cost: | cut size | tier | |---|---| | 0 edges (no support reaches the conclusion) | `trivial` | | 1 edge | `weak` | | 2–3 edges | `medium` | | 4+ edges | `strong` | `robustness` itself is the total cost of the min-cut under `c(e) = d(u) + d(v)`. It scales with both cut size and edge density; the tier is the structural verdict. ## Install ```bash pip install numpy Actually — no dependencies. Pure stdlib. ## Usage ### Analyze a text ```python from hv_core import HVCore m = HVCore() report = m.analyze("The biopsy was negative. The imaging confirmed it. " "Therefore the tumor is benign.") print(report.robustness) # total min-cut cost print(report.robustness_tier) # 'medium' print(report.load_bearing_claim) # {'id': 0, 'density': 0.81, ...} print(report.redundant_claims) # [2] ### Just the numbers ```python m.robustness(text) # the scalar R m.conclusion(text) # detected conclusion m.load_bearing(text) # the claim the argument rests on m.flips(text, top=5) # the edges of the min-cut ``` ### CLI ```bash python hv_core.py # run all demos python hv_core.py --text "..." # analyze a text python hv_core.py --text "..." --robustness # just the scalar python hv_core.py --text "..." --flips 5 # top 5 cut edges python hv_core.py --text "..." --json # JSON output ``` ## The model ### Stage 1 — graph extraction Sentence splitting. Claim extraction (one proposition per sentence). **Discourse-first conclusion detection**: a sentence starting with `therefore`, `thus`, `hence`, `consequently`, … is the conclusion. Fallback is the last sentence if it carries a recommendation marker (`should`, `must`, `is indicated`, …). Final fallback is the last sentence. **Structural edge generation**: 1. Contradiction edges via antonym pairs. 2. Every prior claim → `supports` → conclusion. 3. Conclusion → `implies` → every subsequent claim. 4. Adjacency continuity edges between nearby non-conclusion claims when content-word Jaccard ≥ `adjacency_overlap`. ### Stage 2 — density scoring For each claim, density is the fraction of its content words that are *novel* relative to the union of its ancestors' content words, weighted by the fraction of rare words it carries: d(v) = novelty(v | ancestors(v)) · (0.6 + 0.4 · rare_frac(v)) ### Stage 3 — flip search via min-cut Robustness is the **cheapest set of edges whose simultaneous removal disconnects the conclusion from every leaf premise**. Computed by Edmonds–Karp on a flow network with: - edge capacities `c(e) = d(u) + d(v)` (spec prose: dense edges are expensive to sever) - a super-source connecting all leaf premises with infinite capacity - the conclusion connected to a super-sink with infinite capacity ### Heuristic NLI No transformer. Scoring combines content-word coverage, Jaccard overlap, antonym detection (a fixed lexicon), and negation mismatch. ## Benchmarks ### Sample texts | text | claims | edges | robustness | tier | cut | |---|---:|---:|---:|---|---:| | Medical (MI diagnosis) | 7 | 6 | 7.335 | strong | 5 | | Science (black hole) | 6 | 6 | 6.807 | strong | 5 | | Legal (contract breach) | 6 | 5 | 4.542 | strong | 4 | | Weak argument (CEO stock) | 4 | 3 | 3.027 | medium | 2 | **Reading the table:** - **Weak argument** is the most fragile: two edges flip it. - **Medical** has five independent supports — the argument is multiply grounded. - **Legal** has four supports. - **Science** is the densest graph. ## When to use it - **Argument auditing** — before acting on a memo, brief, or diagnosis. - **Editing** — find the sentence the argument rests on. - **Peer review** — flag conclusions that hinge on one weak claim. - **Debate prep** — find the cheapest attack on the other side. - **Teaching** — show students where an argument would break. ## When *not* to use it - **As ground truth.** The NLI is heuristic. The densities are heuristic. The model ranks; it does not measure. - **For non-English text.** Lexicons and antonym pairs are English. - **For symbolic or code-heavy text.** Content-word novelty misses the structure of proofs and programs. - **For very long documents.** `max_claims` defaults to 64. ## Honest limitations - **The NLI is a bag-of-content-words heuristic.** It will misclassify examples that depend on syntactic structure, quantifier scope, or discourse relations. - **The antonym lexicon is hand-curated (~40 pairs).** Real negation is broader. - **Density is a novelty proxy, not compression.** Real density needs a language model. This is the cheap version. - **Short claims that introduce new vocabulary score high on novelty.** A one-word claim ("Analysts agree") can outscore a longer one on density even when the longer one is intuitively load-bearing. - **The flip set is a set, not a sequence.** Every edge in the cut must be severed *simultaneously*. Severing any strict subset does not flip the conclusion. - **Conclusion detection can fail on texts without an explicit conclusion.** The model falls back to the last sentence and returns something regardless. ## Reference Part of the reader-model series. Companion to `hv-tempo` (pace variation), `hv-ttu` (total comprehension time), and `hv-locality` (feature-map locality). `hv-tempo` answers *where will the reader slow down?* `hv-core` answers *what is the minimal structural change that would invalidate this argument?* ## License Apache-2.0