技术笔记
Eidolon 开发记录
从选型到实现的 AstrBot 群文生图插件——基于火山方舟 Seedream 5.0 Pro,实现指令与自然语言触发、三级限额、并发队列与 LLM 提示词润色。
关联作品: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)仅在此生效。custom:openai_compatible/gemini_native双协议,自填base_url+api_key。
所有后端共用同一个 _post 统一请求(代理、超时、3 次重试、429/5xx 错误分类),保证日志与错误提示一致。
关键设计
- 图生图:附带图片或回复带图消息时自动作为参考图,支持单图编辑与多图融合(最多 8 张参考图)。图生图不进行 LLM 提示词润色,保持修改指令原意。
- 自然语言触发双模式:
@机器人+ 描述即可触发;可用自定义关键词命中即生图,或用LLM 意图判断(独立于润色的文本模型)。非生图请求、未配置模型或判断失败都放行给正常对话。 - 三级限额:总限额、每人限额(按 QQ 号)、管理员豁免;计数在成功发起请求后累加,失败不计。命中冷却/限额时直接提示并截断事件,不让默认 LLM 重复回复。
- 并发与排队:默认最多同时 5 个生成任务,达到上限后按提交顺序排队并即时反馈排队位置。
- LLM 提示词润色:可选项,复用主 key、用豆包文本模型;润色失败自动回退原文,不阻断生图。
- 图片缓存治理:设置容量上限,超限自动清理最旧图片;管理页可手动清空,正在发送的图片不被清理。
版本演进
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 历史自动整理生成,用于个人网站技术笔记栏目。