cascade_risk / knowledge /expert_extraction.md
Lucasoppem's picture
Sync from GitHub main (part 2)
36f9d47 verified
|
Raw
History Blame Contribute Delete
12.9 kB
<!--
Maintainer notes β€” keep consistent or the pipeline drifts:
- This file is the SOURCE OF TRUTH for:
(1) Closed Domain Taxonomy (12 labels, see Β§Closed Domain Taxonomy)
(2) Quantitative severity thresholds (see Β§Severity Scale)
(3) 2-week time window (see Β§Time Offset Buckets)
(4) DAG edge semantics (see Β§DAG Edge Semantics β€” v0.2 issue #9 / B')
- When you edit any of the above, also update:
- src/data/cascade_extractor.py::ALLOWED_DOMAINS,
DOMAIN_REMAP, MAX_TIME_OFFSET_HOURS (code-level enforcement)
- prompts/extract_cascade.txt (the 40-node / 2-week / 12-domain lines + DAG rules)
- knowledge/expert_predict.md Β§Scope Alignment with Extraction
(must cite the same taxonomy & severity rubric so RAG matches)
- prompts/predict_iterative.txt (BFS anchor logic mirrors Rule 1 / Rule 2)
- For extensions (new disaster types, new regions, non-European data)
see technical_report/data_pipeline/cascade_extraction_report.md Β§6.5.3.
-->
# Expert Knowledge: Cascade Chain Extraction Rules
## Scope & Budget
The downstream task is **predicting major cascade risks** for new flood events. Capture the full cascade structure β€” every consequence the news articles report as a notable downstream effect should appear as a node.
- **Grounding (hard rule).** Every node MUST correspond to a specific consequence that is *literally stated* in the input articles β€” named places, named infrastructure, reported numbers, named institutions, named programs. Do NOT add a node because "this typically follows a flood"; only add a node if the articles report it. Hallucinated nodes pollute the dataset and are worse than missing ones.
- **Sparse-input rule.** If the articles are too thin to support extraction (e.g. only a headline confirming a flood occurred, with no specific consequences), it is *correct* to return very few nodes (0–3). Empty `cascade_events: []` is acceptable when no concrete consequences are reported. Do NOT pad to hit a target.
- **Maximum 40 cascade nodes per event.** If the articles describe more than 40 distinct effects, keep only the most consequential.
- **Target density (only for events with rich news coverage):** 12–25 nodes when the articles together provide multiple paragraphs of concrete consequences across several sources. Producing fewer than ~8 from such rich coverage is a strong signal you are being too restrictive β€” re-audit. **Do not apply the density target to thin-input events** (single short article, one-liner headline) β€” there, sparse output is correct output.
- **Time window: 2 weeks (336 hours after flood onset).** Anything later β€” long-term reconstruction, insurance settlements, multi-month mental-health impacts β€” is out of scope.
- **What counts as a node.** A node is worth recording if it meets AT LEAST ONE of:
- Reported casualties (deaths, missing, serious injuries β€” even one person)
- People evacuated, displaced, sheltered, or without essential services (any reported number)
- A service disruption (power, water, transport, telecom, hospital) lasting more than a couple of hours, or affecting a named population/area
- Quantified or qualitatively-described economic damage (property, inventory, agricultural, business closure)
- Named infrastructure damage (substation, bridge, treatment plant, hospital wing, school, etc.)
- Government / institutional response (state of emergency declaration, school closures, evacuation orders, military deployment, international aid request)
- Environmental contamination or chemical spill events
- Triggers a further cascade in a different domain (e.g. power loss β†’ hospital crisis)
- **What to skip.** One-street road closure that resolved within an hour and didn't disrupt anyone, brief individual panic anecdotes without broader effect, social-media noise, single-business minor inventory issues. The bar is "did this affect a named population, named infrastructure, or quantifiable damage?" β€” if yes, include it; if no, skip it.
If the news mentions distinct effects in different communes / municipalities / domains, prefer to keep them as separate nodes rather than merging into a generic "widespread X" β€” separate nodes carry more predictive signal.
## Closed Domain Taxonomy (pick EXACTLY one per node)
You MUST use one of these 12 labels. Do not invent new ones.
- `infrastructure/power` β€” electricity grid outages, substation damage, generator failure
- `infrastructure/water` β€” drinking water supply, wastewater, sewage overflow
- `infrastructure/transport` β€” roads, rail, airports, ports, bridges
- `infrastructure/communication` β€” telecom, internet, cellular, emergency radio
- `health/casualties` β€” deaths, missing persons, serious injuries
- `health/hospital_service` β€” hospital operations, ICU capacity, medical supply, evacuation of patients
- `health/disease_outbreak` β€” waterborne disease, infection clusters, epidemic risk
- `social/evacuation` β€” mandatory or advised evacuation, displacement, emergency sheltering, housing loss
- `social/supply_shortage` β€” food, fuel, medicine, essentials unavailable in affected zone
- `economy/business_damage` β€” business property / inventory / revenue losses, closures
- `economy/agriculture` β€” crop loss, livestock losses, farmland inundation
- `environment/contamination` β€” chemical spills, polluted water bodies, soil contamination
## Severity Scale (use quantitative thresholds)
- **critical** β€” deaths reported, national-level emergency response, > 100 000 people affected, or multi-region infrastructure collapse
- **high** β€” thousands evacuated, regional state-of-emergency, multi-day outages in essential services, > 10 000 people affected
- **medium** β€” hundreds to low-thousands affected, single-day service disruption, localized damage
- **low** β€” transient, small-scale, not a "major impact" by definition above β†’ usually should not appear at all. Only use `low` when the cascade is structurally important (e.g. a parent for a higher-severity child) but otherwise minor.
## Time Offset Buckets (hours after flood onset)
- **0–6 h**: infrastructure damage, first road closures, initial evacuations, immediate casualties
- **6–48 h**: power / comms outages, hospital stress, water supply failure
- **2–7 days**: disease onset, prolonged evacuation, business closure, agricultural losses
- **1–2 weeks**: secondary health impacts, economic assessment, environmental damage detection
- **> 2 weeks**: OUT OF SCOPE β€” do not create nodes here
## DAG Edge Semantics (v0.2 issue #9 / B', tuned in issue #10)
`parent_ids` encodes **causal structure** — what in this chain caused this effect to happen the way you described it. The DAG must capture cause→effect dependency, not just be a flat list of impacts.
### Default behavior: link by default
Walk through every cascade event you've identified and ask:
> "What in this chain caused this effect to happen the way I described it?"
- If the answer is "the flood itself, directly" β†’ `parent_ids: []` (root).
- If the answer names another node already in your list β†’ `parent_ids: ["<that-node-id>"]`. **This is the common case for non-first-order events.**
- If two distinct nodes are *jointly necessary* (per the ablation test below) β†’ `parent_ids: ["E2", "E5"]`.
**Anti-pattern β€” flat DAG.** A chain where almost every node has `parent_ids: []` is almost always wrong. Schools closing, emergency declarations, supply shortages, business closures, evacuations to shelters, hospital strain, international aid requests β€” these are downstream effects, not direct flood-triggered ones. They should chain to the relevant prior node (transport blocked, infrastructure damaged, casualties reported, etc.). If your output has more than ~25% of nodes with empty `parent_ids`, audit again β€” most of those nodes probably have a real upstream cause inside your chain that you missed.
### Cardinality
- **0 parents** β€” root: direct flood-triggered effect (physical inundation, immediate building damage, immediate drowning casualties, primary substation flooding, road submergence).
- **1 parent** β€” single sufficient cause; *the common case for downstream effects*. School closures (cause = damage), hospital strain (cause = power loss), supply shortages (cause = transport blocked), emergency declarations (cause = casualties or service collapse).
- **β‰₯ 2 parents** β€” AND-conjunction; rare. Use ONLY when each listed parent passes the ablation test below.
### Multi-parent rules (apply ONLY when listing 2+ parents)
These rules govern the *second and later* parents. The first parent β€” the most-direct cause β€” is the default chain link and does not need to pass an ablation test by itself; it just needs to actually be the cause.
**Rule 1 β€” Ablation test (multi-parent only).** Before listing a SECOND or later parent P, ask:
> If I remove P, would this child still occur with the same description, severity, and timing?
- **YES** β†’ P is contextual or amplifying. DO NOT list it; use a single parent.
- **NO** β†’ P is jointly necessary. List it.
**Rule 2 β€” No-grandparent.** Do not list P if P is already an ancestor of another listed parent. List the most-direct cause only; transitive ancestors are recoverable by walking the graph.
### Worked examples
Single-parent (common):
- Flood inundates an area E1 (root). Schools close because the buildings are unsafe β†’ `E2.parent_ids = ["E1"]`.
- Roads blocked E3 β†’ public transport suspended E4 β†’ `E4.parent_ids = ["E3"]`.
- 9 deaths from flash floods E1 (root) β†’ national emergency declared E5 β†’ `E5.parent_ids = ["E1"]`.
- Power outage to 42K homes E2 β†’ hospital forced onto generators E6 β†’ `E6.parent_ids = ["E2"]`.
Single-parent with no-grandparent rule:
- Flood E_root β†’ substation damage E5 β†’ power outage E6.
- WRONG: `E6.parent_ids = ["E5", "E_root"]` (E_root is grandparent via E5 β†’ violates Rule 2)
- RIGHT: `E6.parent_ids = ["E5"]`
Multi-parent (rare, ablation-justified):
- Transport disruption E9 + flood inundation E7 β†’ mass displacement E10. Without E9 people would self-evacuate (so smaller scale, not "mass"); without E7 there is nothing to evacuate from. Both pass ablation; neither is ancestor of the other β†’ `E10.parent_ids = ["E9", "E7"]`.
### Anti-patterns (do NOT repeat)
- **Flat DAG** β€” emitting many events all with `parent_ids: []` because the LLM was unsure whether to chain. Default to chaining downstream effects to their causes; only `[]` for events caused directly by the flood physically.
- Listing the macro flood event AND a specific damage as parents of a downstream impact (the macro is a grandparent β†’ drop it).
- Listing every prior infrastructure failure as parent of a long-tail social/economic impact (most are grandparents or contextual; pick the one direct cause).
- Using `parent_ids` to encode "these nodes are related" rather than "these nodes are causal parents".
### Cross-domain preference
Prefer cross-domain edges (power β†’ hospital, transport β†’ supply) over intra-domain edges β€” they carry more predictive signal. The ablation + no-grandparent rules still apply to multi-parent declarations; they do not gate single-parent linking.
## Deduplication Rules (apply BEFORE emitting)
Before finalizing the JSON, merge cascade events that describe the same phenomenon in different words:
- **Same domain + same affected population / mechanism β†’ one node.** E.g. "Mass displacement of residents" and "Displacement due to unsafe living conditions" under `social/evacuation` β†’ merge.
- When merging, keep the most specific description, combine quantitative facts ("371 evacuated" + "189 municipalities" β†’ "371 evacuated across 189 municipalities"), and pick the higher severity.
- For the merged parent set: take the union of all clusters' parents, then re-apply Rule 2 (drop any parent that is now an ancestor of another listed parent within the merged graph). Do NOT keep raw unions β€” the union of two correctly-pruned sets can introduce new grandparent violations after structural merging.
- If two nodes differ only by time offset, keep the earlier time and mention duration in the description.
## Extraction Guidelines
- Explain the **mechanism** for each cascade link (HOW the parent(s) caused this effect), not just that it did. For multi-parent nodes, explicitly justify why each parent is jointly necessary.
- Anchor descriptions in concrete facts from the articles (numbers, place names, named infrastructure). Avoid generic phrasing like "economic losses occurred".
- If articles disagree on numbers, use the latest-dated article's figure.
- Leave `time_offset_hours` null if no article indicates timing; don't guess.
- Cross-domain transitions are the highest-value outputs β€” prioritize extracting them within the 40-node budget.