Ask questions about PDFs and websites, with streamed answers and sources you can inspect.
A personal project exploring the full document Q&A flow: import content, retrieve relevant passages, generate an answer, and collect feedback.
Try the demo · Read the case study · Watch the recording
- Extracts text from PDFs and imports pages from websites, with progress updates.
- Stores document chunks and OpenAI embeddings in Supabase PostgreSQL with pgvector.
- Streams answers with numbered citations and clickable source details.
- Collects thumbs up/down feedback and adjusts the ranking of referenced chunks.
- Shows query history, feedback rates, frequently retrieved chunks, and possible knowledge gaps in an admin dashboard.
- Saves chat locally and reads older stored conversations after the AI SDK migration.
flowchart TD
A[PDF or website] --> B[Extract text and split into chunks]
B --> C[OpenAI embeddings]
C --> D[Supabase PostgreSQL + pgvector]
E[Question] --> F[Embed the question]
F --> D
D --> G[Retrieve up to six source passages]
G --> H[Generate claims with passage references]
H --> I[Check quoted passages and review claim support]
I --> L[Stream accepted claims with source links]
L --> J[Answer feedback]
J --> K[Adjust source chunk quality scores]
K --> D
| Choice | Reason and tradeoff |
|---|---|
| PostgreSQL + pgvector | Keep documents, vectors, queries, and feedback together. Vector search shares resources with application queries. |
| Source details alongside answers | Make answers easier to inspect. A citation is not an automatic correctness guarantee. |
| Streaming import and chat | Show progress during longer operations. Client state needs to handle partial results and errors. |
| Feedback-adjusted retrieval | Explore how user feedback can inform ranking. End-to-end feedback cannot separate retrieval errors from generation errors. |
| Legacy message normalization | Preserve local conversations when moving to the Vercel AI SDK message format. |
Stack: Next.js 14, React, TypeScript, Tailwind CSS, Supabase PostgreSQL, pgvector, OpenAI embeddings, and Vercel AI SDK for chat. The OpenAI SDK handles embeddings directly; chat uses @ai-sdk/openai.
npm ciRun these files in order in the Supabase SQL Editor:
supabase/migrations/0001_init.sql— base tables and vector search.supabase/migrations/0002_add_url_source.sql— URL source fields.supabase/migrations/0003_match_chunks_url.sql— URL details in search results.supabase/migrations/0004_feedback_quality.sql— feedback scores and usage statistics.supabase/migrations/0005_device_id.sql— device tracking and optional retrieval filtering.
Create .env.local:
OPENAI_API_KEY=your_openai_api_key
SUPABASE_URL=https://your_project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your_server_side_service_role_keyKeep the service role key server-side. Do not put it in a NEXT_PUBLIC_ variable or commit .env.local.
Both services are needed for the complete import and chat flow. Without Supabase, data is not persisted; without OpenAI, chat returns a configuration error and the embedding helper currently falls back to zero vectors. Configure OpenAI before importing documents.
npm run devhttp://localhost:3000— landing page.http://localhost:3000/app— document Q&A workspace.http://localhost:3000/admin— prototype monitoring dashboard.
For a production build:
npm run build
npm startpublic/sample-documents/ contains three one-page Harbour AI PDFs: a product brief, pilot results, and a safety policy. All facts and figures are fictional and must not be presented as AskBase performance measurements. Upload these files to run a reproducible demo:
- "For Harbour AI, compare the pilot targets with actual results. Which targets passed?" Expected: 30% handling-time reduction versus 40% target (fail), 96% citation correctness versus 95% target (pass), 3% unsupported answers versus below 2% (fail).
- "Can Harbour AI send replies or issue refunds without approval?" Expected: no; the beta requires human approval.
- "What does Harbour AI need to fix before unattended sending?" Expected: expired policies, ambiguous product identifiers, and tool timeouts; evaluate at least 100 new refund-policy tickets and recheck all three targets.
- "What is Harbour AI's approved public launch date?" Expected: not provided; the documents say no date has been approved.
- "What is Harbour AI's proposed monthly revenue at 10 paying shops?" Expected: AED 2,990 before costs, a proposal rather than actual revenue.
This is a working prototype, not a private document workspace. Document listing and chat retrieval currently use a shared corpus, and admin routes are not authenticated. Device identifiers are tracking data, not an access-control boundary. Use public or sample documents for the demo.
Next improvements:
- Authentication, protected admin routes, and enforced document access throughout the API and retrieval path.
- A retrieval evaluation set with known source passages, followed by hybrid search and reranking experiments.
- Evaluate whether the existing quote and model-review checks actually reject unsupported answers, and add query rewriting for follow-up questions. Retrieval currently embeds only the latest user message.
- Better handling of large documents, failed imports, and repeated feedback.
Reliability checks added: bounded overlapping chunks, stable citation numbers with full passage previews, explicit dependency failures, upload size/text validation, and import storage errors. Run npm test for the regression suite. These checks use mocked services; they do not measure live model accuracy.
No benchmark for answer accuracy, retrieval quality, or latency has been published. Feedback-driven ranking is implemented; its effect on answer quality has not been measured.
| Area | Files |
|---|---|
| PDF and website import | app/api/upload/route.ts, app/api/crawl/route.ts, lib/crawl.ts |
| Chunking, embeddings, retrieval | lib/chunking.ts, lib/embeddings.ts, lib/retrieval.ts |
| Streamed answers and sources | app/api/chat/route.ts, components/Chat.tsx |
| Feedback and monitoring | app/api/feedback/route.ts, app/api/admin/, components/AdminStats.tsx |
| Database functions | supabase/migrations/ |
Import the repository, configure the three server-side variables above, apply all five migrations, and deploy. For use with private data or untrusted users, implement the access controls described above first.
See the 60-second demo script for a suggested recording sequence and sample document.
The previous README described the project as MIT licensed, but this checkout does not include a standalone license file. Confirm the intended license before relying on that statement.
