{"slug": "turning-pdfs-docx-and-phone-photos-into-quiz-questions-what-actually-broke", "title": "Turning PDFs, DOCX and phone photos into quiz questions: what actually broke", "summary": "The developer behind SimpleQuizMaker described how the tool turns PDFs, DOCX files and phone photos into editable quiz questions, with most of the engineering effort going into input validation and output handling rather than the model call itself. Uploads are checked against magic bytes before parsing, model responses are requested in JSON mode and validated against a schema, and generation cost is estimated and capped against a user budget before each run. The developer said the biggest quality gain came from making every generated question editable before sharing, rather than trying to perfect the model's output.", "body_md": "I build SimpleQuizMaker, a tool that turns study material into an editable quiz. The model call takes about five lines. Getting clean input to the model, and keeping its output usable, took everything else. Here's what broke and how we handled it.\n\nBrowsers send whatever MIME type the OS guesses, and an attacker can send anything at all. Every upload is checked against its first bytes before we parse it: `%PDF` for PDFs, `FF D8 FF` for JPEG, `89 50 4E 47` for PNG, `PK` or `D0 CF` for DOCX/DOC. A file whose bytes don't match its claimed type is rejected. It's twelve bytes of reading, and it removes a whole class of problems.\n\n`pdf-parse` (v2 switched from a plain function to a class-based API, which broke our first upgrade).`mammoth` for raw text.\nWe ask the model for `response_format: { type: \"json_object\" }`. OpenAI rejects that unless the word \"json\" appears in the prompt. We have a comment in the code that says \"do not reword this sentence away\" because someone eventually will. And JSON mode guarantees valid JSON, not your schema, so every response is parsed and validated, and a malformed response fails loudly instead of rendering half a quiz.\n\nLong inputs plus a 100-question request can get expensive. Before each generation we estimate the cost from input length and expected output tokens for the chosen model, refuse if it would exceed the user's budget, and record the actual usage afterwards. If one feature makes two model calls, both go into the log, because both are billed.\n\nThe prompt asks for distractors built from common misconceptions, which makes a big difference in multiple-choice quality. But the bigger win was product-side: every question is editable before sharing. We stopped trying to make the output perfect and made it cheap to fix.\n\nIf you're building something similar, I'm happy to go deeper on any of these in the comments. The tool is at [simplequizmaker.com](https://simplequizmaker.com) (free tier available).", "url": "https://wpnews.pro/news/turning-pdfs-docx-and-phone-photos-into-quiz-questions-what-actually-broke", "canonical_source": "https://dev.to/mustafa_buraszeri_1e27/turning-pdfs-docx-and-phone-photos-into-quiz-questions-what-actually-broke-1cah", "published_at": "2026-11-15 00:47:18+00:00", "updated_at": "2026-11-15 00:55:04.623092+00:00", "lang": "en", "topics": ["ai-tools", "large-language-models", "ai-products", "generative-ai"], "entities": ["SimpleQuizMaker", "OpenAI", "pdf-parse", "mammoth"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/turning-pdfs-docx-and-phone-photos-into-quiz-questions-what-actually-broke", "markdown": "https://wpnews.pro/news/turning-pdfs-docx-and-phone-photos-into-quiz-questions-what-actually-broke.md", "text": "https://wpnews.pro/news/turning-pdfs-docx-and-phone-photos-into-quiz-questions-what-actually-broke.txt", "jsonld": "https://wpnews.pro/news/turning-pdfs-docx-and-phone-photos-into-quiz-questions-what-actually-broke.jsonld"}}