better: 更好的表情包发送系统
This commit is contained in:
19
README.md
19
README.md
@@ -37,7 +37,7 @@
|
||||
|
||||
</p>
|
||||
|
||||
## 新版0.6.0部署前先阅读:https://docs.mai-mai.org/manual/usage/mmc_q_a
|
||||
## 新版0.6.x部署前先阅读:https://docs.mai-mai.org/manual/usage/mmc_q_a
|
||||
|
||||
|
||||
## 📝 项目简介
|
||||
@@ -62,7 +62,7 @@
|
||||
|
||||
### 📢 版本信息
|
||||
|
||||
**最新版本: v0.6.0** ([查看更新日志](changelogs/changelog.md))
|
||||
**最新版本: v0.6.2** ([查看更新日志](changelogs/changelog.md))
|
||||
> [!WARNING]
|
||||
> 请阅读教程后更新!!!!!!!
|
||||
> 请阅读教程后更新!!!!!!!
|
||||
@@ -86,7 +86,7 @@
|
||||
|
||||
### ⚠️ 重要提示
|
||||
|
||||
- 升级到v0.6.0版本前请务必阅读:[升级指南](https://docs.mai-mai.org/manual/usage/mmc_q_a)
|
||||
- 升级到v0.6.x版本前请务必阅读:[升级指南](https://docs.mai-mai.org/manual/usage/mmc_q_a)
|
||||
- 本版本基于MaiCore重构,通过nonebot插件与QQ平台交互
|
||||
- 项目处于活跃开发阶段,功能和API可能随时调整
|
||||
|
||||
@@ -115,21 +115,22 @@
|
||||
|
||||
| 模块 | 主要功能 | 特点 |
|
||||
|------|---------|------|
|
||||
| 💬 聊天系统 | • 思维流/推理聊天<br>• 关键词主动发言<br>• 多模型支持<br>• 动态prompt构建<br>• 私聊功能(PFC) | 拟人化交互 |
|
||||
| 🧠 思维流系统 | • 实时思考生成<br>• 自动启停机制<br>• 日程系统联动 | 智能化决策 |
|
||||
| 🧠 记忆系统 2.0 | • 优化记忆抽取<br>• 海马体记忆机制<br>• 聊天记录概括 | 持久化记忆 |
|
||||
| 😊 表情包系统 | • 情绪匹配发送<br>• GIF支持<br>• 自动收集与审查 | 丰富表达 |
|
||||
| 💬 聊天系统 | • 心流/推理聊天<br>• 关键词主动发言<br>• 多模型支持<br>• 动态prompt构建<br>• 私聊功能(PFC) | 拟人化交互 |
|
||||
| 🧠 心流系统 | • 实时思考生成<br>• 自动启停机制<br>• 日程系统联动<br>• 工具调用能力 | 智能化决策 |
|
||||
| 🧠 记忆系统 | • 优化记忆抽取<br>• 海马体记忆机制<br>• 聊天记录概括 | 持久化记忆 |
|
||||
| 😊 表情系统 | • 情绪匹配发送<br>• GIF支持<br>• 自动收集与审查 | 丰富表达 |
|
||||
| 📅 日程系统 | • 动态日程生成<br>• 自定义想象力<br>• 思维流联动 | 智能规划 |
|
||||
| 👥 关系系统 2.0 | • 关系管理优化<br>• 丰富接口支持<br>• 个性化交互 | 深度社交 |
|
||||
| 👥 关系系统 | • 关系管理优化<br>• 丰富接口支持<br>• 个性化交互 | 深度社交 |
|
||||
| 📊 统计系统 | • 使用数据统计<br>• LLM调用记录<br>• 实时控制台显示 | 数据可视 |
|
||||
| 🔧 系统功能 | • 优雅关闭机制<br>• 自动数据保存<br>• 异常处理完善 | 稳定可靠 |
|
||||
| 🛠️ 工具系统 | • 知识获取工具<br>• 自动注册机制<br>• 多工具支持 | 扩展功能 |
|
||||
|
||||
## 📐 项目架构
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[MaiCore] --> B[对话系统]
|
||||
A --> C[思维流系统]
|
||||
A --> C[心流系统]
|
||||
A --> D[记忆系统]
|
||||
A --> E[情感系统]
|
||||
B --> F[多模型支持]
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
- 需要配置支持工具调用的模型才能使用完整功能
|
||||
|
||||
#### 心流系统
|
||||
- 新增了上下文压缩缓存功能,可以有更持久的记忆
|
||||
- 新增了心流系统的README.md文件,详细介绍了系统架构、主要功能和工作流程。
|
||||
- 优化了心流系统的逻辑,包括子心流自动清理和合理配置更新间隔。
|
||||
- 改进了心流观察系统,优化了提示词设计和系统表现,使心流运行更加稳定高效。
|
||||
@@ -27,6 +28,8 @@
|
||||
- 新增了`ReplyGenerator`类,用于根据观察信息和对话信息生成回复。
|
||||
- 优化了消息队列管理系统,支持按时间顺序处理消息。
|
||||
|
||||
#### 现在可以启用更好的表情包发送系统
|
||||
|
||||
### 💻 系统架构优化
|
||||
|
||||
#### 部署支持
|
||||
|
||||
28
src/do_tool/tool_can_use/send_emoji.py
Normal file
28
src/do_tool/tool_can_use/send_emoji.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from src.do_tool.tool_can_use.base_tool import BaseTool
|
||||
from src.common.logger import get_module_logger
|
||||
|
||||
from typing import Dict, Any
|
||||
|
||||
logger = get_module_logger("send_emoji_tool")
|
||||
|
||||
|
||||
class SendEmojiTool(BaseTool):
|
||||
"""发送表情包的工具"""
|
||||
|
||||
name = "send_emoji"
|
||||
description = "当你觉得需要表达情感,或者帮助表达,可以使用这个工具发送表情包"
|
||||
parameters = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"text": {"type": "string", "description": "要发送的表情包描述"}
|
||||
},
|
||||
"required": ["text"],
|
||||
}
|
||||
|
||||
async def execute(self, function_args: Dict[str, Any], message_txt: str) -> Dict[str, Any]:
|
||||
text = function_args.get("text", message_txt)
|
||||
return {
|
||||
"name": "send_emoji",
|
||||
"content": text,
|
||||
}
|
||||
|
||||
@@ -324,27 +324,35 @@ def random_remove_punctuation(text: str) -> str:
|
||||
|
||||
|
||||
def process_llm_response(text: str) -> List[str]:
|
||||
# processed_response = process_text_with_typos(content)
|
||||
# 对西文字符段落的回复长度设置为汉字字符的两倍
|
||||
max_length = global_config.response_max_length * 3
|
||||
# 提取被 () 或 [] 包裹的内容
|
||||
pattern = re.compile(r'[\(\[].*?[\)\]]')
|
||||
_extracted_contents = pattern.findall(text)
|
||||
# 去除 () 和 [] 及其包裹的内容
|
||||
cleaned_text = pattern.sub('', text)
|
||||
logger.debug(f"{text}去除括号处理后的文本: {cleaned_text}")
|
||||
|
||||
# 对清理后的文本进行进一步处理
|
||||
max_length = global_config.response_max_length * 2
|
||||
max_sentence_num = global_config.response_max_sentence_num
|
||||
if len(text) > max_length and not is_western_paragraph(text):
|
||||
logger.warning(f"回复过长 ({len(text)} 字符),返回默认回复")
|
||||
if len(cleaned_text) > max_length and not is_western_paragraph(cleaned_text):
|
||||
logger.warning(f"回复过长 ({len(cleaned_text)} 字符),返回默认回复")
|
||||
return ["懒得说"]
|
||||
elif len(text) > 200:
|
||||
logger.warning(f"回复过长 ({len(text)} 字符),返回默认回复")
|
||||
elif len(cleaned_text) > 200:
|
||||
logger.warning(f"回复过长 ({len(cleaned_text)} 字符),返回默认回复")
|
||||
return ["懒得说"]
|
||||
# 处理长消息
|
||||
|
||||
typo_generator = ChineseTypoGenerator(
|
||||
error_rate=global_config.chinese_typo_error_rate,
|
||||
min_freq=global_config.chinese_typo_min_freq,
|
||||
tone_error_rate=global_config.chinese_typo_tone_error_rate,
|
||||
word_replace_rate=global_config.chinese_typo_word_replace_rate,
|
||||
)
|
||||
|
||||
if global_config.enable_response_splitter:
|
||||
split_sentences = split_into_sentences_w_remove_punctuation(text)
|
||||
split_sentences = split_into_sentences_w_remove_punctuation(cleaned_text)
|
||||
else:
|
||||
split_sentences = [text]
|
||||
split_sentences = [cleaned_text]
|
||||
|
||||
sentences = []
|
||||
for sentence in split_sentences:
|
||||
if global_config.chinese_typo_enable:
|
||||
@@ -354,11 +362,12 @@ def process_llm_response(text: str) -> List[str]:
|
||||
sentences.append(typo_corrections)
|
||||
else:
|
||||
sentences.append(sentence)
|
||||
# 检查分割后的消息数量是否过多(超过3条)
|
||||
|
||||
if len(sentences) > max_sentence_num:
|
||||
logger.warning(f"分割后消息数量过多 ({len(sentences)} 条),返回默认回复")
|
||||
return [f"{global_config.BOT_NICKNAME}不知道哦"]
|
||||
|
||||
# sentences.extend(extracted_contents)
|
||||
|
||||
return sentences
|
||||
|
||||
|
||||
@@ -108,33 +108,35 @@ class ThinkFlowChat:
|
||||
message_manager.add_message(message_set)
|
||||
return first_bot_msg
|
||||
|
||||
async def _handle_emoji(self, message, chat, response):
|
||||
async def _handle_emoji(self, message, chat, response, send_emoji = ""):
|
||||
"""处理表情包"""
|
||||
if random() < global_config.emoji_chance:
|
||||
if send_emoji:
|
||||
emoji_raw = await emoji_manager.get_emoji_for_text(send_emoji)
|
||||
else:
|
||||
emoji_raw = await emoji_manager.get_emoji_for_text(response)
|
||||
if emoji_raw:
|
||||
emoji_path, description = emoji_raw
|
||||
emoji_cq = image_path_to_base64(emoji_path)
|
||||
if emoji_raw:
|
||||
emoji_path, description = emoji_raw
|
||||
emoji_cq = image_path_to_base64(emoji_path)
|
||||
|
||||
thinking_time_point = round(message.message_info.time, 2)
|
||||
thinking_time_point = round(message.message_info.time, 2)
|
||||
|
||||
message_segment = Seg(type="emoji", data=emoji_cq)
|
||||
bot_message = MessageSending(
|
||||
message_id="mt" + str(thinking_time_point),
|
||||
chat_stream=chat,
|
||||
bot_user_info=UserInfo(
|
||||
user_id=global_config.BOT_QQ,
|
||||
user_nickname=global_config.BOT_NICKNAME,
|
||||
platform=message.message_info.platform,
|
||||
),
|
||||
sender_info=message.message_info.user_info,
|
||||
message_segment=message_segment,
|
||||
reply=message,
|
||||
is_head=False,
|
||||
is_emoji=True,
|
||||
)
|
||||
message_segment = Seg(type="emoji", data=emoji_cq)
|
||||
bot_message = MessageSending(
|
||||
message_id="mt" + str(thinking_time_point),
|
||||
chat_stream=chat,
|
||||
bot_user_info=UserInfo(
|
||||
user_id=global_config.BOT_QQ,
|
||||
user_nickname=global_config.BOT_NICKNAME,
|
||||
platform=message.message_info.platform,
|
||||
),
|
||||
sender_info=message.message_info.user_info,
|
||||
message_segment=message_segment,
|
||||
reply=message,
|
||||
is_head=False,
|
||||
is_emoji=True,
|
||||
)
|
||||
|
||||
message_manager.add_message(bot_message)
|
||||
message_manager.add_message(bot_message)
|
||||
|
||||
async def _update_relationship(self, message: MessageRecv, response_set):
|
||||
"""更新关系情绪"""
|
||||
@@ -264,6 +266,7 @@ class ThinkFlowChat:
|
||||
update_relationship = ""
|
||||
get_mid_memory_id = []
|
||||
tool_result_info = {}
|
||||
send_emoji = ""
|
||||
try:
|
||||
with Timer("思考前使用工具", timing_results):
|
||||
tool_result = await self.tool_user.use_tool(
|
||||
@@ -302,6 +305,9 @@ class ThinkFlowChat:
|
||||
# 特殊判定:change_relationship
|
||||
if tool_name == "change_relationship":
|
||||
update_relationship = tool_data[0]["content"]
|
||||
|
||||
if tool_name == "send_emoji":
|
||||
send_emoji = tool_data[0]["content"]
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"思考前工具调用失败: {e}")
|
||||
@@ -357,7 +363,13 @@ class ThinkFlowChat:
|
||||
# 处理表情包
|
||||
try:
|
||||
with Timer("处理表情包", timing_results):
|
||||
await self._handle_emoji(message, chat, response_set)
|
||||
if global_config.emoji_chance == 1:
|
||||
if send_emoji:
|
||||
logger.info(f"麦麦决定发送表情包{send_emoji}")
|
||||
await self._handle_emoji(message, chat, response_set, send_emoji)
|
||||
else:
|
||||
if random() < global_config.emoji_chance:
|
||||
await self._handle_emoji(message, chat, response_set)
|
||||
except Exception as e:
|
||||
logger.error(f"心流处理表情包失败: {e}")
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ def init_prompt():
|
||||
你的名字叫{bot_name},{prompt_identity}。
|
||||
{chat_target},你希望在群里回复:{content}。现在请你根据以下信息修改回复内容。将这个回复修改的更加日常且口语化的回复,平淡一些,回复尽量简短一些。不要回复的太有条理。
|
||||
{prompt_ger},不要刻意突出自身学科背景,注意只输出回复内容。
|
||||
{moderation_prompt}。注意:不要输出多余内容(包括前后缀,冒号和引号,括号,表情包,at或 @等 )。""",
|
||||
{moderation_prompt}。注意:不要输出多余内容(包括前后缀,冒号和引号,at或 @等 )。""",
|
||||
"heart_flow_prompt_response",
|
||||
)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -86,7 +86,7 @@ compress_length_limit = 5 #最多压缩份数,超过该数值的压缩上下
|
||||
|
||||
[message]
|
||||
max_context_size = 12 # 麦麦获得的上文数量,建议12,太短太长都会导致脑袋尖尖
|
||||
emoji_chance = 0.2 # 麦麦使用表情包的概率
|
||||
emoji_chance = 0.2 # 麦麦使用表情包的概率,设置为1让麦麦自己决定发不发
|
||||
thinking_timeout = 60 # 麦麦最长思考时间,超过这个时间的思考会放弃
|
||||
max_response_length = 256 # 麦麦回答的最大token数
|
||||
message_buffer = true # 启用消息缓冲器?启用此项以解决消息的拆分问题,但会使麦麦的回复延迟
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user