ginipick commited on
Commit
016b059
·
verified ·
1 Parent(s): ea5a353

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +249 -136
app.py CHANGED
@@ -1,177 +1,290 @@
1
  import gradio as gr
 
 
2
  import torch
3
-
4
- # Transformers의 파이프라인을 이용해 번역용 파이프라인 로드
5
- from transformers import pipeline as translation_pipeline
6
- translator = translation_pipeline("translation", model="Helsinki-NLP/opus-mt-ko-en", device="cpu")
7
-
8
- # Diffusers 모델 로드
9
  from diffusers import DiffusionPipeline
 
10
 
11
- model_id = "black-forest-labs/FLUX.1-schnell"
 
 
12
 
 
13
  pipe = DiffusionPipeline.from_pretrained(
14
- model_id,
15
- torch_dtype=torch.float32
16
- ).to("cpu") # CPU 사용
17
 
18
- def translate_prompt_if_korean(prompt_text: str) -> str:
19
- if any("가" <= ch <= "힣" for ch in prompt_text):
20
- result = translator(prompt_text)
21
- return result[0]['translation_text']
22
- return prompt_text
23
 
24
- def generate_storyboard(
25
- prompt,
26
- width=768,
27
- height=512,
28
- num_inference_steps=10,
29
- guidance_scale=7.5,
30
- seed=42
31
- ):
32
- # 번역 처리 (한글 -> 영어)
33
- prompt_en = translate_prompt_if_korean(prompt)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
- # 시드 생성
36
- generator = torch.Generator(device="cpu").manual_seed(seed)
 
 
 
37
 
38
- # 이미지 생성
39
- with torch.autocast("cpu"):
40
- result = pipe(
41
- prompt=prompt_en,
42
- width=width,
43
- height=height,
44
- num_inference_steps=num_inference_steps,
45
- guidance_scale=guidance_scale,
46
- generator=generator
47
- ).images[0]
48
- return result
 
 
 
49
 
50
- # --- 비주얼 & 세련된 UI를 위한 CSS ---
51
- custom_css = """
52
- #title {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  text-align: center;
54
- font-size: 3em;
 
 
55
  font-weight: bold;
56
- margin: 20px 0;
57
- color: #333;
 
58
  }
59
- #subtitle {
60
  text-align: center;
61
  color: #666;
62
  margin-bottom: 30px;
63
- font-size: 1.2em;
64
- }
65
- .gradio-container {
66
- background: linear-gradient(120deg, #f8f8f8 0%, #ffffff 100%);
67
  }
68
- .input-panel, .output-panel {
69
  background: white;
70
- border-radius: 12px;
71
  padding: 20px;
 
72
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
 
 
73
  }
74
- #prompt-input {
 
 
75
  font-size: 14px !important;
76
- min-height: 140px !important;
 
77
  }
78
- .advanced-settings {
79
- font-size: 0.9em;
80
- color: #444;
81
- }
82
- .example-box {
83
- background: #f9f9f9;
84
- padding: 10px;
85
- margin-top: 10px;
86
  border-radius: 8px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  }
88
  """
89
 
90
- with gr.Blocks(css=custom_css) as demo:
91
- gr.Markdown("<div id='title'>Gini Storyboard</div>")
92
- gr.Markdown("<div id='subtitle'>Generate a hand-drawn style storyboard in black & white film noir or any style you wish!</div>")
 
 
 
 
93
 
94
- with gr.Row():
95
- with gr.Column(elem_classes="input-panel", scale=1):
96
- prompt = gr.Textbox(
97
- label="Storyboard Prompt",
98
- placeholder="Enter your scene descriptions here (in English or Korean)",
99
- lines=8,
100
- elem_id="prompt-input"
101
- )
102
- seed = gr.Slider(
103
- label="Seed",
104
- value=42,
105
- minimum=0,
106
- maximum=999999,
107
- step=1
108
- )
109
- with gr.Row():
110
- width = gr.Slider(
111
- label="Width",
112
- minimum=256,
113
- maximum=1280,
114
- value=768,
115
- step=64
116
  )
117
- height = gr.Slider(
118
- label="Height",
119
- minimum=256,
120
- maximum=1280,
121
- value=512,
122
- step=64
 
 
 
 
123
  )
124
- with gr.Accordion("Advanced Settings", open=False, elem_classes="advanced-settings"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  num_inference_steps = gr.Slider(
126
  label="Number of inference steps",
127
- value=10,
128
  minimum=1,
129
  maximum=50,
130
- step=1
131
- )
132
- guidance_scale = gr.Slider(
133
- label="Guidance Scale",
134
- value=7.5,
135
- minimum=0.0,
136
- maximum=20.0,
137
- step=0.5
138
  )
139
-
140
- run_button = gr.Button("Generate Storyboard", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
 
142
- with gr.Column(elem_classes="output-panel", scale=1):
143
- result = gr.Image(label="Storyboard Result")
144
-
145
- # 예제 프롬프트
146
- gr.Markdown("### Example Prompt")
147
- # ↓ Box가 아닌 Group으로 변경
148
- with gr.Group(elem_classes="example-box"):
149
- example_text = (
150
- "A hand-drawn storyboard style, film noir theme, black and white.\n"
151
- "SCENE 1: A detective enters a dark alley [Frame 1]\n"
152
- "SCENE 2: He notices a shadow [Frame 2]\n"
153
- "SCENE 3: A sudden flash of light reveals a clue [Frame 3]"
154
- )
155
- gr.Markdown(f"```\n{example_text}\n```")
156
- example_button = gr.Button("Use Example")
157
-
158
- def load_example():
159
- return example_text
160
- example_button.click(fn=load_example, outputs=[prompt])
161
-
162
- run_button.click(
163
- fn=generate_storyboard,
164
- inputs=[prompt, width, height, num_inference_steps, guidance_scale, seed],
165
- outputs=[result]
166
- )
167
-
168
- # 엔터로 제출 시에도 실행
169
- prompt.submit(
170
- fn=generate_storyboard,
171
- inputs=[prompt, width, height, num_inference_steps, guidance_scale, seed],
172
- outputs=[result]
173
  )
174
 
175
  if __name__ == "__main__":
176
  demo.queue()
177
- demo.launch(server_name="0.0.0.0", server_port=7860, share=False)
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ import numpy as np
3
+ import random
4
  import torch
 
 
 
 
 
 
5
  from diffusers import DiffusionPipeline
6
+ import spaces
7
 
8
+ # 기본 설정
9
+ dtype = torch.bfloat16
10
+ device = "cuda" if torch.cuda.is_available() else "cpu"
11
 
12
+ # 모델 로드
13
  pipe = DiffusionPipeline.from_pretrained(
14
+ "black-forest-labs/FLUX.1-schnell",
15
+ torch_dtype=dtype
16
+ ).to(device)
17
 
18
+ MAX_SEED = np.iinfo(np.int32).max
19
+ MAX_IMAGE_SIZE = 2048
 
 
 
20
 
21
+ # 플로우차트 예시
22
+ EXAMPLES = [
23
+ {
24
+ "title": "Business Workflow",
25
+ "prompt": """A hand-drawn style flowchart, vibrant colors, minimalistic icons.
26
+ BUSINESS WORKFLOW
27
+ ├── START [Green Button ~40px]
28
+ │ ├── COLLECT REQUIREMENTS [Folder Icon]
29
+ │ └── ANALYZE DATA [Chart Icon]
30
+ ├── IMPLEMENTATION [Coding Symbol ~50px]
31
+ │ ├── FRONTEND [Browser Icon]
32
+ │ └── BACKEND [Server Icon]
33
+ ├── TEST & INTEGRATION [Gear Icon ~45px]
34
+ └── DEPLOY
35
+ └── END [Checkered Flag ~40px]""",
36
+ "width": 1024,
37
+ "height": 1024
38
+ },
39
+ {
40
+ "title": "Software Release Flow",
41
+ "prompt": """A hand-drawn style flowchart, pastel colors, arrows between stages.
42
+ SOFTWARE RELEASE
43
+ ├── FEATURE BRANCH [Git Branch Icon ~45px]
44
+ │ ├── DEVELOPMENT [Code Editor]
45
+ │ └── UNIT TEST [Check Mark]
46
+ ├── MERGE TO MAIN [Pull Request Icon]
47
+ │ ├── CI/CD [Pipeline Icon ~40px]
48
+ │ └── BUILD [Gear Icon]
49
+ └── PRODUCTION
50
+ └── DEPLOY [Cloud Upload Icon]""",
51
+ "width": 1024,
52
+ "height": 1024
53
+ },
54
+ {
55
+ "title": "E-Commerce Checkout",
56
+ "prompt": """A hand-drawn style flowchart, light watercolor, user journey from cart to payment.
57
+ E-COMMERCE CHECKOUT
58
+ ├── CART [Shopping Cart ~40px]
59
+ │ ├── LOGIN [User Icon]
60
+ │ └── ADDRESS [Location Pin]
61
+ ├── PAYMENT [Credit Card Icon ~45px]
62
+ │ ├── VALIDATION [Lock Icon]
63
+ │ └── CONFIRMATION [Receipt Icon]
64
+ └── ORDER COMPLETE
65
+ └── THANK YOU [Smiley Icon]""",
66
+ "width": 1024,
67
+ "height": 1024
68
+ },
69
+ {
70
+ "title": "Data Pipeline",
71
+ "prompt": """A hand-drawn style flowchart, tech-focused, neon highlights, showing data flow.
72
+ DATA PIPELINE
73
+ ├── INGESTION [Database Icon ~50px]
74
+ │ ├── STREAMING [Kafka Symbol]
75
+ │ └── BATCH [CSV/JSON Files]
76
+ ├── TRANSFORMATION [Gear Icon ~45px]
77
+ │ ├── CLEANING [Brush Icon]
78
+ │ └── AGGREGATION [Bar Graph]
79
+ ├── STORAGE [Cloud Icon ~50px]
80
+ └── ANALYTICS
81
+ └── DASHBOARDS [Monitor Icon]""",
82
+ "width": 1024,
83
+ "height": 1024
84
+ },
85
+ {
86
+ "title": "Machine Learning Lifecycle",
87
+ "prompt": """A hand-drawn style flowchart, pastel palette, ML steps from data to deployment.
88
+ ML LIFECYCLE
89
+ ├── DATA COLLECTION [Folder Icon ~45px]
90
+ │ ├── DATA CLEANING [Soap Icon]
91
+ │ └── FEATURE ENGINEERING [Puzzle Icon]
92
+ ├── MODEL TRAINING [Robot Icon ~50px]
93
+ │ ├── HYPERPARAM TUNING [Dial Knob]
94
+ │ └── EVALUATION [Magnifier Icon]
95
+ ├── DEPLOYMENT [Cloud Icon ~45px]
96
+ └── MONITORING
97
+ └── FEEDBACK LOOP [Arrow Circle Icon]""",
98
+ "width": 1024,
99
+ "height": 1024
100
+ }
101
+ ]
102
 
103
+ # Convert examples to Gradio format (if needed)
104
+ GRADIO_EXAMPLES = [
105
+ [example["prompt"], example["width"], example["height"]]
106
+ for example in EXAMPLES
107
+ ]
108
 
109
+ @spaces.GPU()
110
+ def infer(prompt, seed=42, randomize_seed=False, width=1024, height=1024, num_inference_steps=4, progress=gr.Progress(track_tqdm=True)):
111
+ if randomize_seed:
112
+ seed = random.randint(0, MAX_SEED)
113
+ generator = torch.Generator().manual_seed(seed)
114
+ image = pipe(
115
+ prompt=prompt,
116
+ width=width,
117
+ height=height,
118
+ num_inference_steps=num_inference_steps,
119
+ generator=generator,
120
+ guidance_scale=0.0 # 플로우차트 텍스트에 집중하되, 자유로운 표현
121
+ ).images[0]
122
+ return image, seed
123
 
124
+ # CSS 스타일 (기존 구조 유지, 명칭만 일부 수정)
125
+ css = """
126
+ .container {
127
+ display: flex;
128
+ flex-direction: row;
129
+ height: 100%;
130
+ }
131
+ .input-column {
132
+ flex: 1;
133
+ padding: 20px;
134
+ border-right: 2px solid #eee;
135
+ max-width: 800px;
136
+ }
137
+ .examples-column {
138
+ flex: 1;
139
+ padding: 20px;
140
+ overflow-y: auto;
141
+ background: #f7f7f7;
142
+ }
143
+ .title {
144
  text-align: center;
145
+ color: #2a2a2a;
146
+ padding: 20px;
147
+ font-size: 2.5em;
148
  font-weight: bold;
149
+ background: linear-gradient(90deg, #f0f0f0 0%, #ffffff 100%);
150
+ border-bottom: 3px solid #ddd;
151
+ margin-bottom: 30px;
152
  }
153
+ .subtitle {
154
  text-align: center;
155
  color: #666;
156
  margin-bottom: 30px;
 
 
 
 
157
  }
158
+ .input-box {
159
  background: white;
 
160
  padding: 20px;
161
+ border-radius: 10px;
162
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
163
+ margin-bottom: 20px;
164
+ width: 100%;
165
  }
166
+ .input-box textarea {
167
+ width: 100% !important;
168
+ min-width: 600px !important;
169
  font-size: 14px !important;
170
+ line-height: 1.5 !important;
171
+ padding: 12px !important;
172
  }
173
+ .example-card {
174
+ background: white;
175
+ padding: 15px;
176
+ margin: 10px 0;
 
 
 
 
177
  border-radius: 8px;
178
+ box-shadow: 0 2px 5px rgba(0,0,0,0.05);
179
+ }
180
+ .example-title {
181
+ font-weight: bold;
182
+ color: #2a2a2a;
183
+ margin-bottom: 10px;
184
+ }
185
+ .contain {
186
+ max-width: 1400px !important;
187
+ margin: 0 auto !important;
188
+ }
189
+ .input-area {
190
+ flex: 2 !important;
191
+ }
192
+ .examples-area {
193
+ flex: 1 !important;
194
  }
195
  """
196
 
197
+ # Gradio 인터페이스
198
+ with gr.Blocks(css=css) as demo:
199
+ gr.Markdown(
200
+ """
201
+ <div class="title">GINI Flowchart</div>
202
+ <div class="subtitle">Create professional process flowcharts using FLUX AI</div>
203
+ """)
204
 
205
+ with gr.Row(equal_height=True):
206
+ # 왼쪽 입력 컬럼
207
+ with gr.Column(elem_id="input-column", scale=2):
208
+ with gr.Group(elem_classes="input-box"):
209
+ prompt = gr.Text(
210
+ label="Flowchart Prompt",
211
+ placeholder="Enter your process flowchart structure...",
212
+ lines=10,
213
+ elem_classes="prompt-input"
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  )
215
+ run_button = gr.Button("Generate Flowchart", variant="primary")
216
+ result = gr.Image(label="Generated Flowchart")
217
+
218
+ with gr.Accordion("Advanced Settings", open=False):
219
+ seed = gr.Slider(
220
+ label="Seed",
221
+ minimum=0,
222
+ maximum=MAX_SEED,
223
+ step=1,
224
+ value=0,
225
  )
226
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
227
+
228
+ with gr.Row():
229
+ width = gr.Slider(
230
+ label="Width",
231
+ minimum=256,
232
+ maximum=MAX_IMAGE_SIZE,
233
+ step=32,
234
+ value=1024,
235
+ )
236
+ height = gr.Slider(
237
+ label="Height",
238
+ minimum=256,
239
+ maximum=MAX_IMAGE_SIZE,
240
+ step=32,
241
+ value=1024,
242
+ )
243
+
244
  num_inference_steps = gr.Slider(
245
  label="Number of inference steps",
 
246
  minimum=1,
247
  maximum=50,
248
+ step=1,
249
+ value=4,
 
 
 
 
 
 
250
  )
251
+
252
+ # 오른쪽 예제 컬럼
253
+ with gr.Column(elem_id="examples-column", scale=1):
254
+ gr.Markdown("### Example Flowcharts")
255
+ for example in EXAMPLES:
256
+ with gr.Group(elem_classes="example-card"):
257
+ gr.Markdown(f"#### {example['title']}")
258
+ gr.Markdown(f"```\n{example['prompt']}\n```")
259
+
260
+ def create_example_handler(ex):
261
+ def handler():
262
+ return {
263
+ prompt: ex["prompt"],
264
+ width: ex["width"],
265
+ height: ex["height"]
266
+ }
267
+ return handler
268
+
269
+ gr.Button("Use This Example", size="sm").click(
270
+ fn=create_example_handler(example),
271
+ outputs=[prompt, width, height]
272
+ )
273
 
274
+ # 이벤트 바인딩 (버튼 클릭 & 텍스트박스 엔터)
275
+ gr.on(
276
+ triggers=[run_button.click, prompt.submit],
277
+ fn=infer,
278
+ inputs=[prompt, seed, randomize_seed, width, height, num_inference_steps],
279
+ outputs=[result, seed]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  )
281
 
282
  if __name__ == "__main__":
283
  demo.queue()
284
+ demo.launch(
285
+ server_name="0.0.0.0",
286
+ server_port=7860,
287
+ share=False,
288
+ show_error=True,
289
+ debug=True
290
+ )