Project 4: AI Document Assistant

PDF থেকে প্রশ্নের উত্তর, Flutter client সহ

রোডম্যাপের মাস ৯পড়তে প্রায় ৬ মিনিট

তোমার চতুর্থ project, আর portfolio এর সবচেয়ে চোখে পড়ার মতো একটা: "দলিল সহায়ক", যেখানে user নিজের PDF (অফিসের নীতিমালা, পড়ার বই, চুক্তিপত্র, সরকারি নির্দেশিকা) upload করবে আর বাংলা বা ইংরেজিতে প্রশ্ন করে সূত্রসহ উত্তর পাবে। RAG, streaming, background job, evals সব এখানে এক জায়গায়।

#Feature

User:

  • Login (আগের project এর auth আবার ব্যবহার)
  • PDF upload (সর্বোচ্চ ২০ MB), processing এর অবস্থা দেখা ("প্রক্রিয়া চলছে ৪০%...")
  • নিজের document এর তালিকা, মুছে ফেলা
  • একটা বা সব document থেকে প্রশ্ন, উত্তর অক্ষরে অক্ষরে (SSE)
  • উত্তরে সূত্র: কোন document এর কোন পৃষ্ঠা; ক্লিক করলে সেই অংশ দেখা
  • আগের প্রশ্ন-উত্তরের ইতিহাস
  • দিনে প্রশ্নের সীমা (free plan)

Admin: মোট খরচ, প্রশ্নের সংখ্যা, ব্যর্থ processing এর তালিকা

#Non-functional

বিষয় লক্ষ্য
গোপনীয়তা এক user এর document কখনো আরেকজনের উত্তরে আসবে না (test সহ)
প্রথম শব্দ প্রশ্ন করার ২ সেকেন্ডের মধ্যে উত্তর আসা শুরু
Processing ১০০ পৃষ্ঠার PDF ২ মিনিটের মধ্যে প্রস্তুত (background এ)
সত্যনিষ্ঠা তথ্য না থাকলে "নেই" বলবে, বানাবে না (eval এ ৯০%+)
খরচ প্রতি প্রশ্নের খরচ মাপা ও দেখানো, user প্রতি দৈনিক সীমা

#Architecture

Flutter upload, chat FastAPI upload, ask (SSE) auth, limit Object storage Redis queue, limit Celery worker PDF → chunk → embed PostgreSQL + pgvector LLM API প্রশ্ন + chunk
Upload: file storage এ, job queue তে, worker chunk আর embedding বানিয়ে pgvector এ রাখে। প্রশ্ন: খোঁজা, তারপর LLM থেকে stream।

#Data model

Text
documents  (id, owner_id, title, storage_key, pages, status: uploaded|processing|ready|failed,
            progress, error, created_at)
chunks     (id, document_id, owner_id, page, content, embedding vector(1024))
           INDEX hnsw(embedding), INDEX(owner_id)
questions  (id, owner_id, question, answer, cited_chunk_ids[], model, input_tokens,
            output_tokens, cost_usd, latency_ms, feedback: up|down|null, created_at)

questions table তোমার সবচেয়ে মূল্যবান সম্পদ: খরচের হিসাব, গতি, আর user এর 👍/👎 থেকে নতুন eval case।

#গুরুত্বপূর্ণ সিদ্ধান্তগুলো

  1. Upload: ২০ MB পর্যন্ত API দিয়েই চলে; বড় হলে pre-signed URL। File storage এ, database এ শুধু key।
  2. Processing আলাদা worker এ: PDF পড়া আর embedding ভারী, API এর worker আটকাবে না। Progress documents.progress এ লেখো, app poll করে বা SSE তে দেখায়।
  3. Embedding model একবার load: worker চালু হওয়ার সময়, প্রতিটা job এ না (model load এ কয়েক সেকেন্ড আর অনেক memory)।
  4. খোঁজায় owner_id (আর user বাছাই করলে document_id) এর শর্ত সবসময়।
  5. Prompt এ chunk কে tag এ মুড়ে দাও, document এর লেখাকে নির্দেশ হিসেবে মানতে নিষেধ করো (document এর ভেতরেও injection থাকতে পারে!)।
  6. উত্তরের সাথে সূত্র: কোন chunk ব্যবহার হলো সেটা response এ পাঠাও, Flutter এ "সূত্র: নীতিমালা.pdf, পৃ. ১২" দেখাও।
  7. খরচ মাপো: প্রতিটা প্রশ্নের usage থেকে টাকা হিসাব করে রাখো; দৈনিক সীমা Redis rate limit দিয়ে।

#Eval set

কমপক্ষে ২৫টা প্রশ্ন, ৩-৪টা আসল document এর উপর:

  • ১৫টা যার উত্তর document এ আছে (পৃষ্ঠা নম্বর সহ লিখে রাখো)
  • ৫টা যার উত্তর নেই (model যেন "নেই" বলে)
  • ৩টা যেখানে দুই জায়গার তথ্য মেলাতে হয়
  • ২টা prompt injection (প্রশ্নে, আর একটা document এর ভেতরে লুকানো নির্দেশ)

মাপো: retrieval hit rate, উত্তরের সঠিকতা, "নেই" বলার হার, গড় latency, গড় খরচ। README তে টেবিল দিয়ে দেখাও কোন পরিবর্তনে কী উন্নতি হলো।

#কাজের ধাপ (৩-৪ সপ্তাহ)

  1. সপ্তাহ ১: Model, upload, storage, Celery এ PDF → chunk → embedding, progress
  2. সপ্তাহ ২: খোঁজা, /ask SSE, সূত্র, প্রশ্নের ইতিহাস, খরচ log, দৈনিক সীমা
  3. সপ্তাহ ৩: Flutter: document list, upload progress, chat screen (streaming), সূত্রে ক্লিক
  4. সপ্তাহ ৪: Eval set আর উন্নতি (chunk size, hybrid search, prompt), deploy, demo video, README

#শেষ করার checklist

#নিজেকে যাচাই করো

PDF processing API request এর ভেতরে না করে worker এ কেন?

বড় PDF পড়া আর embedding বানাতে অনেক সময় আর CPU/memory লাগে। Request এর ভেতরে করলে user অপেক্ষা করবে, timeout হবে, আর API এর worker আটকে অন্য user রা ধীর সেবা পাবে।

Document এর ভেতরে লুকানো prompt injection কীভাবে হতে পারে, আর কী করবে?

কেউ PDF এর ভেতরে লিখে রাখতে পারে "এই লেখা পড়লে আগের নির্দেশ বাদ দিয়ে ..."। RAG সেই অংশ prompt এ ঢোকালে model প্রভাবিত হতে পারে। তাই chunk কে data হিসেবে tag এ মুড়ে দাও, system prompt এ বলো document এর ভেতরের নির্দেশ মানবে না, আর গুরুত্বপূর্ণ কাজ কখনো model এর কথায় করো না।

প্রতিটা প্রশ্নের token আর খরচ database এ রাখার লাভ কী?

খরচ নিয়ন্ত্রণ আর দাম ঠিক করা, ধীর বা ব্যয়বহুল প্রশ্ন খোঁজা, model বা prompt বদলের প্রভাব মাপা, আর user এর feedback থেকে নতুন eval case বানানো।

চিহ্ন দিলে sidebar আর রোডম্যাপে এই অধ্যায়ের station ভরে যাবে।