Spaces:
Running
Running
Clean up & Format
Browse files
app.py
CHANGED
@@ -22,7 +22,6 @@ class AppConfig:
|
|
22 |
API_TIMEOUT = 20
|
23 |
|
24 |
|
25 |
-
|
26 |
class DynamicState:
|
27 |
"""动态UI状态"""
|
28 |
|
@@ -72,18 +71,19 @@ class DynamicState:
|
|
72 |
)
|
73 |
self.label_passthrough = False
|
74 |
return output
|
75 |
-
|
76 |
def reset_workspace(self):
|
77 |
"""重置工作区状态"""
|
78 |
self.stream_completed = False
|
79 |
self.should_stream = False
|
80 |
self.in_cot = True
|
81 |
self.waiting_api = False
|
|
|
82 |
return self.ui_state_controller() + (
|
83 |
"",
|
84 |
"",
|
85 |
LANGUAGE_CONFIG["en"]["bot_default"],
|
86 |
-
DEFAULT_PERSISTENT
|
87 |
)
|
88 |
|
89 |
|
@@ -189,14 +189,17 @@ class ConvoState:
|
|
189 |
)
|
190 |
for chunk in response_stream:
|
191 |
chunk_content = chunk.choices[0].delta.content
|
192 |
-
if
|
|
|
|
|
|
|
193 |
dynamic_state.should_stream = False
|
194 |
if not dynamic_state.should_stream:
|
195 |
break
|
196 |
|
197 |
if chunk_content:
|
198 |
dynamic_state.waiting_api = False
|
199 |
-
full_response += chunk_content.replace("<think>","")
|
200 |
self.current["raw"] = full_response
|
201 |
# Update Convo State
|
202 |
think_complete = "</think>" in full_response
|
@@ -219,7 +222,9 @@ class ConvoState:
|
|
219 |
if self.result_editing_toggle:
|
220 |
editor_output = full_response
|
221 |
else:
|
222 |
-
editor_output = self.current["cot"]
|
|
|
|
|
223 |
yield editor_output, gr.update(
|
224 |
label=editor_label
|
225 |
), self.flatten_output()
|
@@ -227,13 +232,15 @@ class ConvoState:
|
|
227 |
interval = 1.0 / self.throughput
|
228 |
start_time = time.time()
|
229 |
while (
|
230 |
-
time.time() - start_time
|
231 |
-
|
|
|
|
|
232 |
time.sleep(0.005)
|
233 |
|
234 |
except Exception as e:
|
235 |
if str(e) == "list index out of range":
|
236 |
-
dynamic_state.stream_completed = True
|
237 |
else:
|
238 |
if str(e) == "The read operation timed out":
|
239 |
error_msg = lang_data["api_interrupted"]
|
@@ -244,7 +251,6 @@ class ConvoState:
|
|
244 |
self.is_error = True
|
245 |
dynamic_state.label_passthrough = True
|
246 |
|
247 |
-
|
248 |
finally:
|
249 |
dynamic_state.should_stream = False
|
250 |
if "response_stream" in locals():
|
@@ -256,17 +262,20 @@ class ConvoState:
|
|
256 |
)
|
257 |
editor_label = f"{lang_data['editor_label']} - {final_status}"
|
258 |
if not self.is_error:
|
259 |
-
yield editor_output, gr.update(
|
|
|
|
|
260 |
else:
|
261 |
-
yield editor_output, gr.update(
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
|
|
270 |
|
271 |
|
272 |
def update_interface_language(selected_lang, convo_state, dynamic_state):
|
@@ -315,18 +324,18 @@ def update_interface_language(selected_lang, convo_state, dynamic_state):
|
|
315 |
theme = gr.themes.Base(font="system-ui", primary_hue="stone")
|
316 |
|
317 |
with gr.Blocks(theme=theme, css_paths="styles.css") as demo:
|
318 |
-
DEFAULT_PERSISTENT = {"prompt_input":"", "thought_editor":""}
|
319 |
convo_state = gr.State(ConvoState)
|
320 |
dynamic_state = gr.State(DynamicState)
|
321 |
persistent_state = gr.BrowserState(DEFAULT_PERSISTENT)
|
322 |
|
323 |
bot_default = LANGUAGE_CONFIG["en"]["bot_default"] + [
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
|
331 |
with gr.Row(variant=""):
|
332 |
title_md = gr.Markdown(
|
@@ -341,7 +350,6 @@ with gr.Blocks(theme=theme, css_paths="styles.css") as demo:
|
|
341 |
container=False,
|
342 |
)
|
343 |
|
344 |
-
|
345 |
with gr.Row(equal_height=True):
|
346 |
with gr.Column(scale=1, min_width=400):
|
347 |
prompt_input = gr.Textbox(
|
@@ -393,10 +401,15 @@ with gr.Blocks(theme=theme, css_paths="styles.css") as demo:
|
|
393 |
label=LANGUAGE_CONFIG["en"]["throughput_label"],
|
394 |
info=LANGUAGE_CONFIG["en"]["throughput_info"],
|
395 |
)
|
396 |
-
result_editing_toggle = gr.Checkbox(
|
|
|
|
|
|
|
|
|
|
|
397 |
|
398 |
intro_md = gr.Markdown(LANGUAGE_CONFIG["en"]["introduction"], visible=False)
|
399 |
-
|
400 |
@demo.load(inputs=[persistent_state], outputs=[prompt_input, thought_editor])
|
401 |
def recover_persistent_state(persistant_state):
|
402 |
if persistant_state["prompt_input"] or persistant_state["thought_editor"]:
|
@@ -404,7 +417,6 @@ with gr.Blocks(theme=theme, css_paths="styles.css") as demo:
|
|
404 |
else:
|
405 |
return gr.update(), gr.update()
|
406 |
|
407 |
-
|
408 |
# 交互逻辑
|
409 |
stateful_ui = (control_button, thought_editor, next_turn_btn)
|
410 |
|
@@ -426,7 +438,12 @@ with gr.Blocks(theme=theme, css_paths="styles.css") as demo:
|
|
426 |
for response in convo_state.generate_ai_response(
|
427 |
prompt, content, dynamic_state
|
428 |
):
|
429 |
-
yield response + (
|
|
|
|
|
|
|
|
|
|
|
430 |
|
431 |
gr.on(
|
432 |
[control_button.click, prompt_input.submit, thought_editor.submit],
|
@@ -453,24 +470,20 @@ with gr.Blocks(theme=theme, css_paths="styles.css") as demo:
|
|
453 |
[dynamic_state],
|
454 |
stateful_ui + (thought_editor, prompt_input, chatbot, persistent_state),
|
455 |
concurrency_limit=None,
|
456 |
-
show_progress=False
|
457 |
)
|
458 |
|
459 |
def toggle_editor_result(convo_state, allow):
|
460 |
setattr(convo_state, "result_editing_toggle", allow)
|
461 |
if allow:
|
462 |
-
print(convo_state.current["raw"])
|
463 |
return gr.update(value=convo_state.current["raw"])
|
464 |
else:
|
465 |
-
print(convo_state.current["cot"])
|
466 |
return gr.update(value=convo_state.current["cot"])
|
467 |
|
468 |
-
|
469 |
-
|
470 |
result_editing_toggle.change(
|
471 |
toggle_editor_result,
|
472 |
inputs=[convo_state, result_editing_toggle],
|
473 |
-
outputs=[thought_editor]
|
474 |
)
|
475 |
|
476 |
lang_selector.change(
|
@@ -487,7 +500,7 @@ with gr.Blocks(theme=theme, css_paths="styles.css") as demo:
|
|
487 |
next_turn_btn,
|
488 |
intro_md,
|
489 |
chatbot,
|
490 |
-
result_editing_toggle
|
491 |
],
|
492 |
concurrency_limit=None,
|
493 |
)
|
|
|
22 |
API_TIMEOUT = 20
|
23 |
|
24 |
|
|
|
25 |
class DynamicState:
|
26 |
"""动态UI状态"""
|
27 |
|
|
|
71 |
)
|
72 |
self.label_passthrough = False
|
73 |
return output
|
74 |
+
|
75 |
def reset_workspace(self):
|
76 |
"""重置工作区状态"""
|
77 |
self.stream_completed = False
|
78 |
self.should_stream = False
|
79 |
self.in_cot = True
|
80 |
self.waiting_api = False
|
81 |
+
|
82 |
return self.ui_state_controller() + (
|
83 |
"",
|
84 |
"",
|
85 |
LANGUAGE_CONFIG["en"]["bot_default"],
|
86 |
+
DEFAULT_PERSISTENT,
|
87 |
)
|
88 |
|
89 |
|
|
|
189 |
)
|
190 |
for chunk in response_stream:
|
191 |
chunk_content = chunk.choices[0].delta.content
|
192 |
+
if (
|
193 |
+
coordinator.should_pause_for_human(full_response)
|
194 |
+
and dynamic_state.in_cot
|
195 |
+
):
|
196 |
dynamic_state.should_stream = False
|
197 |
if not dynamic_state.should_stream:
|
198 |
break
|
199 |
|
200 |
if chunk_content:
|
201 |
dynamic_state.waiting_api = False
|
202 |
+
full_response += chunk_content.replace("<think>", "")
|
203 |
self.current["raw"] = full_response
|
204 |
# Update Convo State
|
205 |
think_complete = "</think>" in full_response
|
|
|
222 |
if self.result_editing_toggle:
|
223 |
editor_output = full_response
|
224 |
else:
|
225 |
+
editor_output = self.current["cot"] + (
|
226 |
+
"</think>" if think_complete else ""
|
227 |
+
)
|
228 |
yield editor_output, gr.update(
|
229 |
label=editor_label
|
230 |
), self.flatten_output()
|
|
|
232 |
interval = 1.0 / self.throughput
|
233 |
start_time = time.time()
|
234 |
while (
|
235 |
+
(time.time() - start_time) < interval
|
236 |
+
and dynamic_state.should_stream
|
237 |
+
and dynamic_state.in_cot
|
238 |
+
):
|
239 |
time.sleep(0.005)
|
240 |
|
241 |
except Exception as e:
|
242 |
if str(e) == "list index out of range":
|
243 |
+
dynamic_state.stream_completed = True
|
244 |
else:
|
245 |
if str(e) == "The read operation timed out":
|
246 |
error_msg = lang_data["api_interrupted"]
|
|
|
251 |
self.is_error = True
|
252 |
dynamic_state.label_passthrough = True
|
253 |
|
|
|
254 |
finally:
|
255 |
dynamic_state.should_stream = False
|
256 |
if "response_stream" in locals():
|
|
|
262 |
)
|
263 |
editor_label = f"{lang_data['editor_label']} - {final_status}"
|
264 |
if not self.is_error:
|
265 |
+
yield editor_output, gr.update(
|
266 |
+
label=editor_label
|
267 |
+
), self.flatten_output()
|
268 |
else:
|
269 |
+
yield editor_output, gr.update(
|
270 |
+
label=editor_label_error
|
271 |
+
), self.flatten_output() + [
|
272 |
+
{
|
273 |
+
"role": "assistant",
|
274 |
+
"content": error_msg,
|
275 |
+
"metadata": {"title": f"❌Error"},
|
276 |
+
}
|
277 |
+
]
|
278 |
+
self.is_error = False
|
279 |
|
280 |
|
281 |
def update_interface_language(selected_lang, convo_state, dynamic_state):
|
|
|
324 |
theme = gr.themes.Base(font="system-ui", primary_hue="stone")
|
325 |
|
326 |
with gr.Blocks(theme=theme, css_paths="styles.css") as demo:
|
327 |
+
DEFAULT_PERSISTENT = {"prompt_input": "", "thought_editor": ""}
|
328 |
convo_state = gr.State(ConvoState)
|
329 |
dynamic_state = gr.State(DynamicState)
|
330 |
persistent_state = gr.BrowserState(DEFAULT_PERSISTENT)
|
331 |
|
332 |
bot_default = LANGUAGE_CONFIG["en"]["bot_default"] + [
|
333 |
+
{
|
334 |
+
"role": "assistant",
|
335 |
+
"content": f"Running `{os.getenv('API_MODEL')}` @ {os.getenv('API_URL')} \n Performance subjects to API provider situation",
|
336 |
+
"metadata": {"title": f"API INFO"},
|
337 |
+
}
|
338 |
+
]
|
339 |
|
340 |
with gr.Row(variant=""):
|
341 |
title_md = gr.Markdown(
|
|
|
350 |
container=False,
|
351 |
)
|
352 |
|
|
|
353 |
with gr.Row(equal_height=True):
|
354 |
with gr.Column(scale=1, min_width=400):
|
355 |
prompt_input = gr.Textbox(
|
|
|
401 |
label=LANGUAGE_CONFIG["en"]["throughput_label"],
|
402 |
info=LANGUAGE_CONFIG["en"]["throughput_info"],
|
403 |
)
|
404 |
+
result_editing_toggle = gr.Checkbox(
|
405 |
+
label=LANGUAGE_CONFIG["en"]["result_editing_toggle"],
|
406 |
+
interactive=True,
|
407 |
+
scale=0,
|
408 |
+
container=False,
|
409 |
+
)
|
410 |
|
411 |
intro_md = gr.Markdown(LANGUAGE_CONFIG["en"]["introduction"], visible=False)
|
412 |
+
|
413 |
@demo.load(inputs=[persistent_state], outputs=[prompt_input, thought_editor])
|
414 |
def recover_persistent_state(persistant_state):
|
415 |
if persistant_state["prompt_input"] or persistant_state["thought_editor"]:
|
|
|
417 |
else:
|
418 |
return gr.update(), gr.update()
|
419 |
|
|
|
420 |
# 交互逻辑
|
421 |
stateful_ui = (control_button, thought_editor, next_turn_btn)
|
422 |
|
|
|
438 |
for response in convo_state.generate_ai_response(
|
439 |
prompt, content, dynamic_state
|
440 |
):
|
441 |
+
yield response + (
|
442 |
+
{
|
443 |
+
"prompt_input": convo_state.current["user"],
|
444 |
+
"thought_editor": convo_state.current["cot"],
|
445 |
+
},
|
446 |
+
)
|
447 |
|
448 |
gr.on(
|
449 |
[control_button.click, prompt_input.submit, thought_editor.submit],
|
|
|
470 |
[dynamic_state],
|
471 |
stateful_ui + (thought_editor, prompt_input, chatbot, persistent_state),
|
472 |
concurrency_limit=None,
|
473 |
+
show_progress=False,
|
474 |
)
|
475 |
|
476 |
def toggle_editor_result(convo_state, allow):
|
477 |
setattr(convo_state, "result_editing_toggle", allow)
|
478 |
if allow:
|
|
|
479 |
return gr.update(value=convo_state.current["raw"])
|
480 |
else:
|
|
|
481 |
return gr.update(value=convo_state.current["cot"])
|
482 |
|
|
|
|
|
483 |
result_editing_toggle.change(
|
484 |
toggle_editor_result,
|
485 |
inputs=[convo_state, result_editing_toggle],
|
486 |
+
outputs=[thought_editor],
|
487 |
)
|
488 |
|
489 |
lang_selector.change(
|
|
|
500 |
next_turn_btn,
|
501 |
intro_md,
|
502 |
chatbot,
|
503 |
+
result_editing_toggle,
|
504 |
],
|
505 |
concurrency_limit=None,
|
506 |
)
|