local-deep-research 0.1.0__py3-none-any.whl → 0.1.1__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/defaults/main.toml +5 -0
- local_deep_research/search_system.py +98 -38
- local_deep_research/web/app.py +360 -117
- local_deep_research/web/static/css/styles.css +28 -2
- local_deep_research/web/static/js/app.js +640 -197
- local_deep_research/web/templates/index.html +3 -1
- local_deep_research/web_search_engines/engines/search_engine_searxng.py +454 -0
- local_deep_research/web_search_engines/search_engine_factory.py +20 -1
- {local_deep_research-0.1.0.dist-info → local_deep_research-0.1.1.dist-info}/METADATA +16 -4
- {local_deep_research-0.1.0.dist-info → local_deep_research-0.1.1.dist-info}/RECORD +14 -13
- {local_deep_research-0.1.0.dist-info → local_deep_research-0.1.1.dist-info}/LICENSE +0 -0
- {local_deep_research-0.1.0.dist-info → local_deep_research-0.1.1.dist-info}/WHEEL +0 -0
- {local_deep_research-0.1.0.dist-info → local_deep_research-0.1.1.dist-info}/entry_points.txt +0 -0
- {local_deep_research-0.1.0.dist-info → local_deep_research-0.1.1.dist-info}/top_level.txt +0 -0
@@ -14,6 +14,11 @@ knowledge_accumulation_context_limit = 2000000
|
|
14
14
|
# Enable fact checking (experimental, works better with large LLMs)
|
15
15
|
enable_fact_checking = false
|
16
16
|
|
17
|
+
[web]
|
18
|
+
port = 5000
|
19
|
+
host = "0.0.0.0"
|
20
|
+
debug = true
|
21
|
+
|
17
22
|
[search]
|
18
23
|
# Search tool to use (auto, wikipedia, arxiv, duckduckgo, serp, google_pse, etc.)
|
19
24
|
# "auto" intelligently selects based on query content (recommended)
|
@@ -25,6 +25,11 @@ class AdvancedSearchSystem:
|
|
25
25
|
self.citation_handler = CitationHandler(self.model)
|
26
26
|
self.progress_callback = None
|
27
27
|
self.all_links_of_system = list()
|
28
|
+
|
29
|
+
# Check if search is available, log warning if not
|
30
|
+
if self.search is None:
|
31
|
+
print("WARNING: Search system initialized with no search engine! Research will not be effective.")
|
32
|
+
self._update_progress("WARNING: No search engine available", None, {"error": "No search engine configured properly"})
|
28
33
|
|
29
34
|
|
30
35
|
|
@@ -114,6 +119,23 @@ class AdvancedSearchSystem:
|
|
114
119
|
"phase": "init",
|
115
120
|
"iterations_planned": total_iterations
|
116
121
|
})
|
122
|
+
|
123
|
+
# Check if search engine is available
|
124
|
+
if self.search is None:
|
125
|
+
error_msg = "Error: No search engine available. Please check your configuration."
|
126
|
+
self._update_progress(error_msg, 100, {
|
127
|
+
"phase": "error",
|
128
|
+
"error": "No search engine available",
|
129
|
+
"status": "failed"
|
130
|
+
})
|
131
|
+
return {
|
132
|
+
"findings": [],
|
133
|
+
"iterations": 0,
|
134
|
+
"questions": {},
|
135
|
+
"formatted_findings": "Error: Unable to conduct research without a search engine.",
|
136
|
+
"current_knowledge": "",
|
137
|
+
"error": error_msg
|
138
|
+
}
|
117
139
|
|
118
140
|
while iteration < self.max_iterations:
|
119
141
|
iteration_progress_base = (iteration / total_iterations) * 100
|
@@ -133,7 +155,21 @@ class AdvancedSearchSystem:
|
|
133
155
|
int(question_progress_base),
|
134
156
|
{"phase": "search", "iteration": iteration + 1, "question_index": q_idx + 1})
|
135
157
|
|
136
|
-
|
158
|
+
try:
|
159
|
+
if self.search is None:
|
160
|
+
self._update_progress(f"Search engine unavailable, skipping search for: {question}",
|
161
|
+
int(question_progress_base + 2),
|
162
|
+
{"phase": "search_error", "error": "No search engine available"})
|
163
|
+
search_results = []
|
164
|
+
else:
|
165
|
+
search_results = self.search.run(question)
|
166
|
+
except Exception as e:
|
167
|
+
error_msg = f"Error during search: {str(e)}"
|
168
|
+
print(f"SEARCH ERROR: {error_msg}")
|
169
|
+
self._update_progress(error_msg,
|
170
|
+
int(question_progress_base + 2),
|
171
|
+
{"phase": "search_error", "error": str(e)})
|
172
|
+
search_results = []
|
137
173
|
|
138
174
|
if search_results is None:
|
139
175
|
self._update_progress(f"No search results found for question: {question}",
|
@@ -155,57 +191,81 @@ class AdvancedSearchSystem:
|
|
155
191
|
int(question_progress_base + 5),
|
156
192
|
{"phase": "analysis"})
|
157
193
|
print("NR OF SOURCES: ", len(self.all_links_of_system))
|
158
|
-
result = self.citation_handler.analyze_followup(
|
159
|
-
question, search_results, current_knowledge, nr_of_links=len(self.all_links_of_system)
|
160
|
-
)
|
161
|
-
links = extract_links_from_search_results(search_results)
|
162
|
-
self.all_links_of_system.extend(links)
|
163
|
-
section_links.extend(links)
|
164
|
-
formatted_links = ""
|
165
|
-
if links:
|
166
|
-
formatted_links=format_links(links=links)
|
167
|
-
|
168
|
-
logger.debug(f"Generated questions: {formatted_links}")
|
169
|
-
if result is not None:
|
170
|
-
results_with_links = str(result["content"])
|
171
|
-
findings.append(
|
172
|
-
{
|
173
|
-
"phase": f"Follow-up {iteration}.{questions.index(question) + 1}",
|
174
|
-
"content": results_with_links,
|
175
|
-
"question": question,
|
176
|
-
"search_results": search_results,
|
177
|
-
"documents": result["documents"],
|
178
|
-
}
|
179
|
-
)
|
180
194
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
195
|
+
try:
|
196
|
+
result = self.citation_handler.analyze_followup(
|
197
|
+
question, search_results, current_knowledge, nr_of_links=len(self.all_links_of_system)
|
198
|
+
)
|
199
|
+
links = extract_links_from_search_results(search_results)
|
200
|
+
self.all_links_of_system.extend(links)
|
201
|
+
section_links.extend(links)
|
202
|
+
formatted_links = ""
|
203
|
+
if links:
|
204
|
+
formatted_links=format_links(links=links)
|
190
205
|
|
191
|
-
|
192
|
-
|
193
|
-
|
206
|
+
logger.debug(f"Generated questions: {formatted_links}")
|
207
|
+
if result is not None:
|
208
|
+
results_with_links = str(result["content"])
|
209
|
+
findings.append(
|
210
|
+
{
|
211
|
+
"phase": f"Follow-up {iteration}.{questions.index(question) + 1}",
|
212
|
+
"content": results_with_links,
|
213
|
+
"question": question,
|
214
|
+
"search_results": search_results,
|
215
|
+
"documents": result["documents"],
|
216
|
+
}
|
217
|
+
)
|
194
218
|
|
219
|
+
if settings.general.knowledge_accumulation != KnowledgeAccumulationApproach.NO_KNOWLEDGE:
|
220
|
+
current_knowledge = current_knowledge + "\n\n\n New: \n" + results_with_links
|
221
|
+
|
222
|
+
print(current_knowledge)
|
223
|
+
if settings.general.knowledge_accumulation == KnowledgeAccumulationApproach.QUESTION:
|
224
|
+
self._update_progress(f"Compress Knowledge for: {question}",
|
225
|
+
int(question_progress_base + 0),
|
226
|
+
{"phase": "analysis"})
|
227
|
+
current_knowledge = self._compress_knowledge(current_knowledge , query, section_links)
|
228
|
+
|
229
|
+
self._update_progress(f"Analysis complete for question: {question}",
|
230
|
+
int(question_progress_base + 10),
|
231
|
+
{"phase": "analysis_complete"})
|
232
|
+
except Exception as e:
|
233
|
+
error_msg = f"Error analyzing results: {str(e)}"
|
234
|
+
print(f"ANALYSIS ERROR: {error_msg}")
|
235
|
+
self._update_progress(error_msg,
|
236
|
+
int(question_progress_base + 10),
|
237
|
+
{"phase": "analysis_error", "error": str(e)})
|
195
238
|
iteration += 1
|
196
239
|
|
197
240
|
self._update_progress(f"Compressing knowledge after iteration {iteration}",
|
198
241
|
int((iteration / total_iterations) * 100 - 5),
|
199
242
|
{"phase": "knowledge_compression"})
|
243
|
+
|
200
244
|
if settings.general.knowledge_accumulation == KnowledgeAccumulationApproach.ITERATION:
|
201
|
-
|
245
|
+
try:
|
246
|
+
current_knowledge = self._compress_knowledge(current_knowledge , query, section_links)
|
247
|
+
except Exception as e:
|
248
|
+
error_msg = f"Error compressing knowledge: {str(e)}"
|
249
|
+
print(f"COMPRESSION ERROR: {error_msg}")
|
250
|
+
self._update_progress(error_msg,
|
251
|
+
int((iteration / total_iterations) * 100 - 3),
|
252
|
+
{"phase": "compression_error", "error": str(e)})
|
253
|
+
|
202
254
|
|
203
255
|
|
204
256
|
self._update_progress(f"Iteration {iteration} complete",
|
205
257
|
int((iteration / total_iterations) * 100),
|
206
258
|
{"phase": "iteration_complete", "iteration": iteration})
|
207
259
|
|
208
|
-
|
260
|
+
try:
|
261
|
+
formatted_findings = self._save_findings(findings, current_knowledge, query)
|
262
|
+
except Exception as e:
|
263
|
+
error_msg = f"Error saving findings: {str(e)}"
|
264
|
+
print(f"SAVE ERROR: {error_msg}")
|
265
|
+
self._update_progress(error_msg,
|
266
|
+
int((iteration / total_iterations) * 100),
|
267
|
+
{"phase": "save_error", "error": str(e)})
|
268
|
+
formatted_findings = "Error: Could not format findings due to an error."
|
209
269
|
|
210
270
|
self._update_progress("Research complete", 95, {"phase": "complete"})
|
211
271
|
|
@@ -213,7 +273,7 @@ class AdvancedSearchSystem:
|
|
213
273
|
"findings": findings,
|
214
274
|
"iterations": iteration,
|
215
275
|
"questions": self.questions_by_iteration,
|
216
|
-
"formatted_findings": formatted_findings,
|
276
|
+
"formatted_findings": formatted_findings if 'formatted_findings' in locals() else "Error: Findings not available.",
|
217
277
|
"current_knowledge": current_knowledge
|
218
278
|
}
|
219
279
|
|