local-deep-research 0.5.7__py3-none-any.whl → 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. local_deep_research/__version__.py +1 -1
  2. local_deep_research/advanced_search_system/candidate_exploration/progressive_explorer.py +11 -1
  3. local_deep_research/advanced_search_system/questions/browsecomp_question.py +32 -6
  4. local_deep_research/advanced_search_system/strategies/focused_iteration_strategy.py +33 -8
  5. local_deep_research/advanced_search_system/strategies/source_based_strategy.py +2 -0
  6. local_deep_research/api/__init__.py +2 -0
  7. local_deep_research/api/research_functions.py +177 -3
  8. local_deep_research/benchmarks/graders.py +150 -5
  9. local_deep_research/benchmarks/models/__init__.py +19 -0
  10. local_deep_research/benchmarks/models/benchmark_models.py +283 -0
  11. local_deep_research/benchmarks/ui/__init__.py +1 -0
  12. local_deep_research/benchmarks/web_api/__init__.py +6 -0
  13. local_deep_research/benchmarks/web_api/benchmark_routes.py +862 -0
  14. local_deep_research/benchmarks/web_api/benchmark_service.py +920 -0
  15. local_deep_research/config/llm_config.py +106 -21
  16. local_deep_research/defaults/default_settings.json +448 -3
  17. local_deep_research/error_handling/report_generator.py +10 -0
  18. local_deep_research/llm/__init__.py +19 -0
  19. local_deep_research/llm/llm_registry.py +155 -0
  20. local_deep_research/metrics/db_models.py +3 -7
  21. local_deep_research/metrics/search_tracker.py +25 -11
  22. local_deep_research/report_generator.py +3 -2
  23. local_deep_research/search_system.py +12 -9
  24. local_deep_research/utilities/log_utils.py +23 -10
  25. local_deep_research/utilities/thread_context.py +99 -0
  26. local_deep_research/web/app_factory.py +32 -8
  27. local_deep_research/web/database/benchmark_schema.py +230 -0
  28. local_deep_research/web/database/convert_research_id_to_string.py +161 -0
  29. local_deep_research/web/database/models.py +55 -1
  30. local_deep_research/web/database/schema_upgrade.py +397 -2
  31. local_deep_research/web/database/uuid_migration.py +265 -0
  32. local_deep_research/web/routes/api_routes.py +62 -31
  33. local_deep_research/web/routes/history_routes.py +13 -6
  34. local_deep_research/web/routes/metrics_routes.py +264 -4
  35. local_deep_research/web/routes/research_routes.py +45 -18
  36. local_deep_research/web/routes/route_registry.py +352 -0
  37. local_deep_research/web/routes/settings_routes.py +382 -22
  38. local_deep_research/web/services/research_service.py +22 -29
  39. local_deep_research/web/services/settings_manager.py +53 -0
  40. local_deep_research/web/services/settings_service.py +2 -0
  41. local_deep_research/web/static/css/styles.css +8 -0
  42. local_deep_research/web/static/js/components/detail.js +7 -14
  43. local_deep_research/web/static/js/components/details.js +8 -10
  44. local_deep_research/web/static/js/components/fallback/ui.js +4 -4
  45. local_deep_research/web/static/js/components/history.js +6 -6
  46. local_deep_research/web/static/js/components/logpanel.js +14 -11
  47. local_deep_research/web/static/js/components/progress.js +51 -46
  48. local_deep_research/web/static/js/components/research.js +250 -89
  49. local_deep_research/web/static/js/components/results.js +5 -7
  50. local_deep_research/web/static/js/components/settings.js +32 -26
  51. local_deep_research/web/static/js/components/settings_sync.js +24 -23
  52. local_deep_research/web/static/js/config/urls.js +285 -0
  53. local_deep_research/web/static/js/main.js +8 -8
  54. local_deep_research/web/static/js/research_form.js +267 -12
  55. local_deep_research/web/static/js/services/api.js +18 -18
  56. local_deep_research/web/static/js/services/keyboard.js +8 -8
  57. local_deep_research/web/static/js/services/socket.js +53 -35
  58. local_deep_research/web/static/js/services/ui.js +1 -1
  59. local_deep_research/web/templates/base.html +4 -1
  60. local_deep_research/web/templates/components/custom_dropdown.html +5 -3
  61. local_deep_research/web/templates/components/mobile_nav.html +3 -3
  62. local_deep_research/web/templates/components/sidebar.html +9 -3
  63. local_deep_research/web/templates/pages/benchmark.html +2697 -0
  64. local_deep_research/web/templates/pages/benchmark_results.html +1136 -0
  65. local_deep_research/web/templates/pages/benchmark_simple.html +453 -0
  66. local_deep_research/web/templates/pages/cost_analytics.html +1 -1
  67. local_deep_research/web/templates/pages/metrics.html +212 -39
  68. local_deep_research/web/templates/pages/research.html +8 -6
  69. local_deep_research/web/templates/pages/star_reviews.html +1 -1
  70. local_deep_research/web_search_engines/engines/search_engine_arxiv.py +14 -1
  71. local_deep_research/web_search_engines/engines/search_engine_brave.py +15 -1
  72. local_deep_research/web_search_engines/engines/search_engine_ddg.py +20 -1
  73. local_deep_research/web_search_engines/engines/search_engine_google_pse.py +26 -2
  74. local_deep_research/web_search_engines/engines/search_engine_pubmed.py +15 -1
  75. local_deep_research/web_search_engines/engines/search_engine_retriever.py +192 -0
  76. local_deep_research/web_search_engines/engines/search_engine_tavily.py +307 -0
  77. local_deep_research/web_search_engines/rate_limiting/__init__.py +14 -0
  78. local_deep_research/web_search_engines/rate_limiting/__main__.py +9 -0
  79. local_deep_research/web_search_engines/rate_limiting/cli.py +209 -0
  80. local_deep_research/web_search_engines/rate_limiting/exceptions.py +21 -0
  81. local_deep_research/web_search_engines/rate_limiting/tracker.py +506 -0
  82. local_deep_research/web_search_engines/retriever_registry.py +108 -0
  83. local_deep_research/web_search_engines/search_engine_base.py +161 -43
  84. local_deep_research/web_search_engines/search_engine_factory.py +14 -0
  85. local_deep_research/web_search_engines/search_engines_config.py +20 -0
  86. local_deep_research-0.6.0.dist-info/METADATA +374 -0
  87. {local_deep_research-0.5.7.dist-info → local_deep_research-0.6.0.dist-info}/RECORD +90 -65
  88. local_deep_research-0.5.7.dist-info/METADATA +0 -420
  89. {local_deep_research-0.5.7.dist-info → local_deep_research-0.6.0.dist-info}/WHEEL +0 -0
  90. {local_deep_research-0.5.7.dist-info → local_deep_research-0.6.0.dist-info}/entry_points.txt +0 -0
  91. {local_deep_research-0.5.7.dist-info → local_deep_research-0.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,453 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% set active_page = 'benchmark' %}
4
+
5
+ {% block title %}Benchmark - Deep Research System{% endblock %}
6
+
7
+ {% block extra_head %}
8
+ <meta name="csrf-token" content="{{ csrf_token() }}">
9
+ <style>
10
+ .benchmark-card {
11
+ max-width: 700px;
12
+ margin: 0 auto;
13
+ }
14
+
15
+ .current-config {
16
+ background: var(--bg-color);
17
+ border: 1px solid var(--border-color);
18
+ border-radius: 8px;
19
+ padding: 20px;
20
+ margin-bottom: 20px;
21
+ }
22
+
23
+ .config-item {
24
+ display: flex;
25
+ justify-content: space-between;
26
+ padding: 8px 0;
27
+ border-bottom: 1px solid var(--border-color);
28
+ }
29
+
30
+ .config-item:last-child {
31
+ border-bottom: none;
32
+ }
33
+
34
+ .config-label {
35
+ font-weight: 500;
36
+ color: var(--text-muted);
37
+ }
38
+
39
+ .config-value {
40
+ font-weight: 600;
41
+ color: var(--primary-color);
42
+ }
43
+
44
+ .dataset-selection {
45
+ margin: 20px 0;
46
+ }
47
+
48
+ .dataset-option {
49
+ display: flex;
50
+ align-items: center;
51
+ padding: 15px;
52
+ margin: 10px 0;
53
+ background: var(--card-bg);
54
+ border: 2px solid var(--border-color);
55
+ border-radius: 8px;
56
+ cursor: pointer;
57
+ transition: all 0.2s;
58
+ }
59
+
60
+ .dataset-option:hover {
61
+ border-color: var(--primary-color);
62
+ }
63
+
64
+ .dataset-option.selected {
65
+ border-color: var(--primary-color);
66
+ background: var(--primary-light);
67
+ }
68
+
69
+ .dataset-option input[type="number"] {
70
+ width: 80px;
71
+ margin-left: auto;
72
+ }
73
+
74
+ .start-button {
75
+ width: 100%;
76
+ padding: 15px;
77
+ font-size: 1.1rem;
78
+ }
79
+
80
+ .progress-section {
81
+ display: none;
82
+ margin-top: 30px;
83
+ }
84
+
85
+ .progress-bar {
86
+ width: 100%;
87
+ height: 30px;
88
+ background: var(--bg-color);
89
+ border-radius: 15px;
90
+ overflow: hidden;
91
+ margin: 20px 0;
92
+ }
93
+
94
+ .progress-fill {
95
+ height: 100%;
96
+ background: linear-gradient(90deg, var(--primary-color), var(--accent-color));
97
+ width: 0%;
98
+ transition: width 0.3s ease;
99
+ }
100
+
101
+ .stats-grid {
102
+ display: grid;
103
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
104
+ gap: 15px;
105
+ margin-top: 20px;
106
+ }
107
+
108
+ .stat-card {
109
+ padding: 15px;
110
+ background: var(--bg-color);
111
+ border-radius: 8px;
112
+ text-align: center;
113
+ }
114
+
115
+ .stat-value {
116
+ font-size: 1.8rem;
117
+ font-weight: bold;
118
+ color: var(--primary-color);
119
+ }
120
+
121
+ .stat-label {
122
+ font-size: 0.9rem;
123
+ color: var(--text-muted);
124
+ margin-top: 5px;
125
+ }
126
+ </style>
127
+ {% endblock %}
128
+
129
+ {% block content %}
130
+ <div class="page active" id="benchmark">
131
+ <div class="page-header">
132
+ <h1>Benchmark Your Configuration</h1>
133
+ <p class="page-subtitle">Test your current settings against standard datasets</p>
134
+ </div>
135
+
136
+ <div id="benchmark-alert" class="settings-alert-container" style="display:none"></div>
137
+
138
+ <div class="card benchmark-card">
139
+ <div class="card-content">
140
+ <!-- Current Configuration Display -->
141
+ <div class="current-config">
142
+ <h3>Current Configuration</h3>
143
+ <div id="config-display">
144
+ <div class="config-item">
145
+ <span class="config-label">Loading...</span>
146
+ <span class="config-value"></span>
147
+ </div>
148
+ </div>
149
+ </div>
150
+
151
+ <!-- Dataset Selection -->
152
+ <div class="dataset-selection">
153
+ <h3>Select Datasets to Test</h3>
154
+
155
+ <div class="dataset-option selected" data-dataset="simpleqa">
156
+ <div>
157
+ <h4>SimpleQA</h4>
158
+ <p>Fact-based questions with clear answers</p>
159
+ </div>
160
+ <input type="number" id="simpleqa_count" value="20" min="1" max="500">
161
+ </div>
162
+
163
+ <div class="dataset-option selected" data-dataset="browsecomp">
164
+ <div>
165
+ <h4>BrowseComp</h4>
166
+ <p>Complex browsing and comparison tasks</p>
167
+ </div>
168
+ <input type="number" id="browsecomp_count" value="10" min="1" max="200">
169
+ </div>
170
+ </div>
171
+
172
+ <!-- Start Button -->
173
+ <button type="button" id="start-benchmark" class="btn btn-primary start-button">
174
+ <i class="fas fa-play"></i> Start Benchmark
175
+ </button>
176
+
177
+ <!-- Progress Section -->
178
+ <div class="progress-section" id="progress-section">
179
+ <h3>Benchmark Progress</h3>
180
+
181
+ <div class="progress-bar">
182
+ <div class="progress-fill" id="progress-fill"></div>
183
+ </div>
184
+
185
+ <div class="stats-grid">
186
+ <div class="stat-card">
187
+ <div class="stat-value" id="stat-accuracy">--%</div>
188
+ <div class="stat-label">Accuracy</div>
189
+ </div>
190
+ <div class="stat-card">
191
+ <div class="stat-value" id="stat-completed">0</div>
192
+ <div class="stat-label">Completed</div>
193
+ </div>
194
+ <div class="stat-card">
195
+ <div class="stat-value" id="stat-rate">--</div>
196
+ <div class="stat-label">Per Minute</div>
197
+ </div>
198
+ <div class="stat-card">
199
+ <div class="stat-value" id="stat-remaining">--</div>
200
+ <div class="stat-label">Time Left</div>
201
+ </div>
202
+ </div>
203
+
204
+ <div style="margin-top: 20px; text-align: center;">
205
+ <button type="button" id="cancel-benchmark" class="btn btn-secondary">
206
+ <i class="fas fa-stop"></i> Cancel
207
+ </button>
208
+ </div>
209
+ </div>
210
+ </div>
211
+ </div>
212
+ </div>
213
+
214
+ <script>
215
+ let currentBenchmarkId = null;
216
+ let progressInterval = null;
217
+
218
+ document.addEventListener('DOMContentLoaded', function() {
219
+ loadCurrentConfig();
220
+ setupEventListeners();
221
+ });
222
+
223
+ async function loadCurrentConfig() {
224
+ try {
225
+ // Get current settings from the database
226
+ const response = await fetch('/research/settings/api');
227
+ const data = await response.json();
228
+
229
+ if (data.settings) {
230
+ const config = {
231
+ provider: data.settings['llm.provider']?.value || 'Not configured',
232
+ model: data.settings['llm.model']?.value || 'Not configured',
233
+ search_tool: data.settings['search.tool']?.value || 'searxng',
234
+ iterations: data.settings['search.iterations']?.value || '8',
235
+ questions_per_iteration: data.settings['search.questions_per_iteration']?.value || '5',
236
+ search_strategy: data.settings['search.search_strategy']?.value || 'focused_iteration'
237
+ };
238
+ displayConfig(config);
239
+ }
240
+ } catch (error) {
241
+ console.error('Error loading config:', error);
242
+ // Use fallback display
243
+ displayConfig({
244
+ provider: 'Loading...',
245
+ model: 'Loading...',
246
+ search_tool: 'Loading...',
247
+ iterations: '-'
248
+ });
249
+ }
250
+ }
251
+
252
+ function displayConfig(config) {
253
+ const configDisplay = document.getElementById('config-display');
254
+ configDisplay.innerHTML = `
255
+ <div class="config-item">
256
+ <span class="config-label">LLM Provider</span>
257
+ <span class="config-value">${config.provider || 'Not set'}</span>
258
+ </div>
259
+ <div class="config-item">
260
+ <span class="config-label">Model</span>
261
+ <span class="config-value">${config.model || 'Not set'}</span>
262
+ </div>
263
+ <div class="config-item">
264
+ <span class="config-label">Search Engine</span>
265
+ <span class="config-value">${config.search_tool || 'searxng'}</span>
266
+ </div>
267
+ <div class="config-item">
268
+ <span class="config-label">Search Iterations</span>
269
+ <span class="config-value">${config.iterations || '8'}</span>
270
+ </div>
271
+ `;
272
+ }
273
+
274
+ function setupEventListeners() {
275
+ // Dataset selection
276
+ document.querySelectorAll('.dataset-option').forEach(option => {
277
+ option.addEventListener('click', function(e) {
278
+ if (!e.target.matches('input')) {
279
+ this.classList.toggle('selected');
280
+ }
281
+ });
282
+ });
283
+
284
+ // Start benchmark
285
+ document.getElementById('start-benchmark').addEventListener('click', startBenchmark);
286
+
287
+ // Cancel benchmark
288
+ document.getElementById('cancel-benchmark').addEventListener('click', cancelBenchmark);
289
+ }
290
+
291
+ async function startBenchmark() {
292
+ // Get dataset configuration
293
+ const datasets = {};
294
+ document.querySelectorAll('.dataset-option.selected').forEach(option => {
295
+ const dataset = option.getAttribute('data-dataset');
296
+ const count = parseInt(option.querySelector('input').value) || 0;
297
+ if (count > 0) {
298
+ datasets[dataset] = { count: count };
299
+ }
300
+ });
301
+
302
+ if (Object.keys(datasets).length === 0) {
303
+ showAlert('Please select at least one dataset', 'error');
304
+ return;
305
+ }
306
+
307
+ // Disable start button
308
+ document.getElementById('start-benchmark').disabled = true;
309
+
310
+ try {
311
+ // Get CSRF token
312
+ const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
313
+
314
+ const response = await fetch('/benchmark/api/start-simple', {
315
+ method: 'POST',
316
+ headers: {
317
+ 'Content-Type': 'application/json',
318
+ 'X-CSRFToken': csrfToken
319
+ },
320
+ body: JSON.stringify({ datasets_config: datasets })
321
+ });
322
+
323
+ const data = await response.json();
324
+
325
+ if (data.success) {
326
+ currentBenchmarkId = data.benchmark_run_id;
327
+ showProgress();
328
+ startProgressTracking();
329
+ showAlert('Benchmark started!', 'success');
330
+ } else {
331
+ showAlert('Error: ' + data.error, 'error');
332
+ document.getElementById('start-benchmark').disabled = false;
333
+ }
334
+ } catch (error) {
335
+ console.error('Error starting benchmark:', error);
336
+ showAlert('Failed to start benchmark', 'error');
337
+ document.getElementById('start-benchmark').disabled = false;
338
+ }
339
+ }
340
+
341
+ function showProgress() {
342
+ document.querySelector('.dataset-selection').style.display = 'none';
343
+ document.getElementById('start-benchmark').style.display = 'none';
344
+ document.getElementById('progress-section').style.display = 'block';
345
+ }
346
+
347
+ function hideProgress() {
348
+ document.querySelector('.dataset-selection').style.display = 'block';
349
+ document.getElementById('start-benchmark').style.display = 'block';
350
+ document.getElementById('progress-section').style.display = 'none';
351
+ document.getElementById('start-benchmark').disabled = false;
352
+ }
353
+
354
+ function startProgressTracking() {
355
+ updateProgress(); // Initial update
356
+ progressInterval = setInterval(updateProgress, 2000);
357
+ }
358
+
359
+ async function updateProgress() {
360
+ if (!currentBenchmarkId) return;
361
+
362
+ try {
363
+ const response = await fetch(`/benchmark/api/status/${currentBenchmarkId}`);
364
+ const data = await response.json();
365
+
366
+ if (data.success) {
367
+ const status = data.status;
368
+
369
+ // Update progress bar
370
+ const percentage = status.total_examples > 0 ?
371
+ (status.completed_examples / status.total_examples * 100) : 0;
372
+ document.getElementById('progress-fill').style.width = percentage + '%';
373
+
374
+ // Update stats
375
+ document.getElementById('stat-accuracy').textContent =
376
+ status.overall_accuracy ? status.overall_accuracy.toFixed(1) + '%' : '--%';
377
+ document.getElementById('stat-completed').textContent =
378
+ `${status.completed_examples}/${status.total_examples}`;
379
+ document.getElementById('stat-rate').textContent =
380
+ status.processing_rate ? status.processing_rate.toFixed(1) : '--';
381
+
382
+ // Estimate remaining time
383
+ if (status.processing_rate > 0 && status.completed_examples < status.total_examples) {
384
+ const remaining = status.total_examples - status.completed_examples;
385
+ const minutes = Math.ceil(remaining / status.processing_rate);
386
+ document.getElementById('stat-remaining').textContent = `${minutes}m`;
387
+ } else {
388
+ document.getElementById('stat-remaining').textContent = '--';
389
+ }
390
+
391
+ // Check if completed
392
+ if (status.status === 'completed' || status.status === 'failed' || status.status === 'cancelled') {
393
+ clearInterval(progressInterval);
394
+ progressInterval = null;
395
+
396
+ if (status.status === 'completed') {
397
+ showAlert(`Benchmark completed! Final accuracy: ${status.overall_accuracy.toFixed(1)}%`, 'success');
398
+ } else {
399
+ showAlert(`Benchmark ${status.status}`, 'error');
400
+ }
401
+
402
+ setTimeout(() => {
403
+ hideProgress();
404
+ currentBenchmarkId = null;
405
+ }, 3000);
406
+ }
407
+ }
408
+ } catch (error) {
409
+ console.error('Error updating progress:', error);
410
+ }
411
+ }
412
+
413
+ async function cancelBenchmark() {
414
+ if (!currentBenchmarkId) return;
415
+
416
+ try {
417
+ const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
418
+ const response = await fetch(`/benchmark/api/cancel/${currentBenchmarkId}`, {
419
+ method: 'POST',
420
+ headers: {
421
+ 'X-CSRFToken': csrfToken
422
+ }
423
+ });
424
+
425
+ const data = await response.json();
426
+ if (data.success) {
427
+ showAlert('Benchmark cancelled', 'info');
428
+ }
429
+ } catch (error) {
430
+ console.error('Error cancelling benchmark:', error);
431
+ }
432
+ }
433
+
434
+ function showAlert(message, type) {
435
+ const alertContainer = document.getElementById('benchmark-alert');
436
+ alertContainer.innerHTML = `
437
+ <div class="settings-alert alert-${type}">
438
+ <span>${message}</span>
439
+ <button type="button" class="close-alert" onclick="this.parentElement.parentElement.style.display='none'">
440
+ <i class="fas fa-times"></i>
441
+ </button>
442
+ </div>
443
+ `;
444
+ alertContainer.style.display = 'block';
445
+
446
+ if (type === 'success') {
447
+ setTimeout(() => {
448
+ alertContainer.style.display = 'none';
449
+ }, 5000);
450
+ }
451
+ }
452
+ </script>
453
+ {% endblock %}
@@ -1094,7 +1094,7 @@
1094
1094
  div.innerHTML = `
1095
1095
  <div class="cost-item-info">
1096
1096
  <div class="cost-item-name">
1097
- <a href="/research/results/${item.research_id}" class="research-link">
1097
+ <a href="/results/${item.research_id}" class="research-link">
1098
1098
  Research Session #${item.research_id}
1099
1099
  </a>
1100
1100
  </div>