better:新增log前缀映射,优化emoji的显示,加强了emoji的识别

This commit is contained in:
SengokuCola
2025-07-24 04:54:47 +08:00
parent 6c9c94d719
commit 6c91b95314
5 changed files with 159 additions and 51 deletions

View File

@@ -6,6 +6,7 @@ import uuid
import io
import asyncio
import numpy as np
import jieba
from typing import Optional, Tuple
from PIL import Image
@@ -94,7 +95,7 @@ class ImageManager:
logger.error(f"保存描述到数据库失败 (Peewee): {str(e)}")
async def get_emoji_description(self, image_base64: str) -> str:
"""获取表情包描述,带查重和保存功能"""
"""获取表情包描述,使用二步走识别并带缓存优化"""
try:
# 计算图片哈希
# 确保base64字符串只包含ASCII字符
@@ -107,33 +108,66 @@ class ImageManager:
# 查询缓存的描述
cached_description = self._get_description_from_db(image_hash, "emoji")
if cached_description:
return f"[表情包,含义看起来是{cached_description}]"
return f"[表情包:{cached_description}]"
# 调用AI获取描述
# === 二步走识别流程 ===
# 第一步VLM视觉分析 - 生成详细描述
if image_format in ["gif", "GIF"]:
image_base64_processed = self.transform_gif(image_base64)
if image_base64_processed is None:
logger.warning("GIF转换失败无法获取描述")
return "[表情包(GIF处理失败)]"
prompt = "这是一个动态图表情包,每一张图代表了动态图的某一帧,黑色背景代表透明,使用1-2个词描述一下表情包表达的情感和内容,简短一些输出一段平文本只输出1-2个词就好不要输出其他内容"
description, _ = await self._llm.generate_response_for_image(prompt, image_base64_processed, "jpg")
vlm_prompt = "这是一个动态图表情包,每一张图代表了动态图的某一帧,黑色背景代表透明,描述一下表情包表达的情感和内容,描述细节,从互联网梗,meme的角度去分析"
detailed_description, _ = await self._llm.generate_response_for_image(vlm_prompt, image_base64_processed, "jpg")
else:
prompt = "图片是一个表情包,请用使用1-2个词描述一下表情包所表达的情感和内容,简短一些输出一段平文本只输出1-2个词就好不要输出其他内容"
description, _ = await self._llm.generate_response_for_image(prompt, image_base64, image_format)
vlm_prompt = "是一个表情包,请详细描述一下表情包所表达的情感和内容,描述细节,从互联网梗,meme的角度去分析"
detailed_description, _ = await self._llm.generate_response_for_image(vlm_prompt, image_base64, image_format)
if description is None:
logger.warning("AI未能生成表情包描述")
return "[表情包(描述生成失败)]"
if detailed_description is None:
logger.warning("VLM未能生成表情包详细描述")
return "[表情包(VLM描述生成失败)]"
# 第二步LLM情感分析 - 基于详细描述生成简短的情感标签
emotion_prompt = f"""
请你基于这个表情包的详细描述提取出最核心的情感含义用1-2个词概括。
详细描述:'{detailed_description}'
要求:
1. 只输出1-2个最核心的情感词汇
2. 从互联网梗、meme的角度理解
3. 输出简短精准,不要解释
4. 如果有多个词用逗号分隔
"""
# 使用较低温度确保输出稳定
emotion_llm = LLMRequest(model=global_config.model.utils, temperature=0.3, max_tokens=50, request_type="emoji")
emotion_result, _ = await emotion_llm.generate_response_async(emotion_prompt)
if emotion_result is None:
logger.warning("LLM未能生成情感标签使用详细描述的前几个词")
# 降级处理:从详细描述中提取关键词
import jieba
words = list(jieba.cut(detailed_description))
emotion_result = "".join(words[:2]) if len(words) >= 2 else (words[0] if words else "表情")
# 处理情感结果取前1-2个最重要的标签
emotions = [e.strip() for e in emotion_result.replace("", ",").split(",") if e.strip()]
final_emotion = emotions[0] if emotions else "表情"
# 如果有第二个情感且不重复,也包含进来
if len(emotions) > 1 and emotions[1] != emotions[0]:
final_emotion = f"{emotions[0]}{emotions[1]}"
logger.info(f"[二步走识别] 详细描述: {detailed_description[:50]}... -> 情感标签: {final_emotion}")
# 再次检查缓存,防止并发写入时重复生成
cached_description = self._get_description_from_db(image_hash, "emoji")
if cached_description:
logger.warning(f"虽然生成了描述,但是找到缓存表情包描述: {cached_description}")
return f"[表情包,含义看起来是{cached_description}]"
return f"[表情包:{cached_description}]"
# 根据配置决定是否保存图片
# if global_config.emoji.save_emoji:
# 生成文件名和路径
# 保存表情包文件和元数据(用于可能的后续分析)
logger.debug(f"保存表情包: {image_hash}")
current_timestamp = time.time()
filename = f"{int(current_timestamp)}_{image_hash[:8]}.{image_format}"
@@ -146,11 +180,11 @@ class ImageManager:
with open(file_path, "wb") as f:
f.write(image_bytes)
# 保存到数据库 (Images表)
# 保存到数据库 (Images表) - 包含详细描述用于可能的注册流程
try:
img_obj = Images.get((Images.emoji_hash == image_hash) & (Images.type == "emoji"))
img_obj.path = file_path
img_obj.description = description
img_obj.description = detailed_description # 保存详细描述
img_obj.timestamp = current_timestamp
img_obj.save()
except Images.DoesNotExist: # type: ignore
@@ -158,17 +192,17 @@ class ImageManager:
emoji_hash=image_hash,
path=file_path,
type="emoji",
description=description,
description=detailed_description, # 保存详细描述
timestamp=current_timestamp,
)
# logger.debug(f"保存表情包元数据: {file_path}")
except Exception as e:
logger.error(f"保存表情包文件或元数据失败: {str(e)}")
# 保存描述到数据库 (ImageDescriptions表)
self._save_description_to_db(image_hash, description, "emoji")
# 保存最终的情感标签到缓存 (ImageDescriptions表)
self._save_description_to_db(image_hash, final_emotion, "emoji")
return f"[表情包:{description}]"
return f"[表情包:{final_emotion}]"
except Exception as e:
logger.error(f"获取表情包描述失败: {str(e)}")
return "[表情包]"