gkdivya commited on
Commit
2950344
Β·
verified Β·
1 Parent(s): 86eb223

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +114 -151
app.py CHANGED
@@ -1,25 +1,17 @@
1
- # app.py
2
  import os
3
  import pandas as pd
4
  import gradio as gr
5
  from huggingface_hub import hf_hub_download
6
 
7
  # ----------------------------------------------------
8
- # Import search & admin modules
9
  # ----------------------------------------------------
10
  from searchschool import (
11
  DEFAULT_STATE_KEY,
12
- on_search_web,
13
  load_master_for_state,
14
  update_blocks,
15
  search_candidates,
16
- )
17
-
18
- from admin_patterns import (
19
- load_pattern_config,
20
- load_global_patterns_for_editor,
21
- load_state_patterns_for_editor,
22
- save_global_patterns_from_editor,
23
  )
24
 
25
  # ----------------------------------------------------
@@ -29,15 +21,12 @@ HF_SCHOOLS_DATASET = "Apf-AI4Good/Schools"
29
  MASTER_ALL_STATES_FILE = "master_all_states.csv"
30
  MASTER_STATE_COL = "School_State__c"
31
 
32
- # ----------------------------------------------------
33
- # Load ADMIN password
34
- # ----------------------------------------------------
35
  ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", None)
36
  if not ADMIN_PASSWORD:
37
- print("⚠ ADMIN_PASSWORD environment variable not set.")
38
 
39
  # ----------------------------------------------------
40
- # πŸ”Ή LOAD STATE LIST ONCE (APP STARTUP)
41
  # ----------------------------------------------------
42
  def load_state_choices_once():
43
  path = hf_hub_download(
@@ -45,118 +34,132 @@ def load_state_choices_once():
45
  repo_type="dataset",
46
  filename=MASTER_ALL_STATES_FILE,
47
  )
48
-
49
  df = pd.read_csv(path, dtype=str)
 
50
 
51
- states = (
52
- df[MASTER_STATE_COL]
53
- .dropna()
54
- .str.upper()
55
- .unique()
56
- .tolist()
57
- )
58
 
59
- return sorted(states)
 
 
 
 
 
 
 
 
 
 
 
60
 
61
 
62
- STATE_CHOICES = load_state_choices_once()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
  # ----------------------------------------------------
65
  # Gradio App
66
  # ----------------------------------------------------
67
- with gr.Blocks(title="State School Fuzzy Matcher (with gated Admin)") as demo:
68
  gr.Markdown(
69
  """
70
  # State School Fuzzy Matcher (RapidFuzz)
71
 
72
- - Public: Search tab
73
- - Admin: Patterns editor (password protected)
 
74
  """
75
  )
76
 
77
- # ================= SEARCH TAB =================
78
- with gr.Tab("Search"):
79
- with gr.Row():
80
- state_dd = gr.Dropdown(
81
- label="State",
82
- choices=STATE_CHOICES,
83
- value=DEFAULT_STATE_KEY if DEFAULT_STATE_KEY in STATE_CHOICES else None,
84
- interactive=True,
85
- )
86
-
87
- with gr.Row():
88
- district_dd = gr.Dropdown(label="District", choices=[], value=None, interactive=True)
89
- block_dd = gr.Dropdown(label="Block", choices=[], value=None, interactive=True)
90
-
91
- school_input = gr.Textbox(
92
- label="Input School Name",
93
- placeholder="Type school name from marksheet..."
94
- )
95
-
96
- search_btn = gr.Button("Find Candidates")
97
-
98
- gr.Markdown("### Candidates (top matches)")
99
- candidates_table = gr.Dataframe(
100
- headers=["School_Name", "State", "District", "Block", "UDISE_Code", "Score"],
101
- datatype=["str", "str", "str", "str", "str", "number"],
102
- interactive=False,
103
  )
104
 
105
- gr.Markdown("### Best Candidate")
106
- best_table = gr.Dataframe(
107
- headers=["School_Name", "State", "District", "Block", "UDISE_Code", "Score"],
108
- datatype=["str", "str", "str", "str", "str", "number"],
109
- interactive=False,
110
- )
111
-
112
- # ================= ADMIN TAB =================
113
- with gr.Tab("Admin"):
114
- gr.Markdown("### Admin β€” Patterns Editor")
115
 
116
- unlock_pwd = gr.Textbox(
117
- label="Admin Password",
118
- type="password",
119
- placeholder="Enter admin password and click Unlock",
120
- )
121
- unlock_btn = gr.Button("Unlock Admin Panel")
122
- unlock_status = gr.Markdown("")
123
-
124
- admin_panel = gr.Column(visible=False)
125
-
126
- with admin_panel:
127
- global_df = gr.Dataframe(
128
- value=load_global_patterns_for_editor(),
129
- headers=["pattern", "replacement"],
130
- datatype=["str", "str"],
131
- interactive=True,
132
- row_count=5,
133
- )
134
 
135
- save_global_btn = gr.Button("πŸ’Ύ Save Global Patterns")
136
- global_status = gr.Markdown("")
137
 
138
- existing_state_keys = sorted(load_pattern_config().get("states", {}).keys())
 
 
139
 
140
- with gr.Row():
141
- state_pattern_dd = gr.Dropdown(
142
- label="Existing state key",
143
- choices=existing_state_keys,
144
- value=existing_state_keys[0] if existing_state_keys else None,
145
- )
146
- new_state_tb = gr.Textbox(
147
- label="Or type new state key",
148
- placeholder="e.g. KARNATAKA",
149
- )
150
 
151
- state_df = gr.Dataframe(
152
- value=pd.DataFrame(columns=["pattern", "replacement"]),
153
- headers=["pattern", "replacement"],
154
- datatype=["str", "str"],
155
- interactive=True,
156
- row_count=3,
157
- )
158
 
159
- load_state_btn = gr.Button("Load patterns for selected / new state")
 
160
 
161
  # ================= Wiring =================
162
  state_dd.change(
@@ -165,12 +168,6 @@ with gr.Blocks(title="State School Fuzzy Matcher (with gated Admin)") as demo:
165
  outputs=[district_dd, block_dd],
166
  )
167
 
168
- demo.load(
169
- fn=load_master_for_state,
170
- inputs=state_dd,
171
- outputs=[district_dd, block_dd],
172
- )
173
-
174
  district_dd.change(
175
  fn=update_blocks,
176
  inputs=district_dd,
@@ -178,56 +175,22 @@ with gr.Blocks(title="State School Fuzzy Matcher (with gated Admin)") as demo:
178
  )
179
 
180
  search_btn.click(
181
- fn=search_candidates,
182
- inputs=[school_input, state_dd, district_dd, block_dd],
183
- outputs=[candidates_table, best_table],
184
- )
185
-
186
- # ensure at top of file you have: from web_search import tavily_search
187
-
188
- # --- inside Search tab UI, after search_btn etc. ---
189
- gr.Markdown("### Web search β€” find UDISE codes on the web")
190
- gr.Markdown("### Use Judiciously - Only if you didnt find or couldnt confirm the school in the above list")
191
- search_web_btn = gr.Button("Search Web")
192
-
193
- web_schools_table = gr.Dataframe(
194
- headers=["School_Name", "State", "District", "Block", "UDISE_Code"],
195
- datatype=["str", "str", "str", "str", "str"],
196
- interactive=False
197
- )
198
-
199
- search_web_btn.click(
200
- fn=on_search_web,
201
  inputs=[school_input, state_dd, district_dd, block_dd],
202
- outputs=[web_schools_table]
203
  )
204
 
205
- # ---------------- Admin gating ----------------
206
- def try_unlock(pwd: str):
207
- if ADMIN_PASSWORD is None:
208
- return gr.update(visible=False), "❌ ADMIN_PASSWORD not configured", None
209
- if pwd == ADMIN_PASSWORD:
210
- return gr.update(visible=True), "πŸ”“ Admin panel unlocked.", True
211
- return gr.update(visible=False), "❌ Wrong password.", False
212
-
213
  unlock_btn.click(
214
- fn=try_unlock,
215
  inputs=unlock_pwd,
216
- outputs=[admin_panel, unlock_status, unlock_pwd],
217
- )
218
-
219
- save_global_btn.click(
220
- fn=lambda df, pwd: save_global_patterns_from_editor(df, pwd, ADMIN_PASSWORD),
221
- inputs=[global_df, unlock_pwd],
222
- outputs=global_status,
223
  )
224
 
225
- load_state_btn.click(
226
- fn=load_state_patterns_for_editor,
227
- inputs=[state_pattern_dd, new_state_tb],
228
- outputs=state_df,
229
  )
230
 
231
-
232
  if __name__ == "__main__":
233
  demo.launch()
 
 
1
  import os
2
  import pandas as pd
3
  import gradio as gr
4
  from huggingface_hub import hf_hub_download
5
 
6
  # ----------------------------------------------------
7
+ # Imports
8
  # ----------------------------------------------------
9
  from searchschool import (
10
  DEFAULT_STATE_KEY,
 
11
  load_master_for_state,
12
  update_blocks,
13
  search_candidates,
14
+ on_search_web,
 
 
 
 
 
 
15
  )
16
 
17
  # ----------------------------------------------------
 
21
  MASTER_ALL_STATES_FILE = "master_all_states.csv"
22
  MASTER_STATE_COL = "School_State__c"
23
 
 
 
 
24
  ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", None)
25
  if not ADMIN_PASSWORD:
26
+ print("⚠ ADMIN_PASSWORD not set")
27
 
28
  # ----------------------------------------------------
29
+ # Load states ONCE
30
  # ----------------------------------------------------
31
  def load_state_choices_once():
32
  path = hf_hub_download(
 
34
  repo_type="dataset",
35
  filename=MASTER_ALL_STATES_FILE,
36
  )
 
37
  df = pd.read_csv(path, dtype=str)
38
+ return sorted(df[MASTER_STATE_COL].dropna().str.upper().unique().tolist())
39
 
40
+ STATE_CHOICES = load_state_choices_once()
 
 
 
 
 
 
41
 
42
+ # ----------------------------------------------------
43
+ # UI RENDER HELPERS
44
+ # ----------------------------------------------------
45
+ def render_header(show_score=True):
46
+ with gr.Row():
47
+ gr.Markdown("**School Name**")
48
+ gr.Markdown("**UDISE Code**")
49
+ gr.Markdown("**State**")
50
+ gr.Markdown("**District**")
51
+ gr.Markdown("**Block**")
52
+ if show_score:
53
+ gr.Markdown("**Score**")
54
 
55
 
56
+ def render_results(rows, show_score=True):
57
+ comps = []
58
+
59
+ if not rows:
60
+ comps.append(gr.Markdown("❌ No results found."))
61
+ return comps
62
+
63
+ render_header(show_score)
64
+
65
+ for r in rows:
66
+ with gr.Row():
67
+ comps.append(
68
+ gr.Textbox(
69
+ r.get("School_Name", ""),
70
+ interactive=False,
71
+ show_copy_button=True,
72
+ container=False,
73
+ )
74
+ )
75
+ comps.append(
76
+ gr.Textbox(
77
+ r.get("UDISE_Code", ""),
78
+ interactive=False,
79
+ show_copy_button=True,
80
+ container=False,
81
+ )
82
+ )
83
+ comps.append(gr.Markdown(r.get("State", "")))
84
+ comps.append(gr.Markdown(r.get("District", "")))
85
+ comps.append(gr.Markdown(r.get("Block", "")))
86
+ if show_score:
87
+ comps.append(gr.Markdown(f"{r.get('Score', 0):.2f}"))
88
+
89
+ return comps
90
+
91
+ # ----------------------------------------------------
92
+ # Wrapped search functions
93
+ # ----------------------------------------------------
94
+ def rapid_search_and_render(name, state, district, block):
95
+ candidates, _ = search_candidates(name, state, district, block)
96
+ return render_results(candidates, show_score=True)
97
+
98
+ def web_search_and_render(name, state, district, block):
99
+ results = on_search_web(name, state, district, block)
100
+ return render_results(results, show_score=False)
101
+
102
+ # ----------------------------------------------------
103
+ # Unlock Web Search
104
+ # ----------------------------------------------------
105
+ def unlock_web_search(pwd):
106
+ if pwd == ADMIN_PASSWORD:
107
+ return gr.update(interactive=True), "πŸ”“ Web search unlocked."
108
+ return gr.update(interactive=False), "❌ Invalid password."
109
 
110
  # ----------------------------------------------------
111
  # Gradio App
112
  # ----------------------------------------------------
113
+ with gr.Blocks(title="State School Fuzzy Matcher") as demo:
114
  gr.Markdown(
115
  """
116
  # State School Fuzzy Matcher (RapidFuzz)
117
 
118
+ **Flow**
119
+ 1. Use Rapid search first
120
+ 2. Unlock Web search only if required
121
  """
122
  )
123
 
124
+ # ================= SEARCH INPUTS =================
125
+ with gr.Row():
126
+ state_dd = gr.Dropdown(
127
+ label="State",
128
+ choices=STATE_CHOICES,
129
+ value=DEFAULT_STATE_KEY if DEFAULT_STATE_KEY in STATE_CHOICES else None,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  )
131
 
132
+ with gr.Row():
133
+ district_dd = gr.Dropdown(label="District", interactive=True)
134
+ block_dd = gr.Dropdown(label="Block", interactive=True)
 
 
 
 
 
 
 
135
 
136
+ school_input = gr.Textbox(
137
+ label="School Name",
138
+ placeholder="Enter school name from marksheet",
139
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
+ search_btn = gr.Button("πŸ” Find Candidates")
 
142
 
143
+ # ================= RAPID RESULTS =================
144
+ gr.Markdown("### πŸ”Ž Rapid Search Results")
145
+ rapid_results_container = gr.Column()
146
 
147
+ # ================= WEB SEARCH =================
148
+ gr.Markdown("### 🌐 Web Search (Locked)")
149
+ gr.Markdown(
150
+ "Use only if Rapid search does not give a confident match."
151
+ )
 
 
 
 
 
152
 
153
+ unlock_pwd = gr.Textbox(
154
+ label="Admin Password",
155
+ type="password",
156
+ placeholder="Enter password to unlock web search",
157
+ )
158
+ unlock_btn = gr.Button("Unlock Web Search")
159
+ web_status = gr.Markdown("")
160
 
161
+ search_web_btn = gr.Button("Search Web", interactive=False)
162
+ web_results_container = gr.Column()
163
 
164
  # ================= Wiring =================
165
  state_dd.change(
 
168
  outputs=[district_dd, block_dd],
169
  )
170
 
 
 
 
 
 
 
171
  district_dd.change(
172
  fn=update_blocks,
173
  inputs=district_dd,
 
175
  )
176
 
177
  search_btn.click(
178
+ fn=rapid_search_and_render,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  inputs=[school_input, state_dd, district_dd, block_dd],
180
+ outputs=rapid_results_container,
181
  )
182
 
 
 
 
 
 
 
 
 
183
  unlock_btn.click(
184
+ fn=unlock_web_search,
185
  inputs=unlock_pwd,
186
+ outputs=[search_web_btn, web_status],
 
 
 
 
 
 
187
  )
188
 
189
+ search_web_btn.click(
190
+ fn=web_search_and_render,
191
+ inputs=[school_input, state_dd, district_dd, block_dd],
192
+ outputs=web_results_container,
193
  )
194
 
 
195
  if __name__ == "__main__":
196
  demo.launch()