সপ্তাহব্যাপী নিরব ডেটা লসের পর LangGraph এজেন্টরা অবশেষে তাদের স্টেট (state) সংরক্ষণ করার একটি নির্ভরযোগ্য উপায় খুঁজে পেয়েছে। তিনটি ব্যর্থ চেকবয়েন্টিং ট্রিক—SQLite, র-অবজেক্ট স্টোরেজ এবং প্রতিটিটির একটি ত্রুটিপূর্ণ সংস্করণ—ব্যবহার করার পর, লেখক একটি অ্যাটমিক-আপডেট প্যাটার্নে পৌঁছেছেন যা প্রতিটি রিকোয়েস্ট আসার সময় এজেন্টদের শুরু থেকে পুনরায় শুরু করা থেকে বিরত রাখে।

LangGraph-এর জন্য কেন চেকবয়েন্টিং গুরুত্বপূর্ণ

LangGraph ডেভেলপারদের LLM কলগুলোকে পুনরায় ব্যবহারযোগ্য “এজেন্ট”-এ যুক্ত করতে সাহায্য করে যা কথোপকথনের আগের ঘটনাগুলো মনে রাখতে পারে। সেই এজেন্টগুলো ব্যবহারকারীর রিকোয়েস্টকে সাব-টাস্কে বিভক্ত করে, মধ্যবর্তী ফলাফলগুলো সংরক্ষণ করে এবং পরবর্তী কলে যেখানে শেষ করেছিল সেখান থেকেই পুনরায় শুরু করে। যদি সংরক্ষিত স্টেট হারিয়ে যায়, তবে এজেন্ট সবকিছু পুনরায় গণনা করে, যা কম্পিউটেশন নষ্ট করে, ল্যাটেন্সি বাড়িয়ে দেয় এবং ব্যবহারকারীর অভিজ্ঞতা খারাপ করে। টেলিগ্রাম মেসেজ হ্যান্ডেল করা একটি প্রোডাকশন বটের ক্ষেত্রে, এই ডেটা লস কয়েক সপ্তাহের কথোপকথনের ইতিহাস মুছে ফেলেছিল।

প্রথম সমাধান: SQLite saver

যখন একটি সিঙ্গেল ইনস্ট্যান্স এজেন্ট চালায়, তখন বিল্ট-ইন SqliteSaver ঠিকঠাক কাজ করে। এটি প্রতিটি চেকবয়েন্ট একটি লোকাল SQLite ফাইলে JSON ব্লব হিসেবে লেখে। সমস্যা শুরু হয় যখন ডেভেলপার AgentState টাইপে একটি নতুন ফিল্ড যোগ করেন এবং পুনরায় ডেপ্লয় করেন। স্কিমা পরিবর্তনের আগে তৈরি করা বিদ্যমান চেকবয়েন্টগুলোতে নতুন ফিল্ডটি ছিল না। যেহেতু SqliteSaver কখনোই মাইগ্রেশন চালায় না, LangGraph অসম্পূর্ণ JSON লোড করে, অনুপস্থিত ডেটা বাদ দিয়ে দেয় এবং এজেন্ট শুরু থেকে পুনরায় শুরু করে।

মূল বিষয়: SQLite স্টোরেজ একটি ডেমো টুল, স্কিমা ইভোলিউশন (schema evolution) প্রয়োজন হলে এটি প্রোডাকশন-রেডি সমাধান নয়।

দ্বিতীয় সমাধান: Object storage

সিরিয়ালাইজেশন ফরম্যাটের ওপর নিয়ন্ত্রণ পেতে লেখক একটি কাস্টম সেভার লিখলেন যা JSON চেকবয়েন্টটি Oracle Cloud Object Storage-এ আপলোড করত। এই পদক্ষেপটি ম্যানুয়ালি স্কিমা ভার্সন করার নমনীয়তা দিলেও এটি একটি নতুন ত্রুটি বা 'failure mode' তৈরি করে। যখন দুটি রিকোয়েস্ট একই সাথে একই কনভারসেশন থ্রেডে হিট করে, তখন উভয়ই একই অবজেক্টকে ওভাররাইট করার চেষ্টা করে। অবজেক্ট স্টোরেজ সার্ভিসগুলো 'write-once, read-many' প্যাটার্নের জন্য অপ্টিমাইজ করা; তারা অ্যাটমিক ওভাররাইট সিম্যান্টিকস (atomic overwrite semantics) প্রদান করে না। এই রেস কন্ডিশনের (race condition) ফলে ত্রুটিপূর্ণ বা অসম্পূর্ণ JSON ফাইল তৈরি হয় এবং এজেন্ট আবারও তার কনটেক্সট হারিয়ে ফেলে।

মূল বিষয়: অবজেক্ট স্টোরেজে সাধারণ ওভাররাইট নিরাপদ নয় যখন একাধিক ওয়ার্কার একই সময়ে একই কী (key) ব্যবহার করতে পারে।

তৃতীয় সমাধান: ভার্সনিং সহ অ্যাটমিক আপডেট

চূড়ান্ত এবং স্থিতিশীল ডিজাইনটি দুটি ধারণার সমন্বয় করে: স্পষ্ট ভার্সন নম্বর এবং অবজেক্টের ETag-এর (স্টোরেজ সার্ভিসের চেকসাম আইডেন্টিফায়ার) ওপর ভিত্তি করে কন্ডিশনাল রাইট।

  1. বর্তমান চেকবয়েন্টটি পড়ুন (Read) এবং এর ETag সংগ্রহ করুন।
  2. চেকবয়েন্ট এনভেলপের (envelope) ভেতরে একটি ভার্সন ফিল্ড বৃদ্ধি করুন (Increment)
  3. একটি কন্ডিশনাল রিকোয়েস্ট ব্যবহার করে আপডেট করা চেকবয়েন্টটি লিখুন (Write), যা কেবল তখনই সফল হবে যদি ETag আগের পড়া ETag-এর সাথে মিলে যায়।
  4. যদি অন্য কোনো প্রসেস অবজেক্টটি পরিবর্তন করার কারণে কন্ডিশনাল রাইট ব্যর্থ হয়, তবে পুরো read-increment-write লুপটি পুনরায় চেষ্টা করুন (Retry)

যেহেতু রাইট তখনই সফল হয় যখন অন্য কোনো প্রসেস ফাইলটি পরিবর্তন করে না, তাই এক সময়ে কেবল একজন ওয়ার্কারই নতুন স্টেট কমিট করতে পারে। ভার্সন ফিল্ডটি পুরনো বা স্টেল (stale) চেকবয়েন্ট শনাক্ত করতে এবং স্কিমা পরিবর্তনের সময় সেগুলোকে মাইগ্রেট করতেও সহজ করে তোলে।

এই প্যাটার্নটি সেই সব অবজেক্ট স্টোরেজের সাথে কাজ করে যা ETag-ভিত্তিক কন্ডিশনাল রাইট সাপোর্ট করে।

AI ইঞ্জিনিয়ারদের জন্য শিক্ষা

  • প্রোটোটাইপের জন্য কেবল SQLite ব্যবহার করুন। প্রোডাকশন এজেন্টদের এমন একটি স্টোর প্রয়োজন যা স্কিমা পরিবর্তন এবং কনকারেন্ট রাইট (concurrent writes) সামলাতে পারে।
  • নিজে স্কিমা মাইগ্রেশন পরিকল্পনা করুন। Typed dictionaries স্ট্যাটিক অ্যানালাইসিসের জন্য আকার বর্ণনা করে কিন্তু রানটাইম স্ট্রাকচার প্রয়োগ করে না।
  • স্টেটকে একটি শেয়ার্ড রিসোর্স হিসেবে বিবেচনা করুন। কনকারেন্সি বাগগুলো নিরব ডেটা লস হিসেবে প্রকাশ পায়; এগুলো সরাসরি এক্সেপশন (exception) হ্যান্ডেল করার চেয়ে ডিবাগ করা অনেক বেশি কঠিন।
  • ক্লাউড প্রিমিটিভস (cloud primitives) ব্যবহার করুন। ETag-ভিত্তিক কন্ডিশনাল রাইট কোনো আলাদা লক সার্ভিস ছাড়াই সাশ্রয়ী অপ্টিমিস্টিক লকিং (optimistic locking) প্রদান করে।
  • প্রতিটি ধাপ লগ করুন। নিরব ব্যর্থতা—যেমন একটি অনুপস্থিত ফিল্ড যা LangGraph উপেক্ষা করে—খুঁজে বের করা সবচেয়ে কঠিন।

LangGraph চেকবয়েন্টিং-এর পরবর্তী ধাপ কী?

যে দলগুলো ইতিমধ্যে একই বাধার সম্মুখীন হয়েছে, তাদের জন্য এই অ্যাটমিক-আপডেট রেসিপিটি একটি দ্রুত এবং স্বল্প-ব্যয়ী সমাধান প্রদান করে। এটি দেখায় যে একটি নির্ভরযোগ্য প্রোডাকশন পাইপলাইনের জন্য কোনো ভারী স্টেট স্টোরের প্রয়োজন নেই—কেবল কনকারেন্সি এবং ভার্সনিংয়ের সতর্ক ব্যবস্থাপনা প্রয়োজন।

মূল কথা (Takeaway): একটি সাধারণ ভার্সনড এনভেলপ এবং কন্ডিশনাল রাইট একটি ভঙ্গুর সিস্টেমকে একটি নির্ভরযোগ্য সিস্টেমে রূপান্তরিত করে, যা AI ইঞ্জিনিয়ারদের নিরন্তর ডেটা-লস ডিবাগিংয়ের পরিবর্তে এজেন্ট লজিকের ওপর মনোযোগ দিতে সাহায্য করে।