aiqcamp's picture
Update app.py
edcf253 verified
raw
history blame
10.7 kB
import os
import gradio as gr
import random
import time
import logging
import google.generativeai as genai
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler("api_debug.log"),
logging.StreamHandler()
]
)
logger = logging.getLogger("idea_generator")
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
genai.configure(api_key=GEMINI_API_KEY)
def choose_alternative(transformation):
if "/" not in transformation:
return transformation
parts = transformation.split("/")
if len(parts) != 2:
return random.choice([part.strip() for part in parts])
left = parts[0].strip()
right = parts[1].strip()
if " " in left:
tokens = left.split(" ", 1)
prefix = tokens[0]
if not right.startswith(prefix):
option1 = left
option2 = prefix + " " + right
else:
option1 = left
option2 = right
return random.choice([option1, option2])
else:
return random.choice([left, right])
physical_transformation_categories = {
"곡간 이동": [
"μ•ž/λ’€ 이동", "쒌/우 이동", "μœ„/μ•„λž˜ 이동", "μ„Έλ‘œμΆ• νšŒμ „(고개 λ„λ•μž„)",
"κ°€λ‘œμΆ• νšŒμ „(고개 μ “κΈ°)", "길이좕 νšŒμ „(μ˜†μœΌλ‘œ κΈ°μšΈμž„)", "원 μš΄λ™", "λ‚˜μ„ ν˜• 이동",
"관성에 μ˜ν•œ λ―Έλ„λŸ¬μ§", "νšŒμ „μΆ• λ³€ν™”", "λΆˆκ·œμΉ™ νšŒμ „", "흔듀림 μš΄λ™", "포물선 이동",
"무쀑λ ₯ λΆ€μœ ", "수면 μœ„ λΆ€μœ ", "점프/도약", "μŠ¬λΌμ΄λ”©", "둀링", "자유 λ‚™ν•˜",
"왕볡 μš΄λ™", "탄성 νŠ•κΉ€", "관톡", "νšŒν”Ό μ›€μ§μž„", "μ§€κ·Έμž¬κ·Έ 이동", "μŠ€μœ™ μš΄λ™"
],
"크기와 ν˜•νƒœ λ³€ν™”": [
"λΆ€ν”Ό λŠ˜μ–΄λ‚¨/쀄어듦", "길이 λŠ˜μ–΄λ‚¨/쀄어듦", "λ„ˆλΉ„ λŠ˜μ–΄λ‚¨/쀄어듦", "높이 λŠ˜μ–΄λ‚¨/쀄어듦",
"밀도 λ³€ν™”", "무게 증가/κ°μ†Œ", "λͺ¨μ–‘ λ³€ν˜•", "μƒνƒœ λ³€ν™”", "λΆˆκ· λ“± λ³€ν˜•",
"λ³΅μž‘ν•œ ν˜•νƒœ λ³€ν˜•", "λΉ„ν‹€λ¦Ό/κΌ¬μž„", "λΆˆκ· μΌν•œ ν™•μž₯/μΆ•μ†Œ", "λͺ¨μ„œλ¦¬ λ‘₯κΈ€κ²Œ/λ‚ μΉ΄λ‘­κ²Œ",
"깨짐/갈라짐", "μ—¬λŸ¬ 쑰각 λ‚˜λˆ μ§", "λ¬Ό μ €ν•­", "λ¨Όμ§€ μ €ν•­", "찌그러짐/볡원",
"μ ‘νž˜/펼쳐짐", "μ••μ°©/팽창", "λŠ˜μ–΄λ‚¨/μˆ˜μΆ•", "ꡬ겨짐/평평해짐", "λ­‰κ°œμ§/단단해짐",
"말림/펴짐", "κΊΎμž„/κ΅¬λΆ€λŸ¬μ§"
],
# ... (쀑간 μƒλž΅: λ‚˜λ¨Έμ§€ μΉ΄ν…Œκ³ λ¦¬λŠ” 동일)
# μƒλž΅λœ 뢀뢄도 κΈ°μ‘΄ μ½”λ“œ κ·ΈλŒ€λ‘œ μœ μ§€
}
def query_gemini_api(prompt):
try:
model = genai.GenerativeModel('gemini-2.0-flash-thinking-exp-01-21')
response = model.generate_content(prompt)
try:
if hasattr(response, 'text'):
return response.text
if hasattr(response, 'candidates') and response.candidates:
if len(response.candidates) > 0:
candidate = response.candidates[0]
if hasattr(candidate, 'content'):
content = candidate.content
if hasattr(content, 'parts') and content.parts:
if len(content.parts) > 0:
return content.parts[0].text
if hasattr(response, 'parts') and response.parts:
if len(response.parts) > 0:
return response.parts[0].text
return "Unable to generate a response. API response structure is different than expected."
except Exception as inner_e:
logger.error(f"Error processing response: {inner_e}")
return f"An error occurred while processing the response: {str(inner_e)}"
except Exception as e:
logger.error(f"Error calling Gemini API: {e}")
if "API key not valid" in str(e):
return "API key is not valid. Please check your GEMINI_API_KEY environment variable."
return f"An error occurred while calling the API: {str(e)}"
def enhance_with_llm(base_description, obj_name, category):
prompt = f"""
λ‹€μŒμ€ '{obj_name}'의 '{category}' κ΄€λ ¨ κ°„λ‹¨ν•œ μ„€λͺ…μž…λ‹ˆλ‹€:
"{base_description}"
μœ„ λ‚΄μš©μ„ 보닀 κ΅¬μ²΄ν™”ν•˜μ—¬,
1) 창의적인 λͺ¨λΈ/컨셉/ν˜•μƒμ˜ 변화에 λŒ€ν•œ 이해,
2) ν˜μ‹  ν¬μΈνŠΈμ™€ κΈ°λŠ₯μ„± 등을 μ€‘μ‹¬μœΌλ‘œ
3~4λ¬Έμž₯의 μ•„μ΄λ””μ–΄λ‘œ ν™•μž₯ν•΄ μ£Όμ„Έμš”.
"""
return query_gemini_api(prompt)
def generate_single_object_transformations(obj):
results = {}
for category, transformations in physical_transformation_categories.items():
transformation = choose_alternative(random.choice(transformations))
base_description = f"{obj}이(κ°€) {transformation} ν˜„μƒμ„ 보인닀"
results[category] = {"base": base_description, "enhanced": None}
return results
def generate_two_objects_interaction(obj1, obj2):
results = {}
for category, transformations in physical_transformation_categories.items():
transformation = choose_alternative(random.choice(transformations))
template = random.choice([
"{obj1}이(κ°€) {obj2}에 κ²°ν•©ν•˜μ—¬ {change}κ°€ λ°œμƒν–ˆλ‹€",
"{obj1}κ³Ό(와) {obj2}이(κ°€) μΆ©λŒν•˜λ©΄μ„œ {change}κ°€ 일어났닀"
])
base_description = template.format(obj1=obj1, obj2=obj2, change=transformation)
results[category] = {"base": base_description, "enhanced": None}
return results
def generate_three_objects_interaction(obj1, obj2, obj3):
results = {}
for category, transformations in physical_transformation_categories.items():
transformation = choose_alternative(random.choice(transformations))
template = random.choice([
"{obj1}, {obj2}, {obj3}이(κ°€) μ‚Όκ°ν˜• ꡬ쑰둜 κ²°ν•©ν•˜μ—¬ {change}κ°€ λ°œμƒν–ˆλ‹€",
"{obj1}이(κ°€) {obj2}와(κ³Ό) {obj3} μ‚¬μ΄μ—μ„œ 맀개체 역할을 ν•˜λ©° {change}λ₯Ό μ΄‰μ§„ν–ˆλ‹€"
])
base_description = template.format(obj1=obj1, obj2=obj2, obj3=obj3, change=transformation)
results[category] = {"base": base_description, "enhanced": None}
return results
def enhance_descriptions(results, objects):
obj_name = " 및 ".join([obj for obj in objects if obj])
for category, result in results.items():
result["enhanced"] = enhance_with_llm(result["base"], obj_name, category)
return results
def generate_transformations(text1, text2=None, text3=None):
if text2 and text3:
results = generate_three_objects_interaction(text1, text2, text3)
objects = [text1, text2, text3]
elif text2:
results = generate_two_objects_interaction(text1, text2)
objects = [text1, text2]
else:
results = generate_single_object_transformations(text1)
objects = [text1]
return enhance_descriptions(results, objects)
def format_results(results):
formatted = ""
for category, result in results.items():
formatted += f"## {category}\n**κΈ°λ³Έ 아이디어**: {result['base']}\n\n**ν™•μž₯된 아이디어**: {result['enhanced']}\n\n---\n\n"
return formatted
##############################################################################
# 슀트리밍(Streaming) λ°©μ‹μœΌλ‘œ 좜λ ₯ν•˜λŠ” ν•¨μˆ˜: yieldλ₯Ό μ‚¬μš©
##############################################################################
def process_inputs_stream(text1, text2, text3):
# 1) 첫 λ©”μ‹œμ§€
yield "μž…λ ₯κ°’ 확인 쀑..."
time.sleep(0.3)
text1 = text1.strip() if text1 else None
text2 = text2.strip() if text2 else None
text3 = text3.strip() if text3 else None
if not text1:
yield "였λ₯˜: μ΅œμ†Œ ν•˜λ‚˜μ˜ ν‚€μ›Œλ“œλ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”."
return # μ—¬κΈ°μ„œ ν•¨μˆ˜ μ’…λ£Œ
# 2) λ‹€μŒ λ©”μ‹œμ§€
yield "창의적인 λͺ¨λΈ/컨셉/ν˜•μƒ λ³€ν™” 아이디어 생성 쀑..."
time.sleep(0.3)
# 3) μ‹€μ œ 아이디어 생성
results = generate_transformations(text1, text2, text3)
# 4) 쀑간 단계 좜λ ₯
yield "κ²°κ³Ό ν¬λ§·νŒ… 쀑..."
time.sleep(0.3)
# 5) μ΅œμ’… κ²°κ³Ό 정리
formatted = format_results(results)
# 6) κ²°κ³Ό 좜λ ₯
yield formatted
# 7) μ™„λ£Œ
yield "μ™„λ£Œ!"
def get_warning_message():
if not GEMINI_API_KEY:
return "⚠️ ν™˜κ²½ λ³€μˆ˜ GEMINI_API_KEYκ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. Gemini API ν‚€λ₯Ό μ„€μ •ν•˜μ„Έμš”."
return ""
with gr.Blocks(title="ν‚€μ›Œλ“œ 기반 창의적 λ³€ν™” 아이디어 생성기",
theme=gr.themes.Soft(primary_hue="teal", secondary_hue="slate", neutral_hue="neutral")) as demo:
gr.HTML("""
<style>
body { background: linear-gradient(135deg, #e0eafc, #cfdef3); font-family: 'Arial', sans-serif; }
.gradio-container { padding: 20px; }
h1, h2 { text-align: center; }
h1 { color: #333; }
h2 { color: #555; }
.output { background-color: #ffffff; padding: 15px; border-radius: 8px; }
.gr-button { background-color: #4CAF50; color: white; border: none; border-radius: 4px; padding: 8px 16px; }
</style>
""")
gr.Markdown("# πŸš€ ν‚€μ›Œλ“œ 기반 창의적 λ³€ν™” 아이디어 생성기")
gr.Markdown("μž…λ ₯ν•œ **ν‚€μ›Œλ“œ**(μ΅œλŒ€ 3개)λ₯Ό λ°”νƒ•μœΌλ‘œ, **창의적인 λͺ¨λΈ/컨셉/ν˜•μƒ λ³€ν™”**에 λŒ€ν•œ 이해와 **ν˜μ‹  포인트**, **κΈ°λŠ₯μ„±** 등을 μ€‘μ‹¬μœΌλ‘œ ν™•μž₯된 아이디어λ₯Ό μ œμ‹œν•©λ‹ˆλ‹€.")
warning = gr.Markdown(get_warning_message())
with gr.Row():
with gr.Column(scale=1):
text_input1 = gr.Textbox(label="ν‚€μ›Œλ“œ 1 (ν•„μˆ˜)", placeholder="예: 슀마트폰")
text_input2 = gr.Textbox(label="ν‚€μ›Œλ“œ 2 (선택)", placeholder="예: 인곡지λŠ₯")
text_input3 = gr.Textbox(label="ν‚€μ›Œλ“œ 3 (선택)", placeholder="예: ν—¬μŠ€μΌ€μ–΄")
submit_button = gr.Button("아이디어 μƒμ„±ν•˜κΈ°")
with gr.Column(scale=2):
with gr.TabItem("창의적인 λͺ¨λΈ/컨셉/ν˜•μƒ λ³€ν™” 아이디어", id="creative_tab"):
# Markdown 좜λ ₯
idea_output = gr.Markdown(label="아이디어 κ²°κ³Ό")
gr.Examples(
examples=[
["슀마트폰", "", ""],
["컀피", "μ±…", ""],
["μžλ™μ°¨", "λ‘œλ΄‡", "인곡지λŠ₯"],
["μš΄λ™ν™”", "μ›¨μ–΄λŸ¬λΈ”", "건강"],
],
inputs=[text_input1, text_input2, text_input3],
)
# stream=True μ˜΅μ…˜μ„ 톡해 ν•¨μˆ˜κ°€ yieldν•˜λŠ” λ¬Έμžμ—΄μ„ μ‹€μ‹œκ°„ 좜λ ₯
submit_button.click(
fn=process_inputs_stream,
inputs=[text_input1, text_input2, text_input3],
outputs=idea_output,
stream=True
)
if __name__ == "__main__":
demo.launch(debug=True)