kita / notes

约 2 分钟

定时总结总是不出图,我把渲染搬进了容器

每天定时的群聊总结,本来说好是一张排版好的图片。

但它时不时变成一段纯文本——就是"聊天记录模式",一行行列出来那种。不是每次都这样,大概隔几天来一次,时间也不固定。

用户自己的猜测是"生图的时候遇到高峰期",还提过"干脆把生图功能部署到本地"。这个判断方向是对的。

先去代码里找"回退"这个词

既然是"没出图、退回文本",那代码里一定有个分支在做这件事。直接搜:

grep -rn -i -e "fallback" -e "回退" -e "chat log" -e "聊天记录" <插件目录>/src

找到了。逻辑是:先尝试渲染成图片,渲染失败就回退成文本。

这类"失败降级"的设计本身没错——总比什么都不发好。但它掩盖了问题:用户在群里看到的是一条丑丑的文本,而不是"渲染失败了"这个事实。

渲染失败的原因

顺着渲染那一侧看下去,发现它调的是 AstrBot 的远程 T2I 服务(text-to-image)。

问题就清楚了:

  • 这个服务是别人的服务器,我不控制
  • 高峰期它会超时或者直接失败
  • 失败一次,插件就回退一次

换句话说:这个插件的出图能力,被我控制不了的东西捏着。

改成容器内自己渲染

解决方案是写一个本地 HTML 渲染器,把渲染这一步搬进 astrbot 容器里:

容器里本来就有 playwright + chromium(做别的事情装的)。那就直接用它们把报告的 HTML 渲染成图片,不再往外发请求。

接口层面要对齐原来那套调用约定,保持方法签名一致(html_render(tmpl, data, return_url, options) 这一套),这样插件里其他调用的地方一行都不用改,只换实现。

改动之后的好处很直接:

  • 不依赖外部服务,高峰期不受影响
  • 快——本地渲染没有网络往返
  • 可控——渲染出来的东西不对,我可以直接调 chromium 的参数(视口大小、字体、等待时机),不用去猜远程服务做了什么

顺带说一句回退逻辑

我保留了回退分支,但把它的触发条件看紧了。降级不是问题,"静悄悄地降级"才是问题。 一个功能失败后应该留下痕迹,而不是伪装成"今天就是这样"。

现在渲染失败会在日志里有明确记录,我能在下一次定时任务之前发现它,而不是等群里的人告诉我"今天怎么又不是图"。

关于"依赖别人的服务"

这个改动不大,但我把它当成一条经验:任何依赖外部服务的功能,都要先想清楚失败时的样子。

如果失败的表现是"功能不可用",那没问题,用户能感知到。但如果失败的表现是"降级成另一个能看的东西",那这个问题就会被长期忽略——因为每次都能出个结果,谁也不会去追为什么。

这次是运气好:用户自己注意到了"有时候是文本有时候是图"。要是降级后的产物再像样一点,这问题可能就一直躺在那儿了。

← 回到全部笔记