Skip to content

[Bug] 引用 GIF 会污染会话历史并导致 Gemini 后续请求持续失败 #9295

Description

@TenmaGabriel0721

What happened / 发生了什么

在 AstrBot v4.26.6 中,引用一条包含动画 GIF 的消息并唤醒多模态模型后,GIF 会以 data:image/gif;base64,... 的形式进入并持久化到会话历史。

当实际模型只支持 JPEG/PNG/WebP、不支持 GIF(例如部分 Gemini OpenAI-compatible 网关)时,之后即使用户只发送纯文本,每次请求也会继续携带历史 GIF,并持续返回 convert_request_failed

现场已经开启 provider_settings.sanitize_context_by_modalities=true,但清理器只判断模型是否支持 image 模态,不检查图片的具体 MIME。模型配置包含 image 后,GIF 会被原样保留。

相关代码路径:

  • astrbot/core/astr_main_agent.py:引用链中的 Image 被加入 req.image_urls
  • astrbot/core/provider/modalities.py:只按 text/image/audio/tool_use 清理,不检查 image/gif
  • astrbot/core/utils/media_utils.py:当前实现和测试明确保留动画 GIF。
  • astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py:成功轮次会将包含 GIF 的 all_messages 保存进会话历史。
  • astrbot/core/provider/sources/openai_source.py:图片降级重试只匹配非 VLM、审核失败、invalid_attachment 等,不匹配 convert_request_failed / mime type is not supported

这似乎与 v4.26.2 的“保留图片格式”改动有关。v4.26.0 的 ensure_jpeg() 会把非 JPEG(包括 GIF)转为静态 JPEG;v4.26.2+ 则明确保留动画 GIF。

期望行为:

  1. 在发送给 Provider 前,根据模型支持的图片 MIME 白名单处理图片;不支持 GIF 时可转为首帧 PNG/JPEG或替换为 [Image]
  2. 对已经保存到历史中的 data:image/gif 同样进行清理,避免会话持续损坏。
  3. 遇到 mime type is not supported / convert_request_failed 时,可删除不支持的图片后自动重试一次。

Reproduce / 如何复现?

  1. 使用 AstrBot v4.26.6,配置一个声明支持 image 的 Gemini/OpenAI-compatible 模型,但该接口实际不接受 image/gif
  2. 开启 provider_settings.sanitize_context_by_modalities
  3. 在 QQ 群中发送一个动画 GIF。QQ 消息中的文件名可以是 .jpg,真实文件内容为 GIF。
  4. 引用这条 GIF 消息并 @/唤醒机器人。
  5. 再发送一条普通纯文本消息。
  6. 后续请求会携带历史中的 GIF,并持续报错。

用于复现的图片指纹:

GIF89a
240x240
126979 bytes
Base64 prefix: R0lGODlh8ADwAPcAAPxzxu+vcPWy...

AstrBot version, deployment method (e.g., Windows Docker Desktop deployment), provider used, and messaging platform used. / AstrBot 版本、部署方式(如 Windows Docker Desktop 部署)、使用的提供商、使用的消息平台适配器

  • AstrBot: v4.26.6
  • Deployment: Linux
  • Provider: OpenAI-compatible Gemini (gemini-3.5-flash)
  • Platform: QQ Official;原始 GIF 同时可由 aiocqhttp/QQ 消息产生
  • sanitize_context_by_modalities: true
  • Model modalities: text, image, audio, tool_use

OS

Linux

Logs / 报错日志

引用消息被识别为包含图片,并直接交给支持图片的主模型:

[Core] [DBUG] Skipping quote image captioning because the main provider supports image input.

GIF 被写入历史后,下一次纯文本请求报错:

[Core] [WARN] Chat Model gemini/gemini-3.5-flash request error:
Error code: 500 - {
  "error": {
    "message": "mime type is not supported by Gemini: 'image/gif', url: 'base64:data:image/gif;base64,R0lGODlh8ADwAPcAAPxzxu+vcPWy...', supported types are: [image/webp image/heif video/mp4 video/avi image/heic video/mpg video/mpegps video/flv audio/mp3 image/png image/jpg text/plain video/mpeg video/wmv application/pdf audio/mpeg video/mov audio/wav image/jpeg]",
    "type": "new_api_error",
    "code": "convert_request_failed"
  }
}

同一个 Base64 前缀会在后续请求中重复出现,直到会话历史被裁剪或清理。

Are you willing to submit a PR? / 你愿意提交 PR 吗?

  • Yes!

Code of Conduct

  • I have read and agree to abide by the project's Code of Conduct.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:coreThe bug / feature is about astrbot's core, backendarea:providerThe bug / feature is about AI Provider, Models, LLM Agent, LLM Agent Runner.

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions