Spaces:
Running
Running
import gradio as gr | |
import random | |
import os | |
import re | |
import openai | |
from fpdf import FPDF | |
from datetime import datetime | |
from zoneinfo import ZoneInfo | |
from sklearn.feature_extraction.text import CountVectorizer | |
# OpenAI API ํด๋ผ์ด์ธํธ ์ค์ | |
openai.api_key = os.getenv("OPENAI_API_KEY") | |
def call_api(content, system_message, max_tokens, temperature, top_p): | |
try: | |
messages = [ | |
{"role": "system", "content": system_message}, | |
{"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 generate_outline(category, style, references1, references2, references3): | |
data = { | |
'category': category, | |
'style': style, | |
'references1': references1, | |
'references2': references2, | |
'references3': references3 | |
} | |
full_content = analyze_info(data) | |
system_prompt = get_outline_prompt(data['category']) + "\n\n" + get_style_prompt(data['style']) | |
modified_text = call_api(full_content, system_prompt, 2000, 0.7, 0.95) | |
# ํต์ฌ๊ธฐ๋ฅ์ ๋ถ๋ฆฌํ์ฌ ๋ฆฌ์คํธ๋ก ๋ฐํ | |
features = re.findall(r'ํต์ฌ๊ธฐ๋ฅ : (.+)', modified_text) | |
return features[:3] # ์ต๋ 3๊ฐ์ ํต์ฌ๊ธฐ๋ฅ๋ง ๋ฐํ | |
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 generate_blog_post(category, style, references1, references2, references3, outline): | |
try: | |
data = { | |
'category': category, | |
'style': style, | |
'references1': references1, | |
'references2': references2, | |
'references3': references3, | |
'outline': outline | |
} | |
system_prompt = get_blog_post_prompt(data['category']) | |
style_prompt = get_style_prompt(data['style']) | |
user_prompt = f""" | |
์นดํ ๊ณ ๋ฆฌ: {data['category']} | |
ํฌ์คํ ์คํ์ผ: {data['style']} | |
ํต์ฌ๊ธฐ๋ฅ: {data['outline']} | |
์ฐธ๊ณ ๊ธ1: {data['references1']} | |
์ฐธ๊ณ ๊ธ2: {data['references2']} | |
์ฐธ๊ณ ๊ธ3: {data['references3']} | |
""" | |
blog_content = call_api( | |
user_prompt, | |
system_prompt + "\n" + style_prompt, | |
5000, | |
0.7, | |
0.95 | |
) | |
filtered_post = remove_unwanted_phrases(blog_content) | |
filtered_post = filtered_post.lstrip() | |
html_post = convert_to_html(filtered_post) | |
return html_post | |
except Exception as e: | |
print(f"๊ธ ์์ฑ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}") | |
return "" | |
def convert_to_html(text): | |
lines = text.split('\n') | |
html_lines = [] | |
for line in lines: | |
line = line.strip() | |
if line.startswith('####'): | |
html_lines.append(f"<h4>{line[4:].strip()}</h4>") | |
elif line.startswith('###'): | |
html_lines.append(f"<h3>{line[3:].strip()}</h3>") | |
elif line.startswith('##'): | |
html_lines.append(f"<h2>{line[2:].strip()}</h2>") | |
elif line.startswith('#'): | |
html_lines.append(f"<h1>{line[1:].strip()}</h1>") | |
elif line.startswith('- '): # ๋ฆฌ์คํธ ์์ดํ | |
html_lines.append(f"<li>{line[2:]}</li>") | |
elif line: # ์ผ๋ฐ ํ ์คํธ (๋น ์ค ์ ์ธ) | |
# '**'๋ก ๊ฐ์ธ์ง ๋ถ๋ถ์ <strong> ํ๊ทธ๋ก ๋ณํ | |
line = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', line) | |
html_lines.append(f"<p>{line}</p>") | |
else: # ๋น ์ค | |
html_lines.append("<br>") | |
html_content = f""" | |
<div style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;"> | |
{"".join(html_lines)} | |
</div> | |
""" | |
return html_content | |
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_outline_prompt(category): | |
if (category == "ํต์ฌ๊ธฐ๋ฅ์ง์คํ"): | |
return """ | |
[์ํ๋ฆฌ๋ทฐ ์์ฃผ์ (Outline) ์์ฑ ๊ท์น] | |
[๊ธฐ๋ณธ๊ท์น] | |
1. ๋ฐ๋์ ํ๊ตญ์ด(ํ๊ธ)๋ก ์์ฑํ๋ผ | |
2. ๋ฐ๋์ ์ํ์ ํต์ฌ ๊ธฐ๋ฅ 3๊ฐ๋ง ์ ์ ํ๋ผ | |
- ํต์ฌ๊ธฐ๋ฅ์ ์ฐธ๊ณ ๊ธ์ ๋ถ์ํ์ฌ ์ ์ ํ๋ผ | |
4. ๋ฐ๋์ ํต์ฌ ๊ธฐ๋ฅ 3๊ฐ์ ๋ํ ํฅ๋ฏธ๋ก์ด ์์ ๋ชฉ๋ง ์์ฑํ๋ผ(์ ๋ ๋ด์ฉ ์์ฑ ๊ธ์ง) | |
5. ๋ฐ๋์ ๋งํฌ๋ค์ด ํ์์ด ์๋ ์์ํ ํ ์คํธ๋ก ์ถ๋ ฅํ๋ผ | |
6. ์์ ๋ชฉ์ ๋ฐ๋์ 30์ ์ด๋ด๋ก ์์ฑํ๋ผ | |
[์ถ๋ ฅ์์] | |
ํต์ฌ๊ธฐ๋ฅ : ์ ์ ํ ํต์ฌ๊ธฐ๋ฅ1์ ์์ ๋ชฉ | |
ํต์ฌ๊ธฐ๋ฅ : ์ ์ ํ ํต์ฌ๊ธฐ๋ฅ2์ ์์ ๋ชฉ | |
ํต์ฌ๊ธฐ๋ฅ : ์ ์ ํ ํต์ฌ๊ธฐ๋ฅ3์ ์์ ๋ชฉ | |
""" | |
def get_blog_post_prompt(category): | |
if (category == "ํต์ฌ๊ธฐ๋ฅ์ง์คํ"): | |
return """ | |
[์ํ๋ฆฌ๋ทฐ ์ฝํ ์ธ ์์ฑ ๊ท์น] | |
[๊ธฐ๋ณธ๊ท์น] | |
1. ๋ฐ๋์ ํ๊ตญ์ด(ํ๊ธ)๋ก ์์ฑํ๋ผ | |
2. ๋ฐ๋์ ์ฃผ์ด์ง ํต์ฌ๊ธฐ๋ฅ 1๊ฐ์ ์ฃผ์ ์ ๋ํด์๋ง ์์ฑํ๋ผ | |
- ์ ๋๋ก ์ฃผ์ด์ง ํต์ฌ๊ธฐ๋ฅ 1๊ฐ์ ์ฃผ์ ์ด์ธ์ ๋ด์ฉ์ ์์ฑํ์ง ๋ง ๊ฒ | |
3. ์ฃผ์ด์ง ํต์ฌ ๊ธฐ๋ฅ 1๊ฐ์ ๋ํ ํน์ฅ์ , ๊ฐ์ข ์ ๋ณด, ํ ๋ฑ์ ์์ธํ ์ค๋ช ํ๋ผ | |
4. ์ ๋ฌธ ์ฉ์ด๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ผ๋ฐ ์ฌ์ฉ์๋ ์ดํด๊ฐ ๋๋๋ก ํ์ด์ ์ค๋ช ํ๋ผ | |
5. ๋งํฌ๋ค์ด ํ์์ผ๋ก ์์ฑํ๋ผ๋ผ | |
[ํ ์คํธ ์์ฑ ๊ท์น] | |
1. ๋ฐ๋์ ์ ๋ ฅ๋ ์ฐธ๊ณ ๊ธ ์์์ ํต์ฌ๊ธฐ๋ฅ 1๊ฐ์ ๋ํ ๋ด์ฉ์ ์์ฑ | |
2. ์ ๋๋ก ์ฃผ์ด์ง ํต์ฌ๊ธฐ๋ฅ 1๊ฐ์ ์ฃผ์ ์ด์ธ์ ๋ด์ฉ์ ์์ฑํ์ง ๋ง ๊ฒ | |
3. ์ ๊ณต๋ ์ฐธ๊ณ ๊ธ์ ์ดํฌ๋ฅผ ๋ฐ์ํ๋, ์ ๋๋ก ํ ๋ฌธ์ฅ ์ด์ ๊ทธ๋๋ก ์ถ๋ ฅํ์ง ๋ง ๊ฒ | |
4. ์ฝ๊ฒ ์ฝํ ์ ์๋๋ก ์ฌ์ด ์ดํ๋ก ์์ฑ | |
5. ํต์ฌ๊ธฐ๋ฅ์ ๋ํ ์๋น์ ํ๊ฒ์ ๋ถ์ํ์ฌ ์์ฑ | |
6. ์ฃผ์ด์ง ํต์ฌ๊ธฐ๋ฅ 1๊ฐ์ ๋ง๋ ์คํ, ๊ธฐ๋ฅ, ์ฑ๋ฅ, ์ฅ๋จ์ , ๊ฐ๊ฒฉ ๋๋น ์ฑ๋ฅ(๊ฐ์ฑ๋น), ํ, ์ฃผ์์ฌํญ ๋ฑ์ ์์ฑ | |
7. ์ฃผ์ด์ง ํต์ฌ๊ธฐ๋ฅ 1๊ฐ์ ๊ด๋ จ๋ ๊ตฌ์ฒด์ ์ธ ์์น(๋ฐ์ดํฐ)๊ฐ ์๋ค๋ฉด ๋ฐ์ํ๋ผ | |
8. ๋ฐ๋์ ํต์ฌ๊ธฐ๋ฅ 1๊ฐ์ ๋ํ ์ฝํ ์ธ ๋ง 1800์ ์ด์ ์์ฑํ๋ผ | |
""" | |
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, outline): | |
try: | |
pdf = PDF() | |
pdf.add_page() | |
# HTML ํ๊ทธ๋ฅผ ํ์ฑํ๊ธฐ ์ํ ์ ๊ทํํ์ | |
tag_pattern = re.compile(r'<(/?)(\w+)([^>]*)>') | |
# ํ์ฌ ๋ ์ง์ ์๊ฐ์ ๊ฐ์ ธ์ต๋๋ค (๋ํ๋ฏผ๊ตญ ์๊ฐ ๊ธฐ์ค) | |
now = datetime.now(ZoneInfo("Asia/Seoul")) | |
date_str = now.strftime("%y%m%d") | |
time_str = now.strftime("%H%M") | |
# ์ฒซ ๋ฒ์งธ ์ ๋ชฉ์ ์ฐพ์ ํ์ผ๋ช ์ผ๋ก ์ฌ์ฉ | |
filename = f"{date_str}_{time_str}_{format_filename(outline)}.pdf" | |
# HTML ๋ด์ฉ์ ์ํํ๋ฉฐ PDF์ ์์ฑ | |
current_tag = '' | |
buffer = '' | |
for part in re.split(tag_pattern, blog_post): | |
# HTML ํ๊ทธ๊ฐ ๋ฑ์ฅํ ๊ฒฝ์ฐ | |
if part in ['h1', 'h2', 'h3', 'p', 'strong', 'li', 'br']: | |
# ์ด์ ํ๊ทธ์ ๋ด์ฉ์ ์ฒ๋ฆฌ | |
if buffer: | |
if current_tag in ['h1', 'h2', 'h3']: | |
pdf.chapter_title(buffer.strip()) # ์์ ๋ชฉ ์ฒ๋ฆฌ | |
elif current_tag == 'p': | |
pdf.chapter_body(buffer.strip()) # ์ผ๋ฐ ๋ฌธ๋จ ์ฒ๋ฆฌ | |
elif current_tag == 'strong': | |
pdf.set_font("NanumGothic", 'B', 11) # ๊ตต์ ๊ธ์จ ์ฒ๋ฆฌ | |
pdf.cell(0, 5, buffer.strip(), 0, 1) | |
pdf.set_font("NanumGothic", '', 11) # ๋ค์ ๊ธฐ๋ณธ ํฐํธ๋ก ๋ณ๊ฒฝ | |
elif current_tag == 'li': | |
pdf.chapter_body("โข " + buffer.strip()) # ๋ฆฌ์คํธ ์์ดํ ์ฒ๋ฆฌ | |
elif current_tag == 'br': | |
pdf.ln(5) # ์ค๋ฐ๊ฟ ์ฒ๋ฆฌ | |
# ํ์ฌ ํ๊ทธ์ ๋ฒํผ ์ด๊ธฐํ | |
buffer = '' | |
current_tag = part | |
# ์ข ๋ฃ ํ๊ทธ๋ ๋ฌด์ (div ํฌํจ) | |
elif part.startswith('/'): | |
continue | |
# ํ ์คํธ ๋ถ๋ถ ์ฒ๋ฆฌ | |
elif not tag_pattern.match(part) and part.strip() != 'div': | |
buffer += part | |
# ๋ง์ง๋ง ๋ฒํผ ์ฒ๋ฆฌ | |
if buffer: | |
if current_tag in ['h1', 'h2', 'h3']: | |
pdf.chapter_title(buffer.strip()) # ์ ๋ชฉ ํ์์ผ๋ก ์ฒ๋ฆฌ | |
elif current_tag == 'p': | |
pdf.chapter_body(buffer.strip()) # ๋ณธ๋ฌธ ํ์์ผ๋ก ์ฒ๋ฆฌ | |
# PDF ์ ์ฅ | |
print(f"Saving PDF as: {filename}") | |
pdf.output(filename, 'F') # 'F' ์ต์ ์ถ๊ฐ | |
return filename | |
except Exception as e: | |
print(f"PDF ์์ฑ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}") | |
import traceback | |
traceback.print_exc() # ์์ธํ ์ค๋ฅ ์ ๋ณด ์ถ๋ ฅ | |
return None # ์ค๋ฅ ๋ฐ์ ์ None ๋ฐํ | |
def save_content_to_pdf(blog_post, outline): | |
pdf_filename = save_to_pdf(blog_post, outline) | |
if pdf_filename: | |
return pdf_filename | |
else: | |
return None | |
title = "ํต์ฌ๊ธฐ๋ฅ์ง์คํ" | |
with gr.Blocks() as demo: | |
gr.Markdown(f"# ํต์ฌ๊ธฐ๋ฅ์ง์คํ") | |
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") | |
gr.HTML("<span style='color: grey;'>[๋์จ ๊ฒฐ๊ณผ๋ฅผ ์์ ํด์ ์ฌ์ฉํด์ฃผ์ธ์]</span>") | |
outline_generate_btn = gr.Button("ํต์ฌ๊ธฐ๋ฅ ์ ์ ํ๊ธฐ") | |
outline_result1 = gr.Textbox(label="ํต์ฌ๊ธฐ๋ฅ 1", lines=2) | |
outline_result2 = gr.Textbox(label="ํต์ฌ๊ธฐ๋ฅ 2", lines=2) | |
outline_result3 = gr.Textbox(label="ํต์ฌ๊ธฐ๋ฅ 3", lines=2) | |
outline_input = gr.Textbox(label="์์ฑํ ํต์ฌ๊ธฐ๋ฅ ์ฃผ์ ์ค์ 1๊ฐ๋ง ์ ๋ ฅํด์ฃผ์ธ์", placeholder="ํต์ฌ๊ธฐ๋ฅ 1๊ฐ๋ง ์ ๋ ฅํ์ธ์", lines=2) | |
outline_generate_btn.click( | |
fn=generate_outline, | |
inputs=[category, style, references1, references2, references3], | |
outputs=[outline_result1, outline_result2, outline_result3] | |
) | |
gr.Markdown("---\n\n") | |
gr.Markdown("### 5๋จ๊ณ: ๊ธ ์์ฑํ๊ธฐ", elem_id="step-title") | |
gr.HTML("<span style='color: grey;'>[ํต์ฌ๊ธฐ๋ฅ์ ํ์ธํ์ธ์]</span>") | |
generate_btn = gr.Button("๋ธ๋ก๊ทธ ๊ธ ์์ฑํ๊ธฐ") | |
html_output = gr.HTML(label="์์ฑ๋ ๋ธ๋ก๊ทธ ๊ธ") | |
generate_btn.click( | |
fn=generate_blog_post, | |
inputs=[category, style, references1, references2, references3, outline_input], | |
outputs=[html_output], | |
show_progress=True | |
) | |
save_pdf_btn = gr.Button("PDF๋ก ์ ์ฅํ๊ธฐ") | |
pdf_output = gr.File(label="์์ฑ๋ PDF ํ์ผ") | |
save_pdf_btn.click( | |
fn=save_content_to_pdf, | |
inputs=[html_output, outline_input], # outline_input ์ถ๊ฐ | |
outputs=[pdf_output], | |
show_progress=True | |
) | |
demo.launch() | |
gr.HTML(""" | |
<style> | |
#step-title { | |
font-size: 1.7em; | |
font-weight: bold; | |
} | |
</style> | |
""") | |