এআই অ্যাপগুলিতে UI, সেশন ও ডেটা স্টেট কীভাবে ফ্রন্টএন্ড ও ব্যাকএন্ডের মধ্যে চলাচল করে—সিঙ্ক, পারসিস্টেন্স, ক্যাশিং এবং সিকিউরিটির ব্যবহারিক প্যাটার্নসহ জানুন।

“স্টেট” হলো আপনার অ্যাপটি ঠিকভাবে কাজ করার জন্য যে সমস্ত তথ্য মনে রাখে তা।
যদি একটি ব্যবহারকারী চ্যাট UI-তে Send চাপেন, অ্যাপটি তাদের টাইপ করা বিষয়, অ্যাসিস্ট্যান্ট যা ইতিমধ্যে উত্তর দিয়েছে, কোনো অনুরোধ চলছে কিনা, বা কোন সেটিং (টোন, মডেল, টুলস) চালু আছে—এসব ভুলে গেলে চলবে না। এগুলোই স্টেট।
স্টেট ভাবার জন্য একটি উপযোগী উপায় হল: অ্যাপের বর্তমান সত্যতা—যে ভ্যালুগুলি ব্যবহারকারীকে কি দেখা যায় এবং সিস্টেম পরবর্তীভাবে কী করবে তা প্রভাবিত করে। এর মধ্যে স্পষ্ট জিনিসগুলো যেমন ফর্ম ইনপুটের পাশাপাশি “অদৃশ্য” বিষয়গুলোও রয়েছে, যেমন:
প্যারাম্পরিক (traditional) অ্যাপগুলো সাধারণত ডেটা পড়ে, দেখায়, এবং আপডেট সংরক্ষণ করে। এআই অ্যাপগুলোতে অতিরিক্ত ধাপ এবং মধ্যবর্তী আউটপুট আসে:
এই অতিরিক্ত চলাচলই এআই অ্যাপ্লিকেশনগুলোর স্টেট ম্যানেজমেন্টকে প্রায়শই লুকানো জটিলতা করে তোলে।
নিচের অংশগুলোতে আমরা স্টেটকে ব্যবহারিক শ্রেণিতে ভাগ করব (UI স্টেট, সেশন স্টেট, পারসিস্ট করা ডেটা, এবং মডেল/রানটাইম স্টেট) এবং দেখাবো প্রতিটি কোথায় থাকা উচিত (ফ্রন্টএন্ড বনাম ব্যাকএন্ড)। আমরা সিঙ্কিং, ক্যাশিং, দীর্ঘকালীন কাজ, স্ট্রিমিং আপডেট, এবং সিকিউরিটি-ও আলোচনা করব—কারণ স্টেট তখনই উপকারী যখন তা সঠিক এবং সুরক্ষিত হয়।
একটি চ্যাট অ্যাপ কল্পনা করুন যেখানে ব্যবহারকারী বলেন: “গত মাসের ইনভয়েসগুলো সারসংক্ষেপ করো এবং অস্বাভাবিক কিছু থাকলে ফ্ল্যাগ করো।” ব্যাকএন্ড সম্ভবত (1) ইনভয়েসগুলো আনবে, (2) একটি বিশ্লেষণ টুল চালাবে, (3) UI-তে সারাংশ স্ট্রিম করবে, এবং (4) চূড়ান্ত রিপোর্ট সংরক্ষণ করবে।
একটি স্নিগ্ধ অভিজ্ঞতা দিতে, অ্যাপটিকে মেসেজ, টুল রেজাল্ট, প্রগতি, এবং সংরক্ষিত আউটপুট ট্র্যাক করতে হবে—কনভার্সেশনগুলোর মধ্যে গুলিয়ে না দেওয়া বা ব্যবহারকারীদের মধ্যে ডেটা লিক করা ছাড়া।
যখন লোকেরা এআই অ্যাপে “স্টেট” বলে, তারা প্রায়শই খুব ভিন্ন জিনিসগুলো মিশিয়ে দেয়। স্টেটকে চারটি স্তরে ভাগ করলে—UI, সেশন, ডেটা, এবং মডেল/রানটাইম—নিশ্চিত করা সহজ হয় কোথায় কিছু থাকা উচিত, কে তা পরিবর্তন করতে পারে, এবং কীভাবে সংরক্ষিত করা উচিত।
UI স্টেট হলো ব্রাউজার বা মোবাইল অ্যাপে লাইভ, মূহর্ত-প্রতি-মূহর্তের স্টেট: টেক্সট ইনপুট, টগল, নির্বাচিত আইটেম, কোন ট্যাব খোলা আছে, এবং কোন বাটন ডিসেবল আছে কিনা।
এআই অ্যাপগুলো কিছু UI-নির্দিষ্ট বিবরণ যোগ করে:
UI স্টেট রিসেট করা সহজ হওয়া উচিত এবং হারানো নিরাপদ। যদি ব্যবহারকারী পৃষ্ঠা রিফ্রেশ করে, আপনি এটি হারায় ফেলতে পারেন—এটি সাধারণত ঠিক আছে।
সেশন স্টেট ব্যবহারকারীকে একটি চলমান ইন্টারঅ্যাকশনের সাথে বাঁধে: ব্যবহারকারী পরিচয়, একটি কনভার্সেশন আইডি, এবং মেসেজ ইতিহাসের একটি সঙ্গতিশীল ভিউ।
এআই অ্যাপগুলোতে এটির মধ্যে প্রায়শই থাকে:
এই স্তরটি প্রায়শই ফ্রন্টএন্ড এবং ব্যাকএন্ড উভয় জায়গায় বিস্তৃত: ফ্রন্টএন্ড হাল্কা আইডেন্টিফায়ার রাখে, আর ব্যাকএন্ড সেশন ধারাবাহিকতা এবং এক্সেস কন্ট্রোলের কর্তৃপক্ষ।
ডাটা স্টেট হলো আপনি ইচ্ছাকৃতভাবে ডাটাবেসে সংরক্ষণ করেন: প্রকল্প, ডকুমেন্ট, এমবেডিং, পছন্দসমূহ, অডিট লগ, বিলিং ইভেন্ট, এবং সংরক্ষিত কনভার্সেশন ট্রান্সক্রিপ্ট।
UI এবং সেশন স্টেটের বিপরীতে, ডাটা স্টেট হওয়া উচিত:
মডেল/রানটাইম স্টেট হলো উত্তর উৎপাদনের জন্য ব্যবহৃত অপারেশনাল সেটআপ: সিস্টেম প্রম্পট, টুলস সক্রিয় আছে কি না, টেম্পারেচার/ম্যাক্স টোকেন, সেফটি সেটিংস, রেট লিমিট, এবং অস্থায়ী ক্যাশ।
কিছু জিনিস কনফিগারেশন (স্থায়ী ডিফল্ট), কিছু অস্থায়ী (শর্ট-লাইভ ক্যাশ বা প্রতি অনুরোধ টোকেন বাজেট)। এগুলোর বেশিরভাগ ব্যাকএন্ডেই থাকা উচিত যাতে একবারে নিয়ন্ত্রণ করা যায় এবং অপ্রয়োজনীয়ভাবে প্রকাশ না হয়।
যখন এই স্তরগুলো ঝাপসা হয়ে যায়, তখন আপনি পাবেন প্রচলিত ব্যর্থতা: UI এমন টেক্সট দেখায় যা সংরক্ষিত হয়নি, ব্যাকএন্ড ফ্রন্টএন্ডের প্রত্যাশার চেয়ে ভিন্ন প্রম্পট সেটিং ব্যবহার করে, বা কনভার্সেশন মেমরি ব্যবহারকারীদের মধ্যে লিক করে। স্পষ্ট সীমানা প্রদান করলে কোনটি স্থায়ী হতে হবে, কোনটি পুনরায় গণনা করা যাবে, এবং কোনটি সুরক্ষিত থাকতে হবে তা পরিষ্কার হয়।
AI অ্যাপগুলিতে বাগ কমানোর নির্ভরযোগ্য উপায় হল প্রতিটি স্টেটের টুকরো জন্য সিদ্ধান্ত নেওয়া: ব্রাউজারে (ফ্রন্টএন্ড), সার্ভারে (ব্যাকএন্ড), নাকি উভয় জায়গায়। এই সিদ্ধান্ত নির্ভরযোগ্যতা, সিকিউরিটি, এবং ব্যবহারকারীর রিফ্রেশ/নতুন ট্যাব/নেটওয়ার্ক বিলুপ্তির সময় অ্যাপ কতটা “অবাক করা” হবে তা প্রভাবিত করে।
ফ্রন্টএন্ড স্টেট তাদের জন্য ভাল যারা দ্রুত পরিবর্তিত হয় এবং রিফ্রেশের পরও টিকে থাকতে হবে না। লোকাল রাখা UI-কে রেসপনসিভ করে এবং অপ্রয়োজনীয় API কল প্রতিরোধ করে।
কমন ফ্রন্টএন্ড-ওনলি উদাহরণ:
যদি আপনি রিফ্রেশে এই স্টেট হারান, তা সাধারণত গ্রহণযোগ্য।
ব্যাকএন্ড স্টেট হওয়া উচিত যেগুলো বিশ্বাসযোগ্য, অডিটযোগ্য বা ধারাবাহিকভাবে রক্ষা করতে হবে। এতে অন্তর্ভুক্ত এমন স্টেট যা অন্য ডিভাইস/ট্যাবকে দেখতে হবে, বা ক্লায়েন্ট পরিবর্তিত হলেও সঠিক থাকতে হবে।
কমন ব্যাকএন্ড-ওনলি উদাহরণ:
একটি ভাল মানসিকতা: যদি ভুল স্টেট খরচ করা বা ডেটা লিক করার কারণ হতে পারে, বা অ্যাক্সেস কন্ট্রোল ভাঙবে, তাহলে তা ব্যাকএন্ডে রাখা উচিত।
কিছু স্টেট স্বভাবতই শেয়ার করা হয়:
শেয়ার করার সময়ও একটি “সোর্স অফ ট্রুথ” বেছে নিন। সাধারণত ব্যাকএন্ডই কর্তৃপক্ষ এবং ফ্রন্টএন্ড দ্রুততার জন্য একটি কপি ক্যাশ করে রাখে।
স্টেটকে যেখানে প্রয়োজন, সেখানে কাছাকাছি রাখুন, তবে যা রিফ্রেশ, ডিভাইস পরিবর্তন বা বিঘ্নে টিকে থাকতে হবে তা পারসিস্ট করুন।
সাধারণ অ্যান্টি-প্যাটার্নটি হলো সংবেদনশীল বা কর্তৃত্বপূর্ণ স্টেট কেবল ব্রাউজারে রাখা (যেমন ক্লায়েন্ট-সাইড isAdmin ফ্ল্যাগ, প্ল্যান টিয়ার, বা জব কমপ্লিশন স্টেটকে সত্যি ধরে নেওয়া)। UI এই মানগুলো প্রদর্শন করতে পারে, কিন্তু ব্যাকএন্ডকে অবশ্যই যাচাই করতে হবে।
একটি এআই ফিচার “একটি কাজ” মনে হয়, কিন্তু আসলে এটি ব্রাউজার ও সার্ভারের মধ্যে স্টেট ট্রানজিশনের একটি চেইন। লাইফসাইকেল বোঝা মিলিয়ে দেয় কীভাবে UI মেলানো যায়, কনটেক্সট নিশ্চিত করা যায়, এবং দ্বিগুণ চার্জ থেকে বাঁচা যায়।
ব্যবহারকারী Send চাপলে UI দ্রুত লোকাল স্টেট আপডেট করে: হয়তো একটি “পেন্ডিং” মেসেজ বাবল যোগ করা হবে, সেন্ড বাটন ডিসেবল হবে, এবং বর্তমান ইনপুট (টেক্সট, অ্যাটাচমেন্ট, নির্বাচিত টুলস) ক্যাপচার করা হবে।
এই সময় ফ্রন্টএন্ডকে করিলেশন আইডি জেনারেট বা সংযুক্ত করা উচিত:
এই আইডিগুলো উভয় পক্ষকে একই ইভেন্ট সম্পর্কে কথা বলতে দেয়, এমনকি যখন উত্তর দেরিতে বা দ্বিগুণ এসে পড়ে।
ফ্রন্টএন্ড ইউজার মেসেজ এবং আইডিগুলো নিয়ে একটি API অনুরোধ পাঠায়। সার্ভার অনুমতি, রেট লিমিট, এবং পে লোড শেইপ যাচাই করে, তারপর ইউজার মেসেজটি (অথবা অন্তত একটি ইমিউটেবল লগ রেকর্ড) conversation_id এবং message_id দিয়ে কীড করে সংরক্ষণ করে।
এই পারসিস্টেন্স ধাপটি রিকোয়েস্ট মাঝখানে রিফ্রেশ করলে “ভূত ইতিহাস” প্রতিরোধ করে।
মডেল কল করার জন্য সার্ভার তার সোর্স-অফ-ট্রুথ থেকে কনটেক্সট পুনর্নির্মাণ করে:
মূল ধারণা: ক্লায়েন্টকে পুরো ইতিহাস দেওয়ার উপর নির্ভর করবেন না। ক্লায়েন্ট স্টেইল হতে পারে।
সার্ভার টুলগুলো কল করতে পারে (সার্চ, ডিবি লুকআপ) মডেল জেনারেশনের আগে বা চলাকালীন। প্রতিটি টুল কল একটি মধ্যবর্তী স্টেট উৎপন্ন করে যা request_id-এর সাথে ট্র্যাক করা উচিত যাতে এটিকে অডিট ও নিরাপদভাবে রিট্রাই করা যায়।
স্ট্রিমিং হলে সার্ভার আংশিক টোকেন/ইভেন্ট প্রেরণ করে। UI পরপর pending assistant মেসেজ আপডেট করে, কিন্তু একটি ফাইনাল ইভেন্ট না এলে এটি “চলমান” ধরেই থাকে।
রিট্রাই, ডাবল-সাবমিট, এবং আউট-অফ-অর্ডার রেসপন্স ঘটে। সার্ভারে ডিউপ করার জন্য request_id ব্যবহার করুন, এবং UI-তে মিলানোর জন্য message_id ব্যবহার করুন (সক্রিয় অনুরোধের সাথে ম্যাচ না করলে দেরিতে আসা চাঙ্ক উপেক্ষা করুন)। সর্বদা স্পষ্ট “failed” স্টেট দেখান এবং একটি নিরাপদ রিট্রাই’opশন দিন যাতে ডুপ্লিকেট মেসেজ তৈরি না হয়।
সেশন হলো সেই “থ্রেড” যা ব্যবহারকারীর অ্যাকশনগুলোকে একসাথে বেঁধে রাখে: তারা কোন ওয়ার্কস্পেসে আছে, তারা শেষ কী সার্চ করেছে, কোন ড্রাফট এডিট করছিল, এবং কোন কনভার্সেশনে AI-র উত্তর চালিয়ে যেতে হবে। ভালো সেশন স্টেট পেজ বদলালেও অ্যাপটিকে ধারাবাহিক মনে করায়—এবং আদর্শভাবে ডিভাইস জুড়ে—বিনা পটিয়ে ব্যাকএন্ডকে সব কিছু জমে রাখা ছাড়া।
লক্ষ্য রাখুন: (1) ধারাবাহিকতা (ব্যবহারকারী ছেড়ে এসে ফেরত আসতে পারে), (2) সঠিকতা (AI সঠিক কনটেক্সটে সাড়া দেয়), এবং (3) কনটেইনমেন্ট (এক সেশন অন্যটির মধ্যে লিক না করে)। যদি আপনি একাধিক ডিভাইস সমর্থন করেন, সেশনকে ব্যবহারকারী-স্কোপড প্লাস ডিভাইস-স্কোপড বিবেচনা করুন: “একই অ্যাকাউন্ট” মানে সবসময় “একই খোলা কাজ” নয়।
আপনি সাধারণত সেশন শনাক্ত করার জন্য নিচের উপায়গুলোর মধ্যে একটি বেছে নেবেন:
HttpOnly, Secure, SameSite) এবং CSRF সমাধান করতে হবে।“মেমরি” হল কেবলই সেই স্টেট যেটি আপনি মডেলের কাছে ফেরত পাঠাতে বেছে নেন।
প্রায়োগিক প্যাটার্ন হল সারাংশ + উইন্ডো: এটি পূর্বাভাসযোগ্য এবং অপ্রত্যাশিত মডেল আচরণ কমায়।
যদি AI টুল ব্যবহার করে (সার্চ, ডাটাবেস কুয়েরি, ফাইল রিড), প্রতিটি টুল কল সংরক্ষণ করুন: ইনপুট, টাইমস্ট্যাম্প, টুল সংস্করণ, এবং ফিরিয়ে দেওয়া আউটপুট (অথবা তার রেফারেন্স)। এতে আপনি বুঝতে পারবেন “কেন AI সেটা বলল,” ডিবাগিংয়ের জন্য রানগুলিকে রেপ্লে করতে পারবেন, এবং টুল বা ডেটাসেট পরিবর্তনের কারণে ফলাফল পরিবর্তন হলে তা সনাক্ত করতে পারবেন।
ডিফল্টভাবে দীর্ঘমেয়াদী মেমরি সংরক্ষণ করবেন না। কেবল ধারাবাহিকতার জন্য প্রয়োজনীয় জিনিসগুলো রাখুন (কনভার্সেশন আইডি, সারাংশ, টুল লগ), রিটেনশন লিমিট সেট করুন, এবং কাঁচা ব্যবহারকারী টেক্সট সংরক্ষণ করা থেকে বিরত থাকুন যদি না স্পষ্ট প্রোডাক্ট কারণ এবং ব্যবহারকারীর সম্মতি থাকে।
যখন একই “বস্তু” একাধিক জায়গায় সম্পাদিত হতে পারে—আপনার UI, আরেকটি ব্রাউজার ট্যাব, বা একটি ব্যাকগ্রাউন্ড জব—স্টেট ঝুঁকিপূর্ণ হয়ে ওঠে। সমাধান চতুর কডিংয়ের চেয়ে স্পষ্ট মালিকানার নিয়মে বেশি।
প্রতিটি স্টেট অংশের জন্য সিদ্ধান্ত নিন কোন সিস্টেম কর্তৃত্বশালী। অধিকাংশ AI অ্যাপ্লিকেশনে ব্যাকএন্ডকে canonical রেকর্ড দেওয়া উচিত যে কোনও কিছুর জন্য যা সঠিক হতে হবে: কনভার্সেশন সেটিংস, টুল পারমিশন, মেসেজ ইতিহাস, বিলিং সীমা, এবং জব স্ট্যাটাস। ফ্রন্টএন্ড কেশ করে কপি রাখতে পারে দ্রুততার জন্য (নির্বাচিত ট্যাব, ড্রাফট প্রম্পট টেক্সট, “টাইপ করছে” নির্দেশ), কিন্তু কোনো মিলবৈরিতা থাকলে ব্যাকএন্ডকে সঠিক ধরুন।
প্র্যাকটিকাল নিয়ম: যদি এটি রিফ্রেশে হারালে আপনি বিরক্ত হবেন, এটি সম্ভবত ব্যাকএন্ডে থাকা উচিত।
অপটিমিস্টিক আপডেট অ্যাপটিকে তাত্ক্ষণিক মনে করায়: কোনো সেটিং টগল করুন, UI তত্ক্ষণিক আপডেট করুন, তারপর সার্ভারের সাথে কনফার্ম করুন। এটি কম-স্টেকস, উল্টানোযোগ্য অ্যাকশনের (যেমন কোনো কনভার্সেশন স্টার করা) জন্য ভাল কাজ করে।
যখন সার্ভার পরিবর্তন প্রত্যাখ্যান বা রূপান্তর করতে পারে (পারমিশন চেক, কোটা লিমিট, ভ্যালিডেশন, বা সার্ভার-সাইড ডিফল্ট), তখন বিভ্রান্তি সৃষ্টি করে। সেই সব ক্ষেত্রে “saving…” স্টেট দেখান এবং কেবল কনফার্ম হওয়ার পরে UI আপডেট করুন।
কনফ্লিক্ট ঘটে যখন দুই ক্লায়েন্ট একই রেকর্ড আলাদা শুরু ভার্সন থেকে আপডেট করে। সাধারণ উদাহরণ: ট্যাব A এবং ট্যাব B উভয়ই মডেল টেম্পারেচার পরিবর্তন করে।
স্টেল রাইট সনাক্ত করার জন্য লাইটওয়েট ভার্শনিং ব্যবহার করুন:
updated_at টাইমস্ট্যাম্প (সহজ এবং মানুষের বোঝার মতো)If-Match হেডার (HTTP-নেটিভ)যদি ভার্সন মেলে না, একটি কনফ্লিক্ট রেসপন্স (প্রায়শই HTTP 409) রিটার্ন করুন এবং সর্বশেষ সার্ভার অবজেক্ট পাঠান।
কোনও রাইটের পরে API-কে সেভ করা অবজেক্ট রিটার্ন করান (সার্ভার-জেনারেটেড ডিফল্ট, নর্মালাইজড ফিল্ড, এবং নতুন ভার্সন সহ)। এতে ফ্রন্টএন্ড তার ক্যাশ করা কপি তৎক্ষণাত প্রতিস্থাপন করতে পারে—এক উৎস-অফ-ট্রুথ আপডেট, অনুমান করার চেয়ে ভালো।
ক্যাশিং অ্যাপটিকে তাত্ক্ষণিক মনে করানোর দ্রুত উপায়গুলোর একটি, কিন্তু এটি একই সময়ে স্টেটের দ্বিতীয় কপি তৈরি করে। যদি আপনি ভুল জিনিস ক্যাচ করেন—অথবা ভুল জায়গায়—তবে আপনি দ্রুত কিন্তু বিভ্রান্তিকর UI পাঠাচ্ছেন।
ক্লায়েন্ট-সাইড ক্যাশগুলো অভিজ্ঞতার উপর ফোকাস করা উচিত, কর্তৃত্ব নয়। ভালো প্রার্থীরা:
ক্লায়েন্ট ক্যাশ ছোট এবং ডিসপোজেবল রাখুন: যদি এটি মুছে যায়, অ্যাপটিকে সার্ভার থেকে পুনরায় নিয়ে কাজ করতে সক্ষম হতে হবে।
সার্ভার ক্যাশগুলো ব্যয়বহুল বা ঘন ঘন পুনরায় চালিত কাজের উপর ফোকাস করা উচিত:
এখানেই আপনি ডেরিভড স্টেটও ক্যাশ করতে পারেন যেমন টোকেন কাউন্ট, মনিটরিং ডিসিশন, বা ডকুমেন্ট পার্সিং আউটপুট—যেগুলো ডিটারমিনিস্টিক এবং ব্যয়বহুল।
তিনটি ব্যবহারিক নিয়ম:
user_id, মডেল, টুল প্যারামিটার, ডকুমেন্ট ভার্সন)।আপনি যদি ব্যাখ্যা করতে না পারেন কখন কোনও ক্যাশ এন্ট্রি ভুল হয়ে যাবে, সেটিকে ক্যাশ করবেন না।
শেয়ার্ড লেয়ারে (CDN) API কী, অথ টোকেন, কাঁচা প্রম্পট বা ব্যবহারকারী-নির্দিষ্ট কনটেন্ট ক্যাশ করবেন না। যদি ব্যবহারকারীর ডেটা ক্যাশ করতে হয়, তাহলে ব্যবহারকারী অনুযায়ী আলাদা করে এনক্রিপ্টেড রাখুন—অথবা প্রাইমারি ডাটাবেসে রাখুন।
ক্যাশিংকে প্রমাণিত করে নিন, অনুমান করে না। p95 ল্যাটেন্সি আগে/পরে মাপুন, ক্যাশ হিট রেট, এবং ব্যবহারকারী-দৃশ্য ত্রুটি ট্র্যাক করুন যেমন “রেন্ডার করার পরে মেসেজ আপডেট হয়েছে”। পরে UI-র সাথে টক্কর খাওয়া একটি দ্রুত প্রতিক্রিয়া সাধারণত ধীরে কিন্তু সামঞ্জস্যপূর্ণ প্রতিক্রিয়ার চাইতে খারাপ।
কিছু এআই ফিচার এক সেকেন্ডে শেষ হয়। কিছু মিনিট নেয়: PDF আপলোড ও পার্স করা, নলেজ বেস এম্বেডিং ও ইনডেক্স করা, অথবা বহু-ধাপ টুল ওয়ারফ্লো চালানো। এসবের জন্য, “স্টেট” কেবল স্ক্রিনে থাকা নয়—এটি রিফ্রেশ, রিট্রাই, এবং সময় সইয়ে টিকে থাকা জিনিস।
কেবলমাত্র যা প্রকৃত প্রোডাক্ট ভ্যালু Unlock করে তা পারসিস্ট করুন।
কনভার্সেশন হিস্ট্রি হলো স্পষ্ট জিনিস: মেসেজ, টাইমস্ট্যাম্প, ব্যবহারকারী আইডেন্টিটি, এবং প্রায়ই কোন মডেল/টুল ব্যবহৃত হয়েছে। এটি “পরে আবার শুরু করুন”, অডিট ট্রেল, এবং শ্রেষ্ঠ সাপোর্ট চালনায় কাজ করে।
ব্যবহারকারী ও ওয়ার্কস্পেস সেটিংস ডাটাবেসে থাকা উচিত: পছন্দকৃত মডেল, টেম্পারেচার ডিফল্ট, ফিচার টগল, সিস্টেম প্রম্পট, এবং যেগুলো ব্যবহারকারী ডিভাইস জুড়ে অনুসরণ করবে এমন UI পছন্দ।
ফাইল ও আর্টিফ্যাক্ট (আপলোড, এক্সট্র্যাক্ট টেক্সট, জেনারেটেড রিপোর্ট) সাধারণত অবজেক্ট স্টোরেজে রাখা হয়, ডাটাবেস রেকর্ডগুলো তাদের পয়েন্টার হয়। ডাটাবেসে মেটাডেটা থাকে (মালিক, সাইজ, কনটেন্ট টাইপ, প্রসেসিং স্টেট) এবং ব্লব স্টোরে বাইটগুলি।
যদি একটি অনুরোধ সাধারণ HTTP টাইমআউটের মধ্যে নির্ভরযোগ্যভাবে শেষ না হতে পারে, কাজটিকে কিউতে সরিয়ে দিন।
টিপিক্যাল প্যাটার্ন:
POST /jobs-এর মতো একটি API কল করে ইনপুট (ফাইল আইডি, কনভার্সেশন আইডি, প্যারামিটার) দিয়ে।job_id রিটার্ন করে।এটি UI-কে রেসপনসিভ রাখে এবং রিট্রাইলকে নিরাপদ করে।
জব স্টেট স্পষ্ট ও কুয়েরি যোগ্য করুন: queued → running → succeeded/failed (ঐচ্ছিক canceled)। এই ট্রানজিশনগুলো সার্ভার-সাইডে টাইমস্ট্যাম্প ও এরর ডিটেইলসহ স্টোর করুন।
ফ্রন্টএন্ডে স্ট্যাটাস স্পষ্টভাবে প্রতিফলিত করুন:
GET /jobs/{id} (পোলিং) বা আপডেট স্ট্রিম (SSE/WebSocket) এক্সপোজ করুন যাতে UI অনুমান না করে।
নেটওয়ার্ক টাইমআউট হয়। যদি ফ্রন্টএন্ড POST /jobs রিট্রাই করে, আপনি দুটি একই জব চান না (এবং দুটি বিল)।
প্রতি লজিক্যাল অ্যাকশনের জন্য একটি Idempotency-Key বাধ্যতামূলক করুন। ব্যাকএন্ড কীটি রেসপন্স/job_id-এর সাথে স্টোর করে এবং পুনরাবৃত্ত অনুরোধে একই ফলাফল রিটার্ন করে।
দীর্ঘমেয়াদী এআই অ্যাপগুলো দ্রুত ডেটা জমা করে। শুরুতেই রিটেনশন রুল নির্ধারণ করুন:
ক্লিনআপকে স্টেট ম্যানেজমেন্টের অংশ হিসেবে বিবেচনা করুন: এটি ঝুঁকি, খরচ, এবং বিভ্রান্তি কমায়।
স্ট্রিমিং মানে “উত্তর” আর একক ব্লব নয়। আপনি আংশিক টোকেন (শব্দে-শব্দে টেক্সট) এবং কখনও কখনও আংশিক টুল কাজের সাথে ডিল করছেন। এর মানে UI ও ব্যাকএন্ডকে অস্থায়ী বনাম চূড়ান্ত স্টেট কী তা নিয়ে একইভাবে সম্মত হতে হবে।
একটি পরিষ্কার প্যাটার্ন হল ছোট ইভেন্টগুলোর সিকোয়েন্স স্ট্রিম করা, প্রতিটিতে একটি টাইপ ও পে-লোড থাকে। উদাহরণ:
token: ইঙ্ক্রিমেন্টাল টেক্সট (অর্থাৎ ছোট চাঙ্ক)tool_start: একটি টুল কল শুরু হয়েছে (উদাহরণ: “Searching…”, একটি id সহ)tool_result: টুল আউটপুট প্রস্তুত (একই id)done: অ্যাসিস্ট্যান্ট মেসেজ সম্পূর্ণerror: কিছু ব্যর্থ হয়েছে (একটি ব্যবহারকারী-নিরাপদ বার্তা এবং একটি ডিবাগ id অন্তর্ভুক্ত)এই ইভেন্ট স্ট্রিম কাঁচা টেক্সট স্ট্রিমিংয়ের তুলনায় ভেসণযোগ্য ও ডিবাগ-বান্ধব, কারণ ফ্রন্টএন্ড প্রগতি সঠিকভাবে রেন্ডার করতে পারে (এবং টুল স্ট্যাটাস দেখাতে পারে) অনুমান না করে।
ক্লায়েন্টে স্ট্রিমিংকে অ্যাপেন্ড-অনলি হিসেবে ধরুন: একটি “ড্রাফট” অ্যাসিস্ট্যান্ট মেসেজ তৈরি করুন এবং token ইভেন্ট আসা মাত্র তা বাড়াতে থাকুন। done এলে একটি কমিট সম্পাদন করুন: মেসেজকে চূড়ান্ত চিহ্নিত করুন, যদি লোকালভাবে সংরক্ষণ করে থাকেন তা পারসিস্ট করুন, এবং কপি/রেট/রিজেনারেট মতো অ্যাকশন আনলক করুন।
এটি ইতিহাস মাঝখানে লিখে ফেলা এড়ায় এবং UI-কে পূর্বানুমানযোগ্য রাখে।
স্ট্রিমিং মাঝপথে আধা-সম্পন্ন কাজের সম্ভবনা বাড়ায়:
পেজ রিফ্রেশ হওয়ার সময় যদি স্ট্রিম চলছে, শেষ স্থিতিশীল স্টেট থেকে পুনর্নির্মাণ করুন: শেষ কমিট করা মেসেজ এবং যে কোনও স্টোর করা ড্রাফট মেটাডেটা (মেসেজ আইডি, জমা হওয়া টেক্সট, টুল স্ট্যাটাস)। যদি আপনি স্ট্রিম পুনরায় শুরু করতে না পারেন, ড্রাফটকে বাধাগ্রস্তভাবে দেখান এবং ব্যবহারকারীকে রিট্রাই করতে দিন—সম্পন্ন হয়েছে বলে ছদ্মবেশ করা থেকে বিরত থাকুন।
স্টেট শুধুই “আপনি যা সংরক্ষণ করেন” নয়—এটি ব্যবহারকারীর প্রম্পট, আপলোড, পছন্দ, জেনারেটেড আউটপুট, এবং যে মেটাডাটা সবকিছুকে একত্রে বাঁধে। এআই অ্যাপে সেই স্টেটটি অসাধারণভাবে সংবেদনশীল হতে পারে (ব্যক্তিগত তথ্য, স্বত্বাধীন ডকুমেন্ট, অভ্যন্তরীণ সিদ্ধান্ত), তাই প্রতিটি স্তরে সিকিউরিটি ডিজাইন করা প্রয়োজন।
কোনোও জিনিসই যা ক্লায়েন্টকে আপনার অ্যাপ হয়ে ছদ্মবেশ করার অনুমতি দেয় তা ব্যাকএন্ড-অনলি রাখুন: API কী, প্রাইভেট কনেক্টর (Slack/Drive/DB ক্রেডেনশিয়াল), এবং অভ্যন্তরীণ সিস্টেম প্রম্পট বা রাউটিং লজিক। ফ্রন্টএন্ড একটি অ্যাকশন অনুরোধ করতে পারে (“এই ফাইল সারসংক্ষেপ করো”), কিন্তু ব্যাকএন্ড সিদ্ধান্ত নেবে কিভাবে ও কোন ক্রেডেনশিয়াল দিয়ে এক্সিকিউট করা হবে।
প্রতিটি স্টেট মিউটেশনকে একটি প্রিভিলেজড অপারেশন হিসেবে বিবেচনা করুন। ক্লায়েন্ট যখন মেসেজ তৈরি করে, কনভার্সেশন রিনেম করে, বা ফাইল অ্যাটাচ করে, ব্যাকএন্ড যাচাই করবে:
এটি “ID guessing” আক্রমণ প্রতিরোধ করে যেখানে কেউ conversation_id বদলে অন্যের ইতিহাস অ্যাক্সেস করে।
কোনো ক্লায়েন্ট-প্রদত্ত স্টেটকে অনুগ্রহ করে অ-ট্রাস্টেড ইনপুট ধরুন। স্কিমা ও সীমা যাচাই করুন (টাইপ, লেন্থ, অনুমোদিত এনাম), এবং গন্তব্য অনুযায়ী স্যানিটাইজ করুন (SQL/NoSQL, লগ, HTML রেন্ডারিং)। যদি আপনি “স্টেট আপডেট” গ্রহণ করেন (যেমন সেটিংস, টুল প্যারামিটার), তাহলে হোয়াইটলিস্টেড ফিল্ডগুলোকেই অনুমতি দিন পরিবর্তে য arbitrary JSON মার্জ করা।
যে অ্যাকশনগুলো স্থায়ী স্টেট বদলে দেয়—শেয়ারিং, এক্সপোর্ট, ডিলিট, কনেক্টর অ্যাক্সেস—কারা কী করেছে ও কখন তা রেকর্ড করুন। একটি হালকা অডিট লগ incident response, কাস্টমার সাপোর্ট, ও কমপ্লায়েন্সে সহায়ক।
ফিচার দেওয়ার জন্য প্রয়োজনীয় যা-ই না থাক তা সংরক্ষণ করবেন না। যদি আপনাকে চিরস্থায়ীভাবে পুরো প্রম্পট রাখতে না হয়, তাহলে রিটেনশন উইন্ডো বা রিড্যাকশন বিবেচনা করুন। সংবেদনশীল স্টেট (টোকেন, কনেক্টর ক্রেডেনশিয়াল, আপলোড করা ডকুমেন্ট) অ্যাট-রেস্ট এনক্রিপ্ট করুন এবং ট্রানজিটে TLS ব্যবহার করুন। অপারেশনাল মেটাডাটা ও কনটেন্ট আলাদা রাখুন যাতে আপনি কন্টেন্টে প্রবেশাধিকার আরও কঠোরভাবে সীমাবদ্ধ করতে পারেন।
AI অ্যাপগুলোর জন্য একটি দরকারি ডিফল্ট সহজ: ব্যাকএন্ড হল সোর্স অফ ট্রুথ, এবং ফ্রন্টএন্ড একটি দ্রুত, অপটিমিস্টিক ক্যাশ। UI তাত্ক্ষণিক মনে হতে পারে, কিন্তু আপনি যা হারাতে দুঃখ করবেন (মেসেজ, জব স্ট্যাটাস, টুল আউটপুট, বিলিং-প্রাসঙ্গিক ইভেন্ট) তা সার্ভার-সাইডে নিশ্চিত ও সংরক্ষিত করা উচিত।
আপনি যদি “vibe-coding” ওয়ার্কফ্লো-এ নির্মাণ করেন—যেখানে অনেক প্রোডাক্ট সারফেস দ্রুত জেনারেট হয়—স্টেট মডেল আরও গুরুত্বপূর্ণ হয়ে ওঠে। Koder.ai-এর মতো প্ল্যাটফর্ম টীমকে চ্যাট থেকে পূর্ণ ওয়েব, ব্যাকএন্ড, ও মোবাইল অ্যাপ শিপ করতে সাহায্য করতে পারে, কিন্তু একই নিয়ম প্রযোজ্য: দ্রুত পুনরাবৃত্তি নিরাপদ যখন আপনার সত্যতার উৎস, আইডি, এবং স্ট্যাটাস ট্রানজিশনগুলি প্রথমেই ডিজাইন করা থাকে।
ফ্রন্টএন্ড (ব্রাউজার/মোবাইল)
session_id, conversation_id, এবং একটি নতুন request_id।ব্যাকএন্ড (API + ওয়ার্কার)
দ্রষ্টব্য: একটি প্র্যাকটিকাল উপায় কনসিস্টেন্ট রাখা early: উদাহরণস্বরূপ, Koder.ai-জেনারেটেড ব্যাকএন্ড সাধারণত Go + PostgreSQL ব্যবহার করে (এবং ফ্রন্টএন্ডে React), যা SQL-এ কর্তৃপক্ষ স্টেট কেন্দ্রীভূত করে এবং ক্লায়েন্ট ক্যাশ ডিসপোজেবল রাখে।
স্ক্রিন তৈরি করার আগে, প্রতিটি স্তরে আপনি উপর নির্ভর করবেন এমন ফিল্ডগুলো সংজ্ঞায়িত করুন:
user_id, org_id, conversation_id, message_id, request_id।created_at, updated_at, এবং মেসেজের জন্য একটি স্পষ্ট sequence।queued | running | streaming | succeeded | failed | canceled (জব ও টুল কলের জন্য)।etag বা version।এটি সেই ক্লাসিক বাগ প্রতিরোধ করে যেখানে UI “ঠিক মনে হচ্ছে” কিন্তু রিট্রাই, রিফ্রেশ, বা সমান্তরাল এডিট রিকনসাইল করতে পারে না।
ফিচারজুড়ে এন্ডপয়েন্টগুলো পূর্বানুমানযোগ্য রাখুন:
GET /conversations (লিস্ট)GET /conversations/{id} (পাওয়া)POST /conversations (তৈরি)POST /conversations/{id}/messages (অ্যাপেন্ড)PATCH /jobs/{id} (স্ট্যাটাস আপডেট)GET /streams/{request_id} বা POST .../stream (স্ট্রিম)সব জায়গায় একই এনভেলপ স্টাইল রিটার্ন করুন (এরর সহ) যাতে ফ্রন্টএন্ড ইউনিফর্মলি স্টেট আপডেট করতে পারে।
প্রতি এআই কলের জন্য লগ ও একটি request_id রিটার্ন করুন। টুল-কলে ইনপুট/আউটপুট রেকর্ড করুন (রিড্যাকশনসহ), ল্যাটেন্সি, রিট্রাই, এবং চূড়ান্ত স্ট্যাটাস। সহজ করে দিন উত্তর: “মডেল কী দেখল, কোন টুলগুলো চালানো হয়েছে, এবং আমরা কী স্টেট পারসিস্ট করলাম?”
request_id (এবং/অথবা Idempotency-Key) ব্যবহার করে।queued থেকে succeeded-এ নেই)।version/etag বা সার্ভার-সাইড মিশ্রণ নীতিমালা দিয়ে হ্যান্ডেল করা হয়।যখন আপনি দ্রুত বিল্ড সাইকেল (এআই-সহায়িত জেনারেশন সহ) গ্রহণ করবেন, এই চেকলিস্টের আইটেমগুলো স্বয়ংক্রিয়ভাবে প্রয়োগ করার গার্ডরেল যোগ করার চিন্তা করুন—স্কিমা ভ্যালিডেশন, আইডেম্পোটেন্সি, এবং ইভেন্টেড স্ট্রিমিং—তাহলে “দ্রুত চলা” স্টেট ড্রিফটে পরিণত হবে না। বাস্তবে, এটাই সেই জায়গা যেখানে Koder.ai-এর মতো একটি end-to-end প্ল্যাটফর্ম সহায়ক হতে পারে: এটি ডেলিভারিকে দ্রুত করে, আবার আপনি সোর্স কোড এক্সপোর্ট করে স্টেট-হ্যান্ডলিং প্যাটার্নগুলো ওয়েব, ব্যাকএন্ড, এবং মোবাইল জুড়ে ধারাবাহিক রাখতে পারবেন।