Download backend/entity_resolver.py from Sanjam19/FinSight: direct link, hf CLI and curl.
- Browser
- Download file 4.56 kB
-
https://huggingface.co/spaces/Sanjam19/FinSight/resolve/main/backend/entity_resolver.py
- Command line
-
hf download hf://spaces/Sanjam19/FinSight/backend/entity_resolver.py
-
curl -L -o entity_resolver.py https://huggingface.co/spaces/Sanjam19/FinSight/resolve/main/backend/entity_resolver.py
4.56 kB
| # backend/entity_resolver.py | |
| import re | |
| from rapidfuzz import fuzz | |
| LEGAL_SUFFIXES = [ | |
| "incorporated", "corporation", "limited", "inc", "ltd", "llc", "corp", | |
| "co", "plc", "company", "industries", "group", "holdings" | |
| ] | |
| KNOWN_ALIASES = { | |
| "apple": "Apple", "aapl": "Apple", "apple inc": "Apple", | |
| "microsoft": "Microsoft", "msft": "Microsoft", | |
| "amazon": "Amazon", "amzn": "Amazon", "amazoncom": "Amazon", | |
| "google": "Google", "alphabet": "Google", "googl": "Google", | |
| "tesla": "Tesla", "tsla": "Tesla", | |
| "3m": "3M", | |
| "boeing": "Boeing", "the boeing company": "Boeing", | |
| "amd": "AMD", "advanced micro devices": "AMD", | |
| "hdfc bank": "HDFC Bank", "hdfc": "HDFC Bank", | |
| "tcs": "TCS", "tata consultancy services": "TCS", | |
| "infosys": "Infosys", "infy": "Infosys", | |
| "reliance": "Reliance Industries", "reliance industries": "Reliance Industries", "ril": "Reliance Industries", | |
| "icici bank": "ICICI Bank", "icici": "ICICI Bank", | |
| "wipro": "Wipro", | |
| "hul": "Hindustan Unilever", "hindustan unilever": "Hindustan Unilever", | |
| "itc": "ITC", | |
| "l&t": "Larsen & Toubro", "larsen & toubro": "Larsen & Toubro", "larsen and toubro": "Larsen & Toubro", | |
| "bajaj finance": "Bajaj Finance", | |
| "tata motors": "Tata Motors", | |
| "maruti": "Maruti Suzuki", "maruti suzuki": "Maruti Suzuki", | |
| "asian paints": "Asian Paints", | |
| "sun pharma": "Sun Pharma", "sun pharmaceutical": "Sun Pharma", | |
| "axis bank": "Axis Bank", | |
| "kotak": "Kotak Mahindra Bank", "kotak mahindra bank": "Kotak Mahindra Bank", | |
| "titan": "Titan Company", | |
| "nestle": "Nestle India", "nestle india": "Nestle India", | |
| "ultratech": "UltraTech Cement", "ultratech cement": "UltraTech Cement", | |
| "sbi": "State Bank of India", "state bank of india": "State Bank of India", | |
| } | |
| def normalize_org_name(text: str) -> str: | |
| t = text.lower().strip() | |
| t = re.sub(r"[^\w\s&]", "", t) | |
| words = t.split() | |
| while words and words[-1] in LEGAL_SUFFIXES: | |
| words.pop() | |
| return " ".join(words).strip() | |
| def resolve_entity(text: str, label: str, existing_orgs: list = None) -> str: | |
| """Returns canonical entity ID for graph node deduplication.""" | |
| if label != "ORG": | |
| clean = re.sub(r"\s+", " ", text.strip()) | |
| return f"{label}_{clean[:50]}" | |
| normalized = normalize_org_name(text) | |
| if normalized in KNOWN_ALIASES: | |
| return f"ORG_{KNOWN_ALIASES[normalized]}" | |
| if existing_orgs: | |
| best_match, best_score = None, 0 | |
| for existing in existing_orgs: | |
| score = fuzz.token_sort_ratio(normalized, existing.lower()) | |
| if score > best_score: | |
| best_score, best_match = score, existing | |
| if best_score >= 85: | |
| return f"ORG_{best_match}" | |
| return f"ORG_{normalized.title()}" | |
| def format_money(value: float, currency: str = "USD") -> str: | |
| """Format a raw monetary value for display, currency-aware. | |
| Takes an explicit `currency` ("INR" or "USD") rather than guessing | |
| from the company name — guessing is unreliable (the same product | |
| handles both US and Indian filings, and even Indian companies | |
| sometimes report figures in USD). Callers should pass the | |
| `currency` tag that metrics_extractor.py now attaches to each | |
| extracted metric, e.g.: | |
| formatted = format_money(raw["value"], raw.get("currency", "USD")) | |
| INR values are shown in crore (and lakh crore for very large | |
| figures) since that's the unit Indian filings and their readers | |
| actually think in — converting to USD billions would require an | |
| exchange-rate assumption that goes stale and adds a layer of | |
| unnecessary approximation on top of an already-extracted figure. | |
| """ | |
| if value is None: | |
| return "N/A" | |
| if currency == "INR": | |
| crore = value / 1_00_00_000 # 1 crore = 10,000,000 | |
| if abs(crore) >= 1_00_000: # >= 1 lakh crore | |
| return f"₹{crore / 1_00_000:.2f} Lakh Cr" | |
| return f"₹{crore:,.1f} Cr" | |
| # USD (default) | |
| if abs(value) >= 1_000_000_000: | |
| return f"${value / 1_000_000_000:.1f}B" | |
| if abs(value) >= 1_000_000: | |
| return f"${value / 1_000_000:.1f}M" | |
| return f"${value:,.2f}" | |
| if __name__ == "__main__": | |
| existing = ["Apple", "HDFC Bank", "3M"] | |
| tests = [ | |
| ("Apple Inc.", "ORG"), ("Apple", "ORG"), ("AAPL", "ORG"), | |
| ("HDFC Bank Limited", "ORG"), ("3M Company", "ORG"), | |
| ("$394.3 billion", "MONEY"), | |
| ] | |
| for text, label in tests: | |
| print(f"{text!r} ({label}) -> {resolve_entity(text, label, existing)}") | |