lionagi 0.5.1__py3-none-any.whl → 0.5.2__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 +0 -1
- lionagi/core/action/tool.py +3 -5
- lionagi/core/communication/action_request.py +3 -3
- lionagi/core/communication/message.py +3 -3
- lionagi/core/communication/utils.py +3 -3
- lionagi/core/generic/component.py +4 -4
- lionagi/core/generic/element.py +51 -47
- lionagi/core/generic/graph.py +1 -1
- lionagi/core/generic/log.py +2 -2
- lionagi/core/generic/pile.py +10 -11
- lionagi/core/generic/progression.py +19 -12
- lionagi/core/generic/utils.py +6 -3
- lionagi/core/models/base.py +11 -68
- lionagi/core/models/field_model.py +42 -19
- lionagi/core/models/{new_model_params.py → model_params.py} +5 -6
- lionagi/core/models/note.py +2 -2
- lionagi/core/models/operable_model.py +8 -4
- lionagi/core/models/schema_model.py +9 -31
- lionagi/core/models/types.py +15 -6
- lionagi/core/session/branch.py +10 -7
- lionagi/core/session/branch_mixins.py +11 -12
- lionagi/core/session/session.py +1 -2
- lionagi/core/typing/__init__.py +4 -4
- lionagi/core/typing/{concepts.py → _concepts.py} +43 -2
- lionagi/core/typing/_id.py +104 -0
- lionagi/integrations/anthropic_/AnthropicModel.py +8 -3
- lionagi/integrations/groq_/GroqModel.py +11 -4
- lionagi/integrations/litellm_/imodel.py +6 -8
- lionagi/integrations/openai_/OpenAIModel.py +8 -3
- lionagi/integrations/openai_/image_token_calculator/image_token_calculator.py +14 -8
- lionagi/integrations/perplexity_/PerplexityModel.py +8 -3
- lionagi/libs/func/async_calls/__init__.py +6 -3
- lionagi/libs/func/async_calls/alcall.py +46 -0
- lionagi/libs/func/async_calls/bcall.py +49 -1
- lionagi/libs/func/async_calls/rcall.py +32 -0
- lionagi/libs/utils.py +12 -1
- lionagi/operations/brainstorm/brainstorm.py +3 -3
- lionagi/operations/plan/plan.py +3 -3
- lionagi/protocols/__init__.py +3 -0
- lionagi/protocols/configs/__init__.py +0 -15
- lionagi/protocols/configs/branch_config.py +1 -1
- lionagi/protocols/configs/imodel_config.py +2 -2
- lionagi/protocols/configs/log_config.py +1 -1
- lionagi/protocols/configs/types.py +15 -0
- lionagi/protocols/operatives/__init__.py +3 -15
- lionagi/protocols/operatives/action.py +4 -0
- lionagi/protocols/operatives/instruct.py +6 -2
- lionagi/protocols/operatives/operative.py +9 -21
- lionagi/protocols/operatives/prompts.py +4 -0
- lionagi/protocols/operatives/reason.py +4 -0
- lionagi/protocols/operatives/step.py +11 -23
- lionagi/protocols/operatives/types.py +19 -0
- lionagi/protocols/registries/__init__.py +3 -0
- lionagi/protocols/registries/_component_registry.py +4 -0
- lionagi/protocols/registries/_pile_registry.py +4 -0
- lionagi/service/__init__.py +3 -0
- lionagi/service/service_match_util.py +4 -4
- lionagi/settings.py +10 -18
- lionagi/strategies/base.py +4 -5
- lionagi/strategies/concurrent.py +4 -3
- lionagi/strategies/concurrent_chunk.py +3 -3
- lionagi/strategies/concurrent_sequential_chunk.py +3 -3
- lionagi/strategies/params.py +7 -4
- lionagi/version.py +1 -1
- {lionagi-0.5.1.dist-info → lionagi-0.5.2.dist-info}/METADATA +4 -2
- {lionagi-0.5.1.dist-info → lionagi-0.5.2.dist-info}/RECORD +71 -70
- lionagi/core/typing/config.py +0 -15
- lionagi/core/typing/id.py +0 -221
- /lionagi/core/typing/{pydantic_.py → _pydantic.py} +0 -0
- /lionagi/core/typing/{typing_.py → _typing.py} +0 -0
- /lionagi/integrations/{services.py → _services.py} +0 -0
- {lionagi-0.5.1.dist-info → lionagi-0.5.2.dist-info}/WHEEL +0 -0
- {lionagi-0.5.1.dist-info → lionagi-0.5.2.dist-info}/licenses/LICENSE +0 -0
@@ -2,9 +2,13 @@
|
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
|
-
from
|
6
|
-
|
7
|
-
from .
|
5
|
+
from lionagi.libs.utils import is_same_dtype
|
6
|
+
|
7
|
+
from ..typing._pydantic import ConfigDict, Field, FieldInfo, field_validator
|
8
|
+
from ..typing._typing import UNDEFINED, Any, Callable, UndefinedType
|
9
|
+
from .schema_model import SchemaModel
|
10
|
+
|
11
|
+
__all__ = ("FieldModel",)
|
8
12
|
|
9
13
|
|
10
14
|
class FieldModel(SchemaModel):
|
@@ -51,24 +55,34 @@ class FieldModel(SchemaModel):
|
|
51
55
|
"""
|
52
56
|
|
53
57
|
model_config = ConfigDict(
|
54
|
-
extra="allow",
|
58
|
+
extra="allow",
|
59
|
+
validate_default=False,
|
60
|
+
populate_by_name=True,
|
61
|
+
arbitrary_types_allowed=True,
|
62
|
+
use_enum_values=True,
|
55
63
|
)
|
56
64
|
|
57
65
|
# Field configuration attributes
|
58
66
|
default: Any = UNDEFINED # Default value
|
59
|
-
default_factory: Callable
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
67
|
+
default_factory: Callable | UndefinedType = (
|
68
|
+
UNDEFINED # Factory function for default value
|
69
|
+
)
|
70
|
+
title: str | UndefinedType = UNDEFINED # Field title
|
71
|
+
description: str | UndefinedType = UNDEFINED # Field description
|
72
|
+
examples: list | UndefinedType = UNDEFINED # Example values
|
73
|
+
validators: list | UndefinedType = UNDEFINED # Validation functions
|
74
|
+
exclude: bool | UndefinedType = UNDEFINED # Exclude from serialization
|
75
|
+
deprecated: bool | UndefinedType = UNDEFINED # Mark as deprecated
|
76
|
+
frozen: bool | UndefinedType = UNDEFINED # Mark as immutable
|
77
|
+
alias: str | UndefinedType = UNDEFINED # Alternative field name
|
78
|
+
alias_priority: int | UndefinedType = (
|
79
|
+
UNDEFINED # Priority for alias resolution
|
80
|
+
)
|
69
81
|
|
70
82
|
# Core field attributes
|
71
|
-
name: str
|
83
|
+
name: str | UndefinedType = Field(
|
84
|
+
..., exclude=True
|
85
|
+
) # Field name (required)
|
72
86
|
annotation: type | Any = Field(UNDEFINED, exclude=True) # Type annotation
|
73
87
|
validator: Callable | Any = Field(
|
74
88
|
UNDEFINED, exclude=True
|
@@ -77,6 +91,18 @@ class FieldModel(SchemaModel):
|
|
77
91
|
default_factory=dict, exclude=True
|
78
92
|
) # Validator parameters
|
79
93
|
|
94
|
+
@field_validator("validators", mode="before")
|
95
|
+
def _validate_validators(cls, v) -> list[Callable]:
|
96
|
+
if v is None or v is UNDEFINED:
|
97
|
+
return []
|
98
|
+
if isinstance(v, Callable):
|
99
|
+
return [v]
|
100
|
+
if isinstance(v, list) and is_same_dtype(v, Callable):
|
101
|
+
return v
|
102
|
+
raise ValueError(
|
103
|
+
"Validators must be a list of functions or a function"
|
104
|
+
)
|
105
|
+
|
80
106
|
@property
|
81
107
|
def field_info(self) -> FieldInfo:
|
82
108
|
"""Generate Pydantic FieldInfo object from field configuration.
|
@@ -92,7 +118,7 @@ class FieldModel(SchemaModel):
|
|
92
118
|
annotation = (
|
93
119
|
self.annotation if self.annotation is not UNDEFINED else Any
|
94
120
|
)
|
95
|
-
field_obj: FieldInfo = Field(**self.to_dict(
|
121
|
+
field_obj: FieldInfo = Field(**self.to_dict()) # type: ignore
|
96
122
|
field_obj.annotation = annotation
|
97
123
|
return field_obj
|
98
124
|
|
@@ -117,6 +143,3 @@ class FieldModel(SchemaModel):
|
|
117
143
|
self.validator
|
118
144
|
)
|
119
145
|
}
|
120
|
-
|
121
|
-
|
122
|
-
__all__ = ["FieldModel"]
|
@@ -9,7 +9,7 @@ from pydantic import BaseModel
|
|
9
9
|
from lionagi.libs.parse import validate_boolean
|
10
10
|
from lionagi.libs.utils import copy
|
11
11
|
|
12
|
-
from ..typing.
|
12
|
+
from ..typing._pydantic import (
|
13
13
|
Field,
|
14
14
|
FieldInfo,
|
15
15
|
PrivateAttr,
|
@@ -17,12 +17,14 @@ from ..typing.pydantic_ import (
|
|
17
17
|
field_validator,
|
18
18
|
model_validator,
|
19
19
|
)
|
20
|
-
from ..typing.
|
20
|
+
from ..typing._typing import Callable, Self
|
21
21
|
from .field_model import FieldModel
|
22
22
|
from .schema_model import SchemaModel
|
23
23
|
|
24
|
+
__all__ = ("ModelParams",)
|
24
25
|
|
25
|
-
|
26
|
+
|
27
|
+
class ModelParams(SchemaModel):
|
26
28
|
"""Configuration class for dynamically creating new Pydantic models."""
|
27
29
|
|
28
30
|
name: str | None = None
|
@@ -190,6 +192,3 @@ class NewModelParams(SchemaModel):
|
|
190
192
|
if self.frozen:
|
191
193
|
a.model_config["frozen"] = True
|
192
194
|
return a
|
193
|
-
|
194
|
-
|
195
|
-
__all__ = ["NewModelParams"]
|
lionagi/core/models/note.py
CHANGED
@@ -5,8 +5,8 @@
|
|
5
5
|
from lionagi.libs.parse import flatten, nget, ninsert, npop, nset, to_list
|
6
6
|
from lionagi.libs.utils import copy
|
7
7
|
|
8
|
-
from ..typing.
|
9
|
-
from ..typing.
|
8
|
+
from ..typing._pydantic import ConfigDict, Field, field_serializer
|
9
|
+
from ..typing._typing import (
|
10
10
|
UNDEFINED,
|
11
11
|
Any,
|
12
12
|
ItemsView,
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
from lionagi.libs.utils import is_same_dtype
|
6
6
|
|
7
|
-
from ..typing.
|
7
|
+
from ..typing._pydantic import (
|
8
8
|
ConfigDict,
|
9
9
|
Field,
|
10
10
|
FieldInfo,
|
@@ -12,8 +12,8 @@ from ..typing.pydantic_ import (
|
|
12
12
|
field_serializer,
|
13
13
|
field_validator,
|
14
14
|
)
|
15
|
-
from ..typing.
|
16
|
-
from .base import BaseAutoModel
|
15
|
+
from ..typing._typing import UNDEFINED, Any, TypeVar, override
|
16
|
+
from .base import BaseAutoModel
|
17
17
|
from .field_model import FieldModel
|
18
18
|
|
19
19
|
FIELD_NAME = TypeVar("FIELD_NAME", bound=str)
|
@@ -55,7 +55,11 @@ class OperableModel(BaseAutoModel):
|
|
55
55
|
"""
|
56
56
|
|
57
57
|
model_config = ConfigDict(
|
58
|
-
extra="forbid",
|
58
|
+
extra="forbid",
|
59
|
+
validate_default=False,
|
60
|
+
populate_by_name=True,
|
61
|
+
arbitrary_types_allowed=True,
|
62
|
+
use_enum_values=True,
|
59
63
|
)
|
60
64
|
|
61
65
|
extra_fields: dict[str, Any] = Field(default_factory=dict)
|
@@ -2,39 +2,20 @@
|
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
|
-
from ..typing.
|
6
|
-
from .base import BaseAutoModel
|
5
|
+
from ..typing._pydantic import ConfigDict
|
6
|
+
from .base import BaseAutoModel
|
7
7
|
|
8
|
+
__all__ = ("SchemaModel",)
|
8
9
|
|
9
|
-
class SchemaModel(BaseAutoModel):
|
10
|
-
"""Schema definition model with strict validation.
|
11
|
-
|
12
|
-
Extends BaseAutoModel to provide:
|
13
|
-
- Extra field forbidding
|
14
|
-
- Disabled default validation
|
15
|
-
- Field name listing
|
16
|
-
- Nested validation
|
17
|
-
|
18
|
-
Example:
|
19
|
-
```python
|
20
|
-
class UserSchema(SchemaModel):
|
21
|
-
name: str = Field(min_length=2)
|
22
|
-
age: int = Field(gt=0)
|
23
|
-
settings: dict[str, Any] = Field(default_factory=dict)
|
24
|
-
|
25
|
-
# Raises error - extra fields forbidden
|
26
|
-
user = UserSchema(name="John", age=30, extra="value")
|
27
|
-
```
|
28
10
|
|
29
|
-
|
30
|
-
model_config: Schema-specific configuration
|
31
|
-
- extra: "forbid" to prevent extra fields
|
32
|
-
- validate_default: False to skip default validation
|
33
|
-
- Plus inherited BaseAutoModel config
|
34
|
-
"""
|
11
|
+
class SchemaModel(BaseAutoModel):
|
35
12
|
|
36
13
|
model_config = ConfigDict(
|
37
|
-
extra="forbid",
|
14
|
+
extra="forbid",
|
15
|
+
validate_default=False,
|
16
|
+
populate_by_name=True,
|
17
|
+
arbitrary_types_allowed=True,
|
18
|
+
use_enum_values=True,
|
38
19
|
)
|
39
20
|
|
40
21
|
@classmethod
|
@@ -45,6 +26,3 @@ class SchemaModel(BaseAutoModel):
|
|
45
26
|
List of field names defined in model schema
|
46
27
|
"""
|
47
28
|
return list(cls.model_fields.keys())
|
48
|
-
|
49
|
-
|
50
|
-
__all__ = ["SchemaModel"]
|
lionagi/core/models/types.py
CHANGED
@@ -2,9 +2,18 @@
|
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
|
-
from .base import
|
6
|
-
from .field_model import
|
7
|
-
from .
|
8
|
-
from .note import
|
9
|
-
from .operable_model import
|
10
|
-
from .schema_model import
|
5
|
+
from .base import BaseAutoModel
|
6
|
+
from .field_model import FieldModel
|
7
|
+
from .model_params import ModelParams
|
8
|
+
from .note import Note
|
9
|
+
from .operable_model import OperableModel
|
10
|
+
from .schema_model import SchemaModel
|
11
|
+
|
12
|
+
__all__ = (
|
13
|
+
"BaseAutoModel",
|
14
|
+
"FieldModel",
|
15
|
+
"ModelParams",
|
16
|
+
"Note",
|
17
|
+
"OperableModel",
|
18
|
+
"SchemaModel",
|
19
|
+
)
|
lionagi/core/session/branch.py
CHANGED
@@ -9,7 +9,6 @@ from pydantic import model_validator
|
|
9
9
|
|
10
10
|
from lionagi.core.generic.types import Component, LogManager, Pile, Progression
|
11
11
|
from lionagi.core.typing import ID
|
12
|
-
from lionagi.integrations.litellm_.imodel import LiteiModel
|
13
12
|
from lionagi.protocols.operatives.instruct import Instruct, OperationInstruct
|
14
13
|
from lionagi.service import iModel
|
15
14
|
from lionagi.settings import Settings
|
@@ -25,8 +24,8 @@ class Branch(Component, BranchActionMixin, BranchOperationMixin):
|
|
25
24
|
name: str | None = None
|
26
25
|
msgs: MessageManager = None
|
27
26
|
acts: ActionManager = None
|
28
|
-
imodel: iModel |
|
29
|
-
parse_imodel: iModel |
|
27
|
+
imodel: iModel | None = None
|
28
|
+
parse_imodel: iModel | None = None
|
30
29
|
|
31
30
|
@model_validator(mode="before")
|
32
31
|
def _validate_data(cls, data: dict) -> dict:
|
@@ -42,29 +41,33 @@ class Branch(Component, BranchActionMixin, BranchOperationMixin):
|
|
42
41
|
)
|
43
42
|
if not message_manager.logger:
|
44
43
|
message_manager.logger = LogManager(
|
45
|
-
**Settings.Branch.BRANCH.message_log_config.to_dict(
|
44
|
+
**Settings.Branch.BRANCH.message_log_config.to_dict()
|
46
45
|
)
|
47
46
|
|
48
47
|
acts = data.pop("acts", None)
|
49
48
|
if not acts:
|
50
49
|
acts = ActionManager()
|
51
50
|
acts.logger = LogManager(
|
52
|
-
**Settings.Branch.BRANCH.action_log_config.to_dict(
|
51
|
+
**Settings.Branch.BRANCH.action_log_config.to_dict()
|
53
52
|
)
|
54
53
|
if "tools" in data:
|
55
54
|
acts.register_tools(data.pop("tools"))
|
56
55
|
|
57
56
|
imodel = data.pop(
|
58
57
|
"imodel",
|
59
|
-
|
58
|
+
iModel(**Settings.iModel.CHAT.to_dict()),
|
59
|
+
)
|
60
|
+
parse_imodel = data.pop(
|
61
|
+
"parse_imodel",
|
62
|
+
iModel(**Settings.iModel.PARSE.to_dict()),
|
60
63
|
)
|
61
|
-
|
62
64
|
out = {
|
63
65
|
"user": user,
|
64
66
|
"name": name,
|
65
67
|
"msgs": message_manager,
|
66
68
|
"acts": acts,
|
67
69
|
"imodel": imodel,
|
70
|
+
"parse_imodel": parse_imodel,
|
68
71
|
**data,
|
69
72
|
}
|
70
73
|
return out
|
@@ -14,13 +14,12 @@ from lionagi.core.typing import (
|
|
14
14
|
UNDEFINED,
|
15
15
|
BaseModel,
|
16
16
|
FieldModel,
|
17
|
-
|
17
|
+
ModelParams,
|
18
18
|
)
|
19
|
-
from lionagi.integrations.litellm_.imodel import LiteiModel
|
20
19
|
from lionagi.integrations.pydantic_ import break_down_pydantic_annotation
|
21
20
|
from lionagi.libs.func.types import alcall
|
22
21
|
from lionagi.libs.parse import to_json, validate_mapping
|
23
|
-
from lionagi.protocols.operatives import (
|
22
|
+
from lionagi.protocols.operatives.types import (
|
24
23
|
ActionRequestModel,
|
25
24
|
ActionResponseModel,
|
26
25
|
Operative,
|
@@ -108,7 +107,7 @@ class BranchOperationMixin(ABC):
|
|
108
107
|
recipient=None,
|
109
108
|
operative_model: type[BaseModel] = None,
|
110
109
|
progress=None,
|
111
|
-
imodel: iModel
|
110
|
+
imodel: iModel = None,
|
112
111
|
reason: bool = False,
|
113
112
|
actions: bool = False,
|
114
113
|
exclude_fields: list | dict | None = None,
|
@@ -120,15 +119,15 @@ class BranchOperationMixin(ABC):
|
|
120
119
|
images: list = None,
|
121
120
|
image_detail: Literal["low", "high", "auto"] = None,
|
122
121
|
max_retries: int = None,
|
123
|
-
retry_imodel: iModel
|
122
|
+
retry_imodel: iModel = None,
|
124
123
|
retry_kwargs: dict = {},
|
125
124
|
auto_retry_parse: bool = True,
|
126
125
|
field_models: list[FieldModel] | None = None,
|
127
126
|
skip_validation: bool = False,
|
128
127
|
tools: str | Tool | list[Tool | str] | bool = None,
|
129
|
-
request_params:
|
128
|
+
request_params: ModelParams = None,
|
130
129
|
request_param_kwargs: dict = {},
|
131
|
-
response_params:
|
130
|
+
response_params: ModelParams = None,
|
132
131
|
response_param_kwargs: dict = {},
|
133
132
|
**kwargs,
|
134
133
|
) -> list | BaseModel | None | dict | str:
|
@@ -269,7 +268,7 @@ class BranchOperationMixin(ABC):
|
|
269
268
|
request_fields=None,
|
270
269
|
request_model: type[BaseModel] = None,
|
271
270
|
progress=None,
|
272
|
-
imodel: iModel
|
271
|
+
imodel: iModel = None,
|
273
272
|
tool_schemas=None,
|
274
273
|
images: list = None,
|
275
274
|
image_detail: Literal["low", "high", "auto"] = None,
|
@@ -321,9 +320,9 @@ class BranchOperationMixin(ABC):
|
|
321
320
|
imodel = imodel or self.imodel
|
322
321
|
api_response = None
|
323
322
|
|
324
|
-
if
|
323
|
+
if not hasattr(imodel, "parse_to_data_model"):
|
325
324
|
api_response = await imodel.invoke(**kwargs)
|
326
|
-
|
325
|
+
else:
|
327
326
|
data_model = imodel.parse_to_data_model(**kwargs)
|
328
327
|
api_response = await imodel.invoke(**data_model)
|
329
328
|
|
@@ -344,12 +343,12 @@ class BranchOperationMixin(ABC):
|
|
344
343
|
progress: ID.IDSeq = None,
|
345
344
|
request_model: type[BaseModel] | BaseModel = None,
|
346
345
|
request_fields: dict | list[str] = None,
|
347
|
-
imodel: iModel
|
346
|
+
imodel: iModel = None,
|
348
347
|
images: list = None,
|
349
348
|
image_detail: Literal["low", "high", "auto"] = None,
|
350
349
|
tools: str | FUNCTOOL | list[FUNCTOOL | str] | bool = None,
|
351
350
|
num_parse_retries: int = 0,
|
352
|
-
retry_imodel: iModel
|
351
|
+
retry_imodel: iModel = None,
|
353
352
|
retry_kwargs: dict = {},
|
354
353
|
handle_validation: Literal[
|
355
354
|
"raise", "return_value", "return_none"
|
lionagi/core/session/session.py
CHANGED
@@ -8,7 +8,6 @@ import pandas as pd
|
|
8
8
|
|
9
9
|
from lionagi.core.generic.types import Component, Pile, Progression
|
10
10
|
from lionagi.core.typing import ID, Field, ItemNotFoundError, JsonValue
|
11
|
-
from lionagi.integrations.litellm_.imodel import LiteiModel
|
12
11
|
from lionagi.libs.parse import to_list
|
13
12
|
from lionagi.service import iModel
|
14
13
|
|
@@ -39,7 +38,7 @@ class Session(Component):
|
|
39
38
|
system_datetime: bool | str = None,
|
40
39
|
user: ID.SenderRecipient = None,
|
41
40
|
name: str | None = None,
|
42
|
-
imodel: iModel |
|
41
|
+
imodel: iModel | None = None,
|
43
42
|
messages: Pile[RoledMessage] = None,
|
44
43
|
progress: Progression = None,
|
45
44
|
tool_manager: ActionManager = None,
|
lionagi/core/typing/__init__.py
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
5
|
from ..models import *
|
6
|
-
from .
|
7
|
-
from .
|
8
|
-
from .
|
9
|
-
from .
|
6
|
+
from ._concepts import *
|
7
|
+
from ._id import *
|
8
|
+
from ._pydantic import *
|
9
|
+
from ._typing import *
|
@@ -2,19 +2,59 @@
|
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
|
+
from __future__ import annotations
|
6
|
+
|
7
|
+
import uuid
|
5
8
|
from abc import ABC, abstractmethod
|
9
|
+
from dataclasses import dataclass
|
6
10
|
from typing import Any, Generic, TypeVar
|
7
11
|
|
12
|
+
from lionagi.settings import Settings
|
13
|
+
|
14
|
+
|
15
|
+
class IDType:
|
16
|
+
|
17
|
+
def __init__(self, _id: uuid.UUID):
|
18
|
+
self._id = _id
|
19
|
+
|
20
|
+
@classmethod
|
21
|
+
def validate(cls, value) -> IDType:
|
22
|
+
if isinstance(value, cls):
|
23
|
+
return value
|
24
|
+
if isinstance(value, str | int):
|
25
|
+
try:
|
26
|
+
_id = uuid.UUID(value, version=Settings.Config.UUID_VERSION)
|
27
|
+
return cls(_id=_id)
|
28
|
+
except Exception as e:
|
29
|
+
raise ValueError(f"Invalid IDType value: {value}") from e
|
30
|
+
raise ValueError(f"Invalid IDType value: {value}")
|
31
|
+
|
32
|
+
def __str__(self):
|
33
|
+
return str(self._id)
|
34
|
+
|
35
|
+
def __repr__(self):
|
36
|
+
return f"{self.__class__.__name__}({self._id})"
|
37
|
+
|
38
|
+
def __hash__(self):
|
39
|
+
return hash(self._id)
|
40
|
+
|
41
|
+
def __eq__(self, other):
|
42
|
+
if not isinstance(other, IDType):
|
43
|
+
return False
|
44
|
+
return self._id == other._id
|
45
|
+
|
46
|
+
__slots__ = ("_id",)
|
47
|
+
|
8
48
|
|
9
49
|
class Observable(ABC):
|
10
50
|
"""
|
11
51
|
Abstract base class for objects that can be uniquely identified and tracked.
|
12
52
|
|
13
|
-
All Observable objects must have a unique identifier (
|
53
|
+
All Observable objects must have a unique identifier (id) that allows them
|
14
54
|
to be tracked and referenced within the Lion system.
|
15
55
|
"""
|
16
56
|
|
17
|
-
ln_id:
|
57
|
+
ln_id: IDType
|
18
58
|
|
19
59
|
|
20
60
|
T = TypeVar("T", bound=Observable)
|
@@ -129,4 +169,5 @@ __all__ = [
|
|
129
169
|
"Condition",
|
130
170
|
"Structure",
|
131
171
|
"RelationError",
|
172
|
+
"IDType",
|
132
173
|
]
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# Copyright (c) 2023 - 2024, HaiyangLi <quantocean.li at gmail dot com>
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
4
|
+
|
5
|
+
from __future__ import annotations
|
6
|
+
|
7
|
+
import uuid
|
8
|
+
|
9
|
+
from lionagi.settings import Settings
|
10
|
+
|
11
|
+
from ._concepts import (
|
12
|
+
Container,
|
13
|
+
Generic,
|
14
|
+
IDType,
|
15
|
+
ItemError,
|
16
|
+
Observable,
|
17
|
+
Ordering,
|
18
|
+
T,
|
19
|
+
)
|
20
|
+
from ._typing import Container, Mapping, Sequence, TypeAlias
|
21
|
+
|
22
|
+
|
23
|
+
class IDError(ItemError):
|
24
|
+
"""Exception raised when an item does not have a Lion ID."""
|
25
|
+
|
26
|
+
def __init__(
|
27
|
+
self,
|
28
|
+
message: str = "Item must contain a Lion ID.",
|
29
|
+
item_id: str | None = None,
|
30
|
+
):
|
31
|
+
super().__init__(message, item_id)
|
32
|
+
|
33
|
+
|
34
|
+
class ID(Generic[T]):
|
35
|
+
"""
|
36
|
+
A generic class that provides ID-related functionality for Observable objects.
|
37
|
+
|
38
|
+
This class handles the generation, validation, and management of unique identifiers
|
39
|
+
within the Lion system. It provides type aliases for various ID-related operations
|
40
|
+
and methods for working with IDs.
|
41
|
+
"""
|
42
|
+
|
43
|
+
# For functions that accept either ID or item
|
44
|
+
Ref: TypeAlias = IDType | T # type: ignore
|
45
|
+
|
46
|
+
# For functions requiring just the ID
|
47
|
+
ID: TypeAlias = IDType
|
48
|
+
|
49
|
+
# For functions requiring Observable object
|
50
|
+
Item = T # type: ignore
|
51
|
+
|
52
|
+
# For collections
|
53
|
+
IDSeq: TypeAlias = list[IDType] | Ordering
|
54
|
+
ItemSeq: TypeAlias = ( # type: ignore
|
55
|
+
Sequence[T] | Mapping[IDType, T] | Container[IDType | T]
|
56
|
+
)
|
57
|
+
RefSeq: TypeAlias = IDSeq | ItemSeq
|
58
|
+
|
59
|
+
# For system-level interactions
|
60
|
+
SenderRecipient: TypeAlias = IDType | T | str # type: ignore
|
61
|
+
|
62
|
+
@staticmethod
|
63
|
+
def id():
|
64
|
+
return IDType(
|
65
|
+
_id=getattr(uuid, f"uuid{Settings.Config.UUID_VERSION}")()
|
66
|
+
)
|
67
|
+
|
68
|
+
@staticmethod
|
69
|
+
def get_id(item, /) -> IDType:
|
70
|
+
|
71
|
+
if isinstance(item, Observable):
|
72
|
+
return item.ln_id
|
73
|
+
try:
|
74
|
+
return IDType.validate(item)
|
75
|
+
except ValueError as e:
|
76
|
+
raise IDError(
|
77
|
+
f"The input object of type <{type(item).__name__}> does "
|
78
|
+
"not contain or is not a valid Lion ID. Item must be an instance"
|
79
|
+
" of `Observable` or a valid `id`."
|
80
|
+
) from e
|
81
|
+
|
82
|
+
@staticmethod
|
83
|
+
def is_id(item, /) -> bool:
|
84
|
+
"""
|
85
|
+
Check if an item is or contains a valid Lion ID.
|
86
|
+
|
87
|
+
Args:
|
88
|
+
item: The item to check.
|
89
|
+
config: Configuration dictionary for ID validation.
|
90
|
+
|
91
|
+
Returns:
|
92
|
+
True if the item is a valid Lion ID, False otherwise.
|
93
|
+
"""
|
94
|
+
try:
|
95
|
+
ID.get_id(item)
|
96
|
+
return True
|
97
|
+
except IDError:
|
98
|
+
return False
|
99
|
+
|
100
|
+
|
101
|
+
__all__ = [
|
102
|
+
"ID",
|
103
|
+
"IDError",
|
104
|
+
]
|
@@ -4,7 +4,6 @@
|
|
4
4
|
|
5
5
|
from pathlib import Path
|
6
6
|
|
7
|
-
import yaml
|
8
7
|
from dotenv import load_dotenv
|
9
8
|
from pydantic import (
|
10
9
|
BaseModel,
|
@@ -34,6 +33,12 @@ price_config_file_name = path / "anthropic_price_data.yaml"
|
|
34
33
|
max_output_token_file_name = path / "anthropic_max_output_token_data.yaml"
|
35
34
|
|
36
35
|
|
36
|
+
class _ModuleImportClass:
|
37
|
+
from lionagi.libs.package.imports import check_import
|
38
|
+
|
39
|
+
yaml = check_import("yaml", pip_name="pyyaml")
|
40
|
+
|
41
|
+
|
37
42
|
class AnthropicModel(BaseModel):
|
38
43
|
model: str = Field(description="ID of the model to use.")
|
39
44
|
|
@@ -234,7 +239,7 @@ class AnthropicModel(BaseModel):
|
|
234
239
|
)
|
235
240
|
if estimated_output_len == 0:
|
236
241
|
with open(max_output_token_file_name) as file:
|
237
|
-
output_token_config = yaml.safe_load(file)
|
242
|
+
output_token_config = _ModuleImportClass.yaml.safe_load(file)
|
238
243
|
estimated_output_len = output_token_config.get(self.model, 0)
|
239
244
|
self.estimated_output_len = estimated_output_len
|
240
245
|
|
@@ -256,7 +261,7 @@ class AnthropicModel(BaseModel):
|
|
256
261
|
num_of_input_tokens = self.text_token_calculator.calculate(input_text)
|
257
262
|
|
258
263
|
with open(price_config_file_name) as file:
|
259
|
-
price_config = yaml.safe_load(file)
|
264
|
+
price_config = _ModuleImportClass.yaml.safe_load(file)
|
260
265
|
|
261
266
|
model_price_info_dict = price_config["model"][self.model]
|
262
267
|
estimated_price = (
|
@@ -5,7 +5,6 @@
|
|
5
5
|
import warnings
|
6
6
|
from pathlib import Path
|
7
7
|
|
8
|
-
import yaml
|
9
8
|
from dotenv import load_dotenv
|
10
9
|
from pydantic import (
|
11
10
|
BaseModel,
|
@@ -34,6 +33,12 @@ max_output_token_file_name = path / "groq_max_output_token_data.yaml"
|
|
34
33
|
rate_limits_file_name = path / "groq_rate_limits.yaml"
|
35
34
|
|
36
35
|
|
36
|
+
class _ModuleImportClass:
|
37
|
+
from lionagi.libs.package.imports import check_import
|
38
|
+
|
39
|
+
yaml = check_import("yaml", pip_name="pyyaml")
|
40
|
+
|
41
|
+
|
37
42
|
class GroqModel(BaseModel):
|
38
43
|
model: str = Field(description="ID of the model to use.")
|
39
44
|
request_model: GroqRequest = Field(description="Making requests")
|
@@ -67,7 +72,7 @@ class GroqModel(BaseModel):
|
|
67
72
|
# Load rate limits from YAML
|
68
73
|
try:
|
69
74
|
with open(rate_limits_file_name) as file:
|
70
|
-
rate_limits = yaml.safe_load(file)
|
75
|
+
rate_limits = _ModuleImportClass.yaml.safe_load(file)
|
71
76
|
model_name = data.get("model")
|
72
77
|
model_limits = None
|
73
78
|
|
@@ -261,7 +266,9 @@ class GroqModel(BaseModel):
|
|
261
266
|
if estimated_output_len == 0:
|
262
267
|
try:
|
263
268
|
with open(max_output_token_file_name) as file:
|
264
|
-
output_token_config = yaml.safe_load(
|
269
|
+
output_token_config = _ModuleImportClass.yaml.safe_load(
|
270
|
+
file
|
271
|
+
)
|
265
272
|
estimated_output_len = output_token_config.get(
|
266
273
|
self.model, 2048
|
267
274
|
) # Default to 2048
|
@@ -297,7 +304,7 @@ class GroqModel(BaseModel):
|
|
297
304
|
|
298
305
|
try:
|
299
306
|
with open(price_config_file_name) as file:
|
300
|
-
price_config = yaml.safe_load(file)
|
307
|
+
price_config = _ModuleImportClass.yaml.safe_load(file)
|
301
308
|
except FileNotFoundError:
|
302
309
|
raise ValueError(
|
303
310
|
f"Price config file not found: {price_config_file_name}"
|