local-deep-research 0.6.1__py3-none-any.whl → 0.6.4__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 +6 -0
- local_deep_research/__version__.py +1 -1
- local_deep_research/setup_data_dir.py +3 -2
- local_deep_research/utilities/db_utils.py +11 -9
- local_deep_research/utilities/log_utils.py +1 -1
- local_deep_research/utilities/threading_utils.py +17 -4
- local_deep_research/web/api.py +5 -3
- local_deep_research/web/app.py +0 -74
- local_deep_research/web/app_factory.py +1 -11
- local_deep_research/web/database/migrations.py +699 -28
- local_deep_research/web/database/uuid_migration.py +2 -247
- local_deep_research/web/models/database.py +0 -79
- local_deep_research/web/routes/settings_routes.py +70 -73
- local_deep_research/web/services/settings_manager.py +13 -28
- local_deep_research/web/services/settings_service.py +6 -40
- local_deep_research/web/services/socket_service.py +1 -1
- local_deep_research/web_search_engines/rate_limiting/tracker.py +1 -3
- {local_deep_research-0.6.1.dist-info → local_deep_research-0.6.4.dist-info}/METADATA +19 -4
- {local_deep_research-0.6.1.dist-info → local_deep_research-0.6.4.dist-info}/RECORD +22 -25
- local_deep_research/migrate_db.py +0 -149
- local_deep_research/web/database/migrate_to_ldr_db.py +0 -297
- local_deep_research/web/database/schema_upgrade.py +0 -519
- {local_deep_research-0.6.1.dist-info → local_deep_research-0.6.4.dist-info}/WHEEL +0 -0
- {local_deep_research-0.6.1.dist-info → local_deep_research-0.6.4.dist-info}/entry_points.txt +0 -0
- {local_deep_research-0.6.1.dist-info → local_deep_research-0.6.4.dist-info}/licenses/LICENSE +0 -0
@@ -66,11 +66,17 @@ class SettingsManager:
|
|
66
66
|
self.db_session = db_session
|
67
67
|
self.db_first = True # Always prioritize DB settings
|
68
68
|
|
69
|
-
|
69
|
+
@property
|
70
|
+
def default_settings(self) -> Dict[str, Any]:
|
71
|
+
"""
|
72
|
+
Returns:
|
73
|
+
The default settings, loaded from JSON.
|
74
|
+
|
75
|
+
"""
|
70
76
|
default_settings = pkg_resources.read_text(
|
71
77
|
defaults, "default_settings.json"
|
72
78
|
)
|
73
|
-
|
79
|
+
return json.loads(default_settings)
|
74
80
|
|
75
81
|
def __get_typed_setting_value(
|
76
82
|
self,
|
@@ -462,27 +468,6 @@ class SettingsManager:
|
|
462
468
|
self.db_session.add(version)
|
463
469
|
self.db_session.commit()
|
464
470
|
|
465
|
-
@classmethod
|
466
|
-
def get_instance(
|
467
|
-
cls, db_session: Optional[Session] = None
|
468
|
-
) -> "SettingsManager":
|
469
|
-
"""
|
470
|
-
Get a singleton instance of the settings manager
|
471
|
-
|
472
|
-
Args:
|
473
|
-
db_session: Optional database session
|
474
|
-
|
475
|
-
Returns:
|
476
|
-
SettingsManager instance
|
477
|
-
"""
|
478
|
-
if not hasattr(cls, "_instance"):
|
479
|
-
cls._instance = cls(db_session)
|
480
|
-
elif db_session and not cls._instance.db_session:
|
481
|
-
# Update existing instance with a session
|
482
|
-
cls._instance.db_session = db_session
|
483
|
-
|
484
|
-
return cls._instance
|
485
|
-
|
486
471
|
def import_settings(
|
487
472
|
self,
|
488
473
|
settings_data: Dict[str, Any],
|
@@ -517,6 +502,11 @@ class SettingsManager:
|
|
517
502
|
setting = Setting(key=key, **setting_values)
|
518
503
|
self.db_session.add(setting)
|
519
504
|
|
505
|
+
if commit or delete_extra:
|
506
|
+
self.db_session.commit()
|
507
|
+
# Emit WebSocket event for all imported settings
|
508
|
+
self._emit_settings_changed(list(settings_data.keys()))
|
509
|
+
|
520
510
|
if delete_extra:
|
521
511
|
all_settings = self.get_all_settings()
|
522
512
|
for key in all_settings:
|
@@ -524,11 +514,6 @@ class SettingsManager:
|
|
524
514
|
logger.debug(f"Deleting extraneous setting: {key}")
|
525
515
|
self.delete_setting(key, commit=False)
|
526
516
|
|
527
|
-
if commit:
|
528
|
-
self.db_session.commit()
|
529
|
-
# Emit WebSocket event for all imported settings
|
530
|
-
self._emit_settings_changed(list(settings_data.keys()))
|
531
|
-
|
532
517
|
def _create_setting(self, key, value, setting_type):
|
533
518
|
"""Create a setting with appropriate metadata"""
|
534
519
|
|
@@ -3,41 +3,10 @@ from typing import Any, Dict, Optional, Union
|
|
3
3
|
from loguru import logger
|
4
4
|
|
5
5
|
from ..database.models import Setting
|
6
|
-
from .
|
6
|
+
from ...utilities.db_utils import get_settings_manager
|
7
7
|
|
8
8
|
|
9
|
-
def
|
10
|
-
"""
|
11
|
-
Get or create the settings manager instance.
|
12
|
-
|
13
|
-
Args:
|
14
|
-
db_session: Optional database session to use
|
15
|
-
|
16
|
-
Returns:
|
17
|
-
SettingsManager: The settings manager instance
|
18
|
-
"""
|
19
|
-
return SettingsManager.get_instance(db_session)
|
20
|
-
|
21
|
-
|
22
|
-
def get_setting(key: str, default: Any = None, db_session=None) -> Any:
|
23
|
-
"""
|
24
|
-
Get a setting value by key
|
25
|
-
|
26
|
-
Args:
|
27
|
-
key: Setting key
|
28
|
-
default: Default value if setting not found
|
29
|
-
db_session: Optional database session to use
|
30
|
-
|
31
|
-
Returns:
|
32
|
-
Any: The setting value
|
33
|
-
"""
|
34
|
-
manager = get_settings_manager(db_session)
|
35
|
-
return manager.get_setting(key, default)
|
36
|
-
|
37
|
-
|
38
|
-
def set_setting(
|
39
|
-
key: str, value: Any, commit: bool = True, db_session=None
|
40
|
-
) -> bool:
|
9
|
+
def set_setting(key: str, value: Any, commit: bool = True) -> bool:
|
41
10
|
"""
|
42
11
|
Set a setting value
|
43
12
|
|
@@ -45,26 +14,23 @@ def set_setting(
|
|
45
14
|
key: Setting key
|
46
15
|
value: Setting value
|
47
16
|
commit: Whether to commit the change
|
48
|
-
db_session: Optional database session
|
49
17
|
|
50
18
|
Returns:
|
51
19
|
bool: True if successful
|
52
20
|
"""
|
53
|
-
manager = get_settings_manager(
|
21
|
+
manager = get_settings_manager()
|
54
22
|
return manager.set_setting(key, value, commit)
|
55
23
|
|
56
24
|
|
57
|
-
def get_all_settings(
|
25
|
+
def get_all_settings() -> Dict[str, Any]:
|
58
26
|
"""
|
59
27
|
Get all settings, optionally filtered by type
|
60
28
|
|
61
|
-
Args:
|
62
|
-
db_session: Optional database session
|
63
|
-
|
64
29
|
Returns:
|
65
30
|
Dict[str, Any]: Dictionary of settings
|
31
|
+
|
66
32
|
"""
|
67
|
-
manager = get_settings_manager(
|
33
|
+
manager = get_settings_manager()
|
68
34
|
return manager.get_all_settings()
|
69
35
|
|
70
36
|
|
@@ -9,7 +9,7 @@ from collections import deque
|
|
9
9
|
from typing import Dict, Optional, Tuple, List
|
10
10
|
|
11
11
|
|
12
|
-
from ...utilities.db_utils import get_db_session
|
12
|
+
from ...utilities.db_utils import get_db_session, get_db_setting
|
13
13
|
from ...web.database.models import RateLimitAttempt, RateLimitEstimate
|
14
14
|
|
15
15
|
logger = logging.getLogger(__name__)
|
@@ -23,8 +23,6 @@ class AdaptiveRateLimitTracker:
|
|
23
23
|
|
24
24
|
def __init__(self):
|
25
25
|
# Load configuration from database settings
|
26
|
-
from ...utilities.db_utils import get_db_setting
|
27
|
-
|
28
26
|
self.memory_window = int(
|
29
27
|
get_db_setting("rate_limiting.memory_window", 100)
|
30
28
|
)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: local-deep-research
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.4
|
4
4
|
Summary: AI-powered research assistant with deep, iterative analysis using LLMs and web searches
|
5
5
|
Author-Email: LearningCircuit <185559241+LearningCircuit@users.noreply.github.com>, HashedViking <6432677+HashedViking@users.noreply.github.com>, djpetti <djpetti@gmail.com>
|
6
6
|
License: MIT License
|
@@ -99,6 +99,7 @@ Description-Content-Type: text/markdown
|
|
99
99
|
|
100
100
|
*Performs deep, iterative research using multiple LLMs and search engines with proper citations*
|
101
101
|
</div>
|
102
|
+
|
102
103
|
## 🚀 What is Local Deep Research?
|
103
104
|
|
104
105
|
LDR is an AI research assistant that performs systematic research by:
|
@@ -118,6 +119,14 @@ It aims to help researchers, students, and professionals find accurate informati
|
|
118
119
|
- **Transparent**: Track costs and performance with built-in analytics
|
119
120
|
- **Open Source**: MIT licensed with an active community
|
120
121
|
|
122
|
+
## 📊 Performance
|
123
|
+
|
124
|
+
**~95% accuracy on SimpleQA benchmark** (preliminary results)
|
125
|
+
- Tested with GPT-4.1-mini + SearXNG + focused-iteration strategy
|
126
|
+
- Comparable to state-of-the-art AI research systems
|
127
|
+
- Local models can achieve similar performance with proper configuration
|
128
|
+
- [Join our community benchmarking effort →](https://github.com/LearningCircuit/local-deep-research/tree/main/community_benchmark_results)
|
129
|
+
|
121
130
|
## ✨ Key Features
|
122
131
|
|
123
132
|
### 🔍 Research Modes
|
@@ -160,7 +169,7 @@ It aims to help researchers, students, and professionals find accurate informati
|
|
160
169
|
|
161
170
|
## ⚡ Quick Start
|
162
171
|
|
163
|
-
### Option 1: Docker (Quickstart
|
172
|
+
### Option 1: Docker (Quickstart on MAC/ARM)
|
164
173
|
|
165
174
|
```bash
|
166
175
|
# Step 1: Pull and run SearXNG for optimal search results
|
@@ -175,7 +184,13 @@ docker run -d -p 5000:5000 --name local-deep-research --volume 'deep-research:/i
|
|
175
184
|
LDR uses Docker compose to bundle the web app and all it's dependencies so
|
176
185
|
you can get up and running quickly.
|
177
186
|
|
178
|
-
#### Option 2a:
|
187
|
+
#### Option 2a: Quick Start (One Command)
|
188
|
+
```bash
|
189
|
+
curl -O https://raw.githubusercontent.com/LearningCircuit/local-deep-research/main/docker-compose.yml && docker compose up -d
|
190
|
+
```
|
191
|
+
Open http://localhost:5000 after ~30 seconds. This starts LDR with SearXNG and all dependencies.
|
192
|
+
|
193
|
+
#### Option 2b: DIY docker-compose
|
179
194
|
See [docker-compose.yml](./docker-compose.yml) for a docker-compose file with reasonable defaults to get up and running with ollama, searxng, and local deep research all running locally.
|
180
195
|
|
181
196
|
Things you may want/need to configure:
|
@@ -184,7 +199,7 @@ Things you may want/need to configure:
|
|
184
199
|
* Ollama keep alive (duration model will stay loaded into VRAM and idle before getting unloaded automatically)
|
185
200
|
* Deep Research model (depends on available VRAM and preference)
|
186
201
|
|
187
|
-
#### Option
|
202
|
+
#### Option 2c: Use Cookie Cutter to tailor a docker-compose to your needs:
|
188
203
|
|
189
204
|
##### Prerequisites
|
190
205
|
|
@@ -1,9 +1,9 @@
|
|
1
|
-
local_deep_research-0.6.
|
2
|
-
local_deep_research-0.6.
|
3
|
-
local_deep_research-0.6.
|
4
|
-
local_deep_research-0.6.
|
5
|
-
local_deep_research/__init__.py,sha256=
|
6
|
-
local_deep_research/__version__.py,sha256=
|
1
|
+
local_deep_research-0.6.4.dist-info/METADATA,sha256=TtghNU7ziPFS-HZL26QwIS_4EcR7JNL85H0e8BRBOCs,15218
|
2
|
+
local_deep_research-0.6.4.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
|
3
|
+
local_deep_research-0.6.4.dist-info/entry_points.txt,sha256=GcXS501Rjh-P80S8db7hnrQ23mS_Jg27PwpVQVO77as,113
|
4
|
+
local_deep_research-0.6.4.dist-info/licenses/LICENSE,sha256=Qg2CaTdu6SWnSqk1_JtgBPp_Da-LdqJDhT1Vt1MUc5s,1072
|
5
|
+
local_deep_research/__init__.py,sha256=_I_QZVYHUi9KSq78IVVNm_MKasj2RByOxBEo6w72PT8,1250
|
6
|
+
local_deep_research/__version__.py,sha256=WMmvm2Keb76yMz8OL_h4fKT34Xpi-1BVfCiTn2QGzz4,22
|
7
7
|
local_deep_research/advanced_search_system/__init__.py,sha256=sGusMj4eFIrhXR6QbOM16UDKB6aI-iS4IFivKWpMlh0,234
|
8
8
|
local_deep_research/advanced_search_system/answer_decoding/__init__.py,sha256=BmmbIPQnouYyboFD61CDq71fW5On555w7dbt42s9gV4,148
|
9
9
|
local_deep_research/advanced_search_system/answer_decoding/browsecomp_answer_decoder.py,sha256=4FDMP4n_z5DOzVIisH3_kexRqNm1AO3MDe-Md3WtgE0,12856
|
@@ -166,35 +166,32 @@ local_deep_research/metrics/pricing/pricing_fetcher.py,sha256=YQThSQIZmy9VJp0TSo
|
|
166
166
|
local_deep_research/metrics/query_utils.py,sha256=BDQk3F-nmI09mIGbelteCCWxq4oSKKKdHv4OO5Q_fGo,1522
|
167
167
|
local_deep_research/metrics/search_tracker.py,sha256=sPC9hKq2X78Wlx4YUVxvneq0Ce1m0HebJAWO-226gd8,15862
|
168
168
|
local_deep_research/metrics/token_counter.py,sha256=QmNvJhAKgpzxmBErCZ0pEAjCwgk8IBMt-gXaQRksXCs,43043
|
169
|
-
local_deep_research/migrate_db.py,sha256=-Ql7bC2VmXlWtDOXj7CGVBvBlSk--wHyZCniWJnhC6c,4648
|
170
169
|
local_deep_research/report_generator.py,sha256=8nBYTT5cO35B0b6NFsjdroBoBvzSJJa9OsUCtdQPAAg,9320
|
171
170
|
local_deep_research/search_system.py,sha256=_JaOavJNo4q8t0Ir8KlvG6fFX3k7P6GkCOwYkCGYJ3E,27348
|
172
|
-
local_deep_research/setup_data_dir.py,sha256=
|
171
|
+
local_deep_research/setup_data_dir.py,sha256=IMp9ndGUqY5XYIbCk0V_F4cEL3n7FWLbut5XeatqUuc,1172
|
173
172
|
local_deep_research/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
174
|
-
local_deep_research/utilities/db_utils.py,sha256=
|
173
|
+
local_deep_research/utilities/db_utils.py,sha256=7FbN5LWiDqv7tLdcSr8cuGREBpOvIU8-f_S1Bnd3v_E,1872
|
175
174
|
local_deep_research/utilities/enums.py,sha256=yFwmodt93uETdQd7qyW4vOUhiAzZF-BHBbVYHKN7scU,223
|
176
175
|
local_deep_research/utilities/es_utils.py,sha256=5jT17BDR0bapHNIwMgezHmrbV4WQ7ZA1rY9CDF8ouAc,14747
|
177
176
|
local_deep_research/utilities/llm_utils.py,sha256=svjDDto95myjtSIJyd6t6uaezBEdEtj_tH-wVGjAHV0,5046
|
178
|
-
local_deep_research/utilities/log_utils.py,sha256=
|
177
|
+
local_deep_research/utilities/log_utils.py,sha256=xFHsS7SJEdQhEdKoxVgcWMbY-wMEbvPD6Bey63pxh7s,5418
|
179
178
|
local_deep_research/utilities/search_cache.py,sha256=BGHU3_1PhRc1gikiFtl-28ziqMMQLm8GBR46Hir1Y_U,13239
|
180
179
|
local_deep_research/utilities/search_utilities.py,sha256=yyQYSBSS1IGGFwaRs0s27gEvSYgYqYRsVTK0v2jZ4GQ,9713
|
181
180
|
local_deep_research/utilities/setup_utils.py,sha256=0Us6doQ6xQtKzgtnN1C4L7sSgxzFKJ35FpmZdj1tCDM,213
|
182
181
|
local_deep_research/utilities/thread_context.py,sha256=M3NszCJD1xHa_9-GJpDrAi5qYmKVe55lj1Vq_Z_P8vw,3104
|
183
|
-
local_deep_research/utilities/threading_utils.py,sha256=
|
182
|
+
local_deep_research/utilities/threading_utils.py,sha256=j1YdqD0PvUuLrcaaI_itLUfWK7ki_B0F18xy0s9gtpo,2888
|
184
183
|
local_deep_research/utilities/url_utils.py,sha256=-GjOVrJCglNCDRs9rePyP1T8d6TeIGwI_nzCA5USPd4,1909
|
185
184
|
local_deep_research/web/__init__.py,sha256=CynnuRxCf9mB0AHeylhF5yVZwdj0H6bxVrZtniw3xmE,44
|
186
|
-
local_deep_research/web/api.py,sha256=
|
187
|
-
local_deep_research/web/app.py,sha256=
|
188
|
-
local_deep_research/web/app_factory.py,sha256=
|
185
|
+
local_deep_research/web/api.py,sha256=JSc3mRrVVB4BHgeYLnUjtq0dxURbKKQNrS2HdRAct2o,11285
|
186
|
+
local_deep_research/web/app.py,sha256=cWiNJL-DExvg3bH6TBmL4C4fO-B-0wakdrn5qdCi-IY,798
|
187
|
+
local_deep_research/web/app_factory.py,sha256=41BwIgnHRz3KMFEp7KmAm6IydrfzIkrjO5OqV0D6CBo,9949
|
189
188
|
local_deep_research/web/database/README.md,sha256=eEDLqLIfOBRvc0TFh3J1HrtFbZceYmVgpjS3-oyZ5nI,2861
|
190
189
|
local_deep_research/web/database/benchmark_schema.py,sha256=nlqqG5o9XVRGtDlLzFS9XNinNntUhvl_JFUYyjMst-w,7629
|
191
190
|
local_deep_research/web/database/convert_research_id_to_string.py,sha256=3xrVy0crCoM94N4TZfLZAEJTt7oYGX60zrDo0PZZrCQ,5619
|
192
|
-
local_deep_research/web/database/
|
193
|
-
local_deep_research/web/database/migrations.py,sha256=BKUDckR98Yz8cMtd473lMxLcVqWTtFyHVFWFPs9PgfY,2468
|
191
|
+
local_deep_research/web/database/migrations.py,sha256=YLa78izXCdwY6YZokYUIPQl2Ryd-5v_jwQ79PJAI8R4,25101
|
194
192
|
local_deep_research/web/database/models.py,sha256=eQN1Rqo_aCHjpefedoGi7zQ_HSbKKFhKTqF-6lOUvqc,7991
|
195
|
-
local_deep_research/web/database/
|
196
|
-
local_deep_research/web/database
|
197
|
-
local_deep_research/web/models/database.py,sha256=uBecKQpZd9cXdt2ZPUr0FOpHFbDZd40kQNKYSZOxnEI,8422
|
193
|
+
local_deep_research/web/database/uuid_migration.py,sha256=12se2wvSLtHUNKctu_e0bfgDjfV-ykZwWCdiYcbXvv0,484
|
194
|
+
local_deep_research/web/models/database.py,sha256=w8A4ORA4jXBVdr0UK0THfLmWfbjNsA-reYv3jO6Vkaw,5915
|
198
195
|
local_deep_research/web/models/settings.py,sha256=rXBI9vY5k3ndR8dPd3fZJy-6HwYltQihhSBRq-sZutw,2314
|
199
196
|
local_deep_research/web/routes/api_routes.py,sha256=RlpM0cl9UKxYdezNtNvzbUQiZsTOyTnlvoRMeylUYK0,21167
|
200
197
|
local_deep_research/web/routes/benchmark_routes.py,sha256=bXiURrmWoaGtbOQ3jhgXgxjs3Qa440Jqk1CPZ1QMyO0,15725
|
@@ -203,12 +200,12 @@ local_deep_research/web/routes/history_routes.py,sha256=h2AeFhpQ8H7uKulKTtddQAH8
|
|
203
200
|
local_deep_research/web/routes/metrics_routes.py,sha256=HiiO_2N4_YZG0xmBaC9iny3yNwIK7lzqqRoC36SuWiE,51054
|
204
201
|
local_deep_research/web/routes/research_routes.py,sha256=H4M_iWStNQUqmhGmMfsFBb-e9wetX6FJVH46J4d0ITE,29054
|
205
202
|
local_deep_research/web/routes/route_registry.py,sha256=4-8hDPSoZme20kXGb3sXCfZR17mEarluhhHEF23MZ0E,10822
|
206
|
-
local_deep_research/web/routes/settings_routes.py,sha256=
|
203
|
+
local_deep_research/web/routes/settings_routes.py,sha256=2oUCDlbLW-OKe49h59OAskNDgkZYRFdJhxVlBSijTQ0,73656
|
207
204
|
local_deep_research/web/services/research_service.py,sha256=H-l37P61VkHENtk2iVdanf96_ocMVIFD6t9PV1XELL4,48166
|
208
205
|
local_deep_research/web/services/resource_service.py,sha256=aU7SDADxcIAAuIymL_TOxUV_HvEMAfL8gZSB5gVSzFM,4674
|
209
|
-
local_deep_research/web/services/settings_manager.py,sha256=
|
210
|
-
local_deep_research/web/services/settings_service.py,sha256=
|
211
|
-
local_deep_research/web/services/socket_service.py,sha256=
|
206
|
+
local_deep_research/web/services/settings_manager.py,sha256=EOdE8rtm4mFV3_4gLfupOtHGlQf6bBAn0m3Xz_t58sY,21235
|
207
|
+
local_deep_research/web/services/settings_service.py,sha256=OemPUMQtb8cfRjG7ZIWVDZ5ZZQTaxdQx4RNrwKgAyDQ,2821
|
208
|
+
local_deep_research/web/services/socket_service.py,sha256=oyO1_S-lFJRIHw06hepheBiz_xYanZ0Fd2gmyGV2hiI,11895
|
212
209
|
local_deep_research/web/static/css/custom_dropdown.css,sha256=MFRm4HaMGM7X2Z-Yvb-_y20BE1NInSmN1cUJc_v5k4k,11542
|
213
210
|
local_deep_research/web/static/css/settings.css,sha256=QZbjLz8zNQZvM_ROzQOH67ZHZHEQ8WohkIPJlsekqfk,24719
|
214
211
|
local_deep_research/web/static/css/styles.css,sha256=u7ZjeXIk_aMwLKLyDAc5lpY6nz9J_I_SaUTZzk6Hk84,37088
|
@@ -284,9 +281,9 @@ local_deep_research/web_search_engines/rate_limiting/__init__.py,sha256=gWBaVMRY
|
|
284
281
|
local_deep_research/web_search_engines/rate_limiting/__main__.py,sha256=9sWZ7ev3dZYPmgKK3K7fEaku2IAnjlrHPbaKV9VlllY,191
|
285
282
|
local_deep_research/web_search_engines/rate_limiting/cli.py,sha256=xX5YD-fNXjdqCaDzx4_aEIoiZFX1AyuQV6Vfya-Wios,5683
|
286
283
|
local_deep_research/web_search_engines/rate_limiting/exceptions.py,sha256=KIzjgVPMxx4sw1J4tjkxz0N9TgrFZGWXQxCemHnVXHI,396
|
287
|
-
local_deep_research/web_search_engines/rate_limiting/tracker.py,sha256=
|
284
|
+
local_deep_research/web_search_engines/rate_limiting/tracker.py,sha256=vvZ0jvi9FbvqrNE0rvoncsXuEXjRwboRpPAcp03bGqk,17520
|
288
285
|
local_deep_research/web_search_engines/retriever_registry.py,sha256=ZErfErn6s1LIQt1q9KjMu61-l7w_D_2jQceQT8kS3xo,3026
|
289
286
|
local_deep_research/web_search_engines/search_engine_base.py,sha256=0ys6nqm4WLTvYqHLZk4x5ZKFTc4BcqhUBjT1m1Jibp0,17114
|
290
287
|
local_deep_research/web_search_engines/search_engine_factory.py,sha256=jKvLkv6rHWSKTnqfLvyvA2WF4qu5qaelgd4IoGOcyVs,12588
|
291
288
|
local_deep_research/web_search_engines/search_engines_config.py,sha256=aZ1Y5YMPWgZqRC-wCJ4JUQgliBNSbU0dOUlCvR_elws,6086
|
292
|
-
local_deep_research-0.6.
|
289
|
+
local_deep_research-0.6.4.dist-info/RECORD,,
|
@@ -1,149 +0,0 @@
|
|
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(
|
64
|
-
"--verbose", action="store_true", help="Enable verbose logging"
|
65
|
-
)
|
66
|
-
|
67
|
-
args = parser.parse_args()
|
68
|
-
|
69
|
-
if args.verbose:
|
70
|
-
logging.getLogger().setLevel(logging.DEBUG)
|
71
|
-
|
72
|
-
print("=" * 80)
|
73
|
-
print("LOCAL DEEP RESEARCH DATABASE MIGRATION")
|
74
|
-
print("=" * 80)
|
75
|
-
|
76
|
-
try:
|
77
|
-
# First try the normal import
|
78
|
-
print(f"Target database will be created at: {DB_PATH}")
|
79
|
-
|
80
|
-
# Check if migration is needed
|
81
|
-
if os.path.exists(DB_PATH) and not args.force:
|
82
|
-
print(f"Target database already exists at: {DB_PATH}")
|
83
|
-
if (
|
84
|
-
input(
|
85
|
-
"Do you want to continue anyway? This may overwrite data. (y/n): "
|
86
|
-
).lower()
|
87
|
-
!= "y"
|
88
|
-
):
|
89
|
-
print("Migration aborted.")
|
90
|
-
return 1
|
91
|
-
|
92
|
-
# Check if source databases exist
|
93
|
-
deep_research_exists = os.path.exists(LEGACY_DEEP_RESEARCH_DB)
|
94
|
-
research_history_exists = os.path.exists(LEGACY_RESEARCH_HISTORY_DB)
|
95
|
-
|
96
|
-
if not deep_research_exists and not research_history_exists:
|
97
|
-
print("No legacy databases found. Nothing to migrate.")
|
98
|
-
return 0
|
99
|
-
|
100
|
-
print("Found legacy databases:")
|
101
|
-
if deep_research_exists:
|
102
|
-
print(f" - {LEGACY_DEEP_RESEARCH_DB}")
|
103
|
-
if research_history_exists:
|
104
|
-
print(f" - {LEGACY_RESEARCH_HISTORY_DB}")
|
105
|
-
|
106
|
-
# Create backups if requested
|
107
|
-
if args.backup:
|
108
|
-
if deep_research_exists:
|
109
|
-
backup_path = f"{LEGACY_DEEP_RESEARCH_DB}.bak"
|
110
|
-
import shutil
|
111
|
-
|
112
|
-
shutil.copy2(LEGACY_DEEP_RESEARCH_DB, backup_path)
|
113
|
-
print(f"Created backup: {backup_path}")
|
114
|
-
|
115
|
-
if research_history_exists:
|
116
|
-
backup_path = f"{LEGACY_RESEARCH_HISTORY_DB}.bak"
|
117
|
-
import shutil
|
118
|
-
|
119
|
-
shutil.copy2(LEGACY_RESEARCH_HISTORY_DB, backup_path)
|
120
|
-
print(f"Created backup: {backup_path}")
|
121
|
-
|
122
|
-
# Run migration or dry run
|
123
|
-
if args.dry_run:
|
124
|
-
print("\nDRY RUN - No changes will be made.")
|
125
|
-
print(f"Would migrate data to: {DB_PATH}")
|
126
|
-
return 0
|
127
|
-
else:
|
128
|
-
print(f"\nStarting migration to: {DB_PATH}")
|
129
|
-
|
130
|
-
success = migrate_to_ldr_db()
|
131
|
-
|
132
|
-
if success:
|
133
|
-
print("\nMigration completed successfully.")
|
134
|
-
print(
|
135
|
-
"You can now start the application with the new unified database."
|
136
|
-
)
|
137
|
-
return 0
|
138
|
-
else:
|
139
|
-
print("\nMigration failed. Check the logs for details.")
|
140
|
-
return 1
|
141
|
-
|
142
|
-
except Exception as e:
|
143
|
-
logger.error(f"Migration error: {e}", exc_info=True)
|
144
|
-
print(f"Error during migration: {e}")
|
145
|
-
return 1
|
146
|
-
|
147
|
-
|
148
|
-
if __name__ == "__main__":
|
149
|
-
sys.exit(main())
|