lionagi 0.0.111__py3-none-any.whl → 0.0.113__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 -2
- lionagi/bridge/__init__.py +7 -0
- lionagi/bridge/langchain.py +131 -0
- lionagi/bridge/llama_index.py +157 -0
- lionagi/configs/__init__.py +7 -0
- lionagi/configs/oai_configs.py +49 -0
- lionagi/configs/openrouter_config.py +49 -0
- lionagi/core/__init__.py +15 -0
- lionagi/{session/conversation.py → core/conversations.py} +10 -17
- lionagi/core/flows.py +1 -0
- lionagi/core/instruction_sets.py +1 -0
- lionagi/{session/message.py → core/messages.py} +5 -5
- lionagi/core/sessions.py +262 -0
- lionagi/datastore/__init__.py +1 -0
- lionagi/datastore/chroma.py +1 -0
- lionagi/datastore/deeplake.py +1 -0
- lionagi/datastore/elasticsearch.py +1 -0
- lionagi/datastore/lantern.py +1 -0
- lionagi/datastore/pinecone.py +1 -0
- lionagi/datastore/postgres.py +1 -0
- lionagi/datastore/qdrant.py +1 -0
- lionagi/loader/__init__.py +12 -0
- lionagi/loader/chunker.py +157 -0
- lionagi/loader/reader.py +124 -0
- lionagi/objs/__init__.py +7 -0
- lionagi/objs/messenger.py +163 -0
- lionagi/objs/tool_registry.py +247 -0
- lionagi/schema/__init__.py +11 -0
- lionagi/schema/base_condition.py +1 -0
- lionagi/schema/base_schema.py +239 -0
- lionagi/schema/base_tool.py +9 -0
- lionagi/schema/data_logger.py +94 -0
- lionagi/services/__init__.py +14 -0
- lionagi/services/anthropic.py +1 -0
- lionagi/services/anyscale.py +0 -0
- lionagi/services/azure.py +1 -0
- lionagi/{api/oai_service.py → services/base_api_service.py} +74 -148
- lionagi/services/bedrock.py +0 -0
- lionagi/services/chatcompletion.py +48 -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 +1 -0
- lionagi/services/localai.py +0 -0
- lionagi/services/mistralai.py +0 -0
- lionagi/services/oai.py +34 -0
- lionagi/services/ollama.py +1 -0
- lionagi/services/openllm.py +0 -0
- lionagi/services/openrouter.py +32 -0
- lionagi/services/perplexity.py +0 -0
- lionagi/services/predibase.py +0 -0
- lionagi/services/rungpt.py +0 -0
- lionagi/services/service_objs.py +282 -0
- lionagi/services/vllm.py +0 -0
- lionagi/services/xinference.py +0 -0
- lionagi/structure/__init__.py +7 -0
- lionagi/structure/relationship.py +128 -0
- lionagi/structure/structure.py +160 -0
- lionagi/tests/__init__.py +0 -0
- lionagi/tests/test_flatten_util.py +426 -0
- lionagi/tools/__init__.py +0 -0
- lionagi/tools/coder.py +1 -0
- lionagi/tools/planner.py +1 -0
- lionagi/tools/prompter.py +1 -0
- lionagi/tools/sandbox.py +1 -0
- lionagi/tools/scorer.py +1 -0
- lionagi/tools/summarizer.py +1 -0
- lionagi/tools/validator.py +1 -0
- lionagi/utils/__init__.py +46 -8
- lionagi/utils/api_util.py +63 -416
- lionagi/utils/call_util.py +347 -0
- lionagi/utils/flat_util.py +540 -0
- lionagi/utils/io_util.py +102 -0
- lionagi/utils/load_utils.py +190 -0
- lionagi/utils/sys_util.py +85 -660
- lionagi/utils/tool_util.py +82 -199
- lionagi/utils/type_util.py +81 -0
- lionagi/version.py +1 -1
- {lionagi-0.0.111.dist-info → lionagi-0.0.113.dist-info}/METADATA +44 -15
- lionagi-0.0.113.dist-info/RECORD +84 -0
- lionagi/api/__init__.py +0 -8
- lionagi/api/oai_config.py +0 -16
- lionagi/session/__init__.py +0 -7
- lionagi/session/session.py +0 -380
- lionagi/utils/doc_util.py +0 -331
- lionagi/utils/log_util.py +0 -86
- lionagi-0.0.111.dist-info/RECORD +0 -20
- {lionagi-0.0.111.dist-info → lionagi-0.0.113.dist-info}/LICENSE +0 -0
- {lionagi-0.0.111.dist-info → lionagi-0.0.113.dist-info}/WHEEL +0 -0
- {lionagi-0.0.111.dist-info → lionagi-0.0.113.dist-info}/top_level.txt +0 -0
lionagi/utils/sys_util.py
CHANGED
@@ -13,226 +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
|
-
import asyncio
|
18
|
-
import copy
|
19
|
-
import csv
|
20
|
-
import json
|
21
16
|
import os
|
22
|
-
import
|
23
|
-
import tempfile
|
24
|
-
import time
|
17
|
+
import copy
|
25
18
|
import hashlib
|
19
|
+
from pathlib import Path
|
26
20
|
from datetime import datetime
|
27
|
-
from
|
28
|
-
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
29
|
-
|
30
|
-
|
31
|
-
def _flatten_dict(input: Dict[str, Any], parent_key: str = '',
|
32
|
-
sep: str = '_') -> Generator[tuple[str, Any], None, None]:
|
33
|
-
"""
|
34
|
-
Recursively flattens a nested dictionary into a flat dictionary.
|
35
|
-
|
36
|
-
This generator function traverses a nested dictionary, concatenating nested keys
|
37
|
-
into a single key using the provided separator. It handles both nested dictionaries
|
38
|
-
and lists within the dictionary.
|
39
|
-
|
40
|
-
Parameters:
|
41
|
-
input (Dict[str, Any]): The dictionary to be flattened.
|
21
|
+
from typing import Any, Generator, List
|
42
22
|
|
43
|
-
|
44
|
-
|
45
|
-
sep (str, optional): Separator for concatenated key. Defaults to '_'.
|
46
|
-
|
47
|
-
Yields:
|
48
|
-
Generator[tuple[str, Any], None, None]: Tuples of flattened keys and their values.
|
49
|
-
|
50
|
-
Examples:
|
51
|
-
>>> example_dict = {"a": 1, "b": {"c": 2, "d": {"e": 3}}}
|
52
|
-
>>> list(_flatten_dict(example_dict))
|
53
|
-
[('a', 1), ('b_c', 2), ('b_d_e', 3)]
|
54
|
-
|
55
|
-
>>> example_dict_with_list = {"a": 1, "b": [{"c": 2}, {"d": 3}]}
|
56
|
-
>>> list(_flatten_dict(example_dict_with_list))
|
57
|
-
[('a', 1), ('b_0_c', 2), ('b_1_d', 3)]
|
58
|
-
"""
|
59
|
-
for key, value in input.items():
|
60
|
-
composed_key = f'{parent_key}{sep}{key}' if parent_key else key
|
61
|
-
if isinstance(value, MutableMapping):
|
62
|
-
yield from _flatten_dict(value, composed_key, sep=sep)
|
63
|
-
elif isinstance(value, list):
|
64
|
-
for i, item in enumerate(value):
|
65
|
-
if isinstance(item, MutableMapping):
|
66
|
-
yield from _flatten_dict(item, f'{composed_key}{sep}{i}', sep=sep)
|
67
|
-
else:
|
68
|
-
yield (f'{composed_key}{sep}{i}', item)
|
69
|
-
else:
|
70
|
-
yield (composed_key, value)
|
71
|
-
|
72
|
-
def to_flat_dict(input: Dict[str, Any], parent_key: str = '', sep: str = '_') -> Dict[str, Any]:
|
73
|
-
"""
|
74
|
-
Transforms a nested dictionary into a flat dictionary.
|
75
|
-
|
76
|
-
This function flattens a dictionary with potentially nested structures, concatenating
|
77
|
-
nested keys using the specified separator. It leverages the '_flatten_dict' generator
|
78
|
-
function for efficient processing.
|
79
|
-
|
80
|
-
Parameters:
|
81
|
-
input (Dict[str, Any]): The nested dictionary to flatten.
|
82
|
-
|
83
|
-
parent_key (str, optional): Initial key for nested structures. Defaults to ''.
|
84
|
-
|
85
|
-
sep (str, optional): Separator for concatenated keys. Defaults to '_'.
|
86
|
-
|
87
|
-
Returns:
|
88
|
-
Dict[str, Any]: The resulting flat dictionary.
|
89
|
-
|
90
|
-
Example:
|
91
|
-
>>> example_nested_dict = {'a': 1, 'b': {'c': 2}}
|
92
|
-
>>> to_flat_dict(example_nested_dict)
|
93
|
-
{'a': 1, 'b_c': 2}
|
94
|
-
"""
|
95
|
-
return dict(_flatten_dict(input, parent_key, sep))
|
96
|
-
|
97
|
-
def _flatten_list(input: List[Any], dropna: bool = True) -> Generator[Any, None, None]:
|
98
|
-
"""
|
99
|
-
Recursively flattens a nested list into a single-level list.
|
100
|
-
|
101
|
-
This generator function iterates through a list, flattening nested lists into a single
|
102
|
-
level. It provides an option to exclude 'None' values from the output, enhancing its utility.
|
103
|
-
|
104
|
-
Parameters:
|
105
|
-
input (List[Any]): The list to be flattened.
|
106
|
-
|
107
|
-
dropna (bool, optional): Flag to indicate whether 'None' values should be omitted. Defaults to True.
|
108
|
-
|
109
|
-
Yields:
|
110
|
-
Generator[Any, None, None]: Elements from the flattened list.
|
111
|
-
|
112
|
-
Example:
|
113
|
-
>>> example_nested_list = [1, [2, 3, None], 4]
|
114
|
-
>>> list(_flatten_list(example_nested_list))
|
115
|
-
[1, 2, 3, 4]
|
116
|
-
"""
|
117
|
-
for element in input:
|
118
|
-
if isinstance(element, list):
|
119
|
-
yield from _flatten_list(element, dropna)
|
120
|
-
elif element is not None or not dropna:
|
121
|
-
yield element
|
122
|
-
|
123
|
-
def to_list(input: Union[Iterable, Any], flatten_dict: bool = False, flat: bool = True,
|
124
|
-
dropna: bool = True, parent_key: str = '', sep: str = '_') -> List[Any]:
|
125
|
-
"""
|
126
|
-
Converts a given input into a list, optionally flattening nested structures.
|
127
|
-
|
128
|
-
This function converts various inputs into a list, with optional handling for
|
129
|
-
flattening nested lists and dictionaries, and dropping 'None' values. If 'flatten_dict'
|
130
|
-
is True and the input is a dictionary, it is flattened before conversion.
|
131
|
-
|
132
|
-
Parameters:
|
133
|
-
input (Union[Iterable, Any]): The input to convert.
|
134
|
-
|
135
|
-
flatten_dict (bool, optional): Flatten dictionary input. Defaults to False.
|
136
|
-
|
137
|
-
flat (bool, optional): Flatten the output list. Defaults to True.
|
138
|
-
|
139
|
-
dropna (bool, optional): Drop 'None' values during flattening. Defaults to True.
|
140
|
-
|
141
|
-
parent_key (str, optional): The parent key for flattening dictionaries. Defaults to an empty string.
|
142
|
-
|
143
|
-
sep (str, optional): The separator for creating flattened dictionary keys. Defaults to '_'.
|
144
|
-
|
145
|
-
Raises:
|
146
|
-
ValueError: If input is None, callable, or unconvertible to a list.
|
147
|
-
|
148
|
-
Returns:
|
149
|
-
List[Any]: The resulting list after applying transformations.
|
150
|
-
|
151
|
-
Example:
|
152
|
-
>>> to_list({'a': 1, 'b': [2, 3]}, flatten_dict=True)
|
153
|
-
[{'a': 1}, {'b_0': 2}, {'b_1': 3}]
|
154
|
-
"""
|
155
|
-
|
156
|
-
if input is None:
|
157
|
-
raise ValueError("Unsupported type: None are not convertible to a list.")
|
158
|
-
|
159
|
-
try:
|
160
|
-
if isinstance(input, dict):
|
161
|
-
if flatten_dict:
|
162
|
-
input = dict(_flatten_dict(input, parent_key, sep)) # Flatten and convert to dictionary first
|
163
|
-
return [{k: v} for k, v in input.items()]
|
164
|
-
output = [input]
|
165
|
-
elif isinstance(input, Iterable) and not isinstance(input, str):
|
166
|
-
output = list(input)
|
167
|
-
else:
|
168
|
-
output = [input]
|
169
|
-
|
170
|
-
if flat: # Flatten if necessary
|
171
|
-
output = list(_flatten_list(output, dropna))
|
172
|
-
return output
|
173
|
-
|
174
|
-
except TypeError as e:
|
175
|
-
raise ValueError(f"Unable to convert input to list. Error: {e}")
|
176
|
-
|
177
|
-
def str_to_num(input: str,
|
178
|
-
upper_bound: Optional[Union[int, float]] = None,
|
179
|
-
lower_bound: Optional[Union[int, float]] = None,
|
180
|
-
num_type: type = int,
|
181
|
-
precision: Optional[int] = None) -> Union[int, float]:
|
182
|
-
"""
|
183
|
-
Converts found numeric value in a string to a specified type.
|
184
|
-
|
185
|
-
This function searches a string for numeric values and converts it to an integer
|
186
|
-
or a float, based on the specified type. It also validates the converted value
|
187
|
-
against optional upper and lower bounds.
|
188
|
-
|
189
|
-
Parameters:
|
190
|
-
input (str): String to search for numeric values.
|
191
|
-
|
192
|
-
upper_bound (Optional[Union[int, float]]): Upper limit for the numeric value. None for no limit.
|
193
|
-
|
194
|
-
lower_bound (Optional[Union[int, float]]): Lower limit for the numeric value. None for no limit.
|
195
|
-
|
196
|
-
num_type (type): Desired type for the numeric value (int or float).
|
197
|
-
|
198
|
-
precision (Optional[int]): Decimal places for rounding if float. None for no rounding.
|
199
|
-
|
200
|
-
Raises:
|
201
|
-
ValueError: If no numeric values are found, for conversion errors, or if the number is out of bounds.
|
202
|
-
|
203
|
-
Returns:
|
204
|
-
Union[int, float]: The converted numeric value, if within specified bounds.
|
205
|
-
|
206
|
-
Example:
|
207
|
-
>>> str_to_num("Temperature is -5.6 degrees", num_type=float, precision=1)
|
208
|
-
-5.6
|
209
|
-
>>> str_to_num("Value is approximately 200", upper_bound=150)
|
210
|
-
ValueError: Number 200 is greater than the upper bound of 150.
|
211
|
-
"""
|
212
|
-
numbers = re.findall(r'-?\d+\.?\d*', input)
|
213
|
-
if not numbers:
|
214
|
-
raise ValueError(f"No numeric values found in the string: {input}")
|
215
|
-
|
216
|
-
try:
|
217
|
-
numbers = numbers[0]
|
218
|
-
|
219
|
-
if num_type is int:
|
220
|
-
numbers = int(float(numbers))
|
221
|
-
elif num_type is float:
|
222
|
-
numbers = round(float(numbers), precision) if precision is not None else float(numbers)
|
223
|
-
else:
|
224
|
-
raise ValueError(f"Invalid number type: {num_type}")
|
225
|
-
|
226
|
-
if upper_bound is not None and numbers > upper_bound:
|
227
|
-
raise ValueError(f"Number {numbers} is greater than the upper bound of {upper_bound}.")
|
228
|
-
if lower_bound is not None and numbers < lower_bound:
|
229
|
-
raise ValueError(f"Number {numbers} is less than the lower bound of {lower_bound}.")
|
230
|
-
|
231
|
-
return numbers
|
232
|
-
except ValueError as e:
|
233
|
-
raise ValueError(f"Error converting string to number: {e}")
|
234
|
-
|
235
|
-
def make_copy(input: Any, n: int) -> Any:
|
23
|
+
def create_copy(input: Any, n: int) -> Any:
|
236
24
|
"""
|
237
25
|
Creates a deep copy of the input object a specified number of times.
|
238
26
|
|
@@ -260,436 +48,24 @@ def make_copy(input: Any, n: int) -> Any:
|
|
260
48
|
raise ValueError(f"'n' must be a positive integer: {n}")
|
261
49
|
return copy.deepcopy(input) if n == 1 else [copy.deepcopy(input) for _ in range(n)]
|
262
50
|
|
263
|
-
def
|
264
|
-
flatten_dict: bool = False,
|
265
|
-
flat: bool = False,
|
266
|
-
dropna: bool = False):
|
267
|
-
"""
|
268
|
-
Converts input to a list and writes it to a temporary file in JSON format, with flattening options.
|
269
|
-
|
270
|
-
This function serializes data to a temporary JSON file, useful for transient storage or testing.
|
271
|
-
It includes options to flatten the input if it contains dictionaries or lists.
|
272
|
-
|
273
|
-
Parameters:
|
274
|
-
input (Any): The data to be converted and written to a file.
|
275
|
-
|
276
|
-
flatten_dict (bool, optional): Flatten dictionaries in the input. Defaults to False.
|
277
|
-
|
278
|
-
flat (bool, optional): Flatten lists in the input. Defaults to False.
|
279
|
-
|
280
|
-
dropna (bool, optional): Exclude 'None' values during flattening. Defaults to False.
|
281
|
-
|
282
|
-
Raises:
|
283
|
-
TypeError: If the input is not JSON serializable.
|
284
|
-
|
285
|
-
Example:
|
286
|
-
>>> temp_file = to_temp({'a': 1, 'b': [2, 3]}, flatten_dict=True)
|
287
|
-
>>> temp_file.name # Doctest: +ELLIPSIS
|
288
|
-
'/var/folders/.../tmp...'
|
289
|
-
"""
|
290
|
-
input = to_list(input, flatten_dict, flat, dropna)
|
291
|
-
|
292
|
-
temp_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
|
293
|
-
try:
|
294
|
-
json.dump(input, temp_file)
|
295
|
-
except TypeError as e:
|
296
|
-
temp_file.close() # Ensuring file closure before raising error
|
297
|
-
raise TypeError(f"Data provided is not JSON serializable: {e}")
|
298
|
-
temp_file.close()
|
299
|
-
return temp_file
|
300
|
-
|
301
|
-
def to_csv(input: List[Dict[str, Any]],
|
302
|
-
filepath: str,
|
303
|
-
file_exist_ok: bool = False) -> None:
|
304
|
-
"""
|
305
|
-
Writes a list of dictionaries to a CSV file, with dictionary keys as headers.
|
306
|
-
|
307
|
-
This function writes a list of dictionaries to a CSV file. It checks if the file exists
|
308
|
-
and handles file creation based on the 'file_exist_ok' flag.
|
309
|
-
|
310
|
-
Parameters:
|
311
|
-
input (List[Dict[str, Any]]): Data to write to the CSV file.
|
312
|
-
|
313
|
-
filepath (str): Path of the output CSV file.
|
314
|
-
|
315
|
-
file_exist_ok (bool, optional): Create the file if it doesn't exist. Defaults to False.
|
316
|
-
|
317
|
-
Raises:
|
318
|
-
FileExistsError: If the file already exists and 'file_exist_ok' is False.
|
319
|
-
|
320
|
-
Example:
|
321
|
-
>>> data = [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]
|
322
|
-
>>> to_csv(data, 'people.csv')
|
323
|
-
"""
|
324
|
-
|
325
|
-
if not os.path.exists(os.path.dirname(filepath)) and os.path.dirname(filepath) != '':
|
326
|
-
if file_exist_ok:
|
327
|
-
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
328
|
-
else:
|
329
|
-
raise FileNotFoundError(f"The directory {os.path.dirname(filepath)} does not exist.")
|
330
|
-
|
331
|
-
with open(filepath, 'w', newline='') as csv_file:
|
332
|
-
writer = csv.DictWriter(csv_file, fieldnames=input[0].keys())
|
333
|
-
writer.writeheader()
|
334
|
-
writer.writerows(input)
|
335
|
-
|
336
|
-
|
337
|
-
def append_to_jsonl(data: Any, filepath: str) -> None:
|
338
|
-
"""
|
339
|
-
Appends data to a JSON lines (jsonl) file.
|
340
|
-
|
341
|
-
Serializes given data to a JSON-formatted string and appends it to a jsonl file.
|
342
|
-
Useful for logging or data collection where entries are added incrementally.
|
343
|
-
|
344
|
-
Parameters:
|
345
|
-
data (Any): Data to be serialized and appended.
|
346
|
-
|
347
|
-
filepath (str): Path to the jsonl file.
|
348
|
-
|
349
|
-
Example:
|
350
|
-
>>> append_to_jsonl({"key": "value"}, "data.jsonl")
|
351
|
-
# Appends {"key": "value"} to 'data.jsonl'
|
352
|
-
"""
|
353
|
-
json_string = json.dumps(data)
|
354
|
-
with open(filepath, "a") as f:
|
355
|
-
f.write(json_string + "\n")
|
356
|
-
|
357
|
-
def hold_call(input: Any,
|
358
|
-
func: Callable,
|
359
|
-
sleep: int = 0.1,
|
360
|
-
message: Optional[str] = None,
|
361
|
-
ignore_error: bool = False,
|
362
|
-
**kwargs) -> Any:
|
363
|
-
"""
|
364
|
-
Executes a function after a specified delay, handling exceptions optionally.
|
365
|
-
|
366
|
-
Waits for 'sleep' seconds before calling 'func' with 'input'. Handles exceptions by
|
367
|
-
printing a message and optionally re-raising them.
|
368
|
-
|
369
|
-
Parameters:
|
370
|
-
input (Any): Input to the function.
|
371
|
-
|
372
|
-
func (Callable): Function to execute.
|
373
|
-
|
374
|
-
sleep (int, optional): Time in seconds to wait before calling the function. Defaults to 0.1.
|
375
|
-
|
376
|
-
message (Optional[str], optional): Message to print on exception. Defaults to None.
|
377
|
-
|
378
|
-
ignore_error (bool, optional): If True, ignores exceptions. Defaults to False.
|
379
|
-
|
380
|
-
**kwargs: Additional keyword arguments for the function.
|
381
|
-
|
382
|
-
Returns:
|
383
|
-
Any: Result of the function call.
|
384
|
-
|
385
|
-
Raises:
|
386
|
-
Exception: Re-raises the exception unless 'ignore_error' is True.
|
387
|
-
|
388
|
-
Example:
|
389
|
-
>>> def add_one(x):
|
390
|
-
... return x + 1
|
391
|
-
>>> hold_call(5, add_one, sleep=2)
|
392
|
-
6
|
393
|
-
"""
|
394
|
-
try:
|
395
|
-
time.sleep(sleep)
|
396
|
-
return func(input, **kwargs)
|
397
|
-
except Exception as e:
|
398
|
-
if message:
|
399
|
-
print(f"{message} Error: {e}")
|
400
|
-
else:
|
401
|
-
print(f"An error occurred: {e}")
|
402
|
-
if not ignore_error:
|
403
|
-
raise
|
404
|
-
|
405
|
-
async def ahold_call(input: Any,
|
406
|
-
func: Callable,
|
407
|
-
sleep: int = 5,
|
408
|
-
message: Optional[str] = None,
|
409
|
-
ignore_error: bool = False,
|
410
|
-
**kwargs) -> Any:
|
411
|
-
"""
|
412
|
-
Asynchronously executes a function after a specified delay, handling exceptions optionally.
|
413
|
-
|
414
|
-
Waits for 'sleep' seconds before calling 'func' with 'input'. Handles exceptions by
|
415
|
-
printing a message and optionally re-raising them.
|
416
|
-
|
417
|
-
Parameters:
|
418
|
-
input (Any): Input to the function.
|
419
|
-
|
420
|
-
func (Callable): Asynchronous function to execute.
|
421
|
-
|
422
|
-
sleep (int, optional): Time in seconds to wait before calling the function. Defaults to 5.
|
423
|
-
|
424
|
-
message (Optional[str], optional): Message to print on exception. Defaults to None.
|
425
|
-
|
426
|
-
ignore_error (bool, optional): If True, ignores exceptions. Defaults to False.
|
427
|
-
|
428
|
-
**kwargs: Additional keyword arguments for the function.
|
429
|
-
|
430
|
-
Returns:
|
431
|
-
Any: Result of the asynchronous function call.
|
432
|
-
|
433
|
-
Raises:
|
434
|
-
Exception: Re-raises the exception unless 'ignore_error' is True.
|
435
|
-
|
436
|
-
Example:
|
437
|
-
>>> async def async_add_one(x):
|
438
|
-
... return x + 1
|
439
|
-
>>> asyncio.run(ahold_call(5, async_add_one, sleep=2))
|
440
|
-
6
|
441
|
-
"""
|
442
|
-
try:
|
443
|
-
if not asyncio.iscoroutinefunction(func):
|
444
|
-
raise TypeError(f"The function {func} must be an asynchronous function.")
|
445
|
-
await asyncio.sleep(sleep)
|
446
|
-
return await func(input, **kwargs)
|
447
|
-
except Exception as e:
|
448
|
-
if message:
|
449
|
-
print(f"{message} Error: {e}")
|
450
|
-
else:
|
451
|
-
print(f"An error occurred: {e}")
|
452
|
-
if not ignore_error:
|
453
|
-
raise
|
454
|
-
|
455
|
-
def l_call(input: Any,
|
456
|
-
func: Callable,
|
457
|
-
flatten_dict: bool = False,
|
458
|
-
flat: bool = False,
|
459
|
-
dropna: bool = True) -> List[Any]:
|
51
|
+
def create_id(n=32) -> str:
|
460
52
|
"""
|
461
|
-
|
462
|
-
|
463
|
-
This function converts the `input` to a list, with options to flatten structures
|
464
|
-
and lists, and then applies a given `func` to each element of the list.
|
465
|
-
|
466
|
-
Parameters:
|
467
|
-
input (Any): The input to be converted to a list and processed.
|
468
|
-
|
469
|
-
func (Callable): The function to apply to each element of the list.
|
470
|
-
|
471
|
-
flatten_dict (bool, optional): If True, flattens dictionaries in the input. Defaults to False.
|
472
|
-
|
473
|
-
flat (bool, optional): If True, flattens nested lists in the input. Defaults to False.
|
474
|
-
|
475
|
-
dropna (bool, optional): If True, drops None values during flattening. Defaults to True.
|
476
|
-
|
477
|
-
Returns:
|
478
|
-
List[Any]: A list containing the results of applying the `func` to each element.
|
479
|
-
|
480
|
-
Raises:
|
481
|
-
ValueError: If the `func` cannot be applied to the `input`.
|
482
|
-
|
483
|
-
Example:
|
484
|
-
>>> def square(x):
|
485
|
-
... return x * x
|
486
|
-
>>> l_call([1, 2, 3], square)
|
487
|
-
[1, 4, 9]
|
488
|
-
"""
|
489
|
-
try:
|
490
|
-
lst = to_list(input, flatten_dict, flat, dropna)
|
491
|
-
return [func(i) for i in lst]
|
492
|
-
except Exception as e:
|
493
|
-
raise ValueError(f"Given function cannot be applied to the input. Error: {e}")
|
494
|
-
|
495
|
-
async def al_call(input: Any,
|
496
|
-
func: Callable,
|
497
|
-
flatten_dict: bool = False,
|
498
|
-
flat: bool = False,
|
499
|
-
dropna: bool = True) -> List[Any]:
|
500
|
-
"""
|
501
|
-
Asynchronously applies a function to each element of `input`, after converting it to a list.
|
502
|
-
|
503
|
-
This function converts the `input` to a list, with options to flatten
|
504
|
-
dictionaries and lists, and then applies a given asynchronous `func` to
|
505
|
-
each element of the list asynchronously.
|
506
|
-
|
507
|
-
Parameters:
|
508
|
-
input (Any): The input to be converted to a list and processed.
|
509
|
-
|
510
|
-
func (Callable): The asynchronous function to apply to each element of the list.
|
511
|
-
|
512
|
-
flatten_dict (bool, optional): If True, flattens dictionaries in the input. Defaults to False.
|
513
|
-
|
514
|
-
flat (bool, optional): If True, flattens nested lists in the input. Defaults to False.
|
515
|
-
|
516
|
-
dropna (bool, optional): If True, drops None values during flattening. Defaults to True.
|
517
|
-
|
518
|
-
Returns:
|
519
|
-
List[Any]: A list containing the results of applying the `func` to each element.
|
520
|
-
|
521
|
-
Raises:
|
522
|
-
ValueError: If the `func` cannot be applied to the `input`.
|
523
|
-
|
524
|
-
Example:
|
525
|
-
>>> async def async_square(x):
|
526
|
-
... return x * x
|
527
|
-
>>> asyncio.run(al_call([1, 2, 3], async_square))
|
528
|
-
[1, 4, 9]
|
529
|
-
"""
|
530
|
-
try:
|
531
|
-
lst = to_list(input, flatten_dict, flat, dropna)
|
532
|
-
tasks = [func(i) for i in lst]
|
533
|
-
return await asyncio.gather(*tasks)
|
534
|
-
except Exception as e:
|
535
|
-
raise ValueError(f"Given function cannot be applied to the input. Error: {e}")
|
536
|
-
|
537
|
-
def m_call(input: Union[Any, List[Any]],
|
538
|
-
func: Union[Callable, List[Callable]],
|
539
|
-
flatten_dict: bool = False,
|
540
|
-
flat: bool = True,
|
541
|
-
dropna: bool = True) -> List[Any]:
|
542
|
-
"""
|
543
|
-
Maps multiple functions to corresponding elements of the input.
|
544
|
-
|
545
|
-
This function applies a list of functions to a list of inputs, with each function
|
546
|
-
being applied to its corresponding input element. It asserts that the number of inputs
|
547
|
-
and functions are the same and raises an error if they are not.
|
548
|
-
|
549
|
-
Parameters:
|
550
|
-
input (Union[Any, List[Any]]): The input or list of inputs to be processed.
|
551
|
-
|
552
|
-
func (Union[Callable, List[Callable]]): The function or list of functions to apply.
|
553
|
-
|
554
|
-
flatten_dict (bool, optional): Whether to flatten dictionaries in the input. Defaults to False.
|
555
|
-
|
556
|
-
flat (bool, optional): Whether the output list should be flattened. Defaults to True.
|
557
|
-
|
558
|
-
dropna (bool, optional): Whether to drop None values during flattening. Defaults to True.
|
559
|
-
|
560
|
-
Returns:
|
561
|
-
List[Any]: A list containing the results from applying each function to its corresponding input.
|
562
|
-
|
563
|
-
Raises:
|
564
|
-
ValueError: If the number of provided inputs and functions are not the same.
|
565
|
-
|
566
|
-
Example:
|
567
|
-
>>> def add_one(x):
|
568
|
-
... return x + 1
|
569
|
-
>>> m_call([1, 2], [add_one, add_one])
|
570
|
-
[2, 3]
|
571
|
-
"""
|
572
|
-
input = to_list(input, flatten_dict, flat, dropna)
|
573
|
-
func = to_list(func)
|
574
|
-
assert len(input) == len(func), "The number of inputs and functions must be the same."
|
575
|
-
return to_list([l_call(inp, f, flatten_dict, flat, dropna)
|
576
|
-
for f, inp in zip(func, input)])
|
577
|
-
|
578
|
-
async def am_call(input: Union[Any, List[Any]],
|
579
|
-
func: Union[Callable, List[Callable]],
|
580
|
-
flatten_dict: bool = False,
|
581
|
-
flat: bool = True,
|
582
|
-
dropna: bool = True) -> List[Any]:
|
583
|
-
"""
|
584
|
-
Asynchronously applies multiple functions to corresponding elements of the input.
|
585
|
-
|
586
|
-
This asynchronous function maps a list of functions to a list of inputs, with each
|
587
|
-
function being applied to its corresponding input element asynchronously. It ensures
|
588
|
-
that the number of inputs and functions are the same, raising a `ValueError` if not.
|
589
|
-
|
590
|
-
Parameters:
|
591
|
-
input (Union[Any, List[Any]]): The input or list of inputs to be processed.
|
592
|
-
|
593
|
-
func (Union[Callable, List[Callable]]): The function or list of functions to apply.
|
594
|
-
|
595
|
-
flatten_dict (bool, optional): Whether to flatten dictionaries in the input. Defaults to False.
|
596
|
-
|
597
|
-
flat (bool, optional): Whether the output list should be flattened. Defaults to True.
|
598
|
-
|
599
|
-
dropna (bool, optional): Whether to drop None values during flattening. Defaults to True.
|
600
|
-
|
601
|
-
Returns:
|
602
|
-
List[Any]: A list containing the results from applying each function to its corresponding input.
|
603
|
-
|
604
|
-
Raises:
|
605
|
-
ValueError: If the number of inputs and functions do not match.
|
606
|
-
|
607
|
-
Example:
|
608
|
-
>>> async def async_add_one(x):
|
609
|
-
... return x + 1
|
610
|
-
>>> asyncio.run(am_call([1, 2], [async_add_one, async_add_one]))
|
611
|
-
[2, 3]
|
612
|
-
"""
|
613
|
-
input = to_list(input, flatten_dict, flat, dropna)
|
614
|
-
func = to_list(func)
|
615
|
-
assert len(input) == len(func), "Input and function counts must match."
|
616
|
-
|
617
|
-
tasks = [al_call(inp, f, flatten_dict, flat, dropna)
|
618
|
-
for f, inp in zip(func, input)]
|
619
|
-
out = await asyncio.gather(*tasks)
|
620
|
-
return to_list(out, flat=True)
|
621
|
-
|
622
|
-
def e_call(input: Any,
|
623
|
-
func: Callable,
|
624
|
-
flatten_dict: bool = False,
|
625
|
-
flat: bool = False,
|
626
|
-
dropna: bool = True) -> List[Any]:
|
627
|
-
"""
|
628
|
-
Applies each function in a list of functions to all elements in the input.
|
629
|
-
|
630
|
-
This function expands the input to match the number of functions and then
|
631
|
-
applies each function to the entire input. It is useful for applying a series
|
632
|
-
of different transformations to the same input.
|
633
|
-
|
634
|
-
Parameters:
|
635
|
-
input (Union[Any, List[Any]]): The input or list of inputs to be processed.
|
636
|
-
|
637
|
-
func (Union[Callable, List[Callable]]): The function or list of functions to apply.
|
638
|
-
|
639
|
-
flatten_dict (bool, optional): Whether to flatten dictionaries in the input. Defaults to False.
|
640
|
-
|
641
|
-
flat (bool, optional): Whether the output list should be flattened. Defaults to True.
|
53
|
+
Generates a unique ID based on the current time and random bytes.
|
642
54
|
|
643
|
-
|
55
|
+
This function combines the current time in ISO 8601 format with 16 random bytes
|
56
|
+
to create a unique identifier. The result is hashed using SHA-256 and the first
|
57
|
+
16 characters of the hexadecimal digest are returned.
|
644
58
|
|
645
59
|
Returns:
|
646
|
-
|
647
|
-
|
648
|
-
Example:
|
649
|
-
>>> def square(x):
|
650
|
-
... return x**2
|
651
|
-
>>> e_call([1, 2, 3], [square])
|
652
|
-
[[1], [4], [9]]
|
653
|
-
"""
|
654
|
-
|
655
|
-
_f = lambda x, y: m_call(make_copy(x, len(to_list(y))), y,
|
656
|
-
flatten_dict=flatten_dict, flat=flat, dropna=dropna)
|
657
|
-
return to_list([_f(inp, func) for inp in to_list(input)], flat=flat)
|
658
|
-
|
659
|
-
async def ae_call(input_: Any,
|
660
|
-
func_: Callable,
|
661
|
-
flatten_dict: bool = False,
|
662
|
-
flat: bool = False,
|
663
|
-
dropna: bool = True):
|
664
|
-
"""
|
665
|
-
Asynchronously applies each function in a list of functions to all elements in the input.
|
666
|
-
|
667
|
-
This asynchronous function expands the input to match the number of functions and
|
668
|
-
then asynchronously applies each function to the entire input. It is useful for applying a series
|
669
|
-
of different asynchronous transformations to the same input.
|
670
|
-
|
671
|
-
Parameters:
|
672
|
-
input_ (Union[Any, List[Any]]): The input or list of inputs to be processed.
|
673
|
-
|
674
|
-
func_ (Union[Callable, List[Callable]]): The function or list of functions to apply.
|
675
|
-
|
676
|
-
flatten_dict (bool, optional): Whether to flatten dictionaries in the input. Defaults to False.
|
677
|
-
|
678
|
-
flat (bool, optional): Whether the output list should be flattened. Defaults to True.
|
679
|
-
|
680
|
-
dropna (bool, optional): Whether to drop None values during flattening. Defaults to True.
|
60
|
+
str: A 16-character unique identifier.
|
681
61
|
|
682
62
|
Example:
|
683
|
-
>>>
|
684
|
-
...
|
685
|
-
>>> asyncio.run(ae_call([1, 2, 3], [async_square]))
|
686
|
-
[[1, 4, 9]]
|
63
|
+
>>> create_id() # Doctest: +ELLIPSIS
|
64
|
+
'...'
|
687
65
|
"""
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
tasks = [_async_f(inp, func_) for inp in to_list(input_)]
|
692
|
-
return await asyncio.gather(*tasks)
|
66
|
+
current_time = datetime.now().isoformat().encode('utf-8')
|
67
|
+
random_bytes = os.urandom(2048)
|
68
|
+
return hashlib.sha256(current_time + random_bytes).hexdigest()[:n]
|
693
69
|
|
694
70
|
def get_timestamp() -> str:
|
695
71
|
"""
|
@@ -708,26 +84,6 @@ def get_timestamp() -> str:
|
|
708
84
|
"""
|
709
85
|
return datetime.now().isoformat().replace(":", "_").replace(".", "_")
|
710
86
|
|
711
|
-
def create_id() -> str:
|
712
|
-
"""
|
713
|
-
Generates a unique ID based on the current time and random bytes.
|
714
|
-
|
715
|
-
This function combines the current time in ISO 8601 format with 16 random bytes
|
716
|
-
to create a unique identifier. The result is hashed using SHA-256 and the first
|
717
|
-
16 characters of the hexadecimal digest are returned.
|
718
|
-
|
719
|
-
Returns:
|
720
|
-
str: A 16-character unique identifier.
|
721
|
-
|
722
|
-
Example:
|
723
|
-
>>> create_id() # Doctest: +ELLIPSIS
|
724
|
-
'...'
|
725
|
-
"""
|
726
|
-
current_time = datetime.now().isoformat().encode('utf-8')
|
727
|
-
random_bytes = os.urandom(16)
|
728
|
-
return hashlib.sha256(current_time + random_bytes).hexdigest()[:16]
|
729
|
-
|
730
|
-
|
731
87
|
def create_path(dir: str, filename: str, timestamp: bool = True, dir_exist_ok: bool = True, time_prefix=False) -> str:
|
732
88
|
"""
|
733
89
|
Creates a file path by optionally appending a timestamp to the filename.
|
@@ -763,4 +119,73 @@ def create_path(dir: str, filename: str, timestamp: bool = True, dir_exist_ok: b
|
|
763
119
|
return f"{dir}{timestamp}_{filename}.{ext}" if time_prefix else f"{dir}{filename}_{timestamp}.{ext}"
|
764
120
|
else:
|
765
121
|
return f"{dir}{filename}"
|
766
|
-
|
122
|
+
|
123
|
+
def split_path(path: Path) -> tuple:
|
124
|
+
folder_name = path.parent.name
|
125
|
+
file_name = path.name
|
126
|
+
return (folder_name, file_name)
|
127
|
+
|
128
|
+
def get_bins(input: List[str], upper: int = 7500) -> List[List[int]]:
|
129
|
+
"""
|
130
|
+
Get index of elements in a list based on their consecutive cumulative sum of length,
|
131
|
+
according to some upper threshold. Return lists of indices as bins.
|
132
|
+
|
133
|
+
Parameters:
|
134
|
+
input (List[str]): List of items to be binned.
|
135
|
+
|
136
|
+
upper (int, optional): Upper threshold for the cumulative sum of the length of items in a bin. Default is 7500.
|
137
|
+
|
138
|
+
Returns:
|
139
|
+
List[List[int]]: List of lists, where each inner list contains the indices of the items that form a bin.
|
140
|
+
|
141
|
+
Example:
|
142
|
+
>>> items = ['apple', 'a', 'b', 'banana', 'cheery', 'c', 'd', 'e']
|
143
|
+
>>> upper = 10
|
144
|
+
>>> get_bins(items, upper)
|
145
|
+
[[0, 1, 2], [3], [4, 5, 6, 7]]
|
146
|
+
"""
|
147
|
+
current = 0
|
148
|
+
bins = []
|
149
|
+
bin = []
|
150
|
+
|
151
|
+
for idx, item in enumerate(input):
|
152
|
+
|
153
|
+
if current + len(item) < upper:
|
154
|
+
bin.append(idx)
|
155
|
+
current += len(item)
|
156
|
+
|
157
|
+
elif current + len(item) >= upper:
|
158
|
+
bins.append(bin)
|
159
|
+
bin = [idx]
|
160
|
+
current = len(item)
|
161
|
+
|
162
|
+
if idx == len(input) - 1 and len(bin) > 0:
|
163
|
+
bins.append(bin)
|
164
|
+
|
165
|
+
return bins
|
166
|
+
|
167
|
+
def task_id_generator() -> Generator[int, None, None]:
|
168
|
+
"""
|
169
|
+
A generator function that yields a sequential series of task IDs.
|
170
|
+
|
171
|
+
Yields:
|
172
|
+
int: The next task ID in the sequence, starting from 0.
|
173
|
+
|
174
|
+
Examples:
|
175
|
+
task_id_gen = task_id_generator()
|
176
|
+
next(task_id_gen) # Yields 0
|
177
|
+
next(task_id_gen) # Yields 1
|
178
|
+
"""
|
179
|
+
task_id = 0
|
180
|
+
while True:
|
181
|
+
yield task_id
|
182
|
+
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
|