☰
游戏Agent实践:从LLM规划到评估体系的9月工程复盘
2026/10/13 11:29:50 网站建设 项目流程

9月这段时间,游戏Agent方向算是我们团队今年投入最密集的一个月。月初我们还在为"Agent能不能在一个复杂环境里稳定完成三步以上的任务"争论,月底的时候,内部的沙盒环境里已经能跑出一套可复现的评测数据了。这篇文章想把9月这个阶段的关键进展拆开来讲——不是宣传某个成果,而是记录哪些方案被验证了,哪些想法被否掉了,以及中间踩过的坑。如果你也在做类似的游戏Agent、游戏AI测试或者自主决策相关的事情,这篇应该对你有用。

1. 为什么9月又把游戏Agent翻出来做

1.1 之前卡住的地方,其实一直没有变

我们团队去年就尝试过做游戏里的自主Agent,当时的方案很朴素:让一个模型直接读游戏状态,然后输出动作。结果可以用"惨烈"来形容。当时试了一个很简单的场景——让Agent在一个封闭房间里,完成"找到钥匙、开门、走到目标点"这个流程。规则脚本几十行就能解决的问题,AI在半小时内反复卡在同一个位置:它知道要去开锁,但始终在锁旁边的墙上来回移动。原因是那个版本的模型对"动作空间"的理解太粗糙,输出动作的范围太大,而且游戏环境的反馈延迟很高。每一帧都要等几百毫秒,Agent等不及反馈就已经输出了下一个动作,整个行为序列完全乱掉。

这里面有一个核心问题我当时没有想清楚:游戏Agent不是一个"模型问题",而是一个"系统问题"。模型只是整个链路里的一环,前端的感知、中端的规划、后端的执行校验、旁路的记忆管理,任何一环出问题都会让Agent表现得像傻子。这个认知兜兜转转,一直到9月我们才真正按系统的方式去搭。

1.2 9月的三个外部条件,让重试变得值得

这次重启不是拍脑袋。9月我们重新评估了三件事,发现条件确实变了,所以才决定再投入一次。

第一个是开放权重模型的推理能力提升。放到前年,让一个小规模模型做"如果门锁着,应该先去拿钥匙,而不是撞门"这种常识推理,输出往往不稳定。现在的模型,这种程度的规划已经相当稳定了,甚至能主动说出"钥匙通常在另一个房间,我需要先探索"这种比我们预期更合理的推断。

第二个是视觉接口的成熟。之前让Agent"看屏幕"需要接一大堆单独的检测模型,还要手工处理坐标映射。9月这个时间点,用多模态模型的视觉抽象能力,配合轻量级的本地OCR和检测模块,已经能在一个合理成本内让Agent获得稳定的视觉输入,不再需要依赖严格的动作枚举接口。

第三个是评估工具链的进步。我们上个月花了不少时间搭了一套带录屏回放、动作序列日志和状态快照的评测环境。有了这套环境,才能快速判断改动到底是"变好了"还是"又坏了"。这是前面几次尝试里完全没有的东西——在没有评测的情况下调Agent,就像闭着眼睛调参。

1.3 9月给自己定的目标:不做通用Agent

项目组对这次的目标做了明确收敛:不做那种"什么游戏都能玩"的通用Agent,只做一个能在自家沙盒环境里,稳定完成复合任务(寻物、解谜、移动、交互)的垂直Agent。范围收缩之后,很多之前纠结的问题就变得具体了。比如"语义理解"我们不追求太深,只要它能分清楚任务描述里的位置词、物品词和动作词就行;"探索策略"也不需要太通用,只要在固定地图上能高效搜索就够了。

9月整个月的推进都围绕这个目标展开。到月底,相关的方案测试、数据采集流程和评测逻辑基本定型,这也就是这篇要记录的重点。

2. 把决策层从规则脚本换成LLM,我们花了三周

2.1 第一周:纯提示词方案,结果一跑就崩

第一周的思路非常直接:既然模型已经很聪明了,那就把所有游戏信息放在提示词里,让它输出JSON格式的动作序列。我们给了模型一套动作接口,比如move_to(x, y)、interact(target)、pick_up(item),然后告诉它当前任务是什么,让它自己规划。

跑下来发现两个致命问题。一是输出不稳定。同一个场景跑十次,有三次给出的动作序列是合理且有顺序的,另外七次会出各种意外:让Agent在没拿钥匙的情况下去开锁,或者连续输出五个完全不相关的移动指令。二是上下文长度不够用。游戏环境的描述、目标信息、历史动作序列全部塞进提示词之后,16K的窗口很快就满了,模型会忘了最开始的任务是什么。后半段我们会发现它在一个房间里来回转圈,因为它只记得"要探索房间",忘了"要找钥匙"。

2.2 第二周:改成"规划—执行"分离架构,立刻见效

第一周结束之后我们做了个关键决定:不要让模型直接出动作序列,改成两层架构。上层是一个规划器(Planner),只负责根据当前状态和目标,决定下一步的子目标,比如"先去厨房区域找钥匙";下层是执行器(Executor),用规则脚本或者微小的预测模型,把这个子目标拆解成具体的移动和交互动作。

这个改动带来的变化非常明显。模型不再需要输出高频动作,它只需要做高层的、低频的决策。对模型来说,做"一步规划、然后看结果"比起"一口气规划十步动作"要简单一个量级。我们原本担心延迟会叠加,实际跑出来的效果反而更好:因为执行器是规则化的,每一步动作的执行时间从几百毫秒降到几十毫秒,Agent的移动表现比纯模型驱动流畅得多。

为了让这个架构跑得通,我们给规划器设计了一套"可感知的子目标集合"。这个集合不是凭空来的,而是来自沙盒环境的底层状态——比如explore(area)、find(item)、move_to(room)、interact_with(object)。模型只能从这组范围受限的选项里选择,这样既保留了LLM的规划能力,又用规则边界砍掉了大量幻觉动作。

2.3 第二周关键改动:状态压缩

在把架构调成两层之后,我们马上面临第二个问题:每次调用规划器,应该给它多少状态?一开始我们直接把房间里的全部可交互对象、物品位置、Agent坐标都塞进去,结果很多信息根本用不上,反而干扰了判断。环境里30个物品,其中28个和当前任务无关,模型还要自己去过滤,既浪费token也引入噪声。

后来我们做了一个叫"状态摘要"的预处理层:根据当前子目标和已探索区域,只提取相关对象的信息输出给模型。比如目标是"找钥匙",摘要里就只包含"厨房、书桌、卧室、床"这些位置信息,以及"门锁状态、已用时间"这些关键变量。实验下来,这个摘要层的过滤逻辑比换更强的模型还要管用。原因很简单:对规划来说,最难的往往不是推理,而是信息过载。

2.4 第三周:上下文管理,让Agent"记住"该记的事

第三周处理的是记忆问题。之前模型容易"中途失忆",本质是我们把历史记录当作流水账全部丢给模型,然后窗口满了就粗暴截断。9月这个阶段,我们尝试了一种简单有效的方法:维护一个固定格式的"工作记忆卡片",每次规划之后,模型输出一个结构化摘要,包括当前目标、最近发现的线索、当前所在位置、下一步打算。下一次规划的时候,我们优先使用这张卡片,而不是原始的历史序列。

贴一段我们定义的工作记忆格式,你感受一下:这个格式本身很简陋,但效果出乎意料地好,它让整个系统对上下文长度不敏感,也方便后续排查。

{ "task": "find_key_and_open_door", "current_room": "kitchen", "discovered_clues": [ {"item": "drewer", "location": "kitchen_north", "state": "unchecked"} ], "last_action": "moved_to_drawer", "last_result": "progressed", "next_plan": "check_drawer_for_key" }

2.5 为什么不能完全抛弃行为树

第三周我们还做了一个看似"开倒车"的决定:把很多底层动作重新用行为树接管。本质上,行为树是一个固定逻辑的树状结构,用于决定什么条件下执行什么动作。比如"如果门是锁的,并且有钥匙,则使用钥匙;如果没钥匙,则搜索周边区域"。LLM擅长的是处理开放性和模糊性问题,但把它用在那些确定性操作上,不仅成本高,而且不稳定。

现在整个Agent的架构是混合的:行为树负责低层、高频、确定性的动作;LLM负责高层、低频、需要常识的规划。这个"不要用大炮打蚊子"的原则,是整个9月最重要的经验之一。当然,这也意味着我们的Agent没法直接迁移到没有规则接口的任意游戏上,但对我们的目标来说,稳定性和可控性比通用性重要得多。

3. 视觉模块:让Agent看到游戏画面,而不只是读坐标

3.1 为什么要做视觉通路

很多朋友可能会问:既然沙盒环境是我们自己搭的,为什么不直接开放一个数据接口给Agent,让它直接读坐标,非得让计算机视觉来掺一脚?

原因很简单:我们的目标是让这套方案未来能适配更接近真实玩家的游戏环境。那些商业游戏或复杂模拟环境里,通常没有完整可靠的数据接口,唯一可靠的信息源就是屏幕画面。所以9月我们在视觉通路上花了不少功夫,就是为了提前验证"只靠画面能不能驱动决策"。

初步跑下来,结论是可以,但要做一些取舍。

3.2 方案选型:为什么不用端到端VLM直接驱动

现在有现成的多模态视觉语言模型(VLM),能不能把截图直接喂给模型,让它直接输出动作?我们试了,但很快放弃了。主要原因是成本和延迟。VLM的每次调用都很贵,而且响应时间往往在数秒以上。游戏环境的特点是一秒内需要做出数十次决策,这个延迟卡死了端到端方案的上限。我们需要的方案是:视觉感知尽量用轻量模块,先在本地把截图转成结构化状态,再把这个状态交给LLM做规划。

于是我们选了三件套:截图、OCR识别、目标检测。截图负责获取当前画面;OCR负责读取游戏里的文字信息(比如提示、任务描述、物品名称);目标检测负责定位关键物体(门、箱子、钥匙、角色位置)。这三部分全部在本地小模型或者轻量服务上运行,只把结构化结果(物品坐标、文字内容、场景描述)传给规划器。

3.3 具体实现细节:坐标归一化、缓存帧、检测间隔

视觉链路的具体实现我们不堆代码,讲几个关键细节。

第一,坐标系必须归一化。屏幕坐标的绝对值没有意义,因为不同分辨率下同一个物体的像素坐标完全不同。我们把所有检测到的物体坐标统一转成0到1之间的相对坐标,并且附带一个置信度分数,这样规划器看到的输入始终是一个标准的空间描述,不会因为环境分辨率变化而崩掉。

第二,缓存帧策略。游戏画面每秒变化很多次,如果每一帧都做目标检测,计算资源会爆。我们的做法是:每200毫秒取一帧做检测,如果检测结果与上一帧相比没有明显变化,就沿用缓存结果,不重复计算。这个策略极大降低了视觉模块的负载,而且对决策质量几乎没有影响,因为游戏里的状态变化本身没有那么高频。

第三,检测间隔要跟Agent的动作节奏匹配。我们在实验里发现,检测频率太高反而会让Agent状态混乱:由于视觉信息更新比动作执行还快,上一秒模型刚根据检测结果输出一个动作,下一秒检测结果又变了,动作就被打断。后来我们把视觉更新的节奏跟执行器的反馈周期对齐,比如Agent每移动到一个目标点才做一次状态刷新,问题就消失了。

3.4 最有价值的小改动:视觉摘要代替裸图

一开始我们试图把整张截图传给规划器模型,让模型自己看。后来我们发现,对大多数决策来说,模型真正需要的信息其实非常少:它在哪个房间、附近有什么物体、这些物体的空间关系是什么。于是我们设计了这个格式的"视觉摘要":

你在厨房的北侧。可见物体: - 木质抽屉(右侧1.2米,未检查) - 冰箱(左侧2米,上锁) - 冰箱(顶部有一个红色小物件,可能是钥匙) 注意:门在东南方向,目前关闭。

这个摘要不是模型生成的,而是由本地目标检测模块+预设模板拼出来的。规划器拿到的就是这样一段简洁文本,不再需要"看"图。这个改动把调用成本降低了近一半,同时模型的决策准确率反而提升了,因为信息里没有了那些无关的背景噪音。

当然,视觉摘要也有它的短板:如果场景里出现了训练目标之外的新物体,或者物体外观变化太大,检测模块会失准。我们在9月底测试的时候,发现当物体被遮挡一半以上时,检测置信度会快速下降,Agent偶尔会"看不见"近在眼前的物品。这是下一步要改进的重点。

4. 评估体系:9月最有价值的产出,其实是一套跑分方法

4.1 三个维度:完成率、步数效率、无效动作率

做Agent和做普通功能不一样,没有精确的验收标准就很难判断进度。9月我们在评测上花的时间,甚至不比写代码少。最终定下的评测维度有三个。

第一个是任务完成率(Completion Rate):在固定的任务集里,Agent成功完成任务的占比。完成率是基础指标,但光看完成率会骗人:如果Agent花了一万年才看到钥匙,它完成了,但没有任何实用意义。所以第二个指标是步数效率(Step Efficiency):完成任务所用的动作步数,跟人类玩家完成同一任务的参考步数相比,比值越低越好。第三个是无效动作率(Invalid Action Rate):Agent执行了但没有产生任何状态变化的动作,比如对着墙移动、反复打开同一个抽屉、在门口原地转圈。这个指标越接近于零越好。

4.2 9月跑出的数据:从版本V1到V3

9月月底我们拿这套评估方法测了三个版本,下面是记录的数据,当然这些数据都是我们内部环境的相对数值:

版本任务完成率平均步数效率无效动作率主要改动
V1(纯提示词)52%61%33%直接输出动作序列
V2(规划-执行分离)78%74%18%两层架构,行为树执行
V3(加入工作记忆)86%82%11%记忆卡片 + 状态摘要

从52%到86%,每一步的跃升都不是来自换更大的模型,而是来自架构和决策链路的调整。这恰好验证了我们之前的判断:这一轮的瓶颈并不在模型智力,而在系统组织方式。

4.3 失败案例分析:真正暴露问题的不是能力,是习惯

9月最让我印象深刻的不是成功案例,而是三个典型的失败模式。

第一个是"卡门"。Agent站在门前,拿到了钥匙,却不去开锁,在门口来回移动。日志显示,它已经检测到了门,但不知道"钥匙的使用点"就在门的正前方,需要先调整到指定朝向再交互。这个问题的本质是执行器的目标拆解不够细:规划器把"开门"交给了执行器,但执行器缺少"走到门的交互区域"这个前置步骤。我们花了半天补了这个规则,成功率立刻提了一截。

第二个是"重复对话"。环境里有一个可以交互的NPC角色,Agent向NPC询问钥匙位置,NPC回答了"钥匙在床上";但Agent没有把这句话存进记忆,而是下一轮又问了一遍,甚至问了五遍。这暴露了我们忽略了一个关键点:非结构化交互信息(比如NPC的对话)也需要进入工作记忆。补上之后,记忆卡片里就多了一个"dialog_clues"字段。

第三个是"视觉误判"。OCR把房间上的房间号"201"识别成了"201",导致Agent跑错了房间。这个问题的根源是OCR模型在低分辨率下的数字识别错误率偏高。我们临时加了一个后处理规则:当识别结果包含多位数字时,降低置信度并追加一帧二次确认。虽然不能完全消除,但误判率降到了一个可接受的范围。

4.4 难度梯度:单任务测试远远不够

9月中旬我们开始意识到,单任务测试看着完成率很高,其实掩盖了Agent的"上限"。因为我们只测了三个固定任务,Agent只要记住了任务模板(如果是模型记忆的错),看起来就会很聪明。参考人类评价AI智能的方向,我们做了一个"难度梯度"任务集:同一类任务,从简单到复杂排列,比如先从单目标寻物开始,再到多目标寻物、有时间限制的寻物、有NPC干扰的寻物,逐级递增。这样测出来的得分曲线比单个完成率更有诊断价值。

结果很真实:Agent在简单任务上完成率93%,但到了需要同时处理三个目标的复杂任务时,完成率下降到61%。这说明它的短板不是基础感知,而是"多目标优先级管理"。9月月底我们把这个结论作为下一个迭代方向,比盲目调提示词有指导意义得多。

5. 调试过程中的典型翻车现场,以及对应的修复逻辑

5.1 模型幻觉动作:加了"动作校验层"

9月不止一次出现这样的日志:Agent在一个没有攻击系统的沙盒环境里,输出了一个"attack"动作。模型并不知道这个环境里没有攻击这个动作,它在自己的训练数据里见过大量战斗场景,于是幻觉式地输出。对于底层执行来说,这个动作如果被直接执行,轻则报错,重则让整个行为链卡住。

修复方式是在规划器和执行器之间加了一层动作校验层(Action Validator)。校验层的职责很简单:核对模型输出的动作是否在预设动作集合里,不在就拒绝;如果模型连续两次输出同一个不存在的动作,就触发一次状态刷新,强制Agent重新感知当前环境。这层逻辑大概只有几十行代码,但它避免了大量的下游错误。

提示:如果你的Agent也经常输出"环境里根本不存在"的动作,别急着怪模型。先检查一下动作空间是否被明确定义,以及是否有校验环节。很多翻车,都是因为跳过校验直接把模型输出喂给了执行器。

5.2 历史截断导致的失忆循环

在V1版本里,我们遇到过一种特别尴尬的循环:Agent在某一个房间反复进出,每次出房间之后忘了之前进房间已经看过什么,于是又进去看一遍。这个问题的根子在上下文管理:我们的历史记录是按时间顺序存储的,但上下文窗口有限,新的动作进来,旧的已经被截断了。而截断掉的,恰恰最早包含了"我已经搜索过这个房间"的信息。

这个问题在引入工作记忆卡片之后就基本解决了,但还有个代价需要注意:规划器做每轮决策之前,还是会读取最近的行为序列,这仍然会占用上下文。后来我们用一条简单的规则约束:行为序列只保留最近10步,更早的决策依据一律由记忆卡片提供。这样既保留了短期行为连贯性,又不会挤出长期记忆的位置。

5.3 状态不同步:Agent"看到了"和"环境真实状态"不一致

9月中旬调试时,Agent出现了一个奇怪现象:它对着本该被打开的箱子,反复执行"打开"动作,但箱子其实已经开了,只是检测模块没刷新,还停留在"关闭"状态。日志里最明显的特征是:视觉检测结果迟于环境变化。

这个问题的根源在于视觉缓存的更新策略。我们只对"检测结果变化"做判定,但有些状态变化是静默的,比如箱子打开之后外观变化很小,检测模块根本检测不到外观变化,于是缓存一直不失效。修复办法是引入"明确的交互反馈"机制:当Agent执行了一个交互动作之后,无论检测结果是否有变化,都强制刷新一次视觉状态,并把这次刷新结果写入日志。也就是说,把"按需刷新"改成了"动作后强制刷新"。这个改动非常小,但让状态同步的准确率提升了非常多。

5.4 日志和回放:没有录屏,调试根本无从谈起

最后想讲一个方法论层面的经验。做Agent调试,最忌讳的是"看一眼现象就猜原因"。Agent的行为是时序的,很多问题必须连着前因后果看才能定位。9月我们花了一周搭建评测环境的回放系统:每一次运行时,不仅记录Agent最终动作日志,还同步录下完整的屏幕画面、规划器的每一步输出、执行器的动作序列、环境状态快照。调试的时候,直接定位到出问题的那一步,观察规划器当时看到了什么状态、为什么会输出这个决策、执行器又是怎么执行的。这个过程让定位精度大幅提升——很多问题,看日志以为是规划器错了,回放之后发现是视觉模块给规划器传了一个错误的状态。

6. 9月留下的问题,以及下个月我想先碰什么

6.1 目前最明显的短板:长时间任务的规划漂移

9月底Agent在短任务上已经比较稳定,但一旦把任务时长拉长到10分钟以上,覆盖率会明显下滑,规划稳定性下降。具体表现是:早期目标执行得很好,后期会逐渐偏离任务主线,开始做一些无意义的探索。这说明我们的工作记忆卡片虽然解决了短期记忆,但对于"任务意图的长期保持"还不够。下一步我打算做一个"目标强度机制":在记忆卡片里增加目标剩余权重,每次规划前先检查当前动作是否和主目标一致,偏离超过某个阈值就强制拉回。

6.2 方向判断:优先补数据闭环,而不是继续调提示词

9月我们调了无数版提示词,越调越发现边际效益很低。真正带来提升的,永远是数据侧和架构侧的改动。所以我更倾向于下一步先搭建一个"失败样本自动收集→标注→回放→针对性修正"的闭环。这么做不是为了上强化学习,而是为了给Agent建立一套持续改进的基础设施。等样本量积累到一定程度,再去看微调模型值不值得。

6.3 我个人的体会:这个月最大的收获,不是某个指标

做AI Agent有一个很危险的心态,就是把"模型能力"当作项目成败的唯一变量。9月把游戏Agent的整条链路从零搭起来之后,我的感受是,决定一个Agent可不可用的,往往是那些不起眼的部分:动作校验层、记忆更新策略、视觉状态同步、评测方法。这些东西没有一项是很酷的技术,但每一项都会让整体表现上一个台阶。

如果拿开车来打比方:模型是发动机,架构是变速箱,评测是仪表盘。发动机换得再好,变速箱换挡逻辑一团糟,仪表盘还是坏的,这车照样没法上路。9月我们在做的,其实就是先把变速箱和仪表盘弄明白。下个月,希望发动机能让这辆车的上限再往上提一提。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询