lfx-nightly 0.1.13.dev0__py3-none-any.whl → 0.2.0.dev26__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 +121 -29
- lfx/base/agents/altk_base_agent.py +380 -0
- lfx/base/agents/altk_tool_wrappers.py +565 -0
- lfx/base/agents/events.py +103 -35
- lfx/base/agents/utils.py +15 -2
- lfx/base/composio/composio_base.py +183 -233
- lfx/base/data/base_file.py +88 -21
- lfx/base/data/storage_utils.py +192 -0
- lfx/base/data/utils.py +178 -14
- lfx/base/datastax/__init__.py +5 -0
- lfx/{components/vectorstores/astradb.py → base/datastax/astradb_base.py} +84 -473
- lfx/base/embeddings/embeddings_class.py +113 -0
- lfx/base/io/chat.py +5 -4
- lfx/base/mcp/util.py +101 -15
- 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_input_constants.py +74 -7
- lfx/base/models/model_utils.py +100 -0
- lfx/base/models/ollama_constants.py +3 -0
- lfx/base/models/openai_constants.py +7 -0
- lfx/base/models/watsonx_constants.py +36 -0
- lfx/base/tools/run_flow.py +601 -129
- lfx/cli/commands.py +7 -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/altk/__init__.py +34 -0
- lfx/components/altk/altk_agent.py +193 -0
- lfx/components/amazon/amazon_bedrock_converse.py +1 -1
- lfx/components/apify/apify_actor.py +4 -4
- 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/{agents → cuga}/__init__.py +5 -7
- 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/__init__.py +12 -6
- lfx/components/datastax/{astra_assistant_manager.py → astradb_assistant_manager.py} +1 -0
- lfx/components/datastax/astradb_chatmemory.py +40 -0
- lfx/components/datastax/astradb_cql.py +6 -32
- lfx/components/datastax/astradb_graph.py +10 -124
- lfx/components/datastax/astradb_tool.py +13 -53
- lfx/components/datastax/astradb_vectorstore.py +134 -977
- lfx/components/datastax/create_assistant.py +1 -0
- lfx/components/datastax/create_thread.py +1 -0
- lfx/components/datastax/dotenv.py +1 -0
- lfx/components/datastax/get_assistant.py +1 -0
- lfx/components/datastax/getenvvar.py +1 -0
- lfx/components/datastax/graph_rag.py +1 -1
- lfx/components/datastax/hcd.py +1 -1
- lfx/components/datastax/list_assistants.py +1 -0
- lfx/components/datastax/run.py +1 -0
- lfx/components/deactivated/json_document_builder.py +1 -1
- lfx/components/elastic/elasticsearch.py +1 -1
- lfx/components/elastic/opensearch_multimodal.py +1575 -0
- 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 +246 -18
- lfx/components/{knowledge_bases → files_and_knowledge}/ingestion.py +17 -9
- lfx/components/{knowledge_bases → files_and_knowledge}/retrieval.py +18 -10
- lfx/components/{data → files_and_knowledge}/save_file.py +142 -22
- 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 +47 -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 +25 -21
- lfx/components/input_output/__init__.py +3 -1
- lfx/components/input_output/chat.py +12 -3
- lfx/components/input_output/chat_output.py +12 -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 +1 -1
- 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 +56 -18
- lfx/components/logic/__init__.py +126 -0
- lfx/components/mem0/mem0_chat_memory.py +11 -0
- lfx/components/mistral/mistral_embeddings.py +1 -1
- lfx/components/models/__init__.py +64 -9
- lfx/components/models_and_agents/__init__.py +49 -0
- lfx/components/{agents → models_and_agents}/agent.py +49 -6
- lfx/components/models_and_agents/embedding_model.py +423 -0
- lfx/components/models_and_agents/language_model.py +398 -0
- lfx/components/{agents → models_and_agents}/mcp_component.py +84 -45
- 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 +235 -14
- lfx/components/openrouter/openrouter.py +49 -147
- lfx/components/processing/__init__.py +9 -57
- 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 +7 -2
- 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/__init__.py +0 -6
- lfx/components/vectorstores/local_db.py +9 -0
- lfx/components/youtube/youtube_transcripts.py +118 -30
- lfx/custom/custom_component/component.py +60 -3
- lfx/custom/custom_component/custom_component.py +68 -6
- lfx/field_typing/constants.py +1 -0
- lfx/graph/edge/base.py +45 -22
- lfx/graph/graph/base.py +5 -2
- lfx/graph/graph/schema.py +3 -2
- lfx/graph/state/model.py +15 -2
- lfx/graph/utils.py +6 -0
- lfx/graph/vertex/base.py +4 -1
- lfx/graph/vertex/param_handler.py +10 -7
- lfx/graph/vertex/vertex_types.py +1 -1
- 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/io/schema.py +6 -0
- lfx/log/logger.py +5 -3
- lfx/schema/schema.py +5 -0
- lfx/services/database/__init__.py +5 -0
- lfx/services/database/service.py +25 -0
- lfx/services/deps.py +87 -22
- lfx/services/manager.py +19 -6
- lfx/services/mcp_composer/service.py +998 -157
- lfx/services/session.py +5 -0
- lfx/services/settings/base.py +51 -7
- lfx/services/settings/constants.py +8 -0
- lfx/services/storage/local.py +76 -46
- lfx/services/storage/service.py +152 -29
- lfx/template/field/base.py +3 -0
- lfx/utils/ssrf_protection.py +384 -0
- lfx/utils/validate_cloud.py +26 -0
- {lfx_nightly-0.1.13.dev0.dist-info → lfx_nightly-0.2.0.dev26.dist-info}/METADATA +38 -22
- {lfx_nightly-0.1.13.dev0.dist-info → lfx_nightly-0.2.0.dev26.dist-info}/RECORD +210 -196
- {lfx_nightly-0.1.13.dev0.dist-info → lfx_nightly-0.2.0.dev26.dist-info}/WHEEL +1 -1
- lfx/components/agents/cuga_agent.py +0 -1013
- lfx/components/datastax/astra_db.py +0 -77
- lfx/components/datastax/cassandra.py +0 -92
- lfx/components/logic/run_flow.py +0 -71
- lfx/components/models/embedding_model.py +0 -114
- lfx/components/models/language_model.py +0 -144
- lfx/components/vectorstores/astradb_graph.py +0 -326
- lfx/components/vectorstores/cassandra.py +0 -264
- lfx/components/vectorstores/cassandra_graph.py +0 -238
- lfx/components/vectorstores/chroma.py +0 -167
- lfx/components/vectorstores/clickhouse.py +0 -135
- lfx/components/vectorstores/couchbase.py +0 -102
- lfx/components/vectorstores/elasticsearch.py +0 -267
- lfx/components/vectorstores/faiss.py +0 -111
- lfx/components/vectorstores/graph_rag.py +0 -141
- lfx/components/vectorstores/hcd.py +0 -314
- lfx/components/vectorstores/milvus.py +0 -115
- lfx/components/vectorstores/mongodb_atlas.py +0 -213
- lfx/components/vectorstores/opensearch.py +0 -243
- lfx/components/vectorstores/pgvector.py +0 -72
- lfx/components/vectorstores/pinecone.py +0 -134
- lfx/components/vectorstores/qdrant.py +0 -109
- lfx/components/vectorstores/supabase.py +0 -76
- lfx/components/vectorstores/upstash.py +0 -124
- lfx/components/vectorstores/vectara.py +0 -97
- lfx/components/vectorstores/vectara_rag.py +0 -164
- lfx/components/vectorstores/weaviate.py +0 -89
- /lfx/components/{data → data_source}/mock_data.py +0 -0
- /lfx/components/datastax/{astra_vectorize.py → astradb_vectorize.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.1.13.dev0.dist-info → lfx_nightly-0.2.0.dev26.dist-info}/entry_points.txt +0 -0
lfx/components/data/__init__.py
CHANGED
|
@@ -1,34 +1,28 @@
|
|
|
1
|
+
"""Data module - backwards compatibility alias for data_source.
|
|
2
|
+
|
|
3
|
+
This module provides backwards compatibility by forwarding all imports
|
|
4
|
+
to data_source where the actual data components are located.
|
|
5
|
+
"""
|
|
6
|
+
|
|
1
7
|
from __future__ import annotations
|
|
2
8
|
|
|
3
|
-
from typing import
|
|
9
|
+
from typing import Any
|
|
4
10
|
|
|
5
11
|
from lfx.components._importing import import_mod
|
|
6
12
|
|
|
7
|
-
|
|
8
|
-
from lfx.components.data.api_request import APIRequestComponent
|
|
9
|
-
from lfx.components.data.csv_to_data import CSVToDataComponent
|
|
10
|
-
from lfx.components.data.directory import DirectoryComponent
|
|
11
|
-
from lfx.components.data.file import FileComponent
|
|
12
|
-
from lfx.components.data.json_to_data import JSONToDataComponent
|
|
13
|
-
from lfx.components.data.news_search import NewsSearchComponent
|
|
14
|
-
from lfx.components.data.rss import RSSReaderComponent
|
|
15
|
-
from lfx.components.data.sql_executor import SQLComponent
|
|
16
|
-
from lfx.components.data.url import URLComponent
|
|
17
|
-
from lfx.components.data.web_search import WebSearchComponent
|
|
18
|
-
from lfx.components.data.webhook import WebhookComponent
|
|
19
|
-
|
|
13
|
+
# Replicate the same dynamic imports as data_source
|
|
20
14
|
_dynamic_imports = {
|
|
21
15
|
"APIRequestComponent": "api_request",
|
|
22
16
|
"CSVToDataComponent": "csv_to_data",
|
|
23
|
-
"DirectoryComponent": "directory",
|
|
24
|
-
"FileComponent": "file",
|
|
25
17
|
"JSONToDataComponent": "json_to_data",
|
|
26
|
-
"
|
|
27
|
-
"URLComponent": "url",
|
|
28
|
-
"WebSearchComponent": "web_search",
|
|
29
|
-
"WebhookComponent": "webhook",
|
|
18
|
+
"MockDataGeneratorComponent": "mock_data",
|
|
30
19
|
"NewsSearchComponent": "news_search",
|
|
31
20
|
"RSSReaderComponent": "rss",
|
|
21
|
+
"URLComponent": "url",
|
|
22
|
+
"WebSearchComponent": "web_search",
|
|
23
|
+
# File and Directory components are in files_and_knowledge, forward them for backwards compatibility
|
|
24
|
+
"FileComponent": ("file", "files_and_knowledge"),
|
|
25
|
+
"DirectoryComponent": ("directory", "files_and_knowledge"),
|
|
32
26
|
}
|
|
33
27
|
|
|
34
28
|
__all__ = [
|
|
@@ -37,28 +31,84 @@ __all__ = [
|
|
|
37
31
|
"DirectoryComponent",
|
|
38
32
|
"FileComponent",
|
|
39
33
|
"JSONToDataComponent",
|
|
34
|
+
"MockDataGeneratorComponent",
|
|
40
35
|
"NewsSearchComponent",
|
|
41
36
|
"RSSReaderComponent",
|
|
42
|
-
"SQLComponent",
|
|
43
37
|
"URLComponent",
|
|
44
38
|
"WebSearchComponent",
|
|
45
|
-
"WebhookComponent",
|
|
46
39
|
]
|
|
47
40
|
|
|
48
41
|
|
|
49
42
|
def __getattr__(attr_name: str) -> Any:
|
|
50
|
-
"""
|
|
43
|
+
"""Forward attribute access to data_source components."""
|
|
44
|
+
# Handle submodule access for backwards compatibility
|
|
45
|
+
# e.g., lfx.components.data.directory -> lfx.components.files_and_knowledge.directory
|
|
46
|
+
if attr_name == "directory":
|
|
47
|
+
from importlib import import_module
|
|
48
|
+
|
|
49
|
+
result = import_module("lfx.components.files_and_knowledge.directory")
|
|
50
|
+
globals()[attr_name] = result
|
|
51
|
+
return result
|
|
52
|
+
if attr_name == "file":
|
|
53
|
+
from importlib import import_module
|
|
54
|
+
|
|
55
|
+
result = import_module("lfx.components.files_and_knowledge.file")
|
|
56
|
+
globals()[attr_name] = result
|
|
57
|
+
return result
|
|
58
|
+
# Data source components were moved to data_source
|
|
59
|
+
if attr_name == "news_search":
|
|
60
|
+
from importlib import import_module
|
|
61
|
+
|
|
62
|
+
result = import_module("lfx.components.data_source.news_search")
|
|
63
|
+
globals()[attr_name] = result
|
|
64
|
+
return result
|
|
65
|
+
if attr_name == "rss":
|
|
66
|
+
from importlib import import_module
|
|
67
|
+
|
|
68
|
+
result = import_module("lfx.components.data_source.rss")
|
|
69
|
+
globals()[attr_name] = result
|
|
70
|
+
return result
|
|
71
|
+
if attr_name == "web_search":
|
|
72
|
+
from importlib import import_module
|
|
73
|
+
|
|
74
|
+
result = import_module("lfx.components.data_source.web_search")
|
|
75
|
+
globals()[attr_name] = result
|
|
76
|
+
return result
|
|
77
|
+
# SQLComponent was moved to utilities
|
|
78
|
+
if attr_name == "sql_executor":
|
|
79
|
+
from importlib import import_module
|
|
80
|
+
|
|
81
|
+
result = import_module("lfx.components.utilities.sql_executor")
|
|
82
|
+
globals()[attr_name] = result
|
|
83
|
+
return result
|
|
84
|
+
|
|
51
85
|
if attr_name not in _dynamic_imports:
|
|
52
86
|
msg = f"module '{__name__}' has no attribute '{attr_name}'"
|
|
53
87
|
raise AttributeError(msg)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
88
|
+
|
|
89
|
+
mapping = _dynamic_imports[attr_name]
|
|
90
|
+
|
|
91
|
+
# Handle FileComponent and DirectoryComponent which are in files_and_knowledge
|
|
92
|
+
if isinstance(mapping, tuple):
|
|
93
|
+
module_name, package = mapping
|
|
94
|
+
try:
|
|
95
|
+
result = import_mod(attr_name, module_name, f"lfx.components.{package}")
|
|
96
|
+
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
|
97
|
+
msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
|
|
98
|
+
raise AttributeError(msg) from e
|
|
99
|
+
else:
|
|
100
|
+
# Import from data_source using the correct package path
|
|
101
|
+
package = "lfx.components.data_source"
|
|
102
|
+
try:
|
|
103
|
+
result = import_mod(attr_name, mapping, package)
|
|
104
|
+
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
|
105
|
+
msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
|
|
106
|
+
raise AttributeError(msg) from e
|
|
107
|
+
|
|
59
108
|
globals()[attr_name] = result
|
|
60
109
|
return result
|
|
61
110
|
|
|
62
111
|
|
|
63
112
|
def __dir__() -> list[str]:
|
|
113
|
+
"""Return directory of available components."""
|
|
64
114
|
return list(__all__)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from lfx.components._importing import import_mod
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from lfx.components.data_source.api_request import APIRequestComponent
|
|
9
|
+
from lfx.components.data_source.csv_to_data import CSVToDataComponent
|
|
10
|
+
from lfx.components.data_source.json_to_data import JSONToDataComponent
|
|
11
|
+
from lfx.components.data_source.mock_data import MockDataGeneratorComponent
|
|
12
|
+
from lfx.components.data_source.news_search import NewsSearchComponent
|
|
13
|
+
from lfx.components.data_source.rss import RSSReaderComponent
|
|
14
|
+
from lfx.components.data_source.sql_executor import SQLComponent
|
|
15
|
+
from lfx.components.data_source.url import URLComponent
|
|
16
|
+
from lfx.components.data_source.web_search import WebSearchComponent
|
|
17
|
+
|
|
18
|
+
_dynamic_imports = {
|
|
19
|
+
"APIRequestComponent": "api_request",
|
|
20
|
+
"CSVToDataComponent": "csv_to_data",
|
|
21
|
+
"JSONToDataComponent": "json_to_data",
|
|
22
|
+
"MockDataGeneratorComponent": "mock_data",
|
|
23
|
+
"NewsSearchComponent": "news_search",
|
|
24
|
+
"RSSReaderComponent": "rss",
|
|
25
|
+
"URLComponent": "url",
|
|
26
|
+
"WebSearchComponent": "web_search",
|
|
27
|
+
"SQLComponent": "sql_executor",
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"APIRequestComponent",
|
|
32
|
+
"CSVToDataComponent",
|
|
33
|
+
"JSONToDataComponent",
|
|
34
|
+
"MockDataGeneratorComponent",
|
|
35
|
+
"NewsSearchComponent",
|
|
36
|
+
"RSSReaderComponent",
|
|
37
|
+
"SQLComponent",
|
|
38
|
+
"URLComponent",
|
|
39
|
+
"WebSearchComponent",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def __getattr__(attr_name: str) -> Any:
|
|
44
|
+
"""Lazily import data source components on attribute access."""
|
|
45
|
+
if attr_name not in _dynamic_imports:
|
|
46
|
+
msg = f"module '{__name__}' has no attribute '{attr_name}'"
|
|
47
|
+
raise AttributeError(msg)
|
|
48
|
+
try:
|
|
49
|
+
result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
|
|
50
|
+
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
|
51
|
+
msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
|
|
52
|
+
raise AttributeError(msg) from e
|
|
53
|
+
globals()[attr_name] = result
|
|
54
|
+
return result
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def __dir__() -> list[str]:
|
|
58
|
+
return list(__all__)
|
|
@@ -27,6 +27,7 @@ from lfx.io import (
|
|
|
27
27
|
from lfx.schema.data import Data
|
|
28
28
|
from lfx.schema.dotdict import dotdict
|
|
29
29
|
from lfx.utils.component_utils import set_current_fields, set_field_advanced, set_field_display
|
|
30
|
+
from lfx.utils.ssrf_protection import SSRFProtectionError, validate_url_for_ssrf
|
|
30
31
|
|
|
31
32
|
# Define fields for each mode
|
|
32
33
|
MODE_FIELDS = {
|
|
@@ -44,7 +45,7 @@ DEFAULT_FIELDS = ["mode"]
|
|
|
44
45
|
class APIRequestComponent(Component):
|
|
45
46
|
display_name = "API Request"
|
|
46
47
|
description = "Make HTTP requests using URL or cURL commands."
|
|
47
|
-
documentation: str = "https://docs.langflow.org/
|
|
48
|
+
documentation: str = "https://docs.langflow.org/api-request"
|
|
48
49
|
icon = "Globe"
|
|
49
50
|
name = "APIRequest"
|
|
50
51
|
|
|
@@ -145,8 +146,13 @@ class APIRequestComponent(Component):
|
|
|
145
146
|
BoolInput(
|
|
146
147
|
name="follow_redirects",
|
|
147
148
|
display_name="Follow Redirects",
|
|
148
|
-
value=
|
|
149
|
-
info=
|
|
149
|
+
value=False,
|
|
150
|
+
info=(
|
|
151
|
+
"Whether to follow HTTP redirects. "
|
|
152
|
+
"WARNING: Enabling redirects may allow SSRF bypass attacks where a public URL "
|
|
153
|
+
"redirects to internal resources. Only enable if you trust the target server. "
|
|
154
|
+
"See OWASP SSRF Prevention Cheat Sheet for details."
|
|
155
|
+
),
|
|
150
156
|
advanced=True,
|
|
151
157
|
),
|
|
152
158
|
BoolInput(
|
|
@@ -424,6 +430,14 @@ class APIRequestComponent(Component):
|
|
|
424
430
|
save_to_file = self.save_to_file
|
|
425
431
|
include_httpx_metadata = self.include_httpx_metadata
|
|
426
432
|
|
|
433
|
+
# Security warning when redirects are enabled
|
|
434
|
+
if follow_redirects:
|
|
435
|
+
self.log(
|
|
436
|
+
"Security Warning: HTTP redirects are enabled. This may allow SSRF bypass attacks "
|
|
437
|
+
"where a public URL redirects to internal resources (e.g., cloud metadata endpoints). "
|
|
438
|
+
"Only enable this if you trust the target server."
|
|
439
|
+
)
|
|
440
|
+
|
|
427
441
|
# if self.mode == "cURL" and self.curl_input:
|
|
428
442
|
# self._build_config = self.parse_curl(self.curl_input, dotdict())
|
|
429
443
|
# # After parsing curl, get the normalized URL
|
|
@@ -437,6 +451,15 @@ class APIRequestComponent(Component):
|
|
|
437
451
|
msg = f"Invalid URL provided: {url}"
|
|
438
452
|
raise ValueError(msg)
|
|
439
453
|
|
|
454
|
+
# SSRF Protection: Validate URL to prevent access to internal resources
|
|
455
|
+
# TODO: In next major version (2.0), remove warn_only=True to enforce blocking
|
|
456
|
+
try:
|
|
457
|
+
validate_url_for_ssrf(url, warn_only=True)
|
|
458
|
+
except SSRFProtectionError as e:
|
|
459
|
+
# This will only raise if SSRF protection is enabled and warn_only=False
|
|
460
|
+
msg = f"SSRF Protection: {e}"
|
|
461
|
+
raise ValueError(msg) from e
|
|
462
|
+
|
|
440
463
|
# Process query parameters
|
|
441
464
|
if isinstance(self.query_params, str):
|
|
442
465
|
query_params = dict(parse_qsl(self.query_params))
|
|
@@ -2,9 +2,11 @@ import csv
|
|
|
2
2
|
import io
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
|
+
from lfx.base.data.storage_utils import read_file_text
|
|
5
6
|
from lfx.custom.custom_component.component import Component
|
|
6
7
|
from lfx.io import FileInput, MessageTextInput, MultilineInput, Output
|
|
7
8
|
from lfx.schema.data import Data
|
|
9
|
+
from lfx.utils.async_helpers import run_until_complete
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class CSVToDataComponent(Component):
|
|
@@ -52,21 +54,24 @@ class CSVToDataComponent(Component):
|
|
|
52
54
|
csv_data = None
|
|
53
55
|
try:
|
|
54
56
|
if self.csv_file:
|
|
55
|
-
|
|
56
|
-
file_path =
|
|
57
|
-
if file_path.
|
|
57
|
+
# FileInput always provides a local file path
|
|
58
|
+
file_path = self.csv_file
|
|
59
|
+
if not file_path.lower().endswith(".csv"):
|
|
58
60
|
self.status = "The provided file must be a CSV file."
|
|
59
61
|
else:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
# Resolve to absolute path and read from local filesystem
|
|
63
|
+
resolved_path = self.resolve_path(file_path)
|
|
64
|
+
csv_bytes = Path(resolved_path).read_bytes()
|
|
65
|
+
csv_data = csv_bytes.decode("utf-8")
|
|
62
66
|
|
|
63
67
|
elif self.csv_path:
|
|
64
|
-
file_path =
|
|
65
|
-
if file_path.
|
|
66
|
-
self.status = "The provided
|
|
68
|
+
file_path = self.csv_path
|
|
69
|
+
if not file_path.lower().endswith(".csv"):
|
|
70
|
+
self.status = "The provided path must be to a CSV file."
|
|
67
71
|
else:
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
csv_data = run_until_complete(
|
|
73
|
+
read_file_text(file_path, encoding="utf-8", resolve_path=self.resolve_path, newline="")
|
|
74
|
+
)
|
|
70
75
|
|
|
71
76
|
else:
|
|
72
77
|
csv_data = self.csv_string
|
|
@@ -3,9 +3,11 @@ from pathlib import Path
|
|
|
3
3
|
|
|
4
4
|
from json_repair import repair_json
|
|
5
5
|
|
|
6
|
+
from lfx.base.data.storage_utils import read_file_text
|
|
6
7
|
from lfx.custom.custom_component.component import Component
|
|
7
8
|
from lfx.io import FileInput, MessageTextInput, MultilineInput, Output
|
|
8
9
|
from lfx.schema.data import Data
|
|
10
|
+
from lfx.utils.async_helpers import run_until_complete
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class JSONToDataComponent(Component):
|
|
@@ -51,19 +53,24 @@ class JSONToDataComponent(Component):
|
|
|
51
53
|
|
|
52
54
|
try:
|
|
53
55
|
if self.json_file:
|
|
54
|
-
|
|
55
|
-
file_path =
|
|
56
|
-
if file_path.
|
|
56
|
+
# FileInput always provides a local file path
|
|
57
|
+
file_path = self.json_file
|
|
58
|
+
if not file_path.lower().endswith(".json"):
|
|
57
59
|
self.status = "The provided file must be a JSON file."
|
|
58
60
|
else:
|
|
59
|
-
|
|
61
|
+
# Resolve to absolute path and read from local filesystem
|
|
62
|
+
resolved_path = self.resolve_path(file_path)
|
|
63
|
+
json_data = Path(resolved_path).read_text(encoding="utf-8")
|
|
60
64
|
|
|
61
65
|
elif self.json_path:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
# User-provided text path - could be local or S3 key
|
|
67
|
+
file_path = self.json_path
|
|
68
|
+
if not file_path.lower().endswith(".json"):
|
|
69
|
+
self.status = "The provided path must be to a JSON file."
|
|
65
70
|
else:
|
|
66
|
-
json_data =
|
|
71
|
+
json_data = run_until_complete(
|
|
72
|
+
read_file_text(file_path, encoding="utf-8", resolve_path=self.resolve_path)
|
|
73
|
+
)
|
|
67
74
|
|
|
68
75
|
else:
|
|
69
76
|
json_data = self.json_string
|
|
@@ -12,7 +12,7 @@ from lfx.schema import DataFrame
|
|
|
12
12
|
class NewsSearchComponent(Component):
|
|
13
13
|
display_name = "News Search"
|
|
14
14
|
description = "Searches Google News via RSS. Returns clean article data."
|
|
15
|
-
documentation: str = "https://docs.langflow.org/
|
|
15
|
+
documentation: str = "https://docs.langflow.org/web-search"
|
|
16
16
|
icon = "newspaper"
|
|
17
17
|
name = "NewsSearch"
|
|
18
18
|
legacy = True
|
|
@@ -11,7 +11,7 @@ from lfx.schema import DataFrame
|
|
|
11
11
|
class RSSReaderComponent(Component):
|
|
12
12
|
display_name = "RSS Reader"
|
|
13
13
|
description = "Fetches and parses an RSS feed."
|
|
14
|
-
documentation: str = "https://docs.langflow.org/
|
|
14
|
+
documentation: str = "https://docs.langflow.org/web-search"
|
|
15
15
|
icon = "rss"
|
|
16
16
|
name = "RSSReaderSimple"
|
|
17
17
|
legacy = True
|
|
@@ -18,7 +18,7 @@ class SQLComponent(ComponentWithCache):
|
|
|
18
18
|
|
|
19
19
|
display_name = "SQL Database"
|
|
20
20
|
description = "Executes SQL queries on SQLAlchemy-compatible databases."
|
|
21
|
-
documentation: str = "https://docs.langflow.org/
|
|
21
|
+
documentation: str = "https://docs.langflow.org/sql-database"
|
|
22
22
|
icon = "database"
|
|
23
23
|
name = "SQLComponent"
|
|
24
24
|
metadata = {"keywords": ["sql", "database", "query", "db", "fetch"]}
|
|
@@ -48,7 +48,7 @@ class URLComponent(Component):
|
|
|
48
48
|
|
|
49
49
|
display_name = "URL"
|
|
50
50
|
description = "Fetch content from one or more web pages, following links recursively."
|
|
51
|
-
documentation: str = "https://docs.langflow.org/
|
|
51
|
+
documentation: str = "https://docs.langflow.org/url"
|
|
52
52
|
icon = "layout-template"
|
|
53
53
|
name = "URLComponent"
|
|
54
54
|
|
|
@@ -21,7 +21,7 @@ from lfx.utils.request_utils import get_user_agent
|
|
|
21
21
|
class WebSearchComponent(Component):
|
|
22
22
|
display_name = "Web Search"
|
|
23
23
|
description = "Search the web, news, or RSS feeds."
|
|
24
|
-
documentation: str = "https://docs.langflow.org/
|
|
24
|
+
documentation: str = "https://docs.langflow.org/web-search"
|
|
25
25
|
icon = "search"
|
|
26
26
|
name = "UnifiedWebSearch"
|
|
27
27
|
|
|
@@ -5,17 +5,19 @@ from typing import TYPE_CHECKING, Any
|
|
|
5
5
|
from lfx.components._importing import import_mod
|
|
6
6
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
|
-
from .
|
|
9
|
-
from .
|
|
10
|
-
from .astra_vectorize import AstraVectorizeComponent
|
|
8
|
+
from .astradb_assistant_manager import AstraAssistantManager
|
|
9
|
+
from .astradb_chatmemory import AstraDBChatMemory
|
|
11
10
|
from .astradb_cql import AstraDBCQLToolComponent
|
|
11
|
+
from .astradb_graph import AstraDBGraphVectorStoreComponent
|
|
12
12
|
from .astradb_tool import AstraDBToolComponent
|
|
13
|
+
from .astradb_vectorize import AstraVectorizeComponent
|
|
13
14
|
from .astradb_vectorstore import AstraDBVectorStoreComponent
|
|
14
15
|
from .create_assistant import AssistantsCreateAssistant
|
|
15
16
|
from .create_thread import AssistantsCreateThread
|
|
16
17
|
from .dotenv import Dotenv
|
|
17
18
|
from .get_assistant import AssistantsGetAssistantName
|
|
18
19
|
from .getenvvar import GetEnvVar
|
|
20
|
+
from .graph_rag import GraphRAGComponent
|
|
19
21
|
from .list_assistants import AssistantsListAssistants
|
|
20
22
|
from .run import AssistantsRun
|
|
21
23
|
|
|
@@ -25,14 +27,16 @@ _dynamic_imports = {
|
|
|
25
27
|
"AssistantsGetAssistantName": "get_assistant",
|
|
26
28
|
"AssistantsListAssistants": "list_assistants",
|
|
27
29
|
"AssistantsRun": "run",
|
|
28
|
-
"AstraAssistantManager": "
|
|
30
|
+
"AstraAssistantManager": "astradb_assistant_manager",
|
|
29
31
|
"AstraDBCQLToolComponent": "astradb_cql",
|
|
30
|
-
"AstraDBChatMemory": "
|
|
32
|
+
"AstraDBChatMemory": "astradb_chatmemory",
|
|
33
|
+
"AstraDBGraphVectorStoreComponent": "astradb_graph",
|
|
31
34
|
"AstraDBToolComponent": "astradb_tool",
|
|
32
35
|
"AstraDBVectorStoreComponent": "astradb_vectorstore",
|
|
33
|
-
"AstraVectorizeComponent": "
|
|
36
|
+
"AstraVectorizeComponent": "astradb_vectorize",
|
|
34
37
|
"Dotenv": "dotenv",
|
|
35
38
|
"GetEnvVar": "getenvvar",
|
|
39
|
+
"GraphRAGComponent": "graph_rag",
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
__all__ = [
|
|
@@ -44,11 +48,13 @@ __all__ = [
|
|
|
44
48
|
"AstraAssistantManager",
|
|
45
49
|
"AstraDBCQLToolComponent",
|
|
46
50
|
"AstraDBChatMemory",
|
|
51
|
+
"AstraDBGraphVectorStoreComponent",
|
|
47
52
|
"AstraDBToolComponent",
|
|
48
53
|
"AstraDBVectorStoreComponent",
|
|
49
54
|
"AstraVectorizeComponent",
|
|
50
55
|
"Dotenv",
|
|
51
56
|
"GetEnvVar",
|
|
57
|
+
"GraphRAGComponent",
|
|
52
58
|
]
|
|
53
59
|
|
|
54
60
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from lfx.base.datastax.astradb_base import AstraDBBaseComponent
|
|
2
|
+
from lfx.base.memory.model import LCChatMemoryComponent
|
|
3
|
+
from lfx.field_typing.constants import Memory
|
|
4
|
+
from lfx.inputs.inputs import MessageTextInput
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AstraDBChatMemory(AstraDBBaseComponent, LCChatMemoryComponent):
|
|
8
|
+
display_name = "Astra DB Chat Memory"
|
|
9
|
+
description = "Retrieves and stores chat messages from Astra DB."
|
|
10
|
+
name = "AstraDBChatMemory"
|
|
11
|
+
icon: str = "AstraDB"
|
|
12
|
+
|
|
13
|
+
inputs = [
|
|
14
|
+
*AstraDBBaseComponent.inputs,
|
|
15
|
+
MessageTextInput(
|
|
16
|
+
name="session_id",
|
|
17
|
+
display_name="Session ID",
|
|
18
|
+
info="The session ID of the chat. If empty, the current session ID parameter will be used.",
|
|
19
|
+
advanced=True,
|
|
20
|
+
),
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
def build_message_history(self) -> Memory:
|
|
24
|
+
try:
|
|
25
|
+
from langchain_astradb.chat_message_histories import AstraDBChatMessageHistory
|
|
26
|
+
except ImportError as e:
|
|
27
|
+
msg = (
|
|
28
|
+
"Could not import langchain Astra DB integration package. "
|
|
29
|
+
"Please install it with `uv pip install langchain-astradb`."
|
|
30
|
+
)
|
|
31
|
+
raise ImportError(msg) from e
|
|
32
|
+
|
|
33
|
+
return AstraDBChatMessageHistory(
|
|
34
|
+
session_id=self.session_id,
|
|
35
|
+
collection_name=self.collection_name,
|
|
36
|
+
token=self.token,
|
|
37
|
+
api_endpoint=self.get_api_endpoint(),
|
|
38
|
+
namespace=self.get_keyspace(),
|
|
39
|
+
environment=self.environment,
|
|
40
|
+
)
|
|
@@ -8,20 +8,22 @@ import requests
|
|
|
8
8
|
from langchain_core.tools import StructuredTool, Tool
|
|
9
9
|
from pydantic import BaseModel, Field, create_model
|
|
10
10
|
|
|
11
|
+
from lfx.base.datastax.astradb_base import AstraDBBaseComponent
|
|
11
12
|
from lfx.base.langchain_utilities.model import LCToolComponent
|
|
12
|
-
from lfx.io import DictInput, IntInput,
|
|
13
|
+
from lfx.io import DictInput, IntInput, StrInput, TableInput
|
|
13
14
|
from lfx.log.logger import logger
|
|
14
15
|
from lfx.schema.data import Data
|
|
15
16
|
from lfx.schema.table import EditMode
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
class AstraDBCQLToolComponent(LCToolComponent):
|
|
19
|
+
class AstraDBCQLToolComponent(AstraDBBaseComponent, LCToolComponent):
|
|
19
20
|
display_name: str = "Astra DB CQL"
|
|
20
21
|
description: str = "Create a tool to get transactional data from DataStax Astra DB CQL Table"
|
|
21
|
-
documentation: str = "https://docs.langflow.org/bundles-datastax
|
|
22
|
+
documentation: str = "https://docs.langflow.org/bundles-datastax"
|
|
22
23
|
icon: str = "AstraDB"
|
|
23
24
|
|
|
24
25
|
inputs = [
|
|
26
|
+
*AstraDBBaseComponent.inputs,
|
|
25
27
|
StrInput(name="tool_name", display_name="Tool Name", info="The name of the tool.", required=True),
|
|
26
28
|
StrInput(
|
|
27
29
|
name="tool_description",
|
|
@@ -29,34 +31,6 @@ class AstraDBCQLToolComponent(LCToolComponent):
|
|
|
29
31
|
info="The tool description to be passed to the model.",
|
|
30
32
|
required=True,
|
|
31
33
|
),
|
|
32
|
-
StrInput(
|
|
33
|
-
name="keyspace",
|
|
34
|
-
display_name="Keyspace",
|
|
35
|
-
value="default_keyspace",
|
|
36
|
-
info="The keyspace name within Astra DB where the data is stored.",
|
|
37
|
-
required=True,
|
|
38
|
-
advanced=True,
|
|
39
|
-
),
|
|
40
|
-
StrInput(
|
|
41
|
-
name="table_name",
|
|
42
|
-
display_name="Table Name",
|
|
43
|
-
info="The name of the table within Astra DB where the data is stored.",
|
|
44
|
-
required=True,
|
|
45
|
-
),
|
|
46
|
-
SecretStrInput(
|
|
47
|
-
name="token",
|
|
48
|
-
display_name="Astra DB Application Token",
|
|
49
|
-
info="Authentication token for accessing Astra DB.",
|
|
50
|
-
value="ASTRA_DB_APPLICATION_TOKEN",
|
|
51
|
-
required=True,
|
|
52
|
-
),
|
|
53
|
-
StrInput(
|
|
54
|
-
name="api_endpoint",
|
|
55
|
-
display_name="API Endpoint",
|
|
56
|
-
info="API endpoint URL for the Astra DB service.",
|
|
57
|
-
value="ASTRA_DB_API_ENDPOINT",
|
|
58
|
-
required=True,
|
|
59
|
-
),
|
|
60
34
|
StrInput(
|
|
61
35
|
name="projection_fields",
|
|
62
36
|
display_name="Projection fields",
|
|
@@ -204,7 +178,7 @@ class AstraDBCQLToolComponent(LCToolComponent):
|
|
|
204
178
|
|
|
205
179
|
def astra_rest(self, args):
|
|
206
180
|
headers = {"Accept": "application/json", "X-Cassandra-Token": f"{self.token}"}
|
|
207
|
-
astra_url = f"{self.
|
|
181
|
+
astra_url = f"{self.get_api_endpoint()}/api/rest/v2/keyspaces/{self.get_keyspace()}/{self.collection_name}/"
|
|
208
182
|
where = {}
|
|
209
183
|
|
|
210
184
|
for param in self.tools_params:
|