PHOENIXREBORNAGAIN commited on
Commit
46af8e9
·
verified ·
1 Parent(s): bd54c37

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +152 -0
app.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import tempfile
3
+ import traceback
4
+ import gradio as gr
5
+
6
+ from slide_generator import generate_presentation
7
+ from pptx_builder import build_pptx
8
+
9
+ STYLES = ["Professional", "Creative", "Academic", "Startup"]
10
+
11
+ CSS = """
12
+ * { box-sizing: border-box; }
13
+ body, .gradio-container {
14
+ background: #f0f7f4 !important;
15
+ font-family: 'Inter', system-ui, sans-serif !important;
16
+ }
17
+ footer { display: none !important; }
18
+ .header-block {
19
+ background: linear-gradient(135deg, #1b6ca8 0%, #19a88a 100%);
20
+ border-radius: 16px;
21
+ padding: 32px 36px 28px;
22
+ margin-bottom: 24px;
23
+ }
24
+ button.primary {
25
+ background: linear-gradient(135deg, #1b6ca8, #19a88a) !important;
26
+ color: #fff !important;
27
+ border: none !important;
28
+ border-radius: 12px !important;
29
+ font-size: 17px !important;
30
+ font-weight: 700 !important;
31
+ padding: 16px 0 !important;
32
+ width: 100% !important;
33
+ cursor: pointer !important;
34
+ box-shadow: 0 4px 16px rgba(25,168,138,0.3) !important;
35
+ }
36
+ button.primary:hover { opacity: .87 !important; }
37
+ textarea, input[type="text"] {
38
+ background: #f5fbf9 !important;
39
+ border: 1.5px solid #b2ddd1 !important;
40
+ border-radius: 10px !important;
41
+ color: #1a3a3a !important;
42
+ font-size: 14px !important;
43
+ }
44
+ input[type="range"] { accent-color: #19a88a !important; }
45
+ .status-ok {
46
+ background: #e6f7f2; border: 1px solid #a8dfd0;
47
+ border-radius: 10px; padding: 12px 18px;
48
+ font-size: 14px; color: #1a5a4a; margin-bottom: 8px;
49
+ }
50
+ .status-wait {
51
+ background: #f0f7ff; border: 1px solid #b2cfe8;
52
+ border-radius: 10px; padding: 12px 18px;
53
+ font-size: 14px; color: #1a3a6a; margin-bottom: 8px;
54
+ }
55
+ """
56
+
57
+
58
+ def format_preview(data: dict) -> str:
59
+ lines = [f"# {data.get('title', '')}", ""]
60
+ if data.get("subtitle"):
61
+ lines += [f"*{data['subtitle']}*", ""]
62
+ lines.append("---")
63
+ for slide in data.get("slides", []):
64
+ num = slide.get("slide_number", "")
65
+ title = slide.get("title", "")
66
+ if slide.get("type") == "title":
67
+ lines.append(f"\n### 🎯 Slide {num} — {title}")
68
+ if slide.get("subtitle"):
69
+ lines.append(f"> {slide['subtitle']}")
70
+ else:
71
+ lines.append(f"\n### 📄 Slide {num} — {title}")
72
+ for b in slide.get("bullets", []):
73
+ lines.append(f"- {b}")
74
+ if slide.get("speaker_notes"):
75
+ lines.append(f"\n*🗒 {slide['speaker_notes']}*")
76
+ return "\n".join(lines)
77
+
78
+
79
+ def generate_and_download(topic, audience, style, num_slides, key_points,
80
+ progress=gr.Progress()):
81
+ if not topic.strip():
82
+ raise gr.Error("Please enter a topic.")
83
+ if not audience.strip():
84
+ raise gr.Error("Please enter the target audience.")
85
+ try:
86
+ progress(0.1, desc="AI is writing your slides…")
87
+ data = generate_presentation(
88
+ topic=topic.strip(), style=style,
89
+ num_slides=int(num_slides),
90
+ audience=audience.strip(),
91
+ key_points=key_points.strip(),
92
+ )
93
+ progress(0.75, desc="Building PPTX…")
94
+ pptx_bytes = build_pptx(data, style)
95
+
96
+ tmp_dir = tempfile.mkdtemp()
97
+ safe = topic[:30].replace(" ", "_").replace("/", "-")
98
+ out_path = os.path.join(tmp_dir, f"{safe}.pptx")
99
+ with open(out_path, "wb") as f:
100
+ f.write(pptx_bytes)
101
+
102
+ progress(1.0, desc="Done!")
103
+ n = len(data.get("slides", []))
104
+ status = f"<div class='status-ok'>✅ <strong>{n} slides</strong> ready — download below!</div>"
105
+ return format_preview(data), out_path, status
106
+
107
+ except gr.Error:
108
+ raise
109
+ except Exception:
110
+ raise gr.Error(traceback.format_exc())
111
+
112
+
113
+ with gr.Blocks(title="SlideAI", css=CSS) as demo:
114
+
115
+ gr.HTML("""
116
+ <div class="header-block">
117
+ <h1 style="margin:0;font-size:28px;font-weight:800;color:#fff;">SlideAI</h1>
118
+ <p style="margin:6px 0 0;font-size:14px;color:rgba(255,255,255,.88);">
119
+ Turn any topic into a polished, download-ready presentation — in seconds.
120
+ </p>
121
+ </div>""")
122
+
123
+ with gr.Row():
124
+ with gr.Column(scale=1, min_width=300):
125
+ topic = gr.Textbox(label="Topic *",
126
+ placeholder="e.g. Climate Change, AI in Medicine…", lines=2)
127
+ audience = gr.Textbox(label="Target Audience *",
128
+ placeholder="e.g. Investors, Students…", lines=1)
129
+ with gr.Row():
130
+ style = gr.Dropdown(choices=STYLES, value="Professional",
131
+ label="Style", scale=1)
132
+ num_slides = gr.Slider(minimum=5, maximum=15, step=1, value=8,
133
+ label="Slides", scale=1)
134
+ key_points = gr.Textbox(label="Key Points (optional)",
135
+ placeholder="Specific facts or ideas to include…", lines=2)
136
+ btn = gr.Button("✨ Generate Presentation", variant="primary", size="lg")
137
+
138
+ with gr.Column(scale=2, min_width=380):
139
+ status = gr.HTML(
140
+ "<div class='status-wait'>Fill in the form on the left and hit <strong>Generate</strong>.</div>"
141
+ )
142
+ preview = gr.Markdown()
143
+ download = gr.File(label="📥 Download your PPTX", interactive=False)
144
+
145
+ btn.click(
146
+ fn=generate_and_download,
147
+ inputs=[topic, audience, style, num_slides, key_points],
148
+ outputs=[preview, download, status],
149
+ )
150
+
151
+ if __name__ == "__main__":
152
+ demo.launch()