kn29 commited on
Commit
5cc5e9b
·
verified ·
1 Parent(s): b511946

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +245 -0
app.py CHANGED
@@ -443,6 +443,251 @@ async def list_active_sessions():
443
  "sessions": sessions
444
  }
445
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
446
  if __name__ == "__main__":
447
  import uvicorn
448
  port = int(os.getenv("PORT", 7861))
 
443
  "sessions": sessions
444
  }
445
 
446
+ # Add this enhanced logging to your chat endpoint in app.py
447
+
448
+ @app.post("/chat/{session_id}", response_model=ChatResponse)
449
+ async def chat_with_document(session_id: str, request: ChatRequest):
450
+ session_logger = create_session_logger(session_id)
451
+ start_time = time.time()
452
+
453
+ try:
454
+ session_logger.info(f"=== CHAT REQUEST START ===")
455
+ session_logger.info(f"Session ID: {session_id}")
456
+ session_logger.info(f"Message length: {len(request.message)}")
457
+ session_logger.info(f"Message preview: {request.message[:100]}...")
458
+ session_logger.info(f"RAG models initialized: {RAG_MODELS_INITIALIZED}")
459
+ session_logger.info(f"MongoDB connected: {APP_STATE['mongodb_connected']}")
460
+
461
+ # Check if session is already loaded in memory
462
+ with STORE_LOCK:
463
+ session_in_memory = session_id in SESSION_STORES
464
+ session_logger.info(f"Session in memory: {session_in_memory}")
465
+
466
+ if not session_in_memory:
467
+ # Lazy load: Load session from MongoDB when first chat request comes
468
+ session_logger.info("=== LAZY LOADING FROM MONGODB ===")
469
+ session_logger.info("Loading session from MongoDB for first chat request")
470
+
471
+ try:
472
+ load_start = time.time()
473
+ session_store = await asyncio.to_thread(load_session_from_mongodb, session_id)
474
+ load_time = time.time() - load_start
475
+ session_logger.info(f"Session loaded from MongoDB in {load_time:.2f}s")
476
+
477
+ SESSION_STORES[session_id] = session_store
478
+ session_logger.info(f"Session added to memory store")
479
+ session_logger.info(f"Chunks loaded: {len(session_store.get('session_rag', {}).chunks_data) if hasattr(session_store.get('session_rag'), 'chunks_data') else 'unknown'}")
480
+
481
+ except Exception as load_error:
482
+ session_logger.error(f"Failed to load session: {load_error}", exc_info=True)
483
+ raise HTTPException(status_code=404, detail=f"Failed to load session: {str(load_error)}")
484
+
485
+ # Update last access time
486
+ SESSION_LAST_ACCESS[session_id] = datetime.utcnow()
487
+ session_rag = SESSION_STORES[session_id]["session_rag"]
488
+ session_logger.info(f"Using session RAG instance: {type(session_rag)}")
489
+
490
+ session_logger.info(f"=== PROCESSING QUERY ===")
491
+
492
+ # Process the query using SessionRAG
493
+ query_start = time.time()
494
+ result = await asyncio.to_thread(session_rag.query_documents, request.message, top_k=5)
495
+ query_time = time.time() - query_start
496
+
497
+ session_logger.info(f"Query processed in {query_time:.2f}s")
498
+ session_logger.info(f"Result keys: {list(result.keys()) if isinstance(result, dict) else 'not dict'}")
499
+
500
+ if 'error' in result:
501
+ session_logger.error(f"Query processing error: {result['error']}")
502
+ raise HTTPException(status_code=500, detail=result['error'])
503
+
504
+ APP_STATE["total_queries"] += 1
505
+ answer = result.get('answer', 'Unable to generate an answer.')
506
+ sources = result.get('sources', [])
507
+
508
+ session_logger.info(f"Generated answer length: {len(answer)}")
509
+ session_logger.info(f"Sources found: {len(sources)}")
510
+
511
+ # Save chat messages asynchronously
512
+ asyncio.create_task(save_chat_message_safely(session_id, "user", request.message))
513
+ asyncio.create_task(save_chat_message_safely(session_id, "assistant", answer))
514
+
515
+ processing_time = time.time() - start_time
516
+ session_logger.info(f"=== CHAT REQUEST COMPLETE ===")
517
+ session_logger.info(f"Total processing time: {processing_time:.2f}s")
518
+
519
+ return ChatResponse(
520
+ success=True,
521
+ answer=answer,
522
+ sources=sources,
523
+ chat_history=[],
524
+ processing_time=processing_time,
525
+ session_id=session_id,
526
+ query_analysis=result.get('query_analysis'),
527
+ confidence=result.get('confidence')
528
+ )
529
+
530
+ except HTTPException:
531
+ session_logger.error(f"HTTP Exception in chat processing")
532
+ raise
533
+ except Exception as e:
534
+ session_logger.error(f"Chat processing failed: {e}", exc_info=True)
535
+ APP_STATE["errors"].append(f"Chat error: {str(e)}")
536
+ raise HTTPException(status_code=500, detail=f"Chat processing error: {str(e)}")
537
+
538
+ # Also add this endpoint for better debugging
539
+ @app.get("/debug/{session_id}")
540
+ async def debug_session(session_id: str):
541
+ """Debug endpoint to check session status"""
542
+ with STORE_LOCK:
543
+ session_in_memory = session_id in SESSION_STORES
544
+ session_info = {}
545
+
546
+ if session_in_memory:
547
+ store = SESSION_STORES[session_id]
548
+ session_rag = store.get("session_rag")
549
+ session_info = {
550
+ "in_memory": True,
551
+ "indexed": store.get("indexed", False),
552
+ "metadata": store.get("metadata", {}),
553
+ "chunks_count": len(session_rag.chunks_data) if hasattr(session_rag, 'chunks_data') else 0,
554
+ "has_dense_index": hasattr(session_rag, 'dense_index') and session_rag.dense_index is not None,
555
+ "has_bm25_index": hasattr(session_rag, 'bm25_index') and session_rag.bm25_index is not None,
556
+ }
557
+ else:
558
+ session_info = {"in_memory": False}
559
+
560
+ # Check MongoDB
561
+ mongodb_info = {"connected": False, "session_exists": False, "chunks_count": 0}
562
+ if DB:
563
+ mongodb_info["connected"] = True
564
+ session_doc = DB.sessions.find_one({"session_id": session_id})
565
+ if session_doc:
566
+ mongodb_info["session_exists"] = True
567
+ mongodb_info["session_status"] = session_doc.get("status")
568
+ mongodb_info["filename"] = session_doc.get("filename")
569
+ chunks_count = DB.chunks.count_documents({"session_id": session_id})
570
+ mongodb_info["chunks_count"] = chunks_count
571
+
572
+ return {
573
+ "session_id": session_id,
574
+ "memory": session_info,
575
+ "mongodb": mongodb_info,
576
+ "app_state": {
577
+ "rag_models_ready": RAG_MODELS_INITIALIZED,
578
+ "mongodb_connected": APP_STATE["mongodb_connected"],
579
+ "active_sessions": len(SESSION_STORES)
580
+ }
581
+ }
582
+
583
+ # Enhanced load_session_from_mongodb with better error handling
584
+ def load_session_from_mongodb(session_id: str) -> Dict[str, Any]:
585
+ """Load pre-existing session data and embeddings from MongoDB"""
586
+ session_logger = create_session_logger(session_id)
587
+ session_logger.info(f"=== LOADING SESSION FROM MONGODB ===")
588
+ session_logger.info(f"Session ID: {session_id}")
589
+
590
+ if not DB:
591
+ session_logger.error("Database not connected")
592
+ raise ValueError("Database not connected")
593
+
594
+ # Load session metadata
595
+ session_logger.info("Loading session metadata...")
596
+ session_doc = DB.sessions.find_one({"session_id": session_id})
597
+ if not session_doc:
598
+ session_logger.error(f"Session {session_id} not found in database")
599
+ raise ValueError(f"Session {session_id} not found in database")
600
+
601
+ session_logger.info(f"Found session: {session_doc.get('filename', 'unknown')} - Status: {session_doc.get('status')}")
602
+
603
+ if session_doc.get("status") != "completed":
604
+ session_logger.error(f"Session not ready - status: {session_doc.get('status')}")
605
+ raise ValueError(f"Session not ready - status: {session_doc.get('status')}")
606
+
607
+ # Load chunks with embeddings from MongoDB
608
+ session_logger.info(f"Loading chunks with embeddings for: {session_doc.get('filename', 'unknown')}")
609
+ chunks_cursor = DB.chunks.find({"session_id": session_id}).sort("created_at", 1)
610
+ chunks_list = list(chunks_cursor)
611
+
612
+ session_logger.info(f"Found {len(chunks_list)} chunks in database")
613
+
614
+ if not chunks_list:
615
+ session_logger.error(f"No chunks found for session {session_id}")
616
+ raise ValueError(f"No chunks found for session {session_id}")
617
+
618
+ # Verify chunks have embeddings
619
+ chunks_with_embeddings = 0
620
+ for chunk in chunks_list:
621
+ if chunk.get('embedding') is not None:
622
+ chunks_with_embeddings += 1
623
+
624
+ session_logger.info(f"Chunks with embeddings: {chunks_with_embeddings}/{len(chunks_list)}")
625
+
626
+ if chunks_with_embeddings == 0:
627
+ session_logger.error("No chunks have embeddings - document may not be fully processed")
628
+ raise ValueError("No chunks have embeddings - document may not be fully processed")
629
+
630
+ # Create SessionRAG instance and load pre-existing data
631
+ try:
632
+ session_logger.info("Creating SessionRAG instance...")
633
+ groq_api_key = os.getenv("GROQ_API_KEY")
634
+ session_rag = SessionRAG(session_id, groq_api_key)
635
+
636
+ session_logger.info(f"Loading existing session data with {len(chunks_list)} chunks")
637
+ load_start = time.time()
638
+ session_rag.load_existing_session_data(chunks_list)
639
+ load_duration = time.time() - load_start
640
+ session_logger.info(f"Session data loaded in {load_duration:.2f}s")
641
+
642
+ session_store = {
643
+ "session_rag": session_rag,
644
+ "indexed": True,
645
+ "metadata": {
646
+ "session_id": session_id,
647
+ "title": session_doc.get("filename", "Document"),
648
+ "chunk_count": len(chunks_list),
649
+ "loaded_at": datetime.utcnow(),
650
+ "load_time": load_duration,
651
+ "document_info": {"filename": session_doc.get("filename", "Unknown")}
652
+ }
653
+ }
654
+ session_logger.info("=== SESSION LOADING COMPLETE ===")
655
+ return session_store
656
+
657
+ except Exception as rag_error:
658
+ session_logger.error(f"Failed to create/load SessionRAG: {rag_error}", exc_info=True)
659
+ raise ValueError(f"Failed to initialize RAG system: {str(rag_error)}")
660
+
661
+ # Add a health check specifically for the chat endpoint
662
+ @app.get("/health/chat")
663
+ async def chat_health_check():
664
+ """Specific health check for chat functionality"""
665
+ issues = []
666
+
667
+ if not RAG_MODELS_INITIALIZED:
668
+ issues.append("RAG models not initialized")
669
+
670
+ if not APP_STATE["mongodb_connected"]:
671
+ issues.append("MongoDB not connected")
672
+
673
+ if not FAISS_AVAILABLE:
674
+ issues.append("FAISS not available")
675
+
676
+ groq_key = os.getenv("GROQ_API_KEY")
677
+ if not groq_key:
678
+ issues.append("GROQ API key not configured")
679
+
680
+ return {
681
+ "status": "healthy" if not issues else "unhealthy",
682
+ "issues": issues,
683
+ "components": {
684
+ "rag_models": RAG_MODELS_INITIALIZED,
685
+ "mongodb": APP_STATE["mongodb_connected"],
686
+ "faiss": FAISS_AVAILABLE,
687
+ "groq_key_configured": bool(groq_key)
688
+ }
689
+ }
690
+
691
  if __name__ == "__main__":
692
  import uvicorn
693
  port = int(os.getenv("PORT", 7861))