একটি ল্যাঙ্গুয়েজ মডেলকে জিজ্ঞাসা করুন “strawberry” শব্দটিতে কতটি অক্ষর আছে। সম্ভবত এটি ভুল উত্তর দেবে। এটি দশটি বলতে পারে। এটি এগারোটি অনুমান করতে পারে। এটি অত্যন্ত আত্মবিশ্বাসের সাথে উত্তর দেবে, তবুও তা ভুল হবে। একই মডেলকে কোনো ঋণের ওপর চক্রবৃদ্ধি সুদ গণনা করতে, বা দুটি বড় সংখ্যা যোগ করতে, অথবা দুটি তারিখের মধ্যে ব্যবসায়িক দিন (business days) গণনা করতে বলুন, এবং আপনি প্রায়শই একটি বিশ্বাসযোগ্য উত্তর পাবেন যার অঙ্কগুলো সামান্য, কিন্তু বিপজ্জনকভাবে ভুল।

এটি ঘটে কারণ লার্জ ল্যাঙ্গুয়েজ মডেলগুলো মানুষের মতো সংখ্যা নিয়ে যুক্তি বা চিন্তাভাবনা করে না। তারা টোকেন (token) প্রেডিক্ট বা অনুমান করে। একটি টোকেন একটি সম্পূর্ণ শব্দ, শব্দের অংশ বা একটি একক অঙ্ক হতে পারে। যখন মডেলটি “strawberry” দেখে, তখন এটি আটটি আলাদা অক্ষরকে সারিবদ্ধভাবে দেখে না। এটি কিছু চ্যাঙ্ক (chunk) বা খণ্ড দেখে। তাকে অক্ষর গণনা করতে শেখানো হয়নি, কেবল পরবর্তী টেক্সট চ্যাঙ্ক কোনটি হবে তা অনুমান করতে শেখানো হয়েছে। একই সীমাবদ্ধতা গাণিতিক কাজের ক্ষেত্রেও প্রযোজ্য। মডেলের কোনো অভ্যন্তরীণ ক্যালকুলেটর নেই। এতে 'ক্যারি লজিক' (carry logic) নেই। স্থানীয় মান (place value) সম্পর্কে এর কোনো প্রকৃত ধারণা নেই। যখন এটি ১৪৮-কে ২৭৯ দিয়ে গুণ করে, তখন এটি গুণ করছে না। এটি প্রশিক্ষণের সময় দেখা অনুরূপ প্রকাশগুলোর সাথে প্যাটার্ন-ম্যাচিং করছে এবং অনুমান করছে যে কোন অঙ্কগুলোর অনুক্রম এরপর আসবে। খুব ছোট যোগফলের ক্ষেত্রে প্যাটার্নটি কাজ করার জন্য যথেষ্ট শক্তিশালী। কিন্তু যেখানে প্রকৃত নির্ভুলতার প্রয়োজন, সেখানে অনুমানটি শেষ পর্যন্ত ভুল হয়ে যায়।

দুটি কাজ, একটি বট

স্ট্যান্ডার্ড প্রম্পটিং পদ্ধতিগুলো একটি মাত্র সিস্টেমকে একসাথে দুটি খুব ভিন্ন কাজ করতে বলে। প্রথমত, সমস্যার যুক্তি বোঝা। দ্বিতীয়ত, সঠিক গণিত সম্পন্ন করা। প্রথম কাজটি করতে মডেলটি সত্যিই অসাধারণ। এটি একটি গাণিতিক সমস্যা পড়তে পারে, ভেরিয়েবল (variables) বের করতে পারে, সম্পর্ক স্থাপন করতে পারে এবং সমাধানের পথ পরিকল্পনা করতে পারে। কিন্তু তারপর তাকে নিজের ক্যালকুলেটর হিসেবে কাজ করতে হয়। সেখানেই চেইনটি ভেঙে যায়। তৃতীয় ধাপে একটি মাত্র অঙ্ক ভুল হলে তার পরের প্রতিটি ধাপ ভুল হয়ে যায়। যুক্তিটি নিখুঁত হতে পারে, তবুও চূড়ান্ত উত্তরটি ভুল হয় কারণ মডেলটি ভুলভাবে যোগ করেছে।

Program-Aided Language Models, বা PAL, কাজটিকে ভাগ করে দিয়ে এই সমস্যার সমাধান করে। মডেলটিকে সরাসরি উত্তর জিজ্ঞাসা করার পরিবর্তে, আপনি তাকে একটি প্রোগ্রাম লিখতে বলেন।

কাজের প্রবাহটি আসলে যেভাবে কাজ করে তা নিচে দেওয়া হলো। আপনি সমস্যাটি উপস্থাপন করেন। মডেলটি যুক্তিটি বুঝে নেয়, ভেরিয়েবলগুলো সংজ্ঞায়িত করে এবং অ্যালগরিদমটি সাজায়। তারপর, নিজে ফলাফল গণনা করার পরিবর্তে, এটি একটি ছোট স্ক্রিপ্ট লেখে, যা সাধারণত Python-এ হয়। সেই স্ক্রিপ্টটি একটি প্রকৃত কোড ইন্টারপ্রেটারের (code interpreter) কাছে হস্তান্তর করা হয়। ইন্টারপ্রেটারটি যুক্তিটি চালায় এবং সঠিক, ডিটারমিনিস্টিক (deterministic) ফলাফল প্রদান করে। মডেলটি গণিতের বর্ণনা দেয়। Python গণিত সম্পন্ন করে।

বাস্তবে কার্যকর যুক্তি (Executable Reasoning)

PAL-কে 'এক্সিকিউটেবল রিজনিং' বা কার্যকর যুক্তি হিসেবে ভাবুন। যদি একটি স্ক্রিপ্ট কোনো সমস্যা সমাধান করতে পারে, তবে মডেলটিকে সেই স্ক্রিপ্টটি লিখতে দিন।

একটি বাস্তব উদাহরণ বিবেচনা করুন। আপনাকে ₹৫০,০০০ টাকার একটি ফিক্সড ডিপোজিটের ম্যাচিউরিটি অ্যামাউন্ট (maturity amount) গণনা করতে হবে, যার বার্ষিক সুদের হার ৮.৫ শতাংশ, ত্রৈমাসিক চক্রবৃদ্ধি (compounded quarterly), এবং মেয়াদ সাত বছর। সরাসরি একটি ল্যাঙ্গুয়েজ মডেলকে জিজ্ঞাসা করলে, এটি একটি সূত্র লিখে দিতে পারে, মানগুলো বসাতে পারে এবং চিন্তার ধারায় (chain of thought) ফলাফল গণনা করতে পারে। তবে গভীরভাবে লক্ষ্য করলে দেখবেন, এটি ত্রৈমাসিক চক্রবৃদ্ধির ক্ষেত্রে সুদের হার ভুলভাবে ভাগ করে ফেলেছে, অথবা কোনো মধ্যবর্তী ধাপে মানটি রাউন্ড (round) করে ফেলেছে এবং সেই ভুলটি পরবর্তী ধাপে নিয়ে গেছে। উত্তরটি দেখতে যুক্তিসঙ্গত মনে হলেও তা কয়েকশ টাকা ভুল হতে পারে।

PAL-এর মাধ্যমে মিথস্ক্রিয়া বা ইন্টারঅ্যাকশন বদলে যায়। আপনি মডেলটিকে এমন একটি Python কোড তৈরি করতে নির্দেশ দেন যা principal = 50000, rate = 0.085, time = 7, এবং n = 4 সংজ্ঞায়িত করে, এবং তারপর amount = principal * (1 + rate/n) ** (n * time) গণনা করে। মডেলটি কোডটি প্রদান করে। একটি Python runtime সেটি কার্যকর করে। আপনি প্রতিবার একদম শেষ দশমিক পর্যন্ত সঠিক সংখ্যাটি পান। গুণ করার ক্ষেত্রে কোনো অনুমান নেই, কোনো কাল্পনিক অবশিষ্টাংশ (remainder) নেই, কিংবা আত্মবিশ্বাসের সাথে ভুল রাউন্ডিং করার কোনো সুযোগ নেই।

এই একই পদ্ধতি তারিখের গণিতের ক্ষেত্রেও প্রযোজ্য। একটি মডেলকে জিজ্ঞাসা করুন যে সপ্তাহান্ত (weekends) বাদ দিয়ে আজ থেকে ঠিক ১২০টি ব্যবসায়িক দিন পর কোন তারিখটি পড়বে। শুধুমাত্র টেক্সট-ভিত্তিক একটি মডেল হয়তো দিন গণনা করতে গিয়ে কোনো শনিবারের ক্ষেত্রে ভুল করে বসতে পারে। PAL পদ্ধতিতে মডেলটি datetime এবং calendar লজিক ব্যবহার করে একটি স্ক্রিপ্ট লেখে এবং তারপর ইন্টারপ্রেটারটি নিখুঁতভাবে গণনা সম্পন্ন করে। ডেটা ম্যানিপুলেশনও একইভাবে কাজ করে। আপনার যদি একটি অগোছালো CSV পার্স (parse) করতে হয়, নেস্টেড JSON ফিল্টার করতে হয়, অথবা দ্রুত কোনো পরিসংখ্যানগত রূপান্তর (statistical transform) চালাতে হয়, তবে মডেলটি লজিকটি তৈরি করবে এবং ইন্টারপ্রেটারটি সেই কাজটি সম্পন্ন করবে।

এটি কেন আসলে গুরুত্বপূর্ণ

গদ্য বা বর্ণনামূলক উত্তর থেকে কার্যকর কোডে এই পরিবর্তন তিনটি ব্যবহারিক সুবিধা প্রদান করে।

ডিটারমিনিজম (Determinism)। একটি ল্যাঙ্গুয়েজ মডেলকে একই প্রশ্ন দুবার জিজ্ঞাসা করলে সেটি তার শব্দচয়ন পরিবর্তন করতে পারে বা একটি সংখ্যা বদলে দিতে পারে। অন্যদিকে, একটি ইন্টারপ্রেটার প্রতিবার একই ইনপুটের জন্য একই আউটপুট প্রদান করে। অ্যাকাউন্টিং, লজিস্টিকস, শিডিউলিং এবং যেকোনো ইঞ্জিনিয়ারিং ক্যালকুলেশনের ক্ষেত্রে এই স্থিতিশীলতা অত্যন্ত গুরুত্বপূর্ণ, যেখানে ধারাবাহিকতা কোনো ঐচ্ছিক বিষয় নয়।

যাচাইযোগ্যতা (Verifiability)। যখন একটি মডেল আপনাকে যুক্তির তিনটি অনুচ্ছেদ প্রদান করে, তখন একটি ভুল সংখ্যা খুঁজে বের করার জন্য আপনাকে প্রতিটি বাক্য খুঁটিয়ে পড়তে হয়। কিন্তু যখন এটি আপনাকে দশ লাইনের একটি স্ক্রিপ্ট দেয়, তখন আপনি কোডটি পর্যালোচনা করতে পারেন। ইন্টারপ্রেটার চালানোর আগেই আপনি যাচাই করে নিতে পারেন যে চক্রবৃদ্ধি সুদের (compound-interest) সূত্রটি সঠিক কি না। আপনি ভেরিয়েবল নামগুলো পরীক্ষা করতে পারেন, 'off-by-one' ত্রুটি শনাক্ত করতে পারেন এবং এমনকি সমাধানের ভার্সন-কন্ট্রোলও করতে পারেন। এর ফলে লুকানো ভুলের ক্ষেত্র নাটকীয়ভাবে সংকুচিত হয়।

নির্ভরযোগ্যতা (Reliability)। মডেলটি তার নির্দিষ্ট সীমার মধ্যে থাকে। এটি ঠিক তা-ই করে যার জন্য এটি তৈরি করা হয়েছে: কাঠামো (structure), সিম্যান্টিকস (semantics) এবং সমস্যা বিভাজন (problem decomposition) নিয়ে যুক্তি প্রদান করা। মেশিনটি ঠিক তা-ই করে যার জন্য এটি তৈরি করা হয়েছে: নির্ভুলভাবে গণনা করা। কাজের এই বিভাজন (separation of concerns) ঠিক এভাবেই নির্ভরযোগ্য সফটওয়্যার আর্কিটেক্ট করা হয়। কম্পোজিশন (Composition) মনোলিথিক ডিজাইনের (monolithic design) চেয়ে অনেক বেশি কার্যকর।

এটিকে অনির্ভরযোগ্য কোড হিসেবে চালান

একটি সতর্কবার্তা দেওয়া প্রয়োজন। জেনারেট করা কোডকে সবসময় অনির্ভরযোগ্য ইনপুট হিসেবে বিবেচনা করা উচিত। মডেলটি এমন একটি স্ক্রিপ্ট লিখতে পারে যাতে ইনফিনিট লুপ (infinite loop), অপ্রয়োজনীয় নেটওয়ার্ক রিকোয়েস্ট বা এমন কোনো ফাইল সিস্টেম অপারেশন থাকে যা আপনি চাননি। এই প্রোগ্রামগুলো সবসময় একটি আইসোলেটেড স্যান্ডবক্সের (isolated sandbox) মধ্যে চালান। সীমিত প্রিভিলেজযুক্ত কন্টেইনার, নেটওয়ার্ক অ্যাক্সেসহীন সার্ভারলেস ফাংশন, অথবা সীমিত CPU টাইম এবং কোনো পারসিস্টেন্ট স্টোরেজ নেই এমন কঠোরভাবে নিয়ন্ত্রিত পরিবেশ ব্যবহার করুন। এখানে নিরাপত্তা কোনো পাদটীকা নয়; এটি সিস্টেম ডিজাইনের একটি অবিচ্ছেদ্য অংশ।

যেখানে PAL কার্যকর, এবং যেখানে এর সীমাবদ্ধতা

গণিত, তারিখ এবং স্ট্রাকচার্ড ডেটা ম্যানিপুলেশনের ক্ষেত্রে PAL চমৎকারভাবে কাজ করে। এটি সেই যান্ত্রিক ত্রুটিগুলো দূর করে যা শুধুমাত্র টেক্সট-ভিত্তিক যুক্তির ক্ষেত্রে দেখা যায়।

তবে, এটি ভুল লজিক ঠিক করতে পারে না। যদি মডেলটি ভুল সূত্র বেছে নেয়,