local-deep-research 0.1.1__tar.gz → 0.1.13__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.
Files changed (66) hide show
  1. {local_deep_research-0.1.1/src/local_deep_research.egg-info → local_deep_research-0.1.13}/PKG-INFO +9 -3
  2. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/README.md +5 -0
  3. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/pyproject.toml +2 -2
  4. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/requirements.txt +3 -2
  5. local_deep_research-0.1.13/src/local_deep_research/config.py +221 -0
  6. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/search_system.py +1 -1
  7. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web/app.py +373 -64
  8. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web/static/css/styles.css +245 -6
  9. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web/static/js/app.js +1917 -675
  10. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web/templates/index.html +34 -0
  11. {local_deep_research-0.1.1 → local_deep_research-0.1.13/src/local_deep_research.egg-info}/PKG-INFO +9 -3
  12. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research.egg-info/requires.txt +1 -1
  13. local_deep_research-0.1.1/src/local_deep_research/config.py +0 -166
  14. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/LICENSE +0 -0
  15. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/MANIFEST.in +0 -0
  16. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/setup.cfg +0 -0
  17. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/__init__.py +0 -0
  18. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/citation_handler.py +0 -0
  19. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/defaults/__init__.py +0 -0
  20. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/defaults/llm_config.py +0 -0
  21. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/defaults/local_collections.toml +0 -0
  22. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/defaults/main.toml +0 -0
  23. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/defaults/search_engines.toml +0 -0
  24. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/local_collections.py +0 -0
  25. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/main.py +0 -0
  26. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/report_generator.py +0 -0
  27. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/utilties/__init__.py +0 -0
  28. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/utilties/enums.py +0 -0
  29. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/utilties/llm_utils.py +0 -0
  30. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/utilties/search_utilities.py +0 -0
  31. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/utilties/setup_utils.py +0 -0
  32. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web/__init__.py +0 -0
  33. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web/templates/api_keys_config.html +0 -0
  34. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web/templates/collections_config.html +0 -0
  35. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web/templates/llm_config.html +0 -0
  36. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web/templates/main_config.html +0 -0
  37. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web/templates/search_engines_config.html +0 -0
  38. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web/templates/settings.html +0 -0
  39. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web/templates/settings_dashboard.html +0 -0
  40. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/__init__.py +0 -0
  41. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/__init__.py +0 -0
  42. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/full_search.py +0 -0
  43. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/meta_search_engine.py +0 -0
  44. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_arxiv.py +0 -0
  45. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_brave.py +0 -0
  46. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_ddg.py +0 -0
  47. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_github.py +0 -0
  48. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_google_pse.py +0 -0
  49. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_guardian.py +0 -0
  50. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_local.py +0 -0
  51. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_local_all.py +0 -0
  52. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_medrxiv.py +0 -0
  53. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_pubmed.py +0 -0
  54. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_searxng.py +0 -0
  55. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_serpapi.py +0 -0
  56. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_wayback.py +0 -0
  57. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/engines/search_engine_wikipedia.py +0 -0
  58. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/full_search.py +0 -0
  59. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/search_engine_base.py +0 -0
  60. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/search_engine_factory.py +0 -0
  61. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research/web_search_engines/search_engines_config.py +0 -0
  62. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research.egg-info/SOURCES.txt +0 -0
  63. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research.egg-info/dependency_links.txt +0 -0
  64. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research.egg-info/entry_points.txt +0 -0
  65. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/src/local_deep_research.egg-info/top_level.txt +0 -0
  66. {local_deep_research-0.1.1 → local_deep_research-0.1.13}/tests/test_google_pse.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: local-deep-research
3
- Version: 0.1.1
3
+ Version: 0.1.13
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
@@ -51,7 +51,7 @@ Requires-Dist: flask-socketio>=5.1.1
51
51
  Requires-Dist: sqlalchemy>=1.4.23
52
52
  Requires-Dist: wikipedia
53
53
  Requires-Dist: arxiv>=1.4.3
54
- Requires-Dist: PyPDF2>=2.0.0
54
+ Requires-Dist: pypdf
55
55
  Requires-Dist: sentence-transformers
56
56
  Requires-Dist: faiss-cpu
57
57
  Requires-Dist: pydantic>=2.0.0
@@ -59,6 +59,7 @@ Requires-Dist: pydantic-settings>=2.0.0
59
59
  Requires-Dist: toml>=0.10.2
60
60
  Requires-Dist: platformdirs>=3.0.0
61
61
  Requires-Dist: dynaconf
62
+ Dynamic: license-file
62
63
 
63
64
  # Local Deep Research
64
65
 
@@ -157,6 +158,11 @@ pip install local-deep-research
157
158
  playwright install
158
159
  ollama pull mistral
159
160
  ```
161
+ ## Community & Support
162
+
163
+ We've just launched our [Discord server](https://discord.gg/2E6gYU2Z) for this project!
164
+
165
+ Our Discord server can help to exchange ideas about research approaches, discuss advanced usage patterns, and share other ideas.
160
166
 
161
167
  # Edit .env with your API keys (if using cloud LLMs)
162
168
  ANTHROPIC_API_KEY=your-api-key-here # For Claude
@@ -95,6 +95,11 @@ pip install local-deep-research
95
95
  playwright install
96
96
  ollama pull mistral
97
97
  ```
98
+ ## Community & Support
99
+
100
+ We've just launched our [Discord server](https://discord.gg/2E6gYU2Z) for this project!
101
+
102
+ Our Discord server can help to exchange ideas about research approaches, discuss advanced usage patterns, and share other ideas.
98
103
 
99
104
  # Edit .env with your API keys (if using cloud LLMs)
100
105
  ANTHROPIC_API_KEY=your-api-key-here # For Claude
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "local-deep-research"
7
- version = "0.1.1"
7
+ version = "0.1.13"
8
8
  description = "AI-powered research assistant with deep, iterative analysis using LLMs and web searches"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -37,7 +37,7 @@ dependencies = [
37
37
  "sqlalchemy>=1.4.23",
38
38
  "wikipedia",
39
39
  "arxiv>=1.4.3",
40
- "PyPDF2>=2.0.0",
40
+ "pypdf",
41
41
  "sentence-transformers",
42
42
  "faiss-cpu",
43
43
  "pydantic>=2.0.0",
@@ -19,7 +19,8 @@ sqlalchemy>=1.4.23
19
19
  google-search-results
20
20
  wikipedia
21
21
  arxiv>=1.4.3
22
- PyPDF2>=2.0.0 # Optional - for extracting text from PDFs if needed
22
+ # PyPDF2>=2.0.0 # Optional - for extracting text from PDFs if needed
23
+ pypdf
23
24
 
24
25
  sentence-transformers # local search
25
- faiss-cpu # faiss-gpu
26
+ faiss-cpu # faiss-gpu
@@ -0,0 +1,221 @@
1
+ # local_deep_research/config.py
2
+ from dynaconf import Dynaconf
3
+ from pathlib import Path
4
+ import logging
5
+ from platformdirs import user_documents_dir
6
+ import os
7
+ # Setup logging
8
+ logger = logging.getLogger(__name__)
9
+
10
+ # Get config directory
11
+ def get_config_dir():
12
+ import platform
13
+
14
+ if platform.system() == "Windows":
15
+ # Windows: Use Documents directory
16
+ from platformdirs import user_documents_dir
17
+ config_dir = Path(user_documents_dir()) / "LearningCircuit" / "local-deep-research"
18
+ else:
19
+ # Linux/Mac: Use standard config directory
20
+ from platformdirs import user_config_dir
21
+ config_dir = Path(user_config_dir("local_deep_research", "LearningCircuit"))
22
+
23
+ print(f"Looking for config in: {config_dir}")
24
+ return config_dir
25
+ # Define config paths
26
+ CONFIG_DIR = get_config_dir() / "config"
27
+ CONFIG_DIR.mkdir(parents=True, exist_ok=True)
28
+ SETTINGS_FILE = CONFIG_DIR / "settings.toml"
29
+ SECRETS_FILE = CONFIG_DIR / ".secrets.toml"
30
+ LLM_CONFIG_FILE = CONFIG_DIR / "llm_config.py"
31
+ SEARCH_ENGINES_FILE = CONFIG_DIR / "search_engines.toml"
32
+
33
+ LOCAL_COLLECTIONS_FILE = CONFIG_DIR / "local_collections.toml"
34
+ print("CONFIGDIR:", CONFIG_DIR)
35
+ print("SECRETS_FILE:", SECRETS_FILE)
36
+ print("SETTINGS_FILE:", SETTINGS_FILE)
37
+
38
+
39
+ # Set environment variable for Dynaconf to use
40
+ docs_base = Path(user_documents_dir()) / "local_deep_research"
41
+ os.environ["DOCS_DIR"] = str(docs_base)
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+ # Expose get_llm function
51
+ def get_llm(*args, **kwargs):
52
+ """
53
+ Helper function to get LLM from llm_config.py
54
+ """
55
+ # Import here to avoid circular imports
56
+ import importlib.util
57
+ import sys
58
+
59
+ llm_config_path = CONFIG_DIR / "llm_config.py"
60
+
61
+ # If llm_config.py exists, use it
62
+ if llm_config_path.exists():
63
+ if str(CONFIG_DIR) not in sys.path:
64
+ sys.path.insert(0, str(CONFIG_DIR))
65
+
66
+ spec = importlib.util.spec_from_file_location("llm_config", llm_config_path)
67
+ llm_config = importlib.util.module_from_spec(spec)
68
+ spec.loader.exec_module(llm_config)
69
+
70
+ if hasattr(llm_config, "get_llm"):
71
+ return llm_config.get_llm(*args, **kwargs)
72
+
73
+ # Fallback to utility function
74
+ from .utilties.llm_utils import get_model
75
+ return get_model(*args, **kwargs)
76
+
77
+ # Expose get_search function
78
+ def get_search(search_tool=None):
79
+ """
80
+ Helper function to get search engine
81
+ """
82
+
83
+ # Use specified tool or default from settings
84
+ tool = search_tool or settings.search.tool
85
+ logger.info(f"Search tool is: {tool}")
86
+
87
+ # Import here to avoid circular imports
88
+ from .web_search_engines.search_engine_factory import get_search as factory_get_search
89
+
90
+ # Get search parameters
91
+ params = {
92
+ "search_tool": tool,
93
+ "llm_instance": get_llm(),
94
+ "max_results": settings.get("max_results"),
95
+ "region": settings.get("region"),
96
+ "time_period": settings.get("time_period"),
97
+ "safe_search": settings.get("safe_search"),
98
+ "search_snippets_only": settings.get("snippets_only"),
99
+ "search_language": settings.get("search_language"),
100
+ "max_filtered_results": settings.get("max_filtered_results")
101
+ }
102
+
103
+ # Create and return search engine
104
+ return factory_get_search(**params)
105
+
106
+ def init_config_files():
107
+ """Initialize config files if they don't exist"""
108
+ import shutil
109
+ import os
110
+ import sys
111
+ import platform
112
+
113
+ # Ensure CONFIG_DIR exists with explicit creation
114
+ os.makedirs(CONFIG_DIR, exist_ok=True)
115
+
116
+ # Get default files path with more reliable approach for Windows
117
+ if platform.system() == "Windows":
118
+ # Use a more reliable method on Windows
119
+ from pkg_resources import resource_filename
120
+ try:
121
+ defaults_dir = Path(resource_filename('local_deep_research', 'defaults'))
122
+ logger.info(f"Using pkg_resources for Windows: {defaults_dir}")
123
+
124
+ # Create settings.toml if it doesn't exist (with explicit Windows paths)
125
+ settings_file = os.path.join(CONFIG_DIR, "settings.toml")
126
+ default_settings = os.path.join(defaults_dir, "main.toml")
127
+ if not os.path.exists(settings_file) and os.path.exists(default_settings):
128
+ shutil.copyfile(default_settings, settings_file)
129
+ logger.info(f"Created settings.toml at {settings_file}")
130
+
131
+ # Create llm_config.py if it doesn't exist
132
+ llm_config_file = os.path.join(CONFIG_DIR, "llm_config.py")
133
+ default_llm = os.path.join(defaults_dir, "llm_config.py")
134
+ if not os.path.exists(llm_config_file) and os.path.exists(default_llm):
135
+ shutil.copyfile(default_llm, llm_config_file)
136
+ logger.info(f"Created llm_config.py at {llm_config_file}")
137
+
138
+ # Create local_collections.toml if it doesn't exist
139
+ collections_file = os.path.join(CONFIG_DIR, "local_collections.toml")
140
+ default_collections = os.path.join(defaults_dir, "local_collections.toml")
141
+ if not os.path.exists(collections_file) and os.path.exists(default_collections):
142
+ shutil.copyfile(default_collections, collections_file)
143
+ logger.info(f"Created local_collections.toml at {collections_file}")
144
+
145
+ # Create search_engines.toml if it doesn't exist
146
+ search_engines_file = os.path.join(CONFIG_DIR, "search_engines.toml")
147
+ default_engines = os.path.join(defaults_dir, "search_engines.toml")
148
+ if not os.path.exists(search_engines_file) and os.path.exists(default_engines):
149
+ shutil.copyfile(default_engines, search_engines_file)
150
+ logger.info(f"Created search_engines.toml at {search_engines_file}")
151
+ except Exception as e:
152
+ logger.error(f"Error initializing Windows config files: {e}")
153
+ else:
154
+ """Initialize config files if they don't exist"""
155
+ import shutil
156
+ from importlib.resources import files
157
+
158
+ # Get default files path
159
+ try:
160
+ defaults_dir = files('local_deep_research.defaults')
161
+ except ImportError:
162
+ # Fallback for older Python versions
163
+ from pkg_resources import resource_filename
164
+ defaults_dir = Path(resource_filename('local_deep_research', 'defaults'))
165
+
166
+ # Create settings.toml if it doesn't exist
167
+ settings_file = CONFIG_DIR / "settings.toml"
168
+ if not settings_file.exists():
169
+ shutil.copy(defaults_dir / "main.toml", settings_file)
170
+ logger.info(f"Created settings.toml at {settings_file}")
171
+
172
+ # Create llm_config.py if it doesn't exist
173
+ llm_config_file = CONFIG_DIR / "llm_config.py"
174
+ if not llm_config_file.exists():
175
+ shutil.copy(defaults_dir / "llm_config.py", llm_config_file)
176
+ logger.info(f"Created llm_config.py at {llm_config_file}")
177
+
178
+ # Create local_collections.toml if it doesn't exist
179
+ collections_file = CONFIG_DIR / "local_collections.toml"
180
+ if not collections_file.exists():
181
+ shutil.copy(defaults_dir / "local_collections.toml", collections_file)
182
+ logger.info(f"Created local_collections.toml at {collections_file}")
183
+
184
+ # Create search_engines.toml if it doesn't exist
185
+ search_engines_file = CONFIG_DIR / "search_engines.toml"
186
+ if not search_engines_file.exists():
187
+ shutil.copy(defaults_dir / "search_engines.toml", search_engines_file)
188
+ logger.info(f"Created search_engines.toml at {search_engines_file}")
189
+
190
+ secrets_file = CONFIG_DIR / ".secrets.toml"
191
+ if not secrets_file.exists():
192
+ with open(secrets_file, "w") as f:
193
+ f.write("""
194
+ # ANTHROPIC_API_KEY = "your-api-key-here"
195
+ # OPENAI_API_KEY = "your-openai-key-here"
196
+ # GOOGLE_API_KEY = "your-google-key-here"
197
+ # SERP_API_KEY = "your-api-key-here"
198
+ # GUARDIAN_API_KEY = "your-api-key-here"
199
+ # GOOGLE_PSE_API_KEY = "your-google-api-key-here"
200
+ # GOOGLE_PSE_ENGINE_ID = "your-programmable-search-engine-id-here"
201
+ """)
202
+
203
+ # Initialize config files on import
204
+ init_config_files()
205
+
206
+ # Use an absolute path to your .secrets.toml for testing
207
+ secrets_file = Path(SECRETS_FILE)
208
+
209
+ settings = Dynaconf(
210
+ settings_files=[
211
+ str(SETTINGS_FILE),
212
+ str(LOCAL_COLLECTIONS_FILE),
213
+ str(SEARCH_ENGINES_FILE),
214
+ ],
215
+ secrets=str(SECRETS_FILE),
216
+ env_prefix="LDR",
217
+ load_dotenv=True,
218
+ envvar_prefix="LDR",
219
+ env_file=str(CONFIG_DIR / ".env"),
220
+ )
221
+
@@ -182,7 +182,7 @@ class AdvancedSearchSystem:
182
182
  int(question_progress_base + 2),
183
183
  {"phase": "search_complete", "result_count": len(search_results)})
184
184
 
185
- logger.info("len search", len(search_results))
185
+ logger.info(f"len search: {len(search_results)}")
186
186
 
187
187
  if len(search_results) == 0:
188
188
  continue