lionagi 0.6.1__py3-none-any.whl → 0.7.0__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/libs/token_transform/__init__.py +0 -0
- lionagi/libs/token_transform/llmlingua.py +1 -0
- lionagi/libs/token_transform/perplexity.py +439 -0
- lionagi/libs/token_transform/synthlang.py +409 -0
- lionagi/operations/ReAct/ReAct.py +126 -0
- lionagi/operations/ReAct/utils.py +28 -0
- lionagi/operations/__init__.py +1 -9
- lionagi/operations/_act/act.py +73 -0
- lionagi/operations/chat/__init__.py +3 -0
- lionagi/operations/chat/chat.py +173 -0
- lionagi/operations/communicate/__init__.py +0 -0
- lionagi/operations/communicate/communicate.py +167 -0
- lionagi/operations/instruct/__init__.py +3 -0
- lionagi/operations/instruct/instruct.py +29 -0
- lionagi/operations/interpret/__init__.py +3 -0
- lionagi/operations/interpret/interpret.py +40 -0
- lionagi/operations/operate/__init__.py +3 -0
- lionagi/operations/operate/operate.py +189 -0
- lionagi/operations/parse/__init__.py +3 -0
- lionagi/operations/parse/parse.py +125 -0
- lionagi/operations/select/__init__.py +0 -4
- lionagi/operations/select/select.py +11 -30
- lionagi/operations/select/utils.py +13 -2
- lionagi/operations/translate/__init__.py +0 -0
- lionagi/operations/translate/translate.py +47 -0
- lionagi/operations/types.py +16 -0
- lionagi/operatives/action/manager.py +20 -21
- lionagi/operatives/strategies/__init__.py +3 -0
- lionagi/session/branch.py +1098 -929
- lionagi/version.py +1 -1
- {lionagi-0.6.1.dist-info → lionagi-0.7.0.dist-info}/METADATA +1 -1
- {lionagi-0.6.1.dist-info → lionagi-0.7.0.dist-info}/RECORD +45 -26
- lionagi/libs/compress/models.py +0 -66
- lionagi/libs/compress/utils.py +0 -69
- lionagi/operations/select/prompt.py +0 -5
- /lionagi/{libs/compress → operations/ReAct}/__init__.py +0 -0
- /lionagi/operations/{strategies → _act}/__init__.py +0 -0
- /lionagi/{operations → operatives}/strategies/base.py +0 -0
- /lionagi/{operations → operatives}/strategies/concurrent.py +0 -0
- /lionagi/{operations → operatives}/strategies/concurrent_chunk.py +0 -0
- /lionagi/{operations → operatives}/strategies/concurrent_sequential_chunk.py +0 -0
- /lionagi/{operations → operatives}/strategies/params.py +0 -0
- /lionagi/{operations → operatives}/strategies/sequential.py +0 -0
- /lionagi/{operations → operatives}/strategies/sequential_chunk.py +0 -0
- /lionagi/{operations → operatives}/strategies/sequential_concurrent_chunk.py +0 -0
- /lionagi/{operations → operatives}/strategies/utils.py +0 -0
- {lionagi-0.6.1.dist-info → lionagi-0.7.0.dist-info}/WHEEL +0 -0
- {lionagi-0.6.1.dist-info → lionagi-0.7.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,125 @@
|
|
1
|
+
# Copyright (c) 2023 - 2024, HaiyangLi <quantocean.li at gmail dot com>
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
4
|
+
|
5
|
+
from typing import TYPE_CHECKING, Any, Literal
|
6
|
+
|
7
|
+
from pydantic import BaseModel
|
8
|
+
|
9
|
+
from lionagi.libs.validate.fuzzy_validate_mapping import fuzzy_validate_mapping
|
10
|
+
from lionagi.operatives.types import Operative
|
11
|
+
from lionagi.utils import breakdown_pydantic_annotation
|
12
|
+
|
13
|
+
if TYPE_CHECKING:
|
14
|
+
from lionagi.session.branch import Branch
|
15
|
+
|
16
|
+
|
17
|
+
async def parse(
|
18
|
+
branch: "Branch",
|
19
|
+
text: str,
|
20
|
+
handle_validation: Literal[
|
21
|
+
"raise", "return_value", "return_none"
|
22
|
+
] = "return_value",
|
23
|
+
max_retries: int = 3,
|
24
|
+
request_type: type[BaseModel] = None,
|
25
|
+
operative: Operative = None,
|
26
|
+
similarity_algo="jaro_winkler",
|
27
|
+
similarity_threshold: float = 0.85,
|
28
|
+
fuzzy_match: bool = True,
|
29
|
+
handle_unmatched: Literal[
|
30
|
+
"ignore", "raise", "remove", "fill", "force"
|
31
|
+
] = "force",
|
32
|
+
fill_value: Any = None,
|
33
|
+
fill_mapping: dict[str, Any] | None = None,
|
34
|
+
strict: bool = False,
|
35
|
+
suppress_conversion_errors: bool = False,
|
36
|
+
response_format=None,
|
37
|
+
):
|
38
|
+
"""Attempts to parse text into a structured Pydantic model.
|
39
|
+
|
40
|
+
Uses optional fuzzy matching to handle partial or unclear fields.
|
41
|
+
|
42
|
+
Args:
|
43
|
+
text (str): The raw text to parse.
|
44
|
+
handle_validation (Literal["raise","return_value","return_none"]):
|
45
|
+
What to do if parsing fails. Defaults to "return_value".
|
46
|
+
max_retries (int):
|
47
|
+
How many times to retry parsing if it fails.
|
48
|
+
request_type (type[BaseModel], optional):
|
49
|
+
The Pydantic model to parse into.
|
50
|
+
operative (Operative, optional):
|
51
|
+
If provided, uses its model and max_retries setting.
|
52
|
+
similarity_algo (str):
|
53
|
+
The similarity algorithm for fuzzy field matching.
|
54
|
+
similarity_threshold (float):
|
55
|
+
A threshold for fuzzy matching (0.0 - 1.0).
|
56
|
+
fuzzy_match (bool):
|
57
|
+
If True, tries to match unrecognized keys to known ones.
|
58
|
+
handle_unmatched (Literal["ignore","raise","remove","fill","force"]):
|
59
|
+
How to handle unmatched fields.
|
60
|
+
fill_value (Any):
|
61
|
+
A default value used when fill is needed.
|
62
|
+
fill_mapping (dict[str, Any] | None):
|
63
|
+
A mapping from field -> fill value override.
|
64
|
+
strict (bool):
|
65
|
+
If True, raises errors on ambiguous fields or data types.
|
66
|
+
suppress_conversion_errors (bool):
|
67
|
+
If True, logs or ignores errors during data conversion.
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
BaseModel | Any | None:
|
71
|
+
The parsed model instance, or a dict/string/None depending
|
72
|
+
on the handling mode.
|
73
|
+
"""
|
74
|
+
_should_try = True
|
75
|
+
num_try = 0
|
76
|
+
response_model = text
|
77
|
+
if operative is not None:
|
78
|
+
max_retries = operative.max_retries
|
79
|
+
response_format = operative.request_type
|
80
|
+
|
81
|
+
while (
|
82
|
+
_should_try
|
83
|
+
and num_try < max_retries
|
84
|
+
and not isinstance(response_model, BaseModel)
|
85
|
+
):
|
86
|
+
num_try += 1
|
87
|
+
_, res = await branch.chat(
|
88
|
+
instruction="reformat text into specified model",
|
89
|
+
guidane="follow the required response format, using the model schema as a guide",
|
90
|
+
context=[{"text_to_format": text}],
|
91
|
+
response_format=response_format or request_type,
|
92
|
+
sender=branch.user,
|
93
|
+
recipient=branch.id,
|
94
|
+
imodel=branch.parse_model,
|
95
|
+
return_ins_res_message=True,
|
96
|
+
)
|
97
|
+
if operative is not None:
|
98
|
+
response_model = operative.update_response_model(res.response)
|
99
|
+
else:
|
100
|
+
response_model = fuzzy_validate_mapping(
|
101
|
+
res.response,
|
102
|
+
breakdown_pydantic_annotation(request_type),
|
103
|
+
similarity_algo=similarity_algo,
|
104
|
+
similarity_threshold=similarity_threshold,
|
105
|
+
fuzzy_match=fuzzy_match,
|
106
|
+
handle_unmatched=handle_unmatched,
|
107
|
+
fill_value=fill_value,
|
108
|
+
fill_mapping=fill_mapping,
|
109
|
+
strict=strict,
|
110
|
+
suppress_conversion_errors=suppress_conversion_errors,
|
111
|
+
)
|
112
|
+
response_model = request_type.model_validate(response_model)
|
113
|
+
|
114
|
+
if not isinstance(response_model, BaseModel):
|
115
|
+
match handle_validation:
|
116
|
+
case "return_value":
|
117
|
+
return response_model
|
118
|
+
case "return_none":
|
119
|
+
return None
|
120
|
+
case "raise":
|
121
|
+
raise ValueError(
|
122
|
+
"Failed to parse response into request format"
|
123
|
+
)
|
124
|
+
|
125
|
+
return response_model
|
@@ -2,56 +2,37 @@
|
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
|
-
|
6
5
|
from enum import Enum
|
7
|
-
from typing import Any
|
6
|
+
from typing import TYPE_CHECKING, Any
|
8
7
|
|
9
|
-
from pydantic import BaseModel
|
8
|
+
from pydantic import BaseModel
|
10
9
|
|
11
10
|
from lionagi.operatives.types import Instruct
|
12
|
-
from lionagi.session.branch import Branch
|
13
|
-
|
14
|
-
from .prompt import PROMPT
|
15
|
-
from .utils import parse_selection, parse_to_representation
|
16
11
|
|
12
|
+
from .utils import SelectionModel
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
selected: list[Any] = Field(default_factory=list)
|
14
|
+
if TYPE_CHECKING:
|
15
|
+
from lionagi.session.branch import Branch
|
22
16
|
|
23
17
|
|
24
18
|
async def select(
|
19
|
+
branch: "Branch",
|
25
20
|
instruct: Instruct | dict[str, Any],
|
26
21
|
choices: list[str] | type[Enum] | dict[str, Any],
|
27
22
|
max_num_selections: int = 1,
|
28
|
-
branch: Branch | None = None,
|
29
23
|
branch_kwargs: dict[str, Any] | None = None,
|
30
24
|
return_branch: bool = False,
|
31
25
|
verbose: bool = False,
|
32
26
|
**kwargs: Any,
|
33
|
-
) -> SelectionModel | tuple[SelectionModel, Branch]:
|
34
|
-
"""Perform a selection operation from given choices.
|
35
|
-
|
36
|
-
Args:
|
37
|
-
instruct: Instruction model or dictionary.
|
38
|
-
choices: Options to select from.
|
39
|
-
max_num_selections: Maximum selections allowed.
|
40
|
-
branch: Existing branch or None to create a new one.
|
41
|
-
branch_kwargs: Additional arguments for branch creation.
|
42
|
-
return_branch: If True, return the branch with the selection.
|
43
|
-
verbose: Whether to enable verbose output.
|
44
|
-
**kwargs: Additional keyword arguments.
|
45
|
-
|
46
|
-
Returns:
|
47
|
-
A SelectionModel instance, optionally with the branch.
|
48
|
-
"""
|
27
|
+
) -> SelectionModel | tuple[SelectionModel, "Branch"]:
|
49
28
|
if verbose:
|
50
29
|
print(f"Starting selection with up to {max_num_selections} choices.")
|
51
30
|
|
31
|
+
from .utils import SelectionModel, parse_selection, parse_to_representation
|
32
|
+
|
52
33
|
branch = branch or Branch(**(branch_kwargs or {}))
|
53
34
|
selections, contents = parse_to_representation(choices)
|
54
|
-
prompt = PROMPT.format(
|
35
|
+
prompt = SelectionModel.PROMPT.format(
|
55
36
|
max_num_selections=max_num_selections, choices=selections
|
56
37
|
)
|
57
38
|
|
@@ -73,7 +54,7 @@ async def select(
|
|
73
54
|
instruct["context"] = context
|
74
55
|
|
75
56
|
response_model: SelectionModel = await branch.operate(
|
76
|
-
|
57
|
+
response_format=SelectionModel,
|
77
58
|
**kwargs,
|
78
59
|
**instruct,
|
79
60
|
)
|
@@ -4,14 +4,25 @@
|
|
4
4
|
|
5
5
|
import inspect
|
6
6
|
from enum import Enum
|
7
|
-
from typing import Any
|
7
|
+
from typing import Any, ClassVar
|
8
8
|
|
9
|
-
from pydantic import BaseModel, JsonValue
|
9
|
+
from pydantic import BaseModel, Field, JsonValue
|
10
10
|
|
11
11
|
from lionagi.libs.validate.string_similarity import string_similarity
|
12
12
|
from lionagi.utils import is_same_dtype
|
13
13
|
|
14
14
|
|
15
|
+
# TODO: Make select a field to be added into a model, much like reason and action
|
16
|
+
class SelectionModel(BaseModel):
|
17
|
+
"""Model representing the selection output."""
|
18
|
+
|
19
|
+
PROMPT: ClassVar[str] = (
|
20
|
+
"Please select up to {max_num_selections} items from the following list {choices}. Provide the selection(s) into appropriate field in format required, and no comments from you"
|
21
|
+
)
|
22
|
+
|
23
|
+
selected: list[Any] = Field(default_factory=list)
|
24
|
+
|
25
|
+
|
15
26
|
def parse_to_representation(
|
16
27
|
choices: Enum | dict | list | tuple | set,
|
17
28
|
) -> tuple[list[str], JsonValue]:
|
File without changes
|
@@ -0,0 +1,47 @@
|
|
1
|
+
from typing import TYPE_CHECKING, Literal
|
2
|
+
|
3
|
+
from lionagi.service.imodel import iModel
|
4
|
+
|
5
|
+
if TYPE_CHECKING:
|
6
|
+
from lionagi.session.branch import Branch
|
7
|
+
|
8
|
+
|
9
|
+
async def translate(
|
10
|
+
branch: "Branch",
|
11
|
+
text: str,
|
12
|
+
technique: Literal["SynthLang"] = "SynthLang",
|
13
|
+
technique_kwargs: dict = None,
|
14
|
+
compress: bool = False,
|
15
|
+
chat_model: iModel = None,
|
16
|
+
compress_model: iModel = None,
|
17
|
+
compression_ratio: float = 0.2,
|
18
|
+
compress_kwargs=None,
|
19
|
+
verbose: bool = True,
|
20
|
+
new_branch: bool = True,
|
21
|
+
**kwargs,
|
22
|
+
):
|
23
|
+
if technique == "SynthLang":
|
24
|
+
from lionagi.libs.token_transform.synthlang import (
|
25
|
+
translate_to_synthlang,
|
26
|
+
)
|
27
|
+
|
28
|
+
if not technique_kwargs:
|
29
|
+
technique_kwargs = {}
|
30
|
+
if not technique_kwargs.get("template_name"):
|
31
|
+
technique_kwargs["template_name"] = "symbolic_systems"
|
32
|
+
|
33
|
+
technique_kwargs = {**technique_kwargs, **kwargs}
|
34
|
+
|
35
|
+
return await translate_to_synthlang(
|
36
|
+
text=text,
|
37
|
+
compress=compress,
|
38
|
+
chat_model=chat_model or branch.chat_model,
|
39
|
+
compress_model=compress_model,
|
40
|
+
compression_ratio=compression_ratio,
|
41
|
+
compress_kwargs=compress_kwargs,
|
42
|
+
verbose=verbose,
|
43
|
+
branch=branch if not new_branch else None,
|
44
|
+
**technique_kwargs,
|
45
|
+
)
|
46
|
+
|
47
|
+
raise ValueError(f"Technique {technique} is not supported.")
|
lionagi/operations/types.py
CHANGED
@@ -3,11 +3,27 @@
|
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
5
|
from .brainstorm.brainstorm import brainstorm
|
6
|
+
from .chat.chat import chat
|
7
|
+
from .communicate.communicate import communicate
|
8
|
+
from .instruct.instruct import instruct
|
9
|
+
from .interpret.interpret import interpret
|
10
|
+
from .operate.operate import operate
|
11
|
+
from .parse.parse import parse
|
6
12
|
from .plan.plan import plan
|
13
|
+
from .ReAct.ReAct import ReAct
|
7
14
|
from .select.select import select
|
15
|
+
from .translate.translate import translate
|
8
16
|
|
9
17
|
__all__ = (
|
10
18
|
"brainstorm",
|
11
19
|
"plan",
|
12
20
|
"select",
|
21
|
+
"chat",
|
22
|
+
"communicate",
|
23
|
+
"instruct",
|
24
|
+
"interpret",
|
25
|
+
"operate",
|
26
|
+
"parse",
|
27
|
+
"ReAct",
|
28
|
+
"translate",
|
13
29
|
)
|
@@ -5,8 +5,7 @@
|
|
5
5
|
from typing import Any
|
6
6
|
|
7
7
|
from lionagi.protocols._concepts import Manager
|
8
|
-
from lionagi.protocols.generic.event import
|
9
|
-
from lionagi.protocols.generic.log import Log
|
8
|
+
from lionagi.protocols.generic.event import Execution
|
10
9
|
from lionagi.protocols.messages.action_request import ActionRequest
|
11
10
|
from lionagi.utils import to_list
|
12
11
|
|
@@ -113,19 +112,28 @@ class ActionManager(Manager):
|
|
113
112
|
]
|
114
113
|
|
115
114
|
def match_tool(
|
116
|
-
self, action_request: ActionRequest | ActionRequestModel
|
115
|
+
self, action_request: ActionRequest | ActionRequestModel | dict
|
117
116
|
) -> FunctionCalling:
|
118
|
-
if not isinstance(
|
117
|
+
if not isinstance(
|
118
|
+
action_request, ActionRequest | ActionRequestModel | dict
|
119
|
+
):
|
119
120
|
raise TypeError(f"Unsupported type {type(action_request)}")
|
120
121
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
122
|
+
func = (
|
123
|
+
action_request["function"]
|
124
|
+
if isinstance(action_request, dict)
|
125
|
+
else action_request.function
|
126
|
+
)
|
127
|
+
args = (
|
128
|
+
action_request["arguments"]
|
129
|
+
if isinstance(action_request, dict)
|
130
|
+
else action_request.arguments
|
128
131
|
)
|
132
|
+
tool = self.registry.get(func, None)
|
133
|
+
|
134
|
+
if not isinstance(tool, Tool):
|
135
|
+
raise ValueError(f"Function {func} is not registered.")
|
136
|
+
return FunctionCalling(func_tool=tool, arguments=args)
|
129
137
|
|
130
138
|
async def invoke(
|
131
139
|
self, func_call: ActionRequestModel | ActionRequest
|
@@ -148,16 +156,7 @@ class ActionManager(Manager):
|
|
148
156
|
Raises:
|
149
157
|
ValueError: If function not registered or call format invalid.
|
150
158
|
"""
|
151
|
-
|
152
|
-
function_calling = self.match_tool(func_call)
|
153
|
-
except ValueError as e:
|
154
|
-
return Log(
|
155
|
-
content={
|
156
|
-
"event_type": "function_call",
|
157
|
-
"status": EventStatus.FAILED,
|
158
|
-
"error": str(e),
|
159
|
-
}
|
160
|
-
)
|
159
|
+
function_calling = self.match_tool(func_call)
|
161
160
|
await function_calling.invoke()
|
162
161
|
return function_calling
|
163
162
|
|