feat:可以阅读gif

This commit is contained in:
SengokuCola
2025-04-04 15:31:56 +08:00
parent 579d6b0a1a
commit e0c5cf95d0
3 changed files with 90 additions and 7 deletions

View File

@@ -1,14 +1,13 @@
# Changelog # Changelog
## [0.6.0] - 2025-3-30 ## [0.6.0] - 2025-4-4
### 🌟 核心功能增强 ### 🌟 核心功能增强
#### 架构重构 #### 架构重构
- 将MaiBot重构为MaiCore独立智能体 - 将MaiBot重构为MaiCore独立智能体
- 移除NoneBot相关代码改为插件方式与NoneBot对接 - 移除NoneBot相关代码改为插件方式与NoneBot对接
- 精简代码结构,优化文件夹组织
- 新增详细统计系统
#### 思维流系统 #### 思维流系统
- 提供两种聊天逻辑思维流聊天ThinkFlowChat和推理聊天ReasoningChat
- 新增思维流作为实验功能 - 新增思维流作为实验功能
- 思维流大核+小核架构 - 思维流大核+小核架构
- 思维流回复意愿模式 - 思维流回复意愿模式
@@ -21,6 +20,8 @@
#### 回复系统 #### 回复系统
- 优化回复逻辑,添加回复前思考机制 - 优化回复逻辑,添加回复前思考机制
- 移除推理模型在回复中的使用 - 移除推理模型在回复中的使用
- 更改了回复引用的逻辑,从基于时间改为基于新消息
- 提供私聊的PFC模式可以进行有目的自由多轮对话
#### 记忆系统优化 #### 记忆系统优化
- 优化记忆抽取策略 - 优化记忆抽取策略
@@ -31,6 +32,13 @@
- 修复relationship_value类型错误 - 修复relationship_value类型错误
- 优化关系管理系统 - 优化关系管理系统
- 改进关系值计算方式 - 改进关系值计算方式
- 修复并重启了关系系统
#### 表情包系统
- 可以识别gif表情包
- 修复了表情包的注册,获取和发送逻辑
- 表情包增加存储上限
- 自动清理缓存图片
### 💻 系统架构优化 ### 💻 系统架构优化
#### 配置系统改进 #### 配置系统改进
@@ -83,6 +91,7 @@
- 优化cmd清理功能 - 优化cmd清理功能
- 改进LLM使用统计 - 改进LLM使用统计
- 优化记忆处理效率 - 优化记忆处理效率
- 增加了调试信息
### 📚 文档更新 ### 📚 文档更新
- 更新README.md内容 - 更新README.md内容
@@ -93,6 +102,7 @@
### 🔧 其他改进 ### 🔧 其他改进
- 新增神秘小测验功能 - 新增神秘小测验功能
- 新增详细统计系统
- 新增人格测评模型 - 新增人格测评模型
- 优化表情包审查功能 - 优化表情包审查功能
- 改进消息转发处理 - 改进消息转发处理
@@ -111,8 +121,6 @@
5. 加强WebUI功能 5. 加强WebUI功能
6. 完善部署文档 6. 完善部署文档
## [0.5.15] - 2025-3-17 ## [0.5.15] - 2025-3-17
### 🌟 核心功能增强 ### 🌟 核心功能增强
#### 关系系统升级 #### 关系系统升级

View File

@@ -1,4 +1,6 @@
这里放置了测试版本的细节更新 这里放置了测试版本的细节更新
## [test-0.6.0-snapshot-9] - 2025-4-4
- 可以识别gif表情包
## [test-0.6.0-snapshot-8] - 2025-4-3 ## [test-0.6.0-snapshot-8] - 2025-4-3
- 修复了表情包的注册,获取和发送逻辑 - 修复了表情包的注册,获取和发送逻辑

View File

@@ -5,6 +5,8 @@ import hashlib
from typing import Optional from typing import Optional
from PIL import Image from PIL import Image
import io import io
import math
import numpy as np
from ...common.database import db from ...common.database import db
@@ -112,6 +114,11 @@ class ImageManager:
return f"[表情包:{cached_description}]" return f"[表情包:{cached_description}]"
# 调用AI获取描述 # 调用AI获取描述
if image_format == "gif" or image_format == "GIF":
image_base64 = self.transform_gif(image_base64)
prompt = "这是一个动态图表情包,每一张图代表了动态图的某一帧,黑色背景代表透明,使用中文简洁的描述一下表情包的内容和表达的情感,简短一些"
description, _ = await self._llm.generate_response_for_image(prompt, image_base64, "jpg")
else:
prompt = "这是一个表情包,使用中文简洁的描述一下表情包的内容和表情包所表达的情感" prompt = "这是一个表情包,使用中文简洁的描述一下表情包的内容和表情包所表达的情感"
description, _ = await self._llm.generate_response_for_image(prompt, image_base64, image_format) description, _ = await self._llm.generate_response_for_image(prompt, image_base64, image_format)
@@ -221,6 +228,72 @@ class ImageManager:
logger.error(f"获取图片描述失败: {str(e)}") logger.error(f"获取图片描述失败: {str(e)}")
return "[图片]" return "[图片]"
def transform_gif(self, gif_base64: str) -> str:
"""将GIF转换为水平拼接的静态图像
Args:
gif_base64: GIF的base64编码字符串
Returns:
str: 拼接后的JPG图像的base64编码字符串
"""
try:
# 解码base64
gif_data = base64.b64decode(gif_base64)
gif = Image.open(io.BytesIO(gif_data))
# 收集所有帧
frames = []
try:
while True:
gif.seek(len(frames))
frame = gif.convert('RGB')
frames.append(frame.copy())
except EOFError:
pass
if not frames:
raise ValueError("No frames found in GIF")
# 计算需要抽取的帧的索引
total_frames = len(frames)
if total_frames <= 15:
selected_frames = frames
else:
# 均匀抽取10帧
indices = [int(i * (total_frames - 1) / 14) for i in range(15)]
selected_frames = [frames[i] for i in indices]
# 获取单帧的尺寸
frame_width, frame_height = selected_frames[0].size
# 计算目标尺寸,保持宽高比
target_height = 200 # 固定高度
target_width = int((target_height / frame_height) * frame_width)
# 调整所有帧的大小
resized_frames = [frame.resize((target_width, target_height), Image.Resampling.LANCZOS)
for frame in selected_frames]
# 创建拼接图像
total_width = target_width * len(resized_frames)
combined_image = Image.new('RGB', (total_width, target_height))
# 水平拼接图像
for idx, frame in enumerate(resized_frames):
combined_image.paste(frame, (idx * target_width, 0))
# 转换为base64
buffer = io.BytesIO()
combined_image.save(buffer, format='JPEG', quality=85)
result_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8')
return result_base64
except Exception as e:
logger.error(f"GIF转换失败: {str(e)}")
return None
# 创建全局单例 # 创建全局单例
image_manager = ImageManager() image_manager = ImageManager()