返回异造手记

技术笔记

  • 实用工具

Eidolon 开发记录

从选型到实现的 AstrBot 群文生图插件——基于火山方舟 Seedream 5.0 Pro,实现指令与自然语言触发、三级限额、并发队列与 LLM 提示词润色。

发布于预计阅读 3 分钟

关联作品:Eidolon

一款 AstrBot 群聊文生图 / 图生图插件,基于火山方舟 Doubao Seedream 5.0 Pro,把群聊里的中文描述“异”笔“画”出,一键成图。

技术栈:Python(AstrBot Star 插件)、httpx + REST,零第三方图片依赖。

仓库:github.com/YamaArashiHZ/astrbot_plugin_eidolon · 版本:v1.0.0 → v1.2.0(2026-08-01 ~ 08-02)


背景与动机

在 QQ 群里“出图”是个高频需求,但手动切到生图工具再贴回来很麻烦。干脆做一个 AstrBot 插件,让群成员用 @机器人 或一条指令就把描述变成图片。

核心目标:中文群聊场景 + 国内部署,要能做到低成本、免代理、按张计费,同时尽量不干扰群里的正常 AI 对话。

技术选型

决策点 选择 理由
生图模型 火山方舟 Doubao Seedream 5.0 Pro 国内直连免代理、人民币按张计费、中文提示词原生友好;images/generations 接口与 OpenAI 兼容高度近似,适配层可直接复用
调用方式 原生 httpx + REST,不用 SDK AstrBot 自带 httpx,零额外依赖、异步友好,符合插件规范
触发方式 @filter.command + 群消息监听 指令与 @机器人 自然语言双通道;@ 用消息链 Comp.At 精确匹配机器人自身 QQ,不依赖唤醒词
限额实现 内存计数 + event.is_admin() 总限额全局记、每人限额按 sender_id 记,管理员豁免;配合群冷却与全局并发队列
图片存储 get_astrbot_data_path() 规范目录 官方存储规范,重装/更新不丢数据

Seedream 5.0 Pro 的 API 走 ark.cn-beijing.volces.com/api/v3,请求模式与 OpenAI 兼容端点接近,因此适配层可以在一套分发逻辑下同时支持预设(Seedream)与自定义 OpenAI 兼容/Gemini 原生平台

架构与适配层

核心是统一的适配层入口 _generate_one(prompt, aspect, size),按 api_provider 分发到不同后端实现:

  • seedream:火山方舟端点,size 用方舟档位映射,watermark: true 溯源,优先 b64_json、失败降级 url 下载。
  • gemini:Google 原生 interactions 端点,x-goog-api-key 认证,image_size(1K/2K/4K)仅在此生效。
  • customopenai_compatible / gemini_native 双协议,自填 base_url + api_key

所有后端共用同一个 _post 统一请求(代理、超时、3 次重试、429/5xx 错误分类),保证日志与错误提示一致。

关键设计

  1. 图生图:附带图片或回复带图消息时自动作为参考图,支持单图编辑与多图融合(最多 8 张参考图)。图生图不进行 LLM 提示词润色,保持修改指令原意。
  2. 自然语言触发双模式@机器人 + 描述即可触发;可用自定义关键词命中即生图,或用LLM 意图判断(独立于润色的文本模型)。非生图请求、未配置模型或判断失败都放行给正常对话。
  3. 三级限额:总限额、每人限额(按 QQ 号)、管理员豁免;计数在成功发起请求后累加,失败不计。命中冷却/限额时直接提示并截断事件,不让默认 LLM 重复回复。
  4. 并发与排队:默认最多同时 5 个生成任务,达到上限后按提交顺序排队并即时反馈排队位置。
  5. LLM 提示词润色:可选项,复用主 key、用豆包文本模型;润色失败自动回退原文,不阻断生图
  6. 图片缓存治理:设置容量上限,超限自动清理最旧图片;管理页可手动清空,正在发送的图片不被清理。

版本演进

v1.2.0 之前的几次迭代主要是在“能用”与“可发布”之间补工程化:

版本 日期 亮点
v1.0.0 08-01 接入 Seedream 5.0 Pro;指令触发、NL 触发、限额、全局并发队列、管理页、MIT 许可证
v1.1.0 08-02 NL 触发关键词/LLM 双模式、润色超时可配、图片缓存上限与自动清理、新增 3:2/2:3/21:9 档位
v1.2.0 08-02 图生图(单图编辑与多图融合)、图生图开关、图生图共用限额/冷却/并发

踩坑与修复

开发中反复修正的几类问题(见 CHANGELOG):

  • 事件截断时机:生图后若不及时 stop_event(),默认 LLM 对话仍会响应并复述提示词,或阻断生图结果发送。
  • LLM 判断模型配置不上润色超时字段缺失导致保存失败——设置页与配置持久化之间需要严格对齐。
  • 用量统计位数不同导致进度条错位、累计生成数始终为 0——前端展示与真实计数字段要对齐。
  • 火山方舟限流(HTTP 429):独立于插件并发,需调大冷却或降低并发。

数据一览

  • 开发周期:2 天(2026-07-31 方案定稿 ~ 08-02 发布 v1.2.0)
  • 提交数:21(conventional commits)
  • 核心源码:main.py 约 1180 行(含适配层、限额、NL 触发、润色、管理页 API)
  • 版本:v1.0.0 → v1.1.0 → v1.2.0

本文档由项目会话记录与 git 历史自动整理生成,用于个人网站技术笔记栏目。