refactor(chat): 重构图片在聊天记录中的处理与表示方式
为了简化LLM的上下文并提高代码可维护性,对聊天记录中图片的处理方式进行了彻底重构。 旧系统使用 [图片1] 等占位符,并在消息头部附加一个独立的图片描述映射块。这种方式结构复杂,容易造成上下文分离。 新系统将图片描述直接内联到消息文本中,格式为 `[图片:一只猫]`,使聊天记录对LLM更加自然和易于理解。 主要变更: - **消息构建 (`chat_message_builder`):** 在构建可读消息时,异步将数据库中的 `[picid:...]` 标签直接替换为完整的 `[图片:描述]`。 - **废弃映射:** 移除了独立的图片映射信息块 (`build_pic_mapping_info` 函数),所有信息都在消息内联。 - **图片处理 (`utils_image`):** `process_image` 流程现在同步返回完整的描述字符串,并增强了VLM调用的重试逻辑和缓存机制,提高了健壮性。 - **消息存储 (`storage`):** 在消息存入数据库前,将 `[图片:描述]` 转换为 `[picid:...]`,以保持存储规范化。 - **修复:** 增加了多处空值检查,提高了代码的稳定性。这不得之前稳定好用多了😋😋😋
This commit is contained in:
@@ -86,7 +86,7 @@ class MaiEmoji:
|
||||
logger.debug(f"[初始化] 正在使用Pillow获取格式: {self.filename}")
|
||||
try:
|
||||
with Image.open(io.BytesIO(image_bytes)) as img:
|
||||
self.format = img.format.lower() # type: ignore
|
||||
self.format = (img.format or "jpeg").lower()
|
||||
logger.debug(f"[初始化] 格式获取成功: {self.format}")
|
||||
except Exception as pil_error:
|
||||
logger.error(f"[初始化错误] Pillow无法处理图片 ({self.filename}): {pil_error}")
|
||||
@@ -327,7 +327,7 @@ async def clear_temp_emoji() -> None:
|
||||
):
|
||||
if os.path.exists(need_clear):
|
||||
files = os.listdir(need_clear)
|
||||
# 如果文件数超过100就全部删除
|
||||
# 如果文件数超过1000就全部删除
|
||||
if len(files) > 1000:
|
||||
for filename in files:
|
||||
file_path = os.path.join(need_clear, filename)
|
||||
@@ -439,12 +439,12 @@ class EmojiManager:
|
||||
stmt = select(Emoji).where(Emoji.emoji_hash == emoji_hash)
|
||||
result = await session.execute(stmt)
|
||||
emoji_update = result.scalar_one_or_none()
|
||||
if emoji_update is None:
|
||||
logger.error(f"记录表情使用失败: 未找到 hash 为 {emoji_hash} 的表情包")
|
||||
else:
|
||||
if emoji_update:
|
||||
emoji_update.usage_count += 1
|
||||
emoji_update.last_used_time = time.time() # Update last used time
|
||||
await session.commit()
|
||||
emoji_update.last_used_time = time.time() # Update last used time
|
||||
await session.commit()
|
||||
else:
|
||||
logger.error(f"记录表情使用失败: 未找到 hash 为 {emoji_hash} 的表情包")
|
||||
except Exception as e:
|
||||
logger.error(f"记录表情使用失败: {e!s}")
|
||||
|
||||
@@ -469,7 +469,7 @@ class EmojiManager:
|
||||
return None
|
||||
|
||||
# 2. 根据全局配置决定候选表情包的数量
|
||||
max_candidates = global_config.emoji.max_emoji_for_llm_select
|
||||
max_candidates = global_config.emoji.max_context_emojis
|
||||
|
||||
# 如果配置为0或者大于等于总数,则选择所有表情包
|
||||
if max_candidates <= 0 or max_candidates >= len(all_emojis):
|
||||
@@ -943,11 +943,7 @@ class EmojiManager:
|
||||
image_base64 = image_base64.encode("ascii", errors="ignore").decode("ascii")
|
||||
image_bytes = base64.b64decode(image_base64)
|
||||
image_hash = hashlib.md5(image_bytes).hexdigest()
|
||||
image_format = (
|
||||
Image.open(io.BytesIO(image_bytes)).format.lower()
|
||||
if Image.open(io.BytesIO(image_bytes)).format
|
||||
else "jpeg"
|
||||
)
|
||||
image_format = (Image.open(io.BytesIO(image_bytes)).format or "jpeg").lower()
|
||||
|
||||
# 2. 检查数据库中是否已存在该表情包的描述,实现复用
|
||||
existing_description = None
|
||||
|
||||
Reference in New Issue
Block a user