lionagi 0.1.2__py3-none-any.whl → 0.2.0__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 +74 -0
- lionagi/core/work/work_function.py +92 -0
- lionagi/core/work/work_queue.py +81 -0
- lionagi/core/work/worker.py +195 -0
- lionagi/core/work/worklog.py +124 -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.0.dist-info/LICENSE +202 -0
- lionagi-0.2.0.dist-info/METADATA +272 -0
- lionagi-0.2.0.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.0.dist-info}/WHEEL +0 -0
- {lionagi-0.1.2.dist-info → lionagi-0.2.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
# import asyncio
|
2
|
+
# from lionagi import alcall
|
3
|
+
# from lionagi.libs.ln_convert import to_list
|
4
|
+
# import numpy as np
|
5
|
+
|
6
|
+
# def split_into_segments(text):
|
7
|
+
# segments = text.split(".") # Splitting by period followed by a space
|
8
|
+
# return [segment.strip() for segment in segments if segment]
|
9
|
+
|
10
|
+
# # Tokenize the segment
|
11
|
+
# def tokenize(segment):
|
12
|
+
# tokens = segment.split() # Simple space-based tokenization
|
13
|
+
# return tokens
|
14
|
+
|
15
|
+
# async def calculate_perplexity(system_msg: str, imodel, tokens, initial_context=None, **kwargs):
|
16
|
+
# _tasks = []
|
17
|
+
# _context = initial_context or ""
|
18
|
+
# for i in range(len(tokens)):
|
19
|
+
# _context += " " + tokens[i]
|
20
|
+
# messages = [
|
21
|
+
# {"role": "system", "content": system_msg},
|
22
|
+
# {"role": "user", "content": _context},
|
23
|
+
# ]
|
24
|
+
# task = asyncio.create_task(
|
25
|
+
# imodel.call_chat_completion(
|
26
|
+
# messages=messages, logprobs=True, max_tokens=1, **kwargs
|
27
|
+
# )
|
28
|
+
# )
|
29
|
+
# _tasks.append(task)
|
30
|
+
|
31
|
+
# results = await asyncio.gather(*_tasks)
|
32
|
+
# logprobs = [
|
33
|
+
# result[1]["choices"][0]["logprobs"]["content"] for result in results
|
34
|
+
# ]
|
35
|
+
# logprobs = to_list(logprobs, flatten=True, dropna=True)
|
36
|
+
# logprobs = [lprob_["logprob"] for lprob_ in logprobs]
|
37
|
+
# return np.exp(np.mean(logprobs))
|
38
|
+
|
39
|
+
# async def rank_by_perplexity(
|
40
|
+
# text: str | list[str] = None, # if list we assume they are already well split
|
41
|
+
# initial_text=None,
|
42
|
+
|
43
|
+
# segments,
|
44
|
+
# initial_text=None,
|
45
|
+
# cumulative=False,
|
46
|
+
# **kwargs
|
47
|
+
# ):
|
48
|
+
# _segments = []
|
49
|
+
# _context = initial_text or ""
|
50
|
+
# _task = []
|
51
|
+
|
52
|
+
# if cumulative:
|
53
|
+
# for i in range(1, len(segments)):
|
54
|
+
# _context += " " + segments[i - 1]
|
55
|
+
# _segments.append(_context)
|
56
|
+
# else:
|
57
|
+
# _segments = segments
|
58
|
+
|
59
|
+
# for i in segments:
|
60
|
+
# _task.append(asyncio.create_task(
|
61
|
+
# calculate_perplexity(
|
62
|
+
# self.system_msg, self.imodel, self.tokenize(i), **kwargs)
|
63
|
+
# )
|
64
|
+
# )
|
65
|
+
# segment_perplexities = await asyncio.gather(*_task)
|
66
|
+
|
67
|
+
# return {
|
68
|
+
# segment: perplexity
|
69
|
+
# for segment, perplexity in zip(segments, segment_perplexities)
|
70
|
+
# }
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# from ..form.predict import predict
|
2
|
+
# from .select import select
|
3
|
+
# from ..form.score import score
|
4
|
+
# from ..form.react import react
|
5
|
+
# from .vote import vote
|
6
|
+
# from ..form.plan import plan
|
7
|
+
# from .cot import chain_of_thoughts, chain_of_react
|
8
|
+
|
9
|
+
|
10
|
+
# __all__ = [
|
11
|
+
# "predict",
|
12
|
+
# "select",
|
13
|
+
# "score",
|
14
|
+
# "vote",
|
15
|
+
# "react",
|
16
|
+
# "plan",
|
17
|
+
# "chain_of_thoughts",
|
18
|
+
# "chain_of_react",
|
19
|
+
# ]
|
@@ -1,7 +1,23 @@
|
|
1
|
+
"""
|
2
|
+
Copyright 2024 HaiyangLi
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
"""
|
16
|
+
|
1
17
|
from typing import List, Optional
|
2
18
|
|
3
|
-
from lionagi.
|
4
|
-
from ..schema import IfNode, TryNode, ForNode
|
19
|
+
from lionagi.experimental.directive.tokenizer import BaseToken
|
20
|
+
from ..template.schema import IfNode, TryNode, ForNode
|
5
21
|
|
6
22
|
|
7
23
|
class BaseDirectiveParser:
|
@@ -76,10 +92,19 @@ class BaseDirectiveParser:
|
|
76
92
|
self.next_token()
|
77
93
|
|
78
94
|
def skip_semicolon(self):
|
95
|
+
"""Skips a semicolon token if it is the current token."""
|
79
96
|
if self.current_token and self.current_token.value == ";":
|
80
97
|
self.next_token()
|
81
98
|
|
82
99
|
def parse_expression(self):
|
100
|
+
"""Parses an expression until a semicolon is encountered.
|
101
|
+
|
102
|
+
Returns:
|
103
|
+
str: The parsed expression as a string.
|
104
|
+
|
105
|
+
Raises:
|
106
|
+
SyntaxError: If a semicolon is not found at the end of the expression.
|
107
|
+
"""
|
83
108
|
expr = ""
|
84
109
|
while self.current_token and self.current_token.value != ";":
|
85
110
|
expr += self.current_token.value + " "
|
@@ -91,6 +116,11 @@ class BaseDirectiveParser:
|
|
91
116
|
return expr.strip()
|
92
117
|
|
93
118
|
def parse_if_block(self):
|
119
|
+
"""Parses a block of statements for an IF condition.
|
120
|
+
|
121
|
+
Returns:
|
122
|
+
list: The parsed block of statements as a list of strings.
|
123
|
+
"""
|
94
124
|
block = []
|
95
125
|
# Parse the block until 'ELSE', 'ENDIF', ensuring not to include semicolons as part of the block
|
96
126
|
while self.current_token and self.current_token.value not in ("ENDIF", "ELSE"):
|
@@ -103,6 +133,14 @@ class BaseDirectiveParser:
|
|
103
133
|
return block
|
104
134
|
|
105
135
|
def parse_if_statement(self):
|
136
|
+
"""Parses an IF statement.
|
137
|
+
|
138
|
+
Returns:
|
139
|
+
IfNode: The parsed IF statement as an IfNode object.
|
140
|
+
|
141
|
+
Raises:
|
142
|
+
SyntaxError: If the IF statement is not properly formed.
|
143
|
+
"""
|
106
144
|
if self.current_token.type != "KEYWORD" or self.current_token.value != "IF":
|
107
145
|
raise SyntaxError("Expected IF statement")
|
108
146
|
self.next_token() # Skip 'IF'
|
@@ -125,6 +163,14 @@ class BaseDirectiveParser:
|
|
125
163
|
return IfNode(condition, true_block, false_block)
|
126
164
|
|
127
165
|
def parse_for_statement(self):
|
166
|
+
"""Parses a FOR statement.
|
167
|
+
|
168
|
+
Returns:
|
169
|
+
ForNode: The parsed FOR statement as a ForNode object.
|
170
|
+
|
171
|
+
Raises:
|
172
|
+
SyntaxError: If the FOR statement is not properly formed.
|
173
|
+
"""
|
128
174
|
if self.current_token.type != "KEYWORD" or self.current_token.value != "FOR":
|
129
175
|
raise SyntaxError("Expected FOR statement")
|
130
176
|
self.next_token() # Skip 'FOR'
|
@@ -153,6 +199,11 @@ class BaseDirectiveParser:
|
|
153
199
|
return ForNode(iterator, collection, true_block)
|
154
200
|
|
155
201
|
def parse_for_block(self):
|
202
|
+
"""Parses a block of statements for a FOR loop.
|
203
|
+
|
204
|
+
Returns:
|
205
|
+
list: The parsed block of statements as a list of strings.
|
206
|
+
"""
|
156
207
|
block = []
|
157
208
|
# Skip initial 'DO' if present
|
158
209
|
if self.current_token and self.current_token.value == "DO":
|
@@ -173,6 +224,14 @@ class BaseDirectiveParser:
|
|
173
224
|
return block
|
174
225
|
|
175
226
|
def parse_try_statement(self):
|
227
|
+
"""Parses a TRY statement.
|
228
|
+
|
229
|
+
Returns:
|
230
|
+
TryNode: The parsed TRY statement as a TryNode object.
|
231
|
+
|
232
|
+
Raises:
|
233
|
+
SyntaxError: If the TRY statement is not properly formed.
|
234
|
+
"""
|
176
235
|
if self.current_token.type != "KEYWORD" or self.current_token.value != "TRY":
|
177
236
|
raise SyntaxError("Expected TRY statement")
|
178
237
|
self.next_token() # Skip 'TRY'
|
@@ -196,6 +255,14 @@ class BaseDirectiveParser:
|
|
196
255
|
return TryNode(try_block, except_block)
|
197
256
|
|
198
257
|
def parse_try_block(self, stop_keyword):
|
258
|
+
"""Parses a block of statements for a TRY or EXCEPT clause.
|
259
|
+
|
260
|
+
Args:
|
261
|
+
stop_keyword (str): The keyword that indicates the end of the block.
|
262
|
+
|
263
|
+
Returns:
|
264
|
+
list: The parsed block of statements as a list of strings.
|
265
|
+
"""
|
199
266
|
block = []
|
200
267
|
while self.current_token and self.current_token.value != stop_keyword:
|
201
268
|
if self.current_token.value == "DO":
|
@@ -1,10 +1,26 @@
|
|
1
|
+
"""
|
2
|
+
Copyright 2024 HaiyangLi
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
"""
|
16
|
+
|
1
17
|
from typing import Any, Dict
|
2
18
|
import re
|
3
19
|
|
4
20
|
from ..evaluator.base_evaluator import BaseEvaluator
|
5
21
|
|
6
22
|
|
7
|
-
class
|
23
|
+
class DirectiveTemplate:
|
8
24
|
"""Enhanced base template class for processing templates with conditionals and loops."""
|
9
25
|
|
10
26
|
def __init__(self, template_str: str):
|
@@ -1,3 +1,19 @@
|
|
1
|
+
"""
|
2
|
+
Copyright 2024 HaiyangLi
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
"""
|
16
|
+
|
1
17
|
import re
|
2
18
|
|
3
19
|
|
@@ -1,3 +1,19 @@
|
|
1
|
+
"""
|
2
|
+
Copyright 2024 HaiyangLi
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
"""
|
16
|
+
|
1
17
|
import ast
|
2
18
|
import operator
|
3
19
|
|
@@ -1,3 +1,19 @@
|
|
1
|
+
"""
|
2
|
+
Copyright 2024 HaiyangLi
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
"""
|
16
|
+
|
1
17
|
import ast
|
2
18
|
import operator
|
3
19
|
from typing import Any, Dict, Tuple, Callable
|
File without changes
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
# TODO
|
@@ -28,6 +28,10 @@ def to_langchain_document(datanode: T, **kwargs: Any) -> Any:
|
|
28
28
|
SysUtil.change_dict_key(dnode, old_key="content", new_key="page_content")
|
29
29
|
SysUtil.change_dict_key(dnode, old_key="lc_id", new_key="id_")
|
30
30
|
dnode = {**dnode, **kwargs}
|
31
|
+
dnode = {k: v for k, v in dnode.items() if v is not None}
|
32
|
+
if "page_content" not in dnode:
|
33
|
+
dnode["page_content"] = ""
|
34
|
+
|
31
35
|
return LangchainDocument(**dnode)
|
32
36
|
|
33
37
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class LlamaIndex:
|
2
|
+
|
3
|
+
@classmethod
|
4
|
+
def index(
|
5
|
+
cls,
|
6
|
+
nodes,
|
7
|
+
llm_obj=None,
|
8
|
+
llm_class=None,
|
9
|
+
llm_kwargs=None,
|
10
|
+
index_type=None,
|
11
|
+
**kwargs,
|
12
|
+
):
|
13
|
+
from llama_index.core import Settings
|
14
|
+
from llama_index.llms.openai import OpenAI
|
15
|
+
|
16
|
+
if not llm_obj:
|
17
|
+
llm_class = llm_class or OpenAI
|
18
|
+
llm_kwargs = llm_kwargs or {}
|
19
|
+
if "model" not in llm_kwargs:
|
20
|
+
llm_kwargs["model"] = "gpt-4o"
|
21
|
+
llm_obj = llm_class(**llm_kwargs)
|
22
|
+
|
23
|
+
Settings.llm = llm_obj
|
24
|
+
|
25
|
+
if not index_type:
|
26
|
+
from llama_index.core import VectorStoreIndex
|
27
|
+
|
28
|
+
index_type = VectorStoreIndex
|
29
|
+
|
30
|
+
return index_type(nodes, **kwargs)
|
@@ -100,3 +100,9 @@ class LlamaIndexBridge:
|
|
100
100
|
from .reader import get_llama_index_reader
|
101
101
|
|
102
102
|
return get_llama_index_reader(*args, **kwargs)
|
103
|
+
|
104
|
+
@staticmethod
|
105
|
+
def index(nodes, **kwargs):
|
106
|
+
from .index import LlamaIndex
|
107
|
+
|
108
|
+
return LlamaIndex.index(nodes, **kwargs)
|
@@ -1,6 +1,8 @@
|
|
1
1
|
from typing import Union, Callable
|
2
2
|
|
3
3
|
from lionagi.libs import func_call
|
4
|
+
from lionagi.libs.ln_convert import to_list
|
5
|
+
from lionagi.core.collections import pile
|
4
6
|
from lionagi.core.generic import Node
|
5
7
|
from ..bridge.langchain_.langchain_bridge import LangchainBridge
|
6
8
|
from ..bridge.llamaindex_.llama_index_bridge import LlamaIndexBridge
|
@@ -10,7 +12,20 @@ from ..loader.load_util import ChunkerType, file_to_chunks, _datanode_parser
|
|
10
12
|
|
11
13
|
|
12
14
|
def datanodes_convert(documents, chunker_type):
|
15
|
+
"""
|
16
|
+
Converts documents to the specified chunker type.
|
13
17
|
|
18
|
+
Args:
|
19
|
+
documents (list): List of documents to be converted.
|
20
|
+
chunker_type (ChunkerType): The type of chunker to convert the documents to.
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
list: The converted documents.
|
24
|
+
|
25
|
+
Example usage:
|
26
|
+
>>> documents = [Node(...), Node(...)]
|
27
|
+
>>> converted_docs = datanodes_convert(documents, ChunkerType.LLAMAINDEX)
|
28
|
+
"""
|
14
29
|
for i in range(len(documents)):
|
15
30
|
if type(documents[i]) == Node:
|
16
31
|
if chunker_type == ChunkerType.LLAMAINDEX:
|
@@ -21,25 +36,71 @@ def datanodes_convert(documents, chunker_type):
|
|
21
36
|
|
22
37
|
|
23
38
|
def text_chunker(documents, args, kwargs):
|
39
|
+
"""
|
40
|
+
Chunks text documents into smaller pieces.
|
41
|
+
|
42
|
+
Args:
|
43
|
+
documents (list): List of documents to be chunked.
|
44
|
+
args (tuple): Positional arguments for the chunking function.
|
45
|
+
kwargs (dict): Keyword arguments for the chunking function.
|
46
|
+
|
47
|
+
Returns:
|
48
|
+
pile: A pile of chunked Node instances.
|
49
|
+
|
50
|
+
Example usage:
|
51
|
+
>>> documents = [Node(...), Node(...)]
|
52
|
+
>>> chunked_docs = text_chunker(documents, args, kwargs)
|
53
|
+
"""
|
24
54
|
|
25
55
|
def chunk_node(node):
|
26
56
|
chunks = file_to_chunks(node.to_dict(), *args, **kwargs)
|
27
|
-
func_call.lcall(chunks, lambda chunk: chunk.pop("
|
57
|
+
func_call.lcall(chunks, lambda chunk: chunk.pop("ln_id"))
|
28
58
|
return [Node.from_obj({**chunk}) for chunk in chunks]
|
29
59
|
|
30
|
-
|
60
|
+
a = to_list([chunk_node(doc) for doc in documents], flatten=True, dropna=True)
|
61
|
+
return pile(a)
|
31
62
|
|
32
63
|
|
33
64
|
def chunk(
|
34
|
-
|
35
|
-
|
65
|
+
docs,
|
66
|
+
field: str = "content",
|
67
|
+
chunk_size: int = 1500,
|
68
|
+
overlap: float = 0.1,
|
69
|
+
threshold: int = 200,
|
70
|
+
chunker="text_chunker",
|
36
71
|
chunker_type=ChunkerType.PLAIN,
|
37
72
|
chunker_args=None,
|
38
73
|
chunker_kwargs=None,
|
39
74
|
chunking_kwargs=None,
|
40
75
|
documents_convert_func=None,
|
41
|
-
|
76
|
+
to_lion: bool | Callable = True,
|
42
77
|
):
|
78
|
+
"""
|
79
|
+
Chunks documents using the specified chunker.
|
80
|
+
|
81
|
+
Args:
|
82
|
+
docs (list): List of documents to be chunked.
|
83
|
+
field (str, optional): The field to chunk. Defaults to "content".
|
84
|
+
chunk_size (int, optional): The size of each chunk. Defaults to 1500.
|
85
|
+
overlap (float, optional): The overlap between chunks. Defaults to 0.1.
|
86
|
+
threshold (int, optional): The threshold for chunking. Defaults to 200.
|
87
|
+
chunker (str, optional): The chunker function or its name. Defaults to "text_chunker".
|
88
|
+
chunker_type (ChunkerType, optional): The type of chunker to use. Defaults to ChunkerType.PLAIN.
|
89
|
+
chunker_args (list, optional): Positional arguments for the chunker function. Defaults to None.
|
90
|
+
chunker_kwargs (dict, optional): Keyword arguments for the chunker function. Defaults to None.
|
91
|
+
chunking_kwargs (dict, optional): Additional keyword arguments for chunking. Defaults to None.
|
92
|
+
documents_convert_func (Callable, optional): Function to convert documents. Defaults to None.
|
93
|
+
to_lion (bool | Callable, optional): Whether to convert the data to Node instances or a custom parser. Defaults to True.
|
94
|
+
|
95
|
+
Returns:
|
96
|
+
pile: A pile of chunked Node instances.
|
97
|
+
|
98
|
+
Raises:
|
99
|
+
ValueError: If the chunker_type is not supported.
|
100
|
+
|
101
|
+
Example usage:
|
102
|
+
>>> chunked_docs = chunk(docs, field='text', chunk_size=1000, overlap=0.2)
|
103
|
+
"""
|
43
104
|
|
44
105
|
if chunker_args is None:
|
45
106
|
chunker_args = []
|
@@ -49,38 +110,42 @@ def chunk(
|
|
49
110
|
chunking_kwargs = {}
|
50
111
|
|
51
112
|
if chunker_type == ChunkerType.PLAIN:
|
113
|
+
chunker_kwargs["field"] = field
|
114
|
+
chunker_kwargs["chunk_size"] = chunk_size
|
115
|
+
chunker_kwargs["overlap"] = overlap
|
116
|
+
chunker_kwargs["threshold"] = threshold
|
52
117
|
return chunk_funcs[ChunkerType.PLAIN](
|
53
|
-
|
118
|
+
docs, chunker, chunker_args, chunker_kwargs
|
54
119
|
)
|
55
120
|
|
56
121
|
elif chunker_type == ChunkerType.LANGCHAIN:
|
57
122
|
return chunk_funcs[ChunkerType.LANGCHAIN](
|
58
|
-
|
123
|
+
docs,
|
59
124
|
documents_convert_func,
|
60
125
|
chunker,
|
61
126
|
chunker_args,
|
62
127
|
chunker_kwargs,
|
63
|
-
|
128
|
+
to_lion,
|
64
129
|
)
|
65
130
|
|
66
131
|
elif chunker_type == ChunkerType.LLAMAINDEX:
|
67
132
|
return chunk_funcs[ChunkerType.LLAMAINDEX](
|
68
|
-
|
133
|
+
docs,
|
69
134
|
documents_convert_func,
|
70
135
|
chunker,
|
71
136
|
chunker_args,
|
72
137
|
chunker_kwargs,
|
73
|
-
|
138
|
+
to_lion,
|
74
139
|
)
|
75
140
|
|
76
141
|
elif chunker_type == ChunkerType.SELFDEFINED:
|
77
142
|
return chunk_funcs[ChunkerType.SELFDEFINED](
|
78
|
-
|
143
|
+
docs,
|
79
144
|
chunker,
|
80
145
|
chunker_args,
|
81
146
|
chunker_kwargs,
|
82
147
|
chunking_kwargs,
|
83
|
-
|
148
|
+
to_lion,
|
84
149
|
)
|
85
150
|
|
86
151
|
else:
|
@@ -95,8 +160,28 @@ def _self_defined_chunker(
|
|
95
160
|
chunker_args,
|
96
161
|
chunker_kwargs,
|
97
162
|
chunking_kwargs,
|
98
|
-
|
163
|
+
to_lion: bool | Callable,
|
99
164
|
):
|
165
|
+
"""
|
166
|
+
Chunks documents using a self-defined chunker.
|
167
|
+
|
168
|
+
Args:
|
169
|
+
documents (list): List of documents to be chunked.
|
170
|
+
chunker (str | Callable): The chunker function or its name.
|
171
|
+
chunker_args (list): Positional arguments for the chunker function.
|
172
|
+
chunker_kwargs (dict): Keyword arguments for the chunker function.
|
173
|
+
chunking_kwargs (dict): Additional keyword arguments for chunking.
|
174
|
+
to_lion (bool | Callable): Whether to convert the data to Node instances or a custom parser.
|
175
|
+
|
176
|
+
Returns:
|
177
|
+
pile: A pile of chunked Node instances or custom parsed nodes.
|
178
|
+
|
179
|
+
Raises:
|
180
|
+
ValueError: If the self-defined chunker is not valid.
|
181
|
+
|
182
|
+
Example usage:
|
183
|
+
>>> chunked_docs = _self_defined_chunker(docs, custom_chunker, ['arg1'], {'key': 'value'}, {}, custom_parser)
|
184
|
+
"""
|
100
185
|
try:
|
101
186
|
splitter = chunker(*chunker_args, **chunker_kwargs)
|
102
187
|
nodes = splitter.split(documents, **chunking_kwargs)
|
@@ -105,10 +190,10 @@ def _self_defined_chunker(
|
|
105
190
|
f"Self defined chunker {chunker} is not valid. Error: {e}"
|
106
191
|
) from e
|
107
192
|
|
108
|
-
if isinstance(
|
193
|
+
if isinstance(to_lion, bool) and to_lion is True:
|
109
194
|
raise ValueError("Please define a valid parser to Node.")
|
110
|
-
elif isinstance(
|
111
|
-
nodes = _datanode_parser(nodes,
|
195
|
+
elif isinstance(to_lion, Callable):
|
196
|
+
nodes = _datanode_parser(nodes, to_lion)
|
112
197
|
return nodes
|
113
198
|
|
114
199
|
|
@@ -118,18 +203,35 @@ def _llama_index_chunker(
|
|
118
203
|
chunker,
|
119
204
|
chunker_args,
|
120
205
|
chunker_kwargs,
|
121
|
-
|
206
|
+
to_lion: bool | Callable,
|
122
207
|
):
|
208
|
+
"""
|
209
|
+
Chunks documents using a LlamaIndex chunker.
|
210
|
+
|
211
|
+
Args:
|
212
|
+
documents (list): List of documents to be chunked.
|
213
|
+
documents_convert_func (Callable): Function to convert documents.
|
214
|
+
chunker (str | Callable): The chunker function or its name.
|
215
|
+
chunker_args (list): Positional arguments for the chunker function.
|
216
|
+
chunker_kwargs (dict): Keyword arguments for the chunker function.
|
217
|
+
to_lion (bool | Callable): Whether to convert the data to Node instances or a custom parser.
|
218
|
+
|
219
|
+
Returns:
|
220
|
+
pile: A pile of chunked Node instances or custom parsed nodes.
|
221
|
+
|
222
|
+
Example usage:
|
223
|
+
>>> chunked_docs = _llama_index_chunker(docs, convert_func, llama_chunker, ['arg1'], {'key': 'value'}, True)
|
224
|
+
"""
|
123
225
|
if documents_convert_func:
|
124
226
|
documents = documents_convert_func(documents, "llama_index")
|
125
227
|
nodes = LlamaIndexBridge.llama_index_parse_node(
|
126
228
|
documents, chunker, chunker_args, chunker_kwargs
|
127
229
|
)
|
128
230
|
|
129
|
-
if isinstance(
|
231
|
+
if isinstance(to_lion, bool) and to_lion is True:
|
130
232
|
nodes = [Node.from_llama_index(i) for i in nodes]
|
131
|
-
elif isinstance(
|
132
|
-
nodes = _datanode_parser(nodes,
|
233
|
+
elif isinstance(to_lion, Callable):
|
234
|
+
nodes = _datanode_parser(nodes, to_lion)
|
133
235
|
return nodes
|
134
236
|
|
135
237
|
|
@@ -139,24 +241,59 @@ def _langchain_chunker(
|
|
139
241
|
chunker,
|
140
242
|
chunker_args,
|
141
243
|
chunker_kwargs,
|
142
|
-
|
244
|
+
to_lion: bool | Callable,
|
143
245
|
):
|
246
|
+
"""
|
247
|
+
Chunks documents using a Langchain chunker.
|
248
|
+
|
249
|
+
Args:
|
250
|
+
documents (list): List of documents to be chunked.
|
251
|
+
documents_convert_func (Callable): Function to convert documents.
|
252
|
+
chunker (str | Callable): The chunker function or its name.
|
253
|
+
chunker_args (list): Positional arguments for the chunker function.
|
254
|
+
chunker_kwargs (dict): Keyword arguments for the chunker function.
|
255
|
+
to_lion (bool | Callable): Whether to convert the data to Node instances or a custom parser.
|
256
|
+
|
257
|
+
Returns:
|
258
|
+
pile: A pile of chunked Node instances or custom parsed nodes.
|
259
|
+
|
260
|
+
Example usage:
|
261
|
+
>>> chunked_docs = _langchain_chunker(docs, convert_func, langchain_chunker, ['arg1'], {'key': 'value'}, True)
|
262
|
+
"""
|
144
263
|
if documents_convert_func:
|
145
264
|
documents = documents_convert_func(documents, "langchain")
|
146
265
|
nodes = LangchainBridge.langchain_text_splitter(
|
147
266
|
documents, chunker, chunker_args, chunker_kwargs
|
148
267
|
)
|
149
|
-
if isinstance(
|
268
|
+
if isinstance(to_lion, bool) and to_lion is True:
|
150
269
|
if isinstance(documents, str):
|
151
270
|
nodes = [Node(content=i) for i in nodes]
|
152
271
|
else:
|
153
272
|
nodes = [Node.from_langchain(i) for i in nodes]
|
154
|
-
elif isinstance(
|
155
|
-
nodes = _datanode_parser(nodes,
|
273
|
+
elif isinstance(to_lion, Callable):
|
274
|
+
nodes = _datanode_parser(nodes, to_lion)
|
156
275
|
return nodes
|
157
276
|
|
158
277
|
|
159
278
|
def _plain_chunker(documents, chunker, chunker_args, chunker_kwargs):
|
279
|
+
"""
|
280
|
+
Chunks documents using a plain chunker.
|
281
|
+
|
282
|
+
Args:
|
283
|
+
documents (list): List of documents to be chunked.
|
284
|
+
chunker (str | Callable): The chunker function or its name.
|
285
|
+
chunker_args (list): Positional arguments for the chunker function.
|
286
|
+
chunker_kwargs (dict): Keyword arguments for the chunker function.
|
287
|
+
|
288
|
+
Returns:
|
289
|
+
pile: A pile of chunked Node instances.
|
290
|
+
|
291
|
+
Raises:
|
292
|
+
ValueError: If the chunker is not supported.
|
293
|
+
|
294
|
+
Example usage:
|
295
|
+
>>> chunked_docs = _plain_chunker(docs, 'text_chunker', ['arg1'], {'key': 'value'})
|
296
|
+
"""
|
160
297
|
try:
|
161
298
|
if chunker == "text_chunker":
|
162
299
|
chunker = text_chunker
|