lionagi 0.0.306__py3-none-any.whl → 0.0.307__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- lionagi/__init__.py +2 -5
- lionagi/core/__init__.py +7 -5
- lionagi/core/agent/__init__.py +3 -0
- lionagi/core/agent/base_agent.py +10 -12
- lionagi/core/branch/__init__.py +4 -0
- lionagi/core/branch/base_branch.py +81 -81
- lionagi/core/branch/branch.py +16 -28
- lionagi/core/branch/branch_flow_mixin.py +3 -7
- lionagi/core/branch/executable_branch.py +86 -56
- lionagi/core/branch/util.py +77 -162
- lionagi/core/{flow/direct → direct}/__init__.py +1 -1
- lionagi/core/{flow/direct/predict.py → direct/parallel_predict.py} +39 -17
- lionagi/core/direct/parallel_react.py +0 -0
- lionagi/core/direct/parallel_score.py +0 -0
- lionagi/core/direct/parallel_select.py +0 -0
- lionagi/core/direct/parallel_sentiment.py +0 -0
- lionagi/core/direct/predict.py +174 -0
- lionagi/core/{flow/direct → direct}/react.py +2 -2
- lionagi/core/{flow/direct → direct}/score.py +28 -23
- lionagi/core/{flow/direct → direct}/select.py +48 -45
- lionagi/core/direct/utils.py +83 -0
- lionagi/core/flow/monoflow/ReAct.py +6 -5
- lionagi/core/flow/monoflow/__init__.py +9 -0
- lionagi/core/flow/monoflow/chat.py +10 -10
- lionagi/core/flow/monoflow/chat_mixin.py +11 -10
- lionagi/core/flow/monoflow/followup.py +6 -5
- lionagi/core/flow/polyflow/__init__.py +1 -0
- lionagi/core/flow/polyflow/chat.py +15 -3
- lionagi/core/mail/mail_manager.py +18 -19
- lionagi/core/mail/schema.py +5 -4
- lionagi/core/messages/schema.py +18 -20
- lionagi/core/prompt/__init__.py +0 -0
- lionagi/core/prompt/prompt_template.py +0 -0
- lionagi/core/schema/__init__.py +2 -2
- lionagi/core/schema/action_node.py +11 -3
- lionagi/core/schema/base_mixin.py +56 -59
- lionagi/core/schema/base_node.py +35 -38
- lionagi/core/schema/condition.py +24 -0
- lionagi/core/schema/data_logger.py +96 -99
- lionagi/core/schema/data_node.py +19 -19
- lionagi/core/schema/prompt_template.py +0 -0
- lionagi/core/schema/structure.py +171 -169
- lionagi/core/session/__init__.py +1 -3
- lionagi/core/session/session.py +196 -214
- lionagi/core/tool/tool_manager.py +95 -103
- lionagi/integrations/__init__.py +1 -3
- lionagi/integrations/bridge/langchain_/documents.py +17 -18
- lionagi/integrations/bridge/langchain_/langchain_bridge.py +14 -14
- lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +22 -22
- lionagi/integrations/bridge/llamaindex_/node_parser.py +12 -12
- lionagi/integrations/bridge/llamaindex_/reader.py +11 -11
- lionagi/integrations/bridge/llamaindex_/textnode.py +7 -7
- lionagi/integrations/config/openrouter_configs.py +0 -1
- lionagi/integrations/provider/oai.py +26 -26
- lionagi/integrations/provider/services.py +38 -38
- lionagi/libs/__init__.py +34 -1
- lionagi/libs/ln_api.py +211 -221
- lionagi/libs/ln_async.py +53 -60
- lionagi/libs/ln_convert.py +118 -120
- lionagi/libs/ln_dataframe.py +32 -33
- lionagi/libs/ln_func_call.py +334 -342
- lionagi/libs/ln_nested.py +99 -107
- lionagi/libs/ln_parse.py +161 -165
- lionagi/libs/sys_util.py +52 -52
- lionagi/tests/test_core/test_session.py +254 -266
- lionagi/tests/test_core/test_session_base_util.py +299 -300
- lionagi/tests/test_core/test_tool_manager.py +70 -74
- lionagi/tests/test_libs/test_nested.py +2 -7
- lionagi/tests/test_libs/test_parse.py +2 -2
- lionagi/version.py +1 -1
- {lionagi-0.0.306.dist-info → lionagi-0.0.307.dist-info}/METADATA +4 -2
- lionagi-0.0.307.dist-info/RECORD +115 -0
- lionagi/core/flow/direct/utils.py +0 -43
- lionagi-0.0.306.dist-info/RECORD +0 -106
- /lionagi/core/{flow/direct → direct}/sentiment.py +0 -0
- {lionagi-0.0.306.dist-info → lionagi-0.0.307.dist-info}/LICENSE +0 -0
- {lionagi-0.0.306.dist-info → lionagi-0.0.307.dist-info}/WHEEL +0 -0
- {lionagi-0.0.306.dist-info → lionagi-0.0.307.dist-info}/top_level.txt +0 -0
lionagi/libs/ln_nested.py
CHANGED
@@ -25,13 +25,13 @@ def nset(nested_structure: dict | list, indices: list[int | str], value: Any) ->
|
|
25
25
|
incorrect.
|
26
26
|
|
27
27
|
Examples:
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
>>> data = {'a': {'b': [10, 20]}}
|
29
|
+
>>> nset(data, ['a', 'b', 1], 99)
|
30
|
+
>>> assert data == {'a': {'b': [10, 99]}}
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
>>> data = [0, [1, 2], 3]
|
33
|
+
>>> nset(data, [1, 1], 99)
|
34
|
+
>>> assert data == [0, [1, 99], 3]
|
35
35
|
"""
|
36
36
|
if not indices:
|
37
37
|
raise ValueError("Indices list is empty, cannot determine target container")
|
@@ -77,12 +77,12 @@ def nget(
|
|
77
77
|
and no default value is provided.
|
78
78
|
|
79
79
|
Examples:
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
80
|
+
>>> data = {'a': {'b': [10, 20]}}
|
81
|
+
>>> assert nget(data, ['a', 'b', 1]) == 20
|
82
|
+
>>> nget(data, ['a', 'b', 2])
|
83
|
+
Traceback (most recent call last):
|
84
|
+
...
|
85
|
+
LookupError: Target not found and no default value provided.
|
86
86
|
"""
|
87
87
|
|
88
88
|
try:
|
@@ -140,20 +140,20 @@ def nmerge(
|
|
140
140
|
that defines custom sorting logic for the merged list.
|
141
141
|
|
142
142
|
Returns:
|
143
|
-
|
144
|
-
|
143
|
+
A merged dictionary or list,
|
144
|
+
depending on the types present in `iterables`.
|
145
145
|
|
146
146
|
Raises:
|
147
|
-
|
148
|
-
|
149
|
-
|
147
|
+
TypeError:
|
148
|
+
If `iterables`
|
149
|
+
contains objects of incompatible types that cannot be merged.
|
150
150
|
|
151
151
|
examples:
|
152
|
-
|
153
|
-
|
152
|
+
>>> nmerge([{'a': 1}, {'b': 2}], overwrite=True)
|
153
|
+
{'a': 1, 'b': 2}
|
154
154
|
|
155
|
-
|
156
|
-
|
155
|
+
>>> nmerge([[1, 2], [3, 4]], sort_list=True)
|
156
|
+
[1, 2, 3, 4]
|
157
157
|
"""
|
158
158
|
if convert.is_homogeneous(nested_structure, dict):
|
159
159
|
return _merge_dicts(
|
@@ -196,19 +196,19 @@ def flatten(
|
|
196
196
|
True, only flattens nested dictionaries, leaving lists intact.
|
197
197
|
|
198
198
|
Returns:
|
199
|
-
|
199
|
+
A flattened dictionary, or None if `inplace` is True.
|
200
200
|
|
201
201
|
Raises:
|
202
|
-
|
202
|
+
ValueError: If `inplace` is True but `nested_structure` is not a dictionary.
|
203
203
|
|
204
204
|
examples:
|
205
|
-
|
206
|
-
|
207
|
-
|
205
|
+
>>> nested_dict = {'a': {'b': {'c': 1}}}
|
206
|
+
>>> flatten(nested_dict)
|
207
|
+
{'a_b_c': 1}
|
208
208
|
|
209
|
-
|
210
|
-
|
211
|
-
|
209
|
+
>>> nested_list = [{'a': 1}, {'b': 2}]
|
210
|
+
>>> flatten(nested_list)
|
211
|
+
{'0_a': 1, '1_b': 2}
|
212
212
|
"""
|
213
213
|
if inplace:
|
214
214
|
if not isinstance(nested_structure, dict):
|
@@ -250,22 +250,22 @@ def unflatten(
|
|
250
250
|
keys and can limit the reconstruction depth.
|
251
251
|
|
252
252
|
Args:
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
253
|
+
flat_dict: A flat dictionary with composite keys to unflatten.
|
254
|
+
sep: The sep used in composite keys, indicating nested levels.
|
255
|
+
custom_logic: An optional function to process each part of the composite keys.
|
256
|
+
max_depth: The maximum depth for nesting during reconstruction.
|
257
257
|
|
258
258
|
Returns:
|
259
|
-
|
259
|
+
The reconstructed nested dictionary or list.
|
260
260
|
|
261
261
|
examples:
|
262
|
-
|
263
|
-
|
264
|
-
|
262
|
+
>>> flat_dict_ = {'a_b_c': 1}
|
263
|
+
>>> unflatten(flat_dict_)
|
264
|
+
{'a': {'b': {'c': 1}}}
|
265
265
|
|
266
|
-
|
267
|
-
|
268
|
-
|
266
|
+
>>> flat_dict_ = {'0_a': 1, '1_b': 2}
|
267
|
+
>>> unflatten(flat_dict_)
|
268
|
+
[{'a': 1}, {'b': 2}]
|
269
269
|
"""
|
270
270
|
unflattened = {}
|
271
271
|
for composite_key, value in flat_dict.items():
|
@@ -285,9 +285,7 @@ def unflatten(
|
|
285
285
|
):
|
286
286
|
max_index = max(unflattened.keys(), default=-1)
|
287
287
|
return [unflattened.get(i) for i in range(max_index + 1)]
|
288
|
-
|
289
|
-
return {}
|
290
|
-
return unflattened
|
288
|
+
return unflattened or {}
|
291
289
|
|
292
290
|
|
293
291
|
def nfilter(
|
@@ -310,13 +308,13 @@ def nfilter(
|
|
310
308
|
containing only items that meet the condition.
|
311
309
|
|
312
310
|
Raises:
|
313
|
-
|
311
|
+
TypeError: Raised if `collection` is not a dictionary or a list.
|
314
312
|
|
315
313
|
Examples:
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
314
|
+
>>> nfilter({'a': 1, 'b': 2, 'c': 3}, lambda x: x[1] > 1)
|
315
|
+
{'b': 2, 'c': 3}
|
316
|
+
>>> nfilter([1, 2, 3, 4], lambda x: x % 2 == 0)
|
317
|
+
[2, 4]
|
320
318
|
"""
|
321
319
|
if isinstance(nested_structure, dict):
|
322
320
|
return _filter_dict(nested_structure, condition)
|
@@ -353,13 +351,13 @@ def ninsert(
|
|
353
351
|
depth during recursive calls.
|
354
352
|
|
355
353
|
Examples:
|
356
|
-
|
357
|
-
|
358
|
-
|
354
|
+
>>> subject_ = {'a': {'b': [1, 2]}}
|
355
|
+
>>> ninsert(subject_, ['a', 'b', 2], 3)
|
356
|
+
>>> assert subject_ == {'a': {'b': [1, 2, 3]}}
|
359
357
|
|
360
|
-
|
361
|
-
|
362
|
-
|
358
|
+
>>> subject_ = []
|
359
|
+
>>> ninsert(subject_, [0, 'a'], 1)
|
360
|
+
>>> assert subject_ == [{'a': 1}]
|
363
361
|
"""
|
364
362
|
indices = convert.to_list(indices)
|
365
363
|
parts_len = len(indices)
|
@@ -376,12 +374,10 @@ def ninsert(
|
|
376
374
|
):
|
377
375
|
next_part = indices[i + 1]
|
378
376
|
nested_structure[part] = [] if isinstance(next_part, int) else {}
|
379
|
-
|
380
|
-
|
381
|
-
if
|
382
|
-
|
383
|
-
nested_structure[part] = [] if isinstance(next_part, int) else {}
|
384
|
-
nested_structure = nested_structure[part]
|
377
|
+
elif part not in nested_structure:
|
378
|
+
next_part = indices[i + 1]
|
379
|
+
nested_structure[part] = [] if isinstance(next_part, int) else {}
|
380
|
+
nested_structure = nested_structure[part]
|
385
381
|
current_depth += 1
|
386
382
|
parts_depth += 1
|
387
383
|
|
@@ -391,11 +387,10 @@ def ninsert(
|
|
391
387
|
last_part = indices[-1]
|
392
388
|
if isinstance(last_part, int):
|
393
389
|
_handle_list_insert(nested_structure, last_part, value)
|
390
|
+
elif isinstance(nested_structure, list):
|
391
|
+
nested_structure.append({last_part: value})
|
394
392
|
else:
|
395
|
-
|
396
|
-
nested_structure.append({last_part: value})
|
397
|
-
else:
|
398
|
-
nested_structure[last_part] = value
|
393
|
+
nested_structure[last_part] = value
|
399
394
|
|
400
395
|
|
401
396
|
# noinspection PyDecorator
|
@@ -423,32 +418,29 @@ def get_flattened_keys(
|
|
423
418
|
modifying the original object.
|
424
419
|
|
425
420
|
Returns:
|
426
|
-
|
421
|
+
A list of strings representing the keys in the flattened structure.
|
427
422
|
|
428
423
|
Raises:
|
429
|
-
|
424
|
+
ValueError: If `inplace` is True but `nested_structure` is not a dictionary.
|
430
425
|
|
431
426
|
Examples:
|
432
|
-
|
433
|
-
|
434
|
-
|
427
|
+
>>> nested_dict = {'a': 1, 'b': {'c': 2, 'd': {'e': 3}}}
|
428
|
+
>>> keys = get_flattened_keys(nested_dict)
|
429
|
+
>>> assert keys == ['a', 'b_c', 'b_d_e']
|
435
430
|
|
436
|
-
|
437
|
-
|
438
|
-
|
431
|
+
>>> nested_list = [{'a': 1}, {'b': 2}]
|
432
|
+
>>> keys = get_flattened_keys(nested_list)
|
433
|
+
>>> assert keys == ['0_a', '1_b']
|
439
434
|
"""
|
440
|
-
if inplace:
|
441
|
-
obj_copy = SysUtil.create_copy(nested_structure, num=1)
|
442
|
-
flatten(
|
443
|
-
obj_copy, sep=sep, max_depth=max_depth, inplace=True, dict_only=dict_only
|
444
|
-
)
|
445
|
-
return convert.to_list(obj_copy.keys())
|
446
|
-
else:
|
435
|
+
if not inplace:
|
447
436
|
return convert.to_list(
|
448
437
|
flatten(
|
449
438
|
nested_structure, sep=sep, max_depth=max_depth, dict_only=dict_only
|
450
439
|
).keys()
|
451
440
|
)
|
441
|
+
obj_copy = SysUtil.create_copy(nested_structure, num=1)
|
442
|
+
flatten(obj_copy, sep=sep, max_depth=max_depth, inplace=True, dict_only=dict_only)
|
443
|
+
return convert.to_list(obj_copy.keys())
|
452
444
|
|
453
445
|
|
454
446
|
def _dynamic_flatten_in_place(
|
@@ -469,19 +461,19 @@ def _dynamic_flatten_in_place(
|
|
469
461
|
dictionaries and to a certain depth.
|
470
462
|
|
471
463
|
Args:
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
464
|
+
nested_structure: The structure to flatten.
|
465
|
+
parent_key: Initial key prefix for all keys in the flattened structure.
|
466
|
+
sep: Separator for nested keys.
|
467
|
+
max_depth: Limits the flattening to a specific depth.
|
468
|
+
current_depth: Tracks the current depth in the recursion.
|
469
|
+
dict_only: Limits the flattening to dictionaries only, ignoring lists.
|
478
470
|
|
479
471
|
Note:
|
480
|
-
|
472
|
+
This function modifies `nested_structure` in place.
|
481
473
|
|
482
474
|
Examples:
|
483
|
-
|
484
|
-
|
475
|
+
Given a nested dictionary `nested_dict` with the appropriate structure,
|
476
|
+
`_dynamic_flatten_in_place(nested_dict)` will modify it to a flattened form.
|
485
477
|
"""
|
486
478
|
if isinstance(nested_structure, dict):
|
487
479
|
keys_to_delete = []
|
@@ -525,12 +517,12 @@ def _handle_list_insert(nested_structure: list, part: int, value: Any) -> None:
|
|
525
517
|
`None` values up to the index, then the specified value is inserted.
|
526
518
|
|
527
519
|
Args:
|
528
|
-
|
529
|
-
|
530
|
-
|
520
|
+
nested_structure: The list to modify.
|
521
|
+
part: The target index for inserting or replacing the value.
|
522
|
+
value: The value to be inserted or to replace an existing value in the list.
|
531
523
|
|
532
524
|
Note:
|
533
|
-
|
525
|
+
This function directly modifies the input list in place.
|
534
526
|
"""
|
535
527
|
while len(nested_structure) <= part:
|
536
528
|
nested_structure.append(None)
|
@@ -547,9 +539,9 @@ def _ensure_list_index(lst_: list, index: int, default: Any = None) -> None:
|
|
547
539
|
with a specified default value until it reaches the required length.
|
548
540
|
|
549
541
|
Args:
|
550
|
-
|
551
|
-
|
552
|
-
|
542
|
+
lst_: The list to extend.
|
543
|
+
index: The target index that the list should reach or exceed.
|
544
|
+
default: The value to append to the list for extension. Defaults to None.
|
553
545
|
|
554
546
|
Note: Modifies the list in place, ensuring it can safely be indexed at `index`
|
555
547
|
without raising an IndexError.
|
@@ -569,14 +561,14 @@ def _deep_update(original: dict, update: dict) -> dict:
|
|
569
561
|
the key-value pair to `original`.
|
570
562
|
|
571
563
|
Args:
|
572
|
-
|
573
|
-
|
564
|
+
original: The dictionary to update.
|
565
|
+
update: The dictionary containing updates to apply to `original`.
|
574
566
|
|
575
567
|
Returns:
|
576
|
-
|
568
|
+
The `original` dictionary after applying updates from `update`.
|
577
569
|
|
578
570
|
Note:
|
579
|
-
|
571
|
+
This method modifies the `original` dictionary in place.
|
580
572
|
"""
|
581
573
|
for key, value in update.items():
|
582
574
|
if isinstance(value, dict) and key in original:
|
@@ -646,14 +638,14 @@ def _deep_merge_dicts(dict1: dict, dict2: dict) -> dict:
|
|
646
638
|
pairs from `dict2`.
|
647
639
|
|
648
640
|
Args:
|
649
|
-
|
650
|
-
|
641
|
+
dict1: The target dictionary to update with values from `dict2`.
|
642
|
+
dict2: The source dictionary providing updates and additional key-value pairs.
|
651
643
|
|
652
644
|
Returns:
|
653
|
-
|
645
|
+
The updated dictionary `dict1` with deeply merged values from `dict2`.
|
654
646
|
|
655
647
|
Note:
|
656
|
-
|
648
|
+
Modifies `dict1` in place, reflecting merged changes from `dict2`.
|
657
649
|
"""
|
658
650
|
for key in dict2:
|
659
651
|
if key in dict1:
|
@@ -712,9 +704,9 @@ def _merge_sequences(
|
|
712
704
|
mechanism or a custom sorting function provided by the user.
|
713
705
|
|
714
706
|
Args:
|
715
|
-
|
716
|
-
|
717
|
-
|
707
|
+
iterables: A collection of iterable sequences to be merged.
|
708
|
+
sort_list: Determines whether to sort the merged list.
|
709
|
+
custom_sort: Optional. A function defining custom sort criteria.
|
718
710
|
|
719
711
|
Returns: list[Any]: The merged (and potentially sorted) list of elements from
|
720
712
|
all provided iterables.
|
@@ -765,7 +757,7 @@ def _filter_list(lst: list[Any], condition: Callable[[Any], bool]) -> list[Any]:
|
|
765
757
|
the filtered list.
|
766
758
|
|
767
759
|
Returns:
|
768
|
-
|
760
|
+
list[Any]: A new list comprising elements that meet the condition.
|
769
761
|
"""
|
770
762
|
return [item for item in lst if condition(item)]
|
771
763
|
|