| import os |
| import gradio as gr |
| from openai import OpenAI |
| from PIL import Image |
| from io import BytesIO |
| import traceback |
| import requests |
|
|
| |
| |
| |
| OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") |
| STABILITY_API_KEY = os.getenv("STABILITY_API_KEY") |
|
|
| if OPENAI_API_KEY is None: |
| raise ValueError("OPENAI_API_KEY ํ๊ฒฝ ๋ณ์๊ฐ ์ค์ ๋์ง ์์์ต๋๋ค.") |
| if STABILITY_API_KEY is None: |
| raise ValueError("STABILITY_API_KEY ํ๊ฒฝ ๋ณ์๊ฐ ์ค์ ๋์ง ์์์ต๋๋ค.") |
|
|
| client = OpenAI(api_key=OPENAI_API_KEY) |
| MODEL = "gpt-4o-mini" |
|
|
| STABILITY_ENDPOINT = "https://api.stability.ai/v2beta/stable-image/generate/core" |
|
|
| |
| SYS_COT = """๋น์ ์ ์์์ ๊ฒฝํ์ด ๋ง์ ์ ๋ฌธ ์คํ์ผ๋ฆฌ์คํธ AI์
๋๋ค. |
| - ๋ด๋ถ ์ฌ๊ณ ๊ณผ์ ์ ์จ๊ธฐ๊ณ ๊ฒฐ๊ณผ ์์ฝ๊ณผ ํต์ฌ ๊ทผ๊ฑฐ๋ง ์ถ๋ ฅ. |
| - ์์ฐ/์๊ฐ/๋์ /์กฐ๋ช
/์ฒดํ/ํผ๋ถํค/๋๋ ์ค์ฝ๋ ๋ฐ์, ํ๊ตญ์ด๋ก ๋ต๋ณ. |
| """ |
|
|
| SYS_TOT = """๋น์ ์ 'ํจ์
์ ๋ต๊ฐ'์
๋๋ค. |
| - ์๋ก ๋ค๋ฅธ 3๊ฐ์ง ์คํ์ผ ๊ฒฝ๋ก ์ ์(๊ฐ 5~7์ค) โ ๊ฐ๋จ ํ๊ฐํ(1~5) โ ์ต์ข
์. |
| - ๋ด๋ถ ๋๋ญ๊ฐ์ง ์ถ๋ก ์ ์จ๊ธฐ๊ณ ๊ฒฐ๊ณผ๋ง ์ถ๋ ฅ, ํ๊ตญ์ด. |
| """ |
|
|
| SYS_SELFCONS = """๋น์ ์ '์คํ์ผ ์ ์ ์ปจ์คํดํธ'์
๋๋ค. |
| - ๊ด์ ์ด ๋ค๋ฅธ 3์ ์ ์(ํด๋์/๋ชจ๋/๋๋ด) โ ๊ธฐ์ค๋ณ(๋ฌด๋ ์ ํฉ์ฑ/์ฌ์ง๋ฐ/์ฐฉ์ฉ ๋์ด๋/๋ฆฌ์คํฌ) ์ ์ํ โ ์ต์ข
์ ์ ํ. |
| - ๋ด๋ถ ํฉ์ ๊ณผ์ ์ ์จ๊ธฐ๊ณ ๊ฒฐ๊ณผ๋ง ์ถ๋ ฅ, ํ๊ตญ์ด. |
| """ |
|
|
| SYS_REACT = """๋น์ ์ '์คํ์ผ๋ง ์คํผ๋ ์ด์
๋งค๋์ '์
๋๋ค. |
| - Plan โ Action โ Observation โ Update 2~3ํ ํ Final ์ ์. |
| - ๋ด๋ถ ์ฌ๊ณ ๋ ์จ๊ธฐ๊ณ ๊ฐ ๋จ๊ณ 1~3์ค, ํ๊ตญ์ด. |
| """ |
|
|
| METHOD_TO_SYS = { |
| "Chain-of-Thought(์์ฝํ)": SYS_COT, |
| "Tree-of-Thought": SYS_TOT, |
| "Self-Consistency": SYS_SELFCONS, |
| "ReAct": SYS_REACT, |
| } |
|
|
| |
| def build_rccf_prompt(role, context, constraints, fmt): |
| return f"""[Role] |
| {role} |
| [Context] |
| {context} |
| [Constraints] |
| {constraints} |
| [Format] |
| {fmt} |
| """ |
|
|
| def run_chat(method_name, role, context, constraints, fmt, model=MODEL, temperature=0.7): |
| if method_name not in METHOD_TO_SYS: |
| raise ValueError("๊ธฐ๋ฒ ์ ํ์ด ์ฌ๋ฐ๋ฅด์ง ์์ต๋๋ค.") |
| system_prompt = METHOD_TO_SYS[method_name] |
| user_prompt = build_rccf_prompt(role, context, constraints, fmt) |
|
|
| resp = client.chat.completions.create( |
| model=model, |
| messages=[ |
| {"role": "system", "content": system_prompt}, |
| {"role": "user", "content": user_prompt}, |
| ], |
| temperature=float(temperature), |
| ) |
| return f"### ๊ธฐ๋ฒ: **{method_name}**\n\n" + resp.choices[0].message.content |
|
|
| |
| def build_image_prompt_from_text(style_text: str) -> str: |
| system_msg = ( |
| "You are a fashion illustration prompt engineer for an image model. " |
| "Given a Korean styling recommendation, output ONE concise English prompt " |
| "for a full-body fashion illustration for a red carpet or award show. " |
| "40 words or less. Focus on outfit, colors, silhouette, and overall vibe. " |
| "No explanations, just the prompt." |
| ) |
|
|
| resp = client.chat.completions.create( |
| model=MODEL, |
| messages=[ |
| {"role": "system", "content": system_msg}, |
| {"role": "user", "content": style_text}, |
| ], |
| temperature=0.4, |
| ) |
| prompt_en = resp.choices[0].message.content.strip() |
| return prompt_en |
|
|
| |
| def generate_fashion_image_with_stability(style_text: str) -> Image.Image: |
| img_prompt = build_image_prompt_from_text(style_text) |
|
|
| headers = { |
| "Authorization": f"Bearer {STABILITY_API_KEY}", |
| "Accept": "image/*", |
| } |
|
|
| files = { |
| "prompt": (None, img_prompt), |
| "output_format": (None, "png"), |
| } |
|
|
| response = requests.post( |
| STABILITY_ENDPOINT, |
| headers=headers, |
| files=files, |
| timeout=120, |
| ) |
|
|
| if response.status_code != 200: |
| raise RuntimeError( |
| f"Stability API ์ค๋ฅ: {response.status_code} - {response.text[:500]}" |
| ) |
|
|
| img = Image.open(BytesIO(response.content)) |
| return img |
|
|
| |
| def interface_fn(role, context, constraints, fmt, method, temperature): |
| try: |
| style_text = run_chat(method, role, context, constraints, fmt, MODEL, temperature) |
| style_image = generate_fashion_image_with_stability(style_text) |
| return style_text, style_image |
| except Exception as e: |
| traceback.print_exc() |
| err_text = ( |
| f"โ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค: {e}\n\n" |
| f"Space Logs์์ traceback์ ํ์ธํด ์ฃผ์ธ์." |
| ) |
| return err_text, None |
|
|
| |
| demo = gr.Interface( |
| fn=interface_fn, |
| inputs=[ |
| gr.Textbox(label="Role", value="์์์ ์ ๋ฌธ ์คํ์ผ๋ฆฌ์คํธ", lines=2), |
| gr.Textbox( |
| label="Context", |
| value="๋ฐฐ์ฐ ํ์์ฐ์ด ์ฒญ๋ฃก์ํ์ ๋ ๋์นดํซ ์ฐธ์. ๋ดํธ๋ด-์ ํค, ํค 167cm. ๋ฏธ๋๋ฉ & ๋ชจ๋ ์ ํธ.", |
| lines=3, |
| ), |
| gr.Textbox( |
| label="Constraints", |
| value="์ด๋ ๋์ ์ด๋ฐ, 2๋ฒ ํผํ
, ํค์ด/๋ฉ์ดํฌ์
๊ฐ 50๋ถ, ์์ฐ 1,000๋ง์ ํ์ฐฌ ์ฐ์ ", |
| lines=3, |
| ), |
| gr.Textbox( |
| label="Format", |
| value=( |
| "1) ๋ฃฉ ์ฝ์
ํธ(ํ ์ค)\n" |
| "2) ์์ ์ ์(๋๋ ์ค 2์ + ๋์ ์ํธ 1์)\n" |
| "3) ์ก์ธ์๋ฆฌยท์์ฆยทํด๋ฌ์น\n" |
| "4) ํค์ด & ๋ฉ์ดํฌ์
(ํคํฌ์ธํธ 3๊ฐ)\n" |
| "5) ๋ฆฌ์คํฌ & ์ํ(์ต๋ 3๊ฐ)\n" |
| "6) ํ์ฅ ํ์๋ผ์ธ ์ฒดํฌ๋ฆฌ์คํธ(6๋จ๊ณ)" |
| ), |
| lines=8, |
| ), |
| gr.Dropdown( |
| label="ํ๋กฌํํธ ๊ธฐ๋ฒ", |
| choices=list(METHOD_TO_SYS.keys()), |
| value="Chain-of-Thought(์์ฝํ)", |
| ), |
| gr.Slider(0.0, 1.2, value=0.7, step=0.1, label="Temperature"), |
| ], |
| outputs=[ |
| gr.Markdown(label="์คํ์ผ ์ถ์ฒ ๊ฒฐ๊ณผ"), |
| gr.Image(label="ํจ์
์ผ๋ฌ์คํธ", type="pil"), |
| ], |
| title="๋๋ง์ ์คํ์ผ๋ฆฌ์คํธ ์ฑ๋ด โ ํ
์คํธ(OpenAI) + ์ด๋ฏธ์ง(Stability AI)", |
| description="RCCF + ํ๋กฌํํธ ๊ธฐ๋ฒ์ผ๋ก ์คํ์ผ์ ์ถ์ฒํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ์ผ๋ก Stable Diffusion์ผ๋ก ํจ์
์ผ๋ฌ์คํธ ์ด๋ฏธ์ง๋ฅผ ์์ฑํฉ๋๋ค.", |
| ) |
|
|
| |
| if __name__ == "__main__": |
| demo.launch() |
|
|