File size: 7,112 Bytes
76684fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
babe5ad
76684fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
import gradio as gr
import os

from gradio.data_classes import FileData

from config import Config
from chatbot import ChatBot
from content_formatter import ContentFormatter
from content_assistant import ContentAssistant
from image_advisor import ImageAdvisor
from input_parser import parse_input_text
from ppt_generator import generate_presentation
from template_manager import load_template, get_layout_mapping
from layout_manager import LayoutManager
from logger import LOG
from openai_whisper import asr, transcribe
# from minicpm_v_model import chat_with_image
from docx_parser import generate_markdown_from_docx


# os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_PROJECT"] = "ChatPPT"

# 实例化 Config,加载配置文件
config = Config()
chatbot = ChatBot(config.chatbot_prompt)
content_formatter = ContentFormatter(config.content_formatter_prompt)
content_assistant = ContentAssistant(config.content_assistant_prompt)
image_advisor = ImageAdvisor(config.image_advisor_prompt)

# 加载 PowerPoint 模板,并获取可用布局
ppt_template = load_template(config.ppt_template)

# 初始化 LayoutManager,管理幻灯片布局
layout_manager = LayoutManager(get_layout_mapping(ppt_template))


# 定义生成幻灯片内容的函数
def generate_contents(message, history):
    try:
        # 初始化一个列表,用于收集用户输入的文本和音频转录
        texts = []

        # 获取文本输入,如果存在则添加到列表
        text_input = message.get("text")
        if text_input:
            texts.append(text_input)

        # 获取上传的文件列表,如果存在则处理每个文件
        for uploaded_file in message.get("files", []):
            LOG.debug(f"[上传文件]: {uploaded_file}")
            # 获取文件的扩展名,并转换为小写
            file_ext = os.path.splitext(uploaded_file)[1].lower()
            if file_ext in ('.wav', '.flac', '.mp3'):
                # 使用 OpenAI Whisper 模型进行语音识别
                audio_text = asr(uploaded_file)
                texts.append(audio_text)
            # 解释说明图像文件
            # elif file_ext in ('.jpg', '.png', '.jpeg'):
            #     if text_input:
            #         image_desc = chat_with_image(uploaded_file, text_input)
            #     else:
            #         image_desc = chat_with_image(uploaded_file)
            #     return image_desc
            # 使用 Docx 文件作为素材创建 PowerPoint
            elif file_ext in ('.docx', '.doc'):
                # 调用 generate_markdown_from_docx 函数,获取 markdown 内容
                raw_content = generate_markdown_from_docx(uploaded_file)
                markdown_content = content_formatter.format(raw_content)
                return content_assistant.adjust_single_picture(markdown_content)
            else:
                LOG.debug(f"[格式不支持]: {uploaded_file}")

        # 将所有文本和转录结果合并为一个字符串,作为用户需求
        user_requirement = "需求如下:\n" + "\n".join(texts)
        LOG.info(user_requirement)

        # 与聊天机器人进行对话,生成幻灯片内容
        slides_content = chatbot.chat_with_history(user_requirement)

        return slides_content
    except Exception as e:
        LOG.error(f"[内容生成错误]: {e}")
        # 抛出 Gradio 错误,以便在界面上显示友好的错误信息
        raise gr.Error(f"网络问题,请重试:)")
        

def handle_image_generate(history):
    try:
        # 获取聊天记录中的最新内容
        slides_content = history[-1]["content"]

        content_with_images, image_pair = image_advisor.generate_images(slides_content)
        
        # for k, v in image_pair.items():
        #     history.append(
        #         # {"text": k, "files": FileData(path=v)}
        #         {"role": "user", "files": FileData(path=v)}
        #     )

        new_message = {"role": "assistant", "content": content_with_images}

        history.append(new_message)

        return history
    except Exception as e:
        LOG.error(f"[配图生成错误]: {e}")
        # 提示用户先输入主题内容或上传文件
        raise gr.Error(f"【提示】未找到合适配图,请重试!")

# 定义处理生成按钮点击事件的函数
def handle_generate(history):
    try:
        # 获取聊天记录中的最新内容
        slides_content = history[-1]["content"]
        # 解析输入文本,生成幻灯片数据和演示文稿标题
        powerpoint_data, presentation_title = parse_input_text(slides_content, layout_manager)
        # 定义输出的 PowerPoint 文件路径
        output_pptx = f"outputs/{presentation_title}.pptx"
        
        # 生成 PowerPoint 演示文稿
        generate_presentation(powerpoint_data, config.ppt_template, output_pptx)
        return output_pptx
    except Exception as e:
        LOG.error(f"[PPT 生成错误]: {e}")
        # 提示用户先输入主题内容或上传文件
        raise gr.Error(f"【提示】请先输入你的主题内容或上传文件")

# 创建 Gradio 界面
with gr.Blocks(
    title="ChatPPT",
    css="""
    body { animation: fadeIn 2s; }
    @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
    """
) as demo:

    # 添加标题
    gr.Markdown("## ChatPPT")

    # 定义语音(mic)转文本的接口
    # gr.Interface(
    #     fn=transcribe,  # 执行转录的函数
    #     inputs=[
    #         gr.Audio(sources="microphone", type="filepath"),  # 使用麦克风录制的音频输入
    #     ],
    #     outputs="text",  # 输出为文本
    #     flagging_mode="never",  # 禁用标记功能
    # )

    # 创建聊天机器人界面,提示用户输入
    contents_chatbot = gr.Chatbot(
        placeholder="<strong>AI 一键生成 PPT</strong><br><br>输入你的主题内容或上传音频文件",
        height=800,
        type="messages",
    )

    # 定义 ChatBot 和生成内容的接口
    gr.ChatInterface(
        fn=generate_contents,  # 处理用户输入的函数
        chatbot=contents_chatbot,  # 绑定的聊天机器人
        type="messages",
        multimodal=True  # 支持多模态输入(文本和文件)
    )

    image_generate_btn = gr.Button("一键为 PowerPoint 配图")

    image_generate_btn.click(
        fn=handle_image_generate,
        inputs=contents_chatbot,
        outputs=contents_chatbot,
    )

    # 创建生成 PowerPoint 的按钮
    generate_btn = gr.Button("一键生成 PowerPoint")

    # 监听生成按钮的点击事件
    generate_btn.click(
        fn=handle_generate,  # 点击时执行的函数
        inputs=contents_chatbot,  # 输入为聊天记录
        outputs=gr.File()  # 输出为文件下载链接
    )

# 主程序入口
if __name__ == "__main__":
    # 启动Gradio应用,允许队列功能,并通过 HTTPS 访问
    demo.queue().launch(
        share=False,
        server_name="0.0.0.0",
        # auth=("django", "qaz!@#$") # ⚠️注意:记住修改密码
    )