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.
- local_deep_research/__version__.py +1 -1
- local_deep_research/advanced_search_system/candidate_exploration/progressive_explorer.py +11 -1
- local_deep_research/advanced_search_system/questions/browsecomp_question.py +32 -6
- local_deep_research/advanced_search_system/strategies/focused_iteration_strategy.py +32 -8
- local_deep_research/advanced_search_system/strategies/source_based_strategy.py +2 -0
- local_deep_research/api/__init__.py +2 -0
- local_deep_research/api/research_functions.py +177 -3
- local_deep_research/benchmarks/graders.py +150 -5
- local_deep_research/benchmarks/models/__init__.py +19 -0
- local_deep_research/benchmarks/models/benchmark_models.py +283 -0
- local_deep_research/benchmarks/ui/__init__.py +1 -0
- local_deep_research/benchmarks/web_api/__init__.py +6 -0
- local_deep_research/benchmarks/web_api/benchmark_routes.py +862 -0
- local_deep_research/benchmarks/web_api/benchmark_service.py +920 -0
- local_deep_research/config/llm_config.py +106 -21
- local_deep_research/defaults/default_settings.json +447 -2
- local_deep_research/error_handling/report_generator.py +10 -0
- local_deep_research/llm/__init__.py +19 -0
- local_deep_research/llm/llm_registry.py +155 -0
- local_deep_research/metrics/db_models.py +3 -7
- local_deep_research/metrics/search_tracker.py +25 -11
- local_deep_research/search_system.py +12 -9
- local_deep_research/utilities/log_utils.py +23 -10
- local_deep_research/utilities/thread_context.py +99 -0
- local_deep_research/web/app_factory.py +32 -8
- local_deep_research/web/database/benchmark_schema.py +230 -0
- local_deep_research/web/database/convert_research_id_to_string.py +161 -0
- local_deep_research/web/database/models.py +55 -1
- local_deep_research/web/database/schema_upgrade.py +397 -2
- local_deep_research/web/database/uuid_migration.py +265 -0
- local_deep_research/web/routes/api_routes.py +62 -31
- local_deep_research/web/routes/history_routes.py +13 -6
- local_deep_research/web/routes/metrics_routes.py +264 -4
- local_deep_research/web/routes/research_routes.py +45 -18
- local_deep_research/web/routes/route_registry.py +352 -0
- local_deep_research/web/routes/settings_routes.py +382 -22
- local_deep_research/web/services/research_service.py +22 -29
- local_deep_research/web/services/settings_manager.py +53 -0
- local_deep_research/web/services/settings_service.py +2 -0
- local_deep_research/web/static/css/styles.css +8 -0
- local_deep_research/web/static/js/components/detail.js +7 -14
- local_deep_research/web/static/js/components/details.js +8 -10
- local_deep_research/web/static/js/components/fallback/ui.js +4 -4
- local_deep_research/web/static/js/components/history.js +6 -6
- local_deep_research/web/static/js/components/logpanel.js +14 -11
- local_deep_research/web/static/js/components/progress.js +51 -46
- local_deep_research/web/static/js/components/research.js +250 -89
- local_deep_research/web/static/js/components/results.js +5 -7
- local_deep_research/web/static/js/components/settings.js +32 -26
- local_deep_research/web/static/js/components/settings_sync.js +24 -23
- local_deep_research/web/static/js/config/urls.js +285 -0
- local_deep_research/web/static/js/main.js +8 -8
- local_deep_research/web/static/js/research_form.js +267 -12
- local_deep_research/web/static/js/services/api.js +18 -18
- local_deep_research/web/static/js/services/keyboard.js +8 -8
- local_deep_research/web/static/js/services/socket.js +53 -35
- local_deep_research/web/static/js/services/ui.js +1 -1
- local_deep_research/web/templates/base.html +4 -1
- local_deep_research/web/templates/components/custom_dropdown.html +5 -3
- local_deep_research/web/templates/components/mobile_nav.html +3 -3
- local_deep_research/web/templates/components/sidebar.html +9 -3
- local_deep_research/web/templates/pages/benchmark.html +2697 -0
- local_deep_research/web/templates/pages/benchmark_results.html +1274 -0
- local_deep_research/web/templates/pages/benchmark_simple.html +453 -0
- local_deep_research/web/templates/pages/cost_analytics.html +1 -1
- local_deep_research/web/templates/pages/metrics.html +212 -39
- local_deep_research/web/templates/pages/research.html +8 -6
- local_deep_research/web/templates/pages/star_reviews.html +1 -1
- local_deep_research/web_search_engines/engines/search_engine_arxiv.py +14 -1
- local_deep_research/web_search_engines/engines/search_engine_brave.py +15 -1
- local_deep_research/web_search_engines/engines/search_engine_ddg.py +20 -1
- local_deep_research/web_search_engines/engines/search_engine_google_pse.py +26 -2
- local_deep_research/web_search_engines/engines/search_engine_pubmed.py +15 -1
- local_deep_research/web_search_engines/engines/search_engine_retriever.py +192 -0
- local_deep_research/web_search_engines/engines/search_engine_tavily.py +307 -0
- local_deep_research/web_search_engines/rate_limiting/__init__.py +14 -0
- local_deep_research/web_search_engines/rate_limiting/__main__.py +9 -0
- local_deep_research/web_search_engines/rate_limiting/cli.py +209 -0
- local_deep_research/web_search_engines/rate_limiting/exceptions.py +21 -0
- local_deep_research/web_search_engines/rate_limiting/tracker.py +506 -0
- local_deep_research/web_search_engines/retriever_registry.py +108 -0
- local_deep_research/web_search_engines/search_engine_base.py +161 -43
- local_deep_research/web_search_engines/search_engine_factory.py +14 -0
- local_deep_research/web_search_engines/search_engines_config.py +20 -0
- local_deep_research-0.6.1.dist-info/METADATA +374 -0
- {local_deep_research-0.5.9.dist-info → local_deep_research-0.6.1.dist-info}/RECORD +89 -64
- local_deep_research-0.5.9.dist-info/METADATA +0 -420
- {local_deep_research-0.5.9.dist-info → local_deep_research-0.6.1.dist-info}/WHEEL +0 -0
- {local_deep_research-0.5.9.dist-info → local_deep_research-0.6.1.dist-info}/entry_points.txt +0 -0
- {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
|