SahilGoel commited on
Commit
19cd60d
·
verified ·
1 Parent(s): 32dfc35

Upload code/company_inference.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. code/company_inference.py +114 -0
code/company_inference.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Conservative company-name labels for transaction model training."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from typing import Optional
7
+
8
+ from pipeline.merchant_classifier import (
9
+ CURATED_TRANSACTION_MARKERS,
10
+ HANDLE_CATEGORY_MAP,
11
+ MERCHANT_ALIASES,
12
+ classify_upi_merchant,
13
+ extract_upi_handle,
14
+ get_merchant,
15
+ )
16
+
17
+ _PERSONAL_CATEGORIES = {
18
+ "personal_transfer",
19
+ "friends",
20
+ "family",
21
+ "staff_salary",
22
+ "rental",
23
+ "transfer",
24
+ "cash_withdrawal",
25
+ }
26
+ _GENERIC_NAMES = {
27
+ "",
28
+ "unknown upi counterparty",
29
+ "upi transfer",
30
+ "payment",
31
+ "transfer",
32
+ "unknown",
33
+ }
34
+
35
+
36
+ def _name_key(value: object) -> str:
37
+ return " ".join(re.sub(r"[^a-z0-9]+", " ", str(value or "").lower()).split())
38
+
39
+
40
+ _CANONICAL_COMPANIES = {
41
+ _name_key(company[0]): company[0]
42
+ for company in (
43
+ *MERCHANT_ALIASES.values(),
44
+ *CURATED_TRANSACTION_MARKERS.values(),
45
+ *HANDLE_CATEGORY_MAP.values(),
46
+ )
47
+ }
48
+ _CANONICAL_ALIASES = {
49
+ "indian cle": "Indian Clearing Corporation",
50
+ "iccl zerodha credit": "Indian Clearing Corporation",
51
+ "iccl zerod": "Indian Clearing Corporation",
52
+ "zerodha br": "Zerodha",
53
+ "zerodha deposit": "Zerodha",
54
+ }
55
+
56
+
57
+ def _clean_company_name(value: object) -> Optional[str]:
58
+ name = " ".join(str(value or "").split()).strip(" -/|")[:100]
59
+ if name.lower() in _GENERIC_NAMES:
60
+ return None
61
+ return name or None
62
+
63
+
64
+ def _canonical_company_name(value: object) -> Optional[str]:
65
+ cleaned = _clean_company_name(value)
66
+ if not cleaned:
67
+ return None
68
+ key = _name_key(cleaned)
69
+ if key.startswith("cred ") or key == "cred":
70
+ return "CRED"
71
+ return _CANONICAL_ALIASES.get(key) or _CANONICAL_COMPANIES.get(key)
72
+
73
+
74
+ def infer_company_name(
75
+ description: str,
76
+ *,
77
+ category: str = "",
78
+ explicit_name: object = None,
79
+ ) -> Optional[str]:
80
+ """Return a company only when merchant evidence is strong enough to label."""
81
+ if category in _PERSONAL_CATEGORIES:
82
+ return None
83
+
84
+ explicit = _canonical_company_name(explicit_name)
85
+ if explicit:
86
+ return explicit
87
+
88
+ handle = extract_upi_handle(description or "")
89
+ if handle:
90
+ try:
91
+ merchant = get_merchant(handle)
92
+ except Exception:
93
+ merchant = None
94
+ if (
95
+ merchant
96
+ and merchant.get("category") not in _PERSONAL_CATEGORIES | {"unclassified", "upi_spend"}
97
+ and float(merchant.get("confidence", 0.0)) >= 0.70
98
+ ):
99
+ company = _canonical_company_name(merchant.get("display_name"))
100
+ if company:
101
+ return company
102
+
103
+ try:
104
+ evidence_description = "" if handle else (description or "")
105
+ inferred = classify_upi_merchant(handle or "", evidence_description, learn=False)
106
+ except Exception:
107
+ return None
108
+
109
+ if (
110
+ inferred.get("category") in _PERSONAL_CATEGORIES | {"unclassified"}
111
+ or float(inferred.get("confidence", 0.0)) < 0.70
112
+ ):
113
+ return None
114
+ return _canonical_company_name(inferred.get("display_name"))