lionagi 0.0.208__py3-none-any.whl → 0.0.210__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.
- lionagi/__init__.py +4 -6
- lionagi/api_service/base_endpoint.py +65 -0
- lionagi/api_service/base_rate_limiter.py +121 -0
- lionagi/api_service/base_service.py +146 -0
- lionagi/api_service/chat_completion.py +6 -0
- lionagi/api_service/embeddings.py +6 -0
- lionagi/api_service/payload_package.py +47 -0
- lionagi/api_service/status_tracker.py +29 -0
- lionagi/core/__init__.py +5 -9
- lionagi/core/branch.py +1191 -0
- lionagi/core/flow.py +423 -0
- lionagi/core/{instruction_set/instruction_set.py → instruction_set.py} +3 -3
- lionagi/core/session.py +872 -0
- lionagi/schema/__init__.py +5 -8
- lionagi/schema/base_schema.py +821 -0
- lionagi/{_services → services}/base_service.py +4 -4
- lionagi/{_services → services}/oai.py +4 -4
- lionagi/structures/graph.py +1 -1
- lionagi/structures/relationship.py +1 -1
- lionagi/structures/structure.py +1 -1
- lionagi/tools/tool_manager.py +0 -163
- lionagi/tools/tool_util.py +2 -1
- lionagi/utils/__init__.py +7 -14
- lionagi/utils/api_util.py +63 -2
- lionagi/utils/core_utils.py +338 -0
- lionagi/utils/sys_util.py +3 -3
- lionagi/version.py +1 -1
- {lionagi-0.0.208.dist-info → lionagi-0.0.210.dist-info}/METADATA +28 -29
- lionagi-0.0.210.dist-info/RECORD +56 -0
- lionagi/_services/anthropic.py +0 -79
- lionagi/_services/anyscale.py +0 -0
- lionagi/_services/azure.py +0 -1
- lionagi/_services/bedrock.py +0 -0
- lionagi/_services/everlyai.py +0 -0
- lionagi/_services/gemini.py +0 -0
- lionagi/_services/gpt4all.py +0 -0
- lionagi/_services/huggingface.py +0 -0
- lionagi/_services/litellm.py +0 -33
- lionagi/_services/localai.py +0 -0
- lionagi/_services/openllm.py +0 -0
- lionagi/_services/openrouter.py +0 -44
- lionagi/_services/perplexity.py +0 -0
- lionagi/_services/predibase.py +0 -0
- lionagi/_services/rungpt.py +0 -0
- lionagi/_services/vllm.py +0 -0
- lionagi/_services/xinference.py +0 -0
- lionagi/agents/planner.py +0 -1
- lionagi/agents/prompter.py +0 -1
- lionagi/agents/scorer.py +0 -1
- lionagi/agents/summarizer.py +0 -1
- lionagi/agents/validator.py +0 -1
- lionagi/bridge/__init__.py +0 -22
- lionagi/bridge/langchain.py +0 -195
- lionagi/bridge/llama_index.py +0 -266
- lionagi/core/branch/__init__.py +0 -0
- lionagi/core/branch/branch.py +0 -841
- lionagi/core/branch/cluster.py +0 -1
- lionagi/core/branch/conversation.py +0 -787
- lionagi/core/core_util.py +0 -0
- lionagi/core/flow/__init__.py +0 -0
- lionagi/core/flow/flow.py +0 -19
- lionagi/core/flow/flow_util.py +0 -62
- lionagi/core/instruction_set/__init__.py +0 -0
- lionagi/core/messages/__init__.py +0 -0
- lionagi/core/sessions/__init__.py +0 -0
- lionagi/core/sessions/session.py +0 -504
- lionagi/datastores/__init__.py +0 -1
- lionagi/datastores/chroma.py +0 -1
- lionagi/datastores/deeplake.py +0 -1
- lionagi/datastores/elasticsearch.py +0 -1
- lionagi/datastores/lantern.py +0 -1
- lionagi/datastores/pinecone.py +0 -1
- lionagi/datastores/postgres.py +0 -1
- lionagi/datastores/qdrant.py +0 -1
- lionagi/loaders/__init__.py +0 -18
- lionagi/loaders/chunker.py +0 -166
- lionagi/loaders/load_util.py +0 -240
- lionagi/loaders/reader.py +0 -122
- lionagi/models/__init__.py +0 -0
- lionagi/models/base_model.py +0 -0
- lionagi/models/imodel.py +0 -53
- lionagi/schema/async_queue.py +0 -158
- lionagi/schema/base_condition.py +0 -1
- lionagi/schema/base_node.py +0 -422
- lionagi/schema/base_tool.py +0 -44
- lionagi/schema/data_logger.py +0 -126
- lionagi/schema/data_node.py +0 -88
- lionagi/schema/status_tracker.py +0 -37
- lionagi/tests/test_utils/test_encrypt_util.py +0 -323
- lionagi/utils/encrypt_util.py +0 -283
- lionagi/utils/url_util.py +0 -55
- lionagi-0.0.208.dist-info/RECORD +0 -106
- lionagi/{agents → api_service}/__init__.py +0 -0
- lionagi/core/{branch/branch_manager.py → branch_manager.py} +0 -0
- lionagi/core/{messages/messages.py → messages.py} +3 -3
- /lionagi/{_services → services}/__init__.py +0 -0
- /lionagi/{_services → services}/mistralai.py +0 -0
- /lionagi/{_services → services}/mlx_service.py +0 -0
- /lionagi/{_services → services}/ollama.py +0 -0
- /lionagi/{_services → services}/services.py +0 -0
- /lionagi/{_services → services}/transformers.py +0 -0
- {lionagi-0.0.208.dist-info → lionagi-0.0.210.dist-info}/LICENSE +0 -0
- {lionagi-0.0.208.dist-info → lionagi-0.0.210.dist-info}/WHEEL +0 -0
- {lionagi-0.0.208.dist-info → lionagi-0.0.210.dist-info}/top_level.txt +0 -0
@@ -103,7 +103,7 @@ class BaseRateLimiter(ABC):
|
|
103
103
|
api_key: str,
|
104
104
|
max_attempts: int = 3,
|
105
105
|
method: str = "post",
|
106
|
-
payload: Dict[str, any]=None
|
106
|
+
payload: Dict[str, any]=None, **kwargs
|
107
107
|
) -> Optional[Dict[str, any]]:
|
108
108
|
"""
|
109
109
|
Makes an API call to the specified endpoint using the provided HTTP session.
|
@@ -125,7 +125,7 @@ class BaseRateLimiter(ABC):
|
|
125
125
|
if self.available_request_capacity < 1 or self.available_token_capacity < 10: # Minimum token count
|
126
126
|
await asyncio.sleep(1) # Wait for capacity
|
127
127
|
continue
|
128
|
-
required_tokens = APIUtil.calculate_num_token(payload, endpoint, self.token_encoding_name)
|
128
|
+
required_tokens = APIUtil.calculate_num_token(payload, endpoint, self.token_encoding_name, **kwargs)
|
129
129
|
|
130
130
|
if await self.request_permission(required_tokens):
|
131
131
|
request_headers = {"Authorization": f"Bearer {api_key}"}
|
@@ -343,7 +343,7 @@ class BaseService:
|
|
343
343
|
if not self.endpoints[ep]._has_initialized:
|
344
344
|
await self.endpoints[ep].init_rate_limiter()
|
345
345
|
|
346
|
-
async def call_api(self, payload, endpoint, method):
|
346
|
+
async def call_api(self, payload, endpoint, method, **kwargs):
|
347
347
|
"""
|
348
348
|
Calls the specified API endpoint with the given payload and method.
|
349
349
|
|
@@ -363,7 +363,7 @@ class BaseService:
|
|
363
363
|
async with aiohttp.ClientSession() as http_session:
|
364
364
|
completion = await self.endpoints[endpoint].rate_limiter._call_api(
|
365
365
|
http_session=http_session, endpoint=endpoint, base_url=self.base_url, api_key=self.api_key,
|
366
|
-
method=method, payload=payload)
|
366
|
+
method=method, payload=payload, **kwargs)
|
367
367
|
return completion
|
368
368
|
|
369
369
|
|
@@ -38,7 +38,7 @@ class OpenAIService(BaseService):
|
|
38
38
|
)
|
39
39
|
self.active_endpoint = []
|
40
40
|
|
41
|
-
async def serve(self, input_, endpoint="chat/completions", method="post", **kwargs):
|
41
|
+
async def serve(self, input_, endpoint="chat/completions", method="post", tokenizer_kwargs={}, **kwargs):
|
42
42
|
"""
|
43
43
|
Serves the input using the specified endpoint and method.
|
44
44
|
|
@@ -66,11 +66,11 @@ class OpenAIService(BaseService):
|
|
66
66
|
if endpoint not in self.active_endpoint:
|
67
67
|
await self. init_endpoint(endpoint)
|
68
68
|
if endpoint == "chat/completions":
|
69
|
-
return await self.serve_chat(input_, **kwargs)
|
69
|
+
return await self.serve_chat(input_, tokenizer_kwargs=tokenizer_kwargs, **kwargs)
|
70
70
|
else:
|
71
71
|
return ValueError(f'{endpoint} is currently not supported')
|
72
72
|
|
73
|
-
async def serve_chat(self, messages, **kwargs):
|
73
|
+
async def serve_chat(self, messages, tokenizer_kwargs={}, **kwargs):
|
74
74
|
"""
|
75
75
|
Serves the chat completion request with the given messages.
|
76
76
|
|
@@ -91,7 +91,7 @@ class OpenAIService(BaseService):
|
|
91
91
|
messages, self.endpoints["chat/completions"].config, self.schema["chat/completions"], **kwargs)
|
92
92
|
|
93
93
|
try:
|
94
|
-
completion = await self.call_api(payload, "chat/completions", "post")
|
94
|
+
completion = await self.call_api(payload, "chat/completions", "post", **tokenizer_kwargs)
|
95
95
|
return payload, completion
|
96
96
|
except Exception as e:
|
97
97
|
self.status_tracker.num_tasks_failed += 1
|
lionagi/structures/graph.py
CHANGED
lionagi/structures/structure.py
CHANGED
lionagi/tools/tool_manager.py
CHANGED
@@ -1,163 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
import asyncio
|
3
|
-
from typing import Dict, Union, List, Tuple, Any
|
4
|
-
from lionagi.utils.call_util import lcall, is_coroutine_func, _call_handler, alcall
|
5
|
-
from lionagi.schema import BaseNode, Tool
|
6
|
-
|
7
|
-
|
8
|
-
class ToolManager(BaseNode):
|
9
|
-
"""
|
10
|
-
A manager class for handling the registration and invocation of tools that are subclasses of Tool.
|
11
|
-
|
12
|
-
This class maintains a registry of tool instances, allowing for dynamic invocation based on
|
13
|
-
tool name and provided arguments. It supports both synchronous and asynchronous tool function
|
14
|
-
calls.
|
15
|
-
|
16
|
-
Attributes:
|
17
|
-
registry (Dict[str, Tool]): A dictionary to hold registered tools, keyed by their names.
|
18
|
-
"""
|
19
|
-
registry: Dict = {}
|
20
|
-
|
21
|
-
def name_existed(self, name: str) -> bool:
|
22
|
-
"""
|
23
|
-
Checks if a tool name already exists in the registry.
|
24
|
-
|
25
|
-
Args:
|
26
|
-
name (str): The name of the tool to check.
|
27
|
-
|
28
|
-
Returns:
|
29
|
-
bool: True if the name exists, False otherwise.
|
30
|
-
"""
|
31
|
-
return True if name in self.registry.keys() else False
|
32
|
-
|
33
|
-
def _register_tool(self, tool: Tool) -> None:
|
34
|
-
"""
|
35
|
-
Registers a tool in the registry. Raises a TypeError if the object is not an instance of Tool.
|
36
|
-
|
37
|
-
Args:
|
38
|
-
tool (Tool): The tool instance to register.
|
39
|
-
|
40
|
-
Raises:
|
41
|
-
TypeError: If the provided object is not an instance of Tool.
|
42
|
-
"""
|
43
|
-
if not isinstance(tool, Tool):
|
44
|
-
raise TypeError('Please register a Tool object.')
|
45
|
-
name = tool.schema_['function']['name']
|
46
|
-
self.registry.update({name: tool})
|
47
|
-
|
48
|
-
async def invoke(self, func_call: Tuple[str, Dict[str, Any]]) -> Any:
|
49
|
-
"""
|
50
|
-
Invokes a registered tool's function with the given arguments. Supports both coroutine and regular functions.
|
51
|
-
|
52
|
-
Args:
|
53
|
-
func_call (Tuple[str, Dict[str, Any]]): A tuple containing the function name and a dictionary of keyword arguments.
|
54
|
-
|
55
|
-
Returns:
|
56
|
-
Any: The result of the function call.
|
57
|
-
|
58
|
-
Raises:
|
59
|
-
ValueError: If the function name is not registered or if there's an error during function invocation.
|
60
|
-
"""
|
61
|
-
name, kwargs = func_call
|
62
|
-
if self.name_existed(name):
|
63
|
-
tool = self.registry[name]
|
64
|
-
func = tool.func
|
65
|
-
parser = tool.parser
|
66
|
-
try:
|
67
|
-
if is_coroutine_func(func):
|
68
|
-
tasks = [_call_handler(func, **kwargs)]
|
69
|
-
out = await asyncio.gather(*tasks)
|
70
|
-
return parser(out[0]) if parser else out[0]
|
71
|
-
else:
|
72
|
-
out = func(**kwargs)
|
73
|
-
return parser(out) if parser else out
|
74
|
-
except Exception as e:
|
75
|
-
raise ValueError(f"Error when invoking function {name} with arguments {kwargs} with error message {e}")
|
76
|
-
else:
|
77
|
-
raise ValueError(f"Function {name} is not registered.")
|
78
|
-
|
79
|
-
@staticmethod
|
80
|
-
def get_function_call(response: Dict) -> Tuple[str, Dict]:
|
81
|
-
"""
|
82
|
-
Extracts a function call and arguments from a response dictionary.
|
83
|
-
|
84
|
-
Args:
|
85
|
-
response (Dict): The response dictionary containing the function call information.
|
86
|
-
|
87
|
-
Returns:
|
88
|
-
Tuple[str, Dict]: A tuple containing the function name and a dictionary of arguments.
|
89
|
-
|
90
|
-
Raises:
|
91
|
-
ValueError: If the response does not contain valid function call information.
|
92
|
-
"""
|
93
|
-
try:
|
94
|
-
func = response['action'][7:]
|
95
|
-
args = json.loads(response['arguments'])
|
96
|
-
return (func, args)
|
97
|
-
except:
|
98
|
-
try:
|
99
|
-
func = response['recipient_name'].split('.')[-1]
|
100
|
-
args = response['parameters']
|
101
|
-
return (func, args)
|
102
|
-
except:
|
103
|
-
raise ValueError('response is not a valid function call')
|
104
|
-
|
105
|
-
def register_tools(self, tools: List[Tool]) -> None:
|
106
|
-
"""
|
107
|
-
Registers multiple tools in the registry.
|
108
|
-
|
109
|
-
Args:
|
110
|
-
tools (List[Tool]): A list of tool instances to register.
|
111
|
-
"""
|
112
|
-
lcall(tools, self._register_tool)
|
113
|
-
|
114
|
-
def to_tool_schema_list(self) -> List[Dict[str, Any]]:
|
115
|
-
"""
|
116
|
-
Generates a list of schemas for all registered tools.
|
117
|
-
|
118
|
-
Returns:
|
119
|
-
List[Dict[str, Any]]: A list of tool schemas.
|
120
|
-
|
121
|
-
"""
|
122
|
-
schema_list = []
|
123
|
-
for tool in self.registry.values():
|
124
|
-
schema_list.append(tool.schema_)
|
125
|
-
return schema_list
|
126
|
-
|
127
|
-
def _tool_parser(self, tools: Union[Dict, Tool, List[Tool], str, List[str], List[Dict]], **kwargs) -> Dict:
|
128
|
-
"""
|
129
|
-
Parses tool information and generates a dictionary for tool invocation.
|
130
|
-
|
131
|
-
Args:
|
132
|
-
tools: Tool information which can be a single Tool instance, a list of Tool instances, a tool name, or a list of tool names.
|
133
|
-
**kwargs: Additional keyword arguments.
|
134
|
-
|
135
|
-
Returns:
|
136
|
-
Dict: A dictionary containing tool schema information and any additional keyword arguments.
|
137
|
-
|
138
|
-
Raises:
|
139
|
-
ValueError: If a tool name is provided that is not registered.
|
140
|
-
"""
|
141
|
-
def tool_check(tool):
|
142
|
-
if isinstance(tool, dict):
|
143
|
-
return tool
|
144
|
-
elif isinstance(tool, Tool):
|
145
|
-
return tool.schema_
|
146
|
-
elif isinstance(tool, str):
|
147
|
-
if self.name_existed(tool):
|
148
|
-
tool = self.registry[tool]
|
149
|
-
return tool.schema_
|
150
|
-
else:
|
151
|
-
raise ValueError(f'Function {tool} is not registered.')
|
152
|
-
|
153
|
-
if isinstance(tools, bool):
|
154
|
-
tool_kwarg = {"tools": self.to_tool_schema_list()}
|
155
|
-
kwargs = {**tool_kwarg, **kwargs}
|
156
|
-
|
157
|
-
else:
|
158
|
-
if not isinstance(tools, list):
|
159
|
-
tools = [tools]
|
160
|
-
tool_kwarg = {"tools": lcall(tools, tool_check)}
|
161
|
-
kwargs = {**tool_kwarg, **kwargs}
|
162
|
-
|
163
|
-
return kwargs
|
lionagi/tools/tool_util.py
CHANGED
lionagi/utils/__init__.py
CHANGED
@@ -1,16 +1,12 @@
|
|
1
|
-
from .sys_util import
|
2
|
-
get_timestamp, create_copy, create_path, split_path,
|
3
|
-
get_bins, change_dict_key, str_to_num, create_id,
|
4
|
-
as_dict, is_package_installed, install_import, to_df
|
5
|
-
)
|
1
|
+
from .sys_util import as_dict, create_copy, get_bins, get_timestamp, str_to_num, to_df
|
6
2
|
|
7
3
|
from .nested_util import (
|
8
4
|
to_readable_dict, nfilter, nset, nget,
|
9
5
|
nmerge, ninsert, flatten, unflatten,
|
10
6
|
is_structure_homogeneous, get_flattened_keys)
|
11
7
|
|
8
|
+
from .core_utils import CoreUtil
|
12
9
|
from .api_util import APIUtil
|
13
|
-
from .encrypt_util import EncrytionUtil
|
14
10
|
from .io_util import IOUtil
|
15
11
|
|
16
12
|
from .call_util import (
|
@@ -20,12 +16,9 @@ from .call_util import (
|
|
20
16
|
|
21
17
|
|
22
18
|
__all__ = [
|
23
|
-
"
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
'is_structure_homogeneous', 'get_flattened_keys', 'APIUtil',
|
29
|
-
'EncrytionUtil', 'IOUtil', 'lcall', 'alcall', 'mcall', 'tcall',
|
30
|
-
'bcall', 'rcall', 'CallDecorator'
|
19
|
+
"as_dict", "create_copy", "get_bins", "get_timestamp", "str_to_num", "to_df",
|
20
|
+
"to_readable_dict", "nfilter", "nset", "nget", "nmerge", "ninsert",
|
21
|
+
"flatten", "unflatten", "is_structure_homogeneous", "get_flattened_keys",
|
22
|
+
"CoreUtil", "APIUtil", "IOUtil",
|
23
|
+
"to_list", "lcall", "alcall", "mcall", "tcall", "bcall", "rcall", "CallDecorator"
|
31
24
|
]
|
lionagi/utils/api_util.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# import requests
|
1
2
|
import aiohttp
|
2
3
|
import asyncio
|
3
4
|
import hashlib
|
@@ -8,6 +9,7 @@ import tiktoken
|
|
8
9
|
from functools import lru_cache
|
9
10
|
from aiocache import cached
|
10
11
|
from typing import Any, Callable, Dict, Optional
|
12
|
+
# from bs4 import BeautifulSoup
|
11
13
|
|
12
14
|
from .sys_util import strip_lower
|
13
15
|
|
@@ -284,6 +286,8 @@ class APIUtil:
|
|
284
286
|
payload: Dict[str, Any] = None,
|
285
287
|
api_endpoint: str = None,
|
286
288
|
token_encoding_name: str = None,
|
289
|
+
disallowed_special = None,
|
290
|
+
**kwargs
|
287
291
|
) -> int:
|
288
292
|
"""
|
289
293
|
Calculates the number of tokens required for a request based on the payload and API endpoint.
|
@@ -309,7 +313,10 @@ class APIUtil:
|
|
309
313
|
# Expected token calculation for the given payload and endpoint.
|
310
314
|
"""
|
311
315
|
|
312
|
-
|
316
|
+
if disallowed_special:
|
317
|
+
kwargs['disallowed_special'] = disallowed_special
|
318
|
+
|
319
|
+
encoding = tiktoken.get_encoding(token_encoding_name, **kwargs)
|
313
320
|
if api_endpoint.endswith("completions"):
|
314
321
|
max_tokens = payload.get("max_tokens", 15)
|
315
322
|
n = payload.get("n", 1)
|
@@ -373,4 +380,58 @@ class APIUtil:
|
|
373
380
|
payload.update({key: config[key]})
|
374
381
|
|
375
382
|
return payload
|
376
|
-
|
383
|
+
|
384
|
+
# @staticmethod
|
385
|
+
# def get_url_response(url: str, timeout: tuple = (1, 1), **kwargs) -> requests.Response:
|
386
|
+
# """
|
387
|
+
# Sends a GET request to a URL and returns the response.
|
388
|
+
|
389
|
+
# Args:
|
390
|
+
# url (str): The URL to send the GET request to.
|
391
|
+
# timeout (tuple): A tuple specifying the connection and read timeouts in seconds.
|
392
|
+
# Defaults to (1, 1).
|
393
|
+
# **kwargs: Additional keyword arguments to be passed to the requests.get() function.
|
394
|
+
|
395
|
+
# Returns:
|
396
|
+
# requests.Response: A Response object containing the server's response to the GET request.
|
397
|
+
|
398
|
+
# Raises:
|
399
|
+
# TimeoutError: If a timeout occurs while requesting or reading the response.
|
400
|
+
# Exception: If an error other than a timeout occurs during the request.
|
401
|
+
# """
|
402
|
+
# try:
|
403
|
+
# response = requests.get(url, timeout=timeout, **kwargs)
|
404
|
+
# response.raise_for_status()
|
405
|
+
# return response
|
406
|
+
# except requests.exceptions.ConnectTimeout:
|
407
|
+
# raise TimeoutError(f"Timeout: requesting >{timeout[0]} seconds.")
|
408
|
+
# except requests.exceptions.ReadTimeout:
|
409
|
+
# raise TimeoutError(f"Timeout: reading >{timeout[1]} seconds.")
|
410
|
+
# except Exception as e:
|
411
|
+
# raise e
|
412
|
+
|
413
|
+
# @staticmethod
|
414
|
+
# def get_url_content(url: str) -> str:
|
415
|
+
# """
|
416
|
+
# Retrieve and parse the content from a given URL.
|
417
|
+
|
418
|
+
# Args:
|
419
|
+
# url (str): The URL to fetch and parse.
|
420
|
+
|
421
|
+
# Returns:
|
422
|
+
# str: The text content extracted from the URL.
|
423
|
+
|
424
|
+
# Raises:
|
425
|
+
# ValueError: If there is an issue during content retrieval or parsing.
|
426
|
+
# """
|
427
|
+
# try:
|
428
|
+
# response = requests.get(url)
|
429
|
+
# response.raise_for_status()
|
430
|
+
|
431
|
+
# soup = BeautifulSoup(response.text, 'html.parser')
|
432
|
+
|
433
|
+
# text_content = ' '.join([p.get_text() for p in soup.find_all('p')])
|
434
|
+
# return text_content
|
435
|
+
# except Exception as e:
|
436
|
+
# raise f"Error fetching content for {url}: {e}"
|
437
|
+
|