先看一个具体的提问
假设一名玩家在虚构游戏《灰烬回廊》里刚打倒“守门人”,他在搜索框里输入:“守门人打完以后去哪”。这个场景是我们为了讲清问题构造的示例,不对应任何真实产品数据。
在这句话里,明确出现的信息只有两条:一个实体名“守门人”,一个疑问词“去哪”。但要给出正确答案,至少还要知道以下几件事:守门人是三段式Boss,玩家打到了哪一段;击败之后触发的是剧情过场还是直接开放地图;玩家有没有先做过“断桥营地”的支线;背包里有没有钟塔钥匙;当前游戏版本里,守门人之后的路线有没有被调整过。
这些信息一个都不在查询字符串里。传统搜索引擎的假设是“答案由词决定”,而游戏里的现实是“答案由词加上玩家状态决定”。爱游戏AI在设计搜索时把这一点当作出发点:玩家的一句话只是查询的一半,另一半在游戏进度里。
关键词匹配会返回什么
把“守门人打完以后去哪”交给纯关键词检索,大致会得到三类结果。第一类是“守门人打法攻略”,因为“守门人”命中标题的权重最高。第二类是“灰烬回廊地图总览”,因为“去哪”被当成地图类问题。第三类是一篇零散的剧情讨论帖,里面恰好同时出现“守门人”和“之后”。
这三类结果各自“相关”,但没有一个直接回答问题。其中一篇攻略如果写于早期版本,路线可能已经失效,却因为被引用得多而排名靠前。词频和链接热度衡量的是“这篇内容有多受欢迎”,不是“这篇内容对眼前这个玩家有没有用”。
还有一种隐蔽的失败:结果很准,但对错了人。一篇讲“打完守门人后进入钟塔顶层,与灰衣人对话解锁第三区域”的文章,对已经去过钟塔的玩家是重复信息,对还没打到第二阶段的玩家则是严重剧透。文字匹配完全无法分辨这两种情况。
先分清玩家到底在问什么
状态之前,先是意图。“打完以后去哪”看似简单,实际可能落在四种不同的问题上:
- 位置:出口在地图哪个角落,要走哪扇门,这是一个空间事实。
- 流程:接下来的任务链是什么,先交任务还是先去下一张图,这是一段顺序。
- 剧情:守门人为什么守在这里,击败后世界发生了什么变化,这是叙事解释。
- 下一步行动:我现在这个状态,最应该做的一件事是什么,这是一个决策建议。
“去哪”本身经常是位置和下一步行动的混合体。爱游戏AI的做法是把意图理解(Intent Understanding,即判断查询想要的答案类型)做成可以给出多个假设的分类,而不是强行选一个。例如“守门人打完以后去哪”,位置和下一步行动都有较高可能,我们倾向于先给出下一步行动,再附一行位置说明;如果玩家写的是“守门人为什么会守着钟塔”,则明确落在剧情上,检索的对象就换成叙事条目。
区分这几类意图的价值在于,它们对应不同的知识来源和不同的呈现形式。位置问题最好返回带标记的地图片段,流程问题返回有序步骤,剧情问题返回一段克制的叙述,下一步行动返回一个明确的动作加一句理由。关于“查事实”和“规划步骤”这两类问题为什么不能共用一套检索逻辑,可以看事实查询与目标规划在检索上的分工,这里不再展开。
实体消解:守门人是哪一个守门人
意图确定之后是实体。“守门人”在《灰烬回廊》的设定里不是一个固定对象:它有第一阶段的“铁面形态”、第二阶段的“裂甲形态”,还有主线通关后重打的“回响版本”。三者共用一个名字,掉落物、战场位置、击败后的触发事件都不同。
实体消解(Entity Resolution,即把文字里的名称对应到知识库里唯一的条目)如果只看名称,就只能在三个条目之间平均分配概率。爱游戏AI会利用玩家状态给候选实体加权:任务日志显示玩家还没通过第二阶段过场,“回响版本”几乎不可能是他的目标;如果他的存档里已经有“灰衣人的信物”,那他很可能是在问回响版本。
这里要设一个边界:状态只能调整候选的先后,不能悄悄替玩家做决定。当两个候选的置信度接近时,系统应该在答案里明确写出“下面按你正在打第一阶段的情况回答”,而不是装作没有歧义。同名任务、同名地图带来的版本与阶段问题,在同名任务的版本、地图和阶段消解里有更细的判断流程。
把游戏状态逐层加进查询
我们把查询条件分成几层,逐层叠加,看每一层能把答案收窄多少。
- 只有文字:“守门人 打完 去哪”,候选结果是攻略、地图、剧情三类混杂。
- 加入意图:判断为“下一步行动”为主,位置为辅,剧情类结果被降权。
- 加入任务阶段:玩家主线停在“取得钟塔钥匙”之前,于是“钟塔顶层”这类后续内容被识别为超前信息。
- 加入已解锁区域:断桥营地已开启,说明玩家走的是先支线后主线的路径,最近的可去目的地有两个,而不是一个。
- 加入背包:背包里没有钟塔钥匙,因此“去钟塔”这个动作实际上暂时无法完成,答案里必须先说明钥匙的来源。
- 加入版本:确认当前版本里钥匙的获取方式没有调整,避免引用已经过期的路线。
每加一层,检索并不是“多一个过滤条件”那么简单。任务阶段、已解锁区域、背包这些信息本身也是知识图谱里的节点,查询是在图上做“从玩家当前节点出发,看守门人被击败这个事件之后可达的节点”。也就是说,状态不是筛选器,而是搜索的起点。
结果对比:词频排序与状态匹配排序
用同一批候选内容做一个示意性的对比。这是我们设计时使用的推演,不是产品指标。
| 候选内容 | 关键词排序 | 状态匹配排序 | 原因 |
|---|---|---|---|
| 守门人三段打法攻略 | 第1位 | 靠后 | 玩家问的不是怎么打,打法已完成 |
| 灰烬回廊地图总览 | 第2位 | 中间 | 只回答位置,不回答顺序 |
| 击败守门人后的任务链(含钥匙来源) | 第4位 | 第1位 | 与阶段、背包、意图三项都匹配 |
| 钟塔顶层剧情解读 | 第3位 | 隐藏或折叠 | 超前于当前进度,属于剧透 |
| 旧版本路线笔记 | 第5位 | 降权并标注版本 | 版本与玩家当前版本不一致 |
排序信号也因此发生了变化:不再是“词出现得多不多”,而是“这条内容的前提条件,玩家满足了多少”。每一条知识条目在入库时就要带上它的适用前提,比如“需要已完成断桥营地支线”“适用于当前主版本”“包含第三区域剧情”。检索时把玩家状态和这些前提做匹配,匹配度高的排前面,超前的内容单独处理。
防剧透:同一个答案的不同粒度
剧透是游戏搜索里特有的问题,普通搜索几乎不用担心这一点。爱游戏AI的做法不是简单地“过滤掉剧情类内容”,而是把同一个事实存成多个粒度,再根据玩家进度选择。
以“守门人击败后开启什么”为例,可以准备三档描述:最粗的一档只说“会开启新的区域,可以继续主线”;中间一档说“通往钟塔方向,需要一把钥匙”;最细的一档才写出具体的人物对话和结局分支。对刚打完守门人的玩家,默认给中间一档;对已经通关的玩家,才展示最细的一档;对明确写“别剧透”的玩家,只给最粗一档,并说明可以展开。
粒度选择还应该可被玩家覆盖。有人就是想看完整剧情,有人卡关了只想要一个明确路线。搜索结果里可以留一个“展开更多细节”的入口,把选择权交还给玩家,而不是由系统替他决定看多少。
状态未知时怎么办
前面的推演都建立在“系统知道玩家状态”上。现实里经常不是这样:玩家没有关联存档,或者在网页上匿名搜索,或者状态数据不完整。这时候硬猜比不回答更危险,因为一次错误的“下一步”可能让玩家白跑一趟。
我们倾向于三层策略。第一层,看能否从查询文本里提取状态线索,例如玩家写“刚打完第二阶段”“我已经有钥匙了”。第二层,如果线索不足,用一到两个成本最低的问题追问,比如“你现在打的是守门人的第几阶段?”这类选项式问题,玩家点一下就能回答,比让他重新输入一段话要轻。第三层,如果玩家选择不回答,就返回分支式答案:“如果你还没拿到钟塔钥匙,先去断桥营地;如果已经有,直接前往钟塔入口”,并把每个分支的前提写清楚。
追问要克制。每多问一个问题,玩家离开的概率就多一分,因此追问只在“不同状态会导致明显不同答案”时才触发。如果所有状态下的答案都一样,就不该追问。判断标准是:候选答案之间的差异是否会让玩家走错路。
这套设计的取舍与边界
把状态放进搜索,也带来新的成本。首先是状态获取的隐私问题:玩家的任务进度和背包属于个人游戏数据,爱游戏AI的思路是只在玩家主动授权或在爱游戏App内主动关联时使用,并只保留完成检索所需的最小信息,不把状态用于与搜索无关的用途。
其次是知识库的维护成本。每条内容都要标注适用前提,这比直接存一篇文章要费力得多。可行的做法是让大模型辅助抽取前提,再由规则校验与人工抽检把关,而不是全部依赖模型判断。前提抽取一旦出错,比如把“需要钥匙”误标成“不需要”,就会直接产生错误的路线建议,所以这一环需要保留可追溯的来源字段。
最后是意图分类本身会出错。“守门人”后面接“为什么”,多半是剧情;但玩家说“守门人这个设计到底什么意思”,可能是在吐槽难度,而不是问剧情。这类模糊表达,只能靠多假设输出加上让玩家纠正的入口来兜底。
回到开头那句话:一个会返回攻略的搜索框不难做,难的是让它知道眼前这位玩家已经走到了哪里。这套搜索把任务阶段、已解锁区域和背包变成查询的一部分,把意图分成位置、流程、剧情与下一步行动,再按状态匹配度排序、按进度控制剧透,这些环节连起来,才可能让“打完以后去哪”得到一个对这位玩家有用的答案。游戏搜索真正困难的是理解玩家当前处于哪个游戏状态。