Note
欢迎使用版本 0.5.4!当前版本修复了关键的历史记录裁剪 Bug(HTTP 400 错误)和 Pydantic 模型兼容性问题。见本次更新
Important
0.5.0 版本加入了自定义工具的功能,会在配置文件夹创建 tools.py 文件。0.5.1 版本加入了提示词文件化的功能,会在配置文件夹创建 prompt 文件夹。0.5.2 版本加入了 Skills 技能系统并创建了 skills 文件夹。0.5.3 版本修复了一个关键的消息历史 Bug。0.5.4 版本修复了一个关键的历史裁剪 Bug 并改进了 Pydantic 兼容性。见Skills 技能。
目录(点击展示)
安装
在MCDR控制台中使用如下命令以安装插件(鉴于现版本的MCDR下载器并不稳定,使用此命令可能无法下载最新版,不建议使用此命令安装)
!!MCDR plugin install games_ai
或者在MCDR插件仓库中获取并安装到你的插件目录内
如果选择手动安装,请先安装Python包OpenAI和requests,使用如下命令安装
pip install openai requests
使用
在任何地方输入命令!!gamesai以显示这个插件的所有功能
有关!!gamesai的所有指令(点击展开)
!!gamesai的所有指令(点击展开)| 指令 | 用途 |
|---|---|
!!gamesai clear | 清除玩家的历史聊天记录,历史聊天记录与公共数据库无关 |
!!gamesai clearall | 清除所有玩家的历史聊天记录,历史聊天记录与公共数据库无关 |
!!gamesai reload | 重新加载插件配置文件 |
!!gamesai check | 检查插件更新 |
你也可以直接输入!!ask向AI提问或者聊天或者帮你做一些事情
有关!!ask的所有指令(点击展开)
!!ask的所有指令(点击展开)| 指令 | 用途 |
|---|---|
!!ask <content> | 向AI提问或者聊天或者帮你做一些事情,content为你想让AI做的事情或者你想问AI的问题 |
!!ask -m <model> <content> | 使用指定的模型向AI提问或者聊天或者帮你做一些事情,model为你想使用的模型的AI_ID或昵称,content为你想让AI做的事情或者你想问AI的问题 |
输入!!data获取有关数据库指令的信息
Tip
更新到0.3.0及以上版本时会自动添加数据库
有关!!gamesai的所有指令(点击展开)
!!gamesai的所有指令(点击展开)| 指令 | 用途 |
|---|---|
!!data write <key> <value> | 在公共数据库内添加一条数据,其中key不能包含空格,value可以是任意字符串 |
!!data add <key> <value> | 将value追加到公共数据库中的key中,不存在时自动创建新key |
!!data del <key> | 在公共数据库内删除一条数据,无论key是否存在 |
!!data read <key> | 读取公共数据库中key对应的value |
!!data list | 读取公共数据库中的所有内容 |
!!data list keys | 读取公共数据库中的所有key |
配置
默认配置文件结构如下:
{
"prefix": "[GamesAI]",
"permission": 3,
"max_history": 10,
"all_ai": {
"<Your AI ID>":{
"prompt": "你是一名成熟、稳重的Minecraft机器人工具,你的名字叫做“GamesAI”",
"ai_name": "[GamesAI]",
"base_url": "<Your API Base URL>",
"ai_model": "<Your AI Model>",
"api_key": "<Your API Key>",
"thinking": false
}
},
"default_ai": "<Your AI ID>"
}
以下是每个参数的简介:
1.prefix
值的类型: str
默认值: [GamesAI]
填入插件的名称,以在插件的回复之前加上一个前缀,可以包含Minecraft格式化代码
2.permission
值的类型:int
默认值:3
执行!!data等指令所必须达到的权限,见MCDR权限相关文档
3.max_history
值的类型: int
默认值: 10
填入每个玩家最大可的保留历史记录,与公共数据库无关
4.all_ai
值的类型: dict
默认值:见文件
填入所有的AI信息,由多个字典组成,每个字典为一个AI模型,字典的键即为插件内部的AI_ID
prompt: 这项配置用于为每个AI编写提示词。使用> xxx.md将提示词指向config/games_ai/prompt/xxx.md文件,不限文件类型
ai_name: 这项配置与prefix功能类似,但是你现在需要单独为每一个模型设置,可以包含Minecraft格式化代码
base_url, ai_model, api_key: 与以前的相关配置功能相同,但是你现在需要单独为每一个模型设置
thinking: 这项配置用于 启用/禁用 模型的思考模式,不填时默认为false,切勿为没有思考模式的模型启用此项,那可能会出错
5.default_ai
值的类型: str
默认值: <Your AI ID>
填入当用户直接使用!!ask时使用的模型,应该填入all_ai字典中的某一个键(即为插件内部的AI_ID),如果错填,会导致无法正常使用!!ask指令
工具、Skills 与自定义工具
工具
GamesAI插件提供了很多自带的工具,见下表。如果你想要更多的工具,可以选择向作者投稿或者选择自定义工具
点击查看所有的自带工具
| 工具ID | 传入参数 | 用途 |
|---|---|---|
| get_online_players | 无 | 获取服务器内在线的玩家列表。依赖于online_player_api插件,不存在时自动关闭此工具 |
| get_whitelist_name | 无 | 获取服务器完整的白名单列表。依赖于whitelist_api插件,不存在时自动关闭此工具 |
| add_to_whitelist | name | 将某个玩家添加到白名单中。依赖于whitelist_api插件,不存在时自动关闭此工具 |
| remove_from_whitelist | name | 将某个玩家从白名单删除。依赖于whitelist_api插件,不存在时自动关闭此工具 |
| search_minecraft_wiki | query | 让AI搜索Minecraft Wiki,以确保回答更准确 |
| calculator | expression | 简单的数学表达式计算器 |
| item_caculator | expression,single_limit | 数学表达式计算器,并将最终结果转换为物品计数法,即 盒、组、个,自动适应物品的堆叠数,不存在时默认使用64 |
| add_pos_pos | name,pos,dimension | 在指定位置添加一个坐标点。依赖于where2go或location_marker插件,两者都存在时,优先使用where2go,均不存在时,自动关闭此工具 |
| add_pos_here | name | 在玩家的位置添加一个坐标点,控制台执行时自动关闭此工具。依赖于where2go或location_marker插件,两者都存在时,优先使用where2go,均不存在时,自动关闭此工具 |
| remove_pos | name | 删除一个坐标点,where2go版本会自动将name转换为id。依赖于where2go或location_marker插件,两者都存在时,优先使用where2go,均不存在时,自动关闭此工具 |
| search_pos | name | 搜索一个坐标点。依赖于where2go或location_marker插件,两者都存在时,优先使用where2go,均不存在时,自动关闭此工具 |
| get_all_pos | 无 | 获取所有的坐标点列表.依赖于where2go或location_marker插件,两者都存在时,优先使用where2go,均不存在时,自动关闭此工具 |
| ai_read_data | key | 读取一条数据库内容 |
| ai_read_all_keys | 无 | 获取数据库中所有的键 |
| ai_write_data | key,value | 向数据库中写入一条数据(覆写模式) |
| ai_add_data | key,value | 向数据库中写入一条数据(追加模式) |
| read_skills | skills | 读取已注册的技能指导文件,引导 AI 执行特定任务 |
| ai_del_data | key | 删除数据库中的一条数据 |
Skills 技能
Skills 技能系统让你可以编写指导文件来规范 AI 处理特定任务的方式——例如白名单管理、假人控制等。
技能文件存放在 config/games_ai/skills/ 目录下,格式为 Markdown(.md)。要注册一项技能,编辑 config/games_ai/skills/skills.json。以下是一个示例配置(whitelist.md 和 player.md 仅为示例文件名,并非插件内置文件):
[
{
"file": "whitelist.md",
"description": "添加/删除/查询白名单时都应读取此技能文件"
},
{
"file": "player.md",
"description": "创建/控制/删除假人时必须读取此技能文件"
}
]
file— 技能文件名(相对于skills文件夹)。description— 展示给 AI 的简短提示,说明何时应当读取此技能。
技能注册后会出现在 AI 的系统提示中。AI 可以使用 read_skills 工具在执行相关任务前读取技能文件的完整内容。
Tip
Skills 就像 AI 的「标准作业程序 (SOP)」——确保 AI 每次都遵循正确的工作流程。
自定义工具
通过修改config/games_ai/tools/tools.py文件来实现自定义修改工具
先来看看默认值如何
from mcdreforged.command.command_source import CommandSource
from games_ai.games_ai_tool import register_tool
@register_tool(description="My Custom Tool")
def my_custom_tool(source: CommandSource, ai_prefix: str):
return "Tool execution completed"
Important
代码中的from games_ai.games_ai_tool import register_tool和函数定义前的@register_tool必须存在
可见,这是十分简单的结构。
接下来我将告诉你如何实践,比如下面的例子:搜索baidu.com
点击展开
想要知道如何实现搜索baidu.com,参考GamesAI源代码中的工具search_minecraft_wiki无疑是最好的选择:
@register_tool(description="搜索Minecraft Wiki以获取相关信息, 请不要使用此方法搜索与Minecraft无关的东西。如果返回了Search results页面, 你可以通过先浏览此页面, 再进行一次精确查询", tr_key="searching_minecraft_wiki", parameters={
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "要搜索的内容,例如某个物品、怪物、机制等的名称。"
}
},
"required": ["query"]
})
def search_minecraft_wiki(source: CommandSource, ai_prefix: str, query: str):
source.reply(f'{ai_prefix}{source.get_server().rtr("games_ai.tools.searching_minecraft_wiki", query=query)}')
lang = source.get_server().get_mcdr_language()
if lang == "en_us":
search_url = f"https://minecraft.wiki/?search={query}"
else:
search_url = f"https://zh.minecraft.wiki/?search={query}"
response = requests.get(search_url)
if response.status_code == 200:
return f"一下是搜索内容 {query} 的结果:\n{response.content.decode('utf-8')}"
else:
return "无法访问Minecraft Wiki进行搜索"
首先来看工具的注册,其中的description类似于提示词,是必填项,是给AI提供的;其中的tr_key是内部方法,外部编写tools.py时不需要包含此项;而parameters就是AI需要传入的参数,可根据实际情况决定是否填写,其中的properties用于填写所有的传入参数,其中的required项则表示有哪些参数是必填的,注意properties与函数定义中传入参数的位置关系,应该需要一一对应。
例如:
@register_tool(description="搜索百度")
但是,搜索百度肯定需要传入搜索内容,所以:
@register_tool(description="搜索百度", parameters={
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "要搜索的内容"
}
},
"required": ["query"]
})
好了,你已经学会如何注册工具了,接下来就可以写函数定义了:
def search_baidu(source: CommandSource, ai_prefix: str, query: str):
上面的代码中,source和ai_prefix项必须编写,因为它们始终会被传入
接下来写函数体:
def search_baidu(source: CommandSource, ai_prefix: str, query: str):
...
return ...
函数体中可以是任何你需要的操作,最后记得一定要return,否则AI将无法正确处理结果
tools.py的完整示例:
import requests
from games_ai.games_ai_tool import register_tool
@register_tool(
description="使用百度搜索互联网上的信息。当你需要查找实时信息、新闻、百科知识等时使用此工具。",
parameters={
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "要在百度搜索的关键词或问题"
}
},
"required": ["query"]
}
)
def search_baidu(source, ai_prefix: str, query: str):
source.reply(f'{ai_prefix}正在搜索百度:{query}...')
try:
url = "https://www.baidu.com/s"
headers = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36"
)
}
response = requests.get(url, params={"wd": query}, headers=headers, timeout=10)
if response.status_code != 200:
return f"百度搜索失败,HTTP 状态码:{response.status_code}"
# 简单提取页面文本(去除 HTML 标签)
import re
text = response.text
# 移除 script 和 style 标签内容
text = re.sub(r'<script[^>]*>.*?</script>', '', text, flags=re.DOTALL | re.IGNORECASE)
text = re.sub(r'<style[^>]*>.*?</style>', '', text, flags=re.DOTALL | re.IGNORECASE)
# 移除 HTML 标签
text = re.sub(r'<[^>]+>', '', text)
# 合并多余空白
text = re.sub(r'\s+', ' ', text).strip()
# 截断过长内容(保留前 3000 字符,适合 AI 上下文)
max_len = 3000
if len(text) > max_len:
text = text[:max_len] + "\n...(内容已截断)"
return f"百度搜索「{query}」的结果:\n{text}"
except requests.Timeout:
return "百度搜索请求超时,请稍后重试"
except Exception as e:
return f"百度搜索出错:{str(e)}"
本次更新
Version 0.5.4
1. 安全历史裁剪修复(关键)
修复了一个关键 Bug:历史记录裁剪逻辑(history[-max_len:])可能在工具调用/工具结果消息对之间切断。当历史列表超出保留上限时,从头部盲目切片可能删除包含 tool_calls 的 assistant 消息,却保留其对应的 tool 结果消息——产生孤立的工具消息。OpenAI 兼容 API 会以 HTTP 400 拒绝此类消息:"Messages with role 'tool' must be a response to a preceding message with 'tool_calls'"。
新增的 _safe_trim_history() 函数确保裁剪后的历史始终从完整的对话轮次边界(user 角色消息)开始,从根本上杜绝孤立的工具消息被发送到 API。
2. Pydantic 模型兼容性修复
修复了 _safe_trim_history() 中的 AttributeError: 'ChatCompletionMessage' object has no attribute 'get' 错误。对话历史列表混合存储了普通 dict 对象(用户消息和工具结果)和 Pydantic ChatCompletionMessage 模型实例(API 返回的 assistant 回复)。该函数现在能正确处理两种类型,正确访问 role 属性。
Version 0.5.3
1. 历史记录损坏修复(关键)
修复了一个关键 Bug:history.append(response_message) 将整个消息列表作为单个元素错误地追加到了对话历史中。这导致在工具调用后的第二次对话中,API 请求格式错误(HTTP 400: "invalid type: map, expected variant identifier")。现已改为正确追加单条消息 history.append(user_message)。
2. 按用户追踪工具调用计数
将全局变量 tool_count 替换为按用户、按 AI 实例的字典(user_tool_counts)。此前 tool_count 跨所有用户和对话持续累加且从不重置,导致历史保留上限(max_history * 2 + tool_count * 2)无限增长。现在每个用户的工具调用计数独立追踪,并在通过 !!gamesai clear 或 !!gamesai clearall 清除对话历史时自动归零。
3. Debug 模式显示修复
修复了一处笔误:在历史上限显示行中将未定义的变量 debug 修正为 debug_mode。此前开启 debug 模式时此处会触发 NameError 运行时错误。
Version 0.5.2
1. Skills 技能系统
Skills 技能系统是一种全新的 AI 行为引导方式。通过编写 Markdown 指导文件并在 skills.json 中注册,你可以精确控制 AI 在特定任务中的行为(如白名单管理、假人控制)。AI 会在执行相关操作前自动读取对应的技能文件。
config/games_ai/skills/skills.json— 技能注册文件。config/games_ai/skills/*.md— 技能指导文件。- 内置
read_skills工具供 AI 读取技能。
另外,本次更新修复了一些问题,并改进了 Python 3.14 兼容性。
鸣谢与声明
特别感谢望海公社服务器为此插件的测试提供了基础
AI(LLM)模型生成的一切内容与此插件无关
自定义工具造成的一切后果与本插件无关
许可证
MIT License, Copyright (c) 2026 yello
介绍文本来源:README.zh-CN.md