diff --git a/docs/architecture.md b/docs/architecture.md index d846223..2fae2eb 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -236,7 +236,7 @@ Control: Risk: -- transcription quality varies by handwriting and image quality +- transcription quality varies by document type, handwriting legibility, and image quality Control: diff --git a/docs/index.md b/docs/index.md index a4471d9..441a8ca 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -## Handwriting Transcription System +## Document Transcription System This project is a production application for transcribing and preserving historical family documents. It is intentionally designed for personal-scale use, with a simplicity-first architecture that is easy to operate and easy to extend. diff --git a/docs/mvp.md b/docs/mvp.md index 867716f..352cedf 100644 --- a/docs/mvp.md +++ b/docs/mvp.md @@ -1,14 +1,14 @@ ## MVP Definition: Historical Document Transcription System ### 1. MVP Objective -Deliver the thinnest possible end-to-end vertical slice — a user uploads an image of a handwritten document, the system transcribes it via an AI provider, and the user reads the resulting transcript — with just enough persistence and structure to validate the core value proposition: *can AI-driven transcription, guided by curated prompts, produce useful verbatim transcripts of historical family documents?* +Deliver the thinnest possible end-to-end vertical slice — a user uploads an image of a document, the system transcribes it via a configurable AI provider, and the user reads the resulting transcript — with just enough persistence and structure to validate the core value proposition: *can AI-driven transcription, guided by curated prompts, produce useful verbatim transcripts of historical family documents?* -The MVP deliberately defers full-text search, export, revision history, MongoDB, timeline assembly, and multi-provider routing. These are additive features that don't need validation before the core transcription loop is proven. +The MVP deliberately defers full-text search, export, revision history, MongoDB, and timeline assembly. These are additive features that don't need validation before the core transcription loop is proven. --- ### 2. Core User Story -*As a family historian, I can upload a photo of a handwritten letter, wait for it to be transcribed, and read the verbatim transcript — so I can evaluate whether this system will work for my thousands of documents.* +*As a family historian, I can upload a photo of a historical document, wait for it to be transcribed, and read the verbatim transcript — so I can evaluate whether this system will work for my thousands of documents.* --- @@ -47,12 +47,12 @@ The MVP deliberately defers full-text search, export, revision history, MongoDB, * An in-process background worker (Python asyncio task or BackgroundTasks) that: 1. Picks up queued jobs. 2. Transitions status to processing. - 3. Sends the image + the curated Markdown prompt to an AI vision model (OpenAI API — already a dependency). + 3. Sends the image + the curated Markdown prompt to an AI vision model via the configured provider (OpenRouter or Gemini). 4. On success: saves the transcript text, transitions to transcribed. 5. On failure: saves the error detail, transitions to failed. #### Feature 3: Transcription Prompt (Markdown Asset) -* A single Markdown file (prompts/transcribe_handwriting.md) encoding the verbatim transcription rules from Intent.md (the Document Issues table, scholarly guidelines, etc.). +* A single Markdown file (prompts/transcribe_document.md) encoding the verbatim transcription rules from Intent.md (the Document Issues table, scholarly guidelines, etc.). * The worker reads this file at invocation time and injects it as the system/user prompt. #### Feature 4: Job Status & Transcript Viewer (UI) @@ -71,8 +71,10 @@ The MVP deliberately defers full-text search, export, revision history, MongoDB, #### Feature 6: Centralized Configuration * A single config.py (or Pydantic BaseSettings) loading: - * OPENAI_API_KEY (required) - * OPENAI_MODEL (default: gpt-4o) + * PROVIDER (default: openrouter; options: openrouter, gemini) + * PROVIDER_API_KEY (required) + * PROVIDER_MODEL (default: provider-appropriate default) + * PROVIDER_BASE_URL (default: provider-appropriate default; overridable) * DATABASE_URL (default: sqlite:///./transcription.db) * UPLOAD_DIR (default: ./uploads) * PROMPT_DIR (default: ./prompts) @@ -94,10 +96,10 @@ The MVP deliberately defers full-text search, export, revision history, MongoDB, │ │ (upload, job lifecycle) │ │ │ └─────┬─────────────┬───────┘ │ │ │ │ │ -│ ┌─────▼─────┐ ┌─────▼─────────────┐ │ -│ │ SQLite DB │ │ Background Worker │ │ -│ │ (SQLModel)│ │ → OpenAI Vision │ │ -│ └───────────┘ └───────────────────┘ │ +│ ┌─────▼─────┐ ┌─────▼───────────────┐ │ +│ │ SQLite DB │ │ Background Worker │ │ +│ │ (SQLModel)│ │ → AI Vision Provider│ │ +│ └───────────┘ └─────────────────────┘ │ │ │ │ │ ┌─────▼──────┐ │ │ │ prompts/ │ │ @@ -114,18 +116,23 @@ The MVP deliberately defers full-text search, export, revision history, MongoDB, project-root/ ├── docs/ # (existing) ├── prompts/ -│ └── transcribe_handwriting.md # curated transcription prompt +│ └── transcribe_document.md # curated transcription prompt ├── src/ -│ └── handwriting/ +│ └── transcription/ │ ├── __init__.py │ ├── app.py # FastAPI + NiceGUI app entrypoint │ ├── config.py # Pydantic BaseSettings │ ├── models.py # SQLModel: Document, Job, Transcript │ ├── db.py # engine, session, create_all +│ ├── providers/ +│ │ ├── __init__.py +│ │ ├── base.py # provider interface (transcribe contract) +│ │ ├── openrouter.py # OpenRouter via openai client +│ │ └── gemini.py # Google Gemini │ ├── services/ │ │ ├── __init__.py │ │ ├── upload.py # save file + create records -│ │ └── transcription.py # call AI provider, update job +│ │ └── transcription.py # call provider, update job │ ├── worker.py # background job loop │ └── ui/ │ ├── __init__.py @@ -144,8 +151,8 @@ project-root/ #### 7. MVP Validation Criteria The MVP is considered validated when: -1. ✅ A user can upload an image of a handwritten document through the browser. -2. ✅ The system asynchronously sends the image to OpenAI's vision model with the curated prompt. +1. ✅ A user can upload an image of a document through the browser. +2. ✅ The system asynchronously sends the image to the configured AI vision model with the curated prompt. 3. ✅ The transcript (or failure reason) is persisted and visible in the UI. 4. ✅ The transcription follows verbatim scholarly rules defined in Intent.md (spot-checked by the user on real family documents). 5. ✅ The transcription prompt is stored as a standalone Markdown file and can be edited without code changes. @@ -158,7 +165,7 @@ These are the real unknowns this MVP exists to resolve: | # | Question | How We Learn | | --- | --- | --- | -| 1 | Is AI transcription quality good enough for this handwriting corpus? | User reviews 20–50 real transcriptions against originals. | +| 1 | Is AI transcription quality good enough for this document corpus? | User reviews 20–50 real transcriptions against originals. | | 2 | Does the verbatim prompt produce scholarly-quality output, or does it need major rework? | Compare output to the Document Issues table rules in Intent.md. | | 3 | What document types are hardest (old cursive, faded ink, pencil, postcards)? | Track which uploads produce failed or low-quality results. | | 4 | Is single-image upload sufficient, or is batch upload needed early? | User friction during real scanning sessions. | @@ -184,10 +191,10 @@ Recommended build order for the MVP (each step produces a testable increment): | Step | Deliverable | Validates | | --- | --- | --- | | 1 | config.py + models.py + db.py — data layer with SQLite | Schema and config foundation | -| 2 | prompts/transcribe_handwriting.md — curated prompt from Intent.md | Prompt asset pattern | -| 3 | services/transcription.py — call OpenAI vision API with prompt + image | Core AI integration | +| 2 | prompts/transcribe_document.md — curated prompt from Intent.md | Prompt asset pattern | +| 3 | services/transcription.py + providers/ — call AI vision provider with prompt + image | Core AI integration | | 4 | services/upload.py + worker.py — upload handling + background job loop | End-to-end pipeline (CLI-testable) | | 5 | ui/upload_page.py + ui/jobs_page.py — NiceGUI pages | User-facing interface | | 6 | tests/ — unit + integration tests Automated verification | -This MVP is deliberately narrow: **one prompt, one provider, one user, one image at a time, SQLite, no containers**. Every omission is intentional — the goal is to get real family documents through the transcription pipeline as fast as possible and let the quality of the output guide every subsequent decision. \ No newline at end of file +This MVP is deliberately narrow: **one prompt, one configurable provider, one user, one image at a time, SQLite, no containers**. Every omission is intentional — the goal is to get real family documents through the transcription pipeline as fast as possible and let the quality of the output guide every subsequent decision. \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index d4d6fe6..d2a7ad4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,7 @@ description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [ + "google-genai>=1.0.0", "openai>=2.43.0", "pydantic>=2.13.4", ]