Build a text-based adventure game with Gemma 2

AUG 14, 2024
Ju-yeong Ji Gemma DevRel

Gemma is a family of open models built from the same research and technology used to create the Gemini models. Instruction-tuned models are fine-tuned on a massive dataset of instructions, making the model particularly well-suited for tasks that require following instructions, such as question answering and text summarization.

In this blog post, we will guide you through the process of creating a text-based adventure game using an instruction-tuned Gemma 2 model. Although you can use your own setup, we've chosen a whimsical journey. You'll be guided by a friendly and helpful AI companion known as the Storyteller. The Storyteller will describe enchanting landscapes, introduce you to curious characters, and weave a tale based on your choices! Get ready to embark on a thrilling adventure where your interactions with the AI will determine the outcome of the game!


Let’s see a Demo

Link to Youtube Video (visible only when JS is disabled)

In this captivating game, you, the player, awaken on a distant island. Your only guide and companion is the Storyteller AI, who will help you navigate the challenges and find a way to escape.


What you will need

Hardware

  • A local environment that can run Gemma locally

  • [Optional] Deploy Gemma in Vertex AI

Software

See “Gemma setup” to get access to Gemma on kaggle.com and generate a Kaggle API key.

If you lack a robust machine for local Gemma execution, consider utilizing Vertex AI as your downstream application to deploy Gemma models. Vertex AI provides a managed platform that enables rapid development and scaling of machine learning projects without the necessity for in-house MLOps expertise.


[Optional] Deploy Gemma in Vertex AI

First, find the Gemma 2 model card from the Model Garden. Once you click the “Deploy” button, you can choose the model variations and the location to deploy.

Deploy Gemma in Vertex AI

Once the deployment is completed, you can find your endpoint here.

To obtain a script for acquiring predictions from your active endpoint, navigate to the "Sample Request" and select "Python".

sample request in Gemma

Build a chatbot

Below is an example of a local Gemma chatbot wrapper class. You can explore more about it from “Building a chatbot with Gemma”.

In our demo, we employed the Gemma 2 2B model. However, if you have sufficient hardware capabilities, you can opt for alternative Gemma models such as 9B or 27B to obtain a more robust result.

# Gemma local

import keras
import keras_nlp

model_name = "gemma2_instruct_2b_en"

class GemmaBot():
  __START_TURN_USER__ = "<start_of_turn>user\n"
  __START_TURN_MODEL__ = "<start_of_turn>model\n"
  __END_TURN__ = "<end_of_turn>\n"

  def __init__(self, system=""):
    self.model = keras_nlp.models.GemmaCausalLM.from_preset(model_name)
    self.system = system
    self.history = []

  def add_to_history_as_user(self, message):
      self.history.append(self.__START_TURN_USER__ + message + self.__END_TURN__)

  def add_to_history_as_model(self, message):
      self.history.append(self.__START_TURN_MODEL__ + message)

  def get_history(self):
      return "".join([*self.history])

  def get_full_prompt(self):
    prompt = self.get_history() + self.__START_TURN_MODEL__
    if len(self.system)>0:
      prompt = self.system + "\n" + prompt
    return prompt

  def ask(self, message):
    self.add_to_history_as_user(message)
    prompt = self.get_full_prompt()
    response = self.model.generate(prompt, max_length=2048)
    result = response.replace(prompt, "")  # Extract only the new response
    self.add_to_history_as_model(result)
    return result

If you deployed Gemma on Vertex AI, copy and paste the sample code on Github into your bot file and use the code below instead. Note that you don’t have to initialize the “self.model” variable since it’s running on Google Cloud.

def __init__(self, system=""):
    self.system = system
    self.history = []

:
<-- skip -->
:

  def ask(self, message):
    self.add_to_history_as_user(message)
    prompt = self.get_full_prompt()
    response = predict_custom_trained_model_sample(
      project="<YOUR_PROJECT_ID>",
      endpoint_id="<YOUR_ENDPONT_ID>",
      location="<YOUR_LOCATION>",
      api_endpoint="<YOUR_LOCATION>-aiplatform.googleapis.com",
      instances={ "inputs": prompt, "max_tokens": 2048 }
      )
    result = response.replace(prompt, "")  # Extract only the new response
    self.add_to_history_as_model(result)
    return result

To test your bot, use the following straightforward code. (Assuming you saved the code above as "gemma.py")

from gemma import GemmaBot
gemma_bot = GemmaBot("You are the Storyteller, guide on this remote island.")
text = gemma_bot.ask("Who are you?")
print(text)

Here’s an example output from the bot.

Output 1 - build a text based adventure

Make a game loop

In case you are unfamiliar with the game loop, it’s the core process that drives the functionality and interactivity of the game. It’s a continuous cycle that repeats throughout the duration of gameplay, ensuring that the game state is updated, input is processed, and visuals are rendered on the screen.

In our simple text-based adventure game, we've implemented a basic game loop as follows:

import StageIntro
current_stage = StageIntro.StageIntro()

def game_loop():
    if current_stage.bot is None:
        # stage type that has no bot
        current_stage.process()
        return

    resp = ""
    print("-"*80)
    print(f"Type \"{current_stage.cmd_exit}\" if you want to end the conversation.")
    print("-"*80)

    if current_stage.preamble != "":
        print(current_stage.preamble)

    while resp != current_stage.cmd_exit:
        if resp == "":
            text = current_stage.intro
            current_stage.bot.add_to_history_as_model(text)
        else:
            text = current_stage.bot.ask(resp)

        print(text)
        resp = input("\n> ")

    prompt(admin_bot.judge(current_stage.bot.get_history()))

def check_end_condition():
    if not current_stage.pass_check():
        check = admin_bot.end_of_game()
        print("Succeed to escape?")
        print(check)
        if check.lower().startswith("true"):
            print("Congratulations! You escaped the island.")
            exit(0)

    next_stage = current_stage.next()
    if next_stage is None:
        print("End Of Game")
        exit(0)

    return next_stage

while True:
    game_loop()
    current_stage = check_end_condition()
    input("Press ENTER to move forward")

To simplify the process, we have designed a basic stage interface class. You can extend this class and establish your own customized stage setup by creating a new stage.

For example, you can create a new stage with a steel gate like below.

from stage import IStage
from gemma import GemmaBot

class StageGate(IStage):
    def __init__(self):
        self.preamble = "The steel gate looms before you, a formidable barrier separating you from the path ahead. Vines crawl along its rusted bars, and the air hums with a faint electrical current.\nThe Storyteller appears beside you, a shimmering presence in the dappled sunlight."
        self.intro = "Greetings! I am the Storyteller, your guide on this island.\nWe've come to a gate... what will you do?"
        self.bot = GemmaBot("You are the Storyteller, a friendly and helpful AI guide on a mysterious island. Your role is to help the player navigate challenges and find a way to escape. You are currently standing before a large steel gate.")

Summary

Using Gemma, you've mastered creating text-based adventure games. You can apply the same structure to craft diverse games with themes ranging from steampunk to fantasy.

Moreover, you can integrate your own concepts for core game mechanics, such as skill-based progression, relationship building, or even mini-games.

Keep in mind that this serves as a foundational starting point. Feel empowered to blend, adapt, and expand upon these elements to create a genuinely unique and captivating text-based adventure game experience.

Consider joining the Google Developer Community's Discord server, where you'll have the opportunity to showcase your projects and establish connections with fellow enthusiasts who share similar interests.

Thanks for reading.