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
|
@@ -7,98 +7,50 @@ from typing import TYPE_CHECKING, Any
|
|
|
7
7
|
from lfx.components._importing import import_mod
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
|
-
from lfx.components.processing.alter_metadata import AlterMetadataComponent
|
|
11
|
-
from lfx.components.processing.batch_run import BatchRunComponent
|
|
12
10
|
from lfx.components.processing.combine_text import CombineTextComponent
|
|
13
11
|
from lfx.components.processing.converter import TypeConverterComponent
|
|
14
|
-
from lfx.components.processing.
|
|
12
|
+
from lfx.components.processing.create_list import CreateListComponent
|
|
15
13
|
from lfx.components.processing.data_operations import DataOperationsComponent
|
|
16
|
-
from lfx.components.processing.data_to_dataframe import DataToDataFrameComponent
|
|
17
14
|
from lfx.components.processing.dataframe_operations import DataFrameOperationsComponent
|
|
18
15
|
from lfx.components.processing.dataframe_to_toolset import DataFrameToToolsetComponent
|
|
19
|
-
from lfx.components.processing.dynamic_create_data import DynamicCreateDataComponent
|
|
20
|
-
from lfx.components.processing.extract_key import ExtractDataKeyComponent
|
|
21
|
-
from lfx.components.processing.filter_data import FilterDataComponent
|
|
22
|
-
from lfx.components.processing.filter_data_values import DataFilterComponent
|
|
23
16
|
from lfx.components.processing.json_cleaner import JSONCleaner
|
|
24
|
-
from lfx.components.processing.
|
|
25
|
-
from lfx.components.processing.llm_router import LLMRouterComponent
|
|
26
|
-
from lfx.components.processing.merge_data import MergeDataComponent
|
|
27
|
-
from lfx.components.processing.message_to_data import MessageToDataComponent
|
|
17
|
+
from lfx.components.processing.output_parser import OutputParserComponent
|
|
28
18
|
from lfx.components.processing.parse_data import ParseDataComponent
|
|
29
|
-
from lfx.components.processing.parse_dataframe import ParseDataFrameComponent
|
|
30
|
-
from lfx.components.processing.parse_json_data import ParseJSONDataComponent
|
|
31
19
|
from lfx.components.processing.parser import ParserComponent
|
|
32
|
-
from lfx.components.processing.prompt import PromptComponent
|
|
33
|
-
from lfx.components.processing.python_repl_core import PythonREPLComponent
|
|
34
20
|
from lfx.components.processing.regex import RegexExtractorComponent
|
|
35
|
-
from lfx.components.processing.select_data import SelectDataComponent
|
|
36
21
|
from lfx.components.processing.split_text import SplitTextComponent
|
|
37
|
-
from lfx.components.processing.
|
|
38
|
-
from lfx.components.processing.update_data import UpdateDataComponent
|
|
22
|
+
from lfx.components.processing.store_message import MessageStoreComponent
|
|
39
23
|
|
|
40
24
|
_dynamic_imports = {
|
|
41
|
-
"AlterMetadataComponent": "alter_metadata",
|
|
42
|
-
"BatchRunComponent": "batch_run",
|
|
43
25
|
"CombineTextComponent": "combine_text",
|
|
44
26
|
"TypeConverterComponent": "converter",
|
|
45
|
-
"
|
|
27
|
+
"CreateListComponent": "create_list",
|
|
46
28
|
"DataOperationsComponent": "data_operations",
|
|
47
|
-
"DataToDataFrameComponent": "data_to_dataframe",
|
|
48
29
|
"DataFrameOperationsComponent": "dataframe_operations",
|
|
49
30
|
"DataFrameToToolsetComponent": "dataframe_to_toolset",
|
|
50
|
-
"DynamicCreateDataComponent": "dynamic_create_data",
|
|
51
|
-
"ExtractDataKeyComponent": "extract_key",
|
|
52
|
-
"FilterDataComponent": "filter_data",
|
|
53
|
-
"DataFilterComponent": "filter_data_values",
|
|
54
31
|
"JSONCleaner": "json_cleaner",
|
|
55
|
-
"
|
|
56
|
-
"LLMRouterComponent": "llm_router",
|
|
57
|
-
"MergeDataComponent": "merge_data",
|
|
58
|
-
"MessageToDataComponent": "message_to_data",
|
|
32
|
+
"OutputParserComponent": "output_parser",
|
|
59
33
|
"ParseDataComponent": "parse_data",
|
|
60
|
-
"ParseDataFrameComponent": "parse_dataframe",
|
|
61
|
-
"ParseJSONDataComponent": "parse_json_data",
|
|
62
34
|
"ParserComponent": "parser",
|
|
63
|
-
"PromptComponent": "prompt",
|
|
64
|
-
"PythonREPLComponent": "python_repl_core",
|
|
65
35
|
"RegexExtractorComponent": "regex",
|
|
66
|
-
"SelectDataComponent": "select_data",
|
|
67
36
|
"SplitTextComponent": "split_text",
|
|
68
|
-
"
|
|
69
|
-
"UpdateDataComponent": "update_data",
|
|
37
|
+
"MessageStoreComponent": "store_message",
|
|
70
38
|
}
|
|
71
39
|
|
|
72
40
|
__all__ = [
|
|
73
|
-
"AlterMetadataComponent",
|
|
74
|
-
"BatchRunComponent",
|
|
75
41
|
"CombineTextComponent",
|
|
76
|
-
"
|
|
77
|
-
"DataFilterComponent",
|
|
42
|
+
"CreateListComponent",
|
|
78
43
|
"DataFrameOperationsComponent",
|
|
79
44
|
"DataFrameToToolsetComponent",
|
|
80
45
|
"DataOperationsComponent",
|
|
81
|
-
"DataToDataFrameComponent",
|
|
82
|
-
"DynamicCreateDataComponent",
|
|
83
|
-
"ExtractDataKeyComponent",
|
|
84
|
-
"FilterDataComponent",
|
|
85
46
|
"JSONCleaner",
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"MergeDataComponent",
|
|
89
|
-
"MessageToDataComponent",
|
|
47
|
+
"MessageStoreComponent",
|
|
48
|
+
"OutputParserComponent",
|
|
90
49
|
"ParseDataComponent",
|
|
91
|
-
"ParseDataFrameComponent",
|
|
92
|
-
"ParseJSONDataComponent",
|
|
93
50
|
"ParserComponent",
|
|
94
|
-
"PromptComponent",
|
|
95
|
-
"PythonREPLComponent",
|
|
96
51
|
"RegexExtractorComponent",
|
|
97
|
-
"SelectDataComponent",
|
|
98
52
|
"SplitTextComponent",
|
|
99
|
-
"StructuredOutputComponent",
|
|
100
53
|
"TypeConverterComponent",
|
|
101
|
-
"UpdateDataComponent",
|
|
102
54
|
]
|
|
103
55
|
|
|
104
56
|
|
|
@@ -140,7 +140,7 @@ def _parse_csv_to_data(text: str) -> Data:
|
|
|
140
140
|
class TypeConverterComponent(Component):
|
|
141
141
|
display_name = "Type Convert"
|
|
142
142
|
description = "Convert between different types (Message, Data, DataFrame)"
|
|
143
|
-
documentation: str = "https://docs.langflow.org/
|
|
143
|
+
documentation: str = "https://docs.langflow.org/type-convert"
|
|
144
144
|
icon = "repeat"
|
|
145
145
|
|
|
146
146
|
inputs = [
|
|
@@ -10,7 +10,7 @@ from lfx.schema.dataframe import DataFrame
|
|
|
10
10
|
class DataFrameOperationsComponent(Component):
|
|
11
11
|
display_name = "DataFrame Operations"
|
|
12
12
|
description = "Perform various operations on a DataFrame."
|
|
13
|
-
documentation: str = "https://docs.langflow.org/
|
|
13
|
+
documentation: str = "https://docs.langflow.org/dataframe-operations"
|
|
14
14
|
icon = "table"
|
|
15
15
|
name = "DataFrameOperations"
|
|
16
16
|
|
|
@@ -84,8 +84,8 @@ class ParseJSONDataComponent(Component):
|
|
|
84
84
|
|
|
85
85
|
full_filter_str = json.dumps(to_filter_as_dict)
|
|
86
86
|
|
|
87
|
-
logger.info("to_filter: ", to_filter)
|
|
87
|
+
logger.info("to_filter: %s", to_filter)
|
|
88
88
|
|
|
89
89
|
results = jq.compile(self.query).input_text(full_filter_str).all()
|
|
90
|
-
logger.info("results: ", results)
|
|
90
|
+
logger.info("results: %s", results)
|
|
91
91
|
return [Data(data=value) if isinstance(value, dict) else Data(text=str(value)) for value in results]
|
|
@@ -10,7 +10,7 @@ from lfx.template.field.base import Output
|
|
|
10
10
|
class ParserComponent(Component):
|
|
11
11
|
display_name = "Parser"
|
|
12
12
|
description = "Extracts text using a template."
|
|
13
|
-
documentation: str = "https://docs.langflow.org/
|
|
13
|
+
documentation: str = "https://docs.langflow.org/parser"
|
|
14
14
|
icon = "braces"
|
|
15
15
|
|
|
16
16
|
inputs = [
|
|
@@ -122,7 +122,12 @@ class ParserComponent(Component):
|
|
|
122
122
|
formatted_text = self.pattern.format(**row.to_dict())
|
|
123
123
|
lines.append(formatted_text)
|
|
124
124
|
elif data is not None:
|
|
125
|
-
|
|
125
|
+
# Use format_map with a dict that returns default_value for missing keys
|
|
126
|
+
class DefaultDict(dict):
|
|
127
|
+
def __missing__(self, key):
|
|
128
|
+
return data.default_value or ""
|
|
129
|
+
|
|
130
|
+
formatted_text = self.pattern.format_map(DefaultDict(data.data))
|
|
126
131
|
lines.append(formatted_text)
|
|
127
132
|
|
|
128
133
|
combined_text = self.sep.join(lines)
|
|
@@ -11,7 +11,7 @@ from lfx.utils.util import unescape_string
|
|
|
11
11
|
class SplitTextComponent(Component):
|
|
12
12
|
display_name: str = "Split Text"
|
|
13
13
|
description: str = "Split text into chunks based on specified criteria."
|
|
14
|
-
documentation: str = "https://docs.langflow.org/
|
|
14
|
+
documentation: str = "https://docs.langflow.org/split-text"
|
|
15
15
|
icon = "scissors-line-dashed"
|
|
16
16
|
name = "SplitText"
|
|
17
17
|
|
lfx/components/qdrant/qdrant.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from langchain.embeddings.base import Embeddings
|
|
2
1
|
from langchain_community.vectorstores import Qdrant
|
|
2
|
+
from langchain_core.embeddings import Embeddings
|
|
3
3
|
|
|
4
4
|
from lfx.base.vectorstores.model import LCVectorStoreComponent, check_cached_vector_store
|
|
5
5
|
from lfx.helpers.data import docs_to_data
|
lfx/components/redis/redis.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
|
-
from langchain.text_splitter import CharacterTextSplitter
|
|
4
3
|
from langchain_community.vectorstores.redis import Redis
|
|
4
|
+
from langchain_text_splitters import CharacterTextSplitter
|
|
5
5
|
|
|
6
6
|
from lfx.base.vectorstores.model import LCVectorStoreComponent, check_cached_vector_store
|
|
7
7
|
from lfx.helpers.data import docs_to_data
|
|
@@ -9,6 +9,13 @@ from lfx.custom import Component
|
|
|
9
9
|
from lfx.inputs import BoolInput, DropdownInput, HandleInput, IntInput
|
|
10
10
|
from lfx.schema import Data
|
|
11
11
|
from lfx.template import Output
|
|
12
|
+
from lfx.utils.validate_cloud import raise_error_if_astra_cloud_disable_component
|
|
13
|
+
|
|
14
|
+
disable_component_in_astra_cloud_msg = (
|
|
15
|
+
"Video processing is not supported in Astra cloud environment. "
|
|
16
|
+
"Video components require local file system access for processing. "
|
|
17
|
+
"Please use local storage mode or process videos locally before uploading."
|
|
18
|
+
)
|
|
12
19
|
|
|
13
20
|
|
|
14
21
|
class SplitVideoComponent(Component):
|
|
@@ -267,6 +274,9 @@ class SplitVideoComponent(Component):
|
|
|
267
274
|
|
|
268
275
|
def process(self) -> list[Data]:
|
|
269
276
|
"""Process the input video and return a list of Data objects containing the clips."""
|
|
277
|
+
# Check if we're in Astra cloud environment and raise an error if we are.
|
|
278
|
+
raise_error_if_astra_cloud_disable_component(disable_component_in_astra_cloud_msg)
|
|
279
|
+
|
|
270
280
|
try:
|
|
271
281
|
# Get the input video path from the previous component
|
|
272
282
|
if not hasattr(self, "videodata") or not isinstance(self.videodata, list) or len(self.videodata) != 1:
|
|
@@ -3,6 +3,13 @@ from pathlib import Path
|
|
|
3
3
|
from lfx.base.data import BaseFileComponent
|
|
4
4
|
from lfx.io import FileInput
|
|
5
5
|
from lfx.schema import Data, DataFrame
|
|
6
|
+
from lfx.utils.validate_cloud import raise_error_if_astra_cloud_disable_component
|
|
7
|
+
|
|
8
|
+
disable_component_in_astra_cloud_msg = (
|
|
9
|
+
"Video processing is not supported in Astra cloud environment. "
|
|
10
|
+
"Video components require local file system access for processing. "
|
|
11
|
+
"Please use local storage mode or process videos locally before uploading."
|
|
12
|
+
)
|
|
6
13
|
|
|
7
14
|
|
|
8
15
|
class VideoFileComponent(BaseFileComponent):
|
|
@@ -97,6 +104,8 @@ class VideoFileComponent(BaseFileComponent):
|
|
|
97
104
|
|
|
98
105
|
def process_files(self, file_list: list[BaseFileComponent.BaseFile]) -> list[BaseFileComponent.BaseFile]:
|
|
99
106
|
"""Process video files."""
|
|
107
|
+
# Check if we're in Astra cloud environment and raise an error if we are.
|
|
108
|
+
raise_error_if_astra_cloud_disable_component(disable_component_in_astra_cloud_msg)
|
|
100
109
|
self.log(f"DEBUG: Processing video files: {len(file_list)}")
|
|
101
110
|
|
|
102
111
|
if not file_list:
|
|
@@ -137,6 +146,9 @@ class VideoFileComponent(BaseFileComponent):
|
|
|
137
146
|
|
|
138
147
|
def load_files(self) -> DataFrame:
|
|
139
148
|
"""Load video files and return a list of Data objects."""
|
|
149
|
+
# Check if we're in Astra cloud environment and raise an error if we are.
|
|
150
|
+
raise_error_if_astra_cloud_disable_component(disable_component_in_astra_cloud_msg)
|
|
151
|
+
|
|
140
152
|
try:
|
|
141
153
|
self.log("DEBUG: Starting video file load")
|
|
142
154
|
if not hasattr(self, "file_path") or not self.file_path:
|
|
@@ -0,0 +1,43 @@
|
|
|
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.utilities.calculator_core import CalculatorComponent
|
|
9
|
+
from lfx.components.utilities.current_date import CurrentDateComponent
|
|
10
|
+
from lfx.components.utilities.id_generator import IDGeneratorComponent
|
|
11
|
+
from lfx.components.utilities.python_repl_core import PythonREPLComponent
|
|
12
|
+
|
|
13
|
+
_dynamic_imports = {
|
|
14
|
+
"CalculatorComponent": "calculator_core",
|
|
15
|
+
"CurrentDateComponent": "current_date",
|
|
16
|
+
"IDGeneratorComponent": "id_generator",
|
|
17
|
+
"PythonREPLComponent": "python_repl_core",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"CalculatorComponent",
|
|
22
|
+
"CurrentDateComponent",
|
|
23
|
+
"IDGeneratorComponent",
|
|
24
|
+
"PythonREPLComponent",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def __getattr__(attr_name: str) -> Any:
|
|
29
|
+
"""Lazily import utility components on attribute access."""
|
|
30
|
+
if attr_name not in _dynamic_imports:
|
|
31
|
+
msg = f"module '{__name__}' has no attribute '{attr_name}'"
|
|
32
|
+
raise AttributeError(msg)
|
|
33
|
+
try:
|
|
34
|
+
result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
|
|
35
|
+
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
|
36
|
+
msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
|
|
37
|
+
raise AttributeError(msg) from e
|
|
38
|
+
globals()[attr_name] = result
|
|
39
|
+
return result
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def __dir__() -> list[str]:
|
|
43
|
+
return list(__all__)
|
|
@@ -11,7 +11,7 @@ from lfx.schema.data import Data
|
|
|
11
11
|
class CalculatorComponent(Component):
|
|
12
12
|
display_name = "Calculator"
|
|
13
13
|
description = "Perform basic arithmetic operations on a given expression."
|
|
14
|
-
documentation: str = "https://docs.langflow.org/
|
|
14
|
+
documentation: str = "https://docs.langflow.org/calculator"
|
|
15
15
|
icon = "calculator"
|
|
16
16
|
|
|
17
17
|
# Cache operators dictionary as a class variable
|
|
@@ -10,7 +10,7 @@ from lfx.schema.message import Message
|
|
|
10
10
|
class CurrentDateComponent(Component):
|
|
11
11
|
display_name = "Current Date"
|
|
12
12
|
description = "Returns the current date and time in the selected timezone."
|
|
13
|
-
documentation: str = "https://docs.langflow.org/
|
|
13
|
+
documentation: str = "https://docs.langflow.org/current-date"
|
|
14
14
|
icon = "clock"
|
|
15
15
|
name = "CurrentDate"
|
|
16
16
|
|
|
@@ -10,7 +10,7 @@ from lfx.schema.data import Data
|
|
|
10
10
|
class PythonREPLComponent(Component):
|
|
11
11
|
display_name = "Python Interpreter"
|
|
12
12
|
description = "Run Python code with optional imports. Use print() to see the output."
|
|
13
|
-
documentation: str = "https://docs.langflow.org/
|
|
13
|
+
documentation: str = "https://docs.langflow.org/python-interpreter"
|
|
14
14
|
icon = "square-terminal"
|
|
15
15
|
|
|
16
16
|
inputs = [
|
|
@@ -5,20 +5,14 @@ from typing import TYPE_CHECKING, Any
|
|
|
5
5
|
from lfx.components._importing import import_mod
|
|
6
6
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
|
-
from .astradb import AstraDBVectorStoreComponent
|
|
9
8
|
from .local_db import LocalDBComponent
|
|
10
|
-
from .mongodb_atlas import MongoVectorStoreComponent
|
|
11
9
|
|
|
12
10
|
_dynamic_imports = {
|
|
13
11
|
"LocalDBComponent": "local_db",
|
|
14
|
-
"AstraDBVectorStoreComponent": "astradb",
|
|
15
|
-
"MongoVectorStoreComponent": "mongodb_atlas",
|
|
16
12
|
}
|
|
17
13
|
|
|
18
14
|
__all__ = [
|
|
19
|
-
"AstraDBVectorStoreComponent",
|
|
20
15
|
"LocalDBComponent",
|
|
21
|
-
"MongoVectorStoreComponent",
|
|
22
16
|
]
|
|
23
17
|
|
|
24
18
|
|
|
@@ -12,6 +12,13 @@ from lfx.log.logger import logger
|
|
|
12
12
|
from lfx.schema.data import Data
|
|
13
13
|
from lfx.schema.dataframe import DataFrame
|
|
14
14
|
from lfx.template.field.base import Output
|
|
15
|
+
from lfx.utils.validate_cloud import raise_error_if_astra_cloud_disable_component
|
|
16
|
+
|
|
17
|
+
disable_component_in_astra_cloud_msg = (
|
|
18
|
+
"Local vector stores are not supported in S3/cloud mode. "
|
|
19
|
+
"Local vector stores require local file system access for persistence. "
|
|
20
|
+
"Please use cloud-based vector stores (Pinecone, Weaviate, etc.) or local storage mode."
|
|
21
|
+
)
|
|
15
22
|
|
|
16
23
|
|
|
17
24
|
class LocalDBComponent(LCVectorStoreComponent):
|
|
@@ -193,6 +200,8 @@ class LocalDBComponent(LCVectorStoreComponent):
|
|
|
193
200
|
@check_cached_vector_store
|
|
194
201
|
def build_vector_store(self) -> Chroma:
|
|
195
202
|
"""Builds the Chroma object."""
|
|
203
|
+
raise_error_if_astra_cloud_disable_component(disable_component_in_astra_cloud_msg)
|
|
204
|
+
|
|
196
205
|
try:
|
|
197
206
|
from langchain_chroma import Chroma
|
|
198
207
|
except ImportError as e:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
1
3
|
import pandas as pd
|
|
2
|
-
import
|
|
3
|
-
from langchain_community.document_loaders import YoutubeLoader
|
|
4
|
-
from langchain_community.document_loaders.youtube import TranscriptFormat
|
|
4
|
+
from youtube_transcript_api import NoTranscriptFound, TranscriptsDisabled, YouTubeTranscriptApi
|
|
5
5
|
|
|
6
6
|
from lfx.custom.custom_component.component import Component
|
|
7
7
|
from lfx.inputs.inputs import DropdownInput, IntInput, MultilineInput
|
|
@@ -48,43 +48,133 @@ class YouTubeTranscriptsComponent(Component):
|
|
|
48
48
|
Output(name="data_output", display_name="Transcript + Source", method="get_data_output"),
|
|
49
49
|
]
|
|
50
50
|
|
|
51
|
+
def _extract_video_id(self, url: str) -> str:
|
|
52
|
+
"""Extract video ID from YouTube URL."""
|
|
53
|
+
patterns = [
|
|
54
|
+
r"(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)",
|
|
55
|
+
r"youtube\.com\/watch\?.*?v=([^&\n?#]+)",
|
|
56
|
+
]
|
|
57
|
+
for pattern in patterns:
|
|
58
|
+
match = re.search(pattern, url)
|
|
59
|
+
if match:
|
|
60
|
+
return match.group(1)
|
|
61
|
+
msg = f"Could not extract video ID from URL: {url}"
|
|
62
|
+
raise ValueError(msg)
|
|
63
|
+
|
|
51
64
|
def _load_transcripts(self, *, as_chunks: bool = True):
|
|
52
65
|
"""Internal method to load transcripts from YouTube."""
|
|
53
|
-
|
|
54
|
-
self.url
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
try:
|
|
67
|
+
video_id = self._extract_video_id(self.url)
|
|
68
|
+
except ValueError as e:
|
|
69
|
+
msg = f"Invalid YouTube URL: {e}"
|
|
70
|
+
raise ValueError(msg) from e
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
# Use new v1.0+ API - create instance
|
|
74
|
+
api = YouTubeTranscriptApi()
|
|
75
|
+
transcript_list = api.list(video_id)
|
|
76
|
+
|
|
77
|
+
# Get transcript in specified language or default to English
|
|
78
|
+
if self.translation:
|
|
79
|
+
# Get any available transcript and translate it
|
|
80
|
+
transcript = transcript_list.find_transcript(["en"])
|
|
81
|
+
transcript = transcript.translate(self.translation)
|
|
82
|
+
else:
|
|
83
|
+
# Try to get transcript in available languages
|
|
84
|
+
try:
|
|
85
|
+
transcript = transcript_list.find_transcript(["en"])
|
|
86
|
+
except NoTranscriptFound:
|
|
87
|
+
# Try auto-generated English
|
|
88
|
+
transcript = transcript_list.find_generated_transcript(["en"])
|
|
89
|
+
|
|
90
|
+
# Fetch the transcript data
|
|
91
|
+
transcript_data = api.fetch(transcript.video_id, [transcript.language_code])
|
|
92
|
+
|
|
93
|
+
except (TranscriptsDisabled, NoTranscriptFound) as e:
|
|
94
|
+
error_type = type(e).__name__
|
|
95
|
+
msg = (
|
|
96
|
+
f"Could not retrieve transcripts for video '{video_id}'. "
|
|
97
|
+
"Possible reasons:\n"
|
|
98
|
+
"1. This video does not have captions/transcripts enabled\n"
|
|
99
|
+
"2. The video is private, restricted, or deleted\n"
|
|
100
|
+
f"\nTechnical error ({error_type}): {e}"
|
|
101
|
+
)
|
|
102
|
+
raise RuntimeError(msg) from e
|
|
103
|
+
except Exception as e:
|
|
104
|
+
error_type = type(e).__name__
|
|
105
|
+
msg = (
|
|
106
|
+
f"Could not retrieve transcripts for video '{video_id}'. "
|
|
107
|
+
"Possible reasons:\n"
|
|
108
|
+
"1. This video does not have captions/transcripts enabled\n"
|
|
109
|
+
"2. The video is private, restricted, or deleted\n"
|
|
110
|
+
"3. YouTube is blocking automated requests\n"
|
|
111
|
+
f"\nTechnical error ({error_type}): {e}"
|
|
112
|
+
)
|
|
113
|
+
raise RuntimeError(msg) from e
|
|
114
|
+
|
|
115
|
+
if as_chunks:
|
|
116
|
+
# Group into chunks based on chunk_size_seconds
|
|
117
|
+
return self._chunk_transcript(transcript_data)
|
|
118
|
+
# Return as continuous text
|
|
119
|
+
return transcript_data
|
|
120
|
+
|
|
121
|
+
def _chunk_transcript(self, transcript_data):
|
|
122
|
+
"""Group transcript segments into time-based chunks."""
|
|
123
|
+
chunks = []
|
|
124
|
+
current_chunk = []
|
|
125
|
+
chunk_start = 0
|
|
126
|
+
|
|
127
|
+
for segment in transcript_data:
|
|
128
|
+
# Handle both dict (old API) and object (new API) formats
|
|
129
|
+
segment_start = segment.start if hasattr(segment, "start") else segment["start"]
|
|
130
|
+
|
|
131
|
+
# If this segment starts beyond the current chunk window, start a new chunk
|
|
132
|
+
if segment_start - chunk_start >= self.chunk_size_seconds and current_chunk:
|
|
133
|
+
chunk_text = " ".join(s.text if hasattr(s, "text") else s["text"] for s in current_chunk)
|
|
134
|
+
chunks.append({"start": chunk_start, "text": chunk_text})
|
|
135
|
+
current_chunk = []
|
|
136
|
+
chunk_start = segment_start
|
|
137
|
+
|
|
138
|
+
current_chunk.append(segment)
|
|
139
|
+
|
|
140
|
+
# Add the last chunk
|
|
141
|
+
if current_chunk:
|
|
142
|
+
chunk_text = " ".join(s.text if hasattr(s, "text") else s["text"] for s in current_chunk)
|
|
143
|
+
chunks.append({"start": chunk_start, "text": chunk_text})
|
|
144
|
+
|
|
145
|
+
return chunks
|
|
60
146
|
|
|
61
147
|
def get_dataframe_output(self) -> DataFrame:
|
|
62
148
|
"""Provides transcript output as a DataFrame with timestamp and text columns."""
|
|
63
149
|
try:
|
|
64
|
-
|
|
150
|
+
chunks = self._load_transcripts(as_chunks=True)
|
|
65
151
|
|
|
66
152
|
# Create DataFrame with timestamp and text columns
|
|
67
153
|
data = []
|
|
68
|
-
for
|
|
69
|
-
start_seconds = int(
|
|
154
|
+
for chunk in chunks:
|
|
155
|
+
start_seconds = int(chunk["start"])
|
|
70
156
|
start_minutes = start_seconds // 60
|
|
71
|
-
start_seconds
|
|
72
|
-
timestamp = f"{start_minutes:02d}:{
|
|
73
|
-
data.append({"timestamp": timestamp, "text":
|
|
157
|
+
start_seconds_remainder = start_seconds % 60
|
|
158
|
+
timestamp = f"{start_minutes:02d}:{start_seconds_remainder:02d}"
|
|
159
|
+
data.append({"timestamp": timestamp, "text": chunk["text"]})
|
|
74
160
|
|
|
75
161
|
return DataFrame(pd.DataFrame(data))
|
|
76
162
|
|
|
77
|
-
except (
|
|
78
|
-
|
|
163
|
+
except (TranscriptsDisabled, NoTranscriptFound, RuntimeError, ValueError) as exc:
|
|
164
|
+
error_msg = f"Failed to get YouTube transcripts: {exc!s}"
|
|
165
|
+
return DataFrame(pd.DataFrame({"error": [error_msg]}))
|
|
79
166
|
|
|
80
167
|
def get_message_output(self) -> Message:
|
|
81
168
|
"""Provides transcript output as continuous text."""
|
|
82
169
|
try:
|
|
83
|
-
|
|
84
|
-
|
|
170
|
+
transcript_data = self._load_transcripts(as_chunks=False)
|
|
171
|
+
# Handle both dict (old API) and object (new API) formats
|
|
172
|
+
result = " ".join(
|
|
173
|
+
segment.text if hasattr(segment, "text") else segment["text"] for segment in transcript_data
|
|
174
|
+
)
|
|
85
175
|
return Message(text=result)
|
|
86
176
|
|
|
87
|
-
except (
|
|
177
|
+
except (TranscriptsDisabled, NoTranscriptFound, RuntimeError, ValueError) as exc:
|
|
88
178
|
error_msg = f"Failed to get YouTube transcripts: {exc!s}"
|
|
89
179
|
return Message(text=error_msg)
|
|
90
180
|
|
|
@@ -100,19 +190,17 @@ class YouTubeTranscriptsComponent(Component):
|
|
|
100
190
|
default_data = {"transcript": "", "video_url": self.url, "error": None}
|
|
101
191
|
|
|
102
192
|
try:
|
|
103
|
-
|
|
104
|
-
if not
|
|
193
|
+
transcript_data = self._load_transcripts(as_chunks=False)
|
|
194
|
+
if not transcript_data:
|
|
105
195
|
default_data["error"] = "No transcripts found."
|
|
106
196
|
return Data(data=default_data)
|
|
107
197
|
|
|
108
|
-
# Combine all transcript
|
|
109
|
-
full_transcript = " ".join(
|
|
198
|
+
# Combine all transcript segments - handle both dict and object formats
|
|
199
|
+
full_transcript = " ".join(
|
|
200
|
+
segment.text if hasattr(segment, "text") else segment["text"] for segment in transcript_data
|
|
201
|
+
)
|
|
110
202
|
return Data(data={"transcript": full_transcript, "video_url": self.url})
|
|
111
203
|
|
|
112
|
-
except (
|
|
113
|
-
youtube_transcript_api.TranscriptsDisabled,
|
|
114
|
-
youtube_transcript_api.NoTranscriptFound,
|
|
115
|
-
youtube_transcript_api.CouldNotRetrieveTranscript,
|
|
116
|
-
) as exc:
|
|
204
|
+
except (TranscriptsDisabled, NoTranscriptFound, RuntimeError, ValueError) as exc:
|
|
117
205
|
default_data["error"] = str(exc)
|
|
118
206
|
return Data(data=default_data)
|