প্রকাশিত: অক্টোবর 10, 2025
ক্লাসিক বোর্ড গেম, কে অনুমান? , ডিডাক্টিভ যুক্তিতে একটি মাস্টার ক্লাস। প্রতিটি খেলোয়াড় মুখের একটি বোর্ড দিয়ে শুরু করে এবং হ্যাঁ বা না প্রশ্নের একটি সিরিজের মাধ্যমে, সম্ভাবনাগুলিকে সংকুচিত করে যতক্ষণ না আপনি আত্মবিশ্বাসের সাথে আপনার প্রতিপক্ষের গোপন চরিত্র সনাক্ত করতে পারেন।
Google I/O Connect-এ বিল্ট-ইন AI- এর একটি ডেমো দেখার পর, আমি ভাবলাম: আমি যদি একজন অনুমান কে খেলতে পারি? AI এর বিরুদ্ধে খেলা যে ব্রাউজারে থাকে? ক্লায়েন্ট-সাইড এআই দিয়ে, ফটোগুলি স্থানীয়ভাবে ব্যাখ্যা করা হবে, তাই একটি কাস্টম অনুমান কে? আমার ডিভাইসে বন্ধু এবং পরিবারের ব্যক্তিগত এবং সুরক্ষিত থাকবে।
আমার ব্যাকগ্রাউন্ড প্রাথমিকভাবে UI এবং UX বিকাশে এবং আমি পিক্সেল-নিখুঁত অভিজ্ঞতা তৈরি করতে অভ্যস্ত। আমি আশা করি যে আমি আমার ব্যাখ্যা দিয়ে ঠিক এটি করতে পারি।
আমার আবেদন, এআই অনুমান কে? , রিঅ্যাক্ট দিয়ে নির্মিত এবং আশ্চর্যজনকভাবে সক্ষম প্রতিপক্ষ তৈরি করতে প্রম্পট API এবং একটি ব্রাউজার বিল্ট-ইন মডেল ব্যবহার করে। এই প্রক্রিয়ায়, আমি আবিষ্কার করেছি "পিক্সেল-নিখুঁত" ফলাফল পাওয়া এত সহজ নয়। কিন্তু, এই অ্যাপ্লিকেশানটি দেখায় যে কীভাবে এআইকে চিন্তাশীল গেমের যুক্তি তৈরি করতে ব্যবহার করা যেতে পারে এবং এই যুক্তিকে পরিমার্জিত করতে এবং আপনার প্রত্যাশিত ফলাফল পেতে প্রম্পট ইঞ্জিনিয়ারিংয়ের গুরুত্ব।
বিল্ট-ইন AI ইন্টিগ্রেশন, আমি যে চ্যালেঞ্জগুলির মুখোমুখি হয়েছি এবং আমি যে সমাধানগুলি নিয়ে এসেছি সেগুলি সম্পর্কে জানতে পড়তে থাকুন। আপনি গেমটি খেলতে পারেন এবং GitHub-এ সোর্স কোড খুঁজে পেতে পারেন।
গেম ফাউন্ডেশন: একটি প্রতিক্রিয়া অ্যাপ্লিকেশন
আপনি AI বাস্তবায়নের দিকে নজর দেওয়ার আগে, আমরা অ্যাপ্লিকেশনটির কাঠামো পর্যালোচনা করব। আমি গেমের কন্ডাক্টর হিসেবে কাজ করার জন্য একটি কেন্দ্রীয় App.tsx
ফাইল সহ TypeScript সহ একটি আদর্শ প্রতিক্রিয়া অ্যাপ্লিকেশন তৈরি করেছি। এই ফাইলটি ধারণ করে:
- গেমের অবস্থা : একটি এনাম যা গেমের বর্তমান পর্বটি ট্র্যাক করে (যেমন
PLAYER_TURN_ASKING
,AI_TURN
,GAME_OVER
)। এটি রাষ্ট্রের সবচেয়ে গুরুত্বপূর্ণ অংশ, কারণ এটি নির্দেশ করে যে ইন্টারফেসটি কী প্রদর্শন করে এবং প্লেয়ারের কাছে কী কী ক্রিয়াকলাপ উপলব্ধ। - অক্ষর তালিকা : একাধিক তালিকা রয়েছে যা সক্রিয় অক্ষর, প্রতিটি খেলোয়াড়ের গোপন চরিত্র এবং কোন অক্ষর বোর্ড থেকে বাদ দেওয়া হয়েছে তা নির্ধারণ করে।
- গেম চ্যাট : প্রশ্ন, উত্তর এবং সিস্টেম বার্তাগুলির একটি চলমান লগ।
ইন্টারফেসটি লজিক্যাল উপাদানে বিভক্ত:


গেমটির বৈশিষ্ট্য যেমন বেড়েছে, তেমনি এর জটিলতাও বেড়েছে। প্রাথমিকভাবে, পুরো গেমের যুক্তি একটি একক, বড় কাস্টম রিঅ্যাক্ট হুকের মধ্যে পরিচালিত হয়েছিল, useGameLogic
, কিন্তু এটি দ্রুত নেভিগেট এবং ডিবাগ করার জন্য খুব বড় হয়ে ওঠে। রক্ষণাবেক্ষণযোগ্যতা উন্নত করার জন্য, আমি এই হুকটিকে একাধিক হুকের মধ্যে রিফ্যাক্টর করেছি, প্রতিটি একটি একক দায়িত্ব সহ। যেমন:
-
useGameState
মূল অবস্থা পরিচালনা করে -
usePlayerActions
হল খেলোয়াড়ের পালা -
useAIActions
হল AI এর যুক্তির জন্য
প্রধান useGameLogic
হুক এখন একটি পরিষ্কার সুরকার হিসাবে কাজ করে, এই ছোট হুকগুলিকে একসাথে রেখে। এই স্থাপত্য পরিবর্তন গেমটির কার্যকারিতা পরিবর্তন করেনি, তবে এটি কোডবেসটিকে সম্পূর্ণরূপে পরিষ্কার করে তুলেছে।
প্রম্পট API সহ গেমের যুক্তি
এই প্রকল্পের মূল হল প্রম্পট এপিআই ব্যবহার করা।
আমি builtInAIService.ts
এ এআই গেম লজিক যোগ করেছি। এগুলো হল এর মূল দায়িত্ব:
- সীমাবদ্ধ, বাইনারি উত্তরের অনুমতি দিন।
- মডেল গেম কৌশল শেখান.
- মডেল বিশ্লেষণ শেখান.
- মডেল অ্যামনেসিয়া দিন।
সীমাবদ্ধ, বাইনারি উত্তরের অনুমতি দিন
প্লেয়ার কিভাবে AI এর সাথে যোগাযোগ করে? যখন একজন খেলোয়াড় জিজ্ঞেস করে, "আপনার চরিত্রে কি টুপি আছে?", তখন AI এর গোপন চরিত্রের চিত্রটি "দেখতে" এবং একটি স্পষ্ট উত্তর দিতে হবে।
আমার প্রথম প্রচেষ্টা একটি জগাখিচুড়ি ছিল. প্রতিক্রিয়াটি কথোপকথনমূলক ছিল: "না, আমি যে চরিত্রের কথা ভাবছি, ইসাবেলা, তাকে হ্যাট বা না" বলার পরিবর্তে টুপি পরা বলে মনে হচ্ছে না। প্রাথমিকভাবে, আমি এটি একটি খুব কঠোর প্রম্পট দিয়ে সমাধান করেছি, মূলত মডেলকে শুধুমাত্র "হ্যাঁ" বা "না" দিয়ে প্রতিক্রিয়া জানানোর নির্দেশ দিয়েছি।
এটি কাজ করার সময়, আমি কাঠামোগত আউটপুট ব্যবহার করে আরও ভাল উপায় সম্পর্কে শিখেছি। মডেলটিতে JSON স্কিমা প্রদান করে, আমি একটি সত্য বা মিথ্যা প্রতিক্রিয়ার গ্যারান্টি দিতে পারি।
const schema = { type: "boolean" };
const result = session.prompt(prompt, { responseConstraint: schema });
এটি আমাকে প্রম্পটটি সরল করার অনুমতি দেয় এবং আমার কোডটি নির্ভরযোগ্যভাবে প্রতিক্রিয়া পরিচালনা করতে দেয়:
JSON.parse(result) ? "Yes" : "No"
মডেল গেম কৌশল শেখান
মডেলকে একটি প্রশ্নের উত্তর দিতে বলা মডেলটি শুরু করে প্রশ্ন জিজ্ঞাসা করার চেয়ে অনেক সহজ। একটি ভাল অনুমান কে? খেলোয়াড় এলোমেলো প্রশ্ন জিজ্ঞাসা করে না। তারা এমন প্রশ্ন জিজ্ঞাসা করে যা একবারে সর্বাধিক অক্ষরকে মুছে দেয়। একটি আদর্শ প্রশ্ন বাইনারি প্রশ্ন ব্যবহার করে সম্ভাব্য অবশিষ্ট অক্ষরগুলিকে অর্ধেকে কমিয়ে দেয়।
আপনি কিভাবে একটি মডেল শেখান যে কৌশল? আবার, প্রম্পট ইঞ্জিনিয়ারিং। generateAIQuestion()
জন্য প্রম্পট আসলে Guess Who এর একটি সংক্ষিপ্ত পাঠ? খেলা তত্ত্ব।
প্রাথমিকভাবে, আমি মডেলটিকে "একটি ভাল প্রশ্ন জিজ্ঞাসা করতে" বলেছিলাম। ফলাফল অপ্রত্যাশিত ছিল. ফলাফল উন্নত করার জন্য, আমি নেতিবাচক সীমাবদ্ধতা যোগ করেছি। প্রম্পটে এখন অনুরূপ নির্দেশাবলী অন্তর্ভুক্ত রয়েছে:
- "সমালোচনা: শুধুমাত্র বিদ্যমান বৈশিষ্ট্য সম্পর্কে জিজ্ঞাসা করুন"
- "সমালোচনা: মূল হোন। একটি প্রশ্ন পুনরাবৃত্তি করবেন না"।
এই সীমাবদ্ধতাগুলি মডেলের ফোকাসকে সংকুচিত করে, এটিকে অপ্রাসঙ্গিক প্রশ্ন জিজ্ঞাসা করা থেকে বাধা দেয়, যা এটিকে অনেক বেশি উপভোগ্য প্রতিপক্ষ করে তোলে। আপনি GitHub-এ সম্পূর্ণ প্রম্পট ফাইল পর্যালোচনা করতে পারেন।
মডেল বিশ্লেষণ শেখান
এটি ছিল, এখন পর্যন্ত, সবচেয়ে কঠিন এবং গুরুত্বপূর্ণ চ্যালেঞ্জ। যখন মডেল একটি প্রশ্ন জিজ্ঞাসা করে, যেমন, "আপনার চরিত্রে কি একটি টুপি আছে" এবং প্লেয়ারটি না উত্তর দেয়, তখন মডেলটি কীভাবে জানবে যে তাদের বোর্ডের কোন অক্ষরগুলি বাদ দেওয়া হয়েছে?
মডেল একটি টুপি সঙ্গে সবাইকে নির্মূল করা উচিত। আমার প্রাথমিক প্রচেষ্টা যৌক্তিক ত্রুটি দ্বারা জর্জরিত ছিল, এবং কখনও কখনও মডেল ভুল অক্ষর বা কোন অক্ষর মুছে ফেলা হয়েছে. এছাড়াও, একটি "টুপি" কি? একটি "বিনি" একটি "টুপি" হিসাবে গণনা করা হয়? এটি হল, আসুন সত্য কথা বলি, এমন কিছু যা মানুষের বিতর্কে ঘটতে পারে। এবং অবশ্যই, সাধারণ ভুলগুলি ঘটবে। AI দৃষ্টিকোণ থেকে চুল টুপির মতো দেখতে পারে।
আমি কোড ডিডাকশন থেকে আলাদা উপলব্ধি করার জন্য আর্কিটেকচারটিকে পুনরায় ডিজাইন করেছি:
এআই চাক্ষুষ বিশ্লেষণের জন্য দায়ী । মডেলগুলি চাক্ষুষ বিশ্লেষণে পারদর্শী। আমি মডেলটিকে তার প্রশ্ন এবং একটি কঠোর JSON স্কিমাতে একটি বিশদ বিশ্লেষণ ফেরত দেওয়ার নির্দেশ দিয়েছি। মডেলটি তার বোর্ডের প্রতিটি অক্ষর বিশ্লেষণ করে এবং প্রশ্নের উত্তর দেয়, "এই চরিত্রটির কি এই বৈশিষ্ট্য আছে?" মডেলটি একটি কাঠামোগত JSON অবজেক্ট প্রদান করে:
{ "character_id": "...", "has_feature": true }
আবারও, স্ট্রাকচার্ড ডেটা একটি সফল ফলাফলের চাবিকাঠি।
গেম কোড চূড়ান্ত সিদ্ধান্ত নিতে বিশ্লেষণ ব্যবহার করে । অ্যাপ্লিকেশন কোড প্লেয়ারের উত্তর ("হ্যাঁ" বা "না") পরীক্ষা করে এবং AI এর বিশ্লেষণের মাধ্যমে পুনরাবৃত্তি করে। যদি প্লেয়ার "না" বলে থাকে, কোডটি এমন প্রতিটি অক্ষর মুছে ফেলতে জানে যেখানে
has_feature
true
।
আমি দেখেছি যে শ্রমের এই বিভাজনটি নির্ভরযোগ্য AI অ্যাপ্লিকেশন তৈরির চাবিকাঠি। এর বিশ্লেষণাত্মক ক্ষমতার জন্য AI ব্যবহার করুন এবং বাইনারি সিদ্ধান্তগুলি আপনার অ্যাপ্লিকেশন কোডে ছেড়ে দিন।
মডেলের উপলব্ধি পরীক্ষা করার জন্য, আমি এই বিশ্লেষণের একটি ভিজ্যুয়ালাইজেশন তৈরি করেছি। এটি মডেলের উপলব্ধি সঠিক কিনা তা নিশ্চিত করা সহজ করে তুলেছে।
প্রম্পট ইঞ্জিনিয়ারিং
যাইহোক, এমনকি এই বিচ্ছেদ সহ, আমি লক্ষ্য করেছি যে মডেলের উপলব্ধি এখনও ত্রুটিপূর্ণ হতে পারে। এটি একটি চরিত্রের চশমা পরেছিল কিনা তা ভুল ধারণা হতে পারে, যা একটি হতাশাজনক, ভুল নির্মূলের দিকে পরিচালিত করে। এটি মোকাবেলা করার জন্য, আমি একটি দ্বি-পদক্ষেপ প্রক্রিয়া নিয়ে পরীক্ষা করেছি: এআই তার প্রশ্ন জিজ্ঞাসা করবে। প্লেয়ারের উত্তর পাওয়ার পর, এটি প্রসঙ্গ হিসাবে উত্তর সহ একটি দ্বিতীয়, নতুন বিশ্লেষণ করবে। তত্ত্বটি ছিল যে একটি দ্বিতীয় চেহারা প্রথম থেকে ত্রুটি ধরতে পারে।
এই প্রবাহটি কীভাবে কাজ করবে তা এখানে:
- AI পালা (API কল 1) : AI জিজ্ঞেস করে, "আপনার চরিত্রের কি দাড়ি আছে?"
- খেলোয়াড়ের পালা : খেলোয়াড় তাদের গোপন চরিত্রের দিকে তাকায়, যে ক্লিন-শেভেন, এবং উত্তর দেয়, "না।"
- AI টার্ন (API কল 2) : AI কার্যকরভাবে নিজেকে তার বাকি সমস্ত অক্ষরগুলি আবার দেখতে বলে এবং প্লেয়ারের উত্তরের উপর ভিত্তি করে কোনটি বাদ দিতে হবে তা নির্ধারণ করতে বলে।
দ্বিতীয় ধাপে, মডেলটি এখনও হালকা খোঁটাযুক্ত একটি চরিত্রকে "দাড়ি না রাখা" হিসাবে ভুলভাবে বুঝতে পারে এবং ব্যবহারকারীর আশা করা সত্ত্বেও সেগুলিকে নির্মূল করতে ব্যর্থ হয়। মূল উপলব্ধি ত্রুটি সংশোধন করা হয়নি, এবং অতিরিক্ত পদক্ষেপ শুধুমাত্র ফলাফল বিলম্বিত. মানব প্রতিপক্ষের বিরুদ্ধে খেলার সময়, আমরা এই বিষয়ে একটি চুক্তি বা স্পষ্টীকরণ নির্দিষ্ট করতে পারি; আমাদের AI প্রতিপক্ষের সাথে বর্তমান সেটআপে, এটি এমন নয়।
এই প্রক্রিয়াটি একটি দ্বিতীয় API কল থেকে লেটেন্সি যোগ করেছে, নির্ভুলতার ক্ষেত্রে উল্লেখযোগ্য উন্নতি না করে। যদি মডেলটি প্রথমবার ভুল হয়, তবে এটি প্রায়শই দ্বিতীয়বারও ভুল ছিল। আমি শুধু একবার পর্যালোচনা করার প্রম্পটটি ফিরিয়ে দিয়েছি।
আরও বিশ্লেষণ যোগ করার পরিবর্তে উন্নতি করুন
আমি একটি UX নীতির উপর নির্ভর করেছিলাম: সমাধানটি আরও বিশ্লেষণ নয়, বরং আরও ভাল বিশ্লেষণ ছিল।
আমি প্রম্পটটি পরিমার্জন করার জন্য প্রচুর পরিমাণে বিনিয়োগ করেছি, মডেলটির কাজকে দুবার পরীক্ষা করতে এবং স্বতন্ত্র বৈশিষ্ট্যগুলিতে ফোকাস করার জন্য সুস্পষ্ট নির্দেশাবলী যোগ করেছি, যা নির্ভুলতা উন্নত করার জন্য আরও কার্যকর কৌশল হিসাবে প্রমাণিত হয়েছে। বর্তমান, আরও নির্ভরযোগ্য প্রবাহ কীভাবে কাজ করে তা এখানে:
AI টার্ন (API কল) : মডেলটিকে একই সময়ে তার প্রশ্ন এবং এর অভ্যন্তরীণ বিশ্লেষণ উভয়ই জেনারেট করতে বলা হয়, একটি একক JSON অবজেক্ট ফেরত দেয়।
- প্রশ্ন : "আপনার চরিত্র কি চশমা পরে?"
- বিশ্লেষণ (তথ্য) :
[ {character_id: 'brad', has_feature: true}, {character_id: 'alex', has_feature: false}, {character_id: 'gina', has_feature: true}, ... ]
খেলোয়াড়ের পালা : খেলোয়াড়ের গোপন চরিত্র হল অ্যালেক্স (চশমা নেই), তাই তারা উত্তর দেয়, "না।"
রাউন্ড এন্ডস : অ্যাপ্লিকেশনের জাভাস্ক্রিপ্ট কোড গ্রহণ করে। এটি AI কে আর কিছু জিজ্ঞাসা করার দরকার নেই। এটি ধাপ 1 থেকে বিশ্লেষণ ডেটার মাধ্যমে পুনরাবৃত্তি করে।
- খেলোয়াড় বললেন, "না।"
- কোডটি প্রতিটি অক্ষরের জন্য দেখায় যেখানে
has_feature
সত্য। - এটি ব্র্যাড এবং জিনার নিচে উল্টে যায়। যুক্তিটি নির্ণয়বাদী এবং তাত্ক্ষণিক।
এই পরীক্ষাটি অত্যন্ত গুরুত্বপূর্ণ ছিল, কিন্তু অনেক ট্রায়াল এবং ত্রুটি প্রয়োজন। আমি কোন ধারণা ছিল না এটা ভাল পেতে যাচ্ছি. কখনও কখনও, এটি আরও খারাপ হয়েছে। কিভাবে সবচেয়ে সামঞ্জস্যপূর্ণ ফলাফল পেতে হয় তা নির্ধারণ করা একটি সঠিক বিজ্ঞান নয় (এখনও, যদি কখনো...)।
কিন্তু আমার নতুন এআই প্রতিপক্ষের সাথে কয়েক রাউন্ডের পরে, একটি চমত্কার নতুন সমস্যা দেখা দিয়েছে: একটি অচলাবস্থা।
অচলাবস্থা এড়ানো
যখন মাত্র দুই বা তিনটি খুব অনুরূপ অক্ষর অবশিষ্ট থাকে, মডেলটি একটি লুপে আটকে যাবে। এটি তাদের সকলে ভাগ করা একটি বৈশিষ্ট্য সম্পর্কে একটি প্রশ্ন জিজ্ঞাসা করবে, যেমন, "আপনার চরিত্রটি কি টুপি পরে?"
আমার কোডটি এটিকে একটি নষ্ট পালা হিসাবে সঠিকভাবে চিহ্নিত করবে, এবং AI আরেকটি চেষ্টা করবে, সমানভাবে বিস্তৃত বৈশিষ্ট্যের অক্ষরগুলিও শেয়ার করা হয়েছে, যেমন, "আপনার চরিত্র কি চশমা পরে?"
আমি একটি নতুন নিয়মের সাথে প্রম্পটটি উন্নত করেছি: যদি একটি প্রশ্ন তৈরির প্রচেষ্টা ব্যর্থ হয় এবং সেখানে তিনটি বা তার কম অক্ষর অবশিষ্ট থাকে, কৌশল পরিবর্তন হয়।
নতুন নির্দেশটি সুস্পষ্ট: "একটি বিস্তৃত বৈশিষ্ট্যের পরিবর্তে, একটি পার্থক্য খুঁজে পেতে আপনাকে অবশ্যই আরও নির্দিষ্ট, অনন্য বা সম্মিলিত ভিজ্যুয়াল বৈশিষ্ট্য সম্পর্কে জিজ্ঞাসা করতে হবে।" উদাহরণস্বরূপ, চরিত্রটি একটি টুপি পরে কিনা তা জিজ্ঞাসা করার পরিবর্তে, তারা একটি বেসবল ক্যাপ পরেছে কিনা তা জিজ্ঞাসা করার জন্য অনুরোধ করা হয়েছে।
এটি মডেলটিকে একটি ছোট বিশদটি খুঁজে পেতে চিত্রগুলিকে আরও ঘনিষ্ঠভাবে দেখতে বাধ্য করে যা অবশেষে একটি অগ্রগতির দিকে নিয়ে যেতে পারে, এটির দেরী-গেমের কৌশলটি বেশিরভাগ সময় কিছুটা ভাল করে।
মডেল অ্যামনেসিয়া দিন
একটি ভাষা মডেলের সবচেয়ে বড় শক্তি হল এর স্মৃতি। কিন্তু এই খেলায় তার সবচেয়ে বড় শক্তি দুর্বলতা হয়ে দাঁড়ায়। যখন আমি একটি দ্বিতীয় গেম শুরু করি, এটি বিভ্রান্তিকর বা অপ্রাসঙ্গিক প্রশ্ন জিজ্ঞাসা করবে। অবশ্যই, আমার স্মার্ট এআই প্রতিপক্ষ আগের খেলা থেকে পুরো চ্যাট ইতিহাস ধরে রাখছিল। এটি একবারে দুটি (বা আরও বেশি) গেম বোঝার চেষ্টা করছিল।
একই AI সেশন পুনরায় ব্যবহার করার পরিবর্তে, আমি এখন প্রতিটি গেমের শেষে স্পষ্টভাবে এটিকে ধ্বংস করি , মূলত AI অ্যামনেশিয়া প্রদান করে।
আপনি যখন প্লে এগেইন ক্লিক করেন, startNewGameSession()
ফাংশনটি বোর্ডকে রিসেট করে এবং একটি একেবারে নতুন AI সেশন তৈরি করে। এটি কেবল অ্যাপে নয়, এআই মডেলের মধ্যেই সেশন স্টেট পরিচালনার একটি আকর্ষণীয় পাঠ ছিল।
ঘণ্টা এবং হুইসেল: কাস্টম গেম এবং ভয়েস ইনপুট
অভিজ্ঞতাকে আরও আকর্ষক করতে, আমি দুটি অতিরিক্ত বৈশিষ্ট্য যোগ করেছি:
কাস্টম অক্ষর :
getUserMedia()
এর সাহায্যে খেলোয়াড়রা তাদের নিজস্ব 5-অক্ষরের সেট তৈরি করতে তাদের ক্যামেরা ব্যবহার করতে পারে। আমি অক্ষর সংরক্ষণ করতে IndexedDB ব্যবহার করেছি, একটি ব্রাউজার ডাটাবেস যা ইমেজ ব্লবসের মতো বাইনারি ডেটা সংরক্ষণের জন্য নিখুঁত। আপনি যখন একটি কাস্টম সেট তৈরি করেন, এটি আপনার ব্রাউজারে সংরক্ষিত হয় এবং একটি রিপ্লে বিকল্প প্রধান মেনুতে প্রদর্শিত হয়।ভয়েস ইনপুট : ক্লায়েন্ট-সাইড মডেলটি মাল্টি-মডেল । এটি পাঠ্য, ছবি এবং অডিও পরিচালনা করতে পারে। মাইক্রোফোন ইনপুট ক্যাপচার করার জন্য MediaRecorder API ব্যবহার করে, আমি একটি প্রম্পটের সাথে মডেলটিতে ফলাফলের অডিও ব্লব ফিড করতে পারি: "নিম্নলিখিত অডিওটি প্রতিলিপি করুন..."। এটি খেলার একটি মজাদার উপায় যোগ করে (এবং এটি আমার ফ্লেমিশ উচ্চারণকে কীভাবে ব্যাখ্যা করে তা দেখার একটি মজার উপায়)। আমি বেশিরভাগই এই নতুন ওয়েব ক্ষমতার বহুমুখিতা দেখানোর জন্য এটি তৈরি করেছি, কিন্তু সত্য বলতে, আমি বারবার প্রশ্ন টাইপ করতে অসুস্থ ছিলাম।
চূড়ান্ত চিন্তা
বিল্ডিং "এআই অনুমান কে?" অবশ্যই একটি চ্যালেঞ্জ ছিল। কিন্তু AI ডিবাগ করতে ডক্স এবং কিছু AI পড়ার সাহায্যে (হ্যাঁ... আমি সেটাই করেছি), এটি একটি মজার পরীক্ষায় পরিণত হয়েছে। এটি একটি ব্যক্তিগত, দ্রুত, নো-ইন্টারনেট-প্রয়োজনীয় অভিজ্ঞতা তৈরি করার জন্য ব্রাউজারে একটি মডেল চালানোর বিপুল সম্ভাবনাকে হাইলাইট করেছে। এটি এখনও একটি পরীক্ষা, এবং কখনও কখনও প্রতিপক্ষ নিখুঁতভাবে খেলতে পারে না। এটি পিক্সেল-নিখুঁত বা যুক্তি-নিখুঁত নয়। জেনারেটিভ এআই সহ, ফলাফলগুলি মডেল-নির্ভর।
পরিপূর্ণতার জন্য চেষ্টা করার পরিবর্তে, আমি ফলাফলের উন্নতির লক্ষ্য রাখব।
এই প্রকল্পটি প্রম্পট ইঞ্জিনিয়ারিংয়ের ধ্রুবক চ্যালেঞ্জগুলিকেও আন্ডারস্কোর করেছে। যে প্রম্পটিং সত্যিই এটির একটি বিশাল অংশ হয়ে উঠেছে, এবং সর্বদা সবচেয়ে মজাদার অংশ নয়। কিন্তু আমি যে সবচেয়ে গুরুত্বপূর্ণ পাঠটি শিখেছি তা হ'ল ডিডাকশন থেকে উপলব্ধি আলাদা করার জন্য অ্যাপ্লিকেশনটিকে আর্কিটেক্ট করা, এআই এবং কোডের ক্ষমতাকে ভাগ করা। এমনকি সেই বিচ্ছেদ সত্ত্বেও, আমি দেখেছি যে AI এখনও (মানুষের কাছে) স্পষ্ট ভুল করতে পারে, যেমন মেক-আপের জন্য বিভ্রান্তিকর ট্যাটু বা কার গোপন চরিত্র নিয়ে আলোচনা করা হচ্ছে তার ট্র্যাক হারানো।
প্রতিবার, সমাধানটি ছিল প্রম্পটগুলিকে আরও স্পষ্ট করে তোলা, নির্দেশাবলী যোগ করা যা একজন মানুষের কাছে স্পষ্ট মনে হয় কিন্তু মডেলের জন্য অপরিহার্য।
কখনও কখনও, খেলা অন্যায্য অনুভূত. মাঝে মাঝে, আমি অনুভব করতাম যে AI গোপন চরিত্রটিকে সময়ের আগেই "জানে", যদিও কোডটি কখনই স্পষ্টভাবে সেই তথ্য ভাগ করেনি। এটি মানব বনাম মেশিনের একটি গুরুত্বপূর্ণ অংশ দেখায়:
একটি AI এর আচরণ শুধুমাত্র সঠিক হতে হবে না; এটা ন্যায্য বোধ করা প্রয়োজন.
এই কারণেই আমি ভোঁতা নির্দেশাবলী সহ প্রম্পটগুলি আপডেট করেছি, যেমন, "আপনি জানেন না আমি কোন চরিত্রটি বেছে নিয়েছি," এবং "কোন প্রতারণা নেই।" আমি শিখেছি যে AI এজেন্ট তৈরি করার সময়, আপনার সীমাবদ্ধতা নির্ধারণে সময় ব্যয় করা উচিত, সম্ভবত নির্দেশাবলীর চেয়েও বেশি।
মডেলের সাথে মিথস্ক্রিয়া উন্নত হতে পারে। একটি অন্তর্নির্মিত মডেলের সাথে কাজ করার মাধ্যমে, আপনি একটি বিশাল সার্ভার-সাইড মডেলের কিছু শক্তি এবং নির্ভরযোগ্যতা হারাবেন, তবে আপনি গোপনীয়তা, গতি এবং অফলাইন ক্ষমতা লাভ করবেন৷ এই ধরনের খেলার জন্য, সেই ট্রেডঅফটি সত্যিই পরীক্ষা করার মতো ছিল। ক্লায়েন্ট-সাইড এআই-এর ভবিষ্যত দিনে দিনে আরও ভাল হচ্ছে, মডেলগুলিও ছোট হচ্ছে, এবং আমরা পরবর্তীতে কী তৈরি করতে সক্ষম হব তা দেখার জন্য আমি অপেক্ষা করতে পারি না।
,প্রকাশিত: অক্টোবর 10, 2025
ক্লাসিক বোর্ড গেম, কে অনুমান? , ডিডাক্টিভ যুক্তিতে একটি মাস্টার ক্লাস। প্রতিটি খেলোয়াড় মুখের একটি বোর্ড দিয়ে শুরু করে এবং হ্যাঁ বা না প্রশ্নের একটি সিরিজের মাধ্যমে, সম্ভাবনাগুলিকে সংকুচিত করে যতক্ষণ না আপনি আত্মবিশ্বাসের সাথে আপনার প্রতিপক্ষের গোপন চরিত্র সনাক্ত করতে পারেন।
Google I/O Connect-এ বিল্ট-ইন AI- এর একটি ডেমো দেখার পর, আমি ভাবলাম: আমি যদি একজন অনুমান কে খেলতে পারি? AI এর বিরুদ্ধে খেলা যে ব্রাউজারে থাকে? ক্লায়েন্ট-সাইড এআই দিয়ে, ফটোগুলি স্থানীয়ভাবে ব্যাখ্যা করা হবে, তাই একটি কাস্টম অনুমান কে? আমার ডিভাইসে বন্ধু এবং পরিবারের ব্যক্তিগত এবং সুরক্ষিত থাকবে।
আমার ব্যাকগ্রাউন্ড প্রাথমিকভাবে UI এবং UX বিকাশে এবং আমি পিক্সেল-নিখুঁত অভিজ্ঞতা তৈরি করতে অভ্যস্ত। আমি আশা করি যে আমি আমার ব্যাখ্যা দিয়ে ঠিক এটি করতে পারি।
আমার আবেদন, এআই অনুমান কে? , রিঅ্যাক্ট দিয়ে নির্মিত এবং আশ্চর্যজনকভাবে সক্ষম প্রতিপক্ষ তৈরি করতে প্রম্পট API এবং একটি ব্রাউজার বিল্ট-ইন মডেল ব্যবহার করে। এই প্রক্রিয়ায়, আমি আবিষ্কার করেছি "পিক্সেল-নিখুঁত" ফলাফল পাওয়া এত সহজ নয়। কিন্তু, এই অ্যাপ্লিকেশানটি দেখায় যে কীভাবে এআইকে চিন্তাশীল গেমের যুক্তি তৈরি করতে ব্যবহার করা যেতে পারে এবং এই যুক্তিকে পরিমার্জিত করতে এবং আপনার প্রত্যাশিত ফলাফল পেতে প্রম্পট ইঞ্জিনিয়ারিংয়ের গুরুত্ব।
বিল্ট-ইন AI ইন্টিগ্রেশন, আমি যে চ্যালেঞ্জগুলির মুখোমুখি হয়েছি এবং আমি যে সমাধানগুলি নিয়ে এসেছি সেগুলি সম্পর্কে জানতে পড়তে থাকুন। আপনি গেমটি খেলতে পারেন এবং GitHub-এ সোর্স কোড খুঁজে পেতে পারেন।
গেম ফাউন্ডেশন: একটি প্রতিক্রিয়া অ্যাপ্লিকেশন
আপনি AI বাস্তবায়নের দিকে নজর দেওয়ার আগে, আমরা অ্যাপ্লিকেশনটির কাঠামো পর্যালোচনা করব। আমি গেমের কন্ডাক্টর হিসেবে কাজ করার জন্য একটি কেন্দ্রীয় App.tsx
ফাইল সহ TypeScript সহ একটি আদর্শ প্রতিক্রিয়া অ্যাপ্লিকেশন তৈরি করেছি। এই ফাইলটি ধারণ করে:
- গেমের অবস্থা : একটি এনাম যা গেমের বর্তমান পর্বটি ট্র্যাক করে (যেমন
PLAYER_TURN_ASKING
,AI_TURN
,GAME_OVER
)। এটি রাষ্ট্রের সবচেয়ে গুরুত্বপূর্ণ অংশ, কারণ এটি নির্দেশ করে যে ইন্টারফেসটি কী প্রদর্শন করে এবং প্লেয়ারের কাছে কী কী ক্রিয়াকলাপ উপলব্ধ। - অক্ষর তালিকা : একাধিক তালিকা রয়েছে যা সক্রিয় অক্ষর, প্রতিটি খেলোয়াড়ের গোপন চরিত্র এবং কোন অক্ষর বোর্ড থেকে বাদ দেওয়া হয়েছে তা নির্ধারণ করে।
- গেম চ্যাট : প্রশ্ন, উত্তর এবং সিস্টেম বার্তাগুলির একটি চলমান লগ।
ইন্টারফেসটি লজিক্যাল উপাদানে বিভক্ত:


গেমটির বৈশিষ্ট্য যেমন বেড়েছে, তেমনি এর জটিলতাও বেড়েছে। প্রাথমিকভাবে, পুরো গেমের যুক্তি একটি একক, বড় কাস্টম রিঅ্যাক্ট হুকের মধ্যে পরিচালিত হয়েছিল, useGameLogic
, কিন্তু এটি দ্রুত নেভিগেট এবং ডিবাগ করার জন্য খুব বড় হয়ে ওঠে। রক্ষণাবেক্ষণযোগ্যতা উন্নত করার জন্য, আমি এই হুকটিকে একাধিক হুকের মধ্যে রিফ্যাক্টর করেছি, প্রতিটি একটি একক দায়িত্ব সহ। যেমন:
-
useGameState
মূল অবস্থা পরিচালনা করে -
usePlayerActions
হল খেলোয়াড়ের পালা -
useAIActions
হল AI এর যুক্তির জন্য
প্রধান useGameLogic
হুক এখন একটি পরিষ্কার সুরকার হিসাবে কাজ করে, এই ছোট হুকগুলিকে একসাথে রেখে। এই স্থাপত্য পরিবর্তন গেমটির কার্যকারিতা পরিবর্তন করেনি, তবে এটি কোডবেসটিকে সম্পূর্ণরূপে পরিষ্কার করে তুলেছে।
প্রম্পট API সহ গেমের যুক্তি
এই প্রকল্পের মূল হল প্রম্পট এপিআই ব্যবহার করা।
আমি builtInAIService.ts
এ এআই গেম লজিক যোগ করেছি। এগুলো হল এর মূল দায়িত্ব:
- সীমাবদ্ধ, বাইনারি উত্তরের অনুমতি দিন।
- মডেল গেম কৌশল শেখান.
- মডেল বিশ্লেষণ শেখান.
- মডেল অ্যামনেসিয়া দিন।
সীমাবদ্ধ, বাইনারি উত্তরের অনুমতি দিন
প্লেয়ার কিভাবে AI এর সাথে যোগাযোগ করে? যখন একজন খেলোয়াড় জিজ্ঞেস করে, "আপনার চরিত্রে কি টুপি আছে?", তখন AI এর গোপন চরিত্রের চিত্রটি "দেখতে" এবং একটি স্পষ্ট উত্তর দিতে হবে।
আমার প্রথম প্রচেষ্টা একটি জগাখিচুড়ি ছিল. প্রতিক্রিয়াটি কথোপকথনমূলক ছিল: "না, আমি যে চরিত্রের কথা ভাবছি, ইসাবেলা, তাকে হ্যাট বা না" বলার পরিবর্তে টুপি পরা বলে মনে হচ্ছে না। প্রাথমিকভাবে, আমি এটি একটি খুব কঠোর প্রম্পট দিয়ে সমাধান করেছি, মূলত মডেলকে শুধুমাত্র "হ্যাঁ" বা "না" দিয়ে প্রতিক্রিয়া জানানোর নির্দেশ দিয়েছি।
এটি কাজ করার সময়, আমি কাঠামোগত আউটপুট ব্যবহার করে আরও ভাল উপায় সম্পর্কে শিখেছি। মডেলটিতে JSON স্কিমা প্রদান করে, আমি একটি সত্য বা মিথ্যা প্রতিক্রিয়ার গ্যারান্টি দিতে পারি।
const schema = { type: "boolean" };
const result = session.prompt(prompt, { responseConstraint: schema });
এটি আমাকে প্রম্পটটি সরল করার অনুমতি দেয় এবং আমার কোডটি নির্ভরযোগ্যভাবে প্রতিক্রিয়া পরিচালনা করতে দেয়:
JSON.parse(result) ? "Yes" : "No"
মডেল গেম কৌশল শেখান
মডেলকে একটি প্রশ্নের উত্তর দিতে বলা মডেলটি শুরু করে প্রশ্ন জিজ্ঞাসা করার চেয়ে অনেক সহজ। একটি ভাল অনুমান কে? খেলোয়াড় এলোমেলো প্রশ্ন জিজ্ঞাসা করে না। তারা এমন প্রশ্ন জিজ্ঞাসা করে যা একবারে সর্বাধিক অক্ষরকে মুছে দেয়। একটি আদর্শ প্রশ্ন বাইনারি প্রশ্ন ব্যবহার করে সম্ভাব্য অবশিষ্ট অক্ষরগুলিকে অর্ধেকে কমিয়ে দেয়।
আপনি কিভাবে একটি মডেল শেখান যে কৌশল? আবার, প্রম্পট ইঞ্জিনিয়ারিং। generateAIQuestion()
জন্য প্রম্পট আসলে Guess Who এর একটি সংক্ষিপ্ত পাঠ? খেলা তত্ত্ব।
প্রাথমিকভাবে, আমি মডেলটিকে "একটি ভাল প্রশ্ন জিজ্ঞাসা করতে" বলেছিলাম। ফলাফল অপ্রত্যাশিত ছিল. ফলাফল উন্নত করার জন্য, আমি নেতিবাচক সীমাবদ্ধতা যোগ করেছি। প্রম্পটে এখন অনুরূপ নির্দেশাবলী অন্তর্ভুক্ত রয়েছে:
- "সমালোচনা: শুধুমাত্র বিদ্যমান বৈশিষ্ট্য সম্পর্কে জিজ্ঞাসা করুন"
- "সমালোচনা: মূল হোন। একটি প্রশ্ন পুনরাবৃত্তি করবেন না"।
এই সীমাবদ্ধতাগুলি মডেলের ফোকাসকে সংকুচিত করে, এটিকে অপ্রাসঙ্গিক প্রশ্ন জিজ্ঞাসা করা থেকে বাধা দেয়, যা এটিকে অনেক বেশি উপভোগ্য প্রতিপক্ষ করে তোলে। আপনি GitHub-এ সম্পূর্ণ প্রম্পট ফাইল পর্যালোচনা করতে পারেন।
মডেল বিশ্লেষণ শেখান
এটি ছিল, এখন পর্যন্ত, সবচেয়ে কঠিন এবং গুরুত্বপূর্ণ চ্যালেঞ্জ। যখন মডেল একটি প্রশ্ন জিজ্ঞাসা করে, যেমন, "আপনার চরিত্রে কি একটি টুপি আছে" এবং প্লেয়ারটি না উত্তর দেয়, তখন মডেলটি কীভাবে জানবে যে তাদের বোর্ডের কোন অক্ষরগুলি বাদ দেওয়া হয়েছে?
মডেল একটি টুপি সঙ্গে সবাইকে নির্মূল করা উচিত। আমার প্রাথমিক প্রচেষ্টা যৌক্তিক ত্রুটি দ্বারা জর্জরিত ছিল, এবং কখনও কখনও মডেল ভুল অক্ষর বা কোন অক্ষর মুছে ফেলা হয়েছে. এছাড়াও, একটি "টুপি" কি? একটি "বিনি" একটি "টুপি" হিসাবে গণনা করা হয়? এটি হল, আসুন সত্য কথা বলি, এমন কিছু যা মানুষের বিতর্কে ঘটতে পারে। এবং অবশ্যই, সাধারণ ভুলগুলি ঘটবে। AI দৃষ্টিকোণ থেকে চুল টুপির মতো দেখতে পারে।
আমি কোড ডিডাকশন থেকে আলাদা উপলব্ধি করার জন্য আর্কিটেকচারটিকে পুনরায় ডিজাইন করেছি:
এআই চাক্ষুষ বিশ্লেষণের জন্য দায়ী । মডেলগুলি চাক্ষুষ বিশ্লেষণে পারদর্শী। আমি মডেলটিকে তার প্রশ্ন এবং একটি কঠোর JSON স্কিমাতে একটি বিশদ বিশ্লেষণ ফেরত দেওয়ার নির্দেশ দিয়েছি। মডেলটি তার বোর্ডের প্রতিটি অক্ষর বিশ্লেষণ করে এবং প্রশ্নের উত্তর দেয়, "এই চরিত্রটির কি এই বৈশিষ্ট্য আছে?" মডেলটি একটি কাঠামোগত JSON অবজেক্ট প্রদান করে:
{ "character_id": "...", "has_feature": true }
আবারও, স্ট্রাকচার্ড ডেটা একটি সফল ফলাফলের চাবিকাঠি।
গেম কোড চূড়ান্ত সিদ্ধান্ত নিতে বিশ্লেষণ ব্যবহার করে । অ্যাপ্লিকেশন কোড প্লেয়ারের উত্তর ("হ্যাঁ" বা "না") পরীক্ষা করে এবং AI এর বিশ্লেষণের মাধ্যমে পুনরাবৃত্তি করে। যদি প্লেয়ার "না" বলে থাকে, কোডটি এমন প্রতিটি অক্ষর মুছে ফেলতে জানে যেখানে
has_feature
true
।
আমি দেখেছি যে শ্রমের এই বিভাজনটি নির্ভরযোগ্য AI অ্যাপ্লিকেশন তৈরির চাবিকাঠি। এর বিশ্লেষণাত্মক ক্ষমতার জন্য AI ব্যবহার করুন এবং বাইনারি সিদ্ধান্তগুলি আপনার অ্যাপ্লিকেশন কোডে ছেড়ে দিন।
মডেলের উপলব্ধি পরীক্ষা করার জন্য, আমি এই বিশ্লেষণের একটি ভিজ্যুয়ালাইজেশন তৈরি করেছি। এটি মডেলের উপলব্ধি সঠিক কিনা তা নিশ্চিত করা সহজ করে তুলেছে।
প্রম্পট ইঞ্জিনিয়ারিং
যাইহোক, এমনকি এই বিচ্ছেদ সহ, আমি লক্ষ্য করেছি যে মডেলের উপলব্ধি এখনও ত্রুটিপূর্ণ হতে পারে। এটি একটি চরিত্রের চশমা পরেছিল কিনা তা ভুল ধারণা হতে পারে, যা একটি হতাশাজনক, ভুল নির্মূলের দিকে পরিচালিত করে। এটি মোকাবেলা করার জন্য, আমি একটি দ্বি-পদক্ষেপ প্রক্রিয়া নিয়ে পরীক্ষা করেছি: এআই তার প্রশ্ন জিজ্ঞাসা করবে। প্লেয়ারের উত্তর পাওয়ার পর, এটি প্রসঙ্গ হিসাবে উত্তর সহ একটি দ্বিতীয়, নতুন বিশ্লেষণ করবে। তত্ত্বটি ছিল যে একটি দ্বিতীয় চেহারা প্রথম থেকে ত্রুটি ধরতে পারে।
এই প্রবাহটি কীভাবে কাজ করবে তা এখানে:
- AI পালা (API কল 1) : AI জিজ্ঞেস করে, "আপনার চরিত্রের কি দাড়ি আছে?"
- খেলোয়াড়ের পালা : খেলোয়াড় তাদের গোপন চরিত্রের দিকে তাকায়, যে ক্লিন-শেভেন, এবং উত্তর দেয়, "না।"
- AI টার্ন (API কল 2) : AI কার্যকরভাবে নিজেকে তার বাকি সমস্ত অক্ষরগুলি আবার দেখতে বলে এবং প্লেয়ারের উত্তরের উপর ভিত্তি করে কোনটি বাদ দিতে হবে তা নির্ধারণ করতে বলে।
দ্বিতীয় ধাপে, মডেলটি এখনও হালকা খোঁটাযুক্ত একটি চরিত্রকে "দাড়ি না রাখা" হিসাবে ভুলভাবে বুঝতে পারে এবং ব্যবহারকারীর আশা করা সত্ত্বেও সেগুলিকে নির্মূল করতে ব্যর্থ হয়। মূল উপলব্ধি ত্রুটি সংশোধন করা হয়নি, এবং অতিরিক্ত পদক্ষেপ শুধুমাত্র ফলাফল বিলম্বিত. মানব প্রতিপক্ষের বিরুদ্ধে খেলার সময়, আমরা এই বিষয়ে একটি চুক্তি বা স্পষ্টীকরণ নির্দিষ্ট করতে পারি; আমাদের AI প্রতিপক্ষের সাথে বর্তমান সেটআপে, এটি এমন নয়।
এই প্রক্রিয়াটি একটি দ্বিতীয় API কল থেকে লেটেন্সি যোগ করেছে, নির্ভুলতার ক্ষেত্রে উল্লেখযোগ্য উন্নতি না করে। যদি মডেলটি প্রথমবার ভুল হয়, তবে এটি প্রায়শই দ্বিতীয়বারও ভুল ছিল। আমি শুধু একবার পর্যালোচনা করার প্রম্পটটি ফিরিয়ে দিয়েছি।
আরও বিশ্লেষণ যোগ করার পরিবর্তে উন্নতি করুন
আমি একটি UX নীতির উপর নির্ভর করেছিলাম: সমাধানটি আরও বিশ্লেষণ নয়, বরং আরও ভাল বিশ্লেষণ ছিল।
আমি প্রম্পটটি পরিমার্জন করার জন্য প্রচুর পরিমাণে বিনিয়োগ করেছি, মডেলটির কাজকে দুবার পরীক্ষা করতে এবং স্বতন্ত্র বৈশিষ্ট্যগুলিতে ফোকাস করার জন্য সুস্পষ্ট নির্দেশাবলী যোগ করেছি, যা নির্ভুলতা উন্নত করার জন্য আরও কার্যকর কৌশল হিসাবে প্রমাণিত হয়েছে। বর্তমান, আরও নির্ভরযোগ্য প্রবাহ কীভাবে কাজ করে তা এখানে:
AI টার্ন (API কল) : মডেলটিকে একই সময়ে তার প্রশ্ন এবং এর অভ্যন্তরীণ বিশ্লেষণ উভয়ই জেনারেট করতে বলা হয়, একটি একক JSON অবজেক্ট ফেরত দেয়।
- প্রশ্ন : "আপনার চরিত্র কি চশমা পরে?"
- বিশ্লেষণ (তথ্য) :
[ {character_id: 'brad', has_feature: true}, {character_id: 'alex', has_feature: false}, {character_id: 'gina', has_feature: true}, ... ]
খেলোয়াড়ের পালা : খেলোয়াড়ের গোপন চরিত্র হল অ্যালেক্স (চশমা নেই), তাই তারা উত্তর দেয়, "না।"
রাউন্ড এন্ডস : অ্যাপ্লিকেশনের জাভাস্ক্রিপ্ট কোড গ্রহণ করে। এটি AI কে আর কিছু জিজ্ঞাসা করার দরকার নেই। এটি ধাপ 1 থেকে বিশ্লেষণ ডেটার মাধ্যমে পুনরাবৃত্তি করে।
- খেলোয়াড় বললেন, "না।"
- কোডটি প্রতিটি অক্ষরের জন্য দেখায় যেখানে
has_feature
সত্য। - এটি ব্র্যাড এবং জিনার নিচে উল্টে যায়। যুক্তিটি নির্ণয়বাদী এবং তাত্ক্ষণিক।
এই পরীক্ষাটি অত্যন্ত গুরুত্বপূর্ণ ছিল, কিন্তু অনেক ট্রায়াল এবং ত্রুটি প্রয়োজন। আমি কোন ধারণা ছিল না এটা ভাল পেতে যাচ্ছি. কখনও কখনও, এটি আরও খারাপ হয়েছে। কিভাবে সবচেয়ে সামঞ্জস্যপূর্ণ ফলাফল পেতে হয় তা নির্ধারণ করা একটি সঠিক বিজ্ঞান নয় (এখনও, যদি কখনো...)।
কিন্তু আমার নতুন এআই প্রতিপক্ষের সাথে কয়েক রাউন্ডের পরে, একটি চমত্কার নতুন সমস্যা দেখা দিয়েছে: একটি অচলাবস্থা।
অচলাবস্থা এড়ানো
যখন মাত্র দুই বা তিনটি খুব অনুরূপ অক্ষর অবশিষ্ট থাকে, মডেলটি একটি লুপে আটকে যাবে। এটি তাদের সকলে ভাগ করা একটি বৈশিষ্ট্য সম্পর্কে একটি প্রশ্ন জিজ্ঞাসা করবে, যেমন, "আপনার চরিত্রটি কি টুপি পরে?"
আমার কোডটি এটিকে একটি নষ্ট পালা হিসাবে সঠিকভাবে চিহ্নিত করবে, এবং AI আরেকটি চেষ্টা করবে, সমানভাবে বিস্তৃত বৈশিষ্ট্যের অক্ষরগুলিও শেয়ার করা হয়েছে, যেমন, "আপনার চরিত্র কি চশমা পরে?"
আমি একটি নতুন নিয়মের সাথে প্রম্পটটি উন্নত করেছি: যদি একটি প্রশ্ন তৈরির প্রচেষ্টা ব্যর্থ হয় এবং সেখানে তিনটি বা তার কম অক্ষর অবশিষ্ট থাকে, কৌশল পরিবর্তন হয়।
নতুন নির্দেশটি সুস্পষ্ট: "একটি বিস্তৃত বৈশিষ্ট্যের পরিবর্তে, একটি পার্থক্য খুঁজে পেতে আপনাকে অবশ্যই আরও নির্দিষ্ট, অনন্য বা সম্মিলিত ভিজ্যুয়াল বৈশিষ্ট্য সম্পর্কে জিজ্ঞাসা করতে হবে।" উদাহরণস্বরূপ, চরিত্রটি একটি টুপি পরে কিনা তা জিজ্ঞাসা করার পরিবর্তে, তারা একটি বেসবল ক্যাপ পরেছে কিনা তা জিজ্ঞাসা করার জন্য অনুরোধ করা হয়েছে।
এটি মডেলটিকে একটি ছোট বিশদটি খুঁজে পেতে চিত্রগুলিকে আরও ঘনিষ্ঠভাবে দেখতে বাধ্য করে যা অবশেষে একটি অগ্রগতির দিকে নিয়ে যেতে পারে, এটির দেরী-গেমের কৌশলটি বেশিরভাগ সময় কিছুটা ভাল করে।
মডেল অ্যামনেসিয়া দিন
একটি ভাষা মডেলের সবচেয়ে বড় শক্তি হল এর স্মৃতি। কিন্তু এই খেলায় তার সবচেয়ে বড় শক্তি দুর্বলতা হয়ে দাঁড়ায়। যখন আমি একটি দ্বিতীয় গেম শুরু করি, এটি বিভ্রান্তিকর বা অপ্রাসঙ্গিক প্রশ্ন জিজ্ঞাসা করবে। অবশ্যই, আমার স্মার্ট এআই প্রতিপক্ষ আগের খেলা থেকে পুরো চ্যাট ইতিহাস ধরে রাখছিল। এটি একবারে দুটি (বা আরও বেশি) গেম বোঝার চেষ্টা করছিল।
একই AI সেশন পুনরায় ব্যবহার করার পরিবর্তে, আমি এখন প্রতিটি গেমের শেষে স্পষ্টভাবে এটিকে ধ্বংস করি , মূলত AI অ্যামনেশিয়া প্রদান করে।
আপনি যখন প্লে এগেইন ক্লিক করেন, startNewGameSession()
ফাংশনটি বোর্ডকে রিসেট করে এবং একটি একেবারে নতুন AI সেশন তৈরি করে। এটি কেবল অ্যাপে নয়, এআই মডেলের মধ্যেই সেশন স্টেট পরিচালনার একটি আকর্ষণীয় পাঠ ছিল।
ঘণ্টা এবং হুইসেল: কাস্টম গেম এবং ভয়েস ইনপুট
অভিজ্ঞতাকে আরও আকর্ষক করতে, আমি দুটি অতিরিক্ত বৈশিষ্ট্য যোগ করেছি:
কাস্টম অক্ষর :
getUserMedia()
এর সাহায্যে খেলোয়াড়রা তাদের নিজস্ব 5-অক্ষরের সেট তৈরি করতে তাদের ক্যামেরা ব্যবহার করতে পারে। আমি অক্ষর সংরক্ষণ করতে IndexedDB ব্যবহার করেছি, একটি ব্রাউজার ডাটাবেস যা ইমেজ ব্লবসের মতো বাইনারি ডেটা সংরক্ষণের জন্য নিখুঁত। আপনি যখন একটি কাস্টম সেট তৈরি করেন, এটি আপনার ব্রাউজারে সংরক্ষিত হয় এবং একটি রিপ্লে বিকল্প প্রধান মেনুতে প্রদর্শিত হয়।ভয়েস ইনপুট : ক্লায়েন্ট-সাইড মডেলটি মাল্টি-মডেল । এটি পাঠ্য, ছবি এবং অডিও পরিচালনা করতে পারে। মাইক্রোফোন ইনপুট ক্যাপচার করার জন্য MediaRecorder API ব্যবহার করে, আমি একটি প্রম্পটের সাথে মডেলটিতে ফলাফলের অডিও ব্লব ফিড করতে পারি: "নিম্নলিখিত অডিওটি প্রতিলিপি করুন..."। এটি খেলার একটি মজাদার উপায় যোগ করে (এবং এটি আমার ফ্লেমিশ উচ্চারণকে কীভাবে ব্যাখ্যা করে তা দেখার একটি মজার উপায়)। আমি বেশিরভাগই এই নতুন ওয়েব ক্ষমতার বহুমুখিতা দেখানোর জন্য এটি তৈরি করেছি, কিন্তু সত্য বলতে, আমি বারবার প্রশ্ন টাইপ করতে অসুস্থ ছিলাম।
চূড়ান্ত চিন্তা
বিল্ডিং "এআই অনুমান কে?" অবশ্যই একটি চ্যালেঞ্জ ছিল। কিন্তু AI ডিবাগ করতে ডক্স এবং কিছু AI পড়ার সাহায্যে (হ্যাঁ... আমি সেটাই করেছি), এটি একটি মজার পরীক্ষায় পরিণত হয়েছে। এটি একটি ব্যক্তিগত, দ্রুত, নো-ইন্টারনেট-প্রয়োজনীয় অভিজ্ঞতা তৈরি করার জন্য ব্রাউজারে একটি মডেল চালানোর বিপুল সম্ভাবনাকে হাইলাইট করেছে। এটি এখনও একটি পরীক্ষা, এবং কখনও কখনও প্রতিপক্ষ নিখুঁতভাবে খেলতে পারে না। এটি পিক্সেল-নিখুঁত বা যুক্তি-নিখুঁত নয়। জেনারেটিভ এআই সহ, ফলাফলগুলি মডেল-নির্ভর।
পরিপূর্ণতার জন্য চেষ্টা করার পরিবর্তে, আমি ফলাফলের উন্নতির লক্ষ্য রাখব।
এই প্রকল্পটি প্রম্পট ইঞ্জিনিয়ারিংয়ের ধ্রুবক চ্যালেঞ্জগুলিকেও আন্ডারস্কোর করেছে। যে প্রম্পটিং সত্যিই এটির একটি বিশাল অংশ হয়ে উঠেছে, এবং সর্বদা সবচেয়ে মজাদার অংশ নয়। কিন্তু আমি যে সবচেয়ে গুরুত্বপূর্ণ পাঠটি শিখেছি তা হ'ল ডিডাকশন থেকে উপলব্ধি আলাদা করার জন্য অ্যাপ্লিকেশনটিকে আর্কিটেক্ট করা, এআই এবং কোডের ক্ষমতাকে ভাগ করা। এমনকি সেই বিচ্ছেদ সত্ত্বেও, আমি দেখেছি যে AI এখনও (মানুষের কাছে) স্পষ্ট ভুল করতে পারে, যেমন মেক-আপের জন্য বিভ্রান্তিকর ট্যাটু বা কার গোপন চরিত্র নিয়ে আলোচনা করা হচ্ছে তার ট্র্যাক হারানো।
প্রতিবার, সমাধানটি ছিল প্রম্পটগুলিকে আরও স্পষ্ট করে তোলা, নির্দেশাবলী যোগ করা যা একজন মানুষের কাছে স্পষ্ট মনে হয় কিন্তু মডেলের জন্য অপরিহার্য।
কখনও কখনও, খেলা অন্যায্য অনুভূত. মাঝে মাঝে, আমি অনুভব করতাম যে AI গোপন চরিত্রটিকে সময়ের আগেই "জানে", যদিও কোডটি কখনই স্পষ্টভাবে সেই তথ্য ভাগ করেনি। এটি মানব বনাম মেশিনের একটি গুরুত্বপূর্ণ অংশ দেখায়:
একটি AI এর আচরণ শুধুমাত্র সঠিক হতে হবে না; এটা ন্যায্য বোধ করা প্রয়োজন.
এই কারণেই আমি ভোঁতা নির্দেশাবলী সহ প্রম্পটগুলি আপডেট করেছি, যেমন, "আপনি জানেন না আমি কোন চরিত্রটি বেছে নিয়েছি," এবং "কোন প্রতারণা নেই।" আমি শিখেছি যে AI এজেন্ট তৈরি করার সময়, আপনার সীমাবদ্ধতা নির্ধারণে সময় ব্যয় করা উচিত, সম্ভবত নির্দেশাবলীর চেয়েও বেশি।
মডেলের সাথে মিথস্ক্রিয়া উন্নত হতে পারে। একটি অন্তর্নির্মিত মডেলের সাথে কাজ করার মাধ্যমে, আপনি একটি বিশাল সার্ভার-সাইড মডেলের কিছু শক্তি এবং নির্ভরযোগ্যতা হারাবেন, তবে আপনি গোপনীয়তা, গতি এবং অফলাইন ক্ষমতা লাভ করবেন৷ এই ধরনের খেলার জন্য, সেই ট্রেডঅফটি সত্যিই পরীক্ষা করার মতো ছিল। ক্লায়েন্ট-সাইড এআই-এর ভবিষ্যত দিনে দিনে আরও ভাল হচ্ছে, মডেলগুলিও ছোট হচ্ছে, এবং আমরা পরবর্তীতে কী তৈরি করতে সক্ষম হব তা দেখার জন্য আমি অপেক্ষা করতে পারি না।
,প্রকাশিত: অক্টোবর 10, 2025
ক্লাসিক বোর্ড গেম, কে অনুমান? , ডিডাক্টিভ যুক্তিতে একটি মাস্টার ক্লাস। প্রতিটি খেলোয়াড় মুখের একটি বোর্ড দিয়ে শুরু করে এবং হ্যাঁ বা না প্রশ্নের একটি সিরিজের মাধ্যমে, সম্ভাবনাগুলিকে সংকুচিত করে যতক্ষণ না আপনি আত্মবিশ্বাসের সাথে আপনার প্রতিপক্ষের গোপন চরিত্র সনাক্ত করতে পারেন।
Google I/O Connect-এ বিল্ট-ইন AI- এর একটি ডেমো দেখার পর, আমি ভাবলাম: আমি যদি একজন অনুমান কে খেলতে পারি? AI এর বিরুদ্ধে খেলা যে ব্রাউজারে থাকে? ক্লায়েন্ট-সাইড এআই দিয়ে, ফটোগুলি স্থানীয়ভাবে ব্যাখ্যা করা হবে, তাই একটি কাস্টম অনুমান কে? আমার ডিভাইসে বন্ধু এবং পরিবারের ব্যক্তিগত এবং সুরক্ষিত থাকবে।
আমার ব্যাকগ্রাউন্ড প্রাথমিকভাবে UI এবং UX বিকাশে এবং আমি পিক্সেল-নিখুঁত অভিজ্ঞতা তৈরি করতে অভ্যস্ত। আমি আশা করি যে আমি আমার ব্যাখ্যা দিয়ে ঠিক এটি করতে পারি।
আমার আবেদন, এআই অনুমান কে? , রিঅ্যাক্ট দিয়ে নির্মিত এবং আশ্চর্যজনকভাবে সক্ষম প্রতিপক্ষ তৈরি করতে প্রম্পট API এবং একটি ব্রাউজার বিল্ট-ইন মডেল ব্যবহার করে। এই প্রক্রিয়ায়, আমি আবিষ্কার করেছি "পিক্সেল-নিখুঁত" ফলাফল পাওয়া এত সহজ নয়। কিন্তু, এই অ্যাপ্লিকেশানটি দেখায় যে কীভাবে এআইকে চিন্তাশীল গেমের যুক্তি তৈরি করতে ব্যবহার করা যেতে পারে এবং এই যুক্তিকে পরিমার্জিত করতে এবং আপনার প্রত্যাশিত ফলাফল পেতে প্রম্পট ইঞ্জিনিয়ারিংয়ের গুরুত্ব।
বিল্ট-ইন AI ইন্টিগ্রেশন, আমি যে চ্যালেঞ্জগুলির মুখোমুখি হয়েছি এবং আমি যে সমাধানগুলি নিয়ে এসেছি সেগুলি সম্পর্কে জানতে পড়তে থাকুন। আপনি গেমটি খেলতে পারেন এবং GitHub-এ সোর্স কোড খুঁজে পেতে পারেন।
গেম ফাউন্ডেশন: একটি প্রতিক্রিয়া অ্যাপ্লিকেশন
আপনি AI বাস্তবায়নের দিকে নজর দেওয়ার আগে, আমরা অ্যাপ্লিকেশনটির কাঠামো পর্যালোচনা করব। আমি গেমের কন্ডাক্টর হিসেবে কাজ করার জন্য একটি কেন্দ্রীয় App.tsx
ফাইল সহ TypeScript সহ একটি আদর্শ প্রতিক্রিয়া অ্যাপ্লিকেশন তৈরি করেছি। এই ফাইলটি ধারণ করে:
- গেমের অবস্থা : একটি এনাম যা গেমের বর্তমান পর্বটি ট্র্যাক করে (যেমন
PLAYER_TURN_ASKING
,AI_TURN
,GAME_OVER
)। এটি রাষ্ট্রের সবচেয়ে গুরুত্বপূর্ণ অংশ, কারণ এটি নির্দেশ করে যে ইন্টারফেসটি কী প্রদর্শন করে এবং প্লেয়ারের কাছে কী কী ক্রিয়াকলাপ উপলব্ধ। - অক্ষর তালিকা : একাধিক তালিকা রয়েছে যা সক্রিয় অক্ষর, প্রতিটি খেলোয়াড়ের গোপন চরিত্র এবং কোন অক্ষর বোর্ড থেকে বাদ দেওয়া হয়েছে তা নির্ধারণ করে।
- Game chat : A running log of questions, answers, and system messages.
The interface is broken down into logical components:


As the game's features grew, so did its complexity. Initially, the entire game's logic was managed within a single, large custom React hook , useGameLogic
, but it quickly became too large to navigate and debug. To improve maintainability, I refactored this hook into multiple hooks, each with a single responsibility. যেমন:
-
useGameState
manages the core state -
usePlayerActions
is for the player's turn -
useAIActions
is for the AI's logic
The main useGameLogic
hook now acts as a clean composer, placing these smaller hooks together. This architectural change didn't alter the game's functionality, but it made the codebase a whole lot cleaner.
Game logic with the Prompt API
The core of this project is the use of the Prompt API.
I added the AI game logic to builtInAIService.ts
. These are its key responsibilities:
- Allow restrictive, binary answers.
- Teach the model game strategy.
- Teach the model analysis.
- Give the model amnesia.
Allow restrictive, binary answers
How does the player interact with the AI? When a player asks, "Does your character have a hat?", the AI needs to "look" at its secret character's image and give a clear answer.
My first attempts were a mess. The response was conversational: "No, the character I'm thinking of, Isabella, does not appear to be wearing a hat," instead of offering a binary yes or no. Initially, I solved this with a very strict prompt, essentially dictating to the model to only respond with "Yes" or "No".
While this worked, I learned of an even better way using structured output . By providing the JSON Schema to the model, I could guarantee a true or false response.
const schema = { type: "boolean" };
const result = session.prompt(prompt, { responseConstraint: schema });
This allowed me to simplify the prompt and let my code reliably handle the response:
JSON.parse(result) ? "Yes" : "No"
Teach the model game strategy
Telling the model to answer a question is much simpler than having the model initiate and ask questions. A good Guess Who? player doesn't ask random questions. They ask questions that eliminate the most characters at once. An ideal question reduces the possible remaining characters in half using binary questions.
How do you teach a model that strategy? Again, prompt engineering. The prompt for generateAIQuestion()
is actually a concise lesson in Guess Who? game theory.
Initially, I asked the model to "ask a good question." The results were unpredictable. To improve the results, I added negative constraints. The prompt now includes instructions similar to:
- "CRITICAL: Ask about existing features ONLY"
- "CRITICAL: Be original. Do NOT repeat a question".
These constraints narrow the model's focus, prevent it from asking irrelevant questions, which make it a much more enjoyable opponent. You can review the full prompt file on GitHub .
Teach the model analysis
This was, by far, the most difficult and important challenge. When the model asks a question, such as, "Does your character have a hat," and the player responds no, how does the model know what characters on their board are eliminated?
The model should eliminate everyone with a hat. My early attempts were plagued with logical errors, and sometimes the model eliminated the wrong characters or no characters. Also, what is a "hat"? Does a "beanie" count as a "hat"? This is, let's be honest, also something that can happen in a human debate. And of course, general mistakes happen. Hair can look like a hat from an AI perspective.
I redesigned the architecture to separate perception from code deduction:
AI is responsible for visual analysis . Models excel at visual analysis. I instructed the model to return its question and a detailed analysis in a strict JSON schema. The model analyzes each character on its board and answers the question, "Does this character have this feature?" The model returns a structured JSON object:
{ "character_id": "...", "has_feature": true }
Once again, structured data is key to a successful outcome.
Game code uses the analysis to make the final decision . The application code checks the player's answer ("Yes" or "No") and iterates through the AI's analysis. If the player said "No," the code knows to eliminate every character where
has_feature
istrue
.
I found this division of labor is key to building reliable AI applications. Use the AI for its analytic capabilities, and leave binary decisions to your application code.
To check the model's perception, I built a visualization of this analysis. This made it easier to confirm if the model's perception was correct.
প্রম্পট ইঞ্জিনিয়ারিং
However, even with this separation, I noticed the model's perception could still be flawed. It might misjudge whether a character wore glasses, leading to a frustrating, incorrect elimination. To combat this, I experimented with a two-step process: the AI would ask its question. After receiving the player's answer, it would perform a second, fresh analysis with the answer as context. The theory was that a second look might catch errors from the first.
Here's how that flow would have worked:
- AI turn (API call 1) : AI asks, "Does your character have a beard?"
- Player's turn : The player looks at their secret character, who is clean-shaven, and answers, "No."
- AI turn (API call 2) : The AI effectively asks itself to look at all of its remaining characters, again, and determine which ones to eliminate based on the player's answer.
In step two, the model might still misperceive a character with a light stubble as "not having a beard" and fail to eliminate them, even though the user expected it to. The core perception error wasn't fixed, and the extra step just delayed the results. When playing against a human opponent, we can specify an agreement or clarification on this; in the current setup with our AI opponent, this isn't the case.
This process added latency from a second API call, without gaining a significant boost in accuracy. If the model was wrong the first time, it was often wrong the second time, too. I reverted the prompt to review just once.
Improve instead of adding more analysis
I relied on a UX principle: The solution wasn't more analysis, but better analysis.
I invested heavily in refining the prompt, adding explicit instructions for the model to double-check its work and focus on distinct features, which proved to be a more effective strategy for improving accuracy. Here's how the current, more reliable flow works:
AI turn (API call) : The model is prompted to generate both its question and its internal analysis at the same time, returning a single JSON object.
- Question : "Does your character wear glasses?"
- Analysis (data) :
[ {character_id: 'brad', has_feature: true}, {character_id: 'alex', has_feature: false}, {character_id: 'gina', has_feature: true}, ... ]
Player's turn : The player's secret character is Alex (no glasses), so they answer, "No."
Round ends : The application's JavaScript code takes over. It doesn't need to ask the AI anything else. It iterates through the analysis data from step 1.
- The player said "No."
- The code looks for every character where
has_feature
is true. - It flips down Brad and Gina. The logic is deterministic and instant.
This experimentation was crucial, but required a lot of trial and error. I had no idea if it was going to get better. Sometimes, it got even worse. Determining how to get the most consistent results isn't an exact science (yet, if ever...).
But after a few rounds with my new AI opponent, a fantastic new issue appeared: a stalemate.
Escape deadlock
When only two or three very similar characters remained, the model would get stuck in a loop. It would ask a question about a feature they all shared, such as, "Does your character wear a hat?"
My code would correctly identify this as a wasted turn, and the AI would try another, equally broad feature the characters also all shared, such as, "Does your character wear glasses?"
I enhanced the prompt with a new rule: if a question generation attempt fails and there are three or fewer characters left, the strategy changes.
The new instruction is explicit: "Instead of a broad feature, you must ask about a more specific, unique, or combined visual feature to find a difference." For example, instead of asking if the character wears a hat, it's prompted to ask if they're wearing a baseball cap.
This forces the model to look much closer at the images to find the one small detail that can finally lead to a breakthrough, making its late-game strategy work a little better, most of the time.
Give the model amnesia
A language model's greatest strength is its memory. But in this game, its greatest strength became a weakness. When I started a second game, it would ask confusing or irrelevant questions. Of course, my smart AI opponent was retaining the entire chat history from the previous game. It was trying to make sense of two (or even more) games at once.
Instead of reusing the same AI session, I now explicitly destroy it at the end of each game, essentially giving the AI amnesia.
When you click Play Again , the startNewGameSession()
function resets the board and creates a brand new AI session. This was an interesting lesson in managing session state not just in the app, but within the AI model itself.
Bells and whistles: Custom games and voice input
To make the experience more engaging, I added two extra features:
Custom characters : With
getUserMedia()
, players can use their camera to create their own 5-character set. I used IndexedDB to save the characters, a browser database perfect for storing binary data like image blobs. When you create a custom set, it's saved to your browser, and a replay option appears in the main menu.Voice input : The client-side model is multi-modal . It can handle text, images, and also audio. Using the MediaRecorder API to capture microphone input, I could feed the resulting audio blob to the model with a prompt: "Transcribe the following audio...". This adds a fun way to play (and a fun way to see how it interprets my Flemish accent). I created this mostly to show the versatility of this new web capability, but truth be told, I was sick of typing questions over and over again.
চূড়ান্ত চিন্তা
Building "AI Guess Who?" was definitely a challenge. But with a bit of help from reading docs and some AI to debug AI (yeah... I did that), it turned out to be a fun experiment. It highlighted the immense potential of running a model in the browser for creating a private, fast, no-internet-required experience. This is still an experiment, and sometimes the opponent just doesn't play perfectly. It's not pixel-perfect or logic-perfect. With generative AI, the results are model-dependent.
Instead of striving for perfection, I'll aim for improving the outcome.
This project also underscored the constant challenges of prompt engineering. That prompting really became a huge part of it, and not always the most fun part. But the most critical lesson I learned was architecting the application to separate perception from deduction, dividing capabilities of AI and code. Even with that separation, I found that the AI could still make (to a human) obvious mistakes, like confusing tattoos for make-up or losing track of whose secret character was being discussed.
Each time, the solution was to make the prompts even more explicit, adding instructions that feel obvious to a human but are essential for the model.
Sometimes, the game felt unfair. Occasionally, I felt like the AI "knew" the secret character ahead of time, even though the code never explicitly shared that information. This shows a crucial part of human versus machine:
An AI's behavior doesn't just need to be correct; it needs to feel fair.
This is why I updated the prompts with blunt instructions, such as, "You do NOT know which character I have picked," and "No cheating." I learned that when building AI agents, you should spend time defining limitations, probably even more than instructions.
The interaction with the model could continue to be improved. By working with a built-in model, you lose some of the power and reliability of a massive server-side model, but you gain privacy, speed, and offline capability. For a game like this, that tradeoff was really worth experimenting with. The future of client-side AI is getting better by the day, models are getting smaller as well, and I can't wait to see what we'll be able to build next.
,প্রকাশিত: অক্টোবর 10, 2025
The classic board game, Guess Who? , is a masterclass in deductive reasoning. Each player starts with a board of faces and, through a series of yes or no questions, narrows down the possibilities until you can confidently identify your opponent's secret character.
After seeing a demo of built-in AI at Google I/O Connect, I wondered: what if I could play a Guess Who? game against AI that lives in the browser? With client-side AI, the photos would be interpreted locally, so a custom Guess Who? of friends and family would remain private and secure on my device.
My background is primarily in UI and UX development, and I'm used to building pixel-perfect experiences. I hoped I could do exactly that with my interpretation.
My application, AI Guess Who? , is built with React and uses the Prompt API and a browser built-in model to create a surprisingly capable opponent. In this process, I discovered it's not so simple to get "pixel-perfect" results. But, this application demonstrates how AI can be used to build thoughtful game logic, and the importance of prompt engineering to refine this logic and get the outcomes you expect.
Keep reading to learn about the built-in AI integration, challenges I faced, and the solutions I landed on. You can play the game and find the source code on GitHub .
Game foundation: A React app
Before you look at the AI implementation, we'll review the application's structure. I built a standard React application with TypeScript, with a central App.tsx
file to act as the game's conductor. This file holds:
- Game state : An enum that tracks the current phase of the game (such as
PLAYER_TURN_ASKING
,AI_TURN
,GAME_OVER
). This is the most important piece of state, as it dictates what the interface displays and what actions are available to the player. - Character lists : There are multiple lists that designate the active characters, each players' secret character, and which characters have been eliminated from the board.
- Game chat : A running log of questions, answers, and system messages.
The interface is broken down into logical components:


As the game's features grew, so did its complexity. Initially, the entire game's logic was managed within a single, large custom React hook , useGameLogic
, but it quickly became too large to navigate and debug. To improve maintainability, I refactored this hook into multiple hooks, each with a single responsibility. যেমন:
-
useGameState
manages the core state -
usePlayerActions
is for the player's turn -
useAIActions
is for the AI's logic
The main useGameLogic
hook now acts as a clean composer, placing these smaller hooks together. This architectural change didn't alter the game's functionality, but it made the codebase a whole lot cleaner.
Game logic with the Prompt API
The core of this project is the use of the Prompt API.
I added the AI game logic to builtInAIService.ts
. These are its key responsibilities:
- Allow restrictive, binary answers.
- Teach the model game strategy.
- Teach the model analysis.
- Give the model amnesia.
Allow restrictive, binary answers
How does the player interact with the AI? When a player asks, "Does your character have a hat?", the AI needs to "look" at its secret character's image and give a clear answer.
My first attempts were a mess. The response was conversational: "No, the character I'm thinking of, Isabella, does not appear to be wearing a hat," instead of offering a binary yes or no. Initially, I solved this with a very strict prompt, essentially dictating to the model to only respond with "Yes" or "No".
While this worked, I learned of an even better way using structured output . By providing the JSON Schema to the model, I could guarantee a true or false response.
const schema = { type: "boolean" };
const result = session.prompt(prompt, { responseConstraint: schema });
This allowed me to simplify the prompt and let my code reliably handle the response:
JSON.parse(result) ? "Yes" : "No"
Teach the model game strategy
Telling the model to answer a question is much simpler than having the model initiate and ask questions. A good Guess Who? player doesn't ask random questions. They ask questions that eliminate the most characters at once. An ideal question reduces the possible remaining characters in half using binary questions.
How do you teach a model that strategy? Again, prompt engineering. The prompt for generateAIQuestion()
is actually a concise lesson in Guess Who? game theory.
Initially, I asked the model to "ask a good question." The results were unpredictable. To improve the results, I added negative constraints. The prompt now includes instructions similar to:
- "CRITICAL: Ask about existing features ONLY"
- "CRITICAL: Be original. Do NOT repeat a question".
These constraints narrow the model's focus, prevent it from asking irrelevant questions, which make it a much more enjoyable opponent. You can review the full prompt file on GitHub .
Teach the model analysis
This was, by far, the most difficult and important challenge. When the model asks a question, such as, "Does your character have a hat," and the player responds no, how does the model know what characters on their board are eliminated?
The model should eliminate everyone with a hat. My early attempts were plagued with logical errors, and sometimes the model eliminated the wrong characters or no characters. Also, what is a "hat"? Does a "beanie" count as a "hat"? This is, let's be honest, also something that can happen in a human debate. And of course, general mistakes happen. Hair can look like a hat from an AI perspective.
I redesigned the architecture to separate perception from code deduction:
AI is responsible for visual analysis . Models excel at visual analysis. I instructed the model to return its question and a detailed analysis in a strict JSON schema. The model analyzes each character on its board and answers the question, "Does this character have this feature?" The model returns a structured JSON object:
{ "character_id": "...", "has_feature": true }
Once again, structured data is key to a successful outcome.
Game code uses the analysis to make the final decision . The application code checks the player's answer ("Yes" or "No") and iterates through the AI's analysis. If the player said "No," the code knows to eliminate every character where
has_feature
istrue
.
I found this division of labor is key to building reliable AI applications. Use the AI for its analytic capabilities, and leave binary decisions to your application code.
To check the model's perception, I built a visualization of this analysis. This made it easier to confirm if the model's perception was correct.
প্রম্পট ইঞ্জিনিয়ারিং
However, even with this separation, I noticed the model's perception could still be flawed. It might misjudge whether a character wore glasses, leading to a frustrating, incorrect elimination. To combat this, I experimented with a two-step process: the AI would ask its question. After receiving the player's answer, it would perform a second, fresh analysis with the answer as context. The theory was that a second look might catch errors from the first.
Here's how that flow would have worked:
- AI turn (API call 1) : AI asks, "Does your character have a beard?"
- Player's turn : The player looks at their secret character, who is clean-shaven, and answers, "No."
- AI turn (API call 2) : The AI effectively asks itself to look at all of its remaining characters, again, and determine which ones to eliminate based on the player's answer.
In step two, the model might still misperceive a character with a light stubble as "not having a beard" and fail to eliminate them, even though the user expected it to. The core perception error wasn't fixed, and the extra step just delayed the results. When playing against a human opponent, we can specify an agreement or clarification on this; in the current setup with our AI opponent, this isn't the case.
This process added latency from a second API call, without gaining a significant boost in accuracy. If the model was wrong the first time, it was often wrong the second time, too. I reverted the prompt to review just once.
Improve instead of adding more analysis
I relied on a UX principle: The solution wasn't more analysis, but better analysis.
I invested heavily in refining the prompt, adding explicit instructions for the model to double-check its work and focus on distinct features, which proved to be a more effective strategy for improving accuracy. Here's how the current, more reliable flow works:
AI turn (API call) : The model is prompted to generate both its question and its internal analysis at the same time, returning a single JSON object.
- Question : "Does your character wear glasses?"
- Analysis (data) :
[ {character_id: 'brad', has_feature: true}, {character_id: 'alex', has_feature: false}, {character_id: 'gina', has_feature: true}, ... ]
Player's turn : The player's secret character is Alex (no glasses), so they answer, "No."
Round ends : The application's JavaScript code takes over. It doesn't need to ask the AI anything else. It iterates through the analysis data from step 1.
- The player said "No."
- The code looks for every character where
has_feature
is true. - It flips down Brad and Gina. The logic is deterministic and instant.
This experimentation was crucial, but required a lot of trial and error. I had no idea if it was going to get better. Sometimes, it got even worse. Determining how to get the most consistent results isn't an exact science (yet, if ever...).
But after a few rounds with my new AI opponent, a fantastic new issue appeared: a stalemate.
Escape deadlock
When only two or three very similar characters remained, the model would get stuck in a loop. It would ask a question about a feature they all shared, such as, "Does your character wear a hat?"
My code would correctly identify this as a wasted turn, and the AI would try another, equally broad feature the characters also all shared, such as, "Does your character wear glasses?"
I enhanced the prompt with a new rule: if a question generation attempt fails and there are three or fewer characters left, the strategy changes.
The new instruction is explicit: "Instead of a broad feature, you must ask about a more specific, unique, or combined visual feature to find a difference." For example, instead of asking if the character wears a hat, it's prompted to ask if they're wearing a baseball cap.
This forces the model to look much closer at the images to find the one small detail that can finally lead to a breakthrough, making its late-game strategy work a little better, most of the time.
Give the model amnesia
A language model's greatest strength is its memory. But in this game, its greatest strength became a weakness. When I started a second game, it would ask confusing or irrelevant questions. Of course, my smart AI opponent was retaining the entire chat history from the previous game. It was trying to make sense of two (or even more) games at once.
Instead of reusing the same AI session, I now explicitly destroy it at the end of each game, essentially giving the AI amnesia.
When you click Play Again , the startNewGameSession()
function resets the board and creates a brand new AI session. This was an interesting lesson in managing session state not just in the app, but within the AI model itself.
Bells and whistles: Custom games and voice input
To make the experience more engaging, I added two extra features:
Custom characters : With
getUserMedia()
, players can use their camera to create their own 5-character set. I used IndexedDB to save the characters, a browser database perfect for storing binary data like image blobs. When you create a custom set, it's saved to your browser, and a replay option appears in the main menu.Voice input : The client-side model is multi-modal . It can handle text, images, and also audio. Using the MediaRecorder API to capture microphone input, I could feed the resulting audio blob to the model with a prompt: "Transcribe the following audio...". This adds a fun way to play (and a fun way to see how it interprets my Flemish accent). I created this mostly to show the versatility of this new web capability, but truth be told, I was sick of typing questions over and over again.
চূড়ান্ত চিন্তা
Building "AI Guess Who?" was definitely a challenge. But with a bit of help from reading docs and some AI to debug AI (yeah... I did that), it turned out to be a fun experiment. It highlighted the immense potential of running a model in the browser for creating a private, fast, no-internet-required experience. This is still an experiment, and sometimes the opponent just doesn't play perfectly. It's not pixel-perfect or logic-perfect. With generative AI, the results are model-dependent.
Instead of striving for perfection, I'll aim for improving the outcome.
This project also underscored the constant challenges of prompt engineering. That prompting really became a huge part of it, and not always the most fun part. But the most critical lesson I learned was architecting the application to separate perception from deduction, dividing capabilities of AI and code. Even with that separation, I found that the AI could still make (to a human) obvious mistakes, like confusing tattoos for make-up or losing track of whose secret character was being discussed.
Each time, the solution was to make the prompts even more explicit, adding instructions that feel obvious to a human but are essential for the model.
Sometimes, the game felt unfair. Occasionally, I felt like the AI "knew" the secret character ahead of time, even though the code never explicitly shared that information. This shows a crucial part of human versus machine:
An AI's behavior doesn't just need to be correct; it needs to feel fair.
This is why I updated the prompts with blunt instructions, such as, "You do NOT know which character I have picked," and "No cheating." I learned that when building AI agents, you should spend time defining limitations, probably even more than instructions.
The interaction with the model could continue to be improved. By working with a built-in model, you lose some of the power and reliability of a massive server-side model, but you gain privacy, speed, and offline capability. For a game like this, that tradeoff was really worth experimenting with. The future of client-side AI is getting better by the day, models are getting smaller as well, and I can't wait to see what we'll be able to build next.