lionagi 0.0.114__py3-none-any.whl → 0.0.116__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 +7 -4
- lionagi/bridge/__init__.py +19 -4
- lionagi/bridge/langchain.py +23 -3
- lionagi/bridge/llama_index.py +5 -3
- lionagi/configs/__init__.py +1 -1
- lionagi/configs/oai_configs.py +88 -1
- lionagi/core/__init__.py +6 -9
- lionagi/core/conversations/__init__.py +5 -0
- lionagi/core/conversations/conversation.py +107 -0
- lionagi/core/flows/__init__.py +8 -0
- lionagi/core/flows/flow.py +8 -0
- lionagi/core/flows/flow_util.py +62 -0
- lionagi/core/instruction_set/__init__.py +5 -0
- lionagi/core/instruction_set/instruction_sets.py +7 -0
- lionagi/core/sessions/__init__.py +5 -0
- lionagi/core/sessions/sessions.py +187 -0
- lionagi/endpoints/__init__.py +5 -0
- lionagi/endpoints/assistants.py +0 -0
- lionagi/endpoints/audio.py +17 -0
- lionagi/endpoints/chatcompletion.py +54 -0
- lionagi/endpoints/embeddings.py +0 -0
- lionagi/endpoints/finetune.py +0 -0
- lionagi/endpoints/image.py +0 -0
- lionagi/endpoints/moderation.py +0 -0
- lionagi/endpoints/vision.py +0 -0
- lionagi/{loader → loaders}/__init__.py +7 -1
- lionagi/{loader → loaders}/chunker.py +6 -12
- lionagi/{utils/load_utils.py → loaders/load_util.py} +47 -6
- lionagi/{loader → loaders}/reader.py +4 -12
- lionagi/messages/__init__.py +11 -0
- lionagi/messages/instruction.py +15 -0
- lionagi/messages/message.py +110 -0
- lionagi/messages/response.py +33 -0
- lionagi/messages/system.py +12 -0
- lionagi/objs/__init__.py +10 -6
- lionagi/objs/abc_objs.py +39 -0
- lionagi/objs/async_queue.py +135 -0
- lionagi/objs/messenger.py +70 -148
- lionagi/objs/status_tracker.py +37 -0
- lionagi/objs/{tool_registry.py → tool_manager.py} +8 -6
- lionagi/schema/__init__.py +3 -3
- lionagi/schema/base_node.py +251 -0
- lionagi/schema/base_tool.py +8 -3
- lionagi/schema/data_logger.py +2 -3
- lionagi/schema/data_node.py +37 -0
- lionagi/services/__init__.py +1 -4
- lionagi/services/base_api_service.py +15 -5
- lionagi/services/oai.py +2 -2
- lionagi/services/openrouter.py +2 -3
- lionagi/structures/graph.py +96 -0
- lionagi/{structure → structures}/relationship.py +10 -2
- lionagi/structures/structure.py +102 -0
- lionagi/tests/test_api_util.py +46 -0
- lionagi/tests/test_call_util.py +115 -0
- lionagi/tests/test_convert_util.py +202 -0
- lionagi/tests/test_encrypt_util.py +33 -0
- lionagi/tests/{test_flatten_util.py → test_flat_util.py} +1 -1
- lionagi/tests/test_io_util.py +0 -0
- lionagi/tests/test_sys_util.py +0 -0
- lionagi/tools/__init__.py +5 -0
- lionagi/tools/tool_util.py +7 -0
- lionagi/utils/__init__.py +55 -35
- lionagi/utils/api_util.py +19 -17
- lionagi/utils/call_util.py +2 -1
- lionagi/utils/convert_util.py +229 -0
- lionagi/utils/encrypt_util.py +16 -0
- lionagi/utils/flat_util.py +38 -0
- lionagi/utils/io_util.py +2 -2
- lionagi/utils/sys_util.py +45 -10
- lionagi/version.py +1 -1
- {lionagi-0.0.114.dist-info → lionagi-0.0.116.dist-info}/METADATA +2 -2
- lionagi-0.0.116.dist-info/RECORD +110 -0
- lionagi/core/conversations.py +0 -108
- lionagi/core/flows.py +0 -1
- lionagi/core/instruction_sets.py +0 -1
- lionagi/core/messages.py +0 -166
- lionagi/core/sessions.py +0 -297
- lionagi/schema/base_schema.py +0 -252
- lionagi/services/chatcompletion.py +0 -48
- lionagi/services/service_objs.py +0 -282
- lionagi/structure/structure.py +0 -160
- lionagi/tools/coder.py +0 -1
- lionagi/tools/sandbox.py +0 -1
- lionagi/utils/tool_util.py +0 -92
- lionagi/utils/type_util.py +0 -81
- lionagi-0.0.114.dist-info/RECORD +0 -84
- /lionagi/configs/{openrouter_config.py → openrouter_configs.py} +0 -0
- /lionagi/{datastore → datastores}/__init__.py +0 -0
- /lionagi/{datastore → datastores}/chroma.py +0 -0
- /lionagi/{datastore → datastores}/deeplake.py +0 -0
- /lionagi/{datastore → datastores}/elasticsearch.py +0 -0
- /lionagi/{datastore → datastores}/lantern.py +0 -0
- /lionagi/{datastore → datastores}/pinecone.py +0 -0
- /lionagi/{datastore → datastores}/postgres.py +0 -0
- /lionagi/{datastore → datastores}/qdrant.py +0 -0
- /lionagi/{structure → structures}/__init__.py +0 -0
- {lionagi-0.0.114.dist-info → lionagi-0.0.116.dist-info}/LICENSE +0 -0
- {lionagi-0.0.114.dist-info → lionagi-0.0.116.dist-info}/WHEEL +0 -0
- {lionagi-0.0.114.dist-info → lionagi-0.0.116.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
import unittest
|
2
|
+
from cryptography.fernet import Fernet
|
3
|
+
|
4
|
+
# Assuming the Python module with the above functions is named 'encryption_utils'
|
5
|
+
from lionagi.utils.encrypt_util import generate_encryption_key, encrypt, decrypt
|
6
|
+
|
7
|
+
class TestEncryptionUtils(unittest.TestCase):
|
8
|
+
|
9
|
+
def test_generate_encryption_key(self):
|
10
|
+
key = generate_encryption_key()
|
11
|
+
self.assertIsInstance(key, str)
|
12
|
+
self.assertEqual(len(key), 44) # Fernet keys are 44 bytes long in URL-safe base64 encoding
|
13
|
+
|
14
|
+
def test_encrypt_decrypt(self):
|
15
|
+
key = generate_encryption_key()
|
16
|
+
original_data = "Test data for encryption"
|
17
|
+
encrypted_data = encrypt(original_data, key)
|
18
|
+
decrypted_data = decrypt(encrypted_data, key)
|
19
|
+
|
20
|
+
self.assertNotEqual(encrypted_data, original_data)
|
21
|
+
self.assertEqual(decrypted_data, original_data)
|
22
|
+
|
23
|
+
def test_invalid_key(self):
|
24
|
+
key = generate_encryption_key()
|
25
|
+
wrong_key = Fernet.generate_key().decode()
|
26
|
+
original_data = "Test data for encryption"
|
27
|
+
encrypted_data = encrypt(original_data, key)
|
28
|
+
|
29
|
+
with self.assertRaises(Exception):
|
30
|
+
decrypt(encrypted_data, wrong_key)
|
31
|
+
|
32
|
+
if __name__ == '__main__':
|
33
|
+
unittest.main()
|
File without changes
|
File without changes
|
lionagi/tools/__init__.py
CHANGED
@@ -0,0 +1,7 @@
|
|
1
|
+
# use schema and convert_util
|
2
|
+
from ..utils.convert_util import func_to_schema
|
3
|
+
from ..schema.base_tool import Tool
|
4
|
+
|
5
|
+
def func_to_tool(func_, parser=None, docstring_style='google'):
|
6
|
+
schema = func_to_schema(func_, docstring_style)
|
7
|
+
return Tool(func=func_, parser=parser, schema_=schema)
|
lionagi/utils/__init__.py
CHANGED
@@ -1,49 +1,69 @@
|
|
1
|
+
from .sys_util import (
|
2
|
+
create_copy, create_id, create_path, create_hash,
|
3
|
+
change_dict_key, get_timestamp, get_bins, timestamp_to_datetime,
|
4
|
+
is_schema, split_path
|
5
|
+
)
|
6
|
+
|
1
7
|
from .flat_util import (
|
2
8
|
flatten_dict, flatten_list, change_separator,
|
3
9
|
unflatten_dict, is_flattenable, dynamic_flatten,
|
4
|
-
unflatten_to_list, flatten_iterable, flatten_iterable_to_list
|
5
|
-
|
6
|
-
|
7
|
-
from .sys_util import (
|
8
|
-
create_copy, get_timestamp, create_id, create_path,
|
9
|
-
split_path, get_bins, change_dict_key
|
10
|
-
)
|
11
|
-
|
10
|
+
unflatten_to_list, flatten_iterable, flatten_iterable_to_list,
|
11
|
+
to_list
|
12
|
+
)
|
12
13
|
|
13
14
|
from .api_util import (
|
14
15
|
api_method, api_endpoint_from_url, api_error,
|
15
16
|
api_rate_limit_error
|
16
|
-
|
17
|
+
)
|
18
|
+
from .encrypt_util import generate_encryption_key, encrypt, decrypt
|
19
|
+
from .convert_util import str_to_num, dict_to_xml, xml_to_dict
|
17
20
|
|
21
|
+
from .io_util import to_temp, to_csv, append_to_jsonl
|
18
22
|
from .call_util import (
|
19
23
|
hcall, ahcall, lcall, alcall,
|
20
24
|
mcall, amcall, ecall, aecall
|
21
|
-
|
22
|
-
|
23
|
-
from .io_util import to_temp, to_csv, append_to_jsonl
|
24
|
-
from .load_utils import dir_to_path, dir_to_nodes, chunk_text, read_text, file_to_chunks
|
25
|
-
from .type_util import str_to_num, to_list
|
26
|
-
from .tool_util import func_to_schema
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
)
|
30
26
|
|
31
27
|
|
32
28
|
__all__ = [
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
29
|
+
'api_method',
|
30
|
+
'api_endpoint_from_url',
|
31
|
+
'api_error',
|
32
|
+
'api_rate_limit_error',
|
33
|
+
'flatten_dict',
|
34
|
+
'flatten_list',
|
35
|
+
'change_separator',
|
36
|
+
'unflatten_dict',
|
37
|
+
'is_flattenable',
|
38
|
+
'dynamic_flatten',
|
39
|
+
'unflatten_to_list',
|
40
|
+
'flatten_iterable',
|
41
|
+
'flatten_iterable_to_list',
|
42
|
+
'create_copy',
|
43
|
+
'create_id',
|
44
|
+
'create_path',
|
45
|
+
'create_hash',
|
46
|
+
'change_dict_key',
|
47
|
+
'get_timestamp',
|
48
|
+
'get_bins',
|
49
|
+
'timestamp_to_datetime',
|
50
|
+
'is_schema',
|
51
|
+
'split_path',
|
52
|
+
'generate_encryption_key',
|
53
|
+
'encrypt', 'decrypt',
|
54
|
+
'str_to_num',
|
55
|
+
'to_list',
|
56
|
+
'dict_to_xml',
|
57
|
+
'xml_to_dict',
|
58
|
+
'to_temp',
|
59
|
+
'to_csv',
|
60
|
+
'append_to_jsonl',
|
61
|
+
'hcall',
|
62
|
+
'ahcall',
|
63
|
+
'lcall',
|
64
|
+
'alcall',
|
65
|
+
'mcall',
|
66
|
+
'amcall',
|
67
|
+
'ecall',
|
68
|
+
'aecall'
|
69
|
+
]
|
lionagi/utils/api_util.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# this module has no internal dependency
|
1
2
|
import logging
|
2
3
|
import re
|
3
4
|
from typing import Callable
|
@@ -32,23 +33,6 @@ def api_method(http_session, method: str = "post") -> Callable:
|
|
32
33
|
return http_session.options
|
33
34
|
elif method == "patch":
|
34
35
|
return http_session.patch
|
35
|
-
|
36
|
-
def api_endpoint_from_url(request_url: str) -> str:
|
37
|
-
"""
|
38
|
-
Extracts the API endpoint from a given URL.
|
39
|
-
|
40
|
-
Parameters:
|
41
|
-
request_url (str): The URL from which to extract the API endpoint.
|
42
|
-
|
43
|
-
Returns:
|
44
|
-
str: The extracted API endpoint, or an empty string if no match is found.
|
45
|
-
|
46
|
-
Examples:
|
47
|
-
endpoint = api_endpoint_from_url("https://api.example.com/v1/users")
|
48
|
-
# endpoint will be 'users'
|
49
|
-
"""
|
50
|
-
match = re.search(r"^https://[^/]+/v\d+/(.+)$", request_url)
|
51
|
-
return match.group(1) if match else ""
|
52
36
|
|
53
37
|
def api_error(response_json: dict) -> bool:
|
54
38
|
"""
|
@@ -84,3 +68,21 @@ def api_rate_limit_error(response_json: dict) -> bool:
|
|
84
68
|
# Handle the rate limit error
|
85
69
|
"""
|
86
70
|
return "Rate limit" in response_json["error"].get("message", "")
|
71
|
+
|
72
|
+
# credit to OpenAI for this method
|
73
|
+
def api_endpoint_from_url(request_url: str) -> str:
|
74
|
+
"""
|
75
|
+
Extracts the API endpoint from a given URL.
|
76
|
+
|
77
|
+
Parameters:
|
78
|
+
request_url (str): The URL from which to extract the API endpoint.
|
79
|
+
|
80
|
+
Returns:
|
81
|
+
str: The extracted API endpoint, or an empty string if no match is found.
|
82
|
+
|
83
|
+
Examples:
|
84
|
+
endpoint = api_endpoint_from_url("https://api.example.com/v1/users")
|
85
|
+
# endpoint will be 'users'
|
86
|
+
"""
|
87
|
+
match = re.search(r"^https://[^/]+/v\d+/(.+)$", request_url)
|
88
|
+
return match.group(1) if match else ""
|
lionagi/utils/call_util.py
CHANGED
@@ -0,0 +1,229 @@
|
|
1
|
+
# this module has no internal dependency
|
2
|
+
import inspect
|
3
|
+
import re
|
4
|
+
import xml.etree.ElementTree as ET
|
5
|
+
from typing import Optional, Union, Any, Type, Dict
|
6
|
+
|
7
|
+
|
8
|
+
def str_to_num(input_: str,
|
9
|
+
upper_bound: Optional[Union[int, float]] = None,
|
10
|
+
lower_bound: Optional[Union[int, float]] = None,
|
11
|
+
num_type: Type[Union[int, float]] = int,
|
12
|
+
precision: Optional[int] = None) -> Union[int, float]:
|
13
|
+
"""
|
14
|
+
Converts the first number in the input string to the specified numeric type.
|
15
|
+
|
16
|
+
Parameters:
|
17
|
+
input_ (str): The input string to extract the number from.
|
18
|
+
|
19
|
+
upper_bound (Optional[Union[int, float]]): The upper bound for the number. Defaults to None.
|
20
|
+
|
21
|
+
lower_bound (Optional[Union[int, float]]): The lower bound for the number. Defaults to None.
|
22
|
+
|
23
|
+
num_type (Type[Union[int, float]]): The type of the number to return (int or float). Defaults to int.
|
24
|
+
|
25
|
+
precision (Optional[int]): The precision for the floating-point number. Defaults to None.
|
26
|
+
|
27
|
+
Returns:
|
28
|
+
Union[int, float]: The converted number.
|
29
|
+
|
30
|
+
Raises:
|
31
|
+
ValueError: If no numeric values are found in the string or if there are conversion errors.
|
32
|
+
"""
|
33
|
+
numbers = re.findall(r'-?\d+\.?\d*', input_)
|
34
|
+
if not numbers:
|
35
|
+
raise ValueError(f"No numeric values found in the string: {input_}")
|
36
|
+
|
37
|
+
try:
|
38
|
+
numbers = numbers[0]
|
39
|
+
if num_type is int:
|
40
|
+
numbers = int(float(numbers))
|
41
|
+
elif num_type is float:
|
42
|
+
numbers = round(float(numbers), precision) if precision is not None else float(numbers)
|
43
|
+
else:
|
44
|
+
raise ValueError(f"Invalid number type: {num_type}")
|
45
|
+
if upper_bound is not None and numbers > upper_bound:
|
46
|
+
raise ValueError(f"Number {numbers} is greater than the upper bound of {upper_bound}.")
|
47
|
+
if lower_bound is not None and numbers < lower_bound:
|
48
|
+
raise ValueError(f"Number {numbers} is less than the lower bound of {lower_bound}.")
|
49
|
+
return numbers
|
50
|
+
|
51
|
+
except ValueError as e:
|
52
|
+
raise ValueError(f"Error converting string to number: {e}")
|
53
|
+
|
54
|
+
def dict_to_xml(data: Dict[str, Any], root_tag: str = 'node') -> str:
|
55
|
+
"""
|
56
|
+
Helper method to convert a dictionary to an XML string.
|
57
|
+
|
58
|
+
Parameters:
|
59
|
+
data (Dict[str, Any]): The dictionary to convert to XML.
|
60
|
+
root_tag (str): The root tag name for the XML.
|
61
|
+
|
62
|
+
Returns:
|
63
|
+
str: An XML string representation of the dictionary.
|
64
|
+
"""
|
65
|
+
root = ET.Element(root_tag)
|
66
|
+
_build_xml(root, data)
|
67
|
+
return ET.tostring(root, encoding='unicode')
|
68
|
+
|
69
|
+
def _build_xml(element: ET.Element, data: Any):
|
70
|
+
"""Recursively builds XML elements from data."""
|
71
|
+
if isinstance(data, dict):
|
72
|
+
for key, value in data.items():
|
73
|
+
sub_element = ET.SubElement(element, key)
|
74
|
+
_build_xml(sub_element, value)
|
75
|
+
elif isinstance(data, list):
|
76
|
+
for item in data:
|
77
|
+
item_element = ET.SubElement(element, 'item')
|
78
|
+
_build_xml(item_element, item)
|
79
|
+
else:
|
80
|
+
element.text = str(data)
|
81
|
+
|
82
|
+
def xml_to_dict(element: ET.Element) -> Dict[str, Any]:
|
83
|
+
"""
|
84
|
+
Helper method to convert an XML element back into a dictionary.
|
85
|
+
"""
|
86
|
+
dict_data = {}
|
87
|
+
for child in element:
|
88
|
+
if child.getchildren():
|
89
|
+
dict_data[child.tag] = xml_to_dict(child)
|
90
|
+
else:
|
91
|
+
dict_data[child.tag] = child.text
|
92
|
+
return dict_data
|
93
|
+
|
94
|
+
def extract_docstring_details_google(func):
|
95
|
+
docstring = inspect.getdoc(func)
|
96
|
+
if not docstring:
|
97
|
+
return "No description available.", {}
|
98
|
+
lines = docstring.split('\n')
|
99
|
+
func_description = lines[0].strip()
|
100
|
+
|
101
|
+
param_start_pos = 0
|
102
|
+
lines_len = len(lines)
|
103
|
+
|
104
|
+
params_description = {}
|
105
|
+
for i in range(1, lines_len):
|
106
|
+
if lines[i].startswith('Args') or lines[i].startswith('Arguments') or lines[i].startswith('Parameters'):
|
107
|
+
param_start_pos = i + 1
|
108
|
+
break
|
109
|
+
|
110
|
+
current_param = None
|
111
|
+
for i in range(param_start_pos, lines_len):
|
112
|
+
if lines[i] == '':
|
113
|
+
continue
|
114
|
+
elif lines[i].startswith(' '):
|
115
|
+
param_desc = lines[i].split(':', 1)
|
116
|
+
if len(param_desc) == 1:
|
117
|
+
params_description[current_param] += ' ' + param_desc[0].strip()
|
118
|
+
continue
|
119
|
+
param, desc = param_desc
|
120
|
+
param = param.split('(')[0].strip()
|
121
|
+
params_description[param] = desc.strip()
|
122
|
+
current_param = param
|
123
|
+
else:
|
124
|
+
break
|
125
|
+
return func_description, params_description
|
126
|
+
|
127
|
+
def extract_docstring_details_rest(func):
|
128
|
+
docstring = inspect.getdoc(func)
|
129
|
+
if not docstring:
|
130
|
+
return "No description available.", {}
|
131
|
+
lines = docstring.split('\n')
|
132
|
+
func_description = lines[0].strip()
|
133
|
+
|
134
|
+
params_description = {}
|
135
|
+
current_param = None
|
136
|
+
for line in lines[1:]:
|
137
|
+
line = line.strip()
|
138
|
+
if line.startswith(':param'):
|
139
|
+
param_desc = line.split(':', 2)
|
140
|
+
_, param, desc = param_desc
|
141
|
+
param = param.split()[-1].strip()
|
142
|
+
params_description[param] = desc.strip()
|
143
|
+
current_param = param
|
144
|
+
elif line.startswith(' '):
|
145
|
+
params_description[current_param] += ' ' + line
|
146
|
+
|
147
|
+
return func_description, params_description
|
148
|
+
|
149
|
+
def extract_docstring_details(func, style='google'):
|
150
|
+
if style == 'google':
|
151
|
+
func_description, params_description = extract_docstring_details_google(func)
|
152
|
+
elif style == 'reST':
|
153
|
+
func_description, params_description = extract_docstring_details_rest(func)
|
154
|
+
else:
|
155
|
+
raise ValueError(f'{style} is not supported. Please choose either "google" or "reST".')
|
156
|
+
return func_description, params_description
|
157
|
+
|
158
|
+
def python_to_json_type(py_type):
|
159
|
+
"""
|
160
|
+
Converts a Python type to its JSON type equivalent.
|
161
|
+
|
162
|
+
Parameters:
|
163
|
+
py_type (str): The name of the Python type.
|
164
|
+
|
165
|
+
Returns:
|
166
|
+
str: The corresponding JSON type.
|
167
|
+
"""
|
168
|
+
type_mapping = {
|
169
|
+
'str': 'string',
|
170
|
+
'int': 'number',
|
171
|
+
'float': 'number',
|
172
|
+
'list': 'array',
|
173
|
+
'tuple': 'array',
|
174
|
+
'bool': 'boolean',
|
175
|
+
'dict': 'object'
|
176
|
+
}
|
177
|
+
return type_mapping.get(py_type, 'object')
|
178
|
+
|
179
|
+
def func_to_schema(func, style='google'):
|
180
|
+
"""
|
181
|
+
Generates a schema description for a given function, using typing hints and docstrings.
|
182
|
+
The schema includes the function's name, description, and parameters.
|
183
|
+
|
184
|
+
Parameters:
|
185
|
+
func (function): The function to generate a schema for.
|
186
|
+
|
187
|
+
style (str): The docstring format.
|
188
|
+
|
189
|
+
Returns:
|
190
|
+
dict: A schema describing the function.
|
191
|
+
"""
|
192
|
+
# Extracting function name and docstring details
|
193
|
+
func_name = func.__name__
|
194
|
+
func_description, params_description = extract_docstring_details(func, style)
|
195
|
+
|
196
|
+
# Extracting parameters with typing hints
|
197
|
+
sig = inspect.signature(func)
|
198
|
+
parameters = {
|
199
|
+
"type": "object",
|
200
|
+
"properties": {},
|
201
|
+
"required": [],
|
202
|
+
}
|
203
|
+
|
204
|
+
for name, param in sig.parameters.items():
|
205
|
+
# Default type to string and update if type hint is available
|
206
|
+
param_type = "string"
|
207
|
+
if param.annotation is not inspect.Parameter.empty:
|
208
|
+
param_type = python_to_json_type(param.annotation.__name__)
|
209
|
+
|
210
|
+
# Extract parameter description from docstring, if available
|
211
|
+
param_description = params_description.get(name, "No description available.")
|
212
|
+
|
213
|
+
# Assuming all parameters are required for simplicity
|
214
|
+
parameters["required"].append(name)
|
215
|
+
parameters["properties"][name] = {
|
216
|
+
"type": param_type,
|
217
|
+
"description": param_description,
|
218
|
+
}
|
219
|
+
|
220
|
+
# Constructing the schema
|
221
|
+
schema = {
|
222
|
+
"type": "function",
|
223
|
+
"function": {
|
224
|
+
"name": func_name,
|
225
|
+
"description": func_description,
|
226
|
+
"parameters": parameters,
|
227
|
+
}
|
228
|
+
}
|
229
|
+
return schema
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# this module has no internal dependency
|
2
|
+
from cryptography.fernet import Fernet
|
3
|
+
|
4
|
+
def generate_encryption_key() -> str:
|
5
|
+
"""Generates a key for encryption."""
|
6
|
+
return Fernet.generate_key().decode()
|
7
|
+
|
8
|
+
def encrypt(data: str, key: str) -> str:
|
9
|
+
"""Encrypts data using the provided key."""
|
10
|
+
fernet = Fernet(key.encode())
|
11
|
+
return fernet.encrypt(data.encode()).decode()
|
12
|
+
|
13
|
+
def decrypt(data: str, key: str) -> str:
|
14
|
+
"""Decrypts data using the provided key."""
|
15
|
+
fernet = Fernet(key.encode())
|
16
|
+
return fernet.decrypt(data.encode()).decode()
|
lionagi/utils/flat_util.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# this module has no internal dependency
|
1
2
|
from typing import Dict, Iterable, List, Any, Callable, Generator, Tuple
|
2
3
|
|
3
4
|
|
@@ -487,6 +488,43 @@ def unflatten_dict_with_custom_logic(
|
|
487
488
|
d[modified_last_part] = modified_value
|
488
489
|
return reconstructed
|
489
490
|
|
491
|
+
def to_list(input_: Any, flatten: bool = True, dropna: bool = False) -> List[Any]:
|
492
|
+
"""
|
493
|
+
Converts the input to a list, optionally flattening it and dropping None values.
|
494
|
+
|
495
|
+
Parameters:
|
496
|
+
input_ (Any): The input to convert to a list.
|
497
|
+
|
498
|
+
flatten (bool): Whether to flatten the input if it is a nested list. Defaults to True.
|
499
|
+
|
500
|
+
dropna (bool): Whether to drop None values from the list. Defaults to False.
|
501
|
+
|
502
|
+
Returns:
|
503
|
+
List[Any]: The input converted to a list.
|
504
|
+
|
505
|
+
Raises:
|
506
|
+
ValueError: If the input cannot be converted to a list.
|
507
|
+
"""
|
508
|
+
if isinstance(input_, list) and flatten:
|
509
|
+
input_ = flatten_list(input_)
|
510
|
+
if dropna:
|
511
|
+
input_ = [i for i in input_ if i is not None]
|
512
|
+
elif isinstance(input_, Iterable) and not isinstance(input_, (str, dict)):
|
513
|
+
try:
|
514
|
+
input_ = list(input_)
|
515
|
+
except:
|
516
|
+
raise ValueError("Input cannot be converted to a list.")
|
517
|
+
else:
|
518
|
+
input_ = [input_]
|
519
|
+
return input_
|
520
|
+
|
521
|
+
|
522
|
+
|
523
|
+
|
524
|
+
|
525
|
+
|
526
|
+
|
527
|
+
|
490
528
|
# def dynamic_unflatten(flat_dict, sep='_', custom_logic=None, max_depth=None):
|
491
529
|
# """
|
492
530
|
# Unflattens a dictionary with flat keys into a nested dictionary or list.
|
lionagi/utils/io_util.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
+
# used flat_util
|
1
2
|
import csv
|
2
3
|
import json
|
3
4
|
import os
|
4
5
|
import tempfile
|
5
6
|
from typing import Any, Dict, List
|
6
|
-
from .
|
7
|
+
from .flat_util import to_list
|
7
8
|
|
8
9
|
|
9
10
|
def to_temp(input: Any,
|
@@ -79,7 +80,6 @@ def to_csv(input: List[Dict[str, Any]]=None,
|
|
79
80
|
writer.writeheader()
|
80
81
|
writer.writerows(input)
|
81
82
|
|
82
|
-
|
83
83
|
def append_to_jsonl(data: Any, filepath: str) -> None:
|
84
84
|
"""
|
85
85
|
Appends data to a JSON lines (jsonl) file.
|
lionagi/utils/sys_util.py
CHANGED
@@ -13,12 +13,14 @@ Copyright 2023 HaiyangLi <ocean@lionagi.ai>
|
|
13
13
|
See the License for the specific language governing permissions and
|
14
14
|
limitations under the License.
|
15
15
|
"""
|
16
|
+
|
17
|
+
# this module has no internal dependency
|
16
18
|
import os
|
17
19
|
import copy
|
18
20
|
import hashlib
|
19
21
|
from pathlib import Path
|
20
22
|
from datetime import datetime
|
21
|
-
from typing import Any, Generator, List
|
23
|
+
from typing import Any, Generator, List, Dict
|
22
24
|
|
23
25
|
def create_copy(input: Any, n: int) -> Any:
|
24
26
|
"""
|
@@ -164,6 +166,48 @@ def get_bins(input: List[str], upper: int = 7500) -> List[List[int]]:
|
|
164
166
|
|
165
167
|
return bins
|
166
168
|
|
169
|
+
def change_dict_key(dict_, old_key, new_key):
|
170
|
+
dict_[new_key] = dict_.pop(old_key)
|
171
|
+
|
172
|
+
def timestamp_to_datetime(timestamp: int) -> str:
|
173
|
+
if isinstance(timestamp, str):
|
174
|
+
try:
|
175
|
+
timestamp = int(timestamp)
|
176
|
+
except:
|
177
|
+
return timestamp
|
178
|
+
return datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
|
179
|
+
|
180
|
+
def is_schema(dict_: Dict, schema: Dict):
|
181
|
+
for key, expected_type in schema.items():
|
182
|
+
if not isinstance(dict_[key], expected_type):
|
183
|
+
return False
|
184
|
+
return True
|
185
|
+
|
186
|
+
def create_hash(data: str, algorithm: str = 'sha256') -> str:
|
187
|
+
"""
|
188
|
+
Generates a hash for the given data using the specified algorithm.
|
189
|
+
|
190
|
+
Parameters:
|
191
|
+
data (str): The data to be hashed.
|
192
|
+
algorithm (str): The hashing algorithm to use (e.g., 'sha256', 'md5').
|
193
|
+
|
194
|
+
Returns:
|
195
|
+
str: The generated hash string.
|
196
|
+
"""
|
197
|
+
hasher = hashlib.new(algorithm)
|
198
|
+
hasher.update(data.encode())
|
199
|
+
return hasher.hexdigest()
|
200
|
+
|
201
|
+
|
202
|
+
|
203
|
+
# def parse_function_call(response: str) -> Tuple[str, Dict]:
|
204
|
+
# out = json.loads(response)
|
205
|
+
# func = out.get('function', '').lstrip('call_')
|
206
|
+
# args = json.loads(out.get('arguments', '{}'))
|
207
|
+
# return func, args
|
208
|
+
|
209
|
+
# ------------------------------------------------------------------------
|
210
|
+
# credit to OpenAI for the following functions
|
167
211
|
def task_id_generator() -> Generator[int, None, None]:
|
168
212
|
"""
|
169
213
|
A generator function that yields a sequential series of task IDs.
|
@@ -180,12 +224,3 @@ def task_id_generator() -> Generator[int, None, None]:
|
|
180
224
|
while True:
|
181
225
|
yield task_id
|
182
226
|
task_id += 1
|
183
|
-
|
184
|
-
def change_dict_key(dict_, old_key, new_key):
|
185
|
-
dict_[new_key] = dict_.pop(old_key)
|
186
|
-
|
187
|
-
# def parse_function_call(response: str) -> Tuple[str, Dict]:
|
188
|
-
# out = json.loads(response)
|
189
|
-
# func = out.get('function', '').lstrip('call_')
|
190
|
-
# args = json.loads(out.get('arguments', '{}'))
|
191
|
-
# return func, args
|
lionagi/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.0.
|
1
|
+
__version__ = "0.0.116"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: lionagi
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.116
|
4
4
|
Summary: Towards automated general intelligence.
|
5
5
|
Author: HaiyangLi
|
6
6
|
Author-email: Haiyang Li <ocean@lionagi.ai>
|
@@ -224,7 +224,7 @@ Requires-Dist: httpx ==0.25.1
|
|
224
224
|
|
225
225
|
|
226
226
|
|
227
|
-
[PyPI](https://pypi.org/project/lionagi/) | [Documentation](https://lionagi.readthedocs.io/en/latest/) | [Discord](https://discord.gg/
|
227
|
+
[PyPI](https://pypi.org/project/lionagi/) | [Documentation](https://lionagi.readthedocs.io/en/latest/) | [Discord](https://discord.gg/mzDD5JtYRp)
|
228
228
|
|
229
229
|
|
230
230
|
# LionAGI
|