Skip to content

Latest commit

Β 

History

699 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

askPDF

A private, local PDF research assistant that reads your documents aloud and answers questions about them. Upload PDFs or capture webpages, then chat with your content using AIβ€”all running on your own machine, no subscriptions required.


πŸš€ Quick Start

1. Install Prerequisites

  • Docker and Docker Compose
  • A local LLM runtime (choose one):
    • Docker Model Runner (built into Docker Desktop)
    • Ollama (lightweight CLI)
    • LMStudio (GUI app)

2. Set Up Your LLM

πŸ“– Choose your LLM setup (click to expand)
  • copy .env.example file and rename it to .env file.
  • Pick an LLM server from below and set "LLM_API_URL' with the url accordingly

Option A: Docker Model Runner (Easiest)

  1. Enable Model Runner in Docker Desktop β†’ Settings β†’ Features
  2. Pull models:
    docker model pull ai/qwen3:latest
    docker model pull ai/nomic-embed-text-v1.5:latest
  3. Set LLM_API_URL in .env file to:
    LLM_API_URL=http://host.docker.internal:12434

Option B: Ollama

  1. Install Ollama
  2. Pull models:
    ollama pull llama3.2
    ollama pull nomic-embed-text
  3. Set LLM_API_URL in .env file to:
    LLM_API_URL=http://host.docker.internal:11434

Option C: LMStudio

  1. Install LMStudio
  2. Download a chat model and embedding model
  3. Start Local Server (port 1234)
  4. Set LLM_API_URL in .env file to:
    LLM_API_URL=http://host.docker.internal:1234/v1

3. Start the App

docker compose up --build

4. Use It!

  • Open: http://localhost:3000
  • Upload PDFs or add webpages
  • Click Play or select PDF text and use the read-aloud icon to hear documents aloud
  • Ask questions about your content

🌟 What You Can Do

οΏ½ Read & Listen

  • Text-to-Speech: High-quality voice reads your PDFs aloud
  • Sentence Tracking: Visual highlighting shows what's being read
  • Multiple Documents: Switch between PDFs and webpages with tabs
  • PDF Annotations: Highlight, draw, and comment directly on documents

πŸ€– Chat with Your Documents

  • AI Assistant: Ask questions about your uploaded content
  • Smart Memory: Remembers previous conversations in each thread
  • Web Search: Optionally include live internet results
  • Reasoning Display: See how the AI thinks through problems

🎨 Easy to Use

  • Modern Interface: Clean, intuitive design
  • Thread Organization: Keep different topics separate
  • Customizable: Adjust AI behavior per conversation
  • Private: Everything runs locally on your machine

πŸ“– How to Use

Getting Started

  1. Create a Thread - Use the sidebar to start a new conversation
  2. Add Content - Upload PDFs or add webpage URLs
  3. Start Reading - Click Play to hear documents aloud
  4. Ask Questions - Type questions in the chat

Reading & Audio

  • Play Controls: Click Play, or select PDF text and click the read-aloud icon in the selection menu
  • Voice Settings: Choose different voices and adjust speed (0.5x-2.0x)
  • Auto-Scroll: Document follows along automatically

Chatting with AI

  • Select Model: Choose your preferred AI model
  • Internet Search: Toggle to include live web results
  • View Reasoning: Expand panels to see AI thinking process
  • Semantic Memory: See which past conversations were used

Customization

  • Thread Settings: Click βš™οΈ to adjust AI behavior
  • System Role: Change the AI's persona
  • Tool Instructions: Guide how AI uses different tools
  • Custom Instructions: Add extra directions

πŸ”§ Technical Details

πŸ—οΈ Architecture & Services

System Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                      Docker Compose                                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    Frontend     β”‚   RAG Service   β”‚  Browser Captureβ”‚   PostgreSQL    β”‚      Weaviate       β”‚
β”‚   (Next.js)     β”‚    (FastAPI)    β”‚   (Selenium)    β”‚   (Primary DB)  β”‚   (Vector DB)       β”‚
β”‚   Port: 3000    β”‚   Port: 8000    β”‚   Port: 8090    β”‚   Port: 5432    β”‚   Port: 8080        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                   β”‚
                                                   β–Ό
                                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                     β”‚         DMR / Ollama / LMStudio / LLM        β”‚
                                     β”‚            (OpenAI-compatible)               β”‚
                                     β”‚             Port: 12434 (default)            β”‚
                                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Services Overview

Service Port Description
Frontend 3000 Next.js React app with PDF viewer, chat UI, thread management, and TTS
RAG Service 8000 FastAPI server for PDF processing, indexing, chat, and the integrated durable agent-task worker
Browser Capture 8090 Selenium-based service for interactive webpage capture and PDF conversion
PostgreSQL 5432 Primary database for threads, messages, files, settings, and annotations
Weaviate 8080 Vector database for semantic and memory search
DMR/Ollama/LMStudio 12434 Local LLM server (external, user-provided)

The current deployment runs rag-service as one Uvicorn process. Its integrated agent-task worker shares the service's PostgreSQL pool and uses database leases and checkpoints for restart recovery. Do not enable multiple Uvicorn/Gunicorn worker processes until agent execution is extracted into its planned dedicated service; each server process would otherwise start another task worker.

πŸ€– Advanced AI Features

Multi-Agent Architecture

  • Agent Workflow Runtime: LangGraph-powered Router RAG and Plan-and-Execute RAG workflows with persisted run metadata
  • Human-in-the-Loop Gates: Optional web-search approval and resumable checkpoints for agent runs awaiting review
  • Tool Contracts: First-party tool contracts for document search, memory recall, timeline search, web search, and clarification
  • Debug Traces: Run-level trace payloads for inspecting routes, node execution, tool calls, warnings, and errors

Reasoning & Thinking Support

  • Multi-Provider Extraction: Supports reasoning traces from Claude, OpenAI o-series, DeepSeek, QwQ, Qwen3-Thinking
  • Database Storage: Reasoning traces persisted alongside answers in PostgreSQL
  • UI Display: Expandable reasoning panels in chat bubbles for transparent AI thinking

RAG & Semantic Memory

  • Thread-Scoped Collections: Each thread has isolated vector collections in Weaviate
  • Multi-Source Retrieval: Simultaneous search across PDFs, webpages, and past conversations
  • Semantic Recollection: UI highlights which past messages were used in current answers
  • Context Management: Intelligent token budgeting for optimal LLM context window usage
πŸ› οΈ Technology Stack

RAG Service

Technology Purpose
FastAPI Web framework
LangChain LLM/Embedding integration
LangGraph Stateful multi-agent workflow
Weaviate Client Vector database operations
SQLModel ORM built on SQLAlchemy
SQLAlchemy Async database operations
Alembic Database migration management
asyncpg Async PostgreSQL driver

Browser Capture Service

Technology Purpose
Selenium WebDriver automation
Brave Browser Headless browser rendering
WeasyPrint PDF conversion fallback
FastAPI Service API framework

Frontend

Technology Purpose
Next.js React framework
Material-UI (MUI) UI components (v7)
EmbedPDF PDF rendering with annotations
react-markdown Chat message rendering
React Query Async state management
πŸ“ Project Structure
askpdf/
β”œβ”€β”€ docker-compose.yml          # Multi-service orchestration
β”œβ”€β”€ run_tests.sh               # Comprehensive test runner
β”œβ”€β”€ browser_capture/           # Selenium-based webpage capture service
β”œβ”€β”€ rag_service/               # FastAPI backend with AI, RAG, and database
β”‚   β”œβ”€β”€ app/
β”‚   β”‚   β”œβ”€β”€ api/               # REST API route handlers
β”‚   β”‚   β”œβ”€β”€ agent/             # Multi-agent AI system
β”‚   β”‚   β”œβ”€β”€ db/                # PostgreSQL data layer
β”‚   β”‚   β”œβ”€β”€ services/          # Business logic services
β”‚   β”‚   └── rag/               # RAG core logic
β”‚   └── tests/                 # Comprehensive test suite
└── frontend/                  # Next.js React application
    β”œβ”€β”€ src/
    β”‚   β”œβ”€β”€ components/        # UI components
    β”‚   β”œβ”€β”€ hooks/             # React hooks
    β”‚   └── lib/               # Utility functions
    └── package.json
βš™οΈ Configuration & Environment

Environment Variables

Environment variables are now managed using a .env file for better security and maintainability. The system uses two approaches:

  1. .env file - For user-configurable settings (models, database URLs, behavior settings)
  2. docker-compose.yml - For service-specific configuration (networking, basic service settings)

Quick Setup

  1. Copy the example file:

    cp .env.example .env
  2. Configure your LLM provider in .env:

    # Choose your LLM provider
    LLM_API_URL=http://host.docker.internal:1234/v1  # LMStudio
    # LLM_API_URL=http://host.docker.internal:11434   # Ollama  
    # LLM_API_URL=http://host.docker.internal:12434   # Docker Model Runner
  3. Review other settings in .env and adjust as needed for your use case.

Environment Variables Reference

User-Configurable Variables (.env file)

LLM Configuration

Variable Default Description
LLM_API_URL (none) External LLM server URL (Docker Model Runner/Ollama/LMStudio)

Model Configuration

Variable Default Description
LOCAL_EMBEDDING_MODEL BAAI/bge-m3 Single local embedding model to use
LOCAL_RERANKER_MODEL BAAI/bge-reranker-v2-m3 Single local reranker model to use
HF_TOKEN (optional) Hugging Face token for higher model-download rate limits
EMBEDDING_DEVICE cpu Device for embedding models (cpu/cuda/mps)
RERANKER_DEVICE cpu Device for reranker models (cpu/cuda/mps)

AI Behavior & Limits

Variable Default Description
DEFAULT_TOKEN_BUDGET 8192 Context window size for AI responses
REPLANS_LIMIT 3 Maximum allowed replans
MAX_CUSTOM_INSTRUCTIONS_CHARS 2000 Maximum custom instruction length
MAX_SYSTEM_ROLE_CHARS 500 Maximum system role description length
MAX_TOOL_INSTRUCTION_CHARS 500 Maximum tool instruction length
INTENT_AGENT_MAX_ITERATIONS 1 Maximum replans for intent agent
MAX_ITERATIONS_SUFFICIENT_COVERAGE 2 Iteration bonus for sufficient coverage
MAX_ITERATIONS_PROBABLY_SUFFICIENT_COVERAGE 4 Iteration bonus for probable sufficient coverage
WEB_SEARCH_ITERATION_BONUS 2 Extra replans when web search is enabled

Document Processing (Docling)

Variable Default Description
DOCLING_DO_OCR True Enable OCR for scanned images (preserves digital text)
DOCLING_DO_TABLE_STRUCTURE True Extract table structure from documents
DOCLING_TABLE_MODE ACCURATE Table extraction mode (FAST/ACCURATE)
DOCLING_FORCE_FULL_PAGE_OCR False Force full-page OCR (keep false for digital PDFs)
DOCLING_DO_FORMULA_ENRICHMENT False Enable mathematical formula extraction

Database Configuration

Variable Default Description
DATABASE_URL postgresql+asyncpg://postgres:postgres@postgresql:5432/askpdf PostgreSQL connection string
TEST_DATABASE_URL postgresql+asyncpg://postgres:postgres@postgresql:5432/test_askpdf Test database connection string
POSTGRES_POOL_SIZE 10 Database connection pool size
POSTGRES_MAX_OVERFLOW 20 Maximum additional connections beyond pool size
Service-Specific Variables (docker-compose.yml)

Frontend Service

Variable Default Description
NEXT_PUBLIC_API_URL Required Public RAG service URL baked into the frontend at build time; the frontend refuses to start or build when it is missing or blank

RAG Service - Core Configuration

Variable Default Description
LOG_LEVEL INFO Logging level (DEBUG, INFO, WARNING, ERROR)
WEAVIATE_URL http://weaviate:8080 Weaviate vector database endpoint
WEAVIATE_HYBRID_ALPHA 0.7 Hybrid search balance (0.0=pure vector, 1.0=pure keyword)
CAPTURE_SERVICE_URL http://browser-capture:8080 Browser capture service endpoint
ASKPDF_AGENT_CHECKPOINTER memory (postgres in Docker/CI) LangGraph checkpointer backend for resumable agent runs (postgres or memory)
AGENT_CHECKPOINT_DATABASE_URL unset Optional Postgres URL override for LangGraph checkpoints; falls back to DATABASE_URL
ASKPDF_AGENT_CHECKPOINTER_SETUP true Run LangGraph Postgres checkpointer setup on startup/use
ASKPDF_AGENT_CHECKPOINTER_ALLOW_MEMORY_FALLBACK unset Explicit opt-in to memory fallback when ASKPDF_AGENT_CHECKPOINTER=postgres is misconfigured
AGENT_RUNTIME_MODE external LangGraph execution transport: external for the runtime service or explicit in_process for development images that install LangGraph
LANGGRAPH_RUNTIME_URL http://langgraph-runtime:8100 Internal URL used when AGENT_RUNTIME_MODE=external
ASKPDF_CONTENT_ROOT /static Backend-only shared-volume root for PDFs and Deep Research artifacts

Agent Runtime Operations

  • Bare Python processes default to the in-memory LangGraph checkpointer for local development and unit tests. Docker and CI explicitly set ASKPDF_AGENT_CHECKPOINTER=postgres so paused HITL runs survive process restarts.
  • Postgres checkpointer mode fails closed when the saver package or database URL is missing. Set ASKPDF_AGENT_CHECKPOINTER_ALLOW_MEMORY_FALLBACK=true only for local debugging where losing resumable checkpoints is acceptable.
  • Built-in workflow JSON files are loaded and seeded automatically at startup. Their runtime features, limits, and profiles are authoritative; no workflow feature flags are required.
  • The visible web-search approval toggle is a UI/thread-settings convenience shim. New agent runs normalize it into config.hitl_policy.gates.web_approval_gate, and the reusable backend contract is hitl_policy.gates, where gates can target any actionable graph node by node_id or node_type and run before or after that node.
  • Agent debug traces redact secret-like keys such as tokens, API keys, cookies, and authorization headers, and bound long preview/raw values before persisting.
  • Stale running-run cleanup and pending-interrupt expiration are separate operations. Cleanup for stale running rows must not mark awaiting_human runs failed; pending review rows should transition through interrupt expiration.
  • Checkpoint pruning should be limited to terminal run statuses (completed, clarification, failed, rejected, expired) and should not delete checkpoints for active awaiting_human runs.
  • The Hermes Phase 7 gateway is an opt-in development proof, not a production runtime. Its file journal rewrites the entire journal on every update, retains events indefinitely, and is restricted to one worker and one replica. Do not deploy it to production until it uses PostgreSQL or another shared transactional journal with a retention policy.

Start the Hermes proof only when a separate Hermes API is reachable:

HERMES_API_URL=http://host.docker.internal:<port> \
docker compose --profile second-runtime-proof up

The Hermes container uses /readyz for deployment health; /healthz is liveness-only and does not prove that Hermes can execute requests.

Setup Instructions

  1. Initial Setup: Copy .env.example to .env and configure your settings:

    cp .env.example .env
    # Edit .env with your preferred settings
  2. Apply Changes: After modifying environment variables, restart the services:

    docker compose down
    docker compose up --build

Docker Portability

The Compose setup builds the frontend with npm ci inside Docker and runs the production Next.js standalone server, so users do not need Node or npm installed locally.

For frontend development with hot reload, add the dev override:

docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build

Model Requirements

You need a chat model with tool calling support and an embedding model:

Runtime Chat model example Embedding model example
DMR ai/qwen3:latest ai/nomic-embed-text-v1.5:latest
Ollama llama3.2 nomic-embed-text
LMStudio google/gemma-3-12b text-embedding-embeddinggemma-300m-qat
πŸ“ API Reference

Key Endpoints

Chat & Threads

  • POST /api/threads - Create new thread
  • POST /api/threads/{thread_id}/chat - Chat with documents
  • PUT /api/threads/{thread_id}/settings - Update thread settings
  • GET /api/threads/{thread_id}/messages - List messages

Files & Documents

  • POST /api/threads/{thread_id}/files/upload - Upload PDF
  • GET /api/threads/{thread_id}/files/{file_hash} - Get file data
  • GET /api/threads/{thread_id}/files/{file_hash}/status - Check processing status

Models & Health

  • GET /api/models - List available models
  • GET /api/health/chat-model/{model} - Check chat model health
  • GET /api/health/embed-model/{model} - Check embedding model health
πŸ§ͺ Testing

Running Tests

./run_tests.sh [options]

The test runner is Docker-native. run_tests.sh starts an isolated askpdf-test Compose project with its own PostgreSQL, Weaviate, network, and volumes, so macOS, Linux, Windows with Docker/WSL, and GitHub Actions all use the same test environment. The normal app stack can keep running while tests run because the test services do not publish host ports.

You can also run the test container directly:

docker compose -p askpdf-test -f docker-compose.test.yml run --rm --build test-runner
docker compose -p askpdf-test -f docker-compose.test.yml run --rm --build test-runner --api
docker compose -p askpdf-test -f docker-compose.test.yml run --rm --build test-runner --group db

Set ASKPDF_TEST_PROJECT_NAME to override the isolated Compose project name. Set ASKPDF_KEEP_TEST_CONTAINERS=1 to keep test containers and volumes after a run for debugging.

Test Options

  • --verbose - Verbose output
  • --file <file> - Run specific test file
  • --test <test> - Run a specific test inside --file
  • --coverage - Run with coverage report
  • --unit - Run unit and mock-based tests
  • --db / --db-tests / --db-only - Run PostgreSQL database tests
  • --api - Run API endpoint tests
  • --integration - Run integration tests
  • --agent-checkpoint - Run the Postgres checkpoint/resume hardening test
  • --schema - Run schema guardrail tests
  • --standalone - Run standalone verification scripts
  • --all / --all-tests - Run the full pytest suite plus standalone checks

Test Categories

  • Database Tests: PostgreSQL operations, models, repositories
  • API Tests: Endpoint testing, integration tests
  • Parsing Tests: PDF processing with Docling and pdfplumber

CI and Merge Gates

GitHub Actions runs Docker build, the default Docker test runner, and a focused Postgres checkpoint/resume hardening lane on pull requests and pushes to main. To block merges unless CI passes, configure a branch ruleset in GitHub:

  1. Go to Settings β†’ Rules β†’ Rulesets.
  2. Create a ruleset for main.
  3. Require pull requests before merging.
  4. Require status checks to pass.
  5. Select the Docker build and Test suite checks from the CI workflow.
  6. Block force pushes and branch deletions.

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

πŸ“„ License

This project uses the following third-party technologies:

πŸ™ Acknowledgments

  • hexgrad for the amazing Kokoro-82M model
  • spaCy for robust NLP capabilities
  • LangChain team for the excellent LLM framework
  • Weaviate for the powerful vector database
  • The open-source community for all the amazing tools

πŸ“§ Contact

For questions, issues, or suggestions, please open an issue on the GitHub repository.

About

Chat with & listen to your PDFs locally. A full-stack RAG assistant featuring synchronized Text-to-Speech (TTS), AI document chat, and 100% local execution for total privacy.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages