Spaces:
Sleeping
Sleeping
| import os | |
| import gradio as gr | |
| from bs4 import BeautifulSoup | |
| from datetime import datetime | |
| from zoneinfo import ZoneInfo | |
| import tempfile | |
| import requests | |
| import re | |
| import logging | |
| from PIL import Image | |
| from urllib.request import urlopen | |
| import io # ๋ฐ์ดํธ ์ฒ๋ฆฌ๋ฅผ ์ํ ์ถ๊ฐ | |
| # google-genai ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ํฌํธ | |
| from google import genai | |
| # Pretendard ํฐํธ ํ์ผ ๊ฒฝ๋ก | |
| FONT_REGULAR_PATH = os.path.join("Pretendard-Regular.otf") | |
| FONT_BOLD_PATH = os.path.join("Pretendard-Bold.otf") | |
| # ๋ฃจํธ ๋ก๊ฑฐ์ ๋ ๋ฒจ์ WARNING์ผ๋ก ์ค์ ํ์ฌ ๋๋ถ๋ถ์ ๋๋ฒ๊ทธ ๋ฉ์์ง ์ ๊ฑฐ | |
| logging.basicConfig(level=logging.WARNING) | |
| # ์ฐ๋ฆฌ ์ฑ์ ๋ก๊ฑฐ๋ง INFO ๋ ๋ฒจ๋ก ์ค์ | |
| logger = logging.getLogger(__name__) | |
| logger.setLevel(logging.INFO) | |
| # ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ก๊ฑฐ ๋ ๋ฒจ์ WARNING์ผ๋ก ์ค์ | |
| logging.getLogger("multipart").setLevel(logging.WARNING) | |
| logging.getLogger("gradio").setLevel(logging.WARNING) | |
| # ํ๊ฒฝ๋ณ์๋ฅผ ํตํด Gemini API ํค๋ฅผ ๊ฐ์ ธ์ด | |
| API_KEY = os.getenv("GENAI_API_KEY") | |
| if API_KEY is None: | |
| raise ValueError("GENAI_API_KEY ํ๊ฒฝ ๋ณ์๊ฐ ์ค์ ๋์ง ์์์ต๋๋ค.") | |
| client = genai.Client(api_key=API_KEY) | |
| # Gemini API๋ฅผ ํธ์ถํ๋ ํจ์ (Gemini๋ max_tokens, temperature, top_p ํ๋ผ๋ฏธํฐ ์์ด ํ๋กฌํํธ๋ฅผ ๊ฒฐํฉํ์ฌ ์์ฒญ) | |
| def call_api(content, system_message, max_tokens=None, temperature=None, top_p=None): | |
| try: | |
| prompt = system_message + "\n" + content | |
| response = client.models.generate_content( | |
| model="gemini-2.0-flash", | |
| contents=prompt | |
| ) | |
| return response.text.strip() | |
| except Exception as e: | |
| logger.error(f"API ํธ์ถ ์ค๋ฅ: {str(e)}") | |
| return f"Gemini API Error: {str(e)}" | |
| def analyze_info(data): | |
| return (f"์ ํํ ์นดํ ๊ณ ๋ฆฌ: {data['category']}\n" | |
| f"์ ํํ ํฌ์คํ ์คํ์ผ: {data['style']}\n" | |
| f"์ฐธ๊ณ ๊ธ1: {data['references1']}\n" | |
| f"์ฐธ๊ณ ๊ธ2: {data['references2']}\n" | |
| f"์ฐธ๊ณ ๊ธ3: {data['references3']}\n") | |
| def generate_outline(category, style, references1, references2, references3, photo_recommendations): | |
| data = { | |
| 'category': category, | |
| 'style': style, | |
| 'references1': references1, | |
| 'references2': references2, | |
| 'references3': references3, | |
| 'photo_recommendations': photo_recommendations | |
| } | |
| full_content = analyze_info(data) | |
| logger.info(f"์์๋ผ์ธ ์์ฑ์ ์ํ ์ ์ฒด ๋ด์ฉ: {full_content}") | |
| system_prompt = get_outline_prompt(data['category']) + "\n\n" + get_style_prompt(data['style']) | |
| user_prompt = f"{full_content}\n\n์ฌ์ง ํค์๋: {photo_recommendations}" | |
| modified_text = call_api(user_prompt, system_prompt, 2000, 0.7, 0.95) | |
| # API ์ค๋ฅ ํ์ธ | |
| if modified_text is None or modified_text.startswith("Gemini API Error"): | |
| logger.error(f"์์๋ผ์ธ ์์ฑ ์ค API ์ค๋ฅ: {modified_text}") | |
| raise Exception(f"์์๋ผ์ธ ์์ฑ API ์ค๋ฅ: {modified_text}") | |
| # ๋ถํ์ํ ๋น ์ค ์ ๊ฑฐ: ์ฐ์๋๋ ๊ฐํ ๋ฌธ์๋ฅผ ๋จ์ผ ๊ฐํ์ผ๋ก ๋ณ๊ฒฝ | |
| modified_text = re.sub(r'\n\s*\n', '\n', modified_text) | |
| logger.info(f"Generated outline: {modified_text}") | |
| return modified_text | |
| def remove_unwanted_phrases(text): | |
| unwanted_phrases = [ | |
| '์ฌ๋ฌ๋ถ', '์ต๊ทผ', '๋ง์ง๋ง์ผ๋ก', '๊ฒฐ๋ก ์ ์ผ๋ก', '๊ฒฐ๊ตญ', | |
| '์ข ํฉ์ ์ผ๋ก', '๋ฐ๋ผ์', '๋ง๋ฌด๋ฆฌ', '์์ฝ' | |
| ] | |
| words = re.findall(r'\S+|\n', text) | |
| result_words = [word for word in words if not any(phrase in word for phrase in unwanted_phrases)] | |
| return ' '.join(result_words).replace(' \n ', '\n').replace(' \n', '\n').replace('\n ', '\n') | |
| def format_sentences(text): | |
| """ | |
| ๊ธด ๋ฌธ์ฅ์ 3~6๊ฐ ๋จ์ด ๋จ์๋ก ๋ถ๋ฆฌํ๋ ํจ์ (ํ๊ตญ์ด์ ์ต์ ํ) | |
| """ | |
| if text is None: | |
| return "" # text๊ฐ None์ธ ๊ฒฝ์ฐ ๋น ๋ฌธ์์ด ๋ฐํ | |
| # ๋ฌธ์ฅ ๋จ์๋ก ๋ถ๋ฆฌ | |
| sentences = re.split(r'(?<=[.!?])\s+', text) | |
| formatted_sentences = [] | |
| for sentence in sentences: | |
| # ๋ฌธ์ฅ์ด ์ถฉ๋ถํ ๊ธธ ๊ฒฝ์ฐ๋ง ๋ถ๋ฆฌ ์ฒ๋ฆฌ | |
| if len(sentence) > 20: # ๋ ์งง์ ๋ฌธ์ฅ์ ๊ทธ๋๋ก ์ ์ง | |
| # ๋์ด์ฐ๊ธฐ๋ฅผ ๊ธฐ์ค์ผ๋ก ๋จ์ด ๋ถ๋ฆฌ | |
| words = sentence.split() | |
| if len(words) <= 4: # ์ด๋ฏธ 6๋จ์ด ์ดํ๋ฉด ๊ทธ๋๋ก ์ฌ์ฉ | |
| formatted_sentences.append(sentence) | |
| continue | |
| chunk = [] | |
| word_count = 0 | |
| for word in words: | |
| chunk.append(word) | |
| word_count += 1 | |
| # ํ๊ธ์ ์์ด๋ณด๋ค ํ ๋จ์ด๊ฐ ๋ ๊ธธ๊ธฐ ๋๋ฌธ์, ๋จ์ด ์๋ฅผ 4~7๊ฐ๋ก ์กฐ์ | |
| if word_count >= 4 and (word_count >= 7 or re.search(r'[,;:]$', word)): | |
| formatted_sentences.append(' '.join(chunk)) | |
| chunk = [] | |
| word_count = 0 | |
| # ๋จ์ ๋จ์ด๋ค ์ฒ๋ฆฌ | |
| if chunk: | |
| formatted_sentences.append(' '.join(chunk)) | |
| else: | |
| formatted_sentences.append(sentence) | |
| return "\n".join(formatted_sentences) | |
| def extract_keywords(text, top_n=5): | |
| from sklearn.feature_extraction.text import CountVectorizer | |
| vectorizer = CountVectorizer(stop_words='english', ngram_range=(1,2)) | |
| count_matrix = vectorizer.fit_transform([text]) | |
| terms = vectorizer.get_feature_names_out() | |
| counts = count_matrix.sum(axis=0).A1 | |
| term_counts = sorted(zip(terms, counts), key=lambda x: x[1], reverse=True) | |
| return [term for term, count in term_counts[:top_n]] | |
| def get_outline_prompt(category): | |
| if category == "๋ฐฉ๋ฌธํ๊ธฐํ": | |
| return """ | |
| ## ์์คํ ์ญํ | |
| ๋น์ ์ ์๋ ๊ฐ์ ๊ฒฝํ์ ๊ฐ์ง ์ ๋ฌธ ๋ฐฉ๋ฌธ ๋ฆฌ๋ทฐ ๋ธ๋ก๊ฑฐ์ ๋๋ค. ๋ง์ง, ์นดํ, ์์, ๊ด๊ด์ง ๋ฑ ๋ค์ํ ์ฅ์์ ๋ํ ์์ํ ๋ฆฌ๋ทฐ๋ก ๋ง์ ๋ ์๋ค์ ์ ๋ขฐ๋ฅผ ๋ฐ๊ณ ์์ต๋๋ค. | |
| ## ๋ถ์ ๋จ๊ณ | |
| 1. ์ฐธ๊ณ ๊ธ 3๊ฐ๋ฅผ ์ฒ ์ ํ ๋ถ์ํ์ฌ ํต์ฌ ์ฃผ์ ์ ์ค์ ์ ๋ณด ํ์ | |
| 2. ๋ฐฉ๋ฌธํ ์ฅ์์ ์ ํ๊ณผ ํน์ฑ ์๋ณ (์๋น, ์นดํ, ์์, ๊ด๊ด์ง ๋ฑ) | |
| 3. ๋ฆฌ๋ทฐ์ ํต์ฌ์ด ๋ 5๊ฐ์ง ์ฃผ์ ์์ ํ์ (๋ถ์๊ธฐ, ๋ง, ์๋น์ค, ๊ฐ๊ฒฉ, ํน๋ณํจ ๋ฑ) | |
| ## ์์๋ผ์ธ ๊ตฌ์ฑ ์์น | |
| 1. ๋์ ๋ถ(1๊ฐ) - ํธ๊ธฐ์ฌ์ ์๊ทนํ๋ ์ ๋ชฉ์ผ๋ก ์์ | |
| 2. ๋ณธ๋ก (4-5๊ฐ) - ์ฐธ๊ณ ๊ธ ๋ถ์์ ํตํด ๋ฐ๊ฒฌํ ์ฅ์/๊ฒฝํ์ ํต์ฌ ๊ฐ์น์ ํน์ง์ ๋ด์ ์์ ๋ชฉ | |
| * ์ฐธ๊ณ ๊ธ์์ ๊ฐ์ฅ ๊ฐ์กฐ๋๋ ํน์ง์ด๋ ์ฅ์ | |
| * ๋ฐฉ๋ฌธ์๋ค์ด ๊ฐ์ฅ ๊ด์ฌ์ ๊ฐ์ง ๋งํ ์์ | |
| * ์ฐจ๋ณํ๋ ๊ฒฝํ์ด๋ ๋ ํนํ ํน์ฑ | |
| * ์ค์ฉ์ ์ธ ์ ๋ณด๋ ์์๋๋ฉด ์ข์ ํ | |
| * (์ ํญ๋ชฉ๋ค์ ์์์ผ ๋ฟ, ์ฐธ๊ณ ๊ธ ๋ถ์์ ํตํด ์์ ๋กญ๊ฒ ๊ฒฐ์ ) | |
| 3. ๊ฒฐ๋ก (1๊ฐ) - ์ ์ฒด ๊ฒฝํ์ ์์ฝํ๋ ๋งค๋ ฅ์ ์ธ ์ ๋ชฉ | |
| ## ํต์ฌ ์ง์นจ | |
| - **์์ ํ ํ๊ตญ์ด๋ก๋ง ์์ฑ**ํ ๊ฒ | |
| - ์์ ๋ชฉ์ **์ต๋ 30์ ์ด๋ด**๋ก ๊ฐ๊ฒฐํ๊ฒ ์์ฑ | |
| - ํธ๊ธฐ์ฌ์ ์๊ทนํ๋ ํํ ์ฌ์ฉ (์: "๊ผญ ์์์ผ ํ ", "๋๋ผ์ด", "์จ๊ฒจ์ง") | |
| - ์ฅ์์ ๊ฐ์ฅ ๋งค๋ ฅ์ ์ธ ํฌ์ธํธ๊ฐ ์์ ๋ชฉ์ ๋ฐ์๋๋๋ก ๊ตฌ์ฑ | |
| - **์ฌ์ง ํค์๋๋ ์์ ๋ชฉ ๊ฒฐ์ ์ ์ํฅ์ ์ฃผ์ง ์์** (๋ณธ๋ฌธ ์์ฑ ์ ์ฐธ๊ณ ์ฌํญ์ผ๋ก๋ง ํ์ฉ) | |
| - ์ ์ฒด ์์๋ผ์ธ์ ๋์ ๋ถ(1) + ๋ณธ๋ก (์ต๋ 5๊ฐ) + ๊ฒฐ๋ก (1)์ผ๋ก ๊ตฌ์ฑ | |
| ## ์ถ๋ ฅ ํ์ | |
| * ์ฐธ๊ณ ๊ธ ๋ถ์์ ํตํด ๊ฐ์ฅ ํต์ฌ์ ์ธ ์ฃผ์ ์ ํน์ง์ ํ์ ํ์ฌ ์์ ๋กญ๊ฒ ์์๋ผ์ธ ๊ตฌ์ฑ | |
| * ํ์ง๋ง ๋ฐ๋์ ๋ค์ ๊ตฌ์กฐ๋ฅผ ์ ์งํ ๊ฒ:(๊ฐ ํญ๋ชฉ๋น 1๋ฒ์ํฐ๋ฅผ ์ ์ฉํ์ ๋น์นธ์ด ๋์ค์ง ์๋๋กํ๋ผ.) | |
| - ๋์ ๋ถ: 1๊ฐ (ํธ๊ธฐ์ฌ์ ์๊ทนํ๋ ํฅ๋ฏธ๋ก์ด ์ ๋ชฉ) | |
| - ๋ณธ๋ก : 4-5๊ฐ (์ฅ์/๊ฒฝํ์ ๊ฐ์ฅ ์ค์ํ ํน์ง์ ๋ฐ์ํ ์ ๋ชฉ) | |
| - ๊ฒฐ๋ก : 1๊ฐ (์ ์ฒด ๊ฒฝํ ์์ฝ ์ ๋ชฉ) | |
| * ์์ ๋ชฉ์ ์ฅ์์ ์ค์ ๊ฒฝํ๊ณผ ํน์ง์ ๋ง๊ฒ ์์ ๋กญ๊ฒ ๊ตฌ์ฑ | |
| * ์ฌ์ง ํค์๋์ ๋ง์ถ์ง ๋ง๊ณ , ์ฐธ๊ณ ๊ธ ๋ถ์์ ํตํด ๋ฐ๊ฒฌํ ํต์ฌ ๊ฐ์น์ ํน์ง ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ฑ | |
| ์์ ํ์ (์ฐธ๊ณ ์ฉ์ผ ๋ฟ, ๋ด์ฉ์ ์ฐธ๊ณ ๊ธ์ ๋ฐ๋ผ ์์ ํ ๋ฌ๋ผ์ง ์ ์์): | |
| ๋์ ๋ถ: [ํฅ๋ฏธ๋ก์ด ๋์ ์ ๋ชฉ] | |
| ๋ณธ๋ก 1: [ํต์ฌ ํน์ง/์ฅ์ ๊ด๋ จ ์ ๋ชฉ] | |
| ๋ณธ๋ก 2: [๋ ๋ค๋ฅธ ์ฃผ์ ํน์ง ๊ด๋ จ ์ ๋ชฉ] | |
| ๋ณธ๋ก 3: [์ฐจ๋ณํ ์์ ๊ด๋ จ ์ ๋ชฉ] | |
| ๋ณธ๋ก 4: [์ ์ฉํ ์ ๋ณด/ํ ๊ด๋ จ ์ ๋ชฉ] | |
| ๋ณธ๋ก 5: [์ถ๊ฐ ํน์ง/์ ๋ณด ๊ด๋ จ ์ ๋ชฉ] (ํ์์) | |
| ๊ฒฐ๋ก : [์ ์ฒด ๊ฒฝํ ์์ฝ ์ ๋ชฉ] | |
| """ | |
| def get_blog_post_prompt(category): | |
| if category == "๋ฐฉ๋ฌธํ๊ธฐํ": | |
| return """ | |
| # ๋ฐฉ๋ฌธํ๊ธฐํ ๋ธ๋ก๊ทธ ์ฝํ ์ธ ์์ฑ ์์คํ [v2.0] | |
| ## ์์คํ ์ญํ | |
| ๋น์ ์ ์๋ง ๋ช ์ ํ๋ก์๋ฅผ ๋ณด์ ํ ์ธ๊ธฐ ๋ฐฉ๋ฌธ ๋ฆฌ๋ทฐ ๋ธ๋ก๊ฑฐ์ ๋๋ค. ์์ํ ํ์ฅ๊ฐ๊ณผ ๋ํ ์ผํ ์ ๋ณด ์ ๊ณต์ผ๋ก ๋ ์๋ค์๊ฒ ์ค์ ๋ฐฉ๋ฌธํ ๋ฏํ ๊ฒฝํ์ ์ ๋ฌํ๋ ์ ๋ฌธ๊ฐ์ ๋๋ค. | |
| ## ์ฝํ ์ธ ์์ฑ ์์น | |
| ### 1. ๊ธ์ ๊ตฌ์กฐ | |
| - **๋์ ๋ถ** (์ ์ฒด ๊ธ์ 10-15%): | |
| * ์ฅ์ ์๊ฐ ๋ฐ ๋ฐฉ๋ฌธ ๊ณ๊ธฐ | |
| * ์ฒซ์ธ์๊ณผ ๊ธฐ๋๊ฐ ํํ | |
| * ์์น์ ๋ณด์ ํจ๊ป "[์ง๋ ์ ๋ณด๋ฅผ ๋ฃ์ด์ฃผ์ธ์]" ๋ช ์ | |
| * ๊ธธ์ด: 500์ ์ด์ | |
| - **๋ณธ๋ก ** (์ ์ฒด ๊ธ์ 70-80%): | |
| * ์์๋ผ์ธ์ ๊ฐ ์์ ๋ชฉ์ ๋ง์ถ ์์ธ ๋ด์ฉ | |
| * ์ฅ์์ ๋ถ์๊ธฐ, ์ ํ/์๋น์ค ํ์ง, ๊ฐ๊ฒฉ, ์๋น์ค ๋ฑ ํต์ฌ ์์ ์์ธ ์ค๋ช | |
| * ์ค์ ๊ฒฝํ ๊ธฐ๋ฐ์ ์์ํ ํํ | |
| * ๊ฐ ์น์ ์ 400-600์ ์์ค์ผ๋ก ๊ท ํ์๊ฒ ์์ฑ | |
| * ๊ธธ์ด: 2500์ ์ด์ | |
| - **๊ฒฐ๋ก ** (์ ์ฒด ๊ธ์ 10-15%): | |
| * ์ ์ฒด ๊ฒฝํ ์์ฝ ๋ฐ ์ถ์ฒ ์ด์ | |
| * ์ถ๊ฐ ํ์ด๋ ๋ฐฉ๋ฌธ ์ ์ฐธ๊ณ ์ฌํญ | |
| * ๊ธธ์ด: 400์ ์ด์ | |
| ### 2. ์ฌ์ง ์ฝ์ ์ง์นจ | |
| - ์ฌ์ง ํค์๋๋ **๋ด์ฉ์ ๋ง๊ฒ** ๋ณธ๋ฌธ ์ค๊ฐ์ ์์ฐ์ค๋ฝ๊ฒ ์ฝ์ | |
| - ์ฌ์ง ํค์๋๋ ๋ด์ฉ๊ณผ ๊ด๋ จ ์์ ๋๋ง ์ฌ์ฉํ๊ณ , ์ต์ง๋ก ๋ชจ๋ ํค์๋๋ฅผ ์ฌ์ฉํ์ง ์์ | |
| - ์ฌ์ง ํค์๋๋ ๋๊ดํธ๋ก ํ์: [ํค์๋] | |
| - ์ฌ์ง ํค์๋ ์๋ค๋ก ๋น ์ค ์ฝ์ | |
| - ์ฌ์ง ํค์๋๋ ์์ ๋ชฉ์ด๋ ๋ด์ฉ ๊ตฌ์ฑ์ ์ํฅ์ ์ฃผ์ง ์์ผ๋ฉฐ, ๊ธ์ ์์ฐ์ค๋ฌ์ด ํ๋ฆ์ ๋ฐ๋ผ ์ ์ ํ ์์น์๋ง ์ฝ์ | |
| - ๊ธ์ ๋ด์ฉ๊ณผ ๋ง์ง ์๋ ์ฌ์ง ํค์๋๋ ๊ณผ๊ฐํ ์๋ต | |
| - ์ฌ์ง ํค์๋๊ฐ ์๊ฑฐ๋ ์ฌ์ฉํ์ง ์์๋ ๊ธ์ ํ๋ฆฌํฐ๋ ์์ฑ๋์๋ ์ ํ ์ํฅ ์์ | |
| ### 3. ๊ธ์ฐ๊ธฐ ์คํ์ผ | |
| - ํ ๋ฌธ์ฅ์ 2-3 ๋ถ๋ถ์ผ๋ก ๋๋ ์ ์ค๋ฐ๊ฟํ์ฌ ๊ฐ๋ ์ฑ ํฅ์ | |
| - ์์ ๋ชฉ์ ๋ณผ๋์ฒด๋ก ๊ตฌ๋ถํ๊ณ ์ ํ์ ๋น ์ค ์ฝ์ | |
| - ๊ฐ๊ด์ ์ฌ์ค๊ณผ ์ฃผ๊ด์ ๊ฒฝํ์ ๊ท ํ์๊ฒ ํผํฉ | |
| - ํต์ฌ ์ฅ์ ๊ณผ ๋จ์ ์ ์์งํ๊ฒ ํํ | |
| - ๊ณผ์ฅ๋ ํํ๋ณด๋ค ๊ตฌ์ฒด์ ์ธ ๋ํ ์ผ๋ก ์ ๋ขฐ๊ฐ ํ์ฑ | |
| - ๊ฐ ๋ฌธ๋จ ์ฌ์ด์ ์ ์ ํ ๋น ์ค์ ์ฝ์ ํ์ฌ ๊ฐ๋ ์ฑ ๋์ | |
| - ๊ธด ๋ฌธ๋จ์ 2-3๊ฐ์ ์์ ๋ฌธ๋จ์ผ๋ก ๋๋์ด ์ฝ๊ธฐ ํธํ๊ฒ ๊ตฌ์ฑ | |
| ### 4. ์ฝํ ์ธ ํ์ง ๊ธฐ์ค | |
| - ์ค์ ๊ฒฝํํ ๋ฏํ ๋ํ ์ผํ ๋ฌ์ฌ | |
| - ๋ชจ๋ ๊ฐ๊ฐ(์๊ฐ, ์ฒญ๊ฐ, ๋ฏธ๊ฐ, ํ๊ฐ, ์ด๊ฐ)์ ํ์ฉํ ํํ | |
| - ๊ฐ๊ฒฉ, ์์ ์๊ฐ, ํน๋ณ ํํ ๋ฑ ์ค์ฉ์ ์ ๋ณด ํฌํจ | |
| - ํน๋ณํ ํ์ด๋ ์๋ฉด ์ ์ฉํ ์ ๋ณด ์ ๊ณต | |
| - ์ ์ฒด ๊ธธ์ด: ์ต์ 3000์์์ด์ | |
| ### 5.์ถ๋ ฅ ํ์ ์๊ตฌ์ฌํญ | |
| - ์์ ๋ชฉ์ ๋ณผ๋์ฒด๋ก ํ์ํ๊ณ ์ ํ์ ๋น ์ค ์ฝ์ | |
| - ๋ชจ๋ ํ ์คํธ๋ ๊ฐ์ด๋ฐ ์ ๋ ฌ | |
| - ๋ฌธ์ฅ์ 2-3๊ฐ ๋จ์๋ก ์ค๋ฐ๊ฟํ์ฌ ๊ฐ๋ ์ฑ ํ๋ณด | |
| - ๊ฐ ๋ฌธ๋จ ์ฌ์ด์๋ ๋ฐ๋์ ๋น ์ค ์ฝ์ | |
| - ์ฌ์ง ํค์๋๋ ํ์ํ ์์น์๋ง ๋๊ดํธ๋ก ํ์ํ๊ณ ์ ํ์ ๋น ์ค ์ฝ์ | |
| - ๋ชจ๋ ๋จ๋ฝ์ ์ ์ ํ ๊ธธ์ด๋ก ๊ท ํ์๊ฒ ๊ตฌ์ฑ | |
| - ํนํ ์ค์ํ ๋ด์ฉ์ด๋ ๊ฐ์กฐํ๊ณ ์ถ์ ๋ถ๋ถ์ ๋ฌธ์ฅ ๋จ์๋ก ์ค๋ฐ๊ฟํ์ฌ ์๊ฐ์ ์ํฉํธ ๊ฐํ | |
| - ์ฐธ๊ณ ๊ธ์ ๋ด์ฉ์ ํ ๋๋ก ์๋กญ๊ฒ ๊ตฌ์ฑํ๋, ๋ค์์ ๋ฐ๋์ ์ค์ํ๋ผ: | |
| - ์ฐธ๊ณ ๊ธ์ ์ธ๊ธ๋ ๋๋ค์, ์ด๋ฆ, ํ์ฌ๋ช , ๋ธ๋๋๋ช ๋ฑ์ ๊ทธ๋๋ก ์ฌ์ฉํ์ง ๋ง๊ณ ๋ค๋ฅธ ๋ช ์นญ์ผ๋ก ๋ณ๊ฒฝํ๋ผ. | |
| - ์ฟ ํกํํธ๋์ค, ๊ด๊ณ , ์ ํ ํ์ฐฌ, ์์ ์ ๊ธ์ก์ด๋ ์ฌ์ํ์ ๋ฐ์๋ค๋ ๋ด์ฉ ์ ์ธํ ๊ฒ | |
| - ์ฐธ๊ณ ๊ธ ์์ฑ์์ ๊ฒฝํ์ด ์๋ ๋์ ์ง์ ๊ฒฝํ์ผ๋ก ์ฌ๊ตฌ์ฑํ ๊ฒ | |
| """ | |
| def get_style_prompt(style): | |
| prompts = { | |
| "์น๊ทผํ": """ | |
| # ์น๊ทผํ ๋ธ๋ก๊ทธ ๊ธ์ฐ๊ธฐ ์คํ์ผ ํ๋กํ | |
| ## ํค & ๋ณด์ด์ค | |
| - ๋ ์์ ๋ํํ๋ ๋ฏํ ์น๊ทผํ๊ณ ํธ์ํ ์ดํฌ | |
| - '~ํด์', '~๋ค์', '~์ธ ๊ฒ ๊ฐ์์' ๋ฑ ๊ตฌ์ด์ฒด ํํ ์ ๊ทน ํ์ฉ | |
| - ๊ฐ์ ๊ณผ ๋๋์ ์์งํ๊ฒ ํํํ๋ ๊ฐ์ธ์ ์ธ ์ด์กฐ | |
| - ๊ฐํ์ฌ๋ฅผ ์ ์ ํ ํ์ฉ (์: ์~, ์ ๋ง!, ใ ใ ) | |
| - ์ด๋ชจํฐ์ฝ์ ์ฌ์ฉํ์ง๋ง๋ผ | |
| ## ๋ฌธ์ฒด & ๋ฌธ๋ฒ | |
| - **ํด์์ฒด ์ ์ฉ**: ๋ชจ๋ ๋ฌธ์ฅ์ '~ํฉ๋๋ค'๊ฐ ์๋ '~ํด์'๋ก ์ข ๊ฒฐ | |
| - ์งง๊ณ ๊ฐ๊ฒฐํ ๋ฌธ์ฅ ๊ตฌ์กฐ๋ก ์ฝ๊ธฐ ์ฝ๊ฒ ๊ตฌ์ฑ | |
| - ์ง๋ฌธํ ๋ฌธ์ฅ์ผ๋ก ๋ ์์ ๊ณต๊ฐ ์ ๋ (์: "์ฌ๋ฌ๋ถ๋ ๊ทธ๋ ์ง ์๋์?") | |
| - ๊ฐ์ธ์ ๊ฒฝํ์ ์์ฐ์ค๋ฝ๊ฒ ๊ณต์ ํ๋ 1์ธ์นญ ์์ | |
| ## ์ดํ & ํํ | |
| - ์ผ์์ ์ด๊ณ ์ฌ์ด ๋จ์ด ์ ํ (์ ๋ฌธ์ฉ์ด ์ฌ์ฉ ์ ํ์ด์ ์ค๋ช ) | |
| - ์ง๊ด์ ์ธ ๋น์ ์ ์์๋ก ์ค๋ช (์: "๋ง์น ๊ตฌ๋ฆ ์๋ฅผ ๊ฑท๋ ๋ฏํ ๋๋์ด์์ด์") | |
| - ์์ํ ๊ฐ๊ฐ์ ํํ์ผ๋ก ํ์ฅ๊ฐ ์ ๋ฌ | |
| - ๊ณผ์ฅ๋ ํํ๋ณด๋ค๋ ์์งํ ๋๋ ์ค์ฌ์ ์์ | |
| ## ๋ ์์์ ๊ด๊ณ | |
| - ๋ ์๋ฅผ '์ฌ๋ฌ๋ถ'์ผ๋ก ์ง์นญํ๋ฉฐ ์น๊ทผ๊ฐ ํ์ฑ | |
| - ๋ ์์ ์ ์ฅ์ ๊ณ ๋ คํ ๊ณต๊ฐ๋ ํ์ฑ ํํ ์ฌ์ฉ | |
| - ๋ ์์๊ฒ ์ง์ ๋ง์ ๊ฑฐ๋ ๋ฏํ ๋ํํ ๋ฌธ์ฒด | |
| - ์ ๋ณด ์ ๋ฌ๊ณผ ํจ๊ป ๊ฐ์ธ์ ์ธ ํ์ด๋ ์กฐ์ธ ์ ๊ณต | |
| ## ์์ ๋ฌธ์ฅ | |
| "์ฌ๊ธฐ ๋ถ์๊ธฐ๊ฐ ์ ๋ง ์ข๋๋ผ๊ณ ์. | |
| ์์ํ ์กฐ๋ช ๊ณผ ์ฐจ๋ถํ ์์ ์ด | |
| ๋ง์์ ํธ์ํ๊ฒ ํด์คฌ์ด์. | |
| ๊ฐ๊ฒฉ์ ์กฐ๊ธ ์๋ ํธ์ด์ง๋ง | |
| ๊ทธ๋งํผ ๊ฐ์น ์๋ ๊ฒฝํ์ด์๋ต๋๋ค. | |
| ๋ค์์ ๋ฐฉ๋ฌธํ์ค ๋๋ | |
| ํ์ผ ์คํ๊ฐ ํ์ ํด์ ์ถ์ฒํด์!" | |
| """, | |
| "์ผ๋ฐ": """ | |
| # ๊ท ํ ์กํ ๋ธ๋ก๊ทธ ๊ธ์ฐ๊ธฐ ์คํ์ผ ํ๋กํ | |
| ## ํค & ๋ณด์ด์ค | |
| - ๊ฐ๊ด์ ์ ๋ณด์ ์ฃผ๊ด์ ์๊ฒฌ์ด ๊ท ํ์ ์ด๋ฃฌ ์ค๋ฆฝ์ ์ด์กฐ | |
| - ์ ์คํ๊ณ ์์ ๋ฐ๋ฅธ ์ดํฌ๋ก ์ ๋ขฐ๊ฐ ํ์ฑ | |
| - ๊ณผ์ฅ๋ ํํ์ด๋ ๊ฐ์ ํํ ์์ | |
| - ๋ช ํํ๊ณ ๊ฐ๊ฒฐํ ๋ฌธ์ฅ์ผ๋ก ํต์ฌ ์ ๋ณด ์ ๋ฌ | |
| ## ๋ฌธ์ฒด & ๋ฌธ๋ฒ | |
| - 'ํฉ๋๋ค/์ต๋๋ค' ์ข ๊ฒฐ์ด๋ฏธ ์ฌ์ฉ์ผ๋ก ๋จ์ ํ ์ธ์ | |
| - ๋ ผ๋ฆฌ์ ๊ตฌ์กฐ์ ๋ช ํํ ํ๋ฆ์ ๊ฐ์ง ๋ฌธ์ฅ ๊ตฌ์ฑ | |
| - ๋ฌธ๋ฒ์ ์ผ๋ก ์ฌ๋ฐ๋ฅด๊ณ ์ ์ ๋ ํํ ์ฌ์ฉ | |
| - ์ ์ ํ ๊ธธ์ด์ ๋จ๋ฝ์ผ๋ก ๊ฐ๋ ์ฑ ํ๋ณด | |
| ## ์ดํ & ํํ | |
| - ์ผ๋ฐ ๋ ์๊ฐ ์ดํดํ ์ ์๋ ์์ค์ ์ดํ ์ ํ | |
| - ์ ๋ฌธ ์ฉ์ด ์ฌ์ฉ ์ ๊ฐ๋ตํ ์ค๋ช ์ ๊ณต | |
| - ๊ตฌ์ฒด์ ์ธ ์์น์ ์ฌ์ค ์ค์ฌ์ ์ค๋ช | |
| - ๋น๊ต์ ๋์กฐ๋ฅผ ํตํ ๋ช ํํ ์ ๋ณด ์ ๋ฌ | |
| ## ๋ ์์์ ๊ด๊ณ | |
| - ์ ์ ํ ๊ฑฐ๋ฆฌ๊ฐ ์ ์ง๋ก ์ ๋ขฐ์ฑ ํ๋ณด | |
| - ๋ ์๋ฅผ ์ํ ์ ์ฉํ ์ ๋ณด ์ค์ฌ ๊ตฌ์ฑ | |
| - ์ง์ ์ ์ธ ์ถ์ฒ์ด๋ ์๊ฒฌ ์ ์ ์ ๊ทผ๊ฑฐ ํจ๊ป ์ ๊ณต | |
| - ๋ ์๊ฐ ์ค์ค๋ก ํ๋จํ ์ ์๋ ๊ฐ๊ด์ ์ ๋ณด ์ ๊ณต | |
| ## ์์ ๋ฌธ์ฅ | |
| "์ด ๋ ์คํ ๋์ 2020๋ ์ ์คํํ | |
| ๋ชจ๋ ์ดํ๋ฆฌ์ ๋ค์ด๋์ ๋๋ค. | |
| ๋ด๋ถ๋ 50์ ๊ท๋ชจ๋ก ๊ตฌ์ฑ๋์ด ์์ผ๋ฉฐ | |
| ํ๋ผ์ด๋นํ ๊ณต๊ฐ๋ ๋ง๋ จ๋์ด ์์ต๋๋ค. | |
| ๊ฐ๊ฒฉ๋๋ 1์ธ๋น 3๋ง์์์ 5๋ง์ ์ ์ผ๋ก | |
| ๋ค๋ฅธ ์ดํ๋ฆฌ์ ๋ ์คํ ๋๊ณผ ๋น๊ตํ์ ๋ | |
| ์ค์์๊ถ์ ์ํฉ๋๋ค. | |
| ํนํ ์์ฒด ์ ์ํ๋ ํ์คํ ๋ฉด์ด | |
| ์ด ๊ณณ์ ์ฐจ๋ณ์ ์ ๋๋ค." | |
| """, | |
| "์ ๋ฌธ์ ์ธ": """ | |
| # ์ ๋ฌธ๊ฐํ ๋ธ๋ก๊ทธ ๊ธ์ฐ๊ธฐ ์คํ์ผ ํ๋กํ | |
| ## ํค & ๋ณด์ด์ค | |
| - ๊น์ด ์๋ ์ง์๊ณผ ๊ฒฝํ์ด ๋๊ปด์ง๋ ์ ๋ฌธ์ ์ด์กฐ | |
| - ๊ฐ๊ด์ ์ฌ์ค๊ณผ ๋ถ์์ ๊ด์ ์ด ๋๋ณด์ด๋ ๋ ผ๋ฆฌ์ ์์ | |
| - ๊ถ์ ์๊ณ ์ค๋๋ ฅ ์๋ ์ดํฌ๋ก ์ ๋ขฐ๊ฐ ํ์ฑ | |
| - ์ ์ ๋ ํํ๊ณผ ์ฒด๊ณ์ ์ธ ๊ตฌ์ฑ์ผ๋ก ์ ๋ฌธ์ฑ ๊ฐ์กฐ | |
| ## ๋ฌธ์ฒด & ๋ฌธ๋ฒ | |
| - ์ ํํ๊ณ ๊ฐ๊ฒฐํ ๋ฌธ์ฅ ๊ตฌ์กฐ | |
| - ๋ณต์กํ ๊ฐ๋ ๋ ๋ช ํํ ์ ๋ฌํ๋ ๋ ผ๋ฆฌ์ ํ๋ฆ | |
| - ์ ๋ฌธ ์ฉ์ด์ ์ ์ ํ ํ์ฉ๊ณผ ์ค๋ช | |
| - ํ์ ์ ๊ธ์ฐ๊ธฐ์ ๊ฐ๊น์ด ์ฒด๊ณ์ ๋ฌธ๋จ ๊ตฌ์ฑ | |
| ## ์ดํ & ํํ | |
| - ํด๋น ๋ถ์ผ์ ์ ๋ฌธ ์ฉ์ด์ ๊ฐ๋ ์ ๊ทน ํ์ฉ | |
| - ๊ตฌ์ฒด์ ์ธ ์์น์ ๋ฐ์ดํฐ ๊ธฐ๋ฐ ์ค๋ช | |
| - ๋น๊ต ๋ถ์๊ณผ ํ๊ฐ๋ฅผ ์ํ ์ ๋ฌธ์ ๊ธฐ์ค ์ ์ | |
| - ์ ํํ ์ธ์ฉ๊ณผ ์ฐธ์กฐ๋ฅผ ํตํ ์ ๋ขฐ์ฑ ํ๋ณด | |
| ## ๋ ์์์ ๊ด๊ณ | |
| - ์ ๋ฌธ๊ฐ๋ก์ ์ง์๊ณผ ํต์ฐฐ๋ ฅ ๊ณต์ | |
| - ๊ฐ๊ด์ ํ๊ฐ์ ์ ๋ฌธ์ ์กฐ์ธ ์ ๊ณต | |
| - ๋ ์์ ์ง์ ํธ๊ธฐ์ฌ์ ์๊ทนํ๋ ์ฌ์ธต ๋ถ์ | |
| - ์ ๊ณ ํธ๋ ๋๋ ์ ๋ฌธ์ ๊ด์ ์์์ ํ๊ฐ ์ ์ | |
| ## ์์ ๋ฌธ์ฅ | |
| "๋ณธ ๋ ์คํ ๋์ ๋ฏธ์๋ฆฐ ์ถ์ ์ ฐํ๊ฐ | |
| ์ดํ๋ฆฌ์ ํด์ง์ ์ ์๋ฅผ ์ ๋ณด์ด๋ ๊ณต๊ฐ์ ๋๋ค. | |
| ํนํ 72์๊ฐ ์ ์จ ์์ฑํ ๋์ฐ๋ฅผ | |
| ํ๋์์ 90์ด๊ฐ ๊ตฌ์๋ด๋ ๋ํด๋ฆฌ ๋ฐฉ์์ ํผ์๋ | |
| ๊ตญ๋ด ์ต๊ณ ์์ค์ผ๋ก ํ๊ฐ๋ฐ๊ณ ์์ต๋๋ค. | |
| ์์ฌ๋ฃ๋ 100% ์ ๊ธฐ๋ ์ธ์ฆ์ ๋ฐ์ | |
| ์ง์ญ ๋๊ฐ์์ ์ง์ก๋๋ฉฐ, | |
| ์์ธ ํ์ด๋ง์ ์ํ ์๋ฏ๋ฆฌ์์ ์ ๋ฌธ์ ์ธ ํ๋ ์ด์ ์ด | |
| ์์ฌ ๊ฒฝํ์ ํ์ธต ๋ ํ๋ถํ๊ฒ ํฉ๋๋ค." | |
| """ | |
| } | |
| return prompts.get(style, "ํฌ์คํ ์คํ์ผ ํ๋กฌํํธ") | |
| def generate_blog_post(category, style, references1, references2, references3, outline, photo_recommendations): | |
| try: | |
| logger.info("1. ๋ฐ์ดํฐ ์ค๋น") | |
| data = { | |
| 'category': category, | |
| 'style': style, | |
| 'references1': references1, | |
| 'references2': references2, | |
| 'references3': references3, | |
| 'outline': outline, | |
| 'photo_recommendations': photo_recommendations | |
| } | |
| logger.info("2. ํ๋กฌํํธ ์ค๋น") | |
| system_prompt = get_blog_post_prompt(data['category']) | |
| style_prompt = get_style_prompt(data['style']) | |
| # ์์ ๋ ์ ์ ํ๋กฌํํธ - ๊ฐ ์ค๋น 4~7๋จ์ด ์ง์ | |
| user_prompt = f""" | |
| **๋ฐ๋์ 3000์ ์ด์ ์์ฑํ๋ผ** | |
| ์ฐธ๊ณ ๊ธ1: {data['references1']} | |
| ์ฐธ๊ณ ๊ธ2: {data['references2']} | |
| ์ฐธ๊ณ ๊ธ3: {data['references3']} | |
| ์์๋ผ์ธ: {data['outline']} | |
| ์ฌ์ง ํค์๋: {data['photo_recommendations']} | |
| ๊ธ ์์ฑ ํ์ ๊ท์น: | |
| 1. ๊ฐ ๋ฌธ์ฅ์ 4~7๋จ์ด ๋จ์๋ก ์ค๋ฐ๊ฟํ์ฌ ์์ฑํ ๊ฒ | |
| 2. ์ฌ์ง ํค์๋๋ [ํค์๋] ํํ๋ก ์๋ค์ ๋น ์ค์ ์ถ๊ฐํ ๊ฒ | |
| 3. ์์ ๋ชฉ์ ๋ณผ๋์ฒด๋ก ํ์ํ๊ณ ์ ํ์ ๋น ์ค ์ฝ์ ํ ๊ฒ | |
| 4. ๋ชจ๋ ํ ์คํธ๋ ๊ฐ์ด๋ฐ ์ ๋ ฌ๋ก ์์ฑํ ๊ฒ | |
| 5. ๋ฌธ๋จ ์ฌ์ด์๋ ๋ฐ๋์ ๋น ์ค์ ๋ฃ์ ๊ฒ | |
| """ | |
| logger.info("3. ๊ธ ์์ฑ ์์") | |
| full_post = call_api( | |
| user_prompt, | |
| system_prompt + "\n" + style_prompt, | |
| max_tokens=15000, | |
| temperature=0.7, | |
| top_p=0.95 | |
| ) | |
| # API ํธ์ถ ์๋ต ํ์ธ | |
| if full_post is None or full_post.startswith("Gemini API Error"): | |
| error_msg = "API ์๋ต ์์" if full_post is None else full_post | |
| logger.error(f"๋ธ๋ก๊ทธ ๊ธ ์์ฑ API ์ค๋ฅ: {error_msg}") | |
| return f"<p style='color: red;'>๊ธ ์์ฑ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค: {error_msg}</p>" | |
| logger.info(f"Gemini๊ฐ ์์ฑํ ์๋ณธ ๊ธ ๊ธธ์ด: {len(full_post)}") | |
| logger.info("4. ๋ถํ์ํ ๋ฌธ๊ตฌ ์ ๊ฑฐ ๋ฐ ํ ์คํธ ํ์ ์กฐ์ ") | |
| # ๋ถํ์ํ ๋ฌธ๊ตฌ ์ ๊ฑฐ | |
| filtered_post = remove_unwanted_phrases(full_post).lstrip() | |
| # ํ์ํ ๊ฒฝ์ฐ ๋ฌธ์ฅ์ 4~7๋จ์ด ๋จ์๋ก ์ถ๊ฐ ํฌ๋งทํ | |
| formatted_post = format_sentences(filtered_post) | |
| # ์ฌ์ง ํค์๋ ํจํด ์๋ค๋ก ๋น ์ค ์ถ๊ฐ | |
| pattern = r'(\[[\w\s๊ฐ-ํฃ]+\])' | |
| processed_text = re.sub(pattern, r'\n\n\1\n\n', formatted_post) | |
| # ์ค๋ณต๋ ๋น ์ค ์ ๋ฆฌ | |
| processed_text = re.sub(r'\n{3,}', '\n\n', processed_text) | |
| logger.info("5. HTML ๋ณํ") | |
| html_post = convert_to_html(processed_text) | |
| logger.info("6. ์ต์ข ๊ฒฐ๊ณผ ๋ฐํ") | |
| return html_post | |
| except Exception as e: | |
| logger.error(f"๊ธ ์์ฑ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}") | |
| return f"<p style='color: red;'>๊ธ ์์ฑ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}</p>" | |
| def convert_to_html(text): | |
| if text is None: | |
| return "<p>ํ ์คํธ ๋ณํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.</p>" | |
| lines = text.split('\n') | |
| html_lines = [] | |
| in_paragraph = False | |
| for i, line in enumerate(lines): | |
| line = line.strip() | |
| # ๋น ์ค ์ฒ๋ฆฌ | |
| if not line: | |
| if in_paragraph: | |
| html_lines.append("</p>") | |
| in_paragraph = False | |
| html_lines.append("<br>") | |
| continue | |
| # ์ฌ์ง ํค์๋ ์ฒ๋ฆฌ (๋๊ดํธ๋ก ๋ ํ ์คํธ) | |
| if re.match(r'^\[[\w\s๊ฐ-ํฃ]+\]$', line): | |
| if in_paragraph: | |
| html_lines.append("</p>") | |
| in_paragraph = False | |
| html_lines.append("<br>") | |
| html_lines.append(f"<p style='text-align: center; font-weight: bold; color: #0066cc; margin: 15px 0; font-size: 1.1em;'>{line}</p>") | |
| html_lines.append("<br>") | |
| continue | |
| # ํค๋ ์ฒ๋ฆฌ | |
| if line.startswith('####'): | |
| if in_paragraph: | |
| html_lines.append("</p>") | |
| in_paragraph = False | |
| html_lines.append(f"<h4 style='text-align: center; margin: 20px 0;'>{line[4:].strip()}</h4>") | |
| elif line.startswith('###'): | |
| if in_paragraph: | |
| html_lines.append("</p>") | |
| in_paragraph = False | |
| html_lines.append(f"<h3 style='text-align: center; margin: 20px 0;'>{line[3:].strip()}</h3>") | |
| elif line.startswith('##'): | |
| if in_paragraph: | |
| html_lines.append("</p>") | |
| in_paragraph = False | |
| html_lines.append(f"<h2 style='text-align: center; margin: 25px 0; color: #2c3e50;'>{line[2:].strip()}</h2>") | |
| elif line.startswith('#'): | |
| if in_paragraph: | |
| html_lines.append("</p>") | |
| in_paragraph = False | |
| html_lines.append(f"<h1 style='text-align: center; margin: 30px 0; color: #2c3e50;'>{line[1:].strip()}</h1>") | |
| # ๋ฆฌ์คํธ ์์ดํ ์ฒ๋ฆฌ | |
| elif line.startswith('- '): | |
| if in_paragraph: | |
| html_lines.append("</p>") | |
| in_paragraph = False | |
| html_lines.append(f"<li style='text-align: center; list-style: none; margin: 5px 0;'>{line[2:]}</li>") | |
| # ์ผ๋ฐ ํ ์คํธ ์ฒ๋ฆฌ - ๋จ๋ฝ ํ์ ์ ์ง | |
| else: | |
| # ๋ณผ๋์ฒด ์ฒ๋ฆฌ | |
| line = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', line) | |
| # ์์ ๋ชฉ ์ฒ๋ฆฌ (๋ณผ๋์ฒด๋ก ์์ํ๋ ๊ฒฝ์ฐ) | |
| if line.startswith('<strong>') and line.endswith('</strong>'): | |
| if in_paragraph: | |
| html_lines.append("</p>") | |
| in_paragraph = False | |
| html_lines.append(f"<h3 style='text-align: center; margin: 20px 0; color: #34495e;'>{line}</h3>") | |
| else: | |
| # ์ผ๋ฐ ํ ์คํธ๋ ๋จ๋ฝ์ผ๋ก ์ฒ๋ฆฌ | |
| if not in_paragraph: | |
| html_lines.append("<p style='text-align: center; margin: 8px 0; line-height: 1.8;'>") | |
| in_paragraph = True | |
| html_lines.append(f"{line}<br>") | |
| # ๋ง์ง๋ง ๋จ๋ฝ ๋ซ๊ธฐ | |
| if in_paragraph: | |
| html_lines.append("</p>") | |
| html_content = f""" | |
| <div style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 800px; margin: 0 auto; padding: 20px;"> | |
| {"".join(html_lines)} | |
| </div> | |
| """ | |
| return html_content | |
| # Gradio ์ฑ ๊ตฌ์ฑ (Gradio 5.0 ์ด์์ ๋ฒ์ ) | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# ๋ธ๋ก๊ทธ ํฌ์คํ ์์ฑ๊ธฐ") | |
| gr.Markdown("### 1๋จ๊ณ: ํฌ์คํ ์นดํ ๊ณ ๋ฆฌ๋ฅผ ์ง์ ํด์ฃผ์ธ์", elem_id="step-title") | |
| category = gr.Radio(choices=["๋ฐฉ๋ฌธํ๊ธฐํ"], label="ํฌ์คํ ์นดํ ๊ณ ๋ฆฌ", value="๋ฐฉ๋ฌธํ๊ธฐํ") | |
| gr.Markdown("---") | |
| gr.Markdown("### 2๋จ๊ณ: ํฌ์คํ ์คํ์ผ์ ์ ํํด์ฃผ์ธ์", elem_id="step-title") | |
| style = gr.Radio(choices=["์น๊ทผํ", "์ผ๋ฐ", "์ ๋ฌธ์ ์ธ"], label="ํฌ์คํ ์คํ์ผ", value="์น๊ทผํ") | |
| gr.Markdown("---") | |
| gr.Markdown("### 3๋จ๊ณ: ์ฐธ๊ณ ๊ธ์ ์ ๋ ฅํ์ธ์", elem_id="step-title") | |
| references1 = gr.Textbox(label="์ฐธ๊ณ ๊ธ 1", placeholder="์ฐธ๊ณ ํ ๊ธ์ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ผ์ธ์", lines=10) | |
| references2 = gr.Textbox(label="์ฐธ๊ณ ๊ธ 2", placeholder="์ฐธ๊ณ ํ ๊ธ์ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ผ์ธ์", lines=10) | |
| references3 = gr.Textbox(label="์ฐธ๊ณ ๊ธ 3", placeholder="์ฐธ๊ณ ํ ๊ธ์ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ผ์ธ์", lines=10) | |
| gr.Markdown("---") | |
| gr.Markdown("### 4๋จ๊ณ: ์ฌ์ง ์์น ์ถ์ฒ", elem_id="step-title") | |
| photo_recommendations = gr.Textbox(label="์ฌ์ง ํํ ํค์๋", placeholder="ํค์๋๋ฅผ ์ฝค๋ง(,)๋ก ๊ตฌ๋ถํ์ฌ ์ ๋ ฅํ์ธ์", lines=2) | |
| gr.Markdown("---") | |
| gr.Markdown("### 5๋จ๊ณ: ์์๋ผ์ธ์ ์์ฑํด์ฃผ์ธ์", elem_id="step-title") | |
| gr.HTML("<span style='color: grey;'>[์์๋ผ์ธ์์ ๋์จ ๊ฒฐ๊ณผ๋ฅผ ์์ ํด์ ์ฌ์ฉํด์ฃผ์ธ์]</span>") | |
| outline_generate_btn = gr.Button("์์๋ผ์ธ ์์ฑํ๊ธฐ") | |
| outline_result = gr.Textbox(label="์์๋ผ์ธ ๊ฒฐ๊ณผ", lines=7) | |
| outline_input = gr.Textbox(label="์์ฑํ ์์๋ผ์ธ์ ์ ๋ ฅํด์ฃผ์ธ์", placeholder="์์ฑ๋ ์์๋ผ์ธ ๋ณต์ฌ, ์์ ํด์ ์ฌ์ฉํ์ธ์", lines=7) | |
| # ์ํ ๋ฉ์์ง ์ถ๊ฐ | |
| status_msg = gr.Textbox(label="์ํ", value="์ค๋น ์๋ฃ", visible=True, interactive=False) | |
| # ์์๋ผ์ธ ์์ฑ ์ด๋ฒคํธ ํธ๋ค๋ฌ | |
| def generate_outline_with_status(category, style, references1, references2, references3, photo_recommendations): | |
| try: | |
| outline = generate_outline(category, style, references1, references2, references3, photo_recommendations) | |
| return outline, "์์๋ผ์ธ ์์ฑ ์๋ฃ" | |
| except Exception as e: | |
| return "", f"์ค๋ฅ ๋ฐ์: {str(e)}" | |
| outline_generate_btn.click( | |
| fn=generate_outline_with_status, | |
| inputs=[category, style, references1, references2, references3, photo_recommendations], | |
| outputs=[outline_result, status_msg] | |
| ) | |
| gr.Markdown("---") | |
| gr.Markdown("### 6๋จ๊ณ: ๊ธ ์์ฑํ๊ธฐ", elem_id="step-title") | |
| gr.HTML("<span style='color: grey;'>[์์๋ผ์ธ์ ํ์ธํ์ธ์]</span>") | |
| generate_btn = gr.Button("๋ธ๋ก๊ทธ ๊ธ ์์ฑํ๊ธฐ") | |
| output_text = gr.HTML(label="์์ฑ๋ ๋ธ๋ก๊ทธ ๊ธ") | |
| def generate_blog_post_with_status(category, style, references1, references2, references3, outline_input, photo_recommendations): | |
| try: | |
| html_result = generate_blog_post(category, style, references1, references2, references3, outline_input, photo_recommendations) | |
| return html_result, "๋ธ๋ก๊ทธ ๊ธ ์์ฑ ์๋ฃ" | |
| except Exception as e: | |
| return f"<p>๊ธ ์์ฑ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}</p>", f"์ค๋ฅ ๋ฐ์: {str(e)}" | |
| generate_btn.click( | |
| fn=generate_blog_post_with_status, | |
| inputs=[category, style, references1, references2, references3, outline_input, photo_recommendations], | |
| outputs=[output_text, status_msg] | |
| ) | |
| # CSS ์คํ์ผ ์ถ๊ฐ | |
| gr.HTML(""" | |
| <style> | |
| #step-title { | |
| font-weight: bold; | |
| color: #2c3e50; | |
| margin-top: 20px; | |
| margin-bottom: 10px; | |
| } | |
| .gradio-button { | |
| background-color: #3498db; | |
| color: white; | |
| border: none; | |
| padding: 10px 20px; | |
| text-align: center; | |
| text-decoration: none; | |
| display: inline-block; | |
| font-size: 16px; | |
| margin: 4px 2px; | |
| cursor: pointer; | |
| border-radius: 5px; | |
| } | |
| .gradio-button:hover { | |
| background-color: #2980b9; | |
| } | |
| </style> | |
| """) | |
| demo.queue() # ๋งค๊ฐ๋ณ์ ์์ด ํธ์ถ | |
| demo.launch(show_error=True) | |