magictreee commited on
Commit
ee03c74
ยท
verified ยท
1 Parent(s): e73399b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +453 -13
app.py CHANGED
@@ -1,17 +1,457 @@
1
- import openai
 
2
  import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- # ํ™˜๊ฒฝ ๋ณ€์ˆ˜์—์„œ API ํ‚ค ๊ฐ€์ ธ์˜ค๊ธฐ
5
- api_key = os.environ.get('OPENAI_API_KEY')
 
 
 
 
 
 
 
6
 
7
- if api_key:
8
- openai.api_key = api_key
9
- else:
10
- raise ValueError("OPENAI_API_KEY ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
11
 
12
- # ํ™˜๊ฒฝ ๋ณ€์ˆ˜์—์„œ 'APP' ์ฝ”๋“œ ๊ฐ€์ ธ์™€ ์‹คํ–‰ํ•˜๊ธฐ (์ฃผ์˜ ํ•„์š”)
13
- app_code = os.environ.get('APP')
14
- if app_code:
15
- exec(app_code)
16
- else:
17
- raise ValueError("APP ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
 
 
 
1
+ import gradio as gr
2
+ import random
3
  import os
4
+ import re
5
+ import openai
6
+ from fpdf import FPDF
7
+ from datetime import datetime
8
+ from zoneinfo import ZoneInfo
9
+ from sklearn.feature_extraction.text import CountVectorizer
10
+
11
+ # OpenAI API ํด๋ผ์ด์–ธํŠธ ์„ค์ •
12
+ openai.api_key = os.getenv("OPENAI_API_KEY")
13
+
14
+ def call_api(content, system_message, max_tokens, temperature, top_p):
15
+ try:
16
+ messages = [
17
+ {"role": "system", "content": system_message},
18
+ {"role": "user", "content": content}
19
+ ]
20
+
21
+ response = openai.ChatCompletion.create(
22
+ model="gpt-4o-mini",
23
+ messages=messages,
24
+ max_tokens=max_tokens,
25
+ temperature=temperature,
26
+ top_p=top_p,
27
+ request_timeout=50
28
+ )
29
+
30
+ return response.choices[0].message['content']
31
+ except Exception as e:
32
+ print(f"API ํ˜ธ์ถœ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
33
+ raise
34
+
35
+ def analyze_info(data):
36
+ return f"์„ ํƒํ•œ ์นดํ…Œ๊ณ ๋ฆฌ: {data['category']}\n์„ ํƒํ•œ ํฌ์ŠคํŒ… ์Šคํƒ€์ผ: {data['style']}\n์ฐธ๊ณ  ๊ธ€1: {data['references1']}\n์ฐธ๊ณ  ๊ธ€2: {data['references2']}\n์ฐธ๊ณ  ๊ธ€3: {data['references3']}"
37
+
38
+ def generate_outline(category, style, references1, references2, references3):
39
+ data = {
40
+ 'category': category,
41
+ 'style': style,
42
+ 'references1': references1,
43
+ 'references2': references2,
44
+ 'references3': references3
45
+ }
46
+ full_content = analyze_info(data)
47
+ system_prompt = get_outline_prompt(data['category']) + "\n\n" + get_style_prompt(data['style'])
48
+ modified_text = call_api(full_content, system_prompt, 2000, 0.7, 0.95)
49
+
50
+ # ํ•ต์‹ฌ๊ธฐ๋Šฅ์„ ๋ถ„๋ฆฌํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฐ˜ํ™˜
51
+ features = re.findall(r'ํ•ต์‹ฌ๊ธฐ๋Šฅ : (.+)', modified_text)
52
+ return features[:3] # ์ตœ๋Œ€ 3๊ฐœ์˜ ํ•ต์‹ฌ๊ธฐ๋Šฅ๋งŒ ๋ฐ˜ํ™˜
53
+ def remove_unwanted_phrases(text):
54
+ unwanted_phrases = [
55
+ '์—ฌ๋Ÿฌ๋ถ„', '์ตœ๊ทผ', '๋งˆ์ง€๋ง‰์œผ๋กœ', '๊ฒฐ๋ก ์ ์œผ๋กœ', '๊ฒฐ๊ตญ',
56
+ '์ข…ํ•ฉ์ ์œผ๋กœ', '๋”ฐ๋ผ์„œ', '๋งˆ๋ฌด๋ฆฌ', '์š”์•ฝ'
57
+ ]
58
+ words = re.findall(r'\S+|\n', text)
59
+ result_words = [word for word in words if not any(phrase in word for phrase in unwanted_phrases)]
60
+ return ' '.join(result_words).replace(' \n ', '\n').replace(' \n', '\n').replace('\n ', '\n')
61
+
62
+ def generate_blog_post(category, style, references1, references2, references3, outline):
63
+ try:
64
+ data = {
65
+ 'category': category,
66
+ 'style': style,
67
+ 'references1': references1,
68
+ 'references2': references2,
69
+ 'references3': references3,
70
+ 'outline': outline
71
+ }
72
+
73
+ system_prompt = get_blog_post_prompt(data['category'])
74
+ style_prompt = get_style_prompt(data['style'])
75
+
76
+ user_prompt = f"""
77
+ ์นดํ…Œ๊ณ ๋ฆฌ: {data['category']}
78
+ ํฌ์ŠคํŒ… ์Šคํƒ€์ผ: {data['style']}
79
+ ํ•ต์‹ฌ๊ธฐ๋Šฅ: {data['outline']}
80
+
81
+ ์ฐธ๊ณ ๊ธ€1: {data['references1']}
82
+ ์ฐธ๊ณ ๊ธ€2: {data['references2']}
83
+ ์ฐธ๊ณ ๊ธ€3: {data['references3']}
84
+ """
85
+
86
+ blog_content = call_api(
87
+ user_prompt,
88
+ system_prompt + "\n" + style_prompt,
89
+ 5000,
90
+ 0.7,
91
+ 0.95
92
+ )
93
+
94
+ filtered_post = remove_unwanted_phrases(blog_content)
95
+ filtered_post = filtered_post.lstrip()
96
+
97
+ html_post = convert_to_html(filtered_post)
98
+
99
+ return html_post
100
+ except Exception as e:
101
+ print(f"๊ธ€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
102
+ return ""
103
+
104
+ def convert_to_html(text):
105
+ lines = text.split('\n')
106
+ html_lines = []
107
+ for line in lines:
108
+ line = line.strip()
109
+ if line.startswith('####'):
110
+ html_lines.append(f"<h4>{line[4:].strip()}</h4>")
111
+ elif line.startswith('###'):
112
+ html_lines.append(f"<h3>{line[3:].strip()}</h3>")
113
+ elif line.startswith('##'):
114
+ html_lines.append(f"<h2>{line[2:].strip()}</h2>")
115
+ elif line.startswith('#'):
116
+ html_lines.append(f"<h1>{line[1:].strip()}</h1>")
117
+ elif line.startswith('- '): # ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ
118
+ html_lines.append(f"<li>{line[2:]}</li>")
119
+ elif line: # ์ผ๋ฐ˜ ํ…์ŠคํŠธ (๋นˆ ์ค„ ์ œ์™ธ)
120
+ # '**'๋กœ ๊ฐ์‹ธ์ง„ ๋ถ€๋ถ„์„ <strong> ํƒœ๊ทธ๋กœ ๋ณ€ํ™˜
121
+ line = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', line)
122
+ html_lines.append(f"<p>{line}</p>")
123
+ else: # ๋นˆ ์ค„
124
+ html_lines.append("<br>")
125
+
126
+ html_content = f"""
127
+ <div style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
128
+ {"".join(html_lines)}
129
+ </div>
130
+ """
131
+ return html_content
132
+
133
+ def remove_unwanted_phrases(text):
134
+ unwanted_phrases = [
135
+ '์—ฌ๋Ÿฌ๋ถ„', '์ตœ๊ทผ', '๋งˆ์ง€๋ง‰์œผ๋กœ', '๊ฒฐ๋ก ์ ์œผ๋กœ', '๊ฒฐ๊ตญ',
136
+ '์ข…ํ•ฉ์ ์œผ๋กœ', '๋”ฐ๋ผ์„œ', '๋งˆ๋ฌด๋ฆฌ', '์š”์•ฝ'
137
+ ]
138
+
139
+ # ๋ฌธ๋‹จ๋ณ„๋กœ ๋‚˜๋ˆ„์–ด ์ฒ˜๋ฆฌ
140
+ lines = text.split('\n')
141
+ result_lines = []
142
+
143
+ for line in lines:
144
+ if "๋‹ค์Œ ์„น์…˜์—์„œ๋Š”" in line:
145
+ parts = line.split("๋‹ค์Œ ์„น์…˜์—์„œ๋Š”")
146
+ if parts[0].strip():
147
+ result_lines.append(parts[0].strip())
148
+ else:
149
+ # ๋ถˆํ•„์š”ํ•œ ํ‘œํ˜„ ์ œ๊ฑฐ (๊ตฌ๋‘์  ํฌํ•จ)
150
+ for phrase in unwanted_phrases:
151
+ # ๋ถˆํ•„์š”ํ•œ ํ‘œํ˜„ ์•ž๋’ค์˜ ๊ตฌ๋‘์ ๊ณผ ๊ณต๋ฐฑ๊นŒ์ง€ ํฌํ•จํ•˜์—ฌ ์ œ๊ฑฐ
152
+ pattern = rf'(\b{re.escape(phrase)}\b[\s,.!?]*)|([,.!?]*\b{re.escape(phrase)}\b)'
153
+ line = re.sub(pattern, '', line)
154
+
155
+ # ๋ฌธ์žฅ ๋‚ด ์ž”์—ฌ ๊ณต๋ฐฑ ๋ฐ ๊ตฌ๋‘์  ์ •๋ฆฌ
156
+ line = re.sub(r'\s{2,}', ' ', line) # ์—ฐ์† ๊ณต๋ฐฑ ์ œ๊ฑฐ
157
+ line = line.strip() # ์•ž๋’ค ๊ณต๋ฐฑ ์ œ๊ฑฐ
158
+ result_lines.append(line)
159
+
160
+ return '\n'.join(result_lines)
161
+
162
+ def get_outline_prompt(category):
163
+ if (category == "ํ•ต์‹ฌ๊ธฐ๋Šฅ์ง‘์ค‘ํ˜•"):
164
+ return """
165
+ [์ƒํ’ˆ๋ฆฌ๋ทฐ ์†Œ์ฃผ์ œ(Outline) ์ƒ์„ฑ ๊ทœ์น™]
166
+ [๊ธฐ๋ณธ๊ทœ์น™]
167
+ 1. ๋ฐ˜๋“œ์‹œ ํ•œ๊ตญ์–ด(ํ•œ๊ธ€)๋กœ ์ž‘์„ฑํ•˜๋ผ
168
+ 2. ๋ฐ˜๋“œ์‹œ ์ƒํ’ˆ์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ 3๊ฐœ๋งŒ ์„ ์ •ํ•˜๋ผ
169
+ - ํ•ต์‹ฌ๊ธฐ๋Šฅ์€ ์ฐธ๊ณ ๊ธ€์„ ๋ถ„์„ํ•˜์—ฌ ์„ ์ •ํ•˜๋ผ
170
+ 4. ๋ฐ˜๋“œ์‹œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ 3๊ฐœ์— ๋Œ€ํ•œ ํฅ๋ฏธ๋กœ์šด ์†Œ์ œ๋ชฉ๋งŒ ์ž‘์„ฑํ•˜๋ผ(์ ˆ๋Œ€ ๋‚ด์šฉ ์ž‘์„ฑ ๊ธˆ์ง€)
171
+ 5. ๋ฐ˜๋“œ์‹œ ๋งˆํฌ๋‹ค์šด ํ˜•์‹์ด ์•„๋‹Œ ์ˆœ์ˆ˜ํ•œ ํ…์ŠคํŠธ๋กœ ์ถœ๋ ฅํ•˜๋ผ
172
+ 6. ์†Œ์ œ๋ชฉ์€ ๋ฐ˜๋“œ์‹œ 30์ž ์ด๋‚ด๋กœ ์ž‘์„ฑํ•˜๋ผ
173
+ [์ถœ๋ ฅ์˜ˆ์‹œ]
174
+ ํ•ต์‹ฌ๊ธฐ๋Šฅ : ์„ ์ •ํ•œ ํ•ต์‹ฌ๊ธฐ๋Šฅ1์˜ ์†Œ์ œ๋ชฉ
175
+ ํ•ต์‹ฌ๊ธฐ๋Šฅ : ์„ ์ •ํ•œ ํ•ต์‹ฌ๊ธฐ๋Šฅ2์˜ ์†Œ์ œ๋ชฉ
176
+ ํ•ต์‹ฌ๊ธฐ๋Šฅ : ์„ ์ •ํ•œ ํ•ต์‹ฌ๊ธฐ๋Šฅ3์˜ ์†Œ์ œ๋ชฉ
177
+ """
178
+
179
+ def get_blog_post_prompt(category):
180
+ if (category == "ํ•ต์‹ฌ๊ธฐ๋Šฅ์ง‘์ค‘ํ˜•"):
181
+ return """
182
+ [์ƒํ’ˆ๋ฆฌ๋ทฐ ์ฝ˜ํ…์ธ  ์ƒ์„ฑ ๊ทœ์น™]
183
+ [๊ธฐ๋ณธ๊ทœ์น™]
184
+ 1. ๋ฐ˜๋“œ์‹œ ํ•œ๊ตญ์–ด(ํ•œ๊ธ€)๋กœ ์ž‘์„ฑํ•˜๋ผ
185
+ 2. ๋ฐ˜๋“œ์‹œ ์ฃผ์–ด์ง„ ํ•ต์‹ฌ๊ธฐ๋Šฅ 1๊ฐœ์˜ ์ฃผ์ œ์— ๋Œ€ํ•ด์„œ๋งŒ ์ž‘์„ฑํ•˜๋ผ
186
+ - ์ ˆ๋Œ€๋กœ ์ฃผ์–ด์ง„ ํ•ต์‹ฌ๊ธฐ๋Šฅ 1๊ฐœ์˜ ์ฃผ์ œ ์ด์™ธ์˜ ๋‚ด์šฉ์„ ์ž‘์„ฑํ•˜์ง€ ๋ง ๊ฒƒ
187
+ 3. ์ฃผ์–ด์ง„ ํ•ต์‹ฌ ๊ธฐ๋Šฅ 1๊ฐœ์— ๋Œ€ํ•œ ํŠน์žฅ์ , ๊ฐ์ข… ์ •๋ณด, ํŒ ๋“ฑ์„ ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๋ผ
188
+ 4. ์ „๋ฌธ ์šฉ์–ด๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๋„ ์ดํ•ด๊ฐ€ ๋˜๋„๋ก ํ’€์–ด์„œ ์„ค๋ช…ํ•˜๋ผ
189
+ 5. ๋งˆํฌ๋‹ค์šด ํ˜•์‹์œผ๋กœ ์ž‘์„ฑํ•˜๋ผ๋ผ
190
+ [ํ…์ŠคํŠธ ์ž‘์„ฑ ๊ทœ์น™]
191
+ 1. ๋ฐ˜๋“œ์‹œ ์ž…๋ ฅ๋œ ์ฐธ๊ณ ๊ธ€ ์•ˆ์—์„œ ํ•ต์‹ฌ๊ธฐ๋Šฅ 1๊ฐœ์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ์ž‘์„ฑ
192
+ 2. ์ ˆ๋Œ€๋กœ ์ฃผ์–ด์ง„ ํ•ต์‹ฌ๊ธฐ๋Šฅ 1๊ฐœ์˜ ์ฃผ์ œ ์ด์™ธ์˜ ๋‚ด์šฉ์„ ์ž‘์„ฑํ•˜์ง€ ๋ง ๊ฒƒ
193
+ 3. ์ œ๊ณต๋œ ์ฐธ๊ณ ๊ธ€์˜ ์–ดํˆฌ๋ฅผ ๋ฐ˜์˜ํ•˜๋˜, ์ ˆ๋Œ€๋กœ ํ•œ ๋ฌธ์žฅ ์ด์ƒ ๊ทธ๋Œ€๋กœ ์ถœ๋ ฅํ•˜์ง€ ๋ง ๊ฒƒ
194
+ 4. ์‰ฝ๊ฒŒ ์ฝํž ์ˆ˜ ์žˆ๋„๋ก ์‰ฌ์šด ์–ดํœ˜๋กœ ์ž‘์„ฑ
195
+ 5. ํ•ต์‹ฌ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์†Œ๋น„์ž ํƒ€๊ฒŸ์„ ๋ถ„์„ํ•˜์—ฌ ์ž‘์„ฑ
196
+ 6. ์ฃผ์–ด์ง„ ํ•ต์‹ฌ๊ธฐ๋Šฅ 1๊ฐœ์— ๋งž๋Š” ์ŠคํŽ™, ๊ธฐ๋Šฅ, ์„ฑ๋Šฅ, ์žฅ๋‹จ์ , ๊ฐ€๊ฒฉ ๋Œ€๋น„ ์„ฑ๋Šฅ(๊ฐ€์„ฑ๋น„), ํŒ, ์ฃผ์˜์‚ฌํ•ญ ๋“ฑ์„ ์ž‘์„ฑ
197
+ 7. ์ฃผ์–ด์ง„ ํ•ต์‹ฌ๊ธฐ๋Šฅ 1๊ฐœ์™€ ๊ด€๋ จ๋œ ๊ตฌ์ฒด์ ์ธ ์ˆ˜์น˜(๋ฐ์ดํ„ฐ)๊ฐ€ ์žˆ๋‹ค๋ฉด ๋ฐ˜์˜ํ•˜๋ผ
198
+ 8. ๋ฐ˜๋“œ์‹œ ํ•ต์‹ฌ๊ธฐ๋Šฅ 1๊ฐœ์— ๋Œ€ํ•œ ์ฝ˜ํ…์ธ ๋งŒ 1800์ž ์ด์ƒ ์ž‘์„ฑํ•˜๋ผ
199
+ """
200
+
201
+ def get_style_prompt(style):
202
+ prompts = {
203
+ "์นœ๊ทผํ•œ": """
204
+ [์นœ๊ทผํ•œ ํฌ์ŠคํŒ… ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ]
205
+ 1. ํ†ค๊ณผ ์–ด์กฐ
206
+ - ๋Œ€ํ™”ํ•˜๋“ฏ ํŽธ์•ˆํ•˜๊ณ  ์นœ๊ทผํ•œ ๋งํˆฌ ์‚ฌ์šฉ
207
+ 2. ๋ฌธ์žฅ ๋ฐ ์–ดํˆฌ
208
+ - ๋ฐ˜๋“œ์‹œ 'ํ•ด์š”์ฒด'๋กœ ์ž‘์„ฑ, ์ ˆ๋Œ€ '์Šต๋‹ˆ๋‹ค'์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ง ๊ฒƒ.
209
+ - '~์š”'๋กœ ๋๋‚˜๋„๋ก ์ž‘์„ฑ, '~๋‹ค'๋กœ ๋๋‚˜์ง€ ์•Š๊ฒŒ ํ•˜๋ผ
210
+ - ๊ตฌ์–ด์ฒด ํ‘œํ˜„ ์‚ฌ์šฉ (์˜ˆ: "~ํ–ˆ์–ด์š”", "~์ธ ๊ฒƒ ๊ฐ™์•„์š”")
211
+ 3. ์šฉ์–ด ๋ฐ ์„ค๋ช… ๋ฐฉ์‹
212
+ - ์ „๋ฌธ ์šฉ์–ด ๋Œ€์‹  ์‰ฌ์šด ๋‹จ์–ด๋กœ ํ’€์–ด์„œ ์„ค๋ช…
213
+ - ๋น„์œ ๋‚˜ ์€์œ ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ณต์žกํ•œ ๊ฐœ๋… ์„ค๋ช…
214
+ - ์ˆ˜์‚ฌ์˜๋ฌธ๋ฌธ ํ™œ์šฉํ•˜์—ฌ ๋…์ž์™€ ์†Œํ†ตํ•˜๋Š” ๋Š๋‚Œ ์ฃผ๊ธฐ
215
+ ์ฃผ์˜์‚ฌํ•ญ: ๋„ˆ๋ฌด ๊ฐ€๋ฒผ์šด ํ†ค์€ ์ง€์–‘ํ•˜๊ณ , ์ฃผ์ œ์˜ ์ค‘์š”์„ฑ์„ ํ•ด์น˜์ง€ ์•Š๋Š” ์„ ์—์„œ ์นœ๊ทผํ•จ ์œ ์ง€
216
+ (์˜ˆ์‹œ: ์ž‡๋‹˜๋“ค~ ์˜ค๋ ˆ์˜ค ์ฝ”์นด์ฝœ๋ผ๋ง›์ด์ƒˆ๋กœ ์ถœ์‹œ๊ฐ€ ๋๋‹ค๋Š”๊ฑฐ ์•Œ๊ณ  ๊ณ„์…จ๋‚˜์š”?!ใ…Ž ์˜ค๋ ˆ์˜ค ์ฝ”์นด์ฝœ๋ผ๋ง›์€ ์–ด๋–ค์ง€ ์†”์งํ‰๊ณผ๊ตฌ๋งค์ •๋ณด, ๊ฐ€๊ฒฉ, ์นผ๋กœ๋ฆฌ ๋“ฑ์— ๋Œ€ํ•ด ์ž์„ธ~ ํžˆ ์ ์–ด๋ณด๋„๋ก ํ• ๊ป˜์š”! ์˜ค๋ ˆ์˜ค๋ฅผ ์ข‹์•„ํ•˜๋Š” ์•„๋“ค์—๊ฒŒ๊ฐ„์‹์œผ๋กœ ์˜ค๋ ˆ์˜ค ์ฝ”์นด์ฝœ๋ผ๋ง›์„ ์คฌ๋”๋‹ˆ๋ง›์žˆ๋‹ค๊ณ  ์ข‹์•„ํ•˜๋”๋ผ๊ตฌ์š”. ์ฝœ๋ผํ–ฅ์ด ๋‚˜์„œ ๋” ๋งˆ์Œ์— ๋“ ๋‹ค๋ฉฐใ…Ž๊ฐœ์ธ์ ์œผ๋กœ๋Š” ๋ณ„ โญ๏ธโญ๏ธโญ๏ธ.์š”๊ฑด ๊ฐœ์ธ์ฐจ๊ฐ€ ์žˆ์„๊ฑฐ ๊ฐ™์•„์š”~)
217
+ """,
218
+ "์ผ๋ฐ˜": """
219
+ #์ผ๋ฐ˜์ ์ธ ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŒ… ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ
220
+ 1. ํ†ค๊ณผ ์–ด์กฐ
221
+ - ์ค‘๋ฆฝ์ ์ด๊ณ  ๊ฐ๊ด€์ ์ธ ํ†ค ์œ ์ง€
222
+ - ์ ์ ˆํ•œ ์กด๋Œ“๋ง ์‚ฌ์šฉ (์˜ˆ: "~ํ•ฉ๋‹ˆ๋‹ค", "~์ž…๋‹ˆ๋‹ค")
223
+ 2. ๋‚ด์šฉ ๊ตฌ์กฐ ๋ฐ ์ „๊ฐœ
224
+ - ๋ช…ํ™•ํ•œ ์ฃผ์ œ ์ œ์‹œ๋กœ ์‹œ์ž‘
225
+ - ๋…ผ๋ฆฌ์ ์ธ ์ˆœ์„œ๋กœ ์ •๋ณด ์ „๊ฐœ
226
+ - ์ฃผ์š” ํฌ์ธํŠธ๋ฅผ ๊ฐ•์กฐํ•˜๋Š” ์†Œ์ œ๋ชฉ ํ™œ์šฉ
227
+ - ์ ์ ˆํ•œ ๊ธธ์ด์˜ ๋‹จ๋ฝ์œผ๋กœ ๊ตฌ์„ฑ
228
+ 3. ์šฉ์–ด ๋ฐ ์„ค๋ช… ๋ฐฉ์‹
229
+ - ์ผ๋ฐ˜์ ์œผ๋กœ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ์šฉ์–ด ์„ ํƒ
230
+ - ํ•„์š”์‹œ ๊ฐ„๋‹จํ•œ ์„ค๋ช… ์ถ”๊ฐ€
231
+ - ๊ฐ๊ด€์ ์ธ ์ •๋ณด ์ œ๊ณต์— ์ค‘์ 
232
+ 4. ํ…์ŠคํŠธ ๊ตฌ์กฐํ™”
233
+ - ๋ถˆ๋ฆฟ ํฌ์ธํŠธ๋‚˜ ๋ฒˆํ˜ธ ๋งค๊ธฐ๊ธฐ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ •๋ณด ๊ตฌ์กฐํ™”
234
+ - ์ค‘์š”ํ•œ ์ •๋ณด๋Š” ๊ตต์€ ๊ธ€์”จ๋‚˜ ๊ธฐ์šธ์ž„๊ผด๋กœ ๊ฐ•์กฐ
235
+ 5. ๋…์ž ์ƒํ˜ธ์ž‘์šฉ
236
+ - ์ ์ ˆํžˆ ๋…์ž์˜ ์ƒ๊ฐ์„ ๋ฌป๋Š” ์งˆ๋ฌธ ํฌํ•จ
237
+ - ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ํ‚ค์›Œ๋“œ ์ œ์‹œ
238
+ 6. ๋งˆ๋ฌด๋ฆฌ
239
+ - ์ฃผ์š” ๋‚ด์šฉ ๊ฐ„๋‹จํžˆ ์š”์•ฝ
240
+ - ์ถ”๊ฐ€ ์ •๋ณด์— ๋Œ€ํ•œ ์•ˆ๋‚ด ์ œ๊ณต
241
+ ์ฃผ์˜์‚ฌํ•ญ: ๋„ˆ๋ฌด ๋”ฑ๋”ฑํ•˜๊ฑฐ๋‚˜ ์ง€๋ฃจํ•˜์ง€ ์•Š๋„๋ก ๊ท ํ˜• ์œ ์ง€
242
+ ์˜ˆ์‹œ: "์ตœ๊ทผ ํ™˜๊ฒฝ ๋ฌธ์ œ๊ฐ€ ๋Œ€๋‘๋˜๋ฉด์„œ '์ œ๋กœ ์›จ์ด์ŠคํŠธ' ๋ผ์ดํ”„์Šคํƒ€์ผ์— ๋Œ€ํ•œ ๊ด€์‹ฌ์ด ๋†’์•„์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ œ๋กœ ์›จ์ด์ŠคํŠธ๋ž€ ์ผ์ƒ์ƒํ™œ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์“ฐ๋ ˆ๊ธฐ๋ฅผ ์ตœ์†Œํ™”ํ•˜๋Š” ์ƒํ™œ ๋ฐฉ์‹์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธ€์—์„œ๋Š” ์ œ๋กœ ์›จ์ด์ŠคํŠธ์˜ ๊ฐœ๋…, ์‹ค์ฒœ ๋ฐฉ๋ฒ•, ๊ทธ๋ฆฌ๊ณ  ๊ทธ ํšจ๊ณผ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋จผ์ € ์ œ๋กœ ์›จ์ด์ŠคํŠธ์˜ ์ •์˜๋ถ€ํ„ฐ ์‚ดํŽด๋ณด๋ฉด...
243
+ """,
244
+ "์ „๋ฌธ์ ์ธ": """
245
+ #์ „๋ฌธ์ ์ธ ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŒ… ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ
246
+ 1. ํ†ค๊ณผ ๊ตฌ์กฐ
247
+ - ๊ณต์‹์ ์ด๊ณ  ํ•™์ˆ ์ ์ธ ํ†ค ์‚ฌ์šฉ
248
+ - ๊ฐ๊ด€์ ์ด๊ณ  ๋ถ„์„์ ์ธ ์ ‘๊ทผ ์œ ์ง€
249
+ - ๋ช…ํ™•ํ•œ ์„œ๋ก , ๋ณธ๋ก , ๊ฒฐ๋ก  ๊ตฌ์กฐ
250
+ - ์ฒด๊ณ„์ ์ธ ๋…ผ์  ์ „๊ฐœ
251
+ - ์„ธ๋ถ€ ์„น์…˜์„ ์œ„ํ•œ ๋ช…ํ™•ํ•œ ์†Œ์ œ๋ชฉ ์‚ฌ์šฉ
252
+ 2. ๋‚ด์šฉ ๊ตฌ์„ฑ ๋ฐ ์ „๊ฐœ
253
+ - ๋ณต์žกํ•œ ๊ฐœ๋…์„ ์ •ํ™•ํžˆ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์žฅ ๊ตฌ์กฐ ์‚ฌ์šฉ
254
+ - ๋…ผ๋ฆฌ์  ์—ฐ๊ฒฐ์„ ์œ„ํ•œ ์ „ํ™˜์–ด ํ™œ์šฉ
255
+ - ํ•ด๋‹น ๋ถ„์•ผ์˜ ์ „๋ฌธ ์šฉ์–ด ์ ๊ทน ํ™œ์šฉ (ํ•„์š”์‹œ ๊ฐ„๋žตํ•œ ์„ค๋ช… ์ œ๊ณต)
256
+ - ์‹ฌ์ธต์ ์ธ ๋ถ„์„๊ณผ ๋น„ํŒ์  ์‚ฌ๊ณ  ์ „๊ฐœ
257
+ - ๋‹ค์–‘ํ•œ ๊ด€์  ์ œ์‹œ ๋ฐ ๋น„๊ต
258
+ 3. ๋ฐ์ดํ„ฐ ๋ฐ ๊ทผ๊ฑฐ ํ™œ์šฉ
259
+ - ํ†ต๊ณ„, ์—ฐ๊ตฌ ๊ฒฐ๊ณผ, ์ „๋ฌธ๊ฐ€ ์˜๊ฒฌ ๋“ฑ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์ถœ์ฒ˜ ์ธ์šฉ
260
+ - ํ•„์š”์‹œ ๊ฐ์ฃผ๋‚˜ ์ฐธ๊ณ ๋ฌธํ—Œ ๋ชฉ๋ก ํฌํ•จ
261
+ - ์ˆ˜์น˜ ๋ฐ์ดํ„ฐ๋Š” ํ…์ŠคํŠธ๋กœ ๋ช…ํ™•ํžˆ ์„ค๋ช…
262
+ 4. ํ…์ŠคํŠธ ๊ตฌ์กฐํ™”
263
+ - ๋…ผ๋ฆฌ์  ๊ตฌ์กฐ๋ฅผ ๊ฐ•์กฐํ•˜๊ธฐ ์œ„ํ•ด ๋ฒˆํ˜ธ ๋งค๊ธฐ๊ธฐ ์‚ฌ์šฉ
264
+ - ํ•ต์‹ฌ ๊ฐœ๋…์ด๋‚˜ ์šฉ์–ด๋Š” ๊ธฐ์šธ์ž„๊ผด๋กœ ๊ฐ•์กฐ
265
+ - ๊ธด ์ธ์šฉ๋ฌธ์€ ๋“ค์—ฌ์“ฐ๊ธฐ๋กœ ๊ตฌ๋ถ„
266
+ 5. ๋งˆ๋ฌด๋ฆฌ
267
+ - ํ•ต์‹ฌ ๋…ผ์  ์žฌ๊ฐ•์กฐ
268
+ - ํ–ฅํ›„ ์—ฐ๊ตฌ ๋ฐฉํ–ฅ์ด๋‚˜ ์‹ค๋ฌด์  ํ•จ์˜ ์ œ์‹œ
269
+ ์ฃผ์˜์‚ฌํ•ญ: ์ „๋ฌธ์„ฑ์„ ์œ ์ง€ํ•˜๋˜, ์™„์ „ํžˆ ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์šด ์ˆ˜์ค€์€ ์ง€์–‘
270
+ ์˜ˆ์‹œ: "๋ณธ ์—ฐ๊ตฌ์—์„œ๋Š” ์ธ๊ณต์ง€๋Šฅ(AI)์˜ ์œค๋ฆฌ์  ํ•จ์˜์— ๋Œ€ํ•ด ๊ณ ์ฐฐํ•œ๋‹ค. ํŠนํžˆ, ์ž์œจ์ฃผํ–‰ ์ž๋™์ฐจ์˜ ์˜์‚ฌ๊ฒฐ์ • ์•Œ๊ณ ๋ฆฌ์ฆ˜์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์œค๋ฆฌ์  ๋”œ๋ ˆ๋งˆ์— ์ดˆ์ ์„ ๋งž์ถ˜๋‹ค. Bonnefon et al. (2016)์˜ ์—ฐ๊ตฌ์— ๋”ฐ๋ฅด๋ฉด, ์ž์œจ์ฃผํ–‰ ์ฐจ๋Ÿ‰์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์ง๋ฉดํ•  ์ˆ˜ ์žˆ๋Š” ์œค๋ฆฌ์  ์„ ํƒ์˜ ๋ณต์žก์„ฑ์ด ์ง€์ ๋œ ๋ฐ” ์žˆ๋‹ค. ๋ณธ๊ณ ์—์„œ๋Š” ์ด๋Ÿฌํ•œ ์œค๋ฆฌ์  ๋”œ๋ ˆ๋งˆ๋ฅผ ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ๊ด€์ ์—์„œ ๋ถ„์„ํ•œ๋‹ค: 1) ๊ณต๋ฆฌ์ฃผ์˜์  ์ ‘๊ทผ, 2) ์˜๋ฌด๋ก ์  ์ ‘๊ทผ, 3) ๋• ์œค๋ฆฌ์  ์ ‘๊ทผ. ๊ฐ ์ ‘๊ทผ๋ฒ•์˜ ์žฅ๋‹จ์ ์„ ๋น„๊ต ๋ถ„์„ํ•˜๊ณ , ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ž์œจ์ฃผํ–‰ ์ฐจ๋Ÿ‰์˜ ์œค๋ฆฌ์  ์˜์‚ฌ๊ฒฐ์ • ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ œ์•ˆํ•˜๊ณ ์ž ํ•œ๋‹ค...
271
+ """
272
+ }
273
+ return prompts.get(style, "ํฌ์ŠคํŒ… ์Šคํƒ€์ผ ํ”„๋กฌํ”„ํŠธ")
274
+
275
+ def split_titles(suggested_titles):
276
+ titles = suggested_titles.split('\n')
277
+ titles = [re.sub(r'^(1\.|2\.|3\.|4\.|5\.|6\.|7\.|8\.|9\.|10\.|## |# |\* |\*\* |\*\*\*)', '', title.strip()) for title in titles if title.strip()]
278
+ titles = titles[::-1] # ๋ฆฌ์ŠคํŠธ๋ฅผ ์—ญ์ˆœ์œผ๋กœ ์ •๋ ฌ
279
+ titles += [""] * (10 - len(titles)) # 10๊ฐœ๋ณด๋‹ค ์ ์œผ๋ฉด ๋นˆ ๋ฌธ์ž์—ด๋กœ ์ฑ„์šฐ๊ธฐ
280
+ return titles[:10] # ์ตœ๋Œ€ 10๊ฐœ์˜ ์ œ๋ชฉ๋งŒ ๋ฐ˜ํ™˜
281
+
282
+ class PDF(FPDF):
283
+ def __init__(self):
284
+ super().__init__(orientation='P', unit='mm', format='A4')
285
+ self.set_margins(10, 10, 10)
286
+ current_dir = os.path.dirname(__file__)
287
+ self.add_font("NanumGothic", "", os.path.join(current_dir, "NanumGothic.ttf"))
288
+ self.add_font("NanumGothic", "B", os.path.join(current_dir, "NanumGothicBold.ttf"))
289
+ self.add_font("NanumGothicExtraBold", "", os.path.join(current_dir, "NanumGothicExtraBold.ttf"))
290
+ self.add_font("NanumGothicLight", "", os.path.join(current_dir, "NanumGothicLight.ttf"))
291
+
292
+ def header(self):
293
+ self.set_font('NanumGothic', '', 10)
294
+ # ํ—ค๋” ๋‚ด์šฉ ์ถ”๊ฐ€ (ํ•„์š”ํ•œ ๊ฒฝ์šฐ)
295
+
296
+ def footer(self):
297
+ self.set_y(-15)
298
+ self.set_font('NanumGothic', '', 8)
299
+ self.cell(0, 10, f'Page {self.page_no()}', 0, 0, 'C')
300
+
301
+ def chapter_title(self, title):
302
+ self.set_font("NanumGothic", 'B', 12)
303
+ self.cell(0, 6, title, 0, 1, 'L')
304
+ self.ln(4)
305
+
306
+ def chapter_body(self, body):
307
+ self.set_font("NanumGothic", '', 11)
308
+ self.multi_cell(0, 5, body)
309
+ self.ln()
310
+
311
+ def print_chapter(self, title, body):
312
+ self.add_page()
313
+ self.chapter_title(title)
314
+ self.chapter_body(body)
315
+
316
+ def format_filename(text):
317
+ if not isinstance(text, str):
318
+ text = str(text) # ๋ฌธ์ž์—ด์ด ์•„๋‹Œ ๊ฒฝ์šฐ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜
319
+ text = re.sub(r'[^\w\s-]', '', text)
320
+ return text[:50].strip()
321
+
322
+ def save_to_pdf(blog_post, outline):
323
+ try:
324
+ pdf = PDF()
325
+ pdf.add_page()
326
+ # HTML ํƒœ๊ทธ๋ฅผ ํŒŒ์‹ฑํ•˜๊ธฐ ์œ„ํ•œ ์ •๊ทœํ‘œํ˜„์‹
327
+ tag_pattern = re.compile(r'<(/?)(\w+)([^>]*)>')
328
+ # ํ˜„์žฌ ๋‚ ์งœ์™€ ์‹œ๊ฐ„์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค (๋Œ€ํ•œ๋ฏผ๊ตญ ์‹œ๊ฐ„ ๊ธฐ์ค€)
329
+ now = datetime.now(ZoneInfo("Asia/Seoul"))
330
+ date_str = now.strftime("%y%m%d")
331
+ time_str = now.strftime("%H%M")
332
+ # ์ฒซ ๋ฒˆ์งธ ์ œ๋ชฉ์„ ์ฐพ์•„ ํŒŒ์ผ๋ช…์œผ๋กœ ์‚ฌ์šฉ
333
+ filename = f"{date_str}_{time_str}_{format_filename(outline)}.pdf"
334
+ # HTML ๋‚ด์šฉ์„ ์ˆœํšŒํ•˜๋ฉฐ PDF์— ์ž‘์„ฑ
335
+ current_tag = ''
336
+ buffer = ''
337
+ for part in re.split(tag_pattern, blog_post):
338
+ # HTML ํƒœ๊ทธ๊ฐ€ ๋“ฑ์žฅํ•œ ๊ฒฝ์šฐ
339
+ if part in ['h1', 'h2', 'h3', 'p', 'strong', 'li', 'br']:
340
+ # ์ด์ „ ํƒœ๊ทธ์˜ ๋‚ด์šฉ์„ ์ฒ˜๋ฆฌ
341
+ if buffer:
342
+ if current_tag in ['h1', 'h2', 'h3']:
343
+ pdf.chapter_title(buffer.strip()) # ์†Œ์ œ๋ชฉ ์ฒ˜๋ฆฌ
344
+ elif current_tag == 'p':
345
+ pdf.chapter_body(buffer.strip()) # ์ผ๋ฐ˜ ๋ฌธ๋‹จ ์ฒ˜๋ฆฌ
346
+ elif current_tag == 'strong':
347
+ pdf.set_font("NanumGothic", 'B', 11) # ๊ตต์€ ๊ธ€์”จ ์ฒ˜๋ฆฌ
348
+ pdf.cell(0, 5, buffer.strip(), 0, 1)
349
+ pdf.set_font("NanumGothic", '', 11) # ๋‹ค์‹œ ๊ธฐ๋ณธ ํฐํŠธ๋กœ ๋ณ€๊ฒฝ
350
+ elif current_tag == 'li':
351
+ pdf.chapter_body("โ€ข " + buffer.strip()) # ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ ์ฒ˜๋ฆฌ
352
+ elif current_tag == 'br':
353
+ pdf.ln(5) # ์ค„๋ฐ”๊ฟˆ ์ฒ˜๋ฆฌ
354
+ # ํ˜„์žฌ ํƒœ๊ทธ์™€ ๋ฒ„ํผ ์ดˆ๊ธฐํ™”
355
+ buffer = ''
356
+ current_tag = part
357
+ # ์ข…๋ฃŒ ํƒœ๊ทธ๋Š” ๋ฌด์‹œ (div ํฌํ•จ)
358
+ elif part.startswith('/'):
359
+ continue
360
+ # ํ…์ŠคํŠธ ๋ถ€๋ถ„ ์ฒ˜๋ฆฌ
361
+ elif not tag_pattern.match(part) and part.strip() != 'div':
362
+ buffer += part
363
+ # ๋งˆ์ง€๋ง‰ ๋ฒ„ํผ ์ฒ˜๋ฆฌ
364
+ if buffer:
365
+ if current_tag in ['h1', 'h2', 'h3']:
366
+ pdf.chapter_title(buffer.strip()) # ์ œ๋ชฉ ํ˜•์‹์œผ๋กœ ์ฒ˜๋ฆฌ
367
+ elif current_tag == 'p':
368
+ pdf.chapter_body(buffer.strip()) # ๋ณธ๋ฌธ ํ˜•์‹์œผ๋กœ ์ฒ˜๋ฆฌ
369
+ # PDF ์ €์žฅ
370
+ print(f"Saving PDF as: {filename}")
371
+ pdf.output(filename, 'F') # 'F' ์˜ต์…˜ ์ถ”๊ฐ€
372
+ return filename
373
+ except Exception as e:
374
+ print(f"PDF ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
375
+ import traceback
376
+ traceback.print_exc() # ์ƒ์„ธํ•œ ์˜ค๋ฅ˜ ์ •๋ณด ์ถœ๋ ฅ
377
+ return None # ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ None ๋ฐ˜ํ™˜
378
+
379
+ def save_content_to_pdf(blog_post, outline):
380
+ pdf_filename = save_to_pdf(blog_post, outline)
381
+ if pdf_filename:
382
+ return pdf_filename
383
+ else:
384
+ return None
385
+
386
+ title = "ํ•ต์‹ฌ๊ธฐ๋Šฅ์ง‘์ค‘ํ˜•"
387
+
388
+ with gr.Blocks() as demo:
389
+ gr.Markdown(f"# ํ•ต์‹ฌ๊ธฐ๋Šฅ์ง‘์ค‘ํ˜•")
390
+
391
+ gr.Markdown("### 1๋‹จ๊ณ„: ํฌ์ŠคํŒ… ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ์ง€์ •ํ•ด์ฃผ์„ธ์š”", elem_id="step-title")
392
+ category = gr.Radio(choices=["ํ•ต์‹ฌ๊ธฐ๋Šฅ์ง‘์ค‘ํ˜•"], label="ํฌ์ŠคํŒ… ์นดํ…Œ๊ณ ๋ฆฌ", value="ํ•ต์‹ฌ๊ธฐ๋Šฅ์ง‘์ค‘ํ˜•")
393
+
394
+ gr.Markdown("---\n\n")
395
+
396
+ gr.Markdown("### 2๋‹จ๊ณ„: ํฌ์ŠคํŒ… ์Šคํƒ€์ผ์„ ์„ ํƒํ•ด์ฃผ์„ธ์š”", elem_id="step-title")
397
+ style = gr.Radio(choices=["์นœ๊ทผํ•œ", "์ผ๋ฐ˜", "์ „๋ฌธ์ ์ธ"], label="ํฌ์ŠคํŒ… ์Šคํƒ€์ผ", value="์นœ๊ทผํ•œ")
398
+
399
+ gr.Markdown("---\n\n")
400
+
401
+ gr.Markdown("### 3๋‹จ๊ณ„: ์ฐธ๊ณ  ๊ธ€์„ ์ž…๋ ฅํ•˜์„ธ์š”", elem_id="step-title")
402
+ references1 = gr.Textbox(label="์ฐธ๊ณ  ๊ธ€ 1", placeholder="์ฐธ๊ณ ํ•  ๊ธ€์„ ๋ณต์‚ฌํ•˜์—ฌ ๋ถ™์—ฌ๋„ฃ์œผ์„ธ์š”", lines=10)
403
+ references2 = gr.Textbox(label="์ฐธ๊ณ  ๊ธ€ 2", placeholder="์ฐธ๊ณ ํ•  ๊ธ€์„ ๋ณต์‚ฌํ•˜์—ฌ ๋ถ™์—ฌ๋„ฃ์œผ์„ธ์š”", lines=10)
404
+ references3 = gr.Textbox(label="์ฐธ๊ณ  ๊ธ€ 3", placeholder="์ฐธ๊ณ ํ•  ๊ธ€์„ ๋ณต์‚ฌํ•˜์—ฌ ๋ถ™์—ฌ๋„ฃ์œผ์„ธ์š”", lines=10)
405
+
406
+ gr.Markdown("---\n\n")
407
+
408
+ gr.Markdown("### 4๋‹จ๊ณ„: ํ•ต์‹ฌ๊ธฐ๋Šฅ์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”", elem_id="step-title")
409
+ gr.HTML("<span style='color: grey;'>[๋‚˜์˜จ ๊ฒฐ๊ณผ๋ฅผ ์ˆ˜์ •ํ•ด์„œ ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”]</span>")
410
+
411
+ outline_generate_btn = gr.Button("ํ•ต์‹ฌ๊ธฐ๋Šฅ ์„ ์ •ํ•˜๊ธฐ")
412
+ outline_result1 = gr.Textbox(label="ํ•ต์‹ฌ๊ธฐ๋Šฅ 1", lines=2)
413
+ outline_result2 = gr.Textbox(label="ํ•ต์‹ฌ๊ธฐ๋Šฅ 2", lines=2)
414
+ outline_result3 = gr.Textbox(label="ํ•ต์‹ฌ๊ธฐ๋Šฅ 3", lines=2)
415
+ outline_input = gr.Textbox(label="์ž‘์„ฑํ•  ํ•ต์‹ฌ๊ธฐ๋Šฅ ์ฃผ์ œ ์ค‘์— 1๊ฐœ๋งŒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”", placeholder="ํ•ต์‹ฌ๊ธฐ๋Šฅ 1๊ฐœ๋งŒ ์ž…๋ ฅํ•˜์„ธ์š”", lines=2)
416
+
417
+ outline_generate_btn.click(
418
+ fn=generate_outline,
419
+ inputs=[category, style, references1, references2, references3],
420
+ outputs=[outline_result1, outline_result2, outline_result3]
421
+ )
422
+
423
+ gr.Markdown("---\n\n")
424
+
425
+ gr.Markdown("### 5๋‹จ๊ณ„: ๊ธ€ ์ƒ์„ฑํ•˜๊ธฐ", elem_id="step-title")
426
+ gr.HTML("<span style='color: grey;'>[ํ•ต์‹ฌ๊ธฐ๋Šฅ์„ ํ™•์ธํ•˜์„ธ์š”]</span>")
427
+
428
+ generate_btn = gr.Button("๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑํ•˜๊ธฐ")
429
+ html_output = gr.HTML(label="์ƒ์„ฑ๋œ ๋ธ”๋กœ๊ทธ ๊ธ€")
430
+
431
+ generate_btn.click(
432
+ fn=generate_blog_post,
433
+ inputs=[category, style, references1, references2, references3, outline_input],
434
+ outputs=[html_output],
435
+ show_progress=True
436
+ )
437
 
438
+ save_pdf_btn = gr.Button("PDF๋กœ ์ €์žฅํ•˜๊ธฐ")
439
+ pdf_output = gr.File(label="์ƒ์„ฑ๋œ PDF ํŒŒ์ผ")
440
+
441
+ save_pdf_btn.click(
442
+ fn=save_content_to_pdf,
443
+ inputs=[html_output, outline_input], # outline_input ์ถ”๊ฐ€
444
+ outputs=[pdf_output],
445
+ show_progress=True
446
+ )
447
 
448
+ demo.launch()
 
 
 
449
 
450
+ gr.HTML("""
451
+ <style>
452
+ #step-title {
453
+ font-size: 1.7em;
454
+ font-weight: bold;
455
+ }
456
+ </style>
457
+ """)