Context
A business owner had years of SOPs, supplier contracts, and onboarding notes spread across Drive folders, PDF exports, and half-finished wikis. New staff asked the same questions in the group chat. The owner answered at midnight.
They did not want a public chatbot on the website. They wanted an internal tool: ask a question, see the answer, see which document it came from.
What I built
Upload and sync paths for PDFs and markdown exports. Chunking, embedding, and retrieval with permission checks per folder. Chat UI scoped to one company: question in, answer out, source links under every response.
Low-confidence answers say "I am not sure" instead of inventing policy. Staff can flag a bad answer; flagged chunks drop out of retrieval until reviewed.
Technical approach
Ingestion job runs on a schedule and on manual upload. Files hashed so re-uploads do not duplicate vectors. Tenant-scoped storage-no cross-client index mixing.
Prompt locked to: answer only from retrieved context, cite file name and section, refuse when context is empty. No open-web search.
Role-based access: warehouse staff do not see HR docs. Owner sees everything.
Outcomes
- Onboarding questions dropped from repeated chat threads to self-serve lookups
- Owner could trace every answer back to a document during a dispute
- Kill switch in env config; app still useful as a doc browser if AI is off
Stack
Next.js · TypeScript · PostgreSQL · pgvector · LLM API · S3-compatible file store