System Design শেখো
সব কেস স্টাডি

Recommendation System ডিজাইন

14 মিনিটadvanced
এক নজরে
  • বড় স্কেলের রেকমেন্ডেশন সাধারণত দুই ধাপে হয় — candidate generation দিয়ে কোটি আইটেম থেকে কয়েকশ বাছাই, তারপর ranking দিয়ে সূক্ষ্ম সাজানো।
  • User ও item embedding এবং একটি feature store হলো সিস্টেমের মূল ভিত্তি, যেখানে offline training আর online serving আলাদা পথে চলে।
  • Cold start, freshness আর feedback loop ঠিকমতো না সামলালে রেকমেন্ডেশন কয়েক সপ্তাহেই বাজে হয়ে যায়।

ধরো তুমি একটা YouTube বা Netflix-এর মতো প্ল্যাটফর্ম বানাচ্ছো, যেখানে হোমপেজে ব্যবহারকারীকে "তোমার জন্য" আইটেম দেখাতে হবে। কোটি কোটি ভিডিও, কোটি কোটি ব্যবহারকারী, আর প্রতিটি পেজ লোডে মাত্র কয়েকশ মিলিসেকেন্ড। ইন্টারভিউতে এই প্রশ্নটা এলে আতঙ্কিত হওয়ার দরকার নেই — কাঠামোগতভাবে এগোলে এটা খুবই সামলানো যায়।

১. সমস্যা বোঝা (Requirements)

প্রথমেই scope পরিষ্কার করো। ইন্টারভিউয়ারকে জিজ্ঞেস করো — হোম ফিড, নাকি "related items", নাকি দুটোই?

Functional requirements:

  • ব্যবহারকারী হোমপেজে এলে personalized আইটেমের একটা ranked তালিকা দেখাও।
  • ব্যবহারকারীর interaction (click, watch time, like, skip) রেকর্ড করো।
  • নতুন আইটেম ও নতুন ব্যবহারকারী দ্রুত সিস্টেমে ঢুকতে পারবে (cold start)।
  • একই আইটেম বারবার না দেখানো (de-duplication, diversity)।

Non-functional requirements (ML-নির্দিষ্ট):

  • Latency: রেকমেন্ডেশন রিকোয়েস্টের p99 ২০০ ms-এর কম।
  • Freshness: নতুন আপলোড করা ভিডিও কয়েক মিনিটের মধ্যে candidate হিসেবে আসতে পারবে।
  • Accuracy/Engagement: offline metric (recall@k, NDCG) এবং online metric (CTR, watch time) — দুটোতেই উন্নতি।
  • Scale: কোটি ব্যবহারকারী, কোটি আইটেম, দিনে শত কোটি interaction।
  • Reliability: মডেল ব্যর্থ হলেও popularity-based fallback থাকবে।
সহজ উদাহরণ

ব্যাপারটা অনেকটা পুরান ঢাকার বিরিয়ানির দোকানে অর্ডার নেওয়ার মতো। পুরো মেনু (কোটি আইটেম) থেকে ওয়েটার প্রথমে দ্রুত আন্দাজ করে তুমি কী ধরনের খাবার চাও — মাংস না সবজি (candidate generation)। তারপর সেই ছোট তালিকা থেকে তোমার আগের পছন্দ মাথায় রেখে নিখুঁতভাবে সাজিয়ে দেয় কোনটা আগে আনবে (ranking)।

২. স্কেল আন্দাজ (Estimation)

আন্দাজের অভ্যাস ইন্টারভিউয়ারকে দেখায় তুমি বাস্তব সংখ্যায় ভাবতে পারো।

ব্যবহারকারী (DAU)        : ১০০ মিলিয়ন
আইটেম (catalog)          : ৫০ মিলিয়ন ভিডিও
প্রতি ব্যবহারকারী/দিন      : গড়ে ১০টি হোম-রিকোয়েস্ট
মোট রিকোয়েস্ট/দিন         : ১০০M × ১০ = ১ বিলিয়ন
গড় QPS                  : ১B / ৮৬,৪০০ ≈ ১১,৫০০ QPS
পিক QPS (৩x)            : ≈ ৩৫,০০০ QPS

Embedding সাইজ          : ১২৮ float × ৪ বাইট = ৫১২ বাইট/vector
Item embedding মোট       : ৫০M × ৫১২B ≈ ২৫ GB (RAM-এ ANN index)
User embedding মোট       : ১০০M × ৫১২B ≈ ৫০ GB

Latency budget (২০০ ms):
  feature fetch     : ~৩০ ms
  candidate gen     : ~৩০ ms (ANN lookup)
  ranking (৫০০ আইটেম): ~৮০ ms
  বাকি (network/merge): ~৬০ ms

Interaction লগ/দিন      : ১B রিকোয়েস্ট × ~৫ ইভেন্ট = ৫B ইভেন্ট/দিন
                         ~১ KB/ইভেন্ট ≈ ৫ TB/দিন raw log

মূল শিক্ষা: ৩৫K QPS-এ প্রতিটি রিকোয়েস্টে ৫০M আইটেম স্ক্যান করা অসম্ভব — তাই candidate generation দিয়ে দ্রুত সংকোচন আবশ্যক।

৩. API ডিজাইন

GET /v1/recommendations
  query: user_id, context (device, location, time), page_size=20, cursor
  → 200 OK
    {
      "items": [
        { "item_id": "...", "score": 0.87, "reason": "watched_similar" }
      ],
      "next_cursor": "..."
    }

POST /v1/feedback
  body: { user_id, item_id, event: "click|watch|skip|like",
          dwell_ms, position, request_id, ts }
  → 202 Accepted

POST /v1/items            # নতুন আইটেম ingest
  body: { item_id, metadata, creator_id }
  → 201 Created

request_id খুব গুরুত্বপূর্ণ — এটা দিয়ে কোন রিকোয়েস্টে কোন আইটেম কোন position-এ দেখানো হয়েছিল আর তার পরে কী ইভেন্ট হয়েছে, তা জোড়া লাগানো যায়। এই জোড়াই পরে training label তৈরি করে।

৪. ডেটা মডেল ও Features

Feature গ্রুপউদাহরণউৎসকোথায় থাকে
User staticবয়স, ভাষা, দেশprofile DBonline + offline
User dynamicশেষ ৫০টি watch, গড় watch timeevent streamonline store
Item staticcategory, length, creatoritem DBonline + offline
Item dynamicগত ১ ঘণ্টার CTR, view velocitystreaming aggonline store (TTL সহ)
Cross/contextdevice, hour, user-item category matchcompute-on-flyrequest-time
Embeddingsuser & item ১২৮-dim vectormodel outputANN index + cache

Feature store-এর দুটো অংশ:

  • Offline store (যেমন parquet/warehouse): training-এর জন্য সব historical feature, point-in-time correct ভাবে।
  • Online store (যেমন Redis/Cassandra): serving-এর জন্য low-latency lookup, একই feature definition থেকে materialized।

দুটোতে একই transformation logic ব্যবহার করাই আসল — নাহলে training-serving skew হয়, মানে training-এ মডেল যে feature দেখেছে আর production-এ যা পাচ্ছে তা ভিন্ন, ফলে accuracy ধসে পড়ে।

৫. হাই-লেভেল ডিজাইন

মূল কম্পোনেন্টগুলো:

  • Client / API Gateway — রিকোয়েস্ট নেয়, auth করে, recommendation service-এ পাঠায়।
  • Recommendation Service (orchestrator) — পুরো flow সাজায়।
  • Feature Store (online) — user/item feature দ্রুত আনে।
  • Candidate Generation — কয়েকটি retriever (embedding ANN, recent trending, co-watch, subscriptions) থেকে candidate জড়ো করে।
  • Ranking Model Server — candidate-দের scoring করে (GPU/CPU inference)।
  • Cache — সদ্য-গণনা করা রেকমেন্ডেশন কিছুক্ষণ ধরে রাখে।
  • Streaming pipeline (Kafka + Flink) — interaction লগ ও real-time feature update।
  • Offline training pipeline — দৈনিক/ঘণ্টা-ভিত্তিক মডেল retrain।

Flow ধাপে ধাপে:

  1. ব্যবহারকারী হোমপেজ খুললে API gateway → recommendation service।
  2. Service আগে cache দেখে; hit হলে সরাসরি ফেরত।
  3. Miss হলে online feature store থেকে user feature আনে।
  4. একাধিক candidate generator সমান্তরালে চালিয়ে ~৫০০-১০০০ candidate জোগাড় করে, de-dup করে।
  5. এই candidate + feature ranking model server-এ পাঠায়; প্রতিটি আইটেমের জন্য score পায়।
  6. Score অনুযায়ী sort, তারপর business rule (diversity, freshness boost, already-seen filter) প্রয়োগ।
  7. Top-N ফেরত পাঠায়, cache-এ লেখে, আর কোন আইটেম কোন position-এ দেখানো হলো তা impression log-এ পাঠায়।
  8. ব্যবহারকারীর click/watch ইভেন্ট Kafka-তে যায়; Flink real-time feature আপডেট করে আর raw log warehouse-এ জমে training-এর জন্য।

৬. গভীরে (Deep Dive)

Candidate Generation (retrieval)

এখানে লক্ষ্য recall, precision নয়। সবচেয়ে জনপ্রিয় কৌশল হলো two-tower model: একটা tower user feature থেকে user embedding বানায়, আরেকটা item feature থেকে item embedding। Training-এ positive pair (ব্যবহারকারী যা দেখেছে) কাছাকাছি আনা হয়, negative দূরে ঠেলা হয় (in-batch negatives)।

Serving-এ সব item embedding আগেই গণনা করে একটা ANN index (যেমন HNSW/ScaNN/FAISS) বানানো হয়। রিকোয়েস্ট-টাইমে শুধু user embedding বানিয়ে nearest neighbor query দিয়ে কয়েকশ আইটেম মুহূর্তে পাওয়া যায়। একটাই retriever যথেষ্ট নয় — তাই trending, freshly-uploaded, subscription-based, co-watch graph ইত্যাদি multiple source মিলিয়ে candidate জোগাড় করা হয়, যাতে coverage ভালো থাকে।

Ranking Model

এখানে precision গুরুত্বপূর্ণ। candidate-প্রতি অনেক feature (user, item, cross, context) নিয়ে একটা ভারী মডেল (যেমন gradient-boosted tree বা DNN) প্রতিটি আইটেমের জন্য একটা score দেয়। সাধারণত একে multi-task বানানো হয় — শুধু pCTR নয়, predicted watch time, like probability ইত্যাদি একসাথে শিখে একটা weighted combination দিয়ে final score।

Label আসে impression log + feedback জোড়া থেকে: দেখানো হয়েছে কিন্তু ক্লিক হয়নি = negative; ক্লিক ও দীর্ঘ watch = strong positive। Position bias একটা বড় ফাঁদ — উপরের আইটেম এমনিতেই বেশি ক্লিক পায়, তাই position-কে training-এ feature হিসেবে দিয়ে serving-এ neutralize করতে হয়।

Training Pipeline ও Feedback Loop

  • Streaming থেকে raw event → warehouse।
  • দৈনিক batch job point-in-time correct feature + label join করে training dataset বানায়।
  • মডেল retrain → offline eval (NDCG, AUC) → champion-challenger তুলনা।
  • পাস করলে online A/B test, তারপর ধীরে ধীরে rollout।
সাবধান

Feedback loop থেকে সাবধান। মডেল যা দেখায় শুধু তার উপরই feedback পায় — যা কখনো দেখায়নি তার কোনো data নেই। এর ফলে সিস্টেম একই ধরনের আইটেমে আটকে যায় (filter bubble / popularity bias)। তাই ইচ্ছাকৃত exploration (যেমন কিছু candidate randomly বা bandit দিয়ে দেখানো) রাখতেই হবে।

৭. বটলনেক ও স্কেলিং

  • Ranking latency: candidate বেশি হলে inference ব্যয়বহুল। সমাধান — candidate সংখ্যা সীমিত রাখা, feature precompute, এবং batching। heavy DNN হলে GPU server, না হলে কম-feature lightweight মডেল দিয়ে দুই-stage ranking।
  • Model serving cost: ৩৫K QPS × ভারী মডেল = বিশাল খরচ। caching দিয়ে অনেক রিকোয়েস্ট serving-ই এড়ানো যায় (সক্রিয় ব্যবহারকারীর জন্য কয়েক মিনিটের TTL সহ precomputed list)।
  • ANN index: ২৫ GB index sharded ও replicated, যাতে একটি নোড পড়লে service চালু থাকে। নতুন আইটেম ঢুকলে incremental index update।
  • Feature freshness vs latency: খুব fresh feature মানে বেশি streaming খরচ; ভারসাম্য রাখতে হয়।
  • Feedback loop ও drift: ব্যবহারকারীর রুচি বদলায়, নতুন trend আসে। তাই নিয়মিত retrain ও monitoring (CTR ধস হলে alert) দরকার।

৮. সারসংক্ষেপ

দুই-ধাপের আর্কিটেকচার — দ্রুত candidate generation দিয়ে কোটি থেকে কয়েকশ, তারপর নিখুঁত ranking — হলো বড় রেকমেন্ডারের মেরুদণ্ড। এর সাথে embedding, একটি সামঞ্জস্যপূর্ণ feature store, streaming feedback, আর নিয়মিত retraining যোগ করলে সিস্টেম স্কেলেবল ও fresh থাকে। Cold start ও exploration ভুলে গেলে শুরুতে ভালো দেখালেও দীর্ঘমেয়াদে আটকে যাবে।

টিপস

ইন্টারভিউয়ার দেখতে চান তুমি retrieval আর ranking-এর আলাদা লক্ষ্য (recall বনাম precision) বুঝেছ কিনা, training-serving skew ও position bias-এর মতো বাস্তব ML ফাঁদ চিনতে পারো কিনা, আর offline metric থেকে online A/B test পর্যন্ত পুরো feedback loop টানতে পারো কিনা। শুধু "একটা ML মডেল লাগাবো" বললে দুর্বল উত্তর — system ও data flow দেখাও।

মিনি কুইজ

1. দুই-ধাপের রেকমেন্ডার-এ candidate generation ধাপের মূল লক্ষ্য কী?

2. Feature store-এ offline ও online অংশ আলাদা রাখার মূল কারণ কী?

3. নতুন ব্যবহারকারীর cold start সমস্যা সামলানোর একটি কার্যকর উপায় কোনটি?