Skip to content

Chat with PDF Documents

Upload a PDF to give the current conversation its extracted text. Numi reads selectable text and can use local OCR for scanned pages when the server has the required software.

Attach a document, extract its text, and compare the answer with the original pages.

Upload and ask a question

  1. Open a chat and select Attach files beside the message input, or drag the PDF into the chat.
  2. Choose a PDF. The default upload limit is 25 MiB per file.
  3. Wait for Uploaded: filename.pdf. PDF processing finishes before this confirmation appears; a failure is shown beside the input.
  4. Send a question that names the document:
Summarize the main findings in report.pdf. Include the page numbers for the findings you use.

Check the answer against the original document, especially numbers and tables. OCR recovers text but does not reconstruct table structure reliably.

You can attach more than one PDF and refer to them by filename. Each chat has its own attachments; uploading a file does not make it available to every chat.

When the answer misses a page

PDF text is included in upload order and then page order, up to a shared limit of 12,000 characters by default. This is a bounded excerpt, not a searchable document index. Later pages or later documents may fall outside the excerpt.

Asking about page 50 does not change which pages are included. If the required section is missing, upload a smaller PDF containing that section in a new chat, or ask the operator to increase the context limit for a model with enough room.

Removing a pending attachment from the message input does not delete its stored PDF context. To work without that document, start a new chat. Do not delete an upload directly from the filesystem to remove its context: extracted page text is stored separately in the database.

Operator: enable OCR for scans

The Docker image includes Poppler, Tesseract, and English/German language data. For a native Debian/Ubuntu installation:

sudo apt-get install poppler-utils tesseract-ocr tesseract-ocr-eng tesseract-ocr-deu

Verify the installed tools:

pdftoppm -v
tesseract --list-langs

At least eng or deu must be listed. PDFs with selectable text do not need these OCR binaries. No external OCR service or OCR API key is used.

The extractor tries OCR on pages containing images and fewer than 100 extracted characters. It renders one page at a time, capped at 2400 pixels on its longest side, and keeps the OCR result only if it recovers more text. PDFs opened through fetch_web_page use the same extractor.

Operator: set processing limits

Set these environment variables in the server's deployment configuration and restart the server after changes. Extraction limits and prompt context limits serve different purposes: a PDF can process successfully while only its opening pages fit into the prompt.

Variable Default Limits
UPLOAD_MAX_UPLOAD_BYTES 26214400 Bytes per uploaded file
UPLOAD_MAX_PDF_WORKERS 2 Concurrent PDF extraction jobs
UPLOAD_MAX_PDF_PAGES 500 Pages per PDF
UPLOAD_MAX_PDF_TEXT_CHARS 2000000 Extracted characters per PDF
UPLOAD_PDF_TIMEOUT_SECONDS 45 Total extraction and OCR time
UPLOAD_PDF_MEMORY_MEGABYTES 768 Memory budget for each extraction worker
PROMPT_MAX_PDF_CONTEXT_CHARS 12000 Shared PDF text budget per chat prompt

The extractor runs in a separate process. A timeout stops that worker and its OCR subprocesses. Identical PDFs previously processed for the same user can reuse stored page text.

If an upload fails:

  • Processing is busy: retry after another upload finishes.
  • Time, page, or text limit exceeded: split the PDF, or adjust the relevant limit after checking server capacity.
  • No readable text: check scan quality and the installed OCR language data.
  • Missing OCR tools: verify pdftoppm and tesseract are on the server's executable path.

API upload

Use the authenticated file endpoints:

curl -X POST "http://localhost:4567/api/v1/upload?chat_id=YOUR_CHAT_UUID" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -F "file=@report.pdf"

A successful response contains the stored filename:

{"status": "success", "filename": "report.pdf"}

List the chat's files with GET /api/v1/chats/{chat_id}/files. No special prompt parameter is needed when sending a message in that chat.