মূল কনটেন্টে যান
Abdullah Al Rafi
মেনু

ট্রিয়ার, জার্মানি · CET

কিছুই সংরক্ষণ না করা ডকুমেন্ট RAG

PDF ও টেক্সট ফাইলের জন্য পূর্ণাঙ্গ RAG সিস্টেম: নিজের Hugging Face টোকেন দিন, নিজের ফাইলের ভিত্তিতে স্ট্রিম করা উত্তর পান, কিছুই সংরক্ষিত হয় না।

সারসংক্ষেপ

ভূমিকা
একক ডেভেলপার
সময়কাল
মার্চ ২০২৬ – বর্তমান
প্রযুক্তি
FastAPI · LangChain · Hugging Face · pypdf · React · Vite · Cloudflare · Sentry

0

সংরক্ষিত আপলোড

প্রতিটি রিকোয়েস্টে মেমরিতেই প্রসেস হয়

5 মিনিট

প্রতি ডকুমেন্টে ভেক্টর-স্টোর ক্যাশ

ফাইল হ্যাশ, মডেল ও চাংকিং দিয়ে কী তৈরি

1–10

প্রতি প্রশ্নে বেছে নেওয়া রিট্রিভড চাংক

এই পেজে
  1. সারসংক্ষেপ
  2. সমস্যা
  3. সীমাবদ্ধতা
  4. পদ্ধতি ও আর্কিটেকচার
  5. ফলাফল
  6. এখন হলে যা অন্যভাবে করতাম

সমস্যা

বেশির ভাগ "PDF-এর সঙ্গে চ্যাট" টুল আপনার ডকুমেন্ট এমন এক ভেক্টর ডেটাবেসে রেখে দেয়, যার নিয়ন্ত্রণ আপনার হাতে নেই। আমি চেয়েছিলাম এমন ডকুমেন্ট প্রশ্নোত্তর ব্যবস্থা, যেখানে আপনি নিজের Hugging Face টোকেন দেবেন, একটি PDF বা টেক্সট ফাইল আপলোড করবেন, আর শুধু সেই ফাইলের ভিত্তিতেই উত্তর পাবেন; সার্ভারে কিছুই সংরক্ষিত হবে না।

সীমাবদ্ধতা

  • কোনো সংরক্ষণ নয়। আপলোড মেমরিতেই প্রসেস হয়, কখনো ডিস্কে বা ডেটাবেসে লেখা হয় না।
  • নিজের টোকেন। ব্রাউজার ব্যবহারকারীর Hugging Face টোকেন localStorage-এ রাখে এবং প্রতিটি রিকোয়েস্টে বেয়ারার হেডার হিসেবে পাঠায়। সার্ভার নিজের টোকেন ব্যবহার করে কেবল তখনই, যদি তা কনফিগার করা থাকে।
  • উন্মুক্ত ডেমো। যে কেউ এটি ব্যবহার করতে পারে, তাই রিকোয়েস্টে রেট লিমিট আছে, প্রশ্ন ১,০০০ অক্ষরে সীমিত, ফাইলের আকার সীমিত, আর শুধু .txt ও .pdf গ্রহণ করা হয়। API ডকুমেন্টেশন একটি গোপন টোকেন দিয়ে সুরক্ষিত।
  • হোস্টেড ইনফারেন্স। এমবেডিং ও জেনারেশন চলে Hugging Face-এর ইনফারেন্স এন্ডপয়েন্টে, তাই একই ডকুমেন্টে বারবার একই কাজ এড়াতে হয়।

পদ্ধতি ও আর্কিটেকচার

  1. Cloudflare-এ React + Vite

    ক্লায়েন্ট

    Hugging Face টোকেন ব্রাউজারের localStorage-এই থাকে

  2. POST /rag/query · ফাইল + প্রশ্ন + বেয়ারার টোকেন

    FastAPI প্রবেশপথ

    API

    রেট লিমিট · শুধু .txt/.pdf · আকার ও ১,০০০ অক্ষরের সীমা

  3. লেখা বের করা

    এক্সট্র্যাক্ট

    PDF-এর জন্য pypdf, টেক্সটের জন্য UTF-8, শুধু মেমরিতে

  4. ক্যাশ কী: SHA-256(ফাইল) + মডেল + চাংকিং + টোকেন হ্যাশ
    • ভেক্টর স্টোর আবার ব্যবহার

      ক্যাশ হিট

      পাঁচ মিনিট বৈধ

    • ভাগ ও এমবেড করা

      ক্যাশ মিস

      রিকার্সিভ স্প্লিটার → HF এমবেডিং → ইন-মেমরি স্টোর

  5. টপ-k সাদৃশ্য অনুসন্ধান

    রিট্রিভ

    প্রতি প্রশ্নে k = ১ থেকে ১০

  6. তথ্যভিত্তিক উত্তর

    জেনারেট

    HF চ্যাট কমপ্লিশন · টেম্পারেচার ০ · সর্বোচ্চ ৫১২ টোকেন

  7. স্ট্রিম করা উত্তর

    আগে উত্তর, তারপর মেট্রিক

    ক্লায়েন্ট

    টোকেন, জেনারেশনের সময় ও প্রতি সেকেন্ডে টোকেন

চিত্র 1 · একটি প্রশ্নের রিকোয়েস্টের পথ। কোনো ধাপেই ডিস্কে কিছু লেখা হয় না।
ডায়াগ্রামের বর্ণনা

React ক্লায়েন্ট ফাইল, প্রশ্ন আর ব্যবহারকারীর Hugging Face টোকেন একটি FastAPI এন্ডপয়েন্টে পাঠায়। API রেট লিমিট ও ইনপুটের সীমা যাচাই করে, মেমরিতে লেখা বের করে, আর ফাইল, মডেল, চাংকিং সেটিং ও টোকেনের হ্যাশ দিয়ে ক্যাশে থাকা ভেক্টর স্টোর খোঁজে। না পেলে লেখা ভাগ করে এমবেড করে; পেলে ক্যাশের স্টোরটিই ব্যবহার করে। এরপর টপ-k চাংক রিট্রিভ করে, টেম্পারেচার ০-তে তথ্যভিত্তিক উত্তর তৈরি করে, এবং উত্তর স্ট্রিম করার পর জেনারেশনের মেট্রিক পাঠায়।

সিদ্ধান্ত

ভেক্টর স্টোর মেমরিতে রাখা, স্বল্পমেয়াদি ক্যাশের পেছনে

প্রতিটি ডকুমেন্টের InMemoryVectorStore পাঁচ মিনিটের জন্য ক্যাশ করা হয়, সর্বোচ্চ ৬৪টি এন্ট্রি পর্যন্ত। ক্যাশ কী তৈরি হয় ফাইলের SHA-256, এমবেডিং মডেল, চাংকিং সেটিং আর ব্যবহারকারীর টোকেনের হ্যাশ মিলিয়ে। পরের প্রশ্নগুলোতে আবার এমবেড করতে হয় না, আর কেউ অন্যের ভেক্টর পায় না।

অন্য যা ভাবা হয়েছিল

  • pgvector বা Pinecone-এর মতো হোস্টেড ভেক্টর ডেটাবেসএমবেডিং সংরক্ষণ করলে 'কিছুই সংরক্ষণ না করার' প্রতিশ্রুতি ভেঙে যেত।

সিদ্ধান্ত

ব্যবহারকারীর টোকেন দিয়ে Hugging Face ইনফারেন্সে মডেল চালানো

এমবেডিং ও জেনারেশন মডেলের নাম এনভায়রনমেন্ট সেটিংয়ে থাকে, তাই কোড না বদলেই যেকোনোটি পাল্টানো যায়।

অন্য যা ভাবা হয়েছিল

  • এমবেডিং ও জেনারেশন মডেল নিজে হোস্ট করাবিনা মূল্যের উন্মুক্ত ডেমোর জন্য তখন GPU হোস্টিং লাগত।

সিদ্ধান্ত

শুধু রিট্রিভ করা কনটেক্সট থেকেই উত্তর দেওয়া

প্রম্পট মডেলকে বলে দেয়, উত্তর কনটেক্সটে না থাকলে যেন জানায় যে সে জানে না। জেনারেশন চলে টেম্পারেচার ০-তে, সর্বোচ্চ ৫১২ টোকেনে।

অন্য যা ভাবা হয়েছিল

  • মডেলকে নিজের জ্ঞান মিশিয়ে উত্তর দিতে দেওয়াতখন উত্তর আর ডকুমেন্টের সঙ্গে মিলিয়ে যাচাই করা যেত না।

সিদ্ধান্ত

টোকেন স্ট্রিম করা, তারপর মেট্রিক জুড়ে দেওয়া

স্ট্রিমের শেষে ছোট একটি মেটাডেটা ব্লক থাকে, যেখানে তৈরি হওয়া টোকেন, জেনারেশনের সময় আর প্রতি সেকেন্ডে টোকেন থাকে; ফলে আলাদা কল ছাড়াই ইন্টারফেস গতি দেখাতে পারে।

অন্য যা ভাবা হয়েছিল

  • মেট্রিকের জন্য আলাদা রিকোয়েস্টআরও একবার আসা-যাওয়া, আর সংখ্যাগুলো হিসাব হতো উত্তর থেকে আলাদাভাবে।

ফলাফল

0

সংরক্ষিত আপলোড

প্রতিটি রিকোয়েস্টে লেখা মেমরিতেই বের করে এমবেড করা হয়

5 মিনিট

প্রতি ডকুমেন্টে ক্যাশের মেয়াদ

পরের প্রশ্নগুলোতে আবার এমবেড করতে হয় না

2

প্রতিটি পুশে CI যাচাই

ব্যাকএন্ডে pytest; ফ্রন্টএন্ডে ইমিউটেবল Yarn 4 ইনস্টল + প্রোডাকশন বিল্ড

সিস্টেমটি চালু আছে rag.abdullahalrafi.com-এ, সোর্স কোড GitHub-এ। এরর যায় Sentry-তে, আর ক্যাশ হিট ও মিস ব্রেডক্রাম্ব হিসেবে লগ হয়, তাই ধীর উত্তরের কারণ যে পুনরায় এমবেডিং, তা খুঁজে বের করা যায়।

এখন হলে যা অন্যভাবে করতাম

  • মডেলের নিজস্ব টোকেনাইজার দিয়ে টোকেন গুনতাম। এখন প্রতি সেকেন্ডে টোকেনের হিসাব হয় ফাঁকা জায়গা ধরে ভাগ করে, যা সাবওয়ার্ড টোকেন কম গোনে এবং বিভিন্ন মডেলের গতি তুলনা কঠিন করে।
  • ছোট একটি লেবেল করা প্রশ্নসেট দিয়ে রিট্রিভাল যাচাই করতাম, আর চাংকের আকার ও টপ-k এনভায়রনমেন্ট ভেরিয়েবলে অনুমান করে না বসিয়ে সেই অনুযায়ী ঠিক করতাম।
  • একাধিক ওয়ার্কারের কথা মাথায় রাখতাম। ক্যাশ এখন একটি প্রসেসেই থাকে; একটি শেয়ার করা, এনক্রিপ্টেড ক্যাশ হিট রেট বাড়াত, তবে তাতে 'কিছুই সংরক্ষণ না করার' প্রতিশ্রুতির সত্যিকারের মূল্য দিতে হতো।