Spaces:
Runtime error
Runtime error
| import uuid | |
| import os | |
| import time | |
| from fastapi import APIRouter, Depends, HTTPException, status, File, UploadFile, Form | |
| from sqlalchemy.orm import Session | |
| from langchain_core.documents import Document as LCDocument | |
| from ... import deps | |
| from ....core.config import settings | |
| from ....db.init_db import q_client, COLLECTION_NAME, get_vector_store | |
| from ....models.user import User | |
| from ....models.document import Document | |
| from ....services.pdf_processor import process_pdf | |
| from ....services.rag_service import rag_service | |
| from qdrant_client.http import models as rest | |
| router = APIRouter() | |
| async def upload_document( | |
| file: UploadFile = File(...), | |
| session_id: str = Form(None), | |
| db: Session = Depends(deps.get_db), | |
| current_user: User = Depends(deps.get_current_active_user) | |
| ): | |
| query = db.query(Document).filter( | |
| Document.user_id == str(current_user.id), | |
| Document.filename == file.filename | |
| ) | |
| if session_id: | |
| query = query.filter(Document.session_id == session_id) | |
| else: | |
| query = query.filter(Document.session_id == None) | |
| if query.first(): | |
| raise HTTPException(status_code=409, detail=f"Document '{file.filename}' already indexed.") | |
| temp_path = f"temp_{uuid.uuid4()}_{file.filename}" | |
| with open(temp_path, "wb") as buffer: | |
| buffer.write(await file.read()) | |
| start_time = time.time() | |
| try: | |
| chunks = process_pdf(temp_path, current_user.id, file.filename, session_id) | |
| if not chunks: | |
| raise HTTPException(status_code=400, detail="No text extracted") | |
| # Legal Audit | |
| text_sample = "\n".join([c["text"] for c in chunks[:3]]) | |
| if not rag_service.validate_is_legal(text_sample): | |
| raise HTTPException(status_code=400, detail="Not a legal document") | |
| vector_store = get_vector_store(rag_service.embeddings) | |
| docs = [LCDocument(page_content=c["text"], metadata=c["metadata"]) for c in chunks] | |
| vector_store.add_documents(docs) | |
| embed_time = time.time() - start_time | |
| new_doc = Document( | |
| user_id=str(current_user.id), | |
| filename=file.filename, | |
| session_id=session_id, | |
| chunk_count=len(chunks), | |
| embed_time_seconds=round(embed_time, 2) | |
| ) | |
| db.add(new_doc) | |
| db.commit() | |
| return { | |
| "message": f"Successfully indexed {file.filename}", | |
| "chunks": len(chunks), | |
| "time": round(embed_time, 2) | |
| } | |
| finally: | |
| if os.path.exists(temp_path): | |
| os.remove(temp_path) | |
| def get_user_documents(db: Session = Depends(deps.get_db), current_user: User = Depends(deps.get_current_active_user)): | |
| from ....models.chat import ChatSession | |
| # Efficiently join Document and ChatSession to avoid N+1 queries (lookup speed-up) | |
| query_results = db.query(Document, ChatSession.title).outerjoin( | |
| ChatSession, Document.session_id == ChatSession.id | |
| ).filter(Document.user_id == str(current_user.id)).all() | |
| results = [] | |
| for doc, chat_title in query_results: | |
| results.append({ | |
| "id": doc.id, | |
| "filename": doc.filename, | |
| "date": doc.upload_date, | |
| "session_id": doc.session_id, | |
| "session_title": chat_title or "Direct Upload", | |
| "chunks": doc.chunk_count or 0, | |
| "embed_time": doc.embed_time_seconds or 0 | |
| }) | |
| return {"documents": results} | |
| def get_session_documents( | |
| session_id: str, | |
| db: Session = Depends(deps.get_db), | |
| current_user: User = Depends(deps.get_current_active_user) | |
| ): | |
| docs = db.query(Document).filter( | |
| Document.user_id == str(current_user.id), | |
| Document.session_id == session_id | |
| ).all() | |
| return { | |
| "documents": [{"filename": d.filename, "chunks": d.chunk_count} for d in docs] | |
| } | |
| def delete_document(filename: str, db: Session = Depends(deps.get_db), current_user: User = Depends(deps.get_current_active_user)): | |
| # Find all variants (different sessions) of this filename for this user | |
| docs = db.query(Document).filter(Document.user_id == str(current_user.id), Document.filename == filename).all() | |
| if not docs: | |
| raise HTTPException(status_code=404, detail="Document not found") | |
| for doc in docs: | |
| db.delete(doc) | |
| db.commit() | |
| q_client.delete( | |
| collection_name=COLLECTION_NAME, | |
| points_selector=rest.Filter( | |
| must=[ | |
| rest.FieldCondition(key="metadata.user_id", match=rest.MatchValue(value=str(current_user.id))), | |
| rest.FieldCondition(key="metadata.filename", match=rest.MatchValue(value=filename)) | |
| ] | |
| ) | |
| ) | |
| return {"message": f"Deleted all instances of {filename}"} | |