Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -5,7 +5,7 @@ import time
|
|
5 |
import logging
|
6 |
import google.generativeai as genai
|
7 |
|
8 |
-
#
|
9 |
logging.basicConfig(
|
10 |
level=logging.INFO,
|
11 |
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
@@ -16,11 +16,11 @@ logging.basicConfig(
|
|
16 |
)
|
17 |
logger = logging.getLogger("idea_generator")
|
18 |
|
19 |
-
#
|
20 |
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
21 |
genai.configure(api_key=GEMINI_API_KEY)
|
22 |
|
23 |
-
#
|
24 |
def choose_alternative(transformation):
|
25 |
if "/" not in transformation:
|
26 |
return transformation
|
@@ -42,7 +42,7 @@ def choose_alternative(transformation):
|
|
42 |
else:
|
43 |
return random.choice([left, right])
|
44 |
|
45 |
-
#
|
46 |
physical_transformation_categories = {
|
47 |
"๊ณต๊ฐ์ ๋ณํ": [
|
48 |
"์ ์ง/ํ์ง ์ด๋", "์ข/์ฐ ์ด๋", "์์น/ํ๊ฐ", "ํผ์น ํ์ ", "์ ํ์ ", "๋กค ํ์ ",
|
@@ -101,103 +101,33 @@ physical_transformation_categories = {
|
|
101 |
]
|
102 |
}
|
103 |
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
"๋ธ๋๋๋ช
๋ณ๊ฒฝ/๋ฆฌ๋ธ๋๋ฉ", "๋ก๊ณ ์ฌ์ค๊ณ/ํ๋ํ", "์ฌ๋ก๊ฑด ์
๋ฐ์ดํธ/๋ณ๊ฒฝ",
|
108 |
-
"๋ธ๋๋ ์ปฌ๋ฌ ํ๋ ํธ ๋ณ๊ฒฝ", "๋ธ๋๋ ๋ณด์ด์ค/ํค ์กฐ์ ", "๋ธ๋๋ ํฌ์ง์
๋ ์ฌ์ ๋ฆฝ",
|
109 |
-
"๋ธ๋๋ ์คํ ๋ฆฌ ์ฌ๊ตฌ์ฑ", "๋ธ๋๋ ์ํคํ
์ฒ ์ฌ๊ตฌ์ฑ", "๋ธ๋๋ ํผ์ค๋๋ฆฌํฐ ์งํ",
|
110 |
-
"๋ธ๋๋ ์ด๋ฏธ์ง ์ฌ์ ๋ฆฝ"
|
111 |
-
],
|
112 |
-
"์ ํ/์๋น์ค ๋ณํ": [
|
113 |
-
"๊ธฐ๋ฅ์ ์
๊ทธ๋ ์ด๋/๋ค์ด๊ทธ๋ ์ด๋", "ํฌ์ฅ/ํจํค์ง ์ฌ์ค๊ณ", "์ ํ ์ฌ์ด์ฆ/์ฉ๋ ์กฐ์ ",
|
114 |
-
"SKU ํ์ฅ/์ถ์", "๋ง์ถคํ/๊ฐ์ธํ ์ต์
์ถ๊ฐ", "ํ๋ฆฌ๋ฏธ์/๋ฒ ์ด์ง ๋ผ์ธ ์ถ์",
|
115 |
-
"ํ์ ํ/์์ฆ ์๋์
์ถ์", "์ฝ๋ผ๋ณด๋ ์ด์
/ํฌ๋ก์ค์ค๋ฒ ์ ํ", "์ง์๊ฐ๋ฅ์ฑ ๊ฐ์ ",
|
116 |
-
"๋ฒ๋ค๋ง/์ธ๋ฒ๋ค๋ง ์ ๋ต ๋ณ๊ฒฝ"
|
117 |
-
],
|
118 |
-
"๊ฐ๊ฒฉ ์ ๋ต ๋ณํ": [
|
119 |
-
"ํ๋ฆฌ๋ฏธ์/๋ญ์
๋ฆฌ ๊ฐ๊ฒฉ ํฌ์ง์
๋", "๊ฐ๊ฒฉ ํ๋ฝ/๊ฒฝ์ ์ ํฌ์ง์
๋", "๊ฐ์น ๊ธฐ๋ฐ ๊ฐ๊ฒฉ ์ฑ
์ ",
|
120 |
-
"๋์ ๊ฐ๊ฒฉ ์ ์ฑ
๋์
", "๋ฉค๋ฒ์ญ/๊ตฌ๋
๋ชจ๋ธ ์ ํ", "๊ฐ๊ฒฉ ์ธ๋ถํ ์ ๋ต",
|
121 |
-
"ํ๋ก๋ชจ์
๊ฐ๊ฒฉ ์ ๋ต ๋ณ๊ฒฝ", "์ฌ๋ฆฌ์ ๊ฐ๊ฒฉ ์ฑ
์ ์ ์ฉ", "๋ฒ๋ค ๊ฐ๊ฒฉ ์ ๋ต ๋์
",
|
122 |
-
"ํ๋ฆฌ๋ฏธ์/์ด์ฝ๋
ธ๋ฏธ ์ด์ค ์ ๋ต"
|
123 |
-
],
|
124 |
-
"ํ๋ก๋ชจ์
/์ปค๋ฎค๋์ผ์ด์
๋ณํ": [
|
125 |
-
"๋ฉ์์ง ํ๋ ์ด๋ฐ ๋ณ๊ฒฝ", "ํ๊ฒ ์ค๋์ธ์ค ํ์ฅ/์ฌ์ ์", "๊ฐ์ฑ์ /์ด์ฑ์ ์๊ตฌ์ ์ ํ",
|
126 |
-
"์คํ ๋ฆฌํ
๋ง ๋ฐฉ์ ๋ณํ", "์ฝํ
์ธ ๋ง์ผํ
์ ๋ต ์กฐ์ ", "ํฌ๋ฆฌ์์ดํฐ๋ธ ๋ฐฉํฅ์ฑ ๋ณ๊ฒฝ",
|
127 |
-
"๊ด๊ณ ์บ ํ์ธ ์ฌ์ค๊ณ", "๋ธ๋๋ ์ฐ๋ฐฐ์๋/์ธํ๋ฃจ์ธ์ ๊ต์ฒด", "์ธ์ด/ํธ๋ก ์กฐ์ ",
|
128 |
-
"๋น์ฃผ์ผ ์์ด๋ดํฐํฐ ์
๋ฐ์ดํธ"
|
129 |
-
],
|
130 |
-
"์ฑ๋/์ ํต ๋ณํ": [
|
131 |
-
"์จ๋ผ์ธ/์คํ๋ผ์ธ ์ ๋ต ์ ํ", "์ด๋์ฑ๋ ํตํฉ/๋ถ๋ฆฌ", "์ ํต ํํธ๋์ญ ํ์ฅ/์ถ์",
|
132 |
-
"D2C(Direct-to-Consumer) ๋ชจ๋ธ ๋์
", "๋ฆฌํ
์ผ ๊ฒฝํ ์ฌ์ค๊ณ", "์๋น์ค ๋๋ฆฌ๋ฒ๋ฆฌ ๋ฐฉ์ ๋ณ๊ฒฝ",
|
133 |
-
"ํ์
/์ด๋ฒคํธ ๊ธฐ๋ฐ ์ ํต ์ ๋ต", "์ง์ญ์ ํ์ฅ/์ถ์", "ํํธ๋ ์ํ๊ณ ์ฌ๊ตฌ์ฑ",
|
134 |
-
"๋์งํธ ๋ง์ผํ๋ ์ด์ค ์ ๋ต ๋ณํ"
|
135 |
-
],
|
136 |
-
"๊ณ ๊ฐ ๊ฒฝํ ๋ณํ": [
|
137 |
-
"๊ณ ๊ฐ ์ฌ์ ์ฌ์ค๊ณ", "ํผ์ค๋๋ผ์ด์ ์ด์
/๋ง์ถคํ ๊ฐํ", "์๋น์ค ๋ ๋ฒจ ์กฐ์ ",
|
138 |
-
"๋ก์ดํฐ ํ๋ก๊ทธ๋จ ์ฌ๊ตฌ์ฑ", "๊ณ ๊ฐ ์ฐธ์ฌ ๋ฉ์ปค๋์ฆ ๋ณํ", "์ฌ์ฉ์ ์ธํฐํ์ด์ค/UX ๊ฐ์ ",
|
139 |
-
"๊ณ ๊ฐ ์๋น์ค ํ๋กํ ์ฝ ๋ณ๊ฒฝ", "ํผ๋๋ฐฑ ๋ฃจํ ์ฌ์ค๊ณ", "์๊ฐ ์๋น์ค ์ต์
ํ์ฅ",
|
140 |
-
"์ฒดํํ ๋ง์ผํ
์์ ๊ฐํ"
|
141 |
-
],
|
142 |
-
"๋์งํธ ๋ง์ผํ
๋ณํ": [
|
143 |
-
"๊ฒ์ ์ต์ ํ(SEO) ์ ๋ต ๋ณ๊ฒฝ", "์์
๋ฏธ๋์ด ํ๋ซํผ ํฌํธํด๋ฆฌ์ค ์กฐ์ ", "์ฝํ
์ธ ํ์
/ํฌ๋งท ๋ค์ํ",
|
144 |
-
"๋ฐ์ดํฐ ๊ธฐ๋ฐ ํ๊ฒํ
์ ๊ตํ", "๋ง์ผํ
์๋ํ ํ์ฅ/์กฐ์ ", "๋์งํธ ๊ด๊ณ ์๊ณ ๋ฆฌ์ฆ ์ต์ ํ",
|
145 |
-
"์ด๋ฉ์ผ ๋ง์ผํ
์ ๋ต ๋ณํ", "๋ชจ๋ฐ์ผ ์ต์ ํ ์ ๋ต ๊ฐํ", "AR/VR ๋ง์ผํ
์์ ํตํฉ",
|
146 |
-
"์ธ๊ณต์ง๋ฅ ๊ธฐ๋ฐ ๋ง์ผํ
๋์
"
|
147 |
-
],
|
148 |
-
"์์ฅ ํฌ์ง์
๋ ๋ณํ": [
|
149 |
-
"์์ฅ ์ธ๊ทธ๋จผํธ ์ฌ์ ์", "๊ฒฝ์์ฌ ๋๋น ํฌ์ง์
๋ ๋ณ๊ฒฝ", "ํ์์์ฅ/๋ฉ์ธ์คํธ๋ฆผ ์ ๋ต ์ ํ",
|
150 |
-
"์ฐ์
/์นดํ
๊ณ ๋ฆฌ ํก๋จ ์ฌํฌ์ง์
๋", "์ง๋ฆฌ์ ํ๊ฒ ์์ฅ ํ์ฅ/์ถ์", "๊ธ๋ก๋ฒ/๋ก์ปฌ ํฌ์ง์
๋ ์กฐ์ ",
|
151 |
-
"๋ฌธํ์ ๋งฅ๋ฝ ์ ์", "์ฃผ์ ์์ฅ ๋ฉ์์ง ์ฌ์ ์", "ํน์ฑ ์ฐจ๋ณํ ๊ฐํ/๋ณ๊ฒฝ",
|
152 |
-
"๊ฐ์น ์ ์ ์ฌ๊ตฌ์ฑ"
|
153 |
-
],
|
154 |
-
"ํ์ /ํธ๋ ๋ ๋ฐ์": [
|
155 |
-
"์ฒจ๋จ ๊ธฐ์ ํตํฉ", "ํธ๋ ๋ ์ผ๋ฆฌ์ด๋ตํฐ/ํ๋ก์ ํฌ์ง์
๋", "์ง์๊ฐ๋ฅ์ฑ/์นํ๊ฒฝ ์ ๋ต ๊ฐํ",
|
156 |
-
"์ฌํ์ ์ฑ
์ ์ด๋์
ํฐ๋ธ ๋์
", "๋์งํธ ํธ๋์คํฌ๋ฉ์ด์
๊ฐ์ํ", "ํฌ์ค/์ฐ๋น ์์ ๊ฐํ",
|
157 |
-
"์ธ๋๋ณ ํธ๋ ๋ ๋ฐ์ ์ ์ฉ", "๋ฏธ๋์งํฅ์ ํ์ ์ปค๋ฎค๋์ผ์ด์
", "๋ฌธํ์ ํ์ ์ฐ๊ณ ๋ง์ผํ
",
|
158 |
-
"ํฌ๋ก์ค ์ธ๋์คํธ๋ฆฌ ํ์ ์ ์ฉ"
|
159 |
-
],
|
160 |
-
"๋ฐ์ดํฐ/๋ถ์ ๊ธฐ๋ฐ ๋ณํ": [
|
161 |
-
"๊ณ ๊ฐ ๋ฐ์ดํฐ ์์ง ๋ฐฉ์ ๋ณ๊ฒฝ", "์์ธก ๋ถ์ ๋ชจ๋ธ ๋์
/๊ฐํ", "A/B ํ
์คํ
์ฒด๊ณ ๊ตฌ์ถ/ํ์ฅ",
|
162 |
-
"์๋น์ ์ธ์ฌ์ดํธ ๋ฐ๊ตด ๋ฐฉ์ ๋ณํ", "๋ง์ผํ
ROI ์ธก์ ํ๋ ์์ํฌ ๋ณ๊ฒฝ", "์ค์๊ฐ ๋ฐ์ดํฐ ํ์ฉ ์ฒด๊ณ ๊ตฌ์ถ",
|
163 |
-
"ํ๋ผ์ด๋ฒ์ ์ค์ฌ ๋ฐ์ดํฐ ์ ๋ต", "์ธ๊ทธ๋จผํ
์ด์
๋ชจ๋ธ ๊ณ ๋ํ", "๋์งํธ ํ๋ ๋ถ์ ์ฒด๊ณ ๊ฐํ",
|
164 |
-
"ํตํฉ ๋ง์ผํ
๋ฐ์ดํฐ ๋์๋ณด๋ ๊ตฌ์ถ"
|
165 |
-
]
|
166 |
-
}
|
167 |
-
|
168 |
def query_gemini_api(prompt):
|
169 |
try:
|
170 |
-
#
|
171 |
model = genai.GenerativeModel('gemini-2.0-flash-thinking-exp-01-21')
|
172 |
|
173 |
-
# Generate content with a simple approach
|
174 |
response = model.generate_content(prompt)
|
175 |
-
|
176 |
-
#
|
177 |
try:
|
178 |
-
# First try .text attribute
|
179 |
if hasattr(response, 'text'):
|
180 |
return response.text
|
181 |
|
182 |
-
# Try accessing candidates (safely)
|
183 |
if hasattr(response, 'candidates') and response.candidates:
|
184 |
if len(response.candidates) > 0:
|
185 |
candidate = response.candidates[0]
|
186 |
-
|
187 |
-
# Try accessing content and parts
|
188 |
if hasattr(candidate, 'content'):
|
189 |
content = candidate.content
|
190 |
-
|
191 |
if hasattr(content, 'parts') and content.parts:
|
192 |
if len(content.parts) > 0:
|
193 |
return content.parts[0].text
|
194 |
-
|
195 |
-
# Direct parts access attempt
|
196 |
if hasattr(response, 'parts') and response.parts:
|
197 |
if len(response.parts) > 0:
|
198 |
return response.parts[0].text
|
199 |
-
|
200 |
-
# Fallback if all attempts fail
|
201 |
return "Unable to generate a response. API response structure is different than expected."
|
202 |
|
203 |
except Exception as inner_e:
|
@@ -206,23 +136,29 @@ def query_gemini_api(prompt):
|
|
206 |
|
207 |
except Exception as e:
|
208 |
logger.error(f"Error calling Gemini API: {e}")
|
209 |
-
|
210 |
-
# Check for API key validation error
|
211 |
if "API key not valid" in str(e):
|
212 |
return "API key is not valid. Please check your GEMINI_API_KEY environment variable."
|
213 |
-
|
214 |
return f"An error occurred while calling the API: {str(e)}"
|
215 |
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
|
|
|
|
220 |
"{base_description}"
|
221 |
-
|
|
|
|
|
|
|
|
|
|
|
222 |
return query_gemini_api(prompt)
|
223 |
|
224 |
-
|
225 |
-
|
|
|
|
|
226 |
results = {}
|
227 |
for category, transformations in physical_transformation_categories.items():
|
228 |
transformation = choose_alternative(random.choice(transformations))
|
@@ -230,17 +166,10 @@ def generate_single_object_physical_transformations(obj):
|
|
230 |
results[category] = {"base": base_description, "enhanced": None}
|
231 |
return results
|
232 |
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
transformation = choose_alternative(random.choice(transformations))
|
238 |
-
base_description = f"{obj}์ด(๊ฐ) {transformation} ์ ๋ต์ ์คํํ๋ค"
|
239 |
-
results[category] = {"base": base_description, "enhanced": None}
|
240 |
-
return results
|
241 |
-
|
242 |
-
# Generate physical transformations for two objects
|
243 |
-
def generate_two_objects_physical_interaction(obj1, obj2):
|
244 |
results = {}
|
245 |
for category, transformations in physical_transformation_categories.items():
|
246 |
transformation = choose_alternative(random.choice(transformations))
|
@@ -252,21 +181,10 @@ def generate_two_objects_physical_interaction(obj1, obj2):
|
|
252 |
results[category] = {"base": base_description, "enhanced": None}
|
253 |
return results
|
254 |
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
transformation = choose_alternative(random.choice(transformations))
|
260 |
-
template = random.choice([
|
261 |
-
"{obj1}์ด(๊ฐ) {obj2}์ ๋ธ๋๋ ํน์ฑ์ ํ์ฉํ์ฌ {change}๋ฅผ ์งํํ๋ค",
|
262 |
-
"{obj1}๊ณผ(์) {obj2}์ ํ์
์ผ๋ก {change}๊ฐ ์์ฅ์ ๋์
๋์๋ค"
|
263 |
-
])
|
264 |
-
base_description = template.format(obj1=obj1, obj2=obj2, change=transformation)
|
265 |
-
results[category] = {"base": base_description, "enhanced": None}
|
266 |
-
return results
|
267 |
-
|
268 |
-
# Generate physical transformations for three objects
|
269 |
-
def generate_three_objects_physical_interaction(obj1, obj2, obj3):
|
270 |
results = {}
|
271 |
for category, transformations in physical_transformation_categories.items():
|
272 |
transformation = choose_alternative(random.choice(transformations))
|
@@ -278,82 +196,43 @@ def generate_three_objects_physical_interaction(obj1, obj2, obj3):
|
|
278 |
results[category] = {"base": base_description, "enhanced": None}
|
279 |
return results
|
280 |
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
transformation = choose_alternative(random.choice(transformations))
|
286 |
-
template = random.choice([
|
287 |
-
"{obj1}, {obj2}, {obj3}์ด(๊ฐ) ๊ณต๋ ๋ง์ผํ
์ผ๋ก {change}๊ฐ ์๋์ง๋ฅผ ์ฐฝ์ถํ๋ค",
|
288 |
-
"{obj1}์ด(๊ฐ) {obj2}์(๊ณผ) {obj3}์ ๊ณ ๊ฐ์ธต์ ํตํฉํ์ฌ {change}๋ก ์๋ก์ด ์์ฅ์ ์ฐฝ์ถํ๋ค"
|
289 |
-
])
|
290 |
-
base_description = template.format(obj1=obj1, obj2=obj2, obj3=obj3, change=transformation)
|
291 |
-
results[category] = {"base": base_description, "enhanced": None}
|
292 |
-
return results
|
293 |
-
|
294 |
-
# Enhance descriptions using the LLM
|
295 |
-
def enhance_descriptions(results, objects, is_marketing=False):
|
296 |
obj_name = " ๋ฐ ".join([obj for obj in objects if obj])
|
297 |
for category, result in results.items():
|
298 |
-
result["enhanced"] = enhance_with_llm(result["base"], obj_name, category
|
299 |
return results
|
300 |
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
objects = [text1, text2, text3]
|
306 |
-
elif text2:
|
307 |
-
results = generate_two_objects_physical_interaction(text1, text2)
|
308 |
-
objects = [text1, text2]
|
309 |
-
else:
|
310 |
-
results = generate_single_object_physical_transformations(text1)
|
311 |
-
objects = [text1]
|
312 |
-
return enhance_descriptions(results, objects, is_marketing=False)
|
313 |
-
|
314 |
-
# Generate marketing transformations based on number of objects
|
315 |
-
def generate_marketing_transformations(text1, text2=None, text3=None):
|
316 |
if text2 and text3:
|
317 |
-
results =
|
318 |
objects = [text1, text2, text3]
|
319 |
elif text2:
|
320 |
-
results =
|
321 |
objects = [text1, text2]
|
322 |
else:
|
323 |
-
results =
|
324 |
objects = [text1]
|
325 |
-
return enhance_descriptions(results, objects
|
326 |
|
327 |
-
|
|
|
|
|
328 |
def format_results(results):
|
329 |
formatted = ""
|
330 |
for category, result in results.items():
|
331 |
-
formatted += f"## {category}\n**๊ธฐ๋ณธ
|
332 |
return formatted
|
333 |
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
time.sleep(0.3)
|
339 |
-
text1 = text1.strip() if text1 else None
|
340 |
-
text2 = text2.strip() if text2 else None
|
341 |
-
text3 = text3.strip() if text3 else None
|
342 |
-
if not text1:
|
343 |
-
messages.append("์ค๋ฅ: ์ต์ ํ๋์ ํค์๋๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.")
|
344 |
-
return "\n\n".join(messages)
|
345 |
-
messages.append("๋ฌผ๋ฆฌ์ ๋ณํ ์์ด๋์ด ์์ฑ ์ค...")
|
346 |
-
time.sleep(0.3)
|
347 |
-
results = generate_physical_transformations(text1, text2, text3)
|
348 |
-
messages.append("๊ฒฐ๊ณผ ํฌ๋งทํ
์ค...")
|
349 |
-
time.sleep(0.3)
|
350 |
-
formatted = format_results(results)
|
351 |
-
messages.append("์๋ฃ!")
|
352 |
-
messages.append(formatted)
|
353 |
-
return "\n\n".join(messages)
|
354 |
-
|
355 |
-
# Process marketing inputs and generate transformations
|
356 |
-
def process_marketing_inputs(text1, text2, text3):
|
357 |
messages = []
|
358 |
messages.append("์
๋ ฅ๊ฐ ํ์ธ ์ค...")
|
359 |
time.sleep(0.3)
|
@@ -363,24 +242,34 @@ def process_marketing_inputs(text1, text2, text3):
|
|
363 |
if not text1:
|
364 |
messages.append("์ค๋ฅ: ์ต์ ํ๋์ ํค์๋๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.")
|
365 |
return "\n\n".join(messages)
|
366 |
-
|
|
|
367 |
time.sleep(0.3)
|
368 |
-
results =
|
|
|
369 |
messages.append("๊ฒฐ๊ณผ ํฌ๋งทํ
์ค...")
|
370 |
time.sleep(0.3)
|
371 |
formatted = format_results(results)
|
|
|
372 |
messages.append("์๋ฃ!")
|
373 |
messages.append(formatted)
|
|
|
374 |
return "\n\n".join(messages)
|
375 |
|
376 |
-
|
|
|
|
|
377 |
def get_warning_message():
|
378 |
if not GEMINI_API_KEY:
|
379 |
return "โ ๏ธ ํ๊ฒฝ ๋ณ์ GEMINI_API_KEY๊ฐ ์ค์ ๋์ง ์์์ต๋๋ค. Gemini API ํค๋ฅผ ์ค์ ํ์ธ์."
|
380 |
return ""
|
381 |
|
382 |
-
|
383 |
-
|
|
|
|
|
|
|
|
|
384 |
gr.HTML("""
|
385 |
<style>
|
386 |
body { background: linear-gradient(135deg, #e0eafc, #cfdef3); font-family: 'Arial', sans-serif; }
|
@@ -392,23 +281,26 @@ with gr.Blocks(title="ํค์๋ ๊ธฐ๋ฐ ์ฐฝ์์ ์์ด๋์ด ์์ฑ๊ธฐ", theme=
|
|
392 |
.gr-button { background-color: #4CAF50; color: white; border: none; border-radius: 4px; padding: 8px 16px; }
|
393 |
</style>
|
394 |
""")
|
395 |
-
|
396 |
-
gr.Markdown("
|
|
|
|
|
397 |
warning = gr.Markdown(get_warning_message())
|
|
|
|
|
398 |
with gr.Row():
|
399 |
with gr.Column(scale=1):
|
400 |
text_input1 = gr.Textbox(label="ํค์๋ 1 (ํ์)", placeholder="์: ์ค๋งํธํฐ")
|
401 |
text_input2 = gr.Textbox(label="ํค์๋ 2 (์ ํ)", placeholder="์: ์ธ๊ณต์ง๋ฅ")
|
402 |
text_input3 = gr.Textbox(label="ํค์๋ 3 (์ ํ)", placeholder="์: ํฌ์ค์ผ์ด")
|
403 |
submit_button = gr.Button("์์ด๋์ด ์์ฑํ๊ธฐ")
|
|
|
|
|
404 |
with gr.Column(scale=2):
|
405 |
-
with gr.
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
marketing_output = gr.Markdown(label="๋ง์ผํ
๋ณํ ์์ด๋์ด ๊ฒฐ๊ณผ")
|
410 |
-
|
411 |
-
# Add some example combinations
|
412 |
gr.Examples(
|
413 |
examples=[
|
414 |
["์ค๋งํธํฐ", "", ""],
|
@@ -419,9 +311,10 @@ with gr.Blocks(title="ํค์๋ ๊ธฐ๋ฐ ์ฐฝ์์ ์์ด๋์ด ์์ฑ๊ธฐ", theme=
|
|
419 |
inputs=[text_input1, text_input2, text_input3],
|
420 |
)
|
421 |
|
422 |
-
#
|
423 |
-
submit_button.click(fn=
|
424 |
-
|
|
|
425 |
|
426 |
if __name__ == "__main__":
|
427 |
-
demo.launch(debug=True)
|
|
|
5 |
import logging
|
6 |
import google.generativeai as genai
|
7 |
|
8 |
+
# ๋ก๊น
์ค์
|
9 |
logging.basicConfig(
|
10 |
level=logging.INFO,
|
11 |
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
|
16 |
)
|
17 |
logger = logging.getLogger("idea_generator")
|
18 |
|
19 |
+
# Gemini API ํค๋ ํ๊ฒฝ ๋ณ์ GEMINI_API_KEY์์ ๊ฐ์ ธ์ต๋๋ค.
|
20 |
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
21 |
genai.configure(api_key=GEMINI_API_KEY)
|
22 |
|
23 |
+
# ์ฌ๋์("/")๊ฐ ํฌํจ๋ ๋ณํ ๋ฌธ์์ด์์ ๋ ์ต์
์ค ํ๋๋ง ์ ํํ๋ ํฌํผ ํจ์
|
24 |
def choose_alternative(transformation):
|
25 |
if "/" not in transformation:
|
26 |
return transformation
|
|
|
42 |
else:
|
43 |
return random.choice([left, right])
|
44 |
|
45 |
+
# ์ฐฝ์์ ์ธ ๋ชจ๋ธ/์ปจ์
/ํ์ ๋ณํ ์์ด๋์ด๋ฅผ ์ํ ์นดํ
๊ณ ๋ฆฌ (๊ธฐ์กด '๋ฌผ๋ฆฌ์ ๋ณํ' ์ฌ์ ์ ์ง)
|
46 |
physical_transformation_categories = {
|
47 |
"๊ณต๊ฐ์ ๋ณํ": [
|
48 |
"์ ์ง/ํ์ง ์ด๋", "์ข/์ฐ ์ด๋", "์์น/ํ๊ฐ", "ํผ์น ํ์ ", "์ ํ์ ", "๋กค ํ์ ",
|
|
|
101 |
]
|
102 |
}
|
103 |
|
104 |
+
##############################################################################
|
105 |
+
# Gemini API ํธ์ถ ํจ์ (์: gemini-2.0-flash-thinking-exp-01-21 -> ๋ค๋ฅธ ๋ชจ๋ธ ์ฌ์ฉ ์ ์์ )
|
106 |
+
##############################################################################
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
def query_gemini_api(prompt):
|
108 |
try:
|
109 |
+
# ์์: ๊ธฐ์กด gemini-2.0... ๋์ , ๋ค๋ฅธ ๋ชจ๋ธ์ด ํ์ํ๋ค๋ฉด ๊ต์ฒดํ์ธ์.
|
110 |
model = genai.GenerativeModel('gemini-2.0-flash-thinking-exp-01-21')
|
111 |
|
|
|
112 |
response = model.generate_content(prompt)
|
113 |
+
|
114 |
+
# ์๋ต ๊ตฌ์กฐ ๋ฐฉ์ด์ ์ผ๋ก ์ฒ๋ฆฌ
|
115 |
try:
|
|
|
116 |
if hasattr(response, 'text'):
|
117 |
return response.text
|
118 |
|
|
|
119 |
if hasattr(response, 'candidates') and response.candidates:
|
120 |
if len(response.candidates) > 0:
|
121 |
candidate = response.candidates[0]
|
|
|
|
|
122 |
if hasattr(candidate, 'content'):
|
123 |
content = candidate.content
|
|
|
124 |
if hasattr(content, 'parts') and content.parts:
|
125 |
if len(content.parts) > 0:
|
126 |
return content.parts[0].text
|
|
|
|
|
127 |
if hasattr(response, 'parts') and response.parts:
|
128 |
if len(response.parts) > 0:
|
129 |
return response.parts[0].text
|
130 |
+
|
|
|
131 |
return "Unable to generate a response. API response structure is different than expected."
|
132 |
|
133 |
except Exception as inner_e:
|
|
|
136 |
|
137 |
except Exception as e:
|
138 |
logger.error(f"Error calling Gemini API: {e}")
|
|
|
|
|
139 |
if "API key not valid" in str(e):
|
140 |
return "API key is not valid. Please check your GEMINI_API_KEY environment variable."
|
|
|
141 |
return f"An error occurred while calling the API: {str(e)}"
|
142 |
|
143 |
+
##############################################################################
|
144 |
+
# ์ค๋ช
ํ์ฅ ํจ์: "๋ชจ๋ธ/์ปจ์
/ํ์์ ๋ณํ์ ๋ํ ์ดํด์ ํ์ ํฌ์ธํธ, ๊ธฐ๋ฅ์ฑ ๋ฑ์ ์ค์ฌ"์ผ๋ก
|
145 |
+
##############################################################################
|
146 |
+
def enhance_with_llm(base_description, obj_name, category):
|
147 |
+
prompt = f"""
|
148 |
+
๋ค์์ '{obj_name}'์ '{category}' ๊ด๋ จ ๊ฐ๋จํ ์ค๋ช
์
๋๋ค:
|
149 |
"{base_description}"
|
150 |
+
|
151 |
+
์ ๋ด์ฉ์ ๋ณด๋ค ๊ตฌ์ฒดํํ์ฌ,
|
152 |
+
1) ์ฐฝ์์ ์ธ ๋ชจ๋ธ/์ปจ์
/ํ์์ ๋ณํ์ ๋ํ ์ดํด,
|
153 |
+
2) ํ์ ํฌ์ธํธ์ ๊ธฐ๋ฅ์ฑ ๋ฑ์ ์ค์ฌ์ผ๋ก
|
154 |
+
3~4๋ฌธ์ฅ์ ์์ด๋์ด๋ก ํ์ฅํด ์ฃผ์ธ์.
|
155 |
+
"""
|
156 |
return query_gemini_api(prompt)
|
157 |
|
158 |
+
##############################################################################
|
159 |
+
# ๋จ์ผ ํค์๋(์ค๋ธ์ ํธ)์ ๋ํ "์ฐฝ์์ ๋ณํ ์์ด๋์ด" ์์ฑ
|
160 |
+
##############################################################################
|
161 |
+
def generate_single_object_transformations(obj):
|
162 |
results = {}
|
163 |
for category, transformations in physical_transformation_categories.items():
|
164 |
transformation = choose_alternative(random.choice(transformations))
|
|
|
166 |
results[category] = {"base": base_description, "enhanced": None}
|
167 |
return results
|
168 |
|
169 |
+
##############################################################################
|
170 |
+
# ๋ ํค์๋์ ๋ํ "์ฐฝ์์ ๋ณํ ์์ด๋์ด" ์์ฑ
|
171 |
+
##############################################################################
|
172 |
+
def generate_two_objects_interaction(obj1, obj2):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
results = {}
|
174 |
for category, transformations in physical_transformation_categories.items():
|
175 |
transformation = choose_alternative(random.choice(transformations))
|
|
|
181 |
results[category] = {"base": base_description, "enhanced": None}
|
182 |
return results
|
183 |
|
184 |
+
##############################################################################
|
185 |
+
# ์ธ ํค์๋์ ๋ํ "์ฐฝ์์ ๋ณํ ์์ด๋์ด" ์์ฑ
|
186 |
+
##############################################################################
|
187 |
+
def generate_three_objects_interaction(obj1, obj2, obj3):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
results = {}
|
189 |
for category, transformations in physical_transformation_categories.items():
|
190 |
transformation = choose_alternative(random.choice(transformations))
|
|
|
196 |
results[category] = {"base": base_description, "enhanced": None}
|
197 |
return results
|
198 |
|
199 |
+
##############################################################################
|
200 |
+
# ์์ฑ๋ ๊ธฐ๋ณธ ์ค๋ช
์ LLM์ ํตํด ํ์ฅ
|
201 |
+
##############################################################################
|
202 |
+
def enhance_descriptions(results, objects):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
obj_name = " ๋ฐ ".join([obj for obj in objects if obj])
|
204 |
for category, result in results.items():
|
205 |
+
result["enhanced"] = enhance_with_llm(result["base"], obj_name, category)
|
206 |
return results
|
207 |
|
208 |
+
##############################################################################
|
209 |
+
# ์ฌ์ฉ์ ์
๋ ฅ(์ต๋ 3๊ฐ ํค์๋)์ ๋ฐ๋ผ ์ฐฝ์์ ๋ณํ ์์ด๋์ด ์์ฑ
|
210 |
+
##############################################################################
|
211 |
+
def generate_transformations(text1, text2=None, text3=None):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
if text2 and text3:
|
213 |
+
results = generate_three_objects_interaction(text1, text2, text3)
|
214 |
objects = [text1, text2, text3]
|
215 |
elif text2:
|
216 |
+
results = generate_two_objects_interaction(text1, text2)
|
217 |
objects = [text1, text2]
|
218 |
else:
|
219 |
+
results = generate_single_object_transformations(text1)
|
220 |
objects = [text1]
|
221 |
+
return enhance_descriptions(results, objects)
|
222 |
|
223 |
+
##############################################################################
|
224 |
+
# ๊ฒฐ๊ณผ ํฌ๋งทํ
|
225 |
+
##############################################################################
|
226 |
def format_results(results):
|
227 |
formatted = ""
|
228 |
for category, result in results.items():
|
229 |
+
formatted += f"## {category}\n**๊ธฐ๋ณธ ์์ด๋์ด**: {result['base']}\n\n**ํ์ฅ๋ ์์ด๋์ด**: {result['enhanced']}\n\n---\n\n"
|
230 |
return formatted
|
231 |
|
232 |
+
##############################################################################
|
233 |
+
# Gradio UI์์ ํธ์ถํ ํจ์
|
234 |
+
##############################################################################
|
235 |
+
def process_inputs(text1, text2, text3):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
messages = []
|
237 |
messages.append("์
๋ ฅ๊ฐ ํ์ธ ์ค...")
|
238 |
time.sleep(0.3)
|
|
|
242 |
if not text1:
|
243 |
messages.append("์ค๋ฅ: ์ต์ ํ๋์ ํค์๋๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.")
|
244 |
return "\n\n".join(messages)
|
245 |
+
|
246 |
+
messages.append("์ฐฝ์์ ์ธ ๋ชจ๋ธ/์ปจ์
/ํ์ ๋ณํ ์์ด๋์ด ์์ฑ ์ค...")
|
247 |
time.sleep(0.3)
|
248 |
+
results = generate_transformations(text1, text2, text3)
|
249 |
+
|
250 |
messages.append("๊ฒฐ๊ณผ ํฌ๋งทํ
์ค...")
|
251 |
time.sleep(0.3)
|
252 |
formatted = format_results(results)
|
253 |
+
|
254 |
messages.append("์๋ฃ!")
|
255 |
messages.append(formatted)
|
256 |
+
|
257 |
return "\n\n".join(messages)
|
258 |
|
259 |
+
##############################################################################
|
260 |
+
# API ํค ๊ฒฝ๊ณ ๋ฉ์์ง
|
261 |
+
##############################################################################
|
262 |
def get_warning_message():
|
263 |
if not GEMINI_API_KEY:
|
264 |
return "โ ๏ธ ํ๊ฒฝ ๋ณ์ GEMINI_API_KEY๊ฐ ์ค์ ๋์ง ์์์ต๋๋ค. Gemini API ํค๋ฅผ ์ค์ ํ์ธ์."
|
265 |
return ""
|
266 |
|
267 |
+
##############################################################################
|
268 |
+
# Gradio UI
|
269 |
+
##############################################################################
|
270 |
+
with gr.Blocks(title="ํค์๋ ๊ธฐ๋ฐ ์ฐฝ์์ ๋ณํ ์์ด๋์ด ์์ฑ๊ธฐ",
|
271 |
+
theme=gr.themes.Soft(primary_hue="teal", secondary_hue="slate", neutral_hue="neutral")) as demo:
|
272 |
+
|
273 |
gr.HTML("""
|
274 |
<style>
|
275 |
body { background: linear-gradient(135deg, #e0eafc, #cfdef3); font-family: 'Arial', sans-serif; }
|
|
|
281 |
.gr-button { background-color: #4CAF50; color: white; border: none; border-radius: 4px; padding: 8px 16px; }
|
282 |
</style>
|
283 |
""")
|
284 |
+
|
285 |
+
gr.Markdown("# ๐ ํค์๋ ๊ธฐ๋ฐ ์ฐฝ์์ ๋ณํ ์์ด๋์ด ์์ฑ๊ธฐ")
|
286 |
+
gr.Markdown("์
๋ ฅํ **ํค์๋**(์ต๋ 3๊ฐ)๋ฅผ ๋ฐํ์ผ๋ก, **์ฐฝ์์ ์ธ ๋ชจ๋ธ/์ปจ์
/ํ์ ๋ณํ**์ ๋ํ ์ดํด์ **ํ์ ํฌ์ธํธ**, **๊ธฐ๋ฅ์ฑ** ๋ฑ์ ์ค์ฌ์ผ๋ก ํ์ฅ๋ ์์ด๋์ด๋ฅผ ์ ์ํฉ๋๋ค.")
|
287 |
+
|
288 |
warning = gr.Markdown(get_warning_message())
|
289 |
+
|
290 |
+
# ์ข์ธก ์
๋ ฅ ์์ญ
|
291 |
with gr.Row():
|
292 |
with gr.Column(scale=1):
|
293 |
text_input1 = gr.Textbox(label="ํค์๋ 1 (ํ์)", placeholder="์: ์ค๋งํธํฐ")
|
294 |
text_input2 = gr.Textbox(label="ํค์๋ 2 (์ ํ)", placeholder="์: ์ธ๊ณต์ง๋ฅ")
|
295 |
text_input3 = gr.Textbox(label="ํค์๋ 3 (์ ํ)", placeholder="์: ํฌ์ค์ผ์ด")
|
296 |
submit_button = gr.Button("์์ด๋์ด ์์ฑํ๊ธฐ")
|
297 |
+
|
298 |
+
# ์ฐ์ธก ์ถ๋ ฅ ์์ญ (ํญ์ ํ๋๋ง ์ฌ์ฉ)
|
299 |
with gr.Column(scale=2):
|
300 |
+
with gr.TabItem("์ฐฝ์์ ์ธ ๋ชจ๋ธ/์ปจ์
/ํ์ ๋ณํ ์์ด๋์ด", id="creative_tab"):
|
301 |
+
idea_output = gr.Markdown(label="์์ด๋์ด ๊ฒฐ๊ณผ")
|
302 |
+
|
303 |
+
# ์์ ์
๋ ฅ
|
|
|
|
|
|
|
304 |
gr.Examples(
|
305 |
examples=[
|
306 |
["์ค๋งํธํฐ", "", ""],
|
|
|
311 |
inputs=[text_input1, text_input2, text_input3],
|
312 |
)
|
313 |
|
314 |
+
# ๋ฒํผ ์ด๋ฒคํธ: ์ฒซ ๋ฒ์งธ ํญ์๋ง ์ฐ๊ฒฐ
|
315 |
+
submit_button.click(fn=process_inputs,
|
316 |
+
inputs=[text_input1, text_input2, text_input3],
|
317 |
+
outputs=idea_output)
|
318 |
|
319 |
if __name__ == "__main__":
|
320 |
+
demo.launch(debug=True)
|