diff --git a/README.md b/README.md index bd6c08487..a0be1bf58 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,10 @@ Therefore, this project, AIRI, offers another possibility here: **let you own yo ## DevLogs we posted & Recent updates +- [DevLog @ 2025.07.18](https://airi.moeru.ai/docs/blog/DevLog-2025.07.18/) on July 18, 2025 - [DreamLog 0x1](https://airi.moeru.ai/docs/blog/dreamlog-0x1/) on June 16, 2025 -- [DevLog @ 2025.06.08](https://airi.moeru.ai/docs/blog/devlog-20250608/) on June 8, 2025 -- [DevLog @ 2025.05.16](https://airi.moeru.ai/docs/blog/devlog-20250516/) on May 16, 2025 +- [DevLog @ 2025.06.08](https://airi.moeru.ai/docs/blog/DevLog-2025.06.08/) on June 8, 2025 +- [DevLog @ 2025.05.16](https://airi.moeru.ai/docs/blog/DevLog-2025.05.16/) on May 16, 2025 - ...more on [documentation site](https://airi.moeru.ai/docs) ## What's so special for this project? diff --git a/docs/content/en/blog/DevLog-2025.07.18/assets/structure-after.png b/docs/content/en/blog/DevLog-2025.07.18/assets/structure-after.png new file mode 100644 index 000000000..75894d5ba Binary files /dev/null and b/docs/content/en/blog/DevLog-2025.07.18/assets/structure-after.png differ diff --git a/docs/content/en/blog/DevLog-2025.07.18/assets/structure-before.png b/docs/content/en/blog/DevLog-2025.07.18/assets/structure-before.png new file mode 100644 index 000000000..8fb47da20 Binary files /dev/null and b/docs/content/en/blog/DevLog-2025.07.18/assets/structure-before.png differ diff --git a/docs/content/en/blog/DevLog-2025.07.18/index.md b/docs/content/en/blog/DevLog-2025.07.18/index.md new file mode 100644 index 000000000..1fb8e0c39 --- /dev/null +++ b/docs/content/en/blog/DevLog-2025.07.18/index.md @@ -0,0 +1,78 @@ +--- +title: DevLog @ 2025.07.18 +category: DevLog +date: 2025-07-18 +--- + +Hello, I'm [@LemonNeko](https://github.com/LemonNekoGH), one of the maintainers of AIRI. + +## Review + +Half a year ago, I first tried to write an AI Agent that can play the famous automation production simulation game [Factorio](https://www.factorio.com/) called [`airi-factorio`](https://github.com/moeru-ai/airi-factorio), and I did the following things: + +- Writing Factorio Mods in TypeScript: Using [tstl](https://github.com/TypeScriptToLua/TypeScriptToLua) to compile TypeScript code into Lua code. +- Using RCON to interact with Factorio Mods: Using [factorio-rcon-api](https://github.com/nekomeowww/factorio-rcon-api) to communicate with Factorio, calling `/c` commands to execute functions registered by the mod. Many thanks to [@nekomeowww](https://github.com/nekomeowww). +- Using LLM for decision-making and generating Lua code to control the player: Through prompt engineering to tell the LLM how to operate the game, how to plan, and encapsulating the RCON interaction code into tools that the LLM can call. +- Interacting with the LLM through the game's built-in chat system: By reading the game's standard output, using regular expressions to parse player chat content in the game, and sending it to the LLM for processing. +- Hot reloading of Factorio Mods: By writing a plugin for tstl to monitor code changes in real-time and send new mod content to the game via RCON. When receiving new mod code, unload all interfaces and execute the mod code once to achieve hot reloading. However, how to properly handle the existing state of the mod became a major challenge. +- Development in DevContainer: Making the environment more controllable and project startup simpler. +- Using symbolic links to link the `tstl` output directory to the game directory, so we can directly see the compiled Lua code in the game directory, making debugging easier. + +This taught me a lot of knowledge ~~(especially that Lua array indices start from 1)~~. + +However, I also encountered many problems. Since our main operations were written in the mod, debugging became very troublesome. We needed to exit the map, return to the game's main interface, and re-enter to apply mod changes. If our mod was slightly more complex with `data.lua`, we needed to restart the game. + +We let the LLM generate Lua code, then execute it by calling the game command `/c` through RCON. However, Factorio has a length limit for each command. If our code was too long, we needed to execute it multiple times. + +The current code has poor robustness and maintainability. If new friends want to participate in development, or even just try it out, starting this project is very difficult. + +## Factorio Learning Environment + +Fast forward to now, I plan to properly organize this project, but I don't know where to start. Coincidentally, someone mentioned a paper called [Factorio Learning Environment](https://arxiv.org/abs/2503.09617). Let me give you a simple read-through. + +In this paper, the authors proposed a framework called Factorio Learning Environment (FLE), where they tested AI's capabilities in long-term planning, program synthesis, resource management, and spatial reasoning. + +FLE has two modes: + +- Lab-play: Testing in 24 manually designed levels with limited resources, examining whether AI can efficiently build production lines with limited resources. +- Open-play: Unlimited large maps, with the goal of building the largest factory on procedurally generated maps, testing AI's long-term autonomous goal setting, exploration, and expansion capabilities. + +They evaluated mainstream LLMs like Claude 3.5 Sonnet, GPT-4o, Deepseek-v3, Gemini-2, etc., but in Lab-play, even the strongest Claude 3.5 at the time only completed 7 levels. + +Reading this, I became curious. Their evaluation was so complex, so they must have also ensured technical maintainability. How did they achieve this? Continuing to read, I found that their implementation method was very similar to `airi-factorio`, but had many advantages compared to `airi-factorio`: + +- Written in Python, the LLM generates Python code and executes it directly in a Python REPL, and can read results directly from standard output. Since Python has far more datasets than Lua, the generation accuracy is higher and can generate more complex code. +- The Lua mod only contains primitive operations for execution, such as place_entity for placing entities. More complex logic is written in Python, which can reduce the possibility of bugs in the Lua mod, so we don't need to restart the game so frequently. +- Using `/sc` commands instead of `/c` commands to execute Lua code, which doesn't output code to the console, keeping the console clean and only leaving the necessary content, simplifying the difficulty of parsing standard input. + +To better evaluate LLM capabilities, they also carefully analyzed all the required recipe production processes and difficulties, summarizing some formulas, such as the cost of producing an item, how to calculate LLM scores, etc. + +They also posted their [system prompt](https://arxiv.org/html/2503.09617v1#A8.SS4), which specifies the environment structure, response format, best practices, how to understand game output, etc. + +## Back to `airi-factorio` + +Compared to FLE, our implementation seems quite naive. So how should we improve `airi-factorio`? + +I don't want to write Python, I'm familiar with TypeScript and Golang, only. Coincidentally, we made [mcp-launcher](https://github.com/moeru-ai/mcp-launcher) just a few ago, a builder suitable for all possible MCP servers. We can use it with Golang to implement an MCP server, then let the LLM call it. + +With that, the structure diagram has changed: + +
+ +![Before](./assets/structure-before.png) + +![After](./assets/structure-after.png) + +
+ +Player chat content will no longer be sent to the LLM, rather stored in the [RconChat](https://gitlab.com/FishBus/rconchat) mod, while LLM reads this content through the MCP server. With the potential MCP server approach, we don't need to let the LLM generate Lua code anymore. + +Regarding system prompts, currently our prompts are AI-generated, but they're still not clear enough, with unclear priorities. I plan to improve them by referencing FLE's system prompt. + +Alright, we've basically overturned all the previous designs again. Time to start over. + +## Conclusion + +Thank you for reading. If you're interested, you can read through FLE's paper and [code](https://github.com/JackHopkins/factorio-learning-environment). Maybe my understanding is incorrect; corrections are welcome! This reading might not be deep enough, but when I follow my ideas to improve `airi-factorio` next, I'll need to read repeatedly and update when there's progress. + +That's it for this DevLog. Have a great weekend! diff --git a/docs/content/zh-Hans/blog/DevLog-2025.07.18/assets/structure-after.png b/docs/content/zh-Hans/blog/DevLog-2025.07.18/assets/structure-after.png new file mode 100644 index 000000000..75894d5ba Binary files /dev/null and b/docs/content/zh-Hans/blog/DevLog-2025.07.18/assets/structure-after.png differ diff --git a/docs/content/zh-Hans/blog/DevLog-2025.07.18/assets/structure-before.png b/docs/content/zh-Hans/blog/DevLog-2025.07.18/assets/structure-before.png new file mode 100644 index 000000000..8fb47da20 Binary files /dev/null and b/docs/content/zh-Hans/blog/DevLog-2025.07.18/assets/structure-before.png differ diff --git a/docs/content/zh-Hans/blog/DevLog-2025.07.18/index.md b/docs/content/zh-Hans/blog/DevLog-2025.07.18/index.md new file mode 100644 index 000000000..6b7c47952 --- /dev/null +++ b/docs/content/zh-Hans/blog/DevLog-2025.07.18/index.md @@ -0,0 +1,78 @@ +--- +title: DevLog @ 2025.07.18 +category: DevLog +date: 2025-07-18 +--- + +大家好,我是 [@LemonNeko](https://github.com/LemonNekoGH),AIRI 的维护者之一。 + +## 回顾 + +半年前,我第一次尝试写一个可以游玩知名自动化生产模拟经营游戏 [Factorio](https://www.factorio.com/) 的 AI Agent [`airi-factorio`](https://github.com/moeru-ai/airi-factorio),并在其中进行了这些实践: + +- 使用 TypeScript 编写 Factorio Mod:使用 [tstl](https://github.com/TypeScriptToLua/TypeScriptToLua) 来将 TypeScript 代码编译成 Lua 代码。 +- 使用 RCON 与 Factorio Mod 进行交互:使用 [factorio-rcon-api](https://github.com/nekomeowww/factorio-rcon-api) 来与 Factorio 通信,调用 `/c` 命令来执行 Mod 注册的函数。很感谢 [@nekomeowww](https://github.com/nekomeowww)。 +- 使用 LLM 进行决策并生成 Lua 代码来操作玩家:通过提示词工程来告诉 LLM 如何操作游戏、如何进行规划,并把与 RCON 交互的代码封装成工具(tool),让 LLM 可以调用。 +- 在游戏内置的聊天系统中与 LLM 进行交互:通过读取游戏的标准输出,使用正则表达式来解析游戏中玩家的聊天内容,发送给 LLM 来处理。 +- Factorio Mod 的热重载:通过为 tstl 写插件的形式来实时监测代码变化,并把新的 Mod 内容通过 RCON 发送给游戏,在收到新的 Mod 代码时卸载所有的接口并且执行一遍 Mod 的代码来实现热重载。但是,如何正确处理 Mod 已经有的状态成了大难题。 +- 在 DevContainer 中进行开发:使环境变得更可控,项目启动也会变得更简单。 +- 通过符号链接的方式把 `tstl` 的输出目录链接到游戏目录,这样我们就可以在游戏目录中直接看到编译后的 Lua 代码,方便调试。 + +这让我学到了很多的知识 ~~(尤其是 Lua 的数组索引从 1 开始)~~。 + +但是,也遇到了非常多的问题,由于我们的主要操作写在 Mod 中,调试起来会非常麻烦,我们需要退出地图回到游戏主界面再重新进入才能应用上 Mod 的改动,如果我们的 Mod 稍微复杂一点,有 `data.lua`,则需要重启游戏。 + +我们让 LLM 来生成 Lua 代码,然后通过 RCON 调用游戏命令 `/c` 来执行,而 Factorio 一条命令的长度是有限制的,如果我们的代码过长,则需要分多次执行。 + +目前的代码健壮性很差,可维护性很差,如果有新朋友想来参与开发,甚至只是尝试一下,启动这个项目都是非常困难的。 + +## Factorio Learning Environment + +时间回到现在,我打算好好理一理这个项目,但是我不知道从哪里开始,刚好有人提到了一篇论文 [Factorio Learning Environment](https://arxiv.org/abs/2503.09617),我来带你简单读一读它。 + +在这篇论文中,作者提出了一个名为 Factorio Learning Environment (FLE) 的框架,他们在这个环境中测试 AI 在长期规划、程序合成、资源管理与空间推理方面的能力。 + +FLE 分为两种模式: + +- Lab-play:在 24 个人为设计的关卡中进行测试,资源有限,考察 AI 能否在有限资源下高效搭建流水线。 +- Open-play:无限制大地图,目标是在程序生成的地图上建造最大的工厂,考查 AI 的长期自主目标制定、探索和扩展能力。 + +他们评测了 Claude 3.5 Sonnet、GPT-4o、Deepseek-v3、Gemini-2 等多款主流 LLM,但是在 Lab-play 中当时最强的 Claude 3.5 也只完成了 7 个关卡。 + +读到这里,我开始好奇,他们的评测如此复杂,那么在技术实现上是如何保证可维护性的呢?继续阅读发现,他们的实现方式与 `airi-factorio` 非常相似,但是相对 `airi-factorio` 来说有很多优点: + +- 使用 Python 编写,LLM 生成 Python 代码并直接在 Python REPL 中执行,可以直接在标准输出中读取结果。由于 Python 的数据集远远多于 Lua,所以生成的准确性更高,也能生成更复杂的代码。 +- Lua mod 中只包含执行操作的原语,比如 place_entity 放置实体,更复杂的逻辑放到 Python 中写,可以减少 Lua mod 出现 bug 的可能,就不用那么频繁的重启游戏。 +- 使用 `/sc` 命令而不是 `/c` 命令来执行 Lua 代码,不会把代码输出在控制台里,保持控制台干净,只留下需要的内容,简化解析标准输入的难度。 + +为了能更好的评测 LLM 的能力,他们还认真分析了所有需要的配方的生产流程和难度,总结了一些公式,比如一个物品生产所需的成本,如何计算 LLM 得分等等。 + +他们还贴出了他们使用的 [系统提示词](https://arxiv.org/html/2503.09617v1#A8.SS4),规定了环境结构、响应格式、最佳实践、如何理解游戏输出等等。 + +## 回到 `airi-factorio` + +和 FLE 比起来,我们的实现显得相当幼稚,那我们要怎么改进 `airi-factorio` 呢? + +我不想写 Python,我只熟悉 TypeScript 和 Golang,很巧,我们最近也写了 [mcp-launcher](https://github.com/moeru-ai/mcp-launcher),一个适用于所有可能的 MCP 服务器的构建器,我们可以配合它来使用 Golang 来实现一个 MCP 服务器,然后让 LLM 来调用它。 + +那么结构图就发生了变化: + +
+ +![之前](./assets/structure-before.png) + +![之后](./assets/structure-after.png) + +
+ +玩家的聊天内容不再被推送给 LLM,而是储存在 [RconChat](https://gitlab.com/FishBus/rconchat) mod 中,LLM 通过 MCP 服务器来读取这些内容。用上了 MCP 服务器,就不需要让 LLM 来生成 Lua 代码了。 + +系统提示词方面,目前我们的提示词虽然是 AI 生成的,但依然不够清晰,主次不明确,我打算参考 FLE 的系统提示词来改进一下。 + +好的,又基本推翻了之前的所有设计,该重新开始了。 + +## 结束 + +感谢阅读,如果感兴趣,可以翻阅 FLE 的论文和 [代码](https://github.com/JackHopkins/factorio-learning-environment),也许我的理解有误,欢迎指正!这次的阅读也许不够深入,但是接下来我在按照我的思路来改进 `airi-factorio` 的时候,会需要反复阅读,在有进展时再更新。 + +这篇 DevLog 就到这里,祝大家周末愉快!