EnigmaOfTheWorld commited on
Commit
2255e63
·
1 Parent(s): 9892c47

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +389 -0
app.py ADDED
@@ -0,0 +1,389 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import re
4
+ import pathlib
5
+
6
+ import requests
7
+ import openai
8
+ from embedchain import App
9
+ from serpapi import GoogleSearch
10
+ from pptx import Presentation
11
+ from pptx.util import Inches
12
+
13
+ from pptx import Presentation
14
+ from pptx.util import Inches, Pt
15
+ import gradio as gr
16
+
17
+ import torch
18
+
19
+ from PIL import Image
20
+ import qrcode
21
+ from pathlib import Path
22
+ from multiprocessing import cpu_count
23
+ import requests
24
+ import io
25
+ import os
26
+ from PIL import Image
27
+
28
+
29
+ from diffusers import (
30
+ StableDiffusionControlNetPipeline,
31
+ ControlNetModel,
32
+ DDIMScheduler,
33
+ DPMSolverMultistepScheduler,
34
+ DEISMultistepScheduler,
35
+ HeunDiscreteScheduler,
36
+ EulerDiscreteScheduler,
37
+ EulerAncestralDiscreteScheduler,
38
+ )
39
+
40
+ def gpt(user_prompt: str) -> str:
41
+ response = openai.Completion.create(
42
+ model="text-davinci-003",
43
+ prompt=user_prompt,
44
+ temperature=0,
45
+ max_tokens=200,
46
+ top_p=1,
47
+ frequency_penalty=0,
48
+ presence_penalty=0)
49
+ return response["choices"][0]["text"]
50
+
51
+ def get_results(query:str, topic:str,index=0)->list[str]:
52
+ combined_q = gpt(f'combine these "{query}" + "{topic}" words and generate one heading')
53
+ print(f'{query = }, {topic = }, {combined_q = }')
54
+
55
+ try:
56
+ params = {
57
+ "engine": "google",
58
+ "q": combined_q,
59
+ "api_key": os.environ[f'SERPAPI_API_KEY{index}']
60
+ }
61
+ search = GoogleSearch(params)
62
+ results = search.get_dict()
63
+ except Exception as e:
64
+ print(e)
65
+ get_results(query, topic,index=index+1)
66
+
67
+
68
+
69
+ organic_results = results["organic_results"]
70
+ return organic_results
71
+
72
+ def extract_points(query:str, topic:str)->list[str]:
73
+ # print('--Sleep--')
74
+ time.sleep(60)
75
+ organic_results = get_results(query, topic)
76
+ embd_chain = App()
77
+ for index, dct in enumerate(organic_results):
78
+ try:
79
+ embd_chain.add('web_page',dct['link'])
80
+ except requests.exceptions.SSLError:
81
+ continue
82
+ except openai.error.RateLimitError:
83
+ break
84
+ print('--sleep--')
85
+ time.sleep(60)
86
+ embd_chain_q = embd_chain.query(f'highlight 7 important points')
87
+
88
+ return
89
+ # Add the title slide
90
+
91
+ def add_slide(prs, title, content, title_font_size=Pt(36), content_font_size=Pt(18)):
92
+ slide_layout = prs.slide_layouts[1] # Use the layout for "Title and Content"
93
+ slide = prs.slides.add_slide(slide_layout)
94
+
95
+ # Set the title and content text
96
+ slide.shapes.title.text = title
97
+ text_box = slide.placeholders[1]
98
+ text_box.text = content
99
+
100
+ # Change the font size for title and content text
101
+ title_text_frame = slide.shapes.title.text_frame
102
+ content_text_frame = text_box.text_frame
103
+ for paragraph in title_text_frame.paragraphs:
104
+ for run in paragraph.runs:
105
+ run.font.size = title_font_size
106
+
107
+ for paragraph in content_text_frame.paragraphs:
108
+ for run in paragraph.runs:
109
+ run.font.size = content_font_size
110
+
111
+
112
+ def add_title_slide(prs, title, title_font_size=Pt(44)):
113
+ slide_layout = prs.slide_layouts[0] # Use the layout for "Title Slide"
114
+ slide = prs.slides.add_slide(slide_layout)
115
+
116
+ # Set the title and subtitle text
117
+ slide.shapes.title.text = title
118
+
119
+
120
+ # Change the font size for title and subtitle text
121
+ title_text_frame = slide.shapes.title.text_frame
122
+
123
+ for paragraph in title_text_frame.paragraphs:
124
+ for run in paragraph.runs:
125
+ run.font.size = title_font_size
126
+
127
+
128
+ def main(user_query:str)->dict[str, str]:
129
+ res = gpt(f'You are assisting me in creating a presentation on "{user_query}" Please generate 5 informative side headings for the slides. Each heading should be concise and reflect a key aspect of the topic.')
130
+ topics = re.sub(r'[\d.]','',res.strip()).split('\n')
131
+ print(f'{topics = }')
132
+ ppt_points = { topic: extract_points(topic, user_query)
133
+ for topic in topics}
134
+ prs = Presentation()
135
+ add_title_slide(prs,user_query, title_font_size=Pt(44))
136
+
137
+ # Data for content slides
138
+
139
+ # Adding each key-value pair as a slide in the presentation with custom font sizes
140
+ for key, value in ppt_points.items():
141
+ add_slide(prs, key, value, title_font_size=Pt(36), content_font_size=Pt(18))
142
+
143
+ # Save the presentation
144
+ prs.save(f'{user_query}.pptx')
145
+
146
+ return f'{user_query}.pptx'
147
+
148
+ controlnet = ControlNetModel.from_pretrained(
149
+ "monster-labs/control_v1p_sd15_qrcode_monster",
150
+ torch_dtype=torch.float16
151
+
152
+ ).to('cpu')
153
+
154
+ pipe = StableDiffusionControlNetPipeline.from_pretrained(
155
+ "runwayml/stable-diffusion-v1-5",
156
+ controlnet=controlnet,
157
+ safety_checker=None,
158
+ torch_dtype=torch.float16
159
+
160
+
161
+ ).to('cuda')
162
+ pipe.enable_xformers_memory_efficient_attention()
163
+
164
+
165
+ SAMPLER_MAP = {
166
+ "DPM++ Karras SDE": lambda config: DPMSolverMultistepScheduler.from_config(config, use_karras=True, algorithm_type="sde-dpmsolver++"),
167
+ "DPM++ Karras": lambda config: DPMSolverMultistepScheduler.from_config(config, use_karras=True),
168
+ "Heun": lambda config: HeunDiscreteScheduler.from_config(config),
169
+ "Euler a": lambda config: EulerAncestralDiscreteScheduler.from_config(config),
170
+ "Euler": lambda config: EulerDiscreteScheduler.from_config(config),
171
+ "DDIM": lambda config: DDIMScheduler.from_config(config),
172
+ "DEIS": lambda config: DEISMultistepScheduler.from_config(config),
173
+ }
174
+
175
+
176
+ def create_code(content: str):
177
+ qr = qrcode.QRCode(
178
+ version=1,
179
+ error_correction=qrcode.constants.ERROR_CORRECT_H,
180
+ box_size=16,
181
+ border=0,
182
+ )
183
+ qr.add_data(content)
184
+ qr.make(fit=True)
185
+ img = qr.make_image(fill_color="black", back_color="white")
186
+
187
+ # find smallest image size multiple of 256 that can fit qr
188
+ offset_min = 8 * 16
189
+ w, h = img.size
190
+ w = (w + 255 + offset_min) // 256 * 256
191
+ h = (h + 255 + offset_min) // 256 * 256
192
+ if w > 1024:
193
+ raise gr.Error("QR code is too large, please use a shorter content")
194
+ bg = Image.new('L', (w, h), 128)
195
+
196
+ # align on 16px grid
197
+ coords = ((w - img.size[0]) // 2 // 16 * 16,
198
+ (h - img.size[1]) // 2 // 16 * 16)
199
+ bg.paste(img, coords)
200
+ return bg
201
+
202
+
203
+ def inference(
204
+ qr_code_content: str,
205
+ prompt: str,
206
+ negative_prompt: str,
207
+ guidance_scale: float = 10.0,
208
+ controlnet_conditioning_scale: float = 2.0,
209
+ seed: int = -1,
210
+ sampler="Euler a",
211
+ ):
212
+
213
+
214
+ pipe.scheduler = SAMPLER_MAP[sampler](pipe.scheduler.config)
215
+
216
+ generator = torch.manual_seed(seed) if seed != -1 else torch.Generator()
217
+
218
+ print("Generating QR Code from content")
219
+ qrcode_image = create_code(qr_code_content)
220
+
221
+ # hack due to gradio examples
222
+ init_image = qrcode_image
223
+
224
+ out = pipe(
225
+ prompt=prompt,
226
+ negative_prompt=negative_prompt,
227
+ image=qrcode_image,
228
+ width=qrcode_image.width,
229
+ height=qrcode_image.height,
230
+ guidance_scale=float(guidance_scale),
231
+ controlnet_conditioning_scale=float(controlnet_conditioning_scale),
232
+
233
+ num_inference_steps=40,
234
+ )
235
+ return out.images[0]
236
+
237
+ import gradio as gr
238
+
239
+
240
+ with gr.Blocks() as demo:
241
+ with gr.Tab('Presentation'):
242
+ with gr.Row():
243
+ with gr.Column():
244
+ txt = gr.Textbox(label="Your Query")
245
+ with gr.Column():
246
+ file = gr.File()
247
+
248
+ btn = gr.Button('Create Presentation')
249
+
250
+
251
+ btn.click(main, txt, file)
252
+ with gr.Tab('Share'):
253
+ gr.Markdown('This feature needs GPU to run')
254
+ with gr.Row():
255
+ with gr.Column():
256
+ qr_code_content = gr.Textbox(
257
+ label="QR Code Content or URL",
258
+ info="The text you want to encode into the QR code",
259
+ value="",
260
+ )
261
+
262
+ prompt = gr.Textbox(
263
+ label="Prompt",
264
+ info="Prompt that guides the generation towards",
265
+ )
266
+ negative_prompt = gr.Textbox(
267
+ label="Negative Prompt",
268
+ value="ugly, disfigured, low quality, blurry, nsfw",
269
+ info="Prompt that guides the generation away from",
270
+ )
271
+
272
+ with gr.Accordion(
273
+ label="Params: The generated QR Code functionality is largely influenced by the parameters detailed below",
274
+ open=True,
275
+ ):
276
+ controlnet_conditioning_scale = gr.Slider(
277
+ minimum=0.5,
278
+ maximum=2.5,
279
+ step=0.01,
280
+ value=1.5,
281
+ label="Controlnet Conditioning Scale",
282
+ info="""Controls the readability/creativity of the QR code.
283
+ High values: The generated QR code will be more readable.
284
+ Low values: The generated QR code will be more creative.
285
+ """
286
+ )
287
+ guidance_scale = gr.Slider(
288
+ minimum=0.0,
289
+ maximum=25.0,
290
+ step=0.25,
291
+ value=7,
292
+ label="Guidance Scale",
293
+ info="Controls the amount of guidance the text prompt guides the image generation"
294
+ )
295
+ sampler = gr.Dropdown(choices=list(
296
+ SAMPLER_MAP.keys()), value="Euler a", label="Sampler")
297
+ seed = gr.Number(
298
+ minimum=-1,
299
+ maximum=9999999999,
300
+ step=1,
301
+ value=2313123,
302
+ label="Seed",
303
+ randomize=True,
304
+ info="Seed for the random number generator. Set to -1 for a random seed"
305
+ )
306
+ with gr.Row():
307
+ run_btn = gr.Button("Run")
308
+ with gr.Column():
309
+ result_image = gr.Image(label="Result Image", elem_id="result_image")
310
+ run_btn.click(
311
+ inference,
312
+ inputs=[
313
+ qr_code_content,
314
+ prompt,
315
+ negative_prompt,
316
+ guidance_scale,
317
+ controlnet_conditioning_scale,
318
+ seed,
319
+ sampler,
320
+ ],
321
+ outputs=[result_image],
322
+ )
323
+
324
+ gr.Examples(
325
+ examples=[
326
+ [
327
+ "test",
328
+ "Baroque rococo architecture, architectural photography, post apocalyptic New York, hyperrealism, [roots], hyperrealistic, octane render, cinematic, hyper detailed, 8K",
329
+ "",
330
+ 7,
331
+ 1.6,
332
+ 2592353769,
333
+ "Euler a",
334
+ ],
335
+ [
336
+ "https://qrcodemonster.art",
337
+ "a centered render of an ancient tree covered in bio - organic micro organisms growing in a mystical setting, cinematic, beautifully lit, by tomasz alen kopera and peter mohrbacher and craig mullins, 3d, trending on artstation, octane render, 8k",
338
+ "",
339
+ 7,
340
+ 1.57,
341
+ 259235398,
342
+ "Euler a",
343
+ ],
344
+ [
345
+ "test",
346
+ "3 cups of coffee with coffee beans around",
347
+ "",
348
+ 7,
349
+ 1.95,
350
+ 1889601353,
351
+ "Euler a",
352
+ ],
353
+ [
354
+ "https://huggingface.co",
355
+ "A top view picture of a sandy beach with a sand castle, beautiful lighting, 8k, highly detailed",
356
+ "sky",
357
+ 7,
358
+ 1.15,
359
+ 46200,
360
+ "Euler a",
361
+ ],
362
+ [
363
+ "test",
364
+ "A top view picture of a sandy beach, organic shapes, beautiful lighting, bumps and shadows, 8k, highly detailed",
365
+ "sky, water, squares",
366
+ 7,
367
+ 1.25,
368
+ 46220,
369
+ "Euler a",
370
+ ],
371
+ ],
372
+ fn=inference,
373
+ inputs=[
374
+ qr_code_content,
375
+ prompt,
376
+ negative_prompt,
377
+ guidance_scale,
378
+ controlnet_conditioning_scale,
379
+ seed,
380
+ sampler,
381
+ ],
382
+ outputs=[result_image],
383
+
384
+ )
385
+
386
+
387
+
388
+ demo.launch(debug=True)
389
+