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

View File

@@ -5,6 +5,8 @@ import hashlib
from typing import Optional
from PIL import Image
import io
import math
import numpy as np
from ...common.database import db
@@ -112,8 +114,13 @@ class ImageManager:
return f"[表情包:{cached_description}]"
# 调用AI获取描述
prompt = "这是一个表情包,使用中文简洁的描述一下表情包的内容和表情包所表达的情感"
description, _ = await self._llm.generate_response_for_image(prompt, image_base64, image_format)
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 = "这是一个表情包,使用中文简洁的描述一下表情包的内容和表情包所表达的情感"
description, _ = await self._llm.generate_response_for_image(prompt, image_base64, image_format)
cached_description = self._get_description_from_db(image_hash, "emoji")
if cached_description:
@@ -221,6 +228,72 @@ class ImageManager:
logger.error(f"获取图片描述失败: {str(e)}")
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()