lionagi 0.0.204__py3-none-any.whl → 0.0.206__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,,