用一次虚构的补丁把问题走一遍。假设某款游戏发布了1.4版本,公告里有六条与图谱有关的改动。我们把它整理成一张变更单,看图谱每一处要怎么动。

补丁的变更单

1.4 更新要点(虚构示例)
1. 霜纹短剑:攻击力下调,附加“寒霜”效果改为需要装备套装
2. 守卫宝箱:不再掉落霜纹短剑;新Boss“潮汐守卫”掉落
3. 锈铁长枪:从游戏中移除,已持有的保留但无法再获得
4. 新增任务“断桥修复”,需完成主线第四章,起点为新NPC
5. 地图“灰烬回廊”第三层更名为“灰烬回廊·深处”
6. 铜钥匙配方:材料由三个改为两个

这六条改动,恰好对应图谱需要处理的六种不同的时间问题。如果只是简单地“把图更新到最新”,会在其中至少两处埋下隐患。

属性变了:实体要有版本

第1条是最常见的一种。霜纹短剑还是那把剑,但它在1.3和1.4里的属性不同。如果直接覆盖属性,1.3的玩家就查不到自己手里的数值了;如果新建一个全新实体,那些指向“霜纹短剑”的攻略、推荐和收藏就都断了。

实体版本化(Entity Versioning)的做法是:保留一个稳定的实体标识,再给它挂多个带版本范围的属性快照。查询时带着版本条件,取范围内的那一份。这样“同一个东西”和“它在不同时期长什么样”被分开表达。

关系变了:边要有有效期

第2条改的是关系而不是实体:守卫宝箱和霜纹短剑之间的“掉落”边不再成立。时序知识图谱(Temporal Knowledge Graph)的核心就是给边加上生效与失效的版本区间。旧边不删除,只把结束版本写成1.4;新边“潮汐守卫—掉落—霜纹短剑”从1.4开始生效。

这一步之所以重要,是因为目标导向的路径规划会在这些边上走。规划器如果不检查边的有效期,就会规划出“先去打守卫宝箱”这种已经不存在的路线。所以在爱游戏AI的查询层里,版本条件是默认注入的,而不是由调用方自己记得加。

实体退役:状态而不是删除

第3条是退役。锈铁长枪不能再获得,但依然有玩家拿着它,也有大量旧攻略提到它。图谱里的处理是给实体增加“生命周期”状态:可获得、仅存量、已移除,并记录状态变化的版本。搜索时,退役实体默认不出现在“怎么获得”的答案里,但被直接搜索时能返回,并明确写“1.4起不可获得”。

新增与更名:别名和增量

第4条新增任务,要连同它的前置边(主线第四章)、起点NPC和奖励一起入图。这里有一个常见的疏漏:只增加了任务节点,忘了增加前置边,结果任务能被搜到,依赖推理却把它当作“无前置、随时可做”。所以我们把“新增实体必须附带哪些必选关系”写成入图时的检查规则。

第5条是更名。旧名称不能丢,要挂成别名并注明使用范围,否则搜“灰烬回廊第三层”的玩家会得不到结果。第6条则是数量变化,属于边属性的版本化,处理方式与第1条类似。

增量更新之后:回归校验

补丁的改动不是孤立的。改了铜钥匙配方,会影响所有依赖铜钥匙的任务链;移除一把武器,会让推荐中提到它的组合失效。所以更新完成后必须做回归校验,我们倾向于准备一组固定的“检查查询”:

  • 被改动实体的一跳、二跳邻居,是否出现了没有有效边的孤立节点。
  • 每一个任务的前置链,是否都能追溯到游戏起点,有没有断链或环。
  • 每一件“可获得”的装备,是否至少有一条有效的获取路径。
  • 一批历史上被玩家频繁搜索的问题,更新前后的答案差异是否与变更单一致。

最后一项尤其有用:答案变了,应当能对应到变更单里的某一条;如果答案变了却找不到对应的补丁说明,就说明图谱里有了没有来源的改动,需要人工复核。

历史查询:“旧版本怎么打”

有效期设计带来一个副产品,就是可以回答历史问题。玩家问“1.3的守卫宝箱怎么拿霜纹短剑”,查询层把版本条件设为1.3,得到的就是旧边和旧属性组成的答案。没有指定版本时,默认使用玩家所选游戏的当前版本,而不是图谱里最新的版本,这一点在同名任务需要先判断版本和阶段时同样适用。

展示层:让玩家看到“这是哪个版本的答案”

图谱内部管好了时间,前台也要把时间说出来。爱游戏AI在答案里固定带一行版本说明,例如“按1.4版本回答”;如果玩家所选版本和答案适用版本不一致,会用一句话提示差异,并给出切换入口。玩家不需要理解有效期区间,只需要知道这份答案是否适用于自己,以及旧版本的内容在哪里。

冲突与来源可信度

补丁并不总有完整公告。玩家社区的实测、数据整理、旧攻略之间会互相矛盾:有人说宝箱不再掉落,有人说概率变低了。爱游戏的做法是给每条入图的事实记录来源类型,并按可信度排序:官方更新说明优先,其次是可复核的实测记录,最后才是未经验证的转述。冲突无法解决时,图谱同时保留两条,标记“存在争议”,前台答案里明确写出依据和不确定之处,而不是悄悄选一个。

还有一条底线:没有来源、没有版本标记的边,不参与规划层的路径求解。它可以出现在展示里,但要标注“未验证”,因为一条过期的边,代价往往是玩家白跑一趟。