local-deep-research 0.3.11__tar.gz → 0.4.0__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.11 → local_deep_research-0.4.0}/PKG-INFO +29 -4
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/README.md +19 -2
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/pyproject.toml +13 -2
- local_deep_research-0.4.0/src/local_deep_research/__version__.py +1 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/filters/base_filter.py +2 -3
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/filters/cross_engine_filter.py +4 -5
- local_deep_research-0.4.0/src/local_deep_research/advanced_search_system/filters/journal_reputation_filter.py +298 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/findings/repository.py +0 -3
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/strategies/base_strategy.py +1 -2
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/strategies/iterdrag_strategy.py +14 -18
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/strategies/parallel_search_strategy.py +4 -8
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/strategies/rapid_search_strategy.py +5 -6
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/strategies/source_based_strategy.py +2 -2
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/strategies/standard_strategy.py +9 -7
- local_deep_research-0.4.0/src/local_deep_research/api/benchmark_functions.py +288 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/api/research_functions.py +8 -4
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/README.md +162 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/__init__.py +51 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/benchmark_functions.py +353 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/cli/__init__.py +16 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/cli/benchmark_commands.py +338 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/cli.py +347 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/comparison/__init__.py +12 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/comparison/evaluator.py +768 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/datasets/__init__.py +53 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/datasets/base.py +295 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/datasets/browsecomp.py +116 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/datasets/custom_dataset_template.py +98 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/datasets/simpleqa.py +74 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/datasets/utils.py +116 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/datasets.py +31 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/efficiency/__init__.py +14 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/efficiency/resource_monitor.py +367 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/efficiency/speed_profiler.py +214 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/evaluators/__init__.py +18 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/evaluators/base.py +74 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/evaluators/browsecomp.py +83 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/evaluators/composite.py +121 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/evaluators/simpleqa.py +271 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/graders.py +410 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/metrics/README.md +80 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/metrics/__init__.py +24 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/metrics/calculation.py +385 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/metrics/reporting.py +155 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/metrics/visualization.py +205 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/metrics.py +11 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/optimization/__init__.py +32 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/optimization/api.py +274 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/optimization/metrics.py +20 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/optimization/optuna_optimizer.py +1163 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/runners.py +434 -0
- local_deep_research-0.4.0/src/local_deep_research/benchmarks/templates.py +65 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/config/llm_config.py +37 -25
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/config/search_config.py +2 -6
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/defaults/default_settings.json +109 -8
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/search_system.py +16 -8
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/utilities/db_utils.py +3 -6
- local_deep_research-0.4.0/src/local_deep_research/utilities/es_utils.py +441 -0
- local_deep_research-0.4.0/src/local_deep_research/utilities/log_utils.py +36 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/utilities/search_utilities.py +8 -9
- local_deep_research-0.4.0/src/local_deep_research/utilities/url_utils.py +57 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/app.py +7 -9
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/app_factory.py +9 -12
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/database/migrations.py +8 -5
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/database/models.py +20 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/database/schema_upgrade.py +5 -8
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/models/database.py +15 -18
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/routes/api_routes.py +18 -9
- local_deep_research-0.4.0/src/local_deep_research/web/routes/benchmark_routes.py +427 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/routes/research_routes.py +13 -17
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/routes/settings_routes.py +279 -72
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/services/research_service.py +47 -57
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/services/settings_manager.py +1 -4
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/services/settings_service.py +4 -6
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/css/styles.css +12 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/components/logpanel.js +164 -155
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/components/research.js +44 -3
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/components/settings.js +27 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/services/socket.js +47 -0
- local_deep_research-0.4.0/src/local_deep_research/web_search_engines/default_search_engines.py +38 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/meta_search_engine.py +100 -33
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_arxiv.py +31 -17
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_brave.py +8 -3
- local_deep_research-0.4.0/src/local_deep_research/web_search_engines/engines/search_engine_elasticsearch.py +343 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_google_pse.py +14 -6
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_local.py +31 -26
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_local_all.py +9 -12
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_searxng.py +12 -17
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_serpapi.py +8 -4
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/search_engine_base.py +22 -5
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/search_engine_factory.py +32 -11
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/search_engines_config.py +14 -1
- local_deep_research-0.4.0/tests/TESTING_PROPOSAL.md +294 -0
- local_deep_research-0.4.0/tests/feature_tests/IMPLEMENTATION_GUIDE_241.md +114 -0
- local_deep_research-0.4.0/tests/feature_tests/README.md +26 -0
- local_deep_research-0.4.0/tests/feature_tests/__init__.py +5 -0
- local_deep_research-0.4.0/tests/feature_tests/test_custom_context.py +139 -0
- local_deep_research-0.4.0/tests/test_settings_manager.py +98 -0
- local_deep_research-0.4.0/tests/test_url_utils.py +55 -0
- local_deep_research-0.4.0/tests/test_url_utils_debug.py +33 -0
- local_deep_research-0.4.0/tests/test_url_utils_simple.py +39 -0
- local_deep_research-0.3.11/src/local_deep_research/__version__.py +0 -1
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/LICENSE +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/filters/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/findings/base_findings.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/knowledge/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/knowledge/base_knowledge.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/knowledge/standard_knowledge.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/questions/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/questions/base_question.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/questions/decomposition_question.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/questions/standard_question.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/repositories/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/strategies/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/tools/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/tools/base_tool.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/tools/knowledge_tools/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/tools/question_tools/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/advanced_search_system/tools/search_tools/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/api/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/app.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/citation_handler.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/config/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/defaults/.env.template +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/defaults/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/migrate_db.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/report_generator.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/setup_data_dir.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/test_migration.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/utilities/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/utilities/enums.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/utilities/llm_utils.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/utilities/setup_utils.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/database/README.md +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/database/migrate_to_ldr_db.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/models/settings.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/routes/history_routes.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/services/resource_service.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/services/socket_service.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/css/custom_dropdown.css +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/css/settings.css +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/components/custom_dropdown.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/components/detail.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/components/fallback/formatting.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/components/fallback/ui.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/components/history.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/components/progress.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/components/results.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/components/settings_sync.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/main.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/research_form.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/services/api.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/services/audio.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/services/formatting.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/services/pdf.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/js/services/ui.js +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/sounds/README.md +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/sounds/error.mp3 +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/static/sounds/success.mp3 +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/templates/base.html +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/templates/components/custom_dropdown.html +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/templates/components/log_panel.html +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/templates/components/mobile_nav.html +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/templates/components/settings_form.html +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/templates/components/sidebar.html +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/templates/pages/details.html +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/templates/pages/history.html +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/templates/pages/progress.html +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/templates/pages/research.html +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/templates/pages/results.html +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/templates/settings_dashboard.html +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/utils/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/utils/formatters.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web/utils/templates.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/full_search.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_ddg.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_github.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_guardian.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_pubmed.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_semantic_scholar.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_wayback.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/src/local_deep_research/web_search_engines/engines/search_engine_wikipedia.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/tests/__init__.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/tests/download_stuff_for_local_test.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/tests/fix_tests/README.md +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/tests/fix_tests/test_duplicate_links_fix.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/tests/searxng/test_searxng_instance.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/tests/searxng/test_searxng_integration.py +0 -0
- {local_deep_research-0.3.11 → local_deep_research-0.4.0}/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
|
+
Version: 0.4.0
|
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
|
@@ -36,7 +36,7 @@ Requires-Dist: langchain-community>=0.3.17
|
|
36
36
|
Requires-Dist: langchain-core>=0.3.34
|
37
37
|
Requires-Dist: langchain-ollama>=0.2.3
|
38
38
|
Requires-Dist: langchain-openai>=0.3.5
|
39
|
-
Requires-Dist:
|
39
|
+
Requires-Dist: langchain-anthropic>=0.3.13
|
40
40
|
Requires-Dist: duckduckgo_search>=7.3.2
|
41
41
|
Requires-Dist: python-dateutil>=2.9.0
|
42
42
|
Requires-Dist: typing_extensions>=4.12.2
|
@@ -67,6 +67,14 @@ Requires-Dist: google-search-results
|
|
67
67
|
Requires-Dist: importlib-resources>=6.5.2
|
68
68
|
Requires-Dist: setuptools>=78.1.0
|
69
69
|
Requires-Dist: flask-wtf>=1.2.2
|
70
|
+
Requires-Dist: optuna>=4.3.0
|
71
|
+
Requires-Dist: elasticsearch==8.14.0
|
72
|
+
Requires-Dist: methodtools>=0.4.7
|
73
|
+
Requires-Dist: loguru>=0.7.3
|
74
|
+
Requires-Dist: matplotlib>=3.10.3
|
75
|
+
Requires-Dist: pandas>=2.2.3
|
76
|
+
Requires-Dist: plotly>=6.0.1
|
77
|
+
Requires-Dist: kaleido==0.1.0
|
70
78
|
Description-Content-Type: text/markdown
|
71
79
|
|
72
80
|
# Local Deep Research
|
@@ -106,7 +114,24 @@ Local Deep Research combines the power of large language models with intelligent
|
|
106
114
|
|
107
115
|
## ⚡ Quick Start
|
108
116
|
|
109
|
-
### Option 1: Docker (
|
117
|
+
### Option 1: Docker (Quickstart no MAC/ARM)
|
118
|
+
|
119
|
+
```bash
|
120
|
+
# Step 1: Pull and run SearXNG for optimal search results
|
121
|
+
docker pull searxng/searxng
|
122
|
+
docker run -d -p 8080:8080 --name searxng searxng/searxng
|
123
|
+
|
124
|
+
# Step 2: Pull and run Local Deep Research (Please build your own docker on ARM)
|
125
|
+
docker pull localdeepresearch/local-deep-research
|
126
|
+
docker run -d -p 5000:5000 --network host --name local-deep-research localdeepresearch/local-deep-research
|
127
|
+
|
128
|
+
# Start containers - Required after each reboot (can be automated with this flag in run command --restart unless-stopped)
|
129
|
+
docker start searxng
|
130
|
+
docker start local-deep-research
|
131
|
+
|
132
|
+
```
|
133
|
+
|
134
|
+
### Option 2: Docker Compose (Recommended)
|
110
135
|
|
111
136
|
LDR uses Docker compose to bundle the web app and all it's dependencies so
|
112
137
|
you can get up and running quickly.
|
@@ -145,7 +170,7 @@ Then visit `http://127.0.0.1:5000` to start researching!
|
|
145
170
|
See [here](https://github.com/LearningCircuit/local-deep-research/wiki/Installation#docker-installation-recommended) for more information about
|
146
171
|
using Docker.
|
147
172
|
|
148
|
-
### Option
|
173
|
+
### Option 3: Python Package (mostly for programmatic access)
|
149
174
|
|
150
175
|
```bash
|
151
176
|
# Install the package
|
@@ -35,7 +35,24 @@ Local Deep Research combines the power of large language models with intelligent
|
|
35
35
|
|
36
36
|
## ⚡ Quick Start
|
37
37
|
|
38
|
-
### Option 1: Docker (
|
38
|
+
### Option 1: Docker (Quickstart no MAC/ARM)
|
39
|
+
|
40
|
+
```bash
|
41
|
+
# Step 1: Pull and run SearXNG for optimal search results
|
42
|
+
docker pull searxng/searxng
|
43
|
+
docker run -d -p 8080:8080 --name searxng searxng/searxng
|
44
|
+
|
45
|
+
# Step 2: Pull and run Local Deep Research (Please build your own docker on ARM)
|
46
|
+
docker pull localdeepresearch/local-deep-research
|
47
|
+
docker run -d -p 5000:5000 --network host --name local-deep-research localdeepresearch/local-deep-research
|
48
|
+
|
49
|
+
# Start containers - Required after each reboot (can be automated with this flag in run command --restart unless-stopped)
|
50
|
+
docker start searxng
|
51
|
+
docker start local-deep-research
|
52
|
+
|
53
|
+
```
|
54
|
+
|
55
|
+
### Option 2: Docker Compose (Recommended)
|
39
56
|
|
40
57
|
LDR uses Docker compose to bundle the web app and all it's dependencies so
|
41
58
|
you can get up and running quickly.
|
@@ -74,7 +91,7 @@ Then visit `http://127.0.0.1:5000` to start researching!
|
|
74
91
|
See [here](https://github.com/LearningCircuit/local-deep-research/wiki/Installation#docker-installation-recommended) for more information about
|
75
92
|
using Docker.
|
76
93
|
|
77
|
-
### Option
|
94
|
+
### Option 3: Python Package (mostly for programmatic access)
|
78
95
|
|
79
96
|
```bash
|
80
97
|
# Install the package
|
@@ -25,7 +25,7 @@ dependencies = [
|
|
25
25
|
"langchain-core>=0.3.34",
|
26
26
|
"langchain-ollama>=0.2.3",
|
27
27
|
"langchain-openai>=0.3.5",
|
28
|
-
"
|
28
|
+
"langchain-anthropic>=0.3.13",
|
29
29
|
"duckduckgo_search>=7.3.2",
|
30
30
|
"python-dateutil>=2.9.0",
|
31
31
|
"typing_extensions>=4.12.2",
|
@@ -56,8 +56,16 @@ dependencies = [
|
|
56
56
|
"importlib-resources>=6.5.2",
|
57
57
|
"setuptools>=78.1.0",
|
58
58
|
"flask-wtf>=1.2.2",
|
59
|
+
"optuna>=4.3.0",
|
60
|
+
"elasticsearch==8.14.0",
|
61
|
+
"methodtools>=0.4.7",
|
62
|
+
"loguru>=0.7.3",
|
63
|
+
"matplotlib>=3.10.3",
|
64
|
+
"pandas>=2.2.3",
|
65
|
+
"plotly>=6.0.1",
|
66
|
+
"kaleido==0.1.0",
|
59
67
|
]
|
60
|
-
version = "0.
|
68
|
+
version = "0.4.0"
|
61
69
|
|
62
70
|
[project.license]
|
63
71
|
file = "LICENSE"
|
@@ -109,4 +117,7 @@ dev = [
|
|
109
117
|
"flake8>=7.1.2",
|
110
118
|
"jupyter>=1.1.1",
|
111
119
|
"cookiecutter>=2.6.0",
|
120
|
+
"pandas>=2.2.3",
|
121
|
+
"optuna>=4.3.0",
|
122
|
+
"pytest-mock>=3.14.0",
|
112
123
|
]
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.4.0"
|
@@ -3,17 +3,16 @@
|
|
3
3
|
Base class for search result filters.
|
4
4
|
"""
|
5
5
|
|
6
|
-
import logging
|
7
6
|
from abc import ABC, abstractmethod
|
8
7
|
from typing import Dict, List
|
9
8
|
|
10
|
-
|
9
|
+
from langchain_core.language_models.chat_models import BaseChatModel
|
11
10
|
|
12
11
|
|
13
12
|
class BaseFilter(ABC):
|
14
13
|
"""Abstract base class for all search result filters."""
|
15
14
|
|
16
|
-
def __init__(self, model=None):
|
15
|
+
def __init__(self, model: BaseChatModel | None = None):
|
17
16
|
"""
|
18
17
|
Initialize the filter.
|
19
18
|
|
@@ -3,15 +3,14 @@ Cross-engine search result filter implementation.
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
import json
|
6
|
-
import logging
|
7
6
|
from typing import Dict, List
|
8
7
|
|
8
|
+
from loguru import logger
|
9
|
+
|
9
10
|
from ...utilities.db_utils import get_db_setting
|
10
11
|
from ...utilities.search_utilities import remove_think_tags
|
11
12
|
from .base_filter import BaseFilter
|
12
13
|
|
13
|
-
logger = logging.getLogger(__name__)
|
14
|
-
|
15
14
|
|
16
15
|
class CrossEngineFilter(BaseFilter):
|
17
16
|
"""Filter that ranks and filters results from multiple search engines."""
|
@@ -194,8 +193,8 @@ If no results seem relevant to the query, return an empty array: []"""
|
|
194
193
|
result["index"] = str(i + start_index + 1)
|
195
194
|
return top_results
|
196
195
|
|
197
|
-
except Exception
|
198
|
-
logger.
|
196
|
+
except Exception:
|
197
|
+
logger.exception("Cross-engine filtering error")
|
199
198
|
top_results = results[: min(self.max_results, len(results))]
|
200
199
|
# Update indices if requested
|
201
200
|
if reindex:
|
@@ -0,0 +1,298 @@
|
|
1
|
+
import time
|
2
|
+
import traceback
|
3
|
+
from datetime import timedelta
|
4
|
+
from typing import Any, Dict, List, Optional
|
5
|
+
|
6
|
+
from langchain_core.language_models.chat_models import BaseChatModel
|
7
|
+
from loguru import logger
|
8
|
+
from methodtools import lru_cache
|
9
|
+
|
10
|
+
from ...config.llm_config import get_llm
|
11
|
+
from ...search_system import AdvancedSearchSystem
|
12
|
+
from ...utilities.db_utils import get_db_session, get_db_setting
|
13
|
+
from ...web.database.models import Journal
|
14
|
+
from ...web_search_engines.search_engine_factory import create_search_engine
|
15
|
+
from .base_filter import BaseFilter
|
16
|
+
|
17
|
+
|
18
|
+
class JournalFilterError(Exception):
|
19
|
+
"""
|
20
|
+
Custom exception for errors related to journal filtering.
|
21
|
+
"""
|
22
|
+
|
23
|
+
|
24
|
+
class JournalReputationFilter(BaseFilter):
|
25
|
+
"""
|
26
|
+
A filter for academic results that considers the reputation of journals.
|
27
|
+
|
28
|
+
Note that this filter requires SearXNG to be available in order to work.
|
29
|
+
"""
|
30
|
+
|
31
|
+
def __init__(
|
32
|
+
self,
|
33
|
+
model: BaseChatModel | None = None,
|
34
|
+
reliability_threshold: int | None = None,
|
35
|
+
max_context: int | None = None,
|
36
|
+
exclude_non_published: bool | None = None,
|
37
|
+
quality_reanalysis_period: timedelta | None = None,
|
38
|
+
):
|
39
|
+
"""
|
40
|
+
Args:
|
41
|
+
model: The LLM model to use for analysis.
|
42
|
+
reliability_threshold: The filter scores journal reliability on a
|
43
|
+
scale of 1-10. Results from any journal with a reliability
|
44
|
+
below this threshold will be culled. Will be read from the
|
45
|
+
settings if not specified.
|
46
|
+
max_context: The maximum number of characters to feed into the
|
47
|
+
LLM when assessing journal reliability.
|
48
|
+
exclude_non_published: If true, it will exclude any results that
|
49
|
+
don't have an associated journal publication.
|
50
|
+
quality_reanalysis_period: Period at which to update journal
|
51
|
+
quality assessments.
|
52
|
+
|
53
|
+
"""
|
54
|
+
super().__init__(model)
|
55
|
+
|
56
|
+
if self.model is None:
|
57
|
+
self.model = get_llm()
|
58
|
+
|
59
|
+
self.__threshold = reliability_threshold
|
60
|
+
if self.__threshold is None:
|
61
|
+
self.__threshold = int(
|
62
|
+
get_db_setting("search.journal_reputation.threshold", 4)
|
63
|
+
)
|
64
|
+
self.__max_context = max_context
|
65
|
+
if self.__max_context is None:
|
66
|
+
self.__max_context = int(
|
67
|
+
get_db_setting("search.journal_reputation.max_context", 3000)
|
68
|
+
)
|
69
|
+
self.__exclude_non_published = exclude_non_published
|
70
|
+
if self.__exclude_non_published is None:
|
71
|
+
self.__exclude_non_published = bool(
|
72
|
+
get_db_setting("search.journal_reputation.exclude_non_published", False)
|
73
|
+
)
|
74
|
+
self.__quality_reanalysis_period = quality_reanalysis_period
|
75
|
+
if self.__quality_reanalysis_period is None:
|
76
|
+
self.__quality_reanalysis_period = timedelta(
|
77
|
+
days=int(
|
78
|
+
get_db_setting("search.journal_reputation.reanalysis_period", 365)
|
79
|
+
)
|
80
|
+
)
|
81
|
+
|
82
|
+
# SearXNG is required so we can search the open web for reputational
|
83
|
+
# information.
|
84
|
+
self.__engine = create_search_engine("searxng", llm=self.model)
|
85
|
+
if self.__engine is None:
|
86
|
+
raise JournalFilterError("SearXNG initialization failed.")
|
87
|
+
|
88
|
+
self.__db_session = get_db_session()
|
89
|
+
|
90
|
+
@classmethod
|
91
|
+
def create_default(
|
92
|
+
cls, model: BaseChatModel | None = None, *, engine_name: str
|
93
|
+
) -> Optional["JournalReputationFilter"]:
|
94
|
+
"""
|
95
|
+
Initializes a default configuration of the filter based on the settings.
|
96
|
+
|
97
|
+
Args:
|
98
|
+
model: Explicitly specify the LLM to use.
|
99
|
+
engine_name: The name of the search engine. Will be used to check
|
100
|
+
the enablement status for that engine.
|
101
|
+
|
102
|
+
Returns:
|
103
|
+
The filter that it created, or None if filtering is disabled in
|
104
|
+
the settings, or misconfigured.
|
105
|
+
|
106
|
+
"""
|
107
|
+
if not bool(
|
108
|
+
get_db_setting(
|
109
|
+
f"search.engine.web.{engine_name}.journal_reputation.enabled",
|
110
|
+
True,
|
111
|
+
)
|
112
|
+
):
|
113
|
+
return None
|
114
|
+
|
115
|
+
try:
|
116
|
+
# Initialize the filter with default settings.
|
117
|
+
return JournalReputationFilter(model=model)
|
118
|
+
except JournalFilterError:
|
119
|
+
logger.error(
|
120
|
+
"SearXNG is not configured, but is required for "
|
121
|
+
"journal reputation filtering. Disabling filtering."
|
122
|
+
)
|
123
|
+
return None
|
124
|
+
|
125
|
+
def __make_search_system(self) -> AdvancedSearchSystem:
|
126
|
+
"""
|
127
|
+
Creates a new `AdvancedSearchSystem` instance.
|
128
|
+
|
129
|
+
Returns:
|
130
|
+
The system it created.
|
131
|
+
|
132
|
+
"""
|
133
|
+
return AdvancedSearchSystem(
|
134
|
+
llm=self.model,
|
135
|
+
search=self.__engine,
|
136
|
+
# We clamp down on the default iterations and questions for speed.
|
137
|
+
max_iterations=2,
|
138
|
+
questions_per_iteration=3,
|
139
|
+
)
|
140
|
+
|
141
|
+
@lru_cache(maxsize=1024)
|
142
|
+
def __analyze_journal_reputation(self, journal_name: str) -> int:
|
143
|
+
"""
|
144
|
+
Analyzes the reputation of a particular journal.
|
145
|
+
|
146
|
+
Args:
|
147
|
+
journal_name: The name of the journal.
|
148
|
+
|
149
|
+
Returns:
|
150
|
+
The reputation of the journal, on a scale from 1-10.
|
151
|
+
|
152
|
+
"""
|
153
|
+
logger.info(f"Analyzing reputation of journal '{journal_name}'...")
|
154
|
+
|
155
|
+
# Perform a search for information about this journal.
|
156
|
+
journal_info = self.__make_search_system().analyze_topic(
|
157
|
+
f'Assess the reputability and reliability of the journal "'
|
158
|
+
f'{journal_name}", with a particular focus on its quartile '
|
159
|
+
f"ranking and peer review status. Be sure to specify the journal "
|
160
|
+
f"name in any generated questions."
|
161
|
+
)
|
162
|
+
journal_info = "\n".join([f["content"] for f in journal_info["findings"]])
|
163
|
+
logger.debug(f"Received raw info about journal: {journal_info}")
|
164
|
+
|
165
|
+
# Have the LLM assess the reliability based on this information.
|
166
|
+
prompt = f"""
|
167
|
+
You are a research assistant helping to assess the reliability and
|
168
|
+
reputability of scientific journals. A reputable journal should be
|
169
|
+
peer-reviewed, not predatory, and high-impact. Please review the
|
170
|
+
following information on the journal "{journal_name}" and output a
|
171
|
+
reputability score between 1 and 10, where 1-3 is not reputable and
|
172
|
+
probably predatory, 4-6 is reputable but low-impact (Q2 or Q3),
|
173
|
+
and 7-10 is reputable Q1 journals. Only output the number, do not
|
174
|
+
provide any explanation or other output.
|
175
|
+
|
176
|
+
JOURNAL INFORMATION:
|
177
|
+
|
178
|
+
{journal_info}
|
179
|
+
"""
|
180
|
+
if len(prompt) > self.__max_context:
|
181
|
+
# If the prompt is too long, truncate it to fit within the max context size.
|
182
|
+
prompt = prompt[: self.__max_context] + "..."
|
183
|
+
|
184
|
+
# Generate a response from the LLM model.
|
185
|
+
response = self.model.invoke(prompt).text()
|
186
|
+
logger.debug(f"Got raw LLM response: {response}")
|
187
|
+
|
188
|
+
# Extract the score from the response.
|
189
|
+
try:
|
190
|
+
reputation_score = int(response.strip())
|
191
|
+
except ValueError:
|
192
|
+
logger.error("Failed to parse reputation score from LLM response.")
|
193
|
+
raise ValueError("Failed to parse reputation score from LLM response.")
|
194
|
+
|
195
|
+
return max(min(reputation_score, 10), 1)
|
196
|
+
|
197
|
+
def __add_journal_to_db(self, *, name: str, quality: int) -> None:
|
198
|
+
"""
|
199
|
+
Saves the journal quality information to the database.
|
200
|
+
|
201
|
+
Args:
|
202
|
+
name: The name of the journal.
|
203
|
+
quality: The quality assessment for the journal.
|
204
|
+
|
205
|
+
"""
|
206
|
+
journal = self.__db_session.query(Journal).filter_by(name=name).first()
|
207
|
+
if journal is not None:
|
208
|
+
journal.quality = quality
|
209
|
+
journal.quality_model = self.model.name
|
210
|
+
journal.quality_analysis_time = int(time.time())
|
211
|
+
else:
|
212
|
+
journal = Journal(
|
213
|
+
name=name,
|
214
|
+
quality=quality,
|
215
|
+
quality_model=self.model.name,
|
216
|
+
quality_analysis_time=int(time.time()),
|
217
|
+
)
|
218
|
+
self.__db_session.add(journal)
|
219
|
+
|
220
|
+
self.__db_session.commit()
|
221
|
+
|
222
|
+
def __clean_journal_name(self, journal_name: str) -> str:
|
223
|
+
"""
|
224
|
+
Cleans up the name of a journal to remove any extraneous information.
|
225
|
+
This is mostly to make caching more effective.
|
226
|
+
|
227
|
+
Args:
|
228
|
+
journal_name: The raw name of the journal.
|
229
|
+
|
230
|
+
Returns:
|
231
|
+
The cleaned name.
|
232
|
+
|
233
|
+
"""
|
234
|
+
logger.debug(f"Cleaning raw journal name: {journal_name}")
|
235
|
+
|
236
|
+
prompt = f"""
|
237
|
+
Clean up the following journal or conference name:
|
238
|
+
|
239
|
+
"{journal_name}"
|
240
|
+
|
241
|
+
Remove any references to volumes, pages, months, or years. Expand
|
242
|
+
abbreviations if possible. For conferences, remove locations. Only
|
243
|
+
output the clean name, do not provide any explanation or other output.
|
244
|
+
"""
|
245
|
+
|
246
|
+
response = self.model.invoke(prompt).text()
|
247
|
+
return response.strip()
|
248
|
+
|
249
|
+
def __check_result(self, result: Dict[str, Any]) -> bool:
|
250
|
+
"""
|
251
|
+
Performs a search to determine the reputability of a result journal..
|
252
|
+
|
253
|
+
Args:
|
254
|
+
result: The result to check.
|
255
|
+
|
256
|
+
Returns:
|
257
|
+
True if the journal is reputable or if it couldn't determine a
|
258
|
+
reputability score, false otherwise.
|
259
|
+
|
260
|
+
"""
|
261
|
+
journal_name = result.get("journal_ref")
|
262
|
+
if journal_name is None:
|
263
|
+
logger.debug(
|
264
|
+
f"Result {result.get('title')} has no associated "
|
265
|
+
f"journal, not evaluating reputation."
|
266
|
+
)
|
267
|
+
return not self.__exclude_non_published
|
268
|
+
journal_name = self.__clean_journal_name(journal_name)
|
269
|
+
|
270
|
+
# Check the database first.
|
271
|
+
journal = self.__db_session.query(Journal).filter_by(name=journal_name).first()
|
272
|
+
if (
|
273
|
+
journal is not None
|
274
|
+
and (time.time() - journal.quality_analysis_time)
|
275
|
+
< self.__quality_reanalysis_period.total_seconds()
|
276
|
+
):
|
277
|
+
logger.debug(f"Found existing reputation for {journal_name} in database.")
|
278
|
+
return journal.quality >= self.__threshold
|
279
|
+
|
280
|
+
# Evaluate reputation.
|
281
|
+
try:
|
282
|
+
quality = self.__analyze_journal_reputation(journal_name)
|
283
|
+
# Save to the database.
|
284
|
+
self.__add_journal_to_db(name=journal_name, quality=quality)
|
285
|
+
return quality >= self.__threshold
|
286
|
+
except ValueError:
|
287
|
+
# The LLM behaved weirdly. In this case, we will just assume it's
|
288
|
+
# okay.
|
289
|
+
return True
|
290
|
+
|
291
|
+
def filter_results(self, results: List[Dict], query: str, **kwargs) -> List[Dict]:
|
292
|
+
try:
|
293
|
+
return list(filter(self.__check_result, results))
|
294
|
+
except Exception as e:
|
295
|
+
logger.error(
|
296
|
+
f"Journal quality filtering failed: {e}, {traceback.format_exc()}"
|
297
|
+
)
|
298
|
+
return results
|
@@ -291,9 +291,6 @@ Use IEEE style citations [1], [2], etc. Never make up your own citations.
|
|
291
291
|
|
292
292
|
# Check if we're on Windows
|
293
293
|
if platform.system() == "Windows":
|
294
|
-
# Windows-compatible timeout using threading
|
295
|
-
class TimeoutError(Exception):
|
296
|
-
pass
|
297
294
|
|
298
295
|
def timeout_handler(timeout_seconds, callback, args):
|
299
296
|
def handler():
|
@@ -3,11 +3,10 @@ Base class for all search strategies.
|
|
3
3
|
Defines the common interface and shared functionality for different search approaches.
|
4
4
|
"""
|
5
5
|
|
6
|
-
import logging
|
7
6
|
from abc import ABC, abstractmethod
|
8
7
|
from typing import Callable, Dict, List, Optional
|
9
8
|
|
10
|
-
|
9
|
+
from loguru import logger
|
11
10
|
|
12
11
|
|
13
12
|
class BaseSearchStrategy(ABC):
|
@@ -3,10 +3,11 @@ IterDRAG strategy implementation.
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
import json
|
6
|
-
import logging
|
7
6
|
from datetime import datetime
|
8
7
|
from typing import Dict, List
|
9
8
|
|
9
|
+
from loguru import logger
|
10
|
+
|
10
11
|
from ...citation_handler import CitationHandler
|
11
12
|
from ...config.llm_config import get_llm
|
12
13
|
from ...config.search_config import get_search
|
@@ -17,8 +18,6 @@ from ..knowledge.standard_knowledge import StandardKnowledge
|
|
17
18
|
from ..questions.decomposition_question import DecompositionQuestionGenerator
|
18
19
|
from .base_strategy import BaseSearchStrategy
|
19
20
|
|
20
|
-
logger = logging.getLogger(__name__)
|
21
|
-
|
22
21
|
|
23
22
|
class IterDRAGStrategy(BaseSearchStrategy):
|
24
23
|
"""IterDRAG strategy that breaks queries into sub-queries."""
|
@@ -83,8 +82,8 @@ Initial Search Results:
|
|
83
82
|
return self.question_generator.generate_questions(
|
84
83
|
query, context, int(get_db_setting("search.questions_per_iteration"))
|
85
84
|
)
|
86
|
-
except Exception
|
87
|
-
logger.
|
85
|
+
except Exception:
|
86
|
+
logger.exception("Error generating sub-queries")
|
88
87
|
return []
|
89
88
|
|
90
89
|
def analyze_topic(self, query: str) -> Dict:
|
@@ -204,8 +203,8 @@ Initial Search Results:
|
|
204
203
|
"result_count": len(sub_results),
|
205
204
|
},
|
206
205
|
)
|
207
|
-
except Exception
|
208
|
-
logger.
|
206
|
+
except Exception:
|
207
|
+
logger.exception("Error searching for sub-query")
|
209
208
|
sub_results = []
|
210
209
|
|
211
210
|
try:
|
@@ -238,8 +237,8 @@ Initial Search Results:
|
|
238
237
|
current_knowledge = (
|
239
238
|
current_knowledge + "\n\n\n New: \n" + result["content"]
|
240
239
|
)
|
241
|
-
except Exception
|
242
|
-
logger.
|
240
|
+
except Exception:
|
241
|
+
logger.exception("Error analyzing sub-query results:")
|
243
242
|
finding = {
|
244
243
|
"phase": f"Follow-up Iteration 0.{i + 1}",
|
245
244
|
"content": "Error analyzing sub-query results.",
|
@@ -344,10 +343,7 @@ This is a fallback response using the accumulated knowledge.
|
|
344
343
|
# Update current knowledge with the synthesized version
|
345
344
|
current_knowledge = final_answer
|
346
345
|
except Exception as e:
|
347
|
-
logger.
|
348
|
-
import traceback
|
349
|
-
|
350
|
-
logger.error(traceback.format_exc())
|
346
|
+
logger.exception("Error synthesizing final answer")
|
351
347
|
|
352
348
|
# Create an error finding
|
353
349
|
error_finding = {
|
@@ -396,7 +392,7 @@ This is an automatically generated fallback response.
|
|
396
392
|
final_answer = fallback_content
|
397
393
|
except Exception as fallback_error:
|
398
394
|
# Last resort fallback
|
399
|
-
logger.
|
395
|
+
logger.exception("Even fallback creation failed")
|
400
396
|
final_answer = f"""
|
401
397
|
# Research Error
|
402
398
|
|
@@ -417,8 +413,8 @@ Please try again with a different query or contact support.
|
|
417
413
|
current_knowledge = self.knowledge_generator.compress_knowledge(
|
418
414
|
current_knowledge, query, section_links
|
419
415
|
)
|
420
|
-
except Exception
|
421
|
-
logger.
|
416
|
+
except Exception:
|
417
|
+
logger.exception("Error compressing knowledge")
|
422
418
|
|
423
419
|
# Format and save findings
|
424
420
|
self._update_progress(
|
@@ -442,8 +438,8 @@ Please try again with a different query or contact support.
|
|
442
438
|
formatted_findings = self.findings_repository.format_findings_to_text(
|
443
439
|
findings, final_answer
|
444
440
|
)
|
445
|
-
except Exception
|
446
|
-
logger.
|
441
|
+
except Exception:
|
442
|
+
logger.exception("Error formatting final findings")
|
447
443
|
formatted_findings = "Error: Could not format findings due to an error."
|
448
444
|
|
449
445
|
self._update_progress("Research complete", 100, {"phase": "complete"})
|
@@ -3,9 +3,10 @@ Parallel search strategy implementation for maximum search speed.
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
import concurrent.futures
|
6
|
-
import logging
|
7
6
|
from typing import Dict
|
8
7
|
|
8
|
+
from loguru import logger
|
9
|
+
|
9
10
|
from ...citation_handler import CitationHandler
|
10
11
|
from ...config.llm_config import get_llm
|
11
12
|
from ...config.search_config import get_search
|
@@ -16,8 +17,6 @@ from ..findings.repository import FindingsRepository
|
|
16
17
|
from ..questions.standard_question import StandardQuestionGenerator
|
17
18
|
from .base_strategy import BaseSearchStrategy
|
18
19
|
|
19
|
-
logger = logging.getLogger(__name__)
|
20
|
-
|
21
20
|
|
22
21
|
class ParallelSearchStrategy(BaseSearchStrategy):
|
23
22
|
"""
|
@@ -212,7 +211,7 @@ class ParallelSearchStrategy(BaseSearchStrategy):
|
|
212
211
|
result = self.search.run(q)
|
213
212
|
return {"question": q, "results": result or []}
|
214
213
|
except Exception as e:
|
215
|
-
logger.
|
214
|
+
logger.exception(f"Error searching for '{q}'")
|
216
215
|
return {"question": q, "results": [], "error": str(e)}
|
217
216
|
|
218
217
|
# Run searches in parallel
|
@@ -408,11 +407,8 @@ class ParallelSearchStrategy(BaseSearchStrategy):
|
|
408
407
|
)
|
409
408
|
|
410
409
|
except Exception as e:
|
411
|
-
import traceback
|
412
|
-
|
413
410
|
error_msg = f"Error in research process: {str(e)}"
|
414
|
-
logger.
|
415
|
-
logger.error(traceback.format_exc())
|
411
|
+
logger.exception(error_msg)
|
416
412
|
synthesized_content = f"Error: {str(e)}"
|
417
413
|
formatted_findings = f"Error: {str(e)}"
|
418
414
|
finding = {
|