first commit
This commit is contained in:
85
skills/ai-ppt-generator-1.1.4/SKILL.md
Normal file
85
skills/ai-ppt-generator-1.1.4/SKILL.md
Normal file
@@ -0,0 +1,85 @@
|
||||
---
|
||||
name: ai-ppt-generator
|
||||
description: Generate PPT with Baidu AI. Smart template selection based on content.
|
||||
metadata: { "openclaw": { "emoji": "📑", "requires": { "bins": ["python3"], "env":["BAIDU_API_KEY"]},"primaryEnv":"BAIDU_API_KEY" } }
|
||||
---
|
||||
|
||||
# AI PPT Generator
|
||||
|
||||
Generate PPT using Baidu AI with intelligent template selection.
|
||||
|
||||
## Smart Workflow
|
||||
1. **User provides PPT topic**
|
||||
2. **Agent asks**: "Want to choose a template style?"
|
||||
3. **If yes** → Show styles from `ppt_theme_list.py` → User picks → Use `generate_ppt.py` with chosen `tpl_id` and real `style_id`
|
||||
4. **If no** → Use `random_ppt_theme.py` (auto-selects appropriate template based on topic content)
|
||||
|
||||
## Intelligent Template Selection
|
||||
`random_ppt_theme.py` analyzes the topic and suggests appropriate template:
|
||||
- **Business topics** → 企业商务 style
|
||||
- **Technology topics** → 未来科技 style
|
||||
- **Education topics** → 卡通手绘 style
|
||||
- **Creative topics** → 创意趣味 style
|
||||
- **Cultural topics** → 中国风 or 文化艺术 style
|
||||
- **Year-end reports** → 年终总结 style
|
||||
- **Minimalist design** → 扁平简约 style
|
||||
- **Artistic content** → 文艺清新 style
|
||||
|
||||
## Scripts
|
||||
- `scripts/ppt_theme_list.py` - List all available templates with style_id and tpl_id
|
||||
- `scripts/random_ppt_theme.py` - Smart template selection + generate PPT
|
||||
- `scripts/generate_ppt.py` - Generate PPT with specific template (uses real style_id and tpl_id from API)
|
||||
|
||||
## Key Features
|
||||
- **Smart categorization**: Analyzes topic content to suggest appropriate style
|
||||
- **Fallback logic**: If template not found, automatically uses random selection
|
||||
- **Complete parameters**: Properly passes both style_id and tpl_id to API
|
||||
|
||||
## Usage Examples
|
||||
```bash
|
||||
# List all templates with IDs
|
||||
python3 scripts/ppt_theme_list.py
|
||||
|
||||
# Smart automatic selection (recommended for most users)
|
||||
python3 scripts/random_ppt_theme.py --query "人工智能发展趋势报告"
|
||||
|
||||
# Specific template with proper style_id
|
||||
python3 scripts/generate_ppt.py --query "儿童英语课件" --tpl_id 106
|
||||
|
||||
# Specific template with auto-suggested category
|
||||
python3 scripts/random_ppt_theme.py --query "企业年度总结" --category "企业商务"
|
||||
```
|
||||
|
||||
## Agent Steps
|
||||
1. Get PPT topic from user
|
||||
2. Ask: "Want to choose a template style?"
|
||||
3. **If user says YES**:
|
||||
- Run `ppt_theme_list.py` to show available templates
|
||||
- User selects a template (note the tpl_id)
|
||||
- Run `generate_ppt.py --query "TOPIC" --tpl_id ID`
|
||||
4. **If user says NO**:
|
||||
- Run `random_ppt_theme.py --query "TOPIC"`
|
||||
- Script will auto-select appropriate template based on topic
|
||||
5. Set timeout to 300 seconds (PPT generation takes 2-5 minutes)
|
||||
6. Monitor output, wait for `is_end: true` to get final PPT URL
|
||||
|
||||
## Output Examples
|
||||
**During generation:**
|
||||
```json
|
||||
{"status": "PPT生成中", "run_time": 45}
|
||||
```
|
||||
|
||||
**Final result:**
|
||||
```json
|
||||
{
|
||||
"status": "PPT导出结束",
|
||||
"is_end": true,
|
||||
"data": {"ppt_url": "https://image0.bj.bcebos.com/...ppt"}
|
||||
}
|
||||
```
|
||||
|
||||
## Technical Notes
|
||||
- **API integration**: Fetches real style_id from Baidu API for each template
|
||||
- **Error handling**: If template not found, falls back to random selection
|
||||
- **Timeout**: Generation takes 2-5 minutes, set sufficient timeout
|
||||
- **Streaming**: Uses streaming API, wait for `is_end: true` before considering complete
|
||||
6
skills/ai-ppt-generator-1.1.4/_meta.json
Normal file
6
skills/ai-ppt-generator-1.1.4/_meta.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"ownerId": "kn7akgt520t01vgs2tzx7yk6m180kt26",
|
||||
"slug": "ai-ppt-generator",
|
||||
"version": "1.1.4",
|
||||
"publishedAt": 1773656502997
|
||||
}
|
||||
148
skills/ai-ppt-generator-1.1.4/scripts/generate_ppt.py
Normal file
148
skills/ai-ppt-generator-1.1.4/scripts/generate_ppt.py
Normal file
@@ -0,0 +1,148 @@
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
import time
|
||||
|
||||
import requests
|
||||
import json
|
||||
import argparse
|
||||
|
||||
URL_PREFIX = "https://qianfan.baidubce.com/v2/tools/ai_ppt/"
|
||||
|
||||
|
||||
class Style:
|
||||
def __init__(self, style_id, tpl_id):
|
||||
self.style_id = style_id
|
||||
self.tpl_id = tpl_id
|
||||
|
||||
|
||||
class Outline:
|
||||
def __init__(self, chat_id, query_id, title, outline):
|
||||
self.chat_id = chat_id
|
||||
self.query_id = query_id
|
||||
self.title = title
|
||||
self.outline = outline
|
||||
|
||||
|
||||
def get_ppt_theme(api_key: str):
|
||||
"""Get a random PPT theme"""
|
||||
headers = {
|
||||
"Authorization": "Bearer %s" % api_key,
|
||||
}
|
||||
response = requests.post(URL_PREFIX + "get_ppt_theme", headers=headers)
|
||||
result = response.json()
|
||||
if "errno" in result and result["errno"] != 0:
|
||||
raise RuntimeError(result["errmsg"])
|
||||
|
||||
style_index = random.randint(0, len(result["data"]["ppt_themes"]) - 1)
|
||||
theme = result["data"]["ppt_themes"][style_index]
|
||||
return Style(style_id=theme["style_id"], tpl_id=theme["tpl_id"])
|
||||
|
||||
|
||||
def ppt_outline_generate(api_key: str, query: str):
|
||||
"""Generate PPT outline"""
|
||||
headers = {
|
||||
"Authorization": "Bearer %s" % api_key,
|
||||
"X-Appbuilder-From": "openclaw",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
headers.setdefault('Accept', 'text/event-stream')
|
||||
headers.setdefault('Cache-Control', 'no-cache')
|
||||
headers.setdefault('Connection', 'keep-alive')
|
||||
params = {
|
||||
"query": query,
|
||||
}
|
||||
title = ""
|
||||
outline = ""
|
||||
chat_id = ""
|
||||
query_id = ""
|
||||
with requests.post(URL_PREFIX + "generate_outline", headers=headers, json=params, stream=True) as response:
|
||||
for line in response.iter_lines():
|
||||
line = line.decode('utf-8')
|
||||
if line and line.startswith("data:"):
|
||||
data_str = line[5:].strip()
|
||||
delta = json.loads(data_str)
|
||||
if not title:
|
||||
title = delta["title"]
|
||||
chat_id = delta["chat_id"]
|
||||
query_id = delta["query_id"]
|
||||
outline += delta["outline"]
|
||||
|
||||
return Outline(chat_id=chat_id, query_id=query_id, title=title, outline=outline)
|
||||
|
||||
|
||||
def ppt_generate(api_key: str, query: str, style_id: int = 0, tpl_id: int = None, web_content: str = None):
|
||||
"""Generate PPT - simple version"""
|
||||
headers = {
|
||||
"Authorization": "Bearer %s" % api_key,
|
||||
"Content-Type": "application/json",
|
||||
"X-Appbuilder-From": "openclaw",
|
||||
}
|
||||
|
||||
# Get theme
|
||||
if tpl_id is None:
|
||||
# Random theme
|
||||
style = get_ppt_theme(api_key)
|
||||
style_id = style.style_id
|
||||
tpl_id = style.tpl_id
|
||||
print(f"Using random template (tpl_id: {tpl_id})", file=sys.stderr)
|
||||
else:
|
||||
# Specific theme - use provided style_id (default 0)
|
||||
print(f"Using template tpl_id: {tpl_id}, style_id: {style_id}", file=sys.stderr)
|
||||
|
||||
# Generate outline
|
||||
outline = ppt_outline_generate(api_key, query)
|
||||
|
||||
# Generate PPT
|
||||
headers.setdefault('Accept', 'text/event-stream')
|
||||
headers.setdefault('Cache-Control', 'no-cache')
|
||||
headers.setdefault('Connection', 'keep-alive')
|
||||
params = {
|
||||
"query_id": int(outline.query_id),
|
||||
"chat_id": int(outline.chat_id),
|
||||
"query": query,
|
||||
"outline": outline.outline,
|
||||
"title": outline.title,
|
||||
"style_id": style_id,
|
||||
"tpl_id": tpl_id,
|
||||
"web_content": web_content,
|
||||
"enable_save_bos": True,
|
||||
}
|
||||
with requests.post(URL_PREFIX + "generate_ppt_by_outline", headers=headers, json=params, stream=True) as response:
|
||||
if response.status_code != 200:
|
||||
print(f"request failed, status code is {response.status_code}, error message is {response.text}")
|
||||
return []
|
||||
for line in response.iter_lines():
|
||||
line = line.decode('utf-8')
|
||||
if line and line.startswith("data:"):
|
||||
data_str = line[5:].strip()
|
||||
yield json.loads(data_str)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate PPT")
|
||||
parser.add_argument("--query", "-q", type=str, required=True, help="PPT topic")
|
||||
parser.add_argument("--style_id", "-si", type=int, default=0, help="Style ID (default: 0)")
|
||||
parser.add_argument("--tpl_id", "-tp", type=int, help="Template ID (optional)")
|
||||
parser.add_argument("--web_content", "-wc", type=str, default=None, help="Web content")
|
||||
args = parser.parse_args()
|
||||
|
||||
api_key = os.getenv("BAIDU_API_KEY")
|
||||
if not api_key:
|
||||
print("Error: BAIDU_API_KEY must be set in environment.")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
start_time = int(time.time())
|
||||
results = ppt_generate(api_key, args.query, args.style_id, args.tpl_id, args.web_content)
|
||||
|
||||
for result in results:
|
||||
if "is_end" in result and result["is_end"]:
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
else:
|
||||
end_time = int(time.time())
|
||||
print(json.dumps({"status": result["status"], "run_time": end_time - start_time}))
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
43
skills/ai-ppt-generator-1.1.4/scripts/ppt_theme_list.py
Normal file
43
skills/ai-ppt-generator-1.1.4/scripts/ppt_theme_list.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import os
|
||||
import sys
|
||||
import requests
|
||||
import json
|
||||
|
||||
|
||||
def ppt_theme_list(api_key: str):
|
||||
url = "https://qianfan.baidubce.com/v2/tools/ai_ppt/get_ppt_theme"
|
||||
headers = {
|
||||
"Authorization": "Bearer %s" % api_key,
|
||||
"X-Appbuilder-From": "openclaw",
|
||||
}
|
||||
response = requests.post(url, headers=headers)
|
||||
result = response.json()
|
||||
if "errno" in result and result["errno"] != 0:
|
||||
raise RuntimeError(result["errmsg"])
|
||||
themes = []
|
||||
count = 0
|
||||
for theme in result["data"]["ppt_themes"]:
|
||||
count += 1
|
||||
if count > 100:
|
||||
break
|
||||
themes.append({
|
||||
"style_name_list": theme["style_name_list"],
|
||||
"style_id": theme["style_id"],
|
||||
"tpl_id": theme["tpl_id"],
|
||||
})
|
||||
return themes
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
api_key = os.getenv("BAIDU_API_KEY")
|
||||
if not api_key:
|
||||
print("Error: BAIDU_API_KEY must be set in environment.")
|
||||
sys.exit(1)
|
||||
try:
|
||||
results = ppt_theme_list(api_key)
|
||||
print(json.dumps(results, ensure_ascii=False, indent=2))
|
||||
except Exception as e:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
print(f"error type:{exc_type}")
|
||||
print(f"error message:{exc_value}")
|
||||
sys.exit(1)
|
||||
321
skills/ai-ppt-generator-1.1.4/scripts/random_ppt_theme.py
Normal file
321
skills/ai-ppt-generator-1.1.4/scripts/random_ppt_theme.py
Normal file
@@ -0,0 +1,321 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Random PPT Theme Selector
|
||||
If user doesn't select a PPT template, this script will randomly select one
|
||||
from the available templates and generate PPT.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import random
|
||||
import argparse
|
||||
import subprocess
|
||||
import time
|
||||
def get_available_themes():
|
||||
"""Get available PPT themes"""
|
||||
try:
|
||||
api_key = os.getenv("BAIDU_API_KEY")
|
||||
if not api_key:
|
||||
print("Error: BAIDU_API_KEY environment variable not set", file=sys.stderr)
|
||||
return []
|
||||
|
||||
# Import the function from ppt_theme_list.py
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(0, script_dir)
|
||||
|
||||
from ppt_theme_list import ppt_theme_list as get_themes
|
||||
themes = get_themes(api_key)
|
||||
return themes
|
||||
except Exception as e:
|
||||
print(f"Error getting themes: {e}", file=sys.stderr)
|
||||
return []
|
||||
|
||||
|
||||
|
||||
def categorize_themes(themes):
|
||||
"""Categorize themes by style for better random selection"""
|
||||
categorized = {
|
||||
"企业商务": [],
|
||||
"文艺清新": [],
|
||||
"卡通手绘": [],
|
||||
"扁平简约": [],
|
||||
"中国风": [],
|
||||
"年终总结": [],
|
||||
"创意趣味": [],
|
||||
"文化艺术": [],
|
||||
"未来科技": [],
|
||||
"默认": []
|
||||
}
|
||||
|
||||
for theme in themes:
|
||||
style_names = theme.get("style_name_list", [])
|
||||
if not style_names:
|
||||
categorized["默认"].append(theme)
|
||||
continue
|
||||
|
||||
added = False
|
||||
for style_name in style_names:
|
||||
if style_name in categorized:
|
||||
categorized[style_name].append(theme)
|
||||
added = True
|
||||
break
|
||||
|
||||
if not added:
|
||||
categorized["默认"].append(theme)
|
||||
|
||||
return categorized
|
||||
|
||||
|
||||
def select_random_theme_by_category(categorized_themes, preferred_category=None):
|
||||
"""Select a random theme, optionally preferring a specific category"""
|
||||
# If preferred category specified and has themes, use it
|
||||
if preferred_category and preferred_category in categorized_themes:
|
||||
if categorized_themes[preferred_category]:
|
||||
return random.choice(categorized_themes[preferred_category])
|
||||
|
||||
# Otherwise, select from all non-empty categories
|
||||
available_categories = []
|
||||
for category, themes in categorized_themes.items():
|
||||
if themes:
|
||||
available_categories.append(category)
|
||||
|
||||
if not available_categories:
|
||||
return None
|
||||
|
||||
# Weighted random selection: prefer non-default categories
|
||||
weights = []
|
||||
for category in available_categories:
|
||||
if category == "默认":
|
||||
weights.append(0.5) # Lower weight for default
|
||||
else:
|
||||
weights.append(2.0) # Higher weight for specific styles
|
||||
|
||||
# Normalize weights
|
||||
total_weight = sum(weights)
|
||||
weights = [w/total_weight for w in weights]
|
||||
|
||||
selected_category = random.choices(available_categories, weights=weights, k=1)[0]
|
||||
return random.choice(categorized_themes[selected_category])
|
||||
|
||||
|
||||
def suggest_category_by_query(query):
|
||||
"""Suggest template category based on query keywords - enhanced version"""
|
||||
query_lower = query.lower()
|
||||
|
||||
# Comprehensive keyword mapping with priority order
|
||||
keyword_mapping = [
|
||||
# Business & Corporate (highest priority for formal content)
|
||||
("企业商务", [
|
||||
"企业", "公司", "商务", "商业", "商务", "商业计划", "商业报告",
|
||||
"营销", "市场", "销售", "财务", "会计", "审计", "投资", "融资",
|
||||
"战略", "管理", "运营", "人力资源", "hr", "董事会", "股东",
|
||||
"年报", "季报", "财报", "业绩", "kpi", "okr", "商业计划书",
|
||||
"提案", "策划", "方案", "报告", "总结", "规划", "计划"
|
||||
]),
|
||||
|
||||
# Technology & Future Tech
|
||||
("未来科技", [
|
||||
"未来", "科技", "人工智能", "ai", "机器学习", "深度学习",
|
||||
"大数据", "云计算", "区块链", "物联网", "iot", "5g", "6g",
|
||||
"量子计算", "机器人", "自动化", "智能制造", "智慧城市",
|
||||
"虚拟现实", "vr", "增强现实", "ar", "元宇宙", "数字孪生",
|
||||
"芯片", "半导体", "集成电路", "电子", "通信", "网络",
|
||||
"网络安全", "信息安全", "数字化", "数字化转型",
|
||||
"科幻", "高科技", "前沿科技", "科技创新", "技术"
|
||||
]),
|
||||
|
||||
# Education & Children
|
||||
("卡通手绘", [
|
||||
"卡通", "动画", "动漫", "儿童", "幼儿", "小学生", "中学生",
|
||||
"教育", "教学", "课件", "教案", "学习", "培训", "教程",
|
||||
"趣味", "有趣", "可爱", "活泼", "生动", "绘本", "漫画",
|
||||
"手绘", "插画", "图画", "图形", "游戏", "玩乐", "娱乐"
|
||||
]),
|
||||
|
||||
# Year-end & Summary
|
||||
("年终总结", [
|
||||
"年终", "年度", "季度", "月度", "周报", "日报",
|
||||
"总结", "回顾", "汇报", "述职", "考核", "评估",
|
||||
"成果", "成绩", "业绩", "绩效", "目标", "完成",
|
||||
"工作汇报", "工作总结", "年度报告", "季度报告"
|
||||
]),
|
||||
|
||||
# Minimalist & Modern Design
|
||||
("扁平简约", [
|
||||
"简约", "简洁", "简单", "极简", "现代", "当代",
|
||||
"设计", "视觉", "ui", "ux", "用户体验", "用户界面",
|
||||
"科技感", "数字感", "数据", "图表", "图形", "信息图",
|
||||
"分析", "统计", "报表", "dashboard", "仪表板",
|
||||
"互联网", "web", "移动", "app", "应用", "软件"
|
||||
]),
|
||||
|
||||
# Chinese Traditional
|
||||
("中国风", [
|
||||
"中国", "中华", "传统", "古典", "古风", "古代",
|
||||
"文化", "文明", "历史", "国学", "东方", "水墨",
|
||||
"书法", "国画", "诗词", "古文", "经典", "传统节日",
|
||||
"春节", "中秋", "端午", "节气", "风水", "易经",
|
||||
"儒", "道", "佛", "禅", "茶道", "瓷器", "丝绸"
|
||||
]),
|
||||
|
||||
# Cultural & Artistic
|
||||
("文化艺术", [
|
||||
"文化", "艺术", "文艺", "美学", "审美", "创意",
|
||||
"创作", "作品", "展览", "博物馆", "美术馆", "画廊",
|
||||
"音乐", "舞蹈", "戏剧", "戏曲", "电影", "影视",
|
||||
"摄影", "绘画", "雕塑", "建筑", "设计", "时尚",
|
||||
"文学", "诗歌", "小说", "散文", "哲学", "思想"
|
||||
]),
|
||||
|
||||
# Artistic & Fresh
|
||||
("文艺清新", [
|
||||
"文艺", "清新", "小清新", "治愈", "温暖", "温柔",
|
||||
"浪漫", "唯美", "优雅", "精致", "细腻", "柔和",
|
||||
"自然", "生态", "环保", "绿色", "植物", "花卉",
|
||||
"风景", "旅行", "游记", "生活", "日常", "情感"
|
||||
]),
|
||||
|
||||
# Creative & Fun
|
||||
("创意趣味", [
|
||||
"创意", "创新", "创造", "发明", "新奇", "新颖",
|
||||
"独特", "个性", "特色", "趣味", "有趣", "好玩",
|
||||
"幽默", "搞笑", "笑话", "娱乐", "休闲", "放松",
|
||||
"脑洞", "想象力", "灵感", "点子", "想法", "概念"
|
||||
]),
|
||||
|
||||
# Academic & Research
|
||||
("默认", [
|
||||
"研究", "学术", "科学", "论文", "课题", "项目",
|
||||
"实验", "调查", "分析", "理论", "方法", "技术",
|
||||
"医学", "健康", "医疗", "生物", "化学", "物理",
|
||||
"数学", "工程", "建筑", "法律", "政治", "经济",
|
||||
"社会", "心理", "教育", "学习", "知识", "信息"
|
||||
])
|
||||
]
|
||||
|
||||
# Check each category with its keywords
|
||||
for category, keywords in keyword_mapping:
|
||||
for keyword in keywords:
|
||||
if keyword in query_lower:
|
||||
return category
|
||||
|
||||
# If no match found, analyze query length and content
|
||||
words = query_lower.split()
|
||||
if len(words) <= 3:
|
||||
# Short query, likely specific - use "默认" or tech-related
|
||||
if any(word in query_lower for word in ["ai", "vr", "ar", "iot", "5g", "tech"]):
|
||||
return "未来科技"
|
||||
return "默认"
|
||||
else:
|
||||
# Longer query, analyze word frequency
|
||||
word_counts = {}
|
||||
for word in words:
|
||||
if len(word) > 1: # Ignore single characters
|
||||
word_counts[word] = word_counts.get(word, 0) + 1
|
||||
|
||||
# Check for business indicators
|
||||
business_words = ["报告", "总结", "计划", "方案", "业绩", "销售", "市场"]
|
||||
if any(word in word_counts for word in business_words):
|
||||
return "企业商务"
|
||||
|
||||
# Check for tech indicators
|
||||
tech_words = ["技术", "科技", "数据", "数字", "智能", "系统"]
|
||||
if any(word in word_counts for word in tech_words):
|
||||
return "未来科技"
|
||||
|
||||
# Default fallback
|
||||
return "默认"
|
||||
|
||||
|
||||
def generate_ppt_with_random_theme(query, preferred_category=None):
|
||||
"""Generate PPT with randomly selected theme"""
|
||||
# Get available themes
|
||||
themes = get_available_themes()
|
||||
if not themes:
|
||||
print("Error: No available themes found", file=sys.stderr)
|
||||
return False
|
||||
|
||||
# Categorize themes
|
||||
categorized = categorize_themes(themes)
|
||||
|
||||
# Select random theme
|
||||
selected_theme = select_random_theme_by_category(categorized, preferred_category)
|
||||
if not selected_theme:
|
||||
print("Error: Could not select a theme", file=sys.stderr)
|
||||
return False
|
||||
|
||||
style_id = selected_theme.get("style_id", 0)
|
||||
tpl_id = selected_theme.get("tpl_id")
|
||||
style_names = selected_theme.get("style_name_list", ["默认"])
|
||||
|
||||
print(f"Selected template: {style_names[0]} (tpl_id: {tpl_id})", file=sys.stderr)
|
||||
|
||||
# Generate PPT
|
||||
script_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "generate_ppt.py")
|
||||
|
||||
try:
|
||||
# Run generate_ppt.py with the selected theme
|
||||
cmd = [
|
||||
sys.executable, script_path,
|
||||
"--query", query,
|
||||
"--tpl_id", str(tpl_id),
|
||||
"--style_id", str(style_id)
|
||||
]
|
||||
|
||||
start_time = int(time.time())
|
||||
process = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
bufsize=1,
|
||||
universal_newlines=True
|
||||
)
|
||||
|
||||
# Stream output
|
||||
for line in process.stdout:
|
||||
line = line.strip()
|
||||
if line:
|
||||
try:
|
||||
data = json.loads(line)
|
||||
if "is_end" in data and data["is_end"]:
|
||||
print(json.dumps(data, ensure_ascii=False))
|
||||
else:
|
||||
end_time = int(time.time())
|
||||
print(json.dumps({"status": data.get("status", "生成中"), "run_time": end_time - start_time}, ensure_ascii=False))
|
||||
except json.JSONDecodeError:
|
||||
# Just print non-JSON output
|
||||
print(line)
|
||||
|
||||
process.wait()
|
||||
return process.returncode == 0
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error generating PPT: {e}", file=sys.stderr)
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Generate PPT with random theme selection")
|
||||
parser.add_argument("--query", "-q", type=str, required=True, help="PPT主题/内容")
|
||||
parser.add_argument("--category", "-c", type=str, help="Preferred category (企业商务/文艺清新/卡通手绘/扁平简约/中国风/年终总结/创意趣味/文化艺术/未来科技)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Determine preferred category
|
||||
preferred_category = args.category
|
||||
if not preferred_category:
|
||||
preferred_category = suggest_category_by_query(args.query)
|
||||
if preferred_category:
|
||||
print(f"Auto-suggested category: {preferred_category}", file=sys.stderr)
|
||||
|
||||
# Generate PPT
|
||||
success = generate_ppt_with_random_theme(args.query, preferred_category)
|
||||
|
||||
if not success:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user