local-deep-research 0.3.6__tar.gz → 0.3.8__tar.gz
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-0.3.6 → local_deep_research-0.3.8}/PKG-INFO +13 -7
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/README.md +12 -6
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/pyproject.toml +1 -1
- local_deep_research-0.3.8/src/local_deep_research/__version__.py +1 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/defaults/default_settings.json +9 -9
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/search_system.py +5 -2
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/utilities/db_utils.py +5 -9
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/services/settings_manager.py +12 -5
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_searxng.py +17 -22
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/search_engines_config.py +16 -9
- local_deep_research-0.3.8/tests/fix_tests/README.md +36 -0
- local_deep_research-0.3.8/tests/fix_tests/test_duplicate_links_fix.py +102 -0
- local_deep_research-0.3.6/src/local_deep_research/__version__.py +0 -1
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/LICENSE +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/__main__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/filters/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/filters/base_filter.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/filters/cross_engine_filter.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/findings/base_findings.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/findings/repository.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/knowledge/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/knowledge/base_knowledge.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/knowledge/standard_knowledge.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/questions/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/questions/base_question.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/questions/decomposition_question.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/questions/standard_question.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/repositories/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/strategies/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/strategies/base_strategy.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/strategies/iterdrag_strategy.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/strategies/parallel_search_strategy.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/strategies/rapid_search_strategy.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/strategies/source_based_strategy.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/strategies/standard_strategy.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/tools/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/tools/base_tool.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/tools/knowledge_tools/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/tools/question_tools/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/advanced_search_system/tools/search_tools/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/api/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/api/research_functions.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/app.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/citation_handler.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/config/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/config/llm_config.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/config/search_config.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/defaults/.env.template +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/defaults/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/main.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/migrate_db.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/report_generator.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/setup_data_dir.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/test_migration.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/utilities/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/utilities/enums.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/utilities/llm_utils.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/utilities/search_utilities.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/utilities/setup_utils.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/app.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/app_factory.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/database/README.md +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/database/migrate_to_ldr_db.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/database/migrations.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/database/models.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/database/schema_upgrade.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/models/database.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/models/settings.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/routes/api_routes.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/routes/history_routes.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/routes/research_routes.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/routes/settings_routes.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/services/research_service.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/services/resource_service.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/services/settings_service.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/services/socket_service.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/css/custom_dropdown.css +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/css/settings.css +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/css/styles.css +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/components/custom_dropdown.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/components/detail.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/components/fallback/formatting.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/components/fallback/ui.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/components/history.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/components/logpanel.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/components/progress.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/components/research.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/components/results.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/components/settings.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/components/settings_sync.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/main.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/research_form.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/services/api.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/services/audio.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/services/formatting.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/services/pdf.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/services/socket.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/js/services/ui.js +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/sounds/README.md +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/sounds/error.mp3 +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/static/sounds/success.mp3 +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/templates/base.html +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/templates/components/custom_dropdown.html +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/templates/components/log_panel.html +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/templates/components/mobile_nav.html +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/templates/components/settings_form.html +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/templates/components/sidebar.html +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/templates/pages/details.html +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/templates/pages/history.html +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/templates/pages/progress.html +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/templates/pages/research.html +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/templates/pages/results.html +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/templates/settings_dashboard.html +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/utils/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/utils/formatters.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/utils/templates.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/full_search.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/meta_search_engine.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_arxiv.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_brave.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_ddg.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_github.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_google_pse.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_guardian.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_local.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_local_all.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_pubmed.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_semantic_scholar.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_serpapi.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_wayback.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/engines/search_engine_wikipedia.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/search_engine_base.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web_search_engines/search_engine_factory.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/tests/__init__.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/tests/download_stuff_for_local_test.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/tests/searxng/test_searxng_instance.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/tests/searxng/test_searxng_integration.py +0 -0
- {local_deep_research-0.3.6 → local_deep_research-0.3.8}/tests/test_google_pse.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: local-deep-research
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.8
|
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>
|
6
6
|
License: MIT License
|
@@ -80,9 +80,14 @@ Description-Content-Type: text/markdown
|
|
80
80
|
|
81
81
|
*AI-powered research assistant that performs deep, iterative analysis using multiple LLMs and web searches*
|
82
82
|
|
83
|
-
<
|
84
|
-
<
|
85
|
-
|
83
|
+
<div align="center">
|
84
|
+
<a href="https://www.youtube.com/watch?v=0ISreg9q0p0">
|
85
|
+
<img src="https://img.youtube.com/vi/0ISreg9q0p0/0.jpg" alt="Local Deep Research">
|
86
|
+
<br>
|
87
|
+
<span>▶️ Watch Video</span>
|
88
|
+
</a>
|
89
|
+
</div>
|
90
|
+
|
86
91
|
|
87
92
|
</div>
|
88
93
|
|
@@ -167,6 +172,7 @@ print(results["summary"])
|
|
167
172
|
|
168
173
|
**Windows**: Docker is the easiest option for Windows users. If preferred, a [Windows Installer](https://github.com/LearningCircuit/local-deep-research/releases/download/v0.1.0/LocalDeepResearch_Setup.exe) is also available.
|
169
174
|
|
175
|
+
For more information on installation options, see [the wiki](https://github.com/LearningCircuit/local-deep-research/wiki/Installation).
|
170
176
|
|
171
177
|
## 🔍 Research Capabilities
|
172
178
|
|
@@ -273,9 +279,9 @@ For enhanced web search capabilities, you can configure these additional engines
|
|
273
279
|
|
274
280
|
```bash
|
275
281
|
# Search API keys (if not using the web UI)
|
276
|
-
|
277
|
-
|
278
|
-
|
282
|
+
LDR_SEARCH_ENGINE_WEB_SERPAPI_API_KEY=your-key-here # Google results via SerpAPI
|
283
|
+
LDR_SEARCH_ENGINE_WEB_GOOGLE_PSE_API_KEY=your-key-here # Google Programmable Search
|
284
|
+
LDR_SEARCH_ENGINE_WEB_BRAVE_API_KEY=your-key-here # Brave Search
|
279
285
|
```
|
280
286
|
|
281
287
|
### Search Engine Comparison
|
@@ -9,9 +9,14 @@
|
|
9
9
|
|
10
10
|
*AI-powered research assistant that performs deep, iterative analysis using multiple LLMs and web searches*
|
11
11
|
|
12
|
-
<
|
13
|
-
<
|
14
|
-
|
12
|
+
<div align="center">
|
13
|
+
<a href="https://www.youtube.com/watch?v=0ISreg9q0p0">
|
14
|
+
<img src="https://img.youtube.com/vi/0ISreg9q0p0/0.jpg" alt="Local Deep Research">
|
15
|
+
<br>
|
16
|
+
<span>▶️ Watch Video</span>
|
17
|
+
</a>
|
18
|
+
</div>
|
19
|
+
|
15
20
|
|
16
21
|
</div>
|
17
22
|
|
@@ -96,6 +101,7 @@ print(results["summary"])
|
|
96
101
|
|
97
102
|
**Windows**: Docker is the easiest option for Windows users. If preferred, a [Windows Installer](https://github.com/LearningCircuit/local-deep-research/releases/download/v0.1.0/LocalDeepResearch_Setup.exe) is also available.
|
98
103
|
|
104
|
+
For more information on installation options, see [the wiki](https://github.com/LearningCircuit/local-deep-research/wiki/Installation).
|
99
105
|
|
100
106
|
## 🔍 Research Capabilities
|
101
107
|
|
@@ -202,9 +208,9 @@ For enhanced web search capabilities, you can configure these additional engines
|
|
202
208
|
|
203
209
|
```bash
|
204
210
|
# Search API keys (if not using the web UI)
|
205
|
-
|
206
|
-
|
207
|
-
|
211
|
+
LDR_SEARCH_ENGINE_WEB_SERPAPI_API_KEY=your-key-here # Google results via SerpAPI
|
212
|
+
LDR_SEARCH_ENGINE_WEB_GOOGLE_PSE_API_KEY=your-key-here # Google Programmable Search
|
213
|
+
LDR_SEARCH_ENGINE_WEB_BRAVE_API_KEY=your-key-here # Brave Search
|
208
214
|
```
|
209
215
|
|
210
216
|
### Search Engine Comparison
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.3.8"
|
@@ -2927,32 +2927,32 @@
|
|
2927
2927
|
"value": "A locally-hosted meta-search engine.",
|
2928
2928
|
"visible": false
|
2929
2929
|
},
|
2930
|
-
"search.engine.web.searxng.
|
2930
|
+
"search.engine.web.searxng.class_name": {
|
2931
2931
|
"category": "searxng",
|
2932
|
-
"description": "
|
2932
|
+
"description": "Setting for searxng.class_name",
|
2933
2933
|
"editable": true,
|
2934
2934
|
"max_value": null,
|
2935
2935
|
"min_value": null,
|
2936
|
-
"name": "
|
2936
|
+
"name": "Class Name",
|
2937
2937
|
"options": null,
|
2938
2938
|
"step": null,
|
2939
2939
|
"type": "SEARCH",
|
2940
|
-
"ui_element": "
|
2941
|
-
"value": "
|
2940
|
+
"ui_element": "text",
|
2941
|
+
"value": "SearXNGSearchEngine",
|
2942
2942
|
"visible": true
|
2943
2943
|
},
|
2944
|
-
"search.engine.web.searxng.
|
2944
|
+
"search.engine.web.searxng.default_params.instance_url": {
|
2945
2945
|
"category": "searxng",
|
2946
|
-
"description": "
|
2946
|
+
"description": "The SearXNG API endpoint URL.",
|
2947
2947
|
"editable": true,
|
2948
2948
|
"max_value": null,
|
2949
2949
|
"min_value": null,
|
2950
|
-
"name": "
|
2950
|
+
"name": "Endpoint URL",
|
2951
2951
|
"options": null,
|
2952
2952
|
"step": null,
|
2953
2953
|
"type": "SEARCH",
|
2954
2954
|
"ui_element": "text",
|
2955
|
-
"value": "
|
2955
|
+
"value": "http://localhost:8080",
|
2956
2956
|
"visible": true
|
2957
2957
|
},
|
2958
2958
|
"search.engine.web.searxng.default_params.categories": {
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/search_system.py
RENAMED
@@ -180,8 +180,11 @@ class AdvancedSearchSystem:
|
|
180
180
|
self.questions_by_iteration = self.strategy.questions_by_iteration.copy()
|
181
181
|
# Send progress message with search info
|
182
182
|
|
183
|
-
# if
|
184
|
-
|
183
|
+
# Only extend if they're different objects in memory to avoid duplication
|
184
|
+
# This check prevents doubling the list when they reference the same object
|
185
|
+
# Fix for issue #301: "too many links in detailed report mode"
|
186
|
+
if id(self.all_links_of_system) != id(self.strategy.all_links_of_system):
|
187
|
+
self.all_links_of_system.extend(self.strategy.all_links_of_system)
|
185
188
|
|
186
189
|
# Include the search system instance for access to citations
|
187
190
|
result["search_system"] = self
|
@@ -6,7 +6,7 @@ from typing import Any, Dict
|
|
6
6
|
from sqlalchemy import create_engine
|
7
7
|
from sqlalchemy.orm import Session, sessionmaker
|
8
8
|
|
9
|
-
from ..web.services.settings_manager import SettingsManager
|
9
|
+
from ..web.services.settings_manager import SettingsManager
|
10
10
|
|
11
11
|
logger = logging.getLogger(__name__)
|
12
12
|
|
@@ -38,7 +38,7 @@ def get_settings_manager() -> SettingsManager:
|
|
38
38
|
|
39
39
|
|
40
40
|
def get_db_setting(
|
41
|
-
key: str, default_value: Any | None = None
|
41
|
+
key: str, default_value: Any | None = None
|
42
42
|
) -> str | Dict[str, Any] | None:
|
43
43
|
"""
|
44
44
|
Get a setting from the database with fallback to default value
|
@@ -46,15 +46,11 @@ def get_db_setting(
|
|
46
46
|
Args:
|
47
47
|
key: The setting key.
|
48
48
|
default_value: If the setting is not found, it will return this instead.
|
49
|
-
check_env: If true, it will check the corresponding environment
|
50
|
-
variable before checking the DB and return that if it is set.
|
51
49
|
|
52
|
-
|
53
|
-
|
54
|
-
env_value = check_env_setting(key)
|
55
|
-
if env_value is not None:
|
56
|
-
return env_value
|
50
|
+
Returns:
|
51
|
+
The setting value.
|
57
52
|
|
53
|
+
"""
|
58
54
|
try:
|
59
55
|
# Get settings manager which handles database access
|
60
56
|
value = get_settings_manager().get_setting(key)
|
@@ -94,11 +94,18 @@ class SettingsManager:
|
|
94
94
|
return value
|
95
95
|
elif len(settings) > 1:
|
96
96
|
# This is a higher-level key.
|
97
|
-
settings_map = {
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
97
|
+
settings_map = {}
|
98
|
+
for setting in settings:
|
99
|
+
output_key = setting.key.removeprefix(f"{key}.")
|
100
|
+
value = setting.value
|
101
|
+
|
102
|
+
if check_env:
|
103
|
+
# Handle possible replacements from environment variables.
|
104
|
+
env_value = check_env_setting(setting.key)
|
105
|
+
if env_value is not None:
|
106
|
+
value = env_value
|
107
|
+
|
108
|
+
settings_map[output_key] = value
|
102
109
|
return settings_map
|
103
110
|
except SQLAlchemyError as e:
|
104
111
|
logger.error(f"Error retrieving setting {key} from database: {e}")
|
@@ -25,7 +25,7 @@ class SearXNGSearchEngine(BaseSearchEngine):
|
|
25
25
|
def __init__(
|
26
26
|
self,
|
27
27
|
max_results: int = 15,
|
28
|
-
instance_url:
|
28
|
+
instance_url: str = "http://localhost:8080",
|
29
29
|
categories: Optional[List[str]] = None,
|
30
30
|
engines: Optional[List[str]] = None,
|
31
31
|
language: str = "en",
|
@@ -35,7 +35,6 @@ class SearXNGSearchEngine(BaseSearchEngine):
|
|
35
35
|
llm: Optional[BaseLLM] = None,
|
36
36
|
max_filtered_results: Optional[int] = None,
|
37
37
|
include_full_content: bool = True,
|
38
|
-
api_key: Optional[str] = None,
|
39
38
|
): # API key is actually the instance URL
|
40
39
|
"""
|
41
40
|
Initialize the SearXNG search engine with ethical usage patterns.
|
@@ -52,7 +51,6 @@ class SearXNGSearchEngine(BaseSearchEngine):
|
|
52
51
|
llm: Language model for relevance filtering
|
53
52
|
max_filtered_results: Maximum number of results to keep after filtering
|
54
53
|
include_full_content: Whether to include full webpage content in results
|
55
|
-
api_key: Alternative way to provide instance URL (takes precedence over instance_url)
|
56
54
|
"""
|
57
55
|
|
58
56
|
# Initialize the BaseSearchEngine with LLM, max_filtered_results, and max_results
|
@@ -60,28 +58,25 @@ class SearXNGSearchEngine(BaseSearchEngine):
|
|
60
58
|
llm=llm, max_filtered_results=max_filtered_results, max_results=max_results
|
61
59
|
)
|
62
60
|
|
63
|
-
|
64
|
-
# 1. api_key parameter (which is actually the instance URL)
|
65
|
-
# 2. SEARXNG_INSTANCE environment variable
|
66
|
-
# 3. instance_url parameter
|
67
|
-
# 4. Default to None, which will disable the engine
|
68
|
-
self.instance_url = api_key or os.getenv("SEARXNG_INSTANCE") or instance_url or "http://localhost:8080"
|
69
|
-
|
70
|
-
# Add debug logging for instance URL
|
71
|
-
logger.info(
|
72
|
-
f"SearXNG init - Instance URL sources: api_key={api_key}, env={os.getenv('SEARXNG_INSTANCE')}, param={instance_url}"
|
73
|
-
)
|
74
|
-
|
61
|
+
self.instance_url = instance_url
|
75
62
|
# Validate and normalize the instance URL if provided
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
63
|
+
self.instance_url = self.instance_url.rstrip("/")
|
64
|
+
logger.info(f"SearXNG initialized with instance URL: {self.instance_url}")
|
65
|
+
try:
|
66
|
+
# Make sure it's accessible.
|
67
|
+
response = requests.get(self.instance_url, timeout=5)
|
68
|
+
if response.status_code == 200:
|
69
|
+
logger.info("SearXNG instance is accessible.")
|
70
|
+
self.is_available = True
|
71
|
+
else:
|
72
|
+
self.is_available = False
|
73
|
+
logger.error(
|
74
|
+
f"Failed to access SearXNG instance at {self.instance_url}. Status code: {response.status_code}"
|
75
|
+
)
|
76
|
+
except requests.RequestException as e:
|
81
77
|
self.is_available = False
|
82
78
|
logger.error(
|
83
|
-
"
|
84
|
-
"Set SEARXNG_INSTANCE environment variable or provide instance_url parameter."
|
79
|
+
f"Error while trying to access SearXNG instance at {self.instance_url}: {str(e)}"
|
85
80
|
)
|
86
81
|
|
87
82
|
# Add debug logging for all parameters
|
@@ -5,7 +5,6 @@ Loads search engine definitions from the user's configuration.
|
|
5
5
|
|
6
6
|
import json
|
7
7
|
import logging
|
8
|
-
from functools import cache
|
9
8
|
from typing import Any, Dict, List
|
10
9
|
|
11
10
|
from ..utilities.db_utils import get_db_setting
|
@@ -25,16 +24,26 @@ def _extract_per_engine_config(raw_config: Dict[str, Any]) -> Dict[str, Dict[str
|
|
25
24
|
Configuration dictionaries indexed by engine name.
|
26
25
|
|
27
26
|
"""
|
28
|
-
|
27
|
+
nested_config = {}
|
29
28
|
for key, value in raw_config.items():
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
if "." in key:
|
30
|
+
# This is a higher-level key.
|
31
|
+
top_level_key = key.split(".")[0]
|
32
|
+
lower_keys = ".".join(key.split(".")[1:])
|
33
|
+
nested_config.setdefault(top_level_key, {})[lower_keys] = value
|
34
|
+
else:
|
35
|
+
# This is a low-level key.
|
36
|
+
nested_config[key] = value
|
33
37
|
|
34
|
-
|
38
|
+
# Expand all the lower-level keys.
|
39
|
+
for key, value in nested_config.items():
|
40
|
+
if isinstance(value, dict):
|
41
|
+
# Expand the child keys.
|
42
|
+
nested_config[key] = _extract_per_engine_config(value)
|
43
|
+
|
44
|
+
return nested_config
|
35
45
|
|
36
46
|
|
37
|
-
@cache
|
38
47
|
def search_config() -> Dict[str, Any]:
|
39
48
|
"""
|
40
49
|
Returns:
|
@@ -105,7 +114,6 @@ def search_config() -> Dict[str, Any]:
|
|
105
114
|
return search_engines
|
106
115
|
|
107
116
|
|
108
|
-
@cache
|
109
117
|
def default_search_engine() -> str:
|
110
118
|
"""
|
111
119
|
Returns:
|
@@ -115,7 +123,6 @@ def default_search_engine() -> str:
|
|
115
123
|
return get_db_setting("search.engine.DEFAULT_SEARCH_ENGINE", "wikipedia")
|
116
124
|
|
117
125
|
|
118
|
-
@cache
|
119
126
|
def local_search_engines() -> List[str]:
|
120
127
|
"""
|
121
128
|
Returns:
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Fix Tests
|
2
|
+
|
3
|
+
This directory contains tests for specific bug fixes in the codebase.
|
4
|
+
|
5
|
+
## Tests
|
6
|
+
|
7
|
+
### test_duplicate_links_fix.py
|
8
|
+
|
9
|
+
Demonstrates and tests the fix for GitHub issue [#301](https://github.com/LearningCircuit/local-deep-research/issues/301) - "too many links in detailed report mode".
|
10
|
+
|
11
|
+
The test simulates the bug where links are duplicated in the `all_links_of_system` list when using detailed report mode. It compares the behavior before and after implementing the fix.
|
12
|
+
|
13
|
+
#### Bug Description
|
14
|
+
|
15
|
+
The bug occurred because `search_system.py` was unconditionally extending `self.all_links_of_system` with `self.strategy.all_links_of_system` in the `analyze_topic` method, even though they were the same list object (when initialized with the same reference).
|
16
|
+
|
17
|
+
#### Fix
|
18
|
+
|
19
|
+
The fix checks if the lists are the same object (have the same `id()`) before extending:
|
20
|
+
|
21
|
+
```python
|
22
|
+
# Only extend if they're different objects in memory to avoid duplication
|
23
|
+
if id(self.all_links_of_system) != id(self.strategy.all_links_of_system):
|
24
|
+
self.all_links_of_system.extend(self.strategy.all_links_of_system)
|
25
|
+
```
|
26
|
+
|
27
|
+
This prevents duplicating the content when both lists are actually the same object.
|
28
|
+
|
29
|
+
#### Running the Test
|
30
|
+
|
31
|
+
```bash
|
32
|
+
cd tests/fix_tests
|
33
|
+
python test_duplicate_links_fix.py
|
34
|
+
```
|
35
|
+
|
36
|
+
The test demonstrates both the bug and the fixed behavior side-by-side.
|
@@ -0,0 +1,102 @@
|
|
1
|
+
"""
|
2
|
+
Test script to demonstrate the duplicate links issue and our fix for issue #301.
|
3
|
+
|
4
|
+
This test demonstrates the problem where the search system duplicates links in detailed report mode
|
5
|
+
by unconditionally extending the all_links_of_system list with itself.
|
6
|
+
|
7
|
+
GitHub issue: https://github.com/LearningCircuit/local-deep-research/issues/301
|
8
|
+
|
9
|
+
The fix is to check if the lists are the same object (have the same id()) before extending.
|
10
|
+
"""
|
11
|
+
|
12
|
+
class Strategy:
|
13
|
+
def __init__(self, all_links=None):
|
14
|
+
# Create a new list if None is provided
|
15
|
+
self.all_links_of_system = [] if all_links is None else all_links
|
16
|
+
print(f"Strategy initialized with list id: {id(self.all_links_of_system)}")
|
17
|
+
|
18
|
+
def analyze_topic(self, query):
|
19
|
+
# Add some links
|
20
|
+
self.all_links_of_system.extend([
|
21
|
+
{"title": "Link 1", "link": "http://example.com/1"},
|
22
|
+
{"title": "Link 2", "link": "http://example.com/2"},
|
23
|
+
])
|
24
|
+
print(f"Strategy now has {len(self.all_links_of_system)} links")
|
25
|
+
return {"content": "Analysis results"}
|
26
|
+
|
27
|
+
class AdvancedSearchSystem:
|
28
|
+
def __init__(self):
|
29
|
+
# Initialize with empty list
|
30
|
+
self.all_links_of_system = []
|
31
|
+
print(f"Search system initialized with list id: {id(self.all_links_of_system)}")
|
32
|
+
|
33
|
+
# Create strategy with our list reference
|
34
|
+
self.strategy = Strategy(all_links=self.all_links_of_system)
|
35
|
+
|
36
|
+
# Check if they're the same object
|
37
|
+
print(f"Are lists the same object? {id(self.all_links_of_system) == id(self.strategy.all_links_of_system)}")
|
38
|
+
|
39
|
+
def analyze_topic_with_bug(self, query):
|
40
|
+
# Run the strategy
|
41
|
+
result = self.strategy.analyze_topic(query)
|
42
|
+
|
43
|
+
# BUG: Unconditionally extend our list with the strategy's list
|
44
|
+
# This is problematic because they're the same list
|
45
|
+
print("\nBUG DEMO: Extending unconditionally")
|
46
|
+
before_count = len(self.all_links_of_system)
|
47
|
+
print(f"Before extending: {before_count} links")
|
48
|
+
|
49
|
+
self.all_links_of_system.extend(self.strategy.all_links_of_system)
|
50
|
+
|
51
|
+
after_count = len(self.all_links_of_system)
|
52
|
+
print(f"After extending: {after_count} links")
|
53
|
+
print(f"Added {after_count - before_count} links (duplicates)")
|
54
|
+
|
55
|
+
# Return results
|
56
|
+
return {
|
57
|
+
"all_links_of_system": self.all_links_of_system,
|
58
|
+
"content": result["content"]
|
59
|
+
}
|
60
|
+
|
61
|
+
def analyze_topic_with_fix(self, query):
|
62
|
+
# Run the strategy
|
63
|
+
result = self.strategy.analyze_topic(query)
|
64
|
+
|
65
|
+
# FIX: Only extend if they're different objects
|
66
|
+
print("\nFIX DEMO: Only extending if lists are different")
|
67
|
+
before_count = len(self.all_links_of_system)
|
68
|
+
print(f"Before fix check: {before_count} links")
|
69
|
+
|
70
|
+
if id(self.all_links_of_system) != id(self.strategy.all_links_of_system):
|
71
|
+
print("Lists are different objects - extending")
|
72
|
+
self.all_links_of_system.extend(self.strategy.all_links_of_system)
|
73
|
+
else:
|
74
|
+
print("Lists are the same object - not extending (avoiding duplicates)")
|
75
|
+
|
76
|
+
after_count = len(self.all_links_of_system)
|
77
|
+
print(f"After fix check: {after_count} links")
|
78
|
+
print(f"Added {after_count - before_count} links")
|
79
|
+
|
80
|
+
# Return results
|
81
|
+
return {
|
82
|
+
"all_links_of_system": self.all_links_of_system,
|
83
|
+
"content": result["content"]
|
84
|
+
}
|
85
|
+
|
86
|
+
def test_bug_and_fix():
|
87
|
+
print("=== Testing Bug and Fix ===\n")
|
88
|
+
|
89
|
+
print("1. Creating first search system to demonstrate the bug:")
|
90
|
+
search_system1 = AdvancedSearchSystem()
|
91
|
+
result1 = search_system1.analyze_topic_with_bug("What is quantum computing?")
|
92
|
+
print(f"\nFinal link count with bug: {len(result1['all_links_of_system'])}")
|
93
|
+
|
94
|
+
print("\n2. Creating second search system to demonstrate the fix:")
|
95
|
+
search_system2 = AdvancedSearchSystem()
|
96
|
+
result2 = search_system2.analyze_topic_with_fix("What is quantum computing?")
|
97
|
+
print(f"\nFinal link count with fix: {len(result2['all_links_of_system'])}")
|
98
|
+
|
99
|
+
print("\nTest complete!")
|
100
|
+
|
101
|
+
if __name__ == "__main__":
|
102
|
+
test_bug_and_fix()
|
@@ -1 +0,0 @@
|
|
1
|
-
__version__ = "0.3.6"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/api/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/citation_handler.py
RENAMED
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/config/__init__.py
RENAMED
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/config/llm_config.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/defaults/__init__.py
RENAMED
File without changes
|
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/migrate_db.py
RENAMED
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/report_generator.py
RENAMED
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/setup_data_dir.py
RENAMED
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/test_migration.py
RENAMED
File without changes
|
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/utilities/enums.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/__init__.py
RENAMED
File without changes
|
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/src/local_deep_research/web/app_factory.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/tests/download_stuff_for_local_test.py
RENAMED
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/tests/searxng/test_searxng_instance.py
RENAMED
File without changes
|
{local_deep_research-0.3.6 → local_deep_research-0.3.8}/tests/searxng/test_searxng_integration.py
RENAMED
File without changes
|
File without changes
|