local-deep-research 0.2.3__py3-none-any.whl → 0.3.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 (41) hide show
  1. local_deep_research/__init__.py +1 -1
  2. local_deep_research/advanced_search_system/filters/cross_engine_filter.py +5 -1
  3. local_deep_research/advanced_search_system/strategies/base_strategy.py +5 -2
  4. local_deep_research/advanced_search_system/strategies/iterdrag_strategy.py +23 -16
  5. local_deep_research/advanced_search_system/strategies/parallel_search_strategy.py +13 -6
  6. local_deep_research/advanced_search_system/strategies/rapid_search_strategy.py +4 -3
  7. local_deep_research/advanced_search_system/strategies/source_based_strategy.py +57 -62
  8. local_deep_research/advanced_search_system/strategies/standard_strategy.py +8 -4
  9. local_deep_research/api/research_functions.py +0 -46
  10. local_deep_research/citation_handler.py +2 -5
  11. local_deep_research/config/llm_config.py +25 -68
  12. local_deep_research/config/search_config.py +8 -21
  13. local_deep_research/defaults/default_settings.json +3814 -0
  14. local_deep_research/search_system.py +34 -31
  15. local_deep_research/utilities/db_utils.py +22 -3
  16. local_deep_research/utilities/search_utilities.py +10 -7
  17. local_deep_research/web/app.py +3 -23
  18. local_deep_research/web/app_factory.py +1 -25
  19. local_deep_research/web/database/migrations.py +20 -418
  20. local_deep_research/web/routes/settings_routes.py +75 -364
  21. local_deep_research/web/services/research_service.py +43 -43
  22. local_deep_research/web/services/settings_manager.py +108 -315
  23. local_deep_research/web/services/settings_service.py +3 -56
  24. local_deep_research/web/static/js/components/research.js +1 -1
  25. local_deep_research/web/static/js/components/settings.js +16 -4
  26. local_deep_research/web/static/js/research_form.js +106 -0
  27. local_deep_research/web/templates/pages/research.html +3 -2
  28. local_deep_research/web_search_engines/engines/meta_search_engine.py +13 -18
  29. local_deep_research/web_search_engines/engines/search_engine_local.py +11 -2
  30. local_deep_research/web_search_engines/engines/search_engine_local_all.py +7 -11
  31. local_deep_research/web_search_engines/search_engine_factory.py +12 -64
  32. local_deep_research/web_search_engines/search_engines_config.py +123 -64
  33. {local_deep_research-0.2.3.dist-info → local_deep_research-0.3.0.dist-info}/METADATA +16 -1
  34. {local_deep_research-0.2.3.dist-info → local_deep_research-0.3.0.dist-info}/RECORD +37 -39
  35. local_deep_research/config/config_files.py +0 -245
  36. local_deep_research/defaults/local_collections.toml +0 -53
  37. local_deep_research/defaults/main.toml +0 -80
  38. local_deep_research/defaults/search_engines.toml +0 -291
  39. {local_deep_research-0.2.3.dist-info → local_deep_research-0.3.0.dist-info}/WHEEL +0 -0
  40. {local_deep_research-0.2.3.dist-info → local_deep_research-0.3.0.dist-info}/entry_points.txt +0 -0
  41. {local_deep_research-0.2.3.dist-info → local_deep_research-0.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -3,35 +3,31 @@ import logging
3
3
  from sqlalchemy import inspect
4
4
 
5
5
  from ..services.settings_manager import SettingsManager
6
- from .models import Base, Setting, SettingType
6
+ from .models import Base, Setting
7
7
 
8
8
  logger = logging.getLogger(__name__)
9
9
 
10
10
 
11
- def migrate_settings_from_files(db_session):
11
+ def import_default_settings_file(db_session):
12
12
  """
13
- Migrate settings from files to database
13
+ Imports all settings from the default settings file to the DB.
14
14
  """
15
- # Check if settings table is empty
16
- settings_count = db_session.query(Setting).count()
17
-
18
- if settings_count == 0:
19
- logger.info("Settings table is empty, importing from files")
20
-
21
- # Create settings manager and import settings
22
- try:
23
- settings_mgr = SettingsManager(db_session)
24
- success = settings_mgr.import_from_file()
25
- if success:
26
- logger.info("Successfully imported settings from files")
27
- else:
28
- logger.warning("Failed to import some settings from files")
29
- except Exception as e:
30
- logger.error("Error importing settings from files: %s", e)
31
- else:
32
- logger.info(
33
- "Settings table already has %s rows, skipping import", settings_count
34
- )
15
+ settings_mgr = SettingsManager(db_session)
16
+ if settings_mgr.db_version_matches_defaults():
17
+ # We probably shouldn't bother loading settings if the version didn't
18
+ # change.
19
+ return
20
+ logger.info("Detected a new version of default settings, upgrading DB.")
21
+
22
+ # Create settings manager and import settings
23
+ try:
24
+ # This will not overwrite existing settings, but will delete
25
+ # extraneous ones. This should be enough to update anyone with
26
+ # old versions of the settings.
27
+ settings_mgr.load_from_defaults_file(overwrite=False, delete_extra=True)
28
+ logger.info("Successfully imported settings from files")
29
+ except Exception as e:
30
+ logger.error("Error importing settings from files: %s", e)
35
31
 
36
32
 
37
33
  def run_migrations(engine, db_session=None):
@@ -50,398 +46,4 @@ def run_migrations(engine, db_session=None):
50
46
 
51
47
  # Import existing settings from files
52
48
  if db_session:
53
- migrate_settings_from_files(db_session)
54
-
55
-
56
- def setup_predefined_settings(db_session):
57
- """
58
- Set up predefined settings with UI metadata
59
-
60
- Args:
61
- db_session: SQLAlchemy session
62
- """
63
- # Define standard UI settings for LLM
64
- llm_settings = [
65
- {
66
- "key": "llm.model",
67
- "name": "LLM Model",
68
- "description": "Language model to use for research and analysis",
69
- "category": "llm_general",
70
- "ui_element": "select",
71
- "options": [
72
- {"value": "gpt-4o", "label": "GPT-4o (OpenAI)"},
73
- {"value": "gpt-3.5-turbo", "label": "GPT-3.5 Turbo (OpenAI)"},
74
- {
75
- "value": "claude-3-5-sonnet-latest",
76
- "label": "Claude 3.5 Sonnet (Anthropic)",
77
- },
78
- {
79
- "value": "claude-3-opus-20240229",
80
- "label": "Claude 3 Opus (Anthropic)",
81
- },
82
- {"value": "llama3", "label": "Llama 3 (Meta)"},
83
- {"value": "mistral", "label": "Mistral (Mistral AI)"},
84
- {"value": "mixtral", "label": "Mixtral (Mistral AI)"},
85
- ],
86
- "value": "gpt-3.5-turbo",
87
- },
88
- {
89
- "key": "llm.provider",
90
- "name": "LLM Provider",
91
- "description": "Service provider for the language model",
92
- "category": "llm_general",
93
- "ui_element": "select",
94
- "options": [
95
- {"value": "openai", "label": "OpenAI API"},
96
- {"value": "anthropic", "label": "Anthropic API"},
97
- {"value": "ollama", "label": "Ollama (Local)"},
98
- {"value": "lmstudio", "label": "LM Studio (Local)"},
99
- {"value": "vllm", "label": "vLLM (Local)"},
100
- {"value": "openai_endpoint", "label": "Custom OpenAI-compatible API"},
101
- ],
102
- "value": "openai",
103
- },
104
- {
105
- "key": "llm.temperature",
106
- "name": "Temperature",
107
- "description": "Controls randomness in model outputs (0.0 - 1.0)",
108
- "category": "llm_parameters",
109
- "ui_element": "slider",
110
- "min_value": 0.0,
111
- "max_value": 1.0,
112
- "step": 0.05,
113
- "value": 0.7,
114
- },
115
- {
116
- "key": "llm.max_tokens",
117
- "name": "Max Tokens",
118
- "description": "Maximum number of tokens in model responses",
119
- "category": "llm_parameters",
120
- "ui_element": "number",
121
- "min_value": 100,
122
- "max_value": 4096,
123
- "value": 1024,
124
- },
125
- ]
126
-
127
- # Define standard UI settings for Search
128
- search_settings = [
129
- {
130
- "key": "search.tool",
131
- "name": "Search Engine",
132
- "description": "Web search engine to use for research",
133
- "category": "search_general",
134
- "ui_element": "select",
135
- "options": [
136
- {"value": "auto", "label": "Auto (Default)"},
137
- {"value": "arxiv", "label": "Arxiv"},
138
- {"value": "wikipedia", "label": "Wikipedia"},
139
- {"value": "pubmed", "label": "Pubmed"},
140
- {"value": "github", "label": "Github"},
141
- {"value": "serpapi", "label": "SerpAPI (Google)"},
142
- {"value": "searxng", "label": "SearXNG (Self-hosted)"},
143
- {"value": "google_pse", "label": "Google Programmable Search Engine"},
144
- {"value": "duckduckgo", "label": "DuckDuckGo"},
145
- {"value": "brave", "label": "Brave"},
146
- {"value": "wayback", "label": "Wayback"},
147
- {"value": "local_all", "label": "Local All"},
148
- ],
149
- "value": "auto",
150
- },
151
- {
152
- "key": "search.max_results",
153
- "name": "Max Results",
154
- "description": "Maximum number of search results to retrieve",
155
- "category": "search_parameters",
156
- "ui_element": "number",
157
- "min_value": 3,
158
- "max_value": 50,
159
- "value": 10,
160
- },
161
- {
162
- "key": "search.region",
163
- "name": "Search Region",
164
- "description": "Geographic region for search results",
165
- "category": "search_parameters",
166
- "ui_element": "select",
167
- "options": [
168
- {"value": "us", "label": "United States"},
169
- {"value": "uk", "label": "United Kingdom"},
170
- {"value": "fr", "label": "France"},
171
- {"value": "de", "label": "Germany"},
172
- {"value": "jp", "label": "Japan"},
173
- {"value": "wt-wt", "label": "No Region (Worldwide)"},
174
- ],
175
- "value": "us",
176
- },
177
- {
178
- "key": "search.time_period",
179
- "name": "Time Period",
180
- "description": "Time period for search results",
181
- "category": "search_parameters",
182
- "ui_element": "select",
183
- "options": [
184
- {"value": "d", "label": "Past 24 hours"},
185
- {"value": "w", "label": "Past week"},
186
- {"value": "m", "label": "Past month"},
187
- {"value": "y", "label": "Past year"},
188
- {"value": "all", "label": "All time"},
189
- ],
190
- "value": "all",
191
- },
192
- {
193
- "key": "search.snippets_only",
194
- "name": "Snippets Only",
195
- "description": "Only retrieve snippets instead of full search results",
196
- "category": "search_parameters",
197
- "ui_element": "checkbox",
198
- "value": True,
199
- },
200
- ]
201
-
202
- # Define standard UI settings for Report generation
203
- report_settings = [
204
- {
205
- "key": "report.searches_per_section",
206
- "name": "Searches Per Section",
207
- "description": "Number of searches to run per report section",
208
- "category": "report_parameters",
209
- "ui_element": "number",
210
- "min_value": 1,
211
- "max_value": 5,
212
- "value": 2,
213
- },
214
- {
215
- "key": "report.enable_fact_checking",
216
- "name": "Enable Fact Checking",
217
- "description": "Enable fact checking for report contents",
218
- "category": "report_parameters",
219
- "ui_element": "checkbox",
220
- "value": True,
221
- },
222
- {
223
- "key": "report.detailed_citations",
224
- "name": "Detailed Citations",
225
- "description": "Include detailed citations in reports",
226
- "category": "report_parameters",
227
- "ui_element": "checkbox",
228
- "value": True,
229
- },
230
- ]
231
-
232
- # Define standard UI settings for App
233
- app_settings = [
234
- {
235
- "key": "app.debug",
236
- "name": "Debug Mode",
237
- "description": "Enable debug mode for the web application",
238
- "category": "app_interface",
239
- "ui_element": "checkbox",
240
- "value": True,
241
- },
242
- {
243
- "key": "app.host",
244
- "name": "Web Host",
245
- "description": "Host address to bind the web server",
246
- "category": "app_interface",
247
- "ui_element": "text",
248
- "value": "0.0.0.0",
249
- },
250
- {
251
- "key": "app.port",
252
- "name": "Web Port",
253
- "description": "Port for the web server",
254
- "category": "app_interface",
255
- "ui_element": "number",
256
- "min_value": 1,
257
- "max_value": 65535,
258
- "value": 5000,
259
- },
260
- {
261
- "key": "app.enable_notifications",
262
- "name": "Enable Notifications",
263
- "description": "Enable browser notifications for research events",
264
- "category": "app_interface",
265
- "ui_element": "checkbox",
266
- "value": True,
267
- },
268
- {
269
- "key": "app.theme",
270
- "name": "UI Theme",
271
- "description": "User interface theme",
272
- "category": "app_interface",
273
- "ui_element": "select",
274
- "options": [
275
- {"value": "dark", "label": "Dark"},
276
- {"value": "light", "label": "Light"},
277
- {"value": "system", "label": "System Default"},
278
- ],
279
- "value": "dark",
280
- },
281
- {
282
- "key": "app.web_interface",
283
- "name": "Web Interface",
284
- "description": "Enable the web interface",
285
- "category": "app_interface",
286
- "ui_element": "checkbox",
287
- "value": True,
288
- },
289
- {
290
- "key": "app.enable_web",
291
- "name": "Enable Web Server",
292
- "description": "Enable the web server",
293
- "category": "app_interface",
294
- "ui_element": "checkbox",
295
- "value": True,
296
- },
297
- ]
298
-
299
- # Update search settings with research-specific settings
300
- search_settings.extend(
301
- [
302
- {
303
- "key": "search.research_iterations",
304
- "name": "Research Iterations",
305
- "description": "Number of research cycles to perform",
306
- "category": "search_parameters",
307
- "ui_element": "number",
308
- "min_value": 1,
309
- "max_value": 5,
310
- "value": 2,
311
- },
312
- {
313
- "key": "search.questions_per_iteration",
314
- "name": "Questions Per Iteration",
315
- "description": "Number of questions to generate per research cycle",
316
- "category": "search_parameters",
317
- "ui_element": "number",
318
- "min_value": 1,
319
- "max_value": 10,
320
- "value": 3,
321
- },
322
- {
323
- "key": "search.searches_per_section",
324
- "name": "Searches Per Section",
325
- "description": "Number of searches to run per report section",
326
- "category": "search_parameters",
327
- "ui_element": "number",
328
- "min_value": 1,
329
- "max_value": 5,
330
- "value": 2,
331
- },
332
- {
333
- "key": "search.skip_relevance_filter",
334
- "name": "Skip Relevance Filter",
335
- "description": "Skip filtering search results for relevance",
336
- "category": "search_parameters",
337
- "ui_element": "checkbox",
338
- "value": False,
339
- },
340
- {
341
- "key": "search.safe_search",
342
- "name": "Safe Search",
343
- "description": "Enable safe search filtering",
344
- "category": "search_parameters",
345
- "ui_element": "checkbox",
346
- "value": True,
347
- },
348
- {
349
- "key": "search.search_language",
350
- "name": "Search Language",
351
- "description": "Language for search results",
352
- "category": "search_parameters",
353
- "ui_element": "select",
354
- "options": [
355
- {"value": "English", "label": "English"},
356
- {"value": "French", "label": "French"},
357
- {"value": "German", "label": "German"},
358
- {"value": "Spanish", "label": "Spanish"},
359
- {"value": "Italian", "label": "Italian"},
360
- {"value": "Japanese", "label": "Japanese"},
361
- {"value": "Chinese", "label": "Chinese"},
362
- ],
363
- "value": "English",
364
- },
365
- ]
366
- )
367
-
368
- # Ensure these predefined settings exist in the database
369
- # This will update existing settings with the same key
370
- all_settings = llm_settings + search_settings + report_settings + app_settings
371
-
372
- # Add/update each setting
373
- for setting_dict in all_settings:
374
- try:
375
- # Convert to correct type based on key prefix
376
- setting_type = None
377
- key = setting_dict.get("key", "")
378
-
379
- if key.startswith("llm."):
380
- setting_type = SettingType.LLM
381
- elif key.startswith("search."):
382
- setting_type = SettingType.SEARCH
383
- elif key.startswith("report."):
384
- setting_type = SettingType.REPORT
385
- elif key.startswith("app."):
386
- setting_type = SettingType.APP
387
-
388
- # Skip if no valid type
389
- if not setting_type:
390
- logger.warning("Skipping setting %s - unknown type", key)
391
- continue
392
-
393
- # Check if setting exists
394
- existing = db_session.query(Setting).filter(Setting.key == key).first()
395
-
396
- if existing:
397
- # Update existing setting
398
- logger.debug("Updating existing setting: %s", key)
399
-
400
- # Only update metadata, not the value (to preserve user settings)
401
- existing.name = setting_dict.get("name", existing.name)
402
- existing.description = setting_dict.get(
403
- "description", existing.description
404
- )
405
- existing.category = setting_dict.get("category", existing.category)
406
- existing.ui_element = setting_dict.get(
407
- "ui_element", existing.ui_element
408
- )
409
- existing.options = setting_dict.get("options", existing.options)
410
- existing.min_value = setting_dict.get("min_value", existing.min_value)
411
- existing.max_value = setting_dict.get("max_value", existing.max_value)
412
- existing.step = setting_dict.get("step", existing.step)
413
-
414
- # Only set value if it's not already set
415
- if existing.value is None and "value" in setting_dict:
416
- existing.value = setting_dict["value"]
417
- else:
418
- # Create new setting
419
- logger.info("Creating new setting: %s", key)
420
- setting = Setting(
421
- key=key,
422
- value=setting_dict.get("value"),
423
- type=setting_type,
424
- name=setting_dict.get(
425
- "name", key.split(".")[-1].replace("_", " ").title()
426
- ),
427
- description=setting_dict.get("description", f"Setting for {key}"),
428
- category=setting_dict.get("category"),
429
- ui_element=setting_dict.get("ui_element", "text"),
430
- options=setting_dict.get("options"),
431
- min_value=setting_dict.get("min_value"),
432
- max_value=setting_dict.get("max_value"),
433
- step=setting_dict.get("step"),
434
- visible=setting_dict.get("visible", True),
435
- editable=setting_dict.get("editable", True),
436
- )
437
- db_session.add(setting)
438
-
439
- # Commit after each successful setting
440
- db_session.commit()
441
-
442
- except Exception as e:
443
- logger.error("Error ensuring setting %s: %s", setting_dict.get("key"), e)
444
- db_session.rollback()
445
-
446
- # Log completion
447
- logger.info("Predefined settings setup complete")
49
+ import_default_settings_file(db_session)