lfx-nightly 0.1.11.dev0__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.
Files changed (699) hide show
  1. lfx/__init__.py +0 -0
  2. lfx/__main__.py +25 -0
  3. lfx/base/__init__.py +0 -0
  4. lfx/base/agents/__init__.py +0 -0
  5. lfx/base/agents/agent.py +268 -0
  6. lfx/base/agents/callback.py +130 -0
  7. lfx/base/agents/context.py +109 -0
  8. lfx/base/agents/crewai/__init__.py +0 -0
  9. lfx/base/agents/crewai/crew.py +231 -0
  10. lfx/base/agents/crewai/tasks.py +12 -0
  11. lfx/base/agents/default_prompts.py +23 -0
  12. lfx/base/agents/errors.py +15 -0
  13. lfx/base/agents/events.py +346 -0
  14. lfx/base/agents/utils.py +205 -0
  15. lfx/base/astra_assistants/__init__.py +0 -0
  16. lfx/base/astra_assistants/util.py +171 -0
  17. lfx/base/chains/__init__.py +0 -0
  18. lfx/base/chains/model.py +19 -0
  19. lfx/base/composio/__init__.py +0 -0
  20. lfx/base/composio/composio_base.py +1291 -0
  21. lfx/base/compressors/__init__.py +0 -0
  22. lfx/base/compressors/model.py +60 -0
  23. lfx/base/constants.py +46 -0
  24. lfx/base/curl/__init__.py +0 -0
  25. lfx/base/curl/parse.py +188 -0
  26. lfx/base/data/__init__.py +5 -0
  27. lfx/base/data/base_file.py +685 -0
  28. lfx/base/data/docling_utils.py +245 -0
  29. lfx/base/data/utils.py +198 -0
  30. lfx/base/document_transformers/__init__.py +0 -0
  31. lfx/base/document_transformers/model.py +43 -0
  32. lfx/base/embeddings/__init__.py +0 -0
  33. lfx/base/embeddings/aiml_embeddings.py +62 -0
  34. lfx/base/embeddings/model.py +26 -0
  35. lfx/base/flow_processing/__init__.py +0 -0
  36. lfx/base/flow_processing/utils.py +86 -0
  37. lfx/base/huggingface/__init__.py +0 -0
  38. lfx/base/huggingface/model_bridge.py +133 -0
  39. lfx/base/io/__init__.py +0 -0
  40. lfx/base/io/chat.py +20 -0
  41. lfx/base/io/text.py +22 -0
  42. lfx/base/langchain_utilities/__init__.py +0 -0
  43. lfx/base/langchain_utilities/model.py +35 -0
  44. lfx/base/langchain_utilities/spider_constants.py +1 -0
  45. lfx/base/langwatch/__init__.py +0 -0
  46. lfx/base/langwatch/utils.py +18 -0
  47. lfx/base/mcp/__init__.py +0 -0
  48. lfx/base/mcp/constants.py +2 -0
  49. lfx/base/mcp/util.py +1398 -0
  50. lfx/base/memory/__init__.py +0 -0
  51. lfx/base/memory/memory.py +49 -0
  52. lfx/base/memory/model.py +38 -0
  53. lfx/base/models/__init__.py +3 -0
  54. lfx/base/models/aiml_constants.py +51 -0
  55. lfx/base/models/anthropic_constants.py +47 -0
  56. lfx/base/models/aws_constants.py +151 -0
  57. lfx/base/models/chat_result.py +76 -0
  58. lfx/base/models/google_generative_ai_constants.py +70 -0
  59. lfx/base/models/groq_constants.py +134 -0
  60. lfx/base/models/model.py +375 -0
  61. lfx/base/models/model_input_constants.py +307 -0
  62. lfx/base/models/model_metadata.py +41 -0
  63. lfx/base/models/model_utils.py +8 -0
  64. lfx/base/models/novita_constants.py +35 -0
  65. lfx/base/models/ollama_constants.py +49 -0
  66. lfx/base/models/openai_constants.py +122 -0
  67. lfx/base/models/sambanova_constants.py +18 -0
  68. lfx/base/processing/__init__.py +0 -0
  69. lfx/base/prompts/__init__.py +0 -0
  70. lfx/base/prompts/api_utils.py +224 -0
  71. lfx/base/prompts/utils.py +61 -0
  72. lfx/base/textsplitters/__init__.py +0 -0
  73. lfx/base/textsplitters/model.py +28 -0
  74. lfx/base/tools/__init__.py +0 -0
  75. lfx/base/tools/base.py +26 -0
  76. lfx/base/tools/component_tool.py +325 -0
  77. lfx/base/tools/constants.py +49 -0
  78. lfx/base/tools/flow_tool.py +132 -0
  79. lfx/base/tools/run_flow.py +224 -0
  80. lfx/base/vectorstores/__init__.py +0 -0
  81. lfx/base/vectorstores/model.py +193 -0
  82. lfx/base/vectorstores/utils.py +22 -0
  83. lfx/base/vectorstores/vector_store_connection_decorator.py +52 -0
  84. lfx/cli/__init__.py +5 -0
  85. lfx/cli/commands.py +319 -0
  86. lfx/cli/common.py +650 -0
  87. lfx/cli/run.py +441 -0
  88. lfx/cli/script_loader.py +247 -0
  89. lfx/cli/serve_app.py +546 -0
  90. lfx/cli/validation.py +69 -0
  91. lfx/components/FAISS/__init__.py +34 -0
  92. lfx/components/FAISS/faiss.py +111 -0
  93. lfx/components/Notion/__init__.py +19 -0
  94. lfx/components/Notion/add_content_to_page.py +269 -0
  95. lfx/components/Notion/create_page.py +94 -0
  96. lfx/components/Notion/list_database_properties.py +68 -0
  97. lfx/components/Notion/list_pages.py +122 -0
  98. lfx/components/Notion/list_users.py +77 -0
  99. lfx/components/Notion/page_content_viewer.py +93 -0
  100. lfx/components/Notion/search.py +111 -0
  101. lfx/components/Notion/update_page_property.py +114 -0
  102. lfx/components/__init__.py +411 -0
  103. lfx/components/_importing.py +42 -0
  104. lfx/components/agentql/__init__.py +3 -0
  105. lfx/components/agentql/agentql_api.py +151 -0
  106. lfx/components/agents/__init__.py +34 -0
  107. lfx/components/agents/agent.py +558 -0
  108. lfx/components/agents/mcp_component.py +501 -0
  109. lfx/components/aiml/__init__.py +37 -0
  110. lfx/components/aiml/aiml.py +112 -0
  111. lfx/components/aiml/aiml_embeddings.py +37 -0
  112. lfx/components/amazon/__init__.py +36 -0
  113. lfx/components/amazon/amazon_bedrock_embedding.py +109 -0
  114. lfx/components/amazon/amazon_bedrock_model.py +124 -0
  115. lfx/components/amazon/s3_bucket_uploader.py +211 -0
  116. lfx/components/anthropic/__init__.py +34 -0
  117. lfx/components/anthropic/anthropic.py +187 -0
  118. lfx/components/apify/__init__.py +5 -0
  119. lfx/components/apify/apify_actor.py +325 -0
  120. lfx/components/arxiv/__init__.py +3 -0
  121. lfx/components/arxiv/arxiv.py +163 -0
  122. lfx/components/assemblyai/__init__.py +46 -0
  123. lfx/components/assemblyai/assemblyai_get_subtitles.py +83 -0
  124. lfx/components/assemblyai/assemblyai_lemur.py +183 -0
  125. lfx/components/assemblyai/assemblyai_list_transcripts.py +95 -0
  126. lfx/components/assemblyai/assemblyai_poll_transcript.py +72 -0
  127. lfx/components/assemblyai/assemblyai_start_transcript.py +188 -0
  128. lfx/components/azure/__init__.py +37 -0
  129. lfx/components/azure/azure_openai.py +95 -0
  130. lfx/components/azure/azure_openai_embeddings.py +83 -0
  131. lfx/components/baidu/__init__.py +32 -0
  132. lfx/components/baidu/baidu_qianfan_chat.py +113 -0
  133. lfx/components/bing/__init__.py +3 -0
  134. lfx/components/bing/bing_search_api.py +61 -0
  135. lfx/components/cassandra/__init__.py +40 -0
  136. lfx/components/cassandra/cassandra.py +264 -0
  137. lfx/components/cassandra/cassandra_chat.py +92 -0
  138. lfx/components/cassandra/cassandra_graph.py +238 -0
  139. lfx/components/chains/__init__.py +3 -0
  140. lfx/components/chroma/__init__.py +34 -0
  141. lfx/components/chroma/chroma.py +167 -0
  142. lfx/components/cleanlab/__init__.py +40 -0
  143. lfx/components/cleanlab/cleanlab_evaluator.py +155 -0
  144. lfx/components/cleanlab/cleanlab_rag_evaluator.py +254 -0
  145. lfx/components/cleanlab/cleanlab_remediator.py +131 -0
  146. lfx/components/clickhouse/__init__.py +34 -0
  147. lfx/components/clickhouse/clickhouse.py +135 -0
  148. lfx/components/cloudflare/__init__.py +32 -0
  149. lfx/components/cloudflare/cloudflare.py +81 -0
  150. lfx/components/cohere/__init__.py +40 -0
  151. lfx/components/cohere/cohere_embeddings.py +81 -0
  152. lfx/components/cohere/cohere_models.py +46 -0
  153. lfx/components/cohere/cohere_rerank.py +51 -0
  154. lfx/components/composio/__init__.py +74 -0
  155. lfx/components/composio/composio_api.py +268 -0
  156. lfx/components/composio/dropbox_compnent.py +11 -0
  157. lfx/components/composio/github_composio.py +11 -0
  158. lfx/components/composio/gmail_composio.py +38 -0
  159. lfx/components/composio/googlecalendar_composio.py +11 -0
  160. lfx/components/composio/googlemeet_composio.py +11 -0
  161. lfx/components/composio/googletasks_composio.py +8 -0
  162. lfx/components/composio/linear_composio.py +11 -0
  163. lfx/components/composio/outlook_composio.py +11 -0
  164. lfx/components/composio/reddit_composio.py +11 -0
  165. lfx/components/composio/slack_composio.py +582 -0
  166. lfx/components/composio/slackbot_composio.py +11 -0
  167. lfx/components/composio/supabase_composio.py +11 -0
  168. lfx/components/composio/todoist_composio.py +11 -0
  169. lfx/components/composio/youtube_composio.py +11 -0
  170. lfx/components/confluence/__init__.py +3 -0
  171. lfx/components/confluence/confluence.py +84 -0
  172. lfx/components/couchbase/__init__.py +34 -0
  173. lfx/components/couchbase/couchbase.py +102 -0
  174. lfx/components/crewai/__init__.py +49 -0
  175. lfx/components/crewai/crewai.py +107 -0
  176. lfx/components/crewai/hierarchical_crew.py +46 -0
  177. lfx/components/crewai/hierarchical_task.py +44 -0
  178. lfx/components/crewai/sequential_crew.py +52 -0
  179. lfx/components/crewai/sequential_task.py +73 -0
  180. lfx/components/crewai/sequential_task_agent.py +143 -0
  181. lfx/components/custom_component/__init__.py +34 -0
  182. lfx/components/custom_component/custom_component.py +31 -0
  183. lfx/components/data/__init__.py +64 -0
  184. lfx/components/data/api_request.py +544 -0
  185. lfx/components/data/csv_to_data.py +95 -0
  186. lfx/components/data/directory.py +113 -0
  187. lfx/components/data/file.py +577 -0
  188. lfx/components/data/json_to_data.py +98 -0
  189. lfx/components/data/news_search.py +164 -0
  190. lfx/components/data/rss.py +69 -0
  191. lfx/components/data/sql_executor.py +101 -0
  192. lfx/components/data/url.py +311 -0
  193. lfx/components/data/web_search.py +112 -0
  194. lfx/components/data/webhook.py +56 -0
  195. lfx/components/datastax/__init__.py +70 -0
  196. lfx/components/datastax/astra_assistant_manager.py +306 -0
  197. lfx/components/datastax/astra_db.py +75 -0
  198. lfx/components/datastax/astra_vectorize.py +124 -0
  199. lfx/components/datastax/astradb.py +1285 -0
  200. lfx/components/datastax/astradb_cql.py +314 -0
  201. lfx/components/datastax/astradb_graph.py +330 -0
  202. lfx/components/datastax/astradb_tool.py +414 -0
  203. lfx/components/datastax/astradb_vectorstore.py +1285 -0
  204. lfx/components/datastax/cassandra.py +92 -0
  205. lfx/components/datastax/create_assistant.py +58 -0
  206. lfx/components/datastax/create_thread.py +32 -0
  207. lfx/components/datastax/dotenv.py +35 -0
  208. lfx/components/datastax/get_assistant.py +37 -0
  209. lfx/components/datastax/getenvvar.py +30 -0
  210. lfx/components/datastax/graph_rag.py +141 -0
  211. lfx/components/datastax/hcd.py +314 -0
  212. lfx/components/datastax/list_assistants.py +25 -0
  213. lfx/components/datastax/run.py +89 -0
  214. lfx/components/deactivated/__init__.py +15 -0
  215. lfx/components/deactivated/amazon_kendra.py +66 -0
  216. lfx/components/deactivated/chat_litellm_model.py +158 -0
  217. lfx/components/deactivated/code_block_extractor.py +26 -0
  218. lfx/components/deactivated/documents_to_data.py +22 -0
  219. lfx/components/deactivated/embed.py +16 -0
  220. lfx/components/deactivated/extract_key_from_data.py +46 -0
  221. lfx/components/deactivated/json_document_builder.py +57 -0
  222. lfx/components/deactivated/list_flows.py +20 -0
  223. lfx/components/deactivated/mcp_sse.py +61 -0
  224. lfx/components/deactivated/mcp_stdio.py +62 -0
  225. lfx/components/deactivated/merge_data.py +93 -0
  226. lfx/components/deactivated/message.py +37 -0
  227. lfx/components/deactivated/metal.py +54 -0
  228. lfx/components/deactivated/multi_query.py +59 -0
  229. lfx/components/deactivated/retriever.py +43 -0
  230. lfx/components/deactivated/selective_passthrough.py +77 -0
  231. lfx/components/deactivated/should_run_next.py +40 -0
  232. lfx/components/deactivated/split_text.py +63 -0
  233. lfx/components/deactivated/store_message.py +24 -0
  234. lfx/components/deactivated/sub_flow.py +124 -0
  235. lfx/components/deactivated/vectara_self_query.py +76 -0
  236. lfx/components/deactivated/vector_store.py +24 -0
  237. lfx/components/deepseek/__init__.py +34 -0
  238. lfx/components/deepseek/deepseek.py +136 -0
  239. lfx/components/docling/__init__.py +43 -0
  240. lfx/components/docling/chunk_docling_document.py +186 -0
  241. lfx/components/docling/docling_inline.py +231 -0
  242. lfx/components/docling/docling_remote.py +193 -0
  243. lfx/components/docling/export_docling_document.py +117 -0
  244. lfx/components/documentloaders/__init__.py +3 -0
  245. lfx/components/duckduckgo/__init__.py +3 -0
  246. lfx/components/duckduckgo/duck_duck_go_search_run.py +92 -0
  247. lfx/components/elastic/__init__.py +37 -0
  248. lfx/components/elastic/elasticsearch.py +267 -0
  249. lfx/components/elastic/opensearch.py +243 -0
  250. lfx/components/embeddings/__init__.py +37 -0
  251. lfx/components/embeddings/similarity.py +76 -0
  252. lfx/components/embeddings/text_embedder.py +64 -0
  253. lfx/components/exa/__init__.py +3 -0
  254. lfx/components/exa/exa_search.py +68 -0
  255. lfx/components/firecrawl/__init__.py +43 -0
  256. lfx/components/firecrawl/firecrawl_crawl_api.py +88 -0
  257. lfx/components/firecrawl/firecrawl_extract_api.py +136 -0
  258. lfx/components/firecrawl/firecrawl_map_api.py +89 -0
  259. lfx/components/firecrawl/firecrawl_scrape_api.py +73 -0
  260. lfx/components/git/__init__.py +4 -0
  261. lfx/components/git/git.py +262 -0
  262. lfx/components/git/gitextractor.py +196 -0
  263. lfx/components/glean/__init__.py +3 -0
  264. lfx/components/glean/glean_search_api.py +173 -0
  265. lfx/components/google/__init__.py +17 -0
  266. lfx/components/google/gmail.py +192 -0
  267. lfx/components/google/google_bq_sql_executor.py +157 -0
  268. lfx/components/google/google_drive.py +92 -0
  269. lfx/components/google/google_drive_search.py +152 -0
  270. lfx/components/google/google_generative_ai.py +147 -0
  271. lfx/components/google/google_generative_ai_embeddings.py +141 -0
  272. lfx/components/google/google_oauth_token.py +89 -0
  273. lfx/components/google/google_search_api_core.py +68 -0
  274. lfx/components/google/google_serper_api_core.py +74 -0
  275. lfx/components/groq/__init__.py +34 -0
  276. lfx/components/groq/groq.py +136 -0
  277. lfx/components/helpers/__init__.py +52 -0
  278. lfx/components/helpers/calculator_core.py +89 -0
  279. lfx/components/helpers/create_list.py +40 -0
  280. lfx/components/helpers/current_date.py +42 -0
  281. lfx/components/helpers/id_generator.py +42 -0
  282. lfx/components/helpers/memory.py +251 -0
  283. lfx/components/helpers/output_parser.py +45 -0
  284. lfx/components/helpers/store_message.py +90 -0
  285. lfx/components/homeassistant/__init__.py +7 -0
  286. lfx/components/homeassistant/home_assistant_control.py +152 -0
  287. lfx/components/homeassistant/list_home_assistant_states.py +137 -0
  288. lfx/components/huggingface/__init__.py +37 -0
  289. lfx/components/huggingface/huggingface.py +197 -0
  290. lfx/components/huggingface/huggingface_inference_api.py +106 -0
  291. lfx/components/ibm/__init__.py +34 -0
  292. lfx/components/ibm/watsonx.py +203 -0
  293. lfx/components/ibm/watsonx_embeddings.py +135 -0
  294. lfx/components/icosacomputing/__init__.py +5 -0
  295. lfx/components/icosacomputing/combinatorial_reasoner.py +84 -0
  296. lfx/components/input_output/__init__.py +38 -0
  297. lfx/components/input_output/chat.py +120 -0
  298. lfx/components/input_output/chat_output.py +200 -0
  299. lfx/components/input_output/text.py +27 -0
  300. lfx/components/input_output/text_output.py +29 -0
  301. lfx/components/jigsawstack/__init__.py +23 -0
  302. lfx/components/jigsawstack/ai_scrape.py +126 -0
  303. lfx/components/jigsawstack/ai_web_search.py +136 -0
  304. lfx/components/jigsawstack/file_read.py +115 -0
  305. lfx/components/jigsawstack/file_upload.py +94 -0
  306. lfx/components/jigsawstack/image_generation.py +205 -0
  307. lfx/components/jigsawstack/nsfw.py +60 -0
  308. lfx/components/jigsawstack/object_detection.py +124 -0
  309. lfx/components/jigsawstack/sentiment.py +112 -0
  310. lfx/components/jigsawstack/text_to_sql.py +90 -0
  311. lfx/components/jigsawstack/text_translate.py +77 -0
  312. lfx/components/jigsawstack/vocr.py +107 -0
  313. lfx/components/langchain_utilities/__init__.py +109 -0
  314. lfx/components/langchain_utilities/character.py +53 -0
  315. lfx/components/langchain_utilities/conversation.py +59 -0
  316. lfx/components/langchain_utilities/csv_agent.py +107 -0
  317. lfx/components/langchain_utilities/fake_embeddings.py +26 -0
  318. lfx/components/langchain_utilities/html_link_extractor.py +35 -0
  319. lfx/components/langchain_utilities/json_agent.py +45 -0
  320. lfx/components/langchain_utilities/langchain_hub.py +126 -0
  321. lfx/components/langchain_utilities/language_recursive.py +49 -0
  322. lfx/components/langchain_utilities/language_semantic.py +138 -0
  323. lfx/components/langchain_utilities/llm_checker.py +39 -0
  324. lfx/components/langchain_utilities/llm_math.py +42 -0
  325. lfx/components/langchain_utilities/natural_language.py +61 -0
  326. lfx/components/langchain_utilities/openai_tools.py +53 -0
  327. lfx/components/langchain_utilities/openapi.py +48 -0
  328. lfx/components/langchain_utilities/recursive_character.py +60 -0
  329. lfx/components/langchain_utilities/retrieval_qa.py +83 -0
  330. lfx/components/langchain_utilities/runnable_executor.py +137 -0
  331. lfx/components/langchain_utilities/self_query.py +80 -0
  332. lfx/components/langchain_utilities/spider.py +142 -0
  333. lfx/components/langchain_utilities/sql.py +40 -0
  334. lfx/components/langchain_utilities/sql_database.py +35 -0
  335. lfx/components/langchain_utilities/sql_generator.py +78 -0
  336. lfx/components/langchain_utilities/tool_calling.py +59 -0
  337. lfx/components/langchain_utilities/vector_store_info.py +49 -0
  338. lfx/components/langchain_utilities/vector_store_router.py +33 -0
  339. lfx/components/langchain_utilities/xml_agent.py +71 -0
  340. lfx/components/langwatch/__init__.py +3 -0
  341. lfx/components/langwatch/langwatch.py +278 -0
  342. lfx/components/link_extractors/__init__.py +3 -0
  343. lfx/components/lmstudio/__init__.py +34 -0
  344. lfx/components/lmstudio/lmstudioembeddings.py +89 -0
  345. lfx/components/lmstudio/lmstudiomodel.py +129 -0
  346. lfx/components/logic/__init__.py +52 -0
  347. lfx/components/logic/conditional_router.py +171 -0
  348. lfx/components/logic/data_conditional_router.py +125 -0
  349. lfx/components/logic/flow_tool.py +110 -0
  350. lfx/components/logic/listen.py +29 -0
  351. lfx/components/logic/loop.py +125 -0
  352. lfx/components/logic/notify.py +88 -0
  353. lfx/components/logic/pass_message.py +35 -0
  354. lfx/components/logic/run_flow.py +71 -0
  355. lfx/components/logic/sub_flow.py +114 -0
  356. lfx/components/maritalk/__init__.py +32 -0
  357. lfx/components/maritalk/maritalk.py +52 -0
  358. lfx/components/mem0/__init__.py +3 -0
  359. lfx/components/mem0/mem0_chat_memory.py +136 -0
  360. lfx/components/milvus/__init__.py +34 -0
  361. lfx/components/milvus/milvus.py +115 -0
  362. lfx/components/mistral/__init__.py +37 -0
  363. lfx/components/mistral/mistral.py +114 -0
  364. lfx/components/mistral/mistral_embeddings.py +58 -0
  365. lfx/components/models/__init__.py +34 -0
  366. lfx/components/models/embedding_model.py +114 -0
  367. lfx/components/models/language_model.py +144 -0
  368. lfx/components/mongodb/__init__.py +34 -0
  369. lfx/components/mongodb/mongodb_atlas.py +213 -0
  370. lfx/components/needle/__init__.py +3 -0
  371. lfx/components/needle/needle.py +104 -0
  372. lfx/components/notdiamond/__init__.py +34 -0
  373. lfx/components/notdiamond/notdiamond.py +228 -0
  374. lfx/components/novita/__init__.py +32 -0
  375. lfx/components/novita/novita.py +130 -0
  376. lfx/components/nvidia/__init__.py +57 -0
  377. lfx/components/nvidia/nvidia.py +157 -0
  378. lfx/components/nvidia/nvidia_embedding.py +77 -0
  379. lfx/components/nvidia/nvidia_ingest.py +317 -0
  380. lfx/components/nvidia/nvidia_rerank.py +63 -0
  381. lfx/components/nvidia/system_assist.py +65 -0
  382. lfx/components/olivya/__init__.py +3 -0
  383. lfx/components/olivya/olivya.py +116 -0
  384. lfx/components/ollama/__init__.py +37 -0
  385. lfx/components/ollama/ollama.py +330 -0
  386. lfx/components/ollama/ollama_embeddings.py +106 -0
  387. lfx/components/openai/__init__.py +37 -0
  388. lfx/components/openai/openai.py +100 -0
  389. lfx/components/openai/openai_chat_model.py +176 -0
  390. lfx/components/openrouter/__init__.py +32 -0
  391. lfx/components/openrouter/openrouter.py +202 -0
  392. lfx/components/output_parsers/__init__.py +3 -0
  393. lfx/components/perplexity/__init__.py +34 -0
  394. lfx/components/perplexity/perplexity.py +75 -0
  395. lfx/components/pgvector/__init__.py +34 -0
  396. lfx/components/pgvector/pgvector.py +72 -0
  397. lfx/components/pinecone/__init__.py +34 -0
  398. lfx/components/pinecone/pinecone.py +134 -0
  399. lfx/components/processing/__init__.py +117 -0
  400. lfx/components/processing/alter_metadata.py +108 -0
  401. lfx/components/processing/batch_run.py +205 -0
  402. lfx/components/processing/combine_text.py +39 -0
  403. lfx/components/processing/converter.py +159 -0
  404. lfx/components/processing/create_data.py +110 -0
  405. lfx/components/processing/data_operations.py +438 -0
  406. lfx/components/processing/data_to_dataframe.py +70 -0
  407. lfx/components/processing/dataframe_operations.py +313 -0
  408. lfx/components/processing/extract_key.py +53 -0
  409. lfx/components/processing/filter_data.py +42 -0
  410. lfx/components/processing/filter_data_values.py +88 -0
  411. lfx/components/processing/json_cleaner.py +103 -0
  412. lfx/components/processing/lambda_filter.py +154 -0
  413. lfx/components/processing/llm_router.py +499 -0
  414. lfx/components/processing/merge_data.py +90 -0
  415. lfx/components/processing/message_to_data.py +36 -0
  416. lfx/components/processing/parse_data.py +70 -0
  417. lfx/components/processing/parse_dataframe.py +68 -0
  418. lfx/components/processing/parse_json_data.py +90 -0
  419. lfx/components/processing/parser.py +143 -0
  420. lfx/components/processing/prompt.py +67 -0
  421. lfx/components/processing/python_repl_core.py +98 -0
  422. lfx/components/processing/regex.py +82 -0
  423. lfx/components/processing/save_file.py +225 -0
  424. lfx/components/processing/select_data.py +48 -0
  425. lfx/components/processing/split_text.py +141 -0
  426. lfx/components/processing/structured_output.py +202 -0
  427. lfx/components/processing/update_data.py +160 -0
  428. lfx/components/prototypes/__init__.py +34 -0
  429. lfx/components/prototypes/python_function.py +73 -0
  430. lfx/components/qdrant/__init__.py +34 -0
  431. lfx/components/qdrant/qdrant.py +109 -0
  432. lfx/components/redis/__init__.py +37 -0
  433. lfx/components/redis/redis.py +89 -0
  434. lfx/components/redis/redis_chat.py +43 -0
  435. lfx/components/sambanova/__init__.py +32 -0
  436. lfx/components/sambanova/sambanova.py +84 -0
  437. lfx/components/scrapegraph/__init__.py +40 -0
  438. lfx/components/scrapegraph/scrapegraph_markdownify_api.py +64 -0
  439. lfx/components/scrapegraph/scrapegraph_search_api.py +64 -0
  440. lfx/components/scrapegraph/scrapegraph_smart_scraper_api.py +71 -0
  441. lfx/components/searchapi/__init__.py +34 -0
  442. lfx/components/searchapi/search.py +79 -0
  443. lfx/components/serpapi/__init__.py +3 -0
  444. lfx/components/serpapi/serp.py +115 -0
  445. lfx/components/supabase/__init__.py +34 -0
  446. lfx/components/supabase/supabase.py +76 -0
  447. lfx/components/tavily/__init__.py +4 -0
  448. lfx/components/tavily/tavily_extract.py +117 -0
  449. lfx/components/tavily/tavily_search.py +212 -0
  450. lfx/components/textsplitters/__init__.py +3 -0
  451. lfx/components/toolkits/__init__.py +3 -0
  452. lfx/components/tools/__init__.py +72 -0
  453. lfx/components/tools/calculator.py +108 -0
  454. lfx/components/tools/google_search_api.py +45 -0
  455. lfx/components/tools/google_serper_api.py +115 -0
  456. lfx/components/tools/python_code_structured_tool.py +327 -0
  457. lfx/components/tools/python_repl.py +97 -0
  458. lfx/components/tools/search_api.py +87 -0
  459. lfx/components/tools/searxng.py +145 -0
  460. lfx/components/tools/serp_api.py +119 -0
  461. lfx/components/tools/tavily_search_tool.py +344 -0
  462. lfx/components/tools/wikidata_api.py +102 -0
  463. lfx/components/tools/wikipedia_api.py +49 -0
  464. lfx/components/tools/yahoo_finance.py +129 -0
  465. lfx/components/twelvelabs/__init__.py +52 -0
  466. lfx/components/twelvelabs/convert_astra_results.py +84 -0
  467. lfx/components/twelvelabs/pegasus_index.py +311 -0
  468. lfx/components/twelvelabs/split_video.py +291 -0
  469. lfx/components/twelvelabs/text_embeddings.py +57 -0
  470. lfx/components/twelvelabs/twelvelabs_pegasus.py +408 -0
  471. lfx/components/twelvelabs/video_embeddings.py +100 -0
  472. lfx/components/twelvelabs/video_file.py +179 -0
  473. lfx/components/unstructured/__init__.py +3 -0
  474. lfx/components/unstructured/unstructured.py +121 -0
  475. lfx/components/upstash/__init__.py +34 -0
  476. lfx/components/upstash/upstash.py +124 -0
  477. lfx/components/vectara/__init__.py +37 -0
  478. lfx/components/vectara/vectara.py +97 -0
  479. lfx/components/vectara/vectara_rag.py +164 -0
  480. lfx/components/vectorstores/__init__.py +40 -0
  481. lfx/components/vectorstores/astradb.py +1285 -0
  482. lfx/components/vectorstores/astradb_graph.py +319 -0
  483. lfx/components/vectorstores/cassandra.py +264 -0
  484. lfx/components/vectorstores/cassandra_graph.py +238 -0
  485. lfx/components/vectorstores/chroma.py +167 -0
  486. lfx/components/vectorstores/clickhouse.py +135 -0
  487. lfx/components/vectorstores/couchbase.py +102 -0
  488. lfx/components/vectorstores/elasticsearch.py +267 -0
  489. lfx/components/vectorstores/faiss.py +111 -0
  490. lfx/components/vectorstores/graph_rag.py +141 -0
  491. lfx/components/vectorstores/hcd.py +314 -0
  492. lfx/components/vectorstores/local_db.py +261 -0
  493. lfx/components/vectorstores/milvus.py +115 -0
  494. lfx/components/vectorstores/mongodb_atlas.py +213 -0
  495. lfx/components/vectorstores/opensearch.py +243 -0
  496. lfx/components/vectorstores/pgvector.py +72 -0
  497. lfx/components/vectorstores/pinecone.py +134 -0
  498. lfx/components/vectorstores/qdrant.py +109 -0
  499. lfx/components/vectorstores/supabase.py +76 -0
  500. lfx/components/vectorstores/upstash.py +124 -0
  501. lfx/components/vectorstores/vectara.py +97 -0
  502. lfx/components/vectorstores/vectara_rag.py +164 -0
  503. lfx/components/vectorstores/weaviate.py +89 -0
  504. lfx/components/vertexai/__init__.py +37 -0
  505. lfx/components/vertexai/vertexai.py +71 -0
  506. lfx/components/vertexai/vertexai_embeddings.py +67 -0
  507. lfx/components/weaviate/__init__.py +34 -0
  508. lfx/components/weaviate/weaviate.py +89 -0
  509. lfx/components/wikipedia/__init__.py +4 -0
  510. lfx/components/wikipedia/wikidata.py +86 -0
  511. lfx/components/wikipedia/wikipedia.py +53 -0
  512. lfx/components/wolframalpha/__init__.py +3 -0
  513. lfx/components/wolframalpha/wolfram_alpha_api.py +54 -0
  514. lfx/components/xai/__init__.py +32 -0
  515. lfx/components/xai/xai.py +167 -0
  516. lfx/components/yahoosearch/__init__.py +3 -0
  517. lfx/components/yahoosearch/yahoo.py +137 -0
  518. lfx/components/youtube/__init__.py +52 -0
  519. lfx/components/youtube/channel.py +227 -0
  520. lfx/components/youtube/comments.py +231 -0
  521. lfx/components/youtube/playlist.py +33 -0
  522. lfx/components/youtube/search.py +120 -0
  523. lfx/components/youtube/trending.py +285 -0
  524. lfx/components/youtube/video_details.py +263 -0
  525. lfx/components/youtube/youtube_transcripts.py +118 -0
  526. lfx/components/zep/__init__.py +3 -0
  527. lfx/components/zep/zep.py +44 -0
  528. lfx/constants.py +6 -0
  529. lfx/custom/__init__.py +7 -0
  530. lfx/custom/attributes.py +86 -0
  531. lfx/custom/code_parser/__init__.py +3 -0
  532. lfx/custom/code_parser/code_parser.py +361 -0
  533. lfx/custom/custom_component/__init__.py +0 -0
  534. lfx/custom/custom_component/base_component.py +128 -0
  535. lfx/custom/custom_component/component.py +1808 -0
  536. lfx/custom/custom_component/component_with_cache.py +8 -0
  537. lfx/custom/custom_component/custom_component.py +588 -0
  538. lfx/custom/dependency_analyzer.py +165 -0
  539. lfx/custom/directory_reader/__init__.py +3 -0
  540. lfx/custom/directory_reader/directory_reader.py +359 -0
  541. lfx/custom/directory_reader/utils.py +171 -0
  542. lfx/custom/eval.py +12 -0
  543. lfx/custom/schema.py +32 -0
  544. lfx/custom/tree_visitor.py +21 -0
  545. lfx/custom/utils.py +877 -0
  546. lfx/custom/validate.py +488 -0
  547. lfx/events/__init__.py +1 -0
  548. lfx/events/event_manager.py +110 -0
  549. lfx/exceptions/__init__.py +0 -0
  550. lfx/exceptions/component.py +15 -0
  551. lfx/field_typing/__init__.py +91 -0
  552. lfx/field_typing/constants.py +215 -0
  553. lfx/field_typing/range_spec.py +35 -0
  554. lfx/graph/__init__.py +6 -0
  555. lfx/graph/edge/__init__.py +0 -0
  556. lfx/graph/edge/base.py +277 -0
  557. lfx/graph/edge/schema.py +119 -0
  558. lfx/graph/edge/utils.py +0 -0
  559. lfx/graph/graph/__init__.py +0 -0
  560. lfx/graph/graph/ascii.py +202 -0
  561. lfx/graph/graph/base.py +2238 -0
  562. lfx/graph/graph/constants.py +63 -0
  563. lfx/graph/graph/runnable_vertices_manager.py +133 -0
  564. lfx/graph/graph/schema.py +52 -0
  565. lfx/graph/graph/state_model.py +66 -0
  566. lfx/graph/graph/utils.py +1024 -0
  567. lfx/graph/schema.py +75 -0
  568. lfx/graph/state/__init__.py +0 -0
  569. lfx/graph/state/model.py +237 -0
  570. lfx/graph/utils.py +200 -0
  571. lfx/graph/vertex/__init__.py +0 -0
  572. lfx/graph/vertex/base.py +823 -0
  573. lfx/graph/vertex/constants.py +0 -0
  574. lfx/graph/vertex/exceptions.py +4 -0
  575. lfx/graph/vertex/param_handler.py +264 -0
  576. lfx/graph/vertex/schema.py +26 -0
  577. lfx/graph/vertex/utils.py +19 -0
  578. lfx/graph/vertex/vertex_types.py +489 -0
  579. lfx/helpers/__init__.py +1 -0
  580. lfx/helpers/base_model.py +71 -0
  581. lfx/helpers/custom.py +13 -0
  582. lfx/helpers/data.py +167 -0
  583. lfx/helpers/flow.py +194 -0
  584. lfx/inputs/__init__.py +68 -0
  585. lfx/inputs/constants.py +2 -0
  586. lfx/inputs/input_mixin.py +328 -0
  587. lfx/inputs/inputs.py +714 -0
  588. lfx/inputs/validators.py +19 -0
  589. lfx/interface/__init__.py +6 -0
  590. lfx/interface/components.py +489 -0
  591. lfx/interface/importing/__init__.py +5 -0
  592. lfx/interface/importing/utils.py +39 -0
  593. lfx/interface/initialize/__init__.py +3 -0
  594. lfx/interface/initialize/loading.py +224 -0
  595. lfx/interface/listing.py +26 -0
  596. lfx/interface/run.py +16 -0
  597. lfx/interface/utils.py +111 -0
  598. lfx/io/__init__.py +63 -0
  599. lfx/io/schema.py +289 -0
  600. lfx/load/__init__.py +8 -0
  601. lfx/load/load.py +256 -0
  602. lfx/load/utils.py +99 -0
  603. lfx/log/__init__.py +5 -0
  604. lfx/log/logger.py +385 -0
  605. lfx/memory/__init__.py +90 -0
  606. lfx/memory/stubs.py +283 -0
  607. lfx/processing/__init__.py +1 -0
  608. lfx/processing/process.py +238 -0
  609. lfx/processing/utils.py +25 -0
  610. lfx/py.typed +0 -0
  611. lfx/schema/__init__.py +66 -0
  612. lfx/schema/artifact.py +83 -0
  613. lfx/schema/content_block.py +62 -0
  614. lfx/schema/content_types.py +91 -0
  615. lfx/schema/data.py +308 -0
  616. lfx/schema/dataframe.py +210 -0
  617. lfx/schema/dotdict.py +74 -0
  618. lfx/schema/encoders.py +13 -0
  619. lfx/schema/graph.py +47 -0
  620. lfx/schema/image.py +131 -0
  621. lfx/schema/json_schema.py +141 -0
  622. lfx/schema/log.py +61 -0
  623. lfx/schema/message.py +473 -0
  624. lfx/schema/openai_responses_schemas.py +74 -0
  625. lfx/schema/properties.py +41 -0
  626. lfx/schema/schema.py +171 -0
  627. lfx/schema/serialize.py +13 -0
  628. lfx/schema/table.py +140 -0
  629. lfx/schema/validators.py +114 -0
  630. lfx/serialization/__init__.py +5 -0
  631. lfx/serialization/constants.py +2 -0
  632. lfx/serialization/serialization.py +314 -0
  633. lfx/services/__init__.py +23 -0
  634. lfx/services/base.py +28 -0
  635. lfx/services/cache/__init__.py +6 -0
  636. lfx/services/cache/base.py +183 -0
  637. lfx/services/cache/service.py +166 -0
  638. lfx/services/cache/utils.py +169 -0
  639. lfx/services/chat/__init__.py +1 -0
  640. lfx/services/chat/config.py +2 -0
  641. lfx/services/chat/schema.py +10 -0
  642. lfx/services/deps.py +129 -0
  643. lfx/services/factory.py +19 -0
  644. lfx/services/initialize.py +19 -0
  645. lfx/services/interfaces.py +103 -0
  646. lfx/services/manager.py +172 -0
  647. lfx/services/schema.py +20 -0
  648. lfx/services/session.py +82 -0
  649. lfx/services/settings/__init__.py +3 -0
  650. lfx/services/settings/auth.py +130 -0
  651. lfx/services/settings/base.py +539 -0
  652. lfx/services/settings/constants.py +31 -0
  653. lfx/services/settings/factory.py +23 -0
  654. lfx/services/settings/feature_flags.py +12 -0
  655. lfx/services/settings/service.py +35 -0
  656. lfx/services/settings/utils.py +40 -0
  657. lfx/services/shared_component_cache/__init__.py +1 -0
  658. lfx/services/shared_component_cache/factory.py +30 -0
  659. lfx/services/shared_component_cache/service.py +9 -0
  660. lfx/services/storage/__init__.py +5 -0
  661. lfx/services/storage/local.py +155 -0
  662. lfx/services/storage/service.py +54 -0
  663. lfx/services/tracing/__init__.py +1 -0
  664. lfx/services/tracing/service.py +21 -0
  665. lfx/settings.py +6 -0
  666. lfx/template/__init__.py +6 -0
  667. lfx/template/field/__init__.py +0 -0
  668. lfx/template/field/base.py +257 -0
  669. lfx/template/field/prompt.py +15 -0
  670. lfx/template/frontend_node/__init__.py +6 -0
  671. lfx/template/frontend_node/base.py +212 -0
  672. lfx/template/frontend_node/constants.py +65 -0
  673. lfx/template/frontend_node/custom_components.py +79 -0
  674. lfx/template/template/__init__.py +0 -0
  675. lfx/template/template/base.py +100 -0
  676. lfx/template/utils.py +217 -0
  677. lfx/type_extraction/__init__.py +19 -0
  678. lfx/type_extraction/type_extraction.py +75 -0
  679. lfx/type_extraction.py +80 -0
  680. lfx/utils/__init__.py +1 -0
  681. lfx/utils/async_helpers.py +42 -0
  682. lfx/utils/component_utils.py +154 -0
  683. lfx/utils/concurrency.py +60 -0
  684. lfx/utils/connection_string_parser.py +11 -0
  685. lfx/utils/constants.py +205 -0
  686. lfx/utils/data_structure.py +212 -0
  687. lfx/utils/exceptions.py +22 -0
  688. lfx/utils/helpers.py +28 -0
  689. lfx/utils/image.py +73 -0
  690. lfx/utils/lazy_load.py +15 -0
  691. lfx/utils/request_utils.py +18 -0
  692. lfx/utils/schemas.py +139 -0
  693. lfx/utils/util.py +481 -0
  694. lfx/utils/util_strings.py +56 -0
  695. lfx/utils/version.py +24 -0
  696. lfx_nightly-0.1.11.dev0.dist-info/METADATA +293 -0
  697. lfx_nightly-0.1.11.dev0.dist-info/RECORD +699 -0
  698. lfx_nightly-0.1.11.dev0.dist-info/WHEEL +4 -0
  699. lfx_nightly-0.1.11.dev0.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,311 @@
1
+ import time
2
+ from concurrent.futures import ThreadPoolExecutor
3
+ from pathlib import Path
4
+ from typing import Any
5
+
6
+ from tenacity import retry, stop_after_attempt, wait_exponential
7
+ from twelvelabs import TwelveLabs
8
+
9
+ from lfx.custom import Component
10
+ from lfx.inputs import DataInput, DropdownInput, SecretStrInput, StrInput
11
+ from lfx.io import Output
12
+ from lfx.schema import Data
13
+
14
+
15
+ class TwelveLabsError(Exception):
16
+ """Base exception for TwelveLabs errors."""
17
+
18
+
19
+ class IndexCreationError(TwelveLabsError):
20
+ """Error raised when there's an issue with an index."""
21
+
22
+
23
+ class TaskError(TwelveLabsError):
24
+ """Error raised when a task fails."""
25
+
26
+
27
+ class TaskTimeoutError(TwelveLabsError):
28
+ """Error raised when a task times out."""
29
+
30
+
31
+ class PegasusIndexVideo(Component):
32
+ """Indexes videos using TwelveLabs Pegasus API and adds the video ID to metadata."""
33
+
34
+ display_name = "TwelveLabs Pegasus Index Video"
35
+ description = "Index videos using TwelveLabs and add the video_id to metadata."
36
+ icon = "TwelveLabs"
37
+ name = "TwelveLabsPegasusIndexVideo"
38
+ documentation = "https://github.com/twelvelabs-io/twelvelabs-developer-experience/blob/main/integrations/Langflow/TWELVE_LABS_COMPONENTS_README.md"
39
+
40
+ inputs = [
41
+ DataInput(
42
+ name="videodata",
43
+ display_name="Video Data",
44
+ info="Video Data objects (from VideoFile or SplitVideo)",
45
+ is_list=True,
46
+ required=True,
47
+ ),
48
+ SecretStrInput(
49
+ name="api_key", display_name="TwelveLabs API Key", info="Enter your TwelveLabs API Key.", required=True
50
+ ),
51
+ DropdownInput(
52
+ name="model_name",
53
+ display_name="Model",
54
+ info="Pegasus model to use for indexing",
55
+ options=["pegasus1.2"],
56
+ value="pegasus1.2",
57
+ advanced=False,
58
+ ),
59
+ StrInput(
60
+ name="index_name",
61
+ display_name="Index Name",
62
+ info="Name of the index to use. If the index doesn't exist, it will be created.",
63
+ required=False,
64
+ ),
65
+ StrInput(
66
+ name="index_id",
67
+ display_name="Index ID",
68
+ info="ID of an existing index to use. If provided, index_name will be ignored.",
69
+ required=False,
70
+ ),
71
+ ]
72
+
73
+ outputs = [
74
+ Output(
75
+ display_name="Indexed Data", name="indexed_data", method="index_videos", output_types=["Data"], is_list=True
76
+ ),
77
+ ]
78
+
79
+ def _get_or_create_index(self, client: TwelveLabs) -> tuple[str, str]:
80
+ """Get existing index or create new one.
81
+
82
+ Returns (index_id, index_name).
83
+ """
84
+ # First check if index_id is provided and valid
85
+ if hasattr(self, "index_id") and self.index_id:
86
+ try:
87
+ index = client.index.retrieve(id=self.index_id)
88
+ except (ValueError, KeyError) as e:
89
+ if not hasattr(self, "index_name") or not self.index_name:
90
+ error_msg = "Invalid index ID provided and no index name specified for fallback"
91
+ raise IndexCreationError(error_msg) from e
92
+ else:
93
+ return self.index_id, index.name
94
+
95
+ # If index_name is provided, try to find it
96
+ if hasattr(self, "index_name") and self.index_name:
97
+ try:
98
+ # List all indexes and find by name
99
+ indexes = client.index.list()
100
+ for idx in indexes:
101
+ if idx.name == self.index_name:
102
+ return idx.id, idx.name
103
+
104
+ # If we get here, index wasn't found - create it
105
+ index = client.index.create(
106
+ name=self.index_name,
107
+ models=[
108
+ {
109
+ "name": self.model_name if hasattr(self, "model_name") else "pegasus1.2",
110
+ "options": ["visual", "audio"],
111
+ }
112
+ ],
113
+ )
114
+ except (ValueError, KeyError) as e:
115
+ error_msg = f"Error with index name {self.index_name}"
116
+ raise IndexCreationError(error_msg) from e
117
+ else:
118
+ return index.id, index.name
119
+
120
+ # If we get here, neither index_id nor index_name was provided
121
+ error_msg = "Either index_name or index_id must be provided"
122
+ raise IndexCreationError(error_msg)
123
+
124
+ def on_task_update(self, task: Any, video_path: str) -> None:
125
+ """Callback for task status updates.
126
+
127
+ Updates the component status with the current task status.
128
+ """
129
+ video_name = Path(video_path).name
130
+ status_msg = f"Indexing {video_name}... Status: {task.status}"
131
+ self.status = status_msg
132
+
133
+ @retry(stop=stop_after_attempt(5), wait=wait_exponential(multiplier=1, min=5, max=60), reraise=True)
134
+ def _check_task_status(
135
+ self,
136
+ client: TwelveLabs,
137
+ task_id: str,
138
+ video_path: str,
139
+ ) -> Any:
140
+ """Check task status once.
141
+
142
+ Makes a single API call to check the status of a task.
143
+ """
144
+ task = client.task.retrieve(id=task_id)
145
+ self.on_task_update(task, video_path)
146
+ return task
147
+
148
+ def _wait_for_task_completion(
149
+ self, client: TwelveLabs, task_id: str, video_path: str, max_retries: int = 120, sleep_time: int = 10
150
+ ) -> Any:
151
+ """Wait for task completion with timeout and improved error handling.
152
+
153
+ Polls the task status until completion or timeout.
154
+ """
155
+ retries = 0
156
+ consecutive_errors = 0
157
+ max_consecutive_errors = 5
158
+ video_name = Path(video_path).name
159
+
160
+ while retries < max_retries:
161
+ try:
162
+ self.status = f"Checking task status for {video_name} (attempt {retries + 1})"
163
+ task = self._check_task_status(client, task_id, video_path)
164
+
165
+ if task.status == "ready":
166
+ self.status = f"Indexing for {video_name} completed successfully!"
167
+ return task
168
+ if task.status == "failed":
169
+ error_msg = f"Task failed for {video_name}: {getattr(task, 'error', 'Unknown error')}"
170
+ self.status = error_msg
171
+ raise TaskError(error_msg)
172
+ if task.status == "error":
173
+ error_msg = f"Task encountered an error for {video_name}: {getattr(task, 'error', 'Unknown error')}"
174
+ self.status = error_msg
175
+ raise TaskError(error_msg)
176
+
177
+ time.sleep(sleep_time)
178
+ retries += 1
179
+ elapsed_time = retries * sleep_time
180
+ self.status = f"Indexing {video_name}... {elapsed_time}s elapsed"
181
+
182
+ except (ValueError, KeyError) as e:
183
+ consecutive_errors += 1
184
+ error_msg = f"Error checking task status for {video_name}: {e!s}"
185
+ self.status = error_msg
186
+
187
+ if consecutive_errors >= max_consecutive_errors:
188
+ too_many_errors = f"Too many consecutive errors checking task status for {video_name}"
189
+ raise TaskError(too_many_errors) from e
190
+
191
+ time.sleep(sleep_time * (2**consecutive_errors))
192
+ continue
193
+
194
+ timeout_msg = f"Timeout waiting for indexing of {video_name} after {max_retries * sleep_time} seconds"
195
+ self.status = timeout_msg
196
+ raise TaskTimeoutError(timeout_msg)
197
+
198
+ def _upload_video(self, client: TwelveLabs, video_path: str, index_id: str) -> str:
199
+ """Upload a single video and return its task ID.
200
+
201
+ Uploads a video file to the specified index and returns the task ID.
202
+ """
203
+ video_name = Path(video_path).name
204
+ with Path(video_path).open("rb") as video_file:
205
+ self.status = f"Uploading {video_name} to index {index_id}..."
206
+ task = client.task.create(index_id=index_id, file=video_file)
207
+ task_id = task.id
208
+ self.status = f"Upload complete for {video_name}. Task ID: {task_id}"
209
+ return task_id
210
+
211
+ def index_videos(self) -> list[Data]:
212
+ """Indexes each video and adds the video_id to its metadata."""
213
+ if not self.videodata:
214
+ self.status = "No video data provided."
215
+ return []
216
+
217
+ if not self.api_key:
218
+ error_msg = "TwelveLabs API Key is required"
219
+ raise IndexCreationError(error_msg)
220
+
221
+ if not (hasattr(self, "index_name") and self.index_name) and not (hasattr(self, "index_id") and self.index_id):
222
+ error_msg = "Either index_name or index_id must be provided"
223
+ raise IndexCreationError(error_msg)
224
+
225
+ client = TwelveLabs(api_key=self.api_key)
226
+ indexed_data_list: list[Data] = []
227
+
228
+ # Get or create the index
229
+ try:
230
+ index_id, index_name = self._get_or_create_index(client)
231
+ self.status = f"Using index: {index_name} (ID: {index_id})"
232
+ except IndexCreationError as e:
233
+ self.status = f"Failed to get/create TwelveLabs index: {e!s}"
234
+ raise
235
+
236
+ # First, validate all videos and create a list of valid ones
237
+ valid_videos: list[tuple[Data, str]] = []
238
+ for video_data_item in self.videodata:
239
+ if not isinstance(video_data_item, Data):
240
+ self.status = f"Skipping invalid data item: {video_data_item}"
241
+ continue
242
+
243
+ video_info = video_data_item.data
244
+ if not isinstance(video_info, dict):
245
+ self.status = f"Skipping item with invalid data structure: {video_info}"
246
+ continue
247
+
248
+ video_path = video_info.get("text")
249
+ if not video_path or not isinstance(video_path, str):
250
+ self.status = f"Skipping item with missing or invalid video path: {video_info}"
251
+ continue
252
+
253
+ if not Path(video_path).exists():
254
+ self.status = f"Video file not found, skipping: {video_path}"
255
+ continue
256
+
257
+ valid_videos.append((video_data_item, video_path))
258
+
259
+ if not valid_videos:
260
+ self.status = "No valid videos to process."
261
+ return []
262
+
263
+ # Upload all videos first and collect their task IDs
264
+ upload_tasks: list[tuple[Data, str, str]] = [] # (data_item, video_path, task_id)
265
+ for data_item, video_path in valid_videos:
266
+ try:
267
+ task_id = self._upload_video(client, video_path, index_id)
268
+ upload_tasks.append((data_item, video_path, task_id))
269
+ except (ValueError, KeyError) as e:
270
+ self.status = f"Failed to upload {video_path}: {e!s}"
271
+ continue
272
+
273
+ # Now check all tasks in parallel using a thread pool
274
+ with ThreadPoolExecutor(max_workers=min(10, len(upload_tasks))) as executor:
275
+ futures = []
276
+ for data_item, video_path, task_id in upload_tasks:
277
+ future = executor.submit(self._wait_for_task_completion, client, task_id, video_path)
278
+ futures.append((data_item, video_path, future))
279
+
280
+ # Process results as they complete
281
+ for data_item, video_path, future in futures:
282
+ try:
283
+ completed_task = future.result()
284
+ if completed_task.status == "ready":
285
+ video_id = completed_task.video_id
286
+ video_name = Path(video_path).name
287
+ self.status = f"Video {video_name} indexed successfully. Video ID: {video_id}"
288
+
289
+ # Add video_id to the metadata
290
+ video_info = data_item.data
291
+ if "metadata" not in video_info:
292
+ video_info["metadata"] = {}
293
+ elif not isinstance(video_info["metadata"], dict):
294
+ self.status = f"Warning: Overwriting non-dict metadata for {video_path}"
295
+ video_info["metadata"] = {}
296
+
297
+ video_info["metadata"].update(
298
+ {"video_id": video_id, "index_id": index_id, "index_name": index_name}
299
+ )
300
+
301
+ updated_data_item = Data(data=video_info)
302
+ indexed_data_list.append(updated_data_item)
303
+ except (TaskError, TaskTimeoutError) as e:
304
+ self.status = f"Failed to process {video_path}: {e!s}"
305
+
306
+ if not indexed_data_list:
307
+ self.status = "No videos were successfully indexed."
308
+ else:
309
+ self.status = f"Finished indexing {len(indexed_data_list)}/{len(self.videodata)} videos."
310
+
311
+ return indexed_data_list
@@ -0,0 +1,291 @@
1
+ import hashlib
2
+ import math
3
+ import subprocess
4
+ from datetime import datetime, timezone
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ from lfx.custom import Component
9
+ from lfx.inputs import BoolInput, DropdownInput, HandleInput, IntInput
10
+ from lfx.schema import Data
11
+ from lfx.template import Output
12
+
13
+
14
+ class SplitVideoComponent(Component):
15
+ """A component that splits a video into multiple clips of specified duration using FFmpeg."""
16
+
17
+ display_name = "Split Video"
18
+ description = "Split a video into multiple clips of specified duration."
19
+ icon = "TwelveLabs"
20
+ name = "SplitVideo"
21
+ documentation = "https://github.com/twelvelabs-io/twelvelabs-developer-experience/blob/main/integrations/Langflow/TWELVE_LABS_COMPONENTS_README.md"
22
+
23
+ inputs = [
24
+ HandleInput(
25
+ name="videodata",
26
+ display_name="Video Data",
27
+ info="Input video data from VideoFile component",
28
+ required=True,
29
+ input_types=["Data"],
30
+ ),
31
+ IntInput(
32
+ name="clip_duration",
33
+ display_name="Clip Duration (seconds)",
34
+ info="Duration of each clip in seconds",
35
+ required=True,
36
+ value=30,
37
+ ),
38
+ DropdownInput(
39
+ name="last_clip_handling",
40
+ display_name="Last Clip Handling",
41
+ info=(
42
+ "How to handle the final clip when it would be shorter than the specified duration:\n"
43
+ "- Truncate: Skip the final clip entirely if it's shorter than the specified duration\n"
44
+ "- Overlap Previous: Start the final clip earlier to maintain full duration, "
45
+ "overlapping with previous clip\n"
46
+ "- Keep Short: Keep the final clip at its natural length, even if shorter than specified duration"
47
+ ),
48
+ options=["Truncate", "Overlap Previous", "Keep Short"],
49
+ value="Overlap Previous",
50
+ required=True,
51
+ ),
52
+ BoolInput(
53
+ name="include_original",
54
+ display_name="Include Original Video",
55
+ info="Whether to include the original video in the output",
56
+ value=False,
57
+ ),
58
+ ]
59
+
60
+ outputs = [
61
+ Output(
62
+ name="clips",
63
+ display_name="Video Clips",
64
+ method="process",
65
+ output_types=["Data"],
66
+ ),
67
+ ]
68
+
69
+ def get_video_duration(self, video_path: str) -> float:
70
+ """Get video duration using FFmpeg."""
71
+ try:
72
+ # Validate video path to prevent shell injection
73
+ if not isinstance(video_path, str) or any(c in video_path for c in ";&|`$(){}[]<>*?!#~"):
74
+ error_msg = "Invalid video path"
75
+ raise ValueError(error_msg)
76
+
77
+ cmd = [
78
+ "ffprobe",
79
+ "-v",
80
+ "error",
81
+ "-show_entries",
82
+ "format=duration",
83
+ "-of",
84
+ "default=noprint_wrappers=1:nokey=1",
85
+ video_path,
86
+ ]
87
+ result = subprocess.run( # noqa: S603
88
+ cmd,
89
+ capture_output=True,
90
+ text=True,
91
+ check=False,
92
+ shell=False, # Explicitly set shell=False for security
93
+ )
94
+ if result.returncode != 0:
95
+ error_msg = f"FFprobe error: {result.stderr}"
96
+ raise RuntimeError(error_msg)
97
+ return float(result.stdout.strip())
98
+ except Exception as e:
99
+ self.log(f"Error getting video duration: {e!s}", "ERROR")
100
+ raise
101
+
102
+ def get_output_dir(self, video_path: str) -> str:
103
+ """Create a unique output directory for clips based on video name and timestamp."""
104
+ # Get the video filename without extension
105
+ path_obj = Path(video_path)
106
+ base_name = path_obj.stem
107
+
108
+ # Create a timestamp
109
+ timestamp = datetime.now(tz=timezone.utc).strftime("%Y-%m-%d_%H-%M-%S")
110
+
111
+ # Create a unique hash from the video path
112
+ path_hash = hashlib.sha256(video_path.encode()).hexdigest()[:8]
113
+
114
+ # Create the output directory path
115
+ output_dir = Path(path_obj.parent) / f"clips_{base_name}_{timestamp}_{path_hash}"
116
+
117
+ # Create the directory if it doesn't exist
118
+ output_dir.mkdir(parents=True, exist_ok=True)
119
+
120
+ return str(output_dir)
121
+
122
+ def process_video(self, video_path: str, clip_duration: int, *, include_original: bool) -> list[Data]:
123
+ """Process video and split it into clips using FFmpeg."""
124
+ try:
125
+ # Get video duration
126
+ total_duration = self.get_video_duration(video_path)
127
+
128
+ # Calculate number of clips (ceiling to include partial clip)
129
+ num_clips = math.ceil(total_duration / clip_duration)
130
+ self.log(
131
+ f"Total duration: {total_duration}s, Clip duration: {clip_duration}s, Number of clips: {num_clips}"
132
+ )
133
+
134
+ # Create output directory for clips
135
+ output_dir = self.get_output_dir(video_path)
136
+
137
+ # Get original video info
138
+ path_obj = Path(video_path)
139
+ original_filename = path_obj.name
140
+ original_name = path_obj.stem
141
+
142
+ # List to store all video paths (including original if requested)
143
+ video_paths: list[Data] = []
144
+
145
+ # Add original video if requested
146
+ if include_original:
147
+ original_data: dict[str, Any] = {
148
+ "text": video_path,
149
+ "metadata": {
150
+ "source": video_path,
151
+ "type": "video",
152
+ "clip_index": -1, # -1 indicates original video
153
+ "duration": int(total_duration), # Convert to int
154
+ "original_video": {
155
+ "name": original_name,
156
+ "filename": original_filename,
157
+ "path": video_path,
158
+ "duration": int(total_duration), # Convert to int
159
+ "total_clips": int(num_clips),
160
+ "clip_duration": int(clip_duration),
161
+ },
162
+ },
163
+ }
164
+ video_paths.append(Data(data=original_data))
165
+
166
+ # Split video into clips
167
+ for i in range(int(num_clips)): # Convert num_clips to int for range
168
+ start_time = float(i * clip_duration) # Convert to float for time calculations
169
+ end_time = min(float((i + 1) * clip_duration), total_duration)
170
+ duration = end_time - start_time
171
+
172
+ # Handle last clip if it's shorter
173
+ if i == int(num_clips) - 1 and duration < clip_duration: # Convert num_clips to int for comparison
174
+ if self.last_clip_handling == "Truncate":
175
+ # Skip if the last clip would be too short
176
+ continue
177
+ if self.last_clip_handling == "Overlap Previous" and i > 0:
178
+ # Start from earlier to make full duration
179
+ start_time = total_duration - clip_duration
180
+ duration = clip_duration
181
+ # For "Keep Short", we use the original start_time and duration
182
+
183
+ # Skip if duration is too small (less than 1 second)
184
+ if duration < 1:
185
+ continue
186
+
187
+ # Generate output path
188
+ output_path = Path(output_dir) / f"clip_{i:03d}.mp4"
189
+ output_path_str = str(output_path)
190
+
191
+ try:
192
+ # Use FFmpeg to split the video
193
+ cmd = [
194
+ "ffmpeg",
195
+ "-i",
196
+ video_path,
197
+ "-ss",
198
+ str(start_time),
199
+ "-t",
200
+ str(duration),
201
+ "-c:v",
202
+ "libx264",
203
+ "-c:a",
204
+ "aac",
205
+ "-y", # Overwrite output file if it exists
206
+ output_path_str,
207
+ ]
208
+
209
+ result = subprocess.run( # noqa: S603
210
+ cmd,
211
+ capture_output=True,
212
+ text=True,
213
+ check=False,
214
+ shell=False, # Explicitly set shell=False for security
215
+ )
216
+ if result.returncode != 0:
217
+ error_msg = f"FFmpeg error: {result.stderr}"
218
+ raise RuntimeError(error_msg)
219
+
220
+ # Create timestamp string for metadata
221
+ start_min = int(start_time // 60)
222
+ start_sec = int(start_time % 60)
223
+ end_min = int(end_time // 60)
224
+ end_sec = int(end_time % 60)
225
+ timestamp_str = f"{start_min:02d}:{start_sec:02d} - {end_min:02d}:{end_sec:02d}"
226
+
227
+ # Create Data object for the clip
228
+ clip_data: dict[str, Any] = {
229
+ "text": output_path_str,
230
+ "metadata": {
231
+ "source": video_path,
232
+ "type": "video",
233
+ "clip_index": i,
234
+ "start_time": float(start_time),
235
+ "end_time": float(end_time),
236
+ "duration": float(duration),
237
+ "original_video": {
238
+ "name": original_name,
239
+ "filename": original_filename,
240
+ "path": video_path,
241
+ "duration": int(total_duration),
242
+ "total_clips": int(num_clips),
243
+ "clip_duration": int(clip_duration),
244
+ },
245
+ "clip": {
246
+ "index": i,
247
+ "total": int(num_clips),
248
+ "duration": float(duration),
249
+ "start_time": float(start_time),
250
+ "end_time": float(end_time),
251
+ "timestamp": timestamp_str,
252
+ },
253
+ },
254
+ }
255
+ video_paths.append(Data(data=clip_data))
256
+
257
+ except Exception as e:
258
+ self.log(f"Error processing clip {i}: {e!s}", "ERROR")
259
+ raise
260
+
261
+ self.log(f"Created {len(video_paths)} clips in {output_dir}")
262
+ except Exception as e:
263
+ self.log(f"Error processing video: {e!s}", "ERROR")
264
+ raise
265
+ else:
266
+ return video_paths
267
+
268
+ def process(self) -> list[Data]:
269
+ """Process the input video and return a list of Data objects containing the clips."""
270
+ try:
271
+ # Get the input video path from the previous component
272
+ if not hasattr(self, "videodata") or not isinstance(self.videodata, list) or len(self.videodata) != 1:
273
+ error_msg = "Please provide exactly one video"
274
+ raise ValueError(error_msg)
275
+
276
+ video_path = self.videodata[0].data.get("text")
277
+ if not video_path or not Path(video_path).exists():
278
+ error_msg = "Invalid video path"
279
+ raise ValueError(error_msg)
280
+
281
+ # Validate video path to prevent shell injection
282
+ if not isinstance(video_path, str) or any(c in video_path for c in ";&|`$(){}[]<>*?!#~"):
283
+ error_msg = "Invalid video path contains unsafe characters"
284
+ raise ValueError(error_msg)
285
+
286
+ # Process the video
287
+ return self.process_video(video_path, self.clip_duration, include_original=self.include_original)
288
+
289
+ except Exception as e:
290
+ self.log(f"Error in split video component: {e!s}", "ERROR")
291
+ raise
@@ -0,0 +1,57 @@
1
+ from twelvelabs import TwelveLabs
2
+
3
+ from lfx.base.embeddings.model import LCEmbeddingsModel
4
+ from lfx.field_typing import Embeddings
5
+ from lfx.io import DropdownInput, FloatInput, IntInput, SecretStrInput
6
+
7
+
8
+ class TwelveLabsTextEmbeddings(Embeddings):
9
+ def __init__(self, api_key: str, model: str) -> None:
10
+ self.client = TwelveLabs(api_key=api_key)
11
+ self.model = model
12
+
13
+ def embed_documents(self, texts: list[str]) -> list[list[float]]:
14
+ all_embeddings: list[list[float]] = []
15
+ for text in texts:
16
+ if not text:
17
+ continue
18
+
19
+ result = self.client.embed.create(model_name=self.model, text=text)
20
+
21
+ if result.text_embedding and result.text_embedding.segments:
22
+ for segment in result.text_embedding.segments:
23
+ all_embeddings.append([float(x) for x in segment.embeddings_float])
24
+ break # Only take first segment for now
25
+
26
+ return all_embeddings
27
+
28
+ def embed_query(self, text: str) -> list[float]:
29
+ result = self.client.embed.create(model_name=self.model, text=text)
30
+
31
+ if result.text_embedding and result.text_embedding.segments:
32
+ return [float(x) for x in result.text_embedding.segments[0].embeddings_float]
33
+ return []
34
+
35
+
36
+ class TwelveLabsTextEmbeddingsComponent(LCEmbeddingsModel):
37
+ display_name = "TwelveLabs Text Embeddings"
38
+ description = "Generate embeddings using TwelveLabs text embedding models."
39
+ icon = "TwelveLabs"
40
+ name = "TwelveLabsTextEmbeddings"
41
+ documentation = "https://github.com/twelvelabs-io/twelvelabs-developer-experience/blob/main/integrations/Langflow/TWELVE_LABS_COMPONENTS_README.md"
42
+
43
+ inputs = [
44
+ SecretStrInput(name="api_key", display_name="TwelveLabs API Key", value="TWELVELABS_API_KEY", required=True),
45
+ DropdownInput(
46
+ name="model",
47
+ display_name="Model",
48
+ advanced=False,
49
+ options=["Marengo-retrieval-2.7"],
50
+ value="Marengo-retrieval-2.7",
51
+ ),
52
+ IntInput(name="max_retries", display_name="Max Retries", value=3, advanced=True),
53
+ FloatInput(name="request_timeout", display_name="Request Timeout", advanced=True),
54
+ ]
55
+
56
+ def build_embeddings(self) -> Embeddings:
57
+ return TwelveLabsTextEmbeddings(api_key=self.api_key, model=self.model)