Nebulixlabs commited on
Commit
f53583e
ยท
verified ยท
1 Parent(s): 1392924

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -35
app.py CHANGED
@@ -10,14 +10,16 @@ import urllib.parse
10
  from datetime import datetime
11
  from contextlib import asynccontextmanager
12
  from fastapi import FastAPI, Query, Request, UploadFile, File
13
- from fastapi.responses import JSONResponse
14
  from fastapi.middleware.cors import CORSMiddleware
15
  from huggingface_hub import hf_hub_download
16
  from rank_bm25 import BM25Okapi
17
  import torch
18
  from PIL import Image
19
  import io
20
- from transformers import pipeline
 
 
21
 
22
  # --- 1. SETUP & CPU ALLOCATION (40% for AI) ---
23
  TOTAL_CORES = multiprocessing.cpu_count()
@@ -29,12 +31,12 @@ print(f"๐Ÿ–ฅ๏ธ Total Cores: {TOTAL_CORES} | Allocating {AI_CORES} cores strictl
29
  raw_data = []
30
  bm25_index = None
31
 
32
- # Queueing System using Semaphore (Text & Vision dono ke liye same queue)
33
  MAX_CONCURRENT_AI = max(1, AI_CORES)
34
  ai_semaphore = asyncio.Semaphore(MAX_CONCURRENT_AI)
35
 
36
  ai_generator = None
37
- vision_ai_generator = None # Naya Vision AI
 
38
 
39
  # --- AI CACHING SYSTEM ---
40
  AI_RESPONSE_CACHE = {}
@@ -104,20 +106,20 @@ def load_and_index_dataset():
104
  print("โŒ Dataset file not found!")
105
 
106
  def load_ai_models():
107
- global ai_generator, vision_ai_generator
108
  print("๐Ÿค– Loading Lightweight AI Models (Text & Vision)...")
109
  try:
110
- # 1. Text AI (Lightweight Qwen)
111
  ai_generator = pipeline("text-generation", model="Qwen/Qwen2.5-0.5B-Instruct", device=-1, dtype=torch.float32)
112
 
113
- # 2. Vision AI (BLIP - Ultra lightweight, perfect for CPU)
114
- # Ye model image ko dekh kar batata hai ki usme kya hai (AI Review)
115
  print("๐Ÿ‘๏ธ Loading Vision AI...")
116
- vision_ai_generator = pipeline("image-to-text", model="Salesforce/blip-image-captioning-base", device=-1)
 
117
 
118
  print("โœ… All AI Models Loaded! System ready.")
119
  except Exception as e:
120
- print("โŒ Model Loading Failed:", e)
121
 
122
 
123
  # --- 3. CORE SEARCH ALGORITHM ---
@@ -162,11 +164,9 @@ async def perform_core_search(raw_query: str):
162
  doc_tag = str(doc.get("tag", "general")).lower()
163
  if tag_filter and tag_filter != doc_tag: continue
164
 
165
- # Adult Content Strict Filter
166
  is_adult = doc_tag in ["adult", "nsfw"] or any(w in str(doc).lower() for w in ADULT_KEYWORDS)
167
  if not user_wants_adult and is_adult: continue
168
 
169
- # Ranking Boosts
170
  final_score = score
171
  exact_phrase = query.lower()
172
  doc_title = str(doc.get("title", "")).lower()
@@ -195,20 +195,19 @@ def _generate_text(messages, max_tokens: int):
195
  return result[0]['generated_text'][-1]['content']
196
 
197
  def _generate_image_review(image: Image):
198
- result = vision_ai_generator(image, max_new_tokens=50)
199
- return result[0]['generated_text']
 
 
 
200
 
201
  async def run_ai_task(messages, max_tokens: int, query_key: str):
202
  if not ai_generator: return "โš ๏ธ AI Model is starting up."
203
-
204
- if query_key in AI_RESPONSE_CACHE:
205
- return AI_RESPONSE_CACHE[query_key]
206
 
207
  async with ai_semaphore:
208
  response = await asyncio.to_thread(_generate_text, messages, max_tokens)
209
-
210
- if len(AI_RESPONSE_CACHE) > MAX_CACHE_SIZE:
211
- AI_RESPONSE_CACHE.clear()
212
  AI_RESPONSE_CACHE[query_key] = response
213
  return response
214
 
@@ -241,56 +240,82 @@ async def rate_limit_middleware(request: Request, call_next):
241
 
242
  return await call_next(request)
243
 
 
 
 
 
 
 
 
 
244
  @app.get("/search")
245
  async def pure_search(q: str = Query(...)):
246
  req_id = str(uuid.uuid4())
247
  results, prediction, _ = await perform_core_search(q)
248
  return {"request_id": req_id, "query": q, "results_count": len(results), "results": results}
249
 
250
- # --- NEW: ADVANCED SMART IMAGE SEARCH ENDPOINT ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  @app.post("/image-search")
252
  async def reverse_image_search(file: UploadFile = File(...)):
253
- if not vision_ai_generator:
254
  return {"error": "Vision AI Model is still loading."}
255
 
256
  req_id = str(uuid.uuid4())
257
 
258
  try:
259
- # 1. Read & Process Uploaded Image
260
  image_bytes = await file.read()
261
  img = Image.open(io.BytesIO(image_bytes)).convert("RGB")
262
 
263
- # 2. Get AI Review (Uses Semaphore queue to manage CPU limit)
264
  async with ai_semaphore:
265
  ai_review = await asyncio.to_thread(_generate_image_review, img)
266
 
267
- # 3. Use AI Review to search dataset for visually relevant content
268
  raw_results, _, _ = await perform_core_search(ai_review)
269
-
270
- # 4. Filter & Format Results (Strictly max 40 results)
271
  visual_results = []
272
 
273
  for doc in raw_results:
274
- # Smart SafeSearch Filter (Pehle bhi hota hai, double safety ke liye yaha bhi)
275
  is_adult = str(doc.get("tag", "general")).lower() in ["adult", "nsfw"] or any(w in str(doc).lower() for w in ADULT_KEYWORDS)
276
  if is_adult: continue
277
 
278
- # Result formatting (Hum images, titles aur related URLs return kar rahe hain)
279
  result_item = {
280
  "title": doc.get("title", "No Title"),
281
  "url": doc.get("url", ""),
282
- "image_url": doc.get("image_url", doc.get("specific_data", {}).get("image", "")), # Try extracting image URL
283
  "description": doc.get("description", "")
284
  }
285
  visual_results.append(result_item)
286
-
287
- # STRICT LIMIT: Maximum 40 results
288
- if len(visual_results) >= 40:
289
- break
290
 
291
  return {
292
  "request_id": req_id,
293
- "ai_review": f"Image Analysis: {ai_review.capitalize()}.",
294
  "message": "Found visually related content and images.",
295
  "results_count": len(visual_results),
296
  "results": visual_results
 
10
  from datetime import datetime
11
  from contextlib import asynccontextmanager
12
  from fastapi import FastAPI, Query, Request, UploadFile, File
13
+ from fastapi.responses import JSONResponse, HTMLResponse
14
  from fastapi.middleware.cors import CORSMiddleware
15
  from huggingface_hub import hf_hub_download
16
  from rank_bm25 import BM25Okapi
17
  import torch
18
  from PIL import Image
19
  import io
20
+
21
+ # DIRECT IMPORTS TO FIX THE PIPELINE BUG
22
+ from transformers import pipeline, BlipProcessor, BlipForConditionalGeneration
23
 
24
  # --- 1. SETUP & CPU ALLOCATION (40% for AI) ---
25
  TOTAL_CORES = multiprocessing.cpu_count()
 
31
  raw_data = []
32
  bm25_index = None
33
 
 
34
  MAX_CONCURRENT_AI = max(1, AI_CORES)
35
  ai_semaphore = asyncio.Semaphore(MAX_CONCURRENT_AI)
36
 
37
  ai_generator = None
38
+ vision_processor = None
39
+ vision_model = None
40
 
41
  # --- AI CACHING SYSTEM ---
42
  AI_RESPONSE_CACHE = {}
 
106
  print("โŒ Dataset file not found!")
107
 
108
  def load_ai_models():
109
+ global ai_generator, vision_processor, vision_model
110
  print("๐Ÿค– Loading Lightweight AI Models (Text & Vision)...")
111
  try:
112
+ # 1. Text AI
113
  ai_generator = pipeline("text-generation", model="Qwen/Qwen2.5-0.5B-Instruct", device=-1, dtype=torch.float32)
114
 
115
+ # 2. Vision AI (Fix: Direct loading to bypass pipeline task errors)
 
116
  print("๐Ÿ‘๏ธ Loading Vision AI...")
117
+ vision_processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base")
118
+ vision_model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base")
119
 
120
  print("โœ… All AI Models Loaded! System ready.")
121
  except Exception as e:
122
+ print(f"โŒ Model Loading Failed: {e}")
123
 
124
 
125
  # --- 3. CORE SEARCH ALGORITHM ---
 
164
  doc_tag = str(doc.get("tag", "general")).lower()
165
  if tag_filter and tag_filter != doc_tag: continue
166
 
 
167
  is_adult = doc_tag in ["adult", "nsfw"] or any(w in str(doc).lower() for w in ADULT_KEYWORDS)
168
  if not user_wants_adult and is_adult: continue
169
 
 
170
  final_score = score
171
  exact_phrase = query.lower()
172
  doc_title = str(doc.get("title", "")).lower()
 
195
  return result[0]['generated_text'][-1]['content']
196
 
197
  def _generate_image_review(image: Image):
198
+ # Direct model generation (Bypasses the buggy pipeline)
199
+ inputs = vision_processor(image, return_tensors="pt")
200
+ with torch.no_grad():
201
+ out = vision_model.generate(**inputs, max_new_tokens=50)
202
+ return vision_processor.decode(out[0], skip_special_tokens=True).capitalize()
203
 
204
  async def run_ai_task(messages, max_tokens: int, query_key: str):
205
  if not ai_generator: return "โš ๏ธ AI Model is starting up."
206
+ if query_key in AI_RESPONSE_CACHE: return AI_RESPONSE_CACHE[query_key]
 
 
207
 
208
  async with ai_semaphore:
209
  response = await asyncio.to_thread(_generate_text, messages, max_tokens)
210
+ if len(AI_RESPONSE_CACHE) > MAX_CACHE_SIZE: AI_RESPONSE_CACHE.clear()
 
 
211
  AI_RESPONSE_CACHE[query_key] = response
212
  return response
213
 
 
240
 
241
  return await call_next(request)
242
 
243
+ # NAYA: Frontend Load Karne Ke Liye
244
+ @app.get("/", response_class=HTMLResponse)
245
+ async def serve_ui():
246
+ if os.path.exists("index.html"):
247
+ with open("index.html", "r", encoding="utf-8") as f:
248
+ return f.read()
249
+ return "<h1>UI Not Found</h1><p>Please save your frontend code as <b>index.html</b> in the same folder as this main.py file.</p>"
250
+
251
  @app.get("/search")
252
  async def pure_search(q: str = Query(...)):
253
  req_id = str(uuid.uuid4())
254
  results, prediction, _ = await perform_core_search(q)
255
  return {"request_id": req_id, "query": q, "results_count": len(results), "results": results}
256
 
257
+ @app.get("/aimode")
258
+ async def ai_mode_short(q: str = Query(...)):
259
+ req_id = str(uuid.uuid4())
260
+ results, _, _ = await perform_core_search(q)
261
+ if not results: return {"request_id": req_id, "ai_response": "I couldn't find any results.", "results": []}
262
+
263
+ context = " ".join([f"{r.get('title', '')} - {r.get('description', '')}" for r in results[:3]])
264
+ messages = [
265
+ {"role": "system", "content": "Provide a brief 2-3 sentence summary based only on the provided context."},
266
+ {"role": "user", "content": f"Query: {q}\nContext: {context}"}
267
+ ]
268
+
269
+ ai_reply = await run_ai_task(messages, 150, query_key=f"short_{q}")
270
+ return {"request_id": req_id, "ai_response": ai_reply, "results": results}
271
+
272
+ @app.get("/aimodechat")
273
+ async def ai_mode_chat(q: str = Query(...)):
274
+ req_id = str(uuid.uuid4())
275
+ results, _, _ = await perform_core_search(q)
276
+
277
+ context_parts = [f"Source [{i+1}]: {r.get('title')} - {r.get('description')}" for i, r in enumerate(results[:5])]
278
+ messages = [
279
+ {"role": "system", "content": "You are a Smart AI Search Assistant. Use search sources to answer accurately."},
280
+ {"role": "user", "content": f"User Query: {q}\n\nContext:\n{chr(10).join(context_parts)}"}
281
+ ]
282
+
283
+ ai_reply = await run_ai_task(messages, 400, query_key=f"chat_{q}")
284
+ return {"request_id": req_id, "ai_response": ai_reply, "results": results}
285
+
286
  @app.post("/image-search")
287
  async def reverse_image_search(file: UploadFile = File(...)):
288
+ if not vision_model: # Yaha updated var check lagaya gaya hai
289
  return {"error": "Vision AI Model is still loading."}
290
 
291
  req_id = str(uuid.uuid4())
292
 
293
  try:
 
294
  image_bytes = await file.read()
295
  img = Image.open(io.BytesIO(image_bytes)).convert("RGB")
296
 
 
297
  async with ai_semaphore:
298
  ai_review = await asyncio.to_thread(_generate_image_review, img)
299
 
 
300
  raw_results, _, _ = await perform_core_search(ai_review)
 
 
301
  visual_results = []
302
 
303
  for doc in raw_results:
 
304
  is_adult = str(doc.get("tag", "general")).lower() in ["adult", "nsfw"] or any(w in str(doc).lower() for w in ADULT_KEYWORDS)
305
  if is_adult: continue
306
 
 
307
  result_item = {
308
  "title": doc.get("title", "No Title"),
309
  "url": doc.get("url", ""),
310
+ "image_url": doc.get("image_url", doc.get("specific_data", {}).get("image", "")),
311
  "description": doc.get("description", "")
312
  }
313
  visual_results.append(result_item)
314
+ if len(visual_results) >= 40: break
 
 
 
315
 
316
  return {
317
  "request_id": req_id,
318
+ "ai_review": f"Image Analysis: {ai_review}.",
319
  "message": "Found visually related content and images.",
320
  "results_count": len(visual_results),
321
  "results": visual_results