几行代码,将AI NPC集成到Unity

在本文中,我们将展示如何在 Unity 引擎中使用大型语言模型 (LLM) 🎮。我们将使用 LLMUnity(https://github.com/undreamai/LLMUnity) 包,并查看一些使用仅几行代码即可设置对话交互的示例!

免责声明:本文来自 LLMUnity 的作者。如果您有任何意见/建议,请通过打开一个 GitHub issue(https://github.com/undreamai/LLMUnity/issues) 🤗 与作者联系!

为什么在游戏中使用 LLM?

目前,几乎所有 PC 游戏交互都基于多项选择对话。这是一种非常原始的交互类型,自 PC 游戏的早期时代就已建立。游戏中的 LLM 可以构建更身临其境的体验,因为它们可以允许与 PC 游戏元素或角色 (NPC) 进行智能交互。*

以 Skyrim 为例,Skyrim 是最成功的 RPG 之一。当你第一次遇到 Lydia 时,Lydia 是你可能在游戏中大部分时间都作为同伴一起度过的 NPC,你只有三个可能的对话选项。如果你想了解更多关于她的信息或讨论其他事情怎么办?

与 Lydia 的互动,Lydia 是 Skyrim 中的 NPC。屏幕截图来自游戏

这就是 LLM 发光发热的地方。你可以描述 AI 的角色以及他们对世界的了解(你已经拥有了这些信息作为游戏叙事的一部分),它们可以提升对话。

基于对话的与 Lydia 交互示例

ChatGPT 怎么样?

大多数访问此页面的人都会熟悉 OpenAI 发布的 ChatGPT,并且会见证与 LLM 的交互是多么自然和强大。那么为什么不在游戏中直接使用 ChatGPT 呢?

  • ChatGPT 的大规模使用成本💸。每次交互的成本都很低,但当大规模进行时,对于成千上万的用户,每次交互数千次,成本就不容忽视。
  • 它会造成依赖🔗。如果由于任何原因 ChatGPT 停止工作,或者价格上涨,开发人员无力承担,游戏就会崩溃。
  • 开源 LLM 具有与 ChatGPT 相当的准确性🏎️。我还没有找到标准化的基准来证明这一点,但 Meta(Llama)和 Mistral 发布的模型在质量上似乎与 ChatGPT 具有相似的准确性。
  • LLM 的尺寸越来越小🤏。最近的 Mistral 7B 击败了 Llama2 13B,并在许多基准测试中优于 Llama 34B。量化方法进一步推动了这一限制,将模型大小缩小到一定程度,使其可以在任何最新的 PC 和 GPU 上使用。使用 Q4_K_M 方法量化的 Mistral 7B (模型(https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.2-GGUF),量化(https://github.com/ggerganov/llama.cpp/pull/1684)) 运行最多需要 7GB RAM!

欢迎使用 LLMUnity!

LLMUnity(https://github.com/undreamai/LLMUnity) 是一个允许在 Unity 引擎中运行和分发 LLM 模型的包。

它建立在很棒的 llama.cpp(https://github.com/ggerganov/llama.cpp) 库之上,该库允许在没有外部软件依赖的情况下使用 LLM,以及 llamafile(https://github.com/Mozilla-Ocho/llamafile),它以跨平台方式部署 llama.cpp。

LLMUnity 提供以下功能:

  • 💻 跨平台!支持 Windows、Linux 和 macOS
  • 🏠 在没有互联网访问的情况下本地运行,但也支持远程服务器
  • ⚡ CPU 和 GPU 上的快速推理
  • 🤗 支持主要 LLM 模型
  • 🔧 易于设置,只需一行代码即可调用
  • 💰 个人和商业用途免费使用

工作原理

LLMUnity 在后台使用 llama.cpp 服务器。服务器接收 POST 请求,在 LLM 上运行推理并返回回复。服务器由 llamafile 编译成可执行文件,并且可以基于 cosmopolitan 库在不同的操作系统(Windows、Linux、MacOS)上使用。
LLMUnity 实现了一个客户端,该客户端发送 POST 请求并将结果传递给你的 Unity 应用程序。

如何设置

LLMUnity 包可以使用 GitHub URL 作为自定义包安装,也可以作为 Unity 资产安装(待资产商店批准)。说明提供 这里(https://github.com/undreamai/LLMUnity?tab=readme-ov-file#setup) 🛠️。

开发人员可以创建一个 LLM 或 LLMClient 对象来使用 LLM 功能。LLMClient 类仅处理客户端功能,而 LLM 类继承 LLMClient 类,并额外处理服务器功能。

然后,开发人员可以指定 LLMClient / LLM 属性:

  • prompt. 这指定了 AI 的角色。
  • 玩家/AI 名称 (可选)。可以为角色定义玩家和 AI 名称。
  • 流功能 (可选). 流功能允许 Unity 应用程序在模型实时生成输出时接收输出。如果禁用,Unity 应用程序将在模型完全生成回复时接收回复。
  • 其他模型选项 (可选)。有一些 更多模型选项(https://github.com/undreamai/LLMUnity?tab=readme-ov-file#hugs-model-settings) 可以由专家用户直接指定,这些选项由 llama.cpp 服务器使用。

以及 LLM 仅有的属性:

  • model. 这指定了要使用的 LLM。Mistral 7B Instruct v0.2 模型 由 TheBloke 量化 可以直接在 Unity Inspector 中下载为默认模型。否则,可以加载 llama.cpp 支持的任何 LLM。llama.cpp 使用 gguf 格式,并提供 转换脚本 用于 HuggingFace 模型。如果你想避免安装 llama.cpp 并自己进行转换,可以使用 TheBloke 已经转换好的模型 💣。
  • 运行资源 (可选)。你可以指定用户应用程序可以使用多少个 CPU 线程,以及 GPU 将运行多少个模型层。如果用户不支持 GPU,则将使用 CPU。

除非你想亲自动手,否则你可以简单地按下“下载模型”并定义提示 😌!

可以在 LLM 脚本中参数化的不同选项

如何使用

现在让我们进入有趣的部分 🎢!

LLMUnity 的编写使得它可以使用最少的代码。你所要做的就是构造一个 LLM 对象,然后使用以下方法与它进行交互:

_ = llm.Chat(message, HandleReply, ReplyCompleted);

其中:

  • message: 一个包含用户输入的字符串对象
  • HandleReply : 一个以字符串类型接收模型回复的方法。在此函数中,你指定如何处理回复。如果启用了流功能(默认行为),此函数将接收实时回复(在模型生成回复时),否则它将接收整个回复(一次)。
  • ReplyCompleted (可选):没有参数的方法。当模型完成回复生成时,将调用此函数。

基本功能

下面展示了一个最小示例🚂。在这里,我们发送一条消息“Hello bot!”,并在控制台中显示模型的回复:

using UnityEngine;
using LLMUnity;

public class MyGame : MonoBehaviour{
  public LLM llm;

  void HandleReply(string reply){
    Debug.Log(reply);
  }

  void Start(){
    _ = llm.Chat("Hello bot!", HandleReply);
  }
}

调用 LLM  Chat 函数,并在模型完成回复时(以流式或非流式方式)异步接收回复,由 HandleReply 函数接收。

然后,你需要在 Unity 中创建一个应用程序,其中包含:

  • 一个用于 LLM 脚本的 GameObject。LLM 对象的属性在 Unity Inspector 中公开,可以按照上一节中的描述进行设置。

  • 一个用于你的 MyGame 脚本的 GameObject。在这里,你将在 Unity Inspector 中的 llm 属性中链接上面创建的 LLM GameObject。

然后… 就这样 ✨!

简单交互

现在让我们看一个演示基本交互的示例:

简单交互示例

这里我们有一个场景,其中包含:

  • 一个用于 LLM 脚本的 GameObject(如前所述)
  • 一个用于 SimpleInteraction 脚本的 GameObject
  • 一个 InputField(绿色),允许用户输入文本
  • 一个 Text 字段(蓝色),接收来自模型的回复

SimpleInteraction 脚本可以按如下方式实现:

using UnityEngine;
using LLMUnity;
using UnityEngine.UI;

public class SimpleInteraction : MonoBehaviour
{
    public LLM llm;
    public InputField playerText;
    public Text AIText;

    void Start()
    {
        playerText.onSubmit.AddListener(onInputFieldSubmit);
        playerText.Select();
    }

    void onInputFieldSubmit(string message)
    {
        playerText.interactable = false;
        AIText.text = "...";
        _ = llm.Chat(message, SetAIText, AIReplyComplete);
    }

    public void SetAIText(string text)
    {
       AIText.text = text;
    }

    public void AIReplyComplete()
    {
        playerText.interactable = true;
        playerText.Select();
        playerText.text = "";
    }
}

该脚本定义了以下函数:

  • Start: 当场景启动时,playerText 输入字段被选中,以便用户可以输入文本。一个监听器附加到 playerText,当文本提交时,它会调用 onInputFieldSubmit 函数。
  • onInputFieldSubmit : 当用户提交输入时,playerText 会被禁用,直到模型回复。模型输出字段 AIText 被清空,然后调用 LLM chat 函数。
  • SetAIText : 当模型生成一些回复时,会调用此函数,并将 AIText 文本设置为回复内容。
  • AIReplyComplete : 当模型完成回复时,会调用此函数。playerText 再次被启用并清空,以便用户可以输入下一个输入。

就这么简单,我们就可以拥有完整的 LLM 交互(完整的,而不是漂亮的,我知道 🙃)。你可以在 SimpleInteraction 示例(https://github.com/undreamai/LLMUnity/tree/main/Samples~/SimpleInteraction) 中找到这个示例。

多个 AI 功能

到目前为止,我们已经看到了与单个 AI 的交互。在实践中,我们将在游戏中拥有不止一个 NPC 🤖。解决这个问题的方法是创建一个 LLM 对象(如上所述),它处理服务器,但拥有额外的 LLMClient 对象,使用不同的提示为 AI 定义额外的行为。

一个展示此功能的示例可以在 ServerClient 示例(https://github.com/undreamai/LLMUnity/tree/main/Samples~/ServerClient) 中找到。这是上面代码的扩展,它使用一个 LLM 对象用于第一个 AI,并使用一个 LLMClient 对象(使用与第一个 AI 相同的服务器)用于第二个 AI(使用不同的提示)。

多个 AI 功能

聊天机器人

创建更像游戏的最终步骤是增强 UI 方面,因为你希望在你的游戏中拥有它们 🏰。我在这里不会详细介绍,因为它超出了 LLM 集成的范围。如果你对更复杂的 UI 感兴趣,你可以查看 ChatBot 示例(https://github.com/undreamai/LLMUnity/tree/main/Samples~/ChatBot),它创建了更令人愉快的交互,类似于消息应用程序。

消息应用程序风格的交互

结束语

就是这样!在本指南中,我们已经了解了如何使用 LLMUnity 包将 LLM 集成到 Unity 中,以及一些实际示例。我希望你发现它有用!请随时向我发送你可能有的任何问题/评论/建议,以改进本文或 LLMUnity 包 🙏。

原文:https://mp.weixin.qq.com/s/25CpLqXbsS0HmMMTpKDMzg