nonebot-plugin-aigf-master 0.1.2__tar.gz → 0.1.4__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.
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/PKG-INFO +9 -7
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/README.md +8 -6
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/llm_client.py +3 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/processor.py +4 -1
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/prompt_builder.py +25 -4
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/response_parser.py +50 -1
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master.egg-info/PKG-INFO +9 -7
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/pyproject.toml +1 -1
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/LICENSE +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/__init__.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/api_hooks.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/command_learner.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/config.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/context_bus.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/image_handler.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/meme_store.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/memory_store.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/models.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/peer_client.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/plugin_discovery.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/plugin_invoker.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/preset_store.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/search_client.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master/vlm_client.py +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master.egg-info/SOURCES.txt +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master.egg-info/dependency_links.txt +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master.egg-info/requires.txt +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/nonebot_plugin_aigf_master.egg-info/top_level.txt +0 -0
- {nonebot_plugin_aigf_master-0.1.2 → nonebot_plugin_aigf_master-0.1.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nonebot-plugin-aigf-master
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: 群聊特化LLM聊天机器人(增强版),具有记忆、表情包、跨插件调用和跨bot通信能力
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Python: <4.0,>=3.10
|
|
@@ -329,12 +329,14 @@ LLM 可以:
|
|
|
329
329
|
|
|
330
330
|
### 搜索 API
|
|
331
331
|
|
|
332
|
-
| API | 说明 | 额外依赖 |
|
|
333
|
-
|
|
334
|
-
| `tavily`(默认) | 专为 AI 设计,返回格式友好 | `tavily-python` |
|
|
335
|
-
| `bocha` | 国产 AI 搜索 API,中文搜索效果好 | 无 |
|
|
336
|
-
| `bing` |
|
|
337
|
-
| `openwebsearch` | 本地 Node.js 搜索服务,聚合多引擎(bing/baidu/duckduckgo 等) | 需先启动 daemon:`cd open-webSearch && npm install && npm run serve`,配置 `AIGFM_OPENWEBSEARCH_URL` |
|
|
332
|
+
| API | 说明 | 额外依赖 | 获取 Key / 部署 |
|
|
333
|
+
|-----|------|---------|----------------|
|
|
334
|
+
| `tavily`(默认) | 专为 AI 设计,返回格式友好 | `tavily-python` | https://app.tavily.com |
|
|
335
|
+
| `bocha` | 国产 AI 搜索 API,中文搜索效果好 | 无 | https://open.bochaai.com |
|
|
336
|
+
| `bing` | 微软必应搜索(Azure Bing Search API v7) | 无 | https://portal.azure.com |
|
|
337
|
+
| `openwebsearch` | 本地 Node.js 搜索服务,聚合多引擎(bing/baidu/duckduckgo 等) | 需先启动 daemon:`cd open-webSearch && npm install && npm run serve`,配置 `AIGFM_OPENWEBSEARCH_URL` | 无需 Key,项目:https://github.com/Aas-ee/open-webSearch |
|
|
338
|
+
|
|
339
|
+
> **Tavily** 需额外安装依赖:`pip install tavily-python`(或安装本插件时带上 extra:`pip install "nonebot-plugin-aigf-master[tavily]"`)
|
|
338
340
|
|
|
339
341
|
## 🧠 记忆系统
|
|
340
342
|
|
|
@@ -309,12 +309,14 @@ LLM 可以:
|
|
|
309
309
|
|
|
310
310
|
### 搜索 API
|
|
311
311
|
|
|
312
|
-
| API | 说明 | 额外依赖 |
|
|
313
|
-
|
|
314
|
-
| `tavily`(默认) | 专为 AI 设计,返回格式友好 | `tavily-python` |
|
|
315
|
-
| `bocha` | 国产 AI 搜索 API,中文搜索效果好 | 无 |
|
|
316
|
-
| `bing` |
|
|
317
|
-
| `openwebsearch` | 本地 Node.js 搜索服务,聚合多引擎(bing/baidu/duckduckgo 等) | 需先启动 daemon:`cd open-webSearch && npm install && npm run serve`,配置 `AIGFM_OPENWEBSEARCH_URL` |
|
|
312
|
+
| API | 说明 | 额外依赖 | 获取 Key / 部署 |
|
|
313
|
+
|-----|------|---------|----------------|
|
|
314
|
+
| `tavily`(默认) | 专为 AI 设计,返回格式友好 | `tavily-python` | https://app.tavily.com |
|
|
315
|
+
| `bocha` | 国产 AI 搜索 API,中文搜索效果好 | 无 | https://open.bochaai.com |
|
|
316
|
+
| `bing` | 微软必应搜索(Azure Bing Search API v7) | 无 | https://portal.azure.com |
|
|
317
|
+
| `openwebsearch` | 本地 Node.js 搜索服务,聚合多引擎(bing/baidu/duckduckgo 等) | 需先启动 daemon:`cd open-webSearch && npm install && npm run serve`,配置 `AIGFM_OPENWEBSEARCH_URL` | 无需 Key,项目:https://github.com/Aas-ee/open-webSearch |
|
|
318
|
+
|
|
319
|
+
> **Tavily** 需额外安装依赖:`pip install tavily-python`(或安装本插件时带上 extra:`pip install "nonebot-plugin-aigf-master[tavily]"`)
|
|
318
320
|
|
|
319
321
|
## 🧠 记忆系统
|
|
320
322
|
|
|
@@ -52,6 +52,7 @@ class LLMClient:
|
|
|
52
52
|
async def chat_with_tools(
|
|
53
53
|
self, prompt: str, model: str,
|
|
54
54
|
tools: list[dict], tool_handler,
|
|
55
|
+
json_mode: bool = False,
|
|
55
56
|
) -> tuple[str | None, bool]:
|
|
56
57
|
"""支持 function calling 的响应生成"""
|
|
57
58
|
messages = [{"role": "user", "content": prompt}]
|
|
@@ -81,6 +82,8 @@ class LLMClient:
|
|
|
81
82
|
messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": result})
|
|
82
83
|
|
|
83
84
|
kwargs: dict = {"messages": messages, "model": model, "temperature": 0.5, "timeout": 300}
|
|
85
|
+
if json_mode:
|
|
86
|
+
kwargs["response_format"] = {"type": "json_object"}
|
|
84
87
|
response = await self._client.chat.completions.create(**kwargs)
|
|
85
88
|
content = response.choices[0].message.content
|
|
86
89
|
return (_strip_think_tags(content) if content else None), used_tool
|
|
@@ -373,7 +373,10 @@ class MessageProcessor:
|
|
|
373
373
|
return result
|
|
374
374
|
return f"未知工具: {name}"
|
|
375
375
|
|
|
376
|
-
return await self.llm.chat_with_tools(
|
|
376
|
+
return await self.llm.chat_with_tools(
|
|
377
|
+
prompt, self.config.aigfm_llm_model, tools, handler,
|
|
378
|
+
json_mode=self.config.aigfm_llm_json_mode,
|
|
379
|
+
)
|
|
377
380
|
|
|
378
381
|
async def _save_memes(self, save_meme: list, cached_stickers: list[dict]):
|
|
379
382
|
current_ids = {s["id"] for s in cached_stickers}
|
|
@@ -108,13 +108,29 @@ def build_prompt(
|
|
|
108
108
|
sticker_section = """
|
|
109
109
|
## 当前消息中出现的图片(可收藏)
|
|
110
110
|
以下图片已通过视觉输入提供。请结合上下文判断是否值得收藏。
|
|
111
|
+
- 标记为"可能是表情包"的图片已附带情感和内容描述,是较可能的收藏候选
|
|
112
|
+
- 仅标记为"图片"的通常为普通图片,一般不需要收藏
|
|
113
|
+
请结合上下文进一步判断:
|
|
114
|
+
- 如果是表情包(能表达一定的情感,适合在群聊中反复使用),且你的表情包库内没有类似的图片,且你觉得值得保存的,可以收藏。
|
|
115
|
+
- 如果只是群友分享的照片、截图、梗图、普通图片,或者表情包库内已有类似图片,则不要收藏。
|
|
116
|
+
- 若群友连续发了多张图片,通常是在分享普通图片
|
|
117
|
+
- 若群友只发了一张图片,而前后均没有与这张图片相关的内容,或是在图片前后仅有对该图片的介绍或评论,通常是在分享普通图片
|
|
118
|
+
- 若群友发的图片内容与之前的内容有关联,或这张图片是在其它群友发言之后发出的,且**包含较为明显的情感**(开心、愤怒、疑惑等),则可能是表情包
|
|
111
119
|
如果值得收藏,在 memory.save_meme 中填入 id、简短描述和关键词。
|
|
112
120
|
可用 id:""" + ", ".join(sticker_ids)
|
|
113
121
|
else:
|
|
114
122
|
sticker_section = """
|
|
115
123
|
## 当前消息中出现的图片(可收藏)
|
|
116
124
|
消息中已标注初步判断结果。请结合上下文进一步判断是否值得收藏。
|
|
117
|
-
|
|
125
|
+
- 标记为"可能是表情包"的图片已附带情感和内容描述,是较可能的收藏候选
|
|
126
|
+
- 仅标记为"图片"的通常为普通图片,一般不需要收藏
|
|
127
|
+
请结合上下文进一步判断:
|
|
128
|
+
- 如果是表情包(能表达一定的情感,适合在群聊中反复使用),且你的表情包库内没有类似的图片,且你觉得值得保存的,可以收藏。
|
|
129
|
+
- 如果只是群友分享的照片、截图、梗图、普通图片,或者表情包库内已有类似图片,则不要收藏。
|
|
130
|
+
- 若群友连续发了多张图片,通常是在分享普通图片
|
|
131
|
+
- 若群友只发了一张图片,而前后均没有与这张图片相关的内容,或是在图片前后仅有对该图片的介绍或评论,通常是在分享普通图片
|
|
132
|
+
- 若群友发的图片内容与之前的内容有关联,或这张图片是在其它群友发言之后发出的,且**包含较为明显的情感**(开心、愤怒、疑惑等),则可能是表情包
|
|
133
|
+
如果值得收藏,在 memory.save_meme 中填入 id 和你写的简短描述。
|
|
118
134
|
可用 id:""" + ", ".join(sticker_ids)
|
|
119
135
|
|
|
120
136
|
# 群友列表
|
|
@@ -129,7 +145,7 @@ def build_prompt(
|
|
|
129
145
|
当用户要求使用以下**本机**功能,且聊天记录中**还没有**该命令的调用记录时,调用 invoke_plugin 工具来执行命令,不要自己编造回复:
|
|
130
146
|
{cmd_list}
|
|
131
147
|
|
|
132
|
-
调用示例:用户说"
|
|
148
|
+
调用示例:用户说"帮我查一下今日小猪",且你此前未调用过,应调用 invoke_plugin(command="今日小猪")
|
|
133
149
|
|
|
134
150
|
## 调用身份
|
|
135
151
|
调用 invoke_plugin 或 invoke_peer_plugin 时,可通过 user_id 参数指定以哪位群友的身份调用(从上方"相关群友信息/已知群友昵称"中选择 QQ 号)。
|
|
@@ -140,7 +156,7 @@ def build_prompt(
|
|
|
140
156
|
调用 invoke_plugin / invoke_peer_plugin 后,插件的响应(文本或图片描述)会以 `[插件名] 内容` 或 `[bot名] 内容` 的形式作为**新消息**出现在后续聊天记录中。
|
|
141
157
|
- 调用后,本次回复必须为空(`"reply": []`),**不要说话**,等插件响应出现
|
|
142
158
|
- 当聊天记录中出现 `[插件名] 内容` 或 `[bot名] 内容` 后,再根据插件响应决定是否回复、回复什么,**不要编造**插件的内容
|
|
143
|
-
- **不要重复调用**:如果聊天记录中已经出现 `[
|
|
159
|
+
- **不要重复调用**:如果聊天记录中已经出现 `[你的名字] 已调用命令「xxx」`,说明该命令已调用过,**绝不要再调用**,直接根据已有内容判断是否回复
|
|
144
160
|
- 如果插件响应一直未出现,再视情况告知用户插件未响应
|
|
145
161
|
|
|
146
162
|
## 重要:已知命令的处理
|
|
@@ -271,10 +287,15 @@ fields: info(一般信息), aliases(称呼), nickname(QQ昵称), past_nicknames(
|
|
|
271
287
|
"friends": {{"123456": {{"add": [], "modify": [], "delete": [], "add_alias": [], "remove_alias": []}}}},
|
|
272
288
|
"save_meme": [{{ "id": "cache_id", "description": "描述", "keywords": ["关键词"] }}],
|
|
273
289
|
"culture": {{"add": [{{"term": "", "meaning": "", "context": ""}}], "modify": [], "delete": []}}
|
|
274
|
-
}}
|
|
290
|
+
}},
|
|
291
|
+
"command_learning": [{{"name": "命令名", "parameters": "可选参数说明(无则留空)", "usage": "命令 [参数]", "hook_type": "current或peer", "source": "current填插件名/peer填bot名", "examples": ["用户发送的原文"]}}],
|
|
292
|
+
"command_edit": [{{"name": "命令名", "parameters": "更新后参数说明", "usage": "更新后用法", "examples": ["更新后示例"]}}],
|
|
293
|
+
"command_delete": ["命令名"]
|
|
275
294
|
}}
|
|
276
295
|
```
|
|
277
296
|
|
|
297
|
+
> `command_learning` / `command_edit` / `command_delete` 是**可选**顶层字段:只在识别到新命令、需修正或删除已有命令时才输出,无相关操作时**整个字段省略**(`reply`、`memory` 各子项为空数组时也要保留外层结构)。
|
|
298
|
+
|
|
278
299
|
## 回复决策
|
|
279
300
|
- 有人 @ 你 → 通常回复
|
|
280
301
|
- 有人回复了你之前的消息 → 回复
|
|
@@ -6,12 +6,61 @@ import re
|
|
|
6
6
|
from .models import MemoryOps, ReplySegment
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
def _extract_json_object(text: str) -> str | None:
|
|
10
|
+
"""扫描每个 '{' 起点做花括号平衡(正确处理字符串内的 {} 与 \\" 转义),
|
|
11
|
+
返回第一个能成功解析为 JSON 的对象子串;找不到返回 None。"""
|
|
12
|
+
n = len(text)
|
|
13
|
+
i = 0
|
|
14
|
+
while i < n:
|
|
15
|
+
if text[i] != "{":
|
|
16
|
+
i += 1
|
|
17
|
+
continue
|
|
18
|
+
depth = 0
|
|
19
|
+
in_str = False
|
|
20
|
+
esc = False
|
|
21
|
+
j = i
|
|
22
|
+
while j < n:
|
|
23
|
+
ch = text[j]
|
|
24
|
+
if in_str:
|
|
25
|
+
if esc:
|
|
26
|
+
esc = False
|
|
27
|
+
elif ch == "\\":
|
|
28
|
+
esc = True
|
|
29
|
+
elif ch == '"':
|
|
30
|
+
in_str = False
|
|
31
|
+
else:
|
|
32
|
+
if ch == '"':
|
|
33
|
+
in_str = True
|
|
34
|
+
elif ch == "{":
|
|
35
|
+
depth += 1
|
|
36
|
+
elif ch == "}":
|
|
37
|
+
depth -= 1
|
|
38
|
+
if depth == 0:
|
|
39
|
+
break
|
|
40
|
+
j += 1
|
|
41
|
+
if j < n:
|
|
42
|
+
candidate = text[i:j + 1]
|
|
43
|
+
try:
|
|
44
|
+
json.loads(candidate)
|
|
45
|
+
return candidate
|
|
46
|
+
except json.JSONDecodeError:
|
|
47
|
+
pass
|
|
48
|
+
i += 1
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
|
|
9
52
|
def parse_llm_response(raw: str) -> dict | None:
|
|
10
|
-
"""解析 LLM 返回的 JSON,去除 think
|
|
53
|
+
"""解析 LLM 返回的 JSON,去除 think 标签和代码块标记;容忍前导/尾随文字"""
|
|
11
54
|
cleaned = re.sub(r"^```json\s*|\s*```$", "", raw.strip())
|
|
12
55
|
try:
|
|
13
56
|
return json.loads(cleaned)
|
|
14
57
|
except json.JSONDecodeError:
|
|
58
|
+
candidate = _extract_json_object(cleaned)
|
|
59
|
+
if candidate:
|
|
60
|
+
try:
|
|
61
|
+
return json.loads(candidate)
|
|
62
|
+
except json.JSONDecodeError:
|
|
63
|
+
return None
|
|
15
64
|
return None
|
|
16
65
|
|
|
17
66
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nonebot-plugin-aigf-master
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: 群聊特化LLM聊天机器人(增强版),具有记忆、表情包、跨插件调用和跨bot通信能力
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Python: <4.0,>=3.10
|
|
@@ -329,12 +329,14 @@ LLM 可以:
|
|
|
329
329
|
|
|
330
330
|
### 搜索 API
|
|
331
331
|
|
|
332
|
-
| API | 说明 | 额外依赖 |
|
|
333
|
-
|
|
334
|
-
| `tavily`(默认) | 专为 AI 设计,返回格式友好 | `tavily-python` |
|
|
335
|
-
| `bocha` | 国产 AI 搜索 API,中文搜索效果好 | 无 |
|
|
336
|
-
| `bing` |
|
|
337
|
-
| `openwebsearch` | 本地 Node.js 搜索服务,聚合多引擎(bing/baidu/duckduckgo 等) | 需先启动 daemon:`cd open-webSearch && npm install && npm run serve`,配置 `AIGFM_OPENWEBSEARCH_URL` |
|
|
332
|
+
| API | 说明 | 额外依赖 | 获取 Key / 部署 |
|
|
333
|
+
|-----|------|---------|----------------|
|
|
334
|
+
| `tavily`(默认) | 专为 AI 设计,返回格式友好 | `tavily-python` | https://app.tavily.com |
|
|
335
|
+
| `bocha` | 国产 AI 搜索 API,中文搜索效果好 | 无 | https://open.bochaai.com |
|
|
336
|
+
| `bing` | 微软必应搜索(Azure Bing Search API v7) | 无 | https://portal.azure.com |
|
|
337
|
+
| `openwebsearch` | 本地 Node.js 搜索服务,聚合多引擎(bing/baidu/duckduckgo 等) | 需先启动 daemon:`cd open-webSearch && npm install && npm run serve`,配置 `AIGFM_OPENWEBSEARCH_URL` | 无需 Key,项目:https://github.com/Aas-ee/open-webSearch |
|
|
338
|
+
|
|
339
|
+
> **Tavily** 需额外安装依赖:`pip install tavily-python`(或安装本插件时带上 extra:`pip install "nonebot-plugin-aigf-master[tavily]"`)
|
|
338
340
|
|
|
339
341
|
## 🧠 记忆系统
|
|
340
342
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|