Qwen/QwQ-32B 基础模型上构建agent实现ppt自动生成

news2025/3/12 17:58:11

关心Qwen/QwQ-32B 性能测试结果可以参考下

https://zhuanlan.zhihu.com/p/28600079208https://zhuanlan.zhihu.com/p/28600079208

官方宣传上是该模型性能比肩满血版 DeepSeek-R1(671B)!

我们实现一个 使用Qwen/QwQ-32B 自动生成 PowerPoint 演示文稿的需求,基于 Qwen/QwQ-32B 的自动化 PPT 生成 Agent,带有一个简单的用户界面。以下是一个使用 Python、Gradio(用于界面)和 python-pptx(用于生成 PPT)的实现方案,先利用提示词工程实现一个简单的ppt生成

  • 前提条件

  1. 你已经下载了 Qwen/QwQ-32B 权重到 ./qwq_32b 目录。
  2. 确保有足够的 GPU 内存(建议至少 24GB VRAM)来加载 32B 模型。
  • 系统提示

    • 设计一个系统提示,指导模型如何生成内容。该提示应包含结构化的内容格式,例如:
      • 第一张幻灯片为标题幻灯片(包含标题和副标题)。
      • 后续幻灯片为内容幻灯片(包含标题和要点)。
  • 内容生成流程

  • 消息构建

    • 将系统提示与用户提示结合,形成完整的输入消息列表。
  • 文本生成

    • 使用分词器将消息转换为模型输入格式,然后调用模型生成文本。
    • 设置生成参数(如最大新令牌数、温度等)来控制生成内容的质量和多样性。

PPT内容处理

  • 解析生成的内容

    • 将模型生成的文本分割为不同的幻灯片,识别标题幻灯片和内容幻灯片。
  • 创建PPT文件

    • 使用 python-pptx 库创建 PowerPoint 演示文稿,根据解析的内容添加幻灯片。
  • 保存PPT文件
  • 将生成的PPT文件保存到指定的位置,方便用户下载和使用。
def generate_ppt_content(topic, slide_count=3):
    system_prompt = (
        "You are Qwen, developed by Alibaba. You are tasked with creating content for a PowerPoint presentation. "
        "Generate a structured response with a title slide and subsequent slides based on the user's topic. "
        f"Provide content for {slide_count} slides in the following format:\n"
        "Slide 1: Title Slide (Title, Subtitle)\n"
        f"Slide 2 to {slide_count}: Content Slide (Slide Title, Bullet Points)\n"
        "Keep each slide concise and professional."
    )

    user_prompt = f"Generate a PPT about '{topic}'."
    messages = [
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": user_prompt}
    ]

    text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
    model_inputs = tokenizer([text], return_tensors="pt").to("cuda")  # 输入放到 GPU
    generated_ids = model.generate(
        model_inputs.input_ids,
        max_new_tokens=512,
        temperature=0.7,
        repetition_penalty=1.2
    )
    generated_ids = [output_ids[len(input_ids):] for input_ids, output_ids in
                     zip(model_inputs.input_ids, generated_ids)]
    response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
    return response

处理流程概述:

  • 定义了一个结构化的提示,用于指示模型(Qwen)预期的输出格式。它具体说明了输出的格式要求,包括标题幻灯片和内容幻灯片。
  • 这将系统提示与请求生成指定主题的演示文稿结合在一起。
  • 将提示进行标记化,意味着将文本转换为模型可以理解的格式。这涉及将文本转换为数字表示(标记)。
  • 将标记化的输入准备好,移动到GPU以加快处理速度。
  • 模型根据输入提示生成响应。参数max_new_tokens、temperature和repetition_penalty决定生成的
  • max_new_tokens:模型可以一次生成的最大标记数(这里设置为512)。
  • temperature:控制输出的随机性。较低的值使输出更确定,而较高的值增加创造性。
  • repetition_penalty:抑制模型重复短语或想法,促进内容的多样性。

将生成的标记ID解码回人类可读的文本格式,排除模型使用的任何特殊标记。

初步运行下报错了

torch.cuda.OutOfMemoryError: CUDA out of memory. Tried to allocate 270.00 MiB. GPU 0 has a total capacity of 23.53 GiB of which 158.56 MiB is free. Including non-PyTorch memory, this process has 23.36 GiB memory in use. Of the allocated memory 22.99 GiB is allocated by PyTorch, and 1.24 MiB is reserved by PyTorch but unallocated. If reserved but unallocated memory is large try setting PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True to avoid fragmentation. See documentation for Memory Management (https://pytorch.org/docs/stable/notes/cuda.html#environment-variables)

机器有两张 NVIDIA 4090 显卡,每张显存 24GB,但当前模型加载时超出了单张 GPU 的显存容量(23.53GiB 已几乎用尽)。由于 Qwen/QwQ-32B 是一个非常大的模型(未经量化可能需要 60GB+ 显存),单张 24GB 显卡无法完整加载,因此需要利用多卡并行加载模型。

以下是实现多卡运行的解决方案,结合你的硬件(2 张 4090,48GB 总显存):

首先确认你的环境支持多卡:

import torch
print("CUDA available:", torch.cuda.is_available())
print("Device count:", torch.cuda.device_count())
for i in range(torch.cuda.device_count()):
    print(f"GPU {i}: {torch.cuda.get_device_name(i)}, {torch.cuda.get_device_properties(i).total_memory / 1024**3:.2f} GB")

使用 accelerate 的多卡支持

transformers 和 accelerate 提供了内置的多卡支持,通过 device_map="auto" 自动将模型分层分配到多个 GPU 上。

# 1. 加载模型和分词器
model_path = "./qwq_32b"
tokenizer = AutoTokenizer.from_pretrained(model_path)

# 使用 accelerate 的多卡加载
model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype=torch.float16,  # 使用 FP16 减少显存占用
    device_map="auto",         # 自动分配到多张 GPU
    low_cpu_mem_usage=True     # 优化内存使用
)
print("Model loaded successfully across multiple GPUs!")

优化显存使用

如果仍然遇到显存不足,可以进一步优化:

1. 使用 4-bit 量化

安装 bitsandbytes:

pip install bitsandbytes

修改模型加载部分:

model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype=torch.float16,
    device_map="auto",
    load_in_4bit=True,              # 4-bit 量化
    bnb_4bit_compute_dtype=torch.float16,
    bnb_4bit_use_double_quant=True  # 双重量化
)
  • 显存需求降至约 20-24GB,两张 4090 完全够用。
  • 可能略微影响生成质量,但对 PPT 内容生成影响不大。
设置环境变量

错误信息提到 PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True,可以尝试设置以优化内存分配:

export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True

或者代码上添加
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True"

修改后代码

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
import gradio as gr
from pptx import Presentation
import os

# 1. 加载模型和分词器
model_path = "./base_model/qwq_32b"
tokenizer = AutoTokenizer.from_pretrained(model_path)

# 使用 accelerate 的多卡加载
model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype=torch.float16,
    device_map="auto",
    load_in_4bit=True,              # 启用 4-bit 量化
    bnb_4bit_compute_dtype=torch.float16,  # 计算用 FP16
    bnb_4bit_use_double_quant=True  # 双重量化,进一步节省显存
)
print("Model loaded successfully across multiple GPUs!")


# 2. 生成 PPT 内容的函数
def generate_ppt_content(topic, slide_count=3):
    system_prompt = (
        "You are Qwen, developed by Alibaba. You are tasked with creating content for a PowerPoint presentation. "
        "Generate a structured response with a title slide and subsequent slides based on the user's topic. "
        f"Provide content for {slide_count} slides in the following format:\n"
        "Slide 1: Title Slide (Title, Subtitle)\n"
        f"Slide 2 to {slide_count}: Content Slide (Slide Title, Bullet Points)\n"
        "Keep each slide concise and professional."
    )

    user_prompt = f"Generate a PPT about '{topic}'."
    messages = [
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": user_prompt}
    ]

    text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
    model_inputs = tokenizer([text], return_tensors="pt").to("cuda")  # 输入放到 GPU
    generated_ids = model.generate(
        model_inputs.input_ids,
        max_new_tokens=512,
        temperature=0.7,
        repetition_penalty=1.2
    )
    generated_ids = [output_ids[len(input_ids):] for input_ids, output_ids in
                     zip(model_inputs.input_ids, generated_ids)]
    response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
    return response


# 3. 创建 PPT 文件
def create_ppt(topic, content):
    prs = Presentation()
    slides = content.split("Slide")[1:]

    for slide_text in slides:
        slide_lines = slide_text.strip().split("\n")
        if not slide_lines:
            continue
        if "1:" in slide_text:
            slide_layout = prs.slide_layouts[0]
            slide = prs.slides.add_slide(slide_layout)
            title, subtitle = slide.shapes.title, slide.placeholders[1]
            title.text = slide_lines[0].replace("1: Title Slide", "").strip()
            subtitle.text = slide_lines[1].strip() if len(slide_lines) > 1 else " "
        else:
            slide_layout = prs.slide_layouts[1]
            slide = prs.slides.add_slide(slide_layout)
            title, body = slide.shapes.title, slide.placeholders[1]
            title.text = slide_lines[0].strip()
            tf = body.text_frame
            tf.text = "\n".join(line.strip() for line in slide_lines[1:] if line.strip())

    output_file = f"{topic.replace(' ', '_')}_presentation.pptx"
    prs.save(output_file)
    return output_file


# 4. 主函数
def ppt_agent(topic):
    content = generate_ppt_content(topic)
    output_file = create_ppt(topic, content)
    return content, output_file


# 5. Gradio 界面
with gr.Blocks(title="PPT 生成 Agent") as demo:
    gr.Markdown("# 自动化 PPT 生成器")
    gr.Markdown("输入主题,生成 PPT 文件。基于 Qwen/QwQ-32B,多卡运行。")
    topic_input = gr.Textbox(label="PPT 主题", placeholder="例如:人工智能简介")
    output_text = gr.Textbox(label="生成的内容", lines=10, interactive=False)
    output_file = gr.File(label="下载 PPT 文件")
    submit_btn = gr.Button("生成 PPT")
    submit_btn.click(fn=ppt_agent, inputs=topic_input, outputs=[output_text, output_file])

demo.launch(server_name="0.0.0.0", server_port=7860)

运行界面如下

点击“生成PPT” 

但是ppt质量有点堪忧

生成的 PPT 内容确实存在以下问题:

  1. 内容质量低:生成的文本包含不自然的表达(如 "I don’t have the prime data regarding from common knowledge up until now"),语法错误较多,逻辑也不够清晰。
  2. 格式问题:内容没有很好地适配 PPT 的结构,段落过长,缺乏简洁的要点化表达。
  3. 语言混杂:中英文混杂(如标题是中文,内容是英文),缺乏统一性。

为了提升 PPT 的质量,引入多个智能体的协作模式,利用联网功能获取更高质量的内容,并优化 PPT 的结构和格式。改进方案:

多智能体协作生成高质量 PPT

智能体角色分工
  1. 内容生成智能体:基于 QwQ-32B 模型,负责生成 PPT 的初步内容(已实现)。
  2. 内容优化智能体:联网搜索最新信息,修正生成内容中的错误,优化语言表达。
  3. 格式设计智能体:优化 PPT 结构,确保内容简洁、要点清晰,并适配 PPT 格式。
  4. 视觉美化智能体:提供 PPT 排版建议,优化字体、颜色、布局等(目前无法直接生成图片,但可以提供设计建议)。
改进步骤
  1. 优化内容生成:调整提示词,提升 QwQ-32B 的输出质量。
  2. 联网搜索补充:搜索与主题相关的最新信息,修正模型生成的内容。
  3. 结构化输出:将内容转为简洁的要点形式,适配 PPT。

修改代码

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
import gradio as gr
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import PP_ALIGN
from pptx.dml.color import RGBColor
from pptx.oxml.xmlchemy import OxmlElement
import os
import requests
from bs4 import BeautifulSoup
import time

# 清理显存
torch.cuda.empty_cache()
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True"

# 1. 加载模型和分词器
model_path = "./base_model/qwq_32b"
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype=torch.float16,
    device_map="auto",
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.float16,
    bnb_4bit_use_double_quant=True
)
print("Model loaded successfully!")


# 2. 联网搜索(使用百度,优化解析逻辑)
def search_web(query, retries=3):
    for attempt in range(retries):
        try:
            url = f"https://www.baidu.com/s?wd={requests.utils.quote(query)}"
            headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
            }
            response = requests.get(url, headers=headers, timeout=10)
            response.raise_for_status()
            soup = BeautifulSoup(response.text, "html.parser")
            snippets = []
            # 调整选择器,适配百度搜索结果
            for result in soup.select(".result.c-container"):
                title = result.select_one("h3 a")
                summary = result.select_one(".c-abstract") or result.select_one(".c-span-last")
                if title and summary:
                    snippets.append(f"{title.get_text()}: {summary.get_text()}")
                elif title:
                    snippets.append(title.get_text())
            if snippets:
                print("Search results:", snippets)  # 调试输出
                return "\n".join(snippets[:3])
            else:
                return "未找到相关搜索结果"
        except Exception as e:
            print(f"Search attempt {attempt + 1} failed: {str(e)}")
            if attempt == retries - 1:
                return "搜索失败,请检查网络连接或稍后再试"
            time.sleep(2)  # 重试前等待 2 秒


# 3. 生成 PPT 内容
def generate_ppt_content(topic, slide_count=3):
    system_prompt = (
        "你是一个专业的 PPT 内容生成助手,语言为中文。你的任务是根据用户提供的主题,生成一份结构化的 PPT 内容。要求:"
        f"1. 生成 {slide_count} 页幻灯片:\n"
        "   - Slide 1: 标题页(标题,副标题)\n"
        f"   - Slide 2 到 {slide_count}: 内容页(页标题,3-5 个简洁的要点)\n"
        "2. 语言简洁、专业,适合 PPT 展示,避免长句。\n"
        "3. 确保内容逻辑清晰,信息准确,基于小米汽车的最新信息(如 2025 年目标交付 30 万台,SU7 和 YU7 系列,智能化布局等)。\n"
        "4. 不要包含不准确的信息(如错误的自动驾驶级别,当前小米汽车未达到 L4)。"
    )

    user_prompt = f"生成一份关于 '{topic}' 的 PPT,重点介绍产品亮点和市场战略。"
    messages = [{"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}]

    text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
    model_inputs = tokenizer([text], return_tensors="pt").to("cuda")
    generated_ids = model.generate(
        model_inputs.input_ids,
        max_new_tokens=256,
        temperature=0.7,
        repetition_penalty=1.2,
        pad_token_id=tokenizer.eos_token_id
    )
    generated_ids = [output_ids[len(input_ids):] for input_ids, output_ids in
                     zip(model_inputs.input_ids, generated_ids)]
    response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

    # 联网搜索补充信息
    search_result = search_web(f"{topic} 2025")
    return response + "\n\n补充信息(来自百度):\n" + search_result


# 4. 创建 PPT 文件(优化美观度)
def create_ppt(topic, content):
    prs = Presentation()
    print("Generated content:\n", content)
    slides = content.split("Slide")[1:]
    
    for slide_index, slide_text in enumerate(slides):
        slide_lines = slide_text.strip().split("\n")
        if not slide_lines:
            continue

        # 设置背景渐变(浅灰色到白色)
        slide_layout = prs.slide_layouts[0 if "1:" in slide_text else 1]
        slide = prs.slides.add_slide(slide_layout)
        background = slide.background
        fill = background.fill
        fill.gradient()
        fill.gradient_stops[0].color.rgb = RGBColor(240, 240, 240)
        fill.gradient_stops[1].color.rgb = RGBColor(255, 255, 255)

        # 添加占位符图片框(右侧)
        left = Inches(6)
        top = Inches(1.5)
        width = Inches(3)
        height = Inches(3)
        slide.shapes.add_picture_placeholder(left=left, top=top, width=width, height=height)

        if "1:" in slide_text:
            # 标题页
            title, subtitle = slide.shapes.title, slide.placeholders[1]
            title.text = slide_lines[0].replace("1: Title Slide", "").strip()
            subtitle.text = slide_lines[1].strip() if len(slide_lines) > 1 else " "

            # 美化标题页(使用小米品牌色:橙色)
            title.text_frame.paragraphs[0].font.size = Pt(44)
            title.text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 103, 0)  # 小米橙色
            title.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
            subtitle.text_frame.paragraphs[0].font.size = Pt(24)
            subtitle.text_frame.paragraphs[0].font.color.rgb = RGBColor(89, 89, 89)
            subtitle.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
        else:
            # 内容页
            title, body = slide.shapes.title, slide.placeholders[1]
            title.text = slide_lines[0].strip()

            # 格式化内容为要点
            tf = body.text_frame
            tf.clear()
            for line in slide_lines[1:]:
                if line.strip():
                    p = tf.add_paragraph()
                    p.text = line.strip()
                    p.level = 0 if not line.startswith("-") else 1
                    p.font.size = Pt(20)
                    p.font.color.rgb = RGBColor(0, 0, 0)
                    p.alignment = PP_ALIGN.LEFT

            # 美化内容页
            title.text_frame.paragraphs[0].font.size = Pt(32)
            title.text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 103, 0)  # 小米橙色

        # 在最后一页添加补充信息
        if slide_index == len(slides) - 1 and "补充信息(来自百度)" in content:
            search_content = content.split("补充信息(来自百度):\n")[-1].strip()
            if search_content and search_content != "未找到相关搜索结果":
                left = Inches(0.5)
                top = Inches(5.5)
                width = Inches(9)
                height = Inches(1.5)
                textbox = slide.shapes.add_textbox(left, top, width, height)
                tf = textbox.text_frame
                tf.text = "补充信息(来自百度):\n" + search_content
                for p in tf.paragraphs:
                    p.font.size = Pt(14)
                    p.font.color.rgb = RGBColor(100, 100, 100)
                    p.alignment = PP_ALIGN.LEFT

    output_file = f"{topic.replace(' ', '_')}_presentation.pptx"
    prs.save(output_file)
    return output_file


# 5. 主函数
def ppt_agent(topic):
    content = generate_ppt_content(topic)
    output_file = create_ppt(topic, content)
    return content, output_file


# 6. Gradio 界面
with gr.Blocks(title="PPT 生成 Agent") as demo:
    gr.Markdown("# 自动化 PPT 生成器")
    gr.Markdown("输入主题,生成高质量 PPT 文件。基于 Qwen/QwQ-32B 和百度联网优化。")
    topic_input = gr.Textbox(label="PPT 主题", placeholder="例如:小米汽车最新发布")
    output_text = gr.Textbox(label="生成的内容", lines=10, interactive=False)
    output_file = gr.File(label="下载 PPT 文件")
    submit_btn = gr.Button("生成 PPT")
    submit_btn.click(fn=ppt_agent, inputs=topic_input, outputs=[output_text, output_file])

demo.launch(server_name="0.0.0.0", server_port=7860)

我们再尝使用添加些样式来丰富下ppt排班

修改代码

def create_ppt(topic, content):
    prs = Presentation()
    print("Generated content:\n", content)
    slides = content.split("Slide")[1:]

    for slide_index, slide_text in enumerate(slides):
        slide_lines = slide_text.strip().split("\n")
        if not slide_lines:
            continue

        # 设置背景渐变(浅灰色到白色)
        slide_layout = prs.slide_layouts[0 if "1:" in slide_text else 1]
        slide = prs.slides.add_slide(slide_layout)
        background = slide.background
        fill = background.fill
        fill.gradient()
        fill.gradient_stops[0].color.rgb = RGBColor(240, 240, 240)
        fill.gradient_stops[1].color.rgb = RGBColor(255, 255, 255)

        # 添加矩形框作为图片占位符
        left = Inches(6)
        top = Inches(1.5)
        width = Inches(3)
        height = Inches(3)
        shape = slide.shapes.add_shape(1, left, top, width, height)  # 1 表示矩形
        shape.fill.solid()
        shape.fill.fore_color.rgb = RGBColor(220, 220, 220)
        shape.line.dash_style = MSO_LINE_DASH_STYLE.DASH  # 使用正确的虚线样式
        shape.line.color.rgb = RGBColor(150, 150, 150)
        txBox = shape.text_frame
        txBox.text = "图片占位符\n(请手动插入图片)"
        p = txBox.paragraphs[0]
        p.font.size = Pt(12)
        p.font.color.rgb = RGBColor(100, 100, 100)
        p.alignment = PP_ALIGN.CENTER

        if "1:" in slide_text:
            # 标题页
            title, subtitle = slide.shapes.title, slide.placeholders[1]
            title.text = slide_lines[0].replace("1: Title Slide", "").strip()
            subtitle.text = slide_lines[1].strip() if len(slide_lines) > 1 else " "

            # 美化标题页(使用小米品牌色:橙色)
            title.text_frame.paragraphs[0].font.size = Pt(44)
            title.text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 103, 0)
            title.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
            subtitle.text_frame.paragraphs[0].font.size = Pt(24)
            subtitle.text_frame.paragraphs[0].font.color.rgb = RGBColor(89, 89, 89)
            subtitle.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
        else:
            # 内容页
            title, body = slide.shapes.title, slide.placeholders[1]
            title.text = slide_lines[0].strip()

            # 格式化内容为要点
            tf = body.text_frame
            tf.clear()
            for line in slide_lines[1:]:
                if line.strip():
                    p = tf.add_paragraph()
                    p.text = line.strip()
                    p.level = 0 if not line.startswith("-") else 1
                    p.font.size = Pt(20)
                    p.font.color.rgb = RGBColor(0, 0, 0)
                    p.alignment = PP_ALIGN.LEFT

            # 美化内容页
            title.text_frame.paragraphs[0].font.size = Pt(32)
            title.text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 103, 0)

        # 在最后一页添加补充信息和分割线
        if slide_index == len(slides) - 1 and "补充信息(来自百度)" in content:
            # 添加分割线
            left = Inches(0.5)
            top = Inches(5.3)
            width = Inches(9)
            height = Inches(0.01)
            line = slide.shapes.add_shape(1, left, top, width, height)
            line.fill.solid()
            line.fill.fore_color.rgb = RGBColor(200, 200, 200)
            line.line.color.rgb = RGBColor(200, 200, 200)

            # 添加补充信息
            search_content = content.split("补充信息(来自百度):\n")[-1].strip()
            if search_content and search_content != "未找到相关搜索结果":
                left = Inches(0.5)
                top = Inches(5.5)
                width = Inches(9)
                height = Inches(1.5)
                textbox = slide.shapes.add_textbox(left, top, width, height)
                tf = textbox.text_frame
                tf.text = "补充信息(来自百度):\n" + search_content
                for p in tf.paragraphs:
                    p.font.size = Pt(14)
                    p.font.color.rgb = RGBColor(100, 100, 100)
                    p.alignment = PP_ALIGN.LEFT

    output_file = f"{topic.replace(' ', '_')}_presentation.pptx"
    prs.save(output_file)
    return output_file

再次运行,控制台和新ppt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2313873.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PostgreSQL17(最新版)安装部署

PostgreSQL 17已与2024年9月26日正式发布!!! 一、Postgres概述 官网地址:PostgreSQL: The world’s most advanced open source database Postgres作为最先进的开源数据库( the latest version of the world’s most…

【AI大模型智能应用】Deepseek生成测试用例

在软件开发过程中,测试用例的设计和编写是确保软件质量的关键。 然而,软件系统的复杂性不断增加,手动编写测试用例的工作量变得异常庞大,且容易出错。 DeepSeek基于人工智能和机器学习,它能够依据软件的需求和设计文…

【高级篇】大疆Pocket 3加ENC编码器实现无线RTMP转HDMI进导播台

【高级篇】大疆Pocket 3加ENC编码器实现无线RTMP转HDMI进导播台 文章目录 准备工作连接设备RTMP概念ENCSHV2推流地址设置大疆Pocket 3直播设置总结 老铁们好! 很久没写软文了,今天给大家带了一个干货,如上图,大疆Pocket 3加ENC编…

机器人交互系统 部署构建

环境要求 Ubuntu 20.04 或更高版本ROS Noetic 或兼容版本Python 3.8 安装步骤 1. 安装ROS环境(如未安装) sudo apt update sudo apt install ros-noetic-desktop-full source /opt/ros/noetic/setup.bash2. 创建工作空间并克隆代码 mkdir -p ~/code…

创建模式-工厂方法模式(Factory Method Pattern)

江城子乙卯正月二十日夜记梦 目的动机简单工厂示例代码 目的 定义一个创建对象的接口,该接口的子类具体负责创建具体的对象。工厂方法模式将对象的实例化延迟到子类。简单工厂是直接在创建方法中负责所有的产品的生成,造成该方法臃肿,并且当…

【eNSP实战】交换机配置端口隔离

交换机端口隔离可以实现在同一个VLAN内对端口进行逻辑隔离,端口隔离分为L2层隔离和L3层隔离,这里只进行L2层隔离演示。 拓扑图 路由器AR1配置GE 0/0/1配置IP,其余PC主机各自配置IP和网关。 现将PC1到PC4四个主机全部进行L2层隔离&#xff0c…

人脸识别之数据集中 PI20 和 CFMT 之间关联的模型预测贝叶斯(Python+论文代码实现)

代码文件(联系作者点击这里末尾) 代码文件描述如下: subjective_objective.ipynb和:这分别是实际的笔记本和 Web 浏览器友好的只读版本。此笔记本读取数据,执行一些预处理,并包含论文中使用的模型规范。它…

静态时序分析:无法满足的生成时钟(TIM-255警告、UITE-461或PTE-075错误)

相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 在阅读本文前,强烈建议首先阅读介绍生成时钟的文章,尤其是其中关于时钟极性和反相的相关内容。 静态时序分析:SDC约束命令cr…

VSTO(C#)Excel开发2:Excel对象模型和基本操作

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…

途游游戏25届AI算法岗内推

熟悉常用的编程语言,如Python、R等,具有良好的编码和调试能力;对常用的机器学习算法和深度学习框架(如TensorFlow、PyTorch等)有深入理解,对大型语言模型有一定了解,具备模型部署和微调的实践经…

【数据分析大屏】基于Django+Vue汽车销售数据分析可视化大屏(完整系统源码+数据库+开发笔记+详细部署教程+虚拟机分布式启动教程)✅

目录 一、项目背景 二、项目创新点 三、项目功能 四、开发技术介绍 五、项目功能展示 六、权威视频链接 一、项目背景 汽车行业数字化转型加速,销售数据多维分析需求激增。本项目针对传统报表系统交互性弱、实时性差等痛点,基于DjangoVue架构构建…

OpenCV应用:三种图像风格化案例

OpenCV 本身主要用于计算机视觉任务,例如图像处理、边缘检测、物体识别等,虽然它并不直接提供像 Photoshop 或其他艺术设计软件那样的 "风格化" 功能,但你可以通过一些图像处理技术在 OpenCV 中实现不同风格化效果。 1. 卡通化效果…

【Axure资料】110套优质可视化大屏模板+图表组件+科技感元件等

本作品集包含110套高保真可视化大屏模板,以及丰富的图表组件和科技感元件,旨在满足各行业对数据可视化展示的需求。所有模板和组件均基于Axure RP 9软件设计,确保高质量的交互体验和视觉效果。 作品类型:Axure原型模板 兼容版本&…

VanillaVueSvelteReactSolidAngularPreact前端框架/库的简要介绍及其优势

VanillaVueSvelteReactSolidAngularPreact前端框架/库的简要介绍及其优势。以下是这些前端框架/库的简要介绍及其优势: 1. Vanilla 定义:Vanilla 并不是一个框架,而是指 原生 JavaScript(即不使用任何框架或库)。优势…

Oracle 字符类型对比

本文以 Oracle12c 为例 1.主要区别对比 类型存储方式最大长度字符集支持适用场景备注​CHAR(M)固定长度空格填充2000 字节,M 代表字节长度默认字符集固定长度编码实际存储长度固定为定义长度(如 CHAR(10) 始终占 10 字节)​VARCHAR2(M)可变长…

阿里云操作系统控制台实战评测:提升云资源管理与监控效率

文章目录 前言产品介绍操作系统控制台体验阿里云操作系统开通 帮助与总结建议 前言 随着云计算和虚拟化技术的发展,操作系统控制台作为运维管理的核心工具之一,在现代IT环境中发挥着越来越重要的作用。它提供了一种更加直观、高效的方式来管理操作系统&…

Linux本地部署deepseek及SpringBoot集成deepseek

一、ollama安装 本文以linux安装为例(服务器主机ip:192.168.109.210) 1、自动安装(方式一) curl -fsSL https://ollama.com/install.sh | sh 2、手动安装(方式二) (1)下载二进制文件 curl -L https://ollama.com/download/ollama-linux-amd64.tgz -o ollama-linu…

用物理信息神经网络(PINN)解决实际优化问题:全面解析与实践

摘要 本文系统介绍了物理信息神经网络(PINN)在解决实际优化问题中的创新应用。通过将物理定律与神经网络深度融合,PINN在摆的倒立控制、最短时间路径规划及航天器借力飞行轨道设计等复杂任务中展现出显著优势。实验表明,PINN相比…

RabbitMQ之旅(1)

相信自己,终会成功 目录 主流MQ产品 1.kafaka 2.RocketMQ 3.RabbitMQ 在xshell上安装RabbitMQ RabbitMQ七种工作模式 1.简单模式 ​编辑 2.工作队列模式 3.发布/订阅模式 4.路由模式 5.通配符模式 6.RPC模式 AMQP.BasicProperties 设置消息属性的类 7.发布确认模…

HTML-网页介绍

一、网页 1.什么是网页: 网站是指在因特网上根据一定的规则,使用 HTML 等制作的用于展示特定内容相关的网页集合。 网页是网站中的一“页”,通常是 HTML 格式的文件,它要通过浏览器来阅读。 网页是构成网站的基本元素&#xf…