bradnow commited on
Commit
0bb4279
·
1 Parent(s): 3b91dce

Add stop button and new styles

Browse files
Files changed (5) hide show
  1. app.py +181 -192
  2. gradio_runner.py +10 -0
  3. styles.css +84 -0
  4. theme.py +89 -32
  5. utils.py +24 -0
app.py CHANGED
@@ -4,21 +4,39 @@ from openai import OpenAI
4
  import gradio as gr
5
 
6
  from theme import apriel
7
- from utils import COMMUNITY_POSTFIX_URL, get_model_config, log_message, check_format, models_config
8
 
9
  MODEL_TEMPERATURE = 0.8
10
  BUTTON_WIDTH = 160
11
 
12
- DEFAULT_MODEL_NAME = "Apriel-Nemotron-15b-Thinker"
13
  # DEFAULT_MODEL_NAME = "Apriel-5b"
14
 
15
  print(f"Gradio version: {gr.__version__}")
16
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  chat_start_count = 0
18
  model_config = {}
19
  openai_client = None
20
 
21
 
 
 
 
 
 
 
22
  def setup_model(model_name, intial=False):
23
  global model_config, openai_client
24
  model_config = get_model_config(model_name)
@@ -40,194 +58,170 @@ def setup_model(model_name, intial=False):
40
  return _description
41
 
42
 
43
- def chat_fn(message, history):
44
- log_message(f"{'-' * 80}")
45
- log_message(f"chat_fn() --> Message: {message}")
46
- log_message(f"chat_fn() --> History: {history}")
47
 
48
- # Check if the message is empty
49
- if not message.strip():
50
- gr.Warning("Please enter a message before sending.")
51
- yield history
52
- return
53
 
54
- global chat_start_count
55
- chat_start_count = chat_start_count + 1
56
- print(
57
- f"{datetime.datetime.now()}: chat_start_count: {chat_start_count}, turns: {int(len(history if history else []) / 3)}")
58
 
59
- is_reasoning = model_config.get("REASONING")
60
 
61
- # Remove any assistant messages with metadata from history for multiple turns
62
- log_message(f"Initial History: {history}")
63
- check_format(history, "messages")
64
- history.append({"role": "user", "content": message})
65
- log_message(f"History with user message: {history}")
66
- check_format(history, "messages")
 
 
 
 
 
 
 
 
 
67
 
68
- # Create the streaming response
69
  try:
70
- history_no_thoughts = [item for item in history if
71
- not (isinstance(item, dict) and
72
- item.get("role") == "assistant" and
73
- isinstance(item.get("metadata"), dict) and
74
- item.get("metadata", {}).get("title") is not None)]
75
- log_message(f"Updated History: {history_no_thoughts}")
76
- check_format(history_no_thoughts, "messages")
77
- log_message(f"history_no_thoughts with user message: {history_no_thoughts}")
78
-
79
- stream = openai_client.chat.completions.create(
80
- model=model_config.get('MODEL_NAME'),
81
- messages=history_no_thoughts,
82
- temperature=MODEL_TEMPERATURE,
83
- stream=True
84
- )
85
- except Exception as e:
86
- print(f"Error: {e}")
87
- yield [{"role": "assistant", "content": "😔 The model is unavailable at the moment. Please try again later."}]
88
- return
89
 
90
- if is_reasoning:
91
- history.append(gr.ChatMessage(
92
- role="assistant",
93
- content="Thinking...",
94
- metadata={"title": "🧠 Thought"}
95
- ))
96
- log_message(f"History added thinking: {history}")
97
  check_format(history, "messages")
98
- else:
99
- history.append(gr.ChatMessage(
100
- role="assistant",
101
- content="",
102
- ))
103
- log_message(f"History added empty assistant: {history}")
104
  check_format(history, "messages")
105
 
106
- output = ""
107
- completion_started = False
108
- for chunk in stream:
109
- # Extract the new content from the delta field
110
- content = getattr(chunk.choices[0].delta, "content", "")
111
- output += content
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
  if is_reasoning:
114
- parts = output.split("[BEGIN FINAL RESPONSE]")
115
-
116
- if len(parts) > 1:
117
- if parts[1].endswith("[END FINAL RESPONSE]"):
118
- parts[1] = parts[1].replace("[END FINAL RESPONSE]", "")
119
- if parts[1].endswith("[END FINAL RESPONSE]\n<|end|>"):
120
- parts[1] = parts[1].replace("[END FINAL RESPONSE]\n<|end|>", "")
121
- if parts[1].endswith("<|end|>"):
122
- parts[1] = parts[1].replace("<|end|>", "")
123
-
124
- history[-1 if not completion_started else -2] = gr.ChatMessage(
125
  role="assistant",
126
- content=parts[0],
127
  metadata={"title": "🧠 Thought"}
128
- )
129
- if completion_started:
130
- history[-1] = gr.ChatMessage(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  role="assistant",
132
- content=parts[1]
 
133
  )
134
- elif len(parts) > 1 and not completion_started:
135
- completion_started = True
136
- history.append(gr.ChatMessage(
 
 
 
 
 
 
 
 
 
 
 
 
137
  role="assistant",
138
- content=parts[1]
139
- ))
140
- else:
141
- if output.endswith("<|end|>"):
142
- output = output.replace("<|end|>", "")
143
- history[-1] = gr.ChatMessage(
144
- role="assistant",
145
- content=output
146
- )
147
 
148
- # log_message(f"Yielding messages: {history}")
149
- yield history
150
 
151
- log_message(f"Final History: {history}")
152
- check_format(history, "messages")
 
 
 
 
 
 
153
 
154
 
155
  title = None
156
  description = None
157
-
158
- # theme = gr.themes.Default(primary_hue="green")
159
- # theme = gr.themes.Soft(primary_hue="gray", secondary_hue="slate", neutral_hue="slate",
160
- # text_size=gr.themes.sizes.text_lg, font=[gr.themes.GoogleFont("Inconsolata"), "Arial", "sans-serif"])
161
- # theme = gr.Theme.from_hub("earneleh/paris")
162
  theme = apriel
163
 
164
- with gr.Blocks(theme=theme) as demo:
165
- gr.HTML("""
166
- <style>
167
- .html-container:has(.css-styles) {
168
- padding: 0;
169
- margin: 0;
170
- }
171
-
172
- .css-styles { height: 0; }
173
-
174
- .model-message {
175
- text-align: end;
176
- }
177
-
178
- .model-dropdown-container {
179
- display: flex;
180
- align-items: center;
181
- gap: 10px;
182
- padding: 0;
183
- }
184
-
185
- .chatbot {
186
- max-height: 1400px;
187
- }
188
-
189
- @media (max-width: 800px) {
190
- .responsive-row {
191
- flex-direction: column;
192
- }
193
- .model-message {
194
- text-align: start;
195
- font-size: 10px !important;
196
- }
197
- .model-dropdown-container {
198
- flex-direction: column;
199
- align-items: flex-start;
200
- }
201
- .chatbot {
202
- max-height: 850px;
203
- }
204
- }
205
-
206
- @media (max-width: 400px) {
207
- .responsive-row {
208
- flex-direction: column;
209
- }
210
- .model-message {
211
- text-align: start;
212
- font-size: 10px !important;
213
- }
214
- .model-dropdown-container {
215
- flex-direction: column;
216
- align-items: flex-start;
217
- }
218
- .chatbot {
219
- max-height: 400px;
220
- }
221
- }
222
- """ + f"""
223
- @media (min-width: 1024px) {{
224
- .send-button-container, .clear-button-container {{
225
- max-width: {BUTTON_WIDTH}px;
226
- }}
227
- }}
228
- </style>
229
- """, elem_classes="css-styles")
230
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  with gr.Row(variant="panel", elem_classes="responsive-row"):
232
  with gr.Column(scale=1, min_width=400, elem_classes="model-dropdown-container"):
233
  model_dropdown = gr.Dropdown(
@@ -248,55 +242,50 @@ with gr.Blocks(theme=theme) as demo:
248
  elem_classes="chatbot",
249
  )
250
 
251
- # chat_interface = gr.ChatInterface(
252
- # chat_fn,
253
- # description="",
254
- # type="messages",
255
- # chatbot=chatbot,
256
- # fill_height=True,
257
- # )
258
-
259
  with gr.Row():
260
  with gr.Column(scale=10, min_width=400, elem_classes="user-input-container"):
261
  user_input = gr.Textbox(
262
  show_label=False,
263
  placeholder="Type your message here and press Enter",
264
- container=False,
265
  )
266
  with gr.Column(scale=1, min_width=BUTTON_WIDTH * 2 + 20):
267
  with gr.Row():
268
  with gr.Column(scale=1, min_width=BUTTON_WIDTH, elem_classes="send-button-container"):
269
  send_btn = gr.Button("Send", variant="primary")
 
270
  with gr.Column(scale=1, min_width=BUTTON_WIDTH, elem_classes="clear-button-container"):
271
  clear_btn = gr.ClearButton(chatbot, value="New Chat", variant="secondary")
272
 
273
- # on Enter: stream into the chatbot, then clear the textbox
274
- user_input.submit(
275
- fn=chat_fn,
276
- inputs=[user_input, chatbot],
277
- outputs=[chatbot]
 
 
 
 
 
 
 
 
 
 
 
278
  )
279
- user_input.submit(lambda: "", None, user_input, queue=False)
280
 
281
- send_btn.click(
282
- fn=chat_fn,
283
- inputs=[user_input, chatbot],
284
- outputs=[chatbot]
285
  )
286
- send_btn.click(lambda: "", None, user_input, queue=False)
287
 
288
  # Ensure the model is reset to default on page reload
289
  demo.load(lambda: setup_model(DEFAULT_MODEL_NAME, intial=False), [], [description_html])
290
 
291
-
292
- def update_model_and_clear(model_name):
293
- actual_model_name = model_name.replace("Model: ", "")
294
- desc = setup_model(actual_model_name)
295
- return desc, []
296
-
297
-
298
  model_dropdown.change(
299
- fn=update_model_and_clear,
300
  inputs=[model_dropdown],
301
  outputs=[description_html, chatbot]
302
  )
 
4
  import gradio as gr
5
 
6
  from theme import apriel
7
+ from utils import COMMUNITY_POSTFIX_URL, get_model_config, log_message, check_format, models_config, DEBUG_MODE
8
 
9
  MODEL_TEMPERATURE = 0.8
10
  BUTTON_WIDTH = 160
11
 
12
+ DEFAULT_MODEL_NAME = "Apriel-Nemotron-15b-Thinker" if not DEBUG_MODE else "Apriel-5b"
13
  # DEFAULT_MODEL_NAME = "Apriel-5b"
14
 
15
  print(f"Gradio version: {gr.__version__}")
16
 
17
+ BUTTON_ENABLED = gr.update(interactive=True)
18
+ BUTTON_DISABLED = gr.update(interactive=False)
19
+ INPUT_ENABLED = gr.update(interactive=True)
20
+ INPUT_DISABLED = gr.update(interactive=False)
21
+ DROPDOWN_ENABLED = gr.update(interactive=True)
22
+ DROPDOWN_DISABLED = gr.update(interactive=False)
23
+
24
+ SEND_BUTTON_ENABLED = gr.update(interactive=True, visible=True)
25
+ SEND_BUTTON_DISABLED = gr.update(interactive=True, visible=False)
26
+ STOP_BUTTON_ENABLED = gr.update(interactive=True, visible=True)
27
+ STOP_BUTTON_DISABLED = gr.update(interactive=True, visible=False)
28
+
29
  chat_start_count = 0
30
  model_config = {}
31
  openai_client = None
32
 
33
 
34
+ def update_model_and_clear_chat(model_name):
35
+ actual_model_name = model_name.replace("Model: ", "")
36
+ desc = setup_model(actual_model_name)
37
+ return desc, []
38
+
39
+
40
  def setup_model(model_name, intial=False):
41
  global model_config, openai_client
42
  model_config = get_model_config(model_name)
 
58
  return _description
59
 
60
 
61
+ def chat_started():
62
+ # outputs: model_dropdown, user_input, send_btn, stop_btn, clear_btn
63
+ return (DROPDOWN_DISABLED, gr.update(value="", interactive=False),
64
+ SEND_BUTTON_DISABLED, STOP_BUTTON_ENABLED, BUTTON_DISABLED)
65
 
 
 
 
 
 
66
 
67
+ def chat_finished():
68
+ # outputs: model_dropdown, user_input, send_btn, stop_btn, clear_btn
69
+ return DROPDOWN_ENABLED, INPUT_ENABLED, SEND_BUTTON_ENABLED, STOP_BUTTON_DISABLED, BUTTON_ENABLED
 
70
 
 
71
 
72
+ def stop_chat(state):
73
+ state["stop_flag"] = True
74
+ gr.Info("Chat stopped")
75
+ return state
76
+
77
+
78
+ def run_chat_inference(history, message, state):
79
+ global chat_start_count
80
+ state["is_streaming"] = True
81
+ state["stop_flag"] = False
82
+
83
+ # outputs: model_dropdown, user_input, send_btn, stop_btn, clear_btn, session_state
84
+ log_message(f"{'-' * 80}")
85
+ log_message(f"chat_fn() --> Message: {message}")
86
+ log_message(f"chat_fn() --> History: {history}")
87
 
 
88
  try:
89
+ # Check if the message is empty
90
+ if not message.strip():
91
+ gr.Info("Please enter a message before sending")
92
+ yield history, INPUT_ENABLED, SEND_BUTTON_ENABLED, STOP_BUTTON_DISABLED, BUTTON_ENABLED, state
93
+ return history, INPUT_ENABLED, SEND_BUTTON_ENABLED, STOP_BUTTON_DISABLED, BUTTON_ENABLED, state
94
+
95
+ chat_start_count = chat_start_count + 1
96
+ print(
97
+ f"{datetime.datetime.now()}: chat_start_count: {chat_start_count}, turns: {int(len(history if history else []) / 3)}")
98
+
99
+ is_reasoning = model_config.get("REASONING")
 
 
 
 
 
 
 
 
100
 
101
+ # Remove any assistant messages with metadata from history for multiple turns
102
+ log_message(f"Initial History: {history}")
 
 
 
 
 
103
  check_format(history, "messages")
104
+ history.append({"role": "user", "content": message})
105
+ log_message(f"History with user message: {history}")
 
 
 
 
106
  check_format(history, "messages")
107
 
108
+ # Create the streaming response
109
+ try:
110
+ history_no_thoughts = [item for item in history if
111
+ not (isinstance(item, dict) and
112
+ item.get("role") == "assistant" and
113
+ isinstance(item.get("metadata"), dict) and
114
+ item.get("metadata", {}).get("title") is not None)]
115
+ log_message(f"Updated History: {history_no_thoughts}")
116
+ check_format(history_no_thoughts, "messages")
117
+ log_message(f"history_no_thoughts with user message: {history_no_thoughts}")
118
+
119
+ stream = openai_client.chat.completions.create(
120
+ model=model_config.get('MODEL_NAME'),
121
+ messages=history_no_thoughts,
122
+ temperature=MODEL_TEMPERATURE,
123
+ stream=True
124
+ )
125
+ except Exception as e:
126
+ print(f"Error: {e}")
127
+ yield ([{"role": "assistant",
128
+ "content": "😔 The model is unavailable at the moment. Please try again later."}],
129
+ INPUT_ENABLED, SEND_BUTTON_ENABLED, STOP_BUTTON_DISABLED, BUTTON_ENABLED, state)
130
+ return history, INPUT_ENABLED, SEND_BUTTON_ENABLED, STOP_BUTTON_DISABLED, BUTTON_ENABLED, state
131
 
132
  if is_reasoning:
133
+ history.append(gr.ChatMessage(
 
 
 
 
 
 
 
 
 
 
134
  role="assistant",
135
+ content="Thinking...",
136
  metadata={"title": "🧠 Thought"}
137
+ ))
138
+ log_message(f"History added thinking: {history}")
139
+ check_format(history, "messages")
140
+ else:
141
+ history.append(gr.ChatMessage(
142
+ role="assistant",
143
+ content="",
144
+ ))
145
+ log_message(f"History added empty assistant: {history}")
146
+ check_format(history, "messages")
147
+
148
+ output = ""
149
+ completion_started = False
150
+ for chunk in stream:
151
+ if state["stop_flag"]:
152
+ log_message(f"chat_fn() --> Stopping streaming...")
153
+ break # Exit the loop if the stop flag is set
154
+ # Extract the new content from the delta field
155
+ content = getattr(chunk.choices[0].delta, "content", "")
156
+ output += content
157
+
158
+ if is_reasoning:
159
+ parts = output.split("[BEGIN FINAL RESPONSE]")
160
+
161
+ if len(parts) > 1:
162
+ if parts[1].endswith("[END FINAL RESPONSE]"):
163
+ parts[1] = parts[1].replace("[END FINAL RESPONSE]", "")
164
+ if parts[1].endswith("[END FINAL RESPONSE]\n<|end|>"):
165
+ parts[1] = parts[1].replace("[END FINAL RESPONSE]\n<|end|>", "")
166
+ if parts[1].endswith("<|end|>"):
167
+ parts[1] = parts[1].replace("<|end|>", "")
168
+
169
+ history[-1 if not completion_started else -2] = gr.ChatMessage(
170
  role="assistant",
171
+ content=parts[0],
172
+ metadata={"title": "🧠 Thought"}
173
  )
174
+ if completion_started:
175
+ history[-1] = gr.ChatMessage(
176
+ role="assistant",
177
+ content=parts[1]
178
+ )
179
+ elif len(parts) > 1 and not completion_started:
180
+ completion_started = True
181
+ history.append(gr.ChatMessage(
182
+ role="assistant",
183
+ content=parts[1]
184
+ ))
185
+ else:
186
+ if output.endswith("<|end|>"):
187
+ output = output.replace("<|end|>", "")
188
+ history[-1] = gr.ChatMessage(
189
  role="assistant",
190
+ content=output
191
+ )
 
 
 
 
 
 
 
192
 
193
+ # log_message(f"Yielding messages: {history}")
194
+ yield history, INPUT_DISABLED, SEND_BUTTON_DISABLED, STOP_BUTTON_ENABLED, BUTTON_DISABLED, state
195
 
196
+ log_message(f"Final History: {history}")
197
+ check_format(history, "messages")
198
+ yield history, INPUT_ENABLED, SEND_BUTTON_ENABLED, STOP_BUTTON_DISABLED, BUTTON_ENABLED, state
199
+ finally:
200
+ state["is_streaming"] = False
201
+ state["stop_flag"] = False
202
+ log_message(f"chat_fn() --> Finished streaming. {chat_start_count} chats started.")
203
+ return history, INPUT_ENABLED, SEND_BUTTON_ENABLED, STOP_BUTTON_DISABLED, BUTTON_ENABLED, state
204
 
205
 
206
  title = None
207
  description = None
 
 
 
 
 
208
  theme = apriel
209
 
210
+ with open('styles.css', 'r') as f:
211
+ custom_css = f.read()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
 
213
+ with gr.Blocks(theme=theme, css=custom_css) as demo:
214
+ session_state = gr.State(value={"is_streaming": False, "stop_flag": False}) # Store session state as a dictionary
215
+
216
+ gr.HTML(f"""
217
+ <style>
218
+ @media (min-width: 1024px) {{
219
+ .send-button-container, .clear-button-container {{
220
+ max-width: {BUTTON_WIDTH}px;
221
+ }}
222
+ }}
223
+ </style>
224
+ """, elem_classes="css-styles")
225
  with gr.Row(variant="panel", elem_classes="responsive-row"):
226
  with gr.Column(scale=1, min_width=400, elem_classes="model-dropdown-container"):
227
  model_dropdown = gr.Dropdown(
 
242
  elem_classes="chatbot",
243
  )
244
 
 
 
 
 
 
 
 
 
245
  with gr.Row():
246
  with gr.Column(scale=10, min_width=400, elem_classes="user-input-container"):
247
  user_input = gr.Textbox(
248
  show_label=False,
249
  placeholder="Type your message here and press Enter",
250
+ container=False
251
  )
252
  with gr.Column(scale=1, min_width=BUTTON_WIDTH * 2 + 20):
253
  with gr.Row():
254
  with gr.Column(scale=1, min_width=BUTTON_WIDTH, elem_classes="send-button-container"):
255
  send_btn = gr.Button("Send", variant="primary")
256
+ stop_btn = gr.Button("Stop", variant="cancel", visible=False)
257
  with gr.Column(scale=1, min_width=BUTTON_WIDTH, elem_classes="clear-button-container"):
258
  clear_btn = gr.ClearButton(chatbot, value="New Chat", variant="secondary")
259
 
260
+ gr.on(
261
+ triggers=[send_btn.click, user_input.submit],
262
+ fn=run_chat_inference, # this generator streams results. do not use logged_event_handler wrapper
263
+ inputs=[chatbot, user_input, session_state],
264
+ outputs=[chatbot, user_input, send_btn, stop_btn, clear_btn, session_state]
265
+ ).then(
266
+ fn=chat_finished, inputs=None, outputs=[model_dropdown, user_input, send_btn, stop_btn, clear_btn], queue=False)
267
+
268
+ # In parallel, disable or update the UI controls
269
+ gr.on(
270
+ triggers=[send_btn.click, user_input.submit],
271
+ fn=chat_started,
272
+ inputs=None,
273
+ outputs=[model_dropdown, user_input, send_btn, stop_btn, clear_btn],
274
+ queue=False,
275
+ show_progress='hidden'
276
  )
 
277
 
278
+ stop_btn.click(
279
+ fn=stop_chat,
280
+ inputs=[session_state],
281
+ outputs=[session_state]
282
  )
 
283
 
284
  # Ensure the model is reset to default on page reload
285
  demo.load(lambda: setup_model(DEFAULT_MODEL_NAME, intial=False), [], [description_html])
286
 
 
 
 
 
 
 
 
287
  model_dropdown.change(
288
+ fn=update_model_and_clear_chat,
289
  inputs=[model_dropdown],
290
  outputs=[description_html, chatbot]
291
  )
gradio_runner.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import sys
3
+ from gradio.cli import cli
4
+
5
+ # This runs a gradio app so that it can be automatically reloaded in the browser
6
+ # Example: python gradio_runner.py app.py
7
+
8
+ if __name__ == '__main__':
9
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
10
+ sys.exit(cli())
styles.css ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --color-grey-50: #f9fafb;
3
+ }
4
+
5
+ .toast-body {
6
+ background-color: var(--color-grey-50);
7
+ }
8
+
9
+ .html-container:has(.css-styles) {
10
+ padding: 0;
11
+ margin: 0;
12
+ }
13
+
14
+ .css-styles {
15
+ height: 0;
16
+ }
17
+
18
+ .model-message {
19
+ text-align: end;
20
+ }
21
+
22
+ .model-dropdown-container {
23
+ display: flex;
24
+ align-items: center;
25
+ gap: 10px;
26
+ padding: 0;
27
+ }
28
+
29
+ .chatbot {
30
+ max-height: 1400px;
31
+ }
32
+
33
+ button.cancel {
34
+ border: var(--button-border-width) solid var(--button-cancel-border-color);
35
+ background: var(--button-cancel-background-fill);
36
+ color: var(--button-cancel-text-color);
37
+ box-shadow: var(--button-cancel-shadow);
38
+ }
39
+
40
+ button.cancel:hover, .cancel[disabled] {
41
+ background: var(--button-cancel-background-fill-hover);
42
+ color: var(--button-cancel-text-color-hover);
43
+ }
44
+
45
+
46
+ @media (max-width: 800px) {
47
+ .responsive-row {
48
+ flex-direction: column;
49
+ }
50
+
51
+ .model-message {
52
+ text-align: start;
53
+ font-size: 10px !important;
54
+ }
55
+
56
+ .model-dropdown-container {
57
+ flex-direction: column;
58
+ align-items: flex-start;
59
+ }
60
+
61
+ .chatbot {
62
+ max-height: 850px;
63
+ }
64
+ }
65
+
66
+ @media (max-width: 400px) {
67
+ .responsive-row {
68
+ flex-direction: column;
69
+ }
70
+
71
+ .model-message {
72
+ text-align: start;
73
+ font-size: 10px !important;
74
+ }
75
+
76
+ .model-dropdown-container {
77
+ flex-direction: column;
78
+ align-items: flex-start;
79
+ }
80
+
81
+ .chatbot {
82
+ max-height: 400px;
83
+ }
84
+ }
theme.py CHANGED
@@ -1,10 +1,36 @@
1
- # from __future__ import annotations
2
  from typing import Iterable
3
- import gradio as gr
4
  from gradio.themes import Soft
5
- # from gradio.themes.base import Base
6
  from gradio.themes.utils import colors, fonts, sizes
7
- import time
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
 
10
  class Apriel(Soft):
@@ -12,8 +38,8 @@ class Apriel(Soft):
12
  self,
13
  *,
14
  primary_hue: colors.Color | str = colors.gray,
15
- secondary_hue: colors.Color | str = colors.slate,
16
- neutral_hue: colors.Color | str = colors.gray,
17
  # spacing_size: sizes.Size | str = sizes.spacing_md,
18
  # radius_size: sizes.Size | str = sizes.radius_md,
19
  text_size: sizes.Size | str = sizes.text_md,
@@ -43,19 +69,47 @@ class Apriel(Soft):
43
  font_mono=font_mono,
44
  )
45
  super().set(
46
- body_background_fill="linear-gradient(135deg, *primary_200, *secondary_300)",
47
- body_background_fill_dark="linear-gradient(135deg, *primary_900, *secondary_800)",
48
- button_primary_background_fill="linear-gradient(90deg, *primary_400, *secondary_600)",
49
- button_primary_background_fill_hover="linear-gradient(90deg, *primary_200, *secondary_300)",
 
 
50
  button_primary_text_color="white",
51
  button_primary_text_color_hover="black",
52
- button_primary_background_fill_dark="linear-gradient(90deg, *primary_500, *secondary_600)",
 
 
 
53
 
54
  button_secondary_text_color="black",
55
  button_secondary_text_color_hover="white",
56
- button_secondary_background_fill="linear-gradient(90deg, *primary_200, *secondary_300)",
57
- button_secondary_background_fill_hover="linear-gradient(90deg, *secondary_400, *secondary_500)",
58
- button_secondary_background_fill_dark="linear-gradient(90deg, *secondary_500, *secondary_600)",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  slider_color="*secondary_300",
61
  slider_color_dark="*secondary_600",
@@ -66,26 +120,29 @@ class Apriel(Soft):
66
  button_large_padding="11px",
67
 
68
  color_accent_soft="*primary_100",
69
- )
70
 
 
71
 
72
- apriel = Apriel()
73
-
74
- with gr.Blocks(theme=apriel) as demo:
75
- textbox = gr.Textbox(label="Name")
76
- slider = gr.Slider(label="Count", minimum=0, maximum=100, step=1)
77
- with gr.Row():
78
- button = gr.Button("Submit", variant="primary")
79
- clear = gr.Button("Clear")
80
- output = gr.Textbox(label="Output")
81
-
82
-
83
- def repeat(name, count):
84
- time.sleep(3)
85
- return name * count
86
 
87
 
88
- button.click(repeat, [textbox, slider], output)
89
 
90
- if __name__ == "__main__":
91
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from typing import Iterable
 
2
  from gradio.themes import Soft
 
3
  from gradio.themes.utils import colors, fonts, sizes
4
+
5
+ colors.teal_gray = colors.Color(
6
+ name="teal_gray",
7
+ c50="#e8f1f4",
8
+ c100="#cddde3",
9
+ c200="#a8c3cf",
10
+ c300="#7da6b8",
11
+ c400="#588aa2",
12
+ c500="#3d6e87",
13
+ c600="#335b70",
14
+ c700="#2b495a",
15
+ c800="#2c5364",
16
+ c900="#233f4b",
17
+ c950="#1b323c",
18
+ )
19
+
20
+ colors.red_gray = colors.Color(
21
+ name="red_gray",
22
+ c50="#f7eded",
23
+ c100="#f5dcdc",
24
+ c200="#efb4b4",
25
+ c300="#e78f8f",
26
+ c400="#d96a6a",
27
+ c500="#c65353",
28
+ c600="#b24444",
29
+ c700="#8f3434",
30
+ c800="#732d2d",
31
+ c900="#5f2626",
32
+ c950="#4d2020",
33
+ )
34
 
35
 
36
  class Apriel(Soft):
 
38
  self,
39
  *,
40
  primary_hue: colors.Color | str = colors.gray,
41
+ secondary_hue: colors.Color | str = colors.teal_gray,
42
+ neutral_hue: colors.Color | str = colors.slate,
43
  # spacing_size: sizes.Size | str = sizes.spacing_md,
44
  # radius_size: sizes.Size | str = sizes.radius_md,
45
  text_size: sizes.Size | str = sizes.text_md,
 
69
  font_mono=font_mono,
70
  )
71
  super().set(
72
+ background_fill_primary="*primary_50",
73
+ background_fill_primary_dark="*primary_900",
74
+
75
+ body_background_fill="linear-gradient(135deg, *primary_200, *primary_100)",
76
+ body_background_fill_dark="linear-gradient(135deg, *primary_900, *primary_800)",
77
+
78
  button_primary_text_color="white",
79
  button_primary_text_color_hover="black",
80
+ button_primary_background_fill="linear-gradient(90deg, *secondary_400, *secondary_400)",
81
+ button_primary_background_fill_hover="linear-gradient(90deg, *secondary_300, *secondary_300)",
82
+ button_primary_background_fill_dark="linear-gradient(90deg, *secondary_600, *secondary_800)",
83
+ button_primary_background_fill_hover_dark="linear-gradient(90deg, *secondary_500, *secondary_500)",
84
 
85
  button_secondary_text_color="black",
86
  button_secondary_text_color_hover="white",
87
+ button_secondary_background_fill="linear-gradient(90deg, *primary_300, *primary_300)",
88
+ button_secondary_background_fill_hover="linear-gradient(90deg, *primary_400, *primary_400)",
89
+ button_secondary_background_fill_dark="linear-gradient(90deg, *primary_500, *primary_600)",
90
+ button_secondary_background_fill_hover_dark="linear-gradient(90deg, *primary_500, *primary_500)",
91
+
92
+ button_cancel_background_fill=f"linear-gradient(90deg, {colors.red_gray.c400}, {colors.red_gray.c500})",
93
+ button_cancel_background_fill_dark=f"linear-gradient(90deg, {colors.red_gray.c700}, {colors.red_gray.c800})",
94
+ button_cancel_background_fill_hover=f"linear-gradient(90deg, {colors.red_gray.c500}, {colors.red_gray.c600})",
95
+ button_cancel_background_fill_hover_dark=f"linear-gradient(90deg, {colors.red_gray.c800}, {colors.red_gray.c900})",
96
+ # button_cancel_background_fill=f"linear-gradient(90deg, {colors.red.c400}, {colors.red.c500})",
97
+ # button_cancel_background_fill_dark=f"linear-gradient(90deg, {colors.red.c700}, {colors.red.c800})",
98
+ # button_cancel_background_fill_hover=f"linear-gradient(90deg, {colors.red.c500}, {colors.red.c600})",
99
+ # button_cancel_background_fill_hover_dark=f"linear-gradient(90deg, {colors.red.c800}, {colors.red.c900})",
100
+ button_cancel_text_color="white",
101
+ button_cancel_text_color_dark="white",
102
+ button_cancel_text_color_hover="white",
103
+ button_cancel_text_color_hover_dark="white",
104
+
105
+ # button_cancel_background_fill=colors.red.c500,
106
+ # button_cancel_background_fill_dark=colors.red.c700,
107
+ # button_cancel_background_fill_hover=colors.red.c600,
108
+ # button_cancel_background_fill_hover_dark=colors.red.c800,
109
+ # button_cancel_text_color="white",
110
+ # button_cancel_text_color_dark="white",
111
+ # button_cancel_text_color_hover="white",
112
+ # button_cancel_text_color_hover_dark="white",
113
 
114
  slider_color="*secondary_300",
115
  slider_color_dark="*secondary_600",
 
120
  button_large_padding="11px",
121
 
122
  color_accent_soft="*primary_100",
 
123
 
124
+ block_label_background_fill="*primary_200",
125
 
126
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
 
129
+ apriel = Apriel()
130
 
131
+ # with gr.Blocks(theme=apriel) as demo:
132
+ # textbox = gr.Textbox(label="Name")
133
+ # slider = gr.Slider(label="Count", minimum=0, maximum=100, step=1)
134
+ # with gr.Row():
135
+ # button = gr.Button("Submit", variant="primary")
136
+ # clear = gr.Button("Clear")
137
+ # output = gr.Textbox(label="Output")
138
+ #
139
+ #
140
+ # def repeat(name, count):
141
+ # time.sleep(3)
142
+ # return name * count
143
+ #
144
+ #
145
+ # button.click(repeat, [textbox, slider], output)
146
+ #
147
+ # if __name__ == "__main__":
148
+ # demo.launch()
utils.py CHANGED
@@ -4,6 +4,7 @@ from typing import Any, Literal
4
 
5
  from gradio import ChatMessage
6
  from gradio.components.chatbot import Message
 
7
 
8
  COMMUNITY_POSTFIX_URL = "/discussions"
9
  DEBUG_MODE = False or os.environ.get("DEBUG_MODE") == "True"
@@ -79,3 +80,26 @@ def check_format(messages: Any, type: Literal["messages", "tuples"] = "messages"
79
  raise Exception(
80
  "Data incompatible with tuples format. Each message should be a list of length 2."
81
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  from gradio import ChatMessage
6
  from gradio.components.chatbot import Message
7
+ from functools import wraps
8
 
9
  COMMUNITY_POSTFIX_URL = "/discussions"
10
  DEBUG_MODE = False or os.environ.get("DEBUG_MODE") == "True"
 
80
  raise Exception(
81
  "Data incompatible with tuples format. Each message should be a list of length 2."
82
  )
83
+
84
+
85
+ def logged_event_handler(log_message='', event_handler=None, timer=None, clear_timer=False):
86
+ @wraps(event_handler)
87
+ def wrapped_event_handler(*args, **kwargs):
88
+ # Log before
89
+ if timer:
90
+ if clear_timer:
91
+ timer.clear()
92
+ timer.add_step(f"Start: {log_message}")
93
+ log_message(f"::: Before event: {log_message}")
94
+
95
+ # Call the original event handler
96
+ result = event_handler(*args, **kwargs)
97
+
98
+ # Log after
99
+ if timer:
100
+ timer.add_step(f"Completed: {log_message}")
101
+ log_message(f"::: After event: {log_message}")
102
+
103
+ return result
104
+
105
+ return wrapped_event_handler