LLM আপনার কোডের ভেতরে প্রবেশ করে না – তারা আপনাকে একটি রিকোয়েস্ট দেয়, এবং আপনি ফাংশনটি চালান। এই সহজ সত্যটি "মডেলটি জাদুকরীভাবে আমার Python রুটিন কল করে" — এই ভুল ধারণাটি বদলে দেয় এবং ডেভেলপারদের ডিবাগিং এবং সিকিউরিটি নিয়ে নতুন করে ভাবতে বাধ্য করে।

ডিসপ্যাচ লুপ (dispatch loop), ধাপে ধাপে

যখন একটি ল্যাঙ্গুয়েজ মডেল (LLM)-এর একটি টুলের প্রয়োজন হয়, তখন এটি একটি নির্দিষ্ট (deterministic) অনুক্রম অনুসরণ করে:

  1. পরিকল্পনা (Planning) – মডেলটি সিদ্ধান্ত নেয় যে একটি অ্যাকশন প্রয়োজন (যেমন, "একটি পেমেন্ট রিফান্ড করা")।
  2. একটি রিকোয়েস্ট তৈরি করা (Generating a request) – এটি একটি স্ট্রাকচার্ড টেক্সট—সাধারণত JSON—আউটপুট হিসেবে দেয়, যেখানে টুলের নাম এবং আর্গুমেন্টগুলো থাকে।
  3. পার্সিং (Parsing) – আপনার অ্যাপ বা একটি সাপোর্টিং ফ্রেমওয়ার্ক সেই টেক্সটটি পড়ে।
  4. ম্যাচিং (Matching) – ফ্রেমওয়ার্কটি আপনার এক্সপোজ করা আসল ফাংশনগুলোর রেজিস্ট্রি থেকে নামটি খুঁজে বের করে।
  5. ভ্যালিডেশন (Validating) – এটি যাচাই করে যে আর্গুমেন্টগুলো ফাংশনের স্কিমার (schema) সাথে মিলছে কি না এবং কলকারী অনুমোদিত কি না।
  6. এক্সিকিউশন (Executing) – ম্যাচ করা ফাংশনটি আপনার এনভায়রনমেন্টে চলে এবং কাজটি সম্পন্ন করে।
  7. রিটার্নিং (Returning) – ফলাফলটি প্যাকেজ করা হয় এবং পরবর্তী যুক্তির (reasoning) জন্য মডেলের কাছে ফেরত পাঠানো হয়।

LLM-কে একজন পরিকল্পনাকারী (planner), ফ্রেমওয়ার্ককে একজন ডিসপ্যাচার (dispatcher) এবং ফাংশনটিকে একজন কর্মী (worker) হিসেবে ভাবুন, যে আসলে ডেটা বা টাকা মুভ করে।

কেন এই "জাদুকরী" ভুল ধারণাটি টিকে আছে

বেশিরভাগ ডেভেলপার মডেলের আউটপুটে একটি মাত্র লাইন দেখেন যা দেখতে একটি ফাংশন কলের মতো এবং ধরে নেন যে মডেলটি নিজেই অপারেশনটি সম্পন্ন করেছে। প্রোভাইডারদের ডকস-এ "tool calling" শব্দটি শুনলে মনে হতে পারে যে মডেলটি সরাসরি কোড কল করছে।

বাস্তবে, মডেলটি কেবল এমন একটি টেক্সট তৈরি করে যা একটি কলকে বর্ণনা করে। আপনার প্রসেসটিই আসল কাজগুলো করে—যেমন লুকআপ (lookup), টাইপ চেকিং, পারমিশন এনফোর্সমেন্ট এবং এরর হ্যান্ডলিং।

ফ্রেমওয়ার্ক যা পেছনের জটিল কাজগুলো লুকিয়ে রাখে

PydanticAI এবং LangChain-এর মতো লাইব্রেরিগুলো এই লুপটিকে অ্যাবস্ট্রাক্ট করে দেয় যাতে আপনি বিজনেস লজিকের ওপর মনোযোগ দিতে পারেন। তারা স্বয়ংক্রিয়ভাবে:

  • একটি স্কিমার (যেমন, একটি Pydantic মডেল) বিপরীতে আর্গুমেন্ট ভ্যালিডেট করে
  • পারমিশন নিশ্চিত করে, যাতে ব্যবহারকারী টুলটি ট্রিগার করার অনুমতিপ্রাপ্ত হন।
  • ব্যর্থ হলে পুনরায় চেষ্টা (Retry) করে, যখন একটি টুল এরর রিটার্ন করে তখন মডেলের কাছে আবার ফিরে যায়।
  • রানঅ্যাওয়ে লুপ (runaway loops) থেকে রক্ষা করে, ক্রমাগত টুল কল করার সংখ্যা সীমিত করে।
  • কনভারসেশন স্টেট বজায় রাখে, টুলের ফলাফলগুলোকে কথোপকথনের সাথে যুক্ত করে।

এই সাহায্যকারী টুলগুলো থাকলেও প্যাটার্নটি একই থাকে: মডেল কখনোই কোড এক্সিকিউট করে না।

প্রোভাইডারদের পক্ষ থেকে নেটিভ টুল-কলিং সাপোর্ট

কিছু প্রোভাইডার একটি "নেটিভ" টুল-কলিং ইন্টারফেস প্রদান করে যা টুলের সংজ্ঞা এবং রিকোয়েস্ট ফরম্যাটগুলোকে স্ট্যান্ডার্ডাইজ করে। এটি ইন্টিগ্রেশন সহজ করে দেয় কিন্তু ডিসপ্যাচ ধাপটি সরিয়ে দেয় না। রিকোয়েস্ট করা অপারেশনটি চালানোর জন্য কোড আপনাকে এখনও লিখতে (বা ইমপোর্ট করতে) হবে।

সমস্যার নাম পরিবর্তন করলে ডিবাগিং সহজ হয়ে যায়

একটি "বিভ্রান্ত এজেন্ট"-কে দোষারোপ করার পরিবর্তে বলুন যে সমস্যাটি হলো "মডেল রেসপন্সে কোনো টুল কল ছিল না।" এই পার্থক্যটি গুরুত্বপূর্ণ:

  • No tool call – মডেলটি সরাসরি উত্তর দিয়েছে অথবা সঠিকভাবে ফরম্যাট করা রিকোয়েস্ট তৈরি করতে ব্যর্থ হয়েছে।
  • Malformed request – JSON-টি সিনট্যাক্স অনুযায়ী ভুল বা প্রয়োজনীয় ফিল্ড নেই, তাই ডিসপ্যাচার এটি প্রত্যাখ্যান করে।
  • Validation failure – আর্গুমেন্টগুলো স্কিমার সাথে মিলছে না, যা এক্সিকিউশনের আগেই একটি এরর ট্রিগার করে।

ব্যর্থতাগুলোকে শ্রেণীবদ্ধ করলে আপনি লুপের প্রতিটি ধাপ লগ করতে পারবেন এবং সমস্যাটি ঠিক কোথায় হয়েছে তা সুনির্দিষ্টভাবে চিহ্নিত করতে পারবেন।

একটি নির্ভরযোগ্য পাইপলাইনের জন্য ব্যবহারিক টিপস

  • মডেল আউটপুটকে অনির্ভরযোগ্য ইনপুট হিসেবে বিবেচনা করুন। কোনো সাইড-ইফেক্টিং (side-effecting) কোড কল করার আগে প্রতিটি রিকোয়েস্টকে একটি নির্দিষ্ট (deterministic) ভ্যালিডেশনের মধ্য দিয়ে চালান।
  • র (raw) রিকোয়েস্ট এবং প্রতিটি ভ্যালিডেশন ধাপের ফলাফল লগ করুন। এটি কোনো সমস্যা হলে পুনরায় পরীক্ষা করার জন্য একটি ট্রেইল তৈরি করে।
  • ক্রমাগত টুল কলের জন্য সুনির্দিষ্ট সীমা নির্ধারণ করুন; একটি রানঅ্যাওয়ে লুপ রিসোর্স শেষ করে দিতে পারে বা রেট লিমিটে পৌঁছে দিতে পারে।
  • প্রতিটি ফাংশনকে একটি try/except ব্লকের মধ্যে রাখুন যা একটি স্ট্রাকচার্ড এরর অবজেক্ট রিটার্ন করে যা মডেল বুঝতে পারে, ফলে এটি পুনরায় চেষ্টা করতে বা সুন্দরভাবে বিকল্প ব্যবস্থা (graceful fallback) নিতে পারে।
  • পারমিশন চেক এবং বিজনেস লজিক আলাদা রাখুন। ফাংশনটি চলার আগে কলকারীর অধিকার যাচাই করুন, বিশেষ করে "delete user"-এর মতো বিশেষাধিকারপ্রাপ্ত কাজের ক্ষেত্রে।
  • স্কিমা-চালিত সংজ্ঞা (যেমন, Pydantic মডেল) ব্যবহার করুন যাতে ফ্রেমওয়ার্কটি স্বয়ংক্রিয়ভাবে সেই JSON স্কিমা তৈরি করতে পারে যা মডেলকে অনুসরণ করতে হবে।

পরবর্তীতে যা খেয়াল রাখবেন

প্রোভাইডাররা যখন নেটিভ টুল-কলিং API-গুলোকে আরও উন্নত করবে, তখন রিকোয়েস্ট ফরম্যাটের ক্ষেত্রে আরও কঠোর নিয়ম এবং আরও বিস্তারিত এরর কোড আশা করতে পারেন। এই পরিবর্তনগুলো ভ্যালিডেশন সহজ করবে এবং ডেভেলপারদের আরও শক্তিশালী সিকিউরিটি ফেন্স (security fences) তৈরি করতে সাহায্য করবে। লাইব্রেরি আপডেটগুলোর দিকে নজর রাখুন—অনেক লাইব্রেরি ইতিমধ্যেই নতুন প্রোভাইডার ফিচারগুলোর জন্য বিল্ট-ইন সাপোর্ট যোগ করছে।

সারসংক্ষেপ (Takeaway)

LLM হলো একটি উন্নতমানের টেক্সট জেনারেটর, কোনো এক্সিকিউটর নয়। আপনার কোডই একমাত্র কর্তৃপক্ষ যা কাজগুলো সম্পাদন করে, এবং আপনি যে ডিসপ্যাচার তৈরি করেন (বা ইমপোর্ট করেন) সেটি হলো সেই গেটকিপার যা কাজগুলোকে যাচাই করে, অনুমোদন দেয় এবং কার্যকর করে। ওয়ার্কফ্লো-কে এভাবে নতুনভাবে দেখলে "ম্যাজিক" বা জাদুর ধারণাটি দূর হয়, ডিবাগিং আরও নিখুঁত হয় এবং প্রতিটি প্রোডাকশন সিস্টেমের জন্য প্রয়োজনীয় নিরাপত্তা শৃঙ্খলা নিশ্চিত হয়।