Spaces:
Running
Running
import gradio as gr | |
import random | |
import os | |
import re | |
import openai | |
import textwrap | |
from fpdf import FPDF | |
from datetime import datetime | |
from zoneinfo import ZoneInfo | |
from sklearn.feature_extraction.text import CountVectorizer | |
from weasyprint import HTML, CSS | |
from weasyprint.fonts import FontConfiguration | |
import tempfile | |
from bs4 import BeautifulSoup | |
# OpenAI API ํด๋ผ์ด์ธํธ ์ค์ | |
openai.api_key = os.getenv("OPENAI_API_KEY") | |
def call_api(content, system_message, max_tokens, temperature, top_p, previous_messages=None): | |
try: | |
if previous_messages is None: | |
previous_messages = [] | |
messages = [] | |
if system_message: | |
messages.append({"role": "system", "content": system_message}) | |
messages.extend(previous_messages) | |
messages.append({"role": "user", "content": content}) | |
response = openai.ChatCompletion.create( | |
model="gpt-4o-mini", | |
messages=messages, | |
max_tokens=max_tokens, | |
temperature=temperature, | |
top_p=top_p, | |
request_timeout=50 | |
) | |
return response.choices[0].message['content'] | |
except Exception as e: | |
print(f"API ํธ์ถ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}") | |
raise | |
def analyze_info(data): | |
return f"์ ํํ ์นดํ ๊ณ ๋ฆฌ: {data['category']}\n์ ํํ ํฌ์คํ ์คํ์ผ: {data['style']}\n์ฐธ๊ณ ๊ธ1: {data['references1']}\n์ฐธ๊ณ ๊ธ2: {data['references2']}\n์ฐธ๊ณ ๊ธ3: {data['references3']}" | |
def suggest_title(category, style, references1, references2, references3): | |
data = { | |
'category': category, | |
'style': style, | |
'references1': references1, | |
'references2': references2, | |
'references3': references3 | |
} | |
full_content = analyze_info(data) | |
system_prompt = get_title_prompt(data['category']) + "\n\n" + get_style_prompt(data['style']) | |
modified_text = call_api(full_content, system_prompt, 1500, 0.75, 0.95) | |
return modified_text | |
def generate_outline(category, style, references1, references2, references3, title): | |
data = { | |
'category': category, | |
'style': style, | |
'references1': references1, | |
'references2': references2, | |
'references3': references3, | |
'title': title | |
} | |
full_content = analyze_info(data) | |
content = f"{full_content}\nTitle: {data['title']}" | |
system_prompt = get_outline_prompt(data['category']) + "\n\n" + get_style_prompt(data['style']) | |
modified_text = call_api(content, system_prompt, 2000, 0.7, 0.95) | |
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 extract_keywords(text, top_n=5): | |
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_group_instruction(group_index): | |
instructions = [ | |
""" | |
**์ ์ฒด ์ฝํ ์ธ ๋ฅผ ์์ฑํ๊ธฐ ์ํ ์์๋ผ์ธ ์น์ ์ ์ผ๋ถ์ด๋ค.** | |
1. ์ฃผ์ด์ง ์์๋ผ์ธ 1๊ทธ๋ฃน์ ์ฒซ๋ฒ์งธ์ค์ ๋์ ๋ถ์ด๋ค. | |
2. ๋ฐ๋์ ๋์ ๋ถ์ ๋ํด์๋ง ๊ฐ๋ตํ๊ฒ ์์ฑํ๋ผ. | |
3. ๋์ ๋ถ์์๋ ์ฃผ์ ๋ฅผ ์๊ฐํ๊ณ , ๋ ์์ ๊ด์ฌ์ ๋์ด์ผ ํ๋ค(๋ฐ๋์ 200์ ์ด๋ด๋ก ์์ฑ) | |
4. ์ฃผ์ด์ง ์์๋ผ์ธ 1๊ทธ๋ฃน์ ๋๋ฒ์งธ์ค์ ๋ณธ๋ฌธ1 ์ด๋ค. | |
5. ๋ฐ๋์ ๋ณธ๋ฌธ1๋ก์๋ง ์์ฑํ๋ผ. | |
6. ๋ฐ๋์ ๋ค์ ์น์ ์ผ๋ก์ ์ ํ์ ์ผ๋์ ๋๊ณ ์์ฑํ๋, ํ์ฌ ์น์ ์ ์์ ํ ๋ง๋ฌด๋ฆฌํ์ง ๋ง ๊ฒ. | |
7. ๋ณธ๋ฌธ1 ์ฃผ์ ์ ๋ด์ฉ์ ์์ธ ๋ด์ ์ฝ 190๋จ์ด๋ก ์์ฑํ๋ผ. | |
""", | |
""" | |
**์ ์ฒด ์ฝํ ์ธ ๋ฅผ ์์ฑํ๊ธฐ ์ํ ์์๋ผ์ธ ์น์ ์ ์ผ๋ถ์ด๋ค.** | |
1. ์ฃผ์ด์ง ์์๋ผ์ธ 2๊ทธ๋ฃน์ ๋ชจ๋ ๋ณธ๋ก (๋ณธ๋ก 2~4)์ด๋ค. | |
2. ๋ฐ๋์ ๋ณธ๋ก ์ ํํ๋ก๋ง ๋ด์ฉ๊ณผ ์ ๋ณด๋ฅผ ๋งค์ฐ ์์ธํ๊ฒ ์์ฑํ๋ผ. | |
3. ์ด์ ์น์ ์์ ์ ์๋ ๋ด์ฉ๊ณผ ์์ฐ์ค๋ฝ๊ฒ ์ฐ๊ฒฐ๋๊ฒ ํ๋ฆ์ ์ ์งํ๋ผ. | |
4. ๋ฐ๋์ ๊ฒฐ๋ก ์ผ๋ก ๋์ด๊ฐ์ง ์๋๋ก ์ฃผ์ํ๋ผ. | |
5. ๋ฐ๋์ ๊ฐ ์น์ ๋ณ ์ฃผ์ ์ ๋ง๋ ๋ด์ฉ์ผ๋ก๋ก ์ฝ 280~330๋จ์ด๋ก ์์ฑํ๋ผ. | |
""", | |
""" | |
**์ ์ฒด ์ฝํ ์ธ ๋ฅผ ์์ฑํ๊ธฐ ์ํ ์์๋ผ์ธ ์น์ ์ ์ผ๋ถ์ด๋ค.** | |
1. ์ฃผ์ด์ง ์์๋ผ์ธ 3๊ทธ๋ฃน์ ์ฒซ๋ฒ์งธ์ค์ ๋ณธ๋ก 5(๋ง์ง๋ง ๋ณธ๋ก )์ด๋ค. | |
2. ๋ฐ๋์ ๋ณธ๋ก ์ ํํ๋ก๋ง ์์ฑํ๋ผ. | |
3. ๋ณธ๋ก ์ ๋ฐ๋์ 190๋จ์ด ์ดํ๋ก ์์ฑํ๋ผ. | |
4. ์ฃผ์ด์ง ์์๋ผ์ธ 3๊ทธ๋ฃน์ ๋๋ฒ์งธ์ค์ ์ ์ฒด ์ฝํ ์ธ ์ ๊ฒฐ๋ก ๋ถ์ด๋ค. | |
5. ๋ฐ๋์ ๊ฒฐ๋ก ์ ํํ๋ก๋ง ์์ฑํ๋ผ(์ธ์ฌ๋ง ๊ธ์ง) | |
6. ๋ฐ๋์ ๊ฒฐ๋ก ์์๋ ์ ์ฒด ๋ด์ฉ์ ์์ฝํ๊ณ ์ต์ข ๋ฉ์์ง๋ฅผ ์ ๋ฌํ๋ผ. | |
7. ๊ฒฐ๋ก ์ 200์ ์ด๋ด๋ก ์์ฑํ๋ผ. | |
""" | |
] | |
return instructions[group_index] | |
def generate_blog_post(category, style, references1, references2, references3, title, outline): | |
try: | |
data = { | |
'category': category, | |
'style': style, | |
'references1': references1, | |
'references2': references2, | |
'references3': references3, | |
'title': title, | |
'outline': outline | |
} | |
system_prompt = get_blog_post_prompt(data['category']) | |
style_prompt = get_style_prompt(data['style']) | |
outline_sections = data['outline'].split('\n') | |
grouped_sections = [ | |
outline_sections[:2], # ๋์ ๋ถ + ๋ณธ๋ฌธ1 | |
outline_sections[2:5], # ๋ณธ๋ฌธ2 + ๋ณธ๋ฌธ3 + ๋ณธ๋ฌธ4 | |
outline_sections[5:] # ๋ณธ๋ฌธ5 + ๊ฒฐ๋ก | |
] | |
sections = [] | |
previous_content = "" | |
previous_messages = [] | |
for i, section_group in enumerate(grouped_sections): | |
print(f"์น์ ๊ทธ๋ฃน {i+1}/{len(grouped_sections)} ์์ฑ ์ค...") | |
max_tokens = [1000, 5000, 1000][i] | |
group_instruction = get_group_instruction(i) | |
user_prompt = f""" | |
์นดํ ๊ณ ๋ฆฌ: {data['category']} | |
ํฌ์คํ ์คํ์ผ: {data['style']} | |
์ฐธ๊ณ ๊ธ1: {data['references1']} | |
์ฐธ๊ณ ๊ธ2: {data['references2']} | |
์ฐธ๊ณ ๊ธ3: {data['references3']} | |
ํ์ฌ ์น์ ๊ทธ๋ฃน: {' / '.join(section_group)} | |
์ด์ ์น์ ์ ๋ง์ง๋ง ๋ด์ฉ: {previous_content} | |
์์ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก '{' / '.join(section_group)}' ์น์ ๊ทธ๋ฃน์ ๋ด์ฉ์ ์์ฑํ๋, ๋ค์ ์ง์นจ์ ๋ฐ๋์ ์ค์ํ๋ผ: | |
1. {group_instruction} | |
2. ์ ์ฒด ์์๋ผ์ธ์ ํ๋ฆ์ ๊ณ ๋ คํ์ฌ ์ผ๊ด์ฑ ์๊ฒ ์์ฑ. | |
3. ๋ฐ๋์ ์ฐธ๊ณ ๊ธ์ ๋ด์ฉ์ ๋ฐํ์ผ๋ก ๊ตฌ์ฑํ๋, ํํ์ ๊ทธ๋๋ก ๋ณต์ฌํ์ง ๋ง ๊ฒ. | |
4. ๊ฐ ์น์ ์ ์ฃผ์ ๋ด์ฉ์ ์ถฉ๋ถํ ๋ค๋ฃจ๋, ์ ์ฒด ๊ธ์ ํ๋ฆ์ ํด์น์ง ์๋๋ก ์ฃผ์. | |
5. ์ด์ ์น์ ๊ณผ์ ์ฐ๊ฒฐ๋ถ๋ถ์ ์์ฐ์ค๋ฝ๊ฒ ์ด์ด์ง๋๋ก ์์ฑ. | |
6. ๊ฐ ์น์ ์ ์ ๋ชฉ์ ์์ฑํ๋ผ. | |
""" | |
try: | |
section_content = call_api( | |
user_prompt, | |
system_prompt + "\n" + style_prompt, | |
max_tokens, | |
0.7, | |
0.95, | |
previous_messages=previous_messages | |
) | |
sections.append(section_content) | |
lines = section_content.splitlines() | |
previous_content = "\n".join(lines[-2:]) | |
previous_messages.append({"role": "user", "content": user_prompt}) | |
previous_messages.append({"role": "assistant", "content": section_content}) | |
except Exception as e: | |
print(f"์น์ ๊ทธ๋ฃน {i+1} ์์ฑ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}") | |
sections.append(f"์น์ ๊ทธ๋ฃน {i+1} ์์ฑ ์ค ์ค๋ฅ ๋ฐ์") | |
full_post = data['title'] + "\n\n" + "\n\n".join(sections) | |
print(f"GPT๊ฐ ์์ฑํ ์๋ณธ ๋ธ๋ก๊ทธ ๊ธ:\n{full_post}") | |
filtered_post = remove_unwanted_phrases(full_post) | |
filtered_post = filtered_post.lstrip() | |
# HTML๋ก ๋ณํ | |
html_post = convert_to_html(filtered_post) | |
return html_post | |
except Exception as e: | |
print(f"๋ธ๋ก๊ทธ ํฌ์คํธ ์์ฑ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}") | |
import traceback | |
traceback.print_exc() | |
return "" | |
def convert_to_html(text): | |
soup = BeautifulSoup('<div class="blog-post"></div>', 'html.parser') | |
main_div = soup.find('div', class_='blog-post') | |
lines = text.split('\n') | |
for line in lines: | |
line = line.strip() | |
if line.startswith('# '): | |
main_div.append(soup.new_tag('h1')) | |
main_div.h1.string = line[2:] | |
elif line.startswith('## '): | |
main_div.append(soup.new_tag('h2')) | |
main_div.h2.string = line[3:] | |
elif line.startswith('### '): | |
main_div.append(soup.new_tag('h3')) | |
main_div.h3.string = line[4:] | |
elif line.startswith('- '): | |
if not main_div.find_all('ul'): | |
main_div.append(soup.new_tag('ul')) | |
li = soup.new_tag('li') | |
li.string = line[2:] | |
main_div.ul.append(li) | |
else: | |
p = soup.new_tag('p') | |
p.string = line | |
main_div.append(p) | |
return str(soup) | |
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 get_title_prompt(category): | |
if (category == "์ผ๋ฐ"): | |
return """ | |
์ ๋ชฉ ์ถ์ฒ์ ์ฌ์ฉํ์ง ์์ต๋๋ค. | |
""" | |
elif (category == "์ํ๊ฑด๊ฐ"): | |
return """ | |
์ ๋ชฉ ์ถ์ฒ์ ์ฌ์ฉํ์ง ์์ต๋๋ค. | |
""" | |
def get_outline_prompt(category): | |
if (category == "์ผ๋ฐ"): | |
return """ | |
[์ํ๋ฆฌ๋ทฐ ์์ฃผ์ (Outline) ์์ฑ ๊ท์น] | |
[๊ธฐ๋ณธ๊ท์น] | |
1. ๋ฐ๋์ ํ๊ตญ์ด(ํ๊ธ)๋ก ์์ฑํ๋ผ | |
2. ๋๋ ๊ฐ์ฅ ์ฃผ๋ชฉ๋ฐ๋ ์ ๋ฌธ ๋ธ๋ก๊ฑฐ ๋ง์ผํฐ์ด๋ค. | |
3. ๋ง์ผํฐ๋ก์ ์ ๋ณด์ ๊ณต๊ณผ ๋ง์ผํ ์ ์ด์ ์ ๋ง์ถฐ ์์ฑํ๋ผ. | |
5. ๋ฐ๋์ ๋งํฌ๋ค์ด ํ์์ด ์๋ ์์ํ ํ ์คํธ๋ก ์ถ๋ ฅํ๋ผ | |
[์์๋ผ์ธ ์์ฑ ๊ท์น] | |
1. ๋ธ๋ก๊ทธ ๊ธ์ ์์ฑํ๊ธฐ ์ํ ์์ฃผ์ (์น์ )๋ง์ ์์ฑํ๋ผ | |
2. ๋ฐ๋์ ์ ๋ ฅ๋ ์ฐธ๊ณ ๊ธ๊ณผ ๋ธ๋ก๊ทธ ์ฃผ์ , ์ ๋ชฉ์ ๋ฐํ์ผ๋ก ํต์ฌ ์ฃผ์ ๋ฅผ ํ์ ํ์ฌ ์์ฃผ์ (์น์ )๋ฅผ ๊ตฌ์ฑํ๋ผ | |
3. ์ ์ฒด ๋งฅ๋ฝ์ ๋ง๊ฒ ์์ฃผ์ (์น์ )๋ฅผ ์์ฑ | |
4. ๋ฐ๋์ ์์ ๋ชฉ์ผ๋ก ์ฌ์ฉํ ์ ์๋๋ก 30์ ์ด๋ด๋ก ์์ฑํ๋ผ | |
5. ์ฐธ๊ณ ๊ธ์ ๋ถ์ํ์ฌ ๋ ์๊ฐ ์ป๊ณ ์ ํ๋ ํฅ๋ฏธ๋ก์ด ์ ๋ณด, ๋์์ด ๋๋ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋๋ก ์์ฃผ์ ๋ฅผ ์์ฑํ๋ผ. | |
6. ๋ฐ๋์ [์์ฃผ์ ๊ตฌ์ฑ]์ ๋ง๊ฒ ์์ฃผ์ ๋ง ์ถ๋ ฅํ๋ผ | |
[์์๋ผ์ธ ๊ตฌ์ฑ] | |
1. ๋ฐ๋์ [๋์ ๋ถ]-1๊ฐ, [๋ณธ๋ก ]-5๊ฐ, [๊ฒฐ๋ก ]-1๊ฐ๋ก ๊ตฌ์ฑํ์ฌ ์ถ๋ ฅํ๋ผ | |
2. ๋ฐ๋์ [๋์ ๋ถ]์ [๊ฒฐ๋ก ]์ ์ ๋ชฉ์ด ์ค๋ณต๋์ง ์๋๋ก ์์ฑํ๋ผ | |
์ถ๋ ฅ์์: | |
- ๋์ ๋ถ: ์ ๋ชฉ | |
- ๋ณธ๋ก 1: ์ ๋ชฉ | |
... | |
- ๋ณธ๋ก 5: ์ ๋ชฉ | |
- ๊ฒฐ๋ก : ์ ๋ชฉ | |
""" | |
elif (category == "์ํ๊ฑด๊ฐ"): | |
return """ | |
[์ํ๋ฆฌ๋ทฐ ์์ฃผ์ (Outline) ์์ฑ ๊ท์น] | |
[๊ธฐ๋ณธ๊ท์น] | |
1. ๋ฐ๋์ ํ๊ตญ์ด(ํ๊ธ)๋ก ์์ฑํ๋ผ | |
2. ๋๋ ๊ฐ์ฅ ์ฃผ๋ชฉ๋ฐ๋ '์ํ๊ฑด๊ฐ' ์ ๋ฌธ ๋ธ๋ก๊ฑฐ ๋ง์ผํฐ์ด๋ค. | |
3. ๋ฐ๋์ ์ํ๊ฑด๊ฐ ์ธก๋ฉด์์ ์ค์ฉ์ ์ธ ์ ๋ณด ์ ๊ณต์ ์ด์ ์ ๋ง์ถฐ ์์ฑํ๋ผ. | |
4. ๋ฐ๋์ ๋งํฌ๋ค์ด ํ์์ด ์๋ ์์ํ ํ ์คํธ๋ก ์ถ๋ ฅํ๋ผ | |
[์์๋ผ์ธ ์์ฑ ๊ท์น] | |
1. ๋ธ๋ก๊ทธ ๊ธ์ ์์ฑํ๊ธฐ ์ํ ์์ฃผ์ (์น์ )๋ง์ ์์ฑํ๋ผ | |
2. ๋ฐ๋์ ์ ๋ ฅ๋ ์ฐธ๊ณ ๊ธ๊ณผ ๋ธ๋ก๊ทธ ์ฃผ์ , ์ ๋ชฉ์ ๋ฐํ์ผ๋ก ํต์ฌ ์ฃผ์ ๋ฅผ ํ์ ํ์ฌ ์์ฃผ์ (์น์ )๋ฅผ ๊ตฌ์ฑํ๋ผ | |
3. ์ ์ฒด ๋งฅ๋ฝ์ ๋ง๊ฒ ์์ฃผ์ (์น์ )๋ฅผ ์์ฑ | |
4. ๋ฐ๋์ ์์ ๋ชฉ์ผ๋ก ์ฌ์ฉํ ์ ์๋๋ก 30์ ์ด๋ด๋ก ์์ฑํ๋ผ | |
5. ์ฐธ๊ณ ๊ธ์ ๋ถ์ํ์ฌ ๋ ์๊ฐ ์ป๊ณ ์ ํ๋ ์ํ์ ๊ธฐ๋ฅ ์ค์์ ํฅ๋ฏธ๋กญ๊ณ ์ค์ฉ์ ์ธ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋๋ก ์์ฃผ์ ๋ฅผ ์์ฑํ๋ผ. | |
6. ํ์ํ ๊ฒฝ์ฐ ์ฐ๊ตฌ ๊ฒฐ๊ณผ๋ ํต๊ณ๋ฑ์ ์ ์ ํ ํ์ฉํ๋ผ | |
7. ๊ฐ์ธ์ ๊ฒฝํ์ด๋ ์ฌ๋ก๋ฅผ ์ ์ ํ ํ์ฉํ๋ผ | |
8. ๋ฌธ์ ์ ๋ํ ์์ธ, ์ฆ์, ์๋ฐฉ ๋๋ ์น๋ฃ ๋ฐฉ๋ฒ์ ๋ํ ์ค์ฉ์ ์ธ ์ ๋ณด๋ฅผ ํฌํจํ๋ผ | |
9. ์ ๋ฌธ์ ์ธ ์ฉ์ด๋ ์ ์ ํ ์ค๋ช ๊ณผ ์ฌ์ด ์ดํ๋ก ๋ณด์ถฉํ๋ผ | |
10. ๋ฐ๋์ [์์ฃผ์ ๊ตฌ์ฑ]์ ๋ง๊ฒ ์์ฃผ์ ๋ง ์ถ๋ ฅํ๋ผ | |
[์์๋ผ์ธ ๊ตฌ์ฑ] | |
1. ๋ฐ๋์ [๋์ ๋ถ]-1๊ฐ, [๋ณธ๋ก ]-5๊ฐ, [๊ฒฐ๋ก ]-1๊ฐ๋ก ๊ตฌ์ฑํ์ฌ ์ถ๋ ฅํ๋ผ | |
2. ๋ฐ๋์ [๋์ ๋ถ]์ [๊ฒฐ๋ก ]์ ์ ๋ชฉ์ด ์ค๋ณต๋์ง ์๋๋ก ์์ฑํ๋ผ | |
์ถ๋ ฅ์์: | |
- ๋์ ๋ถ: ์ ๋ชฉ | |
- ๋ณธ๋ก 1: ์ ๋ชฉ | |
... | |
- ๋ณธ๋ก 5: ์ ๋ชฉ | |
- ๊ฒฐ๋ก : ์ ๋ชฉ | |
""" | |
def get_blog_post_prompt(category): | |
if (category == "์ผ๋ฐ"): | |
return """ | |
[์ํ๋ฆฌ๋ทฐ ์ฝํ ์ธ ์์ฑ ๊ท์น] | |
[๊ธฐ๋ณธ๊ท์น] | |
1. ๋ฐ๋์ ํ๊ตญ์ด(ํ๊ธ)๋ก ์์ฑํ๋ผ | |
2. ๋๋ ์ ๋ฌธ์ ์ธ ์ฝํ ์ธ ์๊ฐ์ด๋ค. ์ฃผ์ด์ง ์ฃผ์ ์ ๋ํด ํ๋ถํ๊ณ ๋งค๋ ฅ์ ์ธ ๋ด์ฉ์ ์์ฑํ๋ผ | |
3. ๊ฐ ์น์ ์ ๋ ๋ฆฝ์ ์ธ ์ ๋ณด ๋จ์๋ก ์ทจ๊ธํ๋ผ | |
4. ๋ค๋ฅธ ์น์ ๊ณผ์ ์ฐ๊ฒฐ์ฑ์ ๊ณ ๋ คํ๋, ๊ฐ ์น์ ์ด ๋ ๋ฆฝ์ ์ผ๋ก๋ ์ดํด๋ ์ ์๊ฒ ์์ฑํ๋ผ | |
5. ์ด ์น์ ์ ๋ ํฐ ์ฝํ ์ธ ์ ์ผ๋ถ์์ ๋ช ์ฌํ๋ผ, ์ ์ฒด์ ์ธ ํ๋ฆ์ ํด์น์ง ์์ผ๋ฉด์ ์ฃผ์ด์ง ์ฃผ์ ๋ฅผ ์ฒ ์ ํ ์์ฑํ๋ผ | |
[ํ ์คํธ ์์ฑ ๊ท์น] | |
1. ๋ฐ๋์ ์ ๋ ฅ๋ ์์ฃผ์ (์์๋ผ์ธ)์ ๋ง๊ฒ ๊ธ์ ์์ฑํ๋ผ | |
2. ๋ฐ๋์ ์ ๋ ฅ๋ ์ฐธ๊ณ ๊ธ์ ๋ด์ฉ์ผ๋ก๋ง ๊ตฌ์ฑ | |
3. ์ ์ฒด ๋งฅ๋ฝ์ ์ดํดํ๊ณ ๋ฌธ์ฅ์ ์ผ๊ด์ฑ์ ์ ์งํ๋ผ | |
4. ์ ๊ณต๋ ์ฐธ๊ณ ๊ธ์ ์ดํฌ๋ฅผ ๋ฐ์ํ๋, ์ ๋๋ก ํ ๋ฌธ์ฅ ์ด์ ๊ทธ๋๋ก ์ถ๋ ฅํ์ง ๋ง ๊ฒ | |
5. ์ฝ๊ฒ ์ฝ์ ์ ์๋๋ก ์ฌ์ด ์ดํ๋ก ์์ฑ | |
6. ์ฐธ๊ณ ๊ธ์ ๊ธฐ๋ฐ์ผ๋ก ๊ธ์ ์ฃผ์ ์ ์ ์ฉํ ์ ๋ณด๋ฅผ ํ์ ํ์ฌ ์์ฑ | |
7. ๋ ์์๊ฒ ๋์์ด๋๊ณ ์ด๋์ด ๋๋ ์ ๋ณด๋ฅผ ์์ฑ | |
8. ๋ ์์ ๊ณต๊ฐ์ ์ป๊ณ ๊ถ๊ธ์ฆ์ ํด๊ฒฐํ๋๋ก ์์ฑ | |
""" | |
elif (category == "์ํ๊ฑด๊ฐ"): | |
return """ | |
[์ํ๋ฆฌ๋ทฐ ์ฝํ ์ธ ์์ฑ ๊ท์น] | |
[๊ธฐ๋ณธ๊ท์น] | |
1. ๋ฐ๋์ ํ๊ตญ์ด(ํ๊ธ)๋ก ์์ฑํ๋ผ | |
2. ๋๋ ์ ๋ฌธ์ ์ธ ์ํ๊ฑด๊ฐ ์ฝํ ์ธ ์๊ฐ์ด๋ค. ์ฃผ์ด์ง ์ฃผ์ ์ ๋ํด ํ๋ถํ๊ณ ๋งค๋ ฅ์ ์ธ ๋ด์ฉ์ ์์ฑํ๋ผ | |
3. ๊ฐ ์น์ ์ ๋ ๋ฆฝ์ ์ธ ์ ๋ณด ๋จ์๋ก ์ทจ๊ธํ๋ผ | |
4. ๋ค๋ฅธ ์น์ ๊ณผ์ ์ฐ๊ฒฐ์ฑ์ ๊ณ ๋ คํ๋, ๊ฐ ์น์ ์ด ๋ ๋ฆฝ์ ์ผ๋ก๋ ์ดํด๋ ์ ์๊ฒ ์์ฑํ๋ผ | |
5. ์ด ์น์ ์ ๋ ํฐ ์ฝํ ์ธ ์ ์ผ๋ถ์์ ๋ช ์ฌํ๋ผ, ์ ์ฒด์ ์ธ ํ๋ฆ์ ํด์น์ง ์์ผ๋ฉด์ ์ฃผ์ด์ง ์ฃผ์ ๋ฅผ ์ฒ ์ ํ ์์ฑํ๋ผ๋ผ | |
6. ๋ฐ๋์ ์ํ๊ฑด๊ฐ ๊ด๋ จ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋๋ก ์์ฑ | |
[ํ ์คํธ ์์ฑ ๊ท์น] | |
1. ๋ฐ๋์ ์ ๋ ฅ๋ ์์ฃผ์ (์์๋ผ์ธ)์ ๋ง๊ฒ ๊ธ์ ์์ฑํ๋ผ | |
2. ๋ฐ๋์ ์ ๋ ฅ๋ ์ฐธ๊ณ ๊ธ์ ๋ด์ฉ์ผ๋ก๋ง ๊ตฌ์ฑ | |
3. ์ ์ฒด ๋งฅ๋ฝ์ ์ดํดํ๊ณ ๋ฌธ์ฅ์ ์ผ๊ด์ฑ์ ์ ์งํ๋ผ | |
4. ์ ๊ณต๋ ์ฐธ๊ณ ๊ธ์ ์ดํฌ๋ฅผ ๋ฐ์ํ๋, ์ ๋๋ก ํ ๋ฌธ์ฅ ์ด์ ๊ทธ๋๋ก ์ถ๋ ฅํ์ง ๋ง ๊ฒ | |
5. ์ฝ๊ฒ ์ฝ์ ์ ์๋๋ก ์ฌ์ด ์ดํ๋ก ์์ฑ | |
6. ๊ฐ์ธ์ ๊ฒฝํ์ด๋ ์ฌ๋ก๋ฅผ ์ ์ ํ ํ์ฉํ๋ผ | |
7. ๋ฌธ์ ์ ๋ํ ์์ธ, ์ฆ์, ์๋ฐฉ ๋๋ ์น๋ฃ ๋ฐฉ๋ฒ์ ๋ํ ์ค์ฉ์ ์ธ ์ ๋ณด๋ฅผ ํฌํจํ๋ผ | |
8. ์ ๋ฌธ์ ์ธ ์ฉ์ด๋ ์ ์ ํ ์ค๋ช ๊ณผ ์ฌ์ด ์ดํ๋ก ๋ณด์ถฉํ๋ผ(ํ์์ ์ถ์ฒ๋ฅผ ํ๊ธฐํ๋ผ) | |
""" | |
def get_style_prompt(style): | |
prompts = { | |
"์น๊ทผํ": """ | |
[์น๊ทผํ ํฌ์คํ ์คํ์ผ ๊ฐ์ด๋] | |
1. ํค๊ณผ ์ด์กฐ | |
- ๋ํํ๋ฏ ํธ์ํ๊ณ ์น๊ทผํ ๋งํฌ ์ฌ์ฉ | |
2. ๋ฌธ์ฅ ๋ฐ ์ดํฌ | |
- ๋ฐ๋์ 'ํด์์ฒด'๋ก ์์ฑ, ์ ๋ '์ต๋๋ค'์ฒด๋ฅผ ์ฌ์ฉํ์ง ๋ง ๊ฒ. | |
- '~์'๋ก ๋๋๋๋ก ์์ฑ, '~๋ค'๋ก ๋๋์ง ์๊ฒ ํ๋ผ | |
- ๊ตฌ์ด์ฒด ํํ ์ฌ์ฉ (์: "~ํ์ด์", "~์ธ ๊ฒ ๊ฐ์์") | |
3. ์ฉ์ด ๋ฐ ์ค๋ช ๋ฐฉ์ | |
- ์ ๋ฌธ ์ฉ์ด ๋์ ์ฌ์ด ๋จ์ด๋ก ํ์ด์ ์ค๋ช | |
- ๋น์ ๋ ์์ ๋ฅผ ํ์ฉํ์ฌ ๋ณต์กํ ๊ฐ๋ ์ค๋ช | |
- ์์ฌ์๋ฌธ๋ฌธ ํ์ฉํ์ฌ ๋ ์์ ์ํตํ๋ ๋๋ ์ฃผ๊ธฐ | |
์ฃผ์์ฌํญ: ๋๋ฌด ๊ฐ๋ฒผ์ด ํค์ ์ง์ํ๊ณ , ์ฃผ์ ์ ์ค์์ฑ์ ํด์น์ง ์๋ ์ ์์ ์น๊ทผํจ ์ ์ง | |
(์์: ์๋๋ค~ ์ค๋ ์ค ์ฝ์นด์ฝ๋ผ๋ง์ด์๋ก ์ถ์๊ฐ ๋๋ค๋๊ฑฐ ์๊ณ ๊ณ์ จ๋์?!ใ ์ค๋ ์ค ์ฝ์นด์ฝ๋ผ๋ง์ ์ด๋ค์ง ์์งํ๊ณผ๊ตฌ๋งค์ ๋ณด, ๊ฐ๊ฒฉ, ์นผ๋ก๋ฆฌ ๋ฑ์ ๋ํด ์์ธ~ ํ ์ ์ด๋ณด๋๋ก ํ ๊ป์! ์ค๋ ์ค๋ฅผ ์ข์ํ๋ ์๋ค์๊ฒ๊ฐ์์ผ๋ก ์ค๋ ์ค ์ฝ์นด์ฝ๋ผ๋ง์ ์คฌ๋๋๋ง์๋ค๊ณ ์ข์ํ๋๋ผ๊ตฌ์. ์ฝ๋ผํฅ์ด ๋์ ๋ ๋ง์์ ๋ ๋ค๋ฉฐใ ๊ฐ์ธ์ ์ผ๋ก๋ ๋ณ โญ๏ธโญ๏ธโญ๏ธ.์๊ฑด ๊ฐ์ธ์ฐจ๊ฐ ์์๊ฑฐ ๊ฐ์์~) | |
""", | |
"์ผ๋ฐ": """ | |
#์ผ๋ฐ์ ์ธ ๋ธ๋ก๊ทธ ํฌ์คํ ์คํ์ผ ๊ฐ์ด๋ | |
1. ํค๊ณผ ์ด์กฐ | |
- ์ค๋ฆฝ์ ์ด๊ณ ๊ฐ๊ด์ ์ธ ํค ์ ์ง | |
- ์ ์ ํ ์กด๋๋ง ์ฌ์ฉ (์: "~ํฉ๋๋ค", "~์ ๋๋ค") | |
2. ๋ด์ฉ ๊ตฌ์กฐ ๋ฐ ์ ๊ฐ | |
- ๋ช ํํ ์ฃผ์ ์ ์๋ก ์์ | |
- ๋ ผ๋ฆฌ์ ์ธ ์์๋ก ์ ๋ณด ์ ๊ฐ | |
- ์ฃผ์ ํฌ์ธํธ๋ฅผ ๊ฐ์กฐํ๋ ์์ ๋ชฉ ํ์ฉ | |
- ์ ์ ํ ๊ธธ์ด์ ๋จ๋ฝ์ผ๋ก ๊ตฌ์ฑ | |
3. ์ฉ์ด ๋ฐ ์ค๋ช ๋ฐฉ์ | |
- ์ผ๋ฐ์ ์ผ๋ก ์ดํดํ๊ธฐ ์ฌ์ด ์ฉ์ด ์ ํ | |
- ํ์์ ๊ฐ๋จํ ์ค๋ช ์ถ๊ฐ | |
- ๊ฐ๊ด์ ์ธ ์ ๋ณด ์ ๊ณต์ ์ค์ | |
4. ํ ์คํธ ๊ตฌ์กฐํ | |
- ๋ถ๋ฆฟ ํฌ์ธํธ๋ ๋ฒํธ ๋งค๊ธฐ๊ธฐ๋ฅผ ํ์ฉํ์ฌ ์ ๋ณด ๊ตฌ์กฐํ | |
- ์ค์ํ ์ ๋ณด๋ ๊ตต์ ๊ธ์จ๋ ๊ธฐ์ธ์๊ผด๋ก ๊ฐ์กฐ | |
5. ๋ ์ ์ํธ์์ฉ | |
- ์ ์ ํ ๋ ์์ ์๊ฐ์ ๋ฌป๋ ์ง๋ฌธ ํฌํจ | |
- ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ฐพ์ ์ ์๋ ํค์๋ ์ ์ | |
6. ๋ง๋ฌด๋ฆฌ | |
- ์ฃผ์ ๋ด์ฉ ๊ฐ๋จํ ์์ฝ | |
- ์ถ๊ฐ ์ ๋ณด์ ๋ํ ์๋ด ์ ๊ณต | |
์ฃผ์์ฌํญ: ๋๋ฌด ๋ฑ๋ฑํ๊ฑฐ๋ ์ง๋ฃจํ์ง ์๋๋ก ๊ท ํ ์ ์ง | |
์์: "์ต๊ทผ ํ๊ฒฝ ๋ฌธ์ ๊ฐ ๋๋๋๋ฉด์ '์ ๋ก ์จ์ด์คํธ' ๋ผ์ดํ์คํ์ผ์ ๋ํ ๊ด์ฌ์ด ๋์์ง๊ณ ์์ต๋๋ค. ์ ๋ก ์จ์ด์คํธ๋ ์ผ์์ํ์์ ๋ฐ์ํ๋ ์ฐ๋ ๊ธฐ๋ฅผ ์ต์ํํ๋ ์ํ ๋ฐฉ์์ ๋งํฉ๋๋ค. ์ด ๊ธ์์๋ ์ ๋ก ์จ์ด์คํธ์ ๊ฐ๋ , ์ค์ฒ ๋ฐฉ๋ฒ, ๊ทธ๋ฆฌ๊ณ ๊ทธ ํจ๊ณผ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ๋จผ์ ์ ๋ก ์จ์ด์คํธ์ ์ ์๋ถํฐ ์ดํด๋ณด๋ฉด... | |
""", | |
"์ ๋ฌธ์ ์ธ": """ | |
#์ ๋ฌธ์ ์ธ ๋ธ๋ก๊ทธ ํฌ์คํ ์คํ์ผ ๊ฐ์ด๋ | |
1. ํค๊ณผ ๊ตฌ์กฐ | |
- ๊ณต์์ ์ด๊ณ ํ์ ์ ์ธ ํค ์ฌ์ฉ | |
- ๊ฐ๊ด์ ์ด๊ณ ๋ถ์์ ์ธ ์ ๊ทผ ์ ์ง | |
- ๋ช ํํ ์๋ก , ๋ณธ๋ก , ๊ฒฐ๋ก ๊ตฌ์กฐ | |
- ์ฒด๊ณ์ ์ธ ๋ ผ์ ์ ๊ฐ | |
- ์ธ๋ถ ์น์ ์ ์ํ ๋ช ํํ ์์ ๋ชฉ ์ฌ์ฉ | |
2. ๋ด์ฉ ๊ตฌ์ฑ ๋ฐ ์ ๊ฐ | |
- ๋ณต์กํ ๊ฐ๋ ์ ์ ํํ ์ ๋ฌํ ์ ์๋ ๋ฌธ์ฅ ๊ตฌ์กฐ ์ฌ์ฉ | |
- ๋ ผ๋ฆฌ์ ์ฐ๊ฒฐ์ ์ํ ์ ํ์ด ํ์ฉ | |
- ํด๋น ๋ถ์ผ์ ์ ๋ฌธ ์ฉ์ด ์ ๊ทน ํ์ฉ (ํ์์ ๊ฐ๋ตํ ์ค๋ช ์ ๊ณต) | |
- ์ฌ์ธต์ ์ธ ๋ถ์๊ณผ ๋นํ์ ์ฌ๊ณ ์ ๊ฐ | |
- ๋ค์ํ ๊ด์ ์ ์ ๋ฐ ๋น๊ต | |
3. ๋ฐ์ดํฐ ๋ฐ ๊ทผ๊ฑฐ ํ์ฉ | |
- ํต๊ณ, ์ฐ๊ตฌ ๊ฒฐ๊ณผ, ์ ๋ฌธ๊ฐ ์๊ฒฌ ๋ฑ ์ ๋ขฐํ ์ ์๋ ์ถ์ฒ ์ธ์ฉ | |
- ํ์์ ๊ฐ์ฃผ๋ ์ฐธ๊ณ ๋ฌธํ ๋ชฉ๋ก ํฌํจ | |
- ์์น ๋ฐ์ดํฐ๋ ํ ์คํธ๋ก ๋ช ํํ ์ค๋ช | |
4. ํ ์คํธ ๊ตฌ์กฐํ | |
- ๋ ผ๋ฆฌ์ ๊ตฌ์กฐ๋ฅผ ๊ฐ์กฐํ๊ธฐ ์ํด ๋ฒํธ ๋งค๊ธฐ๊ธฐ ์ฌ์ฉ | |
- ํต์ฌ ๊ฐ๋ ์ด๋ ์ฉ์ด๋ ๊ธฐ์ธ์๊ผด๋ก ๊ฐ์กฐ | |
- ๊ธด ์ธ์ฉ๋ฌธ์ ๋ค์ฌ์ฐ๊ธฐ๋ก ๊ตฌ๋ถ | |
5. ๋ง๋ฌด๋ฆฌ | |
- ํต์ฌ ๋ ผ์ ์ฌ๊ฐ์กฐ | |
- ํฅํ ์ฐ๊ตฌ ๋ฐฉํฅ์ด๋ ์ค๋ฌด์ ํจ์ ์ ์ | |
์ฃผ์์ฌํญ: ์ ๋ฌธ์ฑ์ ์ ์งํ๋, ์์ ํ ์ดํดํ๊ธฐ ์ด๋ ค์ด ์์ค์ ์ง์ | |
์์: "๋ณธ ์ฐ๊ตฌ์์๋ ์ธ๊ณต์ง๋ฅ(AI)์ ์ค๋ฆฌ์ ํจ์์ ๋ํด ๊ณ ์ฐฐํ๋ค. ํนํ, ์์จ์ฃผํ ์๋์ฐจ์ ์์ฌ๊ฒฐ์ ์๊ณ ๋ฆฌ์ฆ์์ ๋ฐ์ํ ์ ์๋ ์ค๋ฆฌ์ ๋๋ ๋ง์ ์ด์ ์ ๋ง์ถ๋ค. Bonnefon et al. (2016)์ ์ฐ๊ตฌ์ ๋ฐ๋ฅด๋ฉด, ์์จ์ฃผํ ์ฐจ๋์ ์๊ณ ๋ฆฌ์ฆ์ด ์ง๋ฉดํ ์ ์๋ ์ค๋ฆฌ์ ์ ํ์ ๋ณต์ก์ฑ์ด ์ง์ ๋ ๋ฐ ์๋ค. ๋ณธ๊ณ ์์๋ ์ด๋ฌํ ์ค๋ฆฌ์ ๋๋ ๋ง๋ฅผ ์ธ ๊ฐ์ง ์ฃผ์ ๊ด์ ์์ ๋ถ์ํ๋ค: 1) ๊ณต๋ฆฌ์ฃผ์์ ์ ๊ทผ, 2) ์๋ฌด๋ก ์ ์ ๊ทผ, 3) ๋ ์ค๋ฆฌ์ ์ ๊ทผ. ๊ฐ ์ ๊ทผ๋ฒ์ ์ฅ๋จ์ ์ ๋น๊ต ๋ถ์ํ๊ณ , ์ด๋ฅผ ๋ฐํ์ผ๋ก ์์จ์ฃผํ ์ฐจ๋์ ์ค๋ฆฌ์ ์์ฌ๊ฒฐ์ ํ๋ ์์ํฌ๋ฅผ ์ ์ํ๊ณ ์ ํ๋ค... | |
""" | |
} | |
return prompts.get(style, "ํฌ์คํ ์คํ์ผ ํ๋กฌํํธ") | |
def split_titles(suggested_titles): | |
titles = suggested_titles.split('\n') | |
titles = [re.sub(r'^(1\.|2\.|3\.|4\.|5\.|6\.|7\.|8\.|9\.|10\.|## |# |\* |\*\* |\*\*\*)', '', title.strip()) for title in titles if title.strip()] | |
titles = titles[::-1] # ๋ฆฌ์คํธ๋ฅผ ์ญ์์ผ๋ก ์ ๋ ฌ | |
titles += [""] * (10 - len(titles)) # 10๊ฐ๋ณด๋ค ์ ์ผ๋ฉด ๋น ๋ฌธ์์ด๋ก ์ฑ์ฐ๊ธฐ | |
return titles[:10] # ์ต๋ 10๊ฐ์ ์ ๋ชฉ๋ง ๋ฐํ | |
class PDF(FPDF): | |
def __init__(self): | |
super().__init__(orientation='P', unit='mm', format='A4') | |
self.set_margins(10, 10, 10) | |
current_dir = os.path.dirname(__file__) | |
self.add_font("NanumGothic", "", os.path.join(current_dir, "NanumGothic.ttf")) | |
self.add_font("NanumGothic", "B", os.path.join(current_dir, "NanumGothicBold.ttf")) | |
self.add_font("NanumGothicExtraBold", "", os.path.join(current_dir, "NanumGothicExtraBold.ttf")) | |
self.add_font("NanumGothicLight", "", os.path.join(current_dir, "NanumGothicLight.ttf")) | |
def header(self): | |
self.set_font('NanumGothic', '', 10) | |
# ํค๋ ๋ด์ฉ ์ถ๊ฐ (ํ์ํ ๊ฒฝ์ฐ) | |
def footer(self): | |
self.set_y(-15) | |
self.set_font('NanumGothic', '', 8) | |
self.cell(0, 10, f'Page {self.page_no()}', 0, 0, 'C') | |
def chapter_title(self, title): | |
self.set_font("NanumGothic", 'B', 12) | |
self.cell(0, 6, title, 0, 1, 'L') | |
self.ln(4) | |
def chapter_body(self, body): | |
self.set_font("NanumGothic", '', 11) | |
self.multi_cell(0, 5, body) | |
self.ln() | |
def print_chapter(self, title, body): | |
self.add_page() | |
self.chapter_title(title) | |
self.chapter_body(body) | |
def format_filename(text): | |
if not isinstance(text, str): | |
text = str(text) # ๋ฌธ์์ด์ด ์๋ ๊ฒฝ์ฐ ๋ฌธ์์ด๋ก ๋ณํ | |
text = re.sub(r'[^\w\s-]', '', text) | |
return text[:50].strip() | |
def save_to_pdf(blog_post, user_topic): | |
try: | |
# ์์ HTML ํ์ผ ์์ฑ | |
with tempfile.NamedTemporaryFile(mode='w', suffix='.html', delete=False) as temp_html: | |
temp_html.write(blog_post) | |
temp_html_path = temp_html.name | |
# CSS ์ค์ | |
font_config = FontConfiguration() | |
css = CSS(string=''' | |
@import url('https://fonts.googleapis.com/css2?family=Nanum+Gothic:wght@400;700&display=swap'); | |
body { | |
font-family: 'Nanum Gothic', Arial, sans-serif; | |
line-height: 1.6; | |
color: #333; | |
padding: 20px; | |
} | |
h1 { font-size: 24px; margin-bottom: 15px; } | |
h2 { font-size: 20px; margin-bottom: 10px; } | |
h3 { font-size: 18px; margin-bottom: 10px; } | |
p { margin-bottom: 10px; } | |
ul { margin-bottom: 10px; padding-left: 20px; } | |
''', font_config=font_config) | |
# HTML์ PDF๋ก ๋ณํ | |
html = HTML(filename=temp_html_path) | |
pdf_bytes = html.write_pdf(stylesheets=[css], font_config=font_config) | |
# ํ์ผ ์ ์ฅ | |
now = datetime.now(ZoneInfo("Asia/Seoul")) | |
filename = f"{now.strftime('%y%m%d_%H%M')}_{format_filename(user_topic)}.pdf" | |
with open(filename, 'wb') as f: | |
f.write(pdf_bytes) | |
return filename | |
except Exception as e: | |
print(f"PDF ์์ฑ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}") | |
import traceback | |
traceback.print_exc() | |
return None | |
def save_content_to_pdf(blog_post): | |
pdf_filename = save_to_pdf(blog_post, "") | |
if pdf_filename: | |
return pdf_filename | |
else: | |
return None # ์ค๋ฅ ๋ฐ์ ์ None ๋ฐํ | |
title = "์ผ๋ฐ" | |
with gr.Blocks() as demo: | |
gr.Markdown(f"# {title}") | |
gr.Markdown("### 1๋จ๊ณ: ํฌ์คํ ์นดํ ๊ณ ๋ฆฌ๋ฅผ ์ง์ ํด์ฃผ์ธ์", elem_id="step-title") | |
category = gr.Radio(choices=["์ผ๋ฐ", "์ํ๊ฑด๊ฐ"], label="ํฌ์คํ ์นดํ ๊ณ ๋ฆฌ", value="์ผ๋ฐ") | |
gr.Markdown("---\n\n") | |
gr.Markdown("### 2๋จ๊ณ: ํฌ์คํ ์คํ์ผ์ ์ ํํด์ฃผ์ธ์", elem_id="step-title") | |
style = gr.Radio(choices=["์น๊ทผํ", "์ผ๋ฐ", "์ ๋ฌธ์ ์ธ"], label="ํฌ์คํ ์คํ์ผ", value="์น๊ทผํ") | |
gr.Markdown("---\n\n") | |
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("---\n\n") | |
gr.Markdown("### 4๋จ๊ณ: ์ ๋ชฉ ์ถ์ฒํ๊ธฐ", elem_id="step-title") | |
title_suggestions = gr.Textbox(label="์ ๋ชฉ ์ถ์ฒ", lines=10) | |
# 10๊ฐ์ ํ ์คํธ ์ถ๋ ฅ์ฐฝ ์ถ๊ฐ | |
title_outputs = [gr.Textbox(label=f"์ ๋ชฉ {i+1}", lines=1) for i in range(10)] | |
title_btn = gr.Button("์ ๋ชฉ ์ถ์ฒํ๊ธฐ") | |
title_btn.click( | |
fn=suggest_title, | |
inputs=[category, style, references1, references2, references3], | |
outputs=[title_suggestions] | |
) | |
title_suggestions.change( | |
fn=split_titles, | |
inputs=[title_suggestions], | |
outputs=title_outputs | |
) | |
gr.Markdown("---\n\n") | |
gr.Markdown("### 5๋จ๊ณ: ๋ธ๋ก๊ทธ ์ ๋ชฉ์ ์ ๋ ฅํ์ธ์", elem_id="step-title") | |
blog_title = gr.Textbox(label="๋ธ๋ก๊ทธ ์ ๋ชฉ", placeholder="๋ธ๋ก๊ทธ ์ ๋ชฉ์ ์ ๋ ฅํด์ฃผ์ธ์") | |
gr.Markdown("---\n\n") | |
gr.Markdown("### 6๋จ๊ณ: ์์๋ผ์ธ์ ์์ฑํด์ฃผ์ธ์", elem_id="step-title") | |
gr.HTML("<span style='color: grey;'>[์์๋ผ์ธ์์ ๋์จ ๊ฒฐ๊ณผ๋ฅผ ์์ ํด์ ์ฌ์ฉํด์ฃผ์ธ์]</span>") | |
outline_generate_btn = gr.Button("์์๋ผ์ธ ์์ฑํ๊ธฐ") | |
outline_result = gr.Textbox(label="์์๋ผ์ธ ๊ฒฐ๊ณผ", lines=15) | |
outline_input = gr.Textbox(label="์์ฑํ ์์๋ผ์ธ์ ์ ๋ ฅํด์ฃผ์ธ์", placeholder="์์ฑ๋ ์์๋ผ์ธ ๋ณต์ฌ, ์์ ํด์ ์ฌ์ฉํ์ธ์", lines=10) | |
outline_generate_btn.click( | |
fn=generate_outline, | |
inputs=[category, style, references1, references2, references3, blog_title], | |
outputs=[outline_result] | |
) | |
gr.Markdown("---\n\n") | |
gr.Markdown("### 7๋จ๊ณ: ๊ธ ์์ฑํ๊ธฐ", elem_id="step-title") | |
gr.HTML("<span style='color: grey;'>[์์๋ผ์ธ์ ํ์ธํ์ธ์]</span>") | |
generate_btn = gr.Button("๋ธ๋ก๊ทธ ๊ธ ์์ฑํ๊ธฐ") | |
output = gr.HTML(label="์์ฑ๋ ๋ธ๋ก๊ทธ ๊ธ") | |
generate_btn.click( | |
fn=generate_blog_post, | |
inputs=[category, style, references1, references2, references3, blog_title, outline_input], | |
outputs=[output], | |
show_progress=True | |
) | |
save_pdf_btn = gr.Button("PDF๋ก ์ ์ฅํ๊ธฐ") | |
pdf_output = gr.File(label="์์ฑ๋ PDF ํ์ผ") | |
save_pdf_btn.click( | |
fn=save_to_pdf, | |
inputs=[output, blog_title], # blog_title์ user_topic์ผ๋ก ์ฌ์ฉ | |
outputs=[pdf_output], | |
show_progress=True | |
) | |
demo.launch() | |
gr.HTML(""" | |
<style> | |
#step-title { | |
font-size: 1.7em; | |
font-weight: bold; | |
} | |
</style> | |
""") |