lionagi 0.0.306__py3-none-any.whl → 0.0.307__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 +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
|
|