|
import os |
|
import gradio as gr |
|
import openai |
|
import requests |
|
import logging |
|
import asyncio |
|
import aiohttp |
|
|
|
|
|
logging.basicConfig(level=logging.INFO) |
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
openai.api_key = os.getenv("OPENAI_API_KEY") |
|
|
|
|
|
CATEGORIES = [ |
|
"๊ณตํฌ ๋ง์ผํ
", |
|
"์คํ ๋ฆฌํ
๋ง" |
|
] |
|
|
|
def get_category_prompt(category): |
|
if category == "๊ณตํฌ ๋ง์ผํ
": |
|
return """ |
|
# ๊ณตํฌ ๋ง์ผํ
์นดํผ๋ผ์ดํ
์์ฑ ๊ท์น |
|
1. ๋ฐ๋์ ํ๊ธ๋ก ์ถ๋ ฅํ๋ผ. |
|
2. ๋๋ ์ธ๊ณ ์ต๊ณ ์ ๊ณตํฌ ๋ง์ผํ
์นดํผ๋ผ์ดํฐ์ด๋ค. |
|
3. ๋ฐ๋์ ์นดํผ๋ผ์ดํ
์ 30์ ์ด๋ด๋ก ์์ฑํ๊ณ , 20๊ฐ๋ง ์ถ๋ ฅํ๋ผ.(๋ค๋ฅธ ๋ด์ฉ ์ถ๋ ฅ ๊ธ์ง) |
|
4. ๋ฐ๋์ ์
๋ ฅ๋ ์ฃผ์ ๋ก๋ง ์์ฑํ๊ณ ์์๋ฅผ ์ฐธ๊ณ ํ์ฌ ๋ด์ฉ์ ๋ณด๊ฐํ๋ผ. |
|
5. ๋ฐ๋์ 1 ๋ถํฐ 20๊น์ง ๋ฒํธ(๋ฆฌ์คํธํํ)๋ฅผ ๊ฐ์ด ์ถ๋ ฅํ๋ผ |
|
6. ์ฌ๋๋ค์๊ฒ ๋๋ ค์์ ์ฃผ๋ฉด์, ๋์์ ์ ํ์ด๋ ์๋น์ค๋ฅผ ์ฌ์ฉํด์ผ๋ง ํ๋ ์ด์ ๋ฅผ ๊ฐํ๊ฒ ์ดํํ๋ผ. |
|
7. ์ฌ์ฉํ์ง ์์ ๋์ ์ํ์ด๋ ์์ค์ ๊ฐ์กฐํ๋ผ. |
|
8. ๊ฐ์ ์ ์ธ ๋จ์ด์ ํํ์ ์ฌ์ฉํ์ฌ ๋
์์ ๋ถ์์ ์ฆํญ์ํค๋ผ |
|
9. ์ ํ/์๋น์ค์ ์ค์์ฑ๊ณผ ๊ทธ๊ฒ์ด ์์ ๋์ ๊ทน๋จ์ ์ธ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌ์ฒด์ ์ผ๋ก ์ค๋ช
ํ๋ผ. |
|
์์: |
|
- ์ค์ฟผํธ ํ ๋ ์ด ๋์ ํ๋ฉด ๋ฌด๋ฆ ๋ถ์ ์ต๋๋ค |
|
- ์ฑ
์ ์ฝ๋ ์ฌ๋์ด ๊ฐ๋ํ ํ๋ฅ 98%์ธ ์ด์ |
|
- ์ ์ ํ์ ์ถ์ํ ๋ ์คํจํ๋ 7 ๊ฐ์ง ์น๋ช
์ ์ค์ |
|
- ์์
๋ฏธ๋์ด๋ฅผ ์๋ชป ์ฌ์ฉํ๋ฉด ๊ธฐ์
์ด ๋งํ ์ ์๋ ์ด์ |
|
- ์ด ์ฑ ์ ์ฐ๋ฉด ํดํน ๋นํ ํ๋ฅ 80% ์ฆ๊ฐ |
|
- ์ด ๋ณดํ ์์ผ๋ฉด ์ฌ๊ณ ์ ํ์ฐ ์๊ธฐ ์จ๋ค |
|
- ์ถฉ๊ฒฉ! ์ด ์ ํฌ๋ฆผ ์ ๋ฐ๋ฅด๋ฉด ํผ๋ถ์ ์ํ 500% ์ฆ๊ฐ |
|
- ๊ฐ์ต๊ธฐ 2์ผ๋ง ๊ด๋ฆฌํ์ง ์์๋ "์ธ๊ท ๋ฒ๋ฒ
" |
|
- ๋ฐ๋ค ํ๊ฒฝ์ค์ผ, ์ํ์ผ๋ก ๋๋์์จ๋ค. ํ๋ผ์คํฑ ์ฌ์ฉ ์ด๋๋ก ๊ด์ฐฎ์๊ฐ์? |
|
- "๋งฅ์ฃผ ํ์์ด๋ผ๋ ๋ ๋ง๋ค ์ ์ด ๋ก๊ธด๋ค๋ฉด? ์ด๊ฒ ์์ฌํด์ผ" |
|
""" |
|
elif category == "์คํ ๋ฆฌํ
๋ง": |
|
return """ |
|
# ์คํ ๋ฆฌํ
๋ง ์นดํผ๋ผ์ดํ
์์ฑ ๊ท์น |
|
1. ๋ฐ๋์ ํ๊ธ๋ก ์ถ๋ ฅํ๋ผ. |
|
2. ๋๋ ์ธ๊ณ ์ต๊ณ ์ ์คํ ๋ฆฌํ
๋ง ๋ง์ผํ
์นดํผ๋ผ์ดํฐ์ด๋ค. |
|
3. ๋ฐ๋์ ์นดํผ๋ผ์ดํ
์ 30์ ์ด๋ด๋ก ์์ฑํ๊ณ , 20๊ฐ๋ง ์ถ๋ ฅํ๋ผ.(๋ค๋ฅธ ๋ด์ฉ ์ถ๋ ฅ ๊ธ์ง) |
|
4. ๋ฐ๋์ ์
๋ ฅ๋ ์ฃผ์ ๋ก๋ง ์์ฑํ๊ณ ์์๋ฅผ ์ฐธ๊ณ ํ์ฌ ๋ด์ฉ์ ๋ณด๊ฐํ๋ผ. |
|
5. ๋ฐ๋์ 1 ๋ถํฐ 20๊น์ง ๋ฒํธ(๋ฆฌ์คํธํํ)๋ฅผ ๊ฐ์ด ์ถ๋ ฅํ๋ผ |
|
6. ์ ํ/์๋น์ค์ ๊ด๋ จ๋ ์งง๊ณ ํฅ๋ฏธ๋ก์ด ์ด์ผ๊ธฐ๋ฅผ ๋ง๋ค์ด๋ผ. |
|
7. ๊ณ ๊ฐ์ด ๊ณต๊ฐํ ์ ์๋ ์ํฉ์ด๋ ์บ๋ฆญํฐ๋ฅผ ์ค์ ํ๋ผ. |
|
8. ์ด์ผ๊ธฐ๋ฅผ ํตํด ์ ํ/์๋น์ค์ ๊ฐ์น๋ฅผ ์์ฐ์ค๋ฝ๊ฒ ์ ๋ฌํ๋ผ. |
|
์์: |
|
- ํ ์ด๋ถ์ ๊ฟ์์ ์์๋ ํ์ ์ ์ธ ๋์์ฅ๋น |
|
- 100๋
๋ ๊ฐ์กฑ ๋ ์ํผ๋ก ๋ง๋ ์์ ์ผ |
|
- ์ฐ์ฃผ ๋นํ์ฌ์ ์์ด๋์ด๋ก ํ์ํ ์ด๊ฒฝ๋ ์ฌํท |
|
- ํ ๋จธ๋์ 100๋
๋ ๋น๋ฐ ๋ ์ํผ๋ก ๋ง๋ ๊ฑด๊ฐํ ์ง๋ฐฅ ๊ฐ์ |
|
- ํ๋ง๋ผ์ผ ๋ฑ์ฐ๊ฐ์ ๊ณ ๋ฏผ์์ ์์๋ ํ์ ์ ์ด๊ฒฝ๋ ๋ฐฐ๋ญ |
|
- ๋ชฝ๊ณจ ์ ๋ชฉ๋ฏผ์ ์ฒ๋
์งํ๋ฅผ ๋ด์ ์นํ๊ฒฝ ์คํ ์บ ํ ํ
ํธ |
|
- ๋ฐ๋ค๋ฅผ ์ฌ๋ํ ํด์์๋ฌผํ์์ ํ์ ์ ์ธ ํด์ ์ ํ ๊ธฐ์ |
|
- 20๋
๋ถ๋ฉด์ฆ ํ์๊ฐ ์ง์ ๊ฐ๋ฐํ ๊ฟ์ ์ ๋ ์ค๋งํธ ๋ฒ ๊ฐ |
|
- ๊ธธ๊ณ ์์ด 100๋ง๋ฆฌ๋ฅผ ๊ตฌ์กฐํ ์์์ฌ์ ๋ฐ๋ ค๋๋ฌผ ๊ฑด๊ฐ๊ด๋ฆฌ ์ฑ |
|
- ํ ์๋ ์ฅ์ ์ธ ํ๊ฐ์ ๊ฟ์ ์ด๋ค์ค ์ฒจ๋จ ๊ทธ๋ฆผ ๋๊ตฌ |
|
""" |
|
|
|
|
|
|
|
|
|
def call_api_sync(content, system_message, max_tokens, temperature, top_p): |
|
response = requests.post( |
|
"https://api.openai.com/v1/chat/completions", |
|
headers={"Authorization": f"Bearer {openai.api_key}"}, |
|
json={ |
|
"model": "gpt-4o-mini", |
|
"messages": [ |
|
{"role": "system", "content": system_message}, |
|
{"role": "user", "content": content}, |
|
], |
|
"max_tokens": max_tokens, |
|
"temperature": temperature, |
|
"top_p": top_p, |
|
} |
|
) |
|
result = response.json() |
|
return result['choices'][0]['message']['content'] |
|
|
|
def generate_copywriting(categories, topic): |
|
max_tokens = 1000 |
|
temperature = 0.8 |
|
top_p = 0.95 |
|
|
|
results = {} |
|
for category in categories: |
|
prompt = get_category_prompt(category) |
|
user_content = f"์ฃผ์ : {topic}" |
|
copywriting = call_api_sync(user_content, prompt, max_tokens, temperature, top_p) |
|
results[category] = copywriting |
|
return results |
|
|
|
|
|
|
|
|
|
|
|
async def call_api_async(category, content, system_message, max_tokens, temperature, top_p): |
|
""" |
|
๋น๋๊ธฐ๋ก OpenAI API๋ฅผ ํธ์ถํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ |
|
""" |
|
async with aiohttp.ClientSession() as session: |
|
headers = { |
|
"Authorization": f"Bearer {openai.api_key}", |
|
"Content-Type": "application/json" |
|
} |
|
payload = { |
|
"model": "gpt-4o-mini", |
|
"messages": [ |
|
{"role": "system", "content": system_message}, |
|
{"role": "user", "content": content}, |
|
], |
|
"max_tokens": max_tokens, |
|
"temperature": temperature, |
|
"top_p": top_p, |
|
} |
|
async with session.post("https://api.openai.com/v1/chat/completions", headers=headers, json=payload) as resp: |
|
result = await resp.json() |
|
copywriting = result["choices"][0]["message"]["content"] |
|
return category, copywriting |
|
|
|
async def generate_copywriting_async(categories, topic): |
|
""" |
|
๊ฐ ์นดํ
๊ณ ๋ฆฌ์ ๋ํด ๋น๋๊ธฐ๋ก API ํธ์ถ์ ์ํํ๊ณ , |
|
์๋ฃ๋๋ ์์๋๋ก (category, ๊ฒฐ๊ณผ) ๋ฅผ yield |
|
""" |
|
max_tokens = 1000 |
|
temperature = 0.8 |
|
top_p = 0.95 |
|
|
|
tasks = [] |
|
for category in categories: |
|
prompt = get_category_prompt(category) |
|
user_content = f"์ฃผ์ : {topic}" |
|
tasks.append( |
|
asyncio.create_task( |
|
call_api_async(category, user_content, prompt, max_tokens, temperature, top_p) |
|
) |
|
) |
|
|
|
|
|
for task in asyncio.as_completed(tasks): |
|
cat, copywriting = await task |
|
yield cat, copywriting |
|
|
|
|
|
|
|
|
|
|
|
with gr.Blocks() as iface: |
|
gr.Markdown("# AI ์นดํผ๋ผ์ดํ
์์ฑ๊ธฐ") |
|
|
|
with gr.Column(): |
|
topic = gr.Textbox(lines=1, label="์ฃผ์ ๋ฅผ ์
๋ ฅํ์ธ์") |
|
|
|
generate_btn = gr.Button("์นดํผ๋ผ์ดํ
์์ฑํ๊ธฐ") |
|
status = gr.Markdown("์ค๋น๋จ") |
|
|
|
output_boxes = {} |
|
with gr.Column(): |
|
for category in CATEGORIES: |
|
output_box = gr.Textbox(label=category, visible=True) |
|
output_boxes[category] = output_box |
|
|
|
|
|
|
|
|
|
|
|
async def validate_and_generate(topic): |
|
try: |
|
results = {} |
|
|
|
async for cat, copywriting in generate_copywriting_async(CATEGORIES, topic): |
|
results[cat] = copywriting |
|
|
|
yield [ |
|
gr.update(value=f"์งํ์ค: [{cat}] ์นดํผ๋ผ์ดํ
์๋ฃ"), |
|
*[gr.update(value=results.get(c, "")) for c in CATEGORIES] |
|
] |
|
|
|
|
|
yield [ |
|
gr.update(value="์นดํผ๋ผ์ดํ
์์ฑ์ด ์๋ฃ๋์์ต๋๋ค."), |
|
*[gr.update(value=results.get(c, "")) for c in CATEGORIES] |
|
] |
|
|
|
except Exception as e: |
|
logger.error(f"Error during copywriting generation: {str(e)}") |
|
yield [ |
|
gr.update(value=f"์ค๋ฅ ๋ฐ์: {str(e)}"), |
|
*[gr.update(value="") for _ in CATEGORIES] |
|
] |
|
|
|
|
|
generate_btn.click( |
|
fn=validate_and_generate, |
|
inputs=[topic], |
|
outputs=[status] + [output_boxes[category] for category in CATEGORIES] |
|
) |
|
|
|
|
|
iface.queue() |
|
iface.launch() |
|
|