[Bug] aiocqhttp:引用机器人自己发送的图片无法解析(get_msg 返回空 url + 裸文件名)

Đang mở
#10,972 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
22/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
python
Lĩnh vực
backend

Hướng nghiên cứu

Start in astrbot/core/astr_main_agent.py around lines 1601-1621 and 1665, where has_embedded_image is set and the quoted-image fallback is skipped, then read _materialize_media_ref in astrbot/core/utils/media_utils.py. A reasonable done state is that a reply image which fails to materialize falls through to image_resolver.py instead of injecting the [Image unavailable] text, with a test covering that path. The SnowLuma protocol-side resolution is a separate, open question.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

问题描述

AstrBot 4.29.3(Docker)+ aiocqhttp(OneBot v11)+ SnowLuma。

机器人通过插件发送一张图片(Comp.Image),QQ 端显示正常。随后用户引用这条机器人自己发出的图片消息并补上文字,AstrBot 无法解析引用中的图片:

  • 日志出现两条 WARN;
  • 请求中注入 TextPart("[Image unavailable]");
  • 模型据此回复“图片没加载出来”。

与 #10179(私聊中引用图片无法解析)的触发场景不同:这里是引用机器人自己发送的图片,并且协议端对这张图的 get_msg / get_image 都只返回空 url 和裸文件名。相关 PR #10225 / #10194 曾尝试修复 quoted image 的引用解析,但均未合并;当前 master(2026-11-03)仍存在下文的短路逻辑。

如何复现?

  1. 让机器人发送任意一张图片(插件使用 Comp.Image 即可),确认 QQ 端正常显示;
  2. 在 QQ 中引用该图片消息,并回复任意文字;
  3. 查看 AstrBot 日志。

预期行为

引用中的图片能作为视觉输入送给模型。如果协议端确实无法提供可访问的图片来源,至少不应让模型产生“我这边图片加载失败”的表述。

实际行为

图片被判定为 unresolved media ref,模型收到 [Image unavailable],并回复图片未加载。

AstrBot 版本

4.29.3

操作系统

Linux(Docker)

部署方式

Docker

使用的消息平台适配器

aiocqhttp(OneBot v11)+ SnowLuma

错误日志

[WARN] Image processing in reply chain failed for unresolved media ref
       name='<md5>.png' len=36: [Errno 2] image reference is not an existing local file
       or a valid payload: '<md5>.png'
[WARN] Quoted image is unavailable (FileNotFoundError): unresolved media ref
       name='<md5>.png' len=36

每条引用该图片的消息都会稳定出现这两条 WARN。

根因分析

  1. 发送侧:astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py:36-44 将 Image / Record 段无条件转为 base64:// 后发送给协议端。协议端把图片缓存为 md5 命名的文件。

  2. 协议端返回:用户引用该消息后,get_msg 返回的图片段为:

    {"type":"image","data":{"url":"","file":"<md5>.png","sub_type":0,"summary":"[图片]"}}
    

    没有 file_id、没有本地路径、没有 CDN URL。对同一张图单独调用 get_image / get_file,同样只得到 url: ""。

  3. 解析失败:适配器构造出 Image(file="<md5>.png", url="")。astrbot/core/utils/media_utils.py 的 _materialize_media_ref()(约 463 行)只接受 http(s)://、file:、data:、base64://、裸 base64,或真实存在的本地文件;裸文件名在这里抛出 FileNotFoundError(错误文案约 646 行),describe_media_ref()(约 326、382 行)将其格式化为 unresolved media ref name='<md5>.png' len=36。astrbot/core/pipeline/preprocess_stage/stage.py:215 先记录第一条 WARN,随后 astrbot/core/astr_main_agent.py:1610 再次失败并记录第二条 WARN。

  4. fallback 被短路:astrbot/core/astr_main_agent.py:1601-1621 只要 reply chain 中存在 Image 就把 has_embedded_image 置为 True;convert_to_file_path() 失败后注入 [Image unavailable]。由于 has_embedded_image 已为 True,约 1665 行的 if not has_embedded_image: 分支被跳过,现成的 astrbot/core/utils/quoted_message/image_resolver.py(会依次尝试 get_image / get_file / get_group_file_url / get_private_file_url)根本没有机会执行。

  5. 即使进入该 fallback,SnowLuma 对同一张图的 get_image / get_file 仍只返回 url: "",因此该协议端场景还需要额外的解析途径;但第 4 点会让支持 get_image 的协议端也一起失效,属于独立的 AstrBot 侧缺陷。

代码位置

  • 发送:astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py:36-44
  • 媒体解析:astrbot/core/utils/media_utils.py:463(_materialize_media_ref)、:326 / :382(describe_media_ref)、:646(FileNotFoundError 文案)
  • 引用图片处理与 fallback 短路:astrbot/core/astr_main_agent.py:1601-1621、:1665
  • 预处理阶段日志:astrbot/core/pipeline/preprocess_stage/stage.py:215
  • 已存在但未触发的引用解析器:astrbot/core/utils/quoted_message/image_resolver.py

修复建议

  1. 最小修复:astr_main_agent.py 中把 has_embedded_image 改为“图片成功物化后才置为 True”,或在物化失败时仍进入 quoted fallback。这样 get_image 可用的协议端能恢复正常。
  2. SnowLuma 场景:get_msg 和 get_image 都只给空 url + 裸文件名。若可通过协议端共享缓存目录、get_private_file_url 或额外参数解析,请在 ImageResolver 中补上;若确实无法解析,warning 建议带上 reply message_id 与协议端 action 的原始返回,便于区分协议端限制和 AstrBot 缺陷。
  3. 失败提示:解析失败时不要注入 [Image unavailable](或改成中性文本,例如“引用中的图片无法获取”),也可以只记录日志并通过事件暴露给插件,避免模型对用户输出“图片加载失败”。
  4. 发送侧:考虑到 #6717 中维护者说明 base64 是为兼容“协议端与 AstrBot 不同机部署”而保留,这里不建议直接改回 file://。如果协议端能访问 callback_api_base,可以在发送后登记图片的可回取 URL / 协议端 file_id 映射,供引用解析使用;否则优先级应低于第 1、3 点。

相关 issue / PR

  • #10179(open):私聊中引用图片无法解析,触发场景与本条不同,且未提供日志/根因;
  • #3895(closed):v4.7.4 下“引用机器人自身消息 + 图片无法识别”,当时以“插件生成的图片不计入上下文”关闭,本路径未修复;
  • #10225、#10194(closed,未合并):曾尝试解析 quoted image 的 opaque / unusable reference;当前 master 仍存在第 4 点的短路问题。

辅助信息

日志与文件名已脱敏:不含 QQ 号、服务器 IP、Cookie、token 或人格名。

检查清单

  • 我已在 Issue 列表中搜索过相关问题仍无法解决,或该问题从未被报告过。
  • 我已尝试过禁用所有插件,排除了可能是因插件导致的问题。未逐项禁用验证;但失败发生在 core 的引用解析链路(astr_main_agent.py / media_utils.py),发送图片的插件只负责提供 Comp.Image。
  • 我报告的问题与 AstrBot 本体相关,而非在报告某一插件的问题。
  • 我已阅读并同意本项目的贡献者行为准则。
  • (可选)我愿意提交 PR 以帮助修复该问题。
Ngôn ngữ chính
Python
Star
46.4k
Fork
3.4k
Merge trung bình
1 ngày 10 giờ
Pull request đã merge (30 ngày)
123

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của AstrBotDevs/AstrBot

Tất cả issue của AstrBotDevs/AstrBot

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.