ssboost commited on
Commit
7c34f04
ยท
verified ยท
1 Parent(s): 1775df5

Create feature_focus_blog.py

Browse files
Files changed (1) hide show
  1. feature_focus_blog.py +557 -0
feature_focus_blog.py ADDED
@@ -0,0 +1,557 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import random
3
+ import re
4
+ import requests
5
+ import logging
6
+ import tempfile
7
+ from bs4 import BeautifulSoup
8
+ from datetime import datetime
9
+ from zoneinfo import ZoneInfo
10
+ import html
11
+ from PIL import Image
12
+ from urllib.request import urlopen
13
+ import markdown2
14
+ import gradio as gr
15
+
16
+ # ๋กœ๊น… ์„ค์ • (INFO ๋ ˆ๋ฒจ)
17
+ logging.basicConfig(level=logging.INFO)
18
+
19
+ # ์ƒ์ˆ˜ ์ •์˜
20
+ TARGET_CHAR_LENGTH = 4000
21
+ MIN_SECTION_LENGTH = 600
22
+ MAX_TOKENS = 15000
23
+ TEMPERATURE = 0.75
24
+ TOP_P = 0.95
25
+
26
+ # API ๊ด€๋ จ ์„ค์ •
27
+ gemini_api_key = os.getenv("GEMINI_API_KEY")
28
+
29
+ # --- Google Gemini SDK ์ดˆ๊ธฐํ™” ---
30
+ from google import genai
31
+ from google.genai import types
32
+ client = genai.Client(api_key=gemini_api_key)
33
+
34
+ # -------------------------------
35
+ # ๊ธฐ๋ณธ ๋„์šฐ๋ฏธ ํ•จ์ˆ˜๋“ค
36
+ # -------------------------------
37
+
38
+ def remove_unwanted_phrases(text):
39
+ """๋ถˆํ•„์š”ํ•œ ํ‘œํ˜„ ์ œ๊ฑฐ ํ•จ์ˆ˜"""
40
+ unwanted_phrases = [
41
+ '์—ฌ๋Ÿฌ๋ถ„', '์ตœ๊ทผ', '๋งˆ์ง€๋ง‰์œผ๋กœ', '๊ฒฐ๋ก ์ ์œผ๋กœ', '๊ฒฐ๊ตญ',
42
+ '์ข…ํ•ฉ์ ์œผ๋กœ', '๋”ฐ๋ผ์„œ', '๋งˆ๋ฌด๋ฆฌ', '๋์œผ๋กœ', '์š”์•ฝ',
43
+ 'ํ•œ ์ค„ ์š”์•ฝ', '์ •๋ฆฌํ•˜์ž๋ฉด', '์ด์ •๋ฆฌ', '๊ธ€์„ ๋งˆ์น˜๋ฉฐ',
44
+ '์ด์ƒ์œผ๋กœ', '์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค', '์ฐธ๊ณ ํ•˜์„ธ์š”', '๋„์›€์ด ๋˜์…จ๊ธธ',
45
+ '์ข‹์€ ํ•˜๋ฃจ ๋˜์„ธ์š”', '๋‹ค์Œ ๊ธ€์—์„œ', '๋„์›€์ด ๋˜์—ˆ๊ธธ',
46
+ '์ฆ๊ฑฐ์šด ํ•˜๋ฃจ ๋˜์„ธ์š”', '๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค'
47
+ ]
48
+
49
+ # ๋ฌธ๋‹จ๋ณ„๋กœ ๋‚˜๋ˆ„์–ด ์ฒ˜๋ฆฌ
50
+ lines = text.split('\n')
51
+ result_lines = []
52
+
53
+ for line in lines:
54
+ if "๋‹ค์Œ ์„น์…˜์—์„œ๋Š”" in line:
55
+ parts = line.split("๋‹ค์Œ ์„น์…˜์—์„œ๋Š”")
56
+ if parts[0].strip():
57
+ result_lines.append(parts[0].strip())
58
+ else:
59
+ # ๋ถˆํ•„์š”ํ•œ ํ‘œํ˜„ ์ œ๊ฑฐ (๊ตฌ๋‘์  ํฌํ•จ)
60
+ for phrase in unwanted_phrases:
61
+ # ๋ถˆํ•„์š”ํ•œ ํ‘œํ˜„ ์•ž๋’ค์˜ ๊ตฌ๋‘์ ๊ณผ ๊ณต๋ฐฑ๊นŒ์ง€ ํฌํ•จํ•˜์—ฌ ์ œ๊ฑฐ
62
+ pattern = rf'(\b{re.escape(phrase)}\b[\s,.!?]*)|([,.!?]*\b{re.escape(phrase)}\b)'
63
+ line = re.sub(pattern, '', line)
64
+
65
+ # ๋ฌธ์žฅ ๋‚ด ์ž”์—ฌ ๊ณต๋ฐฑ ๋ฐ ๊ตฌ๋‘์  ์ •๋ฆฌ
66
+ line = re.sub(r'\s{2,}', ' ', line) # ์—ฐ์† ๊ณต๋ฐฑ ์ œ๊ฑฐ
67
+ line = line.strip() # ์•ž๋’ค ๊ณต๋ฐฑ ์ œ๊ฑฐ
68
+ result_lines.append(line)
69
+
70
+ return '\n'.join(result_lines)
71
+
72
+ def convert_to_html(text):
73
+ """๋งˆํฌ๋‹ค์šด ํ˜•์‹์„ HTML๋กœ ๋ณ€ํ™˜ - ๊ฐœ์„ ๋œ ๋ฒ„์ „"""
74
+ # ์ œ๋ชฉ ํ˜•์‹ ๋ณ€ํ™˜ (# -> h1, ## -> h2, ๋“ฑ)
75
+ for i in range(6, 0, -1):
76
+ pattern = r'^' + r'#' * i + r'\s+(.+)$'
77
+ text = re.sub(pattern, r'<h' + str(i) + r'>\1</h' + str(i) + r'>', text, flags=re.MULTILINE)
78
+
79
+ # ๋ณผ๋“œ์ฒด ๋ณ€ํ™˜ (**text** -> <strong>text</strong>)
80
+ text = re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', text)
81
+
82
+ # ์ดํƒค๋ฆญ์ฒด ๋ณ€ํ™˜ (*text* -> <em>text</em>)
83
+ text = re.sub(r'\*([^*]+?)\*', r'<em>\1</em>', text)
84
+
85
+ # ๋ชฉ๋ก ๋ณ€ํ™˜ (- item -> <li>item</li>)
86
+ lines = text.split('\n')
87
+ in_list = False
88
+ result_lines = []
89
+
90
+ for line in lines:
91
+ list_match = re.match(r'^[\*\-+]\s+(.+)$', line)
92
+ if list_match:
93
+ if not in_list:
94
+ result_lines.append('<ul>')
95
+ in_list = True
96
+ result_lines.append(f'<li>{list_match.group(1)}</li>')
97
+ else:
98
+ if in_list:
99
+ result_lines.append('</ul>')
100
+ in_list = False
101
+
102
+ # ๋‹จ๋ฝ ์ฒ˜๋ฆฌ
103
+ if line.strip() and not re.match(r'^<h[1-6]>|<ul>|<li>|<\/ul>|<\/li>', line):
104
+ result_lines.append(f'<p>{line}</p>')
105
+ elif not line.strip():
106
+ result_lines.append('<br>')
107
+ else:
108
+ result_lines.append(line)
109
+
110
+ if in_list:
111
+ result_lines.append('</ul>')
112
+
113
+ # ์ตœ์ข… HTML ๊ฒฐํ•ฉ
114
+ html_content = '\n'.join(result_lines)
115
+
116
+ # HTML ์Šคํƒ€์ผ ์ ์šฉ (์ œ๋ชฉ๊ณผ ์†Œ์žฌ๋ชฉ์— Bold ๋ฐ ํฐํŠธ ์ง€์ •)
117
+ styled_html = f"""
118
+ <div style="font-family: 'Pretendard', Arial, sans-serif; color: #333; line-height: 1.6;">
119
+ <style>
120
+ h1 {{
121
+ font-size: 1.8em;
122
+ margin-top: 1.5em;
123
+ margin-bottom: 0.8em;
124
+ color: #111;
125
+ font-weight: bold;
126
+ font-family: 'Pretendard', Arial, sans-serif;
127
+ }}
128
+ h2 {{
129
+ font-size: 1.5em;
130
+ margin-top: 1.3em;
131
+ margin-bottom: 0.7em;
132
+ color: #222;
133
+ font-weight: bold;
134
+ font-family: 'Pretendard', Arial, sans-serif;
135
+ }}
136
+ h3 {{
137
+ font-size: 1.3em;
138
+ margin-top: 1.1em;
139
+ margin-bottom: 0.6em;
140
+ color: #333;
141
+ font-weight: bold;
142
+ font-family: 'Pretendard', Arial, sans-serif;
143
+ }}
144
+ p {{
145
+ margin-bottom: 1em;
146
+ line-height: 1.7;
147
+ font-size: 1.05em;
148
+ }}
149
+ strong {{
150
+ font-weight: bold;
151
+ color: #000;
152
+ }}
153
+ em {{
154
+ font-style: italic;
155
+ }}
156
+ ul {{
157
+ margin-left: 1.5em;
158
+ margin-bottom: 1em;
159
+ }}
160
+ li {{
161
+ margin-bottom: 0.5em;
162
+ }}
163
+ </style>
164
+ {html_content}
165
+ </div>
166
+ """
167
+
168
+ return styled_html
169
+
170
+ def post_process_blog(blog_content, style="์นœ๊ทผํ•œ"):
171
+ """๋ธ”๋กœ๊ทธ ์ปจํ…์ธ  ํ›„์ฒ˜๋ฆฌ ํ•จ์ˆ˜"""
172
+ try:
173
+ # ๋งˆํฌ๋‹ค์šด ์ œ๊ฑฐ (# ํ˜•์‹์˜ ์ œ๋ชฉ ์ œ์™ธ)
174
+ blog_content = re.sub(r'^\s*[\*\-+]\s+', '- ', blog_content, flags=re.MULTILINE) # ๊ธ€๋จธ๋ฆฌ ๊ธฐํ˜ธ ํ†ต์ผ
175
+
176
+ # ์Šคํƒ€์ผ์— ๋”ฐ๋ฅธ ์–ดํˆฌ ์กฐ์ •
177
+ if style == "์นœ๊ทผํ•œ":
178
+ blog_content = re.sub(r'([๊ฐ€-ํžฃ]+)๊ณ ์š”', r'\1๊ตฌ์š”', blog_content)
179
+ blog_content = re.sub(r'๋‹ต๋‹ˆ๋‹ค', '์–ด์š”', blog_content)
180
+ blog_content = re.sub(r'์˜€๋‹ต๋‹ˆ๋‹ค', '์˜€์–ด์š”', blog_content)
181
+ blog_content = re.sub(r'ํ–ˆ๋‹ต๋‹ˆ๋‹ค', 'ํ–ˆ์–ด์š”', blog_content)
182
+ blog_content = re.sub(r'์Šต๋‹ˆ๋‹ค', '์š”', blog_content)
183
+ blog_content = re.sub(r'ํ•ฉ๋‹ˆ๋‹ค', 'ํ•ด์š”', blog_content)
184
+ blog_content = re.sub(r'๋ฉ๋‹ˆ๋‹ค', '๋ผ์š”', blog_content)
185
+ blog_content = re.sub(r'์ž…๋‹ˆ๋‹ค', '์ด์—์š”', blog_content)
186
+
187
+ # ํ•ต์‹ฌ๊ธฐ๋Šฅ ์ „๋ฌธ์šฉ์–ด ๊ฐ•ํ™” ๋ฐ ๊ตฌ์ฒด์  ์ˆ˜์น˜ ๊ฐ•์กฐ
188
+ tech_terms = [
189
+ (r'์„ฑ๋Šฅ\b(?!\s*๋ถ„์„|\s*ํ…Œ์ŠคํŠธ|\s*์ธก์ •)', r'๊ธฐ์ˆ ์  ์„ฑ๋Šฅ'),
190
+ (r'์†๋„\b(?!\s*์ธก์ •|\s*ํ…Œ์ŠคํŠธ)', r'์ฒ˜๋ฆฌ ์†๋„'),
191
+ (r'ํ™”๋ฉด\b(?!\s*ํฌ๊ธฐ|\s*๋ฐ๊ธฐ)', r'๋””์Šคํ”Œ๋ ˆ์ด'),
192
+ (r'์นด๋ฉ”๋ผ\b(?!\s*๋ชจ๋“ˆ|\s*์„ผ์„œ)', r'์ด๋ฏธ์ง€ ์„ผ์„œ ์‹œ์Šคํ…œ'),
193
+ (r'๋ฐฐํ„ฐ๋ฆฌ\b(?!\s*์šฉ๋Ÿ‰|\s*์ˆ˜๋ช…)', r'์ „๋ ฅ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ'),
194
+ (r'์‚ฌ์šฉ\b(?!\s*๋ฐฉ๋ฒ•|\s*์„ค๋ช…|\s*์‚ฌ๋ก€)', r'์šด์šฉ'),
195
+ (r'์ข‹๋‹ค\b(?!\s*๊ณ )', r'ํšจ์œจ์ ์ด๋‹ค'),
196
+ (r'๋น ๋ฅด๋‹ค\b', r'๊ณ ์„ฑ๋Šฅ์ด๋‹ค')
197
+ ]
198
+
199
+ for pattern, replacement in tech_terms:
200
+ blog_content = re.sub(pattern, replacement, blog_content)
201
+
202
+ # ๋ถ„์„์  ํ‘œํ˜„ ๊ฐ•ํ™”
203
+ blog_content = re.sub(r'์ œ ์ƒ๊ฐ์—๋Š”', r'๋ถ„์„ ๊ฒฐ๊ณผ์— ๋”ฐ๋ฅด๋ฉด', blog_content)
204
+ blog_content = re.sub(r'์ œ๊ฐ€ ๋ดค์„ ๋•Œ', r'๊ธฐ์ˆ ์  ๊ด€์ ์—์„œ', blog_content)
205
+ blog_content = re.sub(r'๋А๋‚Œ์ด ๋“ค์–ด์š”', r'ํ™•์ธ๋ฉ๋‹ˆ๋‹ค', blog_content)
206
+
207
+ # ์ˆ˜์น˜์™€ ๋‹จ์œ„ ์‚ฌ์ด์— ๊ณต๋ฐฑ ์ถ”๊ฐ€ ๋ฐ ๊ฐ•์กฐ
208
+ def add_space_to_numbers(match):
209
+ number, unit = match.groups()
210
+ return f"{number} {unit}"
211
+
212
+ blog_content = re.sub(r'(\d+(?:\.\d+)?)([๊ฐ€-ํžฃ]+)', add_space_to_numbers, blog_content)
213
+
214
+ # ์ฃผ์š” ์ˆซ์ž ๋ฐ์ดํ„ฐ ๋ณผ๋“œ ์ฒ˜๋ฆฌ
215
+ blog_content = re.sub(r'(\d+(?:\.\d+)?(?:\s*%|\s*dB|\s*Hz|\s*์‹œ๊ฐ„|\s*mAh|\s*GB|\s*MB|\s*TB|\s*MP))', r'**\1**', blog_content)
216
+
217
+ # ๊ณผ์žฅ๋œ ํ‘œํ˜„ ์ •๋ฆฌ
218
+ exaggerated_expressions = [
219
+ (r'ํ•„์ˆ˜์ ์ธ', r'์ค‘์š”ํ•œ'),
220
+ (r'ํ˜๋ช…์ ์ธ', r'์ฃผ๋ชฉํ• ๋งŒํ•œ'),
221
+ (r'๋†€๋ผ์šด', r'์ฃผ๋ชฉํ•  ๋งŒํ•œ'),
222
+ (r'๊ธฐ์ ์˜', r'ํšจ๊ณผ์ ์ธ'),
223
+ (r'์ตœ๊ณ ์˜', r'์šฐ์ˆ˜ํ•œ'),
224
+ (r'์„ธ๊ณ„์ ์ธ', r'์ฃผ์š”'),
225
+ (r'์™„๋ฒฝํ•œ', r'์šฐ์ˆ˜ํ•œ'),
226
+ (r'๊ทน์ ์ธ', r'์ƒ๋‹นํ•œ'),
227
+ (r'๋ฌดํ•œํ•œ', r'๋‹ค์–‘ํ•œ'),
228
+ (r'์ ˆ๋Œ€์ ์ธ', r'์ค‘์š”ํ•œ'),
229
+ (r'ํ˜์‹ ์ ์ธ', r'์ƒˆ๋กœ์šด'),
230
+ (r'ํ™˜์ƒ์ ์ธ', r'์šฐ์ˆ˜ํ•œ'),
231
+ (r'๊ทผ๋ณธ์ ์ธ', r'๊ธฐ๋ณธ์ ์ธ'),
232
+ (r'ํš๊ธฐ์ ์ธ', r'์ค‘์š”ํ•œ'),
233
+ (r'์ „๋ก€์—†๋Š”', r'ํŠน๋ณ„ํ•œ'),
234
+ (r'์••๋„์ ์ธ', r'๋‘๋“œ๋Ÿฌ์ง„'),
235
+ (r'๊ธฐ๊ฐ€ ๋ง‰ํžŒ', r'ํšจ๊ณผ์ ์ธ'),
236
+ (r'๋ํŒ์™•', r'์ตœ์ƒ์œ„ ๋ชจ๋ธ')
237
+ ]
238
+
239
+ for pattern, replacement in exaggerated_expressions:
240
+ blog_content = re.sub(r'\b' + pattern + r'\b', replacement, blog_content, flags=re.IGNORECASE)
241
+
242
+ # ์ฐธ๊ณ ๊ธ€ ๊ด€๋ จ ํ‘œํ˜„ ์ •๋ฆฌ
243
+ blog_content = re.sub(r'์ฐธ๊ณ ๊ธ€์— ๋”ฐ๋ฅด๋ฉด', r'๊ธฐ์ˆ  ๋ถ„์„์— ๋”ฐ๋ฅด๋ฉด', blog_content)
244
+ blog_content = re.sub(r'์ฐธ๊ณ ๊ธ€', r'๊ธฐ์ˆ  ๋ฌธ์„œ', blog_content)
245
+
246
+ return blog_content
247
+ except Exception as e:
248
+ logging.error(f"๋ธ”๋กœ๊ทธ ๊ธ€ ํ›„์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
249
+ return blog_content
250
+
251
+ def generate_outline(category, style, references1, references2, references3):
252
+ """ํ•ต์‹ฌ๊ธฐ๋Šฅ ์„ ๋ณ„ ํ•จ์ˆ˜ - ๊ฐ„๋‹จํ•œ ์„ค๋ช… ์ถ”๊ฐ€"""
253
+ try:
254
+ # ์ฐธ๊ณ ๊ธ€ ์ •๋ณด ์ค€๋น„
255
+ references = [
256
+ references1.strip() if references1.strip() else "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ",
257
+ references2.strip() if references2.strip() else "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ",
258
+ references3.strip() if references3.strip() else "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ"
259
+ ]
260
+
261
+ # ์˜๋ฏธ ์žˆ๋Š” ์ฐธ๊ณ ๊ธ€๋งŒ ํ•„ํ„ฐ๋ง
262
+ meaningful_refs = [ref for ref in references if ref != "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ"]
263
+
264
+ if not meaningful_refs:
265
+ return ["์ฐธ๊ณ  ์ž๋ฃŒ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค"] * 5
266
+
267
+ # ์Šคํƒ€์ผ ํ”„๋กฌํ”„ํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ
268
+ style_prompt = get_style_prompt(style)
269
+
270
+ # ๋ชจ๋“  ์ฐธ๊ณ ๊ธ€ ๊ฒฐํ•ฉ
271
+ combined_refs = "\n\n".join(meaningful_refs)
272
+
273
+ # LLM์— ํ•ต์‹ฌ๊ธฐ๋Šฅ ์ถ”์ถœ ์š”์ฒญ
274
+ extract_prompt = f"""
275
+ [ํ•ต์‹ฌ๊ธฐ๋Šฅ ์„ ๋ณ„ ์š”์ฒญ]
276
+ ์ œ๊ณต๋œ ์ฐธ๊ณ ๊ธ€์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•˜๊ณ  ํ•ต์‹ฌ์ ์ธ ๊ธฐ๋Šฅ 5๊ฐ€์ง€๋ฅผ ์„ ๋ณ„ํ•˜๊ณ  ๊ฐ๊ฐ์— ๊ฐ„๋‹จํ•œ ์„ค๋ช…์„ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.
277
+
278
+ ์ฐธ๊ณ ๊ธ€:
279
+ {combined_refs}
280
+
281
+ [์‹œ์Šคํ…œ ์—ญํ• ]
282
+ ๋‹น์‹ ์€ ์ˆ˜๋…„๊ฐ„์˜ ๊ฒฝํ—˜์„ ๊ฐ€์ง„ ์ƒํ’ˆ ๊ธฐ๋Šฅ ์ „๋ฌธ ๋ถ„์„๊ฐ€์ž…๋‹ˆ๋‹ค. ์ œํ’ˆ์˜ ๋‹จ์ผ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์„ ์‹ฌ์ธต์ ์œผ๋กœ ๋ถ„์„ํ•˜๊ณ  ๋‹ค์–‘ํ•œ ์ธก๋ฉด์—์„œ ํ‰๊ฐ€ํ•˜์—ฌ ๋งŽ์€ ๋…์ž๋“ค์˜ ์‹ ๋ขฐ๋ฅผ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
283
+
284
+ [๋ถ„์„ ๋‹จ๊ณ„]
285
+ 1. ์ฐธ๊ณ  ์ž๋ฃŒ 3๊ฐœ๋ฅผ ์ฒ ์ €ํžˆ ๋ถ„์„ํ•˜์—ฌ ์ œํ’ˆ์˜ ๋‹จ์ผ ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์‹๋ณ„
286
+ 2. ์„ ์ •ํ•œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์˜ 5๊ฐ€์ง€ ์ฃผ์š” ์ธก๋ฉด ํŒŒ์•… (์„ฑ๋Šฅ, ์‚ฌ์šฉ์„ฑ, ํšจ์œจ์„ฑ, ๊ธฐ์ˆ ์  ํŠน์ง•, ํ™œ์šฉ ๊ฐ€์น˜ ๋“ฑ)
287
+ 3. ์„ ์ •ํ•œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์ด ์ œํ’ˆ ์ „์ฒด์—์„œ ๊ฐ–๋Š” ์ค‘์š”๋„์™€ ์ฐจ๋ณ„์„ฑ ํ‰๊ฐ€
288
+
289
+ [์•„์›ƒ๋ผ์ธ ๊ตฌ์„ฑ ์›์น™]
290
+ 1. ๋ณธ๋ก (5๊ฐœ) - ์ฐธ๊ณ  ์ž๋ฃŒ ๋ถ„์„์„ ํ†ตํ•ด ๋ฐœ๊ฒฌํ•œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์˜ 5๊ฐ€์ง€ ์ค‘์š” ์ธก๋ฉด์„ ๋‹ด์€ ์†Œ์ œ๋ชฉ
291
+ - ํ•ต์‹ฌ ๊ธฐ๋Šฅ์˜ ๊ธฐ์ˆ ์  ์›๋ฆฌ์™€ ์ž‘๋™ ๋ฉ”์ปค๋‹ˆ์ฆ˜
292
+ - ํ•ต์‹ฌ ๊ธฐ๋Šฅ์˜ ์‹ค์ œ ์„ฑ๋Šฅ ๋ฐ ์ธก์ • ๋ฐ์ดํ„ฐ ๋ถ„์„
293
+ - ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ์ธก๋ฉด์—์„œ์˜ ๊ธฐ๋Šฅ ํ‰๊ฐ€
294
+ - ๊ฒฝ์Ÿ ์ œํ’ˆ๊ณผ์˜ ํ•ด๋‹น ๊ธฐ๋Šฅ ๋น„๊ต ๋ถ„์„
295
+ - ํ•ต์‹ฌ ๊ธฐ๋Šฅ์˜ ์‹ค์ƒํ™œ ํ™œ์šฉ ๊ฐ€์น˜์™€ ํ•œ๊ณ„์ 
296
+ - (์œ„ ํ•ญ๋ชฉ๋“ค์€ ์„ ์ •๋œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์— ๋”ฐ๋ผ ์œ ์—ฐํ•˜๊ฒŒ ์กฐ์ •)
297
+
298
+ [ํ•ต์‹ฌ ์ง€์นจ]
299
+ 1. ์™„์ „ํžˆ ํ•œ๊ตญ์–ด๋กœ๋งŒ ์ž‘์„ฑํ•  ๊ฒƒ
300
+ 2. ์†Œ์ œ๋ชฉ์€ ์ตœ๋Œ€ 30์ž ์ด๋‚ด๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑ
301
+ 3. ์„ ์ •๋œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์˜ ์ค‘์š” ์ธก๋ฉด์„ ๋ช…ํ™•ํžˆ ๋“œ๋Ÿฌ๋‚ด๋Š” ํ‘œํ˜„ ์‚ฌ์šฉ (์˜ˆ: "์ •๋ฐ€ ์ธก์ • ์‹คํ—˜์œผ๋กœ ๋ณธ ์„ฑ๋Šฅ ํ•œ๊ณ„", "์ผ์ƒ ํ™˜๊ฒฝ์—์„œ์˜ ๊ธฐ๋Šฅ ์•ˆ์ •์„ฑ ๋ถ„์„")
302
+ 4. ๊ธฐ์ˆ ์  ์ •ํ™•์„ฑ๊ณผ ์‹ฌ์ธต์  ๋ถ„์„์ด ์†Œ์ œ๋ชฉ์— ๋ฐ˜์˜๋˜๋„๋ก ๊ตฌ์„ฑ
303
+ 5. ํ‚ค์›Œ๋“œ๋Š” ์†Œ์ œ๋ชฉ ๊ฒฐ์ •์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Œ (๋ณธ๋ฌธ ์ž‘์„ฑ ์‹œ ์ฐธ๊ณ ์‚ฌํ•ญ์œผ๋กœ๋งŒ ํ™œ์šฉ)
304
+ 6. ๋ณธ๋ก  5๊ฐœ ํ•ญ๋ชฉ๋งŒ์œผ๋กœ ๊ตฌ์„ฑ (๋„์ž…๋ถ€์™€ ๊ฒฐ๋ก  ๋ถˆํ•„์š”)
305
+ 7. ๋‹ค์–‘ํ•œ ์ œํ’ˆ ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹จ์ผ ๊ธฐ๋Šฅ ๋ถ„์„์— ์œ ์—ฐํ•˜๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑ
306
+ 8. ํŠน์ˆ˜๋ฌธ์ž(**, :, #, ## ๋“ฑ)๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  ์ผ๋ฐ˜ ํ…์ŠคํŠธ๋กœ๋งŒ ์ž‘์„ฑํ•˜์„ธ์š”.
307
+
308
+ [์ถœ๋ ฅ ํ˜•์‹]
309
+ 1. ์ฐธ๊ณ  ์ž๋ฃŒ ๋ถ„์„์„ ํ†ตํ•ด ์„ ์ •๋œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์˜ 5๊ฐ€์ง€ ์ค‘์š” ์ธก๋ฉด์„ ํŒŒ์•…ํ•˜์—ฌ ์ž์œ ๋กญ๊ฒŒ ์•„์›ƒ๋ผ์ธ ๊ตฌ์„ฑ
310
+ 2. ๋ฐ˜๋“œ์‹œ ๋ณธ๋ก  5๊ฐœ ํ•ญ๋ชฉ์œผ๋กœ๋งŒ ๊ตฌ์„ฑํ•  ๊ฒƒ:(๊ฐ ํ•ญ๋ชฉ๋‹น 1๋ฒˆ ์—”ํ„ฐ๋ฅผ ์ ์šฉํ•˜์—ฌ ๋นˆ์นธ์ด ๋‚˜์˜ค์ง€ ์•Š๋„๋กํ•˜๋ผ.)
311
+ - ๋ณธ๋ก 1: [ํ•ต์‹ฌ ๊ธฐ๋Šฅ์˜ ๊ธฐ์ˆ ์  ์›๋ฆฌ/์ž‘๋™ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๊ด€๋ จ ์ œ๋ชฉ]
312
+ - ๋ณธ๋ก 2: [ํ•ต์‹ฌ ๊ธฐ๋Šฅ์˜ ์„ฑ๋Šฅ/์ธก์ • ๋ฐ์ดํ„ฐ ๊ด€๋ จ ์ œ๋ชฉ]
313
+ - ๋ณธ๋ก 3: [์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ์ธก๋ฉด์˜ ๊ธฐ๋Šฅ ํ‰๊ฐ€ ๊ด€๋ จ ์ œ๋ชฉ]
314
+ - ๋ณธ๋ก 4: [๊ฒฝ์Ÿ ์ œํ’ˆ๊ณผ์˜ ๊ธฐ๋Šฅ ๋น„๊ต ๊ด€๋ จ ์ œ๋ชฉ]
315
+ - ๋ณธ๋ก 5: [์‹ค์ƒํ™œ ํ™œ์šฉ ๊ฐ€์น˜/ํ•œ๊ณ„์  ๊ด€๋ จ ์ œ๋ชฉ]
316
+ 3. ์†Œ์ œ๋ชฉ์€ ์„ ์ •๋œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์˜ ํŠน์„ฑ์— ๋งž๊ฒŒ ์ž์œ ๋กญ๊ฒŒ ๊ตฌ์„ฑ
317
+ 4. ํ‚ค์›Œ๋“œ์— ๋งž์ถ”์ง€ ๋ง๊ณ , ์ฐธ๊ณ  ์ž๋ฃŒ ๋ถ„์„์„ ํ†ตํ•ด ๋ฐœ๊ฒฌํ•œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์˜ ์ค‘์š” ์ธก๋ฉด ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑ
318
+ 5. ์˜ˆ์‹œ ํ˜•์‹ (์ฐธ๊ณ ์šฉ์ผ ๋ฟ, ๋‚ด์šฉ์€ ์„ ์ •๋œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ๊ณผ ์ฐธ๊ณ  ์ž๋ฃŒ์— ๋”ฐ๋ผ ์™„์ „ํžˆ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ):
319
+ - ๋ณธ๋ก 1: [ํ•ต์‹ฌ ๊ธฐ๋Šฅ์˜ ๊ธฐ์ˆ ์  ์›๋ฆฌ/๋ฉ”์ปค๋‹ˆ์ฆ˜ ๊ด€๋ จ ์ œ๋ชฉ]
320
+ - ๋ณธ๋ก 2: [์‹ค์ธก ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ/์„ฑ๋Šฅ ๋ฐ์ดํ„ฐ ๊ด€๋ จ ์ œ๋ชฉ]
321
+ - ๋ณธ๋ก 3: [์‹ค์‚ฌ์šฉ ํ™˜๊ฒฝ์—์„œ์˜ ์‚ฌ์šฉ์„ฑ/ํšจ์œจ์„ฑ ๊ด€๋ จ ์ œ๋ชฉ]
322
+ - ๋ณธ๋ก 4: [ํƒ€ ์ œํ’ˆ ๋™์ผ ๊ธฐ๋Šฅ๊ณผ์˜ ์ฐจ๋ณ„์  ๊ด€๋ จ ์ œ๋ชฉ]
323
+ - ๋ณธ๋ก 5: [๊ธฐ๋Šฅ์˜ ๋ฏธ๋ž˜ ๋ฐœ์ „ ๊ฐ€๋Šฅ์„ฑ/๊ฐœ์„ ์  ๊ด€๋ จ ์ œ๋ชฉ]
324
+
325
+ {style_prompt}
326
+ """
327
+
328
+ # Gemini API ํ˜ธ์ถœ
329
+ outline_result = call_gemini_api(extract_prompt, temperature=0.3)
330
+
331
+ # ๊ฒฐ๊ณผ์—์„œ ํ•ต์‹ฌ๊ธฐ๋Šฅ ์ถ”์ถœ
332
+ features = []
333
+ for line in outline_result.strip().split('\n'):
334
+ if line.strip():
335
+ # ํŠน์ˆ˜๋ฌธ์ž์™€ ๋ถˆํ•„์š”ํ•œ ํ˜•์‹ ์ œ๊ฑฐ
336
+ clean_feature = re.sub(r'^\s*[-*#]\s*', '', line) # ๋ฒˆํ˜ธ, ๋ถˆ๋ฆฟ ์ œ๊ฑฐ
337
+ clean_feature = re.sub(r'\*\*|\*|##|#', '', clean_feature) # ํŠน์ˆ˜๋ฌธ์ž ์ œ๊ฑฐ
338
+ clean_feature = clean_feature.strip()
339
+
340
+ if clean_feature:
341
+ features.append(clean_feature)
342
+
343
+ # 5๊ฐœ๊ฐ€ ์•ˆ ๋˜๋ฉด ๋นˆ ๊ฐ’์œผ๋กœ ์ฑ„์šฐ๊ธฐ
344
+ while len(features) < 5:
345
+ features.append(f"ํŠน์ง• {len(features) + 1} - ์ถ”๊ฐ€ ์„ค๋ช… ํ•„์š”")
346
+
347
+ return features[:5] # ์ตœ๋Œ€ 5๊ฐœ๋งŒ ๋ฐ˜ํ™˜
348
+
349
+ except Exception as e:
350
+ logging.error(f"ํ•ต์‹ฌ๊ธฐ๋Šฅ ์„ ๋ณ„ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
351
+ return ["ํŠน์ง•์„ ์ถ”์ถœํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค"] * 5
352
+
353
+ def generate_blog_post(category, style, references1, references2, references3, selected_feature):
354
+ """ํ•ต์‹ฌ๊ธฐ๋Šฅ์ง‘์ค‘ํ˜• ๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑ ํ•จ์ˆ˜ - ์œ ์—ฐํ•œ ์†Œ์žฌ ๊ตฌ์„ฑ"""
355
+ try:
356
+ # ์ฐธ๊ณ ๊ธ€ ์ค€๋น„
357
+ references = [
358
+ references1.strip() if references1.strip() else "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ",
359
+ references2.strip() if references2.strip() else "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ",
360
+ references3.strip() if references3.strip() else "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ"
361
+ ]
362
+
363
+ # ์˜๋ฏธ ์žˆ๋Š” ์ฐธ๊ณ ๊ธ€๋งŒ ํ•„ํ„ฐ๋ง
364
+ references = [ref for ref in references if ref != "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ"]
365
+
366
+ if not references:
367
+ return "<p>์ฐธ๊ณ  ์ž๋ฃŒ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ตœ์†Œ ํ•˜๋‚˜ ์ด์ƒ์˜ ์ฐธ๊ณ  ์ž๋ฃŒ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.</p>"
368
+
369
+ if not selected_feature.strip():
370
+ return "<p>ํ•ต์‹ฌ๊ธฐ๋Šฅ์ด ์„ ํƒ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ•ต์‹ฌ๊ธฐ๋Šฅ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.</p>"
371
+
372
+ # ์Šคํƒ€์ผ ํ”„๋กฌํ”„ํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ
373
+ style_prompt = get_style_prompt(style)
374
+
375
+ # ๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑ ํ”„๋กฌํ”„ํŠธ ๊ตฌ์„ฑ
376
+ blog_prompt = f"""
377
+ [ํ•ต์‹ฌ๊ธฐ๋Šฅ ์ง‘์ค‘ํ˜• ์ƒํ’ˆ๋ฆฌ๋ทฐ ์ž‘์„ฑ ์š”์ฒญ]
378
+ ์„ ํƒํ•œ ํ•ต์‹ฌ๊ธฐ๋Šฅ: {selected_feature}
379
+
380
+ [๋ฆฌ๋ทฐ ์ž‘์„ฑ ํ˜•์‹]
381
+ 1. ๋ฆฌ๋ทฐ๋Š” '๋„์ž…๋ถ€', '5๊ฐ€์ง€ ์†Œ์žฌ', '๋งˆ๋ฌด๋ฆฌ' ๊ตฌ์กฐ๋กœ ์ž‘์„ฑํ•˜์„ธ์š”.
382
+ 2. ๋งˆํฌ๋‹ค์šด ํ˜•์‹์€ ์ตœ์†Œํ•œ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ , ๊ฐ€๋Šฅํ•œ ํ•œ ์ผ๋ฐ˜ ํ…์ŠคํŠธ๋กœ ์ž‘์„ฑํ•˜์„ธ์š”.
383
+ 3. ๊ฐ ๋ถ€๋ถ„์€ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„๋˜์–ด์•ผ ํ•˜๋ฉฐ, ์„œ์ˆ ํ˜• ๋ฌธ์žฅ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด์–ด์ง€๋„๋ก ์ž‘์„ฑํ•˜์„ธ์š”.
384
+ 4. ๋‹จ๋ฝ์€ ์ ์ ˆํžˆ ๋‚˜๋ˆ„๋˜, ๋„ˆ๋ฌด ์งง์€ ๋‹จ๋ฝ์„ ๋งŽ์ด ๋งŒ๋“ค์ง€ ๋งˆ์„ธ์š”.
385
+
386
+ [๋ฆฌ๋ทฐ ๋‚ด์šฉ ๊ตฌ์กฐ]
387
+ 1. ๋„์ž…๋ถ€ (์ „์ฒด์˜ 10%)
388
+ - ์„ ํƒํ•œ ํ•ต์‹ฌ๊ธฐ๋Šฅ์˜ ์ค‘์š”์„ฑ๊ณผ ํŠน์ง•์„ ๊ฐ„๋žตํžˆ ์†Œ๊ฐœ
389
+ - ์ด ๊ธฐ๋Šฅ์ด ์ƒํ’ˆ์—์„œ ์–ด๋–ค ๊ฐ€์น˜๋ฅผ ์ œ๊ณตํ•˜๋Š”์ง€ ์„ค๋ช…
390
+ - ๋งˆ์ง€๋ง‰ ๋ฌธ์žฅ์—์„œ ๋ณธ๋ฌธ์—์„œ ๋‹ค๋ฃฐ ๋‚ด์šฉ์„ ์˜ˆ๊ณ 
391
+
392
+ 2. 5๊ฐ€์ง€ ์†Œ์žฌ (์ „์ฒด์˜ 80%)
393
+ - ์„ ํƒํ•œ ํ•ต์‹ฌ๊ธฐ๋Šฅ์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ 5๊ฐ€์ง€ ์†Œ์žฌ๋ฅผ ์ž์œ ๋กญ๊ฒŒ ์„ ์ •ํ•˜์„ธ์š”
394
+ - ๊ฐ ์†Œ์žฌ๋Š” ๊ธฐ๋Šฅ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์ธก๋ฉด์„ ๋‹ค๋ฃจ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค
395
+ - ์˜ˆ์‹œ ์†Œ์žฌ: ๊ธฐ์ˆ ์  ์›๋ฆฌ, ์ž‘๋™ ๋ฐฉ์‹, ์„ฑ๋Šฅ ๋ถ„์„, ๊ฒฝ์Ÿ ์ œํ’ˆ ๋น„๊ต, ํ™œ์šฉ ๋ฐฉ๋ฒ•, ์‚ฌ์šฉ ๊ฒฝํ—˜, ์„ค์ • ํŒ,
396
+ ์—…๋ฐ์ดํŠธ ์ด๋ ฅ, ์‚ฐ์—… ํ‘œ์ค€๊ณผ์˜ ๋น„๊ต, ์‚ฌ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค, ํ˜ธํ™˜์„ฑ, ํ•œ๊ณ„์ ๊ณผ ๊ฐœ์„  ๋ฐฉํ–ฅ ๋“ฑ
397
+ - ๊ฐ ์†Œ์žฌ๋Š” ๋น„์Šทํ•œ ๋ถ„๋Ÿ‰์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์—ฐ๊ฒฐ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค
398
+
399
+ 3. ๋งˆ๋ฌด๋ฆฌ (์ „์ฒด์˜ 10%)
400
+ - ์ด ๊ธฐ๋Šฅ์˜ ์ข…ํ•ฉ์  ํ‰๊ฐ€์™€ ๊ฐ€์น˜
401
+ - ์–ด๋–ค ์œ ํ˜•์˜ ์‚ฌ์šฉ์ž์—๊ฒŒ ํŠนํžˆ ์œ ์šฉํ•œ์ง€
402
+ - ํ•ต์‹ฌ๊ธฐ๋Šฅ๊ณผ ์ œํ’ˆ ์ „์ฒด์— ๋Œ€ํ•œ ์ตœ์ข… ๊ฒฌํ•ด
403
+
404
+ [์ค‘์š” ์ž‘์„ฑ ์ง€์นจ]
405
+ 1. ์ „์ฒด ๊ธ€์€ ์ตœ์†Œ 4000์ž ์ด์ƒ์œผ๋กœ ์ž‘์„ฑํ•˜์„ธ์š”.
406
+ 2. ๊ฐ ์†Œ์žฌ๋Š” ์ตœ์†Œ 600์ž ์ด์ƒ ์ž‘์„ฑํ•˜๊ณ , ์„œ๋กœ ์œ ๊ธฐ์ ์œผ๋กœ ์—ฐ๊ฒฐ๋˜๊ฒŒ ํ•˜์„ธ์š”.
407
+ 3. ์ œ๋ชฉ์€ ๋”ฐ๋กœ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ , ๋„์ž…๋ถ€, ์†Œ์žฌ, ๋งˆ๋ฌด๋ฆฌ๋ฅผ ํ•˜๋‚˜์˜ ์—ฐ๊ฒฐ๋œ ๊ธ€๋กœ ์ž‘์„ฑํ•˜์„ธ์š”.
408
+ 4. ๊ธฐ์ˆ ์  ์ •ํ™•์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ์„ ํƒํ•œ ํ•ต์‹ฌ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์‹ฌ์ธต์  ๋ถ„์„๊ณผ ๊ตฌ์ฒด์ ์ธ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜์„ธ์š”.
409
+ 5. ๋งˆ์ผ€ํŒ…์  ๊ณผ์žฅ ํ‘œํ˜„๋ณด๋‹ค๋Š” ์‚ฌ์‹ค์ ์ด๊ณ  ๋ถ„์„์ ์ธ ํ‘œํ˜„์„ ์‚ฌ์šฉํ•˜์„ธ์š”.
410
+ 6. ๋ถˆํ•„์š”ํ•œ ๋ฐ˜๋ณต์ด๋‚˜ ์žฅํ™ฉํ•œ ์„ค๋ช…์€ ํ”ผํ•˜๊ณ , ํ•ต์‹ฌ ์ •๋ณด์™€ ํ†ต์ฐฐ์„ ๊ฐ•์กฐํ•˜์„ธ์š”.
411
+ 7. ์ „์ฒด ๊ธ€์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๊ณ , ๋ฌธ๋‹จ ๊ฐ„ ์ž์—ฐ์Šค๋Ÿฌ์šด ํ๋ฆ„์„ ๋งŒ๋“œ์„ธ์š”.
412
+ 8. ์†Œ์žฌ๋Š” ํ•ต์‹ฌ๊ธฐ๋Šฅ์˜ ์„ฑ๊ฒฉ์— ๋งž๊ฒŒ ๊ฐ€์žฅ ์ ์ ˆํ•œ ๊ฒƒ์„ ์ž์œ ๋กญ๊ฒŒ ์„ ์ •ํ•˜์„ธ์š”.
413
+
414
+ ์ฐธ๊ณ ๊ธ€:
415
+ {references[0]}
416
+ {references[1] if len(references) > 1 else ""}
417
+ {references[2] if len(references) > 2 else ""}
418
+
419
+ {style_prompt}
420
+ """
421
+
422
+ # Gemini API ํ˜ธ์ถœ
423
+ logging.info("ํ•ต์‹ฌ๊ธฐ๋Šฅ ์ง‘์ค‘ํ˜• ๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑ ์‹œ์ž‘")
424
+ blog_content = call_gemini_api(blog_prompt, temperature=0.7)
425
+ logging.info(f"์ƒ์„ฑ๋œ ์›๋ณธ ๊ธ€ ๊ธธ์ด: {len(blog_content)}")
426
+
427
+ # ํ›„์ฒ˜๋ฆฌ
428
+ processed_content = post_process_blog(blog_content, style)
429
+
430
+ # ๊ธ€์ž ์ˆ˜ ์ฒดํฌ
431
+ char_count = len(processed_content)
432
+ logging.info(f"์ฒ˜๋ฆฌ ํ›„ ๋ธ”๋กœ๊ทธ ๊ธ€ ๊ธ€์ž ์ˆ˜: {char_count}")
433
+
434
+ # ๊ธ€์ž ์ˆ˜๊ฐ€ ๋ชฉํ‘œ์— ๋ฏธ๋‹ฌํ•˜๋ฉด ํ™•์žฅ ์‹œ๋„
435
+ if char_count < TARGET_CHAR_LENGTH:
436
+ logging.info(f"๊ธ€์ž ์ˆ˜ ๋ถ€์กฑ ({char_count} < {TARGET_CHAR_LENGTH}), ํ™•์žฅ ์‹œ๋„")
437
+
438
+ expansion_prompt = f"""
439
+ [ํ•ต์‹ฌ๊ธฐ๋Šฅ ๋ถ„์„ ํ™•์žฅ ์š”์ฒญ]
440
+ ํ˜„์žฌ ๊ธ€์€ ๋ชฉํ‘œ ๊ธ€์ž์ˆ˜์ธ 4000์ž์— ๋ฏธ์น˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ๊ธ€์ž์ˆ˜๋Š” ์•ฝ {char_count}์ž์ž…๋‹ˆ๋‹ค.
441
+ ์„ ํƒํ•œ ํ•ต์‹ฌ๊ธฐ๋Šฅ: {selected_feature}
442
+
443
+ [ํ™•์žฅ ์ง€์นจ]
444
+ 1. ์›๋ž˜ ๊ธ€์˜ ๊ตฌ์กฐ(๋„์ž…๋ถ€, 5๊ฐ€์ง€ ์†Œ์žฌ, ๋งˆ๋ฌด๋ฆฌ)๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ๋‚ด์šฉ์„ ํ™•์žฅํ•˜์„ธ์š”.
445
+ 2. ๊ฐ ์†Œ์žฌ์— ๋” ๊ตฌ์ฒด์ ์ธ ์ •๋ณด, ์˜ˆ์‹œ, ๋ถ„์„ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”.
446
+ 3. ์„œ์ˆ ์  ํ๋ฆ„์„ ์œ ์ง€ํ•˜๊ณ , ๋ถˆํ•„์š”ํ•œ ๋งˆํฌ๋‹ค์šด ์‚ฌ์šฉ์€ ํ”ผํ•˜์„ธ์š”.
447
+ 4. ๊ธ€์˜ ์ „์ฒด ์ผ๊ด€์„ฑ๊ณผ ์‘์ง‘์„ฑ์„ ์œ ์ง€ํ•˜์„ธ์š”.
448
+
449
+ ์›๋ณธ ๊ธ€:
450
+ {processed_content}
451
+ """
452
+
453
+ # ํ™•์žฅ ์‹œ๋„
454
+ expanded_content = call_gemini_api(expansion_prompt, temperature=0.75)
455
+ processed_content = post_process_blog(expanded_content, style)
456
+
457
+ # ๋‹ค์‹œ ๊ธ€์ž ์ˆ˜ ์ฒดํฌ
458
+ char_count = len(processed_content)
459
+ logging.info(f"ํ™•์žฅ ํ›„ ๋ธ”๋กœ๊ทธ ๊ธ€ ๊ธ€์ž ์ˆ˜: {char_count}")
460
+
461
+ # HTML ๋ณ€ํ™˜
462
+ final_html = convert_to_html(processed_content)
463
+
464
+ return final_html
465
+
466
+ except Exception as e:
467
+ logging.error(f"๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
468
+ return f"<p>๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}</p>"
469
+
470
+ def get_style_prompt(style="์นœ๊ทผํ•œ"):
471
+ """๋ธ”๋กœ๊ทธ ๊ธ€์˜ ์Šคํƒ€์ผ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋ฐ˜ํ™˜"""
472
+ prompts = {
473
+ "์นœ๊ทผํ•œ": """
474
+ [์นœ๊ทผํ•œ ํ•ต์‹ฌ๊ธฐ๋Šฅ ๋ฆฌ๋ทฐ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ]
475
+ 1. ํ†ค๊ณผ ์–ด์กฐ
476
+ - ๋Œ€ํ™”ํ•˜๋“ฏ ํŽธ์•ˆํ•˜๊ณ  ์นœ๊ทผํ•œ ๋งํˆฌ ์‚ฌ์šฉ (์˜ˆ: "์˜ค๋Š˜์€ ~์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊ฒŒ์š”")
477
+ - 1์ธ์นญ ์‹œ์ ์œผ๋กœ ์ง์ ‘ ์‚ฌ์šฉํ•œ ๊ฒฝํ—˜์„ ์ƒ์ƒํ•˜๊ฒŒ ํ‘œํ˜„
478
+ - ๊ตฌ์–ด์ฒด์™€ ์ผ์ƒ์ ์ธ ํ‘œํ˜„ ์‚ฌ์šฉํ•˜์—ฌ ์นœ๊ทผํ•จ ์œ ์ง€
479
+
480
+ 2. ๋ฌธ์žฅ ๋ฐ ์–ดํˆฌ
481
+ - 'ํ•ด์š”์ฒด'๋กœ ์ž‘์„ฑ (์˜ˆ: "~ํ–ˆ์–ด์š”", "~์ธ ๊ฒƒ ๊ฐ™์•„์š”")
482
+ - ๋ฌธ์žฅ์€ ๊ธธ์ง€ ์•Š๊ฒŒ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์—ฐ๊ฒฐ
483
+ - ๊ธฐ์ˆ ์  ๋‚ด์šฉ๋„ ์‰ฝ๊ณ  ์ดํ•ดํ•˜๊ธฐ ํŽธํ•œ ํ‘œํ˜„์œผ๋กœ ์„ค๋ช…
484
+
485
+ 3. ์ •๋ณด ์ „๋‹ฌ ๋ฐฉ์‹
486
+ - ๊ฐœ์ธ ๊ฒฝํ—˜๊ณผ ์ฒด๊ฐ์„ ์ค‘์‹ฌ์œผ๋กœ ์ •๋ณด ์ „๋‹ฌ
487
+ - ์ „๋ฌธ์ ์ธ ๋‚ด์šฉ๋„ ์ผ์ƒ์ ์ธ ๋น„์œ ์™€ ์˜ˆ์‹œ๋กœ ํ’€์–ด์„œ ์„ค๋ช…
488
+ - "์ œ๊ฐ€ ์‚ฌ์šฉํ•ด๋ณด๋‹ˆ~", "์‹ค์ œ๋กœ ๊ฒฝํ—˜ํ•ด๋ณด๋ฉด~"๊ณผ ๊ฐ™์€ ํ‘œํ˜„ ํ™œ์šฉ
489
+ - ๋…์ž์—๊ฒŒ ์ง์ ‘ ๋งํ•˜๋“ฏ ์ค‘๊ฐ„์ค‘๊ฐ„ "~ํ•˜์‹œ๋ฉด ์ข‹์•„์š”" ๊ฐ™์€ ์กฐ์–ธ ์ถ”๊ฐ€
490
+ """,
491
+ "์ผ๋ฐ˜": """
492
+ [์ผ๋ฐ˜์ ์ธ ํ•ต์‹ฌ๊ธฐ๋Šฅ ๋ฆฌ๋ทฐ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ]
493
+ 1. ํ†ค๊ณผ ์–ด์กฐ
494
+ - ๊ฐ๊ด€์ ์ด๊ณ  ์ค‘๋ฆฝ์ ์ธ ํ†ค ์œ ์ง€
495
+ - ์ง์ ‘์ ์ธ ๊ฒฝํ—˜๊ณผ ๊ฐ๊ด€์  ๋ฐ์ดํ„ฐ๋ฅผ ๊ท ํ˜• ์žˆ๊ฒŒ ํ™œ์šฉ
496
+ - ์กด๋Œ“๋ง ์‚ฌ์šฉํ•˜๋˜ ๋”ฑ๋”ฑํ•˜์ง€ ์•Š๊ฒŒ ํ‘œํ˜„
497
+
498
+ 2. ๋ฌธ์žฅ ๋ฐ ์–ดํˆฌ
499
+ - 'ํ•ฉ๋‹ˆ๋‹ค์ฒด' ์‚ฌ์šฉ (์˜ˆ: "~ํ•ฉ๋‹ˆ๋‹ค", "~์ž…๋‹ˆ๋‹ค")
500
+ - ๋ช…ํ™•ํ•˜๊ณ  ๊ฐ„๊ฒฐํ•œ ๋ฌธ์žฅ ๊ตฌ์„ฑ
501
+ - ๋‚ด์šฉ์˜ ๋…ผ๋ฆฌ์  ํ๋ฆ„์„ ์ค‘์‹œ
502
+
503
+ 3. ์ •๋ณด ์ „๋‹ฌ ๋ฐฉ์‹
504
+ - ์‚ฌ์‹ค๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ๋‚ด์šฉ ์ „๊ฐœ
505
+ - ๊ฐœ์ธ ๊ฒฝํ—˜๊ณผ ๊ฐ๊ด€์  ๋ถ„์„์„ ์ ์ ˆํžˆ ํ˜ผํ•ฉ
506
+ - ๋ถˆํ•„์š”ํ•œ ๊ณผ์žฅ์ด๋‚˜ ์ฃผ๊ด€์  ํ‰๊ฐ€ ์ตœ์†Œํ™”
507
+ - ์‹ค์šฉ์ ์ธ ๊ด€์ ์—์„œ ๊ธฐ๋Šฅ์˜ ์žฅ๋‹จ์  ๊ท ํ˜•์žˆ๊ฒŒ ์„œ์ˆ 
508
+ """,
509
+ "์ „๋ฌธ์ ์ธ": """
510
+ [์ „๋ฌธ์ ์ธ ํ•ต์‹ฌ๊ธฐ๋Šฅ ๋ฆฌ๋ทฐ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ]
511
+ 1. ํ†ค๊ณผ ์–ด์กฐ
512
+ - ์ „๋ฌธ์ ์ด๊ณ  ๋ถ„์„์ ์ธ ํ†ค ์‚ฌ์šฉ
513
+ - ๊ธฐ์ˆ ์  ๊นŠ์ด์™€ ์ •ํ™•์„ฑ ๊ฐ•์กฐ
514
+ - ์กด์ค‘๊ณผ ๊ถŒ์œ„๋ฅผ ๋А๋‚„ ์ˆ˜ ์žˆ๋Š” ํ‘œํ˜„ ์‚ฌ์šฉ
515
+
516
+ 2. ๋ฌธ์žฅ ๋ฐ ์–ดํˆฌ
517
+ - 'ํ•ฉ๋‹ˆ๋‹ค์ฒด'๋กœ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ์ž‘์„ฑ
518
+ - ๋…ผ๋ฆฌ์ ์ด๊ณ  ์ฒด๊ณ„์ ์ธ ๋ฌธ์žฅ ๊ตฌ์„ฑ
519
+ - ์ „๋ฌธ ์šฉ์–ด๋ฅผ ์ ์ ˆํžˆ ํ™œ์šฉํ•˜๋˜ ํ•„์š”์‹œ ๊ฐ„๋žตํ•œ ์„ค๋ช… ์ œ๊ณต
520
+
521
+ 3. ์ •๋ณด ์ „๋‹ฌ ๋ฐฉ์‹
522
+ - ๊ธฐ์ˆ ์  ์›๋ฆฌ์™€ ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ๋Œ€ํ•œ ์‹ฌ์ธต ๋ถ„์„
523
+ - ๋ฒค์น˜๋งˆํฌ ๋ฐ์ดํ„ฐ์™€ ๊ตฌ์ฒด์  ์ˆ˜์น˜๋ฅผ ํ™œ์šฉํ•œ ๊ฐ๊ด€์  ํ‰๊ฐ€
524
+ - ๊ฒฝ์Ÿ ์ œํ’ˆ๊ณผ์˜ ์„ธ๋ถ€์ ์ธ ๊ธฐ์ˆ  ๋น„๊ต ์ œ๊ณต
525
+ - ๊ธฐ๋Šฅ์˜ ๊ธฐ์ˆ ์  ํ•œ๊ณ„์™€ ๋ฐœ์ „ ๊ฐ€๋Šฅ์„ฑ์— ๋Œ€ํ•œ ํ†ต์ฐฐ ์ œ์‹œ
526
+ """
527
+ }
528
+ return prompts.get(style, prompts["์นœ๊ทผํ•œ"])
529
+
530
+ def call_gemini_api(prompt, temperature=TEMPERATURE, top_p=TOP_P):
531
+ """Gemini API ํ˜ธ์ถœ ํ•จ์ˆ˜"""
532
+ try:
533
+ logging.info("Gemini API ํ˜ธ์ถœ ์‹œ์ž‘")
534
+ response = client.models.generate_content(
535
+ model="gemini-2.0-flash",
536
+ contents=[prompt],
537
+ config=types.GenerateContentConfig(
538
+ max_output_tokens=MAX_TOKENS,
539
+ temperature=temperature,
540
+ top_p=top_p
541
+ )
542
+ )
543
+ logging.info("Gemini API ํ˜ธ์ถœ ์™„๋ฃŒ")
544
+ return response.text.strip()
545
+ except Exception as e:
546
+ logging.error(f"Gemini API ํ˜ธ์ถœ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
547
+ return f"API ํ˜ธ์ถœ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
548
+
549
+ # API ํ•จ์ˆ˜๋“ค
550
+ def generate_outline_4(category, style, ref1, ref2, ref3):
551
+ features = generate_outline(category, style, ref1, ref2, ref3)
552
+ # 3๊ฐœ์˜ ๋ฌธ์ž์—ด ํŠœํ”Œ ๋ฐ˜ํ™˜
553
+ return (features[0], features[1], features[2])
554
+
555
+ def generate_blog_post_4(category, style, ref1, ref2, ref3, outline):
556
+ # outline์€ ์„ ํƒ๋œ ํ•ต์‹ฌ๊ธฐ๋Šฅ ์ด๋ฆ„
557
+ return generate_blog_post(category, style, ref1, ref2, ref3, outline)