使用 Gemma 2 构建基于文本的冒险游戏

八月 09, 2024
Ju-yeong Ji Gemma DevRel

Gemma 是一系列开放模型,与 Gemini 模型基于相同的研究成果和技术构建而成。我们使用庞大的指令数据集对这些经过指令调整的模型进行了微调,使其特别适合需要遵循指令的任务,例如问题回答和文本摘要。

在这篇博文中,我们将引导您完成使用经过指令调整的 Gemma 2 模型制作基于文本的冒险游戏这一过程。虽然您可以使用自己的设置,但我们选择开启一段奇妙的旅程。一位友好且乐于助人的 AI 伴侣(被称为“故事讲述者”)将为您提供指导。故事讲述者将描述迷人的风景,向您介绍奇怪的人物,并根据您的选择编织一个故事!准备好开启一场激动人心的冒险,您与 AI 的互动将决定游戏的结果!


我们来看一个演示

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

在这款充满吸引力的游戏中,身为玩家的您在一个遥远的岛屿上醒来。您唯一的向导和伴侣是 AI 故事讲述者,它将帮助您应对挑战并找到逃离的方法。


您需要的硬件和软件

硬件

  • 可以在本地运行 Gemma 的本地环境

  • [可选] 在 Vertex AI 中部署 Gemma

软件

请参阅“Gemma 设置”以访问 kaggle.com 上的 Gemma 并生成 Kaggle API 密钥。

如果您缺乏可本地执行 Gemma 的强大计算机,请考虑使用 Vertex AI 作为部署 Gemma 模型的下游应用。Vertex AI 提供的托管平台可以快速开发和扩展机器学习项目,而无需拥有 MLOps 内行专业知识。


[可选] 在 Vertex AI 中部署 Gemma

首先,在 Model Garden 中找到 Gemma 2 模型卡片。点击“部署”按钮后,您可以选择模型变体和要部署的位置。

Deploy Gemma in Vertex AI

部署完成后,您可以在此处找到您的端点。

要获取用于从活动端点获取预测数据的脚本,请导航到“示例请求”并选择“Python”。

sample request in Gemma

构建聊天机器人

以下是本地 Gemma 聊天机器人封装容器类的示例。您可以在“利用 Gemma 构建聊天机器人”中了解更多信息。

我们在演示中使用的是 Gemma 2 2B 模型。但是,如果硬件功能足够强大,则可以选择 9B 或 27B 等替代 Gemma 模型,以取得更好的结果。

# 本地 Gemma
 
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, "")  # 仅提取新的响应
    self.add_to_history_as_model(result)
    return result

如果您在 Vertex AI 上部署了 Gemma,请将 Github 上的示例代码复制和粘贴到您的机器人文件中,然后改用下面的代码。请注意,您无需初始化“self.model”变量,因为它正在 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, "")  # 仅提取新的响应
    self.add_to_history_as_model(result)
    return result

要测试您的机器人,请直接使用以下代码。(假设您将上述代码保存为“gemma.py”)

from gemma import GemmaBot
gemma_bot = GemmaBot(“您是故事讲述者这个偏远岛屿的向导。”)
text = gemma_bot.ask(“您是谁?”)
print (text)

这是机器人的输出示例。

Output 1 - build a text based adventure

制作游戏循环

如果您不熟悉游戏循环,请记住一点,它是提升游戏功能和交互性的核心过程。在整个游戏期间,此过程循环往复,以确保游戏状态得到更新、输入得到处理以及视觉效果得以在屏幕上呈现。

在我们简单的基于文本的冒险游戏中,我们实现了一个基本的游戏循环,如下所示:

import StageIntro
current_stage = StageIntro.StageIntro()
 
def game_loop():
    if current_stage.bot is None:
        # 无机器人的关卡类型
        current_stage.process()
        return
 
    resp = ""
    print("-"*80)
    printf"Type \“{current_stage.cmd_exit}\如果您想结束对话。”)
    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(“逃跑成功?”)
        print(check)
        if check.lower().startswith("true"):
            print恭喜您已逃出岛屿。”)
            exit(0)
 
    next_stage = current_stage.next()
    if next_stage is None:
        print(“游戏结束”)
        exit(0)
 
    return next_stage
 
while True:
    game_loop()
    current_stage = check_end_condition()
    input(“ ENTER 键继续”)

为了简化这个过程,我们设计了一个基础关卡接口类。您可以通过创建新的关卡来扩展此类并确定自己的自定义关卡设置。

例如,您可以使用钢闸门创建新的关卡,如下所示。

from stage import IStage
from gemma import GemmaBot
 
class StageGate(IStage):
    def __init__(self):
        self.preamble =钢闸门在您面前若隐若现这个巨大的障碍将您与前面的路隔开藤蔓沿着锈迹斑斑的酒吧生长空气中有微弱的电流嗡嗡作响\n故事讲述者出现在您身边在斑驳的阳光下闪闪发光。”
        self.intro =您好我是故事讲述者是您在这个岛屿的向导\n我们遇到了一个门您会怎么做?”
        self.bot = GemmaBot(“您是故事讲述者是神秘岛屿上一位友好而乐于助人的 AI 向导您的作用是帮助玩家应对挑战并找到逃离的方法您现在站在一个大型钢闸门前。”)

总结

使用 Gemma,您不仅可以掌握制作基于文本的冒险游戏的方法,还可以将相同的结构应用于制作各种主题的游戏,包括蒸汽朋克和奇幻游戏。

此外,您可以整合自己的核心游戏机制概念,例如基于技能的升级、关系建立甚至是迷你游戏。

请记住,这是一个基本的起点。您会感到自己可以混合、调整和扩展这些元素,以打造真正独特且有吸引力的基于文本的冒险游戏体验。

考虑加入 Google 开发者社区的 Discord 服务器,您将有机会展示您的项目,并与有着相似兴趣的爱好者建立联系。

感谢阅读。