Spaces:
Sleeping
Sleeping
import os | |
import gradio as gr | |
from dotenv import load_dotenv | |
from openai import OpenAI | |
import logging | |
import time | |
import uuid | |
# ๋ก๊น ์ค์ - INFO ๋ ๋ฒจ๋ก ๋ณ๊ฒฝ | |
logging.basicConfig(level=logging.INFO) | |
logger = logging.getLogger(__name__) | |
# ํ๊ฒฝ ๋ณ์ ๋ก๋ | |
load_dotenv() | |
# API ํค ์ค์ | |
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") | |
logger.info("API ํค ์ค์ ์๋ฃ") | |
# OpenAI ํด๋ผ์ด์ธํธ ์ค์ | |
openai_client = OpenAI(api_key=OPENAI_API_KEY) | |
# ๋ชจ๋ธ๋ณ ํ๋กฌํํธ ์ ์ | |
GPT_PROMPTS = { | |
"๋ฌธ๋ฒ ๊ต์ ": """ | |
1. ์ฃผ์ด์ง ํ ์คํธ์ ๋ฌธ๋ฒ์ ๊ฒํ ํ๊ณ ๊ต์ ํ๋ผ | |
2. ๋ฐ๋์ ์๋ณธ ํ ์คํธ๋ฅผ ์ ์งํ๋ฉด์ ๋ฌธ๋ฒ์ ์ธ ๋ถ๋ถ์์๋ง ์์ ํ๋ผ | |
3. ๋ง์ถค๋ฒ, ๋์ด์ฐ๊ธฐ, ๋ฌธ์ฅ ๋ถํธ ๋ฑ์ ํ๊ตญ์ด ๋ฌธ๋ฒ์ ๋ง๊ฒ ์ ํํ๊ฒ ์์ ํ๋ผ | |
4. ์ ๋ ์๋ณธ ํ ์คํธ ์ด์ธ์ ๋ค๋ฅธ ๋ถ๊ฐ์ ์ธ ์ค๋ช ์ ์ถ๋ ฅํ์ง ๋ง ๊ฒ | |
- '์์ ๋ ํ ์คํธ', '๊ฐ์ ๋ ํ ์คํธ'๋ฑ ์ถ๋ ฅ๊ธ์ง | |
""", | |
"๋ฌธ์ฅ ๋ค๋ฌ๊ธฐ": """ | |
## ๋ฌธ์ฅ ๊ตฌ์กฐ ๊ฒํ | |
- **๋ถํ์ํ ๋ฌธ๊ตฌ ์ ๊ฑฐ:** ํ์์ ์ด์ง ์์ ํํ์ ์ญ์ ํ์ฌ ๋ฌธ์ฅ์ ๊ฐ๊ฒฐํ๊ฒ ์ ์งํฉ๋๋ค. | |
- **์ฃผ์ด-์์ ์ด ๋ช ํ์ฑ:** ๋ฌธ์ฅ์ ์ฃผ์ด์ ์์ ์ด๋ฅผ ๋ช ํํ ํ์ฌ ์๋ฏธ ์ ๋ฌ์ด ์ค์ ์์ด ์ด๋ฃจ์ด์ง๋๋ก ํฉ๋๋ค. | |
- **๊ธด ๋ฌธ์ฅ ๋ถ๋ฆฌ:** ์ง๋์น๊ฒ ๊ธด ๋ฌธ์ฅ์ ์ฝ๊ธฐ ์ฝ๊ฒ ์ฌ๋ฌ ๋ฌธ์ฅ์ผ๋ก ๋๋๋๋ค. | |
## ๋จ๋ฝ ๊ตฌ์ฑ ์ ๊ฒ | |
- **ํต์ฌ ์ฃผ์ ํ์ธ:** ๊ฐ ๋จ๋ฝ์ด ๋ช ํํ ํต์ฌ ์ฃผ์ ๋ ์ค์ฌ ์๊ฐ์ ๊ฐ์ง๊ณ ์๋์ง ํ์ธํฉ๋๋ค. | |
- **์์ฐ์ค๋ฌ์ด ์ฐ๊ฒฐ:** ๋จ๋ฝ ๊ฐ์ ํ๋ฆ์ด ์์ฐ์ค๋ฝ๋๋ก ์ฐ๊ฒฐ์ด๋ฅผ ์ ์ ํ ์ฌ์ฉํฉ๋๋ค. | |
- **๋จ๋ฝ ๊ธธ์ด ์กฐ์ :** ๋๋ฌด ๊ธธ๊ฑฐ๋ ์งง์ ๋จ๋ฝ์ ์กฐ์ ํ์ฌ ๊ท ํ์ ๋ง์ถฅ๋๋ค. | |
## ์ดํ ๊ฐ์ | |
- **์ธ๋์ด ์ํ:** ๋ถํ์ํ ์ธ๋์ด๋ฅผ ํ๊ตญ์ด๋ก ๋์ฒดํฉ๋๋ค. | |
- **๋จ์ด ๊ตฌ์ฒดํ:** ๋ชจํธํ ํํ์ ๋ณด๋ค ๋ช ํํ ์ฉ์ด๋ก ๋ฐ๊ฟ๋๋ค. | |
- **์ค๋ณต ํํ ์ญ์ :** ์๋ฏธ๊ฐ ์ค๋ณต๋๋ ๋จ์ด๋ฅผ ์ ๊ฑฐํ์ฌ ๋ฌธ์ฅ์ ํจ์จ์ฑ์ ๋์ ๋๋ค. | |
## ์ ๋ฌ๋ ฅ ๊ฐํ | |
- **ํต์ฌ ๋ฉ์์ง ๋ถ๊ฐ:** ๋ฌธ์ฅ์์ ๊ฐ์ฅ ์ค์ํ ๋ฉ์์ง๊ฐ ์ ๋๋ฌ๋๋๋ก ์กฐ์ ํฉ๋๋ค. | |
- **๋ ผ๋ฆฌ์ ํ๋ฆ ๊ฐ์ :** ์ ์ฒด ๋ฌธ๋จ์ ๋ ผ๋ฆฌ์ ์ธ ํ๋ฆ์ด ์์ฐ์ค๋ฝ๋๋ก ๋ง๋ญ๋๋ค. | |
- **๋ ์ ์ดํด ๊ณ ๋ ค:** ๋ ์๊ฐ ์ฝ๊ฒ ์ดํดํ ์ ์๋์ง ๊ณ ๋ คํ์ฌ ํํํฉ๋๋ค. | |
## ์ผ๊ด์ฑ ํ๋ณด | |
- **๋ฌธ์ฒด ํต์ผ:** ๋ฌธ์ฅ์ ํค๊ณผ ์คํ์ผ์ด ์ผ์ ํ์ง ์ ์งํฉ๋๋ค. | |
- **์ฉ์ด ํต์ผ:** ๋์ผํ ์ฉ์ด๋ฅผ ์ผ๊ด์ฑ ์๊ฒ ์ฌ์ฉํฉ๋๋ค. | |
- **์์ ์ผ๊ด์ฑ:** ์์ ๊ฐ ์ผ์ ํ๊ฒ ์ ์ง๋๋๋ก ํฉ๋๋ค. | |
# Output Format | |
- ์๋ณธ๊ณผ ๋์ผํ ๋งํฌ์ ์ด์กฐ๋ฅผ ์ ์งํ์ฌ, ํ์ํ ๋ถ๋ถ๋ง์ ๋ค๋ฌ์ ํ ์คํธ๋ก ์ถ๋ ฅํฉ๋๋ค. | |
- ๋ถ๊ฐ์ ์ธ ์ค๋ช ์์ด ๋จ์ํ ๊ฐ์ ๋ ํ ์คํธ๋ง์ ์ ๊ณตํฉ๋๋ค. | |
""", | |
"๋ช ์ธ์ธ์ฉํ์ฌ ๋ค๋ฌ๊ธฐ": """ | |
1. ์ฃผ์ด์ง ํ ์คํธ์ ๋ฌธ์ฅ์ ์ ์ ํ ๋ช ์ธ์ด๋ ๊ฒฉ์ธ์ ๋ฑํ๋ฒ ์ธ์ฉํ์ฌ ๋ ์ค๋๋ ฅ ์๊ณ ์ธ์์ ์ธ ๋ด์ฉ์ผ๋ก ๋ฐ์ ์์ผ๋ผ | |
2. ์ธ์ฉ๊ตฌ๋ฅผ ๋ฌธ๋งฅ์ ๋ง๊ฒ ์์ฐ์ค๋ฝ๊ฒ ๋ น์๋ค๊ฒ ์์ฑํ๋ผ | |
3. ์๋ณธ ํ ์คํธ์ ๋ด์ฉ๊ณผ ๋ถ์๊ธฐ๋ฅผ ์ต๋ํ ๋ฐ์ํ๋ผ | |
4. ์ ๋ ์๋ณธ ํ ์คํธ ์ด์ธ์ ๋ค๋ฅธ ๋ถ๊ฐ์ ์ธ ์ค๋ช ์ ์ถ๋ ฅํ์ง ๋ง ๊ฒ | |
- '์์ ๋ ํ ์คํธ', '๊ฐ์ ๋ ํ ์คํธ'๋ฑ ์ถ๋ ฅ๊ธ์ง | |
""", | |
"๋ด ๋ง์๋๋ก ๋ค๋ฌ๊ธฐ": """ | |
1. ์ฌ์ฉ์๊ฐ ์ ๊ณตํ ํ๋ฅด์๋์ ๋ชฉ์ ์ ๋ง๊ฒ ํ ์คํธ๋ฅผ ๋ค๋ฌ์ด๋ผ | |
2. ํ ์คํธ์ ์ ๋ฐ์ ์ธ ํค๊ณผ ๋ถ์๊ธฐ๋ฅผ ์ฌ์ฉ์๊ฐ ์ค์ ํ ๋ฐฉํฅ์ ๋ง์ถ์ด ์์ ํ๋ผ | |
3. ๋ช ํ์ฑ, ์ผ๊ด์ฑ, ๋ ์ฐฝ์ฑ์ ์ ์งํ๋ฉฐ ๊ฐ์ ํ๋ผ | |
4. ๋ฐ๋์ ์ฌ์ฉ์ ์ง์ ์ง์นจ์ ๋ฐ๋ผ ์์ ํ๋ผ | |
5. ์ ๋ ๋ค๋ฅธ ๋ถ๊ฐ์ ์ธ ์ค๋ช ์ ์ถ๋ ฅํ์ง ๋ง ๊ฒ | |
- '์์ ๋ ํ ์คํธ', '๊ฐ์ ๋ ํ ์คํธ'๋ฑ ์ถ๋ ฅ๊ธ์ง | |
""", | |
} | |
def process_text(input_text, improvement_type, custom_purpose, persona, temperature, top_p): | |
"""GPT ๋ชจ๋ธ์ฉ ํ ์คํธ ์ฒ๋ฆฌ ํจ์""" | |
try: | |
print("ํ ์คํธ ์ฒ๋ฆฌ ์์") | |
request_id = str(uuid.uuid4())[:8] | |
timestamp_micro = int(time.time() * 1000000) % 1000 | |
if improvement_type == "๋ด ๋ง์๋๋ก ๋ค๋ฌ๊ธฐ": | |
purpose = f"๋ค์ ํ๋ฅด์๋๋ฅผ ๊ฐ์ง๊ณ ํ ์คํธ๋ฅผ ๋ค๋ฌ์ผ์ธ์: {persona}\n\n๋ชฉ์ : {custom_purpose}" | |
else: | |
purpose = GPT_PROMPTS[improvement_type] | |
response = openai_client.chat.completions.create( | |
model="gpt-4o-mini", | |
messages=[ | |
{ | |
"role": "system", | |
"content": f"REQ-{request_id}-{timestamp_micro}" | |
}, | |
{ | |
"role": "user", | |
"content": f"๋ค์ ํ ์คํธ๋ฅผ ๋ชฉ์ ์ ๋ง๊ฒ ๋ค๋ฌ์ด๋ผ.\n\nํ ์คํธ: {input_text}\n\n๋ชฉ์ : {purpose}" | |
} | |
], | |
max_tokens=2000, | |
temperature=temperature, | |
top_p=top_p | |
) | |
print("ํ ์คํธ ์ฒ๋ฆฌ ์๋ฃ") | |
return response.choices[0].message.content | |
except Exception as e: | |
print("ํ ์คํธ ์ฒ๋ฆฌ ์คํจ") | |
logger.error(f"์ฒ๋ฆฌ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}") | |
return f"์ค๋ฅ ๋ฐ์: {str(e)}" | |
def create_interface(): | |
css = """ | |
footer { | |
visibility: hidden; | |
} | |
""" | |
with gr.Blocks(theme=gr.themes.Soft( | |
primary_hue=gr.themes.Color( | |
c50="#FFF7ED", # ๊ฐ์ฅ ๋ฐ์ ์ฃผํฉ | |
c100="#FFEDD5", | |
c200="#FED7AA", | |
c300="#FDBA74", | |
c400="#FB923C", | |
c500="#F97316", # ๊ธฐ๋ณธ ์ฃผํฉ | |
c600="#EA580C", | |
c700="#C2410C", | |
c800="#9A3412", | |
c900="#7C2D12", # ๊ฐ์ฅ ์ด๋์ด ์ฃผํฉ | |
c950="#431407", | |
), | |
secondary_hue="zinc", # ๋ชจ๋ํ ๋๋์ ํ์ ๊ณ์ด | |
neutral_hue="zinc", | |
font=("Pretendard", "sans-serif") | |
), css=css) as demo: | |
gr.Markdown( | |
""" | |
# โจ ํ ์คํธ ๊ฐ์ ๋๊ตฌ | |
### ํ ์คํธ๋ฅผ ๋ชฉ์ ์ ๋ง๊ฒ ๊ฐ์ ํด๋ณด์ธ์ | |
""", | |
elem_classes="text-3xl" | |
) | |
with gr.Row(): | |
with gr.Column(scale=1): | |
input_text = gr.Textbox( | |
label="์๋ณธ ํ ์คํธ", | |
placeholder="์ฌ๊ธฐ์ ๊ฐ์ ํ๊ณ ์ถ์ ํ ์คํธ๋ฅผ ์ ๋ ฅํ์ธ์...1,000์ ์ด์์ ๋ชจ๋ธ์ ๋ฐ๋ผ ํ๋ฆฌํฐ๊ฐ ๋จ์ด์ง ์ ์์ต๋๋ค", | |
lines=6 | |
) | |
improvement_type = gr.Radio( | |
choices=["๋ฌธ๋ฒ ๊ต์ ", "๋ฌธ์ฅ ๋ค๋ฌ๊ธฐ", "๋ช ์ธ์ธ์ฉํ์ฌ ๋ค๋ฌ๊ธฐ", "๋ด ๋ง์๋๋ก ๋ค๋ฌ๊ธฐ"], | |
label="๊ฐ์ ๋ฐฉํฅ", | |
value="๋ฌธ๋ฒ ๊ต์ " | |
) | |
custom_purpose = gr.Textbox( | |
label="๊ฐ์ ๋ชฉ์ /๋ฐฉํฅ์ฑ", | |
placeholder="ํ ์คํธ๋ฅผ ์ด๋ค ๋ฐฉํฅ์ผ๋ก ๊ฐ์ ํ๊ณ ์ถ์ผ์ ์ง ์ค๋ช ํด์ฃผ์ธ์...", | |
lines=4, | |
visible=False | |
) | |
persona = gr.Textbox( | |
label="ํ๋ฅด์๋ ์ ์ฉํ๊ธฐ", | |
placeholder="์ด๋ค ์ญํ , ์ฑ๊ฒฉ์ ๊ฐ์ง๊ณ ํ ์คํธ๋ฅผ ๋ค๋ฌ๊ธธ ์ํ์๋์? (์: ์ ๋จธ๋ฌ์คํ ๊ฐ๊ทธ๋งจ, ์ง์งํ ๊ต์ ๋ฑ)", | |
lines=4, | |
visible=False | |
) | |
with gr.Row(visible=False) as generation_settings: | |
temperature = gr.Slider( | |
minimum=0.0, | |
maximum=1.0, | |
value=0.7, | |
step=0.1, | |
label="Temperature", | |
info="๋์์๋ก ๋ ์ฐฝ์์ ์ธ ๊ฒฐ๊ณผ๊ฐ ์์ฑ๋ฉ๋๋ค" | |
) | |
top_p = gr.Slider( | |
minimum=0.0, | |
maximum=1.0, | |
value=0.9, | |
step=0.1, | |
label="Top P", | |
info="๋์์๋ก ๋ ๋ค์ํ ๋จ์ด๋ฅผ ์ฌ์ฉํฉ๋๋ค" | |
) | |
submit_btn = gr.Button( | |
"โจ ํ ์คํธ ๊ฐ์ ํ๊ธฐ", | |
variant="primary", | |
size="lg" | |
) | |
gr.Markdown(""" | |
### ๐ก ์ฌ์ฉ ๊ฐ์ด๋ | |
1. ๊ฐ์ ํ๊ณ ์ถ์ ํ ์คํธ๋ฅผ ์ ๋ ฅํ์ธ์ | |
2. ๊ฐ์ ๋ฐฉํฅ์ ์ ํํ์ธ์ | |
3. '๋ด ๋ง์๋๋ก ๋ค๋ฌ๊ธฐ' ์ ํ ์: | |
- ๊ฐ์ ๋ชฉ์ /๋ฐฉํฅ์ฑ์ ์ ๋ ฅํ์ธ์ | |
- ํ๋ฅด์๋๋ฅผ ์ค์ ํ์ธ์ | |
- Temperature, Top-p๋ฅผ ์ค์ ํด๋ณด์ธ์ | |
4. 'ํ ์คํธ ๊ฐ์ ํ๊ธฐ' ๋ฒํผ์ ํด๋ฆญํ์ธ์ | |
""") | |
with gr.Column(scale=1): | |
output_text = gr.Textbox( | |
label="๊ฐ์ ๋ ํ ์คํธ", | |
lines=35, | |
show_copy_button=True | |
) | |
def update_custom_inputs_visibility(choice): | |
is_custom = choice == "๋ด ๋ง์๋๋ก ๋ค๋ฌ๊ธฐ" | |
return { | |
custom_purpose: gr.update(visible=is_custom), | |
persona: gr.update(visible=is_custom), | |
generation_settings: gr.update(visible=is_custom) | |
} | |
improvement_type.change( | |
fn=update_custom_inputs_visibility, | |
inputs=[improvement_type], | |
outputs=[custom_purpose, persona, generation_settings] | |
) | |
submit_btn.click( | |
fn=process_text, | |
inputs=[input_text, improvement_type, custom_purpose, persona, temperature, top_p], | |
outputs=output_text, | |
api_name="improve_text" | |
) | |
return demo | |
if __name__ == "__main__": | |
logger.info("์ ํ๋ฆฌ์ผ์ด์ ์์") | |
demo = create_interface() | |
demo.queue() | |
demo.launch() | |