Update app.py
Browse files
app.py
CHANGED
|
@@ -73,7 +73,6 @@ def create_store_with_samples(client_state, samples_dir: str, store_display_name
|
|
| 73 |
Generator. Creates a NEW store and imports whatever classics exist in samples_dir.
|
| 74 |
Yields: store_state(str), store_status(md), progress_html(html), create_button(update)
|
| 75 |
"""
|
| 76 |
-
# Guard. require key
|
| 77 |
if client_state is None:
|
| 78 |
msg = "❌ Set your API key first in the section above."
|
| 79 |
yield "", msg, _progress_html(0, "Waiting for API key"), gr.update(interactive=True)
|
|
@@ -355,6 +354,7 @@ def render_samples_panel(samples_dir: str):
|
|
| 355 |
# UI (palette + theme)
|
| 356 |
# ──────────────────────────────────────────────────────────────────────────────
|
| 357 |
custom_css = """
|
|
|
|
| 358 |
:root {
|
| 359 |
--primary: #6C5CE7; --secondary: #00D2FF; --accent: #FF8A65;
|
| 360 |
--surface: #FFFFFF; --bg: #F6F7FB; --ink: #1B1E2B; --muted: #9AA0B7;
|
|
@@ -365,33 +365,103 @@ html[data-theme="dark"] {
|
|
| 365 |
--surface: #151728; --bg: #0E0F16; --ink: #E9ECFF; --muted: #AAB0D6;
|
| 366 |
--success: #23D497; --danger: #FF6B6B; --code: #0B0F1C;
|
| 367 |
}
|
|
|
|
|
|
|
| 368 |
body { background: var(--bg) !important; }
|
| 369 |
.gradio-container { max-width: 1120px !important; margin: auto !important; }
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 373 |
border: 1px solid color-mix(in oklab, var(--ink) 12%, transparent);
|
| 374 |
-
box-shadow: 0 12px 36px rgba(0,0,0,.
|
|
|
|
|
|
|
| 375 |
.hero h1 { color: var(--surface); font-size: 30px; margin: 0 0 8px; }
|
| 376 |
-
.hero p
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 380 |
input, textarea, select, .gr-textbox, .gr-number, .gr-dropdown, .gr-file, .gr-code {
|
| 381 |
-
background: color-mix(in oklab, var(--surface)
|
| 382 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 383 |
button, .gr-button { border-radius: 10px !important; border: 1px solid color-mix(in oklab, var(--ink) 10%, transparent) !important; }
|
| 384 |
-
button.primary
|
| 385 |
-
button.secondary { background: color-mix(in oklab, var(--surface)
|
| 386 |
-
|
| 387 |
-
|
| 388 |
-
.
|
| 389 |
-
|
| 390 |
-
|
| 391 |
-
border:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 392 |
.section-hd { font-weight: 700; margin-bottom: 8px; color: var(--ink); }
|
| 393 |
-
.gallery { display:
|
| 394 |
@media (max-width: 980px) { .gallery { grid-template-columns: 1fr; } }
|
|
|
|
| 395 |
.file-grid { display:grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 10px; }
|
| 396 |
.file-card { background: color-mix(in oklab, var(--surface) 96%, transparent); border:1px solid color-mix(in oklab, var(--ink) 10%, transparent);
|
| 397 |
border-radius: 12px; padding: 10px 12px; box-shadow:0 6px 16px rgba(0,0,0,.05); }
|
|
@@ -400,18 +470,28 @@ button.secondary { background: color-mix(in oklab, var(--surface) 85%, transpare
|
|
| 400 |
.file-path { color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; word-break: break-all; margin-top: 4px; }
|
| 401 |
.pill { padding: 2px 8px; border-radius: 999px; background: color-mix(in oklab, var(--secondary) 14%, transparent); color: var(--ink);
|
| 402 |
border:1px solid color-mix(in oklab, var(--secondary) 20%, transparent); }
|
|
|
|
| 403 |
.tiles-wrap { display:grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap:12px; }
|
| 404 |
.tile { background: color-mix(in oklab, var(--surface) 96%, transparent); border:1px solid color-mix(in oklab, var(--ink) 10%, transparent);
|
| 405 |
border-radius:12px; padding:12px; box-shadow:0 6px 16px rgba(0,0,0,.06); display:flex; flex-direction:column; gap:6px; }
|
| 406 |
-
.tile-hd { font-weight:700; color:var(--ink); }
|
|
|
|
| 407 |
.tile-path { color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; word-break: break-all; }
|
| 408 |
.badge-ok, .badge-miss { font-size: 11.5px; padding: 3px 8px; border-radius: 999px; color: white; width: fit-content; }
|
| 409 |
-
.badge-ok { background: var(--success); }
|
|
|
|
|
|
|
|
|
|
| 410 |
.gr-code { background: var(--code) !important; color: #d9e1ff !important; border: 1px solid #1f2a44 !important; }
|
| 411 |
-
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 415 |
.progress-head { font-weight: 600; color: var(--ink); margin-bottom: 6px; }
|
| 416 |
.pbar { height: 12px; width: 100%; background: #e8ebff; border-radius: 999px; overflow: hidden; }
|
| 417 |
html[data-theme="dark"] .pbar { background: #2a2f57; }
|
|
@@ -423,7 +503,11 @@ html[data-theme="dark"] .pbar { background: #2a2f57; }
|
|
| 423 |
# Pre-render samples gallery
|
| 424 |
_initial_gallery_html = render_samples_panel(SAMPLES_DIR_DEFAULT)
|
| 425 |
|
| 426 |
-
with gr.Blocks(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 427 |
gr.HTML("""
|
| 428 |
<div class="hero">
|
| 429 |
<h1>Gemini File Search · RAG Demo</h1>
|
|
@@ -435,6 +519,7 @@ with gr.Blocks(title="Gemini File Search – Gradio Demo (Spaces)", css=custom_c
|
|
| 435 |
store_state = gr.State(value="")
|
| 436 |
chat_state = gr.State(value=[])
|
| 437 |
|
|
|
|
| 438 |
with gr.Accordion("API key", open=True):
|
| 439 |
gr.Markdown("_This Space **requires** your Gemini API key for each session. keys are **not** stored server-side._")
|
| 440 |
with gr.Row():
|
|
@@ -442,6 +527,7 @@ with gr.Blocks(title="Gemini File Search – Gradio Demo (Spaces)", css=custom_c
|
|
| 442 |
api_btn = gr.Button("Set key", elem_classes=["primary"])
|
| 443 |
api_status = gr.Markdown()
|
| 444 |
|
|
|
|
| 445 |
with gr.Group():
|
| 446 |
gr.Markdown("### Build a store from your `samples/` folder")
|
| 447 |
with gr.Row():
|
|
@@ -453,6 +539,7 @@ with gr.Blocks(title="Gemini File Search – Gradio Demo (Spaces)", css=custom_c
|
|
| 453 |
store_status = gr.Markdown()
|
| 454 |
store_name_out = gr.Textbox(label="Active store name", interactive=False)
|
| 455 |
|
|
|
|
| 456 |
with gr.Accordion("Use existing store (paste resource name)", open=False):
|
| 457 |
gr.Markdown("_Paste a resource like `fileSearchStores/...` to switch the active store._")
|
| 458 |
with gr.Row():
|
|
@@ -460,6 +547,7 @@ with gr.Blocks(title="Gemini File Search – Gradio Demo (Spaces)", css=custom_c
|
|
| 460 |
use_existing_btn = gr.Button("Use store", elem_classes=["secondary"], scale=1)
|
| 461 |
existing_status = gr.Markdown()
|
| 462 |
|
|
|
|
| 463 |
with gr.Accordion("Upload & index your own files", open=False):
|
| 464 |
gr.Markdown("_Create or select a store. then upload any local file here._")
|
| 465 |
with gr.Row():
|
|
@@ -477,11 +565,23 @@ with gr.Blocks(title="Gemini File Search – Gradio Demo (Spaces)", css=custom_c
|
|
| 477 |
upload_status = gr.Markdown()
|
| 478 |
|
| 479 |
gr.Markdown("---")
|
|
|
|
| 480 |
gr.Markdown("### Ask grounded questions")
|
| 481 |
with gr.Row():
|
| 482 |
model = gr.Dropdown(label="Model", value=DEFAULT_MODEL, choices=["gemini-2.5-flash", "gemini-2.5-pro"], scale=1)
|
| 483 |
metadata_filter = gr.Textbox(label="Optional metadata_filter (AIP-160)", placeholder='author="Jane Austen" AND year=1813', scale=2)
|
| 484 |
chatbot = gr.Chatbot(label="Grounded Q&A", height=520, type="messages")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 485 |
with gr.Row():
|
| 486 |
question_tb = gr.Textbox(placeholder="Type your question…", show_label=False, scale=5)
|
| 487 |
ask_btn = gr.Button("Ask", elem_classes=["primary"], scale=1)
|
|
@@ -490,7 +590,16 @@ with gr.Blocks(title="Gemini File Search – Gradio Demo (Spaces)", css=custom_c
|
|
| 490 |
grounding_md = gr.Code(label="grounding_metadata")
|
| 491 |
note = gr.Markdown()
|
| 492 |
|
| 493 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 494 |
api_btn.click(ui_set_api_key, [api_tb], [client_state, api_status], show_progress=True)
|
| 495 |
|
| 496 |
samples_dir_tb.change(render_samples_panel, [samples_dir_tb], [samples_preview], show_progress=False)
|
|
@@ -509,6 +618,13 @@ with gr.Blocks(title="Gemini File Search – Gradio Demo (Spaces)", css=custom_c
|
|
| 509 |
show_progress=True,
|
| 510 |
).then(lambda s: s, [store_state], [store_name_out], show_progress=False)
|
| 511 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 512 |
upload_btn.click(
|
| 513 |
upload_and_index,
|
| 514 |
[client_state, store_state, file_uploader, disp_file_name, max_tokens, overlap_tokens],
|
|
@@ -530,6 +646,17 @@ with gr.Blocks(title="Gemini File Search – Gradio Demo (Spaces)", css=custom_c
|
|
| 530 |
clear_btn.click(lambda: ([], "", ""), None, [chatbot, grounding_md, note], show_progress=False)\
|
| 531 |
.then(lambda: [], None, [chat_state], show_progress=False)
|
| 532 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 533 |
if __name__ == "__main__":
|
| 534 |
-
# On Spaces. the default launch is fine. queue enables progress bars
|
| 535 |
demo.queue().launch()
|
|
|
|
| 73 |
Generator. Creates a NEW store and imports whatever classics exist in samples_dir.
|
| 74 |
Yields: store_state(str), store_status(md), progress_html(html), create_button(update)
|
| 75 |
"""
|
|
|
|
| 76 |
if client_state is None:
|
| 77 |
msg = "❌ Set your API key first in the section above."
|
| 78 |
yield "", msg, _progress_html(0, "Waiting for API key"), gr.update(interactive=True)
|
|
|
|
| 354 |
# UI (palette + theme)
|
| 355 |
# ──────────────────────────────────────────────────────────────────────────────
|
| 356 |
custom_css = """
|
| 357 |
+
/* ---------- Palette ---------- */
|
| 358 |
:root {
|
| 359 |
--primary: #6C5CE7; --secondary: #00D2FF; --accent: #FF8A65;
|
| 360 |
--surface: #FFFFFF; --bg: #F6F7FB; --ink: #1B1E2B; --muted: #9AA0B7;
|
|
|
|
| 365 |
--surface: #151728; --bg: #0E0F16; --ink: #E9ECFF; --muted: #AAB0D6;
|
| 366 |
--success: #23D497; --danger: #FF6B6B; --code: #0B0F1C;
|
| 367 |
}
|
| 368 |
+
|
| 369 |
+
/* ---------- Layout ---------- */
|
| 370 |
body { background: var(--bg) !important; }
|
| 371 |
.gradio-container { max-width: 1120px !important; margin: auto !important; }
|
| 372 |
+
|
| 373 |
+
/* ---------- Hero ---------- */
|
| 374 |
+
.hero {
|
| 375 |
+
border-radius: 18px;
|
| 376 |
+
padding: 22px 26px;
|
| 377 |
+
background: linear-gradient(135deg,
|
| 378 |
+
color-mix(in oklab, var(--primary) 28%, transparent),
|
| 379 |
+
color-mix(in oklab, var(--secondary) 24%, transparent));
|
| 380 |
border: 1px solid color-mix(in oklab, var(--ink) 12%, transparent);
|
| 381 |
+
box-shadow: 0 12px 36px rgba(0,0,0,.14);
|
| 382 |
+
margin: 8px 0 16px 0;
|
| 383 |
+
}
|
| 384 |
.hero h1 { color: var(--surface); font-size: 30px; margin: 0 0 8px; }
|
| 385 |
+
.hero p { color: color-mix(in oklab, var(--surface) 78%, transparent); margin: 0; }
|
| 386 |
+
|
| 387 |
+
/* ---------- Cards & panels ---------- */
|
| 388 |
+
.gr-box, .gr-panel {
|
| 389 |
+
background: var(--surface) !important;
|
| 390 |
+
border: 1px solid color-mix(in oklab, var(--ink) 10%, transparent) !important;
|
| 391 |
+
border-radius: 14px !important;
|
| 392 |
+
box-shadow: 0 6px 16px rgba(0,0,0,.06);
|
| 393 |
+
}
|
| 394 |
+
|
| 395 |
+
/* ---------- Inputs ---------- */
|
| 396 |
input, textarea, select, .gr-textbox, .gr-number, .gr-dropdown, .gr-file, .gr-code {
|
| 397 |
+
background: color-mix(in oklab, var(--surface) 96%, transparent) !important;
|
| 398 |
+
color: var(--ink) !important;
|
| 399 |
+
border: 1px solid color-mix(in oklab, var(--ink) 12%, transparent) !important;
|
| 400 |
+
border-radius: 10px !important;
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
/* ---------- Buttons ---------- */
|
| 404 |
button, .gr-button { border-radius: 10px !important; border: 1px solid color-mix(in oklab, var(--ink) 10%, transparent) !important; }
|
| 405 |
+
button.primary { background: linear-gradient(135deg, var(--primary), var(--secondary)) !important; color: white !important; }
|
| 406 |
+
button.secondary { background: color-mix(in oklab, var(--surface) 90%, transparent) !important; color: var(--ink) !important; }
|
| 407 |
+
|
| 408 |
+
/* ---------- Accordion (Spaces uses <details>) ---------- */
|
| 409 |
+
.gradio-container details {
|
| 410 |
+
margin: 10px 0;
|
| 411 |
+
background: transparent !important;
|
| 412 |
+
border: 0 !important;
|
| 413 |
+
}
|
| 414 |
+
.gradio-container details > summary {
|
| 415 |
+
list-style: none;
|
| 416 |
+
background: color-mix(in oklab, var(--surface) 98%, transparent);
|
| 417 |
+
border: 1px solid color-mix(in oklab, var(--ink) 10%, transparent);
|
| 418 |
+
border-radius: 12px;
|
| 419 |
+
padding: 10px 14px;
|
| 420 |
+
font-weight: 600;
|
| 421 |
+
color: var(--ink);
|
| 422 |
+
cursor: pointer;
|
| 423 |
+
}
|
| 424 |
+
.gradio-container details > summary::-webkit-details-marker { display: none; }
|
| 425 |
+
.gradio-container details[open] > summary {
|
| 426 |
+
border-bottom-left-radius: 0; border-bottom-right-radius: 0;
|
| 427 |
+
}
|
| 428 |
+
.gradio-container details > div {
|
| 429 |
+
background: var(--surface);
|
| 430 |
+
border: 1px solid color-mix(in oklab, var(--ink) 10%, transparent);
|
| 431 |
+
border-top: 0;
|
| 432 |
+
border-bottom-left-radius: 12px; border-bottom-right-radius: 12px;
|
| 433 |
+
padding: 12px 14px;
|
| 434 |
+
box-shadow: 0 6px 16px rgba(0,0,0,.06);
|
| 435 |
+
}
|
| 436 |
+
|
| 437 |
+
/* ---------- Chatbot ---------- */
|
| 438 |
+
.gr-chatbot {
|
| 439 |
+
background: color-mix(in oklab, var(--surface) 96%, transparent) !important;
|
| 440 |
+
border: 1px solid color-mix(in oklab, var(--ink) 10%, transparent) !important;
|
| 441 |
+
border-radius: 14px !important;
|
| 442 |
+
}
|
| 443 |
+
.gr-chatbot .message {
|
| 444 |
+
border-radius: 14px; padding: 12px 14px; font-size: 17px; line-height: 1.5;
|
| 445 |
+
}
|
| 446 |
+
.gr-chatbot .message.user {
|
| 447 |
+
background: color-mix(in oklab, var(--secondary) 12%, transparent) !important;
|
| 448 |
+
border: 1px solid color-mix(in oklab, var(--secondary) 20%, transparent);
|
| 449 |
+
}
|
| 450 |
+
.gr-chatbot .message.bot {
|
| 451 |
+
background: color-mix(in oklab, var(--primary) 12%, transparent) !important;
|
| 452 |
+
border: 1px solid color-mix(in oklab, var(--primary) 20%, transparent);
|
| 453 |
+
}
|
| 454 |
+
|
| 455 |
+
/* ---------- Chips ---------- */
|
| 456 |
+
.chip { padding:8px 12px; border-radius:999px; background: color-mix(in oklab, var(--primary) 12%, var(--surface));
|
| 457 |
+
color: var(--ink); border:1px solid color-mix(in oklab, var(--primary) 20%, transparent); user-select:none; }
|
| 458 |
+
.chip:hover { filter:brightness(1.04); }
|
| 459 |
+
|
| 460 |
+
/* ---------- Sample gallery ---------- */
|
| 461 |
.section-hd { font-weight: 700; margin-bottom: 8px; color: var(--ink); }
|
| 462 |
+
.gallery { display:grid; grid-template-columns: 1.3fr .9fr; gap: 14px; }
|
| 463 |
@media (max-width: 980px) { .gallery { grid-template-columns: 1fr; } }
|
| 464 |
+
|
| 465 |
.file-grid { display:grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 10px; }
|
| 466 |
.file-card { background: color-mix(in oklab, var(--surface) 96%, transparent); border:1px solid color-mix(in oklab, var(--ink) 10%, transparent);
|
| 467 |
border-radius: 12px; padding: 10px 12px; box-shadow:0 6px 16px rgba(0,0,0,.05); }
|
|
|
|
| 470 |
.file-path { color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; word-break: break-all; margin-top: 4px; }
|
| 471 |
.pill { padding: 2px 8px; border-radius: 999px; background: color-mix(in oklab, var(--secondary) 14%, transparent); color: var(--ink);
|
| 472 |
border:1px solid color-mix(in oklab, var(--secondary) 20%, transparent); }
|
| 473 |
+
|
| 474 |
.tiles-wrap { display:grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap:12px; }
|
| 475 |
.tile { background: color-mix(in oklab, var(--surface) 96%, transparent); border:1px solid color-mix(in oklab, var(--ink) 10%, transparent);
|
| 476 |
border-radius:12px; padding:12px; box-shadow:0 6px 16px rgba(0,0,0,.06); display:flex; flex-direction:column; gap:6px; }
|
| 477 |
+
.tile-hd { font-weight:700; color:var(--ink); }
|
| 478 |
+
.tile-sub { color: var(--muted); font-size: 14px; }
|
| 479 |
.tile-path { color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; word-break: break-all; }
|
| 480 |
.badge-ok, .badge-miss { font-size: 11.5px; padding: 3px 8px; border-radius: 999px; color: white; width: fit-content; }
|
| 481 |
+
.badge-ok { background: var(--success); }
|
| 482 |
+
.badge-miss { background: var(--danger); }
|
| 483 |
+
|
| 484 |
+
/* ---------- Code blocks ---------- */
|
| 485 |
.gr-code { background: var(--code) !important; color: #d9e1ff !important; border: 1px solid #1f2a44 !important; }
|
| 486 |
+
|
| 487 |
+
/* ---------- Progress card ---------- */
|
| 488 |
+
.progress-card {
|
| 489 |
+
background: color-mix(in oklab, var(--surface) 96%, transparent);
|
| 490 |
+
border: 1px solid color-mix(in oklab, var(--ink) 10%, transparent);
|
| 491 |
+
border-radius: 12px;
|
| 492 |
+
padding: 10px 12px;
|
| 493 |
+
box-shadow: 0 6px 16px rgba(0,0,0,.05);
|
| 494 |
+
}
|
| 495 |
.progress-head { font-weight: 600; color: var(--ink); margin-bottom: 6px; }
|
| 496 |
.pbar { height: 12px; width: 100%; background: #e8ebff; border-radius: 999px; overflow: hidden; }
|
| 497 |
html[data-theme="dark"] .pbar { background: #2a2f57; }
|
|
|
|
| 503 |
# Pre-render samples gallery
|
| 504 |
_initial_gallery_html = render_samples_panel(SAMPLES_DIR_DEFAULT)
|
| 505 |
|
| 506 |
+
with gr.Blocks(
|
| 507 |
+
title="Gemini File Search – Gradio Demo (Spaces)",
|
| 508 |
+
css=custom_css,
|
| 509 |
+
theme=gr.themes.Soft(primary_hue="indigo", neutral_hue="slate"),
|
| 510 |
+
) as demo:
|
| 511 |
gr.HTML("""
|
| 512 |
<div class="hero">
|
| 513 |
<h1>Gemini File Search · RAG Demo</h1>
|
|
|
|
| 519 |
store_state = gr.State(value="")
|
| 520 |
chat_state = gr.State(value=[])
|
| 521 |
|
| 522 |
+
# API key
|
| 523 |
with gr.Accordion("API key", open=True):
|
| 524 |
gr.Markdown("_This Space **requires** your Gemini API key for each session. keys are **not** stored server-side._")
|
| 525 |
with gr.Row():
|
|
|
|
| 527 |
api_btn = gr.Button("Set key", elem_classes=["primary"])
|
| 528 |
api_status = gr.Markdown()
|
| 529 |
|
| 530 |
+
# Build from samples
|
| 531 |
with gr.Group():
|
| 532 |
gr.Markdown("### Build a store from your `samples/` folder")
|
| 533 |
with gr.Row():
|
|
|
|
| 539 |
store_status = gr.Markdown()
|
| 540 |
store_name_out = gr.Textbox(label="Active store name", interactive=False)
|
| 541 |
|
| 542 |
+
# Existing store
|
| 543 |
with gr.Accordion("Use existing store (paste resource name)", open=False):
|
| 544 |
gr.Markdown("_Paste a resource like `fileSearchStores/...` to switch the active store._")
|
| 545 |
with gr.Row():
|
|
|
|
| 547 |
use_existing_btn = gr.Button("Use store", elem_classes=["secondary"], scale=1)
|
| 548 |
existing_status = gr.Markdown()
|
| 549 |
|
| 550 |
+
# Upload own files
|
| 551 |
with gr.Accordion("Upload & index your own files", open=False):
|
| 552 |
gr.Markdown("_Create or select a store. then upload any local file here._")
|
| 553 |
with gr.Row():
|
|
|
|
| 565 |
upload_status = gr.Markdown()
|
| 566 |
|
| 567 |
gr.Markdown("---")
|
| 568 |
+
# Q&A
|
| 569 |
gr.Markdown("### Ask grounded questions")
|
| 570 |
with gr.Row():
|
| 571 |
model = gr.Dropdown(label="Model", value=DEFAULT_MODEL, choices=["gemini-2.5-flash", "gemini-2.5-pro"], scale=1)
|
| 572 |
metadata_filter = gr.Textbox(label="Optional metadata_filter (AIP-160)", placeholder='author="Jane Austen" AND year=1813', scale=2)
|
| 573 |
chatbot = gr.Chatbot(label="Grounded Q&A", height=520, type="messages")
|
| 574 |
+
|
| 575 |
+
# Example chips
|
| 576 |
+
gr.Markdown("Try some examples:")
|
| 577 |
+
with gr.Row():
|
| 578 |
+
chip1 = gr.Button("Who is Mr. Darcy. what role does he play", elem_classes=["chip"])
|
| 579 |
+
chip2 = gr.Button("What is the opening line of Moby-Dick", elem_classes=["chip"])
|
| 580 |
+
chip3 = gr.Button("Summarize the tea party scene in Alice", elem_classes=["chip"])
|
| 581 |
+
chip4 = gr.Button("Give 3 clues Holmes uses in a story", elem_classes=["chip"])
|
| 582 |
+
chip5 = gr.Button("What is Pemberley. why is it important", elem_classes=["chip"])
|
| 583 |
+
chip6 = gr.Button("Who is Captain Ahab. what drives him", elem_classes=["chip"])
|
| 584 |
+
|
| 585 |
with gr.Row():
|
| 586 |
question_tb = gr.Textbox(placeholder="Type your question…", show_label=False, scale=5)
|
| 587 |
ask_btn = gr.Button("Ask", elem_classes=["primary"], scale=1)
|
|
|
|
| 590 |
grounding_md = gr.Code(label="grounding_metadata")
|
| 591 |
note = gr.Markdown()
|
| 592 |
|
| 593 |
+
# Manage stores (optional tools)
|
| 594 |
+
with gr.Accordion("Manage stores", open=False):
|
| 595 |
+
list_btn = gr.Button("List my stores", elem_classes=["secondary"])
|
| 596 |
+
list_out = gr.Code()
|
| 597 |
+
with gr.Row():
|
| 598 |
+
del_name = gr.Textbox(label="Store name to delete")
|
| 599 |
+
del_btn = gr.Button("Delete store", elem_classes=["secondary"])
|
| 600 |
+
del_status = gr.Markdown()
|
| 601 |
+
|
| 602 |
+
# Wiring
|
| 603 |
api_btn.click(ui_set_api_key, [api_tb], [client_state, api_status], show_progress=True)
|
| 604 |
|
| 605 |
samples_dir_tb.change(render_samples_panel, [samples_dir_tb], [samples_preview], show_progress=False)
|
|
|
|
| 618 |
show_progress=True,
|
| 619 |
).then(lambda s: s, [store_state], [store_name_out], show_progress=False)
|
| 620 |
|
| 621 |
+
create_empty_btn.click(
|
| 622 |
+
make_empty_store,
|
| 623 |
+
[client_state, upload_store_dn],
|
| 624 |
+
[store_state, upload_status],
|
| 625 |
+
show_progress=True,
|
| 626 |
+
).then(lambda s: s, [store_state], [store_name_out], show_progress=False)
|
| 627 |
+
|
| 628 |
upload_btn.click(
|
| 629 |
upload_and_index,
|
| 630 |
[client_state, store_state, file_uploader, disp_file_name, max_tokens, overlap_tokens],
|
|
|
|
| 646 |
clear_btn.click(lambda: ([], "", ""), None, [chatbot, grounding_md, note], show_progress=False)\
|
| 647 |
.then(lambda: [], None, [chat_state], show_progress=False)
|
| 648 |
|
| 649 |
+
# Chips → prefill the question textbox
|
| 650 |
+
chip1.click(lambda: "Who is Mr. Darcy. what role does he play in the story", None, [question_tb], show_progress=False)
|
| 651 |
+
chip2.click(lambda: "What is the opening line of Moby-Dick", None, [question_tb], show_progress=False)
|
| 652 |
+
chip3.click(lambda: "Summarize the tea party scene and why it is absurd", None, [question_tb], show_progress=False)
|
| 653 |
+
chip4.click(lambda: "Give 3 clues Holmes uses in any one Sherlock Holmes story", None, [question_tb], show_progress=False)
|
| 654 |
+
chip5.click(lambda: "What is Pemberley. why is it important in Pride and Prejudice", None, [question_tb], show_progress=False)
|
| 655 |
+
chip6.click(lambda: "Who is Captain Ahab. what drives his obsession", None, [question_tb], show_progress=False)
|
| 656 |
+
|
| 657 |
+
# Tools
|
| 658 |
+
list_btn.click(list_stores, [client_state], [list_out], show_progress=True)
|
| 659 |
+
del_btn.click(delete_store, [client_state, del_name], [del_status], show_progress=True)
|
| 660 |
+
|
| 661 |
if __name__ == "__main__":
|
|
|
|
| 662 |
demo.queue().launch()
|