aikacl commited on
Commit
ec2affb
Β·
verified Β·
1 Parent(s): ab4e660

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -408
app.py CHANGED
@@ -42,287 +42,6 @@ EXAMPLES = [
42
  },
43
  ]
44
 
45
- # ── Custom CSS ──────────────────────────────────────────────────────────────
46
-
47
- CUSTOM_CSS = """
48
- /* ── Global ──────────────────────────────────────── */
49
- .gradio-container {
50
- max-width: 1200px !important;
51
- font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif !important;
52
- }
53
-
54
- /* ── Header Banner ───────────────────────────────── */
55
- .header-banner {
56
- background: linear-gradient(135deg, #1a1a2e 0%, #16213e 40%, #0f3460 100%);
57
- border-radius: 16px;
58
- padding: 32px 36px;
59
- margin-bottom: 24px;
60
- color: #fff;
61
- position: relative;
62
- overflow: hidden;
63
- }
64
- .header-banner::before {
65
- content: '';
66
- position: absolute;
67
- top: -50%;
68
- right: -20%;
69
- width: 400px;
70
- height: 400px;
71
- background: radial-gradient(circle, rgba(99, 179, 237, 0.15) 0%, transparent 70%);
72
- pointer-events: none;
73
- }
74
- .header-banner h1 {
75
- margin: 0 0 8px 0 !important;
76
- font-size: 28px !important;
77
- font-weight: 700 !important;
78
- letter-spacing: -0.5px;
79
- background: linear-gradient(90deg, #ffffff, #a8d8ea);
80
- -webkit-background-clip: text;
81
- -webkit-text-fill-color: transparent;
82
- background-clip: text;
83
- }
84
- .header-banner p {
85
- margin: 0 !important;
86
- font-size: 14px !important;
87
- color: rgba(255, 255, 255, 0.7) !important;
88
- line-height: 1.6;
89
- }
90
- .header-badge {
91
- display: inline-block;
92
- background: rgba(99, 179, 237, 0.2);
93
- color: #a8d8ea;
94
- font-size: 11px;
95
- font-weight: 600;
96
- padding: 3px 10px;
97
- border-radius: 20px;
98
- margin-bottom: 12px;
99
- border: 1px solid rgba(99, 179, 237, 0.3);
100
- letter-spacing: 0.5px;
101
- text-transform: uppercase;
102
- }
103
-
104
- /* ── Section Cards ───────────────────────────────── */
105
- .section-card {
106
- background: #ffffff;
107
- border: 1px solid #e8ecf1;
108
- border-radius: 12px;
109
- padding: 20px;
110
- margin-bottom: 16px;
111
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
112
- transition: box-shadow 0.2s ease;
113
- }
114
- .section-card:hover {
115
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
116
- }
117
- .section-title {
118
- font-size: 13px !important;
119
- font-weight: 600 !important;
120
- color: #64748b !important;
121
- text-transform: uppercase !important;
122
- letter-spacing: 0.8px !important;
123
- margin-bottom: 12px !important;
124
- padding-bottom: 8px !important;
125
- border-bottom: 1px solid #f1f5f9 !important;
126
- }
127
-
128
- /* ── Form Controls ───────────────────────────────── */
129
- .gr-textbox, .gr-dropdown {
130
- border-radius: 8px !important;
131
- border: 1px solid #e2e8f0 !important;
132
- transition: border-color 0.2s ease, box-shadow 0.2s ease !important;
133
- }
134
- .gr-textbox:focus-within, .gr-dropdown:focus-within {
135
- border-color: #63b3ed !important;
136
- box-shadow: 0 0 0 3px rgba(99, 179, 237, 0.12) !important;
137
- }
138
- textarea {
139
- font-size: 13.5px !important;
140
- line-height: 1.6 !important;
141
- }
142
-
143
- /* ── Document List ───────────────────────────────── */
144
- .doc-list-container {
145
- max-height: 380px;
146
- overflow-y: auto;
147
- padding-right: 4px;
148
- }
149
- .doc-list-container .gr-textbox {
150
- border-left: 3px solid #63b3ed !important;
151
- margin-bottom: 8px !important;
152
- }
153
-
154
- /* ── Buttons ─────────────────────────────────────── */
155
- .doc-btn {
156
- border-radius: 8px !important;
157
- font-weight: 500 !important;
158
- font-size: 13px !important;
159
- padding: 8px 16px !important;
160
- transition: all 0.2s ease !important;
161
- }
162
- .btn-add {
163
- background: #f0f7ff !important;
164
- color: #2b6cb0 !important;
165
- border: 1px solid #bee3f8 !important;
166
- }
167
- .btn-add:hover {
168
- background: #dbeafe !important;
169
- border-color: #90cdf4 !important;
170
- }
171
- .btn-remove {
172
- background: #fff5f5 !important;
173
- color: #c53030 !important;
174
- border: 1px solid #fed7d7 !important;
175
- }
176
- .btn-remove:hover {
177
- background: #fee2e2 !important;
178
- border-color: #feb2b2 !important;
179
- }
180
-
181
- /* ── Submit Button Override ──────────────────────── */
182
- .submit-row .primary-btn {
183
- width: 100%;
184
- padding: 12px !important;
185
- font-size: 15px !important;
186
- font-weight: 600 !important;
187
- border-radius: 10px !important;
188
- background: linear-gradient(135deg, #2b6cb0, #3182ce) !important;
189
- border: none !important;
190
- letter-spacing: 0.3px;
191
- transition: all 0.25s ease !important;
192
- }
193
- .submit-row .primary-btn:hover {
194
- background: linear-gradient(135deg, #2c5282, #2b6cb0) !important;
195
- box-shadow: 0 4px 14px rgba(43, 108, 176, 0.35) !important;
196
- transform: translateY(-1px);
197
- }
198
-
199
- /* ── Results Panel ───────────────────────────────── */
200
- .result-panel {
201
- background: #fafbfc;
202
- border: 1px solid #e8ecf1;
203
- border-radius: 12px;
204
- padding: 20px;
205
- min-height: 200px;
206
- }
207
- .result-panel table {
208
- border-collapse: separate !important;
209
- border-spacing: 0 !important;
210
- width: 100% !important;
211
- font-size: 13px !important;
212
- }
213
- .result-panel thead th {
214
- background: #f1f5f9 !important;
215
- color: #475569 !important;
216
- font-weight: 600 !important;
217
- font-size: 11px !important;
218
- text-transform: uppercase !important;
219
- letter-spacing: 0.5px !important;
220
- padding: 10px 12px !important;
221
- border-bottom: 2px solid #e2e8f0 !important;
222
- }
223
- .result-panel thead th:first-child {
224
- border-radius: 8px 0 0 0 !important;
225
- }
226
- .result-panel thead th:last-child {
227
- border-radius: 0 8px 0 0 !important;
228
- }
229
- .result-panel tbody td {
230
- padding: 10px 12px !important;
231
- border-bottom: 1px solid #f1f5f9 !important;
232
- vertical-align: top !important;
233
- color: #334155 !important;
234
- }
235
- .result-panel tbody tr:hover {
236
- background: #f8fafc !important;
237
- }
238
- .result-panel tbody tr:last-child td {
239
- border-bottom: none !important;
240
- }
241
-
242
- /* ── Summary Badge ───────────────────────────────── */
243
- .summary-badge {
244
- background: linear-gradient(135deg, #f0fff4, #e6fffa);
245
- border: 1px solid #c6f6d5;
246
- border-radius: 10px;
247
- padding: 12px 16px;
248
- margin-top: 12px;
249
- font-size: 13px;
250
- color: #276749;
251
- }
252
-
253
- /* ── Citation Accordion ──────────────────────────── */
254
- .citation-box {
255
- background: #f8fafc;
256
- border: 1px solid #e2e8f0;
257
- border-radius: 10px;
258
- padding: 16px 20px;
259
- margin-top: 20px;
260
- }
261
- .citation-box summary {
262
- cursor: pointer;
263
- font-weight: 600;
264
- font-size: 14px;
265
- color: #475569;
266
- }
267
- .citation-box pre {
268
- background: #1e293b !important;
269
- border-radius: 8px !important;
270
- padding: 14px !important;
271
- margin-top: 10px !important;
272
- font-size: 12px !important;
273
- line-height: 1.7 !important;
274
- color: #e2e8f0 !important;
275
- overflow-x: auto;
276
- }
277
- .citation-box pre code {
278
- color: #e2e8f0 !important;
279
- background: transparent !important;
280
- font-family: 'Fira Code', 'Consolas', monospace !important;
281
- }
282
-
283
- /* ── Config Row (Instruction + ChunkSize + Example) */
284
- .config-row {
285
- display: flex;
286
- gap: 12px;
287
- align-items: flex-end;
288
- }
289
- .config-row > div {
290
- flex: 1;
291
- }
292
-
293
- /* ── Scrollbar ───────────────────────────────────── */
294
- .doc-scroll::-webkit-scrollbar {
295
- width: 5px;
296
- }
297
- .doc-scroll::-webkit-scrollbar-track {
298
- background: transparent;
299
- }
300
- .doc-scroll::-webkit-scrollbar-thumb {
301
- background: #cbd5e1;
302
- border-radius: 10px;
303
- }
304
- .doc-scroll::-webkit-scrollbar-thumb:hover {
305
- background: #94a3b8;
306
- }
307
-
308
- /* ── Label tweaks ────────────────────────────────── */
309
- .label-query label span {
310
- font-size: 14px !important;
311
- font-weight: 600 !important;
312
- color: #1e293b !important;
313
- }
314
- """
315
-
316
- # ── Theme ───────────────────────────────────────────────────────────────────
317
-
318
- theme = gr.themes.Soft(
319
- primary_hue="blue",
320
- secondary_hue="slate",
321
- neutral_hue="slate",
322
- )
323
-
324
- # ── Logic helpers ───────────────────────────────────────────────────────────
325
-
326
 
327
  def _make_vis_updates(count: int):
328
  return [gr.update(visible=(i < count)) for i in range(MAX_DOCS)]
@@ -339,13 +58,18 @@ def remove_doc(count: int):
339
 
340
 
341
  def load_example(example_label):
342
- if example_label is None:
343
  query_upd = gr.update(value="")
344
- doc_upds = [gr.update(value="") for _ in range(MAX_DOCS)]
 
 
 
345
  return [query_upd] + doc_upds + [INIT_DOCS]
 
346
  ex = next((e for e in EXAMPLES if e["label"] == example_label), None)
347
  if ex is None:
348
  return [gr.update()] + [gr.update() for _ in range(MAX_DOCS)] + [INIT_DOCS]
 
349
  docs = ex["docs"]
350
  count = len(docs)
351
  query_upd = gr.update(value=ex["query"])
@@ -395,9 +119,8 @@ def rerank(query: str, instruction: str, chunk_size: int, *doc_texts: str):
395
  table.append([rank_idx, corpus_id, round(score, 6), doc])
396
 
397
  summary = (
398
- f"Reranked **{len(docs)}** documents with "
399
- f"`{MODEL_ID}` (chunk_size={chunk_size}). "
400
- f"Higher score means more relevant."
401
  )
402
  return table, summary
403
  except Exception as error:
@@ -406,135 +129,71 @@ def rerank(query: str, instruction: str, chunk_size: int, *doc_texts: str):
406
 
407
  # ── UI ──────────────────────────────────────────────────────────────────────
408
 
409
- with gr.Blocks(
410
- title="KaLM-Reranker-V1 Demo",
411
- theme=theme,
412
- css=CUSTOM_CSS,
413
- ) as demo:
414
-
415
- # ── Header ──
416
- gr.HTML("""
417
- <div class="header-banner">
418
- <div class="header-badge">Powered by KaLM-Embedding</div>
419
- <h1>KaLM-Reranker-V1 Demo</h1>
420
- <p>A fast but not late-interaction reranker for compressed document reranking. <br/>
421
- Input a query and candidate documents to get relevance scores and reranked results.</p>
422
- </div>
423
- """)
424
-
425
- with gr.Row(equal_height=False):
426
  # ── Left column: inputs ──
427
  with gr.Column(scale=1):
428
-
429
- # Query
430
- with gr.Group(elem_classes=["section-card"]):
431
- gr.Markdown('<div class="section-title">Query</div>', elem_classes="label-query")
432
- query_input = gr.Textbox(
433
- show_label=False,
434
- value="What is the capital of China?",
435
- lines=3,
436
- placeholder="Enter your query here...",
437
- )
438
-
439
- # Config row: Instruction Β· Chunk Size Β· Load Example
440
- with gr.Group(elem_classes=["section-card"]):
441
- gr.Markdown('<div class="section-title">Configuration</div>', elem_classes="label-query")
442
- with gr.Row():
443
- with gr.Column(scale=2):
444
- instruction_input = gr.Textbox(
445
- label="Instruction",
446
- value=DEFAULT_INSTRUCTION,
447
- lines=2,
448
- )
449
- with gr.Column(scale=1):
450
- chunk_size_input = gr.Dropdown(
451
- label="Chunk Size",
452
- choices=[2, 4, 8, 16],
453
- value=4,
454
- interactive=True,
455
- )
456
- example_selector = gr.Dropdown(
457
- label="Quick Example",
458
- choices=[""] + [ex["label"] for ex in EXAMPLES],
459
- value="",
460
- interactive=True,
461
- allow_custom_value=False,
462
- )
463
-
464
- # Candidate Documents
465
- with gr.Group(elem_classes=["section-card"]):
466
- gr.Markdown(
467
- '<div class="section-title">Candidate Documents '
468
- '<span style="float:right;font-weight:400;text-transform:none;letter-spacing:0;font-size:11px;color:#94a3b8">'
469
- f'Max {MAX_DOCS} docs</span></div>',
470
- elem_classes="label-query",
471
- )
472
- doc_count = gr.State(value=INIT_DOCS)
473
- doc_textboxes: List[gr.Textbox] = []
474
-
475
- with gr.Column(elem_classes=["doc-list-container", "doc-scroll"]) as doc_list:
476
- for i in range(MAX_DOCS):
477
- visible = i < INIT_DOCS
478
- tb = gr.Textbox(
479
- label=f" {i + 1}",
480
- lines=2,
481
- placeholder=f"Enter document {i + 1}...",
482
- visible=visible,
483
- show_label=True,
484
- )
485
- doc_textboxes.append(tb)
486
-
487
- with gr.Row():
488
- add_btn = gr.Button(
489
- "+ Add Document",
490
- size="sm",
491
- elem_classes=["doc-btn", "btn-add"],
492
- )
493
- remove_btn = gr.Button(
494
- "- Remove Last",
495
- size="sm",
496
- elem_classes=["doc-btn", "btn-remove"],
497
  )
 
 
 
 
 
498
 
499
- # Submit
500
- with gr.Row(elem_classes=["submit-row"]):
501
- submit = gr.Button(
502
- "Rerank",
503
- variant="primary",
504
- elem_classes=["primary-btn"],
505
- )
506
 
507
  # ── Right column: outputs ──
508
  with gr.Column(scale=1):
509
- with gr.Group(elem_classes=["result-panel"]):
510
- gr.Markdown(
511
- '<div class="section-title">Reranking Results</div>',
512
- elem_classes="label-query",
513
- )
514
- output_table = gr.Dataframe(
515
- headers=["Rank", "Corpus ID", "Score", "Document"],
516
- label=None,
517
- wrap=True,
518
- interactive=False,
519
- )
520
- output_summary = gr.HTML()
521
-
522
- # ── Citation ──
523
- gr.HTML("""
524
- <details class="citation-box">
525
- <summary>Cite this work</summary>
526
- <pre><code>@misc{zhao2026kalmrerankerv1,
527
- title={KaLM-Reranker-V1: Fast but Not Late Interaction for Compressed Document Reranking},
528
- author={Xinping Zhao and Jiaxin Xu and Ziqi Dai and Xin Zhang and Shouzheng Huang
529
- and Danyu Tang and Xinshuo Hu and Meishan Zhang and Baotian Hu and Min Zhang},
530
- year={2026},
531
- eprint={2606.22807},
532
- archivePrefix={arXiv},
533
- primaryClass={cs.CL},
534
- url={https://arxiv.org/abs/2606.22807},
535
- }</code></pre>
536
- </details>
537
- """)
538
 
539
  # ── Events ──
540
  add_btn.click(
@@ -558,6 +217,26 @@ with gr.Blocks(
558
  outputs=[output_table, output_summary],
559
  )
560
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
 
562
  if __name__ == "__main__":
563
  demo.launch()
 
42
  },
43
  ]
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  def _make_vis_updates(count: int):
47
  return [gr.update(visible=(i < count)) for i in range(MAX_DOCS)]
 
58
 
59
 
60
  def load_example(example_label):
61
+ if not example_label:
62
  query_upd = gr.update(value="")
63
+ doc_upds = [
64
+ gr.update(value="", visible=(i < INIT_DOCS))
65
+ for i in range(MAX_DOCS)
66
+ ]
67
  return [query_upd] + doc_upds + [INIT_DOCS]
68
+
69
  ex = next((e for e in EXAMPLES if e["label"] == example_label), None)
70
  if ex is None:
71
  return [gr.update()] + [gr.update() for _ in range(MAX_DOCS)] + [INIT_DOCS]
72
+
73
  docs = ex["docs"]
74
  count = len(docs)
75
  query_upd = gr.update(value=ex["query"])
 
119
  table.append([rank_idx, corpus_id, round(score, 6), doc])
120
 
121
  summary = (
122
+ f"Reranked {len(docs)} documents with "
123
+ f"`{MODEL_ID}` (chunk_size={chunk_size}). Higher score means more relevant."
 
124
  )
125
  return table, summary
126
  except Exception as error:
 
129
 
130
  # ── UI ──────────────────────────────────────────────────────────────────────
131
 
132
+ with gr.Blocks(title="KaLM-Reranker-V1 Demo") as demo:
133
+ gr.Markdown(
134
+ """
135
+ # KaLM-Reranker-V1 Demo
136
+ **KaLM-Reranker-V1** is a fast but not late-interaction reranker for compressed document reranking.
137
+ Input a query and several candidate documents. The demo returns relevance scores and reranked results.
138
+ """
139
+ )
140
+
141
+ with gr.Row():
 
 
 
 
 
 
 
142
  # ── Left column: inputs ──
143
  with gr.Column(scale=1):
144
+ query_input = gr.Textbox(
145
+ label="Query",
146
+ value="",
147
+ lines=2,
148
+ )
149
+ instruction_input = gr.Textbox(
150
+ label="Instruction",
151
+ value=DEFAULT_INSTRUCTION,
152
+ lines=2,
153
+ )
154
+ chunk_size_input = gr.Dropdown(
155
+ label="Chunk Size",
156
+ choices=[2, 4, 8, 16],
157
+ value=2,
158
+ interactive=True,
159
+ )
160
+
161
+ example_selector = gr.Dropdown(
162
+ label="Load Example",
163
+ choices=[""] + [ex["label"] for ex in EXAMPLES],
164
+ value="",
165
+ interactive=True,
166
+ )
167
+
168
+ gr.Markdown("### Candidate Documents")
169
+ doc_count = gr.State(value=INIT_DOCS)
170
+ doc_textboxes: List[gr.Textbox] = []
171
+
172
+ with gr.Column() as doc_list:
173
+ for i in range(MAX_DOCS):
174
+ visible = i < INIT_DOCS
175
+ tb = gr.Textbox(
176
+ label=f"Document {i + 1}",
177
+ lines=2,
178
+ placeholder=f"Enter document {i + 1}...",
179
+ visible=visible,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  )
181
+ doc_textboxes.append(tb)
182
+
183
+ with gr.Row():
184
+ add_btn = gr.Button("+ Add Document", size="sm")
185
+ remove_btn = gr.Button("- Remove Last", size="sm")
186
 
187
+ submit = gr.Button("Rerank", variant="primary")
 
 
 
 
 
 
188
 
189
  # ── Right column: outputs ──
190
  with gr.Column(scale=1):
191
+ output_table = gr.Dataframe(
192
+ headers=["Rank", "Corpus ID", "Score", "Document"],
193
+ label="Reranking Results",
194
+ wrap=True,
195
+ )
196
+ output_summary = gr.Markdown()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
  # ── Events ──
199
  add_btn.click(
 
217
  outputs=[output_table, output_summary],
218
  )
219
 
220
+ gr.Markdown(
221
+ """
222
+ ## Citation
223
+
224
+ If you find this demo useful, please cite:
225
+
226
+ ```bibtex
227
+ @misc{zhao2026kalmrerankerv1,
228
+ title={KaLM-Reranker-V1: Fast but Not Late Interaction for Compressed Document Reranking},
229
+ author={Xinping Zhao and Jiaxin Xu and Ziqi Dai and Xin Zhang and Shouzheng Huang and Danyu Tang and Xinshuo Hu and Meishan Zhang and Baotian Hu and Min Zhang},
230
+ year={2026},
231
+ eprint={2606.22807},
232
+ archivePrefix={arXiv},
233
+ primaryClass={cs.CL},
234
+ url={https://arxiv.org/abs/2606.22807},
235
+ }
236
+ ```
237
+ """
238
+ )
239
+
240
 
241
  if __name__ == "__main__":
242
  demo.launch()