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
lfx/cli/run.py ADDED
@@ -0,0 +1,441 @@
1
+ import json
2
+ import sys
3
+ import tempfile
4
+ from functools import partial
5
+ from io import StringIO
6
+ from pathlib import Path
7
+
8
+ import typer
9
+ from asyncer import syncify
10
+
11
+ from lfx.cli.script_loader import (
12
+ extract_structured_result,
13
+ extract_text_from_result,
14
+ find_graph_variable,
15
+ load_graph_from_script,
16
+ )
17
+ from lfx.cli.validation import validate_global_variables_for_env
18
+ from lfx.log.logger import logger
19
+ from lfx.schema.schema import InputValueRequest
20
+
21
+
22
+ def output_error(error_message: str, *, verbose: bool) -> None:
23
+ """Output error in JSON format to stdout when not verbose, or to stderr when verbose."""
24
+ if verbose:
25
+ typer.echo(f"{error_message}", file=sys.stderr)
26
+ else:
27
+ error_response = {
28
+ "success": False,
29
+ "error": error_message,
30
+ "type": "error",
31
+ }
32
+ typer.echo(json.dumps(error_response))
33
+
34
+
35
+ @partial(syncify, raise_sync_error=False)
36
+ async def run(
37
+ script_path: Path | None = typer.Argument( # noqa: B008
38
+ None, help="Path to the Python script (.py) or JSON flow (.json) containing a graph"
39
+ ),
40
+ input_value: str | None = typer.Argument(None, help="Input value to pass to the graph"),
41
+ input_value_option: str | None = typer.Option(
42
+ None,
43
+ "--input-value",
44
+ help="Input value to pass to the graph (alternative to positional argument)",
45
+ ),
46
+ output_format: str = typer.Option(
47
+ "json",
48
+ "--format",
49
+ "-f",
50
+ help="Output format: json, text, message, or result",
51
+ ),
52
+ flow_json: str | None = typer.Option(
53
+ None,
54
+ "--flow-json",
55
+ help=("Inline JSON flow content as a string (alternative to script_path)"),
56
+ ),
57
+ *,
58
+ stdin: bool | None = typer.Option(
59
+ default=False,
60
+ flag_value="--stdin",
61
+ show_default=True,
62
+ help="Read JSON flow content from stdin (alternative to script_path)",
63
+ ),
64
+ check_variables: bool = typer.Option(
65
+ default=True,
66
+ show_default=True,
67
+ help="Check global variables for environment compatibility",
68
+ ),
69
+ verbose: bool = typer.Option(
70
+ default=False,
71
+ show_default=True,
72
+ help="Show diagnostic output and execution details",
73
+ ),
74
+ timing: bool = typer.Option(
75
+ default=False,
76
+ show_default=True,
77
+ help="Include detailed timing information in output",
78
+ ),
79
+ ) -> None:
80
+ """Execute a Langflow graph script or JSON flow and return the result.
81
+
82
+ This command analyzes and executes either a Python script containing a Langflow graph,
83
+ a JSON flow file, inline JSON, or JSON from stdin, returning the result in the specified format.
84
+ By default, output is minimal for use in containers and serverless environments.
85
+
86
+ Args:
87
+ script_path: Path to the Python script (.py) or JSON flow (.json) containing a graph
88
+ input_value: Input value to pass to the graph (positional argument)
89
+ input_value_option: Input value to pass to the graph (alternative option)
90
+ verbose: Show diagnostic output and execution details
91
+ output_format: Format for output (json, text, message, or result)
92
+ flow_json: Inline JSON flow content as a string
93
+ stdin: Read JSON flow content from stdin
94
+ check_variables: Check global variables for environment compatibility
95
+ timing: Include detailed timing information in output
96
+ """
97
+ # Start timing if requested
98
+ import time
99
+ from datetime import datetime
100
+
101
+ def verbose_print(message: str, level: str = "INFO") -> None:
102
+ if verbose:
103
+ timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3] # Include milliseconds # noqa: DTZ005
104
+ typer.echo(f"[{timestamp}] {level}: {message}", file=sys.stderr)
105
+
106
+ def debug_print(message: str) -> None:
107
+ verbose_print(message, level="DEBUG")
108
+
109
+ start_time = time.time() if timing else None
110
+
111
+ # Use either positional input_value or --input-value option
112
+ final_input_value = input_value or input_value_option
113
+
114
+ # Validate input sources - exactly one must be provided
115
+ input_sources = [script_path is not None, flow_json is not None, bool(stdin)]
116
+ if sum(input_sources) != 1:
117
+ if sum(input_sources) == 0:
118
+ error_msg = "No input source provided. Must provide either script_path, --flow-json, or --stdin"
119
+ else:
120
+ error_msg = (
121
+ "Multiple input sources provided. Cannot use script_path, --flow-json, and "
122
+ "--stdin together. Choose exactly one."
123
+ )
124
+ output_error(error_msg, verbose=verbose)
125
+ raise typer.Exit(1)
126
+
127
+ temp_file_to_cleanup = None
128
+
129
+ if flow_json is not None:
130
+ verbose_print("Processing inline JSON content...")
131
+ try:
132
+ json_data = json.loads(flow_json)
133
+ verbose_print("JSON content is valid")
134
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as temp_file:
135
+ json.dump(json_data, temp_file, indent=2)
136
+ temp_file_to_cleanup = temp_file.name
137
+ script_path = Path(temp_file_to_cleanup)
138
+ verbose_print(f"Created temporary file: {script_path}")
139
+ except json.JSONDecodeError as e:
140
+ output_error(f"Invalid JSON content: {e}", verbose=verbose)
141
+ raise typer.Exit(1) from e
142
+ except Exception as e:
143
+ output_error(f"Error processing JSON content: {e}", verbose=verbose)
144
+ raise typer.Exit(1) from e
145
+ elif stdin:
146
+ verbose_print("Reading JSON content from stdin...")
147
+ try:
148
+ stdin_content = sys.stdin.read().strip()
149
+ if not stdin_content:
150
+ output_error("No content received from stdin", verbose=verbose)
151
+ raise typer.Exit(1)
152
+ json_data = json.loads(stdin_content)
153
+ verbose_print("JSON content from stdin is valid")
154
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as temp_file:
155
+ json.dump(json_data, temp_file, indent=2)
156
+ temp_file_to_cleanup = temp_file.name
157
+ script_path = Path(temp_file_to_cleanup)
158
+ verbose_print(f"Created temporary file from stdin: {script_path}")
159
+ except json.JSONDecodeError as e:
160
+ output_error(f"Invalid JSON content from stdin: {e}", verbose=verbose)
161
+ raise typer.Exit(1) from e
162
+ except Exception as e:
163
+ output_error(f"Error reading from stdin: {e}", verbose=verbose)
164
+ raise typer.Exit(1) from e
165
+
166
+ try:
167
+ if not script_path or not script_path.exists():
168
+ error_msg = f"File '{script_path}' does not exist."
169
+ raise ValueError(error_msg)
170
+ if not script_path.is_file():
171
+ error_msg = f"'{script_path}' is not a file."
172
+ raise ValueError(error_msg)
173
+ file_extension = script_path.suffix.lower()
174
+ if file_extension not in [".py", ".json"]:
175
+ error_msg = f"'{script_path}' must be a .py or .json file."
176
+ raise ValueError(error_msg)
177
+ file_type = "Python script" if file_extension == ".py" else "JSON flow"
178
+ verbose_print(f"Analyzing {file_type}: {script_path}")
179
+ if file_extension == ".py":
180
+ graph_info = find_graph_variable(script_path)
181
+ if not graph_info:
182
+ error_msg = (
183
+ "No 'graph' variable found in the script. Expected to find an assignment like: graph = Graph(...)"
184
+ )
185
+ raise ValueError(error_msg)
186
+ verbose_print(f"Found 'graph' variable at line {graph_info['line_number']}")
187
+ verbose_print(f"Type: {graph_info['type']}")
188
+ verbose_print(f"Source: {graph_info['source_line']}")
189
+ verbose_print("Loading and executing script...")
190
+ graph = load_graph_from_script(script_path)
191
+ elif file_extension == ".json":
192
+ verbose_print("Valid JSON flow file detected")
193
+ verbose_print("\nLoading and executing JSON flow...")
194
+ from lfx.load import aload_flow_from_json
195
+
196
+ graph = await aload_flow_from_json(script_path, disable_logs=not verbose)
197
+ except Exception as e:
198
+ error_type = type(e).__name__
199
+ verbose_print(f"Graph loading failed with {error_type}", level="ERROR")
200
+
201
+ if verbose:
202
+ # Enhanced error context for better debugging
203
+ debug_print(f"Exception type: {error_type}")
204
+ debug_print(f"Exception message: {e!s}")
205
+
206
+ # Try to identify common error patterns
207
+ if "ModuleNotFoundError" in str(e) or "No module named" in str(e):
208
+ verbose_print("This appears to be a missing dependency issue", level="WARN")
209
+ if "langchain" in str(e).lower():
210
+ verbose_print(
211
+ "Missing LangChain dependency detected. Try: pip install langchain-<provider>",
212
+ level="WARN",
213
+ )
214
+ elif "ImportError" in str(e):
215
+ verbose_print("This appears to be an import issue - check component dependencies", level="WARN")
216
+ elif "AttributeError" in str(e):
217
+ verbose_print("This appears to be a component configuration issue", level="WARN")
218
+
219
+ # Show full traceback in debug mode
220
+ logger.exception("Failed to load graph - full traceback:")
221
+
222
+ output_error(f"Failed to load graph: {e}", verbose=verbose)
223
+ if temp_file_to_cleanup:
224
+ try:
225
+ Path(temp_file_to_cleanup).unlink()
226
+ verbose_print(f"Cleaned up temporary file: {temp_file_to_cleanup}", level="SUCCESS")
227
+ except OSError:
228
+ pass
229
+ raise typer.Exit(1) from e
230
+
231
+ inputs = InputValueRequest(input_value=final_input_value) if final_input_value else None
232
+
233
+ # Mark end of loading phase if timing
234
+ load_end_time = time.time() if timing else None
235
+
236
+ verbose_print("Preparing graph for execution...")
237
+ try:
238
+ # Add detailed preparation steps
239
+ if verbose:
240
+ debug_print(f"Graph contains {len(graph.vertices)} vertices")
241
+ debug_print(f"Graph contains {len(graph.edges)} edges")
242
+
243
+ # Show component types being used
244
+ component_types = set()
245
+ for vertex in graph.vertices:
246
+ if hasattr(vertex, "display_name"):
247
+ component_types.add(vertex.display_name)
248
+ debug_print(f"Component types in graph: {', '.join(sorted(component_types))}")
249
+
250
+ graph.prepare()
251
+ verbose_print("Graph preparation completed", level="SUCCESS")
252
+
253
+ # Validate global variables for environment compatibility
254
+ if check_variables:
255
+ verbose_print("Validating global variables...")
256
+ validation_errors = validate_global_variables_for_env(graph)
257
+ if validation_errors:
258
+ error_details = "Global variable validation failed: " + "; ".join(validation_errors)
259
+ verbose_print(f"Variable validation failed: {len(validation_errors)} errors", level="ERROR")
260
+ for error in validation_errors:
261
+ debug_print(f"Validation error: {error}")
262
+ output_error(error_details, verbose=verbose)
263
+ if temp_file_to_cleanup:
264
+ try:
265
+ Path(temp_file_to_cleanup).unlink()
266
+ verbose_print(f"Cleaned up temporary file: {temp_file_to_cleanup}", level="SUCCESS")
267
+ except OSError:
268
+ pass
269
+ if validation_errors:
270
+ raise typer.Exit(1)
271
+ verbose_print("Global variable validation passed", level="SUCCESS")
272
+ else:
273
+ verbose_print("Global variable validation skipped", level="SUCCESS")
274
+ except Exception as e:
275
+ error_type = type(e).__name__
276
+ verbose_print(f"Graph preparation failed with {error_type}", level="ERROR")
277
+
278
+ if verbose:
279
+ debug_print(f"Preparation error: {e!s}")
280
+ logger.exception("Failed to prepare graph - full traceback:")
281
+
282
+ output_error(f"Failed to prepare graph: {e}", verbose=verbose)
283
+ if temp_file_to_cleanup:
284
+ try:
285
+ Path(temp_file_to_cleanup).unlink()
286
+ verbose_print(f"Cleaned up temporary file: {temp_file_to_cleanup}")
287
+ except OSError:
288
+ pass
289
+ raise typer.Exit(1) from e
290
+
291
+ verbose_print("Executing graph...")
292
+ execution_start_time = time.time() if timing else None
293
+
294
+ if verbose:
295
+ debug_print("Setting up execution environment")
296
+ if inputs:
297
+ debug_print(f"Input provided: {inputs.input_value}")
298
+ else:
299
+ debug_print("No input provided")
300
+
301
+ captured_stdout = StringIO()
302
+ captured_stderr = StringIO()
303
+ original_stdout = sys.stdout
304
+ original_stderr = sys.stderr
305
+
306
+ # Track component timing if requested
307
+ component_timings = [] if timing else None
308
+ execution_step_start = execution_start_time if timing else None
309
+
310
+ try:
311
+ sys.stdout = captured_stdout
312
+ sys.stderr = captured_stderr
313
+ results = []
314
+
315
+ verbose_print("Starting graph execution...", level="DEBUG")
316
+ result_count = 0
317
+
318
+ async for result in graph.async_start(inputs):
319
+ result_count += 1
320
+ if verbose:
321
+ debug_print(f"Processing result #{result_count}")
322
+ if hasattr(result, "vertex") and hasattr(result.vertex, "display_name"):
323
+ debug_print(f"Component: {result.vertex.display_name}")
324
+ if timing:
325
+ step_end_time = time.time()
326
+ step_duration = step_end_time - execution_step_start
327
+
328
+ # Extract component information
329
+ if hasattr(result, "vertex"):
330
+ component_name = getattr(result.vertex, "display_name", "Unknown")
331
+ component_id = getattr(result.vertex, "id", "Unknown")
332
+ component_timings.append(
333
+ {
334
+ "component": component_name,
335
+ "component_id": component_id,
336
+ "duration": step_duration,
337
+ "cumulative_time": step_end_time - execution_start_time,
338
+ }
339
+ )
340
+
341
+ execution_step_start = step_end_time
342
+
343
+ results.append(result)
344
+
345
+ verbose_print(f"Graph execution completed. Processed {result_count} results", level="SUCCESS")
346
+
347
+ except Exception as e:
348
+ sys.stdout = original_stdout
349
+ sys.stderr = original_stderr
350
+
351
+ error_type = type(e).__name__
352
+ verbose_print(f"Graph execution failed with {error_type}", level="ERROR")
353
+
354
+ if verbose:
355
+ debug_print(f"Execution error: {e!s}")
356
+ debug_print(f"Failed after processing {result_count} results")
357
+
358
+ # Capture any output that was generated before the error
359
+ captured_content = captured_stdout.getvalue() + captured_stderr.getvalue()
360
+ if captured_content.strip():
361
+ debug_print("Captured output before error:")
362
+ for line in captured_content.strip().split("\n"):
363
+ debug_print(f" | {line}")
364
+
365
+ # Provide context about common execution errors
366
+ if "list can't be used in 'await' expression" in str(e):
367
+ verbose_print("This appears to be an async/await mismatch in a component", level="WARN")
368
+ verbose_print("Check that async methods are properly awaited", level="WARN")
369
+ elif "AttributeError" in error_type and "NoneType" in str(e):
370
+ verbose_print("This appears to be a null reference error", level="WARN")
371
+ verbose_print("A component may be receiving unexpected None values", level="WARN")
372
+ elif "ConnectionError" in str(e) or "TimeoutError" in str(e):
373
+ verbose_print("This appears to be a network connectivity issue", level="WARN")
374
+ verbose_print("Check API keys and network connectivity", level="WARN")
375
+
376
+ logger.exception("Failed to execute graph - full traceback:")
377
+
378
+ output_error(f"Failed to execute graph: {e}", verbose=verbose)
379
+ if temp_file_to_cleanup:
380
+ try:
381
+ Path(temp_file_to_cleanup).unlink()
382
+ verbose_print(f"Cleaned up temporary file: {temp_file_to_cleanup}", level="SUCCESS")
383
+ except OSError:
384
+ pass
385
+ raise typer.Exit(1) from e
386
+ finally:
387
+ sys.stdout = original_stdout
388
+ sys.stderr = original_stderr
389
+ if temp_file_to_cleanup:
390
+ try:
391
+ Path(temp_file_to_cleanup).unlink()
392
+ verbose_print(f"Cleaned up temporary file: {temp_file_to_cleanup}")
393
+ except OSError:
394
+ pass
395
+
396
+ execution_end_time = time.time() if timing else None
397
+
398
+ captured_logs = captured_stdout.getvalue() + captured_stderr.getvalue()
399
+
400
+ # Create timing metadata if requested
401
+ timing_metadata = None
402
+ if timing:
403
+ load_duration = load_end_time - start_time
404
+ execution_duration = execution_end_time - execution_start_time
405
+ total_duration = execution_end_time - start_time
406
+
407
+ timing_metadata = {
408
+ "load_time": round(load_duration, 3),
409
+ "execution_time": round(execution_duration, 3),
410
+ "total_time": round(total_duration, 3),
411
+ "component_timings": [
412
+ {
413
+ "component": ct["component"],
414
+ "component_id": ct["component_id"],
415
+ "duration": round(ct["duration"], 3),
416
+ "cumulative_time": round(ct["cumulative_time"], 3),
417
+ }
418
+ for ct in component_timings
419
+ ],
420
+ }
421
+
422
+ if output_format == "json":
423
+ result_data = extract_structured_result(results)
424
+ result_data["logs"] = captured_logs
425
+ if timing_metadata:
426
+ result_data["timing"] = timing_metadata
427
+ indent = 2 if verbose else None
428
+ typer.echo(json.dumps(result_data, indent=indent))
429
+ elif output_format in {"text", "message"}:
430
+ result_data = extract_structured_result(results)
431
+ output_text = result_data.get("result", result_data.get("text", ""))
432
+ typer.echo(str(output_text))
433
+ elif output_format == "result":
434
+ typer.echo(extract_text_from_result(results))
435
+ else:
436
+ result_data = extract_structured_result(results)
437
+ result_data["logs"] = captured_logs
438
+ if timing_metadata:
439
+ result_data["timing"] = timing_metadata
440
+ indent = 2 if verbose else None
441
+ typer.echo(json.dumps(result_data, indent=indent))
@@ -0,0 +1,247 @@
1
+ """Script loading utilities for LFX CLI.
2
+
3
+ This module provides functionality to load and validate Python scripts
4
+ containing LFX graph variables.
5
+ """
6
+
7
+ import ast
8
+ import importlib.util
9
+ import json
10
+ import sys
11
+ from contextlib import contextmanager
12
+ from pathlib import Path
13
+ from typing import TYPE_CHECKING, Any
14
+
15
+ import typer
16
+
17
+ from lfx.graph import Graph
18
+
19
+ if TYPE_CHECKING:
20
+ from lfx.schema.message import Message
21
+
22
+
23
+ @contextmanager
24
+ def temporary_sys_path(path: str):
25
+ """Temporarily add a path to sys.path."""
26
+ if path not in sys.path:
27
+ sys.path.insert(0, path)
28
+ try:
29
+ yield
30
+ finally:
31
+ sys.path.remove(path)
32
+ else:
33
+ yield
34
+
35
+
36
+ def _load_module_from_script(script_path: Path) -> Any:
37
+ """Load a Python module from a script file."""
38
+ spec = importlib.util.spec_from_file_location("script_module", script_path)
39
+ if spec is None or spec.loader is None:
40
+ msg = f"Could not create module spec for '{script_path}'"
41
+ raise ImportError(msg)
42
+
43
+ module = importlib.util.module_from_spec(spec)
44
+
45
+ with temporary_sys_path(str(script_path.parent)):
46
+ spec.loader.exec_module(module)
47
+
48
+ return module
49
+
50
+
51
+ def _validate_graph_instance(graph_obj: Any) -> Graph:
52
+ """Extract information from a graph object."""
53
+ if not isinstance(graph_obj, Graph):
54
+ msg = f"Graph object is not a LFX Graph instance: {type(graph_obj)}"
55
+ raise TypeError(msg)
56
+
57
+ # Find ChatInput and ChatOutput components
58
+ display_names: set[str] = set()
59
+ for vertex in graph_obj.vertices:
60
+ if vertex.custom_component is not None:
61
+ display_names.add(vertex.custom_component.display_name)
62
+
63
+ if "Chat Input" not in display_names:
64
+ msg = f"Graph does not contain any ChatInput component. Vertices: {display_names}"
65
+ raise ValueError(msg)
66
+
67
+ if "Chat Output" not in display_names:
68
+ msg = f"Graph does not contain any ChatOutput component. Vertices: {display_names}"
69
+ raise ValueError(msg)
70
+
71
+ return graph_obj
72
+
73
+
74
+ def load_graph_from_script(script_path: Path) -> Graph:
75
+ """Load and execute a Python script to extract the 'graph' variable.
76
+
77
+ Args:
78
+ script_path (Path): Path to the Python script file
79
+
80
+ Returns:
81
+ dict: Information about the loaded graph variable including the graph object itself
82
+ """
83
+ try:
84
+ # Load the module
85
+ module = _load_module_from_script(script_path)
86
+
87
+ # Check if 'graph' variable exists
88
+ if not hasattr(module, "graph"):
89
+ msg = "No 'graph' variable found in the executed script"
90
+ raise ValueError(msg)
91
+
92
+ # Extract graph information
93
+ graph_obj = module.graph
94
+ return _validate_graph_instance(graph_obj)
95
+
96
+ except (
97
+ ImportError,
98
+ AttributeError,
99
+ ModuleNotFoundError,
100
+ SyntaxError,
101
+ TypeError,
102
+ ValueError,
103
+ FileNotFoundError,
104
+ ) as e:
105
+ error_msg = f"Error executing script '{script_path}': {e}"
106
+ raise RuntimeError(error_msg) from e
107
+
108
+
109
+ def extract_message_from_result(results: list) -> str:
110
+ """Extract the message from the results."""
111
+ for result in results:
112
+ if (
113
+ hasattr(result, "vertex")
114
+ and result.vertex.custom_component
115
+ and result.vertex.custom_component.display_name == "Chat Output"
116
+ ):
117
+ message: Message = result.result_dict.results["message"]
118
+ try:
119
+ # Parse the JSON to get just the text content
120
+ return json.dumps(json.loads(message.model_dump_json()), ensure_ascii=False)
121
+ except (json.JSONDecodeError, AttributeError):
122
+ # Fallback to string representation
123
+ return str(message)
124
+ return "No response generated"
125
+
126
+
127
+ def extract_text_from_result(results: list) -> str:
128
+ """Extract just the text content from the results."""
129
+ for result in results:
130
+ if (
131
+ hasattr(result, "vertex")
132
+ and result.vertex.custom_component
133
+ and result.vertex.custom_component.display_name == "Chat Output"
134
+ ):
135
+ message: dict | Message = result.result_dict.results.get("message")
136
+ try:
137
+ # Return just the text content
138
+ if isinstance(message, dict):
139
+ text_content = message.get("text") if message.get("text") else str(message)
140
+ else:
141
+ text_content = message.text
142
+ return str(text_content)
143
+ except AttributeError:
144
+ # Fallback to string representation
145
+ return str(message)
146
+ return "No response generated"
147
+
148
+
149
+ def extract_structured_result(results: list, *, extract_text: bool = True) -> dict:
150
+ """Extract structured result data from the results."""
151
+ for result in results:
152
+ if (
153
+ hasattr(result, "vertex")
154
+ and result.vertex.custom_component
155
+ and result.vertex.custom_component.display_name == "Chat Output"
156
+ ):
157
+ message: Message = result.result_dict.results["message"]
158
+ try:
159
+ result_message = message.text if extract_text and hasattr(message, "text") else message
160
+ except (AttributeError, TypeError, ValueError) as e:
161
+ return {
162
+ "text": str(message),
163
+ "type": "message",
164
+ "component": result.vertex.custom_component.display_name,
165
+ "component_id": result.vertex.id,
166
+ "success": True,
167
+ "warning": f"Could not extract text properly: {e}",
168
+ }
169
+
170
+ return {
171
+ "result": result_message,
172
+ "type": "message",
173
+ "component": result.vertex.custom_component.display_name,
174
+ "component_id": result.vertex.id,
175
+ "success": True,
176
+ }
177
+ return {"text": "No response generated", "type": "error", "success": False}
178
+
179
+
180
+ def find_graph_variable(script_path: Path) -> dict | None:
181
+ """Parse a Python script and find the 'graph' variable assignment.
182
+
183
+ Args:
184
+ script_path (Path): Path to the Python script file
185
+
186
+ Returns:
187
+ dict | None: Information about the graph variable if found, None otherwise
188
+ """
189
+ try:
190
+ with script_path.open(encoding="utf-8") as f:
191
+ content = f.read()
192
+
193
+ # Parse the script using AST
194
+ tree = ast.parse(content)
195
+
196
+ # Look for assignments to 'graph' variable
197
+ for node in ast.walk(tree):
198
+ if isinstance(node, ast.Assign):
199
+ # Check if any target is named 'graph'
200
+ for target in node.targets:
201
+ if isinstance(target, ast.Name) and target.id == "graph":
202
+ # Found a graph assignment
203
+ line_number = node.lineno
204
+
205
+ # Try to extract some information about the assignment
206
+ if isinstance(node.value, ast.Call):
207
+ # It's a function call like Graph(...)
208
+ if isinstance(node.value.func, ast.Name):
209
+ func_name = node.value.func.id
210
+ elif isinstance(node.value.func, ast.Attribute):
211
+ # Handle cases like Graph.from_payload(...)
212
+ if isinstance(node.value.func.value, ast.Name):
213
+ func_name = f"{node.value.func.value.id}.{node.value.func.attr}"
214
+ else:
215
+ func_name = node.value.func.attr
216
+ else:
217
+ func_name = "Unknown"
218
+
219
+ # Count arguments
220
+ arg_count = len(node.value.args) + len(node.value.keywords)
221
+
222
+ return {
223
+ "line_number": line_number,
224
+ "type": "function_call",
225
+ "function": func_name,
226
+ "arg_count": arg_count,
227
+ "source_line": content.split("\n")[line_number - 1].strip(),
228
+ }
229
+ # Some other type of assignment
230
+ return {
231
+ "line_number": line_number,
232
+ "type": "assignment",
233
+ "source_line": content.split("\n")[line_number - 1].strip(),
234
+ }
235
+
236
+ except FileNotFoundError:
237
+ typer.echo(f"Error: File '{script_path}' not found.")
238
+ return None
239
+ except SyntaxError as e:
240
+ typer.echo(f"Error: Invalid Python syntax in '{script_path}': {e}")
241
+ return None
242
+ except (OSError, UnicodeDecodeError) as e:
243
+ typer.echo(f"Error parsing '{script_path}': {e}")
244
+ return None
245
+ else:
246
+ # No graph variable found
247
+ return None