ডেভেলপাররা এখন Zod schema-কে Vercel AI SDK বা Anthropic-এর tool-use API-এর সাথে যুক্ত করার মাধ্যমে নিশ্চিত করতে পারেন যে একটি LLM থেকে প্রাপ্ত JSON একটি পূর্বনির্ধারিত শেপ (shape) মেনে চলবে। এর ফলে মডেল যদি কোনো অপ্রত্যাশিত ফিল্ড যোগ করে দেয়, তবে যে runtime crash ঘটে তা এড়ানো সম্ভব হয়।
একটি সুনির্দিষ্ট সুরক্ষার প্রয়োজনীয়তা গত জানুয়ারিতে স্পষ্ট হয়ে ওঠে, যখন প্রোডাকশনে থাকা একটি classifier তিন সপ্তাহ নিখুঁতভাবে চলার পর হঠাৎ একটি দ্বিতীয় “explanation” key প্রদান করতে শুরু করে। কোডটি শুধুমাত্র একটি ফিল্ড আশা করছিল, তাই অতিরিক্ত এই key-টি কোনো কোড ডিপ্লয় ছাড়াই একটি exception তৈরি করে। এই ঘটনাটি একটি বৃহত্তর সমস্যার দিকে ইঙ্গিত করে: বেশিরভাগ টিউটোরিয়াল JSON.parse(response) পর্যন্তই সীমাবদ্ধ থাকে এবং ধরে নেয় যে মডেলটি প্রম্পটের schema মেনে চলবে। বাস্তবে, LLM-গুলো প্রায়ই নিয়ম থেকে বিচ্যুত হয়—যেমন casing পরিবর্তন করা, নতুন ফিল্ড যোগ করা, অথবা আউটপুটকে markdown fences-এর মধ্যে রাখা—যার ফলে ডেটা করাপশন বা সরাসরি সিস্টেম ফেইলর হতে পারে।
কেন সরাসরি JSON parsing অনিরাপদ
LLM-গুলোকে সাহায্য করার জন্য প্রশিক্ষণ দেওয়া হয়, আদেশ মানার জন্য নয়। একটি প্রম্পট যা চায়:
{ "category": "string" }
তা মডেলটিকে সেই নির্দিষ্ট কাঠামোর সাথে বেঁধে রাখতে পারে না। এমনকি একটি সুপরিকল্পিত প্রম্পটও মডেলের অভ্যন্তরীণ heuristics দ্বারা প্রভাবিত হতে পারে, বিশেষ করে যখন temperature setting সৃজনশীলতাকে উৎসাহিত করে অথবা কোনো পরবর্তী নির্দেশ মডেলটিকে বিস্তারিত লিখতে প্ররোচিত করে। এর ফলে এমন একটি টেক্সট স্ট্রিম তৈরি হয় যা দেখতে JSON-এর মতো হলেও একটি নির্দিষ্ট শেপ আশা করা parsers-গুলোকে ভেঙে ফেলার মতো যথেষ্ট বিচ্যুতি ঘটিয়ে ফেলে।
যখন এই ধরনের অমিল প্রোডাকশন কোডে পৌঁছায়, তখন এর প্রভাব তাৎক্ষণিক হয়: একটি exception তৈরি হওয়া, রিকোয়েস্ট ফেইল হওয়া এবং সম্ভাব্যভাবে এর ফলে আরও অনেক ত্রুটি দেখা দেওয়া। বড় পরিসরের সার্ভিসের ক্ষেত্রে, এই কয়েক মিনিটের ডাউনটাইম মানেই হলো রাজস্বের ক্ষতি এবং ব্যবহারকারীর আস্থা কমে যাওয়া।
Zod + Vercel AI SDK: একটি তিন-ধাপের সুরক্ষা ব্যবস্থা
Zod হলো একটি TypeScript-first schema validator যা একটি মডেল থেকে আসা ডেটার সঠিক শেপ বর্ণনা করতে পারে। Vercel AI SDK-এর Output.object helper-এর সাথে এটি ব্যবহার করলে, মডেল তার রেসপন্স জেনারেট করার পরপরই স্বয়ংক্রিয়ভাবে ভ্যালিডেশন সম্পন্ন হয়।
- Schema সংজ্ঞায়িত করা – কাঙ্ক্ষিত JSON-এর অনুরূপ একটি Zod object লিখুন। একটি সাধারণ classifier-এর জন্য এটি হতে পারে
z.object({ category: z.string() }); একটি জটিল invoice extractor-এর ক্ষেত্রে schema-তে objects, arrays, এবং discriminated unions ব্যবহার করা যেতে পারে। - SDK-তে পাস করা – schema-টিকে
Output.object(schema)দিয়ে র্যাপ (wrap) করুন। SDK এমন একটি প্রম্পট ইনজেক্ট করে যা মডেলকে schema অনুযায়ী একটি JSON ব্লক আউটপুট দিতে বলে এবং Zod-এরsafeParseব্যবহার করে ফলাফলটি পার্স করে। - ব্যর্থতা মোকাবিলা করা –
safeParseকোনো exception থ্রো করার পরিবর্তে একটি result object রিটার্ন করে। যদি parsing ব্যর্থ হয়, তবে সেই error-টি মডেলকে পুনরায় পাঠিয়ে দিন এবং আবার চেষ্টা (retry) করুন। ভ্যালিডেশন মেসেজের ওপর ভিত্তি করে মডেলকে আউটপুট সংশোধন করার নির্দেশ দেওয়া যেতে পারে, যা বেশিরভাগ edge case-কে একটি self-healing লুপে পরিণত করে।
যেহেতু SDK প্রম্পটিং, পার্সিং এবং রিট্রাই লজিক এক জায়গাতেই সম্পন্ন করে, তাই ডেভেলপাররা অনেকগুলো বিচ্ছিন্ন string manipulation-এর পরিবর্তে একটি মাত্র type-checked কল ব্যবহার করতে পারেন।
Anthropic tool use: স্ট্রাকচার্ড আউটপুট নিশ্চিত করা
সরাসরি Anthropic-এর API-এর সাথে কাজ করার সময়, “tool use”-এর মাধ্যমে একই নিশ্চয়তা পাওয়া সম্ভব। একটি tool-কে এমন একটি ফাংশন হিসেবে সংজ্ঞায়িত করা হয় যার input schema JSON Schema-তে প্রকাশ করা হয়; Anthropic-এর মডেল কেবল তখনই tool-টি কল করবে যদি সেটি schema মেনে চলতে পারে। tool_choice-কে "any" (অথবা একটি নির্দিষ্ট tool name) হিসেবে সেট করার মাধ্যমে, মডেলটি মুক্ত টেক্সট (free-form text) প্রদান করার পরিবর্তে একটি স্ট্রাকচার্ড ব্লক প্রদান করতে বাধ্য হয়।
এই কাজের ধারাটি (workflow) Vercel-এর পদ্ধতির মতোই:
- একটি Zod schema লিখুন।
- tool definition-এর জন্য এটিকে একটি JSON Schema payload-এ রূপান্তর করুন।
- রিকোয়েস্টে tool-টি অন্তর্ভুক্ত করুন এবং মডেলকে এটি ব্যবহার (invoke) করতে বলুন।
zod.safeParseদিয়ে tool-এর রেসপন্সটি পার্স করুন।
যদি মডেলটি তবুও ত্রুটিপূর্ণ (malformed) ডেটা প্রদান করে, তবে একই retry-with-feedback প্যাটার্ন ব্যবহার করা যেতে পারে।
যখন ভ্যালিডেশন তবুও ব্যর্থ হয়
Schema প্রয়োগ করা সত্ত্বেও মাঝে মাঝে অমিল দেখা দিতে পারে। এর কারণগুলোর মধ্যে রয়েছে:
- Model hallucination: মডেলটি এমন একটি স্ট্রিং তৈরি করতে পারে যা দেখতে JSON-এর মতো কিন্তু তাতে সিনট্যাক্স এরর (syntax errors) রয়েছে।
- Prompt leakage: পূর্ববর্তী কথোপকথনের কারণে ফরম্যাটিং নির্দেশাবলী লিক হতে পারে যা schema রিকোয়েস্টকে ওভাররাইড করে দেয়।
- Version differences: নতুন মডেল রিলিজগুলো মাঝে মাঝে tool call কীভাবে ব্যাখ্যা করতে হবে তা পরিবর্তন করে ফেলে।
এর সমাধানের জন্য একটি হালকা ওজনের (lightweight) retry loop ব্যবহার করার পরামর্শ দেওয়া হয়। পার্সিং ব্যর্থ হলে, কোডটি একটি ফলো-আপ প্রম্পট পাঠায়, যেমন: “Your last output was not valid JSON. It contained … Please return only the fields defined in the schema.” যেহেতু ভ্যালিডেশন এররটি সুনির্দিষ্ট, তাই মডেলটি মানুষের হস্তক্ষেপ ছাড়াই নিজেকে সংশোধন করতে পারে।
পারফরম্যান্স এবং খরচের বিষয়সমূহ
Zod validation যোগ করলে CPU-তে নগণ্য ওভারহেড তৈরি হয়—সাধারণ পেলোডের (payload) ক্ষেত্রে safeParse অপারেশনটি মাইক্রোসেকেন্ডের মধ্যে সম্পন্ন হয়। নেটওয়ার্ক ল্যাটেন্সি অপরিবর্তিত থাকে; রিট্রাই করার জন্য অতিরিক্ত রাউন্ড-ট্রিপ শুধুমাত্র বিরল ব্যর্থতার ক্ষেত্রেই ঘটে। বাস্তবে, একটি সম্ভাব্য এক্সেপশন (exception) প্রতিরোধ করার সুবিধা রিকোয়েস্টের সময়ের সামান্য বৃদ্ধির তুলনায় অনেক বেশি।
পাল্টা যুক্তি: স্কিমা এনফোর্সমেন্ট (schema enforcement) কি অতিরিক্ত কিছু?
কিছু ডেভেলপার যুক্তি দেন যে কঠোর স্কিমা মডেলের নমনীয়তাকে সীমিত করে, বিশেষ করে যখন নতুন ফিল্ডগুলো মূল্যবান কনটেক্সট প্রদান করতে পারে। এটি মূলত নিরাপত্তা এবং উন্মুক্ততার মধ্যে একটি ভারসাম্য। মিশন-ক্রিটিক্যাল সার্ভিসগুলোর ক্ষেত্রে—যেমন পেমেন্ট প্রসেসিং, আইডেন্টিটি ভেরিফিকেশন, কমপ্লায়েন্স রিপোর্টিং—প্রেডিক্টেবিলিটি বা পূর্বাভাসযোগ্যতা সবচেয়ে গুরুত্বপূর্ণ। এক্সপ্লোরেটরি প্রোটোটাইপের ক্ষেত্রে কিছুটা শিথিল পদ্ধতি গ্রহণযোগ্য হতে পারে, তবে সেখানেও একটি ন্যূনতম গার্ড (যেমন, z.object({}).passthrough()) ব্যবহার করলে দরকারী এক্সটেনশনগুলো বাদ না দিয়েই বড় ধরনের পার্সিং ত্রুটি ধরা সম্ভব।
পরবর্তীতে যা লক্ষ্য রাখা উচিত
- SDK evolution: Vercel-এর AI SDK রোডম্যাপে বিল্ট-ইন রিট্রাই পলিসি এবং আরও উন্নত এরর রিপোর্টিং অন্তর্ভুক্ত রয়েছে, যা রিপেয়ার লুপকে আরও সহজতর করবে।
- Tooling standardization: আরও বেশি প্রোভাইডার যখন টুল-ইউজ কনভেনশন গ্রহণ করবে, তখন ক্রস-প্রোভাইডার স্কিমা ভ্যালিডেটর তৈরি হতে পারে, যা প্রোভাইডার-নির্দিষ্ট অ্যাডাপ্টারের প্রয়োজনীয়তা কমিয়ে দেবে।
- Community patterns: ওপেন-সোর্স লাইব্রেরিগুলো এখন প্রম্পট টেমপ্লেটের সাথে Zod স্কিমা যুক্ত করতে শুরু করেছে, যা "schema-first" ওয়ার্কফ্লোকে একটি পুনঃব্যবহারযোগ্য সম্পদে পরিণত করছে।
মূল কথা (Takeaway)
Zod স্কিমাকে একটি চুক্তির (contract) মতো বিবেচনা করার মাধ্যমে, যা মডেল ভাঙতে পারে না, ডেভেলপাররা ভঙ্গুর JSON.parse হ্যাক থেকে একটি ডিটারমিনিস্টিক পাইপলাইনে চলে আসেন; যেখানে অপ্রত্যাশিত ফিল্ডগুলো প্রোডাকশন ক্র্যাশ না ঘটিয়ে একটি নিয়ন্ত্রিত ভ্যালিডেশন ফেইলিউর ঘটায়। Vercel-এর Output.object হেল্পার এবং Anthropic-এর টুল-ইউজ মেকানিজমের সমন্বয় LLM-গুলোকে অনির্দেশ্য টেক্সট জেনারেটর থেকে নির্ভরযোগ্য ডেটা প্রোভাইডারে রূপান্তরিত করে, যা টিমগুলোকে অন্তহীন এজ-কেস ডিবাগিংয়ের পরিবর্তে বিজনেস লজিকের ওপর মনোযোগ দিতে সাহায্য করে।
