local-deep-research 0.5.9__py3-none-any.whl → 0.6.1__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 (90) 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 +32 -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 +447 -2
  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/search_system.py +12 -9
  23. local_deep_research/utilities/log_utils.py +23 -10
  24. local_deep_research/utilities/thread_context.py +99 -0
  25. local_deep_research/web/app_factory.py +32 -8
  26. local_deep_research/web/database/benchmark_schema.py +230 -0
  27. local_deep_research/web/database/convert_research_id_to_string.py +161 -0
  28. local_deep_research/web/database/models.py +55 -1
  29. local_deep_research/web/database/schema_upgrade.py +397 -2
  30. local_deep_research/web/database/uuid_migration.py +265 -0
  31. local_deep_research/web/routes/api_routes.py +62 -31
  32. local_deep_research/web/routes/history_routes.py +13 -6
  33. local_deep_research/web/routes/metrics_routes.py +264 -4
  34. local_deep_research/web/routes/research_routes.py +45 -18
  35. local_deep_research/web/routes/route_registry.py +352 -0
  36. local_deep_research/web/routes/settings_routes.py +382 -22
  37. local_deep_research/web/services/research_service.py +22 -29
  38. local_deep_research/web/services/settings_manager.py +53 -0
  39. local_deep_research/web/services/settings_service.py +2 -0
  40. local_deep_research/web/static/css/styles.css +8 -0
  41. local_deep_research/web/static/js/components/detail.js +7 -14
  42. local_deep_research/web/static/js/components/details.js +8 -10
  43. local_deep_research/web/static/js/components/fallback/ui.js +4 -4
  44. local_deep_research/web/static/js/components/history.js +6 -6
  45. local_deep_research/web/static/js/components/logpanel.js +14 -11
  46. local_deep_research/web/static/js/components/progress.js +51 -46
  47. local_deep_research/web/static/js/components/research.js +250 -89
  48. local_deep_research/web/static/js/components/results.js +5 -7
  49. local_deep_research/web/static/js/components/settings.js +32 -26
  50. local_deep_research/web/static/js/components/settings_sync.js +24 -23
  51. local_deep_research/web/static/js/config/urls.js +285 -0
  52. local_deep_research/web/static/js/main.js +8 -8
  53. local_deep_research/web/static/js/research_form.js +267 -12
  54. local_deep_research/web/static/js/services/api.js +18 -18
  55. local_deep_research/web/static/js/services/keyboard.js +8 -8
  56. local_deep_research/web/static/js/services/socket.js +53 -35
  57. local_deep_research/web/static/js/services/ui.js +1 -1
  58. local_deep_research/web/templates/base.html +4 -1
  59. local_deep_research/web/templates/components/custom_dropdown.html +5 -3
  60. local_deep_research/web/templates/components/mobile_nav.html +3 -3
  61. local_deep_research/web/templates/components/sidebar.html +9 -3
  62. local_deep_research/web/templates/pages/benchmark.html +2697 -0
  63. local_deep_research/web/templates/pages/benchmark_results.html +1274 -0
  64. local_deep_research/web/templates/pages/benchmark_simple.html +453 -0
  65. local_deep_research/web/templates/pages/cost_analytics.html +1 -1
  66. local_deep_research/web/templates/pages/metrics.html +212 -39
  67. local_deep_research/web/templates/pages/research.html +8 -6
  68. local_deep_research/web/templates/pages/star_reviews.html +1 -1
  69. local_deep_research/web_search_engines/engines/search_engine_arxiv.py +14 -1
  70. local_deep_research/web_search_engines/engines/search_engine_brave.py +15 -1
  71. local_deep_research/web_search_engines/engines/search_engine_ddg.py +20 -1
  72. local_deep_research/web_search_engines/engines/search_engine_google_pse.py +26 -2
  73. local_deep_research/web_search_engines/engines/search_engine_pubmed.py +15 -1
  74. local_deep_research/web_search_engines/engines/search_engine_retriever.py +192 -0
  75. local_deep_research/web_search_engines/engines/search_engine_tavily.py +307 -0
  76. local_deep_research/web_search_engines/rate_limiting/__init__.py +14 -0
  77. local_deep_research/web_search_engines/rate_limiting/__main__.py +9 -0
  78. local_deep_research/web_search_engines/rate_limiting/cli.py +209 -0
  79. local_deep_research/web_search_engines/rate_limiting/exceptions.py +21 -0
  80. local_deep_research/web_search_engines/rate_limiting/tracker.py +506 -0
  81. local_deep_research/web_search_engines/retriever_registry.py +108 -0
  82. local_deep_research/web_search_engines/search_engine_base.py +161 -43
  83. local_deep_research/web_search_engines/search_engine_factory.py +14 -0
  84. local_deep_research/web_search_engines/search_engines_config.py +20 -0
  85. local_deep_research-0.6.1.dist-info/METADATA +374 -0
  86. {local_deep_research-0.5.9.dist-info → local_deep_research-0.6.1.dist-info}/RECORD +89 -64
  87. local_deep_research-0.5.9.dist-info/METADATA +0 -420
  88. {local_deep_research-0.5.9.dist-info → local_deep_research-0.6.1.dist-info}/WHEEL +0 -0
  89. {local_deep_research-0.5.9.dist-info → local_deep_research-0.6.1.dist-info}/entry_points.txt +0 -0
  90. {local_deep_research-0.5.9.dist-info → local_deep_research-0.6.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,209 @@
1
+ """
2
+ Command-line interface for rate limiting monitoring and management.
3
+ """
4
+
5
+ import argparse
6
+ import sys
7
+ from datetime import datetime
8
+
9
+ from .tracker import get_tracker
10
+
11
+
12
+ def format_stats_table(stats: list) -> str:
13
+ """Format rate limit statistics as a table."""
14
+ if not stats:
15
+ return "No rate limit data available."
16
+
17
+ # Header
18
+ lines = []
19
+ lines.append("Rate Limit Statistics:")
20
+ lines.append("-" * 80)
21
+ lines.append(
22
+ f"{'Engine':<20} {'Base Wait':<12} {'Range':<20} {'Success':<10} {'Attempts':<10} {'Updated':<15}"
23
+ )
24
+ lines.append("-" * 80)
25
+
26
+ # Data rows
27
+ for row in stats:
28
+ (
29
+ engine_type,
30
+ base_wait,
31
+ min_wait,
32
+ max_wait,
33
+ last_updated,
34
+ attempts,
35
+ success_rate,
36
+ ) = row
37
+
38
+ # Format time
39
+ updated_time = datetime.fromtimestamp(last_updated).strftime(
40
+ "%m-%d %H:%M"
41
+ )
42
+
43
+ # Format range
44
+ range_str = f"{min_wait:.1f}s - {max_wait:.1f}s"
45
+
46
+ lines.append(
47
+ f"{engine_type:<20} {base_wait:<12.2f} {range_str:<20} "
48
+ f"{success_rate:<10.1%} {attempts:<10} {updated_time:<15}"
49
+ )
50
+
51
+ return "\n".join(lines)
52
+
53
+
54
+ def cmd_status(args):
55
+ """Show current rate limit status."""
56
+ tracker = get_tracker()
57
+
58
+ if args.engine:
59
+ stats = tracker.get_stats(args.engine)
60
+ if not stats:
61
+ print(f"No rate limit data found for engine: {args.engine}")
62
+ return
63
+ else:
64
+ stats = tracker.get_stats()
65
+
66
+ print(format_stats_table(stats))
67
+
68
+
69
+ def cmd_reset(args):
70
+ """Reset rate limit data for an engine."""
71
+ tracker = get_tracker()
72
+
73
+ if args.engine:
74
+ tracker.reset_engine(args.engine)
75
+ print(f"Reset rate limit data for {args.engine}")
76
+ else:
77
+ print("Error: --engine parameter is required for reset command")
78
+ sys.exit(1)
79
+
80
+
81
+ def cmd_cleanup(args):
82
+ """Clean up old rate limit data."""
83
+ tracker = get_tracker()
84
+ tracker.cleanup_old_data(days=args.days)
85
+ print(f"Cleaned up rate limit data older than {args.days} days")
86
+
87
+
88
+ def cmd_export(args):
89
+ """Export rate limit data."""
90
+ tracker = get_tracker()
91
+
92
+ # Get all stats
93
+ stats = tracker.get_stats()
94
+
95
+ if args.format == "csv":
96
+ print(
97
+ "engine_type,base_wait_seconds,min_wait_seconds,max_wait_seconds,last_updated,total_attempts,success_rate"
98
+ )
99
+ for row in stats:
100
+ print(",".join(map(str, row)))
101
+ elif args.format == "json":
102
+ import json
103
+
104
+ data = []
105
+ for row in stats:
106
+ (
107
+ engine_type,
108
+ base_wait,
109
+ min_wait,
110
+ max_wait,
111
+ last_updated,
112
+ attempts,
113
+ success_rate,
114
+ ) = row
115
+ data.append(
116
+ {
117
+ "engine_type": engine_type,
118
+ "base_wait_seconds": base_wait,
119
+ "min_wait_seconds": min_wait,
120
+ "max_wait_seconds": max_wait,
121
+ "last_updated": last_updated,
122
+ "total_attempts": attempts,
123
+ "success_rate": success_rate,
124
+ }
125
+ )
126
+ print(json.dumps(data, indent=2))
127
+ else:
128
+ print(format_stats_table(stats))
129
+
130
+
131
+ def main():
132
+ """Main CLI entry point."""
133
+ parser = argparse.ArgumentParser(
134
+ description="Rate limiting monitoring and management",
135
+ formatter_class=argparse.RawDescriptionHelpFormatter,
136
+ epilog="""
137
+ Examples:
138
+ # Show all engine statistics
139
+ python -m local_deep_research.web_search_engines.rate_limiting.cli status
140
+
141
+ # Show specific engine statistics
142
+ python -m local_deep_research.web_search_engines.rate_limiting.cli status --engine DuckDuckGoSearchEngine
143
+
144
+ # Reset rate limit data for an engine
145
+ python -m local_deep_research.web_search_engines.rate_limiting.cli reset --engine SearXNGSearchEngine
146
+
147
+ # Export data as CSV
148
+ python -m local_deep_research.web_search_engines.rate_limiting.cli export --format csv
149
+
150
+ # Clean up old data
151
+ python -m local_deep_research.web_search_engines.rate_limiting.cli cleanup --days 30
152
+ """,
153
+ )
154
+
155
+ subparsers = parser.add_subparsers(
156
+ dest="command", help="Available commands"
157
+ )
158
+
159
+ # Status command
160
+ status_parser = subparsers.add_parser(
161
+ "status", help="Show rate limit statistics"
162
+ )
163
+ status_parser.add_argument(
164
+ "--engine", help="Show stats for specific engine"
165
+ )
166
+ status_parser.set_defaults(func=cmd_status)
167
+
168
+ # Reset command
169
+ reset_parser = subparsers.add_parser("reset", help="Reset rate limit data")
170
+ reset_parser.add_argument("--engine", required=True, help="Engine to reset")
171
+ reset_parser.set_defaults(func=cmd_reset)
172
+
173
+ # Export command
174
+ export_parser = subparsers.add_parser(
175
+ "export", help="Export rate limit data"
176
+ )
177
+ export_parser.add_argument(
178
+ "--format",
179
+ choices=["table", "csv", "json"],
180
+ default="table",
181
+ help="Output format",
182
+ )
183
+ export_parser.set_defaults(func=cmd_export)
184
+
185
+ # Cleanup command
186
+ cleanup_parser = subparsers.add_parser("cleanup", help="Clean up old data")
187
+ cleanup_parser.add_argument(
188
+ "--days",
189
+ type=int,
190
+ default=30,
191
+ help="Remove data older than this many days",
192
+ )
193
+ cleanup_parser.set_defaults(func=cmd_cleanup)
194
+
195
+ args = parser.parse_args()
196
+
197
+ if not args.command:
198
+ parser.print_help()
199
+ sys.exit(1)
200
+
201
+ try:
202
+ args.func(args)
203
+ except Exception as e:
204
+ print(f"Error: {e}")
205
+ sys.exit(1)
206
+
207
+
208
+ if __name__ == "__main__":
209
+ main()
@@ -0,0 +1,21 @@
1
+ """
2
+ Rate limiting specific exceptions for search engines.
3
+ """
4
+
5
+
6
+ class RateLimitError(Exception):
7
+ """Raised when a search engine hits rate limits."""
8
+
9
+ pass
10
+
11
+
12
+ class AdaptiveRetryError(Exception):
13
+ """Raised when adaptive retry fails after all attempts."""
14
+
15
+ pass
16
+
17
+
18
+ class RateLimitConfigError(Exception):
19
+ """Raised when there's an issue with rate limit configuration."""
20
+
21
+ pass