lionagi 0.17.11__py3-none-any.whl → 0.18.1__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/_errors.py +0 -5
- lionagi/fields.py +83 -0
- lionagi/libs/schema/minimal_yaml.py +98 -0
- lionagi/ln/__init__.py +3 -1
- lionagi/ln/concurrency/primitives.py +4 -4
- lionagi/ln/concurrency/task.py +1 -0
- lionagi/ln/types.py +32 -5
- lionagi/models/field_model.py +21 -4
- lionagi/models/hashable_model.py +2 -3
- lionagi/operations/ReAct/ReAct.py +475 -238
- lionagi/operations/ReAct/utils.py +3 -0
- lionagi/operations/act/act.py +206 -0
- lionagi/operations/builder.py +5 -7
- lionagi/operations/chat/chat.py +130 -114
- lionagi/operations/communicate/communicate.py +101 -42
- lionagi/operations/fields.py +380 -0
- lionagi/operations/flow.py +8 -10
- lionagi/operations/interpret/interpret.py +65 -20
- lionagi/operations/node.py +4 -4
- lionagi/operations/operate/operate.py +216 -108
- lionagi/{protocols/operatives → operations/operate}/operative.py +4 -5
- lionagi/{protocols/operatives → operations/operate}/step.py +34 -39
- lionagi/operations/parse/parse.py +170 -142
- lionagi/operations/select/select.py +79 -18
- lionagi/operations/select/utils.py +8 -2
- lionagi/operations/types.py +119 -23
- lionagi/protocols/action/manager.py +5 -6
- lionagi/protocols/contracts.py +2 -2
- lionagi/protocols/generic/__init__.py +22 -0
- lionagi/protocols/generic/element.py +36 -127
- lionagi/protocols/generic/log.py +3 -2
- lionagi/protocols/generic/pile.py +9 -10
- lionagi/protocols/generic/progression.py +23 -22
- lionagi/protocols/graph/edge.py +6 -5
- lionagi/protocols/ids.py +6 -49
- lionagi/protocols/messages/__init__.py +29 -0
- lionagi/protocols/messages/action_request.py +86 -184
- lionagi/protocols/messages/action_response.py +73 -131
- lionagi/protocols/messages/assistant_response.py +130 -159
- lionagi/protocols/messages/base.py +31 -22
- lionagi/protocols/messages/instruction.py +280 -625
- lionagi/protocols/messages/manager.py +112 -62
- lionagi/protocols/messages/message.py +87 -197
- lionagi/protocols/messages/system.py +52 -123
- lionagi/protocols/types.py +1 -13
- lionagi/service/connections/__init__.py +3 -0
- lionagi/service/connections/endpoint.py +0 -8
- lionagi/service/connections/providers/claude_code_cli.py +3 -2
- lionagi/service/connections/providers/oai_.py +29 -94
- lionagi/service/connections/providers/ollama_.py +3 -2
- lionagi/service/hooks/_types.py +1 -1
- lionagi/service/hooks/_utils.py +1 -1
- lionagi/service/hooks/hook_event.py +3 -8
- lionagi/service/hooks/hook_registry.py +5 -5
- lionagi/service/hooks/hooked_event.py +63 -3
- lionagi/service/imodel.py +24 -20
- lionagi/service/third_party/claude_code.py +3 -3
- lionagi/service/third_party/openai_models.py +435 -0
- lionagi/service/token_calculator.py +1 -94
- lionagi/session/branch.py +190 -400
- lionagi/session/session.py +8 -99
- lionagi/tools/file/reader.py +2 -2
- lionagi/version.py +1 -1
- {lionagi-0.17.11.dist-info → lionagi-0.18.1.dist-info}/METADATA +6 -6
- lionagi-0.18.1.dist-info/RECORD +164 -0
- lionagi/fields/__init__.py +0 -47
- lionagi/fields/action.py +0 -188
- lionagi/fields/base.py +0 -153
- lionagi/fields/code.py +0 -239
- lionagi/fields/file.py +0 -234
- lionagi/fields/instruct.py +0 -135
- lionagi/fields/reason.py +0 -55
- lionagi/fields/research.py +0 -52
- lionagi/operations/_act/act.py +0 -86
- lionagi/operations/brainstorm/__init__.py +0 -2
- lionagi/operations/brainstorm/brainstorm.py +0 -498
- lionagi/operations/brainstorm/prompt.py +0 -11
- lionagi/operations/instruct/__init__.py +0 -2
- lionagi/operations/instruct/instruct.py +0 -28
- lionagi/operations/plan/__init__.py +0 -6
- lionagi/operations/plan/plan.py +0 -386
- lionagi/operations/plan/prompt.py +0 -25
- lionagi/operations/utils.py +0 -45
- lionagi/protocols/forms/__init__.py +0 -2
- lionagi/protocols/forms/base.py +0 -85
- lionagi/protocols/forms/flow.py +0 -79
- lionagi/protocols/forms/form.py +0 -86
- lionagi/protocols/forms/report.py +0 -48
- lionagi/protocols/mail/__init__.py +0 -2
- lionagi/protocols/mail/exchange.py +0 -220
- lionagi/protocols/mail/mail.py +0 -51
- lionagi/protocols/mail/mailbox.py +0 -103
- lionagi/protocols/mail/manager.py +0 -218
- lionagi/protocols/mail/package.py +0 -101
- lionagi/protocols/messages/templates/README.md +0 -28
- lionagi/protocols/messages/templates/action_request.jinja2 +0 -5
- lionagi/protocols/messages/templates/action_response.jinja2 +0 -9
- lionagi/protocols/messages/templates/assistant_response.jinja2 +0 -6
- lionagi/protocols/messages/templates/instruction_message.jinja2 +0 -61
- lionagi/protocols/messages/templates/system_message.jinja2 +0 -11
- lionagi/protocols/messages/templates/tool_schemas.jinja2 +0 -7
- lionagi/protocols/operatives/__init__.py +0 -2
- lionagi/service/connections/providers/types.py +0 -28
- lionagi/service/third_party/openai_model_names.py +0 -198
- lionagi/service/types.py +0 -58
- lionagi-0.17.11.dist-info/RECORD +0 -199
- /lionagi/operations/{_act → act}/__init__.py +0 -0
- {lionagi-0.17.11.dist-info → lionagi-0.18.1.dist-info}/WHEEL +0 -0
- {lionagi-0.17.11.dist-info → lionagi-0.18.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
import logging
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
8
9
|
from lionagi.protocols._concepts import Manager
|
|
9
10
|
from lionagi.protocols.messages.action_request import ActionRequest
|
|
10
11
|
from lionagi.utils import to_list
|
|
@@ -121,7 +122,7 @@ class ActionManager(Manager):
|
|
|
121
122
|
self.register_tool(t, update=update)
|
|
122
123
|
|
|
123
124
|
def match_tool(
|
|
124
|
-
self, action_request: ActionRequest |
|
|
125
|
+
self, action_request: ActionRequest | BaseModel | dict
|
|
125
126
|
) -> FunctionCalling:
|
|
126
127
|
"""
|
|
127
128
|
Convert an ActionRequest (or dict with "function"/"arguments")
|
|
@@ -134,9 +135,7 @@ class ActionManager(Manager):
|
|
|
134
135
|
Returns:
|
|
135
136
|
FunctionCalling: The event object that can be invoked.
|
|
136
137
|
"""
|
|
137
|
-
if not isinstance(
|
|
138
|
-
action_request, ActionRequest | ActionRequestModel | dict
|
|
139
|
-
):
|
|
138
|
+
if not isinstance(action_request, ActionRequest | BaseModel | dict):
|
|
140
139
|
raise TypeError(f"Unsupported type {type(action_request)}")
|
|
141
140
|
|
|
142
141
|
func, args = None, None
|
|
@@ -155,7 +154,7 @@ class ActionManager(Manager):
|
|
|
155
154
|
|
|
156
155
|
async def invoke(
|
|
157
156
|
self,
|
|
158
|
-
func_call:
|
|
157
|
+
func_call: BaseModel | ActionRequest,
|
|
159
158
|
) -> FunctionCalling:
|
|
160
159
|
"""
|
|
161
160
|
High-level API to parse and run a function call.
|
lionagi/protocols/contracts.py
CHANGED
|
@@ -24,7 +24,7 @@ class ObservableProto(Protocol):
|
|
|
24
24
|
|
|
25
25
|
This protocol defines the minimal contract for observable objects:
|
|
26
26
|
they must have an 'id' property. The return type is permissive (Any)
|
|
27
|
-
to maintain compatibility with V0's
|
|
27
|
+
to maintain compatibility with V0's UUID wrapper while enabling
|
|
28
28
|
V1 evolution.
|
|
29
29
|
|
|
30
30
|
All V0 Element subclasses automatically satisfy this protocol without
|
|
@@ -33,7 +33,7 @@ class ObservableProto(Protocol):
|
|
|
33
33
|
|
|
34
34
|
@property
|
|
35
35
|
def id(self) -> object:
|
|
36
|
-
"""Unique identifier. Accepts
|
|
36
|
+
"""Unique identifier. Accepts UUID, UUID, or string."""
|
|
37
37
|
...
|
|
38
38
|
|
|
39
39
|
|
|
@@ -1,2 +1,24 @@
|
|
|
1
1
|
# Copyright (c) 2023-2025, HaiyangLi <quantocean.li at gmail dot com>
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
from .element import ID, Element
|
|
5
|
+
from .event import Event, EventStatus, Execution
|
|
6
|
+
from .log import DataLogger, DataLoggerConfig, Log
|
|
7
|
+
from .pile import Pile
|
|
8
|
+
from .processor import Executor, Processor
|
|
9
|
+
from .progression import Progression
|
|
10
|
+
|
|
11
|
+
__all__ = (
|
|
12
|
+
"Element",
|
|
13
|
+
"ID",
|
|
14
|
+
"Event",
|
|
15
|
+
"Execution",
|
|
16
|
+
"Log",
|
|
17
|
+
"DataLogger",
|
|
18
|
+
"DataLoggerConfig",
|
|
19
|
+
"Pile",
|
|
20
|
+
"Progression",
|
|
21
|
+
"Processor",
|
|
22
|
+
"Executor",
|
|
23
|
+
"EventStatus",
|
|
24
|
+
)
|
|
@@ -19,98 +19,16 @@ from pydantic import (
|
|
|
19
19
|
|
|
20
20
|
from lionagi import ln
|
|
21
21
|
from lionagi._class_registry import get_class
|
|
22
|
-
from lionagi._errors import IDError
|
|
23
22
|
from lionagi.utils import import_module, to_dict
|
|
24
23
|
|
|
25
24
|
from .._concepts import Collective, Observable, Ordering
|
|
26
25
|
|
|
27
26
|
__all__ = (
|
|
28
|
-
"IDType",
|
|
29
27
|
"Element",
|
|
30
|
-
"ID",
|
|
31
28
|
"validate_order",
|
|
32
|
-
"DEFAULT_ELEMENT_SERIALIZER",
|
|
33
29
|
)
|
|
34
30
|
|
|
35
31
|
|
|
36
|
-
class IDType:
|
|
37
|
-
"""Represents a UUIDv4-based identifier.
|
|
38
|
-
|
|
39
|
-
This class wraps a UUID object and provides helper methods for
|
|
40
|
-
validating and creating UUID version 4. It also implements equality
|
|
41
|
-
and hashing so that it can be used as dictionary keys or in sets.
|
|
42
|
-
|
|
43
|
-
Attributes:
|
|
44
|
-
_id (UUID): The wrapped UUID object.
|
|
45
|
-
"""
|
|
46
|
-
|
|
47
|
-
__slots__ = ("_id",)
|
|
48
|
-
|
|
49
|
-
def __init__(self, id: UUID) -> None:
|
|
50
|
-
"""Initializes an IDType instance."""
|
|
51
|
-
self._id = id
|
|
52
|
-
|
|
53
|
-
@classmethod
|
|
54
|
-
def validate(cls, value: str | UUID | IDType) -> IDType:
|
|
55
|
-
"""Validates and converts a value into an IDType.
|
|
56
|
-
|
|
57
|
-
Returns:
|
|
58
|
-
IDType: The validated IDType object.
|
|
59
|
-
|
|
60
|
-
Raises:
|
|
61
|
-
IDError: If the provided value is not a valid UUIDv4.
|
|
62
|
-
"""
|
|
63
|
-
if isinstance(value, IDType):
|
|
64
|
-
return value
|
|
65
|
-
try:
|
|
66
|
-
return cls(UUID(str(value), version=4))
|
|
67
|
-
except ValueError:
|
|
68
|
-
raise IDError(f"Invalid ID: {value}") from None
|
|
69
|
-
|
|
70
|
-
@classmethod
|
|
71
|
-
def create(cls) -> IDType:
|
|
72
|
-
"""Creates a new IDType with a randomly generated UUIDv4.
|
|
73
|
-
|
|
74
|
-
Returns:
|
|
75
|
-
IDType: A new IDType instance with a random UUIDv4.
|
|
76
|
-
"""
|
|
77
|
-
return cls(uuid4())
|
|
78
|
-
|
|
79
|
-
def __str__(self) -> str:
|
|
80
|
-
"""Returns the string representation of the underlying UUID.
|
|
81
|
-
|
|
82
|
-
Returns:
|
|
83
|
-
str: The string form of this IDType's UUID.
|
|
84
|
-
"""
|
|
85
|
-
return str(self._id)
|
|
86
|
-
|
|
87
|
-
def __repr__(self) -> str:
|
|
88
|
-
"""Returns the unambiguous string representation of this IDType.
|
|
89
|
-
|
|
90
|
-
Returns:
|
|
91
|
-
str: A developer-friendly string for debugging.
|
|
92
|
-
"""
|
|
93
|
-
return f"IDType({self._id})"
|
|
94
|
-
|
|
95
|
-
def __eq__(self, other: Any) -> bool:
|
|
96
|
-
"""Checks equality with another IDType based on UUID value.
|
|
97
|
-
|
|
98
|
-
Returns:
|
|
99
|
-
bool: True if both have the same underlying UUID; False otherwise.
|
|
100
|
-
"""
|
|
101
|
-
if not isinstance(other, IDType):
|
|
102
|
-
return NotImplemented
|
|
103
|
-
return self._id == other._id
|
|
104
|
-
|
|
105
|
-
def __hash__(self) -> int:
|
|
106
|
-
"""Returns a hash based on the underlying UUID.
|
|
107
|
-
|
|
108
|
-
Returns:
|
|
109
|
-
int: The hash of this object, allowing IDType to be dictionary keys.
|
|
110
|
-
"""
|
|
111
|
-
return hash(self._id)
|
|
112
|
-
|
|
113
|
-
|
|
114
32
|
class Element(BaseModel, Observable):
|
|
115
33
|
"""Basic identifiable, timestamped element.
|
|
116
34
|
|
|
@@ -119,7 +37,7 @@ class Element(BaseModel, Observable):
|
|
|
119
37
|
dictionary.
|
|
120
38
|
|
|
121
39
|
Attributes:
|
|
122
|
-
id (
|
|
40
|
+
id (UUID):
|
|
123
41
|
A unique ID based on UUIDv4 (defaults to a newly generated one).
|
|
124
42
|
created_at (float):
|
|
125
43
|
The creation timestamp as a float (Unix epoch). Defaults to
|
|
@@ -135,8 +53,8 @@ class Element(BaseModel, Observable):
|
|
|
135
53
|
extra="forbid",
|
|
136
54
|
)
|
|
137
55
|
|
|
138
|
-
id:
|
|
139
|
-
default_factory=
|
|
56
|
+
id: UUID = Field(
|
|
57
|
+
default_factory=uuid4,
|
|
140
58
|
title="ID",
|
|
141
59
|
description="Unique identifier for this element.",
|
|
142
60
|
frozen=True,
|
|
@@ -211,12 +129,14 @@ class Element(BaseModel, Observable):
|
|
|
211
129
|
raise ValueError(f"Invalid created_at: {val}") from None
|
|
212
130
|
|
|
213
131
|
@field_validator("id", mode="before")
|
|
214
|
-
def
|
|
215
|
-
"""Ensures `id` is validated as an
|
|
216
|
-
|
|
132
|
+
def _ensure_UUID(cls, val: UUID | str) -> UUID:
|
|
133
|
+
"""Ensures `id` is validated as an UUID."""
|
|
134
|
+
if isinstance(val, UUID):
|
|
135
|
+
return val
|
|
136
|
+
return UUID(str(val))
|
|
217
137
|
|
|
218
138
|
@field_serializer("id")
|
|
219
|
-
def _serialize_id_type(self, val:
|
|
139
|
+
def _serialize_id_type(self, val: UUID) -> str:
|
|
220
140
|
"""Serializes the `id` field to a string."""
|
|
221
141
|
return str(val)
|
|
222
142
|
|
|
@@ -328,28 +248,27 @@ class Element(BaseModel, Observable):
|
|
|
328
248
|
|
|
329
249
|
|
|
330
250
|
DEFAULT_ELEMENT_SERIALIZER = ln.get_orjson_default(
|
|
331
|
-
order=[
|
|
251
|
+
order=[Element, BaseModel],
|
|
332
252
|
additional={
|
|
333
|
-
IDType: lambda o: str(o),
|
|
334
253
|
Element: lambda o: o.to_dict(),
|
|
335
254
|
BaseModel: lambda o: o.model_dump(mode="json"),
|
|
336
255
|
},
|
|
337
256
|
)
|
|
338
257
|
|
|
339
258
|
|
|
340
|
-
def validate_order(order: Any) -> list[
|
|
341
|
-
"""Validates and flattens an ordering into a list of
|
|
259
|
+
def validate_order(order: Any) -> list[UUID]:
|
|
260
|
+
"""Validates and flattens an ordering into a list of UUID objects.
|
|
342
261
|
|
|
343
262
|
This function accepts a variety of possible representations for ordering
|
|
344
263
|
(e.g., a single Element, a list of Elements, a dictionary with ID keys,
|
|
345
|
-
or a nested structure) and returns a flat list of
|
|
264
|
+
or a nested structure) and returns a flat list of UUID objects.
|
|
346
265
|
|
|
347
266
|
Returns:
|
|
348
|
-
list[
|
|
267
|
+
list[UUID]: A flat list of validated UUID objects.
|
|
349
268
|
|
|
350
269
|
Raises:
|
|
351
270
|
ValueError: If an invalid item is encountered or if there's a mixture
|
|
352
|
-
of types not all convertible to
|
|
271
|
+
of types not all convertible to UUID.
|
|
353
272
|
"""
|
|
354
273
|
if isinstance(order, Element):
|
|
355
274
|
return [order.id]
|
|
@@ -357,89 +276,79 @@ def validate_order(order: Any) -> list[IDType]:
|
|
|
357
276
|
order = list(order.keys())
|
|
358
277
|
|
|
359
278
|
stack = [order]
|
|
360
|
-
out: list[
|
|
279
|
+
out: list[UUID] = []
|
|
361
280
|
while stack:
|
|
362
281
|
cur = stack.pop()
|
|
363
282
|
if cur is None:
|
|
364
283
|
continue
|
|
365
284
|
if isinstance(cur, Element):
|
|
366
285
|
out.append(cur.id)
|
|
367
|
-
elif isinstance(cur, IDType):
|
|
368
|
-
out.append(cur)
|
|
369
286
|
elif isinstance(cur, UUID):
|
|
370
|
-
out.append(
|
|
287
|
+
out.append(cur)
|
|
371
288
|
elif isinstance(cur, str):
|
|
372
|
-
out.append(
|
|
289
|
+
out.append(UUID(cur))
|
|
373
290
|
elif isinstance(cur, (list, tuple, set)):
|
|
374
291
|
stack.extend(reversed(cur))
|
|
375
292
|
else:
|
|
376
293
|
raise ValueError("Invalid item in order.")
|
|
377
294
|
|
|
378
|
-
if not out
|
|
379
|
-
return []
|
|
380
|
-
|
|
381
|
-
# Check for consistent IDType usage
|
|
382
|
-
first_type = type(out[0])
|
|
383
|
-
if first_type is IDType:
|
|
384
|
-
for item in out:
|
|
385
|
-
if not isinstance(item, IDType):
|
|
386
|
-
raise ValueError("Mixed types in order.")
|
|
387
|
-
return out
|
|
388
|
-
raise ValueError("Unrecognized type(s) in order.")
|
|
295
|
+
return [] if not out else out
|
|
389
296
|
|
|
390
297
|
|
|
391
298
|
E = TypeVar("E", bound=Element)
|
|
392
299
|
|
|
393
300
|
|
|
394
301
|
class ID(Generic[E]):
|
|
395
|
-
"""Utility class for working with
|
|
302
|
+
"""Utility class for working with UUID objects and Elements.
|
|
396
303
|
|
|
397
304
|
This class provides helper methods to extract IDs from Elements, strings,
|
|
398
305
|
or UUIDs, and to test whether a given object can be interpreted as
|
|
399
306
|
an ID.
|
|
400
307
|
"""
|
|
401
308
|
|
|
402
|
-
ID: TypeAlias =
|
|
309
|
+
ID: TypeAlias = UUID
|
|
403
310
|
Item: TypeAlias = E | Element # type: ignore
|
|
404
|
-
Ref: TypeAlias =
|
|
405
|
-
IDSeq: TypeAlias = Sequence[
|
|
311
|
+
Ref: TypeAlias = UUID | E | str # type: ignore
|
|
312
|
+
IDSeq: TypeAlias = Sequence[UUID] | Ordering[E] # type: ignore
|
|
406
313
|
ItemSeq: TypeAlias = Sequence[E] | Collective[E] # type: ignore
|
|
407
314
|
RefSeq: TypeAlias = ItemSeq | Sequence[Ref] | Ordering[E] # type: ignore
|
|
408
315
|
|
|
409
316
|
@staticmethod
|
|
410
|
-
def get_id(item: E) ->
|
|
411
|
-
"""Retrieves an
|
|
317
|
+
def get_id(item: E) -> UUID:
|
|
318
|
+
"""Retrieves an UUID from multiple possible item forms.
|
|
412
319
|
|
|
413
320
|
Acceptable item types include:
|
|
414
321
|
- Element: Uses its `id` attribute.
|
|
415
|
-
-
|
|
322
|
+
- UUID: Returns it directly.
|
|
416
323
|
- UUID: Validates and wraps it.
|
|
417
324
|
- str: Interpreted as a UUID if possible.
|
|
418
325
|
|
|
419
326
|
Returns:
|
|
420
|
-
|
|
327
|
+
UUID: The validated ID.
|
|
421
328
|
|
|
422
329
|
Raises:
|
|
423
|
-
ValueError: If the item cannot be converted to an
|
|
330
|
+
ValueError: If the item cannot be converted to an UUID.
|
|
424
331
|
"""
|
|
332
|
+
if isinstance(item, UUID):
|
|
333
|
+
return item
|
|
425
334
|
if isinstance(item, Element):
|
|
426
335
|
return item.id
|
|
427
|
-
if isinstance(item,
|
|
428
|
-
return
|
|
336
|
+
if isinstance(item, str):
|
|
337
|
+
return UUID(item)
|
|
429
338
|
raise ValueError("Cannot get ID from item.")
|
|
430
339
|
|
|
431
340
|
@staticmethod
|
|
432
341
|
def is_id(item: Any) -> bool:
|
|
433
|
-
"""Checks if an item can be validated as an
|
|
342
|
+
"""Checks if an item can be validated as an UUID.
|
|
434
343
|
|
|
435
344
|
Returns:
|
|
436
|
-
bool: True if `item` is or can be validated as an
|
|
345
|
+
bool: True if `item` is or can be validated as an UUID;
|
|
437
346
|
otherwise, False.
|
|
438
347
|
"""
|
|
439
348
|
try:
|
|
440
|
-
|
|
349
|
+
ID.get_id(item) # type: ignore
|
|
441
350
|
return True
|
|
442
|
-
except
|
|
351
|
+
except ValueError:
|
|
443
352
|
return False
|
|
444
353
|
|
|
445
354
|
|
lionagi/protocols/generic/log.py
CHANGED
|
@@ -143,10 +143,11 @@ class DataLogger:
|
|
|
143
143
|
if self._config.auto_save_on_exit:
|
|
144
144
|
atexit.register(self.save_at_exit)
|
|
145
145
|
|
|
146
|
-
def log(self, log_:
|
|
146
|
+
def log(self, log_: Any) -> None:
|
|
147
147
|
"""
|
|
148
148
|
Add a log synchronously. If capacity is reached, auto-dump to file.
|
|
149
149
|
"""
|
|
150
|
+
log_ = Log.create(log_) if not isinstance(log_, Log) else log_
|
|
150
151
|
if self._config.capacity and len(self.logs) >= self._config.capacity:
|
|
151
152
|
try:
|
|
152
153
|
self.dump(clear=self._config.clear_after_dump)
|
|
@@ -154,7 +155,7 @@ class DataLogger:
|
|
|
154
155
|
logger.error(f"Failed to auto-dump logs: {e}")
|
|
155
156
|
self.logs.include(log_)
|
|
156
157
|
|
|
157
|
-
async def alog(self, log_:
|
|
158
|
+
async def alog(self, log_: Any) -> None:
|
|
158
159
|
"""
|
|
159
160
|
Add a log asynchronously. If capacity is reached, auto-dump to file.
|
|
160
161
|
"""
|
|
@@ -16,6 +16,7 @@ from collections.abc import (
|
|
|
16
16
|
from functools import wraps
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
from typing import TYPE_CHECKING, Any, ClassVar, Generic, Literal, TypeVar
|
|
19
|
+
from uuid import UUID
|
|
19
20
|
|
|
20
21
|
from pydantic import Field, field_serializer
|
|
21
22
|
from pydapter import Adaptable, AsyncAdaptable
|
|
@@ -32,7 +33,7 @@ from lionagi.utils import (
|
|
|
32
33
|
)
|
|
33
34
|
|
|
34
35
|
from .._concepts import Observable
|
|
35
|
-
from .element import ID, Collective, E, Element,
|
|
36
|
+
from .element import ID, Collective, E, Element, validate_order
|
|
36
37
|
from .progression import Progression
|
|
37
38
|
|
|
38
39
|
if TYPE_CHECKING:
|
|
@@ -112,7 +113,7 @@ def _validate_item_type(value, /) -> set[type[T]] | None:
|
|
|
112
113
|
|
|
113
114
|
|
|
114
115
|
def _validate_progression(
|
|
115
|
-
value: Any, collections: dict[
|
|
116
|
+
value: Any, collections: dict[UUID, T], /
|
|
116
117
|
) -> Progression:
|
|
117
118
|
if not value:
|
|
118
119
|
return Progression(order=list(collections.keys()))
|
|
@@ -198,7 +199,7 @@ class Pile(Element, Collective[T], Generic[T], Adaptable, AsyncAdaptable):
|
|
|
198
199
|
strict_type (bool): Whether to enforce strict type checking
|
|
199
200
|
"""
|
|
200
201
|
|
|
201
|
-
collections: dict[
|
|
202
|
+
collections: dict[UUID, T] = Field(default_factory=dict)
|
|
202
203
|
item_type: set | None = Field(
|
|
203
204
|
default=None,
|
|
204
205
|
description="Set of allowed types for items in the pile.",
|
|
@@ -282,9 +283,7 @@ class Pile(Element, Collective[T], Generic[T], Adaptable, AsyncAdaptable):
|
|
|
282
283
|
super().__init__(**data)
|
|
283
284
|
|
|
284
285
|
@field_serializer("collections")
|
|
285
|
-
def _serialize_collections(
|
|
286
|
-
self, v: dict[IDType, T]
|
|
287
|
-
) -> list[dict[str, Any]]:
|
|
286
|
+
def _serialize_collections(self, v: dict[UUID, T]) -> list[dict[str, Any]]:
|
|
288
287
|
return [i.to_dict() for i in v.values()]
|
|
289
288
|
|
|
290
289
|
@field_serializer("progression")
|
|
@@ -492,7 +491,7 @@ class Pile(Element, Collective[T], Generic[T], Adaptable, AsyncAdaptable):
|
|
|
492
491
|
"""Get all items in order."""
|
|
493
492
|
return [self.collections[key] for key in self.progression]
|
|
494
493
|
|
|
495
|
-
def items(self) -> Sequence[tuple[
|
|
494
|
+
def items(self) -> Sequence[tuple[UUID, T]]:
|
|
496
495
|
"""Get all (ID, item) pairs in order."""
|
|
497
496
|
return [(key, self.collections[key]) for key in self.progression]
|
|
498
497
|
|
|
@@ -797,7 +796,7 @@ class Pile(Element, Collective[T], Generic[T], Adaptable, AsyncAdaptable):
|
|
|
797
796
|
except Exception as e:
|
|
798
797
|
raise ItemNotFoundError(f"index {key}. Error: {e}")
|
|
799
798
|
|
|
800
|
-
elif isinstance(key,
|
|
799
|
+
elif isinstance(key, UUID):
|
|
801
800
|
try:
|
|
802
801
|
return self.collections[key]
|
|
803
802
|
except Exception as e:
|
|
@@ -904,7 +903,7 @@ class Pile(Element, Collective[T], Generic[T], Adaptable, AsyncAdaptable):
|
|
|
904
903
|
if isinstance(key, int | slice):
|
|
905
904
|
try:
|
|
906
905
|
pops = self.progression[key]
|
|
907
|
-
pops = [pops] if isinstance(pops,
|
|
906
|
+
pops = [pops] if isinstance(pops, UUID) else pops
|
|
908
907
|
result = []
|
|
909
908
|
for i in pops:
|
|
910
909
|
self.progression.remove(i)
|
|
@@ -1196,7 +1195,7 @@ def to_list_type(value: Any, /) -> list[Any]:
|
|
|
1196
1195
|
"""Convert input to a list format"""
|
|
1197
1196
|
if value is None:
|
|
1198
1197
|
return []
|
|
1199
|
-
if isinstance(value,
|
|
1198
|
+
if isinstance(value, UUID):
|
|
1200
1199
|
return [value]
|
|
1201
1200
|
if isinstance(value, str):
|
|
1202
1201
|
return ID.get_id(value) if ID.is_id(value) else []
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
6
|
from typing import Any, Generic, TypeVar
|
|
7
|
+
from uuid import UUID
|
|
7
8
|
|
|
8
9
|
from pydantic import Field, field_serializer, field_validator
|
|
9
10
|
from typing_extensions import Self
|
|
@@ -11,7 +12,7 @@ from typing_extensions import Self
|
|
|
11
12
|
from lionagi._errors import ItemNotFoundError
|
|
12
13
|
|
|
13
14
|
from .._concepts import Ordering
|
|
14
|
-
from .element import ID, Element,
|
|
15
|
+
from .element import ID, Element, validate_order
|
|
15
16
|
|
|
16
17
|
T = TypeVar("T", bound=Element)
|
|
17
18
|
|
|
@@ -26,7 +27,7 @@ class Progression(Element, Ordering[T], Generic[T]):
|
|
|
26
27
|
"""Tracks an ordered sequence of item IDs, with optional naming.
|
|
27
28
|
|
|
28
29
|
This class extends `Element` and implements `Ordering`, providing
|
|
29
|
-
list-like operations for managing item IDs (based on `
|
|
30
|
+
list-like operations for managing item IDs (based on `UUID`). It
|
|
30
31
|
supports insertion, removal, slicing, and more. Items are stored in
|
|
31
32
|
`order`, which is a simple list of IDs, and an optional `name`
|
|
32
33
|
attribute can be assigned for identification.
|
|
@@ -50,23 +51,23 @@ class Progression(Element, Ordering[T], Generic[T]):
|
|
|
50
51
|
)
|
|
51
52
|
|
|
52
53
|
@field_validator("order", mode="before")
|
|
53
|
-
def _validate_ordering(cls, value: Any) -> list[
|
|
54
|
-
"""Ensures `order` is a valid list of
|
|
54
|
+
def _validate_ordering(cls, value: Any) -> list[UUID]:
|
|
55
|
+
"""Ensures `order` is a valid list of UUIDs.
|
|
55
56
|
|
|
56
57
|
Args:
|
|
57
58
|
value (Any): Input sequence (could be elements, IDs, etc.).
|
|
58
59
|
|
|
59
60
|
Returns:
|
|
60
|
-
list[
|
|
61
|
+
list[UUID]: The list of validated UUID objects.
|
|
61
62
|
"""
|
|
62
63
|
return validate_order(value)
|
|
63
64
|
|
|
64
65
|
@field_serializer("order")
|
|
65
|
-
def _serialize_order(self, value: list[
|
|
66
|
+
def _serialize_order(self, value: list[UUID]) -> list[str]:
|
|
66
67
|
"""Serializes IDs in `order` to string form.
|
|
67
68
|
|
|
68
69
|
Args:
|
|
69
|
-
value (list[
|
|
70
|
+
value (list[UUID]): The order list of ID objects.
|
|
70
71
|
|
|
71
72
|
Returns:
|
|
72
73
|
list[str]: A list of stringified IDs.
|
|
@@ -85,7 +86,7 @@ class Progression(Element, Ordering[T], Generic[T]):
|
|
|
85
86
|
"""Checks if one or more IDs exist in the progression.
|
|
86
87
|
|
|
87
88
|
Args:
|
|
88
|
-
item (Any): Could be an `Element`, `
|
|
89
|
+
item (Any): Could be an `Element`, `UUID`, `UUID`, string,
|
|
89
90
|
or a sequence of these.
|
|
90
91
|
|
|
91
92
|
Returns:
|
|
@@ -98,14 +99,14 @@ class Progression(Element, Ordering[T], Generic[T]):
|
|
|
98
99
|
except Exception:
|
|
99
100
|
return False
|
|
100
101
|
|
|
101
|
-
def __getitem__(self, key: int | slice) ->
|
|
102
|
+
def __getitem__(self, key: int | slice) -> UUID | list[UUID]:
|
|
102
103
|
"""Gets one or more items by index or slice.
|
|
103
104
|
|
|
104
105
|
Args:
|
|
105
106
|
key (int | slice): The index or slice.
|
|
106
107
|
|
|
107
108
|
Returns:
|
|
108
|
-
|
|
109
|
+
UUID | list[UUID]:
|
|
109
110
|
A single ID if `key` is an int; a new `Progression`
|
|
110
111
|
if `key` is a slice.
|
|
111
112
|
|
|
@@ -164,15 +165,15 @@ class Progression(Element, Ordering[T], Generic[T]):
|
|
|
164
165
|
"""Iterates over the IDs in this progression.
|
|
165
166
|
|
|
166
167
|
Returns:
|
|
167
|
-
Iterator[
|
|
168
|
+
Iterator[UUID]: An iterator over the ID elements.
|
|
168
169
|
"""
|
|
169
170
|
return iter(self.order)
|
|
170
171
|
|
|
171
|
-
def __next__(self) ->
|
|
172
|
+
def __next__(self) -> UUID:
|
|
172
173
|
"""Returns the next item if used as an iterator.
|
|
173
174
|
|
|
174
175
|
Returns:
|
|
175
|
-
|
|
176
|
+
UUID: The next item in the iteration.
|
|
176
177
|
|
|
177
178
|
Raises:
|
|
178
179
|
StopIteration: If there are no more items.
|
|
@@ -182,11 +183,11 @@ class Progression(Element, Ordering[T], Generic[T]):
|
|
|
182
183
|
except StopIteration:
|
|
183
184
|
raise StopIteration("No more items in the progression")
|
|
184
185
|
|
|
185
|
-
def __list__(self) -> list[
|
|
186
|
+
def __list__(self) -> list[UUID]:
|
|
186
187
|
"""Returns a copy of all IDs in the progression.
|
|
187
188
|
|
|
188
189
|
Returns:
|
|
189
|
-
list[
|
|
190
|
+
list[UUID]: A shallow copy of the ID list.
|
|
190
191
|
"""
|
|
191
192
|
return self.order[:]
|
|
192
193
|
|
|
@@ -256,7 +257,7 @@ class Progression(Element, Ordering[T], Generic[T]):
|
|
|
256
257
|
refs = validate_order(item)
|
|
257
258
|
self.order.extend(refs)
|
|
258
259
|
|
|
259
|
-
def pop(self, index: int = -1) ->
|
|
260
|
+
def pop(self, index: int = -1) -> UUID:
|
|
260
261
|
"""Removes and returns one ID by index.
|
|
261
262
|
|
|
262
263
|
Args:
|
|
@@ -264,7 +265,7 @@ class Progression(Element, Ordering[T], Generic[T]):
|
|
|
264
265
|
Position of the item to pop (default is the last item).
|
|
265
266
|
|
|
266
267
|
Returns:
|
|
267
|
-
|
|
268
|
+
UUID: The removed ID.
|
|
268
269
|
|
|
269
270
|
Raises:
|
|
270
271
|
ItemNotFoundError: If the index is invalid or out of range.
|
|
@@ -274,11 +275,11 @@ class Progression(Element, Ordering[T], Generic[T]):
|
|
|
274
275
|
except Exception as e:
|
|
275
276
|
raise ItemNotFoundError(str(e)) from e
|
|
276
277
|
|
|
277
|
-
def popleft(self) ->
|
|
278
|
+
def popleft(self) -> UUID:
|
|
278
279
|
"""Removes and returns the first ID.
|
|
279
280
|
|
|
280
281
|
Returns:
|
|
281
|
-
|
|
282
|
+
UUID: The ID at the front of the progression.
|
|
282
283
|
|
|
283
284
|
Raises:
|
|
284
285
|
ItemNotFoundError: If the progression is empty.
|
|
@@ -300,9 +301,9 @@ class Progression(Element, Ordering[T], Generic[T]):
|
|
|
300
301
|
"""
|
|
301
302
|
try:
|
|
302
303
|
refs = validate_order(item)
|
|
303
|
-
except
|
|
304
|
-
|
|
305
|
-
|
|
304
|
+
except ValueError as e:
|
|
305
|
+
# Invalid UUID strings are treated as not found
|
|
306
|
+
raise ItemNotFoundError(str(item)) from e
|
|
306
307
|
if not refs:
|
|
307
308
|
return
|
|
308
309
|
missing = [r for r in refs if r not in self.order]
|
lionagi/protocols/graph/edge.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
from typing import Any
|
|
5
|
+
from uuid import UUID
|
|
5
6
|
|
|
6
7
|
from pydantic import (
|
|
7
8
|
BaseModel,
|
|
@@ -14,7 +15,7 @@ from pydantic import (
|
|
|
14
15
|
from lionagi.utils import is_same_dtype
|
|
15
16
|
|
|
16
17
|
from .._concepts import Condition, Relational
|
|
17
|
-
from ..generic.element import ID, Element
|
|
18
|
+
from ..generic.element import ID, Element
|
|
18
19
|
|
|
19
20
|
__all__ = (
|
|
20
21
|
"EdgeCondition",
|
|
@@ -51,8 +52,8 @@ class Edge(Element):
|
|
|
51
52
|
metadata, etc., may be stored in `properties`.
|
|
52
53
|
"""
|
|
53
54
|
|
|
54
|
-
head:
|
|
55
|
-
tail:
|
|
55
|
+
head: UUID
|
|
56
|
+
tail: UUID
|
|
56
57
|
properties: dict[str, Any] = Field(
|
|
57
58
|
default_factory=dict,
|
|
58
59
|
title="Properties",
|
|
@@ -106,11 +107,11 @@ class Edge(Element):
|
|
|
106
107
|
super().__init__(head=head, tail=tail, properties=kwargs)
|
|
107
108
|
|
|
108
109
|
@field_serializer("head", "tail")
|
|
109
|
-
def _serialize_id(self, value:
|
|
110
|
+
def _serialize_id(self, value: UUID) -> str:
|
|
110
111
|
return str(value)
|
|
111
112
|
|
|
112
113
|
@field_validator("head", "tail", mode="before")
|
|
113
|
-
def _validate_id(cls, value: str) ->
|
|
114
|
+
def _validate_id(cls, value: str) -> UUID:
|
|
114
115
|
return ID.get_id(value)
|
|
115
116
|
|
|
116
117
|
@property
|