惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - kunyashaw

基于langgraph的智能问答工作流 langgraph 基础使用(条件/循环/嵌套子图) vue3Crush以及对比vue2 渗透与常见服务配置 LangChain教程-3、Langchain进阶 LangChain教程-2、Langchain基础 LangChain教程-1、python基础 openclaw skill--一键生成项目宣讲介绍网页及长截图 openclaw新手skill推荐: openclaw-newbie-faq 用opencode和minimax给娃搭了一个raz学习站点 clawdbot(新名字:moltbot、OpenClaw)折腾过程 angualr基础 node基础 vue基础 某业务技术架构 漏洞治理 堡垒机方案 linux常见软件的环境搭建 linux运维基础
LangChain教程-4、构建简易智能 PPT 生成器
kunyashaw · 2026-03-27 · via 博客园 - kunyashaw

LangChain 实战教程·番外篇(一):用 LangChain 构建智能 PPT 生成器

前置要求:需要 Python 3.10+、一个 MiniMax API Key

前置知识:建议先读完前 20 篇基础教程,对 LCEL 有基本了解

这篇教程解决什么问题

学完前 20 个 Demo,你已经掌握了 LangChain 的各种组件用法。但这些用法是散落的——这篇教程用一条主线任务把所有东西串起来:

做一个智能 PPT 生成器:输入一个主题,输出一个真实的 .pptx 文件

这个任务会用到:

  • D01 LCEL 管道语法
  • D04 Output Parser
  • 以及 python-pptx 库

学完这篇,你会有一个真正能用的工具,同时深刻理解"Chain"这个核心理念。

最终效果预览

(图片:最终运行效果截图)

ppt_tut1_result

Step 0 · 环境准备

0.1 创建项目目录

打开终端,按顺序执行:

mkdir langchain-ppt
cd langchain-ppt
uv init

0.2 安装依赖

本教程需要以下 Python 包:

langchain-core>=1.0.0
langchain-openai>=1.0.0
python-dotenv>=1.0.1
python-pptx>=0.6.23

安装方式(推荐 requirements.txt):

uv sync
# 或
uv pip install -r requirements.txt

什么是 uv?
uv 是新一代 Python 包管理工具,比 pip 更快、更可靠。如果还没安装,执行:

pip install uv

0.3 创建 .env 配置文件

在项目根目录新建 .env 文件:

touch .env

编辑 .env 文件内容:

# MiniMax API Key(必填)
MINIMAX_API_KEY=sk-your-key-here

获取 API Key:访问 MiniMax 开放平台 注册后获取

0.4 验证环境

新建 01_verify_env.py,内容如下(与 demos 目录一致):

# 01_verify_env.py
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
import os

load_dotenv()
print(os.getenv("MINIMAX_API_KEY"))

llm = ChatOpenAI(
    model="MiniMax-M2.7",
    base_url="https://api.minimaxi.com/v1",
    api_key=os.getenv("MINIMAX_API_KEY"),
    temperature=0.7
)

response = llm.invoke("你好")
print(response.content)

运行:

uv run python 01_verify_env.py

看到 你好 的回复,说明环境 OK。

ppt_tut1_env

Step 1 · 让模型吐出结构化 PPT 大纲

1.1 什么是 Output Parser

在前 D04 里学过:LLM 输出的本质是字符串。想让程序自动处理 LLM 的输出,必须先把字符串解析成结构化数据。

OutputParser 就是做这件事的组件:

(图片:Pydantic Parser 工作原理)

LangChain 内置了多种 Parser,本教程用 PydanticOutputParser——因为它可以定义字段描述(Field description),让 LLM 知道每个字段应该填什么,同时自动校验输出格式。

1.2 定义 PPT 大纲的数据模型

用 Pydantic 定义我们想要的 PPT 结构(与 demos/02_ppt_schema.py 一致):

# 02_ppt_schema.py
from pydantic import BaseModel, Field
from typing import List

class Slide(BaseModel):
    """单页幻灯片"""
    title: str = Field(description="幻灯片标题,不超过20字")
    subtitle: str = Field(description="副标题,不超过30字")
    points: List[str] = Field(
        description="要点列表,每个要点不超过50字",
        min_length=2,
        max_length=5
    )
    notes: str = Field(description="演讲备注")

class PPTSchema(BaseModel):
    """完整PPT大纲"""
    title: str = Field(description="PPT主题标题,不超过30字")
    subtitle: str = Field(description="PPT副标题,概括主题")
    author: str = Field(description="演讲者姓名")
    slides: List[Slide] = Field(
        description="幻灯片列表",
        min_length=5,
        max_length=15
    )

Field description 为什么重要?
这里的 description 就是告诉 LLM"我希望你输出什么格式"。LLM 会参考它来生成内容。

1.3 组合 Parser 到 Chain

完整代码(与 demos/02_ppt_schema.py 一致):

# 02_ppt_schema.py
# generate_outline.py
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field
from typing import List

load_dotenv()

# ========== 数据模型 ==========
class Slide(BaseModel):
    title: str = Field(description="幻灯片标题,不超过20字")
    subtitle: str = Field(description="副标题,不超过30字")
    points: List[str] = Field(description="要点列表,每个要点不超过50字", min_length=2, max_length=5)
    notes: str = Field(description="演讲备注")

class PPTSchema(BaseModel):
    title: str = Field(description="PPT主题标题,不超过30字")
    subtitle: str = Field(description="PPT副标题,概括主题")
    author: str = Field(description="演讲者姓名")
    slides: List[Slide] = Field(description="幻灯片列表", min_length=5, max_length=15)

# ========== Parser + Prompt 组合 ==========
parser = PydanticOutputParser(pydantic_object=PPTSchema)

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个专业的PPT内容策划专家。"),
    ("human", "请为「{topic}」这个主题生成一份完整的PPT大纲。\n\n{format_instructions}")
])

prompt = prompt.partial(
    format_instructions=parser.get_format_instructions()
)

# ========== 串联 Chain ==========
chain = prompt | ChatOpenAI(
    model="MiniMax-M2.7",
    base_url="https://api.minimaxi.com/v1",
    api_key=os.getenv("MINIMAX_API_KEY"),
    temperature=0.7
) | parser

# ========== 执行 ==========
result = chain.invoke({"topic": "量子计算技术趋势"})
print(result.model_dump_json(indent=2))

运行结果(JSON 摘要):

{
  "title": "量子计算技术趋势",
  "subtitle": "从原理到应用的全景解析",
  "author": "LangChain助手",
  "slides": [
    {"title": "什么是量子计算", "subtitle": "理解量子力学基础", "points": ["量子叠加态", "量子纠缠原理", "量子比特"], "notes": "开场要通俗易懂"},
    ...
  ]
}

(图片:Pydantic Parser 完整流程)

ppt_tut1_parser

Step 2 · 把大纲变成真实的 PPTX 文件

2.1 python-pptx 基础

python-pptx 是操作 PowerPoint 文件的 Python 库。用法与 demos/03_generate_ppt.py 一致:

# 03_generate_ppt.py
from pptx import Presentation
from pptx.util import Pt, Inches
from pptx.dml.color import RGBColor

# 新建空白演示文稿
prs = Presentation()

# 添加一页(使用"标题+内容"布局,layouts[1])
slide = prs.slides.add_slide(prs.slide_layouts[1])

# 设置标题
title = slide.shapes.title
title.text = "这是标题"

# 设置正文
body = slide.placeholders[1]
body.text = "这是第一行\n这是第二行"

# 保存文件
prs.save("output.pptx")

常见 Slide Layouts 索引:

  • layouts[0]:空白
  • layouts[1]标题 + 内容(最常用)
  • layouts[6]:仅标题

(图片:python-pptx 代码与效果对照)

ppt_tut1_pptx

2.2 把 Parser 结果对接到 PPTX 生成

把 Step 1 的 Parser 输出接到 PPTX 生成函数:

import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field
from typing import List
from pptx import Presentation

load_dotenv()

# ========== 数据模型(与Step1相同)==========
class Slide(BaseModel):
    title: str = Field(description="幻灯片标题,不超过20字")
    subtitle: str = Field(description="副标题,不超过30字")
    points: List[str] = Field(description="要点列表", min_length=2, max_length=5)
    notes: str = Field(description="演讲备注")

class PPTSchema(BaseModel):
    title: str = Field(description="PPT主题标题,不超过30字")
    subtitle: str = Field(description="PPT副标题")
    author: str = Field(description="演讲者姓名")
    slides: List[Slide] = Field(description="幻灯片列表", min_length=5, max_length=15)

# ========== Chain(与Step1相同)==========
parser = PydanticOutputParser(pydantic_object=PPTSchema)
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个专业的PPT内容策划专家。"),
    ("human", "请为「{topic}」生成PPT大纲。\n\n{format_instructions}")
]).partial(format_instructions=parser.get_format_instructions())

chain = prompt | ChatOpenAI(
    model="MiniMax-M2.7",
    base_url="https://api.minimaxi.com/v1",
    api_key=os.getenv("MINIMAX_API_KEY"),
    temperature=0.7
) | parser

# ========== PPTX 生成函数 ==========
def build_pptx(schema: PPTSchema, output_path: str) -> None:
    """把PPTSchema写入真实PPTX文件"""
    os.makedirs(os.path.dirname(output_path), exist_ok=True)
    prs = Presentation()

    for slide_data in schema.slides:
        slide = prs.slides.add_slide(prs.slide_layouts[1])
        slide.shapes.title.text = slide_data.title
        body = slide.placeholders[1] if len(slide.placeholders) > 1 else None
        if body:
            content_lines = [slide_data.subtitle, ""]
            content_lines += [f"- {pt}" for pt in slide_data.points]
            content_lines += ["", f"备注: {slide_data.notes}"]
            body.text = "\n".join(content_lines)

    try:
        prs.save(output_path)
        print(f"✅ PPT已保存至:{output_path}")
    except PermissionError:
        print(f"❌ 权限错误:请关闭已打开的PPT文件后重试")

# ========== 执行完整流程 ==========
if __name__ == "__main__":
    topic = input("请输入PPT主题:").strip()
    if not topic:
        topic = "LangChain 架构解析"

    print("正在生成PPT大纲...")
    result = chain.invoke({"topic": topic})
    print("✅ 大纲生成完成,正在写入文件...")
    output_file = os.path.join("output", f"{topic}.pptx")
    build_pptx(result, output_file)

运行:

uv run python 02_ppt_schema.py
请输入PPT主题:量子计算技术趋势
正在生成PPT大纲...
✅ 大纲生成完成,正在写入文件...
✅ PPT已保存至:output/量子计算技术趋势.pptx

打开 output/量子计算技术趋势.pptx,可以看到真实的 PPT 文件已生成。

Step 3 · 用 LCEL 把所有组件串联成完整系统

3.1 完整 Chain 全貌

回顾一下整个流程:

(图片:LCEL Chain 串联图)

ppt_tut1_chain

我们用 LCEL 的管道语法,把四步串成一条线。完整代码与 demos/04_ai_generate_ppt.py 一致(简化版,不含多风格 Prompt):

# generate_ppt_full.py
# 完整可运行版本:输入主题 → 输出 PPTX 文件
# 依赖:"langchain-openai>=1.0.0" python-dotenv>=1.0.1 python-pptx>=0.6.23

import os
import json
import re
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field
from typing import List
from pptx import Presentation

def get_output_path(filename: str) -> str:
    return os.path.join("output", filename)

def clean_text_for_ppt(text: str) -> str:
    """清理文本,移除可能导致显示问题的字符"""
    if not text:
        return ""
    # 移除控制字符(保留换行)
    cleaned = ''.join(c for c in text if c == '\n' or c == '\t' or (ord(c) >= 32 and ord(c) != 127))
    return cleaned

def extract_json_from_llm_output(text: str) -> str:
    """从LLM输出中提取JSON,即使有额外文字也能工作"""
    # 确保文本是正确的编码
    if isinstance(text, bytes):
        text = text.decode('utf-8', errors='replace')
    
    stack = []
    start_idx = -1
    for i, c in enumerate(text):
        if c == '{':
            if not stack:
                start_idx = i
            stack.append(c)
        elif c == '}':
            stack.pop()
            if not stack and start_idx != -1:
                return text[start_idx:i+1]
    return text

load_dotenv()

# === 数据模型 ===
class Slide(BaseModel):
    title: str = Field(description="幻灯片标题,不超过20字")
    subtitle: str = Field(description="副标题,不超过30字")
    points: List[str] = Field(description="要点列表", min_length=2, max_length=10)
    notes: str = Field(description="演讲备注")

class PPTSchema(BaseModel):
    title: str = Field(description="PPT主题标题,不超过30字")
    subtitle: str = Field(description="PPT副标题")
    author: str = Field(description="演讲者姓名")
    slides: List[Slide] = Field(description="幻灯片列表", min_length=5, max_length=30)

# === Chain ===
# 创建提示词模板,使用 ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个专业的PPT内容策划专家。"),
    ("human", "请为「{topic}」这个主题生成一份完整的PPT大纲。\n\n请按照以下JSON格式输出:\n{{\n  \"title\": \"PPT主题标题\",\n  \"subtitle\": \"PPT副标题\",\n  \"author\": \"演讲者姓名\",\n  \"slides\": [\n    {{\n      \"title\": \"幻灯片标题\",\n      \"subtitle\": \"副标题\",\n      \"points\": [\"要点1\", \"要点2\"],\n      \"notes\": \"演讲备注\"\n    }}\n  ]\n}}")
])

# 可扩展 prompt 方案(保留上面的原始 prompt,不删除)
prompt_strict_json = ChatPromptTemplate.from_messages([
    ("system", "你是一个专业的PPT内容策划专家。你必须只输出一个合法JSON对象,不得输出任何额外文本。"),
    ("human", "请为「{topic}」生成PPT大纲。\n\n要求:\n1. 仅输出 JSON。\n2. 严禁输出 markdown、注释、解释、前后缀文字。\n3. JSON 结构必须为:\n{{\n  \"title\": \"PPT主题标题\",\n  \"subtitle\": \"PPT副标题\",\n  \"author\": \"演讲者姓名\",\n  \"slides\": [\n    {{\n      \"title\": \"幻灯片标题\",\n      \"subtitle\": \"副标题\",\n      \"points\": [\"要点1\", \"要点2\"],\n      \"notes\": \"演讲备注\"\n    }}\n  ]\n}}\n4. slides 数量 5-30。\n5. points 数量 2-10。")
])

prompt_executive = ChatPromptTemplate.from_messages([
    ("system", "你是企业级汇报专家,擅长高管汇报PPT结构设计。输出必须是纯JSON。"),
    ("human", "请为「{topic}」生成一份偏商业汇报风格的PPT大纲,强调业务价值、ROI、落地路径与风险控制。\n\n输出为 JSON:\n{{\n  \"title\": \"PPT主题标题\",\n  \"subtitle\": \"PPT副标题\",\n  \"author\": \"演讲者姓名\",\n  \"slides\": [\n    {{\n      \"title\": \"幻灯片标题\",\n      \"subtitle\": \"副标题\",\n      \"points\": [\"要点1\", \"要点2\"],\n      \"notes\": \"演讲备注\"\n    }}\n  ]\n}}")
])

prompt_workshop = ChatPromptTemplate.from_messages([
    ("system", "你是技术培训讲师,擅长把复杂主题拆成可教学的结构化内容。输出必须是纯JSON。"),
    ("human", "请为「{topic}」生成一份偏教学实战风格的PPT大纲,强调概念-示例-实操-总结的节奏。\n\n输出为 JSON:\n{{\n  \"title\": \"PPT主题标题\",\n  \"subtitle\": \"PPT副标题\",\n  \"author\": \"演讲者姓名\",\n  \"slides\": [\n    {{\n      \"title\": \"幻灯片标题\",\n      \"subtitle\": \"副标题\",\n      \"points\": [\"要点1\", \"要点2\"],\n      \"notes\": \"演讲备注\"\n    }}\n  ]\n}}")
])

PROMPT_PRESETS = {
    "default": prompt,                # 现有 prompt(默认)
    "strict_json": prompt_strict_json,
    "executive": prompt_executive,    # 商业汇报风格
    "workshop": prompt_workshop       # 培训讲解风格
}

PROMPT_STYLE = os.getenv("PPT_PROMPT_STYLE", "default")
selected_prompt = PROMPT_PRESETS.get(PROMPT_STYLE, prompt)

llm = ChatOpenAI(
     model="MiniMax-M2.7",
     base_url="https://api.minimaxi.com/v1",
     api_key=os.getenv("MINIMAX_API_KEY"),
     temperature=0.7
) 

# === PPTX 生成 ===

def build_pptx_fn(input_dict: dict) -> dict:
    schema: PPTSchema = input_dict["schema"]
    topic = input_dict["topic"]
    prs = Presentation()
    for slide_data in schema.slides:
        slide = prs.slides.add_slide(prs.slide_layouts[1])
        slide.shapes.title.text = clean_text_for_ppt(slide_data.title)
        body = slide.placeholders[1] if len(slide.placeholders) > 1 else None
        if body:
            # 移除可能导致乱码的特殊字符,使用简洁的格式
            lines = [clean_text_for_ppt(slide_data.subtitle), ""] + [f"- {clean_text_for_ppt(p)}" for p in slide_data.points]
            lines += ["", "备注: " + clean_text_for_ppt(slide_data.notes)]
            body.text = "\n".join(lines)
    # 更安全的文件名处理
    safe_topic = re.sub(r'[^\w\u4e00-\u9fff\s-]', '', topic)
    safe_topic = safe_topic.strip().replace(' ', '_')
    path = get_output_path(f"{safe_topic}.pptx")
    os.makedirs(os.path.dirname(path), exist_ok=True)
    try:
        prs.save(path)
        return {"path": path, "count": len(schema.slides)}
    except PermissionError:
        return {"path": None, "count": 0, "error": "文件被占用"}
    except Exception as e:
        return {"path": None, "count": 0, "error": str(e)}

if __name__ == "__main__":
    topic = input("请输入PPT主题:").strip() or "LangChain 架构解析"
    print(f"🎯 主题:{topic}")
    try:
        # 直接调用 LLM,不使用解析器
        llm_chain = selected_prompt | llm
        llm_output = llm_chain.invoke({"topic": topic})
        llm_text = llm_output.content if hasattr(llm_output, "content") else str(llm_output)
        
        # 提取 JSON 并解析
        json_text = extract_json_from_llm_output(llm_text)
        
        json_data = json.loads(json_text)
        schema = PPTSchema(**json_data)
        
        print(f"✅ Schema 解析成功,共 {len(schema.slides)} 页")
        
        result = build_pptx_fn({"topic": topic, "schema": schema})
        if result.get("path"):
            print(f"✅ 完成!共 {result['count']} 页\n📁 {result['path']}")
        else:
            print(f"❌ 保存失败:{result.get('error', '未知错误')}")
    except Exception as e:
        print(f"❌ 运行出错:{e}")
        import traceback
        traceback.print_exc()

3.2 最终运行效果

ppt_tut1_result

依赖清单

langchain-core>=1.0.0 LangChain 核心组件 langchain-openai>=1.0.0 LLM 调用(兼容 MiniMax) python-dotenv>=1.0.1 环境变量加载 python-pptx>=0.6.23 PPTX 文件生成
包名 版本 用途

安装命令:

uv sync
# 或
uv pip install -r requirements.txt

常见问题

Q:报错 MINIMAX_API_KEY is not set 或认证错误
A:环境变量未正确加载。检查:

  1. .env 文件是否在项目根目录
  2. API Key 是否正确复制
  3. 运行前确认 load_dotenv() 已执行

Q:JSON 解析失败(Invalid json output 或 OUTPUT_PARSING_FAILURE)
A:LLM 输出格式不稳定,经常包含额外的解释性文字。解决方案:

  1. 使用 extract_json_from_llm_output() 自动提取 JSON(项目已实现)
  2. 适当放宽 schema 限制(slides 从 20 放宽到 30)

Q:NameError: name 'get_output_path' is not defined
A:脚本中缺少函数定义。确保添加:

def get_output_path(filename: str) -> str:
    return os.path.join("output", filename)

Q:FileNotFoundError 或 PermissionError 保存 PPT 失败
A:output/ 目录不存在或没有写入权限。解决:

os.makedirs(os.path.dirname(path), exist_ok=True)

Q:乱码问题或特殊字符显示异常
A:文本中包含 emoji 或特殊字符。解决:

  1. 项目已实现 clean_text_for_ppt() 函数
  2. 使用简洁格式(如 - 而非

Q:1 validation error for PPTSchema slides 数量超限
A:模型生成的幻灯片数量超过 schema 限制。已将 max_length 从 20 放宽到 30。

Q:zsh: command not found: py
A:macOS/Linux 没有 py 命令。使用:

python3 01_verify_env.py
# 或
uv run python 01_verify_env.py

Q:ModuleNotFoundError: No module named 'langchain_openai'
A:依赖未安装。解决:

uv sync
# 或
uv pip install -r requirements.txt
uv run python 01_verify_env.py

Q:error: No pyproject.toml found
A:在没有 pyproject.toml 的目录执行了 uv。先进入项目目录再执行。

Q:openai.AuthenticationError: 401 Invalid Authentication
A:MINIMAX_API_KEY 无效或为空。检查 .env 文件。

Q:openai.BadRequestError: unknown model
A:模型名不存在或不在账号可用范围。当前项目使用 MiniMax-M2.7

Q:zsh: 1.0.0 not found(版本约束被识别为重定向)
A:shell 里直接写 >= 被解释为重定向。解决:

uv sync
# 或
uv pip install -r requirements.txt

终端命令清单

环境与依赖

uv init              # 初始化当前目录为 uv 项目
uv sync             # 根据 pyproject.toml 同步依赖
uv sync
# 或
uv pip install -r requirements.txt  # 新增依赖
uv pip install -r requirements.txt  # 按 requirements.txt 安装

运行脚本

uv run python 01_verify_env.py      # 验证环境
uv run python 04_ai_generate_ppt.py  # 生成 PPT

切换 Prompt 风格运行

PPT_PROMPT_STYLE=default uv run python 04_ai_generate_ppt.py      # 默认风格
PPT_PROMPT_STYLE=strict_json uv run python 04_ai_generate_ppt.py  # 严格JSON
PPT_PROMPT_STYLE=executive uv run python 04_ai_generate_ppt.py     # 商业汇报
PPT_PROMPT_STYLE=workshop uv run python 04_ai_generate_ppt.py      # 培训讲解

打开生成文件

open output/Langchain生态_default.pptx

下一步预告

本篇实现了单链 PPT 生成器——输入主题,输出文件。

但这只是开始。进阶篇我们会做这些事情:

  • 多风格 Prompt(商业汇报、培训讲解、严格 JSON 等)
  • 多 Agent 并行研究(多个角度同时搜集资料)
  • 对话式 Memory(用户说"第3页重写",AI 记住上下文)
  • Callback 进度推送(生成过程中实时显示进度)
  • 三层容错体系(Timeout / Retry / Fallback)

敬请期待。

REF: 本篇对应前 20 个 Demo 中的 D01 LCEL管道语法 + D04 OutputParser