本地用pptx和大模型生产PPT课件

先在智谱提问,让它给出PPT大纲。

以下是为您规划的西门子 WinCC 7.4 脚本编程基础 PPT 大纲,共 20 页。内容精简,重点突出,适合制作教程型 PPT。每页包含标题和核心内容要点。

第 1 页:封面

标题:西门子 WinCC 7.4 脚本编程基础

副标题:从入门到实战的 20 页教程

演讲人:您的名字

日期:202X 年 X 月 X 日

配图:WinCC 7.4 图标或 SCADA 系统界面截图

第 2 页:课程目标与适用对象

适用对象:

WinCC 工程师、自动化调试人员

有 PLC 基础但需提升 HMI 交互能力的技术人员

学习目标:

掌握 WinCC 7.4 脚本环境

熟悉基本语法与数据操作

能够编写常用逻辑控制脚本

了解调试与错误处理

课程时长:建议 45 分钟讲解 + 15 分钟练习

第 3 页:WinCC 7.4 脚本引擎概述

核心语言:基于 VBScript 的扩展语法

然后让它给写出python源代码

以下代码当前时间是调试成功的:

requirements.txt

powershell 复制代码
在这里插入代码片annotated-types==0.7.0
anyio==4.13.0
certifi==2026.5.20
colorama==0.4.6
distro==1.9.0
forge-guardrails==0.7.2
h11==0.16.0
httpcore==1.0.9
httpx==0.28.1
idna==3.17
jiter==0.15.0
lxml==6.1.1
openai==2.38.0
pillow==12.2.0
pydantic==2.13.4
pydantic_core==2.46.4
python-pptx==1.0.2
PyYAML==6.0.3
sniffio==1.3.1
tqdm==4.67.3
typing-inspection==0.4.2
typing_extensions==4.15.0
xlsxwriter==3.2.9

config.yaml

python 复制代码
# LLM 后端配置 (直连 llama-server)
llm:
  base_url: "https://example.com/v1"
  api_key: "api-key"
  model_name: "glm-5"
  temperature: 0.7
  max_tokens: 16000 # 确保足够长,防止大纲较长时截断

# 大纲文件路径
outline_file: "content.txt"

# PPT 渲染配置
ppt_settings:
  output_dir: "./output"
  slide_width: 13.333
  slide_height: 7.5
  font_name: "微软雅黑"
  title_font_size: 36
  body_font_size: 20
  paragraph_spacing: 10
  

可以用阿里、智谱等的免费额度,也可以用本地llama.cpp,本地测试Phi-4-mini-reasoning-Q5_K_M.gguf会失败,总是输出报错。

main.py

python 复制代码
import os
import re
import yaml
import json
from pydantic import BaseModel, Field, ValidationError
from typing import List
from openai import OpenAI
from lxml import etree

from pptx import Presentation
from pptx.util import Pt, Inches
from pptx.enum.text import PP_ALIGN
from pptx.oxml.ns import qn

# ================= 加载配置 =================
def load_config(config_path="config.yaml"):
    if not os.path.exists(config_path):
        raise FileNotFoundError(f"配置文件 {config_path} 不存在!")
    with open(config_path, 'r', encoding='utf-8') as f:
        return yaml.safe_load(f)

CONFIG = load_config()
# ==========================================

# ================= 定义 Pydantic 模型 =================
# 用于验证 LLM 输出的 JSON 结构是否符合预期
class SlideContent(BaseModel):
    title: str = Field(description="当前幻灯片的标题")
    points: List[str] = Field(description="当前幻灯片的要点列表,每个要点不超过30字")

class PPTGenerationParams(BaseModel):
    slides: List[SlideContent] = Field(description="包含所有幻灯片内容的列表")
# =====================================================

def read_outline(file_path: str) -> str:
    """读取大纲文件"""
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"大纲文件 {file_path} 不存在!")
    with open(file_path, 'r', encoding='utf-8') as f:
        return f.read().strip()

def generate_ppt_content(outline_content: str) -> list:
    """调用本地 LLM 生成 PPT 结构化内容,带强容错提取"""
    print(f"🤖 正在让 Qwen 基于大纲生成结构化数据...")
    
    llm_cfg = CONFIG['llm']
    client = OpenAI(base_url=llm_cfg['base_url'], api_key=llm_cfg['api_key'], timeout=300.0)

    system_prompt = """你是一个专业的PPT内容策划师。用户会提供一份现有的PPT大纲。
你的任务是基于这份大纲,输出PPT的结构化数据。
严格要求:
1. 必须完全遵循用户提供的大纲结构和页数,不得自行增删页面。
2. 提取大纲中的核心内容作为 title 和 points。
3. 如果大纲中的要点过于简略,你可以适当润色扩写,但绝不能偏离原意。
4. 【格式要求】你必须且只能输出一个合法的 JSON 数组,不要输出任何解释性文字,绝对不要用 markdown 代码块包裹。
格式示例:
[
  {"title": "第一页标题", "points": ["要点1", "要点2"]},
  {"title": "第二页标题", "points": ["要点1", "要点2"]}
]"""

    user_prompt = f"这是我的PPT大纲:\n---\n{outline_content}\n---\n请基于以上大纲,生成完整的PPT结构化JSON数据。"

    try:
        response = client.chat.completions.create(
            model=llm_cfg['model_name'],
            messages=[
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": user_prompt}
            ],
            temperature=llm_cfg['temperature'],
            max_tokens=llm_cfg['max_tokens']
        )
        raw_content = response.choices[0].message.content.strip()

        # ================= 强容错解析 =================
        # 1. 清洗可能存在的 Markdown 代码块标记
        content = re.sub(r'^```json\s*', '', raw_content)
        content = re.sub(r'^```\s*', '', content)
        content = re.sub(r'\s*```$', '', content)
        
        # 2. 核心:强制截取第一个 '[' 和最后一个 ']' 之间的内容
        # 这样可以无视模型在 JSON 前后输出的任何废话、思维链标记或乱码
        start_idx = content.find('[')
        end_idx = content.rfind(']')
        
        if start_idx != -1 and end_idx != -1 and end_idx > start_idx:
            json_str = content[start_idx:end_idx+1]
        else:
            # 如果连方括号都找不到,说明模型完全没有输出结构,直接报错
            print("❌ 模型输出中未找到合法的 JSON 数组标志 '[' 和 ']'")
            print(f"原始输出:\n{raw_content}")
            return None

        # 3. (新增) 去除 JSON 字符串内部可能混入的控制字符和不可见字符
        # 防止类似 \u200b (零宽空格) 等字符藏在 JSON 键名里导致解析失败
        json_str = re.sub(r'[\x00-\x1f\x7f-\x9f]', '', json_str)

        # 3. 解析 JSON
        data_list = json.loads(json_str)

        # 4. 使用 Pydantic 进行结构校验
        validated_data = PPTGenerationParams(slides=data_list)
        print("✅ 内容生成并校验成功!")
        return [slide.model_dump() for slide in validated_data.slides]

    except json.JSONDecodeError as e:
        print(f"❌ JSON 解析失败,模型可能输出了非法格式: {e}")
        print(f"原始输出:\n{raw_content}")
        return None
    except ValidationError as e:
        print(f"❌ 数据结构校验失败,模型输出的字段不符合要求: {e}")
        return None
    except Exception as e:
        print(f"❌ 调用 LLM 失败: {e}")
        return None

def set_chinese_font(run, font_name, font_size):
    """为文本块设置中文字体 (使用 lxml 原生操作,适配所有 python-pptx 版本)"""
    run.font.name = font_name
    run.font.size = font_size
    
    # 获取底层 rPr (文本属性) 节点
    rPr = run._r.get_or_add_rPr()
    
    # 尝试查找是否已存在东亚字体节点 <a:ea>
    ea = rPr.find(qn('a:ea'))
    
    if ea is None:
        # 如果不存在,使用 lxml 原生方法直接创建子节点
        ea = etree.SubElement(rPr, qn('a:ea'))
    
    # 设置 typeface 属性为指定的中文字体
    ea.set('typeface', font_name)

def create_ppt_file(slides_data: list, filename: str):
    """将 JSON 数据渲染为 PPT 文件"""
    print(f"🎨 正在渲染 PPT 文件...")
    ppt_cfg = CONFIG['ppt_settings']
    font_name = ppt_cfg['font_name']
    title_size = Pt(ppt_cfg['title_font_size'])
    body_size = Pt(ppt_cfg['body_font_size'])
    spacing = Pt(ppt_cfg['paragraph_spacing'])

    prs = Presentation()
    prs.slide_width = Inches(ppt_cfg['slide_width'])
    prs.slide_height = Inches(ppt_cfg['slide_height'])

    for slide_info in slides_data:
        title = slide_info.get("title", "无标题")
        points = slide_info.get("points", [])

        # 使用"标题和内容"布局
        slide_layout = prs.slide_layouts[1]
        slide = prs.slides.add_slide(slide_layout)

        # 渲染标题
        title_shape = slide.shapes.title
        title_shape.text = ""
        p = title_shape.text_frame.paragraphs[0]
        p.alignment = PP_ALIGN.LEFT
        run = p.add_run()
        run.text = title
        set_chinese_font(run, font_name, title_size)

        # 渲染正文
        body_shape = slide.shapes.placeholders[1]
        tf = body_shape.text_frame
        tf.clear()

        for i, point in enumerate(points):
            if i == 0:
                p = tf.paragraphs[0]
            else:
                p = tf.add_paragraph()
            
            p.space_before = spacing
            p.space_after = spacing
            p.level = 0
            
            run = p.add_run()
            run.text = point
            set_chinese_font(run, font_name, body_size)

    output_dir = ppt_cfg['output_dir']
    os.makedirs(output_dir, exist_ok=True)
    filepath = os.path.join(output_dir, filename)
    prs.save(filepath)
    print(f"🎉 PPT 已成功保存至: {os.path.abspath(filepath)}")

if __name__ == "__main__":
    outline_file = CONFIG.get('outline_file', 'content.txt')
    outline_content = read_outline(outline_file)
    print(f"📄 已读取大纲文件,共 {len(outline_content)} 字符。")

    slides = generate_ppt_content(outline_content)
    
    if slides:
        safe_filename = re.sub(r'[\\/:*?"<>|]', '', "output") + ".pptx"
        create_ppt_file(slides, filename=safe_filename)
    else:
        print("生成中断,请检查上方错误信息后重试。")
		

测试时,content.txt里的内容尽量短少,生成PPT成功后再用全部内容,避免浪费。

生成PPT的效果

不咋样,就是糊弄糊弄差事,正儿八经的讲课得润色。

本地纯CPU llama.cpp 9t/s,还是Phi-4-mini 尺寸2.65G。如果本地

相关推荐
codefan※1 小时前
pytorch安装流程
人工智能·pytorch·python
谷哥的小弟2 小时前
大模型核心基础知识(13)—深度学习的发展基础与技术特点
人工智能·深度学习·机器学习·大模型·大语言模型
kaisun642 小时前
国内主流大模型采购清单
大模型·国产
草莓熊Lotso2 小时前
【LangChain】聊天模型实战:结构化输出完全指南(从原理到落地)
数据库·python·langchain·软件工程
lili00122 小时前
AI编程三件套CI集成与质量门禁:从“看起来对“到“证据确凿“
java·人工智能·python·ci/cd·ai编程
原来是猿2 小时前
性能测试(1)
运维·服务器·python·压力测试
追光者♂2 小时前
【测评系列6】CSDN AI数字营销实测体验官——OpenClaw 数据采集工具新手入门指南
人工智能·深度学习·机器学习·ai·大模型·openclaw·前沿科学
谷哥的小弟2 小时前
大模型核心基础知识(12)—机器学习的基本概念与常见方法
人工智能·深度学习·机器学习·大模型·大语言模型
AIFQuant2 小时前
外汇交易平台技术栈深度解析:行情 API、清算、风控、前端一体化方案
前端·python·websocket·金融·restful