seawolf2357 commited on
Commit
6516b92
ยท
verified ยท
1 Parent(s): ec2806b

Update app-backup1.py

Browse files
Files changed (1) hide show
  1. app-backup1.py +631 -156
app-backup1.py CHANGED
@@ -5,21 +5,143 @@ from http import HTTPStatus
5
  from typing import Dict, List, Optional, Tuple
6
  import base64
7
  import anthropic
 
 
 
8
  from functools import partial
9
-
10
  import gradio as gr
11
  import modelscope_studio.components.base as ms
12
  import modelscope_studio.components.legacy as legacy
13
  import modelscope_studio.components.antd as antd
14
- from config import DEMO_LIST, SystemPrompt
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  def get_image_base64(image_path):
17
  with open(image_path, "rb") as image_file:
18
  encoded_string = base64.b64encode(image_file.read()).decode()
19
  return encoded_string
20
-
21
- YOUR_API_TOKEN = os.getenv('ANTHROPIC_API_KEY')
22
- client = anthropic.Anthropic(api_key=YOUR_API_TOKEN)
23
 
24
  class Role:
25
  SYSTEM = "system"
@@ -42,35 +164,72 @@ def messages_to_history(messages: Messages) -> History:
42
  for q, r in zip(messages[1::2], messages[2::2]):
43
  history.append([q['content'], r['content']])
44
  return history
 
 
 
 
45
 
46
- def remove_code_block(text):
47
- pattern = r'```html\n(.+?)\n```'
48
- match = re.search(pattern, text, re.DOTALL)
49
- if match:
50
- return match.group(1).strip()
51
- else:
52
- return text.strip()
53
 
54
- def history_render(history: History):
55
- return gr.update(open=True), history
56
 
57
- def clear_history():
58
- return []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
- def send_to_sandbox(code):
61
- encoded_html = base64.b64encode(code.encode('utf-8')).decode('utf-8')
62
- data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}"
63
- return f"<iframe src=\"{data_uri}\" width=\"100%\" height=\"920px\"></iframe>"
64
 
65
- with gr.Blocks(css_paths="app.css") as demo:
66
- history = gr.State([])
67
- setting = gr.State({
68
- "system": SystemPrompt,
69
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
- def generation_code(query: Optional[str], _setting: Dict[str, str], _history: Optional[History]):
 
 
 
 
 
72
  if not query or query.strip() == '':
73
- query = random.choice(DEMO_LIST)['description'] # ๋นˆ ์ฟผ๋ฆฌ์ผ ๊ฒฝ์šฐ ๋žœ๋ค ์˜ˆ์ œ ์‚ฌ์šฉ
74
 
75
  if _history is None:
76
  _history = []
@@ -78,13 +237,24 @@ with gr.Blocks(css_paths="app.css") as demo:
78
  messages = history_to_messages(_history, _setting['system'])
79
  system_message = messages[0]['content']
80
 
 
81
  claude_messages = [
82
  {"role": msg["role"] if msg["role"] != "system" else "user", "content": msg["content"]}
83
  for msg in messages[1:] + [{'role': Role.USER, 'content': query}]
84
- if msg["content"].strip() != '' # ๋นˆ ๋ฉ”์‹œ์ง€ ํ•„ํ„ฐ๋ง
85
  ]
86
 
 
 
 
 
 
 
 
 
 
87
  try:
 
88
  yield [
89
  "Generating code...",
90
  _history,
@@ -92,34 +262,59 @@ with gr.Blocks(css_paths="app.css") as demo:
92
  gr.update(active_key="loading"),
93
  gr.update(open=True)
94
  ]
95
-
96
- with client.messages.stream(
97
- model="claude-3-5-sonnet-20241022",
98
- max_tokens=7800,
99
- system=system_message,
100
- messages=claude_messages
101
- ) as stream:
102
- collected_content = ""
103
- for chunk in stream:
104
- if chunk.type == "content_block_delta":
105
- delta = chunk.delta.text
106
- collected_content += delta
107
-
108
- yield [
109
- collected_content,
110
- _history,
111
- None,
112
- gr.update(active_key="loading"),
113
- gr.update(open=True)
114
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
 
 
 
 
 
 
 
 
 
116
  _history = messages_to_history([
117
  {'role': Role.SYSTEM, 'content': system_message}
118
  ] + claude_messages + [{
119
  'role': Role.ASSISTANT,
120
- 'content': collected_content
121
  }])
122
-
123
  yield [
124
  collected_content,
125
  _history,
@@ -127,15 +322,333 @@ with gr.Blocks(css_paths="app.css") as demo:
127
  gr.update(active_key="render"),
128
  gr.update(open=True)
129
  ]
130
-
 
 
131
  except Exception as e:
132
- print(f"Error details: {str(e)}") # ๋””๋ฒ„๊น…์„ ์œ„ํ•œ ์—๋Ÿฌ ์ถœ๋ ฅ
133
- raise ValueError(f'Error calling Claude API: {str(e)}')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
  with ms.Application() as app:
136
  with antd.ConfigProvider():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  # ๋ฉ”์ธ ์ปจํ…์ธ ๋ฅผ ์œ„ํ•œ Row
138
- with antd.Row(gutter=[32, 12]) as layout:
139
  # ์ขŒ์ธก ํŒจ๋„
140
  with antd.Col(span=24, md=8):
141
  with antd.Flex(vertical=True, gap="middle", wrap=True):
@@ -158,100 +671,15 @@ with gr.Blocks(css_paths="app.css") as demo:
158
  execute_btn = antd.Button("Code ์‹คํ–‰", type="default", size="large")
159
  clear_btn = antd.Button("Clear", type="default", size="large")
160
 
161
- # Examples ๋ฒ„ํŠผ๋“ค ์ถ”๊ฐ€
162
- antd.Divider("Try these examples")
163
-
164
- # ๋‘ ๋ฒˆ์งธ ์˜ˆ์ œ ๋ฒ„ํŠผ
165
- example_btn0 = antd.Button(
166
- "MBTI ์ง„๋‹จ ์„œ๋น„์Šค",
167
- type="default",
168
- block=True,
169
- size="large"
170
- )
171
- example_btn0.click(
172
- fn=lambda: "MBTI ์ง„๋‹จ์„ ์œ„ํ•ด 15๊ฐœ์˜ ์งˆ๋ฌธ๊ณผ ๊ฐ๊ด€์‹ ๋‹ต๋ณ€์„ ํ†ตํ•ด MBTI ์ง„๋‹จ ๊ฒฐ๊ณผ ๋ฐ ํ•ด๋‹น ์„ฑ๊ฒฉ์— ๋Œ€ํ•œ ์ƒ์„ธํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜๋ผ",
173
- inputs=[],
174
- outputs=[input]
175
- )
176
-
177
- # ์ฒซ ๋ฒˆ์งธ ์˜ˆ์ œ ๋ฒ„ํŠผ
178
- example_btn1 = antd.Button(
179
- "๋‹ค์ด๋‚˜๋ฏน ์ฐจํŠธ ๋Œ€์‰ฌ๋ณด๋“œ",
180
- type="default",
181
- block=True,
182
- size="large"
183
- )
184
- example_btn1.click(
185
- fn=lambda: "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.",
186
- inputs=[],
187
- outputs=[input]
188
- )
189
-
190
- # ๋‘ ๋ฒˆ์งธ ์˜ˆ์ œ ๋ฒ„ํŠผ
191
- example_btn2 = antd.Button(
192
- "[๊ฒŒ์ž„] ์นด๋“œ ๊ธฐ์–ต๋ ฅ",
193
- type="default",
194
- block=True,
195
- size="large"
196
- )
197
- example_btn2.click(
198
- fn=lambda: "Create a classic memory matching card game with flip animations. Include a scoring system, timer, and difficulty levels. Add satisfying match/mismatch animations and sound effects using Web Audio API.",
199
- inputs=[],
200
- outputs=[input]
201
- )
202
-
203
- # ๋‘ ๋ฒˆ์งธ ์˜ˆ์ œ ๋ฒ„ํŠผ
204
- example_btn3 = antd.Button(
205
- "ํƒ€๋กœ์นด๋“œ ์šด์ƒˆ",
206
- type="default",
207
- block=True,
208
- size="large"
209
- )
210
- example_btn3.click(
211
- fn=lambda: "ํƒ€๋กœ์นด๋“œ ์šด์„ธ๋ฅผ ์ ์น˜๋Š”๊ฒƒ์„ ์ƒ์„ฑํ•˜๋ผ. ์•„์ฃผ ์ƒ์„ธํ•˜๊ณ  ์ „๋ฌธ์ ์ด๋ฉด์„œ ์‰ฝ๊ณ  ๊ธธ๊ฒŒ ๋‹ต๋ณ€ํ•˜๋ผ. ๋ชจ๋“  ๋‹ต๋ณ€๊ณผ ์„ค๋ช…์€ ํ•œ๊ธ€๋กœ ํ•˜๋ผ",
212
- inputs=[],
213
- outputs=[input]
214
- )
215
-
216
- # ๋‘ ๋ฒˆ์งธ ์˜ˆ์ œ ๋ฒ„ํŠผ
217
- example_btn4 = antd.Button(
218
- "[๊ฒŒ์ž„] ํ…ŒํŠธ๋ฆฌ์Šค",
219
- type="default",
220
- block=True,
221
- size="large"
222
- )
223
- example_btn4.click(
224
- fn=lambda: "Classic Tetris Game: Start๊ณผ ReStart ๋ฒ„ํŠผ๊ณผ ๊ธฐ๋Šฅ ์ ์šฉ, Game Over(๋ง‰๋Œ€๊ฐ€ ๊ฐ€์žฅ ์ƒ๋‹จ๊นŒ์ง€ ๋ˆ„์ ํ•ด์„œ ์Œ“์˜€์„๋•Œ), ๋ง‰๋Œ€๊ฐ€ ํ•œ์ค„ ๊ฐ€๋“ ์ฑ„์›Œ์กŒ์„๋•Œ ํ•œ์ค„์ด ์‚ญ์ œ, ๋–จ์–ด์ง„ ๋ง‰๋Œ€๋Š” ์‚ฌ๋ผ์ง€์ง€ ์•Š๊ณ  ๋ฐ˜๋“œ์‹œ ๋ˆ„์ ํ•ด์„œ ์Œ“์„๊ฒƒ. ๋ง‰๋Œ€ ์šฐ์ธก/์ขŒ์ธก/๋‚ด๋ฆฌ๊ธฐ(space)/๋ง‰๋Œ€์˜ ์ž์ฒด ๋ชจ์–‘๋งŒ ๋ฐ”๊ฟˆ(up) ๋ฒ„ํŠผ ์ง€์›, ๋‚˜๋จธ์ง€๋Š” Tetris ๊ธฐ๋ณธ ๊ทœ์น™์„ ๋”ฐ๋ฆ„",
225
- inputs=[],
226
- outputs=[input]
227
- )
228
-
229
- example_btn5 = antd.Button(
230
- "ํ…์ŠคํŠธ๋กœ ์Œ์„ฑ ์ƒ์„ฑ ๋ฐ ์กฐ์ •",
231
- type="default",
232
- block=True,
233
- size="large"
234
- )
235
- example_btn5.click(
236
- fn=lambda: "ํ…์ŠคํŠธ๋ฅผ ์Œ์„ฑ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ์Œ์„ฑ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜์„ธ์š”.",
237
- inputs=[],
238
- outputs=[input]
239
- )
240
-
241
- # Drawer ์ปดํฌ๋„ŒํŠธ๋“ค
242
- with antd.Drawer(open=False, title="code", placement="left", width="750px") as code_drawer:
243
- code_output = legacy.Markdown()
244
-
245
- with antd.Drawer(open=False, title="history", placement="left", width="900px") as history_drawer:
246
- history_output = legacy.Chatbot(show_label=False, flushing=False, height=960, elem_classes="history_chatbot")
247
-
248
  # ์šฐ์ธก ํŒจ๋„
249
  with antd.Col(span=24, md=16):
250
  with ms.Div(elem_classes="right_panel"):
251
  with antd.Flex(gap="small", elem_classes="setting-buttons"):
252
- codeBtn = antd.Button("๐Ÿง‘โ€๐Ÿ’ป view code", type="default")
253
- historyBtn = antd.Button("๐Ÿ“œ history", type="default")
254
-
 
255
  gr.HTML('<div class="render_header"><span class="header_btn"></span><span class="header_btn"></span><span class="header_btn"></span></div>')
256
  with antd.Tabs(active_key="empty", render_tab_bar="() => null") as state_tab:
257
  with antd.Tabs.Item(key="empty"):
@@ -261,7 +689,7 @@ with gr.Blocks(css_paths="app.css") as demo:
261
  with antd.Tabs.Item(key="render"):
262
  sandbox = gr.HTML(elem_classes="html_content")
263
 
264
- # Code ์‹คํ–‰ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ
265
  def execute_code(query: str):
266
  if not query or query.strip() == '':
267
  return None, gr.update(active_key="empty")
@@ -287,22 +715,69 @@ with gr.Blocks(css_paths="app.css") as demo:
287
  outputs=[sandbox, state_tab]
288
  )
289
 
290
- codeBtn.click(lambda: gr.update(open=True),
291
- inputs=[], outputs=[code_drawer])
292
- code_drawer.close(lambda: gr.update(
293
- open=False), inputs=[], outputs=[code_drawer])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
 
295
- historyBtn.click(history_render, inputs=[history], outputs=[history_drawer, history_output])
296
- history_drawer.close(lambda: gr.update(
297
- open=False), inputs=[], outputs=[history_drawer])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
 
299
  btn.click(
300
- generation_code,
301
  inputs=[input, setting, history],
302
  outputs=[code_output, history, sandbox, state_tab, code_drawer]
303
  )
304
-
305
- clear_btn.click(clear_history, inputs=[], outputs=[history])
 
 
 
 
306
 
307
  if __name__ == "__main__":
308
- demo.queue(default_concurrency_limit=20).launch(ssr_mode=False)
 
 
 
 
 
 
 
 
5
  from typing import Dict, List, Optional, Tuple
6
  import base64
7
  import anthropic
8
+ import openai
9
+ import asyncio
10
+ import time
11
  from functools import partial
12
+ import json
13
  import gradio as gr
14
  import modelscope_studio.components.base as ms
15
  import modelscope_studio.components.legacy as legacy
16
  import modelscope_studio.components.antd as antd
 
17
 
18
+ import html
19
+ import urllib.parse
20
+
21
+ # SystemPrompt ๋ถ€๋ถ„์„ ์ง์ ‘ ์ •์˜
22
+ SystemPrompt = """๋„ˆ์˜ ์ด๋ฆ„์€ 'MOUSE'์ด๋‹ค. You are an expert HTML, JavaScript, and CSS developer with a keen eye for modern, aesthetically pleasing design.
23
+ Your task is to create a stunning, contemporary, and highly functional website based on the user's request using pure HTML, JavaScript, and CSS.
24
+ This code will be rendered directly in the browser.
25
+ General guidelines:
26
+ - Create clean, modern interfaces using vanilla JavaScript and CSS
27
+ - Use HTML5 semantic elements for better structure
28
+ - Implement CSS3 features for animations and styling
29
+ - Utilize modern JavaScript (ES6+) features
30
+ - Create responsive designs using CSS media queries
31
+ - You can use CDN-hosted libraries like:
32
+ * jQuery
33
+ * Bootstrap
34
+ * Chart.js
35
+ * Three.js
36
+ * D3.js
37
+ - For icons, use Unicode symbols or create simple SVG icons
38
+ - Use CSS animations and transitions for smooth effects
39
+ - Implement proper event handling with JavaScript
40
+ - Create mock data instead of making API calls
41
+ - Ensure cross-browser compatibility
42
+ - Focus on performance and smooth animations
43
+ Focus on creating a visually striking and user-friendly interface that aligns with current web design trends. Pay special attention to:
44
+ - Typography: Use web-safe fonts or Google Fonts via CDN
45
+ - Color: Implement a cohesive color scheme that complements the content
46
+ - Layout: Design an intuitive and balanced layout using Flexbox/Grid
47
+ - Animations: Add subtle CSS transitions and keyframe animations
48
+ - Consistency: Maintain a consistent design language throughout
49
+ Remember to only return code wrapped in HTML code blocks. The code should work directly in a browser without any build steps.
50
+ 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"
 
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 = "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"
170
+ YOUR_OPENAI_TOKEN = "1iufMe4Fw6MuddTFV0za4SG4k0KheWl9zPmgJCP_XyzMpyn5yJnLDnZvaOhmsx_Lg5dJYia0d4T3BlbkFJekZDZDUDClPCcT14CxLpwDIqKYtT6QTRxLHK296VJPdDXBJeRvKxNOBkC_vQ2Khu6mRkisUsUA"
171
 
 
 
 
 
 
 
 
172
 
173
+ claude_client = anthropic.Anthropic(api_key=YOUR_ANTHROPIC_TOKEN)
174
+ openai_client = openai.OpenAI(api_key=YOUR_OPENAI_TOKEN)
175
 
176
+ async def try_claude_api(system_message, claude_messages, timeout=15):
177
+ try:
178
+ start_time = time.time()
179
+ with claude_client.messages.stream(
180
+ model="claude-3-5-sonnet-20241022",
181
+ max_tokens=7800,
182
+ system=system_message,
183
+ messages=claude_messages
184
+ ) as stream:
185
+ collected_content = ""
186
+ for chunk in stream: # async for ์ œ๊ฑฐ, ์ผ๋ฐ˜ for ์‚ฌ์šฉ
187
+ current_time = time.time()
188
+ if current_time - start_time > timeout:
189
+ print(f"Claude API response time: {current_time - start_time:.2f} seconds")
190
+ raise TimeoutError("Claude API timeout")
191
+ if chunk.type == "content_block_delta":
192
+ collected_content += chunk.delta.text
193
+ yield collected_content # ๊ฐ ์ฒญํฌ๋งˆ๋‹ค ์ฆ‰์‹œ yield
194
+ await asyncio.sleep(0) # ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์œ„ํ•œ ๋น„๋™๊ธฐ ์–‘๋ณด
195
+
196
+ # ๊ฐ ์ฒญํฌ๋งˆ๋‹ค ํƒ€์ž„์•„์›ƒ ์นด์šดํ„ฐ ๋ฆฌ์…‹
197
+ start_time = current_time
198
+
199
+ except Exception as e:
200
+ print(f"Claude API error: {str(e)}")
201
+ raise e
202
+
203
 
 
 
 
 
204
 
205
+ async def try_openai_api(openai_messages):
206
+ try:
207
+ stream = openai_client.chat.completions.create(
208
+ model="gpt-4o", # ๋ชจ๋ธ๋ช… ์œ ์ง€
209
+ messages=openai_messages,
210
+ stream=True,
211
+ max_tokens=4096,
212
+ temperature=0.7
213
+ )
214
+
215
+ collected_content = ""
216
+ for chunk in stream:
217
+ if chunk.choices[0].delta.content is not None:
218
+ collected_content += chunk.choices[0].delta.content
219
+ yield collected_content
220
+
221
+ except Exception as e:
222
+ print(f"OpenAI API error: {str(e)}")
223
+ raise e
224
 
225
+ class Demo:
226
+ def __init__(self):
227
+ init_db()
228
+ self.current_session = create_session()
229
+
230
+ async def generation_code(self, query: Optional[str], _setting: Dict[str, str], _history: Optional[History]):
231
  if not query or query.strip() == '':
232
+ query = random.choice(DEMO_LIST)['description']
233
 
234
  if _history is None:
235
  _history = []
 
237
  messages = history_to_messages(_history, _setting['system'])
238
  system_message = messages[0]['content']
239
 
240
+ # Claude ๋ฉ”์‹œ์ง€ ํฌ๋งท
241
  claude_messages = [
242
  {"role": msg["role"] if msg["role"] != "system" else "user", "content": msg["content"]}
243
  for msg in messages[1:] + [{'role': Role.USER, 'content': query}]
244
+ if msg["content"].strip() != ''
245
  ]
246
 
247
+ # OpenAI ๋ฉ”์‹œ์ง€ ํฌ๋งท
248
+ openai_messages = [{"role": "system", "content": system_message}]
249
+ for msg in messages[1:]:
250
+ openai_messages.append({
251
+ "role": msg["role"],
252
+ "content": msg["content"]
253
+ })
254
+ openai_messages.append({"role": "user", "content": query})
255
+
256
  try:
257
+ # ๋จผ์ € ์ฝ”๋“œ ๋ทฐ์–ด๋ฅผ ์—ด๊ธฐ
258
  yield [
259
  "Generating code...",
260
  _history,
 
262
  gr.update(active_key="loading"),
263
  gr.update(open=True)
264
  ]
265
+ await asyncio.sleep(0) # UI ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•œ ์–‘๋ณด
266
+
267
+ collected_content = None
268
+ # Claude API ์‹œ๋„
269
+ try:
270
+ async for content in try_claude_api(system_message, claude_messages):
271
+ yield [
272
+ content,
273
+ _history,
274
+ None,
275
+ gr.update(active_key="loading"),
276
+ gr.update(open=True)
277
+ ]
278
+ await asyncio.sleep(0)
279
+ collected_content = content
280
+
281
+ except Exception as claude_error:
282
+ print(f"Falling back to OpenAI API due to Claude error: {str(claude_error)}")
283
+
284
+ # OpenAI API๋กœ ํด๋ฐฑ
285
+ async for content in try_openai_api(openai_messages):
286
+ yield [
287
+ content,
288
+ _history,
289
+ None,
290
+ gr.update(active_key="loading"),
291
+ gr.update(open=True)
292
+ ]
293
+ await asyncio.sleep(0)
294
+ collected_content = content
295
+
296
+ if collected_content:
297
+ try:
298
+ print(f"Attempting to save chat with session_id: {self.current_session}")
299
+ print(f"Query: {query}")
300
+ print(f"Content length: {len(collected_content)}")
301
 
302
+ # ์ฑ„ํŒ… ๋‚ด์šฉ ์ €์žฅ
303
+ save_chat(self.current_session, query, collected_content)
304
+ print("Chat saved successfully")
305
+
306
+ except Exception as save_error:
307
+ print(f"Error saving chat: {save_error}")
308
+
309
+
310
+
311
  _history = messages_to_history([
312
  {'role': Role.SYSTEM, 'content': system_message}
313
  ] + claude_messages + [{
314
  'role': Role.ASSISTANT,
315
+ 'content': collected_content
316
  }])
317
+
318
  yield [
319
  collected_content,
320
  _history,
 
322
  gr.update(active_key="render"),
323
  gr.update(open=True)
324
  ]
325
+ else:
326
+ raise ValueError("No content was generated from either API")
327
+
328
  except Exception as e:
329
+ print(f"Error details: {str(e)}")
330
+ raise ValueError(f'Error calling APIs: {str(e)}')
331
+
332
+
333
+
334
+ def clear_history(self):
335
+ self.current_session = create_session()
336
+ return []
337
+
338
+
339
+ def remove_code_block(text):
340
+ pattern = r'```html\n(.+?)\n```'
341
+ match = re.search(pattern, text, re.DOTALL)
342
+ if match:
343
+ return match.group(1).strip()
344
+ else:
345
+ return text.strip()
346
+
347
+ def history_render(history: History):
348
+ return gr.update(open=True), history
349
+
350
+
351
+ def send_to_sandbox(code):
352
+ encoded_html = base64.b64encode(code.encode('utf-8')).decode('utf-8')
353
+ data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}"
354
+ return f"<iframe src=\"{data_uri}\" width=\"100%\" height=\"920px\"></iframe>"
355
+
356
+
357
+ theme = gr.themes.Soft()
358
+
359
+ def clear_expired_sessions():
360
+ """30์ผ ์ด์ƒ ๋œ ์„ธ์…˜ ์‚ญ์ œ"""
361
+ conn = sqlite3.connect('chat_history.db')
362
+ try:
363
+ c = conn.cursor()
364
+ c.execute("""DELETE FROM chat_history WHERE session_id IN
365
+ (SELECT session_id FROM sessions
366
+ WHERE created_at < datetime('now', '-30 days'))""")
367
+ c.execute("DELETE FROM sessions WHERE created_at < datetime('now', '-30 days')")
368
+ conn.commit()
369
+ finally:
370
+ conn.close()
371
+
372
+ def update_session_list():
373
+ try:
374
+ conn = sqlite3.connect('chat_history.db')
375
+ c = conn.cursor()
376
+ # ์„ธ์…˜๊ณผ ๊ฐ€์žฅ ์ตœ๊ทผ ๋Œ€ํ™” ์‹œ๊ฐ„์„ ํ•จ๊ป˜ ๊ฐ€์ ธ์˜ด
377
+ c.execute("""
378
+ SELECT s.session_id, MAX(ch.timestamp) as last_chat
379
+ FROM sessions s
380
+ LEFT JOIN chat_history ch ON s.session_id = ch.session_id
381
+ GROUP BY s.session_id
382
+ ORDER BY last_chat DESC NULLS LAST
383
+ """)
384
+ sessions = c.fetchall()
385
+ conn.close()
386
+
387
+ # ์„ธ์…˜ ID์™€ ์‹œ๊ฐ„์„ ํฌ๋งทํŒ…
388
+ formatted_sessions = []
389
+ for session_id, last_chat in sessions:
390
+ if last_chat:
391
+ time_str = datetime.strptime(last_chat, '%Y-%m-%d %H:%M:%S.%f').strftime('%Y-%m-%d %H:%M:%S')
392
+ formatted_sessions.append(f"{session_id} ({time_str})")
393
+ else:
394
+ formatted_sessions.append(session_id)
395
+
396
+ return gr.update(choices=formatted_sessions)
397
+ except Exception as e:
398
+ print(f"Error updating session list: {e}")
399
+ return gr.update(choices=[])
400
+
401
+ def load_json_data():
402
+ # ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜
403
+ return [
404
+ {
405
+ "name": "MBTI ์ง„๋‹จ ์„œ๋น„์Šค",
406
+ "image_url": "data:image/png;base64," + get_image_base64('mbti.png'), # mbti.png ์‚ฌ์šฉ
407
+ "prompt": "MBTI ์ง„๋‹จ์„ ์œ„ํ•ด 15๊ฐœ์˜ ์งˆ๋ฌธ๊ณผ ๊ฐ๊ด€์‹ ๋‹ต๋ณ€์„ ํ†ตํ•ด MBTI ์ง„๋‹จ ๊ฒฐ๊ณผ ๋ฐ ํ•ด๋‹น ์„ฑ๊ฒฉ์— ๋Œ€ํ•œ ์ƒ์„ธํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜๋ผ"
408
+ },
409
+ {
410
+ "name": "ํˆฌ์ž ํฌํŠธํด๋ฆฌ์˜ค ๋Œ€์‹œ๋ณด๋“œ",
411
+ "image_url": "data:image/png;base64," + get_image_base64('dash.png'), # mouse.gif ์‚ฌ์šฉ
412
+ "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.ํˆฌ์ž ํฌํŠธํด๋ฆฌ์˜ค๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์œ„ํ—˜๋„, ์ˆ˜์ต๋ฅ , ์ž์‚ฐ ๋ฐฐ๋ถ„์„ ์‹œ๊ฐํ™”ํ•˜๋Š” ํˆฌ์ž ๊ด€๋ฆฌ ๋„๊ตฌ๋ฅผ ๋งŒ๋“œ์„ธ์š”."
413
+ },
414
+ {
415
+ "name": "์ฒด์Šค ๊ฒŒ์ž„",
416
+ "image_url": "data:image/png;base64," + get_image_base64('chess.png'), # mouse.gif ์‚ฌ์šฉ
417
+ "prompt": "์ฒด์Šค ๊ฒŒ์ž„: ์ฒด์Šค ๊ฒŒ์ž„์˜ ๋ฃฐ์„ ์ •ํ™•ํ•˜๊ฒŒ ์‹๋ณ„ํ•˜๊ณ  ์ ์šฉํ•˜๋ผ, ์ƒ๋Œ€๋ฐฉ์€ auto๋กœ ๊ฒŒ์ž„์„ ์ง„ํ–‰ํ•˜๋ผ"
418
+ },
419
+ {
420
+ "name": "ํƒ€๋กœ์นด๋“œ ์šด์„ธ",
421
+ "image_url": "data:image/png;base64," + get_image_base64('tarot.png'), # mouse.gif ์‚ฌ์šฉ
422
+ "prompt": "ํƒ€๋กœ์นด๋“œ ์šด์„ธ๋ฅผ ์ ์น˜๋Š”๊ฒƒ์„ ์ƒ์„ฑํ•˜๋ผ. ์•„์ฃผ ์ƒ์„ธํ•˜๊ณ  ์ „๋ฌธ์ ์ด๋ฉด์„œ ์‰ฝ๊ณ  ๊ธธ๊ฒŒ ๋‹ต๋ณ€ํ•˜๋ผ. ๋ชจ๋“  ๋‹ต๋ณ€๊ณผ ์„ค๋ช…์€ ํ•œ๊ธ€๋กœ ํ•˜๋ผ"
423
+ },
424
+
425
+ {
426
+ "name": "ํ…์ŠคํŠธ๋กœ ์Œ์„ฑ ์ƒ์„ฑ ๋ฐ ์กฐ์ •",
427
+ "image_url": "data:image/png;base64," + get_image_base64('tts.png'), # mouse.gif ์‚ฌ์šฉ
428
+ "prompt": "ํ…์ŠคํŠธ๋ฅผ ์Œ์„ฑ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ์Œ์„ฑ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜์„ธ์š”."
429
+ },
430
+ {
431
+ "name": "3D ๋ถ„์ž ์‹œ๋ฎฌ๋ ˆ์ด์…˜",
432
+ "image_url": "data:image/png;base64," + get_image_base64('3ds.png'), # mouse.gif ์‚ฌ์šฉ
433
+ "prompt": "Three.js๋กœ 3D ๋ถ„์ž ๊ตฌ์กฐ(์ฃผ์š” ๋ถ„์ž๋“ค์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ)๋ฅผ ์‹œ๊ฐํ™”ํ•˜์„ธ์š”. ํšŒ์ „, ์คŒ, ์›์ž ์ •๋ณด ํ‘œ์‹œ ๊ธฐ๋Šฅ๊ณผ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ๊ตฌํ˜„ํ•˜์„ธ์š”."
434
+ },
435
+ {
436
+ "name": "ํ–‰์šด์˜ ๋ฃฐ๋ ›",
437
+ "image_url": "data:image/png;base64," + get_image_base64('roolet.png'), # mouse.gif ์‚ฌ์šฉ
438
+ "prompt": "ํ–‰์šด์˜ ์›ํ˜• ๋ฃฐ๋ ›์ด ๋น ๋ฅด๊ฒŒ ๋Œ์•„๊ฐ€๊ณ , ๋งˆ์šฐ์Šค๋กœ ํ™”์‚ด ๋ฐœ์‚ฌ ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋ฉด ๋ฃฐ๋ ›์˜ ๋ฒˆํ˜ธ์— ๋žœ๋คํ•˜๊ฒŒ ๋งž๋Š”๋‹ค. ๊ฐ ๋ฒˆํ˜ธ์— ์ƒ๊ธˆ์ด '๊ฝ' ~ '100๋งŒ์›' ๊นŒ์ง€ ๋žœ๋คํ•˜๊ฒŒ ๋ฐฐ์น˜๋˜์–ด ์žˆ๋‹ค. shoot ์„ ํƒ๋œ ๋ฒˆํ˜ธ์— ๋”ฐ๋ผ ํ•ด๋‹น ๋ฒˆํ˜ธ์— ๋ฐฐ์น˜๋œ ์ƒ๊ธˆ ์•ก์ˆ˜๋„ ์ถœ๋ ฅํ•˜๋ผ"
439
+ },
440
+
441
+ {
442
+ "name": "๋ฒฝ๋Œ๊นจ๊ธฐ ๊ฒŒ์ž„",
443
+ "image_url": "data:image/png;base64," + get_image_base64('alcaroid.png'), # mouse.gif ์‚ฌ์šฉ
444
+ "prompt": "๋ฒฝ๋Œ๊นจ๊ธฐ ๊ฒŒ์ž„"
445
+ },
446
+ {
447
+ "name": "ํ…Œ์ŠคํŠธ",
448
+ "image_url": "data:image/gif;base64," + get_image_base64('mouse.gif'), # mouse.gif ์‚ฌ์šฉ
449
+ "prompt": "ํ…Œ์ŠคํŠธ"
450
+ }
451
+ ]
452
+
453
+ def load_session_history(selected_session=None):
454
+ try:
455
+ json_data = load_json_data()
456
+
457
+ html_content = """
458
+ <style>
459
+ .prompt-grid {
460
+ display: grid;
461
+ grid-template-columns: repeat(3, 1fr);
462
+ gap: 20px;
463
+ padding: 20px;
464
+ }
465
+ .prompt-card {
466
+ background: white;
467
+ border: 1px solid #eee;
468
+ border-radius: 8px;
469
+ padding: 15px;
470
+ transition: all 0.3s ease;
471
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
472
+ min-height: 300px;
473
+ cursor: pointer;
474
+ }
475
+ .prompt-card:hover {
476
+ transform: translateY(-2px);
477
+ box-shadow: 0 4px 10px rgba(0,0,0,0.15);
478
+ }
479
+ .card-image {
480
+ width: 100%;
481
+ height: 180px;
482
+ object-fit: cover;
483
+ border-radius: 4px;
484
+ margin-bottom: 10px;
485
+ }
486
+ .card-name {
487
+ font-weight: bold;
488
+ margin-bottom: 8px;
489
+ font-size: 16px;
490
+ color: #333;
491
+ }
492
+ .card-prompt {
493
+ font-size: 11px;
494
+ line-height: 1.4;
495
+ color: #666;
496
+ display: -webkit-box;
497
+ -webkit-line-clamp: 6;
498
+ -webkit-box-orient: vertical;
499
+ overflow: hidden;
500
+ text-overflow: ellipsis;
501
+ height: 90px;
502
+ background-color: #f8f9fa;
503
+ padding: 8px;
504
+ border-radius: 4px;
505
+ border: 1px solid #eee;
506
+ }
507
+ </style>
508
+ <div class="prompt-grid">
509
+ """
510
+
511
+ for item in json_data:
512
+ html_content += f"""
513
+ <div class="prompt-card">
514
+ <img src="{item.get('image_url', '')}" class="card-image" alt="{html.escape(item.get('name', ''))}">
515
+ <div class="card-name">{html.escape(item.get('name', ''))}</div>
516
+ <div class="card-prompt">{html.escape(item.get('prompt', ''))}</div>
517
+ </div>
518
+ """
519
+
520
+ html_content += """
521
+ </div>
522
+ """
523
+
524
+ return gr.HTML(value=html_content)
525
+
526
+ except Exception as e:
527
+ print(f"Error in load_session_history: {str(e)}")
528
+ return gr.HTML("Error loading templates")
529
+
530
+
531
+
532
+ # ํžˆ์Šคํ† ๋ฆฌ ์•„์ดํ…œ ์„ ํƒ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜
533
+ def handle_history_selection(evt: gr.SelectData):
534
+ try:
535
+ prompt = evt.value["prompt"]
536
+ response = evt.value["response"]
537
+
538
+ # ์ฝ”๋“œ ์ถ”์ถœ
539
+ code = response
540
+ if "```html" in response:
541
+ match = re.search(r'```html\n(.*?)\n```', response, re.DOTALL)
542
+ if match:
543
+ code = match.group(1)
544
+
545
+ return (
546
+ prompt, # ์ž…๋ ฅ ํ•„๋“œ์— ํ”„๋กฌํ”„ํŠธ ์„ค์ •
547
+ send_to_sandbox(code), # ์ฝ”๋“œ ์‹คํ–‰
548
+ gr.update(active_key="render"), # ํƒญ ์ƒํƒœ ์—…๋ฐ์ดํŠธ
549
+ gr.update(open=False) # ์„ธ์…˜ ๋“œ๋กœ์–ด ๋‹ซ๊ธฐ
550
+ )
551
+ except Exception as e:
552
+ print(f"Error handling history selection: {e}")
553
+ return None, None, gr.update(active_key="empty"), gr.update(open=True)
554
+
555
+
556
+
557
+ def save_chat(session_id, prompt, response):
558
+ print(f"Starting save_chat with session_id: {session_id}")
559
+ conn = None
560
+ try:
561
+ conn = sqlite3.connect('chat_history.db')
562
+ c = conn.cursor()
563
+
564
+ # ์„ธ์…˜์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
565
+ c.execute("SELECT 1 FROM sessions WHERE session_id = ?", (session_id,))
566
+ if not c.fetchone():
567
+ print(f"Session {session_id} not found, creating new session")
568
+ c.execute("INSERT INTO sessions (session_id, created_at) VALUES (?, ?)",
569
+ (session_id, datetime.now()))
570
+
571
+ # ์ฑ„ํŒ… ์ €์žฅ
572
+ c.execute("""
573
+ INSERT INTO chat_history (session_id, prompt, response, timestamp)
574
+ VALUES (?, ?, ?, ?)
575
+ """, (session_id, prompt, response, datetime.now()))
576
+
577
+ conn.commit()
578
+ print(f"Successfully saved chat for session {session_id}")
579
+
580
+ except sqlite3.Error as e:
581
+ print(f"Database error: {e}")
582
+ if conn:
583
+ conn.rollback()
584
+ raise
585
+ except Exception as e:
586
+ print(f"Unexpected error: {e}")
587
+ if conn:
588
+ conn.rollback()
589
+ raise
590
+ finally:
591
+ if conn:
592
+ conn.close()
593
+
594
+ # Demo ์ธ์Šคํ„ด์Šค ๋จผ์ € ์ƒ์„ฑ
595
+ demo_instance = Demo()
596
+
597
+ with gr.Blocks(css_paths="app.css",theme=theme) as demo:
598
+ history = gr.State([])
599
+ setting = gr.State({
600
+ "system": SystemPrompt,
601
+ })
602
 
603
  with ms.Application() as app:
604
  with antd.ConfigProvider():
605
+ # Drawer ์ปดํฌ๋„ŒํŠธ๋“ค
606
+ with antd.Drawer(open=False, title="code", placement="left", width="750px") as code_drawer:
607
+ code_output = legacy.Markdown()
608
+
609
+ with antd.Drawer(open=False, title="history", placement="left", width="900px") as history_drawer:
610
+ history_output = legacy.Chatbot(show_label=False, flushing=False, height=960, elem_classes="history_chatbot")
611
+
612
+ with antd.Drawer(
613
+ open=False,
614
+ title="Templates",
615
+ placement="right",
616
+ width="900px",
617
+ elem_classes="session-drawer"
618
+ ) as session_drawer:
619
+ with antd.Flex(vertical=True, gap="middle"):
620
+ gr.Markdown("### Available Templates")
621
+ session_history = gr.HTML(
622
+ elem_classes="session-history"
623
+ )
624
+ close_btn = antd.Button(
625
+ "Close",
626
+ type="default",
627
+ elem_classes="close-btn"
628
+ )
629
+
630
+ # ์„ธ์…˜ ๋“œ๋กœ์–ด์—์„œ ์นด๋“œ ํด๋ฆญ ์‹œ ์‹คํ–‰ํ•  ํ•จ์ˆ˜ (Drawer ์ปดํฌ๋„ŒํŠธ๋“ค ๋‹ค์Œ์— ์œ„์น˜)
631
+ def execute_history_item(evt: gr.SelectData): # gr.SelectData๋กœ ์ด๋ฒคํŠธ ๋ฐ์ดํ„ฐ ๋ฐ›๊ธฐ
632
+ try:
633
+ # ํด๋ฆญ๋œ ์นด๋“œ์˜ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ
634
+ prompt = evt.value["prompt"]
635
+ response = evt.value["response"]
636
+
637
+ # ์ฝ”๋“œ ์‹คํ–‰
638
+ code = remove_code_block(response) if '```html' in response else response
639
+
640
+ return (
641
+ gr.update(value=prompt), # ์ž…๋ ฅ ํ•„๋“œ ์—…๋ฐ์ดํŠธ
642
+ send_to_sandbox(code), # ์ฝ”๋“œ ์‹คํ–‰
643
+ gr.update(active_key="render"), # ํƒญ ์ƒํƒœ ์—…๋ฐ์ดํŠธ
644
+ gr.update(open=False) # ์„ธ์…˜ ๋“œ๋กœ์–ด ๋‹ซ๊ธฐ
645
+ )
646
+ except Exception as e:
647
+ print(f"Error executing history item: {e}")
648
+ return None, None, gr.update(active_key="empty"), gr.update(open=True)
649
+
650
  # ๋ฉ”์ธ ์ปจํ…์ธ ๋ฅผ ์œ„ํ•œ Row
651
+ with antd.Row(gutter=[32, 12]) as layout:
652
  # ์ขŒ์ธก ํŒจ๋„
653
  with antd.Col(span=24, md=8):
654
  with antd.Flex(vertical=True, gap="middle", wrap=True):
 
671
  execute_btn = antd.Button("Code ์‹คํ–‰", type="default", size="large")
672
  clear_btn = antd.Button("Clear", type="default", size="large")
673
 
674
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
675
  # ์šฐ์ธก ํŒจ๋„
676
  with antd.Col(span=24, md=16):
677
  with ms.Div(elem_classes="right_panel"):
678
  with antd.Flex(gap="small", elem_classes="setting-buttons"):
679
+ codeBtn = antd.Button("๐Ÿง‘โ€๐Ÿ’ป ์ฝ”๋“œ ๋ณด๊ธฐ", type="default")
680
+ historyBtn = antd.Button("๐Ÿ“œ ํžˆ์Šคํ† ๋ฆฌ", type="default")
681
+ sessionBtn = antd.Button("๐Ÿ“š ํ…œํ”Œ๋ฆฟ", type="default")
682
+
683
  gr.HTML('<div class="render_header"><span class="header_btn"></span><span class="header_btn"></span><span class="header_btn"></span></div>')
684
  with antd.Tabs(active_key="empty", render_tab_bar="() => null") as state_tab:
685
  with antd.Tabs.Item(key="empty"):
 
689
  with antd.Tabs.Item(key="render"):
690
  sandbox = gr.HTML(elem_classes="html_content")
691
 
692
+ # Code ์‹คํ–‰ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜ ์ •์˜
693
  def execute_code(query: str):
694
  if not query or query.strip() == '':
695
  return None, gr.update(active_key="empty")
 
715
  outputs=[sandbox, state_tab]
716
  )
717
 
718
+ codeBtn.click(
719
+ lambda: gr.update(open=True),
720
+ inputs=[],
721
+ outputs=[code_drawer]
722
+ )
723
+
724
+ code_drawer.close(
725
+ lambda: gr.update(open=False),
726
+ inputs=[],
727
+ outputs=[code_drawer]
728
+ )
729
+
730
+ historyBtn.click(
731
+ history_render,
732
+ inputs=[history],
733
+ outputs=[history_drawer, history_output]
734
+ )
735
+
736
+ history_drawer.close(
737
+ lambda: gr.update(open=False),
738
+ inputs=[],
739
+ outputs=[history_drawer]
740
+ )
741
 
742
+
743
+ # ์„ธ์…˜ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ ์ˆ˜์ •
744
+
745
+ sessionBtn.click(
746
+ fn=lambda: (gr.update(open=True), load_session_history()),
747
+ inputs=[],
748
+ outputs=[session_drawer, session_history]
749
+ )
750
+ # ์„ธ์…˜ ๋“œ๋กœ์–ด ๋‹ซ๊ธฐ ์ด๋ฒคํŠธ ์ˆ˜์ •
751
+ session_drawer.close(
752
+ lambda: (gr.update(open=False), gr.HTML("")),
753
+ outputs=[session_drawer, session_history]
754
+ )
755
+
756
+ close_btn.click(
757
+ lambda: (gr.update(open=False), gr.HTML("")),
758
+ outputs=[session_drawer, session_history]
759
+ )
760
+
761
+
762
 
763
  btn.click(
764
+ demo_instance.generation_code,
765
  inputs=[input, setting, history],
766
  outputs=[code_output, history, sandbox, state_tab, code_drawer]
767
  )
768
+
769
+ clear_btn.click(
770
+ demo_instance.clear_history,
771
+ inputs=[],
772
+ outputs=[history]
773
+ )
774
 
775
  if __name__ == "__main__":
776
+ try:
777
+ init_db()
778
+ clear_expired_sessions()
779
+ demo_instance = Demo()
780
+ demo.queue(default_concurrency_limit=20).launch(ssr_mode=False)
781
+ except Exception as e:
782
+ print(f"Initialization error: {e}")
783
+ raise