Spaces:
Paused
Paused
Enhancement
Browse files
app.css
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
|
|
|
|
|
| 1 |
.gradio-container, .main {
|
| 2 |
padding: 0 !important;
|
| 3 |
--layout-gap: 0 !important;
|
| 4 |
}
|
| 5 |
|
| 6 |
-
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');
|
| 7 |
-
|
| 8 |
html {
|
| 9 |
scroll-behavior: smooth;
|
| 10 |
}
|
|
@@ -31,6 +31,7 @@ html {
|
|
| 31 |
|
| 32 |
.sidebar {
|
| 33 |
border-right: 1px solid var(--border-color-primary);
|
|
|
|
| 34 |
}
|
| 35 |
|
| 36 |
.sidebar-parent:has(.sidebar.open:not(.right)) {
|
|
@@ -38,9 +39,20 @@ html {
|
|
| 38 |
}
|
| 39 |
|
| 40 |
.sidebar-content {
|
|
|
|
| 41 |
padding: 50px 0 0 0 !important;
|
| 42 |
-
background:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
background-size: 180px 52px;
|
|
|
|
|
|
|
| 44 |
}
|
| 45 |
|
| 46 |
.toggle-button {
|
|
@@ -104,7 +116,7 @@ html {
|
|
| 104 |
text-overflow: ellipsis;
|
| 105 |
white-space: nowrap;
|
| 106 |
background: transparent;
|
| 107 |
-
color: var(--button-
|
| 108 |
border-bottom: 1px solid var(--border-color-primary);
|
| 109 |
}
|
| 110 |
|
|
@@ -246,7 +258,6 @@ label span {
|
|
| 246 |
.landing-logo svg {
|
| 247 |
height: 60px;
|
| 248 |
width: auto;
|
| 249 |
-
filter: drop-shadow(0 0 20px rgba(241, 236, 236, 0.1));
|
| 250 |
}
|
| 251 |
|
| 252 |
/* Hide landing page when chat has messages */
|
|
@@ -254,6 +265,16 @@ label span {
|
|
| 254 |
display: none !important;
|
| 255 |
}
|
| 256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
/* ============================================
|
| 258 |
INPUT ROW - Terminal-style Global
|
| 259 |
============================================ */
|
|
@@ -269,6 +290,14 @@ label span {
|
|
| 269 |
z-index: 20;
|
| 270 |
}
|
| 271 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 272 |
/* When landing page is hidden (chat active), keep input at bottom */
|
| 273 |
#chat-column:not(.landing-active) #input-row {
|
| 274 |
position: relative;
|
|
|
|
| 1 |
+
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');
|
| 2 |
+
|
| 3 |
.gradio-container, .main {
|
| 4 |
padding: 0 !important;
|
| 5 |
--layout-gap: 0 !important;
|
| 6 |
}
|
| 7 |
|
|
|
|
|
|
|
| 8 |
html {
|
| 9 |
scroll-behavior: smooth;
|
| 10 |
}
|
|
|
|
| 31 |
|
| 32 |
.sidebar {
|
| 33 |
border-right: 1px solid var(--border-color-primary);
|
| 34 |
+
box-shadow: none;
|
| 35 |
}
|
| 36 |
|
| 37 |
.sidebar-parent:has(.sidebar.open:not(.right)) {
|
|
|
|
| 39 |
}
|
| 40 |
|
| 41 |
.sidebar-content {
|
| 42 |
+
position: relative;
|
| 43 |
padding: 50px 0 0 0 !important;
|
| 44 |
+
background: none;
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
.sidebar-content::before {
|
| 48 |
+
content: "";
|
| 49 |
+
position: absolute;
|
| 50 |
+
inset: 0;
|
| 51 |
+
background: url("data:image/svg+xml,%3Csvg width='300' height='42' viewBox='0 0 300 42' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 6H24V12H0V6ZM0 12H6V18H0V12ZM18 12H24V18H18V12ZM30 6H54V12H30V6ZM30 12H36V18H30V12ZM30 36H36V42H30V36ZM48 12H54V18H48V12ZM60 6H84V12H60V6ZM60 12H66V18H60V12ZM78 12H84V18H78V12ZM90 6H114V12H90V6ZM90 12H96V18H90V12ZM108 12H114V18H108V12ZM120 6H150V12H120V6ZM120 12H126V18H120V12ZM132 12H138V18H132V12ZM144 12H150V18H144V12ZM156 6H162V18H156V6ZM174 6H180V18H174V6ZM174 36H180V42H174V36ZM186 6H210V12H186V6ZM192 0H198V6H192V0ZM192 12H198V18H192V12ZM216 0H222V12H216V0ZM216 12H240V18H216V12ZM246 6H270V12H246V6ZM246 12H252V18H246V12ZM264 12H270V18H264V12ZM276 6H300V12H276V6ZM276 12H282V18H276V12Z' fill='%23F1ECEC'/%3E%3Cpath d='M0 18H6V30H0V18ZM0 30H24V36H0V30ZM18 18H24V30H18V18ZM30 18H36V30H30V18ZM30 30H54V36H30V30ZM48 18H54V30H48V18ZM60 18H84V24H60V18ZM60 24H66V30H60V24ZM60 30H84V36H60V30ZM90 18H96V36H90V18ZM108 18H114V36H108V18ZM120 18H126V36H120V18ZM132 18H138V24H132V18ZM144 18H150V36H144V18ZM156 18H162V24H156V18ZM156 24H180V30H156V24ZM174 18H180V24H174V18ZM174 30H180V36H174V30ZM192 18H198V30H192V18ZM192 30H204V36H192V30ZM216 18H222V36H216V18ZM234 18H240V36H234V18ZM246 18H252V30H246V18ZM246 30H270V36H246V30ZM264 18H270V30H264V18ZM276 18H300V24H276V18ZM276 30H300V36H276V30ZM294 24H300V30H294V24Z' fill='%23B7B1B1'/%3E%3C/svg%3E")
|
| 52 |
+
no-repeat top;
|
| 53 |
background-size: 180px 52px;
|
| 54 |
+
pointer-events: none;
|
| 55 |
+
z-index: 0;
|
| 56 |
}
|
| 57 |
|
| 58 |
.toggle-button {
|
|
|
|
| 116 |
text-overflow: ellipsis;
|
| 117 |
white-space: nowrap;
|
| 118 |
background: transparent;
|
| 119 |
+
color: var(--button-secondary-text-color);
|
| 120 |
border-bottom: 1px solid var(--border-color-primary);
|
| 121 |
}
|
| 122 |
|
|
|
|
| 258 |
.landing-logo svg {
|
| 259 |
height: 60px;
|
| 260 |
width: auto;
|
|
|
|
| 261 |
}
|
| 262 |
|
| 263 |
/* Hide landing page when chat has messages */
|
|
|
|
| 265 |
display: none !important;
|
| 266 |
}
|
| 267 |
|
| 268 |
+
.landing-prompt {
|
| 269 |
+
bottom: 5%;
|
| 270 |
+
position: absolute;
|
| 271 |
+
text-align: center;
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
body:not(.dark) .landing-logo svg, body:not(.dark) .sidebar-content::before {
|
| 275 |
+
filter: invert(0.8);
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
/* ============================================
|
| 279 |
INPUT ROW - Terminal-style Global
|
| 280 |
============================================ */
|
|
|
|
| 290 |
z-index: 20;
|
| 291 |
}
|
| 292 |
|
| 293 |
+
#chat-column.landing-active #send-btn,
|
| 294 |
+
#chat-column.landing-active #stop-btn {
|
| 295 |
+
align-self: stretch;
|
| 296 |
+
min-width: 56px;
|
| 297 |
+
padding: 0 8px;
|
| 298 |
+
height: auto;
|
| 299 |
+
}
|
| 300 |
+
|
| 301 |
/* When landing page is hidden (chat active), keep input at bottom */
|
| 302 |
#chat-column:not(.landing-active) #input-row {
|
| 303 |
position: relative;
|
app.py
CHANGED
|
@@ -18,14 +18,21 @@ JS_LOAD_STATE = """(_) => {
|
|
| 18 |
const conversations = [];
|
| 19 |
const conversation_contexts = {};
|
| 20 |
|
| 21 |
-
for (const [id,
|
| 22 |
const raw = localStorage.getItem("chat_id_" + id);
|
| 23 |
if (raw) {
|
| 24 |
-
|
|
|
|
|
|
|
| 25 |
conversation_contexts[id] = JSON.parse(raw);
|
| 26 |
}
|
| 27 |
}
|
| 28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
return JSON.stringify({ conversations, conversation_contexts });
|
| 30 |
}"""
|
| 31 |
|
|
@@ -34,7 +41,7 @@ JS_SAVE_STATE = """(stateJson) => {
|
|
| 34 |
const titles = {};
|
| 35 |
|
| 36 |
for (const conv of (state.conversations || [])) {
|
| 37 |
-
titles[conv.key] = conv.label;
|
| 38 |
const ctx = (state.conversation_contexts || {})[conv.key];
|
| 39 |
if (ctx !== undefined) {
|
| 40 |
localStorage.setItem("chat_id_" + conv.key, JSON.stringify(ctx));
|
|
@@ -58,10 +65,87 @@ JS_SAVE_STATE = """(stateJson) => {
|
|
| 58 |
return stateJson;
|
| 59 |
}"""
|
| 60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
def _conv_choices(state_value):
|
|
|
|
| 63 |
return gr.update(
|
| 64 |
-
choices=[(c["label"], c["key"]) for c in
|
| 65 |
value=state_value.get("conversation_id") or None,
|
| 66 |
)
|
| 67 |
|
|
@@ -80,7 +164,7 @@ class GradioEvents:
|
|
| 80 |
conv_id = str(uuid.uuid4())
|
| 81 |
state_value["conversation_id"] = conv_id
|
| 82 |
state_value["conversations"].append(
|
| 83 |
-
{"label": message[:30], "key": conv_id})
|
| 84 |
state_value["conversation_contexts"][conv_id] = {
|
| 85 |
"history": []
|
| 86 |
}
|
|
@@ -88,6 +172,11 @@ class GradioEvents:
|
|
| 88 |
conv_id = state_value["conversation_id"]
|
| 89 |
state_value["conversation_contexts"].setdefault(
|
| 90 |
conv_id, {"history": []})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
|
| 92 |
ctx = state_value["conversation_contexts"][conv_id]
|
| 93 |
|
|
@@ -269,8 +358,6 @@ class GradioEvents:
|
|
| 269 |
"conversation_contexts": state_value.get("conversation_contexts", {}),
|
| 270 |
})
|
| 271 |
|
| 272 |
-
css = open("./app.css", "r").read()
|
| 273 |
-
|
| 274 |
with gr.Blocks(fill_width=True, title="Demo Chat") as demo:
|
| 275 |
state = gr.State({
|
| 276 |
"conversation_contexts": {},
|
|
@@ -313,6 +400,9 @@ with gr.Blocks(fill_width=True, title="Demo Chat") as demo:
|
|
| 313 |
</svg>
|
| 314 |
</div>
|
| 315 |
</div>
|
|
|
|
|
|
|
|
|
|
| 316 |
</div>
|
| 317 |
""",
|
| 318 |
elem_id="landing-page-container",
|
|
@@ -396,6 +486,11 @@ with gr.Blocks(fill_width=True, title="Demo Chat") as demo:
|
|
| 396 |
)
|
| 397 |
|
| 398 |
demo.load(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 399 |
fn=lambda x: x,
|
| 400 |
inputs=[js_load_output],
|
| 401 |
outputs=[js_load_output],
|
|
@@ -404,89 +499,9 @@ with gr.Blocks(fill_width=True, title="Demo Chat") as demo:
|
|
| 404 |
fn=GradioEvents.load_from_js,
|
| 405 |
inputs=[js_load_output, state],
|
| 406 |
outputs=[conv_choice, state],
|
| 407 |
-
).then(
|
| 408 |
-
fn=None,
|
| 409 |
-
inputs=None,
|
| 410 |
-
outputs=None,
|
| 411 |
-
js="""
|
| 412 |
-
() => {
|
| 413 |
-
// Landing page toggle logic
|
| 414 |
-
const landingPage = document.getElementById('landing-page-container');
|
| 415 |
-
const chatbot = document.getElementById('chatbot');
|
| 416 |
-
const msgInput = document.querySelector('#input-row textarea, #input-row input[type="text"]');
|
| 417 |
-
|
| 418 |
-
if (!landingPage || !chatbot) return;
|
| 419 |
-
|
| 420 |
-
function toggleLanding() {
|
| 421 |
-
// Check if chatbot has any messages
|
| 422 |
-
const messages = chatbot.querySelectorAll('[data-testid="bot"], [data-testid="user"], [class*="message"]');
|
| 423 |
-
const hasMessages = messages.length > 0;
|
| 424 |
-
|
| 425 |
-
// Also check for empty state indicators
|
| 426 |
-
const emptyState = chatbot.querySelector('.empty-state, .placeholder, [class*="empty"]');
|
| 427 |
-
const chatColumn = document.getElementById('chat-column');
|
| 428 |
-
|
| 429 |
-
if (hasMessages && !emptyState) {
|
| 430 |
-
landingPage.classList.add('hidden');
|
| 431 |
-
if (chatColumn) chatColumn.classList.remove('landing-active');
|
| 432 |
-
} else {
|
| 433 |
-
landingPage.classList.remove('hidden');
|
| 434 |
-
if (chatColumn) chatColumn.classList.add('landing-active');
|
| 435 |
-
}
|
| 436 |
-
}
|
| 437 |
-
|
| 438 |
-
// Initial check
|
| 439 |
-
toggleLanding();
|
| 440 |
-
|
| 441 |
-
// Set up mutation observer to watch for chat changes
|
| 442 |
-
const observer = new MutationObserver((mutations) => {
|
| 443 |
-
let shouldToggle = false;
|
| 444 |
-
for (const mutation of mutations) {
|
| 445 |
-
if (mutation.type === 'childList' || mutation.type === 'subtree') {
|
| 446 |
-
shouldToggle = true;
|
| 447 |
-
break;
|
| 448 |
-
}
|
| 449 |
-
}
|
| 450 |
-
if (shouldToggle) {
|
| 451 |
-
// Debounce the toggle check
|
| 452 |
-
clearTimeout(window._landingToggleTimeout);
|
| 453 |
-
window._landingToggleTimeout = setTimeout(toggleLanding, 100);
|
| 454 |
-
}
|
| 455 |
-
});
|
| 456 |
-
|
| 457 |
-
observer.observe(chatbot, {
|
| 458 |
-
childList: true,
|
| 459 |
-
subtree: true,
|
| 460 |
-
attributes: true,
|
| 461 |
-
attributeFilter: ['class']
|
| 462 |
-
});
|
| 463 |
-
|
| 464 |
-
// Also watch for the input area to handle new chat creation
|
| 465 |
-
const inputRow = document.getElementById('input-row');
|
| 466 |
-
if (inputRow) {
|
| 467 |
-
observer.observe(inputRow, {
|
| 468 |
-
childList: true,
|
| 469 |
-
subtree: true
|
| 470 |
-
});
|
| 471 |
-
}
|
| 472 |
-
|
| 473 |
-
// Click on landing prompt to focus input
|
| 474 |
-
const landingPrompt = document.querySelector('.landing-prompt');
|
| 475 |
-
if (landingPrompt && msgInput) {
|
| 476 |
-
landingPrompt.addEventListener('click', () => {
|
| 477 |
-
msgInput.focus();
|
| 478 |
-
msgInput.click();
|
| 479 |
-
});
|
| 480 |
-
}
|
| 481 |
-
|
| 482 |
-
// Store reference for cleanup
|
| 483 |
-
window._landingPageObserver = observer;
|
| 484 |
-
window._landingPage = landingPage;
|
| 485 |
-
}
|
| 486 |
-
""",
|
| 487 |
)
|
| 488 |
|
| 489 |
theme = gr.themes.Base(radius_size="none")
|
| 490 |
|
| 491 |
if __name__ == "__main__":
|
| 492 |
-
demo.queue(default_concurrency_limit=100, max_size=100).launch(ssr_mode=False, max_threads=100,
|
|
|
|
| 18 |
const conversations = [];
|
| 19 |
const conversation_contexts = {};
|
| 20 |
|
| 21 |
+
for (const [id, data] of Object.entries(titles)) {
|
| 22 |
const raw = localStorage.getItem("chat_id_" + id);
|
| 23 |
if (raw) {
|
| 24 |
+
const label = typeof data === 'string' ? data : data.label;
|
| 25 |
+
const last_updated = typeof data === 'string' ? 0 : (data.last_updated || 0);
|
| 26 |
+
conversations.push({ key: id, label: label, last_updated: last_updated });
|
| 27 |
conversation_contexts[id] = JSON.parse(raw);
|
| 28 |
}
|
| 29 |
}
|
| 30 |
|
| 31 |
+
// Sort newest first
|
| 32 |
+
conversations.sort((a, b) => (b.last_updated || 0) - (a.last_updated || 0));
|
| 33 |
+
|
| 34 |
+
console.log("Loaded conversations from localStorage:", conversations);
|
| 35 |
+
|
| 36 |
return JSON.stringify({ conversations, conversation_contexts });
|
| 37 |
}"""
|
| 38 |
|
|
|
|
| 41 |
const titles = {};
|
| 42 |
|
| 43 |
for (const conv of (state.conversations || [])) {
|
| 44 |
+
titles[conv.key] = { label: conv.label, last_updated: conv.last_updated || 0 };
|
| 45 |
const ctx = (state.conversation_contexts || {})[conv.key];
|
| 46 |
if (ctx !== undefined) {
|
| 47 |
localStorage.setItem("chat_id_" + conv.key, JSON.stringify(ctx));
|
|
|
|
| 65 |
return stateJson;
|
| 66 |
}"""
|
| 67 |
|
| 68 |
+
LANDING_PAGE_SCRIPT = """() => {
|
| 69 |
+
// Landing page toggle logic
|
| 70 |
+
const landingPage = document.getElementById('landing-page-container');
|
| 71 |
+
const chatbot = document.getElementById('chatbot');
|
| 72 |
+
const msgInput = document.querySelector('#input-row textarea, #input-row input[type="text"]');
|
| 73 |
+
|
| 74 |
+
if (!landingPage || !chatbot) return;
|
| 75 |
+
|
| 76 |
+
function toggleLanding() {
|
| 77 |
+
// Check if chatbot has any messages
|
| 78 |
+
const messages = chatbot.querySelectorAll('[data-testid="bot"], [data-testid="user"], [class*="message"]');
|
| 79 |
+
const hasMessages = messages.length > 0;
|
| 80 |
+
|
| 81 |
+
// Also check for empty state indicators
|
| 82 |
+
const emptyState = chatbot.querySelector('.empty-state, .placeholder, [class*="empty"]');
|
| 83 |
+
const chatColumn = document.getElementById('chat-column');
|
| 84 |
+
|
| 85 |
+
if (hasMessages && !emptyState) {
|
| 86 |
+
landingPage.classList.add('hidden');
|
| 87 |
+
if (chatColumn) chatColumn.classList.remove('landing-active');
|
| 88 |
+
} else {
|
| 89 |
+
landingPage.classList.remove('hidden');
|
| 90 |
+
if (chatColumn) chatColumn.classList.add('landing-active');
|
| 91 |
+
}
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
// Initial check
|
| 95 |
+
toggleLanding();
|
| 96 |
+
|
| 97 |
+
// Set up mutation observer to watch for chat changes
|
| 98 |
+
const observer = new MutationObserver((mutations) => {
|
| 99 |
+
let shouldToggle = false;
|
| 100 |
+
for (const mutation of mutations) {
|
| 101 |
+
if (mutation.type === 'childList' || mutation.type === 'subtree') {
|
| 102 |
+
shouldToggle = true;
|
| 103 |
+
break;
|
| 104 |
+
}
|
| 105 |
+
}
|
| 106 |
+
if (shouldToggle) {
|
| 107 |
+
// Debounce the toggle check
|
| 108 |
+
clearTimeout(window._landingToggleTimeout);
|
| 109 |
+
window._landingToggleTimeout = setTimeout(toggleLanding, 100);
|
| 110 |
+
}
|
| 111 |
+
});
|
| 112 |
+
|
| 113 |
+
observer.observe(chatbot, {
|
| 114 |
+
childList: true,
|
| 115 |
+
subtree: true,
|
| 116 |
+
attributes: true,
|
| 117 |
+
attributeFilter: ['class']
|
| 118 |
+
});
|
| 119 |
+
|
| 120 |
+
// Also watch for the input area to handle new chat creation
|
| 121 |
+
const inputRow = document.getElementById('input-row');
|
| 122 |
+
if (inputRow) {
|
| 123 |
+
observer.observe(inputRow, {
|
| 124 |
+
childList: true,
|
| 125 |
+
subtree: true
|
| 126 |
+
});
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
// Click on landing prompt to focus input
|
| 130 |
+
const landingPrompt = document.querySelector('.landing-prompt');
|
| 131 |
+
if (landingPrompt && msgInput) {
|
| 132 |
+
landingPrompt.addEventListener('click', () => {
|
| 133 |
+
msgInput.focus();
|
| 134 |
+
msgInput.click();
|
| 135 |
+
});
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
// Store reference for cleanup
|
| 139 |
+
window._landingPageObserver = observer;
|
| 140 |
+
window._landingPage = landingPage;
|
| 141 |
+
}
|
| 142 |
+
"""
|
| 143 |
+
|
| 144 |
|
| 145 |
def _conv_choices(state_value):
|
| 146 |
+
convs = sorted(state_value["conversations"], key=lambda c: c.get("last_updated", 0), reverse=True)
|
| 147 |
return gr.update(
|
| 148 |
+
choices=[(c["label"], c["key"]) for c in convs],
|
| 149 |
value=state_value.get("conversation_id") or None,
|
| 150 |
)
|
| 151 |
|
|
|
|
| 164 |
conv_id = str(uuid.uuid4())
|
| 165 |
state_value["conversation_id"] = conv_id
|
| 166 |
state_value["conversations"].append(
|
| 167 |
+
{"label": message[:30], "key": conv_id, "last_updated": int(time.time() * 1000)})
|
| 168 |
state_value["conversation_contexts"][conv_id] = {
|
| 169 |
"history": []
|
| 170 |
}
|
|
|
|
| 172 |
conv_id = state_value["conversation_id"]
|
| 173 |
state_value["conversation_contexts"].setdefault(
|
| 174 |
conv_id, {"history": []})
|
| 175 |
+
# Update last_updated for existing conversation
|
| 176 |
+
for c in state_value["conversations"]:
|
| 177 |
+
if c["key"] == conv_id:
|
| 178 |
+
c["last_updated"] = int(time.time() * 1000)
|
| 179 |
+
break
|
| 180 |
|
| 181 |
ctx = state_value["conversation_contexts"][conv_id]
|
| 182 |
|
|
|
|
| 358 |
"conversation_contexts": state_value.get("conversation_contexts", {}),
|
| 359 |
})
|
| 360 |
|
|
|
|
|
|
|
| 361 |
with gr.Blocks(fill_width=True, title="Demo Chat") as demo:
|
| 362 |
state = gr.State({
|
| 363 |
"conversation_contexts": {},
|
|
|
|
| 400 |
</svg>
|
| 401 |
</div>
|
| 402 |
</div>
|
| 403 |
+
<div class="landing-prompt">
|
| 404 |
+
<p>Made with ❤️ by KingNish and Himanshu</p>
|
| 405 |
+
</div>
|
| 406 |
</div>
|
| 407 |
""",
|
| 408 |
elem_id="landing-page-container",
|
|
|
|
| 486 |
)
|
| 487 |
|
| 488 |
demo.load(
|
| 489 |
+
fn=lambda: None,
|
| 490 |
+
inputs=None,
|
| 491 |
+
outputs=None,
|
| 492 |
+
js=LANDING_PAGE_SCRIPT,
|
| 493 |
+
).then(
|
| 494 |
fn=lambda x: x,
|
| 495 |
inputs=[js_load_output],
|
| 496 |
outputs=[js_load_output],
|
|
|
|
| 499 |
fn=GradioEvents.load_from_js,
|
| 500 |
inputs=[js_load_output, state],
|
| 501 |
outputs=[conv_choice, state],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 502 |
)
|
| 503 |
|
| 504 |
theme = gr.themes.Base(radius_size="none")
|
| 505 |
|
| 506 |
if __name__ == "__main__":
|
| 507 |
+
demo.queue(default_concurrency_limit=100, max_size=100).launch(ssr_mode=False, max_threads=100, css_paths="app.css", theme=theme)
|