lionagi 0.16.3__py3-none-any.whl → 0.17.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/__init__.py +24 -2
- lionagi/_types.py +47 -3
- lionagi/adapters/_utils.py +10 -9
- lionagi/adapters/async_postgres_adapter.py +83 -79
- lionagi/ln/__init__.py +0 -4
- lionagi/ln/_json_dump.py +0 -6
- lionagi/operations/__init__.py +0 -6
- lionagi/operations/_visualize_graph.py +285 -0
- lionagi/operations/brainstorm/brainstorm.py +14 -12
- lionagi/operations/builder.py +23 -302
- lionagi/operations/flow.py +105 -11
- lionagi/operations/node.py +14 -3
- lionagi/operations/operate/operate.py +5 -11
- lionagi/operations/parse/parse.py +1 -2
- lionagi/operations/types.py +0 -2
- lionagi/operations/utils.py +11 -5
- lionagi/protocols/generic/pile.py +2 -6
- lionagi/protocols/graph/graph.py +23 -6
- lionagi/protocols/graph/node.py +27 -10
- lionagi/protocols/messages/message.py +0 -1
- lionagi/protocols/types.py +0 -15
- lionagi/service/__init__.py +19 -1
- lionagi/service/connections/api_calling.py +13 -4
- lionagi/service/connections/endpoint.py +11 -5
- lionagi/service/types.py +19 -1
- lionagi/session/branch.py +24 -18
- lionagi/session/session.py +44 -18
- lionagi/version.py +1 -1
- {lionagi-0.16.3.dist-info → lionagi-0.17.1.dist-info}/METADATA +5 -2
- {lionagi-0.16.3.dist-info → lionagi-0.17.1.dist-info}/RECORD +32 -32
- lionagi/protocols/graph/_utils.py +0 -22
- {lionagi-0.16.3.dist-info → lionagi-0.17.1.dist-info}/WHEEL +0 -0
- {lionagi-0.16.3.dist-info → lionagi-0.17.1.dist-info}/licenses/LICENSE +0 -0
@@ -9,18 +9,12 @@ from pydantic import BaseModel, JsonValue
|
|
9
9
|
|
10
10
|
from lionagi.fields.instruct import Instruct
|
11
11
|
from lionagi.models import FieldModel, ModelParams
|
12
|
-
from lionagi.protocols.
|
13
|
-
|
14
|
-
Operative,
|
15
|
-
Progression,
|
16
|
-
SenderRecipient,
|
17
|
-
Step,
|
18
|
-
ToolRef,
|
19
|
-
)
|
12
|
+
from lionagi.protocols.operatives.step import Operative, Step
|
13
|
+
from lionagi.protocols.types import Instruction, Progression, SenderRecipient
|
20
14
|
from lionagi.service.imodel import iModel
|
21
15
|
|
22
16
|
if TYPE_CHECKING:
|
23
|
-
from lionagi.session.branch import Branch
|
17
|
+
from lionagi.session.branch import Branch, ToolRef
|
24
18
|
|
25
19
|
|
26
20
|
def _handle_response_format_kwargs(
|
@@ -64,8 +58,8 @@ async def operate(
|
|
64
58
|
image_detail: Literal["low", "high", "auto"] = None,
|
65
59
|
parse_model: iModel = None,
|
66
60
|
skip_validation: bool = False,
|
67
|
-
tools: ToolRef = None,
|
68
|
-
operative: Operative = None,
|
61
|
+
tools: "ToolRef" = None,
|
62
|
+
operative: "Operative" = None,
|
69
63
|
response_format: type[BaseModel] = None, # alias of operative.request_type
|
70
64
|
return_operative: bool = False,
|
71
65
|
actions: bool = False,
|
@@ -7,7 +7,6 @@ from typing import TYPE_CHECKING, Any, Literal
|
|
7
7
|
from pydantic import BaseModel
|
8
8
|
|
9
9
|
from lionagi.ln.fuzzy._fuzzy_validate import fuzzy_validate_mapping
|
10
|
-
from lionagi.protocols.types import Operative
|
11
10
|
from lionagi.utils import breakdown_pydantic_annotation
|
12
11
|
|
13
12
|
if TYPE_CHECKING:
|
@@ -22,7 +21,7 @@ async def parse(
|
|
22
21
|
] = "return_value",
|
23
22
|
max_retries: int = 3,
|
24
23
|
request_type: type[BaseModel] = None,
|
25
|
-
operative
|
24
|
+
operative=None,
|
26
25
|
similarity_algo="jaro_winkler",
|
27
26
|
similarity_threshold: float = 0.85,
|
28
27
|
fuzzy_match: bool = True,
|
lionagi/operations/types.py
CHANGED
@@ -12,7 +12,6 @@ from .parse.parse import parse
|
|
12
12
|
from .plan.plan import plan
|
13
13
|
from .ReAct.ReAct import ReAct
|
14
14
|
from .select.select import select
|
15
|
-
from .translate.translate import translate
|
16
15
|
|
17
16
|
__all__ = (
|
18
17
|
"brainstorm",
|
@@ -25,5 +24,4 @@ __all__ = (
|
|
25
24
|
"operate",
|
26
25
|
"parse",
|
27
26
|
"ReAct",
|
28
|
-
"translate",
|
29
27
|
)
|
lionagi/operations/utils.py
CHANGED
@@ -2,18 +2,24 @@
|
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
|
+
from typing import TYPE_CHECKING
|
6
|
+
|
5
7
|
from lionagi.fields.instruct import Instruct
|
6
|
-
|
8
|
+
|
9
|
+
if TYPE_CHECKING:
|
10
|
+
from lionagi.session.session import Branch, Session
|
7
11
|
|
8
12
|
|
9
13
|
def prepare_session(
|
10
|
-
session: Session
|
11
|
-
branch: Branch
|
14
|
+
session: "Session" = None,
|
15
|
+
branch: "Branch" = None,
|
12
16
|
branch_kwargs=None,
|
13
|
-
) -> tuple[Session, Branch]:
|
17
|
+
) -> tuple["Session", "Branch"]:
|
18
|
+
from lionagi.session.session import Branch, Session
|
19
|
+
|
14
20
|
if session is not None:
|
15
21
|
if branch is not None:
|
16
|
-
branch: Branch = session.branches[branch]
|
22
|
+
branch: "Branch" = session.branches[branch]
|
17
23
|
else:
|
18
24
|
branch = session.new_branch(**(branch_kwargs or {}))
|
19
25
|
else:
|
@@ -18,7 +18,6 @@ from functools import wraps
|
|
18
18
|
from pathlib import Path
|
19
19
|
from typing import Any, ClassVar, Generic, Literal, TypeVar
|
20
20
|
|
21
|
-
import pandas as pd
|
22
21
|
from pydantic import Field, field_serializer
|
23
22
|
from pydantic.fields import FieldInfo
|
24
23
|
from pydapter import Adaptable, AsyncAdaptable
|
@@ -1047,9 +1046,7 @@ class Pile(Element, Collective[T], Generic[T], Adaptable, AsyncAdaptable):
|
|
1047
1046
|
kw["adapt_meth"] = "from_dict"
|
1048
1047
|
return await super().adapt_from_async(obj, obj_key, many=many, **kw)
|
1049
1048
|
|
1050
|
-
def to_df(
|
1051
|
-
self, columns: list[str] | None = None, **kw: Any
|
1052
|
-
) -> pd.DataFrame:
|
1049
|
+
def to_df(self, columns: list[str] | None = None, **kw: Any):
|
1053
1050
|
"""Convert to DataFrame."""
|
1054
1051
|
from pydapter.extras.pandas_ import DataFrameAdapter
|
1055
1052
|
|
@@ -1207,11 +1204,10 @@ def to_list_type(value: Any, /) -> list[Any]:
|
|
1207
1204
|
|
1208
1205
|
if not _ADAPATER_REGISTERED:
|
1209
1206
|
from pydapter.adapters import CsvAdapter, JsonAdapter
|
1210
|
-
from pydapter.extras.pandas_ import DataFrameAdapter
|
1211
1207
|
|
1212
1208
|
Pile.register_adapter(CsvAdapter)
|
1213
1209
|
Pile.register_adapter(JsonAdapter)
|
1214
|
-
|
1210
|
+
|
1215
1211
|
_ADAPATER_REGISTERED = True
|
1216
1212
|
|
1217
1213
|
Pile = Pile
|
lionagi/protocols/graph/graph.py
CHANGED
@@ -19,10 +19,8 @@ from .node import Node
|
|
19
19
|
|
20
20
|
T = TypeVar("T", bound=Node)
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
_NETWORKX_AVAILABLE = check_networkx_available()
|
25
|
-
_MATPLIB_AVAILABLE = check_matplotlib_available()
|
22
|
+
_NETWORKX_AVAILABLE = None
|
23
|
+
_MATPLIB_AVAILABLE = None
|
26
24
|
__all__ = ("Graph",)
|
27
25
|
|
28
26
|
|
@@ -219,8 +217,17 @@ class Graph(Element, Relational, Generic[T]):
|
|
219
217
|
|
220
218
|
def to_networkx(self, **kwargs) -> Any:
|
221
219
|
"""Convert the graph to a NetworkX graph object."""
|
220
|
+
global _NETWORKX_AVAILABLE
|
221
|
+
if _NETWORKX_AVAILABLE is None:
|
222
|
+
from lionagi.ln import is_import_installed
|
223
|
+
|
224
|
+
_NETWORKX_AVAILABLE = is_import_installed("networkx")
|
225
|
+
|
222
226
|
if _NETWORKX_AVAILABLE is not True:
|
223
|
-
raise
|
227
|
+
raise ImportError(
|
228
|
+
"The 'networkx' package is required for this feature. "
|
229
|
+
"Please install `networkx` or `'lionagi[graph]'`."
|
230
|
+
)
|
224
231
|
|
225
232
|
from networkx import DiGraph # type: ignore
|
226
233
|
|
@@ -248,8 +255,18 @@ class Graph(Element, Relational, Generic[T]):
|
|
248
255
|
):
|
249
256
|
"""Display the graph using NetworkX and Matplotlib."""
|
250
257
|
g = self.to_networkx(**kwargs)
|
258
|
+
|
259
|
+
global _MATPLIB_AVAILABLE
|
260
|
+
if _MATPLIB_AVAILABLE is None:
|
261
|
+
from lionagi.ln import is_import_installed
|
262
|
+
|
263
|
+
_MATPLIB_AVAILABLE = is_import_installed("matplotlib")
|
264
|
+
|
251
265
|
if _MATPLIB_AVAILABLE is not True:
|
252
|
-
raise
|
266
|
+
raise ImportError(
|
267
|
+
"The 'matplotlib' package is required for this feature. "
|
268
|
+
"Please install `matplotlib` or `'lionagi[graph]'`."
|
269
|
+
)
|
253
270
|
|
254
271
|
import matplotlib.pyplot as plt # type: ignore
|
255
272
|
import networkx as nx # type: ignore
|
lionagi/protocols/graph/node.py
CHANGED
@@ -62,6 +62,10 @@ class Node(Element, Relational, AsyncAdaptable, Adaptable):
|
|
62
62
|
async def adapt_to_async(
|
63
63
|
self, obj_key: str, many=False, **kwargs: Any
|
64
64
|
) -> Any:
|
65
|
+
# Only register postgres adapter if this specific operation needs it
|
66
|
+
if obj_key == "lionagi_async_pg":
|
67
|
+
_ensure_postgres_adapter()
|
68
|
+
|
65
69
|
kwargs["adapt_meth"] = "to_dict"
|
66
70
|
kwargs["adapt_kw"] = {"mode": "db"}
|
67
71
|
return await super().adapt_to_async(
|
@@ -76,6 +80,10 @@ class Node(Element, Relational, AsyncAdaptable, Adaptable):
|
|
76
80
|
many=False,
|
77
81
|
**kwargs: Any,
|
78
82
|
) -> Node:
|
83
|
+
# Only register postgres adapter if this specific operation needs it
|
84
|
+
if obj_key == "lionagi_async_pg":
|
85
|
+
_ensure_postgres_adapter()
|
86
|
+
|
79
87
|
kwargs["adapt_meth"] = "from_dict"
|
80
88
|
return await super().adapt_from_async(
|
81
89
|
obj, obj_key=obj_key, many=many, **kwargs
|
@@ -122,22 +130,31 @@ class Node(Element, Relational, AsyncAdaptable, Adaptable):
|
|
122
130
|
return value
|
123
131
|
|
124
132
|
|
133
|
+
def _ensure_postgres_adapter():
|
134
|
+
"""Lazy registration of postgres adapter when needed"""
|
135
|
+
if not hasattr(Node, "_postgres_adapter_checked"):
|
136
|
+
from lionagi.adapters._utils import check_async_postgres_available
|
137
|
+
|
138
|
+
if check_async_postgres_available() is True:
|
139
|
+
try:
|
140
|
+
from lionagi.adapters.async_postgres_adapter import (
|
141
|
+
LionAGIAsyncPostgresAdapter,
|
142
|
+
)
|
143
|
+
|
144
|
+
Node.register_async_adapter(LionAGIAsyncPostgresAdapter)
|
145
|
+
except ImportError:
|
146
|
+
pass # Graceful degradation if postgres dependencies missing
|
147
|
+
Node._postgres_adapter_checked = True
|
148
|
+
|
149
|
+
|
125
150
|
if not _ADAPATER_REGISTERED:
|
126
151
|
from pydapter.adapters import JsonAdapter, TomlAdapter
|
127
|
-
from pydapter.extras.pandas_ import SeriesAdapter
|
128
152
|
|
129
153
|
Node.register_adapter(JsonAdapter)
|
130
154
|
Node.register_adapter(TomlAdapter)
|
131
|
-
Node.register_adapter(SeriesAdapter)
|
132
|
-
|
133
|
-
from lionagi.adapters._utils import check_async_postgres_available
|
134
|
-
|
135
|
-
if check_async_postgres_available() is True:
|
136
|
-
from lionagi.adapters.async_postgres_adapter import (
|
137
|
-
LionAGIAsyncPostgresAdapter,
|
138
|
-
)
|
139
155
|
|
140
|
-
|
156
|
+
# PostgreSQL adapter registration is now lazy - only loaded when needed
|
157
|
+
# Call _ensure_postgres_adapter() in methods that actually use async adapters
|
141
158
|
|
142
159
|
_ADAPATER_REGISTERED = True
|
143
160
|
|
lionagi/protocols/types.py
CHANGED
@@ -5,10 +5,7 @@
|
|
5
5
|
from ._concepts import Collective, Communicatable, Condition, Manager
|
6
6
|
from ._concepts import Observable as LegacyObservable
|
7
7
|
from ._concepts import Observer, Ordering, Relational, Sendable
|
8
|
-
from .action.manager import ActionManager, FunctionCalling, Tool, ToolRef
|
9
8
|
from .contracts import Observable, ObservableProto
|
10
|
-
from .forms.flow import FlowDefinition, FlowStep
|
11
|
-
from .forms.report import BaseForm, Form, Report
|
12
9
|
from .generic.element import ID, Element, IDError, IDType, validate_order
|
13
10
|
from .generic.event import Event, EventStatus, Execution
|
14
11
|
from .generic.log import (
|
@@ -43,7 +40,6 @@ from .messages.manager import (
|
|
43
40
|
SenderRecipient,
|
44
41
|
System,
|
45
42
|
)
|
46
|
-
from .operatives.step import Operative, Step
|
47
43
|
|
48
44
|
__all__ = (
|
49
45
|
"Collective",
|
@@ -98,17 +94,6 @@ __all__ = (
|
|
98
94
|
"RoledMessage",
|
99
95
|
"SenderRecipient",
|
100
96
|
"System",
|
101
|
-
"FlowDefinition",
|
102
|
-
"FlowStep",
|
103
|
-
"BaseForm",
|
104
|
-
"Form",
|
105
|
-
"Report",
|
106
|
-
"Operative",
|
107
|
-
"Step",
|
108
|
-
"ActionManager",
|
109
|
-
"Tool",
|
110
|
-
"FunctionCalling",
|
111
|
-
"ToolRef",
|
112
97
|
"MailManager",
|
113
98
|
"DataLogger",
|
114
99
|
"DataLoggerConfig",
|
lionagi/service/__init__.py
CHANGED
@@ -1,10 +1,28 @@
|
|
1
|
+
# Eager imports for core functionality
|
1
2
|
from .connections.api_calling import APICalling
|
2
3
|
from .connections.endpoint import Endpoint, EndpointConfig
|
3
4
|
from .hooks import *
|
4
5
|
from .imodel import iModel
|
5
6
|
from .manager import iModelManager
|
6
7
|
from .rate_limited_processor import RateLimitedAPIExecutor
|
7
|
-
|
8
|
+
|
9
|
+
# Lazy loading cache
|
10
|
+
_lazy_imports = {}
|
11
|
+
|
12
|
+
|
13
|
+
def __getattr__(name: str):
|
14
|
+
"""Lazy loading for heavy service imports."""
|
15
|
+
if name in _lazy_imports:
|
16
|
+
return _lazy_imports[name]
|
17
|
+
|
18
|
+
if name == "TokenCalculator":
|
19
|
+
from .token_calculator import TokenCalculator
|
20
|
+
|
21
|
+
_lazy_imports["TokenCalculator"] = TokenCalculator
|
22
|
+
return TokenCalculator
|
23
|
+
|
24
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
25
|
+
|
8
26
|
|
9
27
|
__all__ = (
|
10
28
|
"APICalling",
|
@@ -12,10 +12,17 @@ from typing_extensions import Self
|
|
12
12
|
from lionagi.protocols.generic.event import Event, EventStatus
|
13
13
|
from lionagi.protocols.types import Log
|
14
14
|
from lionagi.service.hooks import HookEvent, HookEventTypes, global_hook_logger
|
15
|
-
from lionagi.service.token_calculator import TokenCalculator
|
16
15
|
|
17
16
|
from .endpoint import Endpoint
|
18
17
|
|
18
|
+
|
19
|
+
# Lazy import for TokenCalculator
|
20
|
+
def _get_token_calculator():
|
21
|
+
from lionagi.service.token_calculator import TokenCalculator
|
22
|
+
|
23
|
+
return TokenCalculator
|
24
|
+
|
25
|
+
|
19
26
|
logger = logging.getLogger(__name__)
|
20
27
|
|
21
28
|
|
@@ -129,7 +136,7 @@ class APICalling(Event):
|
|
129
136
|
|
130
137
|
# Handle chat completions format
|
131
138
|
if "messages" in self.payload:
|
132
|
-
return
|
139
|
+
return _get_token_calculator().calculate_message_tokens(
|
133
140
|
self.payload["messages"], **self.payload
|
134
141
|
)
|
135
142
|
# Handle responses API format
|
@@ -150,12 +157,14 @@ class APICalling(Event):
|
|
150
157
|
messages.append(item)
|
151
158
|
else:
|
152
159
|
return None
|
153
|
-
return
|
160
|
+
return _get_token_calculator().calculate_message_tokens(
|
154
161
|
messages, **self.payload
|
155
162
|
)
|
156
163
|
# Handle embeddings endpoint
|
157
164
|
elif "embed" in self.endpoint.config.endpoint:
|
158
|
-
return
|
165
|
+
return _get_token_calculator().calculate_embed_token(
|
166
|
+
**self.payload
|
167
|
+
)
|
159
168
|
|
160
169
|
return None
|
161
170
|
|
@@ -5,18 +5,13 @@
|
|
5
5
|
import asyncio
|
6
6
|
import logging
|
7
7
|
|
8
|
-
import aiohttp
|
9
|
-
import backoff
|
10
|
-
from aiocache import cached
|
11
8
|
from pydantic import BaseModel
|
12
9
|
|
13
|
-
from lionagi.config import settings
|
14
10
|
from lionagi.service.resilience import (
|
15
11
|
CircuitBreaker,
|
16
12
|
RetryConfig,
|
17
13
|
retry_with_backoff,
|
18
14
|
)
|
19
|
-
from lionagi.utils import to_dict
|
20
15
|
|
21
16
|
from .endpoint_config import EndpointConfig
|
22
17
|
from .header_factory import HeaderFactory
|
@@ -65,6 +60,8 @@ class Endpoint:
|
|
65
60
|
|
66
61
|
def _create_http_session(self):
|
67
62
|
"""Create a new HTTP session (not thread-safe, create new for each request)."""
|
63
|
+
import aiohttp
|
64
|
+
|
68
65
|
return aiohttp.ClientSession(
|
69
66
|
timeout=aiohttp.ClientTimeout(self.config.timeout),
|
70
67
|
**self.config.client_kwargs,
|
@@ -231,6 +228,9 @@ class Endpoint:
|
|
231
228
|
|
232
229
|
# Handle caching if requested
|
233
230
|
if cache_control:
|
231
|
+
from aiocache import cached
|
232
|
+
|
233
|
+
from lionagi.config import settings
|
234
234
|
|
235
235
|
@cached(**settings.aiocache_config.as_kwargs())
|
236
236
|
async def _cached_call(payload: dict, headers: dict, **kwargs):
|
@@ -268,6 +268,8 @@ class Endpoint:
|
|
268
268
|
Returns:
|
269
269
|
The response from the endpoint.
|
270
270
|
"""
|
271
|
+
import aiohttp
|
272
|
+
import backoff
|
271
273
|
|
272
274
|
async def _make_request_with_backoff():
|
273
275
|
# Create a new session for this request
|
@@ -382,6 +384,8 @@ class Endpoint:
|
|
382
384
|
**kwargs,
|
383
385
|
) as response:
|
384
386
|
if response.status != 200:
|
387
|
+
import aiohttp
|
388
|
+
|
385
389
|
raise aiohttp.ClientResponseError(
|
386
390
|
request_info=response.request_info,
|
387
391
|
history=response.history,
|
@@ -409,6 +413,8 @@ class Endpoint:
|
|
409
413
|
|
410
414
|
@classmethod
|
411
415
|
def from_dict(cls, data: dict):
|
416
|
+
from lionagi.utils import to_dict
|
417
|
+
|
412
418
|
data = to_dict(data, recursive=True)
|
413
419
|
retry_config = data.get("retry_config")
|
414
420
|
circuit_breaker = data.get("circuit_breaker")
|
lionagi/service/types.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
|
+
# Eager imports for core functionality
|
5
6
|
from .connections.api_calling import APICalling
|
6
7
|
from .connections.endpoint import Endpoint, EndpointConfig
|
7
8
|
from .connections.providers.types import *
|
@@ -9,7 +10,24 @@ from .hooks import *
|
|
9
10
|
from .imodel import iModel
|
10
11
|
from .manager import iModelManager
|
11
12
|
from .rate_limited_processor import RateLimitedAPIExecutor
|
12
|
-
|
13
|
+
|
14
|
+
# Lazy loading cache
|
15
|
+
_lazy_imports = {}
|
16
|
+
|
17
|
+
|
18
|
+
def __getattr__(name: str):
|
19
|
+
"""Lazy loading for heavy service imports."""
|
20
|
+
if name in _lazy_imports:
|
21
|
+
return _lazy_imports[name]
|
22
|
+
|
23
|
+
if name == "TokenCalculator":
|
24
|
+
from .token_calculator import TokenCalculator
|
25
|
+
|
26
|
+
_lazy_imports["TokenCalculator"] = TokenCalculator
|
27
|
+
return TokenCalculator
|
28
|
+
|
29
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
30
|
+
|
13
31
|
|
14
32
|
__all__ = (
|
15
33
|
"APICalling",
|
lionagi/session/branch.py
CHANGED
@@ -4,10 +4,8 @@
|
|
4
4
|
|
5
5
|
from collections.abc import AsyncGenerator, Callable
|
6
6
|
from enum import Enum
|
7
|
-
from typing import Any, Literal
|
7
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional
|
8
8
|
|
9
|
-
import pandas as pd
|
10
|
-
from jinja2 import Template
|
11
9
|
from pydantic import BaseModel, Field, JsonValue, PrivateAttr, field_serializer
|
12
10
|
|
13
11
|
from lionagi.config import settings
|
@@ -15,11 +13,11 @@ from lionagi.fields import Instruct
|
|
15
13
|
from lionagi.libs.schema.as_readable import as_readable
|
16
14
|
from lionagi.models.field_model import FieldModel
|
17
15
|
from lionagi.operations.manager import OperationManager
|
16
|
+
from lionagi.protocols.action.manager import ActionManager
|
18
17
|
from lionagi.protocols.action.tool import FuncTool, Tool, ToolRef
|
19
18
|
from lionagi.protocols.types import (
|
20
19
|
ID,
|
21
20
|
MESSAGE_FIELDS,
|
22
|
-
ActionManager,
|
23
21
|
ActionRequest,
|
24
22
|
ActionResponse,
|
25
23
|
AssistantResponse,
|
@@ -34,8 +32,6 @@ from lionagi.protocols.types import (
|
|
34
32
|
Mailbox,
|
35
33
|
MessageManager,
|
36
34
|
MessageRole,
|
37
|
-
Operative,
|
38
|
-
Package,
|
39
35
|
PackageCategory,
|
40
36
|
Pile,
|
41
37
|
Progression,
|
@@ -54,6 +50,10 @@ from lionagi.utils import copy
|
|
54
50
|
|
55
51
|
from .prompts import LION_SYSTEM_MESSAGE
|
56
52
|
|
53
|
+
if TYPE_CHECKING:
|
54
|
+
from lionagi.protocols.operatives.operative import Operative
|
55
|
+
|
56
|
+
|
57
57
|
__all__ = ("Branch",)
|
58
58
|
|
59
59
|
|
@@ -117,18 +117,18 @@ class Branch(Element, Communicatable, Relational):
|
|
117
117
|
def __init__(
|
118
118
|
self,
|
119
119
|
*,
|
120
|
-
user: SenderRecipient = None,
|
120
|
+
user: "SenderRecipient" = None,
|
121
121
|
name: str | None = None,
|
122
122
|
messages: Pile[RoledMessage] = None, # message manager kwargs
|
123
123
|
system: System | JsonValue = None,
|
124
|
-
system_sender: SenderRecipient = None,
|
124
|
+
system_sender: "SenderRecipient" = None,
|
125
125
|
chat_model: iModel | dict = None, # iModelManager kwargs
|
126
126
|
parse_model: iModel | dict = None,
|
127
127
|
imodel: iModel = None, # deprecated, alias of chat_model
|
128
128
|
tools: FuncTool | list[FuncTool] = None, # ActionManager kwargs
|
129
129
|
log_config: LogManagerConfig | dict = None, # LogManager kwargs
|
130
130
|
system_datetime: bool | str = None,
|
131
|
-
system_template
|
131
|
+
system_template=None,
|
132
132
|
system_template_context: dict = None,
|
133
133
|
logs: Pile[Log] = None,
|
134
134
|
use_lion_system_message: bool = False,
|
@@ -163,7 +163,7 @@ class Branch(Element, Communicatable, Relational):
|
|
163
163
|
system_datetime (bool | str, optional):
|
164
164
|
Whether to include timestamps in system messages (True/False)
|
165
165
|
or a string format for datetime.
|
166
|
-
system_template (Template | str, optional):
|
166
|
+
system_template (jinja2.Template | str, optional):
|
167
167
|
Optional Jinja2 template for system messages.
|
168
168
|
system_template_context (dict, optional):
|
169
169
|
Context for rendering the system template.
|
@@ -177,6 +177,8 @@ class Branch(Element, Communicatable, Relational):
|
|
177
177
|
super().__init__(user=user, name=name, **kwargs)
|
178
178
|
|
179
179
|
# --- MessageManager ---
|
180
|
+
from lionagi.protocols.messages.manager import MessageManager
|
181
|
+
|
180
182
|
self._message_manager = MessageManager(messages=messages)
|
181
183
|
|
182
184
|
if any(
|
@@ -401,7 +403,7 @@ class Branch(Element, Communicatable, Relational):
|
|
401
403
|
# -------------------------------------------------------------------------
|
402
404
|
# Conversion / Serialization
|
403
405
|
# -------------------------------------------------------------------------
|
404
|
-
def to_df(self, *, progression: Progression = None)
|
406
|
+
def to_df(self, *, progression: Progression = None):
|
405
407
|
"""
|
406
408
|
Convert branch messages into a `pandas.DataFrame`.
|
407
409
|
|
@@ -412,6 +414,8 @@ class Branch(Element, Communicatable, Relational):
|
|
412
414
|
Returns:
|
413
415
|
pd.DataFrame: Each row represents a message, with columns defined by MESSAGE_FIELDS.
|
414
416
|
"""
|
417
|
+
from lionagi.protocols.generic.pile import Pile
|
418
|
+
|
415
419
|
if progression is None:
|
416
420
|
progression = self.msgs.progression
|
417
421
|
|
@@ -429,7 +433,7 @@ class Branch(Element, Communicatable, Relational):
|
|
429
433
|
def send(
|
430
434
|
self,
|
431
435
|
recipient: IDType,
|
432
|
-
category: PackageCategory
|
436
|
+
category: Optional["PackageCategory"],
|
433
437
|
item: Any,
|
434
438
|
request_source: IDType | None = None,
|
435
439
|
) -> None:
|
@@ -446,6 +450,8 @@ class Branch(Element, Communicatable, Relational):
|
|
446
450
|
request_source (IDType | None):
|
447
451
|
The ID that prompted or requested this send operation (optional).
|
448
452
|
"""
|
453
|
+
from lionagi.protocols.mail.package import Package
|
454
|
+
|
449
455
|
package = Package(
|
450
456
|
category=category,
|
451
457
|
item=item,
|
@@ -833,7 +839,7 @@ class Branch(Element, Communicatable, Relational):
|
|
833
839
|
] = "return_value",
|
834
840
|
max_retries: int = 3,
|
835
841
|
request_type: type[BaseModel] = None,
|
836
|
-
operative: Operative = None,
|
842
|
+
operative: "Operative" = None,
|
837
843
|
similarity_algo="jaro_winkler",
|
838
844
|
similarity_threshold: float = 0.85,
|
839
845
|
fuzzy_match: bool = True,
|
@@ -911,8 +917,8 @@ class Branch(Element, Communicatable, Relational):
|
|
911
917
|
instruction: Instruction | JsonValue = None,
|
912
918
|
guidance: JsonValue = None,
|
913
919
|
context: JsonValue = None,
|
914
|
-
sender: SenderRecipient = None,
|
915
|
-
recipient: SenderRecipient = None,
|
920
|
+
sender: "SenderRecipient" = None,
|
921
|
+
recipient: "SenderRecipient" = None,
|
916
922
|
progression: Progression = None,
|
917
923
|
chat_model: iModel = None,
|
918
924
|
invoke_actions: bool = True,
|
@@ -922,7 +928,7 @@ class Branch(Element, Communicatable, Relational):
|
|
922
928
|
parse_model: iModel = None,
|
923
929
|
skip_validation: bool = False,
|
924
930
|
tools: ToolRef = None,
|
925
|
-
operative: Operative = None,
|
931
|
+
operative: "Operative" = None,
|
926
932
|
response_format: type[
|
927
933
|
BaseModel
|
928
934
|
] = None, # alias of operative.request_type
|
@@ -1063,8 +1069,8 @@ class Branch(Element, Communicatable, Relational):
|
|
1063
1069
|
guidance: JsonValue = None,
|
1064
1070
|
context: JsonValue = None,
|
1065
1071
|
plain_content: str = None,
|
1066
|
-
sender: SenderRecipient = None,
|
1067
|
-
recipient: SenderRecipient = None,
|
1072
|
+
sender: "SenderRecipient" = None,
|
1073
|
+
recipient: "SenderRecipient" = None,
|
1068
1074
|
progression: ID.IDSeq = None,
|
1069
1075
|
response_format: type[BaseModel] = None,
|
1070
1076
|
request_fields: dict | list[str] = None,
|