नहीं, धन्यवाद और अलविदा।
ठीक है, सबसे पहले, मैं क्लिक-बेट शैली शीर्षक के लिए क्षमा चाहता हूँ। कभी-कभार, जब मुझे डेमो का कोई विचार आता है, तो वह काम नहीं करता। लेकिन कभी-कभी , यह मज़ेदार और दिलचस्प तरीके से काम नहीं करता है, और मुझे लगता है कि इसे साझा करना एक अच्छा विचार है। (इसके अलावा, इस बात की हमेशा प्रबल संभावना है कि यह काम नहीं करेगा क्योंकि मैंने कुछ गलत किया है!) मुझे लगता है कि आज का डेमो इसका एक आदर्श उदाहरण है।
इस साल की शुरुआत में, मैंने अल्पाइन.जेएस और काफी उत्कृष्ट डेक ऑफ कार्ड्स एपीआई का उपयोग करके एक ब्लैकजैक गेम बनाया। कल, मैं खेल के बारे में सोच रहा था, और मुझे आश्चर्य हुआ - अगर मैं इसे खेलते समय मदद मांगने के लिए जेनेरिक एआई का उपयोग करूं तो क्या होगा? इसलिए, उदाहरण के लिए, मैं अपने खेल में गया और यह देखा:
Google के PaLM Makersuite ऐप में, मैंने लिखा:
मैं ब्लैकजैक खेल रहा हूं और डीलर के पास छह हीरे दिख रहे हैं। मेरे पास क्लबों का जैक और दिलों का जैक है। क्या मुझे मारना चाहिए या मुझे रहना चाहिए?
और यह प्रतिक्रिया मिली:
आपके पास 20 है, जो एक अच्छा हाथ है। डीलर के पास 16 है, जो औसत से कम है। यदि आप मारते हैं, तो आपको एक कार्ड मिलने का जोखिम है जो आपको नष्ट कर देगा। इसलिए रुकना और आशा करना बेहतर है कि डीलर का भंडाफोड़ हो जाए।
जो, ठीक है, बिल्कुल स्पष्ट है। आप कभी भी दो जैक से वार नहीं करेंगे। लेकिन मुझे वर्णनात्मक प्रतिक्रिया पसंद आई जो खेल के सिद्धांतों को पुष्ट करती है। मैंने सोचा - क्या होगा अगर मैं गेम में एक बटन जोड़ दूं जिससे आप GenAI से मदद मांग सकें? यहां बताया गया है कि मैंने यह कैसे किया:
सामने की ओर, मैंने यूआई परिवर्तनों को बहुत कम रखा। मैंने एक साधारण बटन जोड़कर शुरुआत की:
इस पर क्लिक करने पर दो महत्वपूर्ण काम करने होंगे। सबसे पहले, इसे गेम स्थिति को प्रॉम्प्ट में 'अनुवाद' करने की आवश्यकता है; फिर, इसे इसे एक ऐसी सेवा तक पहुंचाने की जरूरत है जो जेन एआई कॉल को संभालेगी। मैंने एक नया फ़ंक्शन, askForHelp
बनाया है, जो इसे संभालता है:
async askForHelp() { this.aiHelp = '<i>Asking our AI friend...</i>'; // first, "translate" the cards to English let q = `I'm playing blackjack and the dealer currently has ${this.pcCards[1].value} of ${this.pcCards[1].suit.toLowerCase()}. I've got a ${this.playerCards[0].value} of ${this.playerCards[0].suit.toLowerCase()} and a ${this.playerCards[1].value} of ${this.playerCards[1].suit.toLowerCase()}. Should I hit or should I stay?`; console.log(q); let resp = await fetch(`https://eo8dkukowewth66.m.pipedream.net?text=${encodeURIComponent(q)}`); let help = await resp.json(); /* note that help has line breaks and stuff in and in theory we should map to br or something, but im fine ignoring. */ this.aiHelp = ''; alert(help); },
मैं प्लेयर और पीसी कार्डों को दो वेरिएबल्स में संग्रहीत करता हूं जिनमें उनके हाथों का प्रतिनिधित्व करने वाले कार्डों की एक श्रृंखला होती है। प्रत्येक कार्ड का एक 'मूल्य' होता है, जो जैक की तरह या तो एक संख्या या एक नाम होता है। प्रत्येक कार्ड में एक सूट भी होता है। सैद्धांतिक रूप से, यह शायद महत्वपूर्ण जानकारी नहीं है, लेकिन मुझे लगा कि इससे नुकसान नहीं होगा। यहां एक गेम द्वारा उत्पन्न उदाहरण संकेत दिया गया है:
I'm playing blackjack and the dealer currently has 8 of clubs. I've got a 7 of spades and a QUEEN of hearts. Should I hit or should I stay?
इसे मेरी बैकएंड सेवा को भेज दिया जाता है (इसके बारे में एक सेकंड में और अधिक), और परिणाम फिर जावास्क्रिप्ट अलर्ट में प्रदर्शित होता है, जो 100% भयानक यूएक्स है, लेकिन चूंकि यह एक प्रयोग था, मुझे लगा कि यह काफी अच्छा था।
यदि आप उत्सुक हैं, तो प्रतिक्रिया यह थी:
रहना। आपके पास कुल 17 हैं, जो एक अच्छा हाथ है। डीलर का 8 कोई उच्च कार्ड नहीं है, इसलिए यदि आप रुके रहते हैं तो आपके खोने की संभावना नहीं है।
अपने बैकएंड के लिए, मैंने एक त्वरित पाइपड्रीम वर्कफ़्लो तैयार किया। मेरे वर्कफ़्लो में वस्तुतः केवल तीन चरण शामिल थे।
पहला मेरा ट्रिगर है, एक HTTP समापन बिंदु। आप ऊपर फ्रंट-एंड कोड में यूआरएल देख सकते हैं।
दूसरा चरण अंतर्निहित Google PaLM API क्रिया है। मुझे बस यह बताना था कि प्रॉम्प्ट के लिए क्या उपयोग करना है: {{steps.trigger.event.query.text}}
मेरे अंतिम चरण ने बस परिणाम लौटाया:
export default defineComponent({ async run({ steps, $ }) { await $.respond({ status: 200, headers: { "Content-Type":"application/json" }, body: JSON.stringify(steps.generate_text.$return_value[0].candidates[0].output), }) }, })
इसलिए। मेरे पहले कुछ परीक्षण बहुत अच्छे रहे, और फिर... चीज़ें पटरी से उतर गईं। यहाँ एक उदाहरण है. व्यापारी के पास सात दिल थे। मेरे पास हुकुमों की एक रानी और आठ हीरों की रानी थी। जब मैंने मदद मांगी, तो मुझे मिला:
डीलर का अपकार्ड 7 है, जो एक "कठिन" 17 है। इसका मतलब है कि आप चाहे कुछ भी करें, डीलर को खड़ा रहना होगा। आपके पास "सॉफ्ट" 19 है, जिसका अर्थ है कि आपके पास एक इक्का है जो 1 या 11 के रूप में गिना जा सकता है। आपको रहना चाहिए।
ठीक है, ज़रूर, मुझे रुकना चाहिए , लेकिन असल में क्या? मेरे पास 19 हैं? डीलर के पास 17 हैं? और यह बेहतर हो जाता है. एक बार जब मेरे पास 18 शो थे, तो मुझे निम्नलिखित मिला:
मैं मारने की सिफ़ारिश करूंगा. कुल 18 के साथ, आप 21 से केवल एक अंक दूर हैं, जो कि ब्लैकजैक में विजयी हाथ है। डीलर के सात दिलों से उन्हें कुल 17 मिलते हैं, जो 21 की सीमा से नीचे है। इसलिए, इस बात की अच्छी संभावना है कि यदि डीलर हिट करता है तो उसका भंडाफोड़ हो जाएगा, जिससे आपको जीत मिलेगी। हालाँकि, यदि आप रुकते हैं, तो आप अपना हाथ नहीं सुधार पाएंगे और आशा करनी होगी कि डीलर का भंडाफोड़ हो जाए।
18 पर मारना। मैं कोई पेशेवर जुआरी नहीं हूं, लेकिन मुझे पूरा यकीन है कि यह बुरी सलाह है।
इसने मुझे अपने प्रॉम्प्ट के बारे में थोड़ा और सोचने पर मजबूर कर दिया। मैंने कुछ बदलाव किए, जैसे सूट को लोअरकेस करना, क्योंकि मुझे चिंता थी कि इससे एआई भ्रमित हो सकता है। मैंने मेकरसुइट में कुछ विकल्पों को दोहराया, और लगातार, यह कई बार बुनियादी गणित के साथ संघर्ष करता हुआ प्रतीत हुआ। तब भी जब मैं स्पष्ट था:
मेरे पास एक जैक ऑफ क्लब (दस लायक) और आठ हार्ट्स (मूल्य 8) हैं।
यह अभी भी सोचा गया था कि मेरे पास 19 हैं। इसमें मेरी किस्मत बेहतर थी:
मेरे पास एक जैक ऑफ क्लब (दस लायक) और आठ हार्ट्स (मूल्य 8) हैं। मेरे हाथ का कुल योग 18 है.
और मैंने यह भी कोशिश की:
मेरे पास क्लबों का एक इक्का और आठ दिलों का इक्का है। मेरे हाथ का योग 9 या 19 है।
और वह लगातार सही ढंग से काम करता प्रतीत हुआ। तो, इसे ध्यान में रखते हुए, मैं अपनी त्वरित पीढ़ी के पास वापस गया और वहां अपने तर्क को अद्यतन किया। यहाँ अद्यतन संस्करण है:
async askForHelp() { this.aiHelp = '<i>Asking our AI friend...</i>'; let totalOb = this.getCount(this.playerCards); let totalStr = 'My hand has a total of '; if(totalOb.lowCount === totalOb.highCount) { totalStr += totalOb.lowCount; } else { totalStr += `${totalOb.lowCount} or ${totalOb.highCount}`; } // first, "translate" the cards to English let q = `I'm playing blackjack and the dealer currently has ${this.pcCards[1].value} of ${this.pcCards[1].suit.toLowerCase()}. I've got a ${this.playerCards[0].value} of ${this.playerCards[0].suit.toLowerCase()} and a ${this.playerCards[1].value} of ${this.playerCards[1].suit.toLowerCase()}. ${totalStr}. Should I hit or should I stay?`; console.log(q); let resp = await fetch(`https://eo8dkukowewth66.m.pipedream.net?text=${encodeURIComponent(q)}`); let help = await resp.json(); console.log('RESP', help); /* note that help has line breaks and stuff in and in theory we should map to br or something, but im fine ignoring. */ this.aiHelp = ''; alert(help); },
मेरे ब्लैकजैक गेम में एक उपयोगिता फ़ंक्शन है, getCount
, जो एक ऑब्जेक्ट लौटाता है जिसमें दो मान lowCount
होते हैं, जहां Aces को एक माना जाता है, और highCount
, जहां एक Ace को अधिकतम ग्यारह माना जाता है। इसके साथ, मैं कुल के बारे में अपनी त्वरित जानकारी जोड़ता हूं।
इससे काफ़ी मदद मिली , लेकिन मैं अब भी कभी-कभी भ्रामक प्रतिक्रियाएँ देता हूँ।
तो... शायद इसे जुए की मेज़ पर सलाह देने वाला आपका नशे में धुत दोस्त मानें?
मुझे डेमो के इस संस्करण को सार्वजनिक रूप से साझा करना अच्छा लगेगा, और मैं निश्चित रूप से कोड साझा कर सकता हूं, लेकिन मैं पाइपड्रीम वर्कफ़्लो को अक्षम कर रहा हूं ताकि मुझसे इसके लिए शुल्क न लिया जाए। बेझिझक यहां फ्रंट-एंड कोड देखें:
https://codepen.io/cfjedimaster/pen/QWYpQjY/905e31ed6d9e3539c041044b308f5f06?editors=1011
हमेशा की तरह, मुझे बताएं आप क्या सोच रहे हैं!
यहाँ भी प्रकाशित किया गया है.