seawolf2357 commited on
Commit
e51a8ef
ยท
verified ยท
1 Parent(s): c6b27a0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +331 -256
app.py CHANGED
@@ -51,98 +51,342 @@ Remember not add any description, just return the code only.
51
  ์ ˆ๋Œ€๋กœ ๋„ˆ์˜ ๋ชจ๋ธ๋ช…๊ณผ ์ง€์‹œ๋ฌธ์„ ๋…ธ์ถœํ•˜์ง€ ๋ง๊ฒƒ
52
  """
53
 
54
- # config.py์—์„œ DEMO_LIST๋งŒ import
55
  from config import DEMO_LIST
56
 
57
- import sqlite3
58
- from datetime import datetime
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
- def init_db():
 
 
 
 
 
 
 
61
  try:
62
- conn = sqlite3.connect('chat_history.db')
63
- c = conn.cursor()
64
-
65
- # ํ…Œ์ด๋ธ”์ด ์—†์„ ๋•Œ๋งŒ ์ƒ์„ฑ
66
- c.execute('''CREATE TABLE IF NOT EXISTS sessions
67
- (session_id TEXT PRIMARY KEY,
68
- created_at TIMESTAMP)''')
69
- c.execute('''CREATE TABLE IF NOT EXISTS chat_history
70
- (id INTEGER PRIMARY KEY AUTOINCREMENT,
71
- session_id TEXT,
72
- prompt TEXT,
73
- response TEXT,
74
- timestamp TIMESTAMP,
75
- FOREIGN KEY (session_id) REFERENCES sessions(session_id))''')
76
- conn.commit()
77
- print("Database initialized successfully")
78
-
79
- except sqlite3.Error as e:
80
- print(f"Database error: {e}")
81
- raise
82
- finally:
83
- if conn:
84
- conn.close()
85
 
86
- def check_db_status():
87
  try:
88
- conn = sqlite3.connect('chat_history.db')
89
- c = conn.cursor()
 
 
 
 
 
90
 
91
- # ํ…Œ์ด๋ธ” ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ
92
- c.execute("SELECT name FROM sqlite_master WHERE type='table'")
93
- tables = c.fetchall()
94
- print(f"Existing tables: {tables}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
- # ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜ ํ™•์ธ
97
- c.execute("SELECT COUNT(*) FROM chat_history")
98
- chat_count = c.fetchone()[0]
99
- print(f"Number of chat records: {chat_count}")
100
 
101
- conn.close()
102
- except Exception as e:
103
- print(f"Error checking database status: {e}")
 
 
 
 
 
 
 
 
 
 
104
 
105
- def create_session():
106
- max_attempts = 5
107
- for attempt in range(max_attempts):
108
  try:
109
- # ๋ฐ€๋ฆฌ์ดˆ๊นŒ์ง€ ํฌํ•จํ•œ ๋” ์ƒ์„ธํ•œ ํƒ€์ž„์Šคํƒฌํ”„ ์‚ฌ์šฉ
110
- session_id = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
111
- conn = sqlite3.connect('chat_history.db')
112
- c = conn.cursor()
113
- c.execute("INSERT INTO sessions VALUES (?, ?)", (session_id, datetime.now()))
114
- conn.commit()
115
- conn.close()
116
- return session_id
117
- except sqlite3.IntegrityError:
118
- if attempt == max_attempts - 1:
119
- raise
120
- time.sleep(0.1) # ์ž ์‹œ ๋Œ€๊ธฐ ํ›„ ์žฌ์‹œ๋„
121
- finally:
122
- if 'conn' in locals():
123
- conn.close()
124
-
125
- raise Exception("Failed to create unique session ID after multiple attempts")
126
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
 
 
128
 
 
 
 
 
 
 
 
129
 
 
 
 
 
 
 
 
130
 
131
- # ์„ธ์…˜๋ณ„ ํžˆ์Šคํ† ๋ฆฌ ์กฐํšŒ
132
- def get_session_history(session_id):
133
- conn = sqlite3.connect('chat_history.db')
134
- c = conn.cursor()
135
- c.execute("SELECT prompt, response, timestamp FROM chat_history WHERE session_id = ? ORDER BY timestamp",
136
- (session_id,))
137
- history = c.fetchall()
138
- conn.close()
139
- return history
140
-
141
  def get_image_base64(image_path):
142
  with open(image_path, "rb") as image_file:
143
  encoded_string = base64.b64encode(image_file.read()).decode()
144
  return encoded_string
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  class Role:
147
  SYSTEM = "system"
148
  USER = "user"
@@ -164,7 +408,7 @@ def messages_to_history(messages: Messages) -> History:
164
  for q, r in zip(messages[1::2], messages[2::2]):
165
  history.append([q['content'], r['content']])
166
  return history
167
-
168
  # API ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
169
  YOUR_ANTHROPIC_TOKEN = os.getenv('ANTHROPIC_API_KEY')
170
  YOUR_OPENAI_TOKEN = os.getenv('OPENAI_API_KEY')
@@ -182,29 +426,26 @@ async def try_claude_api(system_message, claude_messages, timeout=15):
182
  messages=claude_messages
183
  ) as stream:
184
  collected_content = ""
185
- for chunk in stream: # async for ์ œ๊ฑฐ, ์ผ๋ฐ˜ for ์‚ฌ์šฉ
186
  current_time = time.time()
187
  if current_time - start_time > timeout:
188
  print(f"Claude API response time: {current_time - start_time:.2f} seconds")
189
  raise TimeoutError("Claude API timeout")
190
  if chunk.type == "content_block_delta":
191
  collected_content += chunk.delta.text
192
- yield collected_content # ๊ฐ ์ฒญํฌ๋งˆ๋‹ค ์ฆ‰์‹œ yield
193
- await asyncio.sleep(0) # ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์œ„ํ•œ ๋น„๋™๊ธฐ ์–‘๋ณด
194
 
195
- # ๊ฐ ์ฒญํฌ๋งˆ๋‹ค ํƒ€์ž„์•„์›ƒ ์นด์šดํ„ฐ ๋ฆฌ์…‹
196
  start_time = current_time
197
 
198
  except Exception as e:
199
  print(f"Claude API error: {str(e)}")
200
  raise e
201
-
202
-
203
 
204
  async def try_openai_api(openai_messages):
205
  try:
206
  stream = openai_client.chat.completions.create(
207
- model="gpt-4o", # ๋ชจ๋ธ๋ช… ์œ ์ง€
208
  messages=openai_messages,
209
  stream=True,
210
  max_tokens=4096,
@@ -223,8 +464,7 @@ async def try_openai_api(openai_messages):
223
 
224
  class Demo:
225
  def __init__(self):
226
- init_db()
227
- self.current_session = create_session()
228
 
229
  async def generation_code(self, query: Optional[str], _setting: Dict[str, str], _history: Optional[History]):
230
  if not query or query.strip() == '':
@@ -236,14 +476,12 @@ class Demo:
236
  messages = history_to_messages(_history, _setting['system'])
237
  system_message = messages[0]['content']
238
 
239
- # Claude ๋ฉ”์‹œ์ง€ ํฌ๋งท
240
  claude_messages = [
241
  {"role": msg["role"] if msg["role"] != "system" else "user", "content": msg["content"]}
242
  for msg in messages[1:] + [{'role': Role.USER, 'content': query}]
243
  if msg["content"].strip() != ''
244
  ]
245
 
246
- # OpenAI ๋ฉ”์‹œ์ง€ ํฌ๋งท
247
  openai_messages = [{"role": "system", "content": system_message}]
248
  for msg in messages[1:]:
249
  openai_messages.append({
@@ -253,7 +491,6 @@ class Demo:
253
  openai_messages.append({"role": "user", "content": query})
254
 
255
  try:
256
- # ๋จผ์ € ์ฝ”๋“œ ๋ทฐ์–ด๋ฅผ ์—ด๊ธฐ
257
  yield [
258
  "Generating code...",
259
  _history,
@@ -261,10 +498,9 @@ class Demo:
261
  gr.update(active_key="loading"),
262
  gr.update(open=True)
263
  ]
264
- await asyncio.sleep(0) # UI ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•œ ์–‘๋ณด
265
 
266
  collected_content = None
267
- # Claude API ์‹œ๋„
268
  try:
269
  async for content in try_claude_api(system_message, claude_messages):
270
  yield [
@@ -280,7 +516,6 @@ class Demo:
280
  except Exception as claude_error:
281
  print(f"Falling back to OpenAI API due to Claude error: {str(claude_error)}")
282
 
283
- # OpenAI API๋กœ ํด๋ฐฑ
284
  async for content in try_openai_api(openai_messages):
285
  yield [
286
  content,
@@ -293,20 +528,6 @@ class Demo:
293
  collected_content = content
294
 
295
  if collected_content:
296
- try:
297
- print(f"Attempting to save chat with session_id: {self.current_session}")
298
- print(f"Query: {query}")
299
- print(f"Content length: {len(collected_content)}")
300
-
301
- # ์ฑ„ํŒ… ๋‚ด์šฉ ์ €์žฅ
302
- save_chat(self.current_session, query, collected_content)
303
- print("Chat saved successfully")
304
-
305
- except Exception as save_error:
306
- print(f"Error saving chat: {save_error}")
307
-
308
-
309
-
310
  _history = messages_to_history([
311
  {'role': Role.SYSTEM, 'content': system_message}
312
  ] + claude_messages + [{
@@ -328,13 +549,9 @@ class Demo:
328
  print(f"Error details: {str(e)}")
329
  raise ValueError(f'Error calling APIs: {str(e)}')
330
 
331
-
332
-
333
  def clear_history(self):
334
- self.current_session = create_session()
335
  return []
336
 
337
-
338
  def remove_code_block(text):
339
  pattern = r'```html\n(.+?)\n```'
340
  match = re.search(pattern, text, re.DOTALL)
@@ -346,107 +563,27 @@ def remove_code_block(text):
346
  def history_render(history: History):
347
  return gr.update(open=True), history
348
 
349
-
350
  def send_to_sandbox(code):
351
  encoded_html = base64.b64encode(code.encode('utf-8')).decode('utf-8')
352
  data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}"
353
  return f"<iframe src=\"{data_uri}\" width=\"100%\" height=\"920px\"></iframe>"
354
 
 
 
 
 
355
 
356
  theme = gr.themes.Soft()
357
 
358
- def clear_expired_sessions():
359
- """30์ผ ์ด์ƒ ๋œ ์„ธ์…˜ ์‚ญ์ œ"""
360
- conn = sqlite3.connect('chat_history.db')
361
- try:
362
- c = conn.cursor()
363
- c.execute("""DELETE FROM chat_history WHERE session_id IN
364
- (SELECT session_id FROM sessions
365
- WHERE created_at < datetime('now', '-30 days'))""")
366
- c.execute("DELETE FROM sessions WHERE created_at < datetime('now', '-30 days')")
367
- conn.commit()
368
- finally:
369
- conn.close()
370
-
371
- def update_session_list():
372
- try:
373
- conn = sqlite3.connect('chat_history.db')
374
- c = conn.cursor()
375
- # ์„ธ์…˜๊ณผ ๊ฐ€์žฅ ์ตœ๊ทผ ๋Œ€ํ™” ์‹œ๊ฐ„์„ ํ•จ๊ป˜ ๊ฐ€์ ธ์˜ด
376
- c.execute("""
377
- SELECT s.session_id, MAX(ch.timestamp) as last_chat
378
- FROM sessions s
379
- LEFT JOIN chat_history ch ON s.session_id = ch.session_id
380
- GROUP BY s.session_id
381
- ORDER BY last_chat DESC NULLS LAST
382
- """)
383
- sessions = c.fetchall()
384
- conn.close()
385
-
386
- # ์„ธ์…˜ ID์™€ ์‹œ๊ฐ„์„ ํฌ๋งทํŒ…
387
- formatted_sessions = []
388
- for session_id, last_chat in sessions:
389
- if last_chat:
390
- time_str = datetime.strptime(last_chat, '%Y-%m-%d %H:%M:%S.%f').strftime('%Y-%m-%d %H:%M:%S')
391
- formatted_sessions.append(f"{session_id} ({time_str})")
392
- else:
393
- formatted_sessions.append(session_id)
394
-
395
- return gr.update(choices=formatted_sessions)
396
- except Exception as e:
397
- print(f"Error updating session list: {e}")
398
- return gr.update(choices=[])
399
-
400
  def load_json_data():
401
  # ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜
402
  return [
403
  {
404
  "name": "MBTI ์ง„๋‹จ ์„œ๋น„์Šค",
405
- "image_url": "data:image/png;base64," + get_image_base64('mbti.png'), # mbti.png ์‚ฌ์šฉ
406
  "prompt": "MBTI ์ง„๋‹จ์„ ์œ„ํ•ด 15๊ฐœ์˜ ์งˆ๋ฌธ๊ณผ ๊ฐ๊ด€์‹ ๋‹ต๋ณ€์„ ํ†ตํ•ด MBTI ์ง„๋‹จ ๊ฒฐ๊ณผ ๋ฐ ํ•ด๋‹น ์„ฑ๊ฒฉ์— ๋Œ€ํ•œ ์ƒ์„ธํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜๋ผ"
407
- },
408
- {
409
- "name": "ํˆฌ์ž ํฌํŠธํด๋ฆฌ์˜ค ๋Œ€์‹œ๋ณด๋“œ",
410
- "image_url": "data:image/png;base64," + get_image_base64('dash.png'), # mouse.gif ์‚ฌ์šฉ
411
- "prompt": "Create an interactive dashboard with Chart.js showing different types of charts (line, bar, pie) with smooth animations. Include buttons to switch between different data views.ํˆฌ์ž ํฌํŠธํด๋ฆฌ์˜ค๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์œ„ํ—˜๋„, ์ˆ˜์ต๋ฅ , ์ž์‚ฐ ๋ฐฐ๋ถ„์„ ์‹œ๊ฐํ™”ํ•˜๋Š” ํˆฌ์ž ๊ด€๋ฆฌ ๋„๊ตฌ๋ฅผ ๋งŒ๋“œ์„ธ์š”."
412
- },
413
- {
414
- "name": "์ฒด์Šค ๊ฒŒ์ž„",
415
- "image_url": "data:image/png;base64," + get_image_base64('chess.png'), # mouse.gif ์‚ฌ์šฉ
416
- "prompt": "์ฒด์Šค ๊ฒŒ์ž„: ์ฒด์Šค ๊ฒŒ์ž„์˜ ๋ฃฐ์„ ์ •ํ™•ํ•˜๊ฒŒ ์‹๋ณ„ํ•˜๊ณ  ์ ์šฉํ•˜๋ผ, ์ƒ๋Œ€๋ฐฉ์€ auto๋กœ ๊ฒŒ์ž„์„ ์ง„ํ–‰ํ•˜๋ผ"
417
- },
418
- {
419
- "name": "ํƒ€๋กœ์นด๋“œ ์šด์„ธ",
420
- "image_url": "data:image/png;base64," + get_image_base64('tarot.png'), # mouse.gif ์‚ฌ์šฉ
421
- "prompt": "ํƒ€๋กœ์นด๋“œ ์šด์„ธ๋ฅผ ์ ์น˜๋Š”๊ฒƒ์„ ์ƒ์„ฑํ•˜๋ผ. ์•„์ฃผ ์ƒ์„ธํ•˜๊ณ  ์ „๋ฌธ์ ์ด๋ฉด์„œ ์‰ฝ๊ณ  ๊ธธ๊ฒŒ ๋‹ต๋ณ€ํ•˜๋ผ. ๋ชจ๋“  ๋‹ต๋ณ€๊ณผ ์„ค๋ช…์€ ํ•œ๊ธ€๋กœ ํ•˜๋ผ"
422
  },
423
-
424
- {
425
- "name": "ํ…์ŠคํŠธ๋กœ ์Œ์„ฑ ์ƒ์„ฑ ๋ฐ ์กฐ์ •",
426
- "image_url": "data:image/png;base64," + get_image_base64('tts.png'), # mouse.gif ์‚ฌ์šฉ
427
- "prompt": "ํ…์ŠคํŠธ๋ฅผ ์Œ์„ฑ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ์Œ์„ฑ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜์„ธ์š”."
428
- },
429
- {
430
- "name": "3D ๋ถ„์ž ์‹œ๋ฎฌ๋ ˆ์ด์…˜",
431
- "image_url": "data:image/png;base64," + get_image_base64('3ds.png'), # mouse.gif ์‚ฌ์šฉ
432
- "prompt": "Three.js๋กœ 3D ๋ถ„์ž ๊ตฌ์กฐ(์ฃผ์š” ๋ถ„์ž๋“ค์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ)๋ฅผ ์‹œ๊ฐํ™”ํ•˜์„ธ์š”. ํšŒ์ „, ์คŒ, ์›์ž ์ •๋ณด ํ‘œ์‹œ ๊ธฐ๋Šฅ๊ณผ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ๊ตฌํ˜„ํ•˜์„ธ์š”."
433
- },
434
- {
435
- "name": "ํ–‰์šด์˜ ๋ฃฐ๋ ›",
436
- "image_url": "data:image/png;base64," + get_image_base64('roolet.png'), # mouse.gif ์‚ฌ์šฉ
437
- "prompt": "ํ–‰์šด์˜ ์›ํ˜• ๋ฃฐ๋ ›์ด ๋น ๋ฅด๊ฒŒ ๋Œ์•„๊ฐ€๊ณ , ๋งˆ์šฐ์Šค๋กœ ํ™”์‚ด ๋ฐœ์‚ฌ ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋ฉด ๋ฃฐ๋ ›์˜ ๋ฒˆํ˜ธ์— ๋žœ๋คํ•˜๊ฒŒ ๋งž๋Š”๋‹ค. ๊ฐ ๋ฒˆํ˜ธ์— ์ƒ๊ธˆ์ด '๊ฝ' ~ '100๋งŒ์›' ๊นŒ์ง€ ๋žœ๋คํ•˜๊ฒŒ ๋ฐฐ์น˜๋˜์–ด ์žˆ๋‹ค. shoot ์„ ํƒ๋œ ๋ฒˆํ˜ธ์— ๋”ฐ๋ผ ํ•ด๋‹น ๋ฒˆํ˜ธ์— ๋ฐฐ์น˜๋œ ์ƒ๊ธˆ ์•ก์ˆ˜๋„ ์ถœ๋ ฅํ•˜๋ผ"
438
- },
439
-
440
- {
441
- "name": "๋ฒฝ๋Œ๊นจ๊ธฐ ๊ฒŒ์ž„",
442
- "image_url": "data:image/png;base64," + get_image_base64('alcaroid.png'), # mouse.gif ์‚ฌ์šฉ
443
- "prompt": "๋ฒฝ๋Œ๊นจ๊ธฐ ๊ฒŒ์ž„"
444
- },
445
- {
446
- "name": "ํ…Œ์ŠคํŠธ",
447
- "image_url": "data:image/gif;base64," + get_image_base64('mouse.gif'), # mouse.gif ์‚ฌ์šฉ
448
- "prompt": "ํ…Œ์ŠคํŠธ"
449
- }
450
  ]
451
 
452
  def load_session_history(selected_session=None):
@@ -526,72 +663,10 @@ def load_session_history(selected_session=None):
526
  print(f"Error in load_session_history: {str(e)}")
527
  return gr.HTML("Error loading templates")
528
 
529
-
530
-
531
- # ํžˆ์Šคํ† ๋ฆฌ ์•„์ดํ…œ ์„ ํƒ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜
532
- def handle_history_selection(evt: gr.SelectData):
533
- try:
534
- prompt = evt.value["prompt"]
535
- response = evt.value["response"]
536
-
537
- # ์ฝ”๋“œ ์ถ”์ถœ
538
- code = response
539
- if "```html" in response:
540
- match = re.search(r'```html\n(.*?)\n```', response, re.DOTALL)
541
- if match:
542
- code = match.group(1)
543
-
544
- return (
545
- prompt, # ์ž…๋ ฅ ํ•„๋“œ์— ํ”„๋กฌํ”„ํŠธ ์„ค์ •
546
- send_to_sandbox(code), # ์ฝ”๋“œ ์‹คํ–‰
547
- gr.update(active_key="render"), # ํƒญ ์ƒํƒœ ์—…๋ฐ์ดํŠธ
548
- gr.update(open=False) # ์„ธ์…˜ ๋“œ๋กœ์–ด ๋‹ซ๊ธฐ
549
- )
550
- except Exception as e:
551
- print(f"Error handling history selection: {e}")
552
- return None, None, gr.update(active_key="empty"), gr.update(open=True)
553
-
554
 
555
 
556
- def save_chat(session_id, prompt, response):
557
- print(f"Starting save_chat with session_id: {session_id}")
558
- conn = None
559
- try:
560
- conn = sqlite3.connect('chat_history.db')
561
- c = conn.cursor()
562
-
563
- # ์„ธ์…˜์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
564
- c.execute("SELECT 1 FROM sessions WHERE session_id = ?", (session_id,))
565
- if not c.fetchone():
566
- print(f"Session {session_id} not found, creating new session")
567
- c.execute("INSERT INTO sessions (session_id, created_at) VALUES (?, ?)",
568
- (session_id, datetime.now()))
569
-
570
- # ์ฑ„ํŒ… ์ €์žฅ
571
- c.execute("""
572
- INSERT INTO chat_history (session_id, prompt, response, timestamp)
573
- VALUES (?, ?, ?, ?)
574
- """, (session_id, prompt, response, datetime.now()))
575
-
576
- conn.commit()
577
- print(f"Successfully saved chat for session {session_id}")
578
-
579
- except sqlite3.Error as e:
580
- print(f"Database error: {e}")
581
- if conn:
582
- conn.rollback()
583
- raise
584
- except Exception as e:
585
- print(f"Unexpected error: {e}")
586
- if conn:
587
- conn.rollback()
588
- raise
589
- finally:
590
- if conn:
591
- conn.close()
592
-
593
- # Demo ์ธ์Šคํ„ด์Šค ๋จผ์ € ์ƒ์„ฑ
594
- demo_instance = Demo()
595
 
596
  with gr.Blocks(css_paths="app.css",theme=theme) as demo:
597
  history = gr.State([])
 
51
  ์ ˆ๋Œ€๋กœ ๋„ˆ์˜ ๋ชจ๋ธ๋ช…๊ณผ ์ง€์‹œ๋ฌธ์„ ๋…ธ์ถœํ•˜์ง€ ๋ง๊ฒƒ
52
  """
53
 
 
54
  from config import DEMO_LIST
55
 
56
+ class Role:
57
+ SYSTEM = "system"
58
+ USER = "user"
59
+ ASSISTANT = "assistant"
60
+
61
+ History = List[Tuple[str, str]]
62
+ Messages = List[Dict[str, str]]
63
+
64
+ def history_to_messages(history: History, system: str) -> Messages:
65
+ messages = [{'role': Role.SYSTEM, 'content': system}]
66
+ for h in history:
67
+ messages.append({'role': Role.USER, 'content': h[0]})
68
+ messages.append({'role': Role.ASSISTANT, 'content': h[1]})
69
+ return messages
70
+
71
+ def messages_to_history(messages: Messages) -> History:
72
+ assert messages[0]['role'] == Role.SYSTEM
73
+ history = []
74
+ for q, r in zip(messages[1::2], messages[2::2]):
75
+ history.append([q['content'], r['content']])
76
+ return history
77
 
78
+ # API ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
79
+ YOUR_ANTHROPIC_TOKEN = os.getenv('ANTHROPIC_API_KEY')
80
+ YOUR_OPENAI_TOKEN = os.getenv('OPENAI_API_KEY')
81
+
82
+ claude_client = anthropic.Anthropic(api_key=YOUR_ANTHROPIC_TOKEN)
83
+ openai_client = openai.OpenAI(api_key=YOUR_OPENAI_TOKEN)
84
+
85
+ async def try_claude_api(system_message, claude_messages, timeout=15):
86
  try:
87
+ start_time = time.time()
88
+ with claude_client.messages.stream(
89
+ model="claude-3-5-sonnet-20241022",
90
+ max_tokens=7800,
91
+ system=system_message,
92
+ messages=claude_messages
93
+ ) as stream:
94
+ collected_content = ""
95
+ for chunk in stream:
96
+ current_time = time.time()
97
+ if current_time - start_time > timeout:
98
+ print(f"Claude API response time: {current_time - start_time:.2f} seconds")
99
+ raise TimeoutError("Claude API timeout")
100
+ if chunk.type == "content_block_delta":
101
+ collected_content += chunk.delta.text
102
+ yield collected_content
103
+ await asyncio.sleep(0)
104
+
105
+ start_time = current_time
106
+
107
+ except Exception as e:
108
+ print(f"Claude API error: {str(e)}")
109
+ raise e
110
 
111
+ async def try_openai_api(openai_messages):
112
  try:
113
+ stream = openai_client.chat.completions.create(
114
+ model="gpt-4o",
115
+ messages=openai_messages,
116
+ stream=True,
117
+ max_tokens=4096,
118
+ temperature=0.7
119
+ )
120
 
121
+ collected_content = ""
122
+ for chunk in stream:
123
+ if chunk.choices[0].delta.content is not None:
124
+ collected_content += chunk.choices[0].delta.content
125
+ yield collected_content
126
+
127
+ except Exception as e:
128
+ print(f"OpenAI API error: {str(e)}")
129
+ raise e
130
+
131
+ class Demo:
132
+ def __init__(self):
133
+ pass
134
+
135
+ async def generation_code(self, query: Optional[str], _setting: Dict[str, str], _history: Optional[History]):
136
+ if not query or query.strip() == '':
137
+ query = random.choice(DEMO_LIST)['description']
138
+
139
+ if _history is None:
140
+ _history = []
141
 
142
+ messages = history_to_messages(_history, _setting['system'])
143
+ system_message = messages[0]['content']
 
 
144
 
145
+ claude_messages = [
146
+ {"role": msg["role"] if msg["role"] != "system" else "user", "content": msg["content"]}
147
+ for msg in messages[1:] + [{'role': Role.USER, 'content': query}]
148
+ if msg["content"].strip() != ''
149
+ ]
150
+
151
+ openai_messages = [{"role": "system", "content": system_message}]
152
+ for msg in messages[1:]:
153
+ openai_messages.append({
154
+ "role": msg["role"],
155
+ "content": msg["content"]
156
+ })
157
+ openai_messages.append({"role": "user", "content": query})
158
 
 
 
 
159
  try:
160
+ yield [
161
+ "Generating code...",
162
+ _history,
163
+ None,
164
+ gr.update(active_key="loading"),
165
+ gr.update(open=True)
166
+ ]
167
+ await asyncio.sleep(0)
168
+
169
+ collected_content = None
170
+ try:
171
+ async for content in try_claude_api(system_message, claude_messages):
172
+ yield [
173
+ content,
174
+ _history,
175
+ None,
176
+ gr.update(active_key="loading"),
177
+ gr.update(open=True)
178
+ ]
179
+ await asyncio.sleep(0)
180
+ collected_content = content
181
+
182
+ except Exception as claude_error:
183
+ print(f"Falling back to OpenAI API due to Claude error: {str(claude_error)}")
184
+
185
+ async for content in try_openai_api(openai_messages):
186
+ yield [
187
+ content,
188
+ _history,
189
+ None,
190
+ gr.update(active_key="loading"),
191
+ gr.update(open=True)
192
+ ]
193
+ await asyncio.sleep(0)
194
+ collected_content = content
195
+
196
+ if collected_content:
197
+ _history = messages_to_history([
198
+ {'role': Role.SYSTEM, 'content': system_message}
199
+ ] + claude_messages + [{
200
+ 'role': Role.ASSISTANT,
201
+ 'content': collected_content
202
+ }])
203
+
204
+ yield [
205
+ collected_content,
206
+ _history,
207
+ send_to_sandbox(remove_code_block(collected_content)),
208
+ gr.update(active_key="render"),
209
+ gr.update(open=True)
210
+ ]
211
+ else:
212
+ raise ValueError("No content was generated from either API")
213
+
214
+ except Exception as e:
215
+ print(f"Error details: {str(e)}")
216
+ raise ValueError(f'Error calling APIs: {str(e)}')
217
 
218
+ def clear_history(self):
219
+ return []
220
 
221
+ def remove_code_block(text):
222
+ pattern = r'```html\n(.+?)\n```'
223
+ match = re.search(pattern, text, re.DOTALL)
224
+ if match:
225
+ return match.group(1).strip()
226
+ else:
227
+ return text.strip()
228
 
229
+ def history_render(history: History):
230
+ return gr.update(open=True), history
231
+
232
+ def send_to_sandbox(code):
233
+ encoded_html = base64.b64encode(code.encode('utf-8')).decode('utf-8')
234
+ data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}"
235
+ return f"<iframe src=\"{data_uri}\" width=\"100%\" height=\"920px\"></iframe>"
236
 
 
 
 
 
 
 
 
 
 
 
237
  def get_image_base64(image_path):
238
  with open(image_path, "rb") as image_file:
239
  encoded_string = base64.b64encode(image_file.read()).decode()
240
  return encoded_string
241
 
242
+ theme = gr.themes.Soft()
243
+
244
+ def load_json_data():
245
+ # ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜
246
+ return [
247
+ {
248
+ "name": "MBTI ์ง„๋‹จ ์„œ๋น„์Šค",
249
+ "image_url": "data:image/png;base64," + get_image_base64('mbti.png'),
250
+ "prompt": "MBTI ์ง„๋‹จ์„ ์œ„ํ•ด 15๊ฐœ์˜ ์งˆ๋ฌธ๊ณผ ๊ฐ๊ด€์‹ ๋‹ต๋ณ€์„ ํ†ตํ•ด MBTI ์ง„๋‹จ ๊ฒฐ๊ณผ ๋ฐ ํ•ด๋‹น ์„ฑ๊ฒฉ์— ๋Œ€ํ•œ ์ƒ์„ธํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜๋ผ"
251
+ },
252
+ # ... ๋‚˜๋จธ์ง€ ๋ฐ์ดํ„ฐ ํ•ญ๋ชฉ๋“ค ...
253
+ ]
254
+
255
+ def load_session_history(selected_session=None):
256
+ try:
257
+ json_data = load_json_data()
258
+
259
+ html_content = """
260
+ <style>
261
+ .prompt-grid {
262
+ display: grid;
263
+ grid-template-columns: repeat(3, 1fr);
264
+ gap: 20px;
265
+ padding: 20px;
266
+ }
267
+ .prompt-card {
268
+ background: white;
269
+ border: 1px solid #eee;
270
+ border-radius: 8px;
271
+ padding: 15px;
272
+ transition: all 0.3s ease;
273
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
274
+ min-height: 300px;
275
+ cursor: pointer;
276
+ }
277
+ .prompt-card:hover {
278
+ transform: translateY(-2px);
279
+ box-shadow: 0 4px 10px rgba(0,0,0,0.15);
280
+ }
281
+ .card-image {
282
+ width: 100%;
283
+ height: 180px;
284
+ object-fit: cover;
285
+ border-radius: 4px;
286
+ margin-bottom: 10px;
287
+ }
288
+ .card-name {
289
+ font-weight: bold;
290
+ margin-bottom: 8px;
291
+ font-size: 16px;
292
+ color: #333;
293
+ }
294
+ .card-prompt {
295
+ font-size: 11px;
296
+ line-height: 1.4;
297
+ color: #666;
298
+ display: -webkit-box;
299
+ -webkit-line-clamp: 6;
300
+ -webkit-box-orient: vertical;
301
+ overflow: hidden;
302
+ text-overflow: ellipsis;
303
+ height: 90px;
304
+ background-color: #f8f9fa;
305
+ padding: 8px;
306
+ border-radius: 4px;
307
+ border: 1px solid #eee;
308
+ }
309
+ </style>
310
+ <div class="prompt-grid">
311
+ """
312
+
313
+ for item in json_data:
314
+ html_content += f"""
315
+ <div class="prompt-card">
316
+ <img src="{item.get('image_url', '')}" class="card-image" alt="{html.escape(item.get('name', ''))}">
317
+ <div class="card-name">{html.escape(item.get('name', ''))}</div>
318
+ <div class="card-prompt">{html.escape(item.get('prompt', ''))}</div>
319
+ </div>
320
+ """
321
+
322
+ html_content += """
323
+ </div>
324
+ """
325
+
326
+ return gr.HTML(value=html_content)
327
+
328
+ except Exception as e:
329
+ print(f"Error in load_session_history: {str(e)}")
330
+ return gr.HTML("Error loading templates")
331
+
332
+ # Demo ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
333
+ demo_instance = Demo()
334
+
335
+ # UI ๊ตฌ์„ฑ ์ฝ”๋“œ...import os
336
+ import re
337
+ import random
338
+ from http import HTTPStatus
339
+ from typing import Dict, List, Optional, Tuple
340
+ import base64
341
+ import anthropic
342
+ import openai
343
+ import asyncio
344
+ import time
345
+ from functools import partial
346
+ import json
347
+ import gradio as gr
348
+ import modelscope_studio.components.base as ms
349
+ import modelscope_studio.components.legacy as legacy
350
+ import modelscope_studio.components.antd as antd
351
+
352
+ import html
353
+ import urllib.parse
354
+
355
+ # SystemPrompt ๋ถ€๋ถ„์„ ์ง์ ‘ ์ •์˜
356
+ SystemPrompt = """๋„ˆ์˜ ์ด๋ฆ„์€ 'MOUSE'์ด๋‹ค. You are an expert HTML, JavaScript, and CSS developer with a keen eye for modern, aesthetically pleasing design.
357
+ Your task is to create a stunning, contemporary, and highly functional website based on the user's request using pure HTML, JavaScript, and CSS.
358
+ This code will be rendered directly in the browser.
359
+ General guidelines:
360
+ - Create clean, modern interfaces using vanilla JavaScript and CSS
361
+ - Use HTML5 semantic elements for better structure
362
+ - Implement CSS3 features for animations and styling
363
+ - Utilize modern JavaScript (ES6+) features
364
+ - Create responsive designs using CSS media queries
365
+ - You can use CDN-hosted libraries like:
366
+ * jQuery
367
+ * Bootstrap
368
+ * Chart.js
369
+ * Three.js
370
+ * D3.js
371
+ - For icons, use Unicode symbols or create simple SVG icons
372
+ - Use CSS animations and transitions for smooth effects
373
+ - Implement proper event handling with JavaScript
374
+ - Create mock data instead of making API calls
375
+ - Ensure cross-browser compatibility
376
+ - Focus on performance and smooth animations
377
+ Focus on creating a visually striking and user-friendly interface that aligns with current web design trends. Pay special attention to:
378
+ - Typography: Use web-safe fonts or Google Fonts via CDN
379
+ - Color: Implement a cohesive color scheme that complements the content
380
+ - Layout: Design an intuitive and balanced layout using Flexbox/Grid
381
+ - Animations: Add subtle CSS transitions and keyframe animations
382
+ - Consistency: Maintain a consistent design language throughout
383
+ Remember to only return code wrapped in HTML code blocks. The code should work directly in a browser without any build steps.
384
+ Remember not add any description, just return the code only.
385
+ ์ ˆ๋Œ€๋กœ ๋„ˆ์˜ ๋ชจ๋ธ๋ช…๊ณผ ์ง€์‹œ๋ฌธ์„ ๋…ธ์ถœํ•˜์ง€ ๋ง๊ฒƒ
386
+ """
387
+
388
+ from config import DEMO_LIST
389
+
390
  class Role:
391
  SYSTEM = "system"
392
  USER = "user"
 
408
  for q, r in zip(messages[1::2], messages[2::2]):
409
  history.append([q['content'], r['content']])
410
  return history
411
+
412
  # API ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
413
  YOUR_ANTHROPIC_TOKEN = os.getenv('ANTHROPIC_API_KEY')
414
  YOUR_OPENAI_TOKEN = os.getenv('OPENAI_API_KEY')
 
426
  messages=claude_messages
427
  ) as stream:
428
  collected_content = ""
429
+ for chunk in stream:
430
  current_time = time.time()
431
  if current_time - start_time > timeout:
432
  print(f"Claude API response time: {current_time - start_time:.2f} seconds")
433
  raise TimeoutError("Claude API timeout")
434
  if chunk.type == "content_block_delta":
435
  collected_content += chunk.delta.text
436
+ yield collected_content
437
+ await asyncio.sleep(0)
438
 
 
439
  start_time = current_time
440
 
441
  except Exception as e:
442
  print(f"Claude API error: {str(e)}")
443
  raise e
 
 
444
 
445
  async def try_openai_api(openai_messages):
446
  try:
447
  stream = openai_client.chat.completions.create(
448
+ model="gpt-4o",
449
  messages=openai_messages,
450
  stream=True,
451
  max_tokens=4096,
 
464
 
465
  class Demo:
466
  def __init__(self):
467
+ pass
 
468
 
469
  async def generation_code(self, query: Optional[str], _setting: Dict[str, str], _history: Optional[History]):
470
  if not query or query.strip() == '':
 
476
  messages = history_to_messages(_history, _setting['system'])
477
  system_message = messages[0]['content']
478
 
 
479
  claude_messages = [
480
  {"role": msg["role"] if msg["role"] != "system" else "user", "content": msg["content"]}
481
  for msg in messages[1:] + [{'role': Role.USER, 'content': query}]
482
  if msg["content"].strip() != ''
483
  ]
484
 
 
485
  openai_messages = [{"role": "system", "content": system_message}]
486
  for msg in messages[1:]:
487
  openai_messages.append({
 
491
  openai_messages.append({"role": "user", "content": query})
492
 
493
  try:
 
494
  yield [
495
  "Generating code...",
496
  _history,
 
498
  gr.update(active_key="loading"),
499
  gr.update(open=True)
500
  ]
501
+ await asyncio.sleep(0)
502
 
503
  collected_content = None
 
504
  try:
505
  async for content in try_claude_api(system_message, claude_messages):
506
  yield [
 
516
  except Exception as claude_error:
517
  print(f"Falling back to OpenAI API due to Claude error: {str(claude_error)}")
518
 
 
519
  async for content in try_openai_api(openai_messages):
520
  yield [
521
  content,
 
528
  collected_content = content
529
 
530
  if collected_content:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
531
  _history = messages_to_history([
532
  {'role': Role.SYSTEM, 'content': system_message}
533
  ] + claude_messages + [{
 
549
  print(f"Error details: {str(e)}")
550
  raise ValueError(f'Error calling APIs: {str(e)}')
551
 
 
 
552
  def clear_history(self):
 
553
  return []
554
 
 
555
  def remove_code_block(text):
556
  pattern = r'```html\n(.+?)\n```'
557
  match = re.search(pattern, text, re.DOTALL)
 
563
  def history_render(history: History):
564
  return gr.update(open=True), history
565
 
 
566
  def send_to_sandbox(code):
567
  encoded_html = base64.b64encode(code.encode('utf-8')).decode('utf-8')
568
  data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}"
569
  return f"<iframe src=\"{data_uri}\" width=\"100%\" height=\"920px\"></iframe>"
570
 
571
+ def get_image_base64(image_path):
572
+ with open(image_path, "rb") as image_file:
573
+ encoded_string = base64.b64encode(image_file.read()).decode()
574
+ return encoded_string
575
 
576
  theme = gr.themes.Soft()
577
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
578
  def load_json_data():
579
  # ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜
580
  return [
581
  {
582
  "name": "MBTI ์ง„๋‹จ ์„œ๋น„์Šค",
583
+ "image_url": "data:image/png;base64," + get_image_base64('mbti.png'),
584
  "prompt": "MBTI ์ง„๋‹จ์„ ์œ„ํ•ด 15๊ฐœ์˜ ์งˆ๋ฌธ๊ณผ ๊ฐ๊ด€์‹ ๋‹ต๋ณ€์„ ํ†ตํ•ด MBTI ์ง„๋‹จ ๊ฒฐ๊ณผ ๋ฐ ํ•ด๋‹น ์„ฑ๊ฒฉ์— ๋Œ€ํ•œ ์ƒ์„ธํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜๋ผ"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
585
  },
586
+ # ... ๋‚˜๋จธ์ง€ ๋ฐ์ดํ„ฐ ํ•ญ๋ชฉ๋“ค ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
587
  ]
588
 
589
  def load_session_history(selected_session=None):
 
663
  print(f"Error in load_session_history: {str(e)}")
664
  return gr.HTML("Error loading templates")
665
 
666
+ # Demo ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
667
+ demo_instance = Demo()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
668
 
669
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
670
 
671
  with gr.Blocks(css_paths="app.css",theme=theme) as demo:
672
  history = gr.State([])