sidbhasin commited on
Commit
514f65a
1 Parent(s): 925a409

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +240 -146
app.py CHANGED
@@ -3,24 +3,107 @@ import re
3
  from http import HTTPStatus
4
  from typing import Dict, List, Optional, Tuple
5
  import base64
6
-
7
-
8
  import dashscope
9
  import gradio as gr
10
  from dashscope import Generation
11
  from dashscope.api_entities.dashscope_response import Role
12
-
13
  import modelscope_studio.components.base as ms
14
  import modelscope_studio.components.legacy as legacy
15
  import modelscope_studio.components.antd as antd
16
  from config import DEMO_LIST, SystemPrompt
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  YOUR_API_TOKEN = os.getenv('YOUR_API_TOKEN')
19
  dashscope.api_key = YOUR_API_TOKEN
20
 
21
- History = List[Tuple[str, str]]
22
- Messages = List[Dict[str, str]]
23
-
24
  def history_to_messages(history: History, system: str) -> Messages:
25
  messages = [{'role': Role.SYSTEM, 'content': system}]
26
  for h in history:
@@ -28,180 +111,191 @@ def history_to_messages(history: History, system: str) -> Messages:
28
  messages.append({'role': Role.ASSISTANT, 'content': h[1]})
29
  return messages
30
 
31
-
32
- def messages_to_history(messages: Messages) -> Tuple[str, History]:
33
  assert messages[0]['role'] == Role.SYSTEM
34
  history = []
35
  for q, r in zip(messages[1::2], messages[2::2]):
36
  history.append([q['content'], r['content']])
37
  return history
38
 
39
-
40
  def remove_code_block(text):
41
  pattern = r'```html\n(.+?)\n```'
42
  match = re.search(pattern, text, re.DOTALL)
43
  if match:
44
  return match.group(1).strip()
45
- else:
46
- return text.strip()
47
-
48
- def history_render(history: History):
49
- return gr.update(open=True), history
50
-
51
- def clear_history():
52
- return []
53
 
54
  def send_to_sandbox(code):
55
  encoded_html = base64.b64encode(code.encode('utf-8')).decode('utf-8')
56
  data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}"
57
  return f"<iframe src=\"{data_uri}\" width=\"100%\" height=\"920px\"></iframe>"
58
- # return {
59
- # '/src/App.jsx': {
60
- # 'code': code,
61
- # 'fpath': '/src/App.jsx',
62
- # },
63
- # # 以路径为 key,必须以绝对路径来描述
64
- # '/src/index.js': {
65
- # 'code':
66
- # 'import React from "react"; import ReactDOM from "react-dom"; import App from "./App"; const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);',
67
- # 'fpath': '/src/index.js',
68
- # },
69
- # '/package.json': {
70
- # 'code': '{"name":"demo", "main": "./src/index.js", "dependencies":{ "react": "18.3.1", "react-dom": "18.3.1", "antd": "5.21.6", "styled-components": "6.1.13" }}',
71
- # 'fpath': '/package.json',
72
- # },
73
- # }
74
 
75
  def demo_card_click(e: gr.EventData):
76
  index = e._data['component']['index']
77
  return DEMO_LIST[index]['description']
78
 
79
- with gr.Blocks(css_paths="app.css") as demo:
 
80
  history = gr.State([])
81
- setting = gr.State({
82
- "system": SystemPrompt,
83
- })
84
-
85
  with ms.Application() as app:
86
- with antd.ConfigProvider():
 
 
 
 
 
 
87
  with antd.Row(gutter=[32, 12]) as layout:
 
88
  with antd.Col(span=24, md=8):
89
  with antd.Flex(vertical=True, gap="middle", wrap=True):
90
  header = gr.HTML("""
91
- <div class="left_header">
92
- <img src="//img.alicdn.com/imgextra/i2/O1CN01KDhOma1DUo8oa7OIU_!!6000000000220-1-tps-240-240.gif" width="200px" />
93
- <h1>Qwen2.5-Coder</h2>
94
- </div>
95
- """)
 
96
  input = antd.InputTextarea(
97
- size="large", allow_clear=True, placeholder="Please enter what kind of application you want")
98
- # input = gr.TextArea(placeholder="请输入您想要一个什么样的应用", show_label=False, container=False)
99
- btn = antd.Button("send", type="primary", size="large")
100
- clear_btn = antd.Button("clear history", type="default", size="large")
101
-
102
- antd.Divider("examples")
103
- with antd.Flex(gap="small", wrap=True):
 
 
 
 
 
 
104
  with ms.Each(DEMO_LIST):
105
- with antd.Card(hoverable=True, as_item="card") as demoCard:
106
- antd.CardMeta()
107
- demoCard.click(demo_card_click, outputs=[input])
108
-
109
- antd.Divider("setting")
110
-
111
  with antd.Flex(gap="small", wrap=True):
112
- settingPromptBtn = antd.Button(
113
- "⚙️ set system Prompt", type="default")
114
- codeBtn = antd.Button("🧑‍💻 view code", type="default")
115
- historyBtn = antd.Button("📜 history", type="default")
116
-
117
- with antd.Modal(open=False, title="set system Prompt", width="800px") as system_prompt_modal:
118
- systemPromptInput = antd.InputTextarea(
119
- SystemPrompt, auto_size=True)
120
-
121
- settingPromptBtn.click(lambda: gr.update(
122
- open=True), inputs=[], outputs=[system_prompt_modal])
123
- system_prompt_modal.ok(lambda input: ({"system": input}, gr.update(
124
- open=False)), inputs=[systemPromptInput], outputs=[setting, system_prompt_modal])
125
- system_prompt_modal.cancel(lambda: gr.update(
126
- open=False), outputs=[system_prompt_modal])
127
-
128
- with antd.Drawer(open=False, title="code", placement="left", width="750px") as code_drawer:
129
- code_output = legacy.Markdown()
130
-
131
- codeBtn.click(lambda: gr.update(open=True),
132
- inputs=[], outputs=[code_drawer])
133
- code_drawer.close(lambda: gr.update(
134
- open=False), inputs=[], outputs=[code_drawer])
135
-
136
- with antd.Drawer(open=False, title="history", placement="left", width="900px") as history_drawer:
137
- history_output = legacy.Chatbot(show_label=False, flushing=False, height=960, elem_classes="history_chatbot")
138
-
139
- historyBtn.click(history_render, inputs=[history], outputs=[history_drawer, history_output])
140
- history_drawer.close(lambda: gr.update(
141
- open=False), inputs=[], outputs=[history_drawer])
142
-
143
  with antd.Col(span=24, md=16):
144
  with ms.Div(elem_classes="right_panel"):
145
- gr.HTML('<div class="render_header"><span class="header_btn"></span><span class="header_btn"></span><span class="header_btn"></span></div>')
 
 
 
 
 
 
 
146
  with antd.Tabs(active_key="empty", render_tab_bar="() => null") as state_tab:
147
  with antd.Tabs.Item(key="empty"):
148
- empty = antd.Empty(description="empty input", elem_classes="right_content")
149
- with antd.Tabs.Item(key="loading"):
150
- loading = antd.Spin(True, tip="coding...", size="large", elem_classes="right_content")
151
- with antd.Tabs.Item(key="render"):
152
- sandbox = gr.HTML(elem_classes="html_content")
153
- # sandbox = pro.FrontendCodeSandbox(elem_style={
154
- # 'height': '920px',
155
- # 'width': '100%'
156
- # })
157
-
158
- def generation_code(query: Optional[str], _setting: Dict[str, str], _history: Optional[History]):
159
- if query is None:
160
- query = ''
161
- if _history is None:
162
- _history = []
163
- messages = history_to_messages(_history, _setting['system'])
164
- messages.append({'role': Role.USER, 'content': query})
165
-
166
- gen = Generation.call(model="qwen2.5-coder-32b-instruct",
167
- messages=messages,
168
- result_format='message',
169
- stream=True)
170
- for response in gen:
171
- if response.status_code == HTTPStatus.OK:
172
- role = response.output.choices[0].message.role
173
- content = response.output.choices[0].message.content
174
- if response.output.choices[0].finish_reason == 'stop':
175
- _history = messages_to_history(messages + [{
176
- 'role': role,
177
- 'content': content
178
- }])
179
- print('history')
180
- print(_history)
181
- yield {
182
- code_output: content,
183
- history: _history,
184
- sandbox: send_to_sandbox(remove_code_block(content)),
185
- state_tab: gr.update(active_key="render"),
186
- code_drawer: gr.update(open=False),
187
- }
188
- else:
189
- yield {
190
- code_output: content,
191
- state_tab: gr.update(active_key="loading"),
192
- code_drawer: gr.update(open=True),
193
- }
194
- else:
195
- raise ValueError(
196
- 'Request id: %s, Status code: %s, error code: %s, error message: %s'
197
- % (response.request_id, response.status_code, response.code,
198
- response.message))
199
-
200
- btn.click(generation_code,
201
- inputs=[input, setting, history],
202
- outputs=[code_output, history, sandbox, state_tab, code_drawer])
203
 
204
- clear_btn.click(clear_history, inputs=[], outputs=[history])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
 
 
206
  if __name__ == "__main__":
207
- demo.queue(default_concurrency_limit=20).launch(ssr_mode=False)
 
 
 
 
 
3
  from http import HTTPStatus
4
  from typing import Dict, List, Optional, Tuple
5
  import base64
 
 
6
  import dashscope
7
  import gradio as gr
8
  from dashscope import Generation
9
  from dashscope.api_entities.dashscope_response import Role
 
10
  import modelscope_studio.components.base as ms
11
  import modelscope_studio.components.legacy as legacy
12
  import modelscope_studio.components.antd as antd
13
  from config import DEMO_LIST, SystemPrompt
14
 
15
+ # Custom CSS for improved UI
16
+ custom_css = """
17
+ .left_header {
18
+ text-align: center;
19
+ padding: 2rem;
20
+ background: linear-gradient(135deg, #6366f1, #8b5cf6);
21
+ border-radius: 15px;
22
+ margin-bottom: 1.5rem;
23
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
24
+ }
25
+
26
+ .left_header img {
27
+ max-width: 200px;
28
+ margin-bottom: 1rem;
29
+ transition: transform 0.3s ease;
30
+ }
31
+
32
+ .left_header img:hover {
33
+ transform: scale(1.05);
34
+ }
35
+
36
+ .left_header h1 {
37
+ color: white;
38
+ font-size: 2rem;
39
+ font-weight: 600;
40
+ margin: 0;
41
+ }
42
+
43
+ .right_panel {
44
+ background: white;
45
+ border-radius: 15px;
46
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
47
+ height: 100%;
48
+ }
49
+
50
+ .render_header {
51
+ background: #f3f4f6;
52
+ padding: 12px;
53
+ border-radius: 15px 15px 0 0;
54
+ display: flex;
55
+ gap: 8px;
56
+ }
57
+
58
+ .header_btn {
59
+ width: 12px;
60
+ height: 12px;
61
+ border-radius: 50%;
62
+ }
63
+
64
+ .header_btn:nth-child(1) { background: #ef4444; }
65
+ .header_btn:nth-child(2) { background: #f59e0b; }
66
+ .header_btn:nth-child(3) { background: #10b981; }
67
+
68
+ .html_content {
69
+ height: calc(100vh - 180px);
70
+ overflow: auto;
71
+ padding: 20px;
72
+ }
73
+
74
+ .right_content {
75
+ padding: 2rem;
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ height: calc(100vh - 180px);
80
+ }
81
+
82
+ /* Mobile Responsive Design */
83
+ @media (max-width: 768px) {
84
+ .left_header {
85
+ padding: 1.5rem;
86
+ }
87
+
88
+ .left_header img {
89
+ max-width: 150px;
90
+ }
91
+
92
+ .left_header h1 {
93
+ font-size: 1.5rem;
94
+ }
95
+
96
+ .html_content {
97
+ height: calc(100vh - 140px);
98
+ }
99
+ }
100
+ """
101
+
102
+ # Initialize DashScope
103
  YOUR_API_TOKEN = os.getenv('YOUR_API_TOKEN')
104
  dashscope.api_key = YOUR_API_TOKEN
105
 
106
+ # Helper functions
 
 
107
  def history_to_messages(history: History, system: str) -> Messages:
108
  messages = [{'role': Role.SYSTEM, 'content': system}]
109
  for h in history:
 
111
  messages.append({'role': Role.ASSISTANT, 'content': h[1]})
112
  return messages
113
 
114
+ def messages_to_history(messages: Messages) -> History:
 
115
  assert messages[0]['role'] == Role.SYSTEM
116
  history = []
117
  for q, r in zip(messages[1::2], messages[2::2]):
118
  history.append([q['content'], r['content']])
119
  return history
120
 
 
121
  def remove_code_block(text):
122
  pattern = r'```html\n(.+?)\n```'
123
  match = re.search(pattern, text, re.DOTALL)
124
  if match:
125
  return match.group(1).strip()
126
+ return text.strip()
 
 
 
 
 
 
 
127
 
128
  def send_to_sandbox(code):
129
  encoded_html = base64.b64encode(code.encode('utf-8')).decode('utf-8')
130
  data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}"
131
  return f"<iframe src=\"{data_uri}\" width=\"100%\" height=\"920px\"></iframe>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
 
133
  def demo_card_click(e: gr.EventData):
134
  index = e._data['component']['index']
135
  return DEMO_LIST[index]['description']
136
 
137
+ # Create Gradio interface
138
+ with gr.Blocks(css=custom_css) as demo:
139
  history = gr.State([])
140
+ setting = gr.State({"system": SystemPrompt})
141
+
 
 
142
  with ms.Application() as app:
143
+ with antd.ConfigProvider(theme={
144
+ "token": {
145
+ "colorPrimary": "#6366f1",
146
+ "borderRadius": 8,
147
+ "fontSize": 16
148
+ }
149
+ }):
150
  with antd.Row(gutter=[32, 12]) as layout:
151
+ # Left Column
152
  with antd.Col(span=24, md=8):
153
  with antd.Flex(vertical=True, gap="middle", wrap=True):
154
  header = gr.HTML("""
155
+ <div class="left_header">
156
+ <img src="//img.alicdn.com/imgextra/i2/O1CN01KDhOma1DUo8oa7OIU_!!6000000000220-1-tps-240-240.gif" />
157
+ <h1>AI TOOL BUILDER BY SYNCMERCE</h1>
158
+ </div>
159
+ """)
160
+
161
  input = antd.InputTextarea(
162
+ size="large",
163
+ allow_clear=True,
164
+ placeholder="What kind of application would you like to build?",
165
+ style={"minHeight": "120px"}
166
+ )
167
+
168
+ with antd.Flex(gap="small", justify="space-between"):
169
+ btn = antd.Button("Generate ✨", type="primary", size="large")
170
+ clear_btn = antd.Button("Clear History", size="large")
171
+
172
+ antd.Divider("Examples")
173
+
174
+ with antd.Space(direction="vertical", style={"width": "100%"}):
175
  with ms.Each(DEMO_LIST):
176
+ with antd.Card(hoverable=True, as_item="card") as demoCard:
177
+ antd.CardMeta()
178
+ demoCard.click(demo_card_click, outputs=[input])
179
+
180
+ antd.Divider("Settings")
181
+
182
  with antd.Flex(gap="small", wrap=True):
183
+ settingPromptBtn = antd.Button("⚙️ System Prompt", type="default")
184
+ codeBtn = antd.Button("🧑‍💻 View Code", type="default")
185
+ historyBtn = antd.Button("📜 History", type="default")
186
+
187
+ # Right Column
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  with antd.Col(span=24, md=16):
189
  with ms.Div(elem_classes="right_panel"):
190
+ gr.HTML("""
191
+ <div class="render_header">
192
+ <span class="header_btn"></span>
193
+ <span class="header_btn"></span>
194
+ <span class="header_btn"></span>
195
+ </div>
196
+ """)
197
+
198
  with antd.Tabs(active_key="empty", render_tab_bar="() => null") as state_tab:
199
  with antd.Tabs.Item(key="empty"):
200
+ empty = antd.Empty(
201
+ description="Start by describing your application",
202
+ elem_classes="right_content"
203
+ )
204
+ with antd.Tabs.Item(key="loading"):
205
+ loading = antd.Spin(
206
+ True,
207
+ tip="Creating your application...",
208
+ size="large",
209
+ elem_classes="right_content"
210
+ )
211
+ with antd.Tabs.Item(key="render"):
212
+ sandbox = gr.HTML(elem_classes="html_content")
213
+
214
+ # Add modals and drawers
215
+ with antd.Modal(open=False, title="System Prompt", width="800px") as system_prompt_modal:
216
+ systemPromptInput = antd.InputTextarea(SystemPrompt, auto_size=True)
217
+
218
+ with antd.Drawer(open=False, title="Code", placement="left", width="750px") as code_drawer:
219
+ code_output = legacy.Markdown()
220
+
221
+ with antd.Drawer(open=False, title="History", placement="left", width="900px") as history_drawer:
222
+ history_output = legacy.Chatbot(
223
+ show_label=False,
224
+ height=960,
225
+ elem_classes="history_chatbot"
226
+ )
227
+
228
+ # Event handlers
229
+ def generation_code(query: Optional[str], _setting: Dict[str, str], _history: Optional[History]):
230
+ if query is None or query.strip() == '':
231
+ return
232
+
233
+ if _history is None:
234
+ _history = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
 
236
+ messages = history_to_messages(_history, _setting['system'])
237
+ messages.append({'role': Role.USER, 'content': query})
238
+
239
+ gen = Generation.call(
240
+ model="qwen2.5-coder-32b-instruct",
241
+ messages=messages,
242
+ result_format='message',
243
+ stream=True
244
+ )
245
+
246
+ for response in gen:
247
+ if response.status_code == HTTPStatus.OK:
248
+ role = response.output.choices[0].message.role
249
+ content = response.output.choices[0].message.content
250
+
251
+ if response.output.choices[0].finish_reason == 'stop':
252
+ _history = messages_to_history(messages + [
253
+ {'role': role, 'content': content}
254
+ ])
255
+
256
+ yield {
257
+ code_output: content,
258
+ history: _history,
259
+ sandbox: send_to_sandbox(remove_code_block(content)),
260
+ state_tab: gr.update(active_key="render"),
261
+ code_drawer: gr.update(open=False),
262
+ }
263
+ else:
264
+ yield {
265
+ code_output: content,
266
+ state_tab: gr.update(active_key="loading"),
267
+ code_drawer: gr.update(open=True),
268
+ }
269
+ else:
270
+ raise ValueError(
271
+ f'Request id: {response.request_id}, Status code: {response.status_code}, '
272
+ f'error code: {response.code}, error message: {response.message}'
273
+ )
274
+
275
+ # Connect event handlers
276
+ btn.click(
277
+ generation_code,
278
+ inputs=[input, setting, history],
279
+ outputs=[code_output, history, sandbox, state_tab, code_drawer]
280
+ )
281
+
282
+ clear_btn.click(lambda: [], outputs=[history])
283
+
284
+ settingPromptBtn.click(
285
+ lambda: gr.update(open=True),
286
+ outputs=[system_prompt_modal]
287
+ )
288
+
289
+ system_prompt_modal.ok(
290
+ lambda input: ({"system": input}, gr.update(open=False)),
291
+ inputs=[systemPromptInput],
292
+ outputs=[setting, system_prompt_modal]
293
+ )
294
 
295
+ # Launch the app
296
  if __name__ == "__main__":
297
+ demo.queue(concurrency_count=20).launch(
298
+ server_name="0.0.0.0",
299
+ server_port=7860,
300
+ share=True
301
+ )