lumis-ai 0.1.1a1__tar.gz → 0.1.1a3__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 (106) hide show
  1. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/PKG-INFO +10 -11
  2. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/README.md +1 -0
  3. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/research_agent/tools/search.py +2 -3
  4. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/tools/scraper.py +0 -10
  5. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/tools/search/arxiv.py +22 -6
  6. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/tools/search/pytrends.py +7 -1
  7. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/tools/search/search_engine_client.py +8 -1
  8. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/tools/search/yahoofinance.py +16 -7
  9. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/pyproject.toml +10 -13
  10. lumis_ai-0.1.1a3/uv.lock +5215 -0
  11. lumis_ai-0.1.1a1/uv.lock +0 -3340
  12. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/.github/workflows/publish.yml +0 -0
  13. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/.gitignore +0 -0
  14. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/.python-version +0 -0
  15. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/.vscode/settings.json +0 -0
  16. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/LICENSE +0 -0
  17. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/cookbook/__init__.py +0 -0
  18. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/cookbook/information_extraction.ipynb +0 -0
  19. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/cookbook/nlp.ipynb +0 -0
  20. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/cookbook/utils/config.py +0 -0
  21. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/cookbook/utils/helper.py +0 -0
  22. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/__init__.py +0 -0
  23. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/__init__.py +0 -0
  24. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/base/__init__.py +0 -0
  25. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/base/base_agent.py +0 -0
  26. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/base/core_agent.py +0 -0
  27. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/base/graph_based_agent.py +0 -0
  28. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/prompt_refinement_pipeline.py +0 -0
  29. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/qa_research_agent.py +0 -0
  30. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/react_agent.py +0 -0
  31. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/research_agent/__init__.py +0 -0
  32. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/research_agent/agent.py +0 -0
  33. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/research_agent/source_models.py +0 -0
  34. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/research_agent/source_tracker.py +0 -0
  35. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/research_agent/tools/__init__.py +0 -0
  36. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/research_agent/types.py +0 -0
  37. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/storm/agent.py +0 -0
  38. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/storm/interview_graph.py +0 -0
  39. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/storm/models/outline.py +0 -0
  40. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/agents/storm/models/survey_subjects.py +0 -0
  41. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/common/__init__.py +0 -0
  42. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/__init__.py +0 -0
  43. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/common/coloured_logger.py +0 -0
  44. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/common/logger_mixin.py +0 -0
  45. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/django/__init__.py +0 -0
  46. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/django/models/chat_memory.py +0 -0
  47. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/document.py +0 -0
  48. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/event_emitter.py +0 -0
  49. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/utils/__init__.py +0 -0
  50. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/utils/coroutine.py +0 -0
  51. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/utils/helpers.py +0 -0
  52. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/utils/inference.py +0 -0
  53. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/utils/number.py +0 -0
  54. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/utils/status_manager.py +0 -0
  55. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/utils/string.py +0 -0
  56. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/utils/thread_runner.py +0 -0
  57. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/utils/thread_safe_cache.py +0 -0
  58. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/utils/time.py +0 -0
  59. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/core/utils/types.py +0 -0
  60. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/embedding/__init__.py +0 -0
  61. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/embedding/base_embedding.py +0 -0
  62. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/embedding/huggingface_embedding.py +0 -0
  63. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/embedding/openai_embedding.py +0 -0
  64. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/evaluators/__init__.py +0 -0
  65. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/evaluators/conciseness_and_clarity_analyzer.py +0 -0
  66. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/evaluators/relevancy.py +0 -0
  67. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/kit/__init__.py +0 -0
  68. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/kit/graph.py +0 -0
  69. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/kit/nodes/__init__.py +0 -0
  70. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/kit/nodes/llm_chat_node.py +0 -0
  71. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/kit/nodes/llm_node.py +0 -0
  72. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/kit/nodes/llm_structured_node.py +0 -0
  73. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/kit/utils.py +0 -0
  74. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/llm/__init__.py +0 -0
  75. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/llm/base_llm.py +0 -0
  76. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/llm/gemini_llm.py +0 -0
  77. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/llm/ollama_llm.py +0 -0
  78. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/llm/openai_llm.py +0 -0
  79. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/llm/perplexity_llm.py +0 -0
  80. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/memory/__init__.py +0 -0
  81. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/memory/base_memory.py +0 -0
  82. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/memory/simple_memory.py +0 -0
  83. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/nlp/__init__.py +0 -0
  84. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/nlp/information_extraction/FactExtractor.py +0 -0
  85. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/nlp/ner/config/entity_rel_extraction.cfg +0 -0
  86. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/nlp/ner/config/fill-config.cfg +0 -0
  87. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/nlp/ner/ner.py +0 -0
  88. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/nlp/semantic_parser.py +0 -0
  89. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/nlp/spacy_summarizer.py +0 -0
  90. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/nlp/summarizer.py +0 -0
  91. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/nlp/vector_similarity_retriever.py +0 -0
  92. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/reader/__init__.py +0 -0
  93. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/reader/pdf.py +0 -0
  94. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/storage/__init__.py +0 -0
  95. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/storage/base_vector_db.py +0 -0
  96. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/storage/chroma_vector_db.py +0 -0
  97. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/storage/faiss_vector_db.py +0 -0
  98. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/tools/__init__.py +0 -0
  99. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/tools/search/__init__.py +0 -0
  100. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/tools/search/vector_search_retrieval_engine.py +0 -0
  101. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis/tools/search/wiki.py +0 -0
  102. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/lumis.code-workspace +0 -0
  103. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/poetry.lock +0 -0
  104. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/poetry.toml +0 -0
  105. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/ruff.toml +0 -0
  106. {lumis_ai-0.1.1a1 → lumis_ai-0.1.1a3}/tests/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lumis-ai
3
- Version: 0.1.1a1
3
+ Version: 0.1.1a3
4
4
  Summary: An AI agent framework for building LLM-powered applications
5
5
  Project-URL: Homepage, https://github.com/tareksanger/lumis
6
6
  Project-URL: Repository, https://github.com/tareksanger/lumis
@@ -20,11 +20,11 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
20
  Classifier: Topic :: Software Development :: Libraries
21
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
22
  Requires-Python: >=3.11
23
- Requires-Dist: arxiv>=0.5.0
24
23
  Requires-Dist: asgiref>=3.8.1
25
24
  Requires-Dist: beautifulsoup4>=4.12.0
26
25
  Requires-Dist: deepmerge>=2.0.0
27
26
  Requires-Dist: faiss-cpu>=1.7.0
27
+ Requires-Dist: google-genai>=1.61.0
28
28
  Requires-Dist: googlesearch-python>=1.2.0
29
29
  Requires-Dist: httpx>=0.27.0
30
30
  Requires-Dist: huggingface-hub>=0.24.0
@@ -32,7 +32,6 @@ Requires-Dist: langchain-core>=0.3.13
32
32
  Requires-Dist: langchain>=0.3.4
33
33
  Requires-Dist: lxml>=4.9.0
34
34
  Requires-Dist: minify-html>=0.11.0
35
- Requires-Dist: neo4j>=5.25.0
36
35
  Requires-Dist: nltk>=3.9.0
37
36
  Requires-Dist: numpy>=1.24
38
37
  Requires-Dist: ollama>=0.3.0
@@ -42,14 +41,12 @@ Requires-Dist: pydantic>=2.9.2
42
41
  Requires-Dist: pymupdf>=1.22.0
43
42
  Requires-Dist: pypdf2>=3.0.0
44
43
  Requires-Dist: python-dateutil>=2.8.0
45
- Requires-Dist: pytrends>=5.1.0
46
44
  Requires-Dist: pyvis>=0.3.0
47
- Requires-Dist: readability-lxml>=3.3.0
45
+ Requires-Dist: readability-lxml>=0.8.0
48
46
  Requires-Dist: redis>=5.0.0
49
47
  Requires-Dist: requests>=2.28.0
50
48
  Requires-Dist: scikit-learn>=1.0.0
51
49
  Requires-Dist: sentence-transformers>=2.2.2
52
- Requires-Dist: tavily-python>=0.3.0
53
50
  Requires-Dist: tenacity>=9.0.0
54
51
  Requires-Dist: textstat>=0.7.0
55
52
  Requires-Dist: tiktoken>=0.5.0
@@ -57,14 +54,15 @@ Requires-Dist: torch>=2.5.0
57
54
  Requires-Dist: transformers>=4.0.0
58
55
  Requires-Dist: typing-extensions>=4.0.0
59
56
  Requires-Dist: wikipedia>=1.4.0
60
- Requires-Dist: yfinance>=0.2.0
61
57
  Provides-Extra: django
62
58
  Requires-Dist: django>=4.2; extra == 'django'
59
+ Provides-Extra: search
60
+ Requires-Dist: arxiv>=0.5.0; extra == 'search'
61
+ Requires-Dist: pytrends>=4.5.0; extra == 'search'
62
+ Requires-Dist: tavily-python>=0.3.0; extra == 'search'
63
+ Requires-Dist: yfinance>=0.2.0; extra == 'search'
63
64
  Provides-Extra: spacy
64
- Requires-Dist: coreferee-model-en>=1.0.0; extra == 'spacy'
65
- Requires-Dist: coreferee>=1.3.0; extra == 'spacy'
66
- Requires-Dist: en-core-web-lg<3.8.0,>=3.7.0; extra == 'spacy'
67
- Requires-Dist: en-core-web-trf<3.8.0,>=3.7.0; extra == 'spacy'
65
+ Requires-Dist: pytextrank>=3.2.0; extra == 'spacy'
68
66
  Requires-Dist: spacy-llm>=0.7.2; extra == 'spacy'
69
67
  Requires-Dist: spacy<3.8.0,>=3.7.0; extra == 'spacy'
70
68
  Description-Content-Type: text/markdown
@@ -97,6 +95,7 @@ Some integrations are opt-in to keep the base install lighter:
97
95
  | Extra | What it adds | Install |
98
96
  |------------|-----------------------------------------------|-----------------------------------|
99
97
  | `spacy` | NER, fact extraction, coreference resolution | `pip install lumis-ai[spacy]` |
98
+ | `search` | arXiv, Google Trends, Yahoo Finance | `pip install lumis-ai[search]` |
100
99
  | `django` | Django ORM memory backend | `pip install lumis-ai[django]` |
101
100
 
102
101
  The `spacy` extra requires language models. After installing, download them:
@@ -26,6 +26,7 @@ Some integrations are opt-in to keep the base install lighter:
26
26
  | Extra | What it adds | Install |
27
27
  |------------|-----------------------------------------------|-----------------------------------|
28
28
  | `spacy` | NER, fact extraction, coreference resolution | `pip install lumis-ai[spacy]` |
29
+ | `search` | arXiv, Google Trends, Yahoo Finance | `pip install lumis-ai[search]` |
29
30
  | `django` | Django ORM memory backend | `pip install lumis-ai[django]` |
30
31
 
31
32
  The `spacy` extra requires language models. After installing, download them:
@@ -7,8 +7,6 @@ from typing import Any, Optional
7
7
  from lumis.llm import Gemini
8
8
  from lumis.tools import WikipediaSearcher
9
9
  from lumis.tools.search.arxiv import ArxivResult, ArxivSearcher
10
-
11
- from arxiv import SortCriterion, SortOrder
12
10
  from tenacity import retry, retry_if_exception_type, stop_after_attempt, wait_exponential
13
11
 
14
12
  logger = logging.getLogger(__name__)
@@ -173,7 +171,8 @@ async def search_arxiv( # noqa: C901
173
171
  summary_semaphore = asyncio.Semaphore(4)
174
172
 
175
173
  try:
176
- # Convert string sort parameters to enums
174
+ from arxiv import SortCriterion, SortOrder
175
+
177
176
  sort_criterion = SortCriterion(sort_by)
178
177
  sort_order_enum = SortOrder(sort_order)
179
178
 
@@ -278,16 +278,6 @@ class WebScrapper:
278
278
  raise e
279
279
 
280
280
  return None
281
-
282
- # async def from_gotenberg(self, url: str, metadata: Optional[dict]) -> Optional[Document]:
283
- # # Same logic as before, but uses injected gb_client
284
- # try:
285
- # response = await self.gb_client.afrom_url(url)
286
- # return await self.parse_pdf(response.content, metadata)
287
- # except Exception as e:
288
- # logger.debug(f"Gotenberg failed for {url}: {e}")
289
- # return None
290
-
291
281
  def _url_with_protocol(self, url: str):
292
282
  if not url.startswith("http://") and not url.startswith("https://"):
293
283
  url = "https://" + url
@@ -7,12 +7,15 @@ import logging
7
7
  from typing import Any, Dict, Optional
8
8
  import xml.etree.ElementTree as ET
9
9
 
10
- import arxiv
11
- from arxiv import Client, SortCriterion, SortOrder
10
+ from typing import TYPE_CHECKING
11
+
12
12
  import httpx
13
13
  from lumis.core.document import Document
14
14
  import pymupdf
15
15
 
16
+ if TYPE_CHECKING:
17
+ from arxiv import SortCriterion, SortOrder
18
+
16
19
  logger = logging.getLogger(__name__)
17
20
 
18
21
 
@@ -36,8 +39,16 @@ class ArxivResult:
36
39
 
37
40
  class ArxivSearcher:
38
41
  def __init__(self, max_results: int = 10, max_concurrent_pdfs: int = 5) -> None:
42
+ try:
43
+ import arxiv
44
+ except ImportError:
45
+ raise ImportError(
46
+ "arxiv is required for ArxivSearcher. "
47
+ "Install it with: pip install lumis-ai[search]"
48
+ )
49
+ self._arxiv = arxiv
39
50
  self.max_results: int = max_results
40
- self.client = Client()
51
+ self.client = arxiv.Client()
41
52
  self._http_client = httpx.AsyncClient()
42
53
  self._result_cache: dict[str, ArxivResult] = {} # Cache for results by arxiv_id
43
54
  self._pdf_semaphore = asyncio.Semaphore(max_concurrent_pdfs)
@@ -46,8 +57,8 @@ class ArxivSearcher:
46
57
  self,
47
58
  query: str,
48
59
  max_results: Optional[int] = None,
49
- sort_by: SortCriterion = SortCriterion.SubmittedDate,
50
- sort_order: SortOrder = SortOrder.Descending,
60
+ sort_by: SortCriterion | None = None,
61
+ sort_order: SortOrder | None = None,
51
62
  id_list: Optional[list[str]] = None,
52
63
  read_pdfs: bool = False,
53
64
  ) -> list[ArxivResult]:
@@ -65,8 +76,13 @@ class ArxivSearcher:
65
76
  Returns:
66
77
  list of ArxivResult objects
67
78
  """
79
+ if sort_by is None:
80
+ sort_by = self._arxiv.SortCriterion.SubmittedDate
81
+ if sort_order is None:
82
+ sort_order = self._arxiv.SortOrder.Descending
83
+
68
84
  # Create search object with all available options
69
- search = arxiv.Search(query=query, max_results=max_results or self.max_results, sort_by=sort_by, sort_order=sort_order, id_list=id_list or [])
85
+ search = self._arxiv.Search(query=query, max_results=max_results or self.max_results, sort_by=sort_by, sort_order=sort_order, id_list=id_list or [])
70
86
 
71
87
  results: list[ArxivResult] = []
72
88
  pdf_tasks = []
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from typing import Any, Dict, List
4
4
 
5
5
  from asgiref.sync import sync_to_async
6
- from pytrends.request import TrendReq
7
6
 
8
7
 
9
8
  class PyTrends:
@@ -12,6 +11,13 @@ class PyTrends:
12
11
  """
13
12
 
14
13
  def __init__(self, tz: int = 0, retries: int = 3, backoff: float = 0.1):
14
+ try:
15
+ from pytrends.request import TrendReq
16
+ except ImportError:
17
+ raise ImportError(
18
+ "pytrends is required for PyTrends. "
19
+ "Install it with: pip install lumis-ai[search]"
20
+ )
15
21
  self.pytrends = TrendReq(retries=retries, backoff_factor=backoff, tz=tz) # type: ignore
16
22
 
17
23
  @sync_to_async
@@ -8,9 +8,16 @@ from typing import Literal, Optional, Sequence
8
8
 
9
9
  from googlesearch import search as google_search
10
10
  import redis.asyncio as aioredis
11
- from tavily import TavilyClient, UsageLimitExceededError
12
11
  from typing_extensions import TypedDict
13
12
 
13
+ try:
14
+ from tavili import TavilyClient, UsageLimitExceededError
15
+ except ImportError:
16
+ TavilyClient = None # type: ignore[assignment,misc]
17
+
18
+ class UsageLimitExceededError(Exception): # type: ignore[no-redef]
19
+ pass
20
+
14
21
  logger = logging.getLogger(__name__)
15
22
 
16
23
 
@@ -7,7 +7,6 @@ from typing import Any, cast, Optional
7
7
  from asgiref.sync import sync_to_async
8
8
  import pandas as pd
9
9
  from pydantic import BaseModel, Field
10
- import yfinance as yf
11
10
 
12
11
  logger = logging.getLogger(__name__)
13
12
 
@@ -53,6 +52,16 @@ class YahooFinance:
53
52
  with async codebases.
54
53
  """
55
54
 
55
+ def __init__(self):
56
+ try:
57
+ import yfinance as yf
58
+ except ImportError:
59
+ raise ImportError(
60
+ "yfinance is required for YahooFinance. "
61
+ "Install it with: pip install lumis-ai[search]"
62
+ )
63
+ self._yf = yf
64
+
56
65
  @sync_to_async
57
66
  def get_quote(self, ticker: str) -> QuoteData:
58
67
  """
@@ -70,7 +79,7 @@ class YahooFinance:
70
79
  """
71
80
  try:
72
81
  logger.debug(f"Fetching quote data for ticker: {ticker}")
73
- t = yf.Ticker(ticker)
82
+ t = self._yf.Ticker(ticker)
74
83
  info = t.info
75
84
 
76
85
  return QuoteData(
@@ -114,7 +123,7 @@ class YahooFinance:
114
123
  """
115
124
  try:
116
125
  logger.debug(f"Fetching historical data for {ticker} with period={period}, interval={interval}")
117
- t = yf.Ticker(ticker)
126
+ t = self._yf.Ticker(ticker)
118
127
  hist = t.history(period=period, interval=interval, start=start, end=end)
119
128
 
120
129
  return [
@@ -149,8 +158,8 @@ class YahooFinance:
149
158
  """
150
159
  try:
151
160
  logger.debug(f"Searching for tickers matching: {query}")
152
- # Using yf.Tickers() as get_tickers_by_search is deprecated
153
- tickers = yf.Tickers(query)
161
+ # Using self._yf.Tickers() as get_tickers_by_search is deprecated
162
+ tickers = self._yf.Tickers(query)
154
163
  return [{"symbol": symbol, "name": ticker.info.get("shortName", symbol)} for symbol, ticker in tickers.tickers.items()]
155
164
  except Exception as e:
156
165
  logger.error(f"Error searching tickers for {query}: {str(e)}")
@@ -172,7 +181,7 @@ class YahooFinance:
172
181
  """
173
182
  try:
174
183
  logger.debug(f"Fetching recommendations for {ticker}")
175
- t = yf.Ticker(ticker)
184
+ t = self._yf.Ticker(ticker)
176
185
  if t.recommendations is None:
177
186
  return []
178
187
  df = cast(pd.DataFrame, t.recommendations)
@@ -197,7 +206,7 @@ class YahooFinance:
197
206
  """
198
207
  try:
199
208
  logger.debug(f"Fetching major holders for {ticker}")
200
- t = yf.Ticker(ticker)
209
+ t = self._yf.Ticker(ticker)
201
210
  if t.major_holders is None:
202
211
  return {}
203
212
  df = cast(pd.DataFrame, t.major_holders)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lumis-ai"
3
- version = "0.1.1a1"
3
+ version = "0.1.1a3"
4
4
  description = "An AI agent framework for building LLM-powered applications"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -22,7 +22,6 @@ classifiers = [
22
22
  "Topic :: Scientific/Engineering :: Artificial Intelligence",
23
23
  ]
24
24
  dependencies = [
25
- "arxiv>=0.5.0",
26
25
  "asgiref>=3.8.1",
27
26
  "beautifulsoup4>=4.12.0",
28
27
  "deepmerge>=2.0.0",
@@ -34,7 +33,6 @@ dependencies = [
34
33
  "langchain-core>=0.3.13",
35
34
  "lxml>=4.9.0",
36
35
  "minify-html>=0.11.0",
37
- "neo4j>=5.25.0",
38
36
  "nltk>=3.9.0",
39
37
  "numpy>=1.24",
40
38
  "ollama>=0.3.0",
@@ -44,14 +42,12 @@ dependencies = [
44
42
  "PyPDF2>=3.0.0",
45
43
  "pydantic>=2.9.2",
46
44
  "python-dateutil>=2.8.0",
47
- "pytrends>=5.1.0",
48
45
  "pyvis>=0.3.0",
49
- "readability-lxml>=3.3.0",
46
+ "readability-lxml>=0.8.0",
50
47
  "redis>=5.0.0",
51
48
  "requests>=2.28.0",
52
49
  "scikit-learn>=1.0.0",
53
50
  "sentence-transformers>=2.2.2",
54
- "tavily-python>=0.3.0",
55
51
  "tenacity>=9.0.0",
56
52
  "textstat>=0.7.0",
57
53
  "tiktoken>=0.5.0",
@@ -59,18 +55,21 @@ dependencies = [
59
55
  "transformers>=4.0.0",
60
56
  "typing-extensions>=4.0.0",
61
57
  "wikipedia>=1.4.0",
62
- "yfinance>=0.2.0",
58
+ "google-genai>=1.61.0",
63
59
  ]
64
60
 
65
61
  [project.optional-dependencies]
66
62
  django = [
67
63
  "django>=4.2",
68
64
  ]
65
+ search = [
66
+ "arxiv>=0.5.0",
67
+ "pytrends>=4.5.0",
68
+ "tavily-python>=0.3.0",
69
+ "yfinance>=0.2.0",
70
+ ]
69
71
  spacy = [
70
- "coreferee>=1.3.0",
71
- "coreferee-model-en>=1.0.0",
72
- "en-core-web-lg>=3.7.0,<3.8.0",
73
- "en-core-web-trf>=3.7.0,<3.8.0",
72
+ "pytextrank>=3.2.0",
74
73
  "spacy>=3.7.0,<3.8.0",
75
74
  "spacy-llm>=0.7.2",
76
75
  ]
@@ -94,8 +93,6 @@ dev = [
94
93
  torch = [
95
94
  { index = "pytorch", marker = "sys_platform != 'darwin'" },
96
95
  ]
97
- en-core-web-trf = { url = "https://github.com/explosion/spacy-models/releases/download/en_core_web_trf-3.7.1/en_core_web_trf-3.7.1-py3-none-any.whl" }
98
- en-core-web-lg = { url = "https://github.com/explosion/spacy-models/releases/download/en_core_web_lg-3.7.0/en_core_web_lg-3.7.0-py3-none-any.whl" }
99
96
 
100
97
  [[tool.uv.index]]
101
98
  name = "pytorch"