justmotes commited on
Commit
4f32b7a
·
1 Parent(s): c3b0b08

UI: Single screen redesign with benchmarking table

Browse files
Files changed (1) hide show
  1. app.py +88 -106
app.py CHANGED
@@ -2,7 +2,6 @@ import gradio as gr
2
  import pandas as pd
3
  import os
4
  import time
5
- import json
6
  from src.vector_db import UnifiedQdrant
7
  from src.router import LearnedRouter
8
  from src.comparison import ComparisonEngine
@@ -35,137 +34,120 @@ engine = ComparisonEngine(db, router, embedding_model_name="minilm")
35
  # --- UI Logic ---
36
  def run_comparison(query):
37
  if not query:
38
- return "Please enter a query.", None, None, None, None
39
 
 
40
  res_direct = engine.direct_search(query)
41
  res_xvector = engine.xvector_search(query)
42
 
43
- def format_results(res_dict):
44
- points = res_dict["results"]
45
- html = "<div style='display: flex; flex-direction: column; gap: 10px;'>"
46
- for p in points:
47
- payload = p.payload
48
- text = payload.get("text", "No text") if payload else "No text"
49
- score = p.score
50
- # Card style for results
51
- html += f"""
52
- <div style="padding: 10px; border-radius: 8px; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1);">
53
- <div style="font-size: 0.8em; color: #aaa; margin-bottom: 4px;">Score: {score:.4f}</div>
54
- <div style="font-size: 0.95em;">{text[:200]}...</div>
55
- </div>
56
- """
57
- html += "</div>"
58
- return html
59
-
60
- out_direct = format_results(res_direct)
61
- out_xvector = format_results(res_xvector)
62
-
63
- # Metrics for JSON
64
- metrics_data = {
65
- "Brute Force": {
66
- "Latency": f"{res_direct['latency_ms']:.2f} ms",
67
- "Shards Searched": res_direct['shards_searched']
68
- },
69
- "xVector": {
70
- "Latency": f"{res_xvector['latency_ms']:.2f} ms",
71
- "Shards Searched": res_xvector['shards_searched'],
72
- "Mode": res_xvector['mode']
73
- }
74
- }
75
 
76
- # Savings
77
- savings = (1 - (res_xvector["shards_searched"] / res_direct["shards_searched"])) * 100
78
- savings_html = f"""
79
- <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 12px; color: white;">
80
- <div style="font-size: 1.2em; opacity: 0.9;">Compute Savings</div>
81
- <div style="font-size: 3em; font-weight: bold;">{savings:.1f}%</div>
82
- <div style="font-size: 0.9em; opacity: 0.8;">{res_xvector['shards_searched']} shards vs {res_direct['shards_searched']}</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  </div>
84
  """
85
 
86
- # Telemetry
87
- telemetry_data = {
88
- "Router Confidence": f"{res_xvector.get('confidence', 0):.4f}",
89
- "Target Cluster": int(res_xvector.get('target_cluster', -1)),
90
- "Search Mode": res_xvector['mode']
91
- }
92
-
93
- return out_direct, out_xvector, metrics_data, savings_html, telemetry_data
94
 
95
- # --- Custom CSS ---
96
  custom_css = """
97
- body { background-color: #0b0f19; color: #e0e0e0; }
98
- .gradio-container { font-family: 'Inter', sans-serif; }
99
- h1 { background: -webkit-linear-gradient(45deg, #667eea, #764ba2); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
100
- .result-box { border: 1px solid #333; border-radius: 8px; padding: 10px; }
 
 
 
 
101
  """
102
 
103
  # --- Gradio Layout ---
104
  with gr.Blocks(title="dashVectorspace", theme=gr.themes.Soft(primary_hue="indigo", secondary_hue="slate"), css=custom_css) as demo:
105
 
106
- with gr.Column(elem_id="main-container"):
107
- # Header
108
- gr.HTML("""
109
- <div style="text-align: center; margin-bottom: 30px;">
110
- <h1 style="font-size: 3em; margin-bottom: 10px;">🚀 dashVectorspace</h1>
111
- <p style="font-size: 1.2em; color: #888;">Production-Grade Learned Hybrid Retrieval Engine</p>
112
- </div>
113
- """)
114
-
115
- # Input Section
116
- with gr.Row(variant="panel"):
117
- with gr.Column(scale=4):
118
- query_input = gr.Textbox(
119
- label="Search Query",
120
- placeholder="Ask a complex question (e.g., 'How does AI impact healthcare efficiency?')",
121
- lines=1,
122
- show_label=False,
123
- container=False,
124
- scale=4
125
- )
126
- with gr.Column(scale=1):
127
- submit_btn = gr.Button("🔍 Search", variant="primary", scale=1)
128
-
129
- # Results Section
130
- with gr.Row():
131
- # Left: Brute Force
132
- with gr.Column():
133
- gr.Markdown("### 🐢 Brute Force (Baseline)")
134
- out_baseline = gr.HTML(label="Results")
135
-
136
- # Right: xVector
137
- with gr.Column():
138
- gr.Markdown("### ⚡ xVector (Optimized)")
139
- out_optimized = gr.HTML(label="Results")
140
 
141
- gr.Markdown("---")
 
 
 
 
 
 
 
 
 
 
142
 
143
- # Metrics Section
144
- with gr.Row():
145
- with gr.Column(scale=1):
146
- gr.Markdown("### 📊 Performance Metrics")
147
- metrics_display = gr.JSON(label="Detailed Metrics")
148
-
149
- with gr.Column(scale=1):
150
- gr.Markdown("### 💰 Efficiency")
151
- savings_display = gr.HTML()
152
 
153
- # Telemetry (Accordion)
154
- with gr.Accordion("🛠️ System Telemetry (Debug Info)", open=False):
155
- telemetry_display = gr.JSON(label="Router Decisions")
 
 
 
 
 
 
 
 
156
 
157
- # Event Listener
158
  submit_btn.click(
159
  run_comparison,
160
  inputs=[query_input],
161
- outputs=[out_baseline, out_optimized, metrics_display, savings_display, telemetry_display]
162
  )
163
-
164
- # Allow Enter key to submit
165
  query_input.submit(
166
  run_comparison,
167
  inputs=[query_input],
168
- outputs=[out_baseline, out_optimized, metrics_display, savings_display, telemetry_display]
169
  )
170
 
171
  if __name__ == "__main__":
 
2
  import pandas as pd
3
  import os
4
  import time
 
5
  from src.vector_db import UnifiedQdrant
6
  from src.router import LearnedRouter
7
  from src.comparison import ComparisonEngine
 
34
  # --- UI Logic ---
35
  def run_comparison(query):
36
  if not query:
37
+ return None, None, "Please enter a query."
38
 
39
+ # Run Searches
40
  res_direct = engine.direct_search(query)
41
  res_xvector = engine.xvector_search(query)
42
 
43
+ # --- 1. Benchmarking Table Data ---
44
+ # Sketch Cols: Embedding Model | Router | dash Vector (Time, Shards) | Qdrant Search (Time, Shards)
45
+ # We will format this as a Pandas DataFrame for the gr.Dataframe component
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
+ df = pd.DataFrame({
48
+ "Embedding Model": ["MiniLM-L6-v2"],
49
+ "Router": ["LightGBM"],
50
+ "dashVector (Optimized)": [f"{res_xvector['latency_ms']:.1f} ms | {res_xvector['shards_searched']} Shards"],
51
+ "Qdrant (Baseline)": [f"{res_direct['latency_ms']:.1f} ms | {res_direct['shards_searched']} Shards"],
52
+ "Savings": [f"{(1 - res_xvector['shards_searched']/res_direct['shards_searched'])*100:.1f}%"]
53
+ })
54
+
55
+ # --- 2. Search Results (Top 3) ---
56
+ # Just showing top result text to prove it works, as per sketch focus on table
57
+ def format_top_result(res_dict):
58
+ if not res_dict["results"]:
59
+ return "No results found."
60
+ top_res = res_dict["results"][0]
61
+ payload = top_res.payload
62
+ text = payload.get("text", "No text") if payload else "No text"
63
+ return f"Top Result: {text[:150]}..."
64
+
65
+ results_preview = f"""
66
+ <div style="display: flex; gap: 20px; margin-top: 10px;">
67
+ <div style="flex: 1; padding: 10px; background: rgba(255,255,255,0.05); border-radius: 8px;">
68
+ <strong>dashVector:</strong> {format_top_result(res_xvector)}
69
+ </div>
70
+ <div style="flex: 1; padding: 10px; background: rgba(255,255,255,0.05); border-radius: 8px;">
71
+ <strong>Qdrant:</strong> {format_top_result(res_direct)}
72
+ </div>
73
  </div>
74
  """
75
 
76
+ return df, results_preview
 
 
 
 
 
 
 
77
 
78
+ # --- Custom CSS for Single Screen Layout ---
79
  custom_css = """
80
+ body { background-color: #0b0f19; color: #e0e0e0; overflow: hidden; }
81
+ .gradio-container { max-width: 1200px !important; margin: 0 auto; height: 100vh; display: flex; flex-direction: column; justify-content: center; }
82
+ h1 { font-size: 2.5em; margin-bottom: 0.2em; text-align: center; background: -webkit-linear-gradient(45deg, #667eea, #764ba2); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
83
+ .input-box textarea { background: #1a1f2e !important; border: 1px solid #333 !important; font-size: 1.2em; }
84
+ .dataset-box { border: 1px solid #444; padding: 10px 20px; border-radius: 8px; text-align: center; font-weight: bold; background: #1a1f2e; display: inline-block; }
85
+ .scope-box { margin-top: 20px; padding: 15px; border-left: 4px solid #667eea; background: rgba(102, 126, 234, 0.1); }
86
+ .table-wrap { margin-top: 20px; }
87
+ footer { display: none !important; }
88
  """
89
 
90
  # --- Gradio Layout ---
91
  with gr.Blocks(title="dashVectorspace", theme=gr.themes.Soft(primary_hue="indigo", secondary_hue="slate"), css=custom_css) as demo:
92
 
93
+ # Title
94
+ gr.Markdown("# 🚀 dashVectorspace")
95
+
96
+ # Search Section (Centered)
97
+ with gr.Row(elem_id="search-row"):
98
+ with gr.Column(scale=4):
99
+ query_input = gr.Textbox(
100
+ placeholder="Enter your search query here...",
101
+ show_label=False,
102
+ elem_classes="input-box",
103
+ lines=1
104
+ )
105
+ with gr.Column(scale=1):
106
+ submit_btn = gr.Button("Search", variant="primary", size="lg")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
+ # Benchmarking Table
109
+ gr.Markdown("### ⚡ Benchmarking Results (Live)")
110
+ results_table = gr.Dataframe(
111
+ headers=["Embedding Model", "Router", "dashVector (Optimized)", "Qdrant (Baseline)", "Savings"],
112
+ datatype=["str", "str", "str", "str", "str"],
113
+ interactive=False,
114
+ elem_classes="table-wrap"
115
+ )
116
+
117
+ # Result Preview (Hidden initially, shown after search)
118
+ results_html = gr.HTML()
119
 
120
+ # Footer Section: Dataset & Scope
121
+ with gr.Row(style="margin-top: 40px; align-items: center;"):
122
+ with gr.Column(scale=1):
123
+ gr.HTML("""
124
+ <div class="dataset-box">
125
+ Dataset: MS MARCO
126
+ </div>
127
+ """)
 
128
 
129
+ with gr.Column(scale=2):
130
+ gr.HTML("""
131
+ <div class="scope-box">
132
+ <strong>Project Scope:</strong>
133
+ <ul style="margin-top: 5px; padding-left: 20px;">
134
+ <li><strong>Learned Routing:</strong> Predicts target clusters to reduce search space by 90%.</li>
135
+ <li><strong>Custom Sharding:</strong> Explicit data partitioning for targeted retrieval.</li>
136
+ <li><strong>Matryoshka Embeddings:</strong> Adaptive dimensionality for high-speed filtering.</li>
137
+ </ul>
138
+ </div>
139
+ """)
140
 
141
+ # Event Listeners
142
  submit_btn.click(
143
  run_comparison,
144
  inputs=[query_input],
145
+ outputs=[results_table, results_html]
146
  )
 
 
147
  query_input.submit(
148
  run_comparison,
149
  inputs=[query_input],
150
+ outputs=[results_table, results_html]
151
  )
152
 
153
  if __name__ == "__main__":