Nebulixlabs commited on
Commit
aa82a08
·
verified ·
1 Parent(s): 1289ffa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -14
app.py CHANGED
@@ -9,7 +9,7 @@ import multiprocessing
9
  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
@@ -112,7 +112,7 @@ def load_ai_models():
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")
@@ -186,6 +186,7 @@ async def perform_core_search(raw_query: str):
186
  best_score = scored_results[0][0] if scored_results else 0
187
  prediction = "High confidence" if best_score > 15 else "Medium confidence" if best_score > 5 else "Low confidence"
188
 
 
189
  final_results = [{"match_score": round(s, 2), **doc} for s, doc in scored_results[:100]]
190
  return final_results, prediction, best_score
191
 
@@ -195,7 +196,6 @@ def _generate_text(messages, max_tokens: int):
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)
@@ -219,7 +219,6 @@ async def lifespan(app: FastAPI):
219
  yield
220
 
221
  app = FastAPI(title="Nebulix Advanced SEO & Visual API Engine", lifespan=lifespan)
222
- # CORS Enabled for your separate UI
223
  app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])
224
 
225
  @app.middleware("http")
@@ -241,7 +240,6 @@ async def rate_limit_middleware(request: Request, call_next):
241
 
242
  return await call_next(request)
243
 
244
- # Health Check API Endpoint (No HTML)
245
  @app.get("/")
246
  async def health_check():
247
  return {"status": "ok", "message": "Nebulix API Engine is running smoothly."}
@@ -267,6 +265,7 @@ async def ai_mode_short(q: str = Query(...)):
267
  ai_reply = await run_ai_task(messages, 150, query_key=f"short_{q}")
268
  return {"request_id": req_id, "ai_response": ai_reply, "results": results}
269
 
 
270
  @app.get("/aimodechat")
271
  async def ai_mode_chat(q: str = Query(...)):
272
  req_id = str(uuid.uuid4())
@@ -281,6 +280,41 @@ async def ai_mode_chat(q: str = Query(...)):
281
  ai_reply = await run_ai_task(messages, 400, query_key=f"chat_{q}")
282
  return {"request_id": req_id, "ai_response": ai_reply, "results": results}
283
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  @app.post("/image-search")
285
  async def reverse_image_search(file: UploadFile = File(...)):
286
  if not vision_model:
@@ -292,29 +326,29 @@ async def reverse_image_search(file: UploadFile = File(...)):
292
  image_bytes = await file.read()
293
  img = Image.open(io.BytesIO(image_bytes)).convert("RGB")
294
 
 
295
  async with ai_semaphore:
296
  ai_review = await asyncio.to_thread(_generate_image_review, img)
297
 
 
298
  raw_results, _, _ = await perform_core_search(ai_review)
299
  visual_results = []
300
 
 
301
  for doc in raw_results:
302
  is_adult = str(doc.get("tag", "general")).lower() in ["adult", "nsfw"] or any(w in str(doc).lower() for w in ADULT_KEYWORDS)
303
  if is_adult: continue
304
 
305
- result_item = {
306
- "title": doc.get("title", "No Title"),
307
- "url": doc.get("url", ""),
308
- "image_url": doc.get("image_url", doc.get("specific_data", {}).get("image", "")),
309
- "description": doc.get("description", "")
310
- }
311
- visual_results.append(result_item)
312
  if len(visual_results) >= 40: break
313
 
 
314
  return {
315
  "request_id": req_id,
316
- "ai_review": f"Image Analysis: {ai_review}.",
317
- "message": "Found visually related content and images.",
318
  "results_count": len(visual_results),
319
  "results": visual_results
320
  }
 
9
  import urllib.parse
10
  from datetime import datetime
11
  from contextlib import asynccontextmanager
12
+ from fastapi import FastAPI, Query, Request, UploadFile, File, Form
13
  from fastapi.responses import JSONResponse
14
  from fastapi.middleware.cors import CORSMiddleware
15
  from huggingface_hub import hf_hub_download
 
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
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")
 
186
  best_score = scored_results[0][0] if scored_results else 0
187
  prediction = "High confidence" if best_score > 15 else "Medium confidence" if best_score > 5 else "Low confidence"
188
 
189
+ # Yaha par hum wahi structure bana rahe hain jo frontend ko chahiye
190
  final_results = [{"match_score": round(s, 2), **doc} for s, doc in scored_results[:100]]
191
  return final_results, prediction, best_score
192
 
 
196
  return result[0]['generated_text'][-1]['content']
197
 
198
  def _generate_image_review(image: Image):
 
199
  inputs = vision_processor(image, return_tensors="pt")
200
  with torch.no_grad():
201
  out = vision_model.generate(**inputs, max_new_tokens=50)
 
219
  yield
220
 
221
  app = FastAPI(title="Nebulix Advanced SEO & Visual API Engine", lifespan=lifespan)
 
222
  app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])
223
 
224
  @app.middleware("http")
 
240
 
241
  return await call_next(request)
242
 
 
243
  @app.get("/")
244
  async def health_check():
245
  return {"status": "ok", "message": "Nebulix API Engine is running smoothly."}
 
265
  ai_reply = await run_ai_task(messages, 150, query_key=f"short_{q}")
266
  return {"request_id": req_id, "ai_response": ai_reply, "results": results}
267
 
268
+ # 1. PURANA CHAT API (Current UI ke liye)
269
  @app.get("/aimodechat")
270
  async def ai_mode_chat(q: str = Query(...)):
271
  req_id = str(uuid.uuid4())
 
280
  ai_reply = await run_ai_task(messages, 400, query_key=f"chat_{q}")
281
  return {"request_id": req_id, "ai_response": ai_reply, "results": results}
282
 
283
+ # 2. NAYA CHAT API (Future UI - Image + Text Chat ke liye)
284
+ @app.post("/aimodechat")
285
+ async def ai_mode_chat_vision(q: str = Form(...), file: UploadFile = File(None)):
286
+ req_id = str(uuid.uuid4())
287
+
288
+ vision_context = ""
289
+ # Agar user ne chat me image upload ki hai, toh AI image ko decode karega
290
+ if file and vision_model:
291
+ try:
292
+ image_bytes = await file.read()
293
+ img = Image.open(io.BytesIO(image_bytes)).convert("RGB")
294
+ async with ai_semaphore:
295
+ ai_review = await asyncio.to_thread(_generate_image_review, img)
296
+ vision_context = f"\n[User uploaded an image showing: {ai_review}]\n"
297
+ except Exception:
298
+ vision_context = "\n[User uploaded an image but it could not be analyzed.]\n"
299
+
300
+ # Search query combining text and vision
301
+ search_query = f"{q} {vision_context}".strip()
302
+ results, _, _ = await perform_core_search(search_query)
303
+
304
+ context_parts = [f"Source [{i+1}]: {r.get('title')} - {r.get('description')}" for i, r in enumerate(results[:5])]
305
+
306
+ messages = [
307
+ {"role": "system", "content": "You are a Smart AI Search Assistant capable of understanding text and visual context. Use the provided search sources and image details to answer accurately."},
308
+ {"role": "user", "content": f"User Query: {q}{vision_context}\n\nContext:\n{chr(10).join(context_parts)}"}
309
+ ]
310
+
311
+ # Generate Chat response
312
+ cache_key = f"chat_{q}_{len(vision_context)}"
313
+ ai_reply = await run_ai_task(messages, 400, query_key=cache_key)
314
+
315
+ return {"request_id": req_id, "ai_response": ai_reply, "results": results}
316
+
317
+ # IMAGE SEARCH (Fixed: Same JSON structure as normal text search)
318
  @app.post("/image-search")
319
  async def reverse_image_search(file: UploadFile = File(...)):
320
  if not vision_model:
 
326
  image_bytes = await file.read()
327
  img = Image.open(io.BytesIO(image_bytes)).convert("RGB")
328
 
329
+ # 1. Vision AI process karega
330
  async with ai_semaphore:
331
  ai_review = await asyncio.to_thread(_generate_image_review, img)
332
 
333
+ # 2. Text Search hoga vision ke basis pe
334
  raw_results, _, _ = await perform_core_search(ai_review)
335
  visual_results = []
336
 
337
+ # 3. DIRECTLY append the original FULL document
338
  for doc in raw_results:
339
  is_adult = str(doc.get("tag", "general")).lower() in ["adult", "nsfw"] or any(w in str(doc).lower() for w in ADULT_KEYWORDS)
340
  if is_adult: continue
341
 
342
+ # Pura document direct bhej rahe hain bina modify kiye
343
+ # jisse exact text search wala JSON format barkarar rahe
344
+ visual_results.append(doc)
345
+
 
 
 
346
  if len(visual_results) >= 40: break
347
 
348
+ # 4. Same structure return karenge
349
  return {
350
  "request_id": req_id,
351
+ "query": f"Image Search Analysis: {ai_review}", # Taki UI me ye "query" ki tarah display ho
 
352
  "results_count": len(visual_results),
353
  "results": visual_results
354
  }