from __future__ import annotations SYMPTOM_KEYWORDS: dict[str, list[str]] = { # ── VATA SYMPTOMS ─────────────────────────────────────────────────── "trunk_bent": [ "trunk bent", "bent trunk", "curved trunk", "twisted stem", "crooked trunk", "leaning trunk", ], "knots_on_trunk": [ "knots", "knotted", "knots on trunk", "knots on leaves", "nodules", "galls", "swellings on bark", ], "hard_fruits": [ "hard fruit", "hard fruits", "less juicy", "dry fruit", "no juice", "tasteless fruit", "woody fruit", ], "slow_defoliation": [ "slow defoliation", "leaves not falling", "leaves clinging", "slow leaf drop", "delayed leaf shed", ], "flower_fruit_loss": [ "loss of flowers", "loss of fruits", "fruit drop", "flower drop", "dropping fruit", "flowers falling", "fruits falling", "premature fruit drop", "fruit loss", "flower loss", ], "general_yellowing": [ "yellowing", "yellow leaves", "yellowing of leaves", "yellowing of fruits", "pale leaves", "chlorosis", "leaves turning yellow", "yellow fruit", ], # ── KAPHA SYMPTOMS ────────────────────────────────────────────────── "delayed_fruiting": [ "delayed fruiting", "fruit bearing delayed", "no fruit", "not fruiting", "late fruiting", "delayed bearing", "tree not producing", ], "bland_overripe_fruits": [ "bland fruit", "bland and overripe", "overripe", "tasteless", "flat taste", "no flavour", "watery fruit", ], "oozing_without_injury": [ "oozing", "oozing without injury", "seeping", "gummosis", "sap oozing", "resin oozing", "spontaneous discharge", "leaking sap", ], # ── PITTA SYMPTOMS ────────────────────────────────────────────────── "early_leaf_withering": [ "early withering", "withering early", "leaf withering", "premature withering", "withering", "wilting", "early wilting", "leaves dying early", "withered leaves", ], "early_fruit_flower_decay": [ "early decay", "fruit decay", "flower decay", "blossom blight", "rotting flowers", "rotting fruits", "premature decay", "fruit rot", "flower rot", "decaying", "decay", "decaying prematurely", ], # ── EXTERNAL HEAT / FROST SYMPTOMS ────────────────────────────────── "vata_like_symptoms": [ "vata-like", "vata like symptoms", "vata symptoms", "yellowing and drying", "general decline", "drying and yellowing", ], # ── WIND DAMAGE SYMPTOMS ───────────────────────────────────────────── "tree_uprooting": [ "uprooted", "tree uprooting", "fell", "fallen tree", "roots exposed", "tree fell over", "uprooted tree", ], "branch_breaking": [ "branch breaking", "broken branch", "branches broken", "limbs broken", "snapped branch", "broken limb", ], "tree_twisting": [ "tree twisting", "twisted tree", "twisted trunk", "trunk twisted", "torqued", ], # ── FIRE / DROUGHT / LIGHTNING SYMPTOMS ────────────────────────────── "tree_drying": [ "drying", "tree drying", "drying up", "dried out", "desiccation", "tree dried", "branches drying", "completely dry", ], "lightning_strike": [ "lightning", "struck by lightning", "lightning strike", "thunder damage", "lightning damage", ], # ── MECHANICAL WOUND SYMPTOMS ───────────────────────────────────────── "tree_wounds": [ "wound", "wounded", "axe wound", "cut", "gash", "mechanical damage", "tool damage", "injured bark", "cut with axe", "bark cut", ], # ── FAULTY SEED SYMPTOMS ────────────────────────────────────────────── "tree_unproductive": [ "unproductive", "not bearing", "no yield", "barren tree", "tree not growing", "no produce", "stunted from seed", "failed to grow", ], # ── INSECT / ANT INFESTATION SYMPTOMS ───────────────────────────────── "foul_smell": [ "foul smell", "bad smell", "smell", "odour", "unpleasant odour", "rotten smell", ], "fragrance_loss": [ "fragrance missing", "fragrance lost", "no fragrance", "original fragrance missing", "lost scent", "fragrance is missing", "fragrance", ], "reduced_leaf_size": [ "reduced leaf size", "smaller leaves", "small leaves", "leaf size reduction", "tiny leaves", "reduced in size", "leaves are reduced", ], "stunted_seedlings": [ "stunted seedlings", "seedling stunted", "seedling not growing", "slow seedling", "weak seedling", ], # ── EXCESSIVE WATERING SYMPTOMS ─────────────────────────────────────── "tree_indigestion": [ "indigestion", "tree indigestion", "waterlogged", "soggy roots", "root suffocation", "over watered", "overwatered", "root rot from water", ], "tree_destruction": [ "destruction", "tree destruction", "deteriorating", "collapsing", "decaying rapidly", "dying from water", ], # ── SEASONAL CONTEXT ────────────────────────────────────────────────── "winter_spring_season": [ "winter", "spring", "cold season", "cool season", "winter season", "spring season", ], "end_of_summer": [ "end of summer", "late summer", "summer end", "post summer", "end of hot season", ], } def extract_facts( user_query: str, expanded_queries: list[str], retrieved_chunks: list[str], ) -> set[str]: """ Extract atomic Vrikshayurveda facts from all text sources. Steps: 1. Combine user_query + expanded_queries + retrieved_chunks into a single lowercase string. 2. For each (fact, keywords) entry in SYMPTOM_KEYWORDS, check if ANY keyword appears in the combined text. 3. Return the set of matched fact strings. """ combined = " ".join( [user_query] + expanded_queries + retrieved_chunks ).lower() facts: set[str] = set() for fact, keywords in SYMPTOM_KEYWORDS.items(): if any(kw in combined for kw in keywords): facts.add(fact) return facts