384 lines
11 KiB
Markdown
384 lines
11 KiB
Markdown
|
|
# 📊 PPT智能管理系统 V2.0 说明书
|
|||
|
|
|
|||
|
|
基于 **锚点定位** + **原生图表更新** + **插件化架构** + **WebSocket实时日志** 的下一代PPT自动化平台。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🚀 快速开始
|
|||
|
|
|
|||
|
|
### 1. 环境准备
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd f:\ppt\ppt_manager_v2
|
|||
|
|
pip install -r requirements_v2.txt
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 启动WebSocket服务
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
python web_socket_app.py
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 浏览器访问
|
|||
|
|
|
|||
|
|
打开 **http://localhost:5001**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📁 项目目录结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
ppt_manager_v2/
|
|||
|
|
├── 📄 web_socket_app.py # WebSocket服务端
|
|||
|
|
├── 📄 orchestrator.py # 主编排引擎(Pipeline)
|
|||
|
|
├── 📄 requirements_v2.txt # Python依赖包
|
|||
|
|
├── 📄 README.md # 本文件
|
|||
|
|
├──
|
|||
|
|
├── 📂 core/ # 核心层
|
|||
|
|
│ ├── anchor_engine.py # ✅ 锚点定位引擎
|
|||
|
|
│ ├── native_chart.py # ✅ 原生图表数据源更新
|
|||
|
|
│ └── conditional_renderer.py # ✅ 条件渲染引擎(动态增删页)
|
|||
|
|
├──
|
|||
|
|
├── 📂 plugins/ # 插件化架构
|
|||
|
|
│ ├── base_generator.py # BaseGenerator 标准接口
|
|||
|
|
│ └── generators/ # 插件目录(自动扫描注册)
|
|||
|
|
│ ├── gdp_generator.py # GDP趋势图生成插件
|
|||
|
|
│ └── cpi_generator.py # CPI/PPI图表生成插件
|
|||
|
|
├──
|
|||
|
|
├── 📂 ai/ # AI智能化
|
|||
|
|
│ └── llm_analyst.py # LLM分析师 + Diff对比器
|
|||
|
|
├──
|
|||
|
|
├── 📂 connectors/ # 多数据源适配
|
|||
|
|
│ └── sql_connector.py # MySQL/ClickHouse/REST API/CSV
|
|||
|
|
├──
|
|||
|
|
├── 📂 config/
|
|||
|
|
│ └── project_config_v2.yaml # V2版配置文件范式
|
|||
|
|
├──
|
|||
|
|
├── 📂 templates/ # Flask模板目录
|
|||
|
|
│ └── index_v2.html # WebSocket前端页面
|
|||
|
|
├──
|
|||
|
|
├── 📂 logs/ # 日志目录
|
|||
|
|
└── 📂 web/ # 备用(template_dir配置用)
|
|||
|
|
└── templates/
|
|||
|
|
└── index_v2.html
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
> **输出目录**: `f:\ppt\output\` (所有生成的PPT文件在这里)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 五大核心增强能力
|
|||
|
|
|
|||
|
|
### 一、PPT核心操作层(从"拼图"到"原生替换")
|
|||
|
|
|
|||
|
|
#### 1.1 锚点(Anchor)定位引擎 → 无惧页码变动
|
|||
|
|
|
|||
|
|
**痛点解决**: 旧版YAML写 `page: 5`,老板在第3页插一页,所有配置页码全乱。
|
|||
|
|
|
|||
|
|
**新版方案**:
|
|||
|
|
|
|||
|
|
1. 打开你的PPT模板 → 选中一个 **Shape/图表/文本框**
|
|||
|
|
2. 在PowerPoint的 **"选择窗格"** 里给Shape改名(例如:`chart_gdp_trend`)
|
|||
|
|
3. 在YAML里直接配置 **锚点名**,不是页码:
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
anchors:
|
|||
|
|
- name: chart_gdp_trend # Shape Name(选择窗格里的名称)
|
|||
|
|
type: native_chart_update
|
|||
|
|
plugin: gdp_chart
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**代码参考**: [core/anchor_engine.py](file:///f:/ppt/ppt_manager_v2/core/anchor_engine.py#L21-L60)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### 1.2 原生图表数据源直接更新(不是插PNG!)
|
|||
|
|
|
|||
|
|
**痛点解决**: 旧版先生成PNG再插入PPT → 图片无法编辑、丢失主题配色和动画效果、文件体积大。
|
|||
|
|
|
|||
|
|
**新版方案**: 用 `python-pptx` 直接替换PPT内嵌图表的Excel数据源:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# 在native_chart.py里的实现
|
|||
|
|
chart_data = CategoryChartData()
|
|||
|
|
chart_data.categories = ['2026Q1', '2026Q2', '2026Q3']
|
|||
|
|
chart_data.add_series('GDP同比增长', [5.2, 5.0, 5.1])
|
|||
|
|
chart.replace_data(chart_data) # ✅ 原生数据源替换!
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**这样做的好处**:
|
|||
|
|
- ✅ 生成的PPT里**双击图表可以进入Excel编辑**
|
|||
|
|
- ✅ 自动继承PPT母版的**主题配色**
|
|||
|
|
- ✅ 保留图表原有的**进入/强调动画**效果
|
|||
|
|
- ✅ 文本清晰,不是模糊的点阵图
|
|||
|
|
|
|||
|
|
**代码参考**: [core/native_chart.py](file:///f:/ppt/ppt_manager_v2/core/native_chart.py#L12-L90)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### 1.3 条件渲染与动态增删页
|
|||
|
|
|
|||
|
|
**能力描述**: 支持规则判断动态插入/隐藏页面:
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
slide_conditions:
|
|||
|
|
- condition: unemployment_rate > 5.1
|
|||
|
|
action: insert_slide
|
|||
|
|
template: "risk_warning_template.pptx"
|
|||
|
|
position: 5
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
表达式求值:`unemployment_rate > 5.1 AND gdp_growth < 5.0` 等复合条件。
|
|||
|
|
|
|||
|
|
**代码参考**: [core/conditional_renderer.py](file:///f:/ppt/ppt_manager_v2/core/conditional_renderer.py#L1-L100)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 二、插件化数据流架构(真正的即插即用)
|
|||
|
|
|
|||
|
|
#### 2.1 BaseGenerator 标准接口
|
|||
|
|
|
|||
|
|
所有插件继承 `BaseGenerator` 抽象基类,实现两个方法:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# plugins/base_generator.py 定义
|
|||
|
|
class BaseGenerator(ABC):
|
|||
|
|
generator_id = "gdp_chart"
|
|||
|
|
generator_name = "GDP趋势生成器"
|
|||
|
|
|
|||
|
|
@abstractmethod
|
|||
|
|
def fetch_data(self, params): # 步骤A:取数
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
@abstractmethod
|
|||
|
|
def render(self): # 步骤B:渲染返回原生图表数据
|
|||
|
|
pass
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
插件例子 → [plugins/generators/gdp_generator.py](file:///f:/ppt/ppt_manager_v2/plugins/generators/gdp_generator.py)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### 2.2 插件自动扫描注册
|
|||
|
|
|
|||
|
|
启动时系统自动扫描 `plugins/generators/` 目录下所有 `.py` 文件,发现继承 BaseGenerator 且有 `generator_id` 的类自动注册到插件管理器,**无需修改任何注册代码**,真正即插即用。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
# 启动日志里可以看到:
|
|||
|
|
SUCCESS | 加载插件 [cpi_chart]: CPI/PPI通胀图表生成器
|
|||
|
|
SUCCESS | 加载插件 [gdp_chart]: GDP趋势图表生成器
|
|||
|
|
INFO | 插件扫描完成,共加载 2 个生成器
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**代码参考**: [plugins/base_generator.py - GeneratorPluginManager.discover_plugins()](file:///f:/ppt/ppt_manager_v2/plugins/base_generator.py#L46-L89)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### 2.3 参数化生成
|
|||
|
|
|
|||
|
|
Web端不是单一"开始生成"按钮,而是传参给后端插件:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// 前端传params给WebSocket
|
|||
|
|
socket.emit('start_generation', {
|
|||
|
|
params: {
|
|||
|
|
year: 2026,
|
|||
|
|
quarter: "Q2",
|
|||
|
|
theme: "保守型"
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
插件的 `fetch_data(params)` 拿到这些参数去数据库/API拉对应区间的数据。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 三、WebSocket Web交互体验(实时日志推流)
|
|||
|
|
|
|||
|
|
#### 3.1 启动服务
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
python web_socket_app.py
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
控制台输出:
|
|||
|
|
```
|
|||
|
|
=================================================================
|
|||
|
|
🚀 PPT智能管理系统 V2.0 - WebSocket实时日志版
|
|||
|
|
请在浏览器打开: http://localhost:5001
|
|||
|
|
=================================================================
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.2 前端页面三大区域
|
|||
|
|
|
|||
|
|
| 区域 | 功能 |
|
|||
|
|
|------|------|
|
|||
|
|
| **左上角参数表单** | Year/Quarter 参数化输入 |
|
|||
|
|
| **左下角实时面板** | 动态进度条 0-100% + Loguru日志逐行推送 |
|
|||
|
|
| **右侧边栏** | 已加载插件清单 + 历史生成文件下载列表 |
|
|||
|
|
|
|||
|
|
**WebSocket后端代码**: [web_socket_app.py](file:///f:/ppt/ppt_manager_v2/web_socket_app.py#L1-L95)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 四、主编排引擎 Pipeline
|
|||
|
|
|
|||
|
|
Orchestrator 是串联所有模块的大脑:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# orchestrator.py - run_full_pipeline()
|
|||
|
|
def run_full_pipeline(self):
|
|||
|
|
self.load_template() # 1. 打开PPT,扫描所有锚点
|
|||
|
|
self.run_plugins(params) # 2. 并行执行所有插件 fetch_data + render
|
|||
|
|
self.update_native_charts() # 3. 原生图表数据源逐个更新
|
|||
|
|
self.ai_generate_summary() # 4. LLM生成200字洞察文本
|
|||
|
|
self.process_conditions() # 5. 条件表达式求值动态增删页
|
|||
|
|
return self.save() # 6. 保存最终PPT
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Pipeline代码位置**: [orchestrator.py - 第244-251行](file:///f:/ppt/ppt_manager_v2/orchestrator.py#L244-L251)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 五、AI 智能化(LLM + Diff对比)
|
|||
|
|
|
|||
|
|
#### 5.1 LLM 自动生成"分析结论"
|
|||
|
|
|
|||
|
|
图表只能展示"是什么",LLM帮你解释"为什么":
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# ai/llm_analyst.py
|
|||
|
|
prompt = "基于以下数据:{gdp}、{cpi},200字专业分析师口吻总结本月市场"
|
|||
|
|
llm.generate_analysis({
|
|||
|
|
'gdp_growth': 5.1,
|
|||
|
|
'cpi': 0.9,
|
|||
|
|
'unemployment': 5.2
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
# 返回示例:
|
|||
|
|
"""
|
|||
|
|
本月宏观经济洞察:GDP增长5.1%,动能平稳。CPI同比0.9%,
|
|||
|
|
通胀水平温和为货币政策留出空间。就业失业率5.2%,
|
|||
|
|
青年失业率需重点关注...
|
|||
|
|
"""
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
支持 **Mock模式** / **OpenAI** / **通义千问** 三种provider切换。
|
|||
|
|
|
|||
|
|
**代码参考**: [ai/llm_analyst.py](file:///f:/ppt/ppt_manager_v2/ai/llm_analyst.py#L1-L90)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📄 YAML V2版 配置范式参考
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
project_name: "宏观经济月度分析报告"
|
|||
|
|
version: "2.0"
|
|||
|
|
template: "macro_analysis_template.pptx"
|
|||
|
|
|
|||
|
|
params: # 参数化生成默认值
|
|||
|
|
default_year: 2026
|
|||
|
|
default_quarter: "Q2"
|
|||
|
|
|
|||
|
|
anchors: # 锚点绑定关系
|
|||
|
|
- name: chart_gdp
|
|||
|
|
type: native_chart_update
|
|||
|
|
plugin: gdp_chart
|
|||
|
|
chart_type: line
|
|||
|
|
fallback: gdp_fallback.png
|
|||
|
|
|
|||
|
|
- name: chart_cpi
|
|||
|
|
type: native_chart_update
|
|||
|
|
plugin: cpi_chart
|
|||
|
|
|
|||
|
|
slide_conditions: # 条件渲染规则
|
|||
|
|
- condition: unemployment_rate > 5.1
|
|||
|
|
action: insert_slide
|
|||
|
|
position: 5
|
|||
|
|
|
|||
|
|
connectors: # 多数据源配置
|
|||
|
|
mysql_stats: {type: mysql, database: macro_stats}
|
|||
|
|
|
|||
|
|
ai: # LLM配置
|
|||
|
|
provider: mock # mock/openai/tongyi
|
|||
|
|
model: qwen-turbo
|
|||
|
|
|
|||
|
|
scheduler: # 定时调度
|
|||
|
|
cron: "0 8 1 * *" # 每月1号早上8点
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
配置文件位置: [config/project_config_v2.yaml](file:///f:/ppt/ppt_manager_v2/config/project_config_v2.yaml)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔧 命令行非交互模式测试
|
|||
|
|
|
|||
|
|
直接跑整个Pipeline验证所有环节:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd f:\ppt\ppt_manager_v2
|
|||
|
|
python -c "
|
|||
|
|
import sys
|
|||
|
|
sys.path.insert(0, '.')
|
|||
|
|
from orchestrator import Orchestrator
|
|||
|
|
orch = Orchestrator()
|
|||
|
|
orch.load_template() # 检查: 锚点扫描
|
|||
|
|
result = orch.run_plugins() # 检查: 插件取数+渲染
|
|||
|
|
print('插件结果:', list(result.keys()))
|
|||
|
|
orch.update_native_charts() # 检查: 原生图表更新
|
|||
|
|
orch.ai_generate_summary() # 检查: LLM生成
|
|||
|
|
orch.save() # 检查: 输出文件
|
|||
|
|
print('✅ 全流程通过!')
|
|||
|
|
"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ❓ 常见问题排查
|
|||
|
|
|
|||
|
|
### Q1: TemplateNotFound jinja2 错误
|
|||
|
|
|
|||
|
|
**现象**: `jinja2.exceptions.TemplateNotFound: index_v2.html`
|
|||
|
|
|
|||
|
|
**已修复**: web_socket_app.py第16行明确了 template_folder 绝对路径,且文件在两处备份:
|
|||
|
|
- `f:\ppt\ppt_manager_v2\templates\index_v2.html` (Flask标准位置)
|
|||
|
|
- `f:\ppt\ppt_manager_v2\web\templates\index_v2.html` (配置位置)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Q2: 下载文件找不到 /api/files 返回空
|
|||
|
|
|
|||
|
|
**已修复**: `/api/files` 和 `/download/<filename>` 两处的 `base_dir / "output"` 统一改为 `base_dir.parent / "output"` 指向 `f:\ppt\output\`。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Q3: 'NoneType' object has no attribute 'text'
|
|||
|
|
|
|||
|
|
**现象**: 加载模板时报错
|
|||
|
|
|
|||
|
|
**已修复**: [orchestrator.py](file:///f:/ppt/ppt_manager_v2/orchestrator.py#L75-L90) 先判断 `if slide.shapes.title:` 再安全访问 `.text`。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Q4: 插件不显示/不执行
|
|||
|
|
|
|||
|
|
检查两点:
|
|||
|
|
1. 插件类继承 `BaseGenerator(ABC)`
|
|||
|
|
2. 类属性 `generator_id` 不能是 `None`
|
|||
|
|
3. 目录在 `plugins/generators/*.py` 且文件名不以 `_` 开头
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📌 维护信息
|
|||
|
|
|
|||
|
|
| 项目 | 详情 |
|
|||
|
|
|------|------|
|
|||
|
|
| **版本** | V2.0 2026-05-29 |
|
|||
|
|
| **入口** | `python web_socket_app.py` |
|
|||
|
|
| **前端地址** | http://localhost:5001 |
|
|||
|
|
| **输出目录** | `f:\ppt\output\*.pptx` |
|
|||
|
|
| **日志目录** | `f:\ppt\ppt_manager_v2\logs\` |
|
|||
|
|
| **核心模块** | orchestrator.py / anchor_engine.py / native_chart.py |
|
|||
|
|
| **插件目录** | plugins/generators/ |
|
|||
|
|
|