Spaces:
Sleeping
Sleeping
File size: 3,779 Bytes
ba52610 b1d78ef ba52610 b1d78ef ba52610 b1d78ef ba52610 b1d78ef ba52610 b1d78ef ba52610 b1d78ef ba52610 a741ada ba52610 b1d78ef a741ada b1d78ef a741ada b1d78ef a741ada b1d78ef a741ada b1d78ef ba52610 a741ada ba52610 b1d78ef 284ee47 ba52610 a741ada | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | import gradio as gr
import time
# Inspired by: https://www.gradio.app/guides/agents-and-tool-usage
# Custom timer solution described by Claude Sonnet 4.6:
# https://claude.ai/share/d7adc776-05f2-4c2b-a93a-9cf6089dd7be
def interact_with_agent(prompt, messages=[]):
"""Simulate generation of two assistant messages after delays"""
time.sleep(4)
messages.append(
gr.ChatMessage(
role="assistant", content="First message — gr.Chatbot() timer stops here"
)
)
yield messages
time.sleep(4)
messages.append(
gr.ChatMessage(role="assistant", content="Second message — Custom timer stops here")
)
yield messages
def str_to_message(content, role="user"):
return [gr.ChatMessage(role=role, content=content)]
timer_html = """
<div id="agent-timer" style="font-family: monospace;"></div>
"""
timer_js = """
let startTime = null;
let interval = null;
const el = element.querySelector('#agent-timer');
el.addEventListener('agent-timer:start', () => {
startTime = Date.now();
el.textContent = '⏱ 0.0s';
interval = setInterval(() => {
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
el.textContent = '⏱ ' + elapsed + 's';
}, 100);
});
el.addEventListener('agent-timer:stop', () => {
if (interval) {
clearInterval(interval);
interval = null;
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
el.textContent = '✓ ' + elapsed + 's';
}
});
"""
chatbot_overlay_css = """
#timer-display {
position: absolute;
bottom: 0px;
}
"""
with gr.Blocks() as demo:
with gr.Row():
with gr.Column():
gr.Markdown(
"""
## Gradio chatbot timer that stops at the last (not first) yielded agent message
**Submit any user message to launch a chatbot simulation that responds with two assistant messages with a 4-second delay before each one.**
- The built-in `gr.Chatbot` timer (*lower right*) stops after the first message.
- The custom timer (*lower left*) keeps going until the last message is yielded.
- The custom timer is implemented in JavaScript and CSS and depends on `gr.HTML` capabilities in Gradio 6.
"""
)
input = gr.Textbox(
"Start the timers!",
label="User message",
autofocus=True,
submit_btn=True,
)
gr.Markdown(
"""
### App history
- 2025-07-25: Create demo to support [Gradio issue #11637](https://github.com/gradio-app/gradio/issues/11637) (Gradio 5.38.2)
- 2026-05-30: Add custom timer using [gr.HTML](https://huggingface.co/blog/gradio-html-one-shot-apps) (Gradio 6.15.2)
"""
)
with gr.Column():
chatbot = gr.Chatbot()
gr.HTML(value=timer_html, js_on_load=timer_js, elem_id="timer-display")
input.submit(
# Update chatbot UI with user message immediately
str_to_message,
input,
chatbot,
).then(
# Start custom timer
lambda: None, None, None,
js="() => document.getElementById('agent-timer')"
"?.dispatchEvent(new CustomEvent('agent-timer:start'))",
).then(
# Update chatbot UI with assistant messages
interact_with_agent,
[input, chatbot],
chatbot,
).then(
# Stop custom timer
lambda: None, None, None,
js="() => document.getElementById('agent-timer')"
"?.dispatchEvent(new CustomEvent('agent-timer:stop'))",
)
demo.launch(css=chatbot_overlay_css)
|