规则校验模块(RuleEngineService)接口设计
前面的文章已经分析过规则校验模块的作用这里简单回顾一下。在小说情节驱动的角色扮演平台中AI角色会对玩家的行为做出反应但AI的“自由发挥”必须在一定的规则框架内进行。规则校验模块正是这个框架的执行者。设想这样一个场景玩家操控的角色试图在霍格沃茨大厅对邓布利多使用阿瓦达索命咒但这可能违反①世界观规则不可饶恕咒被魔法部禁止②游戏平衡规则秒杀关键NPC。规则校验模块需要拦截这类不合规的行为并给出相应反馈。总体来说规则校验模块位于行为理解与状态更新之间上游接收来自行为理解层的结构化行为已理解“做什么”下游输出校验后的可执行行为判断“能不能做”。一、设计原则我们看一下基本的设计原则。首先判断某个行为是否可以在当前世界中发生并不是单一的是/否而是一个多阶段的校验流程至少包含以下几个步骤行为输入 → Schema校验 → 实体绑定 → 通用规则 → 配置规则 → 冲突裁决 → 状态执行下文将详细解释主要步骤的含义这里我们简单看一下Schema校验、通用规则校验、配置规则校验在职责上有什么区别层次职责依据Schema校验检查数据结构是否完整、类型是否正确预定义的JSON Schema通用规则校验检查是否违反所有游戏通用的基本规则硬编码的通用逻辑配置规则校验检查是否违反具体小说/场景的特定规则可配置的规则库这种分层使得每个阶段有明确的输入输出和失败处理策略任何一个阶段失败都可以快速返回明确的拒绝原因。同时我们可以利用这种结构对通用规则进行复用并灵活配置特定规则。另一个重要问题是需要保证校验与执行的原子性即规则校验和状态更新必须在一个事务边界内完成。这意味着校验通过后才能开始状态修改如果状态修改过程中出现异常将回滚整个操作避免出现“校验通过但执行失败”导致的不一致状态。二、核心接口设计原则确立之后我们开始核心接口的定义。1.主入口接口主入口executeStructuredAction是系统其他模块调用规则校验的接口其包含了行为的完整校验流程对外屏蔽了内部校验、绑定、执行的各个步骤。换句话说调用者只需调用该函数即可完成规则校验。publicinterfaceRuleEngineService{RuleExecutionResultexecuteStructuredAction(LongsessionId,StructuredActionDTOaction);}我们将完整流程封装成一个接口而非拆分多个独立接口是为了保证原子性。如果调用方需要分别调用validate → bind → execute很容易出现“校验通过后执行前状态被其他操作改变”的竞态条件。另外封装设计使得调用者无需关注规则校验模块的内部实现逻辑便于操作。接下来要介绍的几个接口对应校验的具体步骤其均被主入口调用不暴露给外界。2.Schema校验接口这是整个规则校验流程的第一个步骤也是最轻量级的校验。该函数的作用是检查行为的格式是否正确接口名称如下voidvalidateSchema(StructuredActionDTOaction);我们知道AI解析模块输出的结构化行为可能存在格式问题例如字段缺失如action_type为空、类型错误如target应该是字符串却传了数组、枚举值非法如action_type的值不在预定义的枚举列表中等。这类问题应该在进入业务逻辑前快速过滤避免后续的实体绑定和规则校验处理脏数据。3.实体绑定接口AI解析输出的行为中角色名、物品名通常是字符串形式如“哈利”、“魔杖”我们需要将其绑定到某个特定的人物或物品更准确地说是人物或物品ID。规则校验和状态更新需要基于内部ID进行而实体绑定层就负责这个映射。BoundActionDTObindEntities(LongsessionId,StructuredActionDTOaction);这里需要处理几种情况精确匹配名称完全一致别名匹配用户输入“那位大难不死的男孩”应该映射到“哈利”模糊匹配输入“赫”可能指代“赫敏”或“赫奇帕奇”需要上下文消歧后续实现中绑定结果可能包含匹配的可信度低可信度的绑定会触发额外的确认流程。具体策略需进一步考虑。4.规则校验接口这两个函数分别对应上文提到的通用规则校验和配置规则校验。voidvalidateGenericRules(LongsessionId,BoundActionDTOaction);voidvalidateConfiguredRules(LongsessionId,BoundActionDTOaction);两者的区别在于通用规则被所有游戏共享例如死亡角色不能行动、行动力不足不能执行动作。这类规则变化极少硬编码效率最高。而配置规则从数据库动态加载不同小说可以有完全不同的规则集。例如《哈利波特》有“攻击性魔法需要魔杖”的规则《冰与火之歌》有“守夜人不得娶妻”的规则等。这种分离既保证了性能又提供了灵活性。5.状态应用接口该接口的作用是最终执行动作改变世界状态。voidapplyActionResult(LongsessionId,BoundActionDTOaction);下面我们看一下各动作的处理顺序。首先应当进行Schema校验这是考虑到如果格式本身有问题将无需进行绑定和校验应该尽早拒绝。其次是实体绑定有了绑定的ID后续规则校验才能查询具体的状态。接下来是两种规则的校验由于通用规则成本低、执行快可以快速过滤明显不合规的行为因此我们将通用规则先于配置规则执行。通过了所有校验之后就可以应用并修改状态。以上是校验成功的情况。如果校验失败系统将返回拒绝动作执行的信息不产生状态变更。三、与其他模块的协作下面我们看一下规则校验模块与系统其他模块的关系主要是与行为理解层的联系与区别。为便于理解我们再次展示一下系统整体框架图从上图可以看出行为理解层ActionParser负责接收用户或AI角色传来的自由文本信息并将其转化为结构化表述。规则校验模块传入结构化的行为描述后进行语义校验判断该动作能否执行。而行为理解层输出的结构化表述具有以下形式{actor:哈利,action_type:speak,target:赫敏,content:我们必须现在出发。,parameters:{tone:urgent},raw_text:哈利皱着眉说我们必须现在出发。}因此规则校验模块将接受这种形式的动作描述作为输入。同时规则模块与世界信息层亦有联系从上面的系统架构图可以看出两者的交互主要在于对世界状态的查询和更新。四、总结与后续规划在本模块的设计中我们采用Schema → 通用规则 → 配置规则的分层校验模式各层职责明确同时能够确保校验与执行的原子化维护状态一致性。接下来我将开发各接口的具体实现从而完成该模块的完整功能。