Skip to content

Importing a document

A PDF

POST /api/v1/documents/upload

Moderator-only. PDFs only — checked by filename extension. Size-capped by MAX_UPLOAD_SIZE, which is 100 MB.

Why 100 MB and not more

Size here is work, not storage: a PDF is chunked, vectorised and then read by a model a chunk at a time. The two PREP books already in the bank are 900-odd pages each and fit only because a text export is small. nginx's client_max_body_size is set just above this — raising one without the other turns a clear 400 into a bare 413 from the proxy.

The upload dispatches the Celery task process_pdf, which extracts text page by page with PyMuPDF and stores the page chunks. If Celery or Redis is unreachable, it falls back to processing the file inside the request rather than accepting an upload that will never be processed.

Then, on the document's page, you pick a page range (a section), an extraction mode and a model, and run it.

POST /api/v1/drafts/extract

Moderator-only. Queues the Celery task extract_quiz. It always lands in a draft batch — never in a live question or quiz.

Watch it from /jobs. Progress steps are pushed to a Redis list per job.

A spreadsheet

POST /api/v1/drafts/import

CSV or XLSX. Up to 5,000 rows and 8 MB.

Column Meaning
question_text The stem
option_aoption_e Up to five options
correct_answer A letter, or the option's literal text
explanation
difficulty
category Matched by name

QTI

POST /api/v1/drafts/import/qti

QTI 2.1 XML, filename must end .xml. Reads assessmentItem, prompt, simpleChoice, correctResponse and modalFeedback.

There is no Anki .apkg import.

Categories named in a file are matched, never created

An import will not invent a category. Names it cannot match come back in an unknown_categories list on the response, and those questions arrive unfiled.

This is deliberate: a typo in a spreadsheet column should not silently grow the taxonomy that every question, article and deck is filed against.

Searching the bank by uploading a file

Separate feature, separate plumbing. The question bank lets you upload a document or a photograph as a query — "find me questions like this" — and that path has its own intake layer: PDF, DOCX or image only, 2 MB, with the type sniffed from the leading bytes and a DOCX zip-bomb guard. An extension is a claim, never the decision.

Nothing uploaded this way is stored, and it is never used for extraction. An image query is read by the tool model, and says so plainly when none is configured.

Nextcloud is gone

The Nextcloud browse-and-import integration was removed. It was a per-person cloud integration on a page only an educator reaches, for a corpus one person loads, and it asked every one of them for an app password. A front-end test now asserts the tab is absent. A direct file upload is the only ingestion path. The README has not caught up.