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
lionagi/session/branch.py
CHANGED
|
@@ -2,52 +2,48 @@
|
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
from collections.abc import AsyncGenerator, Callable
|
|
5
|
-
from typing import TYPE_CHECKING, Any, Literal
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
6
6
|
|
|
7
7
|
from pydantic import BaseModel, Field, JsonValue, PrivateAttr, field_serializer
|
|
8
8
|
|
|
9
9
|
from lionagi.config import settings
|
|
10
|
+
from lionagi.ln import AlcallParams
|
|
10
11
|
from lionagi.ln.types import Unset
|
|
11
12
|
from lionagi.models.field_model import FieldModel
|
|
12
|
-
from lionagi.operations.
|
|
13
|
+
from lionagi.operations.fields import Instruct
|
|
13
14
|
from lionagi.operations.manager import OperationManager
|
|
15
|
+
from lionagi.protocols._concepts import Relational
|
|
14
16
|
from lionagi.protocols.action.manager import ActionManager
|
|
15
17
|
from lionagi.protocols.action.tool import FuncTool, Tool, ToolRef
|
|
16
|
-
from lionagi.protocols.
|
|
18
|
+
from lionagi.protocols.generic import (
|
|
17
19
|
ID,
|
|
18
|
-
|
|
20
|
+
DataLogger,
|
|
21
|
+
DataLoggerConfig,
|
|
22
|
+
Element,
|
|
23
|
+
Log,
|
|
24
|
+
Pile,
|
|
25
|
+
Progression,
|
|
26
|
+
)
|
|
27
|
+
from lionagi.protocols.messages import (
|
|
19
28
|
ActionRequest,
|
|
20
29
|
ActionResponse,
|
|
21
30
|
AssistantResponse,
|
|
22
|
-
Communicatable,
|
|
23
|
-
Element,
|
|
24
|
-
IDType,
|
|
25
31
|
Instruction,
|
|
26
|
-
Log,
|
|
27
|
-
LogManager,
|
|
28
|
-
LogManagerConfig,
|
|
29
|
-
Mail,
|
|
30
|
-
Mailbox,
|
|
31
32
|
MessageManager,
|
|
32
33
|
MessageRole,
|
|
33
|
-
PackageCategory,
|
|
34
|
-
Pile,
|
|
35
|
-
Progression,
|
|
36
|
-
Relational,
|
|
37
34
|
RoledMessage,
|
|
38
35
|
SenderRecipient,
|
|
39
36
|
System,
|
|
40
37
|
)
|
|
41
38
|
from lionagi.service.connections.endpoint import Endpoint
|
|
42
|
-
from lionagi.service.
|
|
39
|
+
from lionagi.service.manager import iModel, iModelManager
|
|
43
40
|
from lionagi.tools.base import LionTool
|
|
44
41
|
from lionagi.utils import copy
|
|
45
42
|
|
|
46
43
|
from .prompts import LION_SYSTEM_MESSAGE
|
|
47
44
|
|
|
48
45
|
if TYPE_CHECKING:
|
|
49
|
-
from lionagi.
|
|
50
|
-
from lionagi.protocols.operatives.operative import Operative
|
|
46
|
+
from lionagi.operations.operate.operative import Operative
|
|
51
47
|
|
|
52
48
|
|
|
53
49
|
__all__ = ("Branch",)
|
|
@@ -56,7 +52,7 @@ __all__ = ("Branch",)
|
|
|
56
52
|
_DEFAULT_ALCALL_PARAMS = None
|
|
57
53
|
|
|
58
54
|
|
|
59
|
-
class Branch(Element,
|
|
55
|
+
class Branch(Element, Relational):
|
|
60
56
|
"""
|
|
61
57
|
Manages a conversation 'branch' with messages, tools, and iModels.
|
|
62
58
|
|
|
@@ -65,20 +61,17 @@ class Branch(Element, Communicatable, Relational):
|
|
|
65
61
|
- Registers and invokes tools/actions (`ActionManager`).
|
|
66
62
|
- Manages model instances (`iModelManager`).
|
|
67
63
|
- Logs activity (`LogManager`).
|
|
68
|
-
- Communicates via mailboxes (`Mailbox`).
|
|
69
64
|
|
|
70
65
|
**Key responsibilities**:
|
|
71
66
|
- Storing and organizing messages, including system instructions, user instructions, and model responses.
|
|
72
67
|
- Handling asynchronous or synchronous execution of LLM calls and tool invocations.
|
|
73
|
-
- Providing a consistent interface for
|
|
68
|
+
- Providing a consistent interface for "operate," "chat," "communicate," "parse," etc.
|
|
74
69
|
|
|
75
70
|
Attributes:
|
|
76
71
|
user (SenderRecipient | None):
|
|
77
72
|
The user or "owner" of this branch (often tied to a session).
|
|
78
73
|
name (str | None):
|
|
79
74
|
A human-readable name for this branch.
|
|
80
|
-
mailbox (Mailbox):
|
|
81
|
-
A mailbox for sending and receiving `Package` objects to/from other branches.
|
|
82
75
|
|
|
83
76
|
Note:
|
|
84
77
|
Actual implementations for chat, parse, operate, etc., are referenced
|
|
@@ -101,16 +94,10 @@ class Branch(Element, Communicatable, Relational):
|
|
|
101
94
|
description="A human-readable name of the branch (optional).",
|
|
102
95
|
)
|
|
103
96
|
|
|
104
|
-
mailbox: Mailbox = Field(
|
|
105
|
-
default_factory=Mailbox,
|
|
106
|
-
exclude=True,
|
|
107
|
-
description="Mailbox for cross-branch or external communication.",
|
|
108
|
-
)
|
|
109
|
-
|
|
110
97
|
_message_manager: MessageManager | None = PrivateAttr(None)
|
|
111
98
|
_action_manager: ActionManager | None = PrivateAttr(None)
|
|
112
99
|
_imodel_manager: iModelManager | None = PrivateAttr(None)
|
|
113
|
-
_log_manager:
|
|
100
|
+
_log_manager: DataLogger | None = PrivateAttr(None)
|
|
114
101
|
_operation_manager: OperationManager | None = PrivateAttr(None)
|
|
115
102
|
|
|
116
103
|
def __init__(
|
|
@@ -125,7 +112,7 @@ class Branch(Element, Communicatable, Relational):
|
|
|
125
112
|
parse_model: iModel | dict = None,
|
|
126
113
|
imodel: iModel = None, # deprecated, alias of chat_model
|
|
127
114
|
tools: FuncTool | list[FuncTool] = None, # ActionManager kwargs
|
|
128
|
-
log_config:
|
|
115
|
+
log_config: DataLoggerConfig | dict = None, # LogManager kwargs
|
|
129
116
|
system_datetime: bool | str = None,
|
|
130
117
|
system_template=None,
|
|
131
118
|
system_template_context: dict = None,
|
|
@@ -194,11 +181,11 @@ class Branch(Element, Communicatable, Relational):
|
|
|
194
181
|
system = f"Developer Prompt: {str(system)}" if system else ""
|
|
195
182
|
system = (LION_SYSTEM_MESSAGE + "\n\n" + system).strip()
|
|
196
183
|
|
|
184
|
+
# Note: system_template and system_template_context are deprecated
|
|
185
|
+
# Template rendering has been removed from the message system
|
|
197
186
|
self._message_manager.add_message(
|
|
198
187
|
system=system,
|
|
199
188
|
system_datetime=system_datetime,
|
|
200
|
-
template=system_template,
|
|
201
|
-
template_context=system_template_context,
|
|
202
189
|
recipient=self.id,
|
|
203
190
|
sender=system_sender or self.user or MessageRole.SYSTEM,
|
|
204
191
|
)
|
|
@@ -229,10 +216,10 @@ class Branch(Element, Communicatable, Relational):
|
|
|
229
216
|
# --- LogManager ---
|
|
230
217
|
if log_config:
|
|
231
218
|
if isinstance(log_config, dict):
|
|
232
|
-
log_config =
|
|
233
|
-
self._log_manager =
|
|
219
|
+
log_config = DataLoggerConfig(**log_config)
|
|
220
|
+
self._log_manager = DataLogger.from_config(log_config, logs=logs)
|
|
234
221
|
else:
|
|
235
|
-
self._log_manager =
|
|
222
|
+
self._log_manager = DataLogger(**settings.LOG_CONFIG, logs=logs)
|
|
236
223
|
|
|
237
224
|
self._operation_manager = OperationManager()
|
|
238
225
|
|
|
@@ -414,6 +401,7 @@ class Branch(Element, Communicatable, Relational):
|
|
|
414
401
|
pd.DataFrame: Each row represents a message, with columns defined by MESSAGE_FIELDS.
|
|
415
402
|
"""
|
|
416
403
|
from lionagi.protocols.generic.pile import Pile
|
|
404
|
+
from lionagi.protocols.messages.base import MESSAGE_FIELDS
|
|
417
405
|
|
|
418
406
|
if progression is None:
|
|
419
407
|
progression = self.msgs.progression
|
|
@@ -426,170 +414,6 @@ class Branch(Element, Communicatable, Relational):
|
|
|
426
414
|
p = Pile(collections=msgs)
|
|
427
415
|
return p.to_df(columns=MESSAGE_FIELDS)
|
|
428
416
|
|
|
429
|
-
# -------------------------------------------------------------------------
|
|
430
|
-
# Mailbox Send / Receive
|
|
431
|
-
# -------------------------------------------------------------------------
|
|
432
|
-
def send(
|
|
433
|
-
self,
|
|
434
|
-
recipient: IDType,
|
|
435
|
-
category: Optional["PackageCategory"],
|
|
436
|
-
item: Any,
|
|
437
|
-
request_source: IDType | None = None,
|
|
438
|
-
) -> None:
|
|
439
|
-
"""
|
|
440
|
-
Sends a `Package` (wrapped in a `Mail` object) to a specified recipient.
|
|
441
|
-
|
|
442
|
-
Args:
|
|
443
|
-
recipient (IDType):
|
|
444
|
-
ID of the recipient branch or component.
|
|
445
|
-
category (PackageCategory | None):
|
|
446
|
-
The category/type of the package (e.g., 'message', 'tool', 'imodel').
|
|
447
|
-
item (Any):
|
|
448
|
-
The payload to send (e.g., a message, tool reference, model, etc.).
|
|
449
|
-
request_source (IDType | None):
|
|
450
|
-
The ID that prompted or requested this send operation (optional).
|
|
451
|
-
"""
|
|
452
|
-
from lionagi.protocols.mail.package import Package
|
|
453
|
-
|
|
454
|
-
package = Package(
|
|
455
|
-
category=category,
|
|
456
|
-
item=item,
|
|
457
|
-
request_source=request_source,
|
|
458
|
-
)
|
|
459
|
-
|
|
460
|
-
mail = Mail(
|
|
461
|
-
sender=self.id,
|
|
462
|
-
recipient=recipient,
|
|
463
|
-
package=package,
|
|
464
|
-
)
|
|
465
|
-
self.mailbox.append_out(mail)
|
|
466
|
-
|
|
467
|
-
def receive(
|
|
468
|
-
self,
|
|
469
|
-
sender: IDType,
|
|
470
|
-
message: bool = False,
|
|
471
|
-
tool: bool = False,
|
|
472
|
-
imodel: bool = False,
|
|
473
|
-
) -> None:
|
|
474
|
-
"""
|
|
475
|
-
Retrieves and processes mail from a given sender according to the specified flags.
|
|
476
|
-
|
|
477
|
-
Args:
|
|
478
|
-
sender (IDType):
|
|
479
|
-
The ID of the mail sender.
|
|
480
|
-
message (bool):
|
|
481
|
-
If `True`, process packages categorized as "message".
|
|
482
|
-
tool (bool):
|
|
483
|
-
If `True`, process packages categorized as "tool".
|
|
484
|
-
imodel (bool):
|
|
485
|
-
If `True`, process packages categorized as "imodel".
|
|
486
|
-
|
|
487
|
-
Raises:
|
|
488
|
-
ValueError: If no mail exists from the specified sender,
|
|
489
|
-
or if a package is invalid for the chosen category.
|
|
490
|
-
"""
|
|
491
|
-
sender = ID.get_id(sender)
|
|
492
|
-
if sender not in self.mailbox.pending_ins.keys():
|
|
493
|
-
raise ValueError(f"No mail or package found from sender: {sender}")
|
|
494
|
-
|
|
495
|
-
skipped_requests = Progression()
|
|
496
|
-
while self.mailbox.pending_ins[sender]:
|
|
497
|
-
mail_id = self.mailbox.pending_ins[sender].popleft()
|
|
498
|
-
mail: Mail = self.mailbox.pile_[mail_id]
|
|
499
|
-
|
|
500
|
-
if mail.category == "message" and message:
|
|
501
|
-
if not isinstance(mail.package.item, RoledMessage):
|
|
502
|
-
raise ValueError(
|
|
503
|
-
"Invalid message package: The item must be a `RoledMessage`."
|
|
504
|
-
)
|
|
505
|
-
new_message = mail.package.item.clone()
|
|
506
|
-
new_message.sender = mail.sender
|
|
507
|
-
new_message.recipient = self.id
|
|
508
|
-
self.msgs.messages.include(new_message)
|
|
509
|
-
self.mailbox.pile_.pop(mail_id)
|
|
510
|
-
|
|
511
|
-
elif mail.category == "tool" and tool:
|
|
512
|
-
if not isinstance(mail.package.item, Tool):
|
|
513
|
-
raise ValueError(
|
|
514
|
-
"Invalid tool package: The item must be a `Tool` instance."
|
|
515
|
-
)
|
|
516
|
-
self._action_manager.register_tools(mail.package.item)
|
|
517
|
-
self.mailbox.pile_.pop(mail_id)
|
|
518
|
-
|
|
519
|
-
elif mail.category == "imodel" and imodel:
|
|
520
|
-
if not isinstance(mail.package.item, iModel):
|
|
521
|
-
raise ValueError(
|
|
522
|
-
"Invalid iModel package: The item must be an `iModel` instance."
|
|
523
|
-
)
|
|
524
|
-
self._imodel_manager.register_imodel(
|
|
525
|
-
mail.package.item.name or "chat", mail.package.item
|
|
526
|
-
)
|
|
527
|
-
self.mailbox.pile_.pop(mail_id)
|
|
528
|
-
|
|
529
|
-
else:
|
|
530
|
-
# If the category doesn't match the flags or is unhandled
|
|
531
|
-
skipped_requests.append(mail)
|
|
532
|
-
|
|
533
|
-
# Requeue any skipped mail
|
|
534
|
-
self.mailbox.pending_ins[sender] = skipped_requests
|
|
535
|
-
if len(self.mailbox.pending_ins[sender]) == 0:
|
|
536
|
-
self.mailbox.pending_ins.pop(sender)
|
|
537
|
-
|
|
538
|
-
async def asend(
|
|
539
|
-
self,
|
|
540
|
-
recipient: IDType,
|
|
541
|
-
category: PackageCategory | None,
|
|
542
|
-
package: Any,
|
|
543
|
-
request_source: IDType | None = None,
|
|
544
|
-
):
|
|
545
|
-
"""
|
|
546
|
-
Async version of `send()`.
|
|
547
|
-
|
|
548
|
-
Args:
|
|
549
|
-
recipient (IDType):
|
|
550
|
-
ID of the recipient branch or component.
|
|
551
|
-
category (PackageCategory | None):
|
|
552
|
-
The category/type of the package.
|
|
553
|
-
package (Any):
|
|
554
|
-
The item(s) to send (message/tool/model).
|
|
555
|
-
request_source (IDType | None):
|
|
556
|
-
The origin request ID (if any).
|
|
557
|
-
"""
|
|
558
|
-
async with self.mailbox.pile_:
|
|
559
|
-
self.send(recipient, category, package, request_source)
|
|
560
|
-
|
|
561
|
-
async def areceive(
|
|
562
|
-
self,
|
|
563
|
-
sender: IDType,
|
|
564
|
-
message: bool = False,
|
|
565
|
-
tool: bool = False,
|
|
566
|
-
imodel: bool = False,
|
|
567
|
-
) -> None:
|
|
568
|
-
"""
|
|
569
|
-
Async version of `receive()`.
|
|
570
|
-
|
|
571
|
-
Args:
|
|
572
|
-
sender (IDType):
|
|
573
|
-
The ID of the mail sender.
|
|
574
|
-
message (bool):
|
|
575
|
-
If `True`, process packages categorized as "message".
|
|
576
|
-
tool (bool):
|
|
577
|
-
If `True`, process packages categorized as "tool".
|
|
578
|
-
imodel (bool):
|
|
579
|
-
If `True`, process packages categorized as "imodel".
|
|
580
|
-
"""
|
|
581
|
-
async with self.mailbox.pile_:
|
|
582
|
-
self.receive(sender, message, tool, imodel)
|
|
583
|
-
|
|
584
|
-
def receive_all(self) -> None:
|
|
585
|
-
"""
|
|
586
|
-
Receives mail from all known senders without filtering.
|
|
587
|
-
|
|
588
|
-
(Duplicate method included in your snippet; you may unify or remove.)
|
|
589
|
-
"""
|
|
590
|
-
for key in self.mailbox.pending_ins:
|
|
591
|
-
self.receive(key)
|
|
592
|
-
|
|
593
417
|
def connect(
|
|
594
418
|
self,
|
|
595
419
|
provider: str = None,
|
|
@@ -632,7 +456,7 @@ class Branch(Element, Communicatable, Relational):
|
|
|
632
456
|
async def _connect(**kwargs):
|
|
633
457
|
"""connect to an api endpoint"""
|
|
634
458
|
api_call = await imodel.invoke(**kwargs)
|
|
635
|
-
self._log_manager.log(
|
|
459
|
+
self._log_manager.log(api_call)
|
|
636
460
|
return api_call.response
|
|
637
461
|
|
|
638
462
|
_connect.__name__ = name or imodel.endpoint.name
|
|
@@ -760,6 +584,7 @@ class Branch(Element, Communicatable, Relational):
|
|
|
760
584
|
image_detail: Literal["low", "high", "auto"] = None,
|
|
761
585
|
plain_content: str = None,
|
|
762
586
|
return_ins_res_message: bool = False,
|
|
587
|
+
include_token_usage_to_model: bool = False,
|
|
763
588
|
**kwargs,
|
|
764
589
|
) -> tuple[Instruction, AssistantResponse]:
|
|
765
590
|
"""
|
|
@@ -809,25 +634,27 @@ class Branch(Element, Communicatable, Relational):
|
|
|
809
634
|
tuple[Instruction, AssistantResponse]:
|
|
810
635
|
The `Instruction` object and the final `AssistantResponse`.
|
|
811
636
|
"""
|
|
812
|
-
from lionagi.operations.chat.chat import chat
|
|
637
|
+
from lionagi.operations.chat.chat import ChatParam, chat
|
|
813
638
|
|
|
814
639
|
return await chat(
|
|
815
640
|
self,
|
|
816
641
|
instruction=instruction,
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
642
|
+
chat_param=ChatParam(
|
|
643
|
+
guidance=guidance,
|
|
644
|
+
context=context,
|
|
645
|
+
sender=sender or self.user or "user",
|
|
646
|
+
recipient=recipient or self.id,
|
|
647
|
+
response_format=response_format or request_fields,
|
|
648
|
+
progression=progression,
|
|
649
|
+
tool_schemas=tool_schemas or [],
|
|
650
|
+
images=images or [],
|
|
651
|
+
image_detail=image_detail or "auto",
|
|
652
|
+
plain_content=plain_content or "",
|
|
653
|
+
include_token_usage_to_model=include_token_usage_to_model,
|
|
654
|
+
imodel=imodel or self.chat_model,
|
|
655
|
+
imodel_kw=kwargs,
|
|
656
|
+
),
|
|
829
657
|
return_ins_res_message=return_ins_res_message,
|
|
830
|
-
**kwargs,
|
|
831
658
|
)
|
|
832
659
|
|
|
833
660
|
async def parse(
|
|
@@ -889,25 +716,15 @@ class Branch(Element, Communicatable, Relational):
|
|
|
889
716
|
BaseModel | dict | str | None:
|
|
890
717
|
Parsed model instance, or a fallback based on `handle_validation`.
|
|
891
718
|
"""
|
|
892
|
-
from lionagi.operations.parse.parse import parse
|
|
893
719
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
similarity_threshold=similarity_threshold,
|
|
903
|
-
fuzzy_match=fuzzy_match,
|
|
904
|
-
handle_unmatched=handle_unmatched,
|
|
905
|
-
fill_value=fill_value,
|
|
906
|
-
fill_mapping=fill_mapping,
|
|
907
|
-
strict=strict,
|
|
908
|
-
suppress_conversion_errors=suppress_conversion_errors,
|
|
909
|
-
response_format=response_format,
|
|
910
|
-
)
|
|
720
|
+
_pms = {
|
|
721
|
+
k: v
|
|
722
|
+
for k, v in locals().items()
|
|
723
|
+
if k not in ("self", "_pms") and v is not None
|
|
724
|
+
}
|
|
725
|
+
from lionagi.operations.parse.parse import parse, prepare_parse_kws
|
|
726
|
+
|
|
727
|
+
return await parse(self, **prepare_parse_kws(self, **_pms))
|
|
911
728
|
|
|
912
729
|
async def operate(
|
|
913
730
|
self,
|
|
@@ -1026,39 +843,18 @@ class Branch(Element, Communicatable, Relational):
|
|
|
1026
843
|
- If both `operative_model` and `response_format` or `request_model` are given.
|
|
1027
844
|
- If the LLM's response cannot be parsed into the expected format and `handle_validation='raise'`.
|
|
1028
845
|
"""
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
self,
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
sender=sender,
|
|
1038
|
-
recipient=recipient,
|
|
1039
|
-
progression=progression,
|
|
1040
|
-
chat_model=chat_model,
|
|
1041
|
-
invoke_actions=invoke_actions,
|
|
1042
|
-
tool_schemas=tool_schemas,
|
|
1043
|
-
images=images,
|
|
1044
|
-
image_detail=image_detail,
|
|
1045
|
-
parse_model=parse_model,
|
|
1046
|
-
skip_validation=skip_validation,
|
|
1047
|
-
tools=tools,
|
|
1048
|
-
operative=operative,
|
|
1049
|
-
response_format=response_format,
|
|
1050
|
-
actions=actions,
|
|
1051
|
-
reason=reason,
|
|
1052
|
-
call_params=call_params,
|
|
1053
|
-
action_strategy=action_strategy,
|
|
1054
|
-
verbose_action=verbose_action,
|
|
1055
|
-
field_models=field_models,
|
|
1056
|
-
exclude_fields=exclude_fields,
|
|
1057
|
-
handle_validation=handle_validation,
|
|
1058
|
-
include_token_usage_to_model=include_token_usage_to_model,
|
|
1059
|
-
**kwargs,
|
|
846
|
+
_pms = {
|
|
847
|
+
k: v
|
|
848
|
+
for k, v in locals().items()
|
|
849
|
+
if k not in ("self", "_pms") and v is not None
|
|
850
|
+
}
|
|
851
|
+
from lionagi.operations.operate.operate import (
|
|
852
|
+
operate,
|
|
853
|
+
prepare_operate_kw,
|
|
1060
854
|
)
|
|
1061
855
|
|
|
856
|
+
return await operate(self, **prepare_operate_kw(self, **_pms))
|
|
857
|
+
|
|
1062
858
|
async def communicate(
|
|
1063
859
|
self,
|
|
1064
860
|
instruction: Instruction | JsonValue = None,
|
|
@@ -1132,44 +928,19 @@ class Branch(Element, Communicatable, Relational):
|
|
|
1132
928
|
- A dict of the requested fields,
|
|
1133
929
|
- or `None` if parsing fails and `handle_validation='return_none'`.
|
|
1134
930
|
"""
|
|
1135
|
-
|
|
931
|
+
_pms = {
|
|
932
|
+
k: v
|
|
933
|
+
for k, v in locals().items()
|
|
934
|
+
if k not in ("self", "_pms", "kwargs") and v is not None
|
|
935
|
+
}
|
|
936
|
+
_pms.update(kwargs)
|
|
1136
937
|
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
guidance=guidance,
|
|
1141
|
-
context=context,
|
|
1142
|
-
plain_content=plain_content,
|
|
1143
|
-
sender=sender,
|
|
1144
|
-
recipient=recipient,
|
|
1145
|
-
progression=progression,
|
|
1146
|
-
response_format=response_format,
|
|
1147
|
-
request_fields=request_fields,
|
|
1148
|
-
chat_model=chat_model,
|
|
1149
|
-
parse_model=parse_model,
|
|
1150
|
-
skip_validation=skip_validation,
|
|
1151
|
-
images=images,
|
|
1152
|
-
image_detail=image_detail,
|
|
1153
|
-
num_parse_retries=num_parse_retries,
|
|
1154
|
-
clear_messages=clear_messages,
|
|
1155
|
-
include_token_usage_to_model=include_token_usage_to_model,
|
|
1156
|
-
**kwargs,
|
|
938
|
+
from lionagi.operations.communicate.communicate import (
|
|
939
|
+
communicate,
|
|
940
|
+
prepare_communicate_kw,
|
|
1157
941
|
)
|
|
1158
942
|
|
|
1159
|
-
|
|
1160
|
-
self,
|
|
1161
|
-
action_request: ActionRequest | BaseModel | dict,
|
|
1162
|
-
suppress_errors: bool,
|
|
1163
|
-
verbose_action: bool,
|
|
1164
|
-
) -> ActionResponse:
|
|
1165
|
-
from lionagi.operations._act.act import _act
|
|
1166
|
-
|
|
1167
|
-
return await _act(
|
|
1168
|
-
branch=self,
|
|
1169
|
-
action_request=action_request,
|
|
1170
|
-
suppress_errors=suppress_errors,
|
|
1171
|
-
verbose_action=verbose_action,
|
|
1172
|
-
)
|
|
943
|
+
return await communicate(self, **prepare_communicate_kw(self, **_pms))
|
|
1173
944
|
|
|
1174
945
|
async def act(
|
|
1175
946
|
self,
|
|
@@ -1180,54 +951,15 @@ class Branch(Element, Communicatable, Relational):
|
|
|
1180
951
|
suppress_errors: bool = True,
|
|
1181
952
|
call_params: AlcallParams = None,
|
|
1182
953
|
) -> list[ActionResponse]:
|
|
1183
|
-
global _DEFAULT_ALCALL_PARAMS
|
|
1184
|
-
if call_params is None:
|
|
1185
|
-
if _DEFAULT_ALCALL_PARAMS is None:
|
|
1186
|
-
_DEFAULT_ALCALL_PARAMS = AlcallParams(output_dropna=True)
|
|
1187
|
-
call_params = _DEFAULT_ALCALL_PARAMS
|
|
1188
|
-
|
|
1189
|
-
kw = {
|
|
1190
|
-
"suppress_errors": suppress_errors,
|
|
1191
|
-
"verbose_action": verbose_action,
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
|
-
match strategy:
|
|
1195
|
-
case "concurrent":
|
|
1196
|
-
return await self._concurrent_act(
|
|
1197
|
-
action_request, call_params, **kw
|
|
1198
|
-
)
|
|
1199
|
-
case "sequential":
|
|
1200
|
-
return await self._sequential_act(action_request, **kw)
|
|
1201
|
-
case _:
|
|
1202
|
-
raise ValueError(
|
|
1203
|
-
"Invalid strategy. Choose 'concurrent' or 'sequential'."
|
|
1204
|
-
)
|
|
1205
954
|
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
return await call_params(action_request, self._act, **kwargs)
|
|
955
|
+
_pms = {
|
|
956
|
+
k: v
|
|
957
|
+
for k, v in locals().items()
|
|
958
|
+
if k not in ("self", "_pms") and v is not None
|
|
959
|
+
}
|
|
960
|
+
from lionagi.operations.act.act import act, prepare_act_kw
|
|
1213
961
|
|
|
1214
|
-
|
|
1215
|
-
self,
|
|
1216
|
-
action_request: ActionRequest | BaseModel | dict,
|
|
1217
|
-
suppress_errors: bool = True,
|
|
1218
|
-
verbose_action: bool = False,
|
|
1219
|
-
) -> list:
|
|
1220
|
-
action_request = (
|
|
1221
|
-
action_request
|
|
1222
|
-
if isinstance(action_request, list)
|
|
1223
|
-
else [action_request]
|
|
1224
|
-
)
|
|
1225
|
-
results = []
|
|
1226
|
-
for req in action_request:
|
|
1227
|
-
results.append(
|
|
1228
|
-
await self._act(req, verbose_action, suppress_errors)
|
|
1229
|
-
)
|
|
1230
|
-
return results
|
|
962
|
+
return await act(self, **prepare_act_kw(self, **_pms))
|
|
1231
963
|
|
|
1232
964
|
async def interpret(
|
|
1233
965
|
self,
|
|
@@ -1275,43 +1007,20 @@ class Branch(Element, Communicatable, Relational):
|
|
|
1275
1007
|
# refined might be "Explain step-by-step how to set up a marketing analytics
|
|
1276
1008
|
# pipeline to track campaign performance..."
|
|
1277
1009
|
"""
|
|
1278
|
-
from lionagi.operations.interpret.interpret import interpret
|
|
1279
|
-
|
|
1280
|
-
return await interpret(
|
|
1281
|
-
self,
|
|
1282
|
-
text=text,
|
|
1283
|
-
domain=domain,
|
|
1284
|
-
style=style,
|
|
1285
|
-
interpret_model=interpret_model,
|
|
1286
|
-
**kwargs,
|
|
1287
|
-
)
|
|
1288
|
-
|
|
1289
|
-
async def instruct(
|
|
1290
|
-
self,
|
|
1291
|
-
instruct: "Instruct",
|
|
1292
|
-
/,
|
|
1293
|
-
**kwargs,
|
|
1294
|
-
):
|
|
1295
|
-
"""
|
|
1296
|
-
A convenience method that chooses between `operate()` and `communicate()`
|
|
1297
|
-
based on the contents of an `Instruct` object.
|
|
1298
|
-
|
|
1299
|
-
If the `Instruct` indicates tool usage or advanced response format,
|
|
1300
|
-
`operate()` is used. Otherwise, it defaults to `communicate()`.
|
|
1301
1010
|
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1011
|
+
_pms = {
|
|
1012
|
+
k: v
|
|
1013
|
+
for k, v in locals().items()
|
|
1014
|
+
if k not in ("self", "_pms", "kwargs") and v is not None
|
|
1015
|
+
}
|
|
1016
|
+
_pms.update(kwargs)
|
|
1307
1017
|
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
from lionagi.operations.instruct.instruct import instruct as _ins
|
|
1018
|
+
from lionagi.operations.interpret.interpret import (
|
|
1019
|
+
interpret,
|
|
1020
|
+
prepare_interpret_kw,
|
|
1021
|
+
)
|
|
1313
1022
|
|
|
1314
|
-
return await
|
|
1023
|
+
return await interpret(self, **prepare_interpret_kw(self, **_pms))
|
|
1315
1024
|
|
|
1316
1025
|
async def ReAct(
|
|
1317
1026
|
self,
|
|
@@ -1413,6 +1122,13 @@ class Branch(Element, Communicatable, Relational):
|
|
|
1413
1122
|
"""
|
|
1414
1123
|
from lionagi.operations.ReAct.ReAct import ReAct
|
|
1415
1124
|
|
|
1125
|
+
# Remove potential duplicate parameters from kwargs
|
|
1126
|
+
kwargs_filtered = {
|
|
1127
|
+
k: v
|
|
1128
|
+
for k, v in kwargs.items()
|
|
1129
|
+
if k not in {"verbose_analysis", "verbose_action"}
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1416
1132
|
return await ReAct(
|
|
1417
1133
|
self,
|
|
1418
1134
|
instruct,
|
|
@@ -1438,7 +1154,7 @@ class Branch(Element, Communicatable, Relational):
|
|
|
1438
1154
|
reasoning_effort=reasoning_effort,
|
|
1439
1155
|
display_as=display_as,
|
|
1440
1156
|
include_token_usage_to_model=include_token_usage_to_model,
|
|
1441
|
-
**
|
|
1157
|
+
**kwargs_filtered,
|
|
1442
1158
|
)
|
|
1443
1159
|
|
|
1444
1160
|
async def ReActStream(
|
|
@@ -1466,40 +1182,114 @@ class Branch(Element, Communicatable, Relational):
|
|
|
1466
1182
|
include_token_usage_to_model: bool = True,
|
|
1467
1183
|
**kwargs,
|
|
1468
1184
|
) -> AsyncGenerator:
|
|
1185
|
+
from lionagi.ln.fuzzy import FuzzyMatchKeysParams
|
|
1469
1186
|
from lionagi.operations.ReAct.ReAct import ReActStream
|
|
1187
|
+
from lionagi.operations.ReAct.utils import ReActAnalysis
|
|
1188
|
+
from lionagi.operations.types import (
|
|
1189
|
+
ActionParam,
|
|
1190
|
+
ChatParam,
|
|
1191
|
+
InterpretParam,
|
|
1192
|
+
ParseParam,
|
|
1193
|
+
)
|
|
1194
|
+
|
|
1195
|
+
# Convert Instruct to dict if needed
|
|
1196
|
+
instruct_dict = (
|
|
1197
|
+
instruct.to_dict()
|
|
1198
|
+
if isinstance(instruct, Instruct)
|
|
1199
|
+
else dict(instruct)
|
|
1200
|
+
)
|
|
1201
|
+
|
|
1202
|
+
# Build InterpretContext if interpretation requested
|
|
1203
|
+
intp_param = None
|
|
1204
|
+
if interpret:
|
|
1205
|
+
intp_param = InterpretParam(
|
|
1206
|
+
domain=interpret_domain or "general",
|
|
1207
|
+
style=interpret_style or "concise",
|
|
1208
|
+
sample_writing=interpret_sample or "",
|
|
1209
|
+
imodel=interpret_model or analysis_model or self.chat_model,
|
|
1210
|
+
imodel_kw=interpret_kwargs or {},
|
|
1211
|
+
)
|
|
1212
|
+
|
|
1213
|
+
# Build ChatContext
|
|
1214
|
+
chat_param = ChatParam(
|
|
1215
|
+
guidance=instruct_dict.get("guidance"),
|
|
1216
|
+
context=instruct_dict.get("context"),
|
|
1217
|
+
sender=self.user or "user",
|
|
1218
|
+
recipient=self.id,
|
|
1219
|
+
response_format=None,
|
|
1220
|
+
progression=None,
|
|
1221
|
+
tool_schemas=tool_schemas or [],
|
|
1222
|
+
images=[],
|
|
1223
|
+
image_detail="auto",
|
|
1224
|
+
plain_content="",
|
|
1225
|
+
include_token_usage_to_model=include_token_usage_to_model,
|
|
1226
|
+
imodel=analysis_model or self.chat_model,
|
|
1227
|
+
imodel_kw=kwargs,
|
|
1228
|
+
)
|
|
1229
|
+
|
|
1230
|
+
# Build ActionContext
|
|
1231
|
+
action_param = None
|
|
1232
|
+
if tools is not None or tool_schemas is not None:
|
|
1233
|
+
from lionagi.operations.act.act import _get_default_call_params
|
|
1234
|
+
|
|
1235
|
+
action_param = ActionParam(
|
|
1236
|
+
action_call_params=_get_default_call_params(),
|
|
1237
|
+
tools=tools or True,
|
|
1238
|
+
strategy="concurrent",
|
|
1239
|
+
suppress_errors=True,
|
|
1240
|
+
verbose_action=False,
|
|
1241
|
+
)
|
|
1242
|
+
|
|
1243
|
+
# Build ParseContext
|
|
1244
|
+
from lionagi.operations.parse.parse import get_default_call
|
|
1245
|
+
|
|
1246
|
+
parse_param = ParseParam(
|
|
1247
|
+
response_format=ReActAnalysis,
|
|
1248
|
+
fuzzy_match_params=FuzzyMatchKeysParams(),
|
|
1249
|
+
handle_validation="return_value",
|
|
1250
|
+
alcall_params=get_default_call(),
|
|
1251
|
+
imodel=analysis_model or self.chat_model,
|
|
1252
|
+
imodel_kw={},
|
|
1253
|
+
)
|
|
1254
|
+
|
|
1255
|
+
# Response context for final answer
|
|
1256
|
+
resp_ctx = response_kwargs or {}
|
|
1257
|
+
if response_format:
|
|
1258
|
+
resp_ctx["response_format"] = response_format
|
|
1470
1259
|
|
|
1471
1260
|
async for result in ReActStream(
|
|
1472
1261
|
self,
|
|
1473
|
-
instruct,
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1262
|
+
instruction=instruct_dict.get("instruction", str(instruct)),
|
|
1263
|
+
chat_param=chat_param,
|
|
1264
|
+
action_param=action_param,
|
|
1265
|
+
parse_param=parse_param,
|
|
1266
|
+
intp_param=intp_param,
|
|
1267
|
+
resp_ctx=resp_ctx,
|
|
1268
|
+
reasoning_effort=reasoning_effort,
|
|
1269
|
+
reason=True,
|
|
1270
|
+
field_models=None,
|
|
1271
|
+
handle_validation="return_value",
|
|
1272
|
+
invoke_actions=True,
|
|
1273
|
+
clear_messages=False,
|
|
1483
1274
|
intermediate_response_options=intermediate_response_options,
|
|
1484
1275
|
intermediate_listable=intermediate_listable,
|
|
1485
|
-
|
|
1486
|
-
extension_allowed=extension_allowed,
|
|
1276
|
+
intermediate_nullable=False,
|
|
1487
1277
|
max_extensions=max_extensions,
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
verbose_analysis=True,
|
|
1278
|
+
extension_allowed=extension_allowed,
|
|
1279
|
+
verbose_analysis=verbose,
|
|
1491
1280
|
display_as=display_as,
|
|
1492
1281
|
verbose_length=verbose_length,
|
|
1493
|
-
|
|
1494
|
-
**kwargs,
|
|
1282
|
+
continue_after_failed_response=False,
|
|
1495
1283
|
):
|
|
1496
|
-
analysis, str_ = result
|
|
1497
1284
|
if verbose:
|
|
1285
|
+
analysis, str_ = result
|
|
1498
1286
|
from lionagi.libs.schema.as_readable import as_readable
|
|
1499
1287
|
|
|
1500
1288
|
str_ += "\n---------\n"
|
|
1501
1289
|
as_readable(str_, md=True, display_str=True)
|
|
1502
|
-
|
|
1290
|
+
yield analysis
|
|
1291
|
+
else:
|
|
1292
|
+
yield result
|
|
1503
1293
|
|
|
1504
1294
|
|
|
1505
1295
|
# File: lionagi/session/branch.py
|