Hayır. Teşekkür ederim ve hoşçakalın.
Tamam, öncelikle tıklama tuzağı tarzı başlık için özür dilerim. Arada sırada aklıma bir demo fikri geldiğinde bu işe yaramıyor. Ancak bazen işler eğlenceli ve ilginç bir şekilde yürümüyor ve yine de bunu paylaşmanın iyi bir fikir olduğunu düşünüyorum. (Ayrıca, yanlış bir şey yaptığım için her şeyin yolunda gitmeme ihtimali de her zaman yüksektir !) Bugünkü demo sanırım bunun mükemmel bir örneği.
Bu yılın başlarında Alpine.js'yi ve oldukça mükemmel Deck of Cards API'sini kullanarak bir Blackjack oyunu geliştirdim. Dün oyunu düşünüyordum ve şunu merak ettim: Oyunu oynarken yardım istemek için üretken yapay zekayı kullanırsam ne olurdu? Mesela oyunuma gittim ve şunu gördüm:
Google'ın PaLM Makersuite uygulamasında şunları yazdım:
Blackjack oynuyorum ve krupiyerde altılı karo gösteriliyor. Bir sopam ve bir kupam var. Vurmalı mıyım yoksa kalmalı mıyım?
Ve şu yanıtı aldım:
Elinizde 20 var, bu iyi bir el. Dağıtıcının 16'sı var, bu da ortalamanın altında. Eğer vurursan, seni mahvedecek bir kart alma riskiyle karşı karşıya kalırsın. Bu yüzden kalıp satıcının iflas etmesini ummak daha iyi.
Bu oldukça açık. Asla iki Vale ile vuramazsın. Ancak oyunun ilkelerini güçlendiren açıklayıcı yanıtı sevdim. Peki ya oyuna GenAI'dan yardım istemenizi sağlayan bir düğme ekleseydim? İşte bunu nasıl yaptım:
Ön uçta kullanıcı arayüzü değişikliklerini oldukça minimum düzeyde tuttum. Basit bir düğme ekleyerek başladım:
Buna tıklamanın iki önemli şey yapması gerekir. Öncelikle oyun durumunu bir bilgi istemine 'çevirmesi' gerekiyor; daha sonra bunu gen AI çağrısını yönetecek bir hizmete iletmesi gerekiyor. Bunu yöneten yeni bir işlev askForHelp
oluşturdum:
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); },
Oynatıcıyı ve PC kartlarını, ellerini temsil eden bir dizi kart içeren iki değişkende saklıyorum. Her kartın Jack gibi bir sayı ya da isim olan bir 'değeri' vardır. Her kartın ayrıca bir rengi vardır. Teorik olarak bu muhtemelen kritik bir bilgi değil, ama zararı olmayacağını düşündüm. İşte bir oyun tarafından oluşturulan örnek bir istem:
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?
Bu, arka uç hizmetime iletildi (bir saniye sonra buna daha fazla değineceğim) ve sonuç daha sonra bir JavaScript uyarısında görüntüleniyor ki bu %100 berbat bir kullanıcı deneyimidir, ancak bu bir deney olduğu için bunun yeterince iyi olduğunu düşündüm.
Merak ediyorsanız yanıt şöyle oldu:
Kalmak. Toplamda 17'niz var ve bu iyi bir el. Dağıtıcının 8'i yüksek bir kart değildir, dolayısıyla kalırsanız kaybetmeniz pek olası değildir.
Arka tarafım için hızlı bir Pipedream iş akışı başlattım. İş akışım kelimenin tam anlamıyla sadece üç adımdan oluşuyordu.
Birincisi benim tetikleyicim, bir HTTP uç noktası. URL'yi yukarıdaki ön uç kodunda görebilirsiniz.
İkinci adım, yerleşik Google PaLM API eylemidir. Tek yapmam gereken, istem olarak neyi kullanacağımı söylemekti: {{steps.trigger.event.query.text}}
Son adımım basitçe sonucu döndürdü:
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), }) }, })
Yani evet. İlk birkaç testim harika çalıştı, sonra... işler kontrolden çıktı. İşte bir örnek. Dağıtıcının yedili kupası vardı. Bir maça vezirim ve bir karo sekizim vardı. Yardım istediğimde şunu anladım:
Dağıtıcının açık kartı 7'dir, bu da "zor" bir 17'dir. Bu, dağıtıcının ne yaparsanız yapın ayakta durması gerektiği anlamına gelir. "Yumuşak" bir 19'unuz var, bu da 1 veya 11 olarak sayılabilecek bir asınız olduğu anlamına gelir. Kalmalısınız.
Tamam, elbette kalmalıyım ama gerçekte ne oluyor? 19'um mu var? Satıcının 17'si mi var? Ve daha iyi oluyor. Bir keresinde 18 gösteri yaptığımda aşağıdakileri aldım:
vurmanızı tavsiye ederim. Toplamda 18 ile blackjack'te kazanan el olan 21'e yalnızca bir puan uzaktasınız. Dağıtıcının yedi kupası onlara toplamda 17 verir ve bu da 21 eşiğinin altındadır. Bu nedenle, krupiyerin vurması halinde iflas etme ihtimali yüksektir, bu da size kazanç sağlar. Ancak kalırsanız elinizi geliştiremeyeceksiniz ve krupiyerin iflas edeceğini ummak zorunda kalacaksınız.
18'e vuruyorum. Profesyonel bir kumarbaz değilim ama bunun kötü bir tavsiye olduğuna eminim.
Bu, istemim hakkında biraz daha düşünmemi sağladı. Yapay zekanın kafasını karıştırabileceğinden endişelendiğim için rengi küçültmek gibi bazı ince ayarlar yaptım. Makersuite'teki bazı seçenekleri yineledim ve sürekli olarak zaman zaman temel matematikle boğuşuyor gibi görünüyordu. Açıkça söylediğimde bile:
Bir sinek valem (on değerinde) ve bir sekiz kupam (8 değerinde) var.
Hala 19 yaşında olduğumu sanıyordu. Bu konuda daha şanslıydım:
Bir sinek valem (on değerinde) ve bir sekiz kupam (8 değerinde) var. Elimin toplamı 18.
Ve şunu da denedim:
Elimde bir sinek ası ve bir sekizli kupa var. Elimin toplamı 9 veya 19.
Ve bu sürekli olarak doğru bir şekilde çalışıyor gibi görünüyordu. Böylece bunu aklımda tutarak hızlı neslime geri döndüm ve mantığımı orada güncelledim. İşte güncellenmiş versiyon:
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); },
Blackjack oyunumda getCount
bir yardımcı işlev var; bu işlev, Asların bir olarak değerlendirildiği lowCount
ve en fazla bir As'ın on bir olarak kabul edildiği highCount
olmak üzere iki değer içeren bir nesneyi döndürür. Bununla toplamla ilgili hızlı bilgilerime ekliyorum.
Bu biraz yardımcı oldu ama yine de bazen sanrısal yanıtlar veriyordum.
Yani... kumar masasında tavsiye veren sarhoş arkadaşınız olarak düşünebilir misiniz?
Demonun bu sürümünü herkese açık olarak paylaşmayı çok isterim ve elbette kodu da paylaşabilirim, ancak bunun için ücretlendirilmem diye Pipedream iş akışını devre dışı bırakıyorum. Buradaki ön uç koduna bakmaktan çekinmeyin:
https://codepen.io/cfjedimaster/pen/QWYpQjY/905e31ed6d9e3539c041044b308f5f06?editors=1011
Her zaman olduğu gibi ne düşündüğünüzü bana bildirin!
Burada da yayınlandı.