AI Document Summarizer

Designing an AI feature from POC to production, with built-in quality measurement.

Complete LLM Next.js TypeScript OpenAI API

Stack: Next.js 14 · TypeScript · OpenAI GPT-4o-mini · shadcn/ui
Code: View on GitHub


The Problem

Users of learning management systems and document platforms upload dozens of files (lecture notes, worksheets, reports, scanned pages) and the only way to understand what each file contains is to open it one by one. In edtech, an educator might have 30 attachments in a single course module with no way to scan their content at a glance.

Alternatives like keyword extraction, tagging, or full-text search still require the user to interpret raw data. Summaries give an instant "should I care?" signal. They reduce cognitive load as well as improve findability.

The strategy: a narrow wedge. Summaries are generated automatically right after upload and shown inline wherever files appear. Immediate value with minimal user behavior change.


My Approach

How I think about building AI features:


What I Built

The POC is intentionally minimal. It validates the core UX pattern and prompt quality before adding infrastructure complexity.

POC Data Flow

Upload (drag-and-drop)
  → /api/upload (pdf-parse extracts text)
    → /api/summarize (parallel OpenAI calls: headline + bullets)
      → Summary Card (display + feedback widget)

How I Would Measure Success

These are the success criteria and measurement framework I designed for this feature. The metrics are pre-launch targets; the framework is designed to validate or adjust them with real usage data.

Tiered metrics framework

Metrics are sequenced around what you can learn at each stage. Start with "does it work?", then "is it valuable?", then "how do we improve?"

Tier 1: MVP launch (weeks 1-4): reliability

  • >95% summary generation rate: technical reliability baseline
  • P95 latency <10s: user-perceived performance
  • <1% error rate: system stability
  • <$0.10 cost per summary: economic sustainability

Tier 2: Post-MVP (months 2-3): value

  • >70% positive feedback (thumbs up): direct quality signal
  • >10% feedback rate: if fewer than 5% of users give any feedback, the quality signal isn't meaningful yet. A/B test the feedback UX before trusting the number.
  • <10% edit rate: the most important quality proxy. When users replace an AI summary with their own text, that's a direct signal the output isn't meeting expectations.
  • Measurable reduction in files opened per search (A/B test): efficiency gain

Tier 3: Optimization (month 3+): continuous improvement

  • Automated quality scores (LLM-as-judge): scalable measurement of faithfulness, relevance, and conciseness
  • Edit pattern analysis: what users consistently change reveals actionable prompt improvements
  • Time saved (user surveys): perceived value and ROI
Proxy metrics (no explicit feedback required)
  • Manual summary replacement rate. When users replace an AI summary with their own text, that's a direct quality signal. Thresholds: under 5% is excellent, 5-10% is healthy, 10-15% warrants investigation by file type, and above 20% means users are doing manual work and the feature is failing. Tracking what users change (not just how often) reveals actionable prompt improvements. For example, if users consistently add pricing details the summary missed, the prompt should be updated to extract pricing explicitly.
  • Session pattern analysis. If a user opens an attached file and returns to the app within 10 seconds, the file likely wasn't relevant, which may indicate a misleading summary. If they stay away for 2+ minutes, they're probably reading it, meaning the summary led them to the right content.
Metrics that don't work

Quick return rate (file opened then immediately closed) seems intuitive but is ambiguous. A user closing a file in under 10 seconds could mean three things: they were scanning multiple files (good behavior), the summary was misleading (bad quality), or the summary told them everything they needed (good summary). Without additional context, the metric is uninterpretable.

Similarly, "find files faster" only works if you first understand how users discover files (search, browse, or notification). The metric needs to be scoped to a specific discovery pattern before it means anything.

Quality management framework
  • Regression set: 20 representative documents (short, long, technical, non-technical) evaluated after each prompt change
  • Human rubric: scored 1-5 on four dimensions: correctness, coverage, specificity, tone
  • Prompt versioning: changes can be A/B tested behind feature flags and rolled back if quality drops
Failure acceptance

Not all failures are equal. A failed summarization that surfaces a clear error message and retry option is acceptable because the user knows what happened and what to do. A silently wrong summary is not acceptable because it erodes trust without the user knowing.

Cost model

Rough estimates (prices subject to change with provider pricing updates):

  • GPT-4o-mini input: ~$0.15 / 1M tokens
  • Avg tokens per summary pair: ~2,000
  • Cost per summary: ~$0.0003
  • 10K summaries / month: ~$3 / month

OCR and multi-format parsing add cost. Cost-per-summary is tracked as a production metric alongside quality; the goal is to optimize without quality loss.


Production Roadmap

The roadmap is sequenced around risk, not features. Each phase builds on the reliability and observability of the previous one.

Phase 1: Make the pipeline reliable

The POC is synchronous: the user waits while the API processes. Production needs to handle timeouts, retries, and long documents gracefully.

  • Async job queue: Supabase (chosen for built-in RLS, auth, and Postgres, giving one service for persistence and access control) creates a job row on upload. An AWS Lambda worker (serverless, scales to zero when idle, no infra to manage) processes jobs and writes results back.
  • Summary persistence: summaries are stored in Supabase and served from the database on subsequent views, not regenerated. This eliminates redundant API calls, reduces cost, and makes summaries available instantly across sessions.
  • Run telemetry from day 1: every summarization run logs the model, token count, latency, and errors to Supabase. This is non-negotiable. Without it, quality and cost issues are invisible.
  • Feature flags: enable or disable summarization without breaking existing upload flows. This is both a launch mechanism and a rollback mechanism.
Phase 2: Add trust and access control
  • Supabase Auth + RLS (row-level security): owner-only access by default. RLS is chosen over application-level permission checks because access control lives in the database layer, not scattered across API routes. A user cannot read another user's summaries, enforced at the query level.
  • Status-driven UX: the summary card reflects real job states (queued, processing, succeeded, failed) pulled from the database, not local ephemeral state.
  • Integration and E2E tests before expanding scope. The pipeline must be proven reliable before adding more complexity.
Phase 3: Expand capabilities
  • Multi-format support: .txt, .md, .docx in addition to PDF.
  • OCR for scanned PDFs: this comes after monitoring exists because OCR adds both cost and new failure modes that need the observability from Phase 1.
  • Custom summary replacement + regenerate: users can write their own summary (replacing the AI version) or regenerate a new AI summary. Both are trust mechanisms that give users control. Replacement rate also feeds back into quality measurement.
  • Manual and batch summarization: auto-summarization only covers new uploads. Manual triggers let users summarize existing files on demand, and batch triggers let admins backfill critical content sets. Without this, the feature only works going forward and ignores the existing library.
  • Coverage metric: files with summaries divided by total files in the system. Tracks adoption over time. Target: above 80% within 6 months through a combination of auto-summarization, manual triggers, and batch backfill.
Phase 4: Production and observability
  • Phased rollout via feature flags: start at 5% of users, expand to 25%, 50%, then 100% based on stability metrics. Rollback triggers: error rate exceeds 5%, P95 latency exceeds 10s, cost per summary exceeds $0.50, or user complaints exceed 10 tickets/day. Any trigger kills the feature instantly via feature flag, no code deploy required.
  • Vercel for hosting: zero-config Next.js deployment with preview environments per PR.
  • Dashboards: per-step latency, cost (tokens), success rate, breakdown by file type and provider.
  • Automated alerts: spend spikes, error-rate thresholds, queue backlog, timeout surges, with runbooks for each scenario.
  • Optimization based on production data: tune chunking, prompts, and retry strategies using real telemetry. Reduce cost without quality loss.
Phase 5: Future work
  • Graph database for document relationships: once summaries are persisted, they become a foundation for understanding relationships between documents. A graph database (e.g., Neo4j) can store semantic similarity edges between documents based on their summary embeddings.
  • Related document suggestions: when a user attaches a document to a project, the system suggests other documents with semantically similar content. This turns summaries from a passive feature (read and move on) into an active discovery tool.
  • Embedding pipeline: summaries are embedded at generation time and stored as vectors. Similarity is computed against the existing corpus, and relationships above a confidence threshold are written as edges in the graph. This runs asynchronously alongside summarization, reusing the same job queue infrastructure from Phase 1.

Architecture

POC (what exists today)

File Browser UI
  → Next.js /api/upload (pdf-parse extracts text)
    → Next.js /api/summarize (OpenAI GPT-4o-mini)
      → Summary Card (display + feedback widget)

Synchronous. In-memory. No persistence.

Production (designed)

File Browser UI
  → Next.js on Vercel (zero-config deploys, preview environments)
    → Supabase (Postgres + RLS + Auth: persistence, access control, job queue)
      → AWS Lambda (serverless async worker: extraction + summarization + retry)
        → Supabase (results + run telemetry)
          → Next.js (polling for status updates)
            → Summary Card (display + feedback widget)

Feature flags. Run telemetry. Monitoring dashboards.

The POC proves the UX pattern works. The production architecture makes it reliable, secure, and observable at scale. A key shift: summaries move from ephemeral (generated on every request, lost on refresh) to persistent (stored in Supabase, served instantly on subsequent views).


Key Technical Decisions

Centralized prompts. All AI behavior lives in a single file (prompts/summarize.ts). Prompts are product decisions about tone, length, and specificity. Keeping them in one file makes them reviewable, versionable, and independently tunable without code changes.

Dual-call pattern. Short summary and expanded bullets are generated by parallel, independent OpenAI calls via Promise.all. This enables independent prompt tuning for each output format. A single structured-output call would couple them.

Error discrimination. The PDF parser inspects error messages to distinguish password-protected, corrupt, and image-only failures. Each returns a tailored user-facing message with a concrete next step. The user never sees a stack trace.

15,000 character truncation. A pragmatic token budget control for the POC. Production would use smarter chunking strategies informed by run telemetry data (document length distribution, truncation frequency).


What I Learned

The most consequential part of an AI feature is everything around the API call, including error handling, retry logic, quality measurement, and user trust. In this POC, the OpenAI integration was straightforward, so I focused on what actually creates the greatest impact: making the feature feel reliable.

Prompt engineering is a product concern. The prompts in this project are decisions about tone ("3rd person active voice"), length ("8 words or fewer"), and what to prioritize ("skip introductions, focus on substance"). These are product decisions, not engineering ones.

Defining success criteria before writing code changes what you build. The feedback widget exists because the measurement framework required it. The manual override feature exists because replacement rate is a proxy metric. Starting with "how will we know this works?" shapes the feature itself.


Resources

View on GitHub →