nonebot-plugin-aigf-master 1.6.2__tar.gz → 2.0.0b0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. {nonebot_plugin_aigf_master-1.6.2/nonebot_plugin_aigf_master.egg-info → nonebot_plugin_aigf_master-2.0.0b0}/PKG-INFO +76 -31
  2. nonebot_plugin_aigf_master-1.6.2/PKG-INFO → nonebot_plugin_aigf_master-2.0.0b0/README.md +71 -48
  3. nonebot_plugin_aigf_master-2.0.0b0/nonebot_plugin_aigf_master/__init__.py +795 -0
  4. nonebot_plugin_aigf_master-2.0.0b0/nonebot_plugin_aigf_master/api_hooks.py +226 -0
  5. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/config.py +9 -2
  6. nonebot_plugin_aigf_master-2.0.0b0/nonebot_plugin_aigf_master/context_bus.py +30 -0
  7. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/meme_store.py +13 -13
  8. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/models.py +1 -1
  9. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/peer_client.py +5 -2
  10. nonebot_plugin_aigf_master-2.0.0b0/nonebot_plugin_aigf_master/plugin_invoker.py +199 -0
  11. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/processor.py +32 -26
  12. nonebot_plugin_aigf_master-2.0.0b0/nonebot_plugin_aigf_master/session.py +273 -0
  13. nonebot_plugin_aigf_master-2.0.0b0/nonebot_plugin_aigf_master/unimsg.py +436 -0
  14. nonebot_plugin_aigf_master-1.6.2/README.md → nonebot_plugin_aigf_master-2.0.0b0/nonebot_plugin_aigf_master.egg-info/PKG-INFO +93 -28
  15. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master.egg-info/SOURCES.txt +2 -1
  16. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master.egg-info/requires.txt +3 -1
  17. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/pyproject.toml +5 -3
  18. nonebot_plugin_aigf_master-1.6.2/nonebot_plugin_aigf_master/__init__.py +0 -882
  19. nonebot_plugin_aigf_master-1.6.2/nonebot_plugin_aigf_master/api_hooks.py +0 -260
  20. nonebot_plugin_aigf_master-1.6.2/nonebot_plugin_aigf_master/context_bus.py +0 -30
  21. nonebot_plugin_aigf_master-1.6.2/nonebot_plugin_aigf_master/message_builder.py +0 -92
  22. nonebot_plugin_aigf_master-1.6.2/nonebot_plugin_aigf_master/plugin_invoker.py +0 -111
  23. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/LICENSE +0 -0
  24. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/anime_recognizer.py +0 -0
  25. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/animetrace_client.py +0 -0
  26. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/cache_cleanup.py +0 -0
  27. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/command_learner.py +0 -0
  28. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/image_gen_client.py +0 -0
  29. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/image_handler.py +0 -0
  30. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/llm_client.py +0 -0
  31. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/memory_store.py +0 -0
  32. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/plugin_discovery.py +0 -0
  33. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/preset_store.py +0 -0
  34. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/prompt_builder.py +0 -0
  35. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/response_parser.py +0 -0
  36. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/search_client.py +0 -0
  37. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master/vlm_client.py +0 -0
  38. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master.egg-info/dependency_links.txt +0 -0
  39. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/nonebot_plugin_aigf_master.egg-info/top_level.txt +0 -0
  40. {nonebot_plugin_aigf_master-1.6.2 → nonebot_plugin_aigf_master-2.0.0b0}/setup.cfg +0 -0
@@ -1,14 +1,16 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nonebot-plugin-aigf-master
3
- Version: 1.6.2
4
- Summary: 群聊特化LLM聊天机器人(增强版),具有记忆、表情包、跨插件调用和跨bot通信能力
3
+ Version: 2.0.0b0
4
+ Summary: 群聊特化LLM聊天机器人(增强版),具有记忆、表情包、跨插件调用、跨bot通信与跨适配器支持
5
5
  License-Expression: MIT
6
6
  Requires-Python: <4.0,>=3.10
7
7
  Description-Content-Type: text/markdown
8
8
  License-File: LICENSE
9
- Requires-Dist: nonebot2>=2.3.0
9
+ Requires-Dist: nonebot2>=2.5.0
10
10
  Requires-Dist: nonebot-adapter-onebot>=2.2.0
11
11
  Requires-Dist: nonebot-plugin-localstore>=0.5.0
12
+ Requires-Dist: nonebot-plugin-alconna>=0.62
13
+ Requires-Dist: nonebot-plugin-uninfo>=0.11
12
14
  Requires-Dist: openai>=1.0.0
13
15
  Requires-Dist: httpx>=0.24.0
14
16
  Requires-Dist: anyio>=4.0.0
@@ -24,21 +26,30 @@ Dynamic: license-file
24
26
 
25
27
  ## ✨ AI-group-friend-master ✨
26
28
 
27
- 群聊特化 LLM 聊天机器人,具备表情包管理、记忆存储、联网搜索、跨插件感知、插件调用、LLM 命令学习等能力。
29
+ 群聊特化 LLM 聊天机器人,具备表情包管理、记忆存储、联网搜索、跨插件感知、插件调用、LLM 命令学习等能力,并以适配器无关的方式收发消息(OneBot / Satori / Telegram / Discord 等 alconna 支持的适配器均可)。
28
30
 
29
31
  <p>
30
32
  <img src="https://img.shields.io/badge/python-3.10+-blue?style=flat-square&logo=python&logoColor=white" alt="python">
31
- <img src="https://img.shields.io/badge/nonebot-2.3+-red?style=flat-square" alt="nonebot">
33
+ <img src="https://img.shields.io/badge/nonebot-2.5+-red?style=flat-square" alt="nonebot">
32
34
  </p>
33
35
  </div>
34
36
 
37
+ > [!WARNING]
38
+ > **这是 beta 分支(2.0.0 开发中):跨适配器改造版**,与 1.6.x(main)不兼容,请勿直接覆盖生产环境的稳定版:
39
+ > - 会话改用 `适配器:会话id` 为键(旧版 `memory/{群号}` 目录会在启动时**自动迁移**为 `onebot11_群号`),新增私聊会话支持
40
+ > - 新增依赖 `nonebot-plugin-alconna`(统一消息)与 `nonebot-plugin-uninfo`(跨适配器会话/成员信息)
41
+ > - 插件调用改为「复制真实消息事件」,合成事件里携带**真实发送者的昵称/群名片/角色**(见「无法代为执行的命令」)
42
+ >
43
+ > 稳定版请留在 main 分支(1.6.x),beta 的功能验证完成后再合并发版。
44
+
35
45
  ## 📖 介绍
36
46
 
37
- 一个基于 NoneBot2 的群聊 AI 助手插件,能够自主收集和发送表情包、联网搜索知识、对群内信息进行记忆,还能够感知同实例内其它插件的输出、通过 LLM 调用其它插件、自主学习群内命令用法,并能通过子插件与其它 bot 通信获取消息和远程调用命令。
47
+ 一个基于 NoneBot2 的群聊 AI 助手插件,能够自主收集和发送表情包、联网搜索知识、对群内信息进行记忆,还能够感知同实例内其它插件的输出、通过 LLM 调用其它插件、自主学习群内命令用法,并能通过子插件与其它 bot 通信获取消息和远程调用命令。消息收发走 [nonebot-plugin-alconna](https://github.com/nonebot/plugin-alconna) 的通用消息层、会话与成员信息走 [nonebot-plugin-uninfo](https://github.com/nonebot/plugin-uninfo),因此同一份代码可以在多个适配器上工作(详细边界见「多适配器支持」)。
38
48
  > 本项目有AI高度参与,若有做得不够好及需要改进的地方,欢迎在issue提出意见。
39
49
 
40
50
  ### 核心能力
41
51
 
52
+ - 🧩 **多适配器支持**:消息收发与会话身份走通用层,OneBot / Satori / Telegram / Discord 等适配器共用同一套聊天、记忆、表情包与命令逻辑(跨插件感知、插件调用等能力仍以 OneBot 为主,见下文边界)
42
53
  - 🔌 **跨插件感知**:LLM 能看到同实例内其它插件的输出(如 rollpig 的小猪卡片、搜索结果等)
43
54
  - 🤖 **插件调用**:LLM 可通过 function calling 调用其它插件(如 `/roll`、`/天气`),支持传递参数与 @ 群友(如 `决斗 @张三 10`)
44
55
  - 🧠 **LLM 命令学习**:通过观察群聊自动学习命令用法,支持学习、编辑、删除
@@ -66,20 +77,20 @@ Dynamic: license-file
66
77
  > 要使用本插件, 你至少需要
67
78
  >
68
79
  > - 一个有效的 openai 规范接口 api key,你需要在 `.env` 文件中配置对应的 api 地址
80
+ >
81
+ > 从 2.0 起插件还依赖 `nonebot-plugin-alconna` 与 `nonebot-plugin-uninfo`(跨适配器收发与会话/成员信息),用下面的方式安装时会自动装上。
69
82
 
70
- <details open>
71
- <summary>使用 nb-cli 安装</summary>
72
- 在 nonebot2 项目的根目录下打开命令行, 输入以下指令安装
83
+ ### 安装 beta 版本(2.0.0b0)
73
84
 
74
- nb plugin install nonebot-plugin-aigf-master --upgrade
85
+ `2.0.0b0` 是**预发布(pre-release)版本**,因此:
75
86
 
76
- </details>
87
+ - `pip install nonebot-plugin-aigf-master` 装的仍是稳定版 **1.6.x**
88
+ - `nb plugin install nonebot-plugin-aigf-master` 同样只装稳定版,而且 nb-cli **不支持指定版本**,所以 beta 只能用 pip 装
77
89
 
78
- <details>
79
- <summary>使用包管理器安装</summary>
90
+ 要装 beta,**必须显式写出版本号**:
80
91
 
81
92
  ```bash
82
- pip install nonebot-plugin-aigf-master
93
+ pip install nonebot-plugin-aigf-master==2.0.0b0
83
94
  ```
84
95
 
85
96
  在 `pyproject.toml` 中添加:
@@ -89,7 +100,8 @@ pip install nonebot-plugin-aigf-master
89
100
  plugins = ["nonebot-plugin-aigf-master"]
90
101
  ```
91
102
 
92
- </details>
103
+ > 需要装 beta 分支上尚未发版的改动时,可以直接从分支安装:
104
+ > `pip install git+https://github.com/Funny1Potato/nonebot-plugin-aigf-master.git@beta`
93
105
 
94
106
 
95
107
  ## 配置
@@ -103,7 +115,8 @@ plugins = ["nonebot-plugin-aigf-master"]
103
115
  AIGFM_LLM_API_KEY="sk-xxxxxxxxxxxx" # LLM API Key
104
116
  AIGFM_LLM_BASE_URL="https://api.deepseek.com" # LLM API 地址
105
117
  AIGFM_LLM_MODEL="deepseek-v4-flash" # LLM 模型名称
106
- AIGFM_ENABLED_GROUPS=[123456, 789012] # 启用的群号列表
118
+ AIGFM_ENABLED_GROUPS=[123456, 789012] # 启用的群/频道会话(可写 `适配器:会话id`,只写数字按 OneBot V11 识别)
119
+ AIGFM_ENABLED_PRIVATE=[] # 启用的私聊会话(同上写法;留空则私聊不响应)
107
120
 
108
121
  # --- 图片理解(VLM) ---
109
122
  AIGFM_IMAGE_MODE="vlm" # 图片模式: vlm / llm(默认 vlm)
@@ -187,7 +200,6 @@ AIGFM_ANIME_RECOGNIZE_MAX_CHARACTERS=3 # 展示的角色标签数量上限(
187
200
  AIGFM_ANIME_NSFW_THRESHOLD=0.5 # explicit 概率超过该值标注 [NSFW](默认 0.5;仅本地后端提供画风分级)
188
201
  AIGFM_ANIMETRACE_URL="https://api.animetrace.com" # AnimeTrace API 地址(公共 API、无需鉴权;识别会把图片上传到该服务)
189
202
  AIGFM_ANIMETRACE_TIMEOUT=20.0 # AnimeTrace 请求超时/秒(默认 20.0)
190
- AIGFM_ANIME_RECOGNIZE_ENABLED=false # 【已被 AIGFM_ANIME_BACKEND 取代,仅兼容保留】为 true 且 backend=off 时按 anime-recognize 处理
191
203
 
192
204
  # --- 缓存清理 ---
193
205
  AIGFM_IMAGE_CACHE_MAX_FILES=500 # 描述/角色识别缓存(image_cache 下的 JSON)最大数量,超出按 mtime 最旧删除(默认 500,0=不清理)
@@ -225,6 +237,30 @@ AIGFM_PEER_CAPTURE_PLUGINS=[] # 要捕获输出的插件名列表,为
225
237
  - 每次处理时,LLM 收到最近 **20 条**(可配置)历史聊天记录 + 四层记忆 + 预设 + 表情包列表 + 其它插件响应;本批消息只出现在「新消息」段,同一条插件响应也只注入一次(不会在历史与新消息里重复)
226
238
  - LLM 一次调用同时完成:回复决策 + 记忆管理 + 表情包选择 + 命令学习
227
239
 
240
+ ## 🧩 多适配器支持
241
+
242
+ 插件的消息**收发**(文本、@、图片、语音、视频、群文件、链接分享、回复、合并转发等)走 [nonebot-plugin-alconna](https://github.com/nonebot/plugin-alconna) 的通用消息层,**会话与成员信息**(昵称、群名片、角色、群名、@ 目标解析)走 [nonebot-plugin-uninfo](https://github.com/nonebot/plugin-uninfo)。因此只要适配器被这两个库支持,聊天 / 记忆 / 表情包 / 生图 / 命令学习等功能就能直接工作,不需要为每个适配器改代码。
243
+
244
+ ### 会话与启用清单
245
+
246
+ - 会话以 **`适配器:会话id`** 为键,例如 `onebot11:617770183`(群)、`console:console-chat`(频道)、`onebot11:20001`(私聊)
247
+ - `AIGFM_ENABLED_GROUPS` 管群/频道会话、`AIGFM_ENABLED_PRIVATE` 管私聊会话;条目可写带前缀的完整键,也可以只写 id(**按 OneBot V11 识别**,旧配置无需改动)
248
+ - 落盘目录名不能含 `:`,因此磁盘上写作 `onebot11_617770183`;`memory/` 下旧版裸数字目录会在启动时**一次性自动迁移**(目标已存在则跳过,幂等)
249
+ - 非启用会话不发请求、不入缓冲:插件只会为启用的会话解析成员信息与图片
250
+
251
+ ### 各能力在非 OneBot 适配器上的边界
252
+
253
+ | 能力 | 其它适配器 | 说明 |
254
+ |---|---|---|
255
+ | 聊天、记忆、表情包、生图、命令学习、管理命令 | ✅ 可用 | `status` / `reset` / `set_role` / `presets` / `set_preset` / `reload_meme` 已改为 alconna 响应器,各适配器通用 |
256
+ | 跨插件感知(捕获其它插件的输出) | ✅ 一般可用 | 依赖 NoneBot 基类的 `on_calling_api` 钩子(所有适配器);会话取自当前事件,消息取自适配器消息对象,取不到就静默跳过 |
257
+ | 插件调用(`invoke_plugin`) | ⚠️ 尽力支持 | 通过复制该会话最近一条真实事件来投递命令;事件类型、消息类都由适配器自己决定,不需 onebot 专属类型。目标插件若依赖适配器特有能力(例如 OneBot 的 `get_msg`)仍可能失败 |
258
+ | 群系统通知(戳一戳/禁言/进出群/撤回) | ❌ 仅 OneBot | 这些是 OneBot 专属事件类型,其它适配器没有统一的通知模型,不处理 |
259
+ | 跨 bot 通信(子插件 `/peer/capture`) | ❌ 仅 OneBot | 其它 bot 都是同号 OneBot 实例,推送按 `onebot11:` 会话映射 |
260
+ | 群名片记录 | ✅ 有则记录 | 成员信息来自 uninfo,适配器不提供名片时该项为空 |
261
+
262
+ > 适配器完全不被 alconna/uninfo 支持时,该会话的消息会被静默跳过(只留 debug 日志),不会报错、也不会影响其它适配器。
263
+
228
264
  ## 🔌 跨插件感知
229
265
 
230
266
  ### 工作原理
@@ -365,23 +401,30 @@ LLM 只能调用 prompt 里「可用的群功能」/「其它 bot 的命令」
365
401
 
366
402
  ### 无法代为执行的命令
367
403
 
368
- `invoke_plugin` / `invoke_peer_plugin` 是构造一个**合成群事件**(`GroupMessageEvent`)把命令文本投递给目标插件,而不是让真人发消息。合成事件与真实消息存在字段差异,下列命令**调不动**(表现为投递后聊天记录里始终不出现该插件的响应):
404
+ `invoke_plugin` / `invoke_peer_plugin` 并不是让真人发消息,而是**复制该会话里最近一条真实消息事件**、把消息体换成命令文本后投递(2.0 起改为这种做法,此前是手工拼一个 `GroupMessageEvent`)。因此事件的适配器字段、发送者信息都来自那条真实消息,比过去准确得多,但仍与"真的有人发了这条命令"有差别,下列命令**调不动**(表现为投递后聊天记录里始终不出现该插件的响应):
369
405
 
370
406
  | 命令类型 | 无法执行的原因 |
371
407
  |---|---|
372
- | 需要 @机器人 或呼叫昵称才触发 | 合成事件的 `to_me` 恒为 `False`(该字段由适配器在真实消息上计算,投递时绕过了这一步) |
373
- | 需要管理员 / 群主 / 超级用户权限 | `sender.role` 固定为 `"member"`,且传入的 `user_id` 一般不在 `SUPERUSERS` 内,权限检查直接拒绝 |
374
- | 私聊命令 | 合成事件固定 `message_type="group"`,不会命中只监听私聊的 Matcher |
375
- | 必须先回复/引用某条消息才能执行 | 合成事件的 `reply` 恒为 `None`,且真实消息里的 `reply` 段会被适配器展开,这里没有 |
376
- | 依赖群名片 / 头衔 / 等级 / 地区判断身份 | `sender` 只填 `user_id`、`nickname`(当前群预设名,默认「小助手」;peer 侧由 Bot A 传入同一名字)、`role`,其余字段为空 |
377
- | 依赖真实 `message_id` 的后续操作 | `message_id` 是占位值 `0`,插件拿它去 `get_msg` / 撤回 / 引用回复会失败 |
408
+ | 需要 @机器人 或呼叫昵称才触发 | 合成消息里没有 @机器人,`to_me` 沿用被复制那条消息的值(通常为 `False`) |
409
+ | 私聊命令 / 与事件类型强相关 | 复制的是群/频道事件(`message_type` 保持原样),不会命中只监听私聊或其它事件类型的 Matcher |
410
+ | 必须先回复/引用某条消息才能执行 | 合成消息不含回复段,事件里的 `reply` 也被清空 |
411
+ | 依赖群名片 / 头衔 / 等级 / 地区判断身份 | 发送者昵称、群名片、角色已按真实身份填好(`refresh` 不到的字段仍为空:头衔、等级、地区等) |
412
+ | 需要特殊 `message_id` 语义的操作 | `message_id` 是**被复制那条消息的真实 id**(不再是占位 `0`):引用回复可用,但插件若对"这条消息"做撤回/编辑等操作,作用的其实是那条真实消息 |
413
+
414
+ 关于**权限**:合成事件的发送者是**提出请求的那位群友**(`user_id`、昵称、群名片、角色都按真实身份填),所以:
415
+
416
+ - 需要管理员/群主权限的命令,**请托者本身有相应权限时可以被执行**(1.6.x 及更早版本里 `role` 固定为 `member`,一律拒绝);请托者没有权限时仍会被目标插件拒绝
417
+ - `SUPERUSERS` 相关的命令同理:以请托者的身份通过检查
418
+ - 本插件自己的管理命令(`status`/`reset`/`set_role`/…)**无论谁请托都一律拒绝**,不会代为执行(避免真实用户恰好是 SUPERUSER 时被 LLM 触发)
378
419
 
379
420
  两点补充:
380
421
 
381
422
  - `on_keyword` / `on_regex` / `on_message` 型插件(不用 `on_command` 注册)**不会出现在静态命令列表**里,无法被自动发现;但它们的 rule 只匹配文本时,合成事件仍会命中,所以可以靠 LLM 命令学习掌握后调用。
382
423
  - 命令学习会**主动跳过**上表中无法代为执行的命令(不会为它们生成用法记录),避免 LLM 反复误调用。
383
424
 
384
- > 需要多步确认的命令(执行中等待用户再回复)不在上表内:会话按 `group_{group_id}_{user_id}` 归组,只要后续真实消息来自同一个 `user_id`,等待流程仍能接上。
425
+ > 需要多步确认的命令(执行中等待用户再回复)不在上表内:会话按适配器的会话 id 归组(OneBot V11 为 `group_{group_id}_{user_id}`),只要后续真实消息来自同一个 `user_id`,等待流程仍能接上。
426
+
427
+ > 若目标插件是用 alconna 写的,插件会在投递前把 alconna 按 `message_id` 缓存的那条消息**替换成命令内容**——否则它会把命令读成"原来那条用户消息",永远匹配不上。
385
428
 
386
429
  ## 🌐 跨 bot 通信
387
430
 
@@ -581,7 +624,7 @@ memes/
581
624
  | 后端 | 工作方式 | 擅长 | 代价 |
582
625
  |---|---|---|---|
583
626
  | `anime-recognize` | 本地 WD14 推理服务([aigfm-anime-recognize](https://github.com/Funny1Potato/aigfm-anime-recognize)),**需自行部署** | 动漫 / 手游角色,输出英文 booru 标签(如 `hu_tao_(genshin_impact)`)+ 数值置信度 + 画风分级 | 本地推理、免费无限量;**对 gal / 视觉小说角色识别率低** |
584
- | `animetrace` | [AnimeTrace](https://ai.animedb.cn/) 公共 API,**无需部署、无需鉴权** | gal / 视觉小说角色,并给出作品名(如「胡桃(原神)」) | 图片会上传到该第三方公共服务;有使用配额;不返回数值置信度、无画风分级 |
627
+ | `animetrace` | [AnimeTrace](https://ai.animedb.cn/) 公共 API,**无需部署、无需鉴权** | gal / 视觉小说角色,并给出作品名(如「胡桃(原神)」) | 图片会上传到该第三方公共服务;有使用配额;不返回数值置信度、无画风分级;对gal以外游戏角色的识别率一般 |
585
628
 
586
629
  `both` 模式先问本地服务,本地置信度不足(低于 `AIGFM_ANIME_RECOGNIZE_MIN_CONFIDENCE`)再问 AnimeTrace,两边都没有可信结果才渲染 `[角色识别: 未能识别]`——平时不消耗公共 API 配额。
587
630
 
@@ -592,8 +635,10 @@ memes/
592
635
  ```bash
593
636
  git clone https://github.com/Funny1Potato/aigfm-anime-recognize.git
594
637
  cd aigfm-anime-recognize
638
+ # 安装
595
639
  # Windows: install.bat ;Linux/macOS: chmod +x install.sh && ./install.sh
596
- # 一键完成:建虚拟环境 → 装钉版本依赖 → 下载模型(约 446MB)→ 启动服务(0.0.0.0:8000)
640
+ # 启动
641
+ # Windows: start.bat ; Linux / macOS: chmod +x start.sh && ./start.sh
597
642
  ```
598
643
 
599
644
  **插件配置**:
@@ -603,14 +648,14 @@ cd aigfm-anime-recognize
603
648
  AIGFM_ANIME_BACKEND=both
604
649
 
605
650
  # 本地后端地址(backend 含 anime-recognize 时必填;服务端未启用鉴权时 token 留空)
606
- AIGFM_ANIME_RECOGNIZE_URL=http://127.0.0.1:8000
651
+ AIGFM_ANIME_RECOGNIZE_URL="http://127.0.0.1:8000"
607
652
  # AIGFM_ANIME_RECOGNIZE_TOKEN=可选
608
653
 
609
654
  # 可选调参(默认值如下)
610
655
  # AIGFM_ANIME_RECOGNIZE_MIN_CONFIDENCE=0.85 # 展示角色标签的最低置信度;both 模式下也用它判断本地是否有结果
611
656
  # AIGFM_ANIME_RECOGNIZE_MAX_CHARACTERS=3 # 展示的角色标签数量上限
612
657
  # AIGFM_ANIME_NSFW_THRESHOLD=0.5 # explicit 概率超过该值标注 [NSFW](只标注不拦截;仅本地后端提供分级)
613
- # AIGFM_ANIMETRACE_URL=https://api.animetrace.com
658
+ # AIGFM_ANIMETRACE_URL="https://api.animetrace.com"
614
659
  # AIGFM_ANIMETRACE_TIMEOUT=20 # AnimeTrace 请求超时(秒)
615
660
  ```
616
661
 
@@ -632,8 +677,8 @@ AIGFM_ANIME_RECOGNIZE_URL=http://127.0.0.1:8000
632
677
  - 改 `AIGFM_ANIME_RECOGNIZE_MIN_CONFIDENCE` 只影响此后新识别的图片;已缓存图片要重新判定需删除其 `{md5}_anime.json`
633
678
 
634
679
  **已知局限**:
635
- - **本地后端**:训练数据截止 2024 年前后,新游/新角色可能认不出,**gal / 视觉小说角色识别率尤其低(建议改用 `animetrace` 或 `both`)**;多人合影会漏识别;皮肤/异格不区分;3D 战斗小人/游戏内截图识别率偏低;输出为英文标签(中文映射需自行扩展)
636
- - **AnimeTrace**:不返回数值置信度,只有服务自己的低置信判定——被判低置信时一律按「未能识别」处理,日志 `[角色识别] AnimeTrace 无可信结果,低置信候选: …` 会给出它认为最可能的候选,便于排查;其检测框可能包含误检,多人提示仅供参考;`[NSFW]` 标记只由本地后端提供
680
+ - **本地后端**:训练数据截止 2024 年前后,新游/新角色可能认不出,**gal / 视觉小说角色识别率尤其低(建议改用 `animetrace` 或 `both`)**;多人合影可能会漏识别;3D 战斗小人/游戏内截图识别率不高;输出为英文标签(中文映射需自行扩展)
681
+ - **AnimeTrace**:对gal以外的游戏角色识别率一般;不返回数值置信度,只有服务自己的低置信判定——被判低置信时一律按「未能识别」处理,日志 `[角色识别] AnimeTrace 无可信结果,低置信候选: …` 会给出它认为最可能的候选,便于排查;其检测框可能包含误检,多人提示仅供参考;`[NSFW]` 标记只由本地后端提供
637
682
  - 识别结果(角色名)会进入 LLM 上下文,也就是群里能看到;在意隐私请只用 `anime-recognize`(纯本地)或关闭本功能
638
683
 
639
684
  > 仅 `AIGFM_IMAGE_MODE=vlm` 模式生效;`llm` 模式图片不经过 VLM,无二次元判断。
@@ -1,44 +1,33 @@
1
- Metadata-Version: 2.4
2
- Name: nonebot-plugin-aigf-master
3
- Version: 1.6.2
4
- Summary: 群聊特化LLM聊天机器人(增强版),具有记忆、表情包、跨插件调用和跨bot通信能力
5
- License-Expression: MIT
6
- Requires-Python: <4.0,>=3.10
7
- Description-Content-Type: text/markdown
8
- License-File: LICENSE
9
- Requires-Dist: nonebot2>=2.3.0
10
- Requires-Dist: nonebot-adapter-onebot>=2.2.0
11
- Requires-Dist: nonebot-plugin-localstore>=0.5.0
12
- Requires-Dist: openai>=1.0.0
13
- Requires-Dist: httpx>=0.24.0
14
- Requires-Dist: anyio>=4.0.0
15
- Requires-Dist: pillow>=9.0.0
16
- Requires-Dist: numpy>=1.20.0
17
- Provides-Extra: tavily
18
- Requires-Dist: tavily-python>=0.3.0; extra == "tavily"
19
- Dynamic: license-file
20
-
21
1
  <div align="center">
22
2
  <a href="https://v2.nonebot.dev/store">
23
3
  <img src="https://raw.githubusercontent.com/fllesser/nonebot-plugin-template/refs/heads/resource/.docs/NoneBotPlugin.svg" width="310" alt="logo"></a>
24
4
 
25
5
  ## ✨ AI-group-friend-master ✨
26
6
 
27
- 群聊特化 LLM 聊天机器人,具备表情包管理、记忆存储、联网搜索、跨插件感知、插件调用、LLM 命令学习等能力。
7
+ 群聊特化 LLM 聊天机器人,具备表情包管理、记忆存储、联网搜索、跨插件感知、插件调用、LLM 命令学习等能力,并以适配器无关的方式收发消息(OneBot / Satori / Telegram / Discord 等 alconna 支持的适配器均可)。
28
8
 
29
9
  <p>
30
10
  <img src="https://img.shields.io/badge/python-3.10+-blue?style=flat-square&logo=python&logoColor=white" alt="python">
31
- <img src="https://img.shields.io/badge/nonebot-2.3+-red?style=flat-square" alt="nonebot">
11
+ <img src="https://img.shields.io/badge/nonebot-2.5+-red?style=flat-square" alt="nonebot">
32
12
  </p>
33
13
  </div>
34
14
 
15
+ > [!WARNING]
16
+ > **这是 beta 分支(2.0.0 开发中):跨适配器改造版**,与 1.6.x(main)不兼容,请勿直接覆盖生产环境的稳定版:
17
+ > - 会话改用 `适配器:会话id` 为键(旧版 `memory/{群号}` 目录会在启动时**自动迁移**为 `onebot11_群号`),新增私聊会话支持
18
+ > - 新增依赖 `nonebot-plugin-alconna`(统一消息)与 `nonebot-plugin-uninfo`(跨适配器会话/成员信息)
19
+ > - 插件调用改为「复制真实消息事件」,合成事件里携带**真实发送者的昵称/群名片/角色**(见「无法代为执行的命令」)
20
+ >
21
+ > 稳定版请留在 main 分支(1.6.x),beta 的功能验证完成后再合并发版。
22
+
35
23
  ## 📖 介绍
36
24
 
37
- 一个基于 NoneBot2 的群聊 AI 助手插件,能够自主收集和发送表情包、联网搜索知识、对群内信息进行记忆,还能够感知同实例内其它插件的输出、通过 LLM 调用其它插件、自主学习群内命令用法,并能通过子插件与其它 bot 通信获取消息和远程调用命令。
25
+ 一个基于 NoneBot2 的群聊 AI 助手插件,能够自主收集和发送表情包、联网搜索知识、对群内信息进行记忆,还能够感知同实例内其它插件的输出、通过 LLM 调用其它插件、自主学习群内命令用法,并能通过子插件与其它 bot 通信获取消息和远程调用命令。消息收发走 [nonebot-plugin-alconna](https://github.com/nonebot/plugin-alconna) 的通用消息层、会话与成员信息走 [nonebot-plugin-uninfo](https://github.com/nonebot/plugin-uninfo),因此同一份代码可以在多个适配器上工作(详细边界见「多适配器支持」)。
38
26
  > 本项目有AI高度参与,若有做得不够好及需要改进的地方,欢迎在issue提出意见。
39
27
 
40
28
  ### 核心能力
41
29
 
30
+ - 🧩 **多适配器支持**:消息收发与会话身份走通用层,OneBot / Satori / Telegram / Discord 等适配器共用同一套聊天、记忆、表情包与命令逻辑(跨插件感知、插件调用等能力仍以 OneBot 为主,见下文边界)
42
31
  - 🔌 **跨插件感知**:LLM 能看到同实例内其它插件的输出(如 rollpig 的小猪卡片、搜索结果等)
43
32
  - 🤖 **插件调用**:LLM 可通过 function calling 调用其它插件(如 `/roll`、`/天气`),支持传递参数与 @ 群友(如 `决斗 @张三 10`)
44
33
  - 🧠 **LLM 命令学习**:通过观察群聊自动学习命令用法,支持学习、编辑、删除
@@ -66,20 +55,20 @@ Dynamic: license-file
66
55
  > 要使用本插件, 你至少需要
67
56
  >
68
57
  > - 一个有效的 openai 规范接口 api key,你需要在 `.env` 文件中配置对应的 api 地址
58
+ >
59
+ > 从 2.0 起插件还依赖 `nonebot-plugin-alconna` 与 `nonebot-plugin-uninfo`(跨适配器收发与会话/成员信息),用下面的方式安装时会自动装上。
69
60
 
70
- <details open>
71
- <summary>使用 nb-cli 安装</summary>
72
- 在 nonebot2 项目的根目录下打开命令行, 输入以下指令安装
61
+ ### 安装 beta 版本(2.0.0b0)
73
62
 
74
- nb plugin install nonebot-plugin-aigf-master --upgrade
63
+ `2.0.0b0` 是**预发布(pre-release)版本**,因此:
75
64
 
76
- </details>
65
+ - `pip install nonebot-plugin-aigf-master` 装的仍是稳定版 **1.6.x**
66
+ - `nb plugin install nonebot-plugin-aigf-master` 同样只装稳定版,而且 nb-cli **不支持指定版本**,所以 beta 只能用 pip 装
77
67
 
78
- <details>
79
- <summary>使用包管理器安装</summary>
68
+ 要装 beta,**必须显式写出版本号**:
80
69
 
81
70
  ```bash
82
- pip install nonebot-plugin-aigf-master
71
+ pip install nonebot-plugin-aigf-master==2.0.0b0
83
72
  ```
84
73
 
85
74
  在 `pyproject.toml` 中添加:
@@ -89,7 +78,8 @@ pip install nonebot-plugin-aigf-master
89
78
  plugins = ["nonebot-plugin-aigf-master"]
90
79
  ```
91
80
 
92
- </details>
81
+ > 需要装 beta 分支上尚未发版的改动时,可以直接从分支安装:
82
+ > `pip install git+https://github.com/Funny1Potato/nonebot-plugin-aigf-master.git@beta`
93
83
 
94
84
 
95
85
  ## 配置
@@ -103,7 +93,8 @@ plugins = ["nonebot-plugin-aigf-master"]
103
93
  AIGFM_LLM_API_KEY="sk-xxxxxxxxxxxx" # LLM API Key
104
94
  AIGFM_LLM_BASE_URL="https://api.deepseek.com" # LLM API 地址
105
95
  AIGFM_LLM_MODEL="deepseek-v4-flash" # LLM 模型名称
106
- AIGFM_ENABLED_GROUPS=[123456, 789012] # 启用的群号列表
96
+ AIGFM_ENABLED_GROUPS=[123456, 789012] # 启用的群/频道会话(可写 `适配器:会话id`,只写数字按 OneBot V11 识别)
97
+ AIGFM_ENABLED_PRIVATE=[] # 启用的私聊会话(同上写法;留空则私聊不响应)
107
98
 
108
99
  # --- 图片理解(VLM) ---
109
100
  AIGFM_IMAGE_MODE="vlm" # 图片模式: vlm / llm(默认 vlm)
@@ -187,7 +178,6 @@ AIGFM_ANIME_RECOGNIZE_MAX_CHARACTERS=3 # 展示的角色标签数量上限(
187
178
  AIGFM_ANIME_NSFW_THRESHOLD=0.5 # explicit 概率超过该值标注 [NSFW](默认 0.5;仅本地后端提供画风分级)
188
179
  AIGFM_ANIMETRACE_URL="https://api.animetrace.com" # AnimeTrace API 地址(公共 API、无需鉴权;识别会把图片上传到该服务)
189
180
  AIGFM_ANIMETRACE_TIMEOUT=20.0 # AnimeTrace 请求超时/秒(默认 20.0)
190
- AIGFM_ANIME_RECOGNIZE_ENABLED=false # 【已被 AIGFM_ANIME_BACKEND 取代,仅兼容保留】为 true 且 backend=off 时按 anime-recognize 处理
191
181
 
192
182
  # --- 缓存清理 ---
193
183
  AIGFM_IMAGE_CACHE_MAX_FILES=500 # 描述/角色识别缓存(image_cache 下的 JSON)最大数量,超出按 mtime 最旧删除(默认 500,0=不清理)
@@ -225,6 +215,30 @@ AIGFM_PEER_CAPTURE_PLUGINS=[] # 要捕获输出的插件名列表,为
225
215
  - 每次处理时,LLM 收到最近 **20 条**(可配置)历史聊天记录 + 四层记忆 + 预设 + 表情包列表 + 其它插件响应;本批消息只出现在「新消息」段,同一条插件响应也只注入一次(不会在历史与新消息里重复)
226
216
  - LLM 一次调用同时完成:回复决策 + 记忆管理 + 表情包选择 + 命令学习
227
217
 
218
+ ## 🧩 多适配器支持
219
+
220
+ 插件的消息**收发**(文本、@、图片、语音、视频、群文件、链接分享、回复、合并转发等)走 [nonebot-plugin-alconna](https://github.com/nonebot/plugin-alconna) 的通用消息层,**会话与成员信息**(昵称、群名片、角色、群名、@ 目标解析)走 [nonebot-plugin-uninfo](https://github.com/nonebot/plugin-uninfo)。因此只要适配器被这两个库支持,聊天 / 记忆 / 表情包 / 生图 / 命令学习等功能就能直接工作,不需要为每个适配器改代码。
221
+
222
+ ### 会话与启用清单
223
+
224
+ - 会话以 **`适配器:会话id`** 为键,例如 `onebot11:617770183`(群)、`console:console-chat`(频道)、`onebot11:20001`(私聊)
225
+ - `AIGFM_ENABLED_GROUPS` 管群/频道会话、`AIGFM_ENABLED_PRIVATE` 管私聊会话;条目可写带前缀的完整键,也可以只写 id(**按 OneBot V11 识别**,旧配置无需改动)
226
+ - 落盘目录名不能含 `:`,因此磁盘上写作 `onebot11_617770183`;`memory/` 下旧版裸数字目录会在启动时**一次性自动迁移**(目标已存在则跳过,幂等)
227
+ - 非启用会话不发请求、不入缓冲:插件只会为启用的会话解析成员信息与图片
228
+
229
+ ### 各能力在非 OneBot 适配器上的边界
230
+
231
+ | 能力 | 其它适配器 | 说明 |
232
+ |---|---|---|
233
+ | 聊天、记忆、表情包、生图、命令学习、管理命令 | ✅ 可用 | `status` / `reset` / `set_role` / `presets` / `set_preset` / `reload_meme` 已改为 alconna 响应器,各适配器通用 |
234
+ | 跨插件感知(捕获其它插件的输出) | ✅ 一般可用 | 依赖 NoneBot 基类的 `on_calling_api` 钩子(所有适配器);会话取自当前事件,消息取自适配器消息对象,取不到就静默跳过 |
235
+ | 插件调用(`invoke_plugin`) | ⚠️ 尽力支持 | 通过复制该会话最近一条真实事件来投递命令;事件类型、消息类都由适配器自己决定,不需 onebot 专属类型。目标插件若依赖适配器特有能力(例如 OneBot 的 `get_msg`)仍可能失败 |
236
+ | 群系统通知(戳一戳/禁言/进出群/撤回) | ❌ 仅 OneBot | 这些是 OneBot 专属事件类型,其它适配器没有统一的通知模型,不处理 |
237
+ | 跨 bot 通信(子插件 `/peer/capture`) | ❌ 仅 OneBot | 其它 bot 都是同号 OneBot 实例,推送按 `onebot11:` 会话映射 |
238
+ | 群名片记录 | ✅ 有则记录 | 成员信息来自 uninfo,适配器不提供名片时该项为空 |
239
+
240
+ > 适配器完全不被 alconna/uninfo 支持时,该会话的消息会被静默跳过(只留 debug 日志),不会报错、也不会影响其它适配器。
241
+
228
242
  ## 🔌 跨插件感知
229
243
 
230
244
  ### 工作原理
@@ -365,23 +379,30 @@ LLM 只能调用 prompt 里「可用的群功能」/「其它 bot 的命令」
365
379
 
366
380
  ### 无法代为执行的命令
367
381
 
368
- `invoke_plugin` / `invoke_peer_plugin` 是构造一个**合成群事件**(`GroupMessageEvent`)把命令文本投递给目标插件,而不是让真人发消息。合成事件与真实消息存在字段差异,下列命令**调不动**(表现为投递后聊天记录里始终不出现该插件的响应):
382
+ `invoke_plugin` / `invoke_peer_plugin` 并不是让真人发消息,而是**复制该会话里最近一条真实消息事件**、把消息体换成命令文本后投递(2.0 起改为这种做法,此前是手工拼一个 `GroupMessageEvent`)。因此事件的适配器字段、发送者信息都来自那条真实消息,比过去准确得多,但仍与"真的有人发了这条命令"有差别,下列命令**调不动**(表现为投递后聊天记录里始终不出现该插件的响应):
369
383
 
370
384
  | 命令类型 | 无法执行的原因 |
371
385
  |---|---|
372
- | 需要 @机器人 或呼叫昵称才触发 | 合成事件的 `to_me` 恒为 `False`(该字段由适配器在真实消息上计算,投递时绕过了这一步) |
373
- | 需要管理员 / 群主 / 超级用户权限 | `sender.role` 固定为 `"member"`,且传入的 `user_id` 一般不在 `SUPERUSERS` 内,权限检查直接拒绝 |
374
- | 私聊命令 | 合成事件固定 `message_type="group"`,不会命中只监听私聊的 Matcher |
375
- | 必须先回复/引用某条消息才能执行 | 合成事件的 `reply` 恒为 `None`,且真实消息里的 `reply` 段会被适配器展开,这里没有 |
376
- | 依赖群名片 / 头衔 / 等级 / 地区判断身份 | `sender` 只填 `user_id`、`nickname`(当前群预设名,默认「小助手」;peer 侧由 Bot A 传入同一名字)、`role`,其余字段为空 |
377
- | 依赖真实 `message_id` 的后续操作 | `message_id` 是占位值 `0`,插件拿它去 `get_msg` / 撤回 / 引用回复会失败 |
386
+ | 需要 @机器人 或呼叫昵称才触发 | 合成消息里没有 @机器人,`to_me` 沿用被复制那条消息的值(通常为 `False`) |
387
+ | 私聊命令 / 与事件类型强相关 | 复制的是群/频道事件(`message_type` 保持原样),不会命中只监听私聊或其它事件类型的 Matcher |
388
+ | 必须先回复/引用某条消息才能执行 | 合成消息不含回复段,事件里的 `reply` 也被清空 |
389
+ | 依赖群名片 / 头衔 / 等级 / 地区判断身份 | 发送者昵称、群名片、角色已按真实身份填好(`refresh` 不到的字段仍为空:头衔、等级、地区等) |
390
+ | 需要特殊 `message_id` 语义的操作 | `message_id` 是**被复制那条消息的真实 id**(不再是占位 `0`):引用回复可用,但插件若对"这条消息"做撤回/编辑等操作,作用的其实是那条真实消息 |
391
+
392
+ 关于**权限**:合成事件的发送者是**提出请求的那位群友**(`user_id`、昵称、群名片、角色都按真实身份填),所以:
393
+
394
+ - 需要管理员/群主权限的命令,**请托者本身有相应权限时可以被执行**(1.6.x 及更早版本里 `role` 固定为 `member`,一律拒绝);请托者没有权限时仍会被目标插件拒绝
395
+ - `SUPERUSERS` 相关的命令同理:以请托者的身份通过检查
396
+ - 本插件自己的管理命令(`status`/`reset`/`set_role`/…)**无论谁请托都一律拒绝**,不会代为执行(避免真实用户恰好是 SUPERUSER 时被 LLM 触发)
378
397
 
379
398
  两点补充:
380
399
 
381
400
  - `on_keyword` / `on_regex` / `on_message` 型插件(不用 `on_command` 注册)**不会出现在静态命令列表**里,无法被自动发现;但它们的 rule 只匹配文本时,合成事件仍会命中,所以可以靠 LLM 命令学习掌握后调用。
382
401
  - 命令学习会**主动跳过**上表中无法代为执行的命令(不会为它们生成用法记录),避免 LLM 反复误调用。
383
402
 
384
- > 需要多步确认的命令(执行中等待用户再回复)不在上表内:会话按 `group_{group_id}_{user_id}` 归组,只要后续真实消息来自同一个 `user_id`,等待流程仍能接上。
403
+ > 需要多步确认的命令(执行中等待用户再回复)不在上表内:会话按适配器的会话 id 归组(OneBot V11 为 `group_{group_id}_{user_id}`),只要后续真实消息来自同一个 `user_id`,等待流程仍能接上。
404
+
405
+ > 若目标插件是用 alconna 写的,插件会在投递前把 alconna 按 `message_id` 缓存的那条消息**替换成命令内容**——否则它会把命令读成"原来那条用户消息",永远匹配不上。
385
406
 
386
407
  ## 🌐 跨 bot 通信
387
408
 
@@ -581,7 +602,7 @@ memes/
581
602
  | 后端 | 工作方式 | 擅长 | 代价 |
582
603
  |---|---|---|---|
583
604
  | `anime-recognize` | 本地 WD14 推理服务([aigfm-anime-recognize](https://github.com/Funny1Potato/aigfm-anime-recognize)),**需自行部署** | 动漫 / 手游角色,输出英文 booru 标签(如 `hu_tao_(genshin_impact)`)+ 数值置信度 + 画风分级 | 本地推理、免费无限量;**对 gal / 视觉小说角色识别率低** |
584
- | `animetrace` | [AnimeTrace](https://ai.animedb.cn/) 公共 API,**无需部署、无需鉴权** | gal / 视觉小说角色,并给出作品名(如「胡桃(原神)」) | 图片会上传到该第三方公共服务;有使用配额;不返回数值置信度、无画风分级 |
605
+ | `animetrace` | [AnimeTrace](https://ai.animedb.cn/) 公共 API,**无需部署、无需鉴权** | gal / 视觉小说角色,并给出作品名(如「胡桃(原神)」) | 图片会上传到该第三方公共服务;有使用配额;不返回数值置信度、无画风分级;对gal以外游戏角色的识别率一般 |
585
606
 
586
607
  `both` 模式先问本地服务,本地置信度不足(低于 `AIGFM_ANIME_RECOGNIZE_MIN_CONFIDENCE`)再问 AnimeTrace,两边都没有可信结果才渲染 `[角色识别: 未能识别]`——平时不消耗公共 API 配额。
587
608
 
@@ -592,8 +613,10 @@ memes/
592
613
  ```bash
593
614
  git clone https://github.com/Funny1Potato/aigfm-anime-recognize.git
594
615
  cd aigfm-anime-recognize
616
+ # 安装
595
617
  # Windows: install.bat ;Linux/macOS: chmod +x install.sh && ./install.sh
596
- # 一键完成:建虚拟环境 → 装钉版本依赖 → 下载模型(约 446MB)→ 启动服务(0.0.0.0:8000)
618
+ # 启动
619
+ # Windows: start.bat ; Linux / macOS: chmod +x start.sh && ./start.sh
597
620
  ```
598
621
 
599
622
  **插件配置**:
@@ -603,14 +626,14 @@ cd aigfm-anime-recognize
603
626
  AIGFM_ANIME_BACKEND=both
604
627
 
605
628
  # 本地后端地址(backend 含 anime-recognize 时必填;服务端未启用鉴权时 token 留空)
606
- AIGFM_ANIME_RECOGNIZE_URL=http://127.0.0.1:8000
629
+ AIGFM_ANIME_RECOGNIZE_URL="http://127.0.0.1:8000"
607
630
  # AIGFM_ANIME_RECOGNIZE_TOKEN=可选
608
631
 
609
632
  # 可选调参(默认值如下)
610
633
  # AIGFM_ANIME_RECOGNIZE_MIN_CONFIDENCE=0.85 # 展示角色标签的最低置信度;both 模式下也用它判断本地是否有结果
611
634
  # AIGFM_ANIME_RECOGNIZE_MAX_CHARACTERS=3 # 展示的角色标签数量上限
612
635
  # AIGFM_ANIME_NSFW_THRESHOLD=0.5 # explicit 概率超过该值标注 [NSFW](只标注不拦截;仅本地后端提供分级)
613
- # AIGFM_ANIMETRACE_URL=https://api.animetrace.com
636
+ # AIGFM_ANIMETRACE_URL="https://api.animetrace.com"
614
637
  # AIGFM_ANIMETRACE_TIMEOUT=20 # AnimeTrace 请求超时(秒)
615
638
  ```
616
639
 
@@ -632,8 +655,8 @@ AIGFM_ANIME_RECOGNIZE_URL=http://127.0.0.1:8000
632
655
  - 改 `AIGFM_ANIME_RECOGNIZE_MIN_CONFIDENCE` 只影响此后新识别的图片;已缓存图片要重新判定需删除其 `{md5}_anime.json`
633
656
 
634
657
  **已知局限**:
635
- - **本地后端**:训练数据截止 2024 年前后,新游/新角色可能认不出,**gal / 视觉小说角色识别率尤其低(建议改用 `animetrace` 或 `both`)**;多人合影会漏识别;皮肤/异格不区分;3D 战斗小人/游戏内截图识别率偏低;输出为英文标签(中文映射需自行扩展)
636
- - **AnimeTrace**:不返回数值置信度,只有服务自己的低置信判定——被判低置信时一律按「未能识别」处理,日志 `[角色识别] AnimeTrace 无可信结果,低置信候选: …` 会给出它认为最可能的候选,便于排查;其检测框可能包含误检,多人提示仅供参考;`[NSFW]` 标记只由本地后端提供
658
+ - **本地后端**:训练数据截止 2024 年前后,新游/新角色可能认不出,**gal / 视觉小说角色识别率尤其低(建议改用 `animetrace` 或 `both`)**;多人合影可能会漏识别;3D 战斗小人/游戏内截图识别率不高;输出为英文标签(中文映射需自行扩展)
659
+ - **AnimeTrace**:对gal以外的游戏角色识别率一般;不返回数值置信度,只有服务自己的低置信判定——被判低置信时一律按「未能识别」处理,日志 `[角色识别] AnimeTrace 无可信结果,低置信候选: …` 会给出它认为最可能的候选,便于排查;其检测框可能包含误检,多人提示仅供参考;`[NSFW]` 标记只由本地后端提供
637
660
  - 识别结果(角色名)会进入 LLM 上下文,也就是群里能看到;在意隐私请只用 `anime-recognize`(纯本地)或关闭本功能
638
661
 
639
662
  > 仅 `AIGFM_IMAGE_MODE=vlm` 模式生效;`llm` 模式图片不经过 VLM,无二次元判断。