gkdivya commited on
Commit
0cad454
·
verified ·
1 Parent(s): da8436c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -40
app.py CHANGED
@@ -1,8 +1,9 @@
 
 
 
1
  import gradio as gr
2
  import requests
3
- import json
4
  import pandas as pd
5
- from difflib import get_close_matches
6
 
7
  KYS_SAMPLE = "https://kys.udiseplus.gov.in/webapp/api/search-schools?searchType=3&searchParam={udise}"
8
 
@@ -23,12 +24,12 @@ def call_tavily(tavily_url, api_key, payload_text):
23
  if api_key:
24
  headers["Authorization"] = api_key
25
  body = {"query": payload_text}
 
26
  try:
27
  resp = requests.post(tavily_url, json=body, headers=headers, timeout=12)
28
  resp.raise_for_status()
29
  return {"ok": True, "url": tavily_url, "status_code": resp.status_code, "data": resp.json()}
30
  except Exception as e:
31
- # fallback to GET
32
  try:
33
  params = {"q": payload_text}
34
  resp = requests.get(tavily_url, params=params, headers=headers, timeout=12)
@@ -39,7 +40,6 @@ def call_tavily(tavily_url, api_key, payload_text):
39
 
40
 
41
  def extract_udise_candidates_from_tavily(tavily_json):
42
- # Heuristic: walk the JSON and collect strings that look like UDISE (digits, length 6-14)
43
  found = set()
44
 
45
  def walk(obj):
@@ -61,20 +61,13 @@ def extract_udise_candidates_from_tavily(tavily_json):
61
 
62
 
63
  def json_to_table(obj):
64
- # Try to convert a JSON object/array to pandas DataFrame for display
65
  try:
66
  if isinstance(obj, list):
67
- df = pd.json_normalize(obj)
68
- return df
69
  if isinstance(obj, dict):
70
- # Often tavily returns {"results": [...]}
71
- if "results" in obj and isinstance(obj["results"], list):
72
- return pd.json_normalize(obj["results"])
73
- # common patterns: top-level list wrapped in data or hits
74
- for k in ("data", "hits", "items", "results"):
75
  if k in obj and isinstance(obj[k], list):
76
  return pd.json_normalize(obj[k])
77
- # fallback: flatten dict to single-row table
78
  return pd.json_normalize([obj])
79
  except Exception:
80
  pass
@@ -88,8 +81,7 @@ def to_table_from_kys(kys_json):
88
  items = items["data"]
89
  if not items:
90
  return pd.DataFrame()
91
- df = pd.json_normalize(items)
92
- return df
93
  except Exception:
94
  return pd.DataFrame()
95
 
@@ -106,7 +98,6 @@ def search_workflow(school_name_or_udise, tavily_url, tavily_key, use_tavily, us
106
  else:
107
  out["tavily"] = {"ok": False, "error": "Tavily disabled or no URL provided"}
108
 
109
- # If user provided a numeric UDISE directly and KYS requested, do KYS
110
  if use_kys and school_name_or_udise and school_name_or_udise.strip().isdigit() and 6 <= len(school_name_or_udise.strip()) <= 14:
111
  kys_res = call_kys_by_udise(school_name_or_udise.strip())
112
  out["kys"] = kys_res
@@ -115,17 +106,20 @@ def search_workflow(school_name_or_udise, tavily_url, tavily_key, use_tavily, us
115
 
116
 
117
  with gr.Blocks() as demo:
118
- gr.Markdown("""
119
- # Tavily + KYS Search (Hugging Face Space)
120
-
121
- Enter a school name or a UDISE code and call KYS (UDISE) or your Tavily search endpoint.
122
- """)
123
 
 
 
124
 
125
  with gr.Row():
126
- inp = gr.Textbox(label="School name or UDISE code", placeholder="e.g. 123456789012 or 'Govt High School...'", lines=1)
127
  tavily_url = gr.Textbox(label="Tavily endpoint URL (POST/GET)", placeholder="https://your-tavily.example/api/search")
128
- tavily_key = gr.Textbox(label="Tavily API Key / Authorization (optional)", placeholder="Bearer ... or APIKEY ...")
 
 
 
 
129
 
130
  with gr.Row():
131
  use_tavily = gr.Checkbox(value=True, label="Call Tavily")
@@ -134,36 +128,43 @@ with gr.Blocks() as demo:
134
  run = gr.Button("Search Tavily")
135
 
136
  output_json = gr.JSON(label="Raw Tavily Output (JSON)")
137
- tavily_table = gr.DataFrame(headers=None, label="Tavily results (table)")
138
 
139
- gr.Markdown('''### UDISE candidates found in Tavily results
140
- The dropdown will list all numeric tokens resembling UDISE codes found in Tavily's response. Choose any candidate (or edit the UDISE field) and click 'Lookup UDISE' to call KYS.")
141
- suggestions_dropdown = gr.Dropdown(choices=[], label="UDISE candidates (from Tavily)''')
142
  udise_input = gr.Textbox(label="UDISE to lookup (editable)", placeholder="Pick a candidate or type a UDISE code...", lines=1)
143
  lookup_btn = gr.Button("Lookup UDISE (Call KYS)")
144
 
145
  kys_output_json = gr.JSON(label="KYS Raw Output")
146
  kys_table = gr.DataFrame(headers=None, label="KYS results (table)")
147
 
148
- def on_run(school, turl, tkey, utav, ukys):
149
- res = search_workflow(school, turl, tkey, utav, ukys)
150
- # Prepare tavily table
 
 
 
 
151
  tav_df = pd.DataFrame()
152
  if res.get("tavily") and res["tavily"].get("ok"):
153
  tav_df = json_to_table(res["tavily"]["data"])
154
- # suggestions for dropdown
155
  suggestions = res.get("suggestions", [])
156
- return res.get("tavily"), tav_df, suggestions
 
 
 
 
 
 
157
 
158
- run.click(on_run, inputs=[inp, tavily_url, tavily_key, use_tavily, use_kys], outputs=[output_json, tavily_table, suggestions_dropdown])
 
159
 
160
- # When user selects a suggestion, populate the editable UDISE textbox
161
  def on_select_suggestion(choice):
162
  return choice or ""
163
 
164
  suggestions_dropdown.change(on_select_suggestion, inputs=[suggestions_dropdown], outputs=[udise_input])
165
 
166
- # Lookup button handler: call KYS for whatever is in udise_input
167
  def on_lookup_udise(udise_code):
168
  if not udise_code or not udise_code.strip().isdigit():
169
  return {"ok": False, "error": "Provide a numeric UDISE code (6-14 digits)."}, pd.DataFrame()
@@ -175,12 +176,18 @@ The dropdown will list all numeric tokens resembling UDISE codes found in Tavily
175
 
176
  lookup_btn.click(on_lookup_udise, inputs=[udise_input], outputs=[kys_output_json, kys_table])
177
 
 
 
 
 
 
 
178
  gr.Markdown('''---
179
- **Notes:**
180
- - Tavily results are attempted to be flattened into a table for easy scanning; complex nested structures will be shown as JSON above.
181
- - The UDISE candidates dropdown contains numeric tokens heuristically detected in the Tavily response; you can select one to fill the UDISE field, edit it, or type a different code.
182
- - The 'Search Tavily' button only queries Tavily and fills the table + suggestions; use 'Lookup UDISE' to call KYS for the chosen code.
183
- ''')
184
 
185
  if __name__ == "__main__":
186
  demo.launch()
 
1
+ # tavily_kys_space.py
2
+ # Gradio app for Hugging Face Spaces (Tavily API key textbox + Save key in session)
3
+
4
  import gradio as gr
5
  import requests
 
6
  import pandas as pd
 
7
 
8
  KYS_SAMPLE = "https://kys.udiseplus.gov.in/webapp/api/search-schools?searchType=3&searchParam={udise}"
9
 
 
24
  if api_key:
25
  headers["Authorization"] = api_key
26
  body = {"query": payload_text}
27
+
28
  try:
29
  resp = requests.post(tavily_url, json=body, headers=headers, timeout=12)
30
  resp.raise_for_status()
31
  return {"ok": True, "url": tavily_url, "status_code": resp.status_code, "data": resp.json()}
32
  except Exception as e:
 
33
  try:
34
  params = {"q": payload_text}
35
  resp = requests.get(tavily_url, params=params, headers=headers, timeout=12)
 
40
 
41
 
42
  def extract_udise_candidates_from_tavily(tavily_json):
 
43
  found = set()
44
 
45
  def walk(obj):
 
61
 
62
 
63
  def json_to_table(obj):
 
64
  try:
65
  if isinstance(obj, list):
66
+ return pd.json_normalize(obj)
 
67
  if isinstance(obj, dict):
68
+ for k in ("results", "data", "hits", "items"):
 
 
 
 
69
  if k in obj and isinstance(obj[k], list):
70
  return pd.json_normalize(obj[k])
 
71
  return pd.json_normalize([obj])
72
  except Exception:
73
  pass
 
81
  items = items["data"]
82
  if not items:
83
  return pd.DataFrame()
84
+ return pd.json_normalize(items)
 
85
  except Exception:
86
  return pd.DataFrame()
87
 
 
98
  else:
99
  out["tavily"] = {"ok": False, "error": "Tavily disabled or no URL provided"}
100
 
 
101
  if use_kys and school_name_or_udise and school_name_or_udise.strip().isdigit() and 6 <= len(school_name_or_udise.strip()) <= 14:
102
  kys_res = call_kys_by_udise(school_name_or_udise.strip())
103
  out["kys"] = kys_res
 
106
 
107
 
108
  with gr.Blocks() as demo:
109
+ # Fixed: properly terminated Markdown strings
110
+ gr.Markdown('''# Tavily + KYS Search (Hugging Face Space)
 
 
 
111
 
112
+ Enter a school name or a UDISE code, Tavily endpoint, and optionally an API key.
113
+ Use the 'Save key in session' toggle to keep the key for the current browser session.''')
114
 
115
  with gr.Row():
116
+ inp = gr.Textbox(label="School name", placeholder="'Govt High School...'", lines=1)
117
  tavily_url = gr.Textbox(label="Tavily endpoint URL (POST/GET)", placeholder="https://your-tavily.example/api/search")
118
+
119
+ # Tavily API key textbox + save toggle
120
+ tavily_key = gr.Textbox(label="Tavily API Key (optional)", placeholder="Bearer ... or APIKEY ...", lines=1)
121
+ save_key_toggle = gr.Checkbox(value=False, label="Save key in session (keeps key between interactions)")
122
+ clear_key_btn = gr.Button("Clear saved key")
123
 
124
  with gr.Row():
125
  use_tavily = gr.Checkbox(value=True, label="Call Tavily")
 
128
  run = gr.Button("Search Tavily")
129
 
130
  output_json = gr.JSON(label="Raw Tavily Output (JSON)")
131
+ tavily_table = gr.DataFrame(headers=None, label="Search Results (table)")
132
 
133
+ gr.Markdown("### UDISE candidates found in search results")
134
+ suggestions_dropdown = gr.Dropdown(choices=[], label="UDISE candidates")
 
135
  udise_input = gr.Textbox(label="UDISE to lookup (editable)", placeholder="Pick a candidate or type a UDISE code...", lines=1)
136
  lookup_btn = gr.Button("Lookup UDISE (Call KYS)")
137
 
138
  kys_output_json = gr.JSON(label="KYS Raw Output")
139
  kys_table = gr.DataFrame(headers=None, label="KYS results (table)")
140
 
141
+ # A small gr.State to persist the saved key value inside the session
142
+ saved_key_state = gr.State("")
143
+
144
+ def on_run(school, turl, tkey, save_key, utav, ukys, saved_key):
145
+ # Determine effective key: if save_key and saved_key present use saved_key, else use tkey
146
+ effective_key = saved_key if saved_key else tkey
147
+ res = search_workflow(school, turl, effective_key, utav, ukys)
148
  tav_df = pd.DataFrame()
149
  if res.get("tavily") and res["tavily"].get("ok"):
150
  tav_df = json_to_table(res["tavily"]["data"])
 
151
  suggestions = res.get("suggestions", [])
152
+ # If user asked to save the key for session, return it into saved_key_state and keep the textbox value
153
+ new_saved_key = saved_key
154
+ textbox_value = tkey
155
+ if save_key:
156
+ new_saved_key = tkey or saved_key
157
+ textbox_value = new_saved_key
158
+ return res.get("tavily"), tav_df, suggestions, new_saved_key, textbox_value
159
 
160
+ # run.click outputs: tavily json, tavily table, suggestions dropdown, saved_key_state, tavily_key (textbox)
161
+ run.click(on_run, inputs=[inp, tavily_url, tavily_key, save_key_toggle, use_tavily, use_kys, saved_key_state], outputs=[output_json, tavily_table, suggestions_dropdown, saved_key_state, tavily_key])
162
 
 
163
  def on_select_suggestion(choice):
164
  return choice or ""
165
 
166
  suggestions_dropdown.change(on_select_suggestion, inputs=[suggestions_dropdown], outputs=[udise_input])
167
 
 
168
  def on_lookup_udise(udise_code):
169
  if not udise_code or not udise_code.strip().isdigit():
170
  return {"ok": False, "error": "Provide a numeric UDISE code (6-14 digits)."}, pd.DataFrame()
 
176
 
177
  lookup_btn.click(on_lookup_udise, inputs=[udise_input], outputs=[kys_output_json, kys_table])
178
 
179
+ # Clear saved key handler: empties both the saved_key_state and the textbox
180
+ def on_clear_key(_):
181
+ return "", ""
182
+
183
+ clear_key_btn.click(on_clear_key, inputs=[saved_key_state], outputs=[saved_key_state, tavily_key])
184
+
185
  gr.Markdown('''---
186
+ **Notes:**
187
+ - The 'Save key in session' toggle will keep the key active for the current browser session and across interactions in the Space UI.
188
+ - The key is stored only in-memory for the session (not written to disk) and is not logged.
189
+ - Use the 'Clear saved key' button to remove it from the session.''')
190
+
191
 
192
  if __name__ == "__main__":
193
  demo.launch()