Importing a document¶
A PDF¶
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.
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¶
CSV or XLSX. Up to 5,000 rows and 8 MB.
| Column | Meaning |
|---|---|
question_text |
The stem |
option_a … option_e |
Up to five options |
correct_answer |
A letter, or the option's literal text |
explanation |
|
difficulty |
|
category |
Matched by name |
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.