昨天我們讓 AI 產生簡報大綱。今天直接把大綱做成 PPT 檔
content.txt
(放任何素材:段落、FAQ、圖片說明…)python-pptx
生成 slides.pptx
今天程式碼比較冗長
# make_ppt.py — Day 20:AI 產生 PPT(從大綱到投影片)
import os
import json
from pathlib import Path
from dotenv import load_dotenv
from openai import OpenAI
from pptx import Presentation
from pptx.util import Pt
from pptx.enum.text import PP_ALIGN
# ---------------------------
# 基本設定
# ---------------------------
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
INPUT_TXT = Path("content.txt")
OUTPUT_PPTX = Path("slides.pptx")
# 優先挑常見中文字型(視系統可能改名)
FALLBACK_FONT = "Microsoft JhengHei" # Windows
MAC_FONT = "PingFang TC" # macOS
FONT_CANDIDATES = [MAC_FONT, FALLBACK_FONT, "Arial"]
def pick_font():
# 簡單回傳優先順序的第一個(python-pptx不提供列舉系統字型 API)
return FONT_CANDIDATES[0]
FONT_NAME = pick_font()
# ---------------------------
# 讓 GPT 產生 JSON 大綱
# ---------------------------
def make_outline_json(raw_content: str) -> dict:
prompt = f"""
你是一位簡報顧問。請將下列資料整理為結構化 JSON 的簡報大綱。
需求:
- 使用繁體中文
- 欄位格式如下(務必回傳合法 JSON,勿加註解):
{{
"title": "簡報主題",
"slides": [
{{"title": "投影片標題", "bullets": ["要點1","要點2","要點3"]}}
]
}}
- 5~8 張投影片,每張 2~4 個要點,語句精簡
資料如下:
\"\"\"
{raw_content}
\"\"\"
"""
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "你是嚴謹的結構化輸出專家,只回傳 JSON。"},
{"role": "user", "content": prompt}
],
temperature=0.5,
max_tokens=800,
)
text = resp.choices[0].message.content.strip()
# 嘗試解析 JSON;若失敗再做一次修正要求
try:
return json.loads(text)
except Exception:
fix = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "請將下列內容修正為合法 JSON,只輸出 JSON 本體。"},
{"role": "user", "content": text}
],
temperature=0.0,
max_tokens=800,
)
return json.loads(fix.choices[0].message.content.strip())
# ---------------------------
# 產生 PPT
# ---------------------------
def add_title_slide(prs: Presentation, title_text: str, subtitle_text: str = ""):
slide_layout = prs.slide_layouts[0] # Title slide
slide = prs.slides.add_slide(slide_layout)
slide.shapes.title.text = title_text
if subtitle_text:
subtitle = slide.placeholders[1]
run = subtitle.text_frame.paragraphs[0].add_run()
run.text = subtitle_text
run.font.size = Pt(18)
run.font.name = FONT_NAME
# 設定主標題字型
title = slide.shapes.title
p = title.text_frame.paragraphs[0]
for run in p.runs:
run.font.size = Pt(44)
run.font.name = FONT_NAME
p.alignment = PP_ALIGN.CENTER
def add_bullet_slide(prs: Presentation, title_text: str, bullets: list[str]):
slide_layout = prs.slide_layouts[1] # Title and Content
slide = prs.slides.add_slide(slide_layout)
# 標題
title_shape = slide.shapes.title
title_shape.text = title_text
tp = title_shape.text_frame.paragraphs[0]
for run in tp.runs:
run.font.name = FONT_NAME
run.font.size = Pt(32)
# 內容(子彈點)
body = slide.placeholders[1].text_frame
body.clear()
for i, text in enumerate(bullets):
para = body.add_paragraph() if i > 0 else body.paragraphs[0]
para.text = text
para.level = 0
for run in para.runs:
run.font.name = FONT_NAME
run.font.size = Pt(20)
def build_ppt(outline: dict, output_path: Path):
prs = Presentation()
main_title = outline.get("title", "AI 自動產生簡報")
add_title_slide(prs, main_title, "由 OpenAI + python-pptx 自動生成")
for slide in outline.get("slides", []):
title = slide.get("title", "未命名")
bullets = slide.get("bullets", [])
bullets = [b.strip() for b in bullets if b and isinstance(b, str)]
add_bullet_slide(prs, title, bullets)
prs.save(str(output_path))
# ---------------------------
# 主流程
# ---------------------------
def main():
if not INPUT_TXT.exists():
INPUT_TXT.write_text("請把你的素材貼在這裡:像是文章摘要、FAQ、圖片說明等。", encoding="utf-8")
print(f"已建立 {INPUT_TXT},先把素材寫進去再執行喔!")
return
raw = INPUT_TXT.read_text(encoding="utf-8")
outline = make_outline_json(raw)
build_ppt(outline, OUTPUT_PPTX)
print(f"完成!已輸出:{OUTPUT_PPTX.absolute()}")
if __name__ == "__main__":
main()
來看一下成果:
我們也可以控制風格,把系統訊息調整成「商務簡報/教學簡報/產品發表」等方式
或著是字數控制 圖片插入(可另外寫 add_picture()(python-pptx 支援))
避免亂跑版:子彈點建議 2–4 個,句子短一點
今天我們把 AI 產生的大綱自動做成 PPT:
明天把我們做到這裡的功能包成 FastAPI 服務,變成一支你團隊都能呼叫的小 API!