lionagi 0.1.2__py3-none-any.whl → 0.2.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 +60 -5
- lionagi/core/__init__.py +0 -25
- lionagi/core/_setting/_setting.py +59 -0
- lionagi/core/action/__init__.py +14 -0
- lionagi/core/action/function_calling.py +136 -0
- lionagi/core/action/manual.py +1 -0
- lionagi/core/action/node.py +109 -0
- lionagi/core/action/tool.py +114 -0
- lionagi/core/action/tool_manager.py +356 -0
- lionagi/core/agent/base_agent.py +27 -13
- lionagi/core/agent/eval/evaluator.py +1 -0
- lionagi/core/agent/eval/vote.py +40 -0
- lionagi/core/agent/learn/learner.py +59 -0
- lionagi/core/agent/plan/unit_template.py +1 -0
- lionagi/core/collections/__init__.py +17 -0
- lionagi/core/{generic/data_logger.py → collections/_logger.py} +69 -55
- lionagi/core/collections/abc/__init__.py +53 -0
- lionagi/core/collections/abc/component.py +615 -0
- lionagi/core/collections/abc/concepts.py +297 -0
- lionagi/core/collections/abc/exceptions.py +150 -0
- lionagi/core/collections/abc/util.py +45 -0
- lionagi/core/collections/exchange.py +161 -0
- lionagi/core/collections/flow.py +426 -0
- lionagi/core/collections/model.py +419 -0
- lionagi/core/collections/pile.py +913 -0
- lionagi/core/collections/progression.py +236 -0
- lionagi/core/collections/util.py +64 -0
- lionagi/core/director/direct.py +314 -0
- lionagi/core/director/director.py +2 -0
- lionagi/core/{execute/branch_executor.py → engine/branch_engine.py} +134 -97
- lionagi/core/{execute/instruction_map_executor.py → engine/instruction_map_engine.py} +80 -55
- lionagi/{experimental/directive/evaluator → core/engine}/script_engine.py +17 -1
- lionagi/core/executor/base_executor.py +90 -0
- lionagi/core/{execute/structure_executor.py → executor/graph_executor.py} +62 -66
- lionagi/core/{execute → executor}/neo4j_executor.py +70 -67
- lionagi/core/generic/__init__.py +3 -33
- lionagi/core/generic/edge.py +29 -79
- lionagi/core/generic/edge_condition.py +16 -0
- lionagi/core/generic/graph.py +236 -0
- lionagi/core/generic/hyperedge.py +1 -0
- lionagi/core/generic/node.py +156 -221
- lionagi/core/generic/tree.py +48 -0
- lionagi/core/generic/tree_node.py +79 -0
- lionagi/core/mail/__init__.py +12 -0
- lionagi/core/mail/mail.py +25 -0
- lionagi/core/mail/mail_manager.py +139 -58
- lionagi/core/mail/package.py +45 -0
- lionagi/core/mail/start_mail.py +36 -0
- lionagi/core/message/__init__.py +19 -0
- lionagi/core/message/action_request.py +133 -0
- lionagi/core/message/action_response.py +135 -0
- lionagi/core/message/assistant_response.py +95 -0
- lionagi/core/message/instruction.py +234 -0
- lionagi/core/message/message.py +101 -0
- lionagi/core/message/system.py +86 -0
- lionagi/core/message/util.py +283 -0
- lionagi/core/report/__init__.py +4 -0
- lionagi/core/report/base.py +217 -0
- lionagi/core/report/form.py +231 -0
- lionagi/core/report/report.py +166 -0
- lionagi/core/report/util.py +28 -0
- lionagi/core/rule/_default.py +16 -0
- lionagi/core/rule/action.py +99 -0
- lionagi/core/rule/base.py +238 -0
- lionagi/core/rule/boolean.py +56 -0
- lionagi/core/rule/choice.py +47 -0
- lionagi/core/rule/mapping.py +96 -0
- lionagi/core/rule/number.py +71 -0
- lionagi/core/rule/rulebook.py +109 -0
- lionagi/core/rule/string.py +52 -0
- lionagi/core/rule/util.py +35 -0
- lionagi/core/session/branch.py +431 -0
- lionagi/core/session/directive_mixin.py +287 -0
- lionagi/core/session/session.py +229 -903
- lionagi/core/structure/__init__.py +1 -0
- lionagi/core/structure/chain.py +1 -0
- lionagi/core/structure/forest.py +1 -0
- lionagi/core/structure/graph.py +1 -0
- lionagi/core/structure/tree.py +1 -0
- lionagi/core/unit/__init__.py +5 -0
- lionagi/core/unit/parallel_unit.py +245 -0
- lionagi/core/unit/template/action.py +81 -0
- lionagi/core/unit/template/base.py +51 -0
- lionagi/core/unit/template/plan.py +84 -0
- lionagi/core/unit/template/predict.py +109 -0
- lionagi/core/unit/template/score.py +124 -0
- lionagi/core/unit/template/select.py +104 -0
- lionagi/core/unit/unit.py +362 -0
- lionagi/core/unit/unit_form.py +305 -0
- lionagi/core/unit/unit_mixin.py +1168 -0
- lionagi/core/unit/util.py +71 -0
- lionagi/core/validator/validator.py +364 -0
- lionagi/core/work/work.py +76 -0
- lionagi/core/work/work_function.py +101 -0
- lionagi/core/work/work_queue.py +103 -0
- lionagi/core/work/worker.py +258 -0
- lionagi/core/work/worklog.py +120 -0
- lionagi/experimental/compressor/base.py +46 -0
- lionagi/experimental/compressor/llm_compressor.py +247 -0
- lionagi/experimental/compressor/llm_summarizer.py +61 -0
- lionagi/experimental/compressor/util.py +70 -0
- lionagi/experimental/directive/__init__.py +19 -0
- lionagi/experimental/directive/parser/base_parser.py +69 -2
- lionagi/experimental/directive/{template_ → template}/base_template.py +17 -1
- lionagi/{libs/ln_tokenizer.py → experimental/directive/tokenizer.py} +16 -0
- lionagi/experimental/{directive/evaluator → evaluator}/ast_evaluator.py +16 -0
- lionagi/experimental/{directive/evaluator → evaluator}/base_evaluator.py +16 -0
- lionagi/experimental/knowledge/base.py +10 -0
- lionagi/experimental/memory/__init__.py +0 -0
- lionagi/experimental/strategies/__init__.py +0 -0
- lionagi/experimental/strategies/base.py +1 -0
- lionagi/integrations/bridge/langchain_/documents.py +4 -0
- lionagi/integrations/bridge/llamaindex_/index.py +30 -0
- lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +6 -0
- lionagi/integrations/chunker/chunk.py +161 -24
- lionagi/integrations/config/oai_configs.py +34 -3
- lionagi/integrations/config/openrouter_configs.py +14 -2
- lionagi/integrations/loader/load.py +122 -21
- lionagi/integrations/loader/load_util.py +6 -77
- lionagi/integrations/provider/_mapping.py +46 -0
- lionagi/integrations/provider/litellm.py +2 -1
- lionagi/integrations/provider/mlx_service.py +16 -9
- lionagi/integrations/provider/oai.py +91 -4
- lionagi/integrations/provider/ollama.py +6 -5
- lionagi/integrations/provider/openrouter.py +115 -8
- lionagi/integrations/provider/services.py +2 -2
- lionagi/integrations/provider/transformers.py +18 -22
- lionagi/integrations/storage/__init__.py +3 -3
- lionagi/integrations/storage/neo4j.py +52 -60
- lionagi/integrations/storage/storage_util.py +44 -46
- lionagi/integrations/storage/structure_excel.py +43 -26
- lionagi/integrations/storage/to_excel.py +11 -4
- lionagi/libs/__init__.py +22 -1
- lionagi/libs/ln_api.py +75 -20
- lionagi/libs/ln_context.py +37 -0
- lionagi/libs/ln_convert.py +21 -9
- lionagi/libs/ln_func_call.py +69 -28
- lionagi/libs/ln_image.py +107 -0
- lionagi/libs/ln_nested.py +26 -11
- lionagi/libs/ln_parse.py +82 -23
- lionagi/libs/ln_queue.py +16 -0
- lionagi/libs/ln_tokenize.py +164 -0
- lionagi/libs/ln_validate.py +16 -0
- lionagi/libs/special_tokens.py +172 -0
- lionagi/libs/sys_util.py +95 -24
- lionagi/lions/coder/code_form.py +13 -0
- lionagi/lions/coder/coder.py +50 -3
- lionagi/lions/coder/util.py +30 -25
- lionagi/tests/libs/test_func_call.py +23 -21
- lionagi/tests/libs/test_nested.py +36 -21
- lionagi/tests/libs/test_parse.py +1 -1
- lionagi/tests/test_core/collections/__init__.py +0 -0
- lionagi/tests/test_core/collections/test_component.py +206 -0
- lionagi/tests/test_core/collections/test_exchange.py +138 -0
- lionagi/tests/test_core/collections/test_flow.py +145 -0
- lionagi/tests/test_core/collections/test_pile.py +171 -0
- lionagi/tests/test_core/collections/test_progression.py +129 -0
- lionagi/tests/test_core/generic/test_edge.py +67 -0
- lionagi/tests/test_core/generic/test_graph.py +96 -0
- lionagi/tests/test_core/generic/test_node.py +106 -0
- lionagi/tests/test_core/generic/test_tree_node.py +73 -0
- lionagi/tests/test_core/test_branch.py +115 -294
- lionagi/tests/test_core/test_form.py +46 -0
- lionagi/tests/test_core/test_report.py +105 -0
- lionagi/tests/test_core/test_validator.py +111 -0
- lionagi/version.py +1 -1
- lionagi-0.2.1.dist-info/LICENSE +202 -0
- lionagi-0.2.1.dist-info/METADATA +272 -0
- lionagi-0.2.1.dist-info/RECORD +240 -0
- lionagi/core/branch/base.py +0 -653
- lionagi/core/branch/branch.py +0 -474
- lionagi/core/branch/flow_mixin.py +0 -96
- lionagi/core/branch/util.py +0 -323
- lionagi/core/direct/__init__.py +0 -19
- lionagi/core/direct/cot.py +0 -123
- lionagi/core/direct/plan.py +0 -164
- lionagi/core/direct/predict.py +0 -166
- lionagi/core/direct/react.py +0 -171
- lionagi/core/direct/score.py +0 -279
- lionagi/core/direct/select.py +0 -170
- lionagi/core/direct/sentiment.py +0 -1
- lionagi/core/direct/utils.py +0 -110
- lionagi/core/direct/vote.py +0 -64
- lionagi/core/execute/base_executor.py +0 -47
- lionagi/core/flow/baseflow.py +0 -23
- lionagi/core/flow/monoflow/ReAct.py +0 -240
- lionagi/core/flow/monoflow/__init__.py +0 -9
- lionagi/core/flow/monoflow/chat.py +0 -95
- lionagi/core/flow/monoflow/chat_mixin.py +0 -253
- lionagi/core/flow/monoflow/followup.py +0 -215
- lionagi/core/flow/polyflow/__init__.py +0 -1
- lionagi/core/flow/polyflow/chat.py +0 -251
- lionagi/core/form/action_form.py +0 -26
- lionagi/core/form/field_validator.py +0 -287
- lionagi/core/form/form.py +0 -302
- lionagi/core/form/mixin.py +0 -214
- lionagi/core/form/scored_form.py +0 -13
- lionagi/core/generic/action.py +0 -26
- lionagi/core/generic/component.py +0 -532
- lionagi/core/generic/condition.py +0 -46
- lionagi/core/generic/mail.py +0 -90
- lionagi/core/generic/mailbox.py +0 -36
- lionagi/core/generic/relation.py +0 -70
- lionagi/core/generic/signal.py +0 -22
- lionagi/core/generic/structure.py +0 -362
- lionagi/core/generic/transfer.py +0 -20
- lionagi/core/generic/work.py +0 -40
- lionagi/core/graph/graph.py +0 -126
- lionagi/core/graph/tree.py +0 -190
- lionagi/core/mail/schema.py +0 -63
- lionagi/core/messages/schema.py +0 -325
- lionagi/core/tool/__init__.py +0 -5
- lionagi/core/tool/tool.py +0 -28
- lionagi/core/tool/tool_manager.py +0 -283
- lionagi/experimental/report/form.py +0 -64
- lionagi/experimental/report/report.py +0 -138
- lionagi/experimental/report/util.py +0 -47
- lionagi/experimental/tool/function_calling.py +0 -43
- lionagi/experimental/tool/manual.py +0 -66
- lionagi/experimental/tool/schema.py +0 -59
- lionagi/experimental/tool/tool_manager.py +0 -138
- lionagi/experimental/tool/util.py +0 -16
- lionagi/experimental/validator/rule.py +0 -139
- lionagi/experimental/validator/validator.py +0 -56
- lionagi/experimental/work/__init__.py +0 -10
- lionagi/experimental/work/async_queue.py +0 -54
- lionagi/experimental/work/schema.py +0 -73
- lionagi/experimental/work/work_function.py +0 -67
- lionagi/experimental/work/worker.py +0 -56
- lionagi/experimental/work2/form.py +0 -371
- lionagi/experimental/work2/report.py +0 -289
- lionagi/experimental/work2/schema.py +0 -30
- lionagi/experimental/work2/tests.py +0 -72
- lionagi/experimental/work2/work_function.py +0 -89
- lionagi/experimental/work2/worker.py +0 -12
- lionagi/integrations/bridge/llamaindex_/get_index.py +0 -294
- lionagi/tests/test_core/generic/test_component.py +0 -89
- lionagi/tests/test_core/test_base_branch.py +0 -426
- lionagi/tests/test_core/test_chat_flow.py +0 -63
- lionagi/tests/test_core/test_mail_manager.py +0 -75
- lionagi/tests/test_core/test_prompts.py +0 -51
- lionagi/tests/test_core/test_session.py +0 -254
- lionagi/tests/test_core/test_session_base_util.py +0 -313
- lionagi/tests/test_core/test_tool_manager.py +0 -95
- lionagi-0.1.2.dist-info/LICENSE +0 -9
- lionagi-0.1.2.dist-info/METADATA +0 -174
- lionagi-0.1.2.dist-info/RECORD +0 -206
- /lionagi/core/{branch → _setting}/__init__.py +0 -0
- /lionagi/core/{execute → agent/eval}/__init__.py +0 -0
- /lionagi/core/{flow → agent/learn}/__init__.py +0 -0
- /lionagi/core/{form → agent/plan}/__init__.py +0 -0
- /lionagi/core/{branch/executable_branch.py → agent/plan/plan.py} +0 -0
- /lionagi/core/{graph → director}/__init__.py +0 -0
- /lionagi/core/{messages → engine}/__init__.py +0 -0
- /lionagi/{experimental/directive/evaluator → core/engine}/sandbox_.py +0 -0
- /lionagi/{experimental/directive/evaluator → core/executor}/__init__.py +0 -0
- /lionagi/{experimental/directive/template_ → core/rule}/__init__.py +0 -0
- /lionagi/{experimental/report → core/unit/template}/__init__.py +0 -0
- /lionagi/{experimental/tool → core/validator}/__init__.py +0 -0
- /lionagi/{experimental/validator → core/work}/__init__.py +0 -0
- /lionagi/experimental/{work2 → compressor}/__init__.py +0 -0
- /lionagi/{core/flow/mono_chat_mixin.py → experimental/directive/template/__init__.py} +0 -0
- /lionagi/experimental/directive/{schema.py → template/schema.py} +0 -0
- /lionagi/experimental/{work2/util.py → evaluator/__init__.py} +0 -0
- /lionagi/experimental/{work2/work.py → knowledge/__init__.py} +0 -0
- /lionagi/{tests/libs/test_async.py → experimental/knowledge/graph.py} +0 -0
- {lionagi-0.1.2.dist-info → lionagi-0.2.1.dist-info}/WHEEL +0 -0
- {lionagi-0.1.2.dist-info → lionagi-0.2.1.dist-info}/top_level.txt +0 -0
lionagi/core/generic/relation.py
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
A module for representing relationships between nodes in a graph structure,
|
3
|
-
encapsulating incoming and outgoing edges.
|
4
|
-
"""
|
5
|
-
|
6
|
-
from pydantic import Field
|
7
|
-
from pydantic.dataclasses import dataclass
|
8
|
-
from lionagi.libs import convert
|
9
|
-
from lionagi.core.generic.edge import Edge
|
10
|
-
|
11
|
-
|
12
|
-
@dataclass
|
13
|
-
class Relations:
|
14
|
-
"""
|
15
|
-
Represents the relationships of a node via its incoming and outgoing edges.
|
16
|
-
|
17
|
-
This class stores edges in two dictionaries: `preceding` for outgoing edges
|
18
|
-
and `succeeding` for incoming edges. It provides properties to access all
|
19
|
-
edges together and to get a unique set of all connected node IDs.
|
20
|
-
|
21
|
-
Attributes:
|
22
|
-
preceding (dict[str, Edge]): A dictionary of outgoing edges from the
|
23
|
-
node, with the edge ID as the key and the `Edge` object as the
|
24
|
-
value. Represents edges leading from this node to other nodes.
|
25
|
-
succeeding (dict[str, Edge]): A dictionary of incoming edges to the
|
26
|
-
node, with the edge ID as the key and the `Edge` object as the
|
27
|
-
value. Represents edges from other nodes leading to this node.
|
28
|
-
"""
|
29
|
-
|
30
|
-
points_to: dict[str, Edge] = Field(
|
31
|
-
title="Outgoing edges",
|
32
|
-
default_factory=dict,
|
33
|
-
description="The Outgoing edges of the node, reads self precedes other, \
|
34
|
-
{edge_id: Edge}",
|
35
|
-
)
|
36
|
-
|
37
|
-
pointed_by: dict[str, Edge] = Field(
|
38
|
-
title="Incoming edges",
|
39
|
-
default_factory=dict,
|
40
|
-
description="The Incoming edges of the node, reads self succeeds other, \
|
41
|
-
{edge_id: Edge}",
|
42
|
-
)
|
43
|
-
|
44
|
-
@property
|
45
|
-
def all_edges(self) -> dict[str, Edge]:
|
46
|
-
"""
|
47
|
-
Combines and returns all incoming and outgoing edges of the node.
|
48
|
-
|
49
|
-
Returns:
|
50
|
-
dict[str, Edge]: A dictionary of all edges connected to the node,
|
51
|
-
including both preceding (outgoing) and succeeding (incoming)
|
52
|
-
edges, indexed by edge IDs.
|
53
|
-
"""
|
54
|
-
return {**self.points_to, **self.pointed_by}
|
55
|
-
|
56
|
-
@property
|
57
|
-
def all_nodes(self) -> set[str]:
|
58
|
-
"""
|
59
|
-
Extracts and returns a unique set of all node IDs connected to this
|
60
|
-
node through its edges.
|
61
|
-
|
62
|
-
It processes both heads and tails of each edge in `all_edges`, flattens
|
63
|
-
the list to a one-dimensional list, and then converts it to a set to
|
64
|
-
ensure uniqueness.
|
65
|
-
|
66
|
-
Returns:
|
67
|
-
set[str]: A set of unique node IDs connected to this node, derived
|
68
|
-
from both incoming and outgoing edges.
|
69
|
-
"""
|
70
|
-
return set(convert.to_list([[i.head, i.tail] for i in self.all_edges.values()]))
|
lionagi/core/generic/signal.py
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
from abc import ABC
|
2
|
-
from collections import deque
|
3
|
-
from lionagi.core.generic import BaseNode
|
4
|
-
from lionagi.core.generic.mail import Mail
|
5
|
-
from typing import Any
|
6
|
-
|
7
|
-
|
8
|
-
class Signal(BaseNode, ABC): ...
|
9
|
-
|
10
|
-
|
11
|
-
class Start(Signal):
|
12
|
-
pending_outs: deque = deque()
|
13
|
-
|
14
|
-
def trigger(self, context: Any, structure_id: str, executable_id: str):
|
15
|
-
start_mail_content = {"context": context, "structure_id": structure_id}
|
16
|
-
start_mail = Mail(
|
17
|
-
sender=self.id_,
|
18
|
-
recipient=executable_id,
|
19
|
-
category="start",
|
20
|
-
package=start_mail_content,
|
21
|
-
)
|
22
|
-
self.pending_outs.append(start_mail)
|
@@ -1,362 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
This module provides the BaseStructure class, which represents a node with
|
3
|
-
internal edges and nodes, including methods for managing them.
|
4
|
-
|
5
|
-
The BaseStructure class inherits from the Node class and provides functionality
|
6
|
-
for adding, removing, and querying nodes and edges within the structure, as
|
7
|
-
well as checking if the structure is empty.
|
8
|
-
"""
|
9
|
-
|
10
|
-
from functools import singledispatchmethod
|
11
|
-
from typing import Any
|
12
|
-
from pydantic import Field
|
13
|
-
|
14
|
-
from lionagi.libs import convert, func_call
|
15
|
-
from .condition import Condition
|
16
|
-
from .edge import Edge
|
17
|
-
from .node import Node
|
18
|
-
from .action import ActionSelection
|
19
|
-
from lionagi.core.tool import Tool
|
20
|
-
|
21
|
-
|
22
|
-
class BaseStructure(Node):
|
23
|
-
"""
|
24
|
-
Represents a node with internal edges and nodes, including methods for
|
25
|
-
managing them.
|
26
|
-
|
27
|
-
Provides functionality for adding, removing, and querying nodes and edges
|
28
|
-
within the structure, as well as checking if the structure is empty.
|
29
|
-
"""
|
30
|
-
|
31
|
-
internal_nodes: dict[str, Node] = Field(
|
32
|
-
default_factory=dict,
|
33
|
-
description="A dictionary of all nodes within the structure, keyed by \
|
34
|
-
node ID.",
|
35
|
-
)
|
36
|
-
|
37
|
-
@property
|
38
|
-
def internal_edges(self) -> dict[str, Edge]:
|
39
|
-
"""
|
40
|
-
Gets all internal edges indexed by their ID.
|
41
|
-
|
42
|
-
Returns:
|
43
|
-
dict[str, Edge]: A dictionary of all internal edges within the
|
44
|
-
structure.
|
45
|
-
"""
|
46
|
-
edges = {}
|
47
|
-
for i in self.internal_nodes.values():
|
48
|
-
for _, edge in i.edges.items():
|
49
|
-
if edge.id_ not in edges:
|
50
|
-
edges[edge.id_] = edge
|
51
|
-
return edges
|
52
|
-
|
53
|
-
@property
|
54
|
-
def is_empty(self) -> bool:
|
55
|
-
"""
|
56
|
-
Checks if the structure is empty (contains no nodes).
|
57
|
-
|
58
|
-
Returns:
|
59
|
-
bool: True if the structure has no nodes, False otherwise.
|
60
|
-
"""
|
61
|
-
return len(self.internal_nodes) == 0
|
62
|
-
|
63
|
-
def clear(self):
|
64
|
-
"""Clears all nodes and edges from the structure."""
|
65
|
-
self.internal_nodes.clear()
|
66
|
-
|
67
|
-
def get_node_edges(
|
68
|
-
self,
|
69
|
-
node: Node | str,
|
70
|
-
node_as: str = "both",
|
71
|
-
label: list | str = None,
|
72
|
-
) -> dict[str, list[Edge]]:
|
73
|
-
"""
|
74
|
-
Retrieves edges associated with a specific node.
|
75
|
-
|
76
|
-
Args:
|
77
|
-
node (Node | str): The node or its ID to query for edges.
|
78
|
-
node_as (str, optional): The role of the node in the edges.
|
79
|
-
Defaults to "both".
|
80
|
-
- "both" or "all": Retrieve edges where the node is either the
|
81
|
-
head or tail.
|
82
|
-
- "head", "predecessor", "outgoing", "out", or "predecessors":
|
83
|
-
Retrieve edges where the node is the head.
|
84
|
-
- "tail", "successor", "incoming", "in", or "successors":
|
85
|
-
Retrieve edges where the node is the tail.
|
86
|
-
label (list | str, optional): Filter edges by label(s). Defaults to
|
87
|
-
None.
|
88
|
-
|
89
|
-
Returns:
|
90
|
-
dict[str, list[Edge]]: A dictionary mapping related node IDs to
|
91
|
-
lists of associated edges based on the specified criteria.
|
92
|
-
|
93
|
-
Raises:
|
94
|
-
ValueError: If an invalid role is specified for the node.
|
95
|
-
"""
|
96
|
-
|
97
|
-
node = self.get_node(node)
|
98
|
-
|
99
|
-
if node_as in ["all", "both"]:
|
100
|
-
all_node_edges = {i: [] for i in node.related_nodes}
|
101
|
-
|
102
|
-
for k, v in node.node_relations["points_to"].items():
|
103
|
-
all_node_edges[k].append(v)
|
104
|
-
|
105
|
-
for k, v in node.node_relations["pointed_by"].items():
|
106
|
-
all_node_edges[k].append(v)
|
107
|
-
|
108
|
-
for k, v in all_node_edges.items():
|
109
|
-
all_node_edges[k] = convert.to_list(v, dropna=True, flatten=True)
|
110
|
-
|
111
|
-
if label:
|
112
|
-
for k, v in all_node_edges.items():
|
113
|
-
all_node_edges[k] = (
|
114
|
-
v
|
115
|
-
if v.label in convert.to_list(label, dropna=True, flatten=True)
|
116
|
-
else []
|
117
|
-
)
|
118
|
-
|
119
|
-
return {k: v for k, v in all_node_edges.items() if len(v) > 0}
|
120
|
-
|
121
|
-
elif node_as in ["head", "predecessor", "outgoing", "out", "predecessors"]:
|
122
|
-
return node.node_relations["points_to"]
|
123
|
-
|
124
|
-
elif node_as in ["tail", "successor", "incoming", "in", "successors"]:
|
125
|
-
return node.node_relations["pointed_by"]
|
126
|
-
|
127
|
-
else:
|
128
|
-
raise ValueError(
|
129
|
-
f"Invalid value for self_as: {node_as}, must be 'head' or 'tail'"
|
130
|
-
)
|
131
|
-
|
132
|
-
def relate_nodes(
|
133
|
-
self,
|
134
|
-
head: Node,
|
135
|
-
tail: Node,
|
136
|
-
condition: Condition | None = None,
|
137
|
-
bundle=False,
|
138
|
-
label=None,
|
139
|
-
**kwargs,
|
140
|
-
):
|
141
|
-
"""
|
142
|
-
Relates two nodes within the structure with an edge.
|
143
|
-
|
144
|
-
Args:
|
145
|
-
head (Node): The head node of the edge.
|
146
|
-
tail (Node): The tail node of the edge.
|
147
|
-
condition (Condition | None, optional): The condition associated
|
148
|
-
with the edge. Defaults to None.
|
149
|
-
label (optional): The label for the edge.
|
150
|
-
**kwargs: Additional keyword arguments for the edge creation.
|
151
|
-
|
152
|
-
Raises:
|
153
|
-
ValueError: If there is an error adding the edge.
|
154
|
-
"""
|
155
|
-
try:
|
156
|
-
if isinstance(head, Tool) or isinstance(head, ActionSelection):
|
157
|
-
raise ValueError(
|
158
|
-
f"type {type(tail)} should not be the head of the relationship, "
|
159
|
-
f"please switch position and attach it to the tail of the relationship"
|
160
|
-
)
|
161
|
-
|
162
|
-
if isinstance(tail, Tool) or isinstance(tail, ActionSelection):
|
163
|
-
bundle = True
|
164
|
-
|
165
|
-
if head.id_ not in self.internal_nodes:
|
166
|
-
self.add_node(head)
|
167
|
-
|
168
|
-
if tail.id_ not in self.internal_nodes:
|
169
|
-
self.add_node(tail)
|
170
|
-
|
171
|
-
head.relate(
|
172
|
-
tail,
|
173
|
-
node_as="head",
|
174
|
-
condition=condition,
|
175
|
-
label=label,
|
176
|
-
bundle=bundle,
|
177
|
-
**kwargs,
|
178
|
-
)
|
179
|
-
except Exception as e:
|
180
|
-
raise ValueError(f"Error adding edge: {e}") from e
|
181
|
-
|
182
|
-
def remove_edge(
|
183
|
-
self, edge: Edge | str | list[str | Edge] | dict[str, Edge]
|
184
|
-
) -> bool:
|
185
|
-
"""
|
186
|
-
Removes one or more edges from the structure.
|
187
|
-
|
188
|
-
Args:
|
189
|
-
edge: The edge(s) to be removed, specified as single edge, its ID,
|
190
|
-
a list, or a dictionary of edges.
|
191
|
-
|
192
|
-
Returns:
|
193
|
-
bool: True if all specified edges were successfully removed, False
|
194
|
-
otherwise.
|
195
|
-
"""
|
196
|
-
if isinstance(edge, list):
|
197
|
-
for i in edge:
|
198
|
-
self._remove_edge(i)
|
199
|
-
|
200
|
-
elif isinstance(edge, dict):
|
201
|
-
for i in edge.values():
|
202
|
-
self._remove_edge(i)
|
203
|
-
|
204
|
-
elif isinstance(edge, (Edge, str)):
|
205
|
-
self._remove_edge(edge)
|
206
|
-
|
207
|
-
@singledispatchmethod
|
208
|
-
def add_node(self, node: Any) -> None:
|
209
|
-
"""
|
210
|
-
Method placeholder for adding a node. Will be implemented by register
|
211
|
-
decorators.
|
212
|
-
|
213
|
-
Args:
|
214
|
-
node (Any): The node to be added.
|
215
|
-
|
216
|
-
Raises:
|
217
|
-
NotImplementedError: If the method is not implemented for the type
|
218
|
-
of node.
|
219
|
-
"""
|
220
|
-
raise NotImplementedError
|
221
|
-
|
222
|
-
@add_node.register(Node)
|
223
|
-
def _(self, node) -> None:
|
224
|
-
if node.id_ not in self.internal_nodes:
|
225
|
-
self.internal_nodes[node.id_] = node
|
226
|
-
else:
|
227
|
-
raise ValueError(f"Node {node.id_} already exists in structure.")
|
228
|
-
|
229
|
-
@add_node.register(list)
|
230
|
-
def _(self, node) -> None:
|
231
|
-
for _node in node:
|
232
|
-
self.add_node(_node)
|
233
|
-
|
234
|
-
@add_node.register(dict)
|
235
|
-
def _(self, node) -> None:
|
236
|
-
self.add_node(list(node.values()))
|
237
|
-
|
238
|
-
def get_node(self, node, default="undefined"):
|
239
|
-
"""
|
240
|
-
Retrieves one or more nodes by ID, node instance, or a collection of
|
241
|
-
IDs/nodes.
|
242
|
-
|
243
|
-
Args:
|
244
|
-
node: A single node, node ID, or a collection of nodes/IDs to
|
245
|
-
retrieve.
|
246
|
-
default: The default value to return if a node is not found.
|
247
|
-
|
248
|
-
Returns:
|
249
|
-
The node(s) corresponding to the input, or the default value for
|
250
|
-
any not found.
|
251
|
-
"""
|
252
|
-
if not isinstance(node, (list, dict, set)):
|
253
|
-
return self._get_node(node, default=default)
|
254
|
-
else:
|
255
|
-
node = list(node) if isinstance(node, set) else node
|
256
|
-
node = list(node.values()) if isinstance(node, dict) else node
|
257
|
-
|
258
|
-
return func_call.lcall(node, self._get_node, default=default)
|
259
|
-
|
260
|
-
@singledispatchmethod
|
261
|
-
def remove_node(self, node: Any) -> bool:
|
262
|
-
"""
|
263
|
-
Method placeholder for removing a node. Will be implemented by register
|
264
|
-
decorators.
|
265
|
-
|
266
|
-
Args:
|
267
|
-
node (Any): The node to be removed.
|
268
|
-
|
269
|
-
Returns:
|
270
|
-
bool: True if the node was successfully removed, False otherwise.
|
271
|
-
|
272
|
-
Raises:
|
273
|
-
NotImplementedError: If the method is not implemented for the type
|
274
|
-
of node.
|
275
|
-
"""
|
276
|
-
return NotImplementedError
|
277
|
-
|
278
|
-
@remove_node.register(Node)
|
279
|
-
def _(self, node: Node) -> bool:
|
280
|
-
return self._remove_node(node)
|
281
|
-
|
282
|
-
@remove_node.register(str)
|
283
|
-
def _(self, node: str) -> bool:
|
284
|
-
return self._remove_node(node)
|
285
|
-
|
286
|
-
@remove_node.register(list)
|
287
|
-
def _(self, node: list[str | Node]) -> bool:
|
288
|
-
for i in node:
|
289
|
-
self.remove_node(i)
|
290
|
-
|
291
|
-
@remove_node.register(dict)
|
292
|
-
def _(self, node: dict[str, Node]) -> bool:
|
293
|
-
self.remove_node(list(node.values()))
|
294
|
-
|
295
|
-
def _pop_node(self, node: Node | str, default="undefined"):
|
296
|
-
node = self.get_node(node, default=default)
|
297
|
-
self.remove_node(node)
|
298
|
-
return node
|
299
|
-
|
300
|
-
@singledispatchmethod
|
301
|
-
def pop_node(self, node: Any, default="undefined") -> Node:
|
302
|
-
return NotImplementedError
|
303
|
-
|
304
|
-
@pop_node.register(Node)
|
305
|
-
def _(self, node: Node, default="undefined") -> Node:
|
306
|
-
return self._pop_node(node, default=default)
|
307
|
-
|
308
|
-
@pop_node.register(str)
|
309
|
-
def _(self, node: str, default="undefined") -> Node:
|
310
|
-
return self._pop_node(node, default=default)
|
311
|
-
|
312
|
-
@pop_node.register(list)
|
313
|
-
def _(self, node: list[str | Node], default="undefined") -> list[Node]:
|
314
|
-
nodes = []
|
315
|
-
for i in node:
|
316
|
-
nodes.append(self.pop_node(i, default=default))
|
317
|
-
return nodes
|
318
|
-
|
319
|
-
@pop_node.register(dict)
|
320
|
-
def _(self, node: dict[str, Node], default="undefined") -> list[Node]:
|
321
|
-
return self.pop_node(list(node.values()), default=default)
|
322
|
-
|
323
|
-
def _remove_edge(self, edge: Edge | str) -> bool:
|
324
|
-
"""Helper method to remove an edge by ID or edge instance.
|
325
|
-
|
326
|
-
Args:
|
327
|
-
edge (Edge | str): The edge or its ID to remove.
|
328
|
-
|
329
|
-
Returns:
|
330
|
-
bool: True if the edge was successfully removed, False otherwise.
|
331
|
-
|
332
|
-
Raises:
|
333
|
-
ValueError: If the edge is not found within the structure.
|
334
|
-
"""
|
335
|
-
edge_id = edge.id_ if isinstance(edge, Edge) else edge
|
336
|
-
if not edge_id in self.internal_edges:
|
337
|
-
raise ValueError(f"Edge {edge_id} not found in structure.")
|
338
|
-
|
339
|
-
edge = self.internal_edges[edge_id]
|
340
|
-
|
341
|
-
head: Node = self.get_node(edge.head)
|
342
|
-
tail: Node = self.get_node(edge.tail)
|
343
|
-
|
344
|
-
head.unrelate(tail, edge=edge)
|
345
|
-
|
346
|
-
def _get_node(self, node: Node | str, default="undefined") -> Node:
|
347
|
-
node_id_ = node.id_ if isinstance(node, Node) else node
|
348
|
-
if not node_id_ in self.internal_nodes:
|
349
|
-
if default == "undefined":
|
350
|
-
raise KeyError(f"Node {node_id_} not found in structure.")
|
351
|
-
return default
|
352
|
-
return self.internal_nodes[node_id_]
|
353
|
-
|
354
|
-
def _remove_node(self, node: Node | str) -> bool:
|
355
|
-
try:
|
356
|
-
node = self.get_node(node)
|
357
|
-
related_nodes = self.get_node(node.related_nodes)
|
358
|
-
func_call.lcall(related_nodes, node.unrelate)
|
359
|
-
self.internal_nodes.pop(node.id_)
|
360
|
-
return True
|
361
|
-
except Exception as e:
|
362
|
-
raise ValueError(f"Error removing node: {e}") from e
|
lionagi/core/generic/transfer.py
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
from collections import deque
|
2
|
-
from pydantic import Field
|
3
|
-
from pydantic.dataclasses import dataclass
|
4
|
-
|
5
|
-
from lionagi.core.generic.mail import Mail
|
6
|
-
from lionagi.core.generic.signal import Signal
|
7
|
-
|
8
|
-
|
9
|
-
@dataclass
|
10
|
-
class Transfer:
|
11
|
-
|
12
|
-
schedule: dict[str, deque[Mail | Signal]] = Field(
|
13
|
-
default_factory=dict,
|
14
|
-
description="The sequence of all pending mails - {direction: deque[mail_id]}",
|
15
|
-
)
|
16
|
-
|
17
|
-
@property
|
18
|
-
def is_empty(self) -> bool:
|
19
|
-
"""Returns a flag indicating whether the transfer is empty."""
|
20
|
-
return not any(self.schedule.values())
|
lionagi/core/generic/work.py
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
from pydantic.dataclasses import dataclass
|
2
|
-
from typing import Any
|
3
|
-
from abc import ABC, abstractmethod
|
4
|
-
from pydantic import Field
|
5
|
-
|
6
|
-
from .node import Node
|
7
|
-
|
8
|
-
|
9
|
-
@dataclass
|
10
|
-
class Work:
|
11
|
-
|
12
|
-
work_completed: bool = Field(
|
13
|
-
default=False,
|
14
|
-
description="A flag indicating whether the work is already completed.",
|
15
|
-
)
|
16
|
-
|
17
|
-
work_result: Any | None = Field(
|
18
|
-
default=None,
|
19
|
-
description="The result of the work.",
|
20
|
-
)
|
21
|
-
|
22
|
-
context: dict | str | None = Field(
|
23
|
-
None, description="The context buffer for the next instruction."
|
24
|
-
)
|
25
|
-
|
26
|
-
|
27
|
-
class Worker(Node, ABC):
|
28
|
-
stopped: bool = False
|
29
|
-
|
30
|
-
@abstractmethod
|
31
|
-
def perform(self, *args, **kwargs):
|
32
|
-
pass
|
33
|
-
|
34
|
-
@abstractmethod
|
35
|
-
def forward(self, *args, **kwargs):
|
36
|
-
pass
|
37
|
-
|
38
|
-
def stop(self):
|
39
|
-
self.stopped = True
|
40
|
-
return True
|
lionagi/core/graph/graph.py
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
This module provides the Graph class, which represents a graph structure
|
3
|
-
extending the capabilities of BaseStructure to include graph-specific
|
4
|
-
properties and methods, such as detecting heads, acyclicity, and conversion to
|
5
|
-
NetworkX for visualization.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from collections import deque
|
9
|
-
from typing import Any
|
10
|
-
|
11
|
-
from lionagi.core.generic import Node
|
12
|
-
from lionagi.core.generic import BaseStructure
|
13
|
-
|
14
|
-
|
15
|
-
class Graph(BaseStructure):
|
16
|
-
"""
|
17
|
-
Represents a graph structure extending the capabilities of BaseStructure.
|
18
|
-
|
19
|
-
Includes graph-specific properties and methods, such as detecting heads,
|
20
|
-
acyclicity, and conversion to NetworkX for visualization.
|
21
|
-
"""
|
22
|
-
|
23
|
-
def get_heads(self):
|
24
|
-
return [
|
25
|
-
node
|
26
|
-
for node in self.internal_nodes.values()
|
27
|
-
if not node.relations.pointed_by
|
28
|
-
]
|
29
|
-
|
30
|
-
@property
|
31
|
-
def acyclic(self) -> bool:
|
32
|
-
"""
|
33
|
-
Checks if the graph is acyclic.
|
34
|
-
|
35
|
-
An acyclic graph contains no cycles and can be represented as a directed
|
36
|
-
acyclic graph (DAG).
|
37
|
-
|
38
|
-
Returns:
|
39
|
-
bool: True if the graph is acyclic, False otherwise.
|
40
|
-
"""
|
41
|
-
node_ids = list(self.internal_nodes.keys())
|
42
|
-
check_deque = deque(node_ids)
|
43
|
-
check_dict = {key: 0 for key in node_ids} # 0: not visited, 1: temp, 2: perm
|
44
|
-
|
45
|
-
def visit(key):
|
46
|
-
if check_dict[key] == 2:
|
47
|
-
return True
|
48
|
-
elif check_dict[key] == 1:
|
49
|
-
return False
|
50
|
-
|
51
|
-
check_dict[key] = 1
|
52
|
-
|
53
|
-
points_to_edges = self.internal_nodes[key].relations.points_to
|
54
|
-
|
55
|
-
for _, edge in points_to_edges.items():
|
56
|
-
check = visit(edge.tail)
|
57
|
-
if not check:
|
58
|
-
return False
|
59
|
-
|
60
|
-
check_dict[key] = 2
|
61
|
-
return True
|
62
|
-
|
63
|
-
while check_deque:
|
64
|
-
key = check_deque.pop()
|
65
|
-
check = visit(key)
|
66
|
-
if not check:
|
67
|
-
return False
|
68
|
-
return True
|
69
|
-
|
70
|
-
def to_networkx(self, **kwargs) -> Any:
|
71
|
-
"""
|
72
|
-
Converts the graph into a NetworkX graph object.
|
73
|
-
|
74
|
-
The NetworkX graph object can be used for further analysis or
|
75
|
-
visualization.
|
76
|
-
|
77
|
-
Args:
|
78
|
-
**kwargs: Additional keyword arguments to pass to the NetworkX graph
|
79
|
-
constructor.
|
80
|
-
|
81
|
-
Returns:
|
82
|
-
Any: A NetworkX graph object representing the current graph
|
83
|
-
structure.
|
84
|
-
"""
|
85
|
-
from lionagi.libs import SysUtil
|
86
|
-
|
87
|
-
SysUtil.check_import("networkx")
|
88
|
-
|
89
|
-
from networkx import DiGraph
|
90
|
-
|
91
|
-
g = DiGraph(**kwargs)
|
92
|
-
for node_id, node in self.internal_nodes.items():
|
93
|
-
node_info = node.to_dict()
|
94
|
-
node_info.pop("id_")
|
95
|
-
node_info.update({"class_name": node.class_name})
|
96
|
-
g.add_node(node_id, **node_info)
|
97
|
-
|
98
|
-
for _edge in list(self.internal_edges.values()):
|
99
|
-
edge_info = _edge.to_dict()
|
100
|
-
edge_info.pop("id_")
|
101
|
-
edge_info.update({"class_name": _edge.__class__.__name__})
|
102
|
-
source_node_id = edge_info.pop("head")
|
103
|
-
target_node_id = edge_info.pop("tail")
|
104
|
-
g.add_edge(source_node_id, target_node_id, **edge_info)
|
105
|
-
|
106
|
-
return g
|
107
|
-
|
108
|
-
def display(self, **kwargs):
|
109
|
-
"""
|
110
|
-
Displays the graph using NetworkX's drawing capabilities.
|
111
|
-
|
112
|
-
This method requires NetworkX and a compatible plotting library (like
|
113
|
-
matplotlib) to be installed.
|
114
|
-
|
115
|
-
Args:
|
116
|
-
**kwargs: Additional keyword arguments to pass to the NetworkX graph
|
117
|
-
constructor.
|
118
|
-
"""
|
119
|
-
from lionagi.libs import SysUtil
|
120
|
-
|
121
|
-
SysUtil.check_import("networkx")
|
122
|
-
|
123
|
-
from networkx import draw
|
124
|
-
|
125
|
-
g = self.to_networkx(**kwargs)
|
126
|
-
draw(g)
|