lfx-nightly 0.2.0.dev0__py3-none-any.whl → 0.2.0.dev41__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.
- lfx/_assets/component_index.json +1 -1
- lfx/base/agents/agent.py +21 -4
- lfx/base/agents/altk_base_agent.py +393 -0
- lfx/base/agents/altk_tool_wrappers.py +565 -0
- lfx/base/agents/events.py +2 -1
- lfx/base/composio/composio_base.py +159 -224
- lfx/base/data/base_file.py +97 -20
- lfx/base/data/docling_utils.py +61 -10
- lfx/base/data/storage_utils.py +301 -0
- lfx/base/data/utils.py +178 -14
- lfx/base/mcp/util.py +2 -2
- lfx/base/models/anthropic_constants.py +21 -12
- lfx/base/models/groq_constants.py +74 -58
- lfx/base/models/groq_model_discovery.py +265 -0
- lfx/base/models/model.py +1 -1
- lfx/base/models/model_utils.py +100 -0
- lfx/base/models/openai_constants.py +7 -0
- lfx/base/models/watsonx_constants.py +32 -8
- lfx/base/tools/run_flow.py +601 -129
- lfx/cli/commands.py +9 -4
- lfx/cli/common.py +2 -2
- lfx/cli/run.py +1 -1
- lfx/cli/script_loader.py +53 -11
- lfx/components/Notion/create_page.py +1 -1
- lfx/components/Notion/list_database_properties.py +1 -1
- lfx/components/Notion/list_pages.py +1 -1
- lfx/components/Notion/list_users.py +1 -1
- lfx/components/Notion/page_content_viewer.py +1 -1
- lfx/components/Notion/search.py +1 -1
- lfx/components/Notion/update_page_property.py +1 -1
- lfx/components/__init__.py +19 -5
- lfx/components/{agents → altk}/__init__.py +5 -9
- lfx/components/altk/altk_agent.py +193 -0
- lfx/components/apify/apify_actor.py +1 -1
- lfx/components/composio/__init__.py +70 -18
- lfx/components/composio/apollo_composio.py +11 -0
- lfx/components/composio/bitbucket_composio.py +11 -0
- lfx/components/composio/canva_composio.py +11 -0
- lfx/components/composio/coda_composio.py +11 -0
- lfx/components/composio/composio_api.py +10 -0
- lfx/components/composio/discord_composio.py +1 -1
- lfx/components/composio/elevenlabs_composio.py +11 -0
- lfx/components/composio/exa_composio.py +11 -0
- lfx/components/composio/firecrawl_composio.py +11 -0
- lfx/components/composio/fireflies_composio.py +11 -0
- lfx/components/composio/gmail_composio.py +1 -1
- lfx/components/composio/googlebigquery_composio.py +11 -0
- lfx/components/composio/googlecalendar_composio.py +1 -1
- lfx/components/composio/googledocs_composio.py +1 -1
- lfx/components/composio/googlemeet_composio.py +1 -1
- lfx/components/composio/googlesheets_composio.py +1 -1
- lfx/components/composio/googletasks_composio.py +1 -1
- lfx/components/composio/heygen_composio.py +11 -0
- lfx/components/composio/mem0_composio.py +11 -0
- lfx/components/composio/peopledatalabs_composio.py +11 -0
- lfx/components/composio/perplexityai_composio.py +11 -0
- lfx/components/composio/serpapi_composio.py +11 -0
- lfx/components/composio/slack_composio.py +3 -574
- lfx/components/composio/slackbot_composio.py +1 -1
- lfx/components/composio/snowflake_composio.py +11 -0
- lfx/components/composio/tavily_composio.py +11 -0
- lfx/components/composio/youtube_composio.py +2 -2
- lfx/components/cuga/__init__.py +34 -0
- lfx/components/cuga/cuga_agent.py +730 -0
- lfx/components/data/__init__.py +78 -28
- lfx/components/data_source/__init__.py +58 -0
- lfx/components/{data → data_source}/api_request.py +26 -3
- lfx/components/{data → data_source}/csv_to_data.py +15 -10
- lfx/components/{data → data_source}/json_to_data.py +15 -8
- lfx/components/{data → data_source}/news_search.py +1 -1
- lfx/components/{data → data_source}/rss.py +1 -1
- lfx/components/{data → data_source}/sql_executor.py +1 -1
- lfx/components/{data → data_source}/url.py +1 -1
- lfx/components/{data → data_source}/web_search.py +1 -1
- lfx/components/datastax/astradb_cql.py +1 -1
- lfx/components/datastax/astradb_graph.py +1 -1
- lfx/components/datastax/astradb_tool.py +1 -1
- lfx/components/datastax/astradb_vectorstore.py +1 -1
- lfx/components/datastax/hcd.py +1 -1
- lfx/components/deactivated/json_document_builder.py +1 -1
- lfx/components/docling/__init__.py +0 -3
- lfx/components/docling/chunk_docling_document.py +3 -1
- lfx/components/docling/export_docling_document.py +3 -1
- lfx/components/elastic/elasticsearch.py +1 -1
- lfx/components/files_and_knowledge/__init__.py +47 -0
- lfx/components/{data → files_and_knowledge}/directory.py +1 -1
- lfx/components/{data → files_and_knowledge}/file.py +304 -24
- lfx/components/{knowledge_bases → files_and_knowledge}/retrieval.py +2 -2
- lfx/components/{data → files_and_knowledge}/save_file.py +218 -31
- lfx/components/flow_controls/__init__.py +58 -0
- lfx/components/{logic → flow_controls}/conditional_router.py +1 -1
- lfx/components/{logic → flow_controls}/loop.py +43 -9
- lfx/components/flow_controls/run_flow.py +108 -0
- lfx/components/glean/glean_search_api.py +1 -1
- lfx/components/groq/groq.py +35 -28
- lfx/components/helpers/__init__.py +102 -0
- lfx/components/ibm/watsonx.py +7 -1
- lfx/components/input_output/__init__.py +3 -1
- lfx/components/input_output/chat.py +4 -3
- lfx/components/input_output/chat_output.py +10 -4
- lfx/components/input_output/text.py +1 -1
- lfx/components/input_output/text_output.py +1 -1
- lfx/components/{data → input_output}/webhook.py +1 -1
- lfx/components/knowledge_bases/__init__.py +59 -4
- lfx/components/langchain_utilities/character.py +1 -1
- lfx/components/langchain_utilities/csv_agent.py +84 -16
- lfx/components/langchain_utilities/json_agent.py +67 -12
- lfx/components/langchain_utilities/language_recursive.py +1 -1
- lfx/components/llm_operations/__init__.py +46 -0
- lfx/components/{processing → llm_operations}/batch_run.py +17 -8
- lfx/components/{processing → llm_operations}/lambda_filter.py +1 -1
- lfx/components/{logic → llm_operations}/llm_conditional_router.py +1 -1
- lfx/components/{processing/llm_router.py → llm_operations/llm_selector.py} +3 -3
- lfx/components/{processing → llm_operations}/structured_output.py +1 -1
- lfx/components/logic/__init__.py +126 -0
- lfx/components/mem0/mem0_chat_memory.py +11 -0
- lfx/components/models/__init__.py +64 -9
- lfx/components/models_and_agents/__init__.py +49 -0
- lfx/components/{agents → models_and_agents}/agent.py +6 -4
- lfx/components/models_and_agents/embedding_model.py +353 -0
- lfx/components/models_and_agents/language_model.py +398 -0
- lfx/components/{agents → models_and_agents}/mcp_component.py +53 -44
- lfx/components/{helpers → models_and_agents}/memory.py +1 -1
- lfx/components/nvidia/system_assist.py +1 -1
- lfx/components/olivya/olivya.py +1 -1
- lfx/components/ollama/ollama.py +24 -5
- lfx/components/processing/__init__.py +9 -60
- lfx/components/processing/converter.py +1 -1
- lfx/components/processing/dataframe_operations.py +1 -1
- lfx/components/processing/parse_json_data.py +2 -2
- lfx/components/processing/parser.py +1 -1
- lfx/components/processing/split_text.py +1 -1
- lfx/components/qdrant/qdrant.py +1 -1
- lfx/components/redis/redis.py +1 -1
- lfx/components/twelvelabs/split_video.py +10 -0
- lfx/components/twelvelabs/video_file.py +12 -0
- lfx/components/utilities/__init__.py +43 -0
- lfx/components/{helpers → utilities}/calculator_core.py +1 -1
- lfx/components/{helpers → utilities}/current_date.py +1 -1
- lfx/components/{processing → utilities}/python_repl_core.py +1 -1
- lfx/components/vectorstores/local_db.py +9 -0
- lfx/components/youtube/youtube_transcripts.py +118 -30
- lfx/custom/custom_component/component.py +57 -1
- lfx/custom/custom_component/custom_component.py +68 -6
- lfx/custom/directory_reader/directory_reader.py +5 -2
- lfx/graph/edge/base.py +43 -20
- lfx/graph/state/model.py +15 -2
- lfx/graph/utils.py +6 -0
- lfx/graph/vertex/param_handler.py +10 -7
- lfx/helpers/__init__.py +12 -0
- lfx/helpers/flow.py +117 -0
- lfx/inputs/input_mixin.py +24 -1
- lfx/inputs/inputs.py +13 -1
- lfx/interface/components.py +161 -83
- lfx/log/logger.py +5 -3
- lfx/schema/image.py +2 -12
- lfx/services/database/__init__.py +5 -0
- lfx/services/database/service.py +25 -0
- lfx/services/deps.py +87 -22
- lfx/services/interfaces.py +5 -0
- lfx/services/manager.py +24 -10
- lfx/services/mcp_composer/service.py +1029 -162
- lfx/services/session.py +5 -0
- lfx/services/settings/auth.py +18 -11
- lfx/services/settings/base.py +56 -30
- lfx/services/settings/constants.py +8 -0
- lfx/services/storage/local.py +108 -46
- lfx/services/storage/service.py +171 -29
- lfx/template/field/base.py +3 -0
- lfx/utils/image.py +29 -11
- lfx/utils/ssrf_protection.py +384 -0
- lfx/utils/validate_cloud.py +26 -0
- {lfx_nightly-0.2.0.dev0.dist-info → lfx_nightly-0.2.0.dev41.dist-info}/METADATA +38 -22
- {lfx_nightly-0.2.0.dev0.dist-info → lfx_nightly-0.2.0.dev41.dist-info}/RECORD +189 -160
- {lfx_nightly-0.2.0.dev0.dist-info → lfx_nightly-0.2.0.dev41.dist-info}/WHEEL +1 -1
- lfx/components/agents/altk_agent.py +0 -366
- lfx/components/agents/cuga_agent.py +0 -1013
- lfx/components/docling/docling_remote_vlm.py +0 -284
- lfx/components/logic/run_flow.py +0 -71
- lfx/components/models/embedding_model.py +0 -195
- lfx/components/models/language_model.py +0 -144
- lfx/components/processing/dataframe_to_toolset.py +0 -259
- /lfx/components/{data → data_source}/mock_data.py +0 -0
- /lfx/components/{knowledge_bases → files_and_knowledge}/ingestion.py +0 -0
- /lfx/components/{logic → flow_controls}/data_conditional_router.py +0 -0
- /lfx/components/{logic → flow_controls}/flow_tool.py +0 -0
- /lfx/components/{logic → flow_controls}/listen.py +0 -0
- /lfx/components/{logic → flow_controls}/notify.py +0 -0
- /lfx/components/{logic → flow_controls}/pass_message.py +0 -0
- /lfx/components/{logic → flow_controls}/sub_flow.py +0 -0
- /lfx/components/{processing → models_and_agents}/prompt.py +0 -0
- /lfx/components/{helpers → processing}/create_list.py +0 -0
- /lfx/components/{helpers → processing}/output_parser.py +0 -0
- /lfx/components/{helpers → processing}/store_message.py +0 -0
- /lfx/components/{helpers → utilities}/id_generator.py +0 -0
- {lfx_nightly-0.2.0.dev0.dist-info → lfx_nightly-0.2.0.dev41.dist-info}/entry_points.txt +0 -0
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
from typing import Any
|
|
2
|
-
|
|
3
|
-
from langchain_anthropic import ChatAnthropic
|
|
4
|
-
from langchain_openai import ChatOpenAI
|
|
5
|
-
|
|
6
|
-
from lfx.base.models.anthropic_constants import ANTHROPIC_MODELS
|
|
7
|
-
from lfx.base.models.google_generative_ai_constants import GOOGLE_GENERATIVE_AI_MODELS
|
|
8
|
-
from lfx.base.models.google_generative_ai_model import ChatGoogleGenerativeAIFixed
|
|
9
|
-
from lfx.base.models.model import LCModelComponent
|
|
10
|
-
from lfx.base.models.openai_constants import OPENAI_CHAT_MODEL_NAMES, OPENAI_REASONING_MODEL_NAMES
|
|
11
|
-
from lfx.field_typing import LanguageModel
|
|
12
|
-
from lfx.field_typing.range_spec import RangeSpec
|
|
13
|
-
from lfx.inputs.inputs import BoolInput
|
|
14
|
-
from lfx.io import DropdownInput, MessageInput, MultilineInput, SecretStrInput, SliderInput
|
|
15
|
-
from lfx.schema.dotdict import dotdict
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class LanguageModelComponent(LCModelComponent):
|
|
19
|
-
display_name = "Language Model"
|
|
20
|
-
description = "Runs a language model given a specified provider."
|
|
21
|
-
documentation: str = "https://docs.langflow.org/components-models"
|
|
22
|
-
icon = "brain-circuit"
|
|
23
|
-
category = "models"
|
|
24
|
-
priority = 0 # Set priority to 0 to make it appear first
|
|
25
|
-
|
|
26
|
-
inputs = [
|
|
27
|
-
DropdownInput(
|
|
28
|
-
name="provider",
|
|
29
|
-
display_name="Model Provider",
|
|
30
|
-
options=["OpenAI", "Anthropic", "Google"],
|
|
31
|
-
value="OpenAI",
|
|
32
|
-
info="Select the model provider",
|
|
33
|
-
real_time_refresh=True,
|
|
34
|
-
options_metadata=[{"icon": "OpenAI"}, {"icon": "Anthropic"}, {"icon": "GoogleGenerativeAI"}],
|
|
35
|
-
),
|
|
36
|
-
DropdownInput(
|
|
37
|
-
name="model_name",
|
|
38
|
-
display_name="Model Name",
|
|
39
|
-
options=OPENAI_CHAT_MODEL_NAMES + OPENAI_REASONING_MODEL_NAMES,
|
|
40
|
-
value=OPENAI_CHAT_MODEL_NAMES[0],
|
|
41
|
-
info="Select the model to use",
|
|
42
|
-
real_time_refresh=True,
|
|
43
|
-
),
|
|
44
|
-
SecretStrInput(
|
|
45
|
-
name="api_key",
|
|
46
|
-
display_name="OpenAI API Key",
|
|
47
|
-
info="Model Provider API key",
|
|
48
|
-
required=False,
|
|
49
|
-
show=True,
|
|
50
|
-
real_time_refresh=True,
|
|
51
|
-
),
|
|
52
|
-
MessageInput(
|
|
53
|
-
name="input_value",
|
|
54
|
-
display_name="Input",
|
|
55
|
-
info="The input text to send to the model",
|
|
56
|
-
),
|
|
57
|
-
MultilineInput(
|
|
58
|
-
name="system_message",
|
|
59
|
-
display_name="System Message",
|
|
60
|
-
info="A system message that helps set the behavior of the assistant",
|
|
61
|
-
advanced=False,
|
|
62
|
-
),
|
|
63
|
-
BoolInput(
|
|
64
|
-
name="stream",
|
|
65
|
-
display_name="Stream",
|
|
66
|
-
info="Whether to stream the response",
|
|
67
|
-
value=False,
|
|
68
|
-
advanced=True,
|
|
69
|
-
),
|
|
70
|
-
SliderInput(
|
|
71
|
-
name="temperature",
|
|
72
|
-
display_name="Temperature",
|
|
73
|
-
value=0.1,
|
|
74
|
-
info="Controls randomness in responses",
|
|
75
|
-
range_spec=RangeSpec(min=0, max=1, step=0.01),
|
|
76
|
-
advanced=True,
|
|
77
|
-
),
|
|
78
|
-
]
|
|
79
|
-
|
|
80
|
-
def build_model(self) -> LanguageModel:
|
|
81
|
-
provider = self.provider
|
|
82
|
-
model_name = self.model_name
|
|
83
|
-
temperature = self.temperature
|
|
84
|
-
stream = self.stream
|
|
85
|
-
|
|
86
|
-
if provider == "OpenAI":
|
|
87
|
-
if not self.api_key:
|
|
88
|
-
msg = "OpenAI API key is required when using OpenAI provider"
|
|
89
|
-
raise ValueError(msg)
|
|
90
|
-
|
|
91
|
-
if model_name in OPENAI_REASONING_MODEL_NAMES:
|
|
92
|
-
# reasoning models do not support temperature (yet)
|
|
93
|
-
temperature = None
|
|
94
|
-
|
|
95
|
-
return ChatOpenAI(
|
|
96
|
-
model_name=model_name,
|
|
97
|
-
temperature=temperature,
|
|
98
|
-
streaming=stream,
|
|
99
|
-
openai_api_key=self.api_key,
|
|
100
|
-
)
|
|
101
|
-
if provider == "Anthropic":
|
|
102
|
-
if not self.api_key:
|
|
103
|
-
msg = "Anthropic API key is required when using Anthropic provider"
|
|
104
|
-
raise ValueError(msg)
|
|
105
|
-
return ChatAnthropic(
|
|
106
|
-
model=model_name,
|
|
107
|
-
temperature=temperature,
|
|
108
|
-
streaming=stream,
|
|
109
|
-
anthropic_api_key=self.api_key,
|
|
110
|
-
)
|
|
111
|
-
if provider == "Google":
|
|
112
|
-
if not self.api_key:
|
|
113
|
-
msg = "Google API key is required when using Google provider"
|
|
114
|
-
raise ValueError(msg)
|
|
115
|
-
return ChatGoogleGenerativeAIFixed(
|
|
116
|
-
model=model_name,
|
|
117
|
-
temperature=temperature,
|
|
118
|
-
streaming=stream,
|
|
119
|
-
google_api_key=self.api_key,
|
|
120
|
-
)
|
|
121
|
-
msg = f"Unknown provider: {provider}"
|
|
122
|
-
raise ValueError(msg)
|
|
123
|
-
|
|
124
|
-
def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None) -> dotdict:
|
|
125
|
-
if field_name == "provider":
|
|
126
|
-
if field_value == "OpenAI":
|
|
127
|
-
build_config["model_name"]["options"] = OPENAI_CHAT_MODEL_NAMES + OPENAI_REASONING_MODEL_NAMES
|
|
128
|
-
build_config["model_name"]["value"] = OPENAI_CHAT_MODEL_NAMES[0]
|
|
129
|
-
build_config["api_key"]["display_name"] = "OpenAI API Key"
|
|
130
|
-
elif field_value == "Anthropic":
|
|
131
|
-
build_config["model_name"]["options"] = ANTHROPIC_MODELS
|
|
132
|
-
build_config["model_name"]["value"] = ANTHROPIC_MODELS[0]
|
|
133
|
-
build_config["api_key"]["display_name"] = "Anthropic API Key"
|
|
134
|
-
elif field_value == "Google":
|
|
135
|
-
build_config["model_name"]["options"] = GOOGLE_GENERATIVE_AI_MODELS
|
|
136
|
-
build_config["model_name"]["value"] = GOOGLE_GENERATIVE_AI_MODELS[0]
|
|
137
|
-
build_config["api_key"]["display_name"] = "Google API Key"
|
|
138
|
-
elif field_name == "model_name" and field_value.startswith("o1") and self.provider == "OpenAI":
|
|
139
|
-
# Hide system_message for o1 models - currently unsupported
|
|
140
|
-
if "system_message" in build_config:
|
|
141
|
-
build_config["system_message"]["show"] = False
|
|
142
|
-
elif field_name == "model_name" and not field_value.startswith("o1") and "system_message" in build_config:
|
|
143
|
-
build_config["system_message"]["show"] = True
|
|
144
|
-
return build_config
|
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
"""DataFrame to Toolset Component.
|
|
2
|
-
|
|
3
|
-
This component converts each row of a DataFrame into a callable tool/action within a toolset.
|
|
4
|
-
Each row becomes a tool where the action name comes from one column and the content/response
|
|
5
|
-
comes from another column.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
import re
|
|
11
|
-
from typing import TYPE_CHECKING
|
|
12
|
-
|
|
13
|
-
from langchain.tools import StructuredTool
|
|
14
|
-
from pydantic import BaseModel, create_model
|
|
15
|
-
|
|
16
|
-
from lfx.base.langchain_utilities.model import LCToolComponent
|
|
17
|
-
from lfx.field_typing.constants import Tool
|
|
18
|
-
from lfx.io import HandleInput, Output, StrInput
|
|
19
|
-
from lfx.schema.data import Data
|
|
20
|
-
from lfx.schema.dataframe import DataFrame
|
|
21
|
-
from lfx.schema.message import Message
|
|
22
|
-
|
|
23
|
-
if TYPE_CHECKING:
|
|
24
|
-
from lfx.field_typing.constants import Tool
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class DataFrameToToolsetComponent(LCToolComponent):
|
|
28
|
-
"""Component that converts DataFrame rows into a toolset with multiple callable actions."""
|
|
29
|
-
|
|
30
|
-
display_name = "DataFrame to Toolset"
|
|
31
|
-
description = "Convert each row of a DataFrame into a callable tool/action in a toolset."
|
|
32
|
-
icon = "wrench"
|
|
33
|
-
name = "DataFrameToToolset"
|
|
34
|
-
|
|
35
|
-
inputs = [
|
|
36
|
-
HandleInput(
|
|
37
|
-
name="dataframe",
|
|
38
|
-
display_name="DataFrame",
|
|
39
|
-
input_types=["DataFrame"],
|
|
40
|
-
info="DataFrame where each row will become a tool/action",
|
|
41
|
-
required=True,
|
|
42
|
-
),
|
|
43
|
-
StrInput(
|
|
44
|
-
name="tool_name_column",
|
|
45
|
-
display_name="Tool Name Column",
|
|
46
|
-
info="Column with tool names",
|
|
47
|
-
required=True,
|
|
48
|
-
),
|
|
49
|
-
StrInput(
|
|
50
|
-
name="tool_output_column",
|
|
51
|
-
display_name="Tool Output Column",
|
|
52
|
-
info="Column with tool outputs/responses",
|
|
53
|
-
required=True,
|
|
54
|
-
),
|
|
55
|
-
]
|
|
56
|
-
|
|
57
|
-
outputs = [
|
|
58
|
-
Output(display_name="Tools", name="tools", method="build_tools"),
|
|
59
|
-
Output(display_name="Message", name="message", method="get_message"),
|
|
60
|
-
]
|
|
61
|
-
|
|
62
|
-
def __init__(self, **kwargs):
|
|
63
|
-
super().__init__(**kwargs)
|
|
64
|
-
self._tools_cache: list[Tool] = []
|
|
65
|
-
self._action_data: dict[str, dict[str, str]] = {}
|
|
66
|
-
|
|
67
|
-
def _sanitize_tool_name(self, name: str) -> str:
|
|
68
|
-
"""Sanitize tool name to match required format '^[a-zA-Z0-9_-]+$'."""
|
|
69
|
-
# Replace any non-alphanumeric characters (except _ and -) with underscores
|
|
70
|
-
sanitized = re.sub(r"[^a-zA-Z0-9_-]", "_", str(name))
|
|
71
|
-
# Ensure it starts with a letter or underscore
|
|
72
|
-
if sanitized and not sanitized[0].isalpha() and sanitized[0] != "_":
|
|
73
|
-
sanitized = f"tool_{sanitized}"
|
|
74
|
-
return sanitized or "unnamed_tool"
|
|
75
|
-
|
|
76
|
-
def _prepare_action_data(self) -> None:
|
|
77
|
-
"""Prepare action data from DataFrame."""
|
|
78
|
-
# Check if dataframe exists and is valid
|
|
79
|
-
if not hasattr(self, "dataframe") or self.dataframe is None:
|
|
80
|
-
self._action_data = {}
|
|
81
|
-
return
|
|
82
|
-
|
|
83
|
-
if not isinstance(self.dataframe, DataFrame):
|
|
84
|
-
self._action_data = {}
|
|
85
|
-
return
|
|
86
|
-
|
|
87
|
-
if not hasattr(self.dataframe, "columns"):
|
|
88
|
-
self._action_data = {}
|
|
89
|
-
return
|
|
90
|
-
|
|
91
|
-
# Check if column names are provided
|
|
92
|
-
if not self.tool_name_column or not self.tool_output_column:
|
|
93
|
-
self._action_data = {}
|
|
94
|
-
return
|
|
95
|
-
|
|
96
|
-
if self.tool_name_column not in self.dataframe.columns:
|
|
97
|
-
msg = (
|
|
98
|
-
f"Tool name column '{self.tool_name_column}' not found in DataFrame columns: "
|
|
99
|
-
f"{list(self.dataframe.columns)}"
|
|
100
|
-
)
|
|
101
|
-
raise ValueError(msg)
|
|
102
|
-
|
|
103
|
-
if self.tool_output_column not in self.dataframe.columns:
|
|
104
|
-
msg = (
|
|
105
|
-
f"Tool output column '{self.tool_output_column}' not found in DataFrame columns: "
|
|
106
|
-
f"{list(self.dataframe.columns)}"
|
|
107
|
-
)
|
|
108
|
-
raise ValueError(msg)
|
|
109
|
-
|
|
110
|
-
# Clear previous data
|
|
111
|
-
self._action_data = {}
|
|
112
|
-
|
|
113
|
-
# Process each row to create action mappings
|
|
114
|
-
for _, row in self.dataframe.iterrows():
|
|
115
|
-
action_name = str(row[self.tool_name_column]).strip()
|
|
116
|
-
content = str(row[self.tool_output_column]).strip()
|
|
117
|
-
|
|
118
|
-
if action_name and content:
|
|
119
|
-
sanitized_name = self._sanitize_tool_name(action_name)
|
|
120
|
-
self._action_data[sanitized_name] = {
|
|
121
|
-
"original_name": action_name,
|
|
122
|
-
"content": content,
|
|
123
|
-
"sanitized_name": sanitized_name,
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
def _create_action_function(self, action_name: str, content: str):
|
|
127
|
-
"""Create a function for a specific action that returns the content."""
|
|
128
|
-
|
|
129
|
-
def action_function(**kwargs) -> str:
|
|
130
|
-
# You could extend this to use kwargs to modify the content
|
|
131
|
-
# For now, just return the stored content
|
|
132
|
-
self.log(kwargs) # TODO: Coming soon: implement arguments to modify content
|
|
133
|
-
return content
|
|
134
|
-
|
|
135
|
-
action_function.__name__ = f"execute_{action_name}"
|
|
136
|
-
action_function.__doc__ = f"Execute {action_name} action and return the associated content."
|
|
137
|
-
return action_function
|
|
138
|
-
|
|
139
|
-
def build_tools(self) -> list[Tool]:
|
|
140
|
-
"""Build the toolset from DataFrame data."""
|
|
141
|
-
# Handle case where inputs are not ready
|
|
142
|
-
if not hasattr(self, "dataframe") or self.dataframe is None:
|
|
143
|
-
return []
|
|
144
|
-
|
|
145
|
-
self._prepare_action_data()
|
|
146
|
-
|
|
147
|
-
if not self._action_data:
|
|
148
|
-
return []
|
|
149
|
-
|
|
150
|
-
tools_description_preview_length = 100
|
|
151
|
-
tools_description_content_length = 200
|
|
152
|
-
|
|
153
|
-
tools = []
|
|
154
|
-
|
|
155
|
-
for sanitized_name, action_info in self._action_data.items():
|
|
156
|
-
original_name = action_info["original_name"]
|
|
157
|
-
content = action_info["content"]
|
|
158
|
-
|
|
159
|
-
# Create a simple schema for this tool (no parameters needed)
|
|
160
|
-
# But we could extend this to accept parameters if needed
|
|
161
|
-
tool_schema = create_model(
|
|
162
|
-
f"{sanitized_name}Schema",
|
|
163
|
-
__base__=BaseModel,
|
|
164
|
-
# Add parameters here if you want the tools to accept inputs
|
|
165
|
-
# For now, keeping it simple with no parameters
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
# Create the tool function
|
|
169
|
-
tool_function = self._create_action_function(sanitized_name, content)
|
|
170
|
-
|
|
171
|
-
# Create the StructuredTool
|
|
172
|
-
tool = StructuredTool(
|
|
173
|
-
name=sanitized_name,
|
|
174
|
-
description=(
|
|
175
|
-
f"Execute {original_name} action. Returns: "
|
|
176
|
-
f"{content[:tools_description_preview_length]}"
|
|
177
|
-
f"{'...' if len(content) > tools_description_preview_length else ''}"
|
|
178
|
-
),
|
|
179
|
-
func=tool_function,
|
|
180
|
-
args_schema=tool_schema,
|
|
181
|
-
handle_tool_error=True,
|
|
182
|
-
tags=[sanitized_name],
|
|
183
|
-
metadata={
|
|
184
|
-
"display_name": original_name,
|
|
185
|
-
"display_description": f"Action: {original_name}",
|
|
186
|
-
"original_name": original_name,
|
|
187
|
-
"content_preview": content[:tools_description_content_length],
|
|
188
|
-
},
|
|
189
|
-
)
|
|
190
|
-
|
|
191
|
-
tools.append(tool)
|
|
192
|
-
|
|
193
|
-
self._tools_cache = tools
|
|
194
|
-
return tools
|
|
195
|
-
|
|
196
|
-
def build_tool(self) -> Tool:
|
|
197
|
-
"""Build a single tool (for compatibility with LCToolComponent)."""
|
|
198
|
-
tools = self.build_tools()
|
|
199
|
-
if not tools:
|
|
200
|
-
# Return a placeholder tool when no data is available
|
|
201
|
-
def placeholder_function(**kwargs) -> str:
|
|
202
|
-
self.log(kwargs) # TODO: Coming soon: implement arguments to modify content
|
|
203
|
-
return "No tools available. Please connect a DataFrame with appropriate columns."
|
|
204
|
-
|
|
205
|
-
return StructuredTool(
|
|
206
|
-
name="placeholder_tool",
|
|
207
|
-
description="Placeholder tool - waiting for DataFrame input",
|
|
208
|
-
func=placeholder_function,
|
|
209
|
-
args_schema=create_model("PlaceholderSchema", __base__=BaseModel),
|
|
210
|
-
)
|
|
211
|
-
|
|
212
|
-
# Return the first tool, or create a composite tool
|
|
213
|
-
return tools[0]
|
|
214
|
-
|
|
215
|
-
def get_message(self) -> Message:
|
|
216
|
-
"""Get a message describing the created toolset."""
|
|
217
|
-
# Handle case where inputs are not ready
|
|
218
|
-
if not hasattr(self, "dataframe") or self.dataframe is None:
|
|
219
|
-
return Message(text="Waiting for DataFrame input...")
|
|
220
|
-
|
|
221
|
-
self._prepare_action_data()
|
|
222
|
-
|
|
223
|
-
if not self._action_data:
|
|
224
|
-
return Message(text="No tools were created. Please check your DataFrame and column selections.")
|
|
225
|
-
|
|
226
|
-
tool_count = len(self._action_data)
|
|
227
|
-
tool_names = [info["original_name"] for info in self._action_data.values()]
|
|
228
|
-
|
|
229
|
-
message_text = f"Created toolset with {tool_count} tools:\n"
|
|
230
|
-
for i, name in enumerate(tool_names, 1):
|
|
231
|
-
message_text += f"{i}. {name}\n"
|
|
232
|
-
|
|
233
|
-
return Message(text=message_text)
|
|
234
|
-
|
|
235
|
-
def run_model(self) -> list[Data]:
|
|
236
|
-
"""Run the model and return tool information as Data objects."""
|
|
237
|
-
# Handle case where inputs are not ready
|
|
238
|
-
if not hasattr(self, "dataframe") or self.dataframe is None:
|
|
239
|
-
return [Data(data={"status": "Waiting for DataFrame input"})]
|
|
240
|
-
|
|
241
|
-
tools = self.build_tools()
|
|
242
|
-
|
|
243
|
-
if not tools:
|
|
244
|
-
return [Data(data={"status": "No tools created. Check DataFrame and column selections."})]
|
|
245
|
-
|
|
246
|
-
results = []
|
|
247
|
-
for tool in tools:
|
|
248
|
-
tool_data = {
|
|
249
|
-
"tool_name": tool.name,
|
|
250
|
-
"display_name": tool.metadata.get("display_name", tool.name)
|
|
251
|
-
if hasattr(tool, "metadata")
|
|
252
|
-
else tool.name,
|
|
253
|
-
"description": tool.description,
|
|
254
|
-
"original_name": tool.metadata.get("original_name", "") if hasattr(tool, "metadata") else "",
|
|
255
|
-
"content_preview": tool.metadata.get("content_preview", "") if hasattr(tool, "metadata") else "",
|
|
256
|
-
}
|
|
257
|
-
results.append(Data(data=tool_data))
|
|
258
|
-
|
|
259
|
-
return results
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|