local-deep-research 0.3.0__py3-none-any.whl → 0.3.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- local_deep_research/__init__.py +1 -1
- local_deep_research/__version__.py +1 -0
- local_deep_research/config/llm_config.py +2 -3
- local_deep_research/defaults/default_settings.json +183 -1
- local_deep_research/web/routes/settings_routes.py +2 -4
- local_deep_research/web/services/settings_manager.py +1 -1
- local_deep_research/web/static/js/components/settings.js +8 -4
- local_deep_research/web_search_engines/engines/meta_search_engine.py +44 -4
- local_deep_research-0.3.2.dist-info/METADATA +349 -0
- {local_deep_research-0.3.0.dist-info → local_deep_research-0.3.2.dist-info}/RECORD +13 -12
- local_deep_research-0.3.0.dist-info/METADATA +0 -549
- {local_deep_research-0.3.0.dist-info → local_deep_research-0.3.2.dist-info}/WHEEL +0 -0
- {local_deep_research-0.3.0.dist-info → local_deep_research-0.3.2.dist-info}/entry_points.txt +0 -0
- {local_deep_research-0.3.0.dist-info → local_deep_research-0.3.2.dist-info}/licenses/LICENSE +0 -0
local_deep_research/__init__.py
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
Local Deep Research - A tool for conducting deep research using AI.
|
3
3
|
"""
|
4
4
|
|
5
|
-
__version__ = "0.2.0"
|
6
5
|
__author__ = "Your Name"
|
7
6
|
__description__ = "A tool for conducting deep research using AI"
|
8
7
|
|
8
|
+
from .__version__ import __version__
|
9
9
|
from .config.llm_config import get_llm
|
10
10
|
from .config.search_config import get_search
|
11
11
|
from .report_generator import get_report_generator
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.3.2"
|
@@ -3,6 +3,7 @@ import os
|
|
3
3
|
|
4
4
|
from langchain_anthropic import ChatAnthropic
|
5
5
|
from langchain_community.llms import VLLM
|
6
|
+
from langchain_core.language_models import FakeListChatModel
|
6
7
|
from langchain_ollama import ChatOllama
|
7
8
|
from langchain_openai import ChatOpenAI
|
8
9
|
|
@@ -248,9 +249,7 @@ def get_llm(model_name=None, temperature=None, provider=None, openai_endpoint_ur
|
|
248
249
|
|
249
250
|
def get_fallback_model(temperature=None):
|
250
251
|
"""Create a dummy model for when no providers are available"""
|
251
|
-
|
252
|
-
|
253
|
-
return FakeListLLM(
|
252
|
+
return FakeListChatModel(
|
254
253
|
responses=[
|
255
254
|
"No language models are available. Please install Ollama or set up API keys."
|
256
255
|
]
|
@@ -10,7 +10,7 @@
|
|
10
10
|
"step": null,
|
11
11
|
"type": "APP",
|
12
12
|
"ui_element": "text",
|
13
|
-
"value": "0.3.
|
13
|
+
"value": "0.3.2",
|
14
14
|
"visible": false
|
15
15
|
},
|
16
16
|
"app.debug": {
|
@@ -3810,5 +3810,187 @@
|
|
3810
3810
|
"ui_element": "number",
|
3811
3811
|
"value": 100,
|
3812
3812
|
"visible": true
|
3813
|
+
},
|
3814
|
+
"search.engine.web.pubmed.use_in_auto_search": {
|
3815
|
+
"category": "pubmed",
|
3816
|
+
"description": "Include PubMed in auto search mode",
|
3817
|
+
"editable": true,
|
3818
|
+
"max_value": null,
|
3819
|
+
"min_value": null,
|
3820
|
+
"name": "Include in Auto Search",
|
3821
|
+
"options": null,
|
3822
|
+
"step": null,
|
3823
|
+
"type": "SEARCH",
|
3824
|
+
"ui_element": "checkbox",
|
3825
|
+
"value": true,
|
3826
|
+
"visible": true
|
3827
|
+
},
|
3828
|
+
"search.engine.web.arxiv.use_in_auto_search": {
|
3829
|
+
"category": "arxiv",
|
3830
|
+
"description": "Include ArXiv in auto search mode",
|
3831
|
+
"editable": true,
|
3832
|
+
"max_value": null,
|
3833
|
+
"min_value": null,
|
3834
|
+
"name": "Include in Auto Search",
|
3835
|
+
"options": null,
|
3836
|
+
"step": null,
|
3837
|
+
"type": "SEARCH",
|
3838
|
+
"ui_element": "checkbox",
|
3839
|
+
"value": true,
|
3840
|
+
"visible": true
|
3841
|
+
},
|
3842
|
+
"search.engine.web.searxng.use_in_auto_search": {
|
3843
|
+
"category": "searxng",
|
3844
|
+
"description": "Include SearXNG in auto search mode",
|
3845
|
+
"editable": true,
|
3846
|
+
"max_value": null,
|
3847
|
+
"min_value": null,
|
3848
|
+
"name": "Include in Auto Search",
|
3849
|
+
"options": null,
|
3850
|
+
"step": null,
|
3851
|
+
"type": "SEARCH",
|
3852
|
+
"ui_element": "checkbox",
|
3853
|
+
"value": true,
|
3854
|
+
"visible": true
|
3855
|
+
},
|
3856
|
+
"search.engine.web.github.use_in_auto_search": {
|
3857
|
+
"category": "github",
|
3858
|
+
"description": "Include GitHub in auto search mode",
|
3859
|
+
"editable": true,
|
3860
|
+
"max_value": null,
|
3861
|
+
"min_value": null,
|
3862
|
+
"name": "Include in Auto Search",
|
3863
|
+
"options": null,
|
3864
|
+
"step": null,
|
3865
|
+
"type": "SEARCH",
|
3866
|
+
"ui_element": "checkbox",
|
3867
|
+
"value": true,
|
3868
|
+
"visible": true
|
3869
|
+
},
|
3870
|
+
"search.engine.web.wikipedia.use_in_auto_search": {
|
3871
|
+
"category": "wikipedia",
|
3872
|
+
"description": "Include Wikipedia in auto search mode",
|
3873
|
+
"editable": true,
|
3874
|
+
"max_value": null,
|
3875
|
+
"min_value": null,
|
3876
|
+
"name": "Include in Auto Search",
|
3877
|
+
"options": null,
|
3878
|
+
"step": null,
|
3879
|
+
"type": "SEARCH",
|
3880
|
+
"ui_element": "checkbox",
|
3881
|
+
"value": true,
|
3882
|
+
"visible": true
|
3883
|
+
},
|
3884
|
+
"search.engine.web.brave.use_in_auto_search": {
|
3885
|
+
"category": "brave",
|
3886
|
+
"description": "Include Brave search in auto search mode",
|
3887
|
+
"editable": true,
|
3888
|
+
"max_value": null,
|
3889
|
+
"min_value": null,
|
3890
|
+
"name": "Include in Auto Search",
|
3891
|
+
"options": null,
|
3892
|
+
"step": null,
|
3893
|
+
"type": "SEARCH",
|
3894
|
+
"ui_element": "checkbox",
|
3895
|
+
"value": false,
|
3896
|
+
"visible": true
|
3897
|
+
},
|
3898
|
+
"search.engine.web.google_pse.use_in_auto_search": {
|
3899
|
+
"category": "google_pse",
|
3900
|
+
"description": "Include Google PSE in auto search mode",
|
3901
|
+
"editable": true,
|
3902
|
+
"max_value": null,
|
3903
|
+
"min_value": null,
|
3904
|
+
"name": "Include in Auto Search",
|
3905
|
+
"options": null,
|
3906
|
+
"step": null,
|
3907
|
+
"type": "SEARCH",
|
3908
|
+
"ui_element": "checkbox",
|
3909
|
+
"value": false,
|
3910
|
+
"visible": true
|
3911
|
+
},
|
3912
|
+
"search.engine.web.serpapi.use_in_auto_search": {
|
3913
|
+
"category": "serpapi",
|
3914
|
+
"description": "Include SerpAPI in auto search mode",
|
3915
|
+
"editable": true,
|
3916
|
+
"max_value": null,
|
3917
|
+
"min_value": null,
|
3918
|
+
"name": "Include in Auto Search",
|
3919
|
+
"options": null,
|
3920
|
+
"step": null,
|
3921
|
+
"type": "SEARCH",
|
3922
|
+
"ui_element": "checkbox",
|
3923
|
+
"value": false,
|
3924
|
+
"visible": true
|
3925
|
+
},
|
3926
|
+
"search.engine.web.wayback.use_in_auto_search": {
|
3927
|
+
"category": "wayback",
|
3928
|
+
"description": "Include Wayback in auto search mode",
|
3929
|
+
"editable": true,
|
3930
|
+
"max_value": null,
|
3931
|
+
"min_value": null,
|
3932
|
+
"name": "Include in Auto Search",
|
3933
|
+
"options": null,
|
3934
|
+
"step": null,
|
3935
|
+
"type": "SEARCH",
|
3936
|
+
"ui_element": "checkbox",
|
3937
|
+
"value": false,
|
3938
|
+
"visible": true
|
3939
|
+
},
|
3940
|
+
"search.engine.local.local_all.use_in_auto_search": {
|
3941
|
+
"category": "local_all",
|
3942
|
+
"description": "Include local documents in auto search mode",
|
3943
|
+
"editable": true,
|
3944
|
+
"max_value": null,
|
3945
|
+
"min_value": null,
|
3946
|
+
"name": "Include in Auto Search",
|
3947
|
+
"options": null,
|
3948
|
+
"step": null,
|
3949
|
+
"type": "SEARCH",
|
3950
|
+
"ui_element": "checkbox",
|
3951
|
+
"value": true,
|
3952
|
+
"visible": true
|
3953
|
+
},
|
3954
|
+
"search.engine.local.personal_notes.use_in_auto_search": {
|
3955
|
+
"category": "personal_notes",
|
3956
|
+
"description": "Include personal notes in auto search mode",
|
3957
|
+
"editable": true,
|
3958
|
+
"max_value": null,
|
3959
|
+
"min_value": null,
|
3960
|
+
"name": "Include in Auto Search",
|
3961
|
+
"options": null,
|
3962
|
+
"step": null,
|
3963
|
+
"type": "SEARCH",
|
3964
|
+
"ui_element": "checkbox",
|
3965
|
+
"value": false,
|
3966
|
+
"visible": true
|
3967
|
+
},
|
3968
|
+
"search.engine.local.project_docs.use_in_auto_search": {
|
3969
|
+
"category": "project_docs",
|
3970
|
+
"description": "Include project documents in auto search mode",
|
3971
|
+
"editable": true,
|
3972
|
+
"max_value": null,
|
3973
|
+
"min_value": null,
|
3974
|
+
"name": "Include in Auto Search",
|
3975
|
+
"options": null,
|
3976
|
+
"step": null,
|
3977
|
+
"type": "SEARCH",
|
3978
|
+
"ui_element": "checkbox",
|
3979
|
+
"value": false,
|
3980
|
+
"visible": true
|
3981
|
+
},
|
3982
|
+
"search.engine.local.research_papers.use_in_auto_search": {
|
3983
|
+
"category": "research_papers",
|
3984
|
+
"description": "Include research papers in auto search mode",
|
3985
|
+
"editable": true,
|
3986
|
+
"max_value": null,
|
3987
|
+
"min_value": null,
|
3988
|
+
"name": "Include in Auto Search",
|
3989
|
+
"options": null,
|
3990
|
+
"step": null,
|
3991
|
+
"type": "SEARCH",
|
3992
|
+
"ui_element": "checkbox",
|
3993
|
+
"value": false,
|
3994
|
+
"visible": true
|
3813
3995
|
}
|
3814
3996
|
}
|
@@ -19,6 +19,7 @@ from flask import (
|
|
19
19
|
from flask_wtf.csrf import generate_csrf
|
20
20
|
from sqlalchemy.orm import Session
|
21
21
|
|
22
|
+
from ...utilities.db_utils import get_db_setting
|
22
23
|
from ..database.models import Setting, SettingType
|
23
24
|
from ..services.settings_service import (
|
24
25
|
create_or_update_setting,
|
@@ -666,10 +667,7 @@ def api_get_available_models():
|
|
666
667
|
try:
|
667
668
|
current_app.logger.info("Attempting to connect to Ollama API")
|
668
669
|
|
669
|
-
base_url =
|
670
|
-
"OLLAMA_BASE_URL",
|
671
|
-
"http://localhost:11434",
|
672
|
-
)
|
670
|
+
base_url = get_db_setting("llm.ollama.url", "http://localhost:11434")
|
673
671
|
ollama_response = requests.get(f"{base_url}/api/tags", timeout=5)
|
674
672
|
|
675
673
|
current_app.logger.debug(
|
@@ -34,7 +34,7 @@ def check_env_setting(key: str) -> str | None:
|
|
34
34
|
is not set.
|
35
35
|
|
36
36
|
"""
|
37
|
-
env_variable_name = f"LDR_{
|
37
|
+
env_variable_name = f"LDR_{'_'.join(key.split('.')).upper()}"
|
38
38
|
env_value = os.getenv(env_variable_name)
|
39
39
|
if env_value is not None:
|
40
40
|
logger.debug(f"Overriding {key} setting from environment variable.")
|
@@ -53,7 +53,8 @@
|
|
53
53
|
class="custom-dropdown-input"
|
54
54
|
placeholder="${params.placeholder}"
|
55
55
|
autocomplete="off"
|
56
|
-
aria-haspopup="listbox"
|
56
|
+
aria-haspopup="listbox"
|
57
|
+
${params.disabled ? "disabled" : ""}>
|
57
58
|
<!-- Hidden input that will be included in form submission -->
|
58
59
|
<input type="hidden" name="${params.input_id}" id="${params.input_id}_hidden" value="">
|
59
60
|
<div class="custom-dropdown-list" id="${params.dropdown_id}-list"></div>
|
@@ -1475,7 +1476,8 @@
|
|
1475
1476
|
help_text: setting.description || null,
|
1476
1477
|
allow_custom: false,
|
1477
1478
|
show_refresh: true, // Set to true for provider
|
1478
|
-
data_setting_key: setting.key
|
1479
|
+
data_setting_key: setting.key,
|
1480
|
+
disabled: !setting.editable
|
1479
1481
|
};
|
1480
1482
|
inputElement = renderCustomDropdownHTML(dropdownParams);
|
1481
1483
|
} else if (setting.key === 'search.tool') {
|
@@ -1487,7 +1489,8 @@
|
|
1487
1489
|
help_text: setting.description || null,
|
1488
1490
|
allow_custom: false,
|
1489
1491
|
show_refresh: false, // No refresh for search tool
|
1490
|
-
data_setting_key: setting.key
|
1492
|
+
data_setting_key: setting.key,
|
1493
|
+
disabled: !setting.editable
|
1491
1494
|
};
|
1492
1495
|
inputElement = renderCustomDropdownHTML(dropdownParams);
|
1493
1496
|
} else if (setting.key === 'llm.model') { // ADD THIS ELSE IF
|
@@ -1501,7 +1504,8 @@
|
|
1501
1504
|
allow_custom: true, // Allow custom for model
|
1502
1505
|
show_refresh: true, // Show refresh for model
|
1503
1506
|
refresh_aria_label: "Refresh model list",
|
1504
|
-
data_setting_key: setting.key
|
1507
|
+
data_setting_key: setting.key,
|
1508
|
+
disabled: !setting.editable
|
1505
1509
|
};
|
1506
1510
|
inputElement = renderCustomDropdownHTML(dropdownParams);
|
1507
1511
|
} else {
|
@@ -65,16 +65,43 @@ class MetaSearchEngine(BaseSearchEngine):
|
|
65
65
|
)
|
66
66
|
|
67
67
|
def _get_available_engines(self) -> List[str]:
|
68
|
-
"""Get list of available engines, excluding 'meta' and 'auto'"""
|
68
|
+
"""Get list of available engines, excluding 'meta' and 'auto', based on user settings"""
|
69
69
|
# Filter out 'meta' and 'auto' and check API key availability
|
70
70
|
available = []
|
71
|
+
|
71
72
|
for name, config_ in search_config().items():
|
72
73
|
if name in ["meta", "auto"]:
|
73
74
|
continue
|
74
75
|
|
76
|
+
# Determine if this is a local engine (starts with "local.")
|
77
|
+
is_local_engine = name.startswith("local.")
|
78
|
+
|
79
|
+
# Determine the appropriate setting path based on engine type
|
80
|
+
if is_local_engine:
|
81
|
+
# Format: search.engine.local.{engine_name}.use_in_auto_search
|
82
|
+
local_name = name.replace("local.", "")
|
83
|
+
auto_search_setting = (
|
84
|
+
f"search.engine.local.{local_name}.use_in_auto_search"
|
85
|
+
)
|
86
|
+
else:
|
87
|
+
# Format: search.engine.web.{engine_name}.use_in_auto_search
|
88
|
+
auto_search_setting = f"search.engine.web.{name}.use_in_auto_search"
|
89
|
+
|
90
|
+
# Get setting from database, default to False if not found
|
91
|
+
use_in_auto_search = get_db_setting(auto_search_setting, False)
|
92
|
+
|
93
|
+
# Skip engines that aren't enabled for auto search
|
94
|
+
if not use_in_auto_search:
|
95
|
+
logger.info(
|
96
|
+
f"Skipping {name} engine because it's not enabled for auto search"
|
97
|
+
)
|
98
|
+
continue
|
99
|
+
|
100
|
+
# Skip engines that require API keys if we don't want to use them
|
75
101
|
if config_.get("requires_api_key", False) and not self.use_api_key_services:
|
76
102
|
continue
|
77
103
|
|
104
|
+
# Skip engines that require API keys if the key is not available
|
78
105
|
if config_.get("requires_api_key", False):
|
79
106
|
api_key = config_.get("api_key")
|
80
107
|
if not api_key:
|
@@ -82,9 +109,11 @@ class MetaSearchEngine(BaseSearchEngine):
|
|
82
109
|
|
83
110
|
available.append(name)
|
84
111
|
|
85
|
-
#
|
86
|
-
if not available
|
87
|
-
|
112
|
+
# If no engines are available, raise an error instead of falling back silently
|
113
|
+
if not available:
|
114
|
+
error_msg = "No search engines enabled for auto search. Please enable at least one engine in settings."
|
115
|
+
logger.error(error_msg)
|
116
|
+
raise RuntimeError(error_msg)
|
88
117
|
|
89
118
|
return available
|
90
119
|
|
@@ -131,6 +160,17 @@ class MetaSearchEngine(BaseSearchEngine):
|
|
131
160
|
except KeyError as e:
|
132
161
|
logger.error(f"Missing key for engine {engine_name}: {str(e)}")
|
133
162
|
|
163
|
+
# Only proceed if we have engines available to choose from
|
164
|
+
if not engines_info:
|
165
|
+
logger.warning(
|
166
|
+
"No engine information available for prompt, using reliability-based sorting instead"
|
167
|
+
)
|
168
|
+
return sorted(
|
169
|
+
self.available_engines,
|
170
|
+
key=lambda x: search_config().get(x, {}).get("reliability", 0),
|
171
|
+
reverse=True,
|
172
|
+
)
|
173
|
+
|
134
174
|
prompt = f"""You are a search query analyst. Consider this search query:
|
135
175
|
|
136
176
|
QUERY: {query}
|