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

Abierto
#10,972 1 comentario 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
22/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
python
Área
backend

Línea de trabajo

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.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

问题描述

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 以帮助修复该问题。
Lenguaje dominante
Python
Estrellas
46.4k
Forks
3.4k
Merge medio
1 d 11 h
PR fusionados (30 d)
120

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de AstrBotDevs/AstrBot

Todos los issues de AstrBotDevs/AstrBot

Issues similares

Más issues de Python

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.