- 将默认LLM模型从gemini-2.0-flash升级为gemini-3-flash-preview - 将博主人设从"性感福利主播"更改为"二次元coser" - 优化LLM生成SD提示词的指南,新增中国审美人物描述规则 - 为各SD模型添加颜值核心词、示范prompt和禁止使用的关键词 - 新增三维人物描述法(眼睛/肤色/气质)和专属光线词指导 📦 build(openspec): 归档旧规范并创建新规范 - 将improve-maintainability规范归档至2026-02-25目录 - 新增2026-02-26-improve-ui-layout规范,包含UI布局优化设计 - 新增2026-02-26-optimize-image-generation规范,包含图片生成优化设计 - 在根目录openspec/specs下新增图片质量、后处理、中国审美和LLM提示词规范 ♻️ refactor(sd_service): 优化SD模型配置和图片后处理 - 为各SD模型添加中国审美特征词和欧美面孔排除词 - 新增高画质预设档,SDXL模型启用Hires Fix参数 - 将后处理拆分为beauty_enhance和anti_detect_postprocess两个独立函数 - 新增美化增强功能,支持通过enhance_level参数控制强度 ♻️ refactor(services): 更新内容生成服务以支持美化增强 - 在generate_images函数中新增enhance_level参数 - 将美化强度参数传递至SDService.txt2img调用 ♻️ refactor(ui): 优化UI布局和添加美化强度控件 - 注入自定义CSS主题层,优化字体、按钮和卡片样式 - 将全局设置迁移至独立的"⚙️ 配置"Tab,优化Tab顺序 - 在内容创作Tab的高级设置中添加美化强度滑块控件 - 优化自动运营Tab布局,改为2列卡片网格展示
120 lines
6.0 KiB
Markdown
120 lines
6.0 KiB
Markdown
## Context
|
||
|
||
`main.py` 是整个项目的单一入口,目前 4359 行,包含 10+ 个业务域的业务逻辑、全局状态、UI 组件和事件绑定。上一轮重构已将 Tab 1(内容创作)提取为 `ui/tab_create.py`,建立了 Tab 模块化的模式。本次设计延续该模式,将业务逻辑提取为 `services/` 目录,并完成剩余 Tab 的 UI 拆分。
|
||
|
||
已有外部服务层:`config_manager.py`、`llm_service.py`、`sd_service.py`、`mcp_client.py`、`analytics_service.py`、`publish_queue.py`。
|
||
`main.py` 中剩余的函数是对这些服务的**编排层**,应该独立成模块而非继续膨胀在入口文件里。
|
||
|
||
约束:
|
||
- Python 3.10+(当前环境)
|
||
- 不引入新的外部依赖
|
||
- 重构不改变任何业务行为
|
||
|
||
## Goals / Non-Goals
|
||
|
||
**Goals:**
|
||
- 将 `main.py` 瘦身至 ~300 行纯入口层(导入 + UI 组装 + `app.launch()`)
|
||
- 建立清晰的分层:`services/`(业务编排)→ `ui/`(Gradio 组件)→ `main.py`(入口)
|
||
- 消除模块间隐式依赖,所有依赖通过函数参数显式传递
|
||
- 保持所有函数签名、Gradio 回调绑定不变
|
||
|
||
**Non-Goals:**
|
||
- 不重构或重写任何现有业务逻辑(本次是纯搬迁)
|
||
- 不改变 `config_manager.py`、`llm_service.py` 等已有服务层
|
||
- 不引入类/面向对象重构(保持现有函数式风格)
|
||
- 不添加单元测试(独立变更)
|
||
|
||
## Decisions
|
||
|
||
### D1:分层架构 —— `services/` 不依赖 `ui/`,`ui/` 不依赖 `services/`
|
||
|
||
```
|
||
main.py (入口层:组装 + 启动)
|
||
├── services/ (业务编排层:纯 Python,无 Gradio)
|
||
│ ├── connection.py
|
||
│ ├── content.py
|
||
│ ├── hotspot.py
|
||
│ ├── engagement.py
|
||
│ ├── rate_limiter.py
|
||
│ ├── profile.py
|
||
│ ├── persona.py
|
||
│ ├── scheduler.py
|
||
│ ├── queue_ops.py
|
||
│ └── autostart.py
|
||
├── ui/ (UI 层:Gradio 组件 + 事件绑定)
|
||
│ ├── tab_create.py ← 已存在
|
||
│ ├── tab_hotspot.py
|
||
│ ├── tab_engage.py
|
||
│ ├── tab_profile.py
|
||
│ ├── tab_auto.py
|
||
│ ├── tab_queue.py
|
||
│ ├── tab_analytics.py
|
||
│ └── tab_settings.py
|
||
```
|
||
|
||
**为何不让 `ui/` 依赖 `services/`:** 每个 `build_tab()` 接收回调函数作为参数(已有 `tab_create.py` 的模式),而非直接 import service。这样 UI 层完全解耦,可独立测试或替换。
|
||
|
||
### D2:共享单例通过 `main.py` 初始化,作为参数传入
|
||
|
||
`cfg`、`mcp`、`analytics`、`pub_queue`、`queue_publisher` 仍在 `main.py` 顶层初始化。Service 函数需要它们时通过**函数参数**接收,不在 service 模块顶层 import。
|
||
|
||
**为何不在各 service 模块初始化单例:** 防止循环依赖、防止多次初始化、保持测试时可替换。
|
||
|
||
### D3:有状态模块使用模块级变量(不封装成类)
|
||
|
||
`rate_limiter`、`scheduler`、`engagement` 内部有 `threading.Event`、`_daily_stats` 等状态。保持现有模块级变量风格(不改成类),仅将变量和函数整体搬迁到对应模块。
|
||
|
||
**为何不改成类:** 本次目标是结构拆分,不是重构设计模式,避免引入额外变更风险。
|
||
|
||
### D4:迁移策略 —— 先提取后删除,不做重定向
|
||
|
||
每个域的迁移步骤:
|
||
1. 在 service 模块中写入函数(复制粘贴 + 调整 import)
|
||
2. 在 `main.py` 中删除对应函数,改为 `from services.xxx import ...`
|
||
3. 运行 `ast.parse()` 验证语法
|
||
4. 运行应用验证启动不报错
|
||
|
||
**为何不做 `main.py` 中的临时 re-export:** 简单场景直接删+导入更清晰,且 Gradio 回调绑定在 `main.py` 中通过变量名引用,只需保证同名变量在作用域内即可。
|
||
|
||
### D5:UI Tab 模块统一使用 `build_tab(fn_*, ...)` 签名
|
||
|
||
复用 `tab_create.py` 已建立的模式:
|
||
- 每个 `build_tab()` 接收所需的回调函数和共享 Gradio 组件作为参数
|
||
- 函数内部创建本 Tab 的所有 Gradio 组件及事件绑定
|
||
- 返回 `dict`,包含需要被其他 Tab 或 `app.load()` 引用的组件
|
||
|
||
### D6:`services/` 和 `ui/` 均需 `__init__.py`
|
||
|
||
使用空文件标记为 Python 包,与 `ui/__init__.py` 已有做法一致。
|
||
|
||
## Risks / Trade-offs
|
||
|
||
- **[风险] 大量 import 调整可能遗漏** → 每个模块完成后执行 `ast.parse()` + 应用启动验证,逐域推进
|
||
- **[风险] 全局状态的隐式共享** → 调度器、限流器的模块级变量在模块首次 import 时初始化,Python 模块单例语义保证只初始化一次,行为与当前一致
|
||
- **[权衡] `build_tab()` 参数列表长** → 与现有 `tab_create.py` 的做法一致,接受这种显式依赖的冗长性,可在后续变更中引入 dataclass 参数包
|
||
|
||
## Migration Plan
|
||
|
||
按以下顺序逐域提取,每步验证后再继续:
|
||
|
||
1. `services/rate_limiter.py` —— 无外部依赖,最安全的起点
|
||
2. `services/autostart.py` —— 独立,平台相关逻辑隔离
|
||
3. `services/persona.py` —— 仅依赖 `cfg`
|
||
4. `services/connection.py` —— 依赖 `cfg`、`llm_service`、`sd_service`、`mcp_client`
|
||
5. `services/profile.py` —— 依赖 `mcp_client`
|
||
6. `services/hotspot.py` —— 依赖 `llm_service`、`mcp_client`
|
||
7. `services/content.py` —— 依赖多个服务,最复杂
|
||
8. `services/engagement.py` —— 依赖 `rate_limiter`、`mcp_client`
|
||
9. `services/scheduler.py` —— 依赖 `engagement`、`content`
|
||
10. `services/queue_ops.py` —— 依赖 `content`、`pub_queue`
|
||
11. `ui/tab_hotspot.py` ~ `ui/tab_settings.py` —— 7 个 Tab UI 拆分
|
||
|
||
**回滚策略:** 所有修改通过 git 追踪;每个 service 提取为一个独立 commit,任意步骤可 `git revert`。
|
||
|
||
## Open Questions
|
||
|
||
- `_auto_log` 列表(被 `engagement` 和 `scheduler` 共同写入)归属哪个模块?
|
||
→ 暂定置于 `services/scheduler.py`,`engagement` 接收 `log_fn` 回调参数
|
||
- `queue_publisher` 的 callback 注册(`set_publish_callback`)在哪里调用?
|
||
→ 保留在 `main.py` 初始化段,callback 函数迁移到 `services/queue_ops.py`
|