Spaces:
Runtime error
Runtime error
File size: 3,976 Bytes
c893230 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | """Re-queue ingestion for documents that still have files on disk.
Usage (from project root)::
python scripts/reingest_documents.py
python scripts/reingest_documents.py --tenant tenant_1j4bejfj
python scripts/reingest_documents.py --status failed --limit 20
python scripts/reingest_documents.py --only-missing-chunks --status complete
"""
from __future__ import annotations
import argparse
import asyncio
import logging
from pathlib import Path
from sqlalchemy import select
from app.db.database import get_session_factory, init_db
from app.db.models import Document, IngestStatus
from app.ingest.schedule import _background_tasks, schedule_ingest
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
logger = logging.getLogger(__name__)
async def _run(
*,
tenant_id: str | None,
statuses: tuple[IngestStatus, ...],
limit: int | None,
mark_missing_failed: bool,
only_missing_chunks: bool,
) -> None:
await init_db()
factory = get_session_factory()
from app.vectorstore.factory import get_vectorstore
vs = get_vectorstore()
queued = 0
missing = 0
skipped_indexed = 0
async with factory() as db:
q = select(Document).where(Document.status.in_(statuses))
if tenant_id:
q = q.where(Document.tenant_id == tenant_id)
rows = (await db.execute(q)).scalars().all()
for doc in rows:
path = Path(doc.file_path)
if not path.is_file():
missing += 1
if mark_missing_failed and doc.status != IngestStatus.failed:
doc.status = IngestStatus.failed
doc.error_message = f"Upload file not found: {path}"
continue
if only_missing_chunks and vs.count_for_doc(doc.id) > 0:
skipped_indexed += 1
continue
if limit is not None and queued >= limit:
break
doc.status = IngestStatus.pending
doc.error_message = None
schedule_ingest(doc_id=doc.id, file_path=path)
queued += 1
logger.info("Queued %s (%s)", doc.filename, doc.id)
if mark_missing_failed:
await db.commit()
logger.info(
"Done: queued=%d skipped_already_indexed=%d missing_files=%d (statuses=%s)",
queued,
skipped_indexed,
missing,
",".join(s.value for s in statuses),
)
if queued:
logger.info("Waiting for %d background ingest task(s)…", len(_background_tasks))
await asyncio.gather(*list(_background_tasks), return_exceptions=True)
logger.info("All queued ingests finished.")
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--tenant", default=None, help="Only this tenant_id")
parser.add_argument(
"--status",
action="append",
default=None,
choices=[s.value for s in IngestStatus],
help="Document statuses to retry (repeatable; default: failed, pending, processing)",
)
parser.add_argument("--limit", type=int, default=None, help="Max documents to queue")
parser.add_argument(
"--no-mark-missing",
action="store_true",
help="Do not mark rows with missing files as failed",
)
parser.add_argument(
"--only-missing-chunks",
action="store_true",
help="Skip documents that already have chunks in the vector index",
)
args = parser.parse_args()
status_values = args.status or ["failed", "pending", "processing"]
statuses = tuple(IngestStatus(s) for s in status_values)
asyncio.run(
_run(
tenant_id=args.tenant,
statuses=statuses,
limit=args.limit,
mark_missing_failed=not args.no_mark_missing,
only_missing_chunks=args.only_missing_chunks,
)
)
if __name__ == "__main__":
main()
|