Nebulixlabs commited on
Commit
e1650da
ยท
verified ยท
1 Parent(s): 76e7cff

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -67
app.py CHANGED
@@ -2,6 +2,7 @@ import gradio as gr
2
  import json
3
  import hashlib
4
  import uuid
 
5
  from datetime import datetime
6
  from rapidfuzz import fuzz
7
  from transformers import pipeline
@@ -24,25 +25,35 @@ else:
24
  print(f"Warning: {DATA_FILE} not found! Please upload your data file to the space.")
25
 
26
  # ==========================================
27
- # 2. REAL AI MODEL SETUP (Zero-Shot Intent)
28
  # ==========================================
29
- print("Loading Real AI Model for Intent & Mood Prediction...")
30
- # Hum ek fast Zero-Shot model use kar rahe hain taaki batch processing tez ho.
31
- # Ye direct user intent samjhega.
32
  intent_classifier = pipeline(
33
  "zero-shot-classification",
34
  model="typeform/distilbert-base-uncased-mnli"
35
  )
36
-
37
  INTENT_LABELS = ["self-harm", "adult", "technology", "news", "entertainment", "sports", "information"]
38
 
39
  # ==========================================
40
- # 3. CORE BATCH SEARCH ALGORITHM
 
 
 
 
 
 
 
 
 
 
 
41
  # ==========================================
42
- # 'batch=True' hone ki wajah se ye function ek list of queries lega
43
- # ex: queries = ["latest news", "adult video", "code tool"]
44
  def batch_search_engine(queries, limits, user_ids):
45
- # Step A: Limit check (Max 30, Default 30)
 
 
 
 
46
  processed_limits = []
47
  for l in limits:
48
  try:
@@ -54,57 +65,69 @@ def batch_search_engine(queries, limits, user_ids):
54
  except:
55
  processed_limits.append(30)
56
 
57
- # Step B: AI Processing in BATCH! (Ek sath saare users ka intent predict hoga)
58
- # Pipeline automatically list of strings ko parallel process karta hai
59
- print(f"Processing Batch of {len(queries)} queries simultaneously...")
60
- ai_results = intent_classifier(queries, INTENT_LABELS)
61
-
62
- # Handle single element vs list response from pipeline
63
  if isinstance(ai_results, dict):
64
  ai_results = [ai_results]
65
 
66
- final_batch_responses = []
67
-
68
- # Step C: Har query ke liye Fuzzy Match aur Privacy Logging apply karna
69
  for i in range(len(queries)):
70
- query = queries[i]
71
  limit = processed_limits[i]
72
  user_id = user_ids[i]
73
- top_intent = ai_results[i]['labels'][0]
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  # --- PRIVACY LOGGING ---
76
- # Query dikhegi nahi log me, sirf hash banega. User ki pehchaan UUID se hogi.
77
  query_hash = hashlib.sha256(query.encode()).hexdigest()[:16]
78
- timestamp = datetime.utcnow().isoformat()
 
79
  log_entry = {
80
  "user_id": user_id,
81
- "query_id": query_hash,
82
- "timestamp": timestamp,
83
- "predicted_intent": top_intent
84
  }
85
- print(f"SECURE LOG: {log_entry}") # Ise database me save kar sakte ho future me
86
-
87
  # --- SELF HARM CHECK ---
88
  if top_intent == "self-harm":
89
- final_batch_responses.append(json.dumps({
 
90
  "status": "blocked",
91
- "intent": "self-harm",
92
- "message": "Safety Alert: We do not provide search results for self-harm. Please seek help.",
93
  "results": []
94
- }, indent=2))
95
  continue
96
 
97
- # --- FUZZY MATCH & INTENT BOOSTING ---
98
  results_with_scores = []
99
 
100
  for item in search_db:
101
- # RapidFuzz for high-speed fuzzy text matching
102
- fuzzy_score = fuzz.token_set_ratio(query.lower(), item.get('search_index', '').lower())
 
 
103
 
104
- # AI Intent Boosting: Agar intent domain se match kare toh data rank me upar aayega
105
  boost = 0
106
  domain = item.get('domain', '').lower()
107
 
 
108
  if top_intent == "adult" and domain in ["xhname", "avideos", "redwap", "dlsite"]:
109
  boost = 25
110
  elif top_intent == "technology" and domain in ["github", "scmp", "workspace", "bitdefender"]:
@@ -116,77 +139,76 @@ def batch_search_engine(queries, limits, user_ids):
116
 
117
  final_score = fuzzy_score + boost
118
 
119
- # Threshold Check (Kam se kam 30% relevancy honi chahiye)
120
  if final_score > 30:
121
  results_with_scores.append({
122
  "score": final_score,
123
  "data": item
124
  })
125
 
126
- # Highest score wale ko top pe rakhna (Rank sorting)
127
  results_with_scores.sort(key=lambda x: x["score"], reverse=True)
128
 
129
- # Filter and extract Top Results up to Limit
130
  final_data = [res["data"] for res in results_with_scores[:limit]]
131
 
132
- # Prepare JSON response
133
- response_json = {
134
- "predicted_intent": top_intent,
 
 
 
135
  "total_found": len(final_data),
136
- "showing_results": len(final_data),
137
  "results": final_data
138
- }
139
- final_batch_responses.append(json.dumps(response_json, indent=2, ensure_ascii=False))
140
 
141
- # Return the processed batch to respective users
142
- return final_batch_responses
143
 
144
  # ==========================================
145
- # 4. GRADIO UI & QUEUE SYSTEM
146
  # ==========================================
147
- # Generate unique User ID for session
148
- def generate_user_id():
149
- return f"user_{uuid.uuid4().hex[:10]}"
150
-
151
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
152
- gr.Markdown("# ๐Ÿš€ AI Smart Search Engine")
153
- gr.Markdown("Search for Tech, News, Adult, Sports, etc. Powered by True AI Intent & Fuzzy Match.")
154
 
155
- # State variable for user anonymity & tracking (Stored in user's browser session)
156
  session_user_id = gr.State(generate_user_id)
157
 
158
  with gr.Row():
159
- query_input = gr.Textbox(label="Enter Search Query...", placeholder="What do you want to find?", scale=4)
160
- limit_input = gr.Number(label="Results Limit (Max 30)", value=30, precision=0, scale=1)
161
 
162
  search_btn = gr.Button("Search ๐Ÿ”", variant="primary")
163
 
164
- # Output section
165
- output_display = gr.Code(label="Search Results", language="json")
 
 
 
166
 
167
- # Event Listener with BATCHING ENABLED
168
  search_btn.click(
169
  fn=batch_search_engine,
170
  inputs=[query_input, limit_input, session_user_id],
171
- outputs=[output_display],
172
- # Yaha pe magic hai! Batch=True ki wajah se Gradio requests ekathi karke AI ko bhejta hai.
173
  batch=True,
174
- max_batch_size=10, # Ek time pe maximum 10 logo ki request AI ko sath bhejega
175
- api_name="search" # Log ise as an API "/api/search" bhi call kar sakte hain
176
  )
177
 
178
  query_input.submit(
179
  fn=batch_search_engine,
180
  inputs=[query_input, limit_input, session_user_id],
181
- outputs=[output_display],
182
  batch=True,
183
  max_batch_size=10
184
  )
185
 
186
- # Enable Queue for "First Come First Serve" logic
187
  demo.queue(
188
- default_concurrency_limit=5, # Kitne concurrent batches chalenge
189
- max_size=100 # Queue me max kitne log wait kar sakte hain
190
  )
191
 
192
  if __name__ == "__main__":
 
2
  import json
3
  import hashlib
4
  import uuid
5
+ import re
6
  from datetime import datetime
7
  from rapidfuzz import fuzz
8
  from transformers import pipeline
 
25
  print(f"Warning: {DATA_FILE} not found! Please upload your data file to the space.")
26
 
27
  # ==========================================
28
+ # 2. AI MODEL SETUP (Zero-Shot Intent)
29
  # ==========================================
30
+ print("Loading AI Model for Smart Decision Making...")
 
 
31
  intent_classifier = pipeline(
32
  "zero-shot-classification",
33
  model="typeform/distilbert-base-uncased-mnli"
34
  )
 
35
  INTENT_LABELS = ["self-harm", "adult", "technology", "news", "entertainment", "sports", "information"]
36
 
37
  # ==========================================
38
+ # 3. HELPER FUNCTIONS
39
+ # ==========================================
40
+ def is_url(text):
41
+ # Check agar user ne direct URL daala hai
42
+ pattern = re.compile(r'^(https?://|www\.)\S+$', re.IGNORECASE)
43
+ return bool(pattern.match(text.strip()))
44
+
45
+ def generate_user_id():
46
+ return f"user_{uuid.uuid4().hex[:10]}"
47
+
48
+ # ==========================================
49
+ # 4. CORE BATCH SEARCH ENGINE (AI + FUZZY)
50
  # ==========================================
 
 
51
  def batch_search_engine(queries, limits, user_ids):
52
+ # Returns 2 lists: one for JSON outputs, one for HTML (Redirections)
53
+ final_json_responses = []
54
+ final_html_responses = []
55
+
56
+ # Check limits
57
  processed_limits = []
58
  for l in limits:
59
  try:
 
65
  except:
66
  processed_limits.append(30)
67
 
68
+ # Process batch with AI (Skip direct URLs for AI processing to save time)
69
+ ai_queries = [q if not is_url(q) else "bypass" for q in queries]
70
+ ai_results = intent_classifier(ai_queries, INTENT_LABELS)
 
 
 
71
  if isinstance(ai_results, dict):
72
  ai_results = [ai_results]
73
 
 
 
 
74
  for i in range(len(queries)):
75
+ query = str(queries[i]).strip()
76
  limit = processed_limits[i]
77
  user_id = user_ids[i]
 
78
 
79
+ # --- DIRECT URL REDIRECT LOGIC ---
80
+ if is_url(query):
81
+ url_to_open = query if query.startswith("http") else "http://" + query
82
+ # Redirect via HTML meta tag
83
+ redirect_html = f'<meta http-equiv="refresh" content="0; url={url_to_open}">'
84
+ final_html_responses.append(redirect_html)
85
+
86
+ # Add small info in JSON
87
+ final_json_responses.append({
88
+ "status": "redirecting",
89
+ "message": f"Direct URL detected. Redirecting to {url_to_open}",
90
+ "url": url_to_open
91
+ })
92
+ continue
93
+
94
  # --- PRIVACY LOGGING ---
 
95
  query_hash = hashlib.sha256(query.encode()).hexdigest()[:16]
96
+ top_intent = ai_results[i]['labels'][0]
97
+
98
  log_entry = {
99
  "user_id": user_id,
100
+ "query_hash": query_hash,
101
+ "timestamp": datetime.utcnow().isoformat(),
102
+ "ai_intent": top_intent
103
  }
104
+ print(f"SECURE LOG: {log_entry}")
105
+
106
  # --- SELF HARM CHECK ---
107
  if top_intent == "self-harm":
108
+ final_html_responses.append("<div></div>") # No HTML redirect
109
+ final_json_responses.append({
110
  "status": "blocked",
111
+ "ai_intent": "self-harm",
112
+ "message": "โš ๏ธ Safety Alert: We do not provide search results for self-harm. Please seek help.",
113
  "results": []
114
+ })
115
  continue
116
 
117
+ # --- AI + FUZZY MATCH LOGIC ---
118
  results_with_scores = []
119
 
120
  for item in search_db:
121
+ text_to_search = item.get('search_index', '')
122
+
123
+ # 1. Fuzzy Token Set Ratio (Keywords aage-peeche ho toh bhi chalega)
124
+ fuzzy_score = fuzz.token_set_ratio(query.lower(), text_to_search.lower())
125
 
126
+ # 2. AI Decision Boosting (Konsa dena hai)
127
  boost = 0
128
  domain = item.get('domain', '').lower()
129
 
130
+ # AI samajh raha hai ki user ko exact kis domain ka content chahiye
131
  if top_intent == "adult" and domain in ["xhname", "avideos", "redwap", "dlsite"]:
132
  boost = 25
133
  elif top_intent == "technology" and domain in ["github", "scmp", "workspace", "bitdefender"]:
 
139
 
140
  final_score = fuzzy_score + boost
141
 
142
+ # Minimum 30 score hona chahiye text match ka tabhi result aayega
143
  if final_score > 30:
144
  results_with_scores.append({
145
  "score": final_score,
146
  "data": item
147
  })
148
 
149
+ # Highest score (AI decides + Fuzzy match) will be on TOP
150
  results_with_scores.sort(key=lambda x: x["score"], reverse=True)
151
 
152
+ # Limit the results (Max 30)
153
  final_data = [res["data"] for res in results_with_scores[:limit]]
154
 
155
+ final_html_responses.append("<div></div>") # Empty HTML for normal searches
156
+
157
+ # Using Python Dictionary directly to avoid UI bug `{`
158
+ final_json_responses.append({
159
+ "status": "success",
160
+ "ai_predicted_intent": top_intent,
161
  "total_found": len(final_data),
162
+ "limit_applied": limit,
163
  "results": final_data
164
+ })
 
165
 
166
+ # Return lists because batch=True requires list of outputs for each component
167
+ return final_json_responses, final_html_responses
168
 
169
  # ==========================================
170
+ # 5. GRADIO UI & QUEUE SYSTEM
171
  # ==========================================
 
 
 
 
172
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
173
+ gr.Markdown("# ๐Ÿš€ Ultimate AI Search Engine")
174
+ gr.Markdown("Type your search query or paste a direct **URL**. Powered by AI Intent & Fuzzy Text Search.")
175
 
 
176
  session_user_id = gr.State(generate_user_id)
177
 
178
  with gr.Row():
179
+ query_input = gr.Textbox(label="Search Box", placeholder="Search anything or paste a URL (e.g. https://google.com)...", scale=4)
180
+ limit_input = gr.Number(label="Limit (Max 30)", value=30, precision=0, scale=1)
181
 
182
  search_btn = gr.Button("Search ๐Ÿ”", variant="primary")
183
 
184
+ # Fixed UI Issue: Using gr.JSON instead of gr.Code
185
+ output_json = gr.JSON(label="Search Results")
186
+
187
+ # Hidden HTML component for URL redirection
188
+ redirect_html = gr.HTML(label="", visible=False)
189
 
190
+ # Link Button & Enter Key (Batch Mode enabled)
191
  search_btn.click(
192
  fn=batch_search_engine,
193
  inputs=[query_input, limit_input, session_user_id],
194
+ outputs=[output_json, redirect_html],
 
195
  batch=True,
196
+ max_batch_size=10,
197
+ api_name="search"
198
  )
199
 
200
  query_input.submit(
201
  fn=batch_search_engine,
202
  inputs=[query_input, limit_input, session_user_id],
203
+ outputs=[output_json, redirect_html],
204
  batch=True,
205
  max_batch_size=10
206
  )
207
 
208
+ # Queue System: First come first serve with concurrency
209
  demo.queue(
210
+ default_concurrency_limit=5,
211
+ max_size=200
212
  )
213
 
214
  if __name__ == "__main__":