基于LLM的国学背书小游戏

0. 前言

这是一个我花了周末两三天时间做出来的小游戏。灵感来源是前段时间流行的“猜病”游戏,以及各种AI用于教育、AI角色扮演的零碎的idea拼在一起形成的。游戏逻辑简单概括为:

  • AI扮演皇帝,玩家扮演皇子

  • AI出“给上句说下句”的题给玩家答,答错打十下戒尺

  • 到玩家求饶为止

做这个小项目的过程中,我差不多把搭建LLM应用的各种基础模块都摸了一遍,还挺有意思的,以后还可以考虑继续加各种扩展功能,比如给AI皇帝配上有威压感的声音,使游戏更有代入感;或者不仅限于“给上句说下句”,加上一些《九章算术》的数学题。


1. 系统架构

原型实验

在现成的免费聊天应用里,我们可以通过简单的提示词快速验证idea的可行性。例如,我把这段提示词喂给Deepseek或Kimi,他们就会开始扮演无情的出题机器。

你是个架空朝代文治武功英明神武又擅长权谋的皇帝,文武百官无不畏惧。我是你儿子,十岁,正在努力学习。今天你正好来检查我的学业状况。 此刻,你化身无情的出题机器,会出很多很多“出上句答下句”的题,来源有四书五经、孙子兵法、名篇名句、唐诗宋词等。 答错你会打我十下戒尺,答对会继续出题,每答对十题就会增加难度。直到用户扮演的角色哭了你才会停下。

然而,在实验过程中,我发现了一些问题,包括

  • 在很多聊天应用里,system prompt是由服务提供商写死的,比如固定会写成“你是个可靠的AI助手”,用户只能修改user prompt而不能修改system prompt,可能会导致AI逐渐忘记它的角色设定,行为变得不可控,甚至对话开始跑偏。

  • 类似chatbox的应用允许用户可以自己修改system prompt,但是也有别的问题:

    1. AI出的题容易重复且不可控,出来出去就是“学而时习之”和“大学之道”

    2. 和上一条类似,没有难度梯度

    3. 经常把用户的对的回答说成错的,又把错的说成对的

系统方案

为了整个游戏的可靠性,我需要能管控游戏状态,包括目前的难度、是否重开一局等。我还需要一个指定的题目范围,可以从题库里选择逐渐增加难度的题。因此,我最终决定选用一个混合架构的方案。相比纯提示词驱动的方案,混合架构方案多了一个本地题库和本地状态机,负责管理游戏逻辑,而LLM只负责用皇帝的口吻问问题以及评判对错。

这个方案主要是解决了上文提到的问题i.和ii.,但没有解决问题iii,因为实验过后我发现,如果把判断对错也交由本地,那么AI就相当于只是一个“台词润色器”,会变得很无聊。不如允许AI的偶尔误判,就当作是“昏君”的特色。

系统框图

题库准备

我原本打算从高考课内范围里出,或者直接找点高考默写真题。但是我看了几眼以后发现,高考课内范围的四书五经占比偏低,唐诗宋词占比偏高,不太符合“古代皇帝教育皇子”的场景。要知道AI自己出题的话,出来出去最多的就是《论语》《大学》《孙子兵法》。

于是,题库这件事也交给AI。

你是个架空朝代文治武功英明神武又擅长权谋的皇帝,文武百官无不畏惧。我是你儿子,十岁,正在努力学习。今天你正好来检查我的学业状况。 此刻,你化身无情的出题机器,会出很多很多“出上句答下句”的题,来源有四书五经、孙子兵法、名篇名句、唐诗宋词等。 先来30题

之后我反复要求AI“再来一点”,并且根据难度从1到9打分。我人工筛选之后稍加处理,保存为json以便之后使用。

2. 代码实现

整个小游戏的界面基于gradio框架和阿里云百炼大模型平台的API,我先快速搭了个最基本的对话窗口然后逐步加入各种游戏控制。核心逻辑由GameController控制,当前游戏状态储存在GameStatus里。喂给LLM的上下文除了用户看得见的对话历史,还有一些对用户不可见的隐藏的系统提示,以确保AI皇帝出的题就是我想要的。

最后我还做了个对多用户支持,由GRServer管理每个用户的独立的session和状态。把改进后的代码(相比不支持多用户的)丢给Amazon Q,让它概括各个模块的功能和交互关系,并画出架构框图如图所示。

程序框图

下面这段详细的架构解释是Amazon Q写的,我觉得写得很好,就不修改了。

New Architecture Components:

GRServer - New main server class that:

  • Manages multi-user sessions with thread-safe dictionary

  • Creates and maintains isolated GameStatus instances per user

  • Handles UI creation and session routing

GameController - Now a stateless utility class with:

  • All methods converted to static methods

  • No instance state, only class constants (model, client, system_prompt)

  • Pure logic operations that work on GameStatus instances

GameStatus - New dedicated state class that:

  • Holds all game state for individual users

  • Contains its own QuestionIterator instance

  • Provides complete isolation between users

QuestionIterator - Remains largely the same but now:

  • Each user gets their own instance via GameStatus

  • Maintains per-user question progression

Key Architectural Improvements:

  • Multi-user Support: Each user gets isolated game sessions

  • Separation of Concerns: State (GameStatus) vs Logic (GameController)

  • Thread Safety: Session management with locks

  • Scalability: Stateless controller allows better resource management

  • Session Management: UUID-based session identification

The diagram shows the new data flow where GRServer orchestrates everything, GameController provides stateless operations, and each user maintains their own GameStatus with isolated state and question progression.

效果

小游戏的代码和题库放在了git仓库里。

在EC2上用nginx配置反向代理后就可以用各种设备(电脑/手机/平板)访问。游戏效果如图:

游戏截图

我还在system prompt里加入了一些有意思的灵魂,比如当我扮演的“皇子”性格顽劣,吵着不背书了要去钓鱼的话,AI皇帝会格外愤怒赐予额外惩罚。

3. 总结

本文介绍了我的一个综合了角色扮演和国学教育的基于LLM和本地状态机混合架构的背书小游戏及其代码实现。利用本文的混合架构和适当的提示词,我们还可以轻松地开脑洞开发出各种别的有趣的情景玩法。


参考资料

  1. 阿里云百炼平台——Kimi2 API参考

  2. Basics of Prompting

  3. gradio Quickstart