lionagi 0.0.204__py3-none-any.whl → 0.0.206__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.
@@ -1 +1,33 @@
1
- # TODO
1
+ from ..utils.sys_util import install_import, is_package_installed
2
+ from .base_service import BaseService
3
+
4
+
5
+ class LiteLLMService(BaseService):
6
+ def __init__(self, model: str = None, **kwargs):
7
+ super().__init__()
8
+
9
+ try:
10
+ if not is_package_installed('litellm'):
11
+ install_import(
12
+ package_name='litellm',
13
+ import_name='acompletion'
14
+ )
15
+ from litellm import acompletion
16
+ self.acompletion = acompletion
17
+ except:
18
+ raise ImportError(f'Unable to import required module from ollama. Please make sure that ollama is installed.')
19
+
20
+ self.model = model
21
+ self.kwargs = kwargs
22
+
23
+ async def serve_chat(self, messages, **kwargs):
24
+ payload = {'messages': messages}
25
+ kwargs = {**self.kwargs, **kwargs}
26
+
27
+ try:
28
+ completion = await self.acompletion(model=self.model, messages=messages, **kwargs)
29
+ return payload, completion
30
+ except Exception as e:
31
+ self.status_tracker.num_tasks_failed += 1
32
+ raise e
33
+
@@ -0,0 +1,39 @@
1
+ from ..utils.sys_util import install_import, is_package_installed, as_dict
2
+ from .base_service import BaseService
3
+
4
+
5
+ class MlXService(BaseService):
6
+ def __init__(self, model="mlx-community/OLMo-7B-hf-4bit-mlx", **kwargs):
7
+
8
+ if not is_package_installed('mlx_lm'):
9
+ install_import(package_name='mlx_lm')
10
+
11
+ from mlx_lm import load, generate
12
+ super().__init__()
13
+
14
+ model_, tokenizer = load(model, **kwargs)
15
+
16
+ self.model_name = model
17
+ self.model = model_
18
+ self.tokenizer = tokenizer
19
+ self.generate = generate
20
+
21
+ async def serve_chat(self, messages, **kwargs):
22
+ prompts = [as_dict(msg['content'])['instruction'] for msg in messages if msg['role'] == 'user']
23
+
24
+ payload = {'messages': messages}
25
+
26
+ try:
27
+ response = self.generate(
28
+ self.model, self.tokenizer, prompt=f"{prompts[-1]} \nOutput: ", **kwargs
29
+ )
30
+ completion = {
31
+ 'model': self.model_name,
32
+ 'choices': [{'message': response}]
33
+ }
34
+
35
+ return payload, completion
36
+ except Exception as e:
37
+ self.status_tracker.num_tasks_failed += 1
38
+ raise e
39
+
@@ -1 +1,33 @@
1
- # TODO
1
+ from ..utils.sys_util import install_import, is_package_installed
2
+ from .base_service import BaseService
3
+
4
+ class OllamaService(BaseService):
5
+ def __init__(self, model: str = None, **kwargs):
6
+ super().__init__()
7
+
8
+ try:
9
+ if not is_package_installed('ollama'):
10
+ install_import(
11
+ package_name='ollama',
12
+ import_name='Client'
13
+ )
14
+ import ollama
15
+ self.ollama = ollama
16
+ except:
17
+ raise ImportError(f'Unable to import required module from ollama. Please make sure that ollama is installed.')
18
+
19
+ self.model = model
20
+ self.client = self.ollama.Client(**kwargs)
21
+
22
+ async def serve_chat(self, messages, **kwargs):
23
+ self.ollama.pull(self.model)
24
+ payload = {'messages': messages}
25
+
26
+ try:
27
+ completion = self.client.chat(model=self.model, messages=messages, **kwargs)
28
+ completion['choices'] = [{'message': completion.pop('message')}]
29
+ return payload, completion
30
+ except Exception as e:
31
+ self.status_tracker.num_tasks_failed += 1
32
+ raise e
33
+
@@ -89,3 +89,43 @@ class Services:
89
89
 
90
90
  from .anthropic import AnthropicService
91
91
  return AnthropicService(**kwargs)
92
+
93
+ @staticmethod
94
+ def Ollama(**kwargs):
95
+ """
96
+ A service to interact with Ollama
97
+
98
+ Attributes:
99
+ model (str): name of the model to use
100
+ kwargs (Optional[Any]): additional kwargs for calling the model
101
+ """
102
+
103
+ from .ollama import OllamaService
104
+ return OllamaService(**kwargs)
105
+
106
+ @staticmethod
107
+ def LiteLLM(**kwargs):
108
+ """
109
+ A service to interact with Litellm
110
+
111
+ Attributes:
112
+ model (str): name of the model to use
113
+ kwargs (Optional[Any]): additional kwargs for calling the model
114
+ """
115
+
116
+ from .litellm import LiteLLMService
117
+ return LiteLLMService(**kwargs)
118
+
119
+ @staticmethod
120
+ def MLX(**kwargs):
121
+ """
122
+ A service to interact with MlX
123
+
124
+ Attributes:
125
+ model (str): name of the model to use
126
+ kwargs (Optional[Any]): additional kwargs for calling the model
127
+ """
128
+
129
+ from .mlx_service import MlXService
130
+ return MlXService(**kwargs)
131
+
@@ -1,46 +1,73 @@
1
- from typing import Union, str, Dict, Any
2
- from transformers import pipeline, Conversation
1
+ from typing import Union, Dict, Any
2
+ import subprocess
3
3
 
4
+ from ..utils.sys_util import install_import, get_cpu_architecture, is_package_installed
4
5
  from .base_service import BaseService
5
6
 
6
- import functools
7
- from concurrent.futures import ThreadPoolExecutor
8
- import asyncio
9
7
 
8
+ def get_pytorch_install_command():
9
+ cpu_arch = get_cpu_architecture()
10
10
 
11
- def force_async(fn):
12
- pool = ThreadPoolExecutor()
13
-
14
- @functools.wraps(fn)
15
- def wrapper(*args, **kwargs):
16
- future = pool.submit(fn, *args, **kwargs)
17
- return asyncio.wrap_future(future) # make it awaitable
18
-
19
- return wrapper
11
+ if cpu_arch == 'apple_silicon':
12
+ return "pip install --pre torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/nightly/cpu"
13
+ else:
14
+ # Default CPU installation
15
+ return "pip install torch torchvision torchaudio"
20
16
 
17
+ def install_pytorch():
18
+ command = get_pytorch_install_command()
19
+ try:
20
+ subprocess.run(command.split(), check=True)
21
+ print("PyTorch installed successfully.")
22
+ except subprocess.CalledProcessError as e:
23
+ print(f"Failed to install PyTorch: {e}")
21
24
 
22
25
  class TransformersService(BaseService):
23
- def __init__(self, task: str = None, model: Union[str, Any] = None, config: Union[str, Dict, Any] = None, **kwargs):
26
+ def __init__(self, task: str = None, model: Union[str, Any] = None, config: Union[str, Dict, Any] = None, device='cpu', **kwargs):
24
27
  super().__init__()
25
28
  self.task = task
26
29
  self.model = model
27
30
  self.config = config
28
- self.pipe = pipeline(task=task, model=model, config=config, **kwargs)
31
+ try:
32
+ from transformers import pipeline
33
+ self.pipeline = pipeline
34
+ except ImportError:
35
+ try:
36
+ if not is_package_installed('torch'):
37
+ in_ = input("PyTorch is required for transformers. Would you like to install it now? (y/n): ")
38
+ if in_ == 'y':
39
+ install_pytorch()
40
+ if not is_package_installed('transformers'):
41
+ in_ = input("transformers is required. Would you like to install it now? (y/n): ")
42
+ if in_ == 'y':
43
+ install_import(
44
+ package_name='transformers',
45
+ import_name='pipeline'
46
+ )
47
+ from transformers import pipeline
48
+ self.pipeline = pipeline
49
+ except Exception as e:
50
+ raise ImportError(f'Unable to import required module from transformers. Please make sure that transformers is installed. Error: {e}')
51
+
52
+ self.pipe = self.pipeline(task=task, model=model, config=config, device=device, **kwargs)
29
53
 
30
- @force_async
31
- def serve_chat(self, messages, **kwargs):
54
+ async def serve_chat(self, messages, **kwargs):
32
55
  if self.task:
33
56
  if self.task != 'conversational':
34
- raise ValueError(f"Invalid transformers pipeline task: {self.task}. Valid task: 'conversational'")
57
+ raise ValueError(f"Invalid transformers pipeline task: {self.task}.")
35
58
 
36
59
  payload = {'messages': messages}
37
- conversation = self.pipe(Conversation(messages), **kwargs)
38
- completion = {"Conversation id": conversation.uuid,
60
+ conversation = self.pipe(str(messages), **kwargs)
61
+
62
+ texts = conversation[-1]['generated_text']
63
+ msgs = str(texts.split(']')[1:]).replace('\\n', '').replace("[\'", "").replace('\\', '')
64
+
65
+ completion = {
39
66
  "model": self.pipe.model,
40
67
  "choices": [{
41
- "message": conversation.messages[-1]
68
+ "message": msgs
42
69
  }]
43
70
  }
44
71
 
45
72
  return payload, completion
46
-
73
+
@@ -1,5 +1,5 @@
1
1
  from typing import Union, Callable, List, Dict, Any, TypeVar
2
- from ..utils.sys_util import change_dict_key
2
+ from ..utils.sys_util import change_dict_key, install_import
3
3
  from ..schema.data_node import DataNode
4
4
 
5
5
 
@@ -43,7 +43,18 @@ def to_langchain_document(datanode: T, **kwargs: Any) -> Any:
43
43
  >>> isinstance(lc_document, LangchainDocument)
44
44
  True
45
45
  """
46
- from langchain.schema import Document
46
+ try:
47
+ from langchain.schema import Document
48
+ except ImportError:
49
+ try:
50
+ install_import(
51
+ package_name='langchain',
52
+ module_name='schema',
53
+ import_name='Document',
54
+ )
55
+ from langchain.schema import Document
56
+ except Exception as e:
57
+ raise ImportError(f'Unable to import required module from langchain. Please make sure that langchain is installed. Error: {e}')
47
58
 
48
59
  dnode = datanode.to_dict()
49
60
  change_dict_key(dnode, old_key='content', new_key='page_content')
@@ -73,11 +84,24 @@ def langchain_loader(loader: Union[str, Callable],
73
84
  >>> isinstance(data, dict)
74
85
  True
75
86
  """
76
- import langchain.document_loaders as document_loaders
77
-
87
+ try:
88
+ import langchain.document_loaders as document_loaders
89
+ except ImportError:
90
+ try:
91
+ install_import(
92
+ package_name='langchain',
93
+ module_name='document_loaders',
94
+ )
95
+ import langchain.document_loaders as document_loaders
96
+ except Exception as e:
97
+ raise ImportError(f'Unable to import required module from langchain. Please make sure that langchain is installed. Error: {e}')
98
+
78
99
  try:
79
100
  if isinstance(loader, str):
80
- loader = getattr(document_loaders, loader)
101
+ try:
102
+ loader = getattr(document_loaders, loader)
103
+ except ImportError as e:
104
+ raise ValueError(f'Unable to import {loader} from langchain.document_loaders. Some dependency of LangChain are not installed. Error: {e}')
81
105
  else:
82
106
  loader = loader
83
107
  except Exception as e:
@@ -110,7 +134,17 @@ def langchain_text_splitter(data: Union[str, List],
110
134
  ValueError: If the specified text splitter is invalid or if the splitting fails.
111
135
  """
112
136
 
113
- import langchain.text_splitter as text_splitter
137
+ try:
138
+ import langchain.text_splitter as text_splitter
139
+ except ImportError:
140
+ try:
141
+ install_import(
142
+ package_name='langchain',
143
+ module_name='text_splitter'
144
+ )
145
+ import langchain.text_splitter as text_splitter
146
+ except Exception as e:
147
+ raise ImportError(f'Unable to import required module from langchain. Please make sure that langchain is installed. Error: {e}')
114
148
 
115
149
  try:
116
150
  if isinstance(splitter, str):
@@ -1,5 +1,5 @@
1
1
  from typing import Union, Callable, List, Any, Dict, TypeVar
2
- from ..utils.sys_util import change_dict_key
2
+ from ..utils.sys_util import change_dict_key, install_import, is_package_installed
3
3
  from ..schema.data_node import DataNode
4
4
 
5
5
 
@@ -38,7 +38,18 @@ def to_llama_index_textnode(datanode: T, **kwargs: Any) -> Any:
38
38
  datanode = DataNode(...)
39
39
  textnode = to_llama_index_textnode(datanode, additional_arg=1)
40
40
  """
41
- from llama_index.schema import TextNode
41
+ try:
42
+ from llama_index.schema import TextNode
43
+ except ImportError:
44
+ try:
45
+ install_import(
46
+ package_name='llama_index',
47
+ module_name='schema',
48
+ import_name='TextNode'
49
+ )
50
+ from llama_index.schema import TextNode
51
+ except Exception as e:
52
+ raise ImportError(f'Unable to import required module from llama_index. Please make sure that llama_index is installed. Error: {e}')
42
53
 
43
54
  dnode = datanode.to_dict()
44
55
  change_dict_key(dnode, old_key='content', new_key='text')
@@ -67,14 +78,36 @@ def get_llama_reader(reader: Union[str, Callable]) -> Callable:
67
78
  def custom_reader(): pass
68
79
  reader = get_llama_reader(custom_reader)
69
80
  """
81
+
70
82
  try:
71
83
  if isinstance(reader, str):
72
84
  if reader == 'SimpleDirectoryReader':
73
- from llama_index import SimpleDirectoryReader
74
- return SimpleDirectoryReader
75
- else:
76
- from llama_index import download_loader
77
- return download_loader(reader)
85
+ try:
86
+ from llama_index import SimpleDirectoryReader
87
+ return SimpleDirectoryReader
88
+ except ImportError or ModuleNotFoundError:
89
+ try:
90
+ install_import(
91
+ package_name='llama_index',
92
+ import_name='SimpleDirectoryReader'
93
+ )
94
+ from llama_index import SimpleDirectoryReader
95
+ return SimpleDirectoryReader
96
+ except Exception as e:
97
+ raise ImportError(f'Failed to import SimpleDirectoryReader. Error: {e}')
98
+ else:
99
+ try:
100
+ from llama_index import download_loader
101
+ return download_loader(reader)
102
+ except ImportError:
103
+ try:
104
+ install_import(
105
+ package_name='llama_index',
106
+ import_name='download_loader'
107
+ )
108
+ return download_loader(reader)
109
+ except Exception as e:
110
+ raise ImportError(f'Failed to import download_loader from LlamaIndex. Error: {e}')
78
111
  else:
79
112
  return reader
80
113
  except Exception as e:
@@ -133,11 +166,43 @@ def get_llama_parser(parser: Union[str, Callable]) -> Callable:
133
166
  def custom_parser(): pass
134
167
  parser = get_llama_parser(custom_parser)
135
168
  """
136
- import llama_index.node_parser as node_parser
137
- import llama_index.text_splitter as text_splitter
169
+
170
+ try:
171
+ import llama_index.node_parser as node_parser
172
+ except ImportError:
173
+ try:
174
+ install_import(
175
+ package_name='llama_index',
176
+ module_name='node_parser'
177
+ )
178
+ import llama_index.node_parser as node_parser
179
+ except ImportError:
180
+ raise ImportError('Failed to import Llama Index. Please install Llama Index to use this function.')
181
+ except Exception as e:
182
+ raise ValueError(f'Invalid node parser: {parser}. Error: {e}')
138
183
 
139
184
  try:
140
- return getattr(node_parser, parser)
185
+ import llama_index.text_splitter as text_splitter
186
+ except ImportError:
187
+ try:
188
+ install_import(
189
+ package_name='llama_index',
190
+ module_name='text_splitter'
191
+ )
192
+ import llama_index.text_splitter as text_splitter
193
+ except ImportError:
194
+ raise ImportError('Failed to import Llama Index. Please install Llama Index to use this function.')
195
+
196
+ try:
197
+ if parser == 'CodeSplitter':
198
+ if not is_package_installed('tree_sitter_languages'):
199
+ install_import(package_name='tree_sitter_languages')
200
+
201
+ a = getattr(node_parser, parser)
202
+ if a is not None:
203
+ return a
204
+ else:
205
+ raise ImportError(f'Failed to import {parser} from Llama Index.')
141
206
  except Exception as e1:
142
207
  try:
143
208
  if isinstance(parser, str):
@@ -172,13 +237,25 @@ def llama_index_node_parser(documents: List[Any],
172
237
  Example:
173
238
  nodes = llama_index_node_parser(documents, "DefaultNodeParser")
174
239
  """
175
- parser = get_llama_parser(parser)
176
240
 
177
241
  try:
242
+ parser = get_llama_parser(parser)
178
243
  parser_obj = parser(*parser_args, **parser_kwargs)
179
244
  nodes = parser_obj.get_nodes_from_documents(documents, **parsing_kwargs)
180
245
  return nodes
181
246
 
247
+ except ImportError as e:
248
+ module_name = str(e).split("\'")[-2]
249
+ try:
250
+ install_import(package_name=module_name)
251
+ parser = get_llama_parser(parser)
252
+ parser_obj = parser(*parser_args, **parser_kwargs)
253
+ nodes = parser_obj.get_nodes_from_documents(documents, **parsing_kwargs)
254
+ return nodes
255
+ except Exception as e:
256
+ raise ImportError(f'Failed to install and import {module_name}. Error: {e}')
257
+
258
+
182
259
  except Exception as e1:
183
260
  try:
184
261
  parser_obj = parser.from_defaults(*parser_args, **parser_kwargs)
@@ -7,7 +7,7 @@ from collections import deque
7
7
  import asyncio
8
8
  from dotenv import load_dotenv
9
9
 
10
- from lionagi.utils import as_dict, get_flattened_keys, lcall
10
+ from lionagi.utils import as_dict, get_flattened_keys, alcall, lcall, mcall, to_list
11
11
  from lionagi.schema import Tool
12
12
  from lionagi._services.base_service import StatusTracker, BaseService
13
13
  from lionagi._services.oai import OpenAIService
@@ -375,10 +375,10 @@ class Branch(Conversation):
375
375
  self.tool_manager.get_function_call
376
376
  )
377
377
 
378
- # outs = await alcall(func_calls, self.tool_manager.invoke)
378
+ outs = await alcall(func_calls, self.tool_manager.invoke)
379
+
380
+ outs = to_list(outs, flatten=True)
379
381
 
380
- tasks = [self.tool_manager.invoke(i) for i in func_calls]
381
- outs = await asyncio.gather(*tasks)
382
382
  for out_, f in zip(outs, func_calls):
383
383
  self.add_message(
384
384
  response={
@@ -8,9 +8,9 @@ from ..messages.messages import System, Instruction
8
8
  from ..branch.branch import Branch
9
9
  from ..branch.branch_manager import BranchManager
10
10
 
11
-
11
+
12
12
  load_dotenv()
13
- OAIService = OpenAIService()
13
+
14
14
 
15
15
  class Session:
16
16
  """
@@ -33,7 +33,7 @@ class Session:
33
33
  sender: Optional[str] = None,
34
34
  dir: Optional[str] = None,
35
35
  llmconfig: Optional[Dict[str, Any]] = None,
36
- service: OpenAIService = OAIService,
36
+ service: OpenAIService = None,
37
37
  branches: Optional[Dict[str, Branch]] = None,
38
38
  default_branch: Optional[Branch] = None,
39
39
  default_branch_name: str = 'main',
@@ -52,6 +52,9 @@ class Session:
52
52
  """
53
53
 
54
54
  self.branches = branches if isinstance(branches, dict) else {}
55
+ if service is None:
56
+ service = OpenAIService()
57
+
55
58
  self.default_branch = default_branch if default_branch else Branch(name=default_branch_name, service=service, llmconfig=llmconfig)
56
59
  self.default_branch_name = default_branch_name
57
60
  if system:
@@ -140,7 +140,8 @@ def chunk(documents,
140
140
  elif chunker_type == ChunkerType.LLAMAINDEX:
141
141
  if documents_convert_func:
142
142
  documents = documents_convert_func(documents, 'llama_index')
143
- nodes = llama_index_node_parser(documents, chunker, chunker_args, chunker_kwargs, chunking_kwargs)
143
+ nodes = llama_index_node_parser(documents, chunker, chunker_args, chunker_kwargs, chunking_kwargs)
144
+
144
145
  if isinstance(to_datanode, bool) and to_datanode is True:
145
146
  nodes = lcall(nodes, from_llama_index)
146
147
  elif isinstance(to_datanode, Callable):
@@ -1,7 +1,7 @@
1
1
  import json
2
2
  import asyncio
3
3
  from typing import Dict, Union, List, Tuple, Any
4
- from lionagi.utils import lcall
4
+ from lionagi.utils.call_util import lcall, is_coroutine_func, _call_handler
5
5
  from lionagi.schema import BaseNode, Tool
6
6
 
7
7
 
@@ -74,10 +74,10 @@ class ToolManager(BaseNode):
74
74
  func = tool.func
75
75
  parser = tool.parser
76
76
  try:
77
- if asyncio.iscoroutinefunction(func):
78
- return await parser(func(**kwargs)) if parser else func(**kwargs)
79
- else:
80
- return parser(func(**kwargs)) if parser else func(**kwargs)
77
+ tasks = [await _call_handler(func, **kwargs)]
78
+ out = await asyncio.gather(*tasks)
79
+ return parser(out) if parser else out
80
+
81
81
  except Exception as e:
82
82
  raise ValueError(f"Error when invoking function {name} with arguments {kwargs} with error message {e}")
83
83
  else:
lionagi/utils/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from .sys_util import (
2
2
  get_timestamp, create_copy, create_path, split_path,
3
3
  get_bins, change_dict_key, str_to_num, create_id,
4
- as_dict)
4
+ as_dict, is_package_installed, install_import)
5
5
 
6
6
  from .nested_util import (
7
7
  to_readable_dict, nfilter, nset, nget,
@@ -19,6 +19,7 @@ from .call_util import (
19
19
 
20
20
 
21
21
  __all__ = [
22
+ "is_package_installed", "install_import",
22
23
  'get_timestamp', 'create_copy', 'create_path', 'split_path',
23
24
  'get_bins', 'change_dict_key', 'str_to_num', 'create_id',
24
25
  'as_dict', 'to_list', 'to_readable_dict', 'nfilter', 'nset',
@@ -2,6 +2,8 @@ import asyncio
2
2
  import functools
3
3
  import logging
4
4
  import time
5
+
6
+ from concurrent.futures import ThreadPoolExecutor
5
7
  from typing import Any, Callable, Generator, Iterable, List, Dict, Optional, Tuple
6
8
 
7
9
  from aiocache import cached
@@ -643,6 +645,17 @@ class CallDecorator:
643
645
  reducing the frequency of resource-intensive operations.
644
646
  """
645
647
  return Throttle(period)
648
+
649
+ @staticmethod
650
+ def force_async(fn):
651
+ pool = ThreadPoolExecutor()
652
+
653
+ @functools.wraps(fn)
654
+ def wrapper(*args, **kwargs):
655
+ future = pool.submit(fn, *args, **kwargs)
656
+ return asyncio.wrap_future(future) # make it awaitable
657
+
658
+ return wrapper
646
659
 
647
660
  class Throttle:
648
661
  """
lionagi/utils/sys_util.py CHANGED
@@ -1,15 +1,27 @@
1
1
  import os
2
+ import subprocess
3
+ import sys
2
4
  import copy
3
5
  from datetime import datetime
4
6
  import hashlib
5
7
  import re
6
-
8
+ import importlib.util
9
+ import platform
7
10
  import json
8
11
  import logging
9
12
 
10
13
  from typing import Any, List, Dict, Union
11
14
 
12
15
 
16
+
17
+ def get_cpu_architecture():
18
+ arch = platform.machine()
19
+ if 'arm' in arch or 'aarch64' in arch:
20
+ return 'apple_silicon'
21
+ else:
22
+ return 'other_cpu'
23
+
24
+
13
25
  def get_timestamp() -> str:
14
26
  """
15
27
  Generates a current timestamp in ISO format with colons and periods replaced by
@@ -352,3 +364,53 @@ def is_schema(dict_: Dict, schema: Dict):
352
364
  def timestamp_to_datetime(timestamp):
353
365
  return datetime.fromtimestamp(timestamp)
354
366
 
367
+ def install_import(package_name, module_name=None, import_name=None, pip_name=None):
368
+
369
+ """
370
+ For a simple package import where package name matches pip name
371
+ import xx
372
+ install_and_import('xx')
373
+
374
+
375
+ For importing a module from a package
376
+ import xx.yy
377
+ install_and_import('xx', 'yy')
378
+
379
+ For importing a specific attribute from a module/sub-module
380
+ from xx.yy import zz
381
+ install_and_import('xx', 'yy', 'zz')
382
+
383
+ For cases where pip name differs from package name
384
+ install_and_import('xx', pip_name='different_pip_name')
385
+
386
+ For full example with different pip name
387
+ install_and_import('xx', 'yy', 'zz', 'different_pip_name')
388
+ """
389
+
390
+ if pip_name is None:
391
+ pip_name = package_name # Defaults to package_name if pip_name is not explicitly provided
392
+
393
+ full_import_path = package_name if module_name is None else f"{package_name}.{module_name}"
394
+
395
+ try:
396
+ if import_name:
397
+ # For importing a specific name from a module or sub-module
398
+ module = __import__(full_import_path, fromlist=[import_name])
399
+ getattr(module, import_name)
400
+ else:
401
+ # For importing the module or package itself
402
+ __import__(full_import_path)
403
+ print(f"Successfully imported {import_name or full_import_path}.")
404
+ except ImportError:
405
+ print(f"Module {full_import_path} or attribute {import_name} not found. Installing {pip_name}...")
406
+ subprocess.check_call([sys.executable, "-m", "pip", "install", pip_name])
407
+ # Retry the import after installation
408
+ if import_name:
409
+ module = __import__(full_import_path, fromlist=[import_name])
410
+ getattr(module, import_name)
411
+ else:
412
+ __import__(full_import_path)
413
+
414
+ def is_package_installed(package_name):
415
+ package_spec = importlib.util.find_spec(package_name)
416
+ return package_spec is not None
lionagi/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.0.204"
1
+ __version__ = "0.0.206"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lionagi
3
- Version: 0.0.204
3
+ Version: 0.0.206
4
4
  Summary: Towards automated general intelligence.
5
5
  Author: HaiyangLi
6
6
  Author-email: Haiyang Li <ocean@lionagi.ai>
@@ -1,5 +1,5 @@
1
1
  lionagi/__init__.py,sha256=pRm9tnfYQnj_ZCan3xr3HQO7tbUeqwRhSBtwOvXJ-o8,886
2
- lionagi/version.py,sha256=DFD_QxPb5C0pITp5fF5NUF2YLCrCu9FEfCgCY7YVy4I,24
2
+ lionagi/version.py,sha256=EA6dDEL8t5RD8Hger4VXh3to9S0SeeSMjzOVsPldZLo,24
3
3
  lionagi/_services/__init__.py,sha256=zU5sxmSI9-Jtp_WsI-Zsb6hmT8y5zF9YtJ7XikAjnbs,60
4
4
  lionagi/_services/anthropic.py,sha256=pLebbnr2H1A41bzXrJrU7yQbZY35swKrSi4mktXoIyk,3195
5
5
  lionagi/_services/anyscale.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -10,18 +10,19 @@ lionagi/_services/everlyai.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
10
10
  lionagi/_services/gemini.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  lionagi/_services/gpt4all.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  lionagi/_services/huggingface.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- lionagi/_services/litellm.py,sha256=chG3GNX2BBDTWIuSVfZUJ_YF_ZVBSoel2d_AN0OChS0,6
13
+ lionagi/_services/litellm.py,sha256=ho_iSwU6Zdez5fZV_UaSMK899iY-5tLRx1kepyOinGY,1118
14
14
  lionagi/_services/localai.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  lionagi/_services/mistralai.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ lionagi/_services/mlx_service.py,sha256=1AF_RcV4KQmpxC67n2E0zRbssSlsTFmdnojydUXdJn4,1285
16
17
  lionagi/_services/oai.py,sha256=Jiuw_TibpYhN6x1PmHYUMi_0Nugrxmi5G1eimAuw21I,3958
17
- lionagi/_services/ollama.py,sha256=chG3GNX2BBDTWIuSVfZUJ_YF_ZVBSoel2d_AN0OChS0,6
18
+ lionagi/_services/ollama.py,sha256=Cnl8S2dpOHZlHMg7f1l8x0jB_27Ww7Zdyb0WB5Hjs8U,1179
18
19
  lionagi/_services/openllm.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
20
  lionagi/_services/openrouter.py,sha256=MuuwoT2ro9FmY7O1jzCenRrL2YfiYUMM8-0kKoGZHAY,1799
20
21
  lionagi/_services/perplexity.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
22
  lionagi/_services/predibase.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
23
  lionagi/_services/rungpt.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- lionagi/_services/services.py,sha256=kY2TpT98pDS_qCrCO4H1YBlDYNDqekx5S9rWQdWm5Ck,4007
24
- lionagi/_services/transformers.py,sha256=tHlo9QVV5ycB2xUEKNRf-b665o_21fPC6c4ycH3Hjk4,1444
24
+ lionagi/_services/services.py,sha256=TwjAizQCTFCv_I8XZbTvpcryJPGt4vQAGYkGdZqJST0,5077
25
+ lionagi/_services/transformers.py,sha256=nGfQbcECKzA1biHe4i9l01aKCMgULKFQ4LZyqjtvSXk,2934
25
26
  lionagi/_services/vllm.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
27
  lionagi/_services/xinference.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
28
  lionagi/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -31,15 +32,15 @@ lionagi/agents/scorer.py,sha256=chG3GNX2BBDTWIuSVfZUJ_YF_ZVBSoel2d_AN0OChS0,6
31
32
  lionagi/agents/summarizer.py,sha256=chG3GNX2BBDTWIuSVfZUJ_YF_ZVBSoel2d_AN0OChS0,6
32
33
  lionagi/agents/validator.py,sha256=chG3GNX2BBDTWIuSVfZUJ_YF_ZVBSoel2d_AN0OChS0,6
33
34
  lionagi/bridge/__init__.py,sha256=YDKi-pniFEknEXTSEvX6yEe4Y69f0kLvbjvEQ0TdrTU,575
34
- lionagi/bridge/langchain.py,sha256=NuuUOJ5oV0l6ae4EeXxaeB82nJ6FDJHVC4AFBoIqiDs,5726
35
- lionagi/bridge/llama_index.py,sha256=oggpASmfVA6IhfgBOJS8CWJrQb3zrGaDApUQ7MWT8OM,6652
35
+ lionagi/bridge/langchain.py,sha256=y15hTYUrmvDdEyGCSgaUgrp5OalTvlMfkQb_-XISnEA,7233
36
+ lionagi/bridge/llama_index.py,sha256=PHoWPXuYuEX8PPfFFW509n7Tzq3RgNAtpu_EuXcryhA,9901
36
37
  lionagi/configs/__init__.py,sha256=QOd4Rs7vjIpNWvIocxWQeU-q-MPRC-AOxh-gM-eBJ2o,142
37
38
  lionagi/configs/oai_configs.py,sha256=Q2ESc5QiMprnRc_w7SeMlaTYUWl_Y4SEzZSE4iOkz4Q,2646
38
39
  lionagi/configs/openrouter_configs.py,sha256=IBQHqb8mo4Jb3kYAm_7NOHSKRPwSdGbPpDJoiwHxLYw,1269
39
40
  lionagi/core/__init__.py,sha256=6uDjq1WCWBahNiCpzGaUCJe7GDg6lwUD_cGNT86GhwM,200
40
41
  lionagi/core/core_util.py,sha256=80fmVywc0UC9FklXpQr5_dHdtdHdosv5Zxwy9tC-Ufg,2339
41
42
  lionagi/core/branch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
- lionagi/core/branch/branch.py,sha256=w3GZAws8_qgY17XOn6svmO4ECQqhNQ_rWMzXiwBQVO8,23403
43
+ lionagi/core/branch/branch.py,sha256=JpoyOC_merGuQbHDgVk0n55qh773YX-yifiLt58B8tI,23367
43
44
  lionagi/core/branch/branch_manager.py,sha256=kLVYUYVUmFQ2CPV34vfVRrkR6fhlizoAr3Dw2ilMX6M,4904
44
45
  lionagi/core/branch/cluster.py,sha256=chG3GNX2BBDTWIuSVfZUJ_YF_ZVBSoel2d_AN0OChS0,6
45
46
  lionagi/core/branch/conversation.py,sha256=q05EwDouTAH5eMDCp2wwRHK0ipbm0MYFngk8R6vOTB0,18664
@@ -51,7 +52,7 @@ lionagi/core/instruction_set/instruction_set.py,sha256=bxrxPxLJdaenvZ2CMaiucNB4f
51
52
  lionagi/core/messages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
53
  lionagi/core/messages/messages.py,sha256=bokGS8hu4wQxa-4Gsf2Eg7Q99ANccjjixZpE-DC0P7g,6533
53
54
  lionagi/core/sessions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
- lionagi/core/sessions/session.py,sha256=-dSlIIzHmD2dGd3zu4m_U-UE0BKraKYyt1H_DAzpngk,17694
55
+ lionagi/core/sessions/session.py,sha256=uj0hokNNVaKClvL0WbDZi6u8FdLQPf05TdPg2n7oDVg,17723
55
56
  lionagi/datastores/__init__.py,sha256=chG3GNX2BBDTWIuSVfZUJ_YF_ZVBSoel2d_AN0OChS0,6
56
57
  lionagi/datastores/chroma.py,sha256=chG3GNX2BBDTWIuSVfZUJ_YF_ZVBSoel2d_AN0OChS0,6
57
58
  lionagi/datastores/deeplake.py,sha256=chG3GNX2BBDTWIuSVfZUJ_YF_ZVBSoel2d_AN0OChS0,6
@@ -61,7 +62,7 @@ lionagi/datastores/pinecone.py,sha256=chG3GNX2BBDTWIuSVfZUJ_YF_ZVBSoel2d_AN0OChS
61
62
  lionagi/datastores/postgres.py,sha256=chG3GNX2BBDTWIuSVfZUJ_YF_ZVBSoel2d_AN0OChS0,6
62
63
  lionagi/datastores/qdrant.py,sha256=chG3GNX2BBDTWIuSVfZUJ_YF_ZVBSoel2d_AN0OChS0,6
63
64
  lionagi/loaders/__init__.py,sha256=vOOwHkdI0yIA_jV_pNyOrdkS5Ghs0k4od75S1U60jJE,451
64
- lionagi/loaders/chunker.py,sha256=UY6GrC8qC0MLRaHiSfgG5HMnrtWSTuIvaRPhYfdm9ak,6438
65
+ lionagi/loaders/chunker.py,sha256=noh7NagZ3PBYNgUTIjbYvLlHP9UvoLaShTfc843h7Co,6455
65
66
  lionagi/loaders/load_util.py,sha256=4fzhMk3H6OvcQcViUwlLPSTMpcY4alfdel16lJgXz8Y,8358
66
67
  lionagi/loaders/reader.py,sha256=xI1uxw9qGJ_rWev_s3vtW8Ep9YaK-15q7ts-Jy61PGg,4625
67
68
  lionagi/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -88,19 +89,19 @@ lionagi/tests/test_utils/test_io_util.py,sha256=cFZCT6EikVeuXB13w-UbtO3YceCHBO5R
88
89
  lionagi/tests/test_utils/test_nested_util.py,sha256=Z1boHufhjZryw51qW2lABOnnyJ1snAFp26KKzzzD8Bs,12612
89
90
  lionagi/tests/test_utils/test_sys_util.py,sha256=TDCkzll-JLa6NuBbN_-ay5Rw9KTa_HcSHHAq62RVwGI,13545
90
91
  lionagi/tools/__init__.py,sha256=ZEck-ReP5Co05nAA2gUXTpKoDN2QZqrL7DvU9Z09gqg,69
91
- lionagi/tools/tool_manager.py,sha256=4yCjMVOrKo4PoEMv0xF6wMirpj20qhLx4J7op0v5h2w,6543
92
+ lionagi/tools/tool_manager.py,sha256=bucA0bg-4NGw-CuVmigyC1o1lbgYOuu4F3Un6NV7yUM,6525
92
93
  lionagi/tools/tool_util.py,sha256=5ln7lnqC_rjhKDDwef10xrBrjP1yLzsQvphllD5crec,9252
93
- lionagi/utils/__init__.py,sha256=FJAqYyb19Mp6kiietyjtp0WLlW2857-HAHl7OxqCc5Y,954
94
+ lionagi/utils/__init__.py,sha256=GhpBUHB4uYeUK7Eah7292Ww_uehE5BAQJULQebfH5gM,1038
94
95
  lionagi/utils/api_util.py,sha256=YV-DKPgR4lCKO_riroSKyq6mO-8vz-SilRo_gWtg4Zg,15282
95
- lionagi/utils/call_util.py,sha256=G3K8dkEZ9AehrBdbKHK6Xtr1pZZWxrtqhQEu5xkItuo,32919
96
+ lionagi/utils/call_util.py,sha256=lDZiFE8b1MmkkQDulzkqXXufsG3sBUEnXjF6J6qYXx8,33268
96
97
  lionagi/utils/encrypt_util.py,sha256=iZjZdXVvl0lw4Yw_YNzIWriM3F2qKtzai7PgSQ1TExc,9316
97
98
  lionagi/utils/io_util.py,sha256=xoVsq8sP5JGsosuC80Kad3GkGjm8Qm0OLYyTw-U5ru8,6455
98
99
  lionagi/utils/nested_util.py,sha256=67j-ySQtuMGxtjnC-Ty2mwQgqp2g1gZhXRy1MulUu1U,26656
99
100
  lionagi/utils/pd_util.py,sha256=ShLdNRJI-U2nN9TmZEGPdRXHzFMfrmw-sTpUbxNWr1w,2274
100
- lionagi/utils/sys_util.py,sha256=iZQu3HvYLl-12mmZ0kk4lX-3FnkRh-EAMAefPt_6P7k,10893
101
+ lionagi/utils/sys_util.py,sha256=40VY2a7jgBjwAlKBbD29_Zj55ZHst2BIjOUoMsYUjiI,13045
101
102
  lionagi/utils/url_util.py,sha256=fu1uRFwSR9D3dO1nfSYVNRD1b1BZVClcbpgF7tA_U4s,1864
102
- lionagi-0.0.204.dist-info/LICENSE,sha256=TBnSyG8fs_tMRtK805GzA1cIyExleKyzoN_kuVxT9IY,11358
103
- lionagi-0.0.204.dist-info/METADATA,sha256=kxTcrwAWtkK8cRY0CAxJaOZ8lBIVQgFcy-8HT92mTuc,17894
104
- lionagi-0.0.204.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
105
- lionagi-0.0.204.dist-info/top_level.txt,sha256=szvch_d2jE1Lu9ZIKsl26Ll6BGfYfbOgt5lm-UpFSo4,8
106
- lionagi-0.0.204.dist-info/RECORD,,
103
+ lionagi-0.0.206.dist-info/LICENSE,sha256=TBnSyG8fs_tMRtK805GzA1cIyExleKyzoN_kuVxT9IY,11358
104
+ lionagi-0.0.206.dist-info/METADATA,sha256=bB1lTsiI0QovUpI9EZmvekqslY3Ugg0jP-jiF6D-zOI,17894
105
+ lionagi-0.0.206.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
106
+ lionagi-0.0.206.dist-info/top_level.txt,sha256=szvch_d2jE1Lu9ZIKsl26Ll6BGfYfbOgt5lm-UpFSo4,8
107
+ lionagi-0.0.206.dist-info/RECORD,,