---
title: "借助开源大语言模型，无需联网在本机实现和游戏 NPC 自由对话 [译]"
url: "https://paooo.com/ai-study/7155/"
author: "宝玉的分享"
published_at: "2024-03-24T12:17:30+08:00"
updated_at: "2024-03-24T12:17:30+08:00"
categories: "强化 AI 学习"
tags: "AI音频与语音, Claude, Llama, OpenAI"
source: "Prompt 语宙 (https://paooo.com)"
ai_tools_directory: "语宙 AI 导航 (https://ai.paooo.com)"
---

# 借助开源大语言模型，无需联网在本机实现和游戏 NPC 自由对话 [译]

> 来源：[Prompt 语宙 (paooo.com)](https://paooo.com/ai-study/7155/) · 作者：宝玉的分享 · 发布时间：2024-03-24

## AI 30 秒核心看点 (TL;DR)

- 用 llama.cpp 和 Mistral7B 在本机离线生成 NPC 对话，避免联网延迟与云端成本。
- 结合 StyleTTS2 语音合成与 Unreal Engine 5，可实现逐句输出、边说边生成的交互流程。
- 实测帧率影响不大，但模型会跑题、出错，适合概念验证，正式落地仍需 RAG 与微调。

#### 
引言

关于 GPT4、Claude 等模型，有很多相关讨论，它们非常出色，我也经常使用，但在某些情况下可能不是最佳选择。比如，在制作游戏时，如果你希望游戏中的 NPC 能够与玩家进行动态对话，通过服务器来回传递信息可能会有显著的延迟，这不仅降低游戏体验，还可能因为依赖于 OpenAI 或其他公司的服务器而带来风险（比如服务器故障导致游戏无法进行）。此外，这些模型的使用成本可能会随着玩家数量的增加而变得高昂，对于成本较低或玩家游玩次数过多的游戏来说，这并不经济。为了节约成本，你可能会尽量减少游戏中基于大语言模型的内容，因为你需要为每个 Token 支付费用，很快费用就上去了。

#### 
我使用的工具

我在制作中使用了 llama.cpp 和 Mistral7b 来生成对话，并用 StyleTTS2 来产生配音，同时利用 Unreal Engine 5 进行渲染。我原本尝试将 llama.cpp 作为 DLL 文件集成到 Unreal 中，但最终遇到了难题。因此，我采取了一个临时的解决方案，使用了 Node 脚本。我利用了 mrfakename's 提供的 StyleTTS2 演示 Docker 镜像 来生成语音，通过 Gradio API 接口包进行交互。理想情况下我不想使用 Docker 镜像，但由于无法在我电脑上直接运行 StyleTTS2 模型，只能采取这种方法。

我在家用的 PC 上进行这些操作，配置如下：

- HDD: Samsung 980 PRO M.2 1TB

- CPU: Intel Core i5 12600KF

- Memory: 64GB DDR5

- GPU: GeForce RTX 4070 12GB

#### 
如何工作

这个 Node（节点）脚本是通过 Unreal 引擎中的 FInteractiveProcess（交互式处理）类来启动的。它把先前的对话历史作为命令行参数传递给脚本，然后脚本逐句输出 NPC 的对话。为了提高效率，我们选择逐行处理——而不是等待整个对话生成完成。这样，我们就可以在 NPC 正在说当前句子时，就生成并播放下一句。输出的内容是一个 JSON（JavaScript 对象表示法）对象，其中包含字幕文本和对应该句的音频文件位置，之后 Unreal 会将其解析为结构体并进行播放。

#### 
性能

性能方面出乎意料地好。在生成新对话行时会稍微有点卡顿，但影响不大。StyleTTS2（文本转语音系统）需要占用约 14GB 的 RAM，而基于 llama.cpp 运行的服务器占用 3GB，因此运行这一系统需要较大的 RAM 容量。不过我相信 StyleTTS 还有进一步优化的空间。从视频中可以看出，对帧率影响不大，游戏画面依然能够保持流畅的 60 帧每秒。

生成一句新对话的时间大约为 2-3 秒，我认为这已经相当不错了。可能可以通过播放某种动画来弥补生成对话时的等待时间，使其显得不那么突兀。如果搭配使用 Whisper 技术，可以在生成回应的同时，延迟显示玩家语音转录的文字，这是人们在使用类似 Siri 这样的语音助手时已经习惯的体验。

#### 
缺点

尽管 Mistral 模型的处理速度更快，但主要缺陷在于其一致性不如 GPT3.5。它容易偏离主题，并且不太能坚持事实。例如，在我的一次测试中，它指引玩家前往几英里外的一个村庄，但实际上玩家已经在那个村庄里了。还有，在视频中可以看到，它提到了玩家名为 John，但这个名字并未在对话中提及；它还提到了 Angers 这个地名，但这个名字直到几百年后才会被使用。

此外，Mistral 在判断游戏世界中哪些事情可能发生哪些不可能方面也不是很准确。比如，在演示中出现的关于训练村民的任务，在游戏中实际上是无法实现的，因为游戏中根本没有相关机制。我认为可以通过一种叫做“检索式增强生成”（Retrieval-Augmented Generation，RAG）的方法来解决这个问题（详见结论部分）。

StyleTTS2 的语音合成效果也不够自然，还带有些许机械感。对于它不熟悉的词汇，它的发音不太准确，或者会根据上下文错误地发音（例如，Angers 这个城市的发音与动词“to anger”发音不同）。

#### 
未来改进

这只是一个初步的概念验证，如果真要在游戏中应用，还有许多方面可以进行改进。

- 我首先会尝试让 llama.cpp 作为动态链接库（DLL）在 Unreal 中运行。这样可以避免使用 Node 脚本，从而使分发过程更为简便。

- Mistral 有时候会话题跑偏，因此最好对其进行微调（fine-tune），使其更符合游戏环境。例如，通过提示语似乎无法完全避免它产生时代错误，当你的 12 世纪 NPC 能够解释如何使用 AWS 的时候，玩家会感觉很突兀。

- 同样可以微调它，在文本输出中添加情感标记。通过使用 StyleTTS2，你可以传递语音克隆（voice cloning）片段，因此让配音演员（VA）用不同情感读出示例语句，就可以根据这个特定示例来调用。目前我只有一个语音克隆示例，但在完整的游戏中，你会希望为每个 NPC 的每种情感都有一套完整的示例。

- 我还会尝试找到一种方法，让 StyleTTS2 更紧密地与 Unreal 结合。我不确定如何实现，但如果能不依赖特定的 Python 版本和特定的 Python 包，那会非常理想。

- StyleTTS2 还可能需要微调，让它在对话中更像一个人，而不是像在叙述一本书。它也倾向于听起来过于美式。此外，它一次处理一行文本的方式使得朗读显得有些断断续续，可以通过一次性读完整个内容来解决，但这样会在朗读大量信息时耗时较长。

- 集成 Whisper 会是一个不错的选择——与 NPC 对话并得到回答会感觉更自然，尽管我认为出于几个原因（如避免让感到尴尬的人或打扰家人、室友），保留一个额外的文本字段是必要的。Whisper.cpp 也运行效率很高，在 LLM/StyleTTS 之前 运行不会对游戏性能产生额外影响。

- 我还打算探索一种方法，让玩家在 NPC 讲话时可以打断它，并且让 NPC 对此做出反应。我认为这将是一个很酷的功能，能让 NPC 显得更加生动。

在演示方面，有许多其他的相关方面也可以带来改善，尽管这些并不是我们的重点。比如，NPC 在说话时嘴巴不动，这一点明显是不理想的。我们可以采用像 audio2face 这样的技术来解决，而且我认为这对性能的影响应该不大。此外，我们还可以让大语言模型 (LLM) 控制 NPC 的肢体语言，比如通过返回一个包含动画指令的 JSON 文件来实现。

#### 
结论

从长远来看，我想创建一个数据库，每当玩家开始对话时就进行更新。这个数据库会包含玩家、NPC（包括他们的背景和目标）、世界等方面的信息，以确保整个游戏环境的一致性。你可以创建一个详尽的文档，其中包括玩家完成的所有任务（只要是这个 NPC 知道的）、玩家身上的装备、当前的天气、NPC 与其他 NPC 的互动、他们与玩家的聊天记录（包括日期、时间等，以便推断玩家所提及的是过去的事情）等等，然后在提交给大语言模型之前，先进行自然语言查询。

当然，最理想的情况是手动设计任务。目前我们还没有达到让大语言模型自主设计整个任务系列的水平——如果那样做，可能会出现类似于《上古卷轴》系列中“辐射任务”的情况，那种任务通常只是简单的“去某地做某事”。玩家对此并不感兴趣，我认为主要是因为这些任务缺乏人性化的设计。

主要的挑战在于对大语言模型进行适当的训练，让它保持主题不偏离，并拒绝执行它无法完成的任务。可以给它设定一系列允许的功能（比如给予物品、拿走物品、开启任务等），并让它拒绝执行其他操作。

所有这些改进都是为了在完整游戏中实现这一效果所必需的。但本文的要点是展示了在本地完整运行一个 NPC 是可行的，而且实现起来并不困难。我对这一成果感到非常满意，并期待看到更多人的尝试和创新。

相关源码：https://github.com/joe-gibbs/local-llms-ue5

## 常见问题解答 (FAQ)

### 本地离线实现游戏 NPC 对话需要哪些工具？
文章中使用了 llama.cpp 和 Mistral7B 生成对话，StyleTTS2 负责语音合成，Unreal Engine 5 负责渲染与交互；脚本通过 Unreal 的 FInteractiveProcess 启动，并以 JSON 形式把字幕和音频路径传回引擎。

### 这种方案的性能表现怎么样？
实测在生成新对话行时会有轻微卡顿，但整体影响不大，游戏仍能保持接近 60 帧每秒。单句生成时间约 2-3 秒，不过 StyleTTS2 约占 14GB 内存，llama.cpp 服务器约占 3GB，对 RAM 要求较高。

### 为什么还需要 RAG 或微调？
因为 Mistral 在一致性和事实性上不如 GPT3.5，容易跑题、编造信息或出现时代错误。作者认为可通过 RAG 约束世界观与任务信息，再结合微调提升 NPC 的语气、情感标记和游戏适配度。

---
探索 2,800+ 全球实用 AI 工具与官方直达入口：[语宙 AI 导航 (https://ai.paooo.com/)](https://ai.paooo.com/)
