local-deep-research 0.1.26__py3-none-any.whl → 0.2.2__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/__init__.py +23 -22
- local_deep_research/__main__.py +16 -0
- local_deep_research/advanced_search_system/__init__.py +7 -0
- local_deep_research/advanced_search_system/filters/__init__.py +8 -0
- local_deep_research/advanced_search_system/filters/base_filter.py +38 -0
- local_deep_research/advanced_search_system/filters/cross_engine_filter.py +200 -0
- local_deep_research/advanced_search_system/findings/base_findings.py +81 -0
- local_deep_research/advanced_search_system/findings/repository.py +452 -0
- local_deep_research/advanced_search_system/knowledge/__init__.py +1 -0
- local_deep_research/advanced_search_system/knowledge/base_knowledge.py +151 -0
- local_deep_research/advanced_search_system/knowledge/standard_knowledge.py +159 -0
- local_deep_research/advanced_search_system/questions/__init__.py +1 -0
- local_deep_research/advanced_search_system/questions/base_question.py +64 -0
- local_deep_research/advanced_search_system/questions/decomposition_question.py +445 -0
- local_deep_research/advanced_search_system/questions/standard_question.py +119 -0
- local_deep_research/advanced_search_system/repositories/__init__.py +7 -0
- local_deep_research/advanced_search_system/strategies/__init__.py +1 -0
- local_deep_research/advanced_search_system/strategies/base_strategy.py +118 -0
- local_deep_research/advanced_search_system/strategies/iterdrag_strategy.py +450 -0
- local_deep_research/advanced_search_system/strategies/parallel_search_strategy.py +312 -0
- local_deep_research/advanced_search_system/strategies/rapid_search_strategy.py +270 -0
- local_deep_research/advanced_search_system/strategies/standard_strategy.py +300 -0
- local_deep_research/advanced_search_system/tools/__init__.py +1 -0
- local_deep_research/advanced_search_system/tools/base_tool.py +100 -0
- local_deep_research/advanced_search_system/tools/knowledge_tools/__init__.py +1 -0
- local_deep_research/advanced_search_system/tools/question_tools/__init__.py +1 -0
- local_deep_research/advanced_search_system/tools/search_tools/__init__.py +1 -0
- local_deep_research/api/__init__.py +5 -5
- local_deep_research/api/research_functions.py +154 -160
- local_deep_research/app.py +8 -0
- local_deep_research/citation_handler.py +25 -16
- local_deep_research/{config.py → config/config_files.py} +102 -110
- local_deep_research/config/llm_config.py +472 -0
- local_deep_research/config/search_config.py +77 -0
- local_deep_research/defaults/__init__.py +10 -5
- local_deep_research/defaults/main.toml +2 -2
- local_deep_research/defaults/search_engines.toml +60 -34
- local_deep_research/main.py +121 -19
- local_deep_research/migrate_db.py +147 -0
- local_deep_research/report_generator.py +87 -45
- local_deep_research/search_system.py +153 -283
- local_deep_research/setup_data_dir.py +35 -0
- local_deep_research/test_migration.py +178 -0
- local_deep_research/utilities/__init__.py +0 -0
- local_deep_research/utilities/db_utils.py +49 -0
- local_deep_research/{utilties → utilities}/enums.py +2 -2
- local_deep_research/{utilties → utilities}/llm_utils.py +63 -29
- local_deep_research/utilities/search_utilities.py +242 -0
- local_deep_research/{utilties → utilities}/setup_utils.py +4 -2
- local_deep_research/web/__init__.py +0 -1
- local_deep_research/web/app.py +86 -1709
- local_deep_research/web/app_factory.py +289 -0
- local_deep_research/web/database/README.md +70 -0
- local_deep_research/web/database/migrate_to_ldr_db.py +289 -0
- local_deep_research/web/database/migrations.py +447 -0
- local_deep_research/web/database/models.py +117 -0
- local_deep_research/web/database/schema_upgrade.py +107 -0
- local_deep_research/web/models/database.py +294 -0
- local_deep_research/web/models/settings.py +94 -0
- local_deep_research/web/routes/api_routes.py +559 -0
- local_deep_research/web/routes/history_routes.py +354 -0
- local_deep_research/web/routes/research_routes.py +715 -0
- local_deep_research/web/routes/settings_routes.py +1583 -0
- local_deep_research/web/services/research_service.py +947 -0
- local_deep_research/web/services/resource_service.py +149 -0
- local_deep_research/web/services/settings_manager.py +669 -0
- local_deep_research/web/services/settings_service.py +187 -0
- local_deep_research/web/services/socket_service.py +210 -0
- local_deep_research/web/static/css/custom_dropdown.css +277 -0
- local_deep_research/web/static/css/settings.css +1223 -0
- local_deep_research/web/static/css/styles.css +525 -48
- local_deep_research/web/static/js/components/custom_dropdown.js +428 -0
- local_deep_research/web/static/js/components/detail.js +348 -0
- local_deep_research/web/static/js/components/fallback/formatting.js +122 -0
- local_deep_research/web/static/js/components/fallback/ui.js +215 -0
- local_deep_research/web/static/js/components/history.js +487 -0
- local_deep_research/web/static/js/components/logpanel.js +949 -0
- local_deep_research/web/static/js/components/progress.js +1107 -0
- local_deep_research/web/static/js/components/research.js +1865 -0
- local_deep_research/web/static/js/components/results.js +766 -0
- local_deep_research/web/static/js/components/settings.js +3981 -0
- local_deep_research/web/static/js/components/settings_sync.js +106 -0
- local_deep_research/web/static/js/main.js +226 -0
- local_deep_research/web/static/js/services/api.js +253 -0
- local_deep_research/web/static/js/services/audio.js +31 -0
- local_deep_research/web/static/js/services/formatting.js +119 -0
- local_deep_research/web/static/js/services/pdf.js +622 -0
- local_deep_research/web/static/js/services/socket.js +882 -0
- local_deep_research/web/static/js/services/ui.js +546 -0
- local_deep_research/web/templates/base.html +72 -0
- local_deep_research/web/templates/components/custom_dropdown.html +47 -0
- local_deep_research/web/templates/components/log_panel.html +32 -0
- local_deep_research/web/templates/components/mobile_nav.html +22 -0
- local_deep_research/web/templates/components/settings_form.html +299 -0
- local_deep_research/web/templates/components/sidebar.html +21 -0
- local_deep_research/web/templates/pages/details.html +73 -0
- local_deep_research/web/templates/pages/history.html +51 -0
- local_deep_research/web/templates/pages/progress.html +57 -0
- local_deep_research/web/templates/pages/research.html +139 -0
- local_deep_research/web/templates/pages/results.html +59 -0
- local_deep_research/web/templates/settings_dashboard.html +78 -192
- local_deep_research/web/utils/__init__.py +0 -0
- local_deep_research/web/utils/formatters.py +76 -0
- local_deep_research/web_search_engines/engines/full_search.py +18 -16
- local_deep_research/web_search_engines/engines/meta_search_engine.py +182 -131
- local_deep_research/web_search_engines/engines/search_engine_arxiv.py +224 -139
- local_deep_research/web_search_engines/engines/search_engine_brave.py +88 -71
- local_deep_research/web_search_engines/engines/search_engine_ddg.py +48 -39
- local_deep_research/web_search_engines/engines/search_engine_github.py +415 -204
- local_deep_research/web_search_engines/engines/search_engine_google_pse.py +123 -90
- local_deep_research/web_search_engines/engines/search_engine_guardian.py +210 -157
- local_deep_research/web_search_engines/engines/search_engine_local.py +532 -369
- local_deep_research/web_search_engines/engines/search_engine_local_all.py +42 -36
- local_deep_research/web_search_engines/engines/search_engine_pubmed.py +358 -266
- local_deep_research/web_search_engines/engines/search_engine_searxng.py +212 -160
- local_deep_research/web_search_engines/engines/search_engine_semantic_scholar.py +213 -170
- local_deep_research/web_search_engines/engines/search_engine_serpapi.py +84 -68
- local_deep_research/web_search_engines/engines/search_engine_wayback.py +186 -154
- local_deep_research/web_search_engines/engines/search_engine_wikipedia.py +115 -77
- local_deep_research/web_search_engines/search_engine_base.py +174 -99
- local_deep_research/web_search_engines/search_engine_factory.py +192 -102
- local_deep_research/web_search_engines/search_engines_config.py +22 -15
- {local_deep_research-0.1.26.dist-info → local_deep_research-0.2.2.dist-info}/METADATA +177 -97
- local_deep_research-0.2.2.dist-info/RECORD +135 -0
- {local_deep_research-0.1.26.dist-info → local_deep_research-0.2.2.dist-info}/WHEEL +1 -2
- {local_deep_research-0.1.26.dist-info → local_deep_research-0.2.2.dist-info}/entry_points.txt +3 -0
- local_deep_research/defaults/llm_config.py +0 -338
- local_deep_research/utilties/search_utilities.py +0 -114
- local_deep_research/web/static/js/app.js +0 -3763
- local_deep_research/web/templates/api_keys_config.html +0 -82
- local_deep_research/web/templates/collections_config.html +0 -90
- local_deep_research/web/templates/index.html +0 -348
- local_deep_research/web/templates/llm_config.html +0 -120
- local_deep_research/web/templates/main_config.html +0 -89
- local_deep_research/web/templates/search_engines_config.html +0 -154
- local_deep_research/web/templates/settings.html +0 -519
- local_deep_research-0.1.26.dist-info/RECORD +0 -61
- local_deep_research-0.1.26.dist-info/top_level.txt +0 -1
- /local_deep_research/{utilties → config}/__init__.py +0 -0
- {local_deep_research-0.1.26.dist-info → local_deep_research-0.2.2.dist-info}/licenses/LICENSE +0 -0
@@ -2,12 +2,12 @@
|
|
2
2
|
# This file defines all available search engines and their properties
|
3
3
|
|
4
4
|
[wikipedia]
|
5
|
-
module_path = "
|
5
|
+
module_path = ".engines.search_engine_wikipedia"
|
6
6
|
class_name = "WikipediaSearchEngine"
|
7
7
|
requires_api_key = false
|
8
8
|
reliability = 0.95
|
9
9
|
strengths = [
|
10
|
-
"factual information", "general knowledge", "definitions",
|
10
|
+
"factual information", "general knowledge", "definitions",
|
11
11
|
"historical facts", "biographies", "overview information"
|
12
12
|
]
|
13
13
|
weaknesses = ["recent events", "specialized academic topics", "product comparisons"]
|
@@ -17,12 +17,12 @@ max_results = 20
|
|
17
17
|
include_content = true
|
18
18
|
|
19
19
|
[arxiv]
|
20
|
-
module_path = "
|
20
|
+
module_path = ".engines.search_engine_arxiv"
|
21
21
|
class_name = "ArXivSearchEngine"
|
22
22
|
requires_api_key = false
|
23
23
|
reliability = 0.9
|
24
24
|
strengths = [
|
25
|
-
"scientific papers", "academic research", "physics", "computer science",
|
25
|
+
"scientific papers", "academic research", "physics", "computer science",
|
26
26
|
"mathematics", "statistics", "machine learning", "preprints"
|
27
27
|
]
|
28
28
|
weaknesses = ["non-academic topics", "consumer products", "news", "general information"]
|
@@ -33,17 +33,17 @@ sort_by = "relevance"
|
|
33
33
|
sort_order = "descending"
|
34
34
|
|
35
35
|
[pubmed]
|
36
|
-
module_path = "
|
36
|
+
module_path = ".engines.search_engine_pubmed"
|
37
37
|
class_name = "PubMedSearchEngine"
|
38
38
|
requires_api_key = false
|
39
39
|
api_key_env = "NCBI_API_KEY"
|
40
40
|
reliability = 0.98
|
41
41
|
strengths = [
|
42
|
-
"biomedical literature", "medical research", "clinical studies",
|
42
|
+
"biomedical literature", "medical research", "clinical studies",
|
43
43
|
"life sciences", "health information", "scientific papers"
|
44
44
|
]
|
45
45
|
weaknesses = [
|
46
|
-
"non-medical topics", "very recent papers may be missing",
|
46
|
+
"non-medical topics", "very recent papers may be missing",
|
47
47
|
"limited to published research"
|
48
48
|
]
|
49
49
|
requires_llm = true
|
@@ -57,12 +57,12 @@ days_limit = 0
|
|
57
57
|
optimize_queries = true
|
58
58
|
|
59
59
|
[github]
|
60
|
-
module_path = "
|
60
|
+
module_path = ".engines.search_engine_github"
|
61
61
|
class_name = "GitHubSearchEngine"
|
62
62
|
requires_api_key = false
|
63
63
|
reliability = 0.99
|
64
64
|
strengths = [
|
65
|
-
"code repositories", "software documentation", "open source projects",
|
65
|
+
"code repositories", "software documentation", "open source projects",
|
66
66
|
"programming issues", "developer information", "technical documentation"
|
67
67
|
]
|
68
68
|
weaknesses = ["non-technical content", "content outside GitHub", "rate limits without API key"]
|
@@ -75,13 +75,13 @@ include_readme = true
|
|
75
75
|
include_issues = false
|
76
76
|
|
77
77
|
[serpapi]
|
78
|
-
module_path = "
|
78
|
+
module_path = ".engines.search_engine_serpapi"
|
79
79
|
class_name = "SerpAPISearchEngine"
|
80
80
|
requires_api_key = true
|
81
81
|
api_key_env = "SERP_API_KEY"
|
82
82
|
reliability = 0.6
|
83
83
|
strengths = [
|
84
|
-
"comprehensive web search", "product information", "reviews",
|
84
|
+
"comprehensive web search", "product information", "reviews",
|
85
85
|
"recent content", "news", "broad coverage"
|
86
86
|
]
|
87
87
|
weaknesses = ["requires API key with usage limits", "not specialized for academic content"]
|
@@ -95,23 +95,49 @@ time_period = "y"
|
|
95
95
|
safe_search = true
|
96
96
|
search_language = "English"
|
97
97
|
|
98
|
+
[searxng]
|
99
|
+
module_path = ".engines.search_engine_searxng"
|
100
|
+
class_name = "SearXNGSearchEngine"
|
101
|
+
requires_api_key = false
|
102
|
+
api_key_env = "SEARXNG_INSTANCE"
|
103
|
+
reliability = 0.9
|
104
|
+
strengths = [
|
105
|
+
"privacy-focused", "metasearch engine", "self-hosted",
|
106
|
+
"no tracking", "configurable", "multiple engines in one"
|
107
|
+
]
|
108
|
+
weaknesses = [
|
109
|
+
"requires self-hosting", "depends on other search engines",
|
110
|
+
"may be rate limited by underlying engines"
|
111
|
+
]
|
112
|
+
supports_full_search = true
|
113
|
+
full_search_module = ".engines.full_search"
|
114
|
+
full_search_class = "FullSearchResults"
|
115
|
+
|
116
|
+
[searxng.default_params]
|
117
|
+
max_results = 15
|
118
|
+
categories = ["general"]
|
119
|
+
language = "en"
|
120
|
+
safe_search = 1
|
121
|
+
delay_between_requests = 0.0
|
122
|
+
include_full_content = true
|
123
|
+
|
98
124
|
[google_pse]
|
99
|
-
module_path = "
|
125
|
+
module_path = ".engines.search_engine_google_pse"
|
100
126
|
class_name = "GooglePSESearchEngine"
|
101
127
|
requires_api_key = true
|
102
128
|
api_key_env = "GOOGLE_PSE_API_KEY"
|
103
129
|
reliability = 0.9
|
104
130
|
strengths = [
|
105
|
-
"custom search scope", "high-quality results", "domain-specific search",
|
131
|
+
"custom search scope", "high-quality results", "domain-specific search",
|
106
132
|
"configurable search experience", "control over search index"
|
107
133
|
]
|
108
134
|
weaknesses = [
|
109
|
-
"requires API key with usage limits",
|
135
|
+
"requires API key with usage limits",
|
110
136
|
"limited to 10,000 queries/day on free tier",
|
111
137
|
"requires search engine configuration in Google Control Panel"
|
112
138
|
]
|
113
139
|
supports_full_search = true
|
114
|
-
full_search_module = "
|
140
|
+
full_search_module = ".engines.full_search"
|
115
141
|
full_search_class = "FullSearchResults"
|
116
142
|
|
117
143
|
[google_pse.default_params]
|
@@ -120,13 +146,13 @@ safe_search = true
|
|
120
146
|
search_language = "English"
|
121
147
|
|
122
148
|
[brave]
|
123
|
-
module_path = "
|
149
|
+
module_path = ".engines.search_engine_brave"
|
124
150
|
class_name = "BraveSearchEngine"
|
125
151
|
requires_api_key = true
|
126
152
|
api_key_env = "BRAVE_API_KEY"
|
127
153
|
reliability = 0.7
|
128
154
|
strengths = [
|
129
|
-
"privacy-focused web search", "product information", "reviews",
|
155
|
+
"privacy-focused web search", "product information", "reviews",
|
130
156
|
"recent content", "news", "broad coverage"
|
131
157
|
]
|
132
158
|
weaknesses = ["requires API key with usage limits", "smaller index than Google"]
|
@@ -141,16 +167,16 @@ safe_search = true
|
|
141
167
|
search_language = "English"
|
142
168
|
|
143
169
|
[wayback]
|
144
|
-
module_path = "
|
170
|
+
module_path = ".engines.search_engine_wayback"
|
145
171
|
class_name = "WaybackSearchEngine"
|
146
172
|
requires_api_key = false
|
147
173
|
reliability = 0.5
|
148
174
|
strengths = [
|
149
|
-
"historical web content", "archived websites", "content verification",
|
175
|
+
"historical web content", "archived websites", "content verification",
|
150
176
|
"deleted or changed web pages", "website evolution tracking"
|
151
177
|
]
|
152
178
|
weaknesses = [
|
153
|
-
"limited to previously archived content", "may miss recent changes",
|
179
|
+
"limited to previously archived content", "may miss recent changes",
|
154
180
|
"archiving quality varies"
|
155
181
|
]
|
156
182
|
supports_full_search = true
|
@@ -162,12 +188,12 @@ closest_only = false
|
|
162
188
|
language = "English"
|
163
189
|
|
164
190
|
[auto]
|
165
|
-
module_path = "
|
191
|
+
module_path = ".engines.meta_search_engine"
|
166
192
|
class_name = "MetaSearchEngine"
|
167
193
|
requires_api_key = false
|
168
194
|
reliability = 0.85
|
169
195
|
strengths = [
|
170
|
-
"intelligent engine selection", "adaptable to query type",
|
196
|
+
"intelligent engine selection", "adaptable to query type",
|
171
197
|
"fallback capabilities"
|
172
198
|
]
|
173
199
|
weaknesses = ["slightly slower due to LLM analysis"]
|
@@ -178,7 +204,7 @@ use_api_key_services = true
|
|
178
204
|
max_engines_to_try = 3
|
179
205
|
|
180
206
|
[local_all]
|
181
|
-
module_path = "
|
207
|
+
module_path = ".engines.search_engine_local_all"
|
182
208
|
class_name = "LocalAllSearchEngine"
|
183
209
|
requires_api_key = false
|
184
210
|
reliability = 0.85
|
@@ -187,16 +213,16 @@ weaknesses = ["may return too many results", "requires indexing"]
|
|
187
213
|
requires_llm = true
|
188
214
|
|
189
215
|
#[semantic_scholar]
|
190
|
-
#module_path = "
|
216
|
+
#module_path = ".engines.search_engine_semantic_scholar"
|
191
217
|
#class_name = "SemanticScholarSearchEngine"
|
192
218
|
#requires_api_key = false
|
193
219
|
#api_key_env = "S2_API_KEY"
|
194
220
|
#reliability = 0.87
|
195
221
|
#strengths = [
|
196
|
-
# "comprehensive scientific literature",
|
197
|
-
# "extensive citation network",
|
198
|
-
# "AI-generated summaries (TLDRs)",
|
199
|
-
# "academic paper metadata",
|
222
|
+
# "comprehensive scientific literature",
|
223
|
+
# "extensive citation network",
|
224
|
+
# "AI-generated summaries (TLDRs)",
|
225
|
+
# "academic paper metadata",
|
200
226
|
# "cross-disciplinary coverage",
|
201
227
|
# "200M+ papers across all fields",
|
202
228
|
# "usable without API key"
|
@@ -232,34 +258,34 @@ DEFAULT_SEARCH_ENGINE = "wikipedia"
|
|
232
258
|
# Uncomment and modify these templates as needed
|
233
259
|
|
234
260
|
# [duckduckgo]
|
235
|
-
# module_path = "
|
261
|
+
# module_path = ".engines.search_engine_ddg"
|
236
262
|
# class_name = "DuckDuckGoSearchEngine"
|
237
263
|
# requires_api_key = false
|
238
264
|
# reliability = 0.4
|
239
265
|
# strengths = [
|
240
|
-
# "web search", "product information", "reviews", "recent information",
|
266
|
+
# "web search", "product information", "reviews", "recent information",
|
241
267
|
# "news", "general queries", "broad coverage"
|
242
268
|
# ]
|
243
269
|
# weaknesses = ["inconsistent due to rate limits", "not specialized for academic content"]
|
244
270
|
# supports_full_search = true
|
245
271
|
# full_search_module = "local_deep_research.web_search_engines.engines.full_search"
|
246
272
|
# full_search_class = "FullSearchResults"
|
247
|
-
#
|
273
|
+
#
|
248
274
|
# [duckduckgo.default_params]
|
249
275
|
# region = "us"
|
250
276
|
# safe_search = true
|
251
277
|
|
252
278
|
# [guardian]
|
253
|
-
# module_path = "
|
279
|
+
# module_path = ".engines.search_engine_guardian"
|
254
280
|
# class_name = "GuardianSearchEngine"
|
255
281
|
# requires_api_key = true
|
256
282
|
# api_key_env = "GUARDIAN_API_KEY"
|
257
283
|
# reliability = 0.5
|
258
284
|
# strengths = [
|
259
|
-
# "news articles", "current events", "opinion pieces", "journalism",
|
285
|
+
# "news articles", "current events", "opinion pieces", "journalism",
|
260
286
|
# "UK and global news", "political analysis"
|
261
287
|
# ]
|
262
288
|
# weaknesses = ["primarily focused on news", "limited historical content pre-1999"]
|
263
|
-
#
|
289
|
+
#
|
264
290
|
# [guardian.default_params]
|
265
291
|
# order_by = "relevance"
|
local_deep_research/main.py
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
-
|
1
|
+
import logging
|
2
|
+
import sys
|
2
3
|
from typing import Dict
|
3
|
-
|
4
|
+
|
5
|
+
from . import get_advanced_search_system, get_report_generator
|
6
|
+
from .config.config_files import settings
|
7
|
+
from .utilities.db_utils import get_db_setting
|
8
|
+
|
4
9
|
|
5
10
|
def print_report(report: Dict):
|
6
11
|
"""Print and save the report in a readable format"""
|
@@ -11,8 +16,6 @@ def print_report(report: Dict):
|
|
11
16
|
# Print content
|
12
17
|
print(report["content"])
|
13
18
|
|
14
|
-
|
15
|
-
|
16
19
|
# Save to file in markdown format
|
17
20
|
with open("report.md", "w", encoding="utf-8") as markdown_file:
|
18
21
|
# Write content
|
@@ -24,31 +27,40 @@ def print_report(report: Dict):
|
|
24
27
|
|
25
28
|
markdown_file.write(f"- Query: {report['metadata']['query']}\n")
|
26
29
|
|
27
|
-
print(
|
30
|
+
print("\nReport has been saved to report.md")
|
28
31
|
|
29
32
|
|
30
|
-
|
33
|
+
# Create the report generator lazily to avoid circular imports
|
34
|
+
def get_report_generator_instance():
|
35
|
+
return get_report_generator()
|
31
36
|
|
32
|
-
report_generator = IntegratedReportGenerator()
|
33
37
|
|
38
|
+
# report_generator = IntegratedReportGenerator()
|
39
|
+
report_generator = None # Will be initialized when needed
|
34
40
|
|
35
41
|
|
36
42
|
def main():
|
37
|
-
import os
|
38
43
|
import logging
|
39
|
-
|
40
|
-
|
44
|
+
|
45
|
+
from .utilities.setup_utils import setup_user_directories
|
46
|
+
|
41
47
|
# Configure logging
|
42
48
|
logging.basicConfig(level=logging.INFO)
|
43
49
|
logger = logging.getLogger(__name__)
|
44
|
-
|
45
|
-
|
46
|
-
|
50
|
+
search_iterations = get_db_setting("search.iterations", settings.search.iterations)
|
51
|
+
questions_per_iteration = get_db_setting(
|
52
|
+
"search.questions_per_iteration", settings.search.questions_per_iteration
|
53
|
+
)
|
54
|
+
logger.info(
|
55
|
+
f"Starting with settings: iterations={search_iterations}, "
|
56
|
+
f"questions_per_iteration={questions_per_iteration}"
|
57
|
+
)
|
58
|
+
|
47
59
|
# Explicitly run setup
|
48
60
|
logger.info("Initializing configuration...")
|
49
61
|
setup_user_directories()
|
50
|
-
|
51
|
-
system =
|
62
|
+
|
63
|
+
system = get_advanced_search_system()
|
52
64
|
|
53
65
|
print("Welcome to the Advanced Research System")
|
54
66
|
print("Type 'quit' to exit")
|
@@ -97,9 +109,12 @@ def main():
|
|
97
109
|
|
98
110
|
else:
|
99
111
|
# Full Report
|
100
|
-
|
101
|
-
|
102
|
-
|
112
|
+
# Initialize report_generator if not already done
|
113
|
+
global report_generator
|
114
|
+
if report_generator is None:
|
115
|
+
report_generator = get_report_generator()
|
116
|
+
|
117
|
+
final_report = report_generator.generate_report(results, query)
|
103
118
|
print("\n=== RESEARCH REPORT ===")
|
104
119
|
print_report(final_report)
|
105
120
|
|
@@ -109,5 +124,92 @@ def main():
|
|
109
124
|
else:
|
110
125
|
print("Research failed. Please try again.")
|
111
126
|
|
127
|
+
|
128
|
+
# Add command for database migration
|
112
129
|
if __name__ == "__main__":
|
113
|
-
|
130
|
+
import argparse
|
131
|
+
|
132
|
+
parser = argparse.ArgumentParser(description="Local Deep Research")
|
133
|
+
parser.add_argument("--web", action="store_true", help="Start the web server")
|
134
|
+
parser.add_argument(
|
135
|
+
"--migrate-db", action="store_true", help="Migrate legacy databases to ldr.db"
|
136
|
+
)
|
137
|
+
parser.add_argument("--debug", action="store_true", help="Enable debug mode")
|
138
|
+
parser.add_argument(
|
139
|
+
"--test-migration",
|
140
|
+
action="store_true",
|
141
|
+
help="Test migration by checking database contents",
|
142
|
+
)
|
143
|
+
parser.add_argument(
|
144
|
+
"--schema-upgrade",
|
145
|
+
action="store_true",
|
146
|
+
help="Run schema upgrades on the database (e.g., remove redundant tables)",
|
147
|
+
)
|
148
|
+
|
149
|
+
args = parser.parse_args()
|
150
|
+
|
151
|
+
if args.debug:
|
152
|
+
logging.basicConfig(level=logging.DEBUG)
|
153
|
+
else:
|
154
|
+
logging.basicConfig(level=logging.INFO)
|
155
|
+
|
156
|
+
if args.migrate_db:
|
157
|
+
try:
|
158
|
+
# First ensure data directory exists
|
159
|
+
from src.local_deep_research.setup_data_dir import setup_data_dir
|
160
|
+
|
161
|
+
setup_data_dir()
|
162
|
+
|
163
|
+
# Then run the migration
|
164
|
+
from src.local_deep_research.web.database.migrate_to_ldr_db import (
|
165
|
+
migrate_to_ldr_db,
|
166
|
+
)
|
167
|
+
|
168
|
+
print("Starting database migration...")
|
169
|
+
success = migrate_to_ldr_db()
|
170
|
+
if success:
|
171
|
+
print("Database migration completed successfully")
|
172
|
+
sys.exit(0)
|
173
|
+
else:
|
174
|
+
print("Database migration failed")
|
175
|
+
sys.exit(1)
|
176
|
+
except Exception as e:
|
177
|
+
print(f"Error running database migration: {e}")
|
178
|
+
sys.exit(1)
|
179
|
+
|
180
|
+
if args.test_migration:
|
181
|
+
try:
|
182
|
+
from src.local_deep_research.test_migration import main as test_main
|
183
|
+
|
184
|
+
sys.exit(test_main())
|
185
|
+
except Exception as e:
|
186
|
+
print(f"Error running migration test: {e}")
|
187
|
+
sys.exit(1)
|
188
|
+
|
189
|
+
if args.schema_upgrade:
|
190
|
+
try:
|
191
|
+
from src.local_deep_research.web.database.schema_upgrade import (
|
192
|
+
run_schema_upgrades,
|
193
|
+
)
|
194
|
+
|
195
|
+
print("Running database schema upgrades...")
|
196
|
+
success = run_schema_upgrades()
|
197
|
+
if success:
|
198
|
+
print("Schema upgrades completed successfully")
|
199
|
+
sys.exit(0)
|
200
|
+
else:
|
201
|
+
print("Schema upgrades failed")
|
202
|
+
sys.exit(1)
|
203
|
+
except Exception as e:
|
204
|
+
print(f"Error running schema upgrades: {e}")
|
205
|
+
sys.exit(1)
|
206
|
+
|
207
|
+
if args.web:
|
208
|
+
from src.local_deep_research.web.app import main as web_main
|
209
|
+
|
210
|
+
web_main()
|
211
|
+
else:
|
212
|
+
# Default to web if no command specified
|
213
|
+
from src.local_deep_research.web.app import main as web_main
|
214
|
+
|
215
|
+
web_main()
|
@@ -0,0 +1,147 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
"""
|
3
|
+
Database migration script for Local Deep Research.
|
4
|
+
Migrates data from legacy databases (deep_research.db and research_history.db) to the new unified database (ldr.db).
|
5
|
+
"""
|
6
|
+
|
7
|
+
import argparse
|
8
|
+
import logging
|
9
|
+
import os
|
10
|
+
import sys
|
11
|
+
|
12
|
+
try:
|
13
|
+
from local_deep_research.web.database.migrate_to_ldr_db import (
|
14
|
+
migrate_to_ldr_db,
|
15
|
+
)
|
16
|
+
from local_deep_research.web.models.database import (
|
17
|
+
DB_PATH,
|
18
|
+
LEGACY_DEEP_RESEARCH_DB,
|
19
|
+
LEGACY_RESEARCH_HISTORY_DB,
|
20
|
+
)
|
21
|
+
except ImportError:
|
22
|
+
# If that fails, try with the relative path.
|
23
|
+
from .web.database.migrate_to_ldr_db import migrate_to_ldr_db
|
24
|
+
from .web.models.database import (
|
25
|
+
DB_PATH,
|
26
|
+
LEGACY_DEEP_RESEARCH_DB,
|
27
|
+
LEGACY_RESEARCH_HISTORY_DB,
|
28
|
+
)
|
29
|
+
|
30
|
+
# Configure logging
|
31
|
+
logging.basicConfig(
|
32
|
+
level=logging.INFO,
|
33
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
34
|
+
handlers=[logging.StreamHandler()],
|
35
|
+
)
|
36
|
+
logger = logging.getLogger("migrate_db")
|
37
|
+
|
38
|
+
# Add proper paths for import
|
39
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
40
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(current_dir)))
|
41
|
+
|
42
|
+
|
43
|
+
def main():
|
44
|
+
"""Main migration function that parses arguments and runs the migration"""
|
45
|
+
parser = argparse.ArgumentParser(
|
46
|
+
description="Local Deep Research Database Migration"
|
47
|
+
)
|
48
|
+
parser.add_argument(
|
49
|
+
"--backup",
|
50
|
+
action="store_true",
|
51
|
+
help="Create backup of existing databases before migration",
|
52
|
+
)
|
53
|
+
parser.add_argument(
|
54
|
+
"--force",
|
55
|
+
action="store_true",
|
56
|
+
help="Force migration even if target database exists",
|
57
|
+
)
|
58
|
+
parser.add_argument(
|
59
|
+
"--dry-run",
|
60
|
+
action="store_true",
|
61
|
+
help="Only check what would be migrated, don't perform actual migration",
|
62
|
+
)
|
63
|
+
parser.add_argument("--verbose", action="store_true", help="Enable verbose logging")
|
64
|
+
|
65
|
+
args = parser.parse_args()
|
66
|
+
|
67
|
+
if args.verbose:
|
68
|
+
logging.getLogger().setLevel(logging.DEBUG)
|
69
|
+
|
70
|
+
print("=" * 80)
|
71
|
+
print("LOCAL DEEP RESEARCH DATABASE MIGRATION")
|
72
|
+
print("=" * 80)
|
73
|
+
|
74
|
+
try:
|
75
|
+
# First try the normal import
|
76
|
+
print(f"Target database will be created at: {DB_PATH}")
|
77
|
+
|
78
|
+
# Check if migration is needed
|
79
|
+
if os.path.exists(DB_PATH) and not args.force:
|
80
|
+
print(f"Target database already exists at: {DB_PATH}")
|
81
|
+
if (
|
82
|
+
input(
|
83
|
+
"Do you want to continue anyway? This may overwrite data. (y/n): "
|
84
|
+
).lower()
|
85
|
+
!= "y"
|
86
|
+
):
|
87
|
+
print("Migration aborted.")
|
88
|
+
return 1
|
89
|
+
|
90
|
+
# Check if source databases exist
|
91
|
+
deep_research_exists = os.path.exists(LEGACY_DEEP_RESEARCH_DB)
|
92
|
+
research_history_exists = os.path.exists(LEGACY_RESEARCH_HISTORY_DB)
|
93
|
+
|
94
|
+
if not deep_research_exists and not research_history_exists:
|
95
|
+
print("No legacy databases found. Nothing to migrate.")
|
96
|
+
return 0
|
97
|
+
|
98
|
+
print("Found legacy databases:")
|
99
|
+
if deep_research_exists:
|
100
|
+
print(f" - {LEGACY_DEEP_RESEARCH_DB}")
|
101
|
+
if research_history_exists:
|
102
|
+
print(f" - {LEGACY_RESEARCH_HISTORY_DB}")
|
103
|
+
|
104
|
+
# Create backups if requested
|
105
|
+
if args.backup:
|
106
|
+
if deep_research_exists:
|
107
|
+
backup_path = f"{LEGACY_DEEP_RESEARCH_DB}.bak"
|
108
|
+
import shutil
|
109
|
+
|
110
|
+
shutil.copy2(LEGACY_DEEP_RESEARCH_DB, backup_path)
|
111
|
+
print(f"Created backup: {backup_path}")
|
112
|
+
|
113
|
+
if research_history_exists:
|
114
|
+
backup_path = f"{LEGACY_RESEARCH_HISTORY_DB}.bak"
|
115
|
+
import shutil
|
116
|
+
|
117
|
+
shutil.copy2(LEGACY_RESEARCH_HISTORY_DB, backup_path)
|
118
|
+
print(f"Created backup: {backup_path}")
|
119
|
+
|
120
|
+
# Run migration or dry run
|
121
|
+
if args.dry_run:
|
122
|
+
print("\nDRY RUN - No changes will be made.")
|
123
|
+
print(f"Would migrate data to: {DB_PATH}")
|
124
|
+
return 0
|
125
|
+
else:
|
126
|
+
print(f"\nStarting migration to: {DB_PATH}")
|
127
|
+
|
128
|
+
success = migrate_to_ldr_db()
|
129
|
+
|
130
|
+
if success:
|
131
|
+
print("\nMigration completed successfully.")
|
132
|
+
print(
|
133
|
+
"You can now start the application with the new unified database."
|
134
|
+
)
|
135
|
+
return 0
|
136
|
+
else:
|
137
|
+
print("\nMigration failed. Check the logs for details.")
|
138
|
+
return 1
|
139
|
+
|
140
|
+
except Exception as e:
|
141
|
+
logger.error(f"Migration error: {e}", exc_info=True)
|
142
|
+
print(f"Error during migration: {e}")
|
143
|
+
return 1
|
144
|
+
|
145
|
+
|
146
|
+
if __name__ == "__main__":
|
147
|
+
sys.exit(main())
|