Intelex / backend /api /sources.py
yakub
feat: implement real-time source ingestion progress, chitchat intent classifier, and empty state fallback
fd1e711
Raw
History Blame Contribute Delete
3.45 kB
from fastapi import APIRouter, HTTPException
from backend.database.connection import get_connection
from backend.vectorstore import delete_vectors
from pathlib import Path
import os
router = APIRouter()
@router.get("/sources")
def get_sources():
"""
GET /sources
Returns all ingested sources for the frontend dashboard,
knowledge sources page, and sidebar preview.
"""
with get_connection() as conn:
cursor = conn.cursor(dictionary=True)
cursor.execute("""
SELECT
id,
type,
title,
origin,
language,
chunk_count AS chunkCount,
status,
progress_percentage,
error_message,
created_at AS createdAt
FROM sources
ORDER BY created_at DESC
""")
sources = cursor.fetchall()
# Convert datetime to ISO string for JSON serialization
for s in sources:
if s["createdAt"]:
s["createdAt"] = s["createdAt"].isoformat()
return {"sources": sources}
@router.get("/sources/{source_id}")
def get_source_progress(source_id: str):
"""
GET /sources/{source_id}
Returns details for a single source, including progress_percentage and error_message.
"""
with get_connection() as conn:
cursor = conn.cursor(dictionary=True)
cursor.execute("""
SELECT
id,
type,
title,
origin,
language,
chunk_count AS chunkCount,
status,
progress_percentage,
error_message,
created_at AS createdAt
FROM sources
WHERE id = %s
""", (source_id,))
source = cursor.fetchone()
if not source:
raise HTTPException(status_code=404, detail="Source not found")
# Convert datetime to ISO string for JSON serialization
if source["createdAt"]:
source["createdAt"] = source["createdAt"].isoformat()
return source
@router.delete("/sources/{source_id}")
def delete_source(source_id: str):
"""
DELETE /sources/{id}
Deletes a source and all its chunks from FAISS, MySQL, and disk.
"""
with get_connection() as conn:
cursor = conn.cursor(dictionary=True)
cursor.execute(
"SELECT id, type, origin FROM sources WHERE id = %s",
(source_id,)
)
source = cursor.fetchone()
if not source:
raise HTTPException(status_code=404, detail="Source not found")
cursor.execute(
"SELECT id FROM chunks WHERE source_id = %s",
(source_id,)
)
chunk_rows = cursor.fetchall()
chunk_ids = {row["id"] for row in chunk_rows}
if chunk_ids:
delete_vectors(chunk_ids)
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute("DELETE FROM sources WHERE id = %s", (source_id,))
conn.commit()
if source["type"] == "pdf" and source["origin"]:
pdf_path = Path(source["origin"])
if pdf_path.exists():
os.remove(pdf_path)
print(f"[Sources] Deleted file: {pdf_path}")
print(f"[Sources] Deleted source: {source_id} ({len(chunk_ids)} chunks)")
return {"message": "Source deleted successfully", "id": source_id}