Update app.py
Browse files
app.py
CHANGED
|
@@ -209,7 +209,7 @@ def get_or_load_session(session_id: str) -> Dict[str, Any]:
|
|
| 209 |
|
| 210 |
async def save_chat_message_safely(session_id: str, role: str, message: str):
|
| 211 |
"""Save chat messages to MongoDB asynchronously"""
|
| 212 |
-
if
|
| 213 |
return
|
| 214 |
try:
|
| 215 |
await asyncio.to_thread(
|
|
@@ -223,10 +223,10 @@ async def save_chat_message_safely(session_id: str, role: str, message: str):
|
|
| 223 |
)
|
| 224 |
except Exception as e:
|
| 225 |
logger.error(f"Failed to save chat message for session {session_id}: {e}")
|
| 226 |
-
|
| 227 |
def get_chat_history_safely(session_id: str, limit: int = 50) -> List[Dict[str, Any]]:
|
| 228 |
"""Get chat history from MongoDB with error handling"""
|
| 229 |
-
if
|
| 230 |
return []
|
| 231 |
try:
|
| 232 |
chats_cursor = DB.chats.find({"session_id": session_id}).sort("created_at", -1).limit(limit)
|
|
@@ -389,11 +389,11 @@ async def get_session_history(session_id: str):
|
|
| 389 |
"chat_history": history,
|
| 390 |
"count": len(history)
|
| 391 |
}
|
| 392 |
-
|
| 393 |
@app.get("/session/{session_id}/info")
|
| 394 |
async def get_session_info(session_id: str):
|
| 395 |
"""Get session metadata from MongoDB"""
|
| 396 |
-
if
|
| 397 |
raise HTTPException(status_code=503, detail="Database not connected")
|
| 398 |
|
| 399 |
session_doc = await asyncio.to_thread(DB.sessions.find_one, {"session_id": session_id})
|
|
@@ -413,6 +413,217 @@ async def get_session_info(session_id: str):
|
|
| 413 |
"in_memory": in_memory
|
| 414 |
}
|
| 415 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 416 |
@app.delete("/session/{session_id}/cache")
|
| 417 |
async def clear_session_cache(session_id: str):
|
| 418 |
"""Remove session from memory cache (data remains in MongoDB)"""
|
|
|
|
| 209 |
|
| 210 |
async def save_chat_message_safely(session_id: str, role: str, message: str):
|
| 211 |
"""Save chat messages to MongoDB asynchronously"""
|
| 212 |
+
if DB is None: # ✅ CORRECT
|
| 213 |
return
|
| 214 |
try:
|
| 215 |
await asyncio.to_thread(
|
|
|
|
| 223 |
)
|
| 224 |
except Exception as e:
|
| 225 |
logger.error(f"Failed to save chat message for session {session_id}: {e}")
|
| 226 |
+
|
| 227 |
def get_chat_history_safely(session_id: str, limit: int = 50) -> List[Dict[str, Any]]:
|
| 228 |
"""Get chat history from MongoDB with error handling"""
|
| 229 |
+
if DB is None: # ✅ CORRECT
|
| 230 |
return []
|
| 231 |
try:
|
| 232 |
chats_cursor = DB.chats.find({"session_id": session_id}).sort("created_at", -1).limit(limit)
|
|
|
|
| 389 |
"chat_history": history,
|
| 390 |
"count": len(history)
|
| 391 |
}
|
| 392 |
+
|
| 393 |
@app.get("/session/{session_id}/info")
|
| 394 |
async def get_session_info(session_id: str):
|
| 395 |
"""Get session metadata from MongoDB"""
|
| 396 |
+
if DB is None: # ✅ CORRECT
|
| 397 |
raise HTTPException(status_code=503, detail="Database not connected")
|
| 398 |
|
| 399 |
session_doc = await asyncio.to_thread(DB.sessions.find_one, {"session_id": session_id})
|
|
|
|
| 413 |
"in_memory": in_memory
|
| 414 |
}
|
| 415 |
|
| 416 |
+
@app.get("/debug/sessions/list")
|
| 417 |
+
async def list_all_sessions():
|
| 418 |
+
"""List all sessions in MongoDB to see what session IDs actually exist"""
|
| 419 |
+
if DB is None:
|
| 420 |
+
return {"error": "Database not connected"}
|
| 421 |
+
|
| 422 |
+
try:
|
| 423 |
+
# Get all sessions
|
| 424 |
+
sessions = list(DB.sessions.find({}, {
|
| 425 |
+
"session_id": 1,
|
| 426 |
+
"filename": 1,
|
| 427 |
+
"status": 1,
|
| 428 |
+
"created_at": 1,
|
| 429 |
+
"_id": 0
|
| 430 |
+
}).sort("created_at", -1).limit(20))
|
| 431 |
+
|
| 432 |
+
# Get total counts
|
| 433 |
+
total_sessions = DB.sessions.count_documents({})
|
| 434 |
+
total_chunks = DB.chunks.count_documents({})
|
| 435 |
+
|
| 436 |
+
return {
|
| 437 |
+
"total_sessions": total_sessions,
|
| 438 |
+
"total_chunks": total_chunks,
|
| 439 |
+
"recent_sessions": sessions,
|
| 440 |
+
"session_ids_only": [s["session_id"] for s in sessions]
|
| 441 |
+
}
|
| 442 |
+
|
| 443 |
+
except Exception as e:
|
| 444 |
+
return {"error": f"Failed to list sessions: {str(e)}"}
|
| 445 |
+
|
| 446 |
+
@app.get("/debug/sessions/search/{partial_id}")
|
| 447 |
+
async def search_sessions_by_partial_id(partial_id: str):
|
| 448 |
+
"""Search for sessions that contain the partial ID"""
|
| 449 |
+
if DB is None:
|
| 450 |
+
return {"error": "Database not connected"}
|
| 451 |
+
|
| 452 |
+
try:
|
| 453 |
+
# Search for sessions containing the partial ID
|
| 454 |
+
sessions = list(DB.sessions.find({
|
| 455 |
+
"session_id": {"$regex": partial_id, "$options": "i"}
|
| 456 |
+
}, {
|
| 457 |
+
"session_id": 1,
|
| 458 |
+
"filename": 1,
|
| 459 |
+
"status": 1,
|
| 460 |
+
"created_at": 1,
|
| 461 |
+
"_id": 0
|
| 462 |
+
}).limit(10))
|
| 463 |
+
|
| 464 |
+
return {
|
| 465 |
+
"search_term": partial_id,
|
| 466 |
+
"matches": sessions,
|
| 467 |
+
"match_count": len(sessions)
|
| 468 |
+
}
|
| 469 |
+
|
| 470 |
+
except Exception as e:
|
| 471 |
+
return {"error": f"Search failed: {str(e)}"}
|
| 472 |
+
|
| 473 |
+
@app.get("/debug/chunks/by-session/{session_id}")
|
| 474 |
+
async def debug_chunks_for_session(session_id: str):
|
| 475 |
+
"""Check if chunks exist for a session ID (maybe the chunks use a different ID format)"""
|
| 476 |
+
if DB is None:
|
| 477 |
+
return {"error": "Database not connected"}
|
| 478 |
+
|
| 479 |
+
try:
|
| 480 |
+
# Check exact match
|
| 481 |
+
chunks_exact = DB.chunks.count_documents({"session_id": session_id})
|
| 482 |
+
|
| 483 |
+
# Check partial matches (in case of ID truncation)
|
| 484 |
+
chunks_partial = list(DB.chunks.find({
|
| 485 |
+
"session_id": {"$regex": session_id[:8], "$options": "i"} # First 8 chars
|
| 486 |
+
}, {
|
| 487 |
+
"session_id": 1,
|
| 488 |
+
"chunk_id": 1,
|
| 489 |
+
"_id": 0
|
| 490 |
+
}).limit(5))
|
| 491 |
+
|
| 492 |
+
# Check if any chunks exist at all
|
| 493 |
+
sample_chunks = list(DB.chunks.find({}, {
|
| 494 |
+
"session_id": 1,
|
| 495 |
+
"_id": 0
|
| 496 |
+
}).limit(5))
|
| 497 |
+
|
| 498 |
+
return {
|
| 499 |
+
"searched_session_id": session_id,
|
| 500 |
+
"chunks_exact_match": chunks_exact,
|
| 501 |
+
"chunks_partial_matches": chunks_partial,
|
| 502 |
+
"sample_chunk_session_ids": [c.get("session_id") for c in sample_chunks]
|
| 503 |
+
}
|
| 504 |
+
|
| 505 |
+
except Exception as e:
|
| 506 |
+
return {"error": f"Chunk search failed: {str(e)}"}
|
| 507 |
+
|
| 508 |
+
|
| 509 |
+
@app.get("/debug/frontend-session")
|
| 510 |
+
async def debug_frontend_session_issue():
|
| 511 |
+
"""General debug info to help identify frontend/backend session ID mismatch"""
|
| 512 |
+
if DB is None:
|
| 513 |
+
return {"error": "Database not connected"}
|
| 514 |
+
|
| 515 |
+
try:
|
| 516 |
+
# Get sample of how session IDs are actually stored
|
| 517 |
+
sessions_sample = list(DB.sessions.find({}, {
|
| 518 |
+
"session_id": 1,
|
| 519 |
+
"_id": 0
|
| 520 |
+
}).limit(5))
|
| 521 |
+
|
| 522 |
+
chunks_sample = list(DB.chunks.find({}, {
|
| 523 |
+
"session_id": 1,
|
| 524 |
+
"_id": 0
|
| 525 |
+
}).limit(5))
|
| 526 |
+
|
| 527 |
+
# Get session ID patterns
|
| 528 |
+
session_id_lengths = {}
|
| 529 |
+
for session in sessions_sample:
|
| 530 |
+
sid = session.get("session_id", "")
|
| 531 |
+
length = len(sid)
|
| 532 |
+
if length not in session_id_lengths:
|
| 533 |
+
session_id_lengths[length] = []
|
| 534 |
+
session_id_lengths[length].append(sid)
|
| 535 |
+
|
| 536 |
+
return {
|
| 537 |
+
"sessions_collection": {
|
| 538 |
+
"sample_session_ids": [s.get("session_id") for s in sessions_sample],
|
| 539 |
+
"session_id_lengths": session_id_lengths
|
| 540 |
+
},
|
| 541 |
+
"chunks_collection": {
|
| 542 |
+
"sample_session_ids": [c.get("session_id") for c in chunks_sample]
|
| 543 |
+
},
|
| 544 |
+
"analysis": {
|
| 545 |
+
"frontend_looking_for": "5ca64618-04fb-48c3-bb15-9d06eb720033",
|
| 546 |
+
"frontend_id_length": len("5ca64618-04fb-48c3-bb15-9d06eb720033"),
|
| 547 |
+
"frontend_id_format": "UUID with dashes"
|
| 548 |
+
}
|
| 549 |
+
}
|
| 550 |
+
|
| 551 |
+
except Exception as e:
|
| 552 |
+
return {"error": f"Debug failed: {str(e)}"}
|
| 553 |
+
|
| 554 |
+
@app.get("/debug/session/{session_id}")
|
| 555 |
+
async def debug_session_status(session_id: str):
|
| 556 |
+
"""Enhanced debug endpoint to check session status in MongoDB"""
|
| 557 |
+
if DB is None:
|
| 558 |
+
return {"error": "Database not connected"}
|
| 559 |
+
|
| 560 |
+
try:
|
| 561 |
+
# Check session document
|
| 562 |
+
session_doc = DB.sessions.find_one({"session_id": session_id})
|
| 563 |
+
|
| 564 |
+
# Check chunks
|
| 565 |
+
chunks_count = DB.chunks.count_documents({"session_id": session_id})
|
| 566 |
+
|
| 567 |
+
# If exact match fails, try partial matching
|
| 568 |
+
partial_sessions = []
|
| 569 |
+
partial_chunks = 0
|
| 570 |
+
|
| 571 |
+
if not session_doc:
|
| 572 |
+
# Try searching with first 8 characters (common truncation)
|
| 573 |
+
short_id = session_id[:8] if len(session_id) >= 8 else session_id
|
| 574 |
+
partial_sessions = list(DB.sessions.find({
|
| 575 |
+
"session_id": {"$regex": f"^{short_id}", "$options": "i"}
|
| 576 |
+
}, {"session_id": 1, "filename": 1, "_id": 0}).limit(3))
|
| 577 |
+
|
| 578 |
+
partial_chunks = DB.chunks.count_documents({
|
| 579 |
+
"session_id": {"$regex": f"^{short_id}", "$options": "i"}
|
| 580 |
+
})
|
| 581 |
+
|
| 582 |
+
# Sample chunks for debugging
|
| 583 |
+
sample_chunks = list(DB.chunks.find(
|
| 584 |
+
{"session_id": session_id},
|
| 585 |
+
{"chunk_id": 1, "content": 1, "embedding": 1, "_id": 0}
|
| 586 |
+
).limit(2))
|
| 587 |
+
|
| 588 |
+
# Check if chunks have embeddings
|
| 589 |
+
chunks_with_embeddings = DB.chunks.count_documents({
|
| 590 |
+
"session_id": session_id,
|
| 591 |
+
"embedding": {"$exists": True, "$ne": None}
|
| 592 |
+
})
|
| 593 |
+
|
| 594 |
+
return {
|
| 595 |
+
"searched_session_id": session_id,
|
| 596 |
+
"session_id_length": len(session_id),
|
| 597 |
+
"exact_match": {
|
| 598 |
+
"session_exists": session_doc is not None,
|
| 599 |
+
"session_status": session_doc.get("status") if session_doc else None,
|
| 600 |
+
"session_filename": session_doc.get("filename") if session_doc else None,
|
| 601 |
+
"chunks_count": chunks_count,
|
| 602 |
+
"chunks_with_embeddings": chunks_with_embeddings,
|
| 603 |
+
},
|
| 604 |
+
"partial_matches": {
|
| 605 |
+
"sessions_found": partial_sessions,
|
| 606 |
+
"chunks_count": partial_chunks
|
| 607 |
+
},
|
| 608 |
+
"sample_chunks": [
|
| 609 |
+
{
|
| 610 |
+
"chunk_id": chunk.get("chunk_id"),
|
| 611 |
+
"content_length": len(chunk.get("content", "")),
|
| 612 |
+
"has_embedding": chunk.get("embedding") is not None
|
| 613 |
+
}
|
| 614 |
+
for chunk in sample_chunks
|
| 615 |
+
],
|
| 616 |
+
"in_memory_cache": session_id in SESSION_STORES,
|
| 617 |
+
"suggestions": [
|
| 618 |
+
"Check if session was created with different upload service",
|
| 619 |
+
"Verify frontend is using correct session ID from upload response",
|
| 620 |
+
"Check if session creation completed successfully"
|
| 621 |
+
]
|
| 622 |
+
}
|
| 623 |
+
|
| 624 |
+
except Exception as e:
|
| 625 |
+
return {"error": f"Debug failed: {str(e)}"}
|
| 626 |
+
|
| 627 |
@app.delete("/session/{session_id}/cache")
|
| 628 |
async def clear_session_cache(session_id: str):
|
| 629 |
"""Remove session from memory cache (data remains in MongoDB)"""
|