| | 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() |
| |
|