4g3gf-2 / travel_blog.py
ssboost's picture
Create travel_blog.py
07558d5 verified
import os
import random
import re
import requests
import logging
import tempfile
from bs4 import BeautifulSoup
from datetime import datetime
from zoneinfo import ZoneInfo
import html
from PIL import Image
from urllib.request import urlopen
import markdown2
import gradio as gr
# ๋กœ๊น… ์„ค์ • (INFO ๋ ˆ๋ฒจ)
logging.basicConfig(level=logging.INFO)
# ์ƒ์ˆ˜ ์ •์˜
TARGET_CHAR_LENGTH = 4000
MIN_SECTION_LENGTH = 600
MAX_TOKENS = 15000
TEMPERATURE = 0.75
TOP_P = 0.95
# API ๊ด€๋ จ ์„ค์ •
gemini_api_key = os.getenv("GEMINI_API_KEY")
# --- Google Gemini SDK ์ดˆ๊ธฐํ™” ---
from google import genai
from google.genai import types
client = genai.Client(api_key=gemini_api_key)
# -------------------------------
# ๊ธฐ๋ณธ ๋„์šฐ๋ฏธ ํ•จ์ˆ˜๋“ค
# -------------------------------
def remove_unwanted_phrases(text):
"""๋ถˆํ•„์š”ํ•œ ํ‘œํ˜„ ์ œ๊ฑฐ ํ•จ์ˆ˜"""
unwanted_phrases = [
'์—ฌ๋Ÿฌ๋ถ„', '์ตœ๊ทผ', '๋งˆ์ง€๋ง‰์œผ๋กœ', '๊ฒฐ๋ก ์ ์œผ๋กœ', '๊ฒฐ๊ตญ',
'์ข…ํ•ฉ์ ์œผ๋กœ', '๋”ฐ๋ผ์„œ', '๋งˆ๋ฌด๋ฆฌ', '๋์œผ๋กœ', '์š”์•ฝ',
'ํ•œ ์ค„ ์š”์•ฝ', '์ •๋ฆฌํ•˜์ž๋ฉด', '์ด์ •๋ฆฌ', '๊ธ€์„ ๋งˆ์น˜๋ฉฐ',
'์ด์ƒ์œผ๋กœ', '์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค', '์ฐธ๊ณ ํ•˜์„ธ์š”', '๋„์›€์ด ๋˜์…จ๊ธธ',
'์ข‹์€ ํ•˜๋ฃจ ๋˜์„ธ์š”', '๋‹ค์Œ ๊ธ€์—์„œ', '๋„์›€์ด ๋˜์—ˆ๊ธธ',
'์ฆ๊ฑฐ์šด ํ•˜๋ฃจ ๋˜์„ธ์š”', '๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค'
]
# ๋ฌธ๋‹จ๋ณ„๋กœ ๋‚˜๋ˆ„์–ด ์ฒ˜๋ฆฌ
lines = text.split('\n')
result_lines = []
for line in lines:
if "๋‹ค์Œ ์„น์…˜์—์„œ๋Š”" in line:
parts = line.split("๋‹ค์Œ ์„น์…˜์—์„œ๋Š”")
if parts[0].strip():
result_lines.append(parts[0].strip())
else:
# ๋ถˆํ•„์š”ํ•œ ํ‘œํ˜„ ์ œ๊ฑฐ (๊ตฌ๋‘์  ํฌํ•จ)
for phrase in unwanted_phrases:
# ๋ถˆํ•„์š”ํ•œ ํ‘œํ˜„ ์•ž๋’ค์˜ ๊ตฌ๋‘์ ๊ณผ ๊ณต๋ฐฑ๊นŒ์ง€ ํฌํ•จํ•˜์—ฌ ์ œ๊ฑฐ
pattern = rf'(\b{re.escape(phrase)}\b[\s,.!?]*)|([,.!?]*\b{re.escape(phrase)}\b)'
line = re.sub(pattern, '', line)
# ๋ฌธ์žฅ ๋‚ด ์ž”์—ฌ ๊ณต๋ฐฑ ๋ฐ ๊ตฌ๋‘์  ์ •๋ฆฌ
line = re.sub(r'\s{2,}', ' ', line) # ์—ฐ์† ๊ณต๋ฐฑ ์ œ๊ฑฐ
line = line.strip() # ์•ž๋’ค ๊ณต๋ฐฑ ์ œ๊ฑฐ
result_lines.append(line)
return '\n'.join(result_lines)
def convert_to_html(text):
"""๋งˆํฌ๋‹ค์šด ํ˜•์‹์„ HTML๋กœ ๋ณ€ํ™˜"""
text = re.sub(r'^\s*[-*]\s+', '', text, flags=re.MULTILINE)
text = re.sub(r'^\s*\d+\.\s+', '', text, flags=re.MULTILINE)
text = re.sub(r'^\s*#{1,6}\s+', '', text, flags=re.MULTILINE)
return markdown2.markdown(text)
def format_blog_post(blog_post, query="", with_title=False):
"""๋ธ”๋กœ๊ทธ ํฌ์ŠคํŠธ ํฌ๋งทํŒ… ํ•จ์ˆ˜ - ์†Œ์ œ๋ชฉ ๊ฐ•ํ™” ๋ฒ„์ „"""
blog_post = re.sub(r'^#+\s+', '', blog_post, flags=re.MULTILINE)
blog_post = re.sub(r'^\d+\.\s+', '', blog_post, flags=re.MULTILINE)
blog_post = re.sub(r'^[\*\-]\s+', '', blog_post, flags=re.MULTILINE)
# ์ฒซ ์ค„(์›๋ณธ ์ œ๋ชฉ)๊ณผ ๋น„์Šทํ•œ ํŒจํ„ด์ด ์žˆ๋‹ค๋ฉด ์ œ๊ฑฐ
lines = blog_post.split('\n')
if lines and len(lines) > 0:
first_line = lines[0].strip()
# ์ฒซ ์ค„์ด ์ œ๋ชฉ์ธ ๊ฒฝ์šฐ, ๋น„์Šทํ•œ ๋‚ด์šฉ์˜ ๋ผ์ธ์„ ๋ชจ๋‘ ์ œ๊ฑฐ
if first_line and len(first_line) > 5:
# ์ฒซ ์ค„๊ณผ ์œ ์‚ฌํ•œ ๋‚ด์šฉ์„ ๊ฐ€์ง„ ๋ผ์ธ ์ฐพ์•„ ์ œ๊ฑฐ
filtered_lines = []
for line in lines:
# ์ฒซ ์ค„๊ณผ ์œ ์‚ฌํ•˜๋ฉด ์ œ๊ฑฐ
if line.strip() and (first_line in line or line in first_line):
continue
filtered_lines.append(line)
lines = filtered_lines
# ๋„์ž…๋ถ€, ๊ฒฐ๋ก  ์†Œ์ œ๋ชฉ ํŒจํ„ด
intro_pattern = r'(?i)๋„์ž…๋ถ€\s*[:]?\s*(.*?)$'
conclusion_pattern = r'(?i)๊ฒฐ๋ก \s*[:]?\s*(.*?)$'
# ๋„์ž…๋ถ€, ๊ฒฐ๋ก  ์†Œ์ œ๋ชฉ ์ œ๊ฑฐ
filtered_lines = []
for line in lines:
if re.match(intro_pattern, line) or re.match(conclusion_pattern, line):
continue
filtered_lines.append(line)
lines = filtered_lines
# ๋ณธ๋ก  ์†Œ์ œ๋ชฉ ํŒจํ„ด ๊ฐ•ํ™”
section_patterns = [
r'^๋ณธ๋ก \d+\s*[:]?\s*(.*?)$', # ๋ณธ๋ก 1: ๋‚ด์šฉ ํŒจํ„ด
r'^.{5,50}์˜ [๊ฐ€-ํžฃ\s]+$', # ~์˜ ~ ํŒจํ„ด
r'^[๊ฐ€-ํžฃ\s]{5,30}(์ด๋ž€|์ด๋ž€\?|์ด๋ž€\s๋ฌด์—‡์ธ๊ฐ€|์ด๋ž€\s๋ฌด์—‡์ผ๊นŒ)[\?\s]*$', # ~์ด๋ž€? ํŒจํ„ด
r'^[๊ฐ€-ํžฃ\s]{5,50}\s[-โ€“]\s.{5,30}$', # ๊ฐ•์กฐ ํ‘œํ˜„ ํŒจํ„ด (์˜ˆ: ํšจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ• - ์‹ค์ฒœํ•˜๊ธฐ)
r'^[๊ฐ€-ํžฃA-Za-z\s]{10,50}[\.!\?]$', # ๊ธด ๋ฌธ์žฅ์œผ๋กœ ๋œ ์†Œ์ œ๋ชฉ ํŒจํ„ด
]
formatted_lines = []
in_paragraph = False
# ๋ณธ๋ก  ์„น์…˜ ๋ฒˆํ˜ธ ์ถ”์ 
section_number = 1
for i, line in enumerate(lines):
line = line.strip()
if not line:
if in_paragraph:
formatted_lines.append("</p>")
in_paragraph = False
formatted_lines.append("<br>")
continue
# ๋‹ค์Œ ์ค„๊ณผ ์ด์ „ ์ค„์ด ๋น„์–ด์žˆ๋Š”์ง€ ํ™•์ธ
prev_empty = i == 0 or not lines[i-1].strip()
next_empty = i == len(lines) - 1 or not lines[i+1].strip()
# ์†Œ์ œ๋ชฉ์ธ์ง€ ์ฒดํฌ
is_subtitle = False
clean_subtitle = line
# ํŒจํ„ด ๋งค์นญ์œผ๋กœ ์†Œ์ œ๋ชฉ ํ™•์ธ
for pattern in section_patterns:
if re.match(pattern, line):
is_subtitle = True
# ๋ณธ๋ก X: ํŒจํ„ด์ธ ๊ฒฝ์šฐ ์ •๋ฆฌ
if "๋ณธ๋ก " in line:
clean_subtitle = re.sub(r'^๋ณธ๋ก \d+\s*[:]?\s*', '', line)
break
# ํŒจํ„ด์— ๋งค์นญ๋˜์ง€ ์•Š์•˜์ง€๋งŒ ๋‹ค์Œ ๊ทœ์น™์œผ๋กœ ์†Œ์ œ๋ชฉ์œผ๋กœ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ
if not is_subtitle:
# ์•ž๋’ค ์ค„์ด ๋น„์–ด์žˆ๊ณ , ๊ธธ์ด๊ฐ€ ์งง์€(5-50์ž) ๋ฌธ์žฅ์€ ์†Œ์ œ๋ชฉ์œผ๋กœ ์ฒ˜๋ฆฌ
if prev_empty and next_empty and 5 <= len(line) <= 50:
is_subtitle = True
# ์ด์ „์— ์žˆ๋˜ ์†Œ์ œ๋ชฉ๋“ค๊ณผ ๋น„์Šทํ•œ ๊ธธ์ด๋ฅผ ๊ฐ€์ง„ ๊ฒฝ์šฐ๋„ ์†Œ์ œ๋ชฉ์œผ๋กœ ๊ฐ„์ฃผ
elif section_number > 1 and prev_empty and 5 <= len(line) <= 50:
is_subtitle = True
if is_subtitle and clean_subtitle.strip():
if in_paragraph:
formatted_lines.append("</p>")
in_paragraph = False
# ์†Œ์ œ๋ชฉ์ด ์—†๊ฑฐ๋‚˜ ๋„ˆ๋ฌด ์งง์€ ๊ฒฝ์šฐ ๊ธฐ๋ณธ ์†Œ์ œ๋ชฉ ์‚ฌ์šฉ
if not clean_subtitle.strip() or len(clean_subtitle.strip()) < 2:
clean_subtitle = f"์ฃผ์š” ํฌ์ธํŠธ {section_number}"
# ์†Œ์ œ๋ชฉ ํ˜•์‹ ๊ฐ•ํ™” - ํ•ญ์ƒ ๋ณผ๋“œ์ฒ˜๋ฆฌ์™€ ์Šคํƒ€์ผ๋ง ์ ์šฉ
formatted_lines.append(
f'<h2 style="font-size: 1.4em; margin-top: 30px; margin-bottom: 15px; font-weight: bold; color: #333; border-bottom: 1px solid #eee; padding-bottom: 8px;">{html.escape(clean_subtitle)}</h2>'
)
section_number += 1
else:
# ์ผ๋ฐ˜ ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ
if not in_paragraph:
formatted_lines.append("<p>")
in_paragraph = True
content = html.escape(line)
bold_content = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', content)
formatted_lines.append(bold_content)
if in_paragraph:
formatted_lines.append("</p>")
return '\n'.join(formatted_lines)
# -------------------------------
# ์Šคํƒ€์ผ ๋ฐ ํ”„๋กฌํ”„ํŠธ ๊ฐ€์ด๋“œ ํ•จ์ˆ˜
# -------------------------------
def get_style_prompt(style="์นœ๊ทผํ•œ"):
"""๋ธ”๋กœ๊ทธ ๊ธ€์˜ ์Šคํƒ€์ผ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋ฐ˜ํ™˜"""
prompts = {
"์นœ๊ทผํ•œ": """
[์นœ๊ทผํ•œ ์—ฌํ–‰ ๋ธ”๋กœ๊ทธ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ]
1. ํ†ค๊ณผ ์–ด์กฐ
- ๋Œ€ํ™”ํ•˜๋“ฏ ํŽธ์•ˆํ•˜๊ณ  ์นœ๊ทผํ•œ ๋งํˆฌ ์‚ฌ์šฉ
- ์—ฌํ–‰์ง€์— ๋Œ€ํ•œ ๊ด€์‹ฌ๊ณผ ํ˜ธ๊ธฐ์‹ฌ์„ ๋‹ด์€ ํ‘œํ˜„ ์‚ฌ์šฉ
- ์‹ค์ œ ์—ฌํ–‰์„ ๊ฒฝํ—˜ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์ƒ์ƒํ•œ ๋ฌ˜์‚ฌ
2. ๋ฌธ์žฅ ๋ฐ ์–ดํˆฌ
- ๋ฐ˜๋“œ์‹œ 'ํ•ด์š”์ฒด'๋กœ ์ž‘์„ฑ, ์ ˆ๋Œ€ '์Šต๋‹ˆ๋‹ค'์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ง ๊ฒƒ
- '~์š”'๋กœ ๋๋‚˜๋„๋ก ์ž‘์„ฑ, '~๋‹ค'๋กœ ๋๋‚˜์ง€ ์•Š๊ฒŒ ํ•˜๋ผ
- ๊ตฌ์–ด์ฒด ํ‘œํ˜„ ์‚ฌ์šฉ (์˜ˆ: "~ํ–ˆ์–ด์š”", "~์ธ ๊ฒƒ ๊ฐ™์•„์š”")
- ์ ์ ˆํ•œ ๊ฐ์ • ํ‘œํ˜„๊ณผ ๊ณต๊ฐ๋Œ€ ํ˜•์„ฑ
3. ์šฉ์–ด ๋ฐ ์„ค๋ช… ๋ฐฉ์‹
- ์—ฌํ–‰ ๊ด€๋ จ ์ „๋ฌธ ์šฉ์–ด๋Š” ์‰ฌ์šด ๋‹จ์–ด๋กœ ํ’€์–ด์„œ ์„ค๋ช…
- ๋น„์œ ๋‚˜ ์€์œ ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์žฅ์†Œ์™€ ๊ฒฝํ—˜ ๋ฌ˜์‚ฌ
- ์ˆ˜์‚ฌ์˜๋ฌธ๋ฌธ ํ™œ์šฉํ•˜์—ฌ ๋…์ž์™€ ์†Œํ†ตํ•˜๋Š” ๋А๋‚Œ ์ฃผ๊ธฐ (์˜ˆ: "์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์„ธ์š”?", "์ด๋Ÿฐ ๊ฒฝํ—˜ ์žˆ์œผ์‹ ๊ฐ€์š”?")
- ๊ตฌ์ฒด์  ์‚ฌ๋ก€์™€ ์‹ค์ œ ๊ฒฝํ—˜์— ๊ธฐ๋ฐ˜ํ•œ ํŒ ์ œ๊ณต
4. ์ •๋ณด ์ „๋‹ฌ ๋ฐฉ์‹
- ๊ฐœ์ธ์ ์ธ ๊ด€์ ์— ๋…น์—ฌ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ •๋ณด ์ „๋‹ฌ
- ์‹ค์ œ ์—ฌํ–‰์ž์˜ ์‹œ์„ ์œผ๋กœ ์žฅ์†Œ์™€ ๊ฒฝํ—˜ ๋ฌ˜์‚ฌ
- ๋…์ž๊ฐ€ ์‹ค์ œ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‹ค์šฉ์  ์ •๋ณด ์ œ๊ณต (๊ตํ†ต, ๋น„์šฉ, ์‹œ๊ฐ„, ์ถ”์ฒœ ์ฝ”์Šค ๋“ฑ)
5. ๋…์ž์™€์˜ ์ƒํ˜ธ์ž‘์šฉ
- ๋…์ž์˜ ์˜๊ฒฌ์„ ๋ฌผ์–ด๋ณด๋Š” ์งˆ๋ฌธ ํฌํ•จ
- ์‹ค์ œ ์—ฌํ–‰์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํŒ์ด๋‚˜ ์กฐ์–ธ ์ œ๊ณต
์ฃผ์˜์‚ฌํ•ญ: ์ž์—ฐ์Šค๋Ÿฌ์šด ๋Œ€ํ™”์ฒด๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ์ •๋ณด์˜ ์งˆ๊ณผ ๋‚ด์šฉ์˜ ๊นŠ์ด๋ฅผ ์žƒ์ง€ ์•Š๋„๋ก ํ•œ๋‹ค
""",
"์ผ๋ฐ˜": """
[์ผ๋ฐ˜์ ์ธ ์—ฌํ–‰ ๋ธ”๋กœ๊ทธ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ]
1. ํ†ค๊ณผ ์–ด์กฐ
- ์ค‘๋ฆฝ์ ์ด๊ณ  ๊ฐ๊ด€์ ์ธ ํ†ค ์œ ์ง€
- ์ ์ ˆํ•œ ์กด๋Œ“๋ง ์‚ฌ์šฉ (์˜ˆ: "~ํ•ฉ๋‹ˆ๋‹ค", "~์ž…๋‹ˆ๋‹ค")
- ์—ฌํ–‰ ์ •๋ณด ์ „๋‹ฌ ์ค‘์‹ฌ์˜ ๋ช…ํ™•ํ•œ ์–ดํˆฌ
2. ๋‚ด์šฉ ๊ตฌ์กฐ ๋ฐ ์ „๊ฐœ
- ๋ช…ํ™•ํ•œ ์—ฌํ–‰์ง€ ์†Œ๊ฐœ๋กœ ์‹œ์ž‘
- ๋…ผ๋ฆฌ์ ์ธ ์ˆœ์„œ๋กœ ์ •๋ณด ์ „๊ฐœ (๊ตํ†ต โ†’ ์ˆ™๋ฐ• โ†’ ๊ด€๊ด‘์ง€ โ†’ ์Œ์‹ ๋“ฑ)
- ํ•ต์‹ฌ ํฌ์ธํŠธ๋ฅผ ๊ฐ•์กฐํ•˜๋Š” ์†Œ์ œ๋ชฉ ํ™œ์šฉ
- ์ ์ ˆํ•œ ๊ธธ์ด์˜ ๋‹จ๋ฝ์œผ๋กœ ๊ตฌ์„ฑ
3. ์šฉ์–ด ๋ฐ ์„ค๋ช… ๋ฐฉ์‹
- ์ผ๋ฐ˜์ ์œผ๋กœ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ์šฉ์–ด ์„ ํƒ
- ํ•„์š”์‹œ ์ง€์—ญ ํŠน์œ ์˜ ์šฉ์–ด์— ๊ฐ„๋‹จํ•œ ์„ค๋ช… ์ถ”๊ฐ€
- ๊ฐ๊ด€์ ์ธ ์—ฌํ–‰ ์ •๋ณด ์ œ๊ณต์— ์ค‘์ 
- ๊ท ํ˜• ์žกํžŒ ์‹œ๊ฐ์—์„œ ์—ฌํ–‰์ง€์˜ ์žฅ๋‹จ์  ์ œ์‹œ
4. ์ •๋ณด ์ „๋‹ฌ ๋ฐฉ์‹
- ์—ฌํ–‰์ง€์˜ ๊ธฐ๋ณธ ์ •๋ณด์™€ ํŠน์ง• ๋ช…ํ™•ํ•˜๊ฒŒ ์ œ๊ณต
- ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ์™€ ์ถ”์ฒœ ์ฝ”์Šค ํฌํ•จ
- ์ตœ์‹  ์—ฌํ–‰ ์ •๋ณด์™€ ๋™ํ–ฅ ์ฐธ๊ณ 
5. ๋…์ž ์ƒํ˜ธ์ž‘์šฉ
- ์ ์ ˆํžˆ ๋…์ž์˜ ์ƒ๊ฐ์„ ๋ฌป๋Š” ์งˆ๋ฌธ ํฌํ•จ
- ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ํ‚ค์›Œ๋“œ ์ œ์‹œ
- ์‹ค์šฉ์ ์ธ ์—ฌํ–‰ ํŒ ์ œ๊ณต
์ฃผ์˜์‚ฌํ•ญ: ๊ฐ๊ด€์  ์ •๋ณด ์ œ๊ณต์„ ์ค‘์‹ฌ์œผ๋กœ ํ•˜๋˜, ๋…์ž์˜ ์—ฌํ–‰ ๊ณ„ํš๊ณผ ์‹คํ–‰์„ ๋„์šธ ์ˆ˜ ์žˆ๋Š” ๋งฅ๋ฝ๊ณผ ์„ค๋ช…์„ ์ถฉ๋ถ„ํžˆ ์ œ๊ณตํ•œ๋‹ค
""",
"์ „๋ฌธ์ ์ธ": """
[์ „๋ฌธ์ ์ธ ์—ฌํ–‰ ๋ธ”๋กœ๊ทธ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ]
1. ํ†ค๊ณผ ๊ตฌ์กฐ
- ๊ณต์‹์ ์ด๊ณ  ์ „๋ฌธ์ ์ธ ํ†ค ์‚ฌ์šฉ
- ๊ฐ๊ด€์ ์ด๊ณ  ๋ถ„์„์ ์ธ ์ ‘๊ทผ ์œ ์ง€
- ๋ช…ํ™•ํ•œ ์„œ๋ก (์—ฌํ–‰์ง€ ๊ฐœ์š”), ๋ณธ๋ก (์ƒ์„ธ ๋ถ„์„), ๊ฒฐ๋ก (์ข…ํ•ฉ ํ‰๊ฐ€) ๊ตฌ์กฐ
- ์ฒด๊ณ„์ ์ธ ์—ฌํ–‰ ์ •๋ณด ์ „๊ฐœ
- ์„ธ๋ถ€ ์„น์…˜์„ ์œ„ํ•œ ๋ช…ํ™•ํ•œ ์†Œ์ œ๋ชฉ ์‚ฌ์šฉ
2. ๋‚ด์šฉ ๊ตฌ์„ฑ ๋ฐ ์ „๊ฐœ
- ์—ฌํ–‰์ง€์˜ ์—ญ์‚ฌ์  ๋ฐฐ๊ฒฝ, ๋ฌธํ™”์  ํŠน์ง•, ํ˜„์žฌ ๋™ํ–ฅ ๋“ฑ ์‹ฌ์ธต์  ์ •๋ณด ํฌํ•จ
- ๋…ผ๋ฆฌ์  ์—ฐ๊ฒฐ์„ ์œ„ํ•œ ์ „ํ™˜์–ด ํ™œ์šฉ
- ์—ฌํ–‰ ์šฉ์–ด ์ ์ ˆํžˆ ํ™œ์šฉ (ํ•„์š”์‹œ ๊ฐ„๋žตํ•œ ์„ค๋ช… ์ œ๊ณต)
- ์‹ฌ์ธต์ ์ธ ๋ถ„์„๊ณผ ๋น„ํŒ์  ํ‰๊ฐ€ ์ œ๊ณต
- ๋‹ค์–‘ํ•œ ๊ด€์ ์—์„œ ์—ฌํ–‰์ง€ ๋ถ„์„
3. ๋ฐ์ดํ„ฐ ๋ฐ ๊ทผ๊ฑฐ ํ™œ์šฉ
- ํ†ต๊ณ„, ์‹œ์ฆŒ๋ณ„ ์ •๋ณด, ์‹ค์ œ ์‚ฌ๋ก€ ๋“ฑ ๊ฐ๊ด€์  ๋ฐ์ดํ„ฐ ํ™œ์šฉ
- ์—ฌํ–‰์ง€ ๋ถ„์„์„ ์œ„ํ•œ ์ฒด๊ณ„์ ์ธ ํ”„๋ ˆ์ž„์›Œํฌ ์ œ์‹œ
- ๊ฐ๊ด€์  ์ •๋ณด์™€ ์ „๋ฌธ๊ฐ€ ๊ด€์ ์˜ ๊ท ํ˜•
4. ์ „๋ฌธ์  ์ •๋ณด ์ œ๊ณต
- ์ตœ์‹  ์—ฌํ–‰ ๋™ํ–ฅ ๋ฐ ๋ณ€ํ™” ๋ถ„์„
- ๋ฌธํ™”, ์—ญ์‚ฌ์  ๋งฅ๋ฝ์—์„œ์˜ ์—ฌํ–‰์ง€ ๋ถ„์„
- ์—ฌํ–‰ ๊ด€๋ จ ์Ÿ์ ๊ณผ ๊ณ ๋ ค์‚ฌํ•ญ ์†Œ๊ฐœ
- ์ฒด๊ณ„์ ์ธ ์—ฌํ–‰ ๊ณ„ํš ์ ‘๊ทผ๋ฒ• ์ œ์‹œ
์ฃผ์˜์‚ฌํ•ญ: ์ „๋ฌธ์„ฑ๊ณผ ๊นŠ์ด๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ์ดํ•ด ๊ฐ€๋Šฅํ•œ ์šฉ์–ด์™€ ์„ค๋ช…์„ ํ†ตํ•ด ์ ‘๊ทผ์„ฑ์„ ๋†’์ธ๋‹ค
"""
}
return prompts.get(style, prompts["์นœ๊ทผํ•œ"])
def get_category_outline_prompt(category="์—ฌํ–‰ ๋‹จ์ผ"):
"""์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์•„์›ƒ๋ผ์ธ ์ƒ์„ฑ ํ”„๋กฌํ”„ํŠธ"""
prompts = {
"์—ฌํ–‰ ๋‹จ์ผ": """
[์—ฌํ–‰ ๋‹จ์ผ์ง€์  ์†Œ์ฃผ์ œ(Outline) ์ƒ์„ฑ ๊ทœ์น™]
[์‹œ์Šคํ…œ ์—ญํ• ]
๋‹น์‹ ์€ ์ˆ˜๋…„๊ฐ„์˜ ๊ฒฝํ—˜์„ ๊ฐ€์ง„ ์ „๋ฌธ ์—ฌํ–‰ ๋ธ”๋กœ๊ฑฐ์ž…๋‹ˆ๋‹ค. ํŠน์ • ๋ช…์†Œ, ์ถ•์ œ, ์ด๋ฒคํŠธ ๋“ฑ ๋‹จ์ผ ์—ฌํ–‰ ์ฝ”์Šค์— ๋Œ€ํ•œ ์ƒ์ƒํ•œ ๊ฒฝํ—˜๊ณผ ์œ ์šฉํ•œ ์ •๋ณด๋กœ ๋งŽ์€ ๋…์ž๋“ค์˜ ์‹ ๋ขฐ๋ฅผ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
[๋ถ„์„ ๋‹จ๊ณ„]
1.์ฐธ๊ณ  ์ž๋ฃŒ 3๊ฐœ๋ฅผ ์ฒ ์ €ํžˆ ๋ถ„์„ํ•˜์—ฌ ํ•ด๋‹น ๋ช…์†Œ/์ถ•์ œ์˜ ํ•ต์‹ฌ ํŠน์ง•๊ณผ ์ค‘์š” ์ •๋ณด ํŒŒ์•…
2. ์—ฌํ–‰ ๋ช…์†Œ/์ถ•์ œ์˜ ์œ ํ˜•๊ณผ ํŠน์„ฑ ์‹๋ณ„ (๊ณ„์ ˆ ์ถ•์ œ, ๋ฌธํ™” ํ–‰์‚ฌ, ์ž์—ฐ ๋ช…์†Œ, ์—ญ์‚ฌ ์œ ์ ์ง€ ๋“ฑ)
3. ํฌ์ŠคํŒ…์˜ ํ•ต์‹ฌ์ด ๋  5๊ฐ€์ง€ ์ฃผ์š” ์š”์†Œ ํŒŒ์•… (ํ–‰์‚ฌ ํŠน์ง•, ๋ณผ๊ฑฐ๋ฆฌ, ์ฆ๊ธธ๊ฑฐ๋ฆฌ, ๋ฐฉ๋ฌธ ํŒ, ๊ตํ†ต/ํŽธ์˜์‹œ์„ค ๋“ฑ)
[์•„์›ƒ๋ผ์ธ ๊ตฌ์„ฑ ์›์น™]
1. ๋„์ž…๋ถ€(1๊ฐœ) - ํ•ด๋‹น ๋ช…์†Œ/์ถ•์ œ์˜ ๋งค๋ ฅ์„ ์ง‘์•ฝํ•œ ํฅ๋ฏธ๋กœ์šด ์ œ๋ชฉ์œผ๋กœ ์‹œ์ž‘
2. ๋ณธ๋ก (4-5๊ฐœ) - ์ฐธ๊ณ  ์ž๋ฃŒ ๋ถ„์„์„ ํ†ตํ•ด ๋ฐœ๊ฒฌํ•œ ๋ช…์†Œ/์ถ•์ œ์˜ ํ•ต์‹ฌ ํŠน์ง•๊ณผ ๋ฐฉ๋ฌธ ์ •๋ณด๋ฅผ ๋‹ด์€ ์†Œ์ œ๋ชฉ
- ๋ช…์†Œ/์ถ•์ œ์˜ ์ฃผ์š” ํŠน์ง•๊ณผ ์—ญ์‚ฌ์ /๋ฌธํ™”์  ์˜๋ฏธ
- ๋ฐ˜๋“œ์‹œ ๋†“์น˜์ง€ ๋ง์•„์•ผ ํ•  ํ•ต์‹ฌ ๋ณผ๊ฑฐ๋ฆฌ์™€ ์ฆ๊ธธ๊ฑฐ๋ฆฌ
- ๋ฐฉ๋ฌธ ์‹œ๊ธฐ, ์‹œ๊ฐ„๋Œ€, ๊ณ„์ ˆ๋ณ„ ํŠน์ง•
- ๊ตํ†ต, ์ž…์žฅ๋ฃŒ, ์ฃผ์ฐจ, ํŽธ์˜์‹œ์„ค ๋“ฑ ์‹ค์šฉ์  ์ •๋ณด
- ๋ฐฉ๋ฌธ ์‹œ ์œ ์šฉํ•œ ๊ฟ€ํŒ๊ณผ ์ฃผ์˜์‚ฌํ•ญ
- (์œ„ ํ•ญ๋ชฉ๋“ค์€ ์˜ˆ์‹œ์ผ ๋ฟ, ์ฐธ๊ณ  ์ž๋ฃŒ ๋ถ„์„์„ ํ†ตํ•ด ์ž์œ ๋กญ๊ฒŒ ๊ฒฐ์ •)
3. ๊ฒฐ๋ก (1๊ฐœ) - ์ „์ฒด ๊ฒฝํ—˜์„ ์š”์•ฝํ•˜๊ณ  ๋ฐฉ๋ฌธ ๊ฐ€์น˜๋ฅผ ๊ฐ•์กฐํ•˜๋Š” ์ œ๋ชฉ
[ํ•ต์‹ฌ ์ง€์นจ]
1. ์™„์ „ํžˆ ํ•œ๊ตญ์–ด๋กœ๋งŒ ์ž‘์„ฑํ•  ๊ฒƒ
2. ์†Œ์ œ๋ชฉ์€ ์ตœ๋Œ€ 30์ž ์ด๋‚ด๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑ
3. ๋…์ž์˜ ํ˜ธ๊ธฐ์‹ฌ๊ณผ ๋ฐฉ๋ฌธ ์š•๊ตฌ๋ฅผ ์ž๊ทนํ•˜๋Š” ํ‘œํ˜„ ์‚ฌ์šฉ (์˜ˆ: "๋†“์น˜๋ฉด ํ›„ํšŒํ• ", "์ˆจ๊ฒจ์ง„ ์ฆ๊ธธ๊ฑฐ๋ฆฌ", "ํ˜„์ง€์ธ๋„ ์ถ”์ฒœํ•˜๋Š”")
4. ๋ช…์†Œ/์ถ•์ œ์˜ ๊ฐ€์žฅ ๋…ํŠนํ•˜๊ณ  ๋งค๋ ฅ์ ์ธ ํŠน์ง•์ด ์†Œ์ œ๋ชฉ์— ๋ฐ˜์˜๋˜๋„๋ก ๊ตฌ์„ฑ
5. ํ‚ค์›Œ๋“œ๋Š” ์†Œ์ œ๋ชฉ ๊ฒฐ์ •์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Œ (๋ณธ๋ฌธ ์ž‘์„ฑ ์‹œ ์ฐธ๊ณ ์‚ฌํ•ญ์œผ๋กœ๋งŒ ํ™œ์šฉ)
6. ์ „์ฒด ์•„์›ƒ๋ผ์ธ์€ ๋„์ž…๋ถ€(1) + ๋ณธ๋ก (์ตœ๋Œ€ 5๊ฐœ) + ๊ฒฐ๋ก (1)์œผ๋กœ ๊ตฌ์„ฑ
[์ถœ๋ ฅ ํ˜•์‹]
1. ์ฐธ๊ณ  ์ž๋ฃŒ ๋ถ„์„์„ ํ†ตํ•ด ๊ฐ€์žฅ ํ•ต์‹ฌ์ ์ธ ๋ช…์†Œ/์ถ•์ œ ํŠน์ง•๊ณผ ์ •๋ณด๋ฅผ ํŒŒ์•…ํ•˜์—ฌ ์ž์œ ๋กญ๊ฒŒ ์•„์›ƒ๋ผ์ธ ๊ตฌ์„ฑ
2. ํ•˜์ง€๋งŒ ๋ฐ˜๋“œ์‹œ ๋‹ค์Œ ๊ตฌ์กฐ๋ฅผ ์œ ์ง€ํ•  ๊ฒƒ:(๊ฐ ํ•ญ๋ชฉ๋‹น 1๋ฒˆ ์—”ํ„ฐ๋ฅผ ์ ์šฉํ•˜์—ฌ ๋นˆ์นธ์ด ๋‚˜์˜ค์ง€ ์•Š๋„๋กํ•˜๋ผ.)
3. ๋„์ž…๋ถ€: 1๊ฐœ (๋ช…์†Œ/์ถ•์ œ์˜ ๋งค๋ ฅ์„ ๋‹ด์€ ํฅ๋ฏธ๋กœ์šด ์ œ๋ชฉ)
4. ๋ณธ๋ก : 4-5๊ฐœ (๋ช…์†Œ/์ถ•์ œ์˜ ํ•ต์‹ฌ ํŠน์ง•๊ณผ ์‹ค์šฉ ์ •๋ณด๋ฅผ ๋ฐ˜์˜ํ•œ ์ œ๋ชฉ)
5. ๊ฒฐ๋ก : 1๊ฐœ (์ „์ฒด ๊ฒฝํ—˜ ์š”์•ฝ ๋ฐ ๋ฐฉ๋ฌธ ๊ฐ€์น˜ ๊ฐ•์กฐ ์ œ๋ชฉ)
6. ์†Œ์ œ๋ชฉ์€ ํ•ด๋‹น ๋ช…์†Œ/์ถ•์ œ์˜ ์‹ค์ œ ํŠน์ง•๊ณผ ๋ฐฉ๋ฌธ ์ •๋ณด์— ๋งž๊ฒŒ ์ž์œ ๋กญ๊ฒŒ ๊ตฌ์„ฑ
7. ํ‚ค์›Œ๋“œ์— ๋งž์ถ”์ง€ ๋ง๊ณ , ์ฐธ๊ณ  ์ž๋ฃŒ ๋ถ„์„์„ ํ†ตํ•ด ๋ฐœ๊ฒฌํ•œ ํ•ต์‹ฌ ๊ฐ€์น˜์™€ ์ •๋ณด ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑ
8. ์˜ˆ์‹œ ํ˜•์‹ (์ฐธ๊ณ ์šฉ์ผ ๋ฟ, ๋‚ด์šฉ์€ ์ฐธ๊ณ  ์ž๋ฃŒ์— ๋”ฐ๋ผ ์™„์ „ํžˆ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ):
- ๋„์ž…๋ถ€: [๋ช…์†Œ/์ถ•์ œ์˜ ๋งค๋ ฅ ์†Œ๊ฐœ ์ œ๋ชฉ]
- ๋ณธ๋ก 1: [ํ•ต์‹ฌ ํŠน์ง•/์—ญ์‚ฌ์  ์˜๋ฏธ ๊ด€๋ จ ์ œ๋ชฉ]
- ๋ณธ๋ก 2: [์ฃผ์š” ๋ณผ๊ฑฐ๋ฆฌ/์ฆ๊ธธ๊ฑฐ๋ฆฌ ๊ด€๋ จ ์ œ๋ชฉ]
- ๋ณธ๋ก 3: [์ตœ์ ์˜ ๋ฐฉ๋ฌธ ์‹œ๊ธฐ/์‹œ๊ฐ„ ๊ด€๋ จ ์ œ๋ชฉ]
- ๋ณธ๋ก 4: [๊ตํ†ต/ํŽธ์˜์‹œ์„ค ์ •๋ณด ๊ด€๋ จ ์ œ๋ชฉ]
- ๋ณธ๋ก 5: [๋ฐฉ๋ฌธ ๊ฟ€ํŒ/์ฃผ์˜์‚ฌํ•ญ ๊ด€๋ จ ์ œ๋ชฉ] (ํ•„์š”์‹œ)
- ๊ฒฐ๋ก : [๊ฒฝํ—˜ ์š”์•ฝ ๋ฐ ๋ฐฉ๋ฌธ ๊ฐ€์น˜ ๊ฐ•์กฐ ์ œ๋ชฉ]
""",
"์—ฌํ–‰ ์ฝ”์Šค": """
[์—ฌํ–‰ ์ฝ”์Šค ์†Œ์ฃผ์ œ(Outline) ์ƒ์„ฑ ๊ทœ์น™]
[์‹œ์Šคํ…œ ์—ญํ• ]
๋‹น์‹ ์€ ์ˆ˜๋…„๊ฐ„์˜ ๊ฒฝํ—˜์„ ๊ฐ€์ง„ ์ „๋ฌธ ์—ฌํ–‰ ์ฝ”์Šค ๊ธฐํš์ž์ž…๋‹ˆ๋‹ค. ํšจ์œจ์ ์ด๊ณ  ๋งค๋ ฅ์ ์ธ ์—ฌํ–‰ ์ฝ”์Šค ์„ค๊ณ„์™€ ์‹ค์šฉ์ ์ธ
์—ฌํ–‰ ํŒ์œผ๋กœ ๋งŽ์€ ๋…์ž๋“ค์˜ ์‹ ๋ขฐ๋ฅผ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
[๋ถ„์„ ๋‹จ๊ณ„]
1. ์ฐธ๊ณ  ์ž๋ฃŒ 3๊ฐœ๋ฅผ ์ฒ ์ €ํžˆ ๋ถ„์„ํ•˜์—ฌ ํ•ด๋‹น ์ง€์—ญ์˜ ํ•ต์‹ฌ ๋ช…์†Œ์™€ ์—ฌํ–‰ ์ •๋ณด ํŒŒ์•…
2. ์—ฌํ–‰ ์ง€์—ญ์˜ ์œ ํ˜•๊ณผ ํŠน์„ฑ ์‹๋ณ„ (๋„์‹œ ์—ฌํ–‰, ์ž์—ฐ ์—ฌํ–‰, ๋ฌธํ™” ํƒ๋ฐฉ, ๋ง›์ง‘ ํˆฌ์–ด ๋“ฑ)
3. ํฌ์ŠคํŒ…์˜ ํ•ต์‹ฌ์ด ๋  5๊ฐ€์ง€ ์ฃผ์š” ์š”์†Œ ํŒŒ์•… (์—ฌํ–‰ ๊ธฐ๊ฐ„, ์ฃผ์š” ๋ช…์†Œ, ์ด๋™ ๋ฐฉ๋ฒ•, ์ˆ™๋ฐ• ์˜ต์…˜, ์˜ˆ์‚ฐ ๋“ฑ)
[์•„์›ƒ๋ผ์ธ ๊ตฌ์„ฑ ์›์น™]
1. ๋„์ž…๋ถ€(1๊ฐœ) - ํ•ด๋‹น ์ง€์—ญ์˜ ๋งค๋ ฅ๊ณผ ์ฝ”์Šค์˜ ํŠน์ง•์„ ์ง‘์•ฝํ•œ ํฅ๋ฏธ๋กœ์šด ์ œ๋ชฉ์œผ๋กœ ์‹œ์ž‘
2. ๋ณธ๋ก (4-5๊ฐœ) - ์ฐธ๊ณ  ์ž๋ฃŒ ๋ถ„์„์„ ํ†ตํ•ด ์„ค๊ณ„ํ•œ ์—ฌํ–‰ ์ฝ”์Šค์˜ ์ฃผ์š” ์ผ์ •๊ณผ ์ •๋ณด๋ฅผ ๋‹ด์€ ์†Œ์ œ๋ชฉ
3. ์ฝ”์Šค ๊ฐœ์š”์™€ ์—ฌํ–‰ ๊ธฐ๊ฐ„๋ณ„ ์ถ”์ฒœ ์ผ์ •
4. ์ผ์ฐจ๋ณ„ ๋˜๋Š” ํ…Œ๋งˆ๋ณ„ ์„ธ๋ถ€ ์ฝ”์Šค ๊ตฌ์„ฑ
5. ํšจ์œจ์ ์ธ ์ด๋™ ๋ฐฉ๋ฒ•๊ณผ ๊ตํ†ต ์ •๋ณด
6. ์ˆ™์†Œ ๋ฐ ์‹๋‹น ์ถ”์ฒœ๊ณผ ์˜ˆ์•ฝ ํŒ
7. ์—ฌํ–‰ ์˜ˆ์‚ฐ๊ณผ ๋น„์šฉ ์ ˆ์•ฝ ๋ฐฉ๋ฒ•
8. (์œ„ ํ•ญ๋ชฉ๋“ค์€ ์˜ˆ์‹œ์ผ ๋ฟ, ์ฐธ๊ณ  ์ž๋ฃŒ ๋ถ„์„์„ ํ†ตํ•ด ์ž์œ ๋กญ๊ฒŒ ๊ฒฐ์ •)
9. ๊ฒฐ๋ก (1๊ฐœ) - ์ „์ฒด ์ฝ”์Šค์˜ ํŠน์ง•์„ ์š”์•ฝํ•˜๊ณ  ์—ฌํ–‰ ๊ณ„ํš ์ˆ˜๋ฆฝ์— ๋„์›€์„ ์ฃผ๋Š” ์ œ๋ชฉ
[ํ•ต์‹ฌ ์ง€์นจ]
1. ์™„์ „ํžˆ ํ•œ๊ตญ์–ด๋กœ๋งŒ ์ž‘์„ฑํ•  ๊ฒƒ
2. ์†Œ์ œ๋ชฉ์€ ์ตœ๋Œ€ 30์ž ์ด๋‚ด๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑ
3. ๋…์ž์˜ ์—ฌํ–‰ ๊ณ„ํš ์ˆ˜๋ฆฝ์„ ๋•๋Š” ์‹ค์šฉ์ ์ธ ํ‘œํ˜„ ์‚ฌ์šฉ (์˜ˆ: "์™„๋ฒฝํ•œ 3๋ฐ• 4์ผ ์ฝ”์Šค", "ํšจ์œจ์ ์ธ ๋™์„  ์„ค๊ณ„", "ํ˜„์ง€์ธ์ด ์•Œ๋ ค์ฃผ๋Š” ๊ฟ€์ฝ”์Šค")
4. ์ฝ”์Šค์˜ ํšจ์œจ์„ฑ๊ณผ ๋งค๋ ฅ์ ์ธ ํŠน์ง•์ด ์†Œ์ œ๋ชฉ์— ๋ฐ˜์˜๋˜๋„๋ก ๊ตฌ์„ฑ
5. ํ‚ค์›Œ๋“œ๋Š” ์†Œ์ œ๋ชฉ ๊ฒฐ์ •์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Œ (๋ณธ๋ฌธ ์ž‘์„ฑ ์‹œ ์ฐธ๊ณ ์‚ฌํ•ญ์œผ๋กœ๋งŒ ํ™œ์šฉ)
6. ์ „์ฒด ์•„์›ƒ๋ผ์ธ์€ ๋„์ž…๋ถ€(1) + ๋ณธ๋ก (์ตœ๋Œ€ 5๊ฐœ) + ๊ฒฐ๋ก (1)์œผ๋กœ ๊ตฌ์„ฑ
[์ถœ๋ ฅ ํ˜•์‹]
1. ์ฐธ๊ณ  ์ž๋ฃŒ ๋ถ„์„์„ ํ†ตํ•ด ๊ฐ€์žฅ ํšจ์œจ์ ์ด๊ณ  ๋งค๋ ฅ์ ์ธ ์—ฌํ–‰ ์ฝ”์Šค๋ฅผ ์„ค๊ณ„ํ•˜์—ฌ ์ž์œ ๋กญ๊ฒŒ ์•„์›ƒ๋ผ์ธ ๊ตฌ์„ฑ
2. ํ•˜์ง€๋งŒ ๋ฐ˜๋“œ์‹œ ๋‹ค์Œ ๊ตฌ์กฐ๋ฅผ ์œ ์ง€ํ•  ๊ฒƒ:(๊ฐ ํ•ญ๋ชฉ๋‹น 1๋ฒˆ ์—”ํ„ฐ๋ฅผ ์ ์šฉํ•˜์—ฌ ๋นˆ์นธ์ด ๋‚˜์˜ค์ง€ ์•Š๋„๋กํ•˜๋ผ.)
3. ๋„์ž…๋ถ€: 1๊ฐœ (์ง€์—ญ ๋งค๋ ฅ๊ณผ ์ฝ”์Šค ํŠน์ง•์„ ๋‹ด์€ ํฅ๋ฏธ๋กœ์šด ์ œ๋ชฉ)
4. ๋ณธ๋ก : 4-5๊ฐœ (ํšจ์œจ์ ์ธ ์—ฌํ–‰ ๋™์„ ๊ณผ ์‹ค์šฉ ์ •๋ณด๋ฅผ ๋ฐ˜์˜ํ•œ ์ œ๋ชฉ)
5. ๊ฒฐ๋ก : 1๊ฐœ (์ „์ฒด ์ฝ”์Šค ์š”์•ฝ ๋ฐ ๊ณ„ํš ์ˆ˜๋ฆฝ ๋„์›€ ์ œ๋ชฉ)
6. ์†Œ์ œ๋ชฉ์€ ํ•ด๋‹น ์ง€์—ญ์˜ ์‹ค์ œ ํŠน์ง•๊ณผ ์ฝ”์Šค ์ •๋ณด์— ๋งž๊ฒŒ ์ž์œ ๋กญ๊ฒŒ ๊ตฌ์„ฑ
7. ํ‚ค์›Œ๋“œ์— ๋งž์ถ”์ง€ ๋ง๊ณ , ์ฐธ๊ณ  ์ž๋ฃŒ ๋ถ„์„์„ ํ†ตํ•ด ๋ฐœ๊ฒฌํ•œ ํ•ต์‹ฌ ์ฝ”์Šค์™€ ์ •๋ณด ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑ
8. ์˜ˆ์‹œ ํ˜•์‹ (์ฐธ๊ณ ์šฉ์ผ ๋ฟ, ๋‚ด์šฉ์€ ์ฐธ๊ณ  ์ž๋ฃŒ์— ๋”ฐ๋ผ ์™„์ „ํžˆ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ):
- ๋„์ž…๋ถ€: [์ง€์—ญ ๋งค๋ ฅ๊ณผ ์ฝ”์Šค ํŠน์ง• ์†Œ๊ฐœ ์ œ๋ชฉ]
- ๋ณธ๋ก 1: [์—ฌํ–‰ ๊ธฐ๊ฐ„๋ณ„ ์ถ”์ฒœ ์ผ์ • ๊ด€๋ จ ์ œ๋ชฉ]
- ๋ณธ๋ก 2: [์ผ์ฐจ๋ณ„/ํ…Œ๋งˆ๋ณ„ ์„ธ๋ถ€ ์ฝ”์Šค ๊ด€๋ จ ์ œ๋ชฉ]
- ๋ณธ๋ก 3: [๊ตํ†ต/์ด๋™ ๋ฐฉ๋ฒ• ๊ด€๋ จ ์ œ๋ชฉ]
- ๋ณธ๋ก 4: [์ˆ™์†Œ/์‹๋‹น ์ถ”์ฒœ ๊ด€๋ จ ์ œ๋ชฉ]
- ๋ณธ๋ก 5: [์˜ˆ์‚ฐ/๋น„์šฉ ์ ˆ์•ฝ ํŒ ๊ด€๋ จ ์ œ๋ชฉ] (ํ•„์š”์‹œ)
- ๊ฒฐ๋ก : [์ฝ”์Šค ์š”์•ฝ ๋ฐ ๊ณ„ํš ์ˆ˜๋ฆฝ ๋„์›€ ์ œ๋ชฉ]
"""
}
return prompts.get(category, prompts["์—ฌํ–‰ ๋‹จ์ผ"])
def get_category_blog_prompt(category="์—ฌํ–‰ ๋‹จ์ผ"):
"""์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑ ํ”„๋กฌํ”„ํŠธ"""
prompts = {
"์—ฌํ–‰ ๋‹จ์ผ": """
[์—ฌํ–‰ ๋‹จ์ผ์ง€์  ๋ธ”๋กœ๊ทธ ์ž‘์„ฑ ๊ฐ€์ด๋“œ]
1. ๋„ˆ๋Š” ์ตœ๊ณ ์˜ ์—ฌํ–‰ ๋ธ”๋กœ๊ทธ ์ž‘๊ฐ€์ด์ž ์—ฌํ–‰ ์ •๋ณด ์ „๋‹ฌ ์ „๋ฌธ๊ฐ€์ด๋‹ค.
2. ์ฃผ์–ด์ง„ ์•„์›ƒ๋ผ์ธ๊ณผ ์ฐธ๊ณ ๊ธ€์„ ๋ฐ”ํƒ•์œผ๋กœ ๋…์ž์—๊ฒŒ ๊ฐ€์น˜ ์žˆ๋Š” ์—ฌํ–‰ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋ผ.
3. ์ •๋ณด์˜ ์ •ํ™•์„ฑ๊ณผ ๊นŠ์ด๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•˜๋ผ.
[์ฝ˜ํ…์ธ  ์ž‘์„ฑ ๊ทœ์น™]
1. ์—ฌํ–‰์ง€์— ๋Œ€ํ•œ ๊ฐ๊ด€์ ์ธ ์ •๋ณด ์ œ๊ณต์— ์ค‘์ ์„ ๋‘๋˜, ๋…์ž์˜ ๊ด€์‹ฌ๊ณผ ์ฐธ์—ฌ๋ฅผ ์œ ๋„ํ•˜๋ผ.
2. ์—ฌํ–‰์ง€์˜ ํŠน์ง•๊ณผ ๋งค๋ ฅ์„ ์ƒ์ƒํ•˜๊ฒŒ ๋ฌ˜์‚ฌํ•˜๋ผ.
3. ์—ฌํ–‰์ง€์— ๋Œ€ํ•œ ๋‹ค์–‘ํ•œ ๊ด€์ ๊ณผ ์ธก๋ฉด์„ ๊ท ํ˜• ์žˆ๊ฒŒ ๋‹ค๋ฃจ์–ด๋ผ.
4. ๋…์ž๊ฐ€ ์‹ค์ œ ์—ฌํ–‰์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‹ค์šฉ์ ์ธ ์ •๋ณด์™€ ํŒ์„ ์ œ๊ณตํ•˜๋ผ.
- ๊ตํ†ต ์ •๋ณด: ๋Œ€์ค‘๊ตํ†ต, ์ฃผ์ฐจ, ํƒ์‹œ ๋“ฑ
- ๋น„์šฉ ์ •๋ณด: ์ž…์žฅ๋ฃŒ, ํ‰๊ท  ์‹์‚ฌ ๋น„์šฉ ๋“ฑ
- ์‹œ๊ฐ„ ์ •๋ณด: ์ตœ์  ๋ฐฉ๋ฌธ ์‹œ๊ฐ„, ์†Œ์š” ์‹œ๊ฐ„ ๋“ฑ
- ์ถ”์ฒœ ์ฝ”์Šค: ๊ด€๊ด‘์ง€ ๋‚ด ๋™์„ , ์ธ๊ทผ ์—ฐ๊ณ„ ๊ด€๊ด‘์ง€ ๋“ฑ
5. ์ฐธ๊ณ ๊ธ€์˜ ์ •๋ณด๋ฅผ ์žฌ๊ตฌ์„ฑํ•˜๋˜, ํ‘œํ˜„์„ ๋‹จ์ˆœํžˆ ๋ณต์‚ฌํ•˜์ง€ ๋ง๊ณ  ์ฐฝ์˜์ ์œผ๋กœ ์žฌ๊ตฌ์„ฑํ•˜๋ผ.
6. ๊ฐ ์„น์…˜์€ ์ตœ์†Œ {MIN_SECTION_LENGTH}์ž ์ด์ƒ์˜ ์ถฉ๋ถ„ํ•œ ๋‚ด์šฉ์œผ๋กœ ์ž‘์„ฑํ•˜๋ผ.
7. ๊ธ€ ์ „์ฒด ๊ธธ์ด๋Š” ์ตœ์†Œ {TARGET_CHAR_LENGTH}์ž๊ฐ€ ๋˜๋„๋ก ์ž‘์„ฑํ•˜๋ผ.
8. ๊ธ€ ์ „์ฒด ๊ธธ์ด๋Š” {TARGET_CHAR_LENGTH}์ž์—์„œ {TARGET_CHAR_LENGTH + 1000}์ž ์‚ฌ์ด๊ฐ€ ๋˜๋„๋ก ์ž‘์„ฑํ•˜๋ผ.
[์ค‘์š” ๊ทœ์น™]
1. ๋งˆํฌ๋‹ค์šด ํ˜•์‹(#, *, -, 1., 2. ๋“ฑ)์„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  ์ผ๋ฐ˜ ํ…์ŠคํŠธ๋กœ ์ž‘์„ฑํ•˜๋ผ.
2. ์†Œ์ œ๋ชฉ๊ณผ ๊ฒฐ๋ก ์€ ๋ฒˆํ˜ธ ์—†์ด ์ผ๋ฐ˜ ๋ฌธ์žฅ ํ˜•ํƒœ๋กœ ์ž‘์„ฑํ•˜๋ผ.
3. ๋ชฉ๋ก์€ ๋ถˆ๋ฆฟ์ด๋‚˜ ๋ฒˆํ˜ธ ๋Œ€์‹  ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ฌธ์žฅ์œผ๋กœ ์„œ์ˆ ํ•˜๋ผ.
4. "์ฐธ๊ณ ๊ธ€", "์ฐธ๊ณ ๊ธ€์— ๋”ฐ๋ฅด๋ฉด" ๋“ฑ์˜ ํ‘œํ˜„์„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๋ผ.
5. "์—ฌ๋Ÿฌ๋ถ„", "๋…์ž ์—ฌ๋Ÿฌ๋ถ„" ๋“ฑ์˜ ์ง์ ‘์ ์ธ ํ˜ธ์นญ์„ ์ง€์–‘ํ•˜๋ผ.
""",
"์—ฌํ–‰ ์ฝ”์Šค": """
[์—ฌํ–‰ ์ฝ”์Šค ๋ธ”๋กœ๊ทธ ์ž‘์„ฑ ๊ฐ€์ด๋“œ]
1. ๋„ˆ๋Š” ์ตœ๊ณ ์˜ ์—ฌํ–‰ ์ฝ”์Šค ๋ธ”๋กœ๊ทธ ์ž‘๊ฐ€์ด์ž ์—ฌํ–‰ ์ผ์ • ๊ธฐํš ์ „๋ฌธ๊ฐ€์ด๋‹ค.
2. ์ฃผ์–ด์ง„ ์•„์›ƒ๋ผ์ธ๊ณผ ์ฐธ๊ณ ๊ธ€์„ ๋ฐ”ํƒ•์œผ๋กœ ๋…์ž์—๊ฒŒ ์ตœ์ ํ™”๋œ ์—ฌํ–‰ ์ฝ”์Šค ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋ผ.
3. ์ •๋ณด์˜ ์ •ํ™•์„ฑ๊ณผ ๊นŠ์ด๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ์‹ค์ œ ์—ฌํ–‰์— ์ ์šฉํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•˜๋ผ.
[์ฝ˜ํ…์ธ  ์ž‘์„ฑ ๊ทœ์น™]
1. ์—ฌํ–‰ ์ฝ”์Šค์— ๋Œ€ํ•œ ๊ฐ๊ด€์ ์ธ ์ •๋ณด ์ œ๊ณต์— ์ค‘์ ์„ ๋‘๋˜, ๋…์ž์˜ ๊ด€์‹ฌ๊ณผ ์ฐธ์—ฌ๋ฅผ ์œ ๋„ํ•˜๋ผ.
2. ์—ฌํ–‰ ์ฝ”์Šค์˜ ๋…ผ๋ฆฌ์  ํ๋ฆ„๊ณผ ํšจ์œจ์„ฑ์„ ๋ช…ํ™•ํžˆ ์„ค๋ช…ํ•˜๋ผ.
3. ์‹œ๊ฐ„, ๊ฑฐ๋ฆฌ, ๊ตํ†ต ์ •๋ณด๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์ œ์‹œํ•˜์—ฌ ์‹ค์ œ ์—ฌํ–‰ ๊ณ„ํš์— ๋„์›€์„ ์ฃผ๋ผ.
4. ๋…์ž๊ฐ€ ์‹ค์ œ ์—ฌํ–‰์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‹ค์šฉ์ ์ธ ์ •๋ณด์™€ ํŒ์„ ์ œ๊ณตํ•˜๋ผ.
- ์ผ์ž๋ณ„ ์„ธ๋ถ€ ์ผ์ • ๋ฐ ์†Œ์š” ์‹œ๊ฐ„
- ์žฅ์†Œ๊ฐ„ ์ด๋™ ๋ฐฉ๋ฒ• ๋ฐ ์†Œ์š” ์‹œ๊ฐ„
- ๊ฐ ์žฅ์†Œ๋ณ„ ์ฃผ์š” ๋ณผ๊ฑฐ๋ฆฌ ๋ฐ ์ถ”์ฒœ ํ™œ๋™
- ์‹์‚ฌ ๋ฐ ํœด์‹ ์žฅ์†Œ ์ถ”์ฒœ
- ์˜ˆ์‚ฐ ์ •๋ณด ๋ฐ ์˜ˆ์•ฝ ํŒ
5. ์ฐธ๊ณ ๊ธ€์˜ ์ •๋ณด๋ฅผ ์žฌ๊ตฌ์„ฑํ•˜๋˜, ํ‘œํ˜„์„ ๋‹จ์ˆœํžˆ ๋ณต์‚ฌํ•˜์ง€ ๋ง๊ณ  ์ฐฝ์˜์ ์œผ๋กœ ์žฌ๊ตฌ์„ฑํ•˜๋ผ.
6. ๊ฐ ์„น์…˜์€ ์ตœ์†Œ {MIN_SECTION_LENGTH}์ž ์ด์ƒ์˜ ์ถฉ๋ถ„ํ•œ ๋‚ด์šฉ์œผ๋กœ ์ž‘์„ฑํ•˜๋ผ.
7. ๊ธ€ ์ „์ฒด ๊ธธ์ด๋Š” ์ตœ์†Œ {TARGET_CHAR_LENGTH}์ž๊ฐ€ ๋˜๋„๋ก ์ž‘์„ฑํ•˜๋ผ.
8. ๊ธ€ ์ „์ฒด ๊ธธ์ด๋Š” {TARGET_CHAR_LENGTH}์ž์—์„œ {TARGET_CHAR_LENGTH + 1000}์ž ์‚ฌ์ด๊ฐ€ ๋˜๋„๋ก ์ž‘์„ฑํ•˜๋ผ.
[์ค‘์š” ๊ทœ์น™]
1. ๋งˆํฌ๋‹ค์šด ํ˜•์‹(#, *, -, 1., 2. ๋“ฑ)์„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  ์ผ๋ฐ˜ ํ…์ŠคํŠธ๋กœ ์ž‘์„ฑํ•˜๋ผ.
2. ์†Œ์ œ๋ชฉ๊ณผ ๊ฒฐ๋ก ์€ ๋ฒˆํ˜ธ ์—†์ด ์ผ๋ฐ˜ ๋ฌธ์žฅ ํ˜•ํƒœ๋กœ ์ž‘์„ฑํ•˜๋ผ.
3. ๋ชฉ๋ก์€ ๋ถˆ๋ฆฟ์ด๋‚˜ ๋ฒˆํ˜ธ ๋Œ€์‹  ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ฌธ์žฅ์œผ๋กœ ์„œ์ˆ ํ•˜๋ผ.
4. "์ฐธ๊ณ ๊ธ€", "์ฐธ๊ณ ๊ธ€์— ๋”ฐ๋ฅด๋ฉด" ๋“ฑ์˜ ํ‘œํ˜„์„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๋ผ.
5. "์—ฌ๋Ÿฌ๋ถ„", "๋…์ž ์—ฌ๋Ÿฌ๋ถ„" ๋“ฑ์˜ ์ง์ ‘์ ์ธ ํ˜ธ์นญ์„ ์ง€์–‘ํ•˜๋ผ.
"""
}
return prompts.get(category, prompts["์—ฌํ–‰ ๋‹จ์ผ"])
def generate_blog_post(category, style, outline_input, references1, references2, references3):
"""ํ•œ ๋ฒˆ์˜ ํ˜ธ์ถœ๋กœ ์ „์ฒด ๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑ ํ•จ์ˆ˜ (ํ‡ด๊ณ  ๋ฐ ํ™•์žฅ ๊ธฐ๋Šฅ ํฌํ•จ)"""
try:
# ์ฐธ๊ณ ๊ธ€ ์ค€๋น„
references = [
references1.strip() if references1.strip() else "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ",
references2.strip() if references2.strip() else "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ",
references3.strip() if references3.strip() else "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ"
]
# ์˜๋ฏธ ์žˆ๋Š” ์ฐธ๊ณ ๊ธ€๋งŒ ํ•„ํ„ฐ๋ง
references = [ref for ref in references if ref != "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ"]
if not references:
return "<p>์ฐธ๊ณ  ์ž๋ฃŒ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ตœ์†Œ ํ•˜๋‚˜ ์ด์ƒ์˜ ์ฐธ๊ณ  ์ž๋ฃŒ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.</p>", 0
if not outline_input.strip():
return "<p>์•„์›ƒ๋ผ์ธ์ด ์—†์Šต๋‹ˆ๋‹ค. ์•„์›ƒ๋ผ์ธ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.</p>", 0
# ์นดํ…Œ๊ณ ๋ฆฌ ๋ฐ ์Šคํƒ€์ผ ํ”„๋กฌํ”„ํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ
category_prompt = get_category_blog_prompt(category)
style_prompt = get_style_prompt(style)
# Phase 1: ์ดˆ๊ธฐ ๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑ
blog_prompt = f"""
[์—ฌํ–‰ ๋ธ”๋กœ๊ทธ ๊ธ€ ์ž‘์„ฑ ์š”์ฒญ]
์นดํ…Œ๊ณ ๋ฆฌ: {category}
ํฌ์ŠคํŒ… ์Šคํƒ€์ผ: {style}
์•„์›ƒ๋ผ์ธ:
{outline_input}
์ฐธ๊ณ ๊ธ€:
{references[0]}
{references[1] if len(references) > 1 else ""}
{references[2] if len(references) > 2 else ""}
{category_prompt}
{style_prompt}
[์†Œ์ œ๋ชฉ ์ž‘์„ฑ ๊ฐ€์ด๋“œ]
1. ๋ณธ๋ก ์˜ ๊ฐ ๋ถ€๋ถ„๋งˆ๋‹ค ๋ช…ํ™•ํ•œ ์†Œ์ œ๋ชฉ์„ ์‚ฌ์šฉํ•˜์„ธ์š”.
2. ์†Œ์ œ๋ชฉ์€ 10~20์ž ๋‚ด์™ธ๋กœ ๋ช…ํ™•ํ•˜๊ณ  ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑํ•˜์„ธ์š”.
3. ์†Œ์ œ๋ชฉ์€ ๋…๋ฆฝ๋œ ์ค„์— ์œ„์น˜ํ•˜๊ณ  ์•ž๋’ค์— ๋นˆ ์ค„์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
4. ์†Œ์ œ๋ชฉ ์˜ˆ์‹œ: '์ œ์ฃผ๋„์˜ ์ˆจ์€ ๋ช…์†Œ', '๊ตํ†ต ๋ฐ ์ด๋™ ๊ฐ€์ด๋“œ', '๋ง›์ง‘ ํƒ๋ฐฉ ์ฝ”์Šค'
[์ค‘์š” ์ž‘์„ฑ ๊ทœ์น™]
1. ๋ฐ˜๋“œ์‹œ ์œ„์˜ ์•„์›ƒ๋ผ์ธ ์ˆœ์„œ์™€ ๊ตฌ์กฐ์— ๋”ฐ๋ผ ์ž‘์„ฑํ•˜๋ผ.
2. ๊ฐ ์„น์…˜์€ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„๋˜์–ด์•ผ ํ•˜๋ฉฐ, ์„น์…˜ ์ œ๋ชฉ์„ ํฌํ•จํ•˜๋ผ.
3. ๋„์ž…๋ถ€๋Š” ์—ฌํ–‰์ž์˜ ๊ด€์‹ฌ์„ ๋Œ๊ณ  ์—ฌํ–‰์ง€๋‚˜ ์ฝ”์Šค๋ฅผ ๋งค๋ ฅ์ ์œผ๋กœ ์†Œ๊ฐœํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž‘์„ฑํ•˜๋ผ.
4. ๋ณธ๋ก  ๊ฐ ๋ถ€๋ถ„์€ ์—ฌํ–‰์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์ธก๋ฉด(๊ตํ†ต, ๋ณผ๊ฑฐ๋ฆฌ, ์Œ์‹, ์ˆ™๋ฐ• ๋“ฑ)์„ ๋‹ค๋ฃจ๋ฉฐ, ๊ตฌ์ฒด์ ์ธ ์ •๋ณด์™€ ์˜ˆ์‹œ๋ฅผ ํฌํ•จํ•˜๋ผ.
5. ๊ฒฐ๋ก ์€ ํ•ต์‹ฌ ๋‚ด์šฉ์„ ์š”์•ฝํ•˜๊ณ  ์ตœ์ข… ์ถ”์ฒœ์ด๋‚˜ ํ†ต์ฐฐ์„ ์ œ๊ณตํ•˜๋ผ.
6. ์ „์ฒด ๊ธ€์˜ ๊ธธ์ด๋Š” ์ตœ์†Œ {TARGET_CHAR_LENGTH}์ž๊ฐ€ ๋˜๋„๋ก ์ž‘์„ฑํ•˜๋ผ.
7. ๊ฐ ์„น์…˜์€ ์ตœ์†Œ {MIN_SECTION_LENGTH}์ž ์ด์ƒ์˜ ์ถฉ๋ถ„ํ•œ ๋‚ด์šฉ์œผ๋กœ ์ž‘์„ฑํ•˜๋ผ.
8. ๋งˆํฌ๋‹ค์šด ํ˜•์‹(#, *, -, 1., 2. ๋“ฑ)์„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  ์ผ๋ฐ˜ ํ…์ŠคํŠธ๋กœ ์ž‘์„ฑํ•˜๋ผ.
9. ์†Œ์ œ๋ชฉ๊ณผ ๊ฒฐ๋ก ์€ ๋ฒˆํ˜ธ ์—†์ด ์ผ๋ฐ˜ ๋ฌธ์žฅ ํ˜•ํƒœ๋กœ ์ž‘์„ฑํ•˜๋ผ.
10. ๋ชฉ๋ก์€ ๋ถˆ๋ฆฟ์ด๋‚˜ ๋ฒˆํ˜ธ ๋Œ€์‹  ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ฌธ์žฅ์œผ๋กœ ์„œ์ˆ ํ•˜๋ผ.
11. "์ฐธ๊ณ ๊ธ€", "์ฐธ๊ณ ๊ธ€์— ๋”ฐ๋ฅด๋ฉด" ๋“ฑ์˜ ํ‘œํ˜„์„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๋ผ.
12. "์—ฌ๋Ÿฌ๋ถ„", "๋…์ž ์—ฌ๋Ÿฌ๋ถ„" ๋“ฑ์˜ ์ง์ ‘์ ์ธ ํ˜ธ์นญ์„ ์ง€์–‘ํ•˜๋ผ.
13. ๊ณผ์žฅ๋œ ํ‘œํ˜„์ด๋‚˜ ๋ถˆํ•„์š”ํ•œ ๋ฐ˜๋ณต์„ ํ”ผํ•˜๋ผ.
14. ๊ฐ ์„น์…˜ ์‚ฌ์ด์— ์ž์—ฐ์Šค๋Ÿฌ์šด ์—ฐ๊ฒฐ์„ฑ์„ ์œ ์ง€ํ•˜๋ผ.
15. ๊ธ€์˜ ์ฒ˜์Œ์— ์ „์ฒด ๊ธ€์˜ ๋งค๋ ฅ์ ์ธ ์ œ๋ชฉ์„ ๋ฐ˜๋“œ์‹œ ์ถ”๊ฐ€ํ•˜๋ผ.
16. ๋ฐ˜๋“œ์‹œ ๊ตฌ์ฒด์ ์ธ ์—ฌํ–‰ ์ •๋ณด(์œ„์น˜, ๊ตํ†ต, ์‹œ๊ฐ„, ๋น„์šฉ, ์˜ˆ์•ฝ๋ฐฉ๋ฒ•, ํŒ ๋“ฑ)๋ฅผ ํฌํ•จํ•˜๋ผ.
"""
# Gemini API ํ˜ธ์ถœ (ํ•œ ๋ฒˆ์˜ ํ˜ธ์ถœ๋กœ ์ „์ฒด ๊ธ€ ์ƒ์„ฑ)
logging.info("์ „์ฒด ๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑ ์‹œ์ž‘")
blog_content = call_gemini_api(blog_prompt, temperature=0.7)
logging.info(f"์ƒ์„ฑ๋œ ์›๋ณธ ๊ธ€ ๊ธธ์ด: {len(blog_content)}")
# ํ›„์ฒ˜๋ฆฌ
processed_content = post_process_blog(blog_content, style)
# HTML ๋ณ€ํ™˜ํ•˜์—ฌ ๊ธ€์ž ์ˆ˜ ์ฒดํฌ
temp_html = format_blog_post(processed_content)
soup = BeautifulSoup(temp_html, 'html.parser')
char_count = len(soup.get_text())
logging.info(f"์ดˆ๊ธฐ ๋ธ”๋กœ๊ทธ ๊ธ€ ๊ธ€์ž ์ˆ˜: {char_count}")
# Phase 2: ๊ธ€์ž ์ˆ˜๊ฐ€ ๋ชฉํ‘œ์— ๋ฏธ๋‹ฌํ•˜๋ฉด ํ‡ด๊ณ  ๋ฐ ํ™•์žฅ
if char_count < TARGET_CHAR_LENGTH * 0.8: # ๋ชฉํ‘œ์˜ 80% ๋ฏธ๋งŒ์ด๋ฉด ํ™•์žฅ
logging.info(f"๊ธ€์ž ์ˆ˜ ๋ถ€์กฑ ({char_count} < {TARGET_CHAR_LENGTH * 0.8}), ํ™•์žฅ ์‹œ๋„")
# ๊ฐ€์žฅ ๊ธด ์ฐธ๊ณ ๊ธ€ ์„ ํƒ
longest_ref = max(references, key=len)
expansion_prompt = f"""
[์—ฌํ–‰ ๋ธ”๋กœ๊ทธ ๊ธ€ ํ™•์žฅ ์š”์ฒญ]
์นดํ…Œ๊ณ ๋ฆฌ: {category}
ํฌ์ŠคํŒ… ์Šคํƒ€์ผ: {style}
์›๋ณธ ๊ธ€:
{processed_content}
์ฐธ๊ณ ๊ธ€:
{longest_ref}
๋ฌธ์ œ์ :
์ด ๊ธ€์€ ๋ชฉํ‘œ ๊ธ€์ž์ˆ˜์ธ {TARGET_CHAR_LENGTH}์ž์— ๋ฏธ์น˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ๊ธ€์ž์ˆ˜๋Š” ์•ฝ {char_count}์ž์ž…๋‹ˆ๋‹ค.
๋‚ด์šฉ์ด ๋ถ€์‹คํ•˜์—ฌ ํ™•์žฅ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
{style_prompt}
[ํ™•์žฅ ์š”๊ตฌ์‚ฌํ•ญ]
1. ์›๋ณธ ๊ธ€์˜ ๊ตฌ์กฐ์™€ ์•„์›ƒ๋ผ์ธ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ๊ฐ ์„น์…˜์˜ ๋‚ด์šฉ์„ ๋Œ€ํญ ํ™•์žฅํ•˜๋ผ.
2. ๊ฐ ์„น์…˜์— ๋” ๊ตฌ์ฒด์ ์ธ ์ •๋ณด, ์˜ˆ์‹œ, ์‚ฌ๋ก€, ํ†ต๊ณ„ ๋“ฑ์„ ์ถ”๊ฐ€ํ•˜๋ผ.
- ๊ตํ†ต ์ •๋ณด, ์œ„์น˜ ์ •๋ณด, ๋น„์šฉ ์ •๋ณด, ์˜์—…์‹œ๊ฐ„, ์˜ˆ์•ฝ ๋ฐฉ๋ฒ• ๋“ฑ ์‹ค์šฉ์  ์ •๋ณด ์ถ”๊ฐ€
- ๊ณ„์ ˆ๋ณ„/์‹œ๊ฐ„๋ณ„ ํŠน์ง•, ๊ด€๊ด‘๊ฐ ์ˆ˜, ์†Œ์š” ์‹œ๊ฐ„ ๋“ฑ ๊ตฌ์ฒด์  ์ •๋ณด ์ถ”๊ฐ€
- ์ฃผ๋ณ€ ๊ด€๊ด‘์ง€, ์—ฐ๊ณ„ ๊ฐ€๋Šฅํ•œ ์žฅ์†Œ ๋“ฑ ์ถ”๊ฐ€ ์ •๋ณด ์ œ๊ณต
3. ์ „์ฒด ๊ธ€์ž ์ˆ˜๋ฅผ ์ตœ์†Œ {TARGET_CHAR_LENGTH}์ž ์ด์ƒ ๋‹ฌ์„ฑํ•˜๋ผ.
4. ์Šคํƒ€์ผ๊ณผ ์–ด์กฐ๋Š” ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๋ผ.
5. ๋งˆํฌ๋‹ค์šด ํ˜•์‹(#, *, -, 1., 2. ๋“ฑ)์„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  ์ผ๋ฐ˜ ํ…์ŠคํŠธ๋กœ ์ž‘์„ฑํ•˜๋ผ.
6. ์†Œ์ œ๋ชฉ๊ณผ ๊ฒฐ๋ก ์€ ๋ฒˆํ˜ธ ์—†์ด ์ผ๋ฐ˜ ๋ฌธ์žฅ ํ˜•ํƒœ๋กœ ์ž‘์„ฑํ•˜๋ผ.
7. ๋ชฉ๋ก์€ ๋ถˆ๋ฆฟ์ด๋‚˜ ๋ฒˆํ˜ธ ๋Œ€์‹  ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ฌธ์žฅ์œผ๋กœ ์„œ์ˆ ํ•˜๋ผ.
8. "์ฐธ๊ณ ๊ธ€" ๊ด€๋ จ ํ‘œํ˜„์„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๋ผ.
9. ๋ถ€์ž์—ฐ์Šค๋Ÿฌ์šด ๋ฐ˜๋ณต์ด๋‚˜ ๊ณผ์žฅ๋œ ํ‘œํ˜„์„ ํ”ผํ•˜๋ผ.
"""
# ํ™•์žฅ ์‹œ๋„
expanded_content = call_gemini_api(expansion_prompt, temperature=0.75)
processed_content = post_process_blog(expanded_content, style)
# ๋‹ค์‹œ ๊ธ€์ž ์ˆ˜ ์ฒดํฌ
temp_html = format_blog_post(processed_content)
soup = BeautifulSoup(temp_html, 'html.parser')
char_count = len(soup.get_text())
logging.info(f"ํ™•์žฅ ํ›„ ๋ธ”๋กœ๊ทธ ๊ธ€ ๊ธ€์ž ์ˆ˜: {char_count}")
# Phase 3: ์—ฌ์ „ํžˆ ๋ถ€์กฑํ•˜๋ฉด ์ถ”๊ฐ€ ํ™•์žฅ ์‹œ๋„
if char_count < TARGET_CHAR_LENGTH * 0.9: # ๋ชฉํ‘œ์˜ 90% ๋ฏธ๋งŒ์ด๋ฉด ์ถ”๊ฐ€ ํ™•์žฅ
logging.info(f"์—ฌ์ „ํžˆ ๊ธ€์ž ์ˆ˜ ๋ถ€์กฑ ({char_count} < {TARGET_CHAR_LENGTH * 0.9}), ์ถ”๊ฐ€ ํ™•์žฅ ์‹œ๋„")
additional_expansion_prompt = f"""
[์—ฌํ–‰ ๋ธ”๋กœ๊ทธ ๊ธ€ ์ถ”๊ฐ€ ํ™•์žฅ ์š”์ฒญ]
์นดํ…Œ๊ณ ๋ฆฌ: {category}
ํฌ์ŠคํŒ… ์Šคํƒ€์ผ: {style}
์›๋ณธ ๊ธ€:
{processed_content}
๋ฌธ์ œ์ :
์ด ๊ธ€์€ ์—ฌ์ „ํžˆ ๋ชฉํ‘œ ๊ธ€์ž์ˆ˜์ธ {TARGET_CHAR_LENGTH}์ž์— ๋ฏธ์น˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ๊ธ€์ž์ˆ˜๋Š” ์•ฝ {char_count}์ž์ž…๋‹ˆ๋‹ค.
[์ถ”๊ฐ€ ํ™•์žฅ ์š”๊ตฌ์‚ฌํ•ญ]
1. ๋ณธ๋ก  ๋ถ€๋ถ„์„ ์ค‘์‹ฌ์œผ๋กœ ์„ธ๋ถ€ ๋‚ด์šฉ์„ ํฌ๊ฒŒ ํ™•์žฅํ•˜๋ผ.
2. ๋‹ค์Œ ํ•ญ๋ชฉ์— ๋Œ€ํ•œ ๋” ๊นŠ์€ ์„ค๋ช…๊ณผ ์‹ค์šฉ์ ์ธ ์ ์šฉ ๋ฐฉ๋ฒ•์„ ์ถ”๊ฐ€ํ•˜๋ผ:
- ์—ฌํ–‰์ง€ ํŠน์œ ์˜ ๋ฌธํ™”๋‚˜ ์—ญ์‚ฌ์  ๋ฐฐ๊ฒฝ
- ํ˜„์ง€์ธ๋งŒ ์•„๋Š” ์ˆจ์€ ๋ช…์†Œ๋‚˜ ํŒ
- ์—ฌํ–‰์ง€ ๋ฐฉ๋ฌธ ์‹œ ์ฃผ์˜์‚ฌํ•ญ์ด๋‚˜ ์—ํ‹ฐ์ผ“
- ์‹œ๊ฐ„๋Œ€๋ณ„/๋‚ ์”จ๋ณ„ ๋ฐฉ๋ฌธ ํŒ
- ๊ตฌ์ฒด์ ์ธ ๊ตํ†ตํŽธ, ์†Œ์š”์‹œ๊ฐ„, ๋น„์šฉ ์ •๋ณด
3. ์—ฌํ–‰์ž์—๊ฒŒ ์œ ์šฉํ•œ ํ•ต์‹ฌ ์ •๋ณด์™€ ์ธ์‚ฌ์ดํŠธ๋ฅผ ๋” ํ’๋ถ€ํ•˜๊ฒŒ ์ œ๊ณตํ•˜๋ผ.
4. ์ „์ฒด ๊ธ€์ž ์ˆ˜๋ฅผ ์ตœ์†Œ {TARGET_CHAR_LENGTH}์ž ์ด์ƒ์œผ๋กœ ํ™•์žฅํ•˜๋ผ.
5. ์Šคํƒ€์ผ๊ณผ ์–ด์กฐ์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๋ผ.
6. ๋ฐ˜๋ณต๋˜๋Š” ๋‚ด์šฉ์ด๋‚˜ ์ค‘๋ณต์€ ํ”ผํ•˜๋ผ.
"""
# ์ถ”๊ฐ€ ํ™•์žฅ ์‹œ๋„
further_expanded_content = call_gemini_api(additional_expansion_prompt, temperature=0.8)
processed_content = post_process_blog(further_expanded_content, style)
# ์ตœ์ข… HTML ๋ณ€ํ™˜
final_html = format_blog_post(processed_content)
# ์ตœ์ข… ๊ธ€์ž ์ˆ˜ ๊ณ„์‚ฐ
soup = BeautifulSoup(final_html, 'html.parser')
final_char_count = len(soup.get_text())
logging.info(f"์ตœ์ข… ๋ธ”๋กœ๊ทธ ๊ธ€ ๊ธ€์ž ์ˆ˜: {final_char_count}")
return final_html, final_char_count
except Exception as e:
logging.error(f"๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
return f"<p>๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}</p>", 0
def post_process_blog(blog_content, style="์นœ๊ทผํ•œ"):
"""๋ธ”๋กœ๊ทธ ์ปจํ…์ธ  ํ›„์ฒ˜๋ฆฌ ํ•จ์ˆ˜"""
try:
# ๋ฒˆํ˜ธ ๋ชฉ๋ก, ๋ถˆ๋ฆฟ, ํ—ค๋”ฉ ๋“ฑ ์ œ๊ฑฐ
blog_content = re.sub(r'^\d+\.\s+', '', blog_content, flags=re.MULTILINE)
blog_content = re.sub(r'^[\*\-\โ€ข]\s+', '', blog_content, flags=re.MULTILINE)
blog_content = re.sub(r'^#+\s+', '', blog_content, flags=re.MULTILINE)
# ์Šคํƒ€์ผ์— ๋”ฐ๋ฅธ ์–ดํˆฌ ์กฐ์ •
if style == "์นœ๊ทผํ•œ":
blog_content = re.sub(r'([๊ฐ€-ํžฃ]+)๊ณ ์š”', r'\1๊ตฌ์š”', blog_content)
blog_content = re.sub(r'๋‹ต๋‹ˆ๋‹ค', '์–ด์š”', blog_content)
blog_content = re.sub(r'์˜€๋‹ต๋‹ˆ๋‹ค', '์˜€์–ด์š”', blog_content)
blog_content = re.sub(r'ํ–ˆ๋‹ต๋‹ˆ๋‹ค', 'ํ–ˆ์–ด์š”', blog_content)
blog_content = re.sub(r'์Šต๋‹ˆ๋‹ค', '์š”', blog_content)
blog_content = re.sub(r'ํ•ฉ๋‹ˆ๋‹ค', 'ํ•ด์š”', blog_content)
blog_content = re.sub(r'๋ฉ๋‹ˆ๋‹ค', '๋ผ์š”', blog_content)
blog_content = re.sub(r'์ž…๋‹ˆ๋‹ค', '์ด์—์š”', blog_content)
# ๊ณผ์žฅ๋œ ํ‘œํ˜„ ์ •๋ฆฌ
exaggerated_expressions = [
(r'ํ•„์ˆ˜์ ์ธ', r'์ค‘์š”ํ•œ'),
(r'ํ˜๋ช…์ ์ธ', r'์ค‘์š”ํ•œ'),
(r'๋†€๋ผ์šด', r'์ฃผ๋ชฉํ•  ๋งŒํ•œ'),
(r'๊ธฐ์ ์˜', r'ํšจ๊ณผ์ ์ธ'),
(r'์ตœ๊ณ ์˜', r'์ข‹์€'),
(r'์„ธ๊ณ„์ ์ธ', r'์œ ๋ช…ํ•œ'),
(r'์™„๋ฒฝํ•œ', r'์šฐ์ˆ˜ํ•œ'),
(r'๊ทน์ ์ธ', r'์ƒ๋‹นํ•œ'),
(r'๋ฌดํ•œํ•œ', r'๋งŽ์€'),
(r'์ ˆ๋Œ€์ ์ธ', r'์ƒ๋‹นํ•œ'),
(r'ํ˜์‹ ์ ์ธ', r'์ƒˆ๋กœ์šด'),
(r'ํ™˜์ƒ์ ์ธ', r'์ข‹์€'),
(r'๊ทผ๋ณธ์ ์ธ', r'๊ธฐ๋ณธ์ ์ธ'),
(r'ํš๊ธฐ์ ์ธ', r'์ค‘์š”ํ•œ'),
(r'์ „๋ก€์—†๋Š”', r'ํŠน๋ณ„ํ•œ'),
(r'์••๋„์ ์ธ', r'์ฃผ๋ชฉํ•  ๋งŒํ•œ'),
(r'ํ™ฉํ™€ํ•œ', r'์ข‹์€'),
(r'์ฒœ์ƒ์˜', r'์šฐ์ˆ˜ํ•œ'),
(r'๊ธฐ๊ฐ€ ๋ง‰ํžŒ', r'ํšจ๊ณผ์ ์ธ'),
(r'๋ํŒ์™•', r'์ตœ์ƒ์œ„'),
(r'๊ทธ ์ž์ฒด', r''),
(r'์ด .{1,10} ๊ทธ ์ž์ฒด์˜€์–ด์š”', r'์ด \1์˜€์–ด์š”'),
(r'๊ฐ€ .{1,10} ๊ทธ ์ž์ฒด์˜€์–ด์š”', r'๊ฐ€ \1์˜€์–ด์š”'),
(r'์••๋„์ ์ธ', r'์ค‘์š”ํ•œ'),
(r'์ฒœ๊ตญ', r'์ข‹์€ ๊ณณ'),
(r'ํ™ฉํ™€ํ–ˆ์–ด์š”', r'์ข‹์•˜์–ด์š”'),
(r'ํ™˜์ƒ์˜', r'์ข‹์€'),
(r'์ตœ์ ์˜', r'์ข‹์€'),
(r'์™„๋ฒฝํ•œ', r'์ข‹์€'),
(r'๊ผญ ๊ฐ€๋ด์•ผ ํ• ', r'์ถ”์ฒœํ•˜๋Š”'),
(r'๊ผญ ๋จน์–ด๋ด์•ผ ํ• ', r'์ถ”์ฒœํ•˜๋Š”'),
(r'๊ผญ ํ•ด๋ด์•ผ ํ• ', r'์ถ”์ฒœํ•˜๋Š”')
]
for pattern, replacement in exaggerated_expressions:
blog_content = re.sub(pattern, replacement, blog_content, flags=re.IGNORECASE)
blog_content = re.sub(r'์ฐธ๊ณ ๊ธ€์— ๋”ฐ๋ฅด๋ฉด', r'์•Œ๋ ค์ง„ ๋ฐ”๋กœ๋Š”', blog_content)
blog_content = re.sub(r'์ฐธ๊ณ ๊ธ€', r'๊ด€๋ จ ์ •๋ณด', blog_content)
# ์—ฌํ–‰ ๊ด€๋ จ ํ‘œํ˜„ ์ •๋ฆฌ
travel_specific_adjustments = [
(r'๋ฐฉ๋ฌธํ•ด๋ณด์„ธ์š”', r'๋ฐฉ๋ฌธํ•ด ๋ณด์„ธ์š”'),
(r'๊ฒฝํ—˜ํ•ด๋ณด์„ธ์š”', r'๊ฒฝํ—˜ํ•ด ๋ณด์„ธ์š”'),
(r'๋จน์–ด๋ณด์„ธ์š”', r'๋จน์–ด ๋ณด์„ธ์š”'),
(r'ํƒ€๋ณด์„ธ์š”', r'ํƒ€ ๋ณด์„ธ์š”'),
(r'ํ•ด๋ณด์„ธ์š”', r'ํ•ด ๋ณด์„ธ์š”'),
(r'์—ฌํ–‰๊ฐ๋“ค์—๊ฒŒ (.*?)์„ ๊ฐ•๋ ฅ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค', r'์—ฌํ–‰๊ฐ๋“ค์—๊ฒŒ \1์„ ์ถ”์ฒœํ•ด์š”'),
(r'์—ฌํ–‰๊ฐ๋“ค์—๊ฒŒ (.*?)๋ฅผ ๊ฐ•๋ ฅ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค', r'์—ฌํ–‰๊ฐ๋“ค์—๊ฒŒ \1๋ฅผ ์ถ”์ฒœํ•ด์š”'),
(r'์—ฌํ–‰๊ฐ๋“ค์—๊ฒŒ (.*?)์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค', r'์—ฌํ–‰๊ฐ๋“ค์—๊ฒŒ \1์„ ์ถ”์ฒœํ•ด์š”'),
(r'์—ฌํ–‰๊ฐ๋“ค์—๊ฒŒ (.*?)๋ฅผ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค', r'์—ฌํ–‰๊ฐ๋“ค์—๊ฒŒ \1๋ฅผ ์ถ”์ฒœํ•ด์š”'),
(r'์—ฌํ–‰๊ฐ์—๊ฒŒ (.*?)์„ ๊ฐ•๋ ฅ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค', r'์—ฌํ–‰๊ฐ์—๊ฒŒ \1์„ ์ถ”์ฒœํ•ด์š”'),
(r'์—ฌํ–‰๊ฐ์—๊ฒŒ (.*?)๋ฅผ ๊ฐ•๋ ฅ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค', r'์—ฌํ–‰๊ฐ์—๊ฒŒ \1๋ฅผ ์ถ”์ฒœํ•ด์š”')
]
for pattern, replacement in travel_specific_adjustments:
blog_content = re.sub(pattern, replacement, blog_content)
return blog_content
except Exception as e:
logging.error(f"๋ธ”๋กœ๊ทธ ๊ธ€ ํ›„์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
return blog_content
def format_blog_post(blog_post, query="", with_title=False):
"""๋ธ”๋กœ๊ทธ ํฌ์ŠคํŠธ ํฌ๋งทํŒ… ํ•จ์ˆ˜ - ์†Œ์ œ๋ชฉ ๊ฐ•ํ™” ๋ฒ„์ „"""
blog_post = re.sub(r'^#+\s+', '', blog_post, flags=re.MULTILINE)
blog_post = re.sub(r'^\d+\.\s+', '', blog_post, flags=re.MULTILINE)
blog_post = re.sub(r'^[\*\-]\s+', '', blog_post, flags=re.MULTILINE)
# ์ฒซ ์ค„(์›๋ณธ ์ œ๋ชฉ)๊ณผ ๋น„์Šทํ•œ ํŒจํ„ด์ด ์žˆ๋‹ค๋ฉด ์ œ๊ฑฐ
lines = blog_post.split('\n')
if lines and len(lines) > 0:
first_line = lines[0].strip()
# ์ฒซ ์ค„์ด ์ œ๋ชฉ์ธ ๊ฒฝ์šฐ, ๋น„์Šทํ•œ ๋‚ด์šฉ์˜ ๋ผ์ธ์„ ๋ชจ๋‘ ์ œ๊ฑฐ
if first_line and len(first_line) > 5:
# ์ฒซ ์ค„๊ณผ ์œ ์‚ฌํ•œ ๋‚ด์šฉ์„ ๊ฐ€์ง„ ๋ผ์ธ ์ฐพ์•„ ์ œ๊ฑฐ
filtered_lines = []
for line in lines:
# ์ฒซ ์ค„๊ณผ ์œ ์‚ฌํ•˜๋ฉด ์ œ๊ฑฐ
if line.strip() and (first_line in line or line in first_line):
continue
filtered_lines.append(line)
lines = filtered_lines
# ๋„์ž…๋ถ€, ๊ฒฐ๋ก  ์†Œ์ œ๋ชฉ ํŒจํ„ด
intro_pattern = r'(?i)๋„์ž…๋ถ€\s*[:]?\s*(.*?)$'
conclusion_pattern = r'(?i)๊ฒฐ๋ก \s*[:]?\s*(.*?)$'
# ๋„์ž…๋ถ€, ๊ฒฐ๋ก  ์†Œ์ œ๋ชฉ ์ œ๊ฑฐ
filtered_lines = []
for line in lines:
if re.match(intro_pattern, line) or re.match(conclusion_pattern, line):
continue
filtered_lines.append(line)
lines = filtered_lines
# ๋ณธ๋ก  ์†Œ์ œ๋ชฉ ํŒจํ„ด ๊ฐ•ํ™”
section_patterns = [
r'^๋ณธ๋ก \d+\s*[:]?\s*(.*?)$', # ๋ณธ๋ก 1: ๋‚ด์šฉ ํŒจํ„ด
r'^.{5,50}์˜ [๊ฐ€-ํžฃ\s]+$', # ~์˜ ~ ํŒจํ„ด
r'^[๊ฐ€-ํžฃ\s]{5,30}(์ด๋ž€|์ด๋ž€\?|์ด๋ž€\s๋ฌด์—‡์ธ๊ฐ€|์ด๋ž€\s๋ฌด์—‡์ผ๊นŒ)[\?\s]*$', # ~์ด๋ž€? ํŒจํ„ด
r'^[๊ฐ€-ํžฃ\s]{5,50}\s[-โ€“]\s.{5,30}$', # ๊ฐ•์กฐ ํ‘œํ˜„ ํŒจํ„ด (์˜ˆ: ํšจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ• - ์‹ค์ฒœํ•˜๊ธฐ)
r'^[๊ฐ€-ํžฃA-Za-z\s]{10,50}[\.!\?]$', # ๊ธด ๋ฌธ์žฅ์œผ๋กœ ๋œ ์†Œ์ œ๋ชฉ ํŒจํ„ด
]
formatted_lines = []
in_paragraph = False
# ๋ณธ๋ก  ์„น์…˜ ๋ฒˆํ˜ธ ์ถ”์ 
section_number = 1
for i, line in enumerate(lines):
line = line.strip()
if not line:
if in_paragraph:
formatted_lines.append("</p>")
in_paragraph = False
formatted_lines.append("<br>")
continue
# ๋‹ค์Œ ์ค„๊ณผ ์ด์ „ ์ค„์ด ๋น„์–ด์žˆ๋Š”์ง€ ํ™•์ธ
prev_empty = i == 0 or not lines[i-1].strip()
next_empty = i == len(lines) - 1 or not lines[i+1].strip()
# ์†Œ์ œ๋ชฉ์ธ์ง€ ์ฒดํฌ
is_subtitle = False
clean_subtitle = line
# ํŒจํ„ด ๋งค์นญ์œผ๋กœ ์†Œ์ œ๋ชฉ ํ™•์ธ
for pattern in section_patterns:
if re.match(pattern, line):
is_subtitle = True
# ๋ณธ๋ก X: ํŒจํ„ด์ธ ๊ฒฝ์šฐ ์ •๋ฆฌ
if "๋ณธ๋ก " in line:
clean_subtitle = re.sub(r'^๋ณธ๋ก \d+\s*[:]?\s*', '', line)
break
# ํŒจํ„ด์— ๋งค์นญ๋˜์ง€ ์•Š์•˜์ง€๋งŒ ๋‹ค์Œ ๊ทœ์น™์œผ๋กœ ์†Œ์ œ๋ชฉ์œผ๋กœ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ
if not is_subtitle:
# ์•ž๋’ค ์ค„์ด ๋น„์–ด์žˆ๊ณ , ๊ธธ์ด๊ฐ€ ์งง์€(5-50์ž) ๋ฌธ์žฅ์€ ์†Œ์ œ๋ชฉ์œผ๋กœ ์ฒ˜๋ฆฌ
if prev_empty and next_empty and 5 <= len(line) <= 50:
is_subtitle = True
# ์ด์ „์— ์žˆ๋˜ ์†Œ์ œ๋ชฉ๋“ค๊ณผ ๋น„์Šทํ•œ ๊ธธ์ด๋ฅผ ๊ฐ€์ง„ ๊ฒฝ์šฐ๋„ ์†Œ์ œ๋ชฉ์œผ๋กœ ๊ฐ„์ฃผ
elif section_number > 1 and prev_empty and 5 <= len(line) <= 50:
is_subtitle = True
if is_subtitle and clean_subtitle.strip():
if in_paragraph:
formatted_lines.append("</p>")
in_paragraph = False
# ์†Œ์ œ๋ชฉ์ด ์—†๊ฑฐ๋‚˜ ๋„ˆ๋ฌด ์งง์€ ๊ฒฝ์šฐ ๊ธฐ๋ณธ ์†Œ์ œ๋ชฉ ์‚ฌ์šฉ
if not clean_subtitle.strip() or len(clean_subtitle.strip()) < 2:
clean_subtitle = f"์ฃผ์š” ํฌ์ธํŠธ {section_number}"
# ์†Œ์ œ๋ชฉ ํ˜•์‹ ๊ฐ•ํ™” - ํ•ญ์ƒ ๋ณผ๋“œ์ฒ˜๋ฆฌ์™€ ์Šคํƒ€์ผ๋ง ์ ์šฉ
formatted_lines.append(
f'<h2 style="font-size: 1.4em; margin-top: 30px; margin-bottom: 15px; font-weight: bold; color: #333; border-bottom: 1px solid #eee; padding-bottom: 8px;">{html.escape(clean_subtitle)}</h2>'
)
section_number += 1
else:
# ์ผ๋ฐ˜ ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ
if not in_paragraph:
formatted_lines.append("<p>")
in_paragraph = True
content = html.escape(line)
bold_content = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', content)
formatted_lines.append(bold_content)
if in_paragraph:
formatted_lines.append("</p>")
return '\n'.join(formatted_lines)
def call_gemini_api(prompt, temperature=TEMPERATURE, top_p=TOP_P):
"""Gemini API ํ˜ธ์ถœ ํ•จ์ˆ˜"""
try:
logging.info("Gemini API ํ˜ธ์ถœ ์‹œ์ž‘")
response = client.models.generate_content(
model="gemini-2.0-flash",
contents=[prompt],
config=types.GenerateContentConfig(
max_output_tokens=MAX_TOKENS,
temperature=temperature,
top_p=top_p
)
)
logging.info("Gemini API ํ˜ธ์ถœ ์™„๋ฃŒ")
return response.text.strip()
except Exception as e:
logging.error(f"Gemini API ํ˜ธ์ถœ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
return f"API ํ˜ธ์ถœ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
def get_style_prompt(style="์นœ๊ทผํ•œ"):
"""๋ธ”๋กœ๊ทธ ๊ธ€์˜ ์Šคํƒ€์ผ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋ฐ˜ํ™˜"""
prompts = {
"์นœ๊ทผํ•œ": """
[์นœ๊ทผํ•œ ์—ฌํ–‰ ๋ธ”๋กœ๊ทธ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ]
1. ํ†ค๊ณผ ์–ด์กฐ
- ๋Œ€ํ™”ํ•˜๋“ฏ ํŽธ์•ˆํ•˜๊ณ  ์นœ๊ทผํ•œ ๋งํˆฌ ์‚ฌ์šฉ
- ์—ฌํ–‰์ง€์— ๋Œ€ํ•œ ๊ด€์‹ฌ๊ณผ ํ˜ธ๊ธฐ์‹ฌ์„ ๋‹ด์€ ํ‘œํ˜„ ์‚ฌ์šฉ
- ์‹ค์ œ ์—ฌํ–‰์„ ๊ฒฝํ—˜ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์ƒ์ƒํ•œ ๋ฌ˜์‚ฌ
2. ๋ฌธ์žฅ ๋ฐ ์–ดํˆฌ
- ๋ฐ˜๋“œ์‹œ 'ํ•ด์š”์ฒด'๋กœ ์ž‘์„ฑ, ์ ˆ๋Œ€ '์Šต๋‹ˆ๋‹ค'์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ง ๊ฒƒ
- '~์š”'๋กœ ๋๋‚˜๋„๋ก ์ž‘์„ฑ, '~๋‹ค'๋กœ ๋๋‚˜์ง€ ์•Š๊ฒŒ ํ•˜๋ผ
- ๊ตฌ์–ด์ฒด ํ‘œํ˜„ ์‚ฌ์šฉ (์˜ˆ: "~ํ–ˆ์–ด์š”", "~์ธ ๊ฒƒ ๊ฐ™์•„์š”")
- ์ ์ ˆํ•œ ๊ฐ์ • ํ‘œํ˜„๊ณผ ๊ณต๊ฐ๋Œ€ ํ˜•์„ฑ
3. ์šฉ์–ด ๋ฐ ์„ค๋ช… ๋ฐฉ์‹
- ์—ฌํ–‰ ๊ด€๋ จ ์ „๋ฌธ ์šฉ์–ด๋Š” ์‰ฌ์šด ๋‹จ์–ด๋กœ ํ’€์–ด์„œ ์„ค๋ช…
- ๋น„์œ ๋‚˜ ์€์œ ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์žฅ์†Œ์™€ ๊ฒฝํ—˜ ๋ฌ˜์‚ฌ
- ์ˆ˜์‚ฌ์˜๋ฌธ๋ฌธ ํ™œ์šฉํ•˜์—ฌ ๋…์ž์™€ ์†Œํ†ตํ•˜๋Š” ๋А๋‚Œ ์ฃผ๊ธฐ (์˜ˆ: "์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์„ธ์š”?", "์ด๋Ÿฐ ๊ฒฝํ—˜ ์žˆ์œผ์‹ ๊ฐ€์š”?")
- ๊ตฌ์ฒด์  ์‚ฌ๋ก€์™€ ์‹ค์ œ ๊ฒฝํ—˜์— ๊ธฐ๋ฐ˜ํ•œ ํŒ ์ œ๊ณต
4. ์ •๋ณด ์ „๋‹ฌ ๋ฐฉ์‹
- ๊ฐœ์ธ์ ์ธ ๊ด€์ ์— ๋…น์—ฌ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ •๋ณด ์ „๋‹ฌ
- ์‹ค์ œ ์—ฌํ–‰์ž์˜ ์‹œ์„ ์œผ๋กœ ์žฅ์†Œ์™€ ๊ฒฝํ—˜ ๋ฌ˜์‚ฌ
- ๋…์ž๊ฐ€ ์‹ค์ œ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‹ค์šฉ์  ์ •๋ณด ์ œ๊ณต (๊ตํ†ต, ๋น„์šฉ, ์‹œ๊ฐ„, ์ถ”์ฒœ ์ฝ”์Šค ๋“ฑ)
5. ๋…์ž์™€์˜ ์ƒํ˜ธ์ž‘์šฉ
- ๋…์ž์˜ ์˜๊ฒฌ์„ ๋ฌผ์–ด๋ณด๋Š” ์งˆ๋ฌธ ํฌํ•จ
- ์‹ค์ œ ์—ฌํ–‰์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํŒ์ด๋‚˜ ์กฐ์–ธ ์ œ๊ณต
์ฃผ์˜์‚ฌํ•ญ: ์ž์—ฐ์Šค๋Ÿฌ์šด ๋Œ€ํ™”์ฒด๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ์ •๋ณด์˜ ์งˆ๊ณผ ๋‚ด์šฉ์˜ ๊นŠ์ด๋ฅผ ์žƒ์ง€ ์•Š๋„๋ก ํ•œ๋‹ค
""",
"์ผ๋ฐ˜": """
[์ผ๋ฐ˜์ ์ธ ์—ฌํ–‰ ๋ธ”๋กœ๊ทธ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ]
1. ํ†ค๊ณผ ์–ด์กฐ
- ์ค‘๋ฆฝ์ ์ด๊ณ  ๊ฐ๊ด€์ ์ธ ํ†ค ์œ ์ง€
- ์ ์ ˆํ•œ ์กด๋Œ“๋ง ์‚ฌ์šฉ (์˜ˆ: "~ํ•ฉ๋‹ˆ๋‹ค", "~์ž…๋‹ˆ๋‹ค")
- ์—ฌํ–‰ ์ •๋ณด ์ „๋‹ฌ ์ค‘์‹ฌ์˜ ๋ช…ํ™•ํ•œ ์–ดํˆฌ
2. ๋‚ด์šฉ ๊ตฌ์กฐ ๋ฐ ์ „๊ฐœ
- ๋ช…ํ™•ํ•œ ์—ฌํ–‰์ง€ ์†Œ๊ฐœ๋กœ ์‹œ์ž‘
- ๋…ผ๋ฆฌ์ ์ธ ์ˆœ์„œ๋กœ ์ •๋ณด ์ „๊ฐœ (๊ตํ†ต โ†’ ์ˆ™๋ฐ• โ†’ ๊ด€๊ด‘์ง€ โ†’ ์Œ์‹ ๋“ฑ)
- ํ•ต์‹ฌ ํฌ์ธํŠธ๋ฅผ ๊ฐ•์กฐํ•˜๋Š” ์†Œ์ œ๋ชฉ ํ™œ์šฉ
- ์ ์ ˆํ•œ ๊ธธ์ด์˜ ๋‹จ๋ฝ์œผ๋กœ ๊ตฌ์„ฑ
3. ์šฉ์–ด ๋ฐ ์„ค๋ช… ๋ฐฉ์‹
- ์ผ๋ฐ˜์ ์œผ๋กœ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ์šฉ์–ด ์„ ํƒ
- ํ•„์š”์‹œ ์ง€์—ญ ํŠน์œ ์˜ ์šฉ์–ด์— ๊ฐ„๋‹จํ•œ ์„ค๋ช… ์ถ”๊ฐ€
- ๊ฐ๊ด€์ ์ธ ์—ฌํ–‰ ์ •๋ณด ์ œ๊ณต์— ์ค‘์ 
- ๊ท ํ˜• ์žกํžŒ ์‹œ๊ฐ์—์„œ ์—ฌํ–‰์ง€์˜ ์žฅ๋‹จ์  ์ œ์‹œ
4. ์ •๋ณด ์ „๋‹ฌ ๋ฐฉ์‹
- ์—ฌํ–‰์ง€์˜ ๊ธฐ๋ณธ ์ •๋ณด์™€ ํŠน์ง• ๋ช…ํ™•ํ•˜๊ฒŒ ์ œ๊ณต
- ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ์™€ ์ถ”์ฒœ ์ฝ”์Šค ํฌํ•จ
- ์ตœ์‹  ์—ฌํ–‰ ์ •๋ณด์™€ ๋™ํ–ฅ ์ฐธ๊ณ 
5. ๋…์ž ์ƒํ˜ธ์ž‘์šฉ
- ์ ์ ˆํžˆ ๋…์ž์˜ ์ƒ๊ฐ์„ ๋ฌป๋Š” ์งˆ๋ฌธ ํฌํ•จ
- ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ํ‚ค์›Œ๋“œ ์ œ์‹œ
- ์‹ค์šฉ์ ์ธ ์—ฌํ–‰ ํŒ ์ œ๊ณต
์ฃผ์˜์‚ฌํ•ญ: ๊ฐ๊ด€์  ์ •๋ณด ์ œ๊ณต์„ ์ค‘์‹ฌ์œผ๋กœ ํ•˜๋˜, ๋…์ž์˜ ์—ฌํ–‰ ๊ณ„ํš๊ณผ ์‹คํ–‰์„ ๋„์šธ ์ˆ˜ ์žˆ๋Š” ๋งฅ๋ฝ๊ณผ ์„ค๋ช…์„ ์ถฉ๋ถ„ํžˆ ์ œ๊ณตํ•œ๋‹ค
""",
"์ „๋ฌธ์ ์ธ": """
[์ „๋ฌธ์ ์ธ ์—ฌํ–‰ ๋ธ”๋กœ๊ทธ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ]
1. ํ†ค๊ณผ ๊ตฌ์กฐ
- ๊ณต์‹์ ์ด๊ณ  ์ „๋ฌธ์ ์ธ ํ†ค ์‚ฌ์šฉ
- ๊ฐ๊ด€์ ์ด๊ณ  ๋ถ„์„์ ์ธ ์ ‘๊ทผ ์œ ์ง€
- ๋ช…ํ™•ํ•œ ์„œ๋ก (์—ฌํ–‰์ง€ ๊ฐœ์š”), ๋ณธ๋ก (์ƒ์„ธ ๋ถ„์„), ๊ฒฐ๋ก (์ข…ํ•ฉ ํ‰๊ฐ€) ๊ตฌ์กฐ
- ์ฒด๊ณ„์ ์ธ ์—ฌํ–‰ ์ •๋ณด ์ „๊ฐœ
- ์„ธ๋ถ€ ์„น์…˜์„ ์œ„ํ•œ ๋ช…ํ™•ํ•œ ์†Œ์ œ๋ชฉ ์‚ฌ์šฉ
2. ๋‚ด์šฉ ๊ตฌ์„ฑ ๋ฐ ์ „๊ฐœ
- ์—ฌํ–‰์ง€์˜ ์—ญ์‚ฌ์  ๋ฐฐ๊ฒฝ, ๋ฌธํ™”์  ํŠน์ง•, ํ˜„์žฌ ๋™ํ–ฅ ๋“ฑ ์‹ฌ์ธต์  ์ •๋ณด ํฌํ•จ
- ๋…ผ๋ฆฌ์  ์—ฐ๊ฒฐ์„ ์œ„ํ•œ ์ „ํ™˜์–ด ํ™œ์šฉ
- ์—ฌํ–‰ ์šฉ์–ด ์ ์ ˆํžˆ ํ™œ์šฉ (ํ•„์š”์‹œ ๊ฐ„๋žตํ•œ ์„ค๋ช… ์ œ๊ณต)
- ์‹ฌ์ธต์ ์ธ ๋ถ„์„๊ณผ ๋น„ํŒ์  ํ‰๊ฐ€ ์ œ๊ณต
- ๋‹ค์–‘ํ•œ ๊ด€์ ์—์„œ ์—ฌํ–‰์ง€ ๋ถ„์„
3. ๋ฐ์ดํ„ฐ ๋ฐ ๊ทผ๊ฑฐ ํ™œ์šฉ
- ํ†ต๊ณ„, ์‹œ์ฆŒ๋ณ„ ์ •๋ณด, ์‹ค์ œ ์‚ฌ๋ก€ ๋“ฑ ๊ฐ๊ด€์  ๋ฐ์ดํ„ฐ ํ™œ์šฉ
- ์—ฌํ–‰์ง€ ๋ถ„์„์„ ์œ„ํ•œ ์ฒด๊ณ„์ ์ธ ํ”„๋ ˆ์ž„์›Œํฌ ์ œ์‹œ
- ๊ฐ๊ด€์  ์ •๋ณด์™€ ์ „๋ฌธ๊ฐ€ ๊ด€์ ์˜ ๊ท ํ˜•
4. ์ „๋ฌธ์  ์ •๋ณด ์ œ๊ณต
- ์ตœ์‹  ์—ฌํ–‰ ๋™ํ–ฅ ๋ฐ ๋ณ€ํ™” ๋ถ„์„
- ๋ฌธํ™”, ์—ญ์‚ฌ์  ๋งฅ๋ฝ์—์„œ์˜ ์—ฌํ–‰์ง€ ๋ถ„์„
- ์—ฌํ–‰ ๊ด€๋ จ ์Ÿ์ ๊ณผ ๊ณ ๋ ค์‚ฌํ•ญ ์†Œ๊ฐœ
- ์ฒด๊ณ„์ ์ธ ์—ฌํ–‰ ๊ณ„ํš ์ ‘๊ทผ๋ฒ• ์ œ์‹œ
์ฃผ์˜์‚ฌํ•ญ: ์ „๋ฌธ์„ฑ๊ณผ ๊นŠ์ด๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ์ดํ•ด ๊ฐ€๋Šฅํ•œ ์šฉ์–ด์™€ ์„ค๋ช…์„ ํ†ตํ•ด ์ ‘๊ทผ์„ฑ์„ ๋†’์ธ๋‹ค
"""
}
return prompts.get(style, prompts["์นœ๊ทผํ•œ"])
def get_category_outline_prompt(category="์—ฌํ–‰ ๋‹จ์ผ"):
"""์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์•„์›ƒ๋ผ์ธ ์ƒ์„ฑ ํ”„๋กฌํ”„ํŠธ"""
prompts = {
"์—ฌํ–‰ ๋‹จ์ผ": """
[์—ฌํ–‰ ๋‹จ์ผ์ง€์  ์†Œ์ฃผ์ œ(Outline) ์ƒ์„ฑ ๊ทœ์น™]
1. ๋„ˆ๋Š” ์ตœ๊ณ ์˜ ์—ฌํ–‰ ๋ธ”๋กœ๊ทธ ์ž‘๊ฐ€์ด์ž ์—ฌํ–‰ ์ฝ˜ํ…์ธ  ๊ตฌ์„ฑ ์ „๋ฌธ๊ฐ€์ด๋‹ค.
2. ์ฃผ์–ด์ง„ ์ฐธ๊ณ ๊ธ€์„ ๊นŠ์ด ๋ถ„์„ํ•˜์—ฌ ํ•ด๋‹น ์—ฌํ–‰์ง€์— ๋Œ€ํ•œ ๊ฐ€์žฅ ํšจ๊ณผ์ ์ธ ์ฝ˜ํ…์ธ  ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด๋ผ.
3. ์—ฌํ–‰์ž์˜ ๊ด€์‹ฌ์„ ๋Œ๊ณ  ์œ ์šฉํ•œ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐ ์ดˆ์ ์„ ๋งž์ถฐ๋ผ.
4. ์—ฌํ–‰์ง€์— ๋Œ€ํ•œ ํ†ต์ฐฐ๋ ฅ ์žˆ๋Š” ๋ถ„์„๊ณผ ์‹ค์šฉ์ ์ธ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ์„ค๊ณ„ํ•˜๋ผ.
[์•„์›ƒ๋ผ์ธ ์ž‘์„ฑ ๊ทœ์น™]
1. ๋ฐ˜๋“œ์‹œ ์ฐธ๊ณ ๊ธ€์„ ๊นŠ์ด ๋ถ„์„ํ•˜์—ฌ ์—ฌํ–‰์ง€์˜ ํ•ต์‹ฌ ํŠน์ง•๊ณผ ๊ฐ€์น˜ ์žˆ๋Š” ์ •๋ณด๋ฅผ ํŒŒ์•…ํ•˜๋ผ.
2. ์—ฌํ–‰์ž์˜ ๊ด€์‹ฌ์„ ๋Œ๊ธฐ ์œ„ํ•œ ๋งค๋ ฅ์ ์ธ ์†Œ๊ฐœ๋กœ ์‹œ์ž‘ํ•˜๋ผ.
3. ์—ฌํ–‰์ง€์— ๋Œ€ํ•œ ์‹ฌ์ธต์  ์ดํ•ด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋…ผ๋ฆฌ์  ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด๋ผ.
4. ๊ฐ ์†Œ์ฃผ์ œ๋Š” 20์ž ์ด๋‚ด์˜ ๋ช…ํ™•ํ•˜๊ณ  ๋งค๋ ฅ์ ์ธ ์ œ๋ชฉ์œผ๋กœ ์ž‘์„ฑํ•˜๋ผ.
5. ์†Œ์ฃผ์ œ๋“ค์€ ์ „์ฒด์ ์œผ๋กœ ์ผ๊ด€๋œ ํ๋ฆ„๊ณผ ์—ฐ๊ฒฐ์„ฑ์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.
6. ์—ฌํ–‰์ž์—๊ฒŒ ์‹ค์งˆ์ ์ธ ๊ฐ€์น˜์™€ ํ†ต์ฐฐ์„ ์ œ๊ณตํ•˜๋Š” ์ •๋ณด ์ค‘์‹ฌ์œผ๋กœ ๊ตฌ์„ฑํ•˜๋ผ.
7. ์ฐธ๊ณ ๊ธ€์˜ ๋‚ด์šฉ๊ณผ ํŠน์„ฑ์— ๋”ฐ๋ผ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์†Œ์ฃผ์ œ๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ๊ตฌ์„ฑํ•˜๋ผ.
[์•„์›ƒ๋ผ์ธ ๊ตฌ์„ฑ]
๋ฐ˜๋“œ์‹œ ๋‹ค์Œ ๊ตฌ์กฐ๋กœ ์†Œ์ฃผ์ œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ทธ๋Œ€๋กœ ์ถœ๋ ฅํ•˜๋ผ:
- ๋„์ž…๋ถ€: [์—ฌํ–‰์ง€ ์†Œ๊ฐœ ๋ฐ ํŠน์ง•]
- ๋ณธ๋ก 1~5: [์ฐธ๊ณ ๊ธ€์—์„œ ํŒŒ์•…๋œ ์ฃผ์š” ๋‚ด์šฉ์— ๋”ฐ๋ผ ์œ ์—ฐํ•˜๊ฒŒ ๊ตฌ์„ฑ]
- ๊ฒฐ๋ก : [์—ฌํ–‰์ง€ ์ตœ์ข… ํ‰๊ฐ€ ๋ฐ ์ถ”์ฒœ]
""",
"์—ฌํ–‰ ์ฝ”์Šค": """
[์—ฌํ–‰ ์ฝ”์Šค ์†Œ์ฃผ์ œ(Outline) ์ƒ์„ฑ ๊ทœ์น™]
1. ๋„ˆ๋Š” ์ตœ๊ณ ์˜ ์—ฌํ–‰ ๋ธ”๋กœ๊ทธ ์ž‘๊ฐ€์ด์ž ์—ฌํ–‰ ์ฝ”์Šค ๊ธฐํš ์ „๋ฌธ๊ฐ€์ด๋‹ค.
2. ์ฃผ์–ด์ง„ ์ฐธ๊ณ ๊ธ€์„ ๊นŠ์ด ๋ถ„์„ํ•˜์—ฌ ์ตœ์ ์˜ ์—ฌํ–‰ ์ฝ”์Šค ๊ตฌ์„ฑ๊ณผ ์ฝ˜ํ…์ธ  ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด๋ผ.
3. ์—ฌํ–‰์ž์˜ ์‹œ๊ฐ„๊ณผ ๊ฒฝํ—˜์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”์Šค ๊ตฌ์„ฑ์— ์ดˆ์ ์„ ๋งž์ถฐ๋ผ.
4. ์‹ค์šฉ์ ์ด๊ณ  ํšจ์œจ์ ์ธ ์—ฌํ–‰ ๊ณ„ํš์„ ์ œ๊ณตํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ์„ค๊ณ„ํ•˜๋ผ.
[์•„์›ƒ๋ผ์ธ ์ž‘์„ฑ ๊ทœ์น™]
1. ์ฐธ๊ณ ๊ธ€์„ ์ฒ ์ €ํžˆ ๋ถ„์„ํ•˜์—ฌ ์—ฌํ–‰ ์ฝ”์Šค์˜ ํ•ต์‹ฌ ์š”์†Œ์™€ ํ๋ฆ„์„ ํŒŒ์•…ํ•˜๋ผ.
2. ์—ฌํ–‰ ์ฝ”์Šค์˜ ๋งค๋ ฅ๊ณผ ํŠน์ง•์„ ๊ฐ•์กฐํ•˜๋Š” ์†Œ๊ฐœ๋กœ ์‹œ์ž‘ํ•˜๋ผ.
3. ์—ฌํ–‰ ์ผ์ •์˜ ๋…ผ๋ฆฌ์  ํ๋ฆ„์„ ๋ฐ˜์˜ํ•œ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด๋ผ.
4. ๊ฐ ์†Œ์ฃผ์ œ๋Š” 20์ž ์ด๋‚ด์˜ ๋ช…ํ™•ํ•˜๊ณ  ๋งค๋ ฅ์ ์ธ ์ œ๋ชฉ์œผ๋กœ ์ž‘์„ฑํ•˜๋ผ.
5. ์†Œ์ฃผ์ œ๋“ค์ด ์ „์ฒด ์—ฌํ–‰ ํ๋ฆ„์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด๋Œ์–ด๊ฐˆ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑํ•˜๋ผ.
6. ์—ฌํ–‰์ž๊ฐ€ ์‹ค์ œ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์ฒด์ ์ธ ์ •๋ณด ์ค‘์‹ฌ์œผ๋กœ ๊ตฌ์„ฑํ•˜๋ผ.
7. ์ฐธ๊ณ ๊ธ€์˜ ๋‚ด์šฉ๊ณผ ํŠน์„ฑ์— ๋”ฐ๋ผ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์†Œ์ฃผ์ œ๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ๊ตฌ์„ฑํ•˜๋ผ.
[์•„์›ƒ๋ผ์ธ ๊ตฌ์„ฑ]
๋ฐ˜๋“œ์‹œ ๋‹ค์Œ ๊ตฌ์กฐ๋กœ ์†Œ์ฃผ์ œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ทธ๋Œ€๋กœ ์ถœ๋ ฅํ•˜๋ผ:
- ๋„์ž…๋ถ€: [์—ฌํ–‰ ์ฝ”์Šค ๊ฐœ์š” ๋ฐ ํŠน์ง•]
- ๋ณธ๋ก 1~5: [์ฐธ๊ณ ๊ธ€์—์„œ ํŒŒ์•…๋œ ์ฃผ์š” ๋‚ด์šฉ์— ๋”ฐ๋ผ ์œ ์—ฐํ•˜๊ฒŒ ๊ตฌ์„ฑ]
- ๊ฒฐ๋ก : [์ฝ”์Šค์˜ ์žฅ์  ๋ฐ ์ตœ์ข… ์กฐ์–ธ]
"""
}
return prompts.get(category, prompts["์—ฌํ–‰ ๋‹จ์ผ"])
def generate_outline(category, style, references1, references2, references3):
"""์•„์›ƒ๋ผ์ธ ์ƒ์„ฑ ํ•จ์ˆ˜"""
try:
category_prompt = get_category_outline_prompt(category)
style_prompt = get_style_prompt(style)
# ์ฐธ๊ณ ๊ธ€ ์ •๋ณด ์ค€๋น„
references = [
references1.strip() if references1.strip() else "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ",
references2.strip() if references2.strip() else "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ",
references3.strip() if references3.strip() else "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ"
]
# ์˜๋ฏธ ์žˆ๋Š” ์ฐธ๊ณ ๊ธ€๋งŒ ํ•„ํ„ฐ๋ง
meaningful_refs = [ref for ref in references if ref != "์ฐธ๊ณ  ์ž๋ฃŒ ์—†์Œ"]
if not meaningful_refs:
return "์ฐธ๊ณ  ์ž๋ฃŒ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ตœ์†Œ ํ•˜๋‚˜ ์ด์ƒ์˜ ์ฐธ๊ณ  ์ž๋ฃŒ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
outline_prompt = f"""
[์—ฌํ–‰ ๋ธ”๋กœ๊ทธ ์•„์›ƒ๋ผ์ธ ์ƒ์„ฑ ์š”์ฒญ]
์นดํ…Œ๊ณ ๋ฆฌ: {category}
ํฌ์ŠคํŒ… ์Šคํƒ€์ผ: {style}
์ฐธ๊ณ ๊ธ€:
{references[0]}
{references[1] if len(meaningful_refs) > 1 else ""}
{references[2] if len(meaningful_refs) > 2 else ""}
{category_prompt}
์•„์›ƒ๋ผ์ธ ์ƒ์„ฑ ์‹œ ์ถ”๊ฐ€ ์ง€์นจ:
1. ์ฐธ๊ณ ๊ธ€์˜ ํ•ต์‹ฌ ์ฃผ์ œ์™€ ๊ฐ€์น˜ ์žˆ๋Š” ์ •๋ณด๋ฅผ ์ •ํ™•ํžˆ ํŒŒ์•…ํ•˜๋ผ.
2. ๊ฐ ์†Œ์ฃผ์ œ๋Š” 20์ž ์ด๋‚ด๋กœ ๋ช…ํ™•ํ•˜๊ณ  ๋งค๋ ฅ์ ์œผ๋กœ ์ž‘์„ฑํ•˜๋ผ.
3. ์ „์ฒด ์•„์›ƒ๋ผ์ธ์ด ๋…ผ๋ฆฌ์  ํ๋ฆ„๊ณผ ์ผ๊ด€์„ฑ์„ ๊ฐ€์ง€๋„๋ก ๊ตฌ์„ฑํ•˜๋ผ.
4. ๋…์ž์˜ ๊ด€์‹ฌ๊ณผ ํ˜ธ๊ธฐ์‹ฌ์„ ์œ ๋ฐœํ•˜๋Š” ์†Œ์ฃผ์ œ๋ฅผ ์„ค๊ณ„ํ•˜๋ผ.
5. ์†Œ์ฃผ์ œ๋งŒ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ถœ๋ ฅํ•˜๊ณ  ์„ค๋ช…์€ ํฌํ•จํ•˜์ง€ ๋ง๋ผ.
6. ๊ฐ ์†Œ์ฃผ์ œ๊ฐ€ ์•ฝ์†๋œ ์„น์…˜(๋„์ž…๋ถ€, ๋ณธ๋ก 1~5, ๊ฒฐ๋ก )์— ์ ํ•ฉํ•œ์ง€ ํ™•์ธํ•˜๋ผ.
7. ๋ฐฑํ‹ฑ(```)์ด๋‚˜ ์ฝ”๋“œ ๋ธ”๋ก ํ‘œ์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ง๋ผ.
8. ์ •ํ™•ํžˆ 7์ค„๋กœ ๊ตฌ์„ฑํ•˜์—ฌ '๋„์ž…๋ถ€', '๋ณธ๋ก 1~5', '๊ฒฐ๋ก '๋งŒ ์ถœ๋ ฅํ•˜๋ผ.
"""
# Gemini API ํ˜ธ์ถœ
outline_result = call_gemini_api(outline_prompt, temperature=0.7)
# ๊ฒฐ๊ณผ ํ›„์ฒ˜๋ฆฌ (๋ถˆํ•„์š”ํ•œ ํ˜•์‹ ์ œ๊ฑฐ)
outline_result = re.sub(r'^\s*[-*]\s+', '', outline_result, flags=re.MULTILINE)
outline_result = re.sub(r'^\s*\d+\.\s+', '', outline_result, flags=re.MULTILINE)
# ๋ฐฑํ‹ฑ ๋ฐ ์ฝ”๋“œ ๋ธ”๋ก ์ œ๊ฑฐ
outline_result = re.sub(r'```[a-zA-Z]*\n?', '', outline_result)
outline_result = re.sub(r'```', '', outline_result)
# ์ •ํ™•ํžˆ 7์ค„ ํ˜•์‹์œผ๋กœ ์ •๋ฆฌ
lines = outline_result.strip().split('\n')
clean_lines = []
for line in lines:
line = line.strip()
if line and (line.startswith('๋„์ž…๋ถ€:') or
line.startswith('๋ณธ๋ก ') or
line.startswith('๊ฒฐ๋ก :')):
clean_lines.append(line)
# ์ •ํ™•ํžˆ 7์ค„์ด ๋‚˜์˜ค๋„๋ก ์กฐ์ •
if len(clean_lines) > 7:
clean_lines = clean_lines[:7]
elif len(clean_lines) < 7:
sections = ['๋„์ž…๋ถ€:', '๋ณธ๋ก 1:', '๋ณธ๋ก 2:', '๋ณธ๋ก 3:', '๋ณธ๋ก 4:', '๋ณธ๋ก 5:', '๊ฒฐ๋ก :']
while len(clean_lines) < 7:
missing_section = sections[len(clean_lines)]
clean_lines.append(f"{missing_section} ์ถ”๊ฐ€ ๋‚ด์šฉ ํ•„์š”")
return '\n'.join(clean_lines)
except Exception as e:
logging.error(f"์•„์›ƒ๋ผ์ธ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
return f"์•„์›ƒ๋ผ์ธ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
def save_content_to_pdf(blog_post, user_topic=""):
# ์‚ฌ์šฉํ•˜์ง€ ์•Š์ง€๋งŒ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด ๋‚จ๊ฒจ๋‘ 
return None
def format_filename(text):
text = re.sub(r'[^\w\s-]', '', text)
return text[:50].strip()
# API ํ•จ์ˆ˜๋“ค
def generate_outline_2(category, style, ref1, ref2, ref3):
return generate_outline(category, style, ref1, ref2, ref3)
def generate_blog_post_2(category, style, ref1, ref2, ref3, outline):
result = generate_blog_post(category, style, outline, ref1, ref2, ref3)
return result[0] # ํŠœํ”Œ์—์„œ HTML๋งŒ ๋ฐ˜ํ™˜