对于那些在1980年代玩Hack(以及更早的Rogue)成长起来的人,在现代实时战略时代之前……
摘要
一个名为GPT 6 Astra的LLM代理在NetHack游戏中实现了飞升,标志着首次有LLM通过自主构建工具击败这款复杂游戏的记录实例。
查看缓存全文
缓存时间: 2026/09/25 22:44
对于那些在上世纪80年代玩《Hack》(以及更早的《Rogue》)长大、早于现代实时策略游戏时代的人来说,这作为突破性AI确实恰如其分!
https://t.co/0IAunSMtId
大语言模型(LLM)通关NetHack
来源:https://kenforthewin.github.io/blog/posts/llm-nethack-ascension/ GPT-6 Astra 通关了NetHack。据我所知,这是首次有记录的大语言模型代理完成通关。
它在Hardfought服务器上,通过终端,使用名为“CodexDelver“的矮人女武神角色,游玩了NetHack 3.6.7版本。在9月21日,经过37,140个游戏回合,它成功飞升。以下是服务器转储文件(https://www.hardfought.org/userdata/C/CodexDelver/nethack/dumplog/1788964024.nh.txt),或者你可以直接跳转浏览全部三次运行记录(https://kenforthewin.github.io/blog/posts/llm-nethack-ascension/#explore-the-runs)。
我研究让LLM玩NetHack已有一段时间。早在一月份,我就写过关于构建工具集、尝试不同模型以及观察它们挣扎的经历(https://kenforthewin.github.io/blog/posts/nethack-agent/)。那篇文章的结尾,我曾好奇究竟是我还是LLM会先通关这个游戏。
嗯… LLM赢了,而我至今仍未飞升。
今年一月,我坚信让LLM通关NetHack的路径是精心手工打造一个工具集,为LLM提供完美的接口和上下文以助其飞升。然而最终,获胜的代理是自主构建了它的工具集,完全放手去做。我一行代码都没写,而且坦白说,我甚至没读过Astra的代码——它在第一次尝试时就已非常接近胜利,第三次尝试便成功了。
为何选择NetHack
NetHack是一个有用的测试,因为知道该做什么和实际去做是截然不同的。一个模型可以完美地解释抗性、物品管理或特定怪物互动,但当菜单打开且其最后的地图观察已过时,它却无法应用这些知识。
这个差距在我早期的实验中反复出现。存在导航失败、目标遗忘,以及代理对屏幕上已消失的事物做出反应的情况。我一月份最好的一次运行达到了地牢第10层。知识看起来很丰富,但可靠的执行能力却不足。
《BALROG》(https://arxiv.org/abs/2411.13543)是一个评估跨六款游戏的LLM/VLM代理的基准,它更系统地研究了这个问题。它在NetHack上的结果明确区分了拥有游戏知识和在长序列决策中运用知识的能力。论文还发现,给模型提供图像可能使其表现变差,而非变好。一个更丰富的界面并不自动意味着一个更可用的界面。
截至9月21日,BALROG排行榜(https://balrogai.com/)显示GPT-6-Astra-Max在NetHack进度上达到13.2 ± 2.7%,该条目日期为9月18日。这是一个平均进度指标,而非胜率,它并未告诉我们每一次独立运行的结果。但它提供了为什么一次真正的通关值得一提的背景。
这次运行并非BALROG的提交项。BALROG支持不同的代理策略;它并非简单地测试一个裸模型选择按键。为了公平比较,我们需要在相同的评估协议、资源核算和重复试验设置下运行这个系统。
这里的问题更开放:如果一个能力强大的编码代理可以致力于解决这个问题,包括改进它用来解决问题的工具,会发生什么?
显然,答案是通关。
Astra构建了工具集
今年一月,我花了大量时间围绕NetHack学习环境构建一个定制的Python接口。上下文管理、观察掩码、操作API、路径规划——在模型能够正常运作之前,有太多东西需要调整。
这次尝试始于一个简单得多的需求:玩NetHack,也许就通过终端,并将其直播到Twitch。我建议使用Hardfought服务器,这样游戏会有外部记录。我告诉它可以用攻略,建议批量命令,并将持久化记忆交由它决定。
然后,它就构建了所需的一切。
这并不等同于没有工具集。到结束时,这个工具集已经相当庞大。区别在于是我设计一个任务特定的系统,还是代理将这项工程作为任务的一部分来完成。
它也不是一次性构建所有东西然后执行一个完美无缺的计划。它发现了弱点,进行了修补,添加了检查,并持续推进。有些改动源于错误,有些源于死亡。它编写和维护常规软件的能力,是其能够玩好游戏的一部分。
这似乎就是这里有趣的结果:工具集提供了帮助,但生成这个工具集本身就是LLM可以完成的工作。
工具集架构
架构设计刻意追求普通:
01 / 游戏循环
代理通过tmux和SSH连接的受保护Python包装器,与Hardfought NetHack服务器交换动作和观察结果。(https://kenforthewin.github.io/blog/diagrams/nethack-play-light.svg)代理通过tmux和SSH连接的受保护Python包装器,与Hardfought NetHack服务器交换动作和观察结果。(https://kenforthewin.github.io/blog/diagrams/nethack-play-dark.svg)
02 / 持久化状态
代理读取和更新运行日志、地图和物品知识,并编写和测试其辅助代码。(https://kenforthewin.github.io/blog/diagrams/nethack-memory-light.svg)代理读取和更新运行日志、地图和物品知识,并编写和测试其辅助代码。(https://kenforthewin.github.io/blog/diagrams/nethack-memory-dark.svg)
03 / 证据与广播
输入、屏幕截图和转录内容发送至私有审计存档。公开的屏幕、命令和解说通过浏览器、OBS和Twitch进行直播。Hardfought服务器单独记录ttyrec文件和最终转储。(https://kenforthewin.github.io/blog/diagrams/nethack-record-light.svg)输入、屏幕截图和转录内容发送至私有审计存档。公开的屏幕、命令和解说通过浏览器、OBS和Twitch进行直播。Hardfought服务器单独记录ttyrec文件和最终转储。(https://kenforthewin.github.io/blog/diagrams/nethack-record-dark.svg)
游戏循环、其工作记忆以及留下的记录。代理主机提供了模型/工具循环。代码库包含游戏接口和支持工具,而非一个独立的推理服务或一个可以直接运行来重现结果的单一ascend.py文件。
观察结果:带有部分结构的终端
游戏在远程运行。本地进程无法访问运行中的引擎内部地图、随机数生成器状态或未识别物品的真实身份。它接收到的是终端显示的内容。
会话包装器将tmux窗格捕获为文本。显示配置为使用curses库、彩色界面和144列×36行的持久化物品栏。一种紧凑的观察模式添加了行号、光标坐标以及所选可见地图特征的坐标。这省去了代理在大段文本中反复计算字符位置的麻烦。
在描述结果时,这点很重要:它并非完全基于截图的计算机使用,也非未经处理的ASCII流。存在针对特定任务的解析和标注。但这些标注来自终端,而非暴露隐藏游戏状态的“神谕”。
浏览器/OBS端是同一屏幕的另一个消费者。它渲染终端颜色,并显示公开的解说和近期命令。观众看不到模型私密的内部推理过程,代理也不需要观看自己的Twitch直播流来了解当前状况。
动作:批量执行而非盲目按键
每次移动都调用一次工具成本高昂且繁琐。一长串未经观察的移动是死亡的好方法。
最终的折中方案是带检查的批量处理。对于请求的移动序列,工具集会解析显示的位置、生命值、游戏回合、地牢层数、状态效果和附近生物。它发送一步指令,捕获结果,检查它,并决定下一步是否仍可进行。
检查包括生命值过低、附近非宠物生物、未知或危险的目的地格子、意外的位置偏移、受伤、层数变化以及回合数过度推进。这些都是对终端状态的具体谓词判断,而非由另一个LLM来判断每一步是否看起来安全。
这个区别很重要:批量处理意味着减少与模型的往返次数,而非跳过所有中间观察。战斗仍需要单独操作和再次查看屏幕。多键输入也需要一个已识别的地图提示,并对经过审查的菜单响应有明确的日志记录例外。
移动循环大致如下——这是伪代码,而非第二次模型调用:
1 2 3 4 5 6 7 8
for key in requested_route: before = observe_terminal() if preflight_rejects(before, key): break log_intent_and_send(key) after = observe_terminal() if unexpected_change(before, after, key): break
例如,实际的预检会拒绝生命值低于三分之二的批量操作,而后置步骤检查会在角色未落在预期方格时停止。代码位于scripts/guard.py中;当批量操作停止时,模型仍需决定如何处理。
这个守卫模块并非NetHack的完整模型。它无法让不安全的策略变得安全,有时也需要修补。例如,在通关运行的后期,它在元素位面拒绝命令,因为其状态解析器无法识别新的层级标签。代理扩展了解析器,测试了更改,创建了检查点,并继续前进。
这是一个相当平凡的软件错误。但如果玩家无法修复自己的工具,固定接口恰恰容易将这类问题变成硬性障碍。
辅助程序:让代码处理繁琐部分
代理还构建了基于记忆地形的路线提议器、索班关卡规划与执行检查辅助程序,以及用于重复性物品栏操作的小工具。
路线辅助程序对显示的地图执行图搜索,而非让模型在脑中追踪每一条走廊。索班辅助程序处理巨石周围规划和移动的部分,并有针对观察结果的检查。物品栏辅助程序可以逐步执行存放黄金的操作,同时检查预期的袋子、数量和菜单状态。
这些辅助程序值得称道。LLM并非独立推导出每一个基本移动。但我也没有将这些实现作为完整的NetHack解决方案交给他。它编写了工具来减少需要以语言进行的不可靠工作量,然后使用了它们。
这感觉更接近我希望一个编码代理处理困难任务的一般方式。如果同一个小操作不断出错,就编写一个能可靠执行它的工具。
记忆:文件,而非一次巨大的对话
通关运行从9月9日持续到9月21日,包括暂停和存档读档。这是日历日期,而非连续十二天的推理过程。
代理维护了一份较长的运行日志和一份紧凑的紧急参考信息。这些跟踪了已识别的物品、路线、抗性、消耗品、当前威胁和下一个目标。工作指令告诉它恢复运行和上下文压缩后需要阅读什么。地图和随机化的物品身份限定在单次运行范围内,因此死亡角色的信息不会成为下一个角色的“知识”。
这只是磁盘上普通的Markdown和JSON,并非花哨的记忆服务。困难在于保持状态准确:例如,区分观察到的魔杖充能和估计的充能,以及及时更新被盗或消耗的物品。
外部记忆并未消除错误。它使得在暂停或上下文边界后继续变得可行。代理负责维护这些记忆,而不仅仅是检索别人为其编写的完美摘要。
开卷考试,包括源代码
我给了它不受限制的访问权限,可以查阅攻略、Wiki、网络以及公开的NetHack源代码。它可以在承诺执行一个动作之前研究规则,包括在终局游戏期间。这不是对记忆的NetHack知识的闭卷评估。
阅读魔杖效果的实现代码会告诉你规则。但它不会告诉你在本次特定游戏中你找到了哪个未识别的魔杖,或者它还剩多少次充能。远程终端的边界仍然重要。
我不认为访问参考资料让这次通关变得无趣。在数万个游戏回合中,将规则在正确的状态下转化为正确的行动,才是早期系统不断失败的部分。但访问权限是结果的一部分,需要明确说明。
整个尝试没有固定的基准式预算,工具和指令在游戏过程中也发生了变化。因此,我们无法单独量化有多少改进来自模型、额外的计算、记忆、参考访问或不断演化的工具集。我们能说的是,这种组合奏效了,并且许多特定任务的工程是由代理自身完成的。
这花了多少钱?
我支付了每月200美元的Codex计划费用,并在此实验期间购买了大约300美元的额外信用额度。所以实际答案是额外信用购买加上我运行它期间的订阅费用。我没有清晰的每次运行成本分析。
这真的是首次吗?
据我们所知,是的:首次有记录的由LLM代理完成的NetHack通关。我们也未找到更早的、有记录的、针对3.6系列版本的机器人通关记录。如果有人拥有更早的运行记录,我真的很想看看。
这并不意味着没有AI或机器人曾击败过NetHack。BotHack在2015年(https://github.com/krajj7/BotHack)记录了一次通关,使用的是3.4.3时代,依靠手工编码的机器人和包含“ pudding farming”的策略。
《NeurIPS 2021 NetHack挑战赛报告》(https://arxiv.org/abs/2203.11889)指出没有参赛者接近获胜。这是有用的历史背景,但并非证明该竞赛之外无人完成。同样,排行榜上的低平均进度也不能证明每一次独立尝试都失败了。
我们的声明基于我们能找到的早期系统和记录,并非基于对每个人运行过的所有机器人的详尽登记。结果是确定的;历史优先权仍可接受纠正。
使结果可验证
一旦这开始显得可信,我想要比一张通关截图更好的凭证。代理也构建了这些。
本地审计记录器将事件与哈希值关联,并在发送按键前记录输入意图。它跟踪排队的输入、观察结果、终端输出和可观察的对话。它保存实现和内存检查点,以便我们可以看到工具是如何变化的。当记录器不健康或绑定到错误会话时,游戏输入会安全失败。
Hardfought提供了另一个证据来源:服务器端的终端记录和最终转储。本地检查核对了账本、存档工件和记录的投射与原始会话源。游戏结果并非依赖于相信本文中的某段描述。
这仍然不会让本地哈希链变得神奇。它检测相对于检查点的不一致;它无法证明计算机所有者不能通过其他途径篡改文件或提供输入。确认此次游玩需要关联日志和记录,而不仅仅是哈希它们。
工具集代码和运行日志托管在GitHub上(https://github.com/kenforthewin/nethack_astra),工具集采用MIT许可证。审查过的证据存档作为发布版本提供下载(https://github.com/kenforthewin/nethack_astra/releases/tag/v1.0.0),包括失败的运行记录、人类消息、命令记录、观察结果和历史快照。私有
相似文章
自我对弈帮助AI在围棋中达到超人类水平,那么为何对LLM未能如此?研究人员找到了解决方案。
研究人员引入了自导自对弈(Self-Guided Self-Play, SGS),这是一种用于LLM的自我对弈算法,通过使用指引角色(Guide)对合成问题进行评分来防止奖励作弊(reward hacking)。应用于Lean4中的定理证明时,SGS超越了强化学习基线,并使7B模型胜过671B模型。
GPT-6 Astra 独立为我击败了 STS2(计算机使用)
用户报告称,GPT-6 在没有外部协助的情况下独立游玩并赢得了 Slay the Spire 2 的一局游戏,尽管有错误和使用限制,这让他们推测其可能具有 proto-AGI(初级通用人工智能)的潜力。
GPT-6 Astra 成功通过了所有 48 个关卡的《I'm Not A Robot》游戏
GPT-6 Astra 成功通过了所有 48 个关卡的《I'm Not A Robot》游戏,展示了在交互式挑战环境中的先进 AI 能力。
@patio11: 没有哪句话比今天我给几个朋友发的‘AI 发射了火箭’更需要加上‘(在[一款电子游戏里])’这个注释的了…
GPT6 Astra,一个AI模型,正在玩Factorio Space Age,已经到达第三颗星球,超过了之前的模型Fable 5.1。有直播可用,预计很快完成游戏。
将NetHack加入我的社区应用,这款38年历史的游戏始终让我措手不及
一位开发者将NetHack加入自己的社区应用,发现了这款38年历史的Roguelike游戏惊人的深度,包括通过Bones文件实现的多人在线模式,以及无数隐蔽的互动方式。