From 674189c06965b67c63a984ffcc10f312d261491c Mon Sep 17 00:00:00 2001 From: Negusonnn Date: Mon, 6 Apr 2026 16:21:25 +0800 Subject: [PATCH 1/6] Create README.md --- .../AIroleplay/README.md" | 247 ++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 "scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" diff --git "a/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" "b/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" new file mode 100644 index 0000000..a7a16fb --- /dev/null +++ "b/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" @@ -0,0 +1,247 @@ +# SealDiceAIroleplay + +> Vibe coded by Claude, conceived by Lelia. ฅ^•ﻌ•^ฅ +> 为海豹骰设计的 AI角色扮演回复插件,oc人大欢迎 + +--- + +## 项目简介 + +SealDiceAIroleplay 是一个海豹骰 JS 插件,通过接入 AI API,让你的骰子可以扮演自定义的角色人设。通过指令,玩家可以直接和骰子对话,骰子会以该角色的身份回应。 + +你可以自定义任何角色。按照格式填写角色设定后,AI 会以该角色的身份回应玩家,支持上下文记忆,同一会话内角色会记住对话内容。 + +**功能:** +- 自定义角色人设(名字、身份、性格、说话风格、人物关系) +- 短期上下文记忆(同一会话内) +- 支持 DeepSeek / Claude 等 AI API +- 接入海豹骰,玩家直接在 QQ 等平台使用指令对话 + +--- + +## 效果预览 + +``` +玩家:.hekate 你是谁? +骰子:十字路口的火炬为你点燃。我是赫卡特,你寻我何事? + +玩家:.hekate 我在寻找一条通往冥界的路。 +骰子:(沉默片刻)每一条路都通往冥界,只是时间早晚。你真正想问的,是能否活着回来。 +``` + +--- + +## 准备工作 + +你需要准备: + +- **海豹骰 SealDice 1.5.1** 或以上版本 +- **Python 3.8+** +- **一个 AI API Key**,推荐以下两个: + - [DeepSeek](https://www.deepseek.com) — 价格便宜,中文效果好,推荐新手使用 + - [Anthropic Claude](https://www.anthropic.com) — 质量更高,笔者认为的效果最好,适合对效果有更高要求的用户,但价格昂贵且大陆地区连接不稳定 +- 一台能运行 Python 的设备(本地电脑或云服务器均可) + +--- + +## 部署 Flask 服务 + +### 1. 下载文件 + +下载本仓库中的 `app.py` 和 `requirements.txt`,放在同一个文件夹里,例如 `~/aibot/`。 + +### 2. 安装依赖 + +```bash +pip install -r requirements.txt +``` + +✅ 成功:所有依赖安装完成,无报错 +❌ 失败:出现 `ERROR` 或 `Could not find a version`,请检查 Python 版本是否为 3.8+ + +### 3. 填写角色设定 + +用文本编辑器打开 `app.py`,找到顶部角色设定区域,按注释说明填写。详见下方「角色设定填写指南」。 + +同时填入你的 API Key: + +```python +AI_API_KEY = "你的API Key" +``` + +### 4. 启动服务 + +**本地运行:** + +```bash +cd ~/aibot +python app.py +``` + +✅ 成功:终端出现 `Running on http://0.0.0.0:5000` +❌ 失败:出现 `Address already in use`,说明5000端口被占用,换一个端口或关闭占用进程 + +**服务器后台运行(推荐):** + +```bash +cd ~/aibot +gunicorn -w 2 -b 0.0.0.0:5000 app:app --daemon +``` + +✅ 成功:命令执行后无报错,回到命令行 +❌ 失败:出现 `command not found: gunicorn`,请先运行 `pip install gunicorn` + +启动后可用以下命令测试服务是否正常: + +```bash +curl -X POST http://localhost:5000/chat \ + -H "Content-Type: application/json" \ + -d '{"message": "你好", "playerName": "测试"}' +``` + +✅ 成功:返回包含 `reply` 字段的 JSON +❌ 失败:返回 `Connection refused`,说明服务未启动 + +### 常见问题 + +**Q: 云服务器上启动了但外部访问不了?** +A: 检查服务器防火墙是否放行了5000端口。 + +**Q: API Key 填写后报错 `401`?** +A: API Key 填写有误,请检查是否复制完整。 + +**Q: 返回 `500` 错误?** +A: 查看终端日志,通常是 API Key 无效或余额不足。 + +--- + +## 安装 JS 插件 + +### 1. 下载文件 + +下载本仓库中的 `sealdiceAIroleplay.js`,用文本编辑器打开,找到顶部配置区填写: + +```javascript +// ===== 配置区 ===== +const FLASK_URL = 'http://你的IP:5000/chat'; // Flask 服务地址,必填 +const COMMAND_NAME = 'hekate'; // 指令名,玩家用 .指令名 触发,必填 +const CHAR_NAME = '赫卡特'; // 角色名,仅用于提示语显示,必填 +``` + +**Flask 服务地址如何填写:** +- 本地运行:填 `http://127.0.0.1:5000/chat` +- 云服务器运行:填 `http://你的服务器公网IP:5000/chat`,例如 `http://106.55.29.59:5000/chat` + - Linux 服务器查询公网IP:`curl ifconfig.me` + - Windows 本地查询IP:`ipconfig`,找到「IPv4 地址」 + +**指令名如何设置:** +- 指令名即玩家触发对话的命令,例如填 `hekate`,玩家发 `.hekate 你好` 即可触发 +- 建议用角色名的英文或拼音,3个字母以上 +- ⚠️ 避免使用和海豹骰内置指令相近的开头,例如 `r`、`ra`、`sc`、`a` 开头的短命令,容易被误解析 +- ⚠️ 指令名需要在 JS 插件配置区和后续使用中保持一致,改了这里记得同步更新 + +### 2. 上传插件 + +进入海豹骰后台 → 扩展功能 → JS扩展 → 上传插件,选择 `sealdiceAIroleplay.js`。 + +### 3. 重载 JS + +点击右上角「重载 JS」按钮。 + +✅ 成功:插件列表出现你的角色名,且「禁用指令」栏有你设置的指令名 +❌ 失败:插件列表显示「佚名」且无指令,点击「重载 JS」再试一次 + +### 4. 测试 + +在 QQ 或其他平台发送: + +``` +.hekate 你好 +``` + +✅ 成功:骰子会先发送一条等待提示,例如「赫卡特听见了你,请等待她的回音。」,随后返回角色回复 +❌ 失败:无任何回应,请检查 Flask 服务是否正常运行 + +> 💡 等待提示语来自 JS 插件中的设置,你可以在 `sealdiceAIroleplay.js` 里找到并修改成你喜欢的文字。 +> 💡 等待提示语可以删去,但强烈推荐保留——当角色迟迟没有回复时,它能帮助你快速判断是指令没有触发,还是 Flask 服务出现了问题。 + +### 常见问题 + +**Q: 上传后指令没有反应?** +A: 确认 Flask 服务正在运行,用 curl 测试服务是否正常(见上方部署章节)。 + +**Q: 提示「未设置快捷指令」?** +A: 指令名设置有问题,避免使用单个字母或以 `.a` 开头的名字。 + +**Q: 重载后插件失效?** +A: 这是海豹骰的已知缓存问题,重载 JS 不会清空已注册的扩展。删除插件后重新上传即可。 + +--- + +## 角色设定填写指南 + +打开 `app.py`,找到角色设定区域,按以下说明填写: + +| 变量 | 说明 | 示例 | +|------|------|------| +| `CHAR_NAME` | 角色主名 | 赫卡特 | +| `CHAR_ALIASES` | 别名,没有可留空 | 黑暗女神、十字路口的守护者 | +| `CHAR_ROLE` | 角色身份 | 魔法与月亮的掌管者,冥界的引路人 | +| `CHAR_WORLD` | 世界观背景 | 古希腊神话世界 | +| `CHAR_DESCRIPTION` | 对角色的简短描述 | 古老而强大的存在、普通的高中生、江湖游历的侠客 | +| `CHAR_PERSONALITY` | 性格 | 神秘而深邃,冷静但不冷漠 | +| `CHAR_SPEECH_STYLE` | 语言风格 | 简短有力,带有预言般的韵味 | +| `CHAR_SPEECH_FORMAT` | 语言格式,已预设可删改 | 动作描写用括号表示… | +| `CHAR_RESTRICTIONS` | 角色专属限制,填写角色能与不能 | 不称呼对方为「孩子」 | +| `CHAR_RELATIONSHIPS` | 人物关系,每行一个 | 宙斯:诸神之王,我与他井水不犯河水 | + +> 💡 填写越详细,AI 的角色扮演效果越好。人物关系部分尤其推荐填写,当玩家提及相关人物时,角色会有对应的情绪反应。 + +--- + +## 隐私说明 + +1. 只有通过指令触发的消息才会发送给 AI,普通聊天内容不会被读取 +2. 对话记录仅存于内存,服务重启后自动清空,不写入任何文件 +3. 本项目调用方式不会主动上传数据,但最终取决于你所使用的 AI API 服务商的隐私条款。例如 [Anthropic Claude](https://www.anthropic.com) 和 [DeepSeek](https://www.deepseek.com) 均在其条款中说明不将 API 调用数据用于模型训练,使用其他服务商请自行查阅对应条款。 + +--- + +## 已知限制 + +- 重启 Flask 服务后,所有对话记忆清空 +- 当前不支持跨会话持久记忆 +- 对话历史过长时可能超出 API token 限制,建议定期重启服务清空记忆 +- 当前版本默认使用 DeepSeek API 格式,使用 Claude 等其他格式需自行修改 `app.py` 中的请求部分 + +--- + +## 未来计划 + +- [ ] 持久化记忆(跨会话记忆、人物关系记忆) +- [ ] 更丰富的应用场景,例如在沙盒模组中扮演随机路人 NPC,丰富玩家探索体验 +- [ ] 卫星:AI角色补位,顶替扮演、骰点等 + +--- + +## 致谢 + +- [Anthropic Claude](https://www.anthropic.com) — 本项目的开发伙伴,笔者认为目前效果最佳的 AI,超级昂贵但超级好用 ฅ^•ﻌ•^ฅ +- [DeepSeek](https://www.deepseek.com) — 默认 AI 后端,便宜好用 +- [SealDice](https://sealdice.com) — 骰子平台支持 + +--- + +## 写在最后 + +SealDiceAIroleplay 的初衷绝对不是认为AI创作可以替代人类创作!我只是试图在原本的固定自定义回复中,多探索一些机动的可能性,从而丰富体验。 + +人类的赞歌是勇气的赞歌、是智慧的赞歌,在任何模组里任何伟大的冒险旅途,都离不开每一位作者、玩家、主持人的共同创作。 + +向伟大的创作者致敬!祝诸位骰运昌隆,所历皆传奇。 + +感恩赫卡特女神及祂的尊名、仁慈和智慧🔥 + +--- + +*Vibe coded by Claude, conceived by Lelia. ฅ^•ﻌ•^ฅ* From d6735a401588ffa5b7f24f44c16bac1ac32d959e Mon Sep 17 00:00:00 2001 From: Negusonnn Date: Mon, 6 Apr 2026 16:23:45 +0800 Subject: [PATCH 2/6] Add files via upload --- .../AIroleplay/app.py" | 130 ++++++++++++++++++ .../AIroleplay/requirements.txt" | 3 + .../AIroleplay/sealdiceAIroleplay.js" | 56 ++++++++ 3 files changed, 189 insertions(+) create mode 100644 "scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/app.py" create mode 100644 "scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/requirements.txt" create mode 100644 "scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/sealdiceAIroleplay.js" diff --git "a/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/app.py" "b/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/app.py" new file mode 100644 index 0000000..384f14d --- /dev/null +++ "b/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/app.py" @@ -0,0 +1,130 @@ +from flask import Flask, request, jsonify +import requests + +app = Flask(__name__) + +# ===== 请在这里填写你的 API Key 和服务地址 ===== +AI_API_KEY = "你的AI API Key" # 如 DeepSeek、Claude 等 +AI_API_URL = "https://api.deepseek.com/chat/completions" # 默认使用 DeepSeek +AI_MODEL = "deepseek-chat" # 模型名称 + +# 其他服务商参考: +# DeepSeek(推荐入门): +# URL: https://api.deepseek.com/chat/completions +# Model: deepseek-chat +# 申请:https://www.deepseek.com +# +# Anthropic Claude(推荐追求质量): +# Claude 使用独立 API 格式,需替换 app.py 中的请求部分,详见: +# https://www.anthropic.com +# 笔者认为效果最佳,但价格较高且大陆地区连接不稳定,物有所值。 +# +# OpenAI GPT(兼容格式): +# URL: https://api.openai.com/v1/chat/completions +# Model: gpt-4o 等 +# ================================================ + +# ===== 隐私说明 ===== +# 1. 只有通过指令触发的消息才会发送给 AI,普通聊天内容不会被读取 +# 2. 对话记录仅存于内存,服务重启后自动清空,不写入任何文件 +# 3. 本项目调用方式不会主动上传数据,但最终取决于你所使用的 AI API 服务商的隐私条款。 +# 例如 Anthropic Claude(https://www.anthropic.com)和 DeepSeek(https://www.deepseek.com) +# 均在其条款中说明不将 API 调用数据用于模型训练,使用其他服务商请自行查阅对应条款。 +# ==================== + + +# ===== 角色设定,请在这里填写你想扮演的角色 ===== + +CHAR_NAME = "赫卡特" # 角色主名 +CHAR_ALIASES = "黑暗女神、十字路口的守护者" # 别名(没有可留空) +CHAR_ROLE = "魔法与月亮的掌管者,冥界的引路人" # 身份 +CHAR_WORLD = "古希腊神话世界" # 世界观背景 +CHAR_DESCRIPTION = "古老而强大的存在" # 对角色的简短描述,如「普通的高中生」「江湖游历的侠客」 +CHAR_PERSONALITY = "神秘而深邃,冷静但不冷漠,见过无数灵魂的来去,对世人保持悲悯" # 性格 +CHAR_SPEECH_STYLE = "简短有力,带有预言般的韵味,偶尔用隐喻和暗语说话" # 语言风格 + +# 语言格式——已预设,可删改 +CHAR_SPEECH_FORMAT = """ +- 动作描写用括号表示,仅在推进剧情的关键时刻使用,日常对话不加 +- 回复控制在150字以内 +""" + +# 限制条件——请填写你的角色专属的能与不能 +CHAR_RESTRICTIONS = """ +- 不称呼对方为「孩子」或任何俗世间长辈对晚辈的称谓 +""" + +# 人物关系——每行一个,格式:人物名:关系描述,没有可留空 +CHAR_RELATIONSHIPS = """ +宙斯:诸神之王,我与他井水不犯河水。 +珀耳塞福涅:冥界的王后,我为她点燃火炬。 +赫敏斯:信使之神,十字路口我们时常相遇。 +""" + +# ================================================ + + +SYSTEM_PROMPT = f"""你是{CHAR_NAME},亦名{CHAR_ALIASES},{CHAR_ROLE}。 + +你存在于{CHAR_WORLD}中,是一个{CHAR_DESCRIPTION}。 + +【性格】 +{CHAR_PERSONALITY}。 + +【语言风格】 +{CHAR_SPEECH_STYLE}。 + +【语言格式】 +{CHAR_SPEECH_FORMAT} + +【限制条件】 +{CHAR_RESTRICTIONS} + +【人物关系】 +{CHAR_RELATIONSHIPS} +""" + + +# ===== 记忆系统 ===== +# 当前版本支持短期上下文记忆,即每位玩家在同一次会话中,角色会记住对话内容。 +# 重启服务后记忆清空。 +# 如需持久化记忆(跨会话记忆、人物关系记忆),可扩展此处逻辑, +# 例如将 conversation_history 存入本地文件或数据库。 +conversation_history = {} + + +@app.route('/chat', methods=['POST']) +def chat(): + data = request.json + user_message = data.get('message', '') + player_name = data.get('playerName', '访客') + + if player_name not in conversation_history: + conversation_history[player_name] = [] + + conversation_history[player_name].append({'role': 'user', 'content': user_message}) + + messages = [{'role': 'system', 'content': SYSTEM_PROMPT}] + conversation_history[player_name] + + response = requests.post( + AI_API_URL, + headers={ + 'Authorization': f'Bearer {AI_API_KEY}', + 'Content-Type': 'application/json' + }, + json={ + 'model': AI_MODEL, + 'messages': messages, + 'max_tokens': 300 + } + ) + result = response.json() + reply = result['choices'][0]['message']['content'] + + conversation_history[player_name].append({'role': 'assistant', 'content': reply}) + + return jsonify({'reply': reply}) + + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000) diff --git "a/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/requirements.txt" "b/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/requirements.txt" new file mode 100644 index 0000000..4287cd1 --- /dev/null +++ "b/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/requirements.txt" @@ -0,0 +1,3 @@ +flask +requests +gunicorn \ No newline at end of file diff --git "a/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/sealdiceAIroleplay.js" "b/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/sealdiceAIroleplay.js" new file mode 100644 index 0000000..e545156 --- /dev/null +++ "b/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/sealdiceAIroleplay.js" @@ -0,0 +1,56 @@ +// ==UserScript== +// @name SealDiceAIroleplay +// @author Lelia +// @version 1.0.0 +// @description 为海豹骰设计的 AI 角色扮演回复插件 | Vibe coded by Claude, conceived by Lelia. +// @timestamp 1700000000 +// @license Apache-2 +// @homepageURL https://github.com/Lelia7OR/SealDiceAIroleplay +// ==/UserScript== + +// ===== 配置区 ===== +// ⚠️ 以下三项请按你的实际情况修改 +const FLASK_URL = 'http://你的IP:5000/chat'; // Flask 服务地址,必填 +const COMMAND_NAME = 'hekate'; // 指令名,玩家用 .指令名 触发,必填 +const CHAR_NAME = '赫卡特'; // 角色名,仅用于提示语显示,必填 +// ================== + +// ===== 提示语,可按喜好修改 ===== +const WAIT_MSG = `${CHAR_NAME}听见了你,请等待她的回音。`; // 可删除,但强烈推荐保留,便于排查问题 +const ERROR_MSG = `${CHAR_NAME}暂时无法回应,请稍后再试。`; // 可修改 +// ================================ + +// ⚠️ 以下内容为逻辑部分,请勿修改 +let ext = seal.ext.find(COMMAND_NAME); +if (!ext) { + ext = seal.ext.new(COMMAND_NAME, 'Lelia', '1.0.0'); + seal.ext.register(ext); +} + +const cmd = seal.ext.newCmdItemInfo(); +cmd.name = COMMAND_NAME; +cmd.help = `和${CHAR_NAME}对话,例如:.${COMMAND_NAME} 你好`; +cmd.solve = (ctx, msg, cmdArgs) => { + const userMessage = cmdArgs.rawArgs; + if (!userMessage) { + seal.replyToSender(ctx, msg, `请输入你想说的话,例如:.${COMMAND_NAME} 你好`); + return seal.ext.newCmdExecuteResult(true); + } + + const playerName = ctx.player.name; + + seal.replyToSender(ctx, msg, WAIT_MSG); + + fetch(FLASK_URL, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ message: userMessage, playerName: playerName }) + }) + .then(res => res.json()) + .then(data => { seal.replyToSender(ctx, msg, data.reply); }) + .catch(err => { seal.replyToSender(ctx, msg, ERROR_MSG); }); + + return seal.ext.newCmdExecuteResult(true); +}; + +ext.cmdMap[COMMAND_NAME] = cmd; From ed0fe0cd67edbfb8affcd810cafc5b8b59a82ba3 Mon Sep 17 00:00:00 2001 From: Negusonnn Date: Mon, 6 Apr 2026 16:25:37 +0800 Subject: [PATCH 3/6] =?UTF-8?q?Delete=20scripts/=E5=A8=B1=E4=B9=90?= =?UTF-8?q?=E5=90=91/scripts/=E5=A8=B1=E4=B9=90=E5=90=91/AIroleplay=20dire?= =?UTF-8?q?ctory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AIroleplay/README.md" | 247 ------------------ .../AIroleplay/app.py" | 130 --------- .../AIroleplay/requirements.txt" | 3 - .../AIroleplay/sealdiceAIroleplay.js" | 56 ---- 4 files changed, 436 deletions(-) delete mode 100644 "scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" delete mode 100644 "scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/app.py" delete mode 100644 "scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/requirements.txt" delete mode 100644 "scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/sealdiceAIroleplay.js" diff --git "a/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" "b/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" deleted file mode 100644 index a7a16fb..0000000 --- "a/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" +++ /dev/null @@ -1,247 +0,0 @@ -# SealDiceAIroleplay - -> Vibe coded by Claude, conceived by Lelia. ฅ^•ﻌ•^ฅ -> 为海豹骰设计的 AI角色扮演回复插件,oc人大欢迎 - ---- - -## 项目简介 - -SealDiceAIroleplay 是一个海豹骰 JS 插件,通过接入 AI API,让你的骰子可以扮演自定义的角色人设。通过指令,玩家可以直接和骰子对话,骰子会以该角色的身份回应。 - -你可以自定义任何角色。按照格式填写角色设定后,AI 会以该角色的身份回应玩家,支持上下文记忆,同一会话内角色会记住对话内容。 - -**功能:** -- 自定义角色人设(名字、身份、性格、说话风格、人物关系) -- 短期上下文记忆(同一会话内) -- 支持 DeepSeek / Claude 等 AI API -- 接入海豹骰,玩家直接在 QQ 等平台使用指令对话 - ---- - -## 效果预览 - -``` -玩家:.hekate 你是谁? -骰子:十字路口的火炬为你点燃。我是赫卡特,你寻我何事? - -玩家:.hekate 我在寻找一条通往冥界的路。 -骰子:(沉默片刻)每一条路都通往冥界,只是时间早晚。你真正想问的,是能否活着回来。 -``` - ---- - -## 准备工作 - -你需要准备: - -- **海豹骰 SealDice 1.5.1** 或以上版本 -- **Python 3.8+** -- **一个 AI API Key**,推荐以下两个: - - [DeepSeek](https://www.deepseek.com) — 价格便宜,中文效果好,推荐新手使用 - - [Anthropic Claude](https://www.anthropic.com) — 质量更高,笔者认为的效果最好,适合对效果有更高要求的用户,但价格昂贵且大陆地区连接不稳定 -- 一台能运行 Python 的设备(本地电脑或云服务器均可) - ---- - -## 部署 Flask 服务 - -### 1. 下载文件 - -下载本仓库中的 `app.py` 和 `requirements.txt`,放在同一个文件夹里,例如 `~/aibot/`。 - -### 2. 安装依赖 - -```bash -pip install -r requirements.txt -``` - -✅ 成功:所有依赖安装完成,无报错 -❌ 失败:出现 `ERROR` 或 `Could not find a version`,请检查 Python 版本是否为 3.8+ - -### 3. 填写角色设定 - -用文本编辑器打开 `app.py`,找到顶部角色设定区域,按注释说明填写。详见下方「角色设定填写指南」。 - -同时填入你的 API Key: - -```python -AI_API_KEY = "你的API Key" -``` - -### 4. 启动服务 - -**本地运行:** - -```bash -cd ~/aibot -python app.py -``` - -✅ 成功:终端出现 `Running on http://0.0.0.0:5000` -❌ 失败:出现 `Address already in use`,说明5000端口被占用,换一个端口或关闭占用进程 - -**服务器后台运行(推荐):** - -```bash -cd ~/aibot -gunicorn -w 2 -b 0.0.0.0:5000 app:app --daemon -``` - -✅ 成功:命令执行后无报错,回到命令行 -❌ 失败:出现 `command not found: gunicorn`,请先运行 `pip install gunicorn` - -启动后可用以下命令测试服务是否正常: - -```bash -curl -X POST http://localhost:5000/chat \ - -H "Content-Type: application/json" \ - -d '{"message": "你好", "playerName": "测试"}' -``` - -✅ 成功:返回包含 `reply` 字段的 JSON -❌ 失败:返回 `Connection refused`,说明服务未启动 - -### 常见问题 - -**Q: 云服务器上启动了但外部访问不了?** -A: 检查服务器防火墙是否放行了5000端口。 - -**Q: API Key 填写后报错 `401`?** -A: API Key 填写有误,请检查是否复制完整。 - -**Q: 返回 `500` 错误?** -A: 查看终端日志,通常是 API Key 无效或余额不足。 - ---- - -## 安装 JS 插件 - -### 1. 下载文件 - -下载本仓库中的 `sealdiceAIroleplay.js`,用文本编辑器打开,找到顶部配置区填写: - -```javascript -// ===== 配置区 ===== -const FLASK_URL = 'http://你的IP:5000/chat'; // Flask 服务地址,必填 -const COMMAND_NAME = 'hekate'; // 指令名,玩家用 .指令名 触发,必填 -const CHAR_NAME = '赫卡特'; // 角色名,仅用于提示语显示,必填 -``` - -**Flask 服务地址如何填写:** -- 本地运行:填 `http://127.0.0.1:5000/chat` -- 云服务器运行:填 `http://你的服务器公网IP:5000/chat`,例如 `http://106.55.29.59:5000/chat` - - Linux 服务器查询公网IP:`curl ifconfig.me` - - Windows 本地查询IP:`ipconfig`,找到「IPv4 地址」 - -**指令名如何设置:** -- 指令名即玩家触发对话的命令,例如填 `hekate`,玩家发 `.hekate 你好` 即可触发 -- 建议用角色名的英文或拼音,3个字母以上 -- ⚠️ 避免使用和海豹骰内置指令相近的开头,例如 `r`、`ra`、`sc`、`a` 开头的短命令,容易被误解析 -- ⚠️ 指令名需要在 JS 插件配置区和后续使用中保持一致,改了这里记得同步更新 - -### 2. 上传插件 - -进入海豹骰后台 → 扩展功能 → JS扩展 → 上传插件,选择 `sealdiceAIroleplay.js`。 - -### 3. 重载 JS - -点击右上角「重载 JS」按钮。 - -✅ 成功:插件列表出现你的角色名,且「禁用指令」栏有你设置的指令名 -❌ 失败:插件列表显示「佚名」且无指令,点击「重载 JS」再试一次 - -### 4. 测试 - -在 QQ 或其他平台发送: - -``` -.hekate 你好 -``` - -✅ 成功:骰子会先发送一条等待提示,例如「赫卡特听见了你,请等待她的回音。」,随后返回角色回复 -❌ 失败:无任何回应,请检查 Flask 服务是否正常运行 - -> 💡 等待提示语来自 JS 插件中的设置,你可以在 `sealdiceAIroleplay.js` 里找到并修改成你喜欢的文字。 -> 💡 等待提示语可以删去,但强烈推荐保留——当角色迟迟没有回复时,它能帮助你快速判断是指令没有触发,还是 Flask 服务出现了问题。 - -### 常见问题 - -**Q: 上传后指令没有反应?** -A: 确认 Flask 服务正在运行,用 curl 测试服务是否正常(见上方部署章节)。 - -**Q: 提示「未设置快捷指令」?** -A: 指令名设置有问题,避免使用单个字母或以 `.a` 开头的名字。 - -**Q: 重载后插件失效?** -A: 这是海豹骰的已知缓存问题,重载 JS 不会清空已注册的扩展。删除插件后重新上传即可。 - ---- - -## 角色设定填写指南 - -打开 `app.py`,找到角色设定区域,按以下说明填写: - -| 变量 | 说明 | 示例 | -|------|------|------| -| `CHAR_NAME` | 角色主名 | 赫卡特 | -| `CHAR_ALIASES` | 别名,没有可留空 | 黑暗女神、十字路口的守护者 | -| `CHAR_ROLE` | 角色身份 | 魔法与月亮的掌管者,冥界的引路人 | -| `CHAR_WORLD` | 世界观背景 | 古希腊神话世界 | -| `CHAR_DESCRIPTION` | 对角色的简短描述 | 古老而强大的存在、普通的高中生、江湖游历的侠客 | -| `CHAR_PERSONALITY` | 性格 | 神秘而深邃,冷静但不冷漠 | -| `CHAR_SPEECH_STYLE` | 语言风格 | 简短有力,带有预言般的韵味 | -| `CHAR_SPEECH_FORMAT` | 语言格式,已预设可删改 | 动作描写用括号表示… | -| `CHAR_RESTRICTIONS` | 角色专属限制,填写角色能与不能 | 不称呼对方为「孩子」 | -| `CHAR_RELATIONSHIPS` | 人物关系,每行一个 | 宙斯:诸神之王,我与他井水不犯河水 | - -> 💡 填写越详细,AI 的角色扮演效果越好。人物关系部分尤其推荐填写,当玩家提及相关人物时,角色会有对应的情绪反应。 - ---- - -## 隐私说明 - -1. 只有通过指令触发的消息才会发送给 AI,普通聊天内容不会被读取 -2. 对话记录仅存于内存,服务重启后自动清空,不写入任何文件 -3. 本项目调用方式不会主动上传数据,但最终取决于你所使用的 AI API 服务商的隐私条款。例如 [Anthropic Claude](https://www.anthropic.com) 和 [DeepSeek](https://www.deepseek.com) 均在其条款中说明不将 API 调用数据用于模型训练,使用其他服务商请自行查阅对应条款。 - ---- - -## 已知限制 - -- 重启 Flask 服务后,所有对话记忆清空 -- 当前不支持跨会话持久记忆 -- 对话历史过长时可能超出 API token 限制,建议定期重启服务清空记忆 -- 当前版本默认使用 DeepSeek API 格式,使用 Claude 等其他格式需自行修改 `app.py` 中的请求部分 - ---- - -## 未来计划 - -- [ ] 持久化记忆(跨会话记忆、人物关系记忆) -- [ ] 更丰富的应用场景,例如在沙盒模组中扮演随机路人 NPC,丰富玩家探索体验 -- [ ] 卫星:AI角色补位,顶替扮演、骰点等 - ---- - -## 致谢 - -- [Anthropic Claude](https://www.anthropic.com) — 本项目的开发伙伴,笔者认为目前效果最佳的 AI,超级昂贵但超级好用 ฅ^•ﻌ•^ฅ -- [DeepSeek](https://www.deepseek.com) — 默认 AI 后端,便宜好用 -- [SealDice](https://sealdice.com) — 骰子平台支持 - ---- - -## 写在最后 - -SealDiceAIroleplay 的初衷绝对不是认为AI创作可以替代人类创作!我只是试图在原本的固定自定义回复中,多探索一些机动的可能性,从而丰富体验。 - -人类的赞歌是勇气的赞歌、是智慧的赞歌,在任何模组里任何伟大的冒险旅途,都离不开每一位作者、玩家、主持人的共同创作。 - -向伟大的创作者致敬!祝诸位骰运昌隆,所历皆传奇。 - -感恩赫卡特女神及祂的尊名、仁慈和智慧🔥 - ---- - -*Vibe coded by Claude, conceived by Lelia. ฅ^•ﻌ•^ฅ* diff --git "a/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/app.py" "b/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/app.py" deleted file mode 100644 index 384f14d..0000000 --- "a/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/app.py" +++ /dev/null @@ -1,130 +0,0 @@ -from flask import Flask, request, jsonify -import requests - -app = Flask(__name__) - -# ===== 请在这里填写你的 API Key 和服务地址 ===== -AI_API_KEY = "你的AI API Key" # 如 DeepSeek、Claude 等 -AI_API_URL = "https://api.deepseek.com/chat/completions" # 默认使用 DeepSeek -AI_MODEL = "deepseek-chat" # 模型名称 - -# 其他服务商参考: -# DeepSeek(推荐入门): -# URL: https://api.deepseek.com/chat/completions -# Model: deepseek-chat -# 申请:https://www.deepseek.com -# -# Anthropic Claude(推荐追求质量): -# Claude 使用独立 API 格式,需替换 app.py 中的请求部分,详见: -# https://www.anthropic.com -# 笔者认为效果最佳,但价格较高且大陆地区连接不稳定,物有所值。 -# -# OpenAI GPT(兼容格式): -# URL: https://api.openai.com/v1/chat/completions -# Model: gpt-4o 等 -# ================================================ - -# ===== 隐私说明 ===== -# 1. 只有通过指令触发的消息才会发送给 AI,普通聊天内容不会被读取 -# 2. 对话记录仅存于内存,服务重启后自动清空,不写入任何文件 -# 3. 本项目调用方式不会主动上传数据,但最终取决于你所使用的 AI API 服务商的隐私条款。 -# 例如 Anthropic Claude(https://www.anthropic.com)和 DeepSeek(https://www.deepseek.com) -# 均在其条款中说明不将 API 调用数据用于模型训练,使用其他服务商请自行查阅对应条款。 -# ==================== - - -# ===== 角色设定,请在这里填写你想扮演的角色 ===== - -CHAR_NAME = "赫卡特" # 角色主名 -CHAR_ALIASES = "黑暗女神、十字路口的守护者" # 别名(没有可留空) -CHAR_ROLE = "魔法与月亮的掌管者,冥界的引路人" # 身份 -CHAR_WORLD = "古希腊神话世界" # 世界观背景 -CHAR_DESCRIPTION = "古老而强大的存在" # 对角色的简短描述,如「普通的高中生」「江湖游历的侠客」 -CHAR_PERSONALITY = "神秘而深邃,冷静但不冷漠,见过无数灵魂的来去,对世人保持悲悯" # 性格 -CHAR_SPEECH_STYLE = "简短有力,带有预言般的韵味,偶尔用隐喻和暗语说话" # 语言风格 - -# 语言格式——已预设,可删改 -CHAR_SPEECH_FORMAT = """ -- 动作描写用括号表示,仅在推进剧情的关键时刻使用,日常对话不加 -- 回复控制在150字以内 -""" - -# 限制条件——请填写你的角色专属的能与不能 -CHAR_RESTRICTIONS = """ -- 不称呼对方为「孩子」或任何俗世间长辈对晚辈的称谓 -""" - -# 人物关系——每行一个,格式:人物名:关系描述,没有可留空 -CHAR_RELATIONSHIPS = """ -宙斯:诸神之王,我与他井水不犯河水。 -珀耳塞福涅:冥界的王后,我为她点燃火炬。 -赫敏斯:信使之神,十字路口我们时常相遇。 -""" - -# ================================================ - - -SYSTEM_PROMPT = f"""你是{CHAR_NAME},亦名{CHAR_ALIASES},{CHAR_ROLE}。 - -你存在于{CHAR_WORLD}中,是一个{CHAR_DESCRIPTION}。 - -【性格】 -{CHAR_PERSONALITY}。 - -【语言风格】 -{CHAR_SPEECH_STYLE}。 - -【语言格式】 -{CHAR_SPEECH_FORMAT} - -【限制条件】 -{CHAR_RESTRICTIONS} - -【人物关系】 -{CHAR_RELATIONSHIPS} -""" - - -# ===== 记忆系统 ===== -# 当前版本支持短期上下文记忆,即每位玩家在同一次会话中,角色会记住对话内容。 -# 重启服务后记忆清空。 -# 如需持久化记忆(跨会话记忆、人物关系记忆),可扩展此处逻辑, -# 例如将 conversation_history 存入本地文件或数据库。 -conversation_history = {} - - -@app.route('/chat', methods=['POST']) -def chat(): - data = request.json - user_message = data.get('message', '') - player_name = data.get('playerName', '访客') - - if player_name not in conversation_history: - conversation_history[player_name] = [] - - conversation_history[player_name].append({'role': 'user', 'content': user_message}) - - messages = [{'role': 'system', 'content': SYSTEM_PROMPT}] + conversation_history[player_name] - - response = requests.post( - AI_API_URL, - headers={ - 'Authorization': f'Bearer {AI_API_KEY}', - 'Content-Type': 'application/json' - }, - json={ - 'model': AI_MODEL, - 'messages': messages, - 'max_tokens': 300 - } - ) - result = response.json() - reply = result['choices'][0]['message']['content'] - - conversation_history[player_name].append({'role': 'assistant', 'content': reply}) - - return jsonify({'reply': reply}) - - -if __name__ == '__main__': - app.run(host='0.0.0.0', port=5000) diff --git "a/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/requirements.txt" "b/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/requirements.txt" deleted file mode 100644 index 4287cd1..0000000 --- "a/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/requirements.txt" +++ /dev/null @@ -1,3 +0,0 @@ -flask -requests -gunicorn \ No newline at end of file diff --git "a/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/sealdiceAIroleplay.js" "b/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/sealdiceAIroleplay.js" deleted file mode 100644 index e545156..0000000 --- "a/scripts/\345\250\261\344\271\220\345\220\221/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/sealdiceAIroleplay.js" +++ /dev/null @@ -1,56 +0,0 @@ -// ==UserScript== -// @name SealDiceAIroleplay -// @author Lelia -// @version 1.0.0 -// @description 为海豹骰设计的 AI 角色扮演回复插件 | Vibe coded by Claude, conceived by Lelia. -// @timestamp 1700000000 -// @license Apache-2 -// @homepageURL https://github.com/Lelia7OR/SealDiceAIroleplay -// ==/UserScript== - -// ===== 配置区 ===== -// ⚠️ 以下三项请按你的实际情况修改 -const FLASK_URL = 'http://你的IP:5000/chat'; // Flask 服务地址,必填 -const COMMAND_NAME = 'hekate'; // 指令名,玩家用 .指令名 触发,必填 -const CHAR_NAME = '赫卡特'; // 角色名,仅用于提示语显示,必填 -// ================== - -// ===== 提示语,可按喜好修改 ===== -const WAIT_MSG = `${CHAR_NAME}听见了你,请等待她的回音。`; // 可删除,但强烈推荐保留,便于排查问题 -const ERROR_MSG = `${CHAR_NAME}暂时无法回应,请稍后再试。`; // 可修改 -// ================================ - -// ⚠️ 以下内容为逻辑部分,请勿修改 -let ext = seal.ext.find(COMMAND_NAME); -if (!ext) { - ext = seal.ext.new(COMMAND_NAME, 'Lelia', '1.0.0'); - seal.ext.register(ext); -} - -const cmd = seal.ext.newCmdItemInfo(); -cmd.name = COMMAND_NAME; -cmd.help = `和${CHAR_NAME}对话,例如:.${COMMAND_NAME} 你好`; -cmd.solve = (ctx, msg, cmdArgs) => { - const userMessage = cmdArgs.rawArgs; - if (!userMessage) { - seal.replyToSender(ctx, msg, `请输入你想说的话,例如:.${COMMAND_NAME} 你好`); - return seal.ext.newCmdExecuteResult(true); - } - - const playerName = ctx.player.name; - - seal.replyToSender(ctx, msg, WAIT_MSG); - - fetch(FLASK_URL, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ message: userMessage, playerName: playerName }) - }) - .then(res => res.json()) - .then(data => { seal.replyToSender(ctx, msg, data.reply); }) - .catch(err => { seal.replyToSender(ctx, msg, ERROR_MSG); }); - - return seal.ext.newCmdExecuteResult(true); -}; - -ext.cmdMap[COMMAND_NAME] = cmd; From 283e1bd5eb2058baa15533ec1158a531fa32d197 Mon Sep 17 00:00:00 2001 From: Negusonnn Date: Mon, 6 Apr 2026 16:27:31 +0800 Subject: [PATCH 4/6] Create README for SealDiceAIroleplay plugin Add README for SealDiceAIroleplay plugin with setup instructions and features. --- .../AIroleplay/README.md" | 247 ++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 "scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" diff --git "a/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" "b/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" new file mode 100644 index 0000000..3836327 --- /dev/null +++ "b/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" @@ -0,0 +1,247 @@ +# SealDiceAIroleplay + +> Vibe coded by Claude, conceived by Lelia. ฅ^•ﻌ•^ฅ +> 为海豹骰设计的 AI角色扮演回复插件,方便oc人随时和自己的骰子对话 + +--- + +## 项目简介 + +SealDiceAIroleplay 是一个海豹骰 JS 插件,通过接入 AI API,让你的骰子可以扮演自定义的角色人设。通过指令,玩家可以直接和骰子对话,骰子会以该角色的身份回应。 + +按照格式填写角色设定后,AI 会以该角色的身份回应玩家,支持上下文记忆。 + +**功能:** +- 自定义角色人设(名字、身份、性格、说话风格、人物关系) +- 短期上下文记忆(同一会话内) +- 支持 DeepSeek / Claude 等 AI API +- 海豹骰插件,可以直接在QQ内部用指令使用 + +--- + +## 效果预览 + +``` +玩家:.hekate 你是谁? +骰子:十字路口的火炬为你点燃。我是赫卡特,你寻我何事? + +玩家:.hekate 我在寻找一条通往冥界的路。 +骰子:(沉默片刻)每一条路都通往冥界,只是时间早晚。你真正想问的,是能否活着回来。 +``` + +--- + +## 准备工作 + +你需要准备: + +- **海豹骰 SealDice 1.5.1** 或以上版本 +- **Python 3.8+** +- **一个 AI API Key**,推荐以下两个: + - [DeepSeek](https://www.deepseek.com) — 价格便宜,中文效果好,推荐新手使用 + - [Anthropic Claude](https://www.anthropic.com) — 质量更高,笔者认为的效果最好,适合对效果有更高要求的用户,但价格昂贵且大陆地区连接不稳定 +- 一台能运行 Python 的设备(本地电脑或云服务器均可) + +--- + +## 部署 Flask 服务 + +### 1. 下载文件 + +下载本仓库中的 `app.py` 和 `requirements.txt`,放在同一个文件夹里,例如 `~/aibot/`。 + +### 2. 安装依赖 + +```bash +pip install -r requirements.txt +``` + +✅ 成功:所有依赖安装完成,无报错 +❌ 失败:出现 `ERROR` 或 `Could not find a version`,请检查 Python 版本是否为 3.8+ + +### 3. 填写角色设定 + +用文本编辑器打开 `app.py`,找到顶部角色设定区域,按注释说明填写。详见下方「角色设定填写指南」。 + +同时填入你的 API Key: + +```python +AI_API_KEY = "你的API Key" +``` + +### 4. 启动服务 + +**本地运行:** + +```bash +cd ~/aibot +python app.py +``` + +✅ 成功:终端出现 `Running on http://0.0.0.0:5000` +❌ 失败:出现 `Address already in use`,说明5000端口被占用,换一个端口或关闭占用进程 + +**服务器后台运行(推荐):** + +```bash +cd ~/aibot +gunicorn -w 2 -b 0.0.0.0:5000 app:app --daemon +``` + +✅ 成功:命令执行后无报错,回到命令行 +❌ 失败:出现 `command not found: gunicorn`,请先运行 `pip install gunicorn` + +启动后可用以下命令测试服务是否正常: + +```bash +curl -X POST http://localhost:5000/chat \ + -H "Content-Type: application/json" \ + -d '{"message": "你好", "playerName": "测试"}' +``` + +✅ 成功:返回包含 `reply` 字段的 JSON +❌ 失败:返回 `Connection refused`,说明服务未启动 + +### 常见问题 + +**Q: 云服务器上启动了但外部访问不了?** +A: 检查服务器防火墙是否放行了5000端口。 + +**Q: API Key 填写后报错 `401`?** +A: API Key 填写有误,请检查是否复制完整。 + +**Q: 返回 `500` 错误?** +A: 查看终端日志,通常是 API Key 无效或余额不足。 + +--- + +## 安装 JS 插件 + +### 1. 下载文件 + +下载本仓库中的 `sealdiceAIroleplay.js`,用文本编辑器打开,找到顶部配置区填写: + +```javascript +// ===== 配置区 ===== +const FLASK_URL = 'http://你的IP:5000/chat'; // Flask 服务地址,必填 +const COMMAND_NAME = 'hekate'; // 指令名,玩家用 .指令名 触发,必填 +const CHAR_NAME = '赫卡特'; // 角色名,仅用于提示语显示,必填 +``` + +**Flask 服务地址如何填写:** +- 本地运行:填 `http://127.0.0.1:5000/chat` +- 云服务器运行:填 `http://你的服务器公网IP:5000/chat`,例如 `http://106.55.29.59:5000/chat` + - Linux 服务器查询公网IP:`curl ifconfig.me` + - Windows 本地查询IP:`ipconfig`,找到「IPv4 地址」 + +**指令名如何设置:** +- 指令名即玩家触发对话的命令,例如填 `hekate`,玩家发 `.hekate 你好` 即可触发 +- 建议用角色名的英文或拼音,3个字母以上 +- ⚠️ 避免使用和海豹骰内置指令相近的开头,例如 `r`、`ra`、`sc`、`a` 开头的短命令,容易被误解析 +- ⚠️ 指令名需要在 JS 插件配置区和后续使用中保持一致,改了这里记得同步更新 + +### 2. 上传插件 + +进入海豹骰后台 → 扩展功能 → JS扩展 → 上传插件,选择 `sealdiceAIroleplay.js`。 + +### 3. 重载 JS + +点击右上角「重载 JS」按钮。 + +✅ 成功:插件列表出现你的角色名,且「禁用指令」栏有你设置的指令名 +❌ 失败:插件列表显示「佚名」且无指令,点击「重载 JS」再试一次 + +### 4. 测试 + +在 QQ 或其他平台发送: + +``` +.hekate 你好 +``` + +✅ 成功:骰子会先发送一条等待提示,例如「赫卡特听见了你,请等待她的回音。」,随后返回角色回复 +❌ 失败:无任何回应,请检查 Flask 服务是否正常运行 + +> 💡 等待提示语来自 JS 插件中的设置,你可以在 `sealdiceAIroleplay.js` 里找到并修改成你喜欢的文字。 +> 💡 等待提示语可以删去,但强烈推荐保留——当角色迟迟没有回复时,它能帮助你快速判断是指令没有触发,还是 Flask 服务出现了问题。 + +### 常见问题 + +**Q: 上传后指令没有反应?** +A: 确认 Flask 服务正在运行,用 curl 测试服务是否正常(见上方部署章节)。 + +**Q: 提示「未设置快捷指令」?** +A: 指令名设置有问题,避免使用单个字母或以 `.a` 开头的名字。 + +**Q: 重载后插件失效?** +A: 这是海豹骰的已知缓存问题,重载 JS 不会清空已注册的扩展。删除插件后重新上传即可。 + +--- + +## 角色设定填写指南 + +打开 `app.py`,找到角色设定区域,按以下说明填写: + +| 变量 | 说明 | 示例 | +|------|------|------| +| `CHAR_NAME` | 角色主名 | 赫卡特 | +| `CHAR_ALIASES` | 别名,没有可留空 | 黑暗女神、十字路口的守护者 | +| `CHAR_ROLE` | 角色身份 | 魔法与月亮的掌管者,冥界的引路人 | +| `CHAR_WORLD` | 世界观背景 | 古希腊神话世界 | +| `CHAR_DESCRIPTION` | 对角色的简短描述 | 古老而强大的存在、普通的高中生、江湖游历的侠客 | +| `CHAR_PERSONALITY` | 性格 | 神秘而深邃,冷静但不冷漠 | +| `CHAR_SPEECH_STYLE` | 语言风格 | 简短有力,带有预言般的韵味 | +| `CHAR_SPEECH_FORMAT` | 语言格式,已预设可删改 | 动作描写用括号表示… | +| `CHAR_RESTRICTIONS` | 角色专属限制,填写角色能与不能 | 不称呼对方为「孩子」 | +| `CHAR_RELATIONSHIPS` | 人物关系,每行一个 | 宙斯:诸神之王,我与他井水不犯河水 | + +> 💡 填写越详细,AI 的角色扮演效果越好。人物关系部分尤其推荐填写,当玩家提及相关人物时,角色会有对应的情绪反应。 + +--- + +## 隐私说明 + +1. 只有通过指令触发的消息才会发送给 AI,普通聊天内容不会被读取 +2. 对话记录仅存于内存,服务重启后自动清空,不写入任何文件 +3. 本项目调用方式不会主动上传数据,但最终取决于你所使用的 AI API 服务商的隐私条款。例如 [Anthropic Claude](https://www.anthropic.com) 和 [DeepSeek](https://www.deepseek.com) 均在其条款中说明不将 API 调用数据用于模型训练,使用其他服务商请自行查阅对应条款。 + +--- + +## 已知限制 + +- 重启 Flask 服务后,所有对话记忆清空 +- 当前不支持跨会话持久记忆 +- 对话历史过长时可能超出 API token 限制,建议定期重启服务清空记忆 +- 当前版本默认使用 DeepSeek API 格式,使用 Claude 等其他格式需自行修改 `app.py` 中的请求部分 + +--- + +## 未来计划 + +- [ ] 持久化记忆(跨会话记忆、人物关系记忆) +- [ ] 更丰富的应用场景,例如在沙盒模组中扮演随机路人 NPC,丰富玩家探索体验 +- [ ] 还有一个天坑之AI角色补位,为单机玩家设置的 + +--- + +## 致谢 + +- [Anthropic Claude](https://www.anthropic.com) — 本项目的开发伙伴,笔者认为目前效果最佳的 AI,超级昂贵但超级好用 ฅ^•ﻌ•^ฅ +- [DeepSeek](https://www.deepseek.com) — 默认 AI 后端,便宜好用 +- [SealDice](https://sealdice.com) — 骰子平台支持 + +--- + +## 写在最后 + +SealDiceAIroleplay 的初衷绝对不是认为AI创作可以替代人类创作!我只是试图在原本的固定自定义回复中,多探索一些机动的可能性,从而丰富体验。 + +人类的赞歌是勇气的赞歌、是智慧的赞歌,在任何模组里任何伟大的冒险旅途,都离不开每一位作者、玩家、主持人的共同创作。 + +向伟大的创作者致敬!祝诸位骰运昌隆,所历皆传奇。 + +感恩赫卡特女神及祂的尊名、仁慈和智慧🔥 + +--- + +*Vibe coded by Claude, conceived by Lelia. ฅ^•ﻌ•^ฅ* From fd7820c316d8c3c67a0970ba8db43ae6ef842888 Mon Sep 17 00:00:00 2001 From: Negusonnn Date: Mon, 6 Apr 2026 16:28:32 +0800 Subject: [PATCH 5/6] Add files via upload --- .../AIroleplay/app.py" | 130 ++++++++++++++++++ .../AIroleplay/requirements.txt" | 3 + .../AIroleplay/sealdiceAIroleplay.js" | 56 ++++++++ 3 files changed, 189 insertions(+) create mode 100644 "scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/app.py" create mode 100644 "scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/requirements.txt" create mode 100644 "scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/sealdiceAIroleplay.js" diff --git "a/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/app.py" "b/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/app.py" new file mode 100644 index 0000000..384f14d --- /dev/null +++ "b/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/app.py" @@ -0,0 +1,130 @@ +from flask import Flask, request, jsonify +import requests + +app = Flask(__name__) + +# ===== 请在这里填写你的 API Key 和服务地址 ===== +AI_API_KEY = "你的AI API Key" # 如 DeepSeek、Claude 等 +AI_API_URL = "https://api.deepseek.com/chat/completions" # 默认使用 DeepSeek +AI_MODEL = "deepseek-chat" # 模型名称 + +# 其他服务商参考: +# DeepSeek(推荐入门): +# URL: https://api.deepseek.com/chat/completions +# Model: deepseek-chat +# 申请:https://www.deepseek.com +# +# Anthropic Claude(推荐追求质量): +# Claude 使用独立 API 格式,需替换 app.py 中的请求部分,详见: +# https://www.anthropic.com +# 笔者认为效果最佳,但价格较高且大陆地区连接不稳定,物有所值。 +# +# OpenAI GPT(兼容格式): +# URL: https://api.openai.com/v1/chat/completions +# Model: gpt-4o 等 +# ================================================ + +# ===== 隐私说明 ===== +# 1. 只有通过指令触发的消息才会发送给 AI,普通聊天内容不会被读取 +# 2. 对话记录仅存于内存,服务重启后自动清空,不写入任何文件 +# 3. 本项目调用方式不会主动上传数据,但最终取决于你所使用的 AI API 服务商的隐私条款。 +# 例如 Anthropic Claude(https://www.anthropic.com)和 DeepSeek(https://www.deepseek.com) +# 均在其条款中说明不将 API 调用数据用于模型训练,使用其他服务商请自行查阅对应条款。 +# ==================== + + +# ===== 角色设定,请在这里填写你想扮演的角色 ===== + +CHAR_NAME = "赫卡特" # 角色主名 +CHAR_ALIASES = "黑暗女神、十字路口的守护者" # 别名(没有可留空) +CHAR_ROLE = "魔法与月亮的掌管者,冥界的引路人" # 身份 +CHAR_WORLD = "古希腊神话世界" # 世界观背景 +CHAR_DESCRIPTION = "古老而强大的存在" # 对角色的简短描述,如「普通的高中生」「江湖游历的侠客」 +CHAR_PERSONALITY = "神秘而深邃,冷静但不冷漠,见过无数灵魂的来去,对世人保持悲悯" # 性格 +CHAR_SPEECH_STYLE = "简短有力,带有预言般的韵味,偶尔用隐喻和暗语说话" # 语言风格 + +# 语言格式——已预设,可删改 +CHAR_SPEECH_FORMAT = """ +- 动作描写用括号表示,仅在推进剧情的关键时刻使用,日常对话不加 +- 回复控制在150字以内 +""" + +# 限制条件——请填写你的角色专属的能与不能 +CHAR_RESTRICTIONS = """ +- 不称呼对方为「孩子」或任何俗世间长辈对晚辈的称谓 +""" + +# 人物关系——每行一个,格式:人物名:关系描述,没有可留空 +CHAR_RELATIONSHIPS = """ +宙斯:诸神之王,我与他井水不犯河水。 +珀耳塞福涅:冥界的王后,我为她点燃火炬。 +赫敏斯:信使之神,十字路口我们时常相遇。 +""" + +# ================================================ + + +SYSTEM_PROMPT = f"""你是{CHAR_NAME},亦名{CHAR_ALIASES},{CHAR_ROLE}。 + +你存在于{CHAR_WORLD}中,是一个{CHAR_DESCRIPTION}。 + +【性格】 +{CHAR_PERSONALITY}。 + +【语言风格】 +{CHAR_SPEECH_STYLE}。 + +【语言格式】 +{CHAR_SPEECH_FORMAT} + +【限制条件】 +{CHAR_RESTRICTIONS} + +【人物关系】 +{CHAR_RELATIONSHIPS} +""" + + +# ===== 记忆系统 ===== +# 当前版本支持短期上下文记忆,即每位玩家在同一次会话中,角色会记住对话内容。 +# 重启服务后记忆清空。 +# 如需持久化记忆(跨会话记忆、人物关系记忆),可扩展此处逻辑, +# 例如将 conversation_history 存入本地文件或数据库。 +conversation_history = {} + + +@app.route('/chat', methods=['POST']) +def chat(): + data = request.json + user_message = data.get('message', '') + player_name = data.get('playerName', '访客') + + if player_name not in conversation_history: + conversation_history[player_name] = [] + + conversation_history[player_name].append({'role': 'user', 'content': user_message}) + + messages = [{'role': 'system', 'content': SYSTEM_PROMPT}] + conversation_history[player_name] + + response = requests.post( + AI_API_URL, + headers={ + 'Authorization': f'Bearer {AI_API_KEY}', + 'Content-Type': 'application/json' + }, + json={ + 'model': AI_MODEL, + 'messages': messages, + 'max_tokens': 300 + } + ) + result = response.json() + reply = result['choices'][0]['message']['content'] + + conversation_history[player_name].append({'role': 'assistant', 'content': reply}) + + return jsonify({'reply': reply}) + + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000) diff --git "a/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/requirements.txt" "b/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/requirements.txt" new file mode 100644 index 0000000..4287cd1 --- /dev/null +++ "b/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/requirements.txt" @@ -0,0 +1,3 @@ +flask +requests +gunicorn \ No newline at end of file diff --git "a/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/sealdiceAIroleplay.js" "b/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/sealdiceAIroleplay.js" new file mode 100644 index 0000000..e545156 --- /dev/null +++ "b/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/sealdiceAIroleplay.js" @@ -0,0 +1,56 @@ +// ==UserScript== +// @name SealDiceAIroleplay +// @author Lelia +// @version 1.0.0 +// @description 为海豹骰设计的 AI 角色扮演回复插件 | Vibe coded by Claude, conceived by Lelia. +// @timestamp 1700000000 +// @license Apache-2 +// @homepageURL https://github.com/Lelia7OR/SealDiceAIroleplay +// ==/UserScript== + +// ===== 配置区 ===== +// ⚠️ 以下三项请按你的实际情况修改 +const FLASK_URL = 'http://你的IP:5000/chat'; // Flask 服务地址,必填 +const COMMAND_NAME = 'hekate'; // 指令名,玩家用 .指令名 触发,必填 +const CHAR_NAME = '赫卡特'; // 角色名,仅用于提示语显示,必填 +// ================== + +// ===== 提示语,可按喜好修改 ===== +const WAIT_MSG = `${CHAR_NAME}听见了你,请等待她的回音。`; // 可删除,但强烈推荐保留,便于排查问题 +const ERROR_MSG = `${CHAR_NAME}暂时无法回应,请稍后再试。`; // 可修改 +// ================================ + +// ⚠️ 以下内容为逻辑部分,请勿修改 +let ext = seal.ext.find(COMMAND_NAME); +if (!ext) { + ext = seal.ext.new(COMMAND_NAME, 'Lelia', '1.0.0'); + seal.ext.register(ext); +} + +const cmd = seal.ext.newCmdItemInfo(); +cmd.name = COMMAND_NAME; +cmd.help = `和${CHAR_NAME}对话,例如:.${COMMAND_NAME} 你好`; +cmd.solve = (ctx, msg, cmdArgs) => { + const userMessage = cmdArgs.rawArgs; + if (!userMessage) { + seal.replyToSender(ctx, msg, `请输入你想说的话,例如:.${COMMAND_NAME} 你好`); + return seal.ext.newCmdExecuteResult(true); + } + + const playerName = ctx.player.name; + + seal.replyToSender(ctx, msg, WAIT_MSG); + + fetch(FLASK_URL, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ message: userMessage, playerName: playerName }) + }) + .then(res => res.json()) + .then(data => { seal.replyToSender(ctx, msg, data.reply); }) + .catch(err => { seal.replyToSender(ctx, msg, ERROR_MSG); }); + + return seal.ext.newCmdExecuteResult(true); +}; + +ext.cmdMap[COMMAND_NAME] = cmd; From 440a76631918d22bc39aaa3e3198698999c479f6 Mon Sep 17 00:00:00 2001 From: Negusonnn Date: Mon, 6 Apr 2026 16:52:03 +0800 Subject: [PATCH 6/6] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20AIroleplay=20A?= =?UTF-8?q?I=E8=A7=92=E8=89=B2=E6=89=AE=E6=BC=94=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated wording from '回应' to '回复' for consistency. --- .../\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" "b/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" index 3836327..fd6deb7 100644 --- "a/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" +++ "b/scripts/\345\250\261\344\271\220\345\220\221/AIroleplay/README.md" @@ -7,7 +7,7 @@ ## 项目简介 -SealDiceAIroleplay 是一个海豹骰 JS 插件,通过接入 AI API,让你的骰子可以扮演自定义的角色人设。通过指令,玩家可以直接和骰子对话,骰子会以该角色的身份回应。 +SealDiceAIroleplay 是一个海豹骰 JS 插件,通过接入 AI API,让你的骰子可以扮演自定义的角色人设。通过指令,玩家可以直接和骰子对话,骰子会以该角色的身份回复。 按照格式填写角色设定后,AI 会以该角色的身份回应玩家,支持上下文记忆。