আমি আমার RAG পাইপলাইনকে একটি ব্ল্যাক বক্সের মতো দেখতাম। এমবেডিং (Embeddings) ইনপুট হিসেবে যেত, উত্তর আসত, আর এর মাঝেই কোথাও আমার ক্লাউড বিল বাড়তে থাকল। আমি যাদের সাথে কথা বলেছি বেশিরভাগ ডেভেলপারের মতোই আমি ধরে নিয়েছিলাম যে ডেন্স ভেক্টর মডেলগুলোই (dense vector models) আসল অপরাধী। এগুলো শুনতে বেশ ব্যয়বহুল মনে হতো। হাজার হাজার পৃষ্ঠাকে হাই-ডাইমেনশনাল ফ্লোটে (high-dimensional floats) রূপান্তর করাটা ভারী উৎপাদন প্রক্রিয়ার মতো মনে হতো, তাই আমি অত্যন্ত সতর্কতার সাথে এটি নিয়ে কাজ করতাম। এমনকি আমি ইতিমধ্যে প্রসেস করা ডেটা পুনরায় এমবেড করা এড়ানোর জন্য একটি বিশেষ ক্যাশিং লেয়ার (caching layer) তৈরি করেছিলাম। আমি সেই অপ্টিমাইজেশন নিয়ে গর্বিত ছিলাম। তারপর আমি ইনভয়েসটি খুললাম এবং হিসেব করলাম।
আমি সম্পূর্ণ ভুল জিনিস অপ্টিমাইজ করছিলাম।
এমবেডিংয়ের ফাঁদ (The Embedding Trap)
এখানে সেই সংখ্যাটি দেওয়া হলো যা আমার ধারণা বদলে দিয়েছে: ১,০০০ পৃষ্ঠার একটি ডকুমেন্টের এমবেডিং করতে খরচ হয় মাত্র প্রায় ১৮ সেন্ট। এটি কোনো টাইপো নয়। বেশিরভাগ শহরে এক কাপ কফির দামের চেয়েও কম খরচে আপনি একটি পুরো বই ভেক্টরাইজ (vectorize) করতে পারেন। আরও গুরুত্বপূর্ণ বিষয় হলো, এই খরচটি মাত্র একবার দিতে হয়, ইনজেশনের (ingestion) সময়। প্রাথমিক ধাপের পর, সেই ভেক্টরগুলো স্টোরেজে জমা থাকে এবং অপেক্ষা করে। প্রতিবার যখন কোনো ব্যবহারকারী আপনার অ্যাপ্লিকেশনটি ওপেন করেন, তখন এগুলো বাড়তি কোনো ফি তৈরি করে না। এটি একটি মূলধনী খরচ (capital expense), কোনো ধারাবাহিক খরচ (recurring drain) নয়।
তবুও এই ভুল ধারণাটি রয়ে গেছে। এই বিভ্রান্তির একটি অংশ হলো কাঠামোগত। ইঞ্জিনিয়াররা তাদের প্রাথমিক শক্তি ব্যয় করেন ইনজেশন পাইপলাইনে। আপনি চাঙ্কার (chunker) লিখছেন, টোকেনাইজারের (tokenizer) সাথে লড়াই করছেন, আপনার টার্মিনালে প্রগ্রেস বার (progress bars) ধীরে ধীরে এগোতে দেখছেন। এই দৃশ্যমান প্রচেষ্টা একটি অনুপাতের বিভ্রম তৈরি করে। এটি ব্যয়বহুল মনে হয় কারণ এটি অত্যন্ত শ্রমসাধ্য কাজ। কিন্তু শ্রম এবং খরচ এক নয়, এবং RAG-এর ক্ষেত্রে এগুলো প্রায়ই বিপরীতমুখী সম্পর্কযুক্ত।
তিনটি সম্পূর্ণ ভিন্ন বিল
একবার যখন আমি খরচগুলোকে একত্রে না রেখে ধাপ অনুযায়ী আলাদা করলাম, তখন বিষয়টি পরিষ্কার হয়ে গেল। একটি RAG সিস্টেম তিনটি ভিন্ন অর্থনৈতিক মডেলে চলে, এবং আপনি যদি আপনার বাজেট নিয়ন্ত্রণে রাখতে চান তবে এই পার্থক্যগুলো বোঝা অপরিহার্য।
এমবেডিং হলো একবারের উৎপাদন খরচ। আপনি ডকুমেন্টগুলোকে ভেক্টরে রূপান্তর করার জন্য অর্থ প্রদান করেন, এবং তারপর আপনার কাজ শেষ। যদি আপনার ডকুমেন্টগুলো স্ট্যাটিক (static) হয়, তবে আপনার মাসিক বিলে এই খরচটি খুব একটা দেখা যাবে না।
ভেক্টর ডেটাবেস হলো ইনফ্রাস্ট্রাকচার ভাড়া। সিস্টেমটিকে চব্বিশ ঘণ্টা সচল রাখতে আপনি অর্থ প্রদান করেন। লক্ষ লক্ষ চাঙ্ক (chunks) ধরে রাখার জন্য SSD, ইনডেক্স বজায় রাখার জন্য CPU কোর, এবং ১০০ মিলিসেকেন্ডের কম সময়ে সার্চ প্রদান করার জন্য নেটওয়ার্কের জন্য আপনি টাকা দেন। এই খরচটি বাস্তব এবং এটি ডেটার পরিমাণের সাথে বাড়ে, তবে এটি সাধারণত অনুমানযোগ্য। এটি একটি জিমের মেম্বারশিপের মতো কাজ করে। আপনি একবার সার্চ করুন বা দশ হাজার বার, মূল ইনফ্রাস্ট্রাকচার খরচ মোটামুটি একই থাকে।
লার্জ ল্যাঙ্গুয়েজ মডেল (LLM) হলো ব্যবহারের ওপর কর। প্রতিটি ব্যবহারকারীর প্রশ্ন একটি নতুন বিল তৈরি করে। আপনার রিট্রিভাল লেয়ার (retrieval layer) থেকে প্রতিটি টোকেন যা প্রম্পটে (prompt) প্রবেশ করে, তার জন্য খরচ দিতে হয়। প্রতিটি রিজনিং স্টেপ (reasoning step), প্রতিটি ফরম্যাটিং ইন্সট্রাকশন (formatting instruction), এবং মডেলকে দিয়ে তৈরি করা প্রতিটি সাইটেশন (citation) ক্ষুদ্রাতিক্ষুদ্র খরচ যোগ করে। কিন্তু এই ক্ষুদ্র খরচগুলো সেশনের সংখ্যার সাথে গুণিতক হারে বাড়ে, এবং সেশনের সংখ্যা ক্রমাগত বৃদ্ধি পায়। এখানেই ল্যাটেন্সি (latency) এবং খরচের মেলবন্ধন ঘটে। একটি ধীরগতির কুয়েরি কেবল ব্যবহারকারীর জন্য বিরক্তিকর নয়; ব্যবহারকারী অপেক্ষা করার সময় এটি সক্রিয়ভাবে আপনার টাকা খরচ করে দিচ্ছে।
এগুলো একই সমস্যার ভিন্ন রূপ নয়। এগুলো তিনটি আলাদা সমস্যা। ইনজেশন প্রক্রিয়া সস্তা করে আপনি কুয়েরি-টাইম বা ব্যবহারের সময়কার খরচ কমাতে পারবেন না। এটি অনেকটা পার্কিংয়ের টাকা বাঁচাতে গাড়ির ইঞ্জিন টিউন করার মতো।
টাকা আসলে কোথায় খরচ হচ্ছে
আপনি যদি একটি প্রোডাকশন RAG অ্যাপ্লিকেশন চালান, তবে আপনার কস্ট এক্সপ্লোরার (cost explorer) খুলুন এবং ব্যবহারের ধরন (usage type) অনুযায়ী ফিল্টার করুন। আমি বাজি ধরে বলতে পারি যে আপনার এমবেডিং জবটি দিনে একবার একটি ফ্ল্যাট লাইন (flat line) হিসেবে দেখাবে, যেখানে আপনার LLM এন্ডপয়েন্টটি ট্রাফিকের সাথে হার্টবিটের মতো স্পাইক (spike) দেখাবে। এই প্যাটার্নটি পুরো গল্পটি বলে দেয়। আপনার ভেক্টরগুলো ঘুমিয়ে থাকে; কিন্তু ব্যবহারকারীর যখনই কোনো প্রশ্ন থাকে, তখনই আপনার মডেল জেগে ওঠে।
এই উপলব্ধিটি আমার ইঞ্জিনিয়ারিং কাজের অগ্রাধিকার পরিবর্তন করে দিয়েছে। আমি কীভাবে ইনজেশন সস্তা করা যায় তা জিজ্ঞেস করা বন্ধ করে দিয়েছি এবং কীভাবে প্রতিটি প্রশ্ন আরও সস্তা করা যায় তা নিয়ে ভাবতে শুরু করেছি। এই পরিবর্তনটি শুনতে খুব সহজ মনে হলেও বেশিরভাগ টিম এখনও অনুমানের ওপর ভিত্তি করে কাজ করে। তারা এমবেডিং স্টেজের জন্য জটিল ডিডুপ্লিকেশন লজিক (deduplication logic) তৈরি করে এবং তারপর কোনো দ্বিতীয় চিন্তা ছাড়াই LLM-কে অতিরিক্ত বড় এবং অগোছালো কনটেক্সট উইন্ডো (context windows) প্রদান করে। তারা ছাদের ফুটো থাকা সত্ত্বেও মেঝে পালিশ করছে।
পাইপলাইন নষ্ট না করে কীভাবে খরচ কমানো যায়
একটি RAG সিস্টেমে টাকা বাঁচাতে হলে খরচ মডেলের সাথে সামঞ্জস্য রেখে কৌশল গ্রহণ করতে হয়। এখানে যা আসলে কাজ করে:
প্রসেস করার আগে ডিডুপ্লিকেট (Deduplicate) করুন
বেশিরভাগ প্রাতিষ্ঠানিক নলেজ বেস ধীরগতিতে কাজ করে। পলিসি, হ্যান্ডবুক, রিসার্চ পিডিএফ এবং আর্কাইভ করা রিপোর্ট মাসের পর মাস অপরিবর্তিত অবস্থায় পড়ে থাকে। অনেক পাইপলাইনে, ইনজেশন রানের (ingestion runs) মধ্যে প্রায় ৮০% সোর্স ডকুমেন্ট একই থাকে। তা সত্ত্বেও, অনেক সিস্টেম একটি নির্দিষ্ট সময় অন্তর পুরো কর্পাস ফেলে দিয়ে ইনডেক্স নতুন করে তৈরি করে। এমনটা করবেন না। আপনার পাইপলাইনের প্রবেশপথে একটি গেট তৈরি করুন। ইনকামিং ফাইলগুলোর হ্যাশ (hash) করুন। লাস্ট-মডিফাইড টাইমস্ট্যাম্প তুলনা করুন। যদি কোনো ডকুমেন্ট পরিবর্তিত না হয়, তবে সেটি পুরোপুরি বাদ দিন। স্ট্যাটিক ফাইলগুলো পুনরায় প্রসেস করা সম্পূর্ণ অপচয়। এটি কম্পিউট খরচ বাড়ায়, অপ্রয়োজনে SSD ক্ষয় করে এবং ইনজেশন লগগুলোকে ভুল অ্যাক্টিভিটি দিয়ে ফুলিয়ে তোলে।
বাস্তবে, একটি হালকা ওজনের ম্যানিফেস্ট (manifest) সংরক্ষণ করুন যা ফাইল পাথগুলোকে চেকসামের (checksums) সাথে ম্যাপ করে। যখন শিডিউলার চালু হবে, তাকে প্রথমে ম্যানিফেস্টটি পরীক্ষা করতে দিন। শুধুমাত্র পরিবর্তিত অল্প কিছু ফাইলই চাঙ্কারের (chunker) কাছে যাওয়া উচিত।
ডকুমেন্ট প্যাচ করুন, প্রতিস্থাপন করবেন না
যখন কোনো ডকুমেন্ট পরিবর্তিত হয়, তখন সেটিকে সম্পূর্ণ নতুন ফাইল হিসেবে বিবেচনা করার প্রবণতা এড়িয়ে চলুন। একটি ৫০ পৃষ্ঠার টেকনিক্যাল স্পেসিফিকেশনের হয়তো চতুর্থ সেকশনে মাত্র দুই প্যারার একটি সংশোধন থাকতে পারে। যদি আপনার পাইপলাইন পুরো ফাইলটি প্রতিস্থাপন করে, তবে আপনি কোনো কারণ ছাড়াই উনপঞ্চাশটি নিখুঁত পৃষ্ঠা পুনরায় চাঙ্ক (re-chunk) এবং রি-এমবেড (re-embed) করবেন।
পরিবর্তে, নতুন ভার্সনটিকে পুরনো ভার্সনের সাথে তুলনা করুন। পরিবর্তন বা ডেল্টা (delta) চিহ্নিত করুন। তারপর শুধুমাত্র পরিবর্তিত সেকশনগুলো পুনরায় চাঙ্ক এবং রি-এমবেড করুন। বাউন্ডারি ট্র্যাক করার জন্য পেজ নম্বর, সেকশন আইডি, হেডার অ্যাঙ্কর বা প্যারাগ্রাফ রেঞ্জের মতো মেটাডেটা ব্যবহার করুন। আপনার চাঙ্কিং স্ট্র্যাটেজি যদি ডকুমেন্টের গঠন মেনে চলে, তবে এটি খুব সহজ। যদি না চলে, তবে একটি বড় ইনফারেন্স ক্লাস্টার কেনার চেয়ে আপনার চাঙ্কারটি ঠিক করা অনেক ভালো বিনিয়োগ। ডকুমেন্ট সংখ্যা বাড়ার সাথে সাথে একটি ডিফ-অ্যাওয়ার (diff-aware) পাইপলাইন বজায় রাখার ইঞ্জিনিয়ারিং খরচ কয়েক সপ্তাহের মধ্যেই উঠে আসবে।
পুনরাবৃত্তিমূলক খরচগুলো সরাসরি মোকাবিলা করুন
যেহেতু প্রতিটি কুয়েরির জন্য LLM কল করতে হয়, তাই মাত্র কয়েকটা টোকেন বাঁচানো বা কিছু রেসপন্স ক্যাশ (cache) করা বিশাল সাশ্রয় করতে পারে। প্রম্পট ক্যাশিং (prompt caching) দিয়ে শুরু করুন। যদি একজন ব্যবহারকারী আপনার রিফান্ড পলিসি সম্পর্কে জিজ্ঞাসা করেন এবং অন্য একজন দশ মিনিট পরে একই প্রশ্ন করেন, তবে মডেলটিকে দ্বিতীয়বার কল করার কোনো প্রয়োজন নেই। সিম্যান্টিক সিমিলারিটি ম্যাচিংয়ের (semantic similarity matching) মাধ্যমে সাম্প্রতিক কুয়েরি-রেসপন্স জোড়াগুলো সংরক্ষণ করুন। যখন কোনো নতুন প্রশ্ন ক্যাশ করা প্রশ্নের সিমিলারিটি থ্রেশহোল্ডের (similarity threshold) মধ্যে আসবে, তখন সরাসরি সংরক্ষিত উত্তরটি প্রদান করুন। এতে কোনো টোকেন খরচ হবে না, কোনো ডলারও ব্যয় হবে না।
এরপর, আপনার রিট্রিভাল কোয়ালিটির (retrieval quality) দিকে গভীরভাবে নজর দিন। একটি অগোছালো রিট্রিভার (retriever) একটি সুঁই খোঁজার জন্য LLM-কে খড়ের গাদা পড়তে বাধ্য করে। যদি আপনার top-k কাটঅফ খুব ঢিলেঢালা হয় এবং আপনি প্রম্পটে বিশটি অপ্রাসঙ্গিক চাঙ্ক ঢুকিয়ে দেন, তবে আপনি মডেলটিকে অপ্রয়োজনীয় তথ্য পড়ার জন্য টাকা দিচ্ছেন। আপনার রিট্রিভাল আরও সুনির্দিষ্ট করুন। top-k কমিয়ে আনুন। চাঙ্কগুলো পাঠানোর আগে কম্প্রেস (compress) করুন। ইনজেশনের সময় বয়েলারপ্লেট ফুটার এবং হেডারগুলো সরিয়ে ফেলুন যাতে সেগুলো প্রম্পটে না পৌঁছায়। কনটেক্সট উইন্ডো থেকে আপনি প্রতিটি টোকেন যত কমাবেন, তা এক সেন্টের ক্ষুদ্র অংশ হলেও হাজার হাজার দৈনিক কুয়েরির মাধ্যমে সেই সঞ্চয় বিশাল হয়ে দাঁড়াবে।
উন্নত রিট্রিভাল ল্যাটেন্সিও (latency) কমায়, যা খরচের আরেকটি দিক। ব্যবহারকারীরা ধীরগতির ইন্টারফেস ব্যবহার করা ছেড়ে দেয়। দ্রুত উত্তর দেওয়া যেমন সাশ্রয়ী, তেমনি এটি ব্যবহারকারী ধরে রাখার জন্যও ভালো।
আসল শিক্ষা
যা ব্যয়বহুল মনে হয় তা অপ্টিমাইজ করা বন্ধ করুন এবং আপনার ইনভয়েস যা ব্যয়বহুল বলছে তা অপ্টিমাইজ করা শুরু করুন। প্রতিটি ধাপ স্বতন্ত্রভাবে পরিমাপ করুন। আপনি সম্ভবত দেখতে পাবেন যে এমবেডিং (embeddings) হলো সস্তা অংশ, ভেক্টর স্টোরেজ (vector storage) হলো স্থিতিশীল অংশ এবং LLM ইনফারেন্স (inference) হলো সেই অংশ যা সবচেয়ে বেশি খরচ করে। আপনার শক্তি ব্যয় করুন কুয়েরি-টাইম এফিসিয়েন্সি (query-time efficiency), ইনক্রিমেন্টাল আপডেট এবং সার্জিক্যাল ডিডুপ্লিকেশন (surgical deduplication)-এর ওপর। পঞ্চাশতম ডকুমেন্ট আপলোডের জন্য নয়, বরং হাজারতম ব্যবহারকারীর প্রশ্নের জন্য সিস্টেমটি তৈরি করুন। বাটলনেক (bottleneck) সাধারণত সেখানে থাকে না যেখানে আপনি মনে করেন।
উৎস: Where Does RAG Actually Cost You Money? I Decided to Stop Guessing
- GyaanSetu AI learning community-এ আলোচনায় যোগ দিন।*
