lfx-nightly 0.2.0.dev25__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.

Potentially problematic release.


This version of lfx-nightly might be problematic. Click here for more details.

Files changed (769) hide show
  1. lfx/__init__.py +0 -0
  2. lfx/__main__.py +25 -0
  3. lfx/_assets/component_index.json +1 -0
  4. lfx/base/__init__.py +0 -0
  5. lfx/base/agents/__init__.py +0 -0
  6. lfx/base/agents/agent.py +375 -0
  7. lfx/base/agents/altk_base_agent.py +380 -0
  8. lfx/base/agents/altk_tool_wrappers.py +565 -0
  9. lfx/base/agents/callback.py +130 -0
  10. lfx/base/agents/context.py +109 -0
  11. lfx/base/agents/crewai/__init__.py +0 -0
  12. lfx/base/agents/crewai/crew.py +231 -0
  13. lfx/base/agents/crewai/tasks.py +12 -0
  14. lfx/base/agents/default_prompts.py +23 -0
  15. lfx/base/agents/errors.py +15 -0
  16. lfx/base/agents/events.py +430 -0
  17. lfx/base/agents/utils.py +237 -0
  18. lfx/base/astra_assistants/__init__.py +0 -0
  19. lfx/base/astra_assistants/util.py +171 -0
  20. lfx/base/chains/__init__.py +0 -0
  21. lfx/base/chains/model.py +19 -0
  22. lfx/base/composio/__init__.py +0 -0
  23. lfx/base/composio/composio_base.py +2584 -0
  24. lfx/base/compressors/__init__.py +0 -0
  25. lfx/base/compressors/model.py +60 -0
  26. lfx/base/constants.py +46 -0
  27. lfx/base/curl/__init__.py +0 -0
  28. lfx/base/curl/parse.py +188 -0
  29. lfx/base/data/__init__.py +5 -0
  30. lfx/base/data/base_file.py +810 -0
  31. lfx/base/data/docling_utils.py +338 -0
  32. lfx/base/data/storage_utils.py +192 -0
  33. lfx/base/data/utils.py +362 -0
  34. lfx/base/datastax/__init__.py +5 -0
  35. lfx/base/datastax/astradb_base.py +896 -0
  36. lfx/base/document_transformers/__init__.py +0 -0
  37. lfx/base/document_transformers/model.py +43 -0
  38. lfx/base/embeddings/__init__.py +0 -0
  39. lfx/base/embeddings/aiml_embeddings.py +62 -0
  40. lfx/base/embeddings/embeddings_class.py +113 -0
  41. lfx/base/embeddings/model.py +26 -0
  42. lfx/base/flow_processing/__init__.py +0 -0
  43. lfx/base/flow_processing/utils.py +86 -0
  44. lfx/base/huggingface/__init__.py +0 -0
  45. lfx/base/huggingface/model_bridge.py +133 -0
  46. lfx/base/io/__init__.py +0 -0
  47. lfx/base/io/chat.py +21 -0
  48. lfx/base/io/text.py +22 -0
  49. lfx/base/knowledge_bases/__init__.py +3 -0
  50. lfx/base/knowledge_bases/knowledge_base_utils.py +137 -0
  51. lfx/base/langchain_utilities/__init__.py +0 -0
  52. lfx/base/langchain_utilities/model.py +35 -0
  53. lfx/base/langchain_utilities/spider_constants.py +1 -0
  54. lfx/base/langwatch/__init__.py +0 -0
  55. lfx/base/langwatch/utils.py +18 -0
  56. lfx/base/mcp/__init__.py +0 -0
  57. lfx/base/mcp/constants.py +2 -0
  58. lfx/base/mcp/util.py +1659 -0
  59. lfx/base/memory/__init__.py +0 -0
  60. lfx/base/memory/memory.py +49 -0
  61. lfx/base/memory/model.py +38 -0
  62. lfx/base/models/__init__.py +3 -0
  63. lfx/base/models/aiml_constants.py +51 -0
  64. lfx/base/models/anthropic_constants.py +51 -0
  65. lfx/base/models/aws_constants.py +151 -0
  66. lfx/base/models/chat_result.py +76 -0
  67. lfx/base/models/cometapi_constants.py +54 -0
  68. lfx/base/models/google_generative_ai_constants.py +70 -0
  69. lfx/base/models/google_generative_ai_model.py +38 -0
  70. lfx/base/models/groq_constants.py +150 -0
  71. lfx/base/models/groq_model_discovery.py +265 -0
  72. lfx/base/models/model.py +375 -0
  73. lfx/base/models/model_input_constants.py +378 -0
  74. lfx/base/models/model_metadata.py +41 -0
  75. lfx/base/models/model_utils.py +108 -0
  76. lfx/base/models/novita_constants.py +35 -0
  77. lfx/base/models/ollama_constants.py +52 -0
  78. lfx/base/models/openai_constants.py +129 -0
  79. lfx/base/models/sambanova_constants.py +18 -0
  80. lfx/base/models/watsonx_constants.py +36 -0
  81. lfx/base/processing/__init__.py +0 -0
  82. lfx/base/prompts/__init__.py +0 -0
  83. lfx/base/prompts/api_utils.py +224 -0
  84. lfx/base/prompts/utils.py +61 -0
  85. lfx/base/textsplitters/__init__.py +0 -0
  86. lfx/base/textsplitters/model.py +28 -0
  87. lfx/base/tools/__init__.py +0 -0
  88. lfx/base/tools/base.py +26 -0
  89. lfx/base/tools/component_tool.py +325 -0
  90. lfx/base/tools/constants.py +49 -0
  91. lfx/base/tools/flow_tool.py +132 -0
  92. lfx/base/tools/run_flow.py +698 -0
  93. lfx/base/vectorstores/__init__.py +0 -0
  94. lfx/base/vectorstores/model.py +193 -0
  95. lfx/base/vectorstores/utils.py +22 -0
  96. lfx/base/vectorstores/vector_store_connection_decorator.py +52 -0
  97. lfx/cli/__init__.py +5 -0
  98. lfx/cli/commands.py +327 -0
  99. lfx/cli/common.py +650 -0
  100. lfx/cli/run.py +506 -0
  101. lfx/cli/script_loader.py +289 -0
  102. lfx/cli/serve_app.py +546 -0
  103. lfx/cli/validation.py +69 -0
  104. lfx/components/FAISS/__init__.py +34 -0
  105. lfx/components/FAISS/faiss.py +111 -0
  106. lfx/components/Notion/__init__.py +19 -0
  107. lfx/components/Notion/add_content_to_page.py +269 -0
  108. lfx/components/Notion/create_page.py +94 -0
  109. lfx/components/Notion/list_database_properties.py +68 -0
  110. lfx/components/Notion/list_pages.py +122 -0
  111. lfx/components/Notion/list_users.py +77 -0
  112. lfx/components/Notion/page_content_viewer.py +93 -0
  113. lfx/components/Notion/search.py +111 -0
  114. lfx/components/Notion/update_page_property.py +114 -0
  115. lfx/components/__init__.py +428 -0
  116. lfx/components/_importing.py +42 -0
  117. lfx/components/agentql/__init__.py +3 -0
  118. lfx/components/agentql/agentql_api.py +151 -0
  119. lfx/components/aiml/__init__.py +37 -0
  120. lfx/components/aiml/aiml.py +115 -0
  121. lfx/components/aiml/aiml_embeddings.py +37 -0
  122. lfx/components/altk/__init__.py +34 -0
  123. lfx/components/altk/altk_agent.py +193 -0
  124. lfx/components/amazon/__init__.py +36 -0
  125. lfx/components/amazon/amazon_bedrock_converse.py +195 -0
  126. lfx/components/amazon/amazon_bedrock_embedding.py +109 -0
  127. lfx/components/amazon/amazon_bedrock_model.py +130 -0
  128. lfx/components/amazon/s3_bucket_uploader.py +211 -0
  129. lfx/components/anthropic/__init__.py +34 -0
  130. lfx/components/anthropic/anthropic.py +187 -0
  131. lfx/components/apify/__init__.py +5 -0
  132. lfx/components/apify/apify_actor.py +325 -0
  133. lfx/components/arxiv/__init__.py +3 -0
  134. lfx/components/arxiv/arxiv.py +169 -0
  135. lfx/components/assemblyai/__init__.py +46 -0
  136. lfx/components/assemblyai/assemblyai_get_subtitles.py +83 -0
  137. lfx/components/assemblyai/assemblyai_lemur.py +183 -0
  138. lfx/components/assemblyai/assemblyai_list_transcripts.py +95 -0
  139. lfx/components/assemblyai/assemblyai_poll_transcript.py +72 -0
  140. lfx/components/assemblyai/assemblyai_start_transcript.py +188 -0
  141. lfx/components/azure/__init__.py +37 -0
  142. lfx/components/azure/azure_openai.py +95 -0
  143. lfx/components/azure/azure_openai_embeddings.py +83 -0
  144. lfx/components/baidu/__init__.py +32 -0
  145. lfx/components/baidu/baidu_qianfan_chat.py +113 -0
  146. lfx/components/bing/__init__.py +3 -0
  147. lfx/components/bing/bing_search_api.py +61 -0
  148. lfx/components/cassandra/__init__.py +40 -0
  149. lfx/components/cassandra/cassandra.py +264 -0
  150. lfx/components/cassandra/cassandra_chat.py +92 -0
  151. lfx/components/cassandra/cassandra_graph.py +238 -0
  152. lfx/components/chains/__init__.py +3 -0
  153. lfx/components/chroma/__init__.py +34 -0
  154. lfx/components/chroma/chroma.py +169 -0
  155. lfx/components/cleanlab/__init__.py +40 -0
  156. lfx/components/cleanlab/cleanlab_evaluator.py +155 -0
  157. lfx/components/cleanlab/cleanlab_rag_evaluator.py +254 -0
  158. lfx/components/cleanlab/cleanlab_remediator.py +131 -0
  159. lfx/components/clickhouse/__init__.py +34 -0
  160. lfx/components/clickhouse/clickhouse.py +135 -0
  161. lfx/components/cloudflare/__init__.py +32 -0
  162. lfx/components/cloudflare/cloudflare.py +81 -0
  163. lfx/components/cohere/__init__.py +40 -0
  164. lfx/components/cohere/cohere_embeddings.py +81 -0
  165. lfx/components/cohere/cohere_models.py +46 -0
  166. lfx/components/cohere/cohere_rerank.py +51 -0
  167. lfx/components/cometapi/__init__.py +32 -0
  168. lfx/components/cometapi/cometapi.py +166 -0
  169. lfx/components/composio/__init__.py +222 -0
  170. lfx/components/composio/agentql_composio.py +11 -0
  171. lfx/components/composio/agiled_composio.py +11 -0
  172. lfx/components/composio/airtable_composio.py +11 -0
  173. lfx/components/composio/apollo_composio.py +11 -0
  174. lfx/components/composio/asana_composio.py +11 -0
  175. lfx/components/composio/attio_composio.py +11 -0
  176. lfx/components/composio/bitbucket_composio.py +11 -0
  177. lfx/components/composio/bolna_composio.py +11 -0
  178. lfx/components/composio/brightdata_composio.py +11 -0
  179. lfx/components/composio/calendly_composio.py +11 -0
  180. lfx/components/composio/canva_composio.py +11 -0
  181. lfx/components/composio/canvas_composio.py +11 -0
  182. lfx/components/composio/coda_composio.py +11 -0
  183. lfx/components/composio/composio_api.py +278 -0
  184. lfx/components/composio/contentful_composio.py +11 -0
  185. lfx/components/composio/digicert_composio.py +11 -0
  186. lfx/components/composio/discord_composio.py +11 -0
  187. lfx/components/composio/dropbox_compnent.py +11 -0
  188. lfx/components/composio/elevenlabs_composio.py +11 -0
  189. lfx/components/composio/exa_composio.py +11 -0
  190. lfx/components/composio/figma_composio.py +11 -0
  191. lfx/components/composio/finage_composio.py +11 -0
  192. lfx/components/composio/firecrawl_composio.py +11 -0
  193. lfx/components/composio/fireflies_composio.py +11 -0
  194. lfx/components/composio/fixer_composio.py +11 -0
  195. lfx/components/composio/flexisign_composio.py +11 -0
  196. lfx/components/composio/freshdesk_composio.py +11 -0
  197. lfx/components/composio/github_composio.py +11 -0
  198. lfx/components/composio/gmail_composio.py +38 -0
  199. lfx/components/composio/googlebigquery_composio.py +11 -0
  200. lfx/components/composio/googlecalendar_composio.py +11 -0
  201. lfx/components/composio/googleclassroom_composio.py +11 -0
  202. lfx/components/composio/googledocs_composio.py +11 -0
  203. lfx/components/composio/googlemeet_composio.py +11 -0
  204. lfx/components/composio/googlesheets_composio.py +11 -0
  205. lfx/components/composio/googletasks_composio.py +8 -0
  206. lfx/components/composio/heygen_composio.py +11 -0
  207. lfx/components/composio/instagram_composio.py +11 -0
  208. lfx/components/composio/jira_composio.py +11 -0
  209. lfx/components/composio/jotform_composio.py +11 -0
  210. lfx/components/composio/klaviyo_composio.py +11 -0
  211. lfx/components/composio/linear_composio.py +11 -0
  212. lfx/components/composio/listennotes_composio.py +11 -0
  213. lfx/components/composio/mem0_composio.py +11 -0
  214. lfx/components/composio/miro_composio.py +11 -0
  215. lfx/components/composio/missive_composio.py +11 -0
  216. lfx/components/composio/notion_composio.py +11 -0
  217. lfx/components/composio/onedrive_composio.py +11 -0
  218. lfx/components/composio/outlook_composio.py +11 -0
  219. lfx/components/composio/pandadoc_composio.py +11 -0
  220. lfx/components/composio/peopledatalabs_composio.py +11 -0
  221. lfx/components/composio/perplexityai_composio.py +11 -0
  222. lfx/components/composio/reddit_composio.py +11 -0
  223. lfx/components/composio/serpapi_composio.py +11 -0
  224. lfx/components/composio/slack_composio.py +11 -0
  225. lfx/components/composio/slackbot_composio.py +11 -0
  226. lfx/components/composio/snowflake_composio.py +11 -0
  227. lfx/components/composio/supabase_composio.py +11 -0
  228. lfx/components/composio/tavily_composio.py +11 -0
  229. lfx/components/composio/timelinesai_composio.py +11 -0
  230. lfx/components/composio/todoist_composio.py +11 -0
  231. lfx/components/composio/wrike_composio.py +11 -0
  232. lfx/components/composio/youtube_composio.py +11 -0
  233. lfx/components/confluence/__init__.py +3 -0
  234. lfx/components/confluence/confluence.py +84 -0
  235. lfx/components/couchbase/__init__.py +34 -0
  236. lfx/components/couchbase/couchbase.py +102 -0
  237. lfx/components/crewai/__init__.py +49 -0
  238. lfx/components/crewai/crewai.py +108 -0
  239. lfx/components/crewai/hierarchical_crew.py +47 -0
  240. lfx/components/crewai/hierarchical_task.py +45 -0
  241. lfx/components/crewai/sequential_crew.py +53 -0
  242. lfx/components/crewai/sequential_task.py +74 -0
  243. lfx/components/crewai/sequential_task_agent.py +144 -0
  244. lfx/components/cuga/__init__.py +34 -0
  245. lfx/components/cuga/cuga_agent.py +730 -0
  246. lfx/components/custom_component/__init__.py +34 -0
  247. lfx/components/custom_component/custom_component.py +31 -0
  248. lfx/components/data/__init__.py +114 -0
  249. lfx/components/data_source/__init__.py +58 -0
  250. lfx/components/data_source/api_request.py +577 -0
  251. lfx/components/data_source/csv_to_data.py +101 -0
  252. lfx/components/data_source/json_to_data.py +106 -0
  253. lfx/components/data_source/mock_data.py +398 -0
  254. lfx/components/data_source/news_search.py +166 -0
  255. lfx/components/data_source/rss.py +71 -0
  256. lfx/components/data_source/sql_executor.py +101 -0
  257. lfx/components/data_source/url.py +311 -0
  258. lfx/components/data_source/web_search.py +326 -0
  259. lfx/components/datastax/__init__.py +76 -0
  260. lfx/components/datastax/astradb_assistant_manager.py +307 -0
  261. lfx/components/datastax/astradb_chatmemory.py +40 -0
  262. lfx/components/datastax/astradb_cql.py +288 -0
  263. lfx/components/datastax/astradb_graph.py +217 -0
  264. lfx/components/datastax/astradb_tool.py +378 -0
  265. lfx/components/datastax/astradb_vectorize.py +122 -0
  266. lfx/components/datastax/astradb_vectorstore.py +449 -0
  267. lfx/components/datastax/create_assistant.py +59 -0
  268. lfx/components/datastax/create_thread.py +33 -0
  269. lfx/components/datastax/dotenv.py +36 -0
  270. lfx/components/datastax/get_assistant.py +38 -0
  271. lfx/components/datastax/getenvvar.py +31 -0
  272. lfx/components/datastax/graph_rag.py +141 -0
  273. lfx/components/datastax/hcd.py +315 -0
  274. lfx/components/datastax/list_assistants.py +26 -0
  275. lfx/components/datastax/run.py +90 -0
  276. lfx/components/deactivated/__init__.py +15 -0
  277. lfx/components/deactivated/amazon_kendra.py +66 -0
  278. lfx/components/deactivated/chat_litellm_model.py +158 -0
  279. lfx/components/deactivated/code_block_extractor.py +26 -0
  280. lfx/components/deactivated/documents_to_data.py +22 -0
  281. lfx/components/deactivated/embed.py +16 -0
  282. lfx/components/deactivated/extract_key_from_data.py +46 -0
  283. lfx/components/deactivated/json_document_builder.py +57 -0
  284. lfx/components/deactivated/list_flows.py +20 -0
  285. lfx/components/deactivated/mcp_sse.py +61 -0
  286. lfx/components/deactivated/mcp_stdio.py +62 -0
  287. lfx/components/deactivated/merge_data.py +93 -0
  288. lfx/components/deactivated/message.py +37 -0
  289. lfx/components/deactivated/metal.py +54 -0
  290. lfx/components/deactivated/multi_query.py +59 -0
  291. lfx/components/deactivated/retriever.py +43 -0
  292. lfx/components/deactivated/selective_passthrough.py +77 -0
  293. lfx/components/deactivated/should_run_next.py +40 -0
  294. lfx/components/deactivated/split_text.py +63 -0
  295. lfx/components/deactivated/store_message.py +24 -0
  296. lfx/components/deactivated/sub_flow.py +124 -0
  297. lfx/components/deactivated/vectara_self_query.py +76 -0
  298. lfx/components/deactivated/vector_store.py +24 -0
  299. lfx/components/deepseek/__init__.py +34 -0
  300. lfx/components/deepseek/deepseek.py +136 -0
  301. lfx/components/docling/__init__.py +43 -0
  302. lfx/components/docling/chunk_docling_document.py +186 -0
  303. lfx/components/docling/docling_inline.py +238 -0
  304. lfx/components/docling/docling_remote.py +195 -0
  305. lfx/components/docling/export_docling_document.py +117 -0
  306. lfx/components/documentloaders/__init__.py +3 -0
  307. lfx/components/duckduckgo/__init__.py +3 -0
  308. lfx/components/duckduckgo/duck_duck_go_search_run.py +92 -0
  309. lfx/components/elastic/__init__.py +37 -0
  310. lfx/components/elastic/elasticsearch.py +267 -0
  311. lfx/components/elastic/opensearch.py +789 -0
  312. lfx/components/elastic/opensearch_multimodal.py +1575 -0
  313. lfx/components/embeddings/__init__.py +37 -0
  314. lfx/components/embeddings/similarity.py +77 -0
  315. lfx/components/embeddings/text_embedder.py +65 -0
  316. lfx/components/exa/__init__.py +3 -0
  317. lfx/components/exa/exa_search.py +68 -0
  318. lfx/components/files_and_knowledge/__init__.py +47 -0
  319. lfx/components/files_and_knowledge/directory.py +113 -0
  320. lfx/components/files_and_knowledge/file.py +841 -0
  321. lfx/components/files_and_knowledge/ingestion.py +694 -0
  322. lfx/components/files_and_knowledge/retrieval.py +264 -0
  323. lfx/components/files_and_knowledge/save_file.py +746 -0
  324. lfx/components/firecrawl/__init__.py +43 -0
  325. lfx/components/firecrawl/firecrawl_crawl_api.py +88 -0
  326. lfx/components/firecrawl/firecrawl_extract_api.py +136 -0
  327. lfx/components/firecrawl/firecrawl_map_api.py +89 -0
  328. lfx/components/firecrawl/firecrawl_scrape_api.py +73 -0
  329. lfx/components/flow_controls/__init__.py +58 -0
  330. lfx/components/flow_controls/conditional_router.py +208 -0
  331. lfx/components/flow_controls/data_conditional_router.py +126 -0
  332. lfx/components/flow_controls/flow_tool.py +111 -0
  333. lfx/components/flow_controls/listen.py +29 -0
  334. lfx/components/flow_controls/loop.py +163 -0
  335. lfx/components/flow_controls/notify.py +88 -0
  336. lfx/components/flow_controls/pass_message.py +36 -0
  337. lfx/components/flow_controls/run_flow.py +108 -0
  338. lfx/components/flow_controls/sub_flow.py +115 -0
  339. lfx/components/git/__init__.py +4 -0
  340. lfx/components/git/git.py +262 -0
  341. lfx/components/git/gitextractor.py +196 -0
  342. lfx/components/glean/__init__.py +3 -0
  343. lfx/components/glean/glean_search_api.py +173 -0
  344. lfx/components/google/__init__.py +17 -0
  345. lfx/components/google/gmail.py +193 -0
  346. lfx/components/google/google_bq_sql_executor.py +157 -0
  347. lfx/components/google/google_drive.py +92 -0
  348. lfx/components/google/google_drive_search.py +152 -0
  349. lfx/components/google/google_generative_ai.py +144 -0
  350. lfx/components/google/google_generative_ai_embeddings.py +141 -0
  351. lfx/components/google/google_oauth_token.py +89 -0
  352. lfx/components/google/google_search_api_core.py +68 -0
  353. lfx/components/google/google_serper_api_core.py +74 -0
  354. lfx/components/groq/__init__.py +34 -0
  355. lfx/components/groq/groq.py +143 -0
  356. lfx/components/helpers/__init__.py +154 -0
  357. lfx/components/homeassistant/__init__.py +7 -0
  358. lfx/components/homeassistant/home_assistant_control.py +152 -0
  359. lfx/components/homeassistant/list_home_assistant_states.py +137 -0
  360. lfx/components/huggingface/__init__.py +37 -0
  361. lfx/components/huggingface/huggingface.py +199 -0
  362. lfx/components/huggingface/huggingface_inference_api.py +106 -0
  363. lfx/components/ibm/__init__.py +34 -0
  364. lfx/components/ibm/watsonx.py +207 -0
  365. lfx/components/ibm/watsonx_embeddings.py +135 -0
  366. lfx/components/icosacomputing/__init__.py +5 -0
  367. lfx/components/icosacomputing/combinatorial_reasoner.py +84 -0
  368. lfx/components/input_output/__init__.py +40 -0
  369. lfx/components/input_output/chat.py +109 -0
  370. lfx/components/input_output/chat_output.py +184 -0
  371. lfx/components/input_output/text.py +27 -0
  372. lfx/components/input_output/text_output.py +29 -0
  373. lfx/components/input_output/webhook.py +56 -0
  374. lfx/components/jigsawstack/__init__.py +23 -0
  375. lfx/components/jigsawstack/ai_scrape.py +126 -0
  376. lfx/components/jigsawstack/ai_web_search.py +136 -0
  377. lfx/components/jigsawstack/file_read.py +115 -0
  378. lfx/components/jigsawstack/file_upload.py +94 -0
  379. lfx/components/jigsawstack/image_generation.py +205 -0
  380. lfx/components/jigsawstack/nsfw.py +60 -0
  381. lfx/components/jigsawstack/object_detection.py +124 -0
  382. lfx/components/jigsawstack/sentiment.py +112 -0
  383. lfx/components/jigsawstack/text_to_sql.py +90 -0
  384. lfx/components/jigsawstack/text_translate.py +77 -0
  385. lfx/components/jigsawstack/vocr.py +107 -0
  386. lfx/components/knowledge_bases/__init__.py +89 -0
  387. lfx/components/langchain_utilities/__init__.py +109 -0
  388. lfx/components/langchain_utilities/character.py +53 -0
  389. lfx/components/langchain_utilities/conversation.py +59 -0
  390. lfx/components/langchain_utilities/csv_agent.py +175 -0
  391. lfx/components/langchain_utilities/fake_embeddings.py +26 -0
  392. lfx/components/langchain_utilities/html_link_extractor.py +35 -0
  393. lfx/components/langchain_utilities/json_agent.py +100 -0
  394. lfx/components/langchain_utilities/langchain_hub.py +126 -0
  395. lfx/components/langchain_utilities/language_recursive.py +49 -0
  396. lfx/components/langchain_utilities/language_semantic.py +138 -0
  397. lfx/components/langchain_utilities/llm_checker.py +39 -0
  398. lfx/components/langchain_utilities/llm_math.py +42 -0
  399. lfx/components/langchain_utilities/natural_language.py +61 -0
  400. lfx/components/langchain_utilities/openai_tools.py +53 -0
  401. lfx/components/langchain_utilities/openapi.py +48 -0
  402. lfx/components/langchain_utilities/recursive_character.py +60 -0
  403. lfx/components/langchain_utilities/retrieval_qa.py +83 -0
  404. lfx/components/langchain_utilities/runnable_executor.py +137 -0
  405. lfx/components/langchain_utilities/self_query.py +80 -0
  406. lfx/components/langchain_utilities/spider.py +142 -0
  407. lfx/components/langchain_utilities/sql.py +40 -0
  408. lfx/components/langchain_utilities/sql_database.py +35 -0
  409. lfx/components/langchain_utilities/sql_generator.py +78 -0
  410. lfx/components/langchain_utilities/tool_calling.py +59 -0
  411. lfx/components/langchain_utilities/vector_store_info.py +49 -0
  412. lfx/components/langchain_utilities/vector_store_router.py +33 -0
  413. lfx/components/langchain_utilities/xml_agent.py +71 -0
  414. lfx/components/langwatch/__init__.py +3 -0
  415. lfx/components/langwatch/langwatch.py +278 -0
  416. lfx/components/link_extractors/__init__.py +3 -0
  417. lfx/components/llm_operations/__init__.py +46 -0
  418. lfx/components/llm_operations/batch_run.py +205 -0
  419. lfx/components/llm_operations/lambda_filter.py +218 -0
  420. lfx/components/llm_operations/llm_conditional_router.py +421 -0
  421. lfx/components/llm_operations/llm_selector.py +499 -0
  422. lfx/components/llm_operations/structured_output.py +244 -0
  423. lfx/components/lmstudio/__init__.py +34 -0
  424. lfx/components/lmstudio/lmstudioembeddings.py +89 -0
  425. lfx/components/lmstudio/lmstudiomodel.py +133 -0
  426. lfx/components/logic/__init__.py +181 -0
  427. lfx/components/maritalk/__init__.py +32 -0
  428. lfx/components/maritalk/maritalk.py +52 -0
  429. lfx/components/mem0/__init__.py +3 -0
  430. lfx/components/mem0/mem0_chat_memory.py +147 -0
  431. lfx/components/milvus/__init__.py +34 -0
  432. lfx/components/milvus/milvus.py +115 -0
  433. lfx/components/mistral/__init__.py +37 -0
  434. lfx/components/mistral/mistral.py +114 -0
  435. lfx/components/mistral/mistral_embeddings.py +58 -0
  436. lfx/components/models/__init__.py +89 -0
  437. lfx/components/models_and_agents/__init__.py +49 -0
  438. lfx/components/models_and_agents/agent.py +644 -0
  439. lfx/components/models_and_agents/embedding_model.py +423 -0
  440. lfx/components/models_and_agents/language_model.py +398 -0
  441. lfx/components/models_and_agents/mcp_component.py +594 -0
  442. lfx/components/models_and_agents/memory.py +268 -0
  443. lfx/components/models_and_agents/prompt.py +67 -0
  444. lfx/components/mongodb/__init__.py +34 -0
  445. lfx/components/mongodb/mongodb_atlas.py +213 -0
  446. lfx/components/needle/__init__.py +3 -0
  447. lfx/components/needle/needle.py +104 -0
  448. lfx/components/notdiamond/__init__.py +34 -0
  449. lfx/components/notdiamond/notdiamond.py +228 -0
  450. lfx/components/novita/__init__.py +32 -0
  451. lfx/components/novita/novita.py +130 -0
  452. lfx/components/nvidia/__init__.py +57 -0
  453. lfx/components/nvidia/nvidia.py +151 -0
  454. lfx/components/nvidia/nvidia_embedding.py +77 -0
  455. lfx/components/nvidia/nvidia_ingest.py +317 -0
  456. lfx/components/nvidia/nvidia_rerank.py +63 -0
  457. lfx/components/nvidia/system_assist.py +65 -0
  458. lfx/components/olivya/__init__.py +3 -0
  459. lfx/components/olivya/olivya.py +116 -0
  460. lfx/components/ollama/__init__.py +37 -0
  461. lfx/components/ollama/ollama.py +548 -0
  462. lfx/components/ollama/ollama_embeddings.py +103 -0
  463. lfx/components/openai/__init__.py +37 -0
  464. lfx/components/openai/openai.py +100 -0
  465. lfx/components/openai/openai_chat_model.py +176 -0
  466. lfx/components/openrouter/__init__.py +32 -0
  467. lfx/components/openrouter/openrouter.py +104 -0
  468. lfx/components/output_parsers/__init__.py +3 -0
  469. lfx/components/perplexity/__init__.py +34 -0
  470. lfx/components/perplexity/perplexity.py +75 -0
  471. lfx/components/pgvector/__init__.py +34 -0
  472. lfx/components/pgvector/pgvector.py +72 -0
  473. lfx/components/pinecone/__init__.py +34 -0
  474. lfx/components/pinecone/pinecone.py +134 -0
  475. lfx/components/processing/__init__.py +72 -0
  476. lfx/components/processing/alter_metadata.py +109 -0
  477. lfx/components/processing/combine_text.py +40 -0
  478. lfx/components/processing/converter.py +248 -0
  479. lfx/components/processing/create_data.py +111 -0
  480. lfx/components/processing/create_list.py +40 -0
  481. lfx/components/processing/data_operations.py +528 -0
  482. lfx/components/processing/data_to_dataframe.py +71 -0
  483. lfx/components/processing/dataframe_operations.py +313 -0
  484. lfx/components/processing/dataframe_to_toolset.py +259 -0
  485. lfx/components/processing/dynamic_create_data.py +357 -0
  486. lfx/components/processing/extract_key.py +54 -0
  487. lfx/components/processing/filter_data.py +43 -0
  488. lfx/components/processing/filter_data_values.py +89 -0
  489. lfx/components/processing/json_cleaner.py +104 -0
  490. lfx/components/processing/merge_data.py +91 -0
  491. lfx/components/processing/message_to_data.py +37 -0
  492. lfx/components/processing/output_parser.py +46 -0
  493. lfx/components/processing/parse_data.py +71 -0
  494. lfx/components/processing/parse_dataframe.py +69 -0
  495. lfx/components/processing/parse_json_data.py +91 -0
  496. lfx/components/processing/parser.py +148 -0
  497. lfx/components/processing/regex.py +83 -0
  498. lfx/components/processing/select_data.py +49 -0
  499. lfx/components/processing/split_text.py +141 -0
  500. lfx/components/processing/store_message.py +91 -0
  501. lfx/components/processing/update_data.py +161 -0
  502. lfx/components/prototypes/__init__.py +35 -0
  503. lfx/components/prototypes/python_function.py +73 -0
  504. lfx/components/qdrant/__init__.py +34 -0
  505. lfx/components/qdrant/qdrant.py +109 -0
  506. lfx/components/redis/__init__.py +37 -0
  507. lfx/components/redis/redis.py +89 -0
  508. lfx/components/redis/redis_chat.py +43 -0
  509. lfx/components/sambanova/__init__.py +32 -0
  510. lfx/components/sambanova/sambanova.py +84 -0
  511. lfx/components/scrapegraph/__init__.py +40 -0
  512. lfx/components/scrapegraph/scrapegraph_markdownify_api.py +64 -0
  513. lfx/components/scrapegraph/scrapegraph_search_api.py +64 -0
  514. lfx/components/scrapegraph/scrapegraph_smart_scraper_api.py +71 -0
  515. lfx/components/searchapi/__init__.py +34 -0
  516. lfx/components/searchapi/search.py +79 -0
  517. lfx/components/serpapi/__init__.py +3 -0
  518. lfx/components/serpapi/serp.py +115 -0
  519. lfx/components/supabase/__init__.py +34 -0
  520. lfx/components/supabase/supabase.py +76 -0
  521. lfx/components/tavily/__init__.py +4 -0
  522. lfx/components/tavily/tavily_extract.py +117 -0
  523. lfx/components/tavily/tavily_search.py +212 -0
  524. lfx/components/textsplitters/__init__.py +3 -0
  525. lfx/components/toolkits/__init__.py +3 -0
  526. lfx/components/tools/__init__.py +66 -0
  527. lfx/components/tools/calculator.py +109 -0
  528. lfx/components/tools/google_search_api.py +45 -0
  529. lfx/components/tools/google_serper_api.py +115 -0
  530. lfx/components/tools/python_code_structured_tool.py +328 -0
  531. lfx/components/tools/python_repl.py +98 -0
  532. lfx/components/tools/search_api.py +88 -0
  533. lfx/components/tools/searxng.py +145 -0
  534. lfx/components/tools/serp_api.py +120 -0
  535. lfx/components/tools/tavily_search_tool.py +345 -0
  536. lfx/components/tools/wikidata_api.py +103 -0
  537. lfx/components/tools/wikipedia_api.py +50 -0
  538. lfx/components/tools/yahoo_finance.py +130 -0
  539. lfx/components/twelvelabs/__init__.py +52 -0
  540. lfx/components/twelvelabs/convert_astra_results.py +84 -0
  541. lfx/components/twelvelabs/pegasus_index.py +311 -0
  542. lfx/components/twelvelabs/split_video.py +301 -0
  543. lfx/components/twelvelabs/text_embeddings.py +57 -0
  544. lfx/components/twelvelabs/twelvelabs_pegasus.py +408 -0
  545. lfx/components/twelvelabs/video_embeddings.py +100 -0
  546. lfx/components/twelvelabs/video_file.py +191 -0
  547. lfx/components/unstructured/__init__.py +3 -0
  548. lfx/components/unstructured/unstructured.py +121 -0
  549. lfx/components/upstash/__init__.py +34 -0
  550. lfx/components/upstash/upstash.py +124 -0
  551. lfx/components/utilities/__init__.py +43 -0
  552. lfx/components/utilities/calculator_core.py +89 -0
  553. lfx/components/utilities/current_date.py +42 -0
  554. lfx/components/utilities/id_generator.py +42 -0
  555. lfx/components/utilities/python_repl_core.py +98 -0
  556. lfx/components/vectara/__init__.py +37 -0
  557. lfx/components/vectara/vectara.py +97 -0
  558. lfx/components/vectara/vectara_rag.py +164 -0
  559. lfx/components/vectorstores/__init__.py +34 -0
  560. lfx/components/vectorstores/local_db.py +270 -0
  561. lfx/components/vertexai/__init__.py +37 -0
  562. lfx/components/vertexai/vertexai.py +71 -0
  563. lfx/components/vertexai/vertexai_embeddings.py +67 -0
  564. lfx/components/vlmrun/__init__.py +34 -0
  565. lfx/components/vlmrun/vlmrun_transcription.py +224 -0
  566. lfx/components/weaviate/__init__.py +34 -0
  567. lfx/components/weaviate/weaviate.py +89 -0
  568. lfx/components/wikipedia/__init__.py +4 -0
  569. lfx/components/wikipedia/wikidata.py +86 -0
  570. lfx/components/wikipedia/wikipedia.py +53 -0
  571. lfx/components/wolframalpha/__init__.py +3 -0
  572. lfx/components/wolframalpha/wolfram_alpha_api.py +54 -0
  573. lfx/components/xai/__init__.py +32 -0
  574. lfx/components/xai/xai.py +167 -0
  575. lfx/components/yahoosearch/__init__.py +3 -0
  576. lfx/components/yahoosearch/yahoo.py +137 -0
  577. lfx/components/youtube/__init__.py +52 -0
  578. lfx/components/youtube/channel.py +227 -0
  579. lfx/components/youtube/comments.py +231 -0
  580. lfx/components/youtube/playlist.py +33 -0
  581. lfx/components/youtube/search.py +120 -0
  582. lfx/components/youtube/trending.py +285 -0
  583. lfx/components/youtube/video_details.py +263 -0
  584. lfx/components/youtube/youtube_transcripts.py +206 -0
  585. lfx/components/zep/__init__.py +3 -0
  586. lfx/components/zep/zep.py +45 -0
  587. lfx/constants.py +6 -0
  588. lfx/custom/__init__.py +7 -0
  589. lfx/custom/attributes.py +87 -0
  590. lfx/custom/code_parser/__init__.py +3 -0
  591. lfx/custom/code_parser/code_parser.py +361 -0
  592. lfx/custom/custom_component/__init__.py +0 -0
  593. lfx/custom/custom_component/base_component.py +128 -0
  594. lfx/custom/custom_component/component.py +1890 -0
  595. lfx/custom/custom_component/component_with_cache.py +8 -0
  596. lfx/custom/custom_component/custom_component.py +650 -0
  597. lfx/custom/dependency_analyzer.py +165 -0
  598. lfx/custom/directory_reader/__init__.py +3 -0
  599. lfx/custom/directory_reader/directory_reader.py +359 -0
  600. lfx/custom/directory_reader/utils.py +171 -0
  601. lfx/custom/eval.py +12 -0
  602. lfx/custom/schema.py +32 -0
  603. lfx/custom/tree_visitor.py +21 -0
  604. lfx/custom/utils.py +877 -0
  605. lfx/custom/validate.py +523 -0
  606. lfx/events/__init__.py +1 -0
  607. lfx/events/event_manager.py +110 -0
  608. lfx/exceptions/__init__.py +0 -0
  609. lfx/exceptions/component.py +15 -0
  610. lfx/field_typing/__init__.py +91 -0
  611. lfx/field_typing/constants.py +216 -0
  612. lfx/field_typing/range_spec.py +35 -0
  613. lfx/graph/__init__.py +6 -0
  614. lfx/graph/edge/__init__.py +0 -0
  615. lfx/graph/edge/base.py +300 -0
  616. lfx/graph/edge/schema.py +119 -0
  617. lfx/graph/edge/utils.py +0 -0
  618. lfx/graph/graph/__init__.py +0 -0
  619. lfx/graph/graph/ascii.py +202 -0
  620. lfx/graph/graph/base.py +2298 -0
  621. lfx/graph/graph/constants.py +63 -0
  622. lfx/graph/graph/runnable_vertices_manager.py +133 -0
  623. lfx/graph/graph/schema.py +53 -0
  624. lfx/graph/graph/state_model.py +66 -0
  625. lfx/graph/graph/utils.py +1024 -0
  626. lfx/graph/schema.py +75 -0
  627. lfx/graph/state/__init__.py +0 -0
  628. lfx/graph/state/model.py +250 -0
  629. lfx/graph/utils.py +206 -0
  630. lfx/graph/vertex/__init__.py +0 -0
  631. lfx/graph/vertex/base.py +826 -0
  632. lfx/graph/vertex/constants.py +0 -0
  633. lfx/graph/vertex/exceptions.py +4 -0
  634. lfx/graph/vertex/param_handler.py +316 -0
  635. lfx/graph/vertex/schema.py +26 -0
  636. lfx/graph/vertex/utils.py +19 -0
  637. lfx/graph/vertex/vertex_types.py +489 -0
  638. lfx/helpers/__init__.py +141 -0
  639. lfx/helpers/base_model.py +71 -0
  640. lfx/helpers/custom.py +13 -0
  641. lfx/helpers/data.py +167 -0
  642. lfx/helpers/flow.py +308 -0
  643. lfx/inputs/__init__.py +68 -0
  644. lfx/inputs/constants.py +2 -0
  645. lfx/inputs/input_mixin.py +352 -0
  646. lfx/inputs/inputs.py +718 -0
  647. lfx/inputs/validators.py +19 -0
  648. lfx/interface/__init__.py +6 -0
  649. lfx/interface/components.py +897 -0
  650. lfx/interface/importing/__init__.py +5 -0
  651. lfx/interface/importing/utils.py +39 -0
  652. lfx/interface/initialize/__init__.py +3 -0
  653. lfx/interface/initialize/loading.py +317 -0
  654. lfx/interface/listing.py +26 -0
  655. lfx/interface/run.py +16 -0
  656. lfx/interface/utils.py +111 -0
  657. lfx/io/__init__.py +63 -0
  658. lfx/io/schema.py +295 -0
  659. lfx/load/__init__.py +8 -0
  660. lfx/load/load.py +256 -0
  661. lfx/load/utils.py +99 -0
  662. lfx/log/__init__.py +5 -0
  663. lfx/log/logger.py +411 -0
  664. lfx/logging/__init__.py +11 -0
  665. lfx/logging/logger.py +24 -0
  666. lfx/memory/__init__.py +70 -0
  667. lfx/memory/stubs.py +302 -0
  668. lfx/processing/__init__.py +1 -0
  669. lfx/processing/process.py +238 -0
  670. lfx/processing/utils.py +25 -0
  671. lfx/py.typed +0 -0
  672. lfx/schema/__init__.py +66 -0
  673. lfx/schema/artifact.py +83 -0
  674. lfx/schema/content_block.py +62 -0
  675. lfx/schema/content_types.py +91 -0
  676. lfx/schema/cross_module.py +80 -0
  677. lfx/schema/data.py +309 -0
  678. lfx/schema/dataframe.py +210 -0
  679. lfx/schema/dotdict.py +74 -0
  680. lfx/schema/encoders.py +13 -0
  681. lfx/schema/graph.py +47 -0
  682. lfx/schema/image.py +184 -0
  683. lfx/schema/json_schema.py +186 -0
  684. lfx/schema/log.py +62 -0
  685. lfx/schema/message.py +493 -0
  686. lfx/schema/openai_responses_schemas.py +74 -0
  687. lfx/schema/properties.py +41 -0
  688. lfx/schema/schema.py +180 -0
  689. lfx/schema/serialize.py +13 -0
  690. lfx/schema/table.py +142 -0
  691. lfx/schema/validators.py +114 -0
  692. lfx/serialization/__init__.py +5 -0
  693. lfx/serialization/constants.py +2 -0
  694. lfx/serialization/serialization.py +314 -0
  695. lfx/services/__init__.py +26 -0
  696. lfx/services/base.py +28 -0
  697. lfx/services/cache/__init__.py +6 -0
  698. lfx/services/cache/base.py +183 -0
  699. lfx/services/cache/service.py +166 -0
  700. lfx/services/cache/utils.py +169 -0
  701. lfx/services/chat/__init__.py +1 -0
  702. lfx/services/chat/config.py +2 -0
  703. lfx/services/chat/schema.py +10 -0
  704. lfx/services/database/__init__.py +5 -0
  705. lfx/services/database/service.py +25 -0
  706. lfx/services/deps.py +194 -0
  707. lfx/services/factory.py +19 -0
  708. lfx/services/initialize.py +19 -0
  709. lfx/services/interfaces.py +103 -0
  710. lfx/services/manager.py +185 -0
  711. lfx/services/mcp_composer/__init__.py +6 -0
  712. lfx/services/mcp_composer/factory.py +16 -0
  713. lfx/services/mcp_composer/service.py +1441 -0
  714. lfx/services/schema.py +21 -0
  715. lfx/services/session.py +87 -0
  716. lfx/services/settings/__init__.py +3 -0
  717. lfx/services/settings/auth.py +133 -0
  718. lfx/services/settings/base.py +668 -0
  719. lfx/services/settings/constants.py +43 -0
  720. lfx/services/settings/factory.py +23 -0
  721. lfx/services/settings/feature_flags.py +11 -0
  722. lfx/services/settings/service.py +35 -0
  723. lfx/services/settings/utils.py +40 -0
  724. lfx/services/shared_component_cache/__init__.py +1 -0
  725. lfx/services/shared_component_cache/factory.py +30 -0
  726. lfx/services/shared_component_cache/service.py +9 -0
  727. lfx/services/storage/__init__.py +5 -0
  728. lfx/services/storage/local.py +185 -0
  729. lfx/services/storage/service.py +177 -0
  730. lfx/services/tracing/__init__.py +1 -0
  731. lfx/services/tracing/service.py +21 -0
  732. lfx/settings.py +6 -0
  733. lfx/template/__init__.py +6 -0
  734. lfx/template/field/__init__.py +0 -0
  735. lfx/template/field/base.py +260 -0
  736. lfx/template/field/prompt.py +15 -0
  737. lfx/template/frontend_node/__init__.py +6 -0
  738. lfx/template/frontend_node/base.py +214 -0
  739. lfx/template/frontend_node/constants.py +65 -0
  740. lfx/template/frontend_node/custom_components.py +79 -0
  741. lfx/template/template/__init__.py +0 -0
  742. lfx/template/template/base.py +100 -0
  743. lfx/template/utils.py +217 -0
  744. lfx/type_extraction/__init__.py +19 -0
  745. lfx/type_extraction/type_extraction.py +75 -0
  746. lfx/type_extraction.py +80 -0
  747. lfx/utils/__init__.py +1 -0
  748. lfx/utils/async_helpers.py +42 -0
  749. lfx/utils/component_utils.py +154 -0
  750. lfx/utils/concurrency.py +60 -0
  751. lfx/utils/connection_string_parser.py +11 -0
  752. lfx/utils/constants.py +233 -0
  753. lfx/utils/data_structure.py +212 -0
  754. lfx/utils/exceptions.py +22 -0
  755. lfx/utils/helpers.py +34 -0
  756. lfx/utils/image.py +79 -0
  757. lfx/utils/langflow_utils.py +52 -0
  758. lfx/utils/lazy_load.py +15 -0
  759. lfx/utils/request_utils.py +18 -0
  760. lfx/utils/schemas.py +139 -0
  761. lfx/utils/ssrf_protection.py +384 -0
  762. lfx/utils/util.py +626 -0
  763. lfx/utils/util_strings.py +56 -0
  764. lfx/utils/validate_cloud.py +26 -0
  765. lfx/utils/version.py +24 -0
  766. lfx_nightly-0.2.0.dev25.dist-info/METADATA +312 -0
  767. lfx_nightly-0.2.0.dev25.dist-info/RECORD +769 -0
  768. lfx_nightly-0.2.0.dev25.dist-info/WHEEL +4 -0
  769. lfx_nightly-0.2.0.dev25.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,218 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import re
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ from lfx.custom.custom_component.component import Component
8
+ from lfx.io import DataInput, HandleInput, IntInput, MultilineInput, Output
9
+ from lfx.schema.data import Data
10
+ from lfx.schema.dataframe import DataFrame
11
+
12
+ if TYPE_CHECKING:
13
+ from collections.abc import Callable
14
+
15
+
16
+ class LambdaFilterComponent(Component):
17
+ display_name = "Smart Transform"
18
+ description = "Uses an LLM to generate a function for filtering or transforming structured data."
19
+ documentation: str = "https://docs.langflow.org/smart-transform"
20
+ icon = "square-function"
21
+ name = "Smart Transform"
22
+
23
+ inputs = [
24
+ DataInput(
25
+ name="data",
26
+ display_name="Data",
27
+ info="The structured data to filter or transform using a lambda function.",
28
+ input_types=["Data", "DataFrame"],
29
+ is_list=True,
30
+ required=True,
31
+ ),
32
+ HandleInput(
33
+ name="llm",
34
+ display_name="Language Model",
35
+ info="Connect the 'Language Model' output from your LLM component here.",
36
+ input_types=["LanguageModel"],
37
+ required=True,
38
+ ),
39
+ MultilineInput(
40
+ name="filter_instruction",
41
+ display_name="Instructions",
42
+ info=(
43
+ "Natural language instructions for how to filter or transform the data using a lambda function. "
44
+ "Example: Filter the data to only include items where the 'status' is 'active'."
45
+ ),
46
+ value="Filter the data to...",
47
+ required=True,
48
+ ),
49
+ IntInput(
50
+ name="sample_size",
51
+ display_name="Sample Size",
52
+ info="For large datasets, number of items to sample from head/tail.",
53
+ value=1000,
54
+ advanced=True,
55
+ ),
56
+ IntInput(
57
+ name="max_size",
58
+ display_name="Max Size",
59
+ info="Number of characters for the data to be considered large.",
60
+ value=30000,
61
+ advanced=True,
62
+ ),
63
+ ]
64
+
65
+ outputs = [
66
+ Output(
67
+ display_name="Output",
68
+ name="data_output",
69
+ method="process_as_data",
70
+ ),
71
+ Output(
72
+ display_name="Output",
73
+ name="dataframe_output",
74
+ method="process_as_dataframe",
75
+ ),
76
+ ]
77
+
78
+ def get_data_structure(self, data):
79
+ """Extract the structure of data, replacing values with their types."""
80
+ if isinstance(data, list):
81
+ # For lists, get structure of first item if available
82
+ if data:
83
+ return [self.get_data_structure(data[0])]
84
+ return []
85
+ if isinstance(data, dict):
86
+ return {k: self.get_data_structure(v) for k, v in data.items()}
87
+ # For primitive types, return the type name
88
+ return type(data).__name__
89
+
90
+ def _validate_lambda(self, lambda_text: str) -> bool:
91
+ """Validate the provided lambda function text."""
92
+ # Return False if the lambda function does not start with 'lambda' or does not contain a colon
93
+ return lambda_text.strip().startswith("lambda") and ":" in lambda_text
94
+
95
+ async def _execute_lambda(self) -> Any:
96
+ self.log(str(self.data))
97
+
98
+ # Convert input to a unified format
99
+ if isinstance(self.data, list):
100
+ # Handle list of Data or DataFrame objects
101
+ combined_data = []
102
+ for item in self.data:
103
+ if isinstance(item, DataFrame):
104
+ # DataFrame to list of dicts
105
+ combined_data.extend(item.to_dict(orient="records"))
106
+ elif hasattr(item, "data"):
107
+ # Data object
108
+ if isinstance(item.data, dict):
109
+ combined_data.append(item.data)
110
+ elif isinstance(item.data, list):
111
+ combined_data.extend(item.data)
112
+
113
+ # If we have a single dict, unwrap it so lambdas can access it directly
114
+ if len(combined_data) == 1 and isinstance(combined_data[0], dict):
115
+ data = combined_data[0]
116
+ elif len(combined_data) == 0:
117
+ data = {}
118
+ else:
119
+ data = combined_data # type: ignore[assignment]
120
+ elif isinstance(self.data, DataFrame):
121
+ # Single DataFrame to list of dicts
122
+ data = self.data.to_dict(orient="records")
123
+ elif hasattr(self.data, "data"):
124
+ # Single Data object
125
+ data = self.data.data
126
+ else:
127
+ data = self.data
128
+
129
+ dump = json.dumps(data)
130
+ self.log(str(data))
131
+
132
+ llm = self.llm
133
+ instruction = self.filter_instruction
134
+ sample_size = self.sample_size
135
+
136
+ # Get data structure and samples
137
+ data_structure = self.get_data_structure(data)
138
+ dump_structure = json.dumps(data_structure)
139
+ self.log(dump_structure)
140
+
141
+ # For large datasets, sample from head and tail
142
+ if len(dump) > self.max_size:
143
+ data_sample = (
144
+ f"Data is too long to display... \n\n First lines (head): {dump[:sample_size]} \n\n"
145
+ f" Last lines (tail): {dump[-sample_size:]})"
146
+ )
147
+ else:
148
+ data_sample = dump
149
+
150
+ self.log(data_sample)
151
+
152
+ prompt = f"""Given this data structure and examples, create a Python lambda function that
153
+ implements the following instruction:
154
+
155
+ Data Structure:
156
+ {dump_structure}
157
+
158
+ Example Items:
159
+ {data_sample}
160
+
161
+ Instruction: {instruction}
162
+
163
+ Return ONLY the lambda function and nothing else. No need for ```python or whatever.
164
+ Just a string starting with lambda.
165
+ """
166
+
167
+ response = await llm.ainvoke(prompt)
168
+ response_text = response.content if hasattr(response, "content") else str(response)
169
+ self.log(response_text)
170
+
171
+ # Extract lambda using regex
172
+ lambda_match = re.search(r"lambda\s+\w+\s*:.*?(?=\n|$)", response_text)
173
+ if not lambda_match:
174
+ msg = f"Could not find lambda in response: {response_text}"
175
+ raise ValueError(msg)
176
+
177
+ lambda_text = lambda_match.group().strip()
178
+ self.log(lambda_text)
179
+
180
+ # Validation is commented out as requested
181
+ if not self._validate_lambda(lambda_text):
182
+ msg = f"Invalid lambda format: {lambda_text}"
183
+ raise ValueError(msg)
184
+
185
+ # Create and apply the function
186
+ fn: Callable[[Any], Any] = eval(lambda_text) # noqa: S307
187
+
188
+ # Apply the lambda function to the data
189
+ return fn(data)
190
+
191
+ async def process_as_data(self) -> Data:
192
+ """Process the data and return as a Data object."""
193
+ result = await self._execute_lambda()
194
+
195
+ # Convert result to Data based on type
196
+ if isinstance(result, dict):
197
+ return Data(data=result)
198
+ if isinstance(result, list):
199
+ return Data(data={"_results": result})
200
+ # For other types, convert to string
201
+ return Data(data={"text": str(result)})
202
+
203
+ async def process_as_dataframe(self) -> DataFrame:
204
+ """Process the data and return as a DataFrame."""
205
+ result = await self._execute_lambda()
206
+
207
+ # Convert result to DataFrame based on type
208
+ if isinstance(result, list):
209
+ # Check if it's a list of dicts
210
+ if all(isinstance(item, dict) for item in result):
211
+ return DataFrame(result)
212
+ # List of non-dicts: wrap each value
213
+ return DataFrame([{"value": item} for item in result])
214
+ if isinstance(result, dict):
215
+ # Single dict becomes single-row DataFrame
216
+ return DataFrame([result])
217
+ # Other types: convert to string and wrap
218
+ return DataFrame([{"value": str(result)}])
@@ -0,0 +1,421 @@
1
+ from typing import Any
2
+
3
+ from lfx.custom import Component
4
+ from lfx.io import BoolInput, HandleInput, MessageInput, MessageTextInput, MultilineInput, Output, TableInput
5
+ from lfx.schema.message import Message
6
+ from lfx.schema.table import EditMode
7
+
8
+
9
+ class SmartRouterComponent(Component):
10
+ display_name = "Smart Router"
11
+ description = "Routes an input message using LLM-based categorization."
12
+ icon = "route"
13
+ name = "SmartRouter"
14
+
15
+ def __init__(self, **kwargs):
16
+ super().__init__(**kwargs)
17
+ self._matched_category = None
18
+
19
+ inputs = [
20
+ HandleInput(
21
+ name="llm",
22
+ display_name="Language Model",
23
+ info="LLM to use for categorization.",
24
+ input_types=["LanguageModel"],
25
+ required=True,
26
+ ),
27
+ MessageTextInput(
28
+ name="input_text",
29
+ display_name="Input",
30
+ info="The primary text input for the operation.",
31
+ required=True,
32
+ ),
33
+ TableInput(
34
+ name="routes",
35
+ display_name="Routes",
36
+ info=(
37
+ "Define the categories for routing. Each row should have a route/category name "
38
+ "and optionally a custom output value."
39
+ ),
40
+ table_schema=[
41
+ {
42
+ "name": "route_category",
43
+ "display_name": "Route Name",
44
+ "type": "str",
45
+ "description": "Name for the route (used for both output name and category matching)",
46
+ "edit_mode": EditMode.INLINE,
47
+ },
48
+ {
49
+ "name": "route_description",
50
+ "display_name": "Route Description",
51
+ "type": "str",
52
+ "description": "Description of when this route should be used (helps LLM understand the category)",
53
+ "default": "",
54
+ "edit_mode": EditMode.POPOVER,
55
+ },
56
+ {
57
+ "name": "output_value",
58
+ "display_name": "Route Message (Optional)",
59
+ "type": "str",
60
+ "description": (
61
+ "Optional message to send when this route is matched."
62
+ "Leave empty to pass through the original input text."
63
+ ),
64
+ "default": "",
65
+ "edit_mode": EditMode.POPOVER,
66
+ },
67
+ ],
68
+ value=[
69
+ {
70
+ "route_category": "Positive",
71
+ "route_description": "Positive feedback, satisfaction, or compliments",
72
+ "output_value": "",
73
+ },
74
+ {
75
+ "route_category": "Negative",
76
+ "route_description": "Complaints, issues, or dissatisfaction",
77
+ "output_value": "",
78
+ },
79
+ ],
80
+ real_time_refresh=True,
81
+ required=True,
82
+ ),
83
+ MessageInput(
84
+ name="message",
85
+ display_name="Override Output",
86
+ info=(
87
+ "Optional override message that will replace both the Input and Output Value "
88
+ "for all routes when filled."
89
+ ),
90
+ required=False,
91
+ advanced=True,
92
+ ),
93
+ BoolInput(
94
+ name="enable_else_output",
95
+ display_name="Include Else Output",
96
+ info="Include an Else output for cases that don't match any route.",
97
+ value=False,
98
+ advanced=True,
99
+ ),
100
+ MultilineInput(
101
+ name="custom_prompt",
102
+ display_name="Additional Instructions",
103
+ info=(
104
+ "Additional instructions for LLM-based categorization. "
105
+ "These will be added to the base prompt. "
106
+ "Use {input_text} for the input text and {routes} for the available categories."
107
+ ),
108
+ advanced=True,
109
+ ),
110
+ ]
111
+
112
+ outputs: list[Output] = []
113
+
114
+ def update_outputs(self, frontend_node: dict, field_name: str, field_value: Any) -> dict:
115
+ """Create a dynamic output for each category in the categories table."""
116
+ if field_name in {"routes", "enable_else_output"}:
117
+ frontend_node["outputs"] = []
118
+
119
+ # Get the routes data - either from field_value (if routes field) or from component state
120
+ routes_data = field_value if field_name == "routes" else getattr(self, "routes", [])
121
+
122
+ # Add a dynamic output for each category - all using the same method
123
+ for i, row in enumerate(routes_data):
124
+ route_category = row.get("route_category", f"Category {i + 1}")
125
+ frontend_node["outputs"].append(
126
+ Output(
127
+ display_name=route_category,
128
+ name=f"category_{i + 1}_result",
129
+ method="process_case",
130
+ group_outputs=True,
131
+ )
132
+ )
133
+ # Add default output only if enabled
134
+ if field_name == "enable_else_output":
135
+ enable_else = field_value
136
+ else:
137
+ enable_else = getattr(self, "enable_else_output", False)
138
+
139
+ if enable_else:
140
+ frontend_node["outputs"].append(
141
+ Output(display_name="Else", name="default_result", method="default_response", group_outputs=True)
142
+ )
143
+ return frontend_node
144
+
145
+ def process_case(self) -> Message:
146
+ """Process all categories using LLM categorization and return message for matching category."""
147
+ # Clear any previous match state
148
+ self._matched_category = None
149
+
150
+ # Get categories and input text
151
+ categories = getattr(self, "routes", [])
152
+ input_text = getattr(self, "input_text", "")
153
+
154
+ # Find the matching category using LLM-based categorization
155
+ matched_category = None
156
+ llm = getattr(self, "llm", None)
157
+
158
+ if llm and categories:
159
+ # Create prompt for categorization
160
+ category_info = []
161
+ for i, category in enumerate(categories):
162
+ cat_name = category.get("route_category", f"Category {i + 1}")
163
+ cat_desc = category.get("route_description", "")
164
+ if cat_desc and cat_desc.strip():
165
+ category_info.append(f'"{cat_name}": {cat_desc}')
166
+ else:
167
+ category_info.append(f'"{cat_name}"')
168
+
169
+ categories_text = "\n".join([f"- {info}" for info in category_info if info])
170
+
171
+ # Create base prompt
172
+ base_prompt = (
173
+ f"You are a text classifier. Given the following text and categories, "
174
+ f"determine which category best matches the text.\n\n"
175
+ f'Text to classify: "{input_text}"\n\n'
176
+ f"Available categories:\n{categories_text}\n\n"
177
+ f"Respond with ONLY the exact category name that best matches the text. "
178
+ f'If none match well, respond with "NONE".\n\n'
179
+ f"Category:"
180
+ )
181
+
182
+ # Use custom prompt as additional instructions if provided
183
+ custom_prompt = getattr(self, "custom_prompt", "")
184
+ if custom_prompt and custom_prompt.strip():
185
+ self.status = "Using custom prompt as additional instructions"
186
+ # Format custom prompt with variables
187
+ # For the routes variable, create a simpler format for custom prompt usage
188
+ simple_routes = ", ".join(
189
+ [f'"{cat.get("route_category", f"Category {i + 1}")}"' for i, cat in enumerate(categories)]
190
+ )
191
+ formatted_custom = custom_prompt.format(input_text=input_text, routes=simple_routes)
192
+ # Combine base prompt with custom instructions
193
+ prompt = f"{base_prompt}\n\nAdditional Instructions:\n{formatted_custom}"
194
+ else:
195
+ self.status = "Using default prompt for LLM categorization"
196
+ prompt = base_prompt
197
+
198
+ # Log the final prompt being sent to LLM
199
+ self.status = f"Prompt sent to LLM:\n{prompt}"
200
+
201
+ try:
202
+ # Use the LLM to categorize
203
+ if hasattr(llm, "invoke"):
204
+ response = llm.invoke(prompt)
205
+ if hasattr(response, "content"):
206
+ categorization = response.content.strip().strip('"')
207
+ else:
208
+ categorization = str(response).strip().strip('"')
209
+ else:
210
+ categorization = str(llm(prompt)).strip().strip('"')
211
+
212
+ # Log the categorization process
213
+ self.status = f"LLM response: '{categorization}'"
214
+
215
+ # Find matching category based on LLM response
216
+ for i, category in enumerate(categories):
217
+ route_category = category.get("route_category", "")
218
+
219
+ # Log each comparison attempt
220
+ self.status = (
221
+ f"Comparing '{categorization}' with category {i + 1}: route_category='{route_category}'"
222
+ )
223
+
224
+ # Case-insensitive match
225
+ if categorization.lower() == route_category.lower():
226
+ matched_category = i
227
+ self.status = f"MATCH FOUND! Category {i + 1} matched with '{categorization}'"
228
+ break
229
+
230
+ if matched_category is None:
231
+ self.status = (
232
+ f"No match found for '{categorization}'. Available categories: "
233
+ f"{[category.get('route_category', '') for category in categories]}"
234
+ )
235
+
236
+ except RuntimeError as e:
237
+ self.status = f"Error in LLM categorization: {e!s}"
238
+ else:
239
+ self.status = "No LLM provided for categorization"
240
+
241
+ if matched_category is not None:
242
+ # Store the matched category for other outputs to check
243
+ self._matched_category = matched_category
244
+
245
+ # Stop all category outputs except the matched one
246
+ for i in range(len(categories)):
247
+ if i != matched_category:
248
+ self.stop(f"category_{i + 1}_result")
249
+
250
+ # Also stop the default output (if it exists)
251
+ enable_else = getattr(self, "enable_else_output", False)
252
+ if enable_else:
253
+ self.stop("default_result")
254
+
255
+ route_category = categories[matched_category].get("route_category", f"Category {matched_category + 1}")
256
+ self.status = f"Categorized as {route_category}"
257
+
258
+ # Check if there's an override output (takes precedence over everything)
259
+ override_output = getattr(self, "message", None)
260
+ if (
261
+ override_output
262
+ and hasattr(override_output, "text")
263
+ and override_output.text
264
+ and str(override_output.text).strip()
265
+ ):
266
+ return Message(text=str(override_output.text))
267
+ if override_output and isinstance(override_output, str) and override_output.strip():
268
+ return Message(text=str(override_output))
269
+
270
+ # Check if there's a custom output value for this category
271
+ custom_output = categories[matched_category].get("output_value", "")
272
+ # Treat None, empty string, or whitespace as blank
273
+ if custom_output and str(custom_output).strip() and str(custom_output).strip().lower() != "none":
274
+ # Use custom output value
275
+ return Message(text=str(custom_output))
276
+ # Use input as default output
277
+ return Message(text=input_text)
278
+ # No match found, stop all category outputs
279
+ for i in range(len(categories)):
280
+ self.stop(f"category_{i + 1}_result")
281
+
282
+ # Check if else output is enabled
283
+ enable_else = getattr(self, "enable_else_output", False)
284
+ if enable_else:
285
+ # The default_response will handle the else case
286
+ self.stop("process_case")
287
+ return Message(text="")
288
+ # No else output, so no output at all
289
+ self.status = "No match found and Else output is disabled"
290
+ return Message(text="")
291
+
292
+ def default_response(self) -> Message:
293
+ """Handle the else case when no conditions match."""
294
+ # Check if else output is enabled
295
+ enable_else = getattr(self, "enable_else_output", False)
296
+ if not enable_else:
297
+ self.status = "Else output is disabled"
298
+ return Message(text="")
299
+
300
+ # Clear any previous match state if not already set
301
+ if not hasattr(self, "_matched_category"):
302
+ self._matched_category = None
303
+
304
+ categories = getattr(self, "routes", [])
305
+ input_text = getattr(self, "input_text", "")
306
+
307
+ # Check if a match was already found in process_case
308
+ if hasattr(self, "_matched_category") and self._matched_category is not None:
309
+ self.status = (
310
+ f"Match already found in process_case (Category {self._matched_category + 1}), "
311
+ "stopping default_response"
312
+ )
313
+ self.stop("default_result")
314
+ return Message(text="")
315
+
316
+ # Check if any category matches using LLM categorization
317
+ has_match = False
318
+ llm = getattr(self, "llm", None)
319
+
320
+ if llm and categories:
321
+ try:
322
+ # Create prompt for categorization
323
+ category_info = []
324
+ for i, category in enumerate(categories):
325
+ cat_name = category.get("route_category", f"Category {i + 1}")
326
+ cat_desc = category.get("route_description", "")
327
+ if cat_desc and cat_desc.strip():
328
+ category_info.append(f'"{cat_name}": {cat_desc}')
329
+ else:
330
+ category_info.append(f'"{cat_name}"')
331
+
332
+ categories_text = "\n".join([f"- {info}" for info in category_info if info])
333
+
334
+ # Create base prompt
335
+ base_prompt = (
336
+ "You are a text classifier. Given the following text and categories, "
337
+ "determine which category best matches the text.\n\n"
338
+ f'Text to classify: "{input_text}"\n\n'
339
+ f"Available categories:\n{categories_text}\n\n"
340
+ "Respond with ONLY the exact category name that best matches the text. "
341
+ 'If none match well, respond with "NONE".\n\n'
342
+ "Category:"
343
+ )
344
+
345
+ # Use custom prompt as additional instructions if provided
346
+ custom_prompt = getattr(self, "custom_prompt", "")
347
+ if custom_prompt and custom_prompt.strip():
348
+ self.status = "Using custom prompt as additional instructions (default check)"
349
+ # Format custom prompt with variables
350
+ # For the routes variable, create a simpler format for custom prompt usage
351
+ simple_routes = ", ".join(
352
+ [f'"{cat.get("route_category", f"Category {i + 1}")}"' for i, cat in enumerate(categories)]
353
+ )
354
+ formatted_custom = custom_prompt.format(input_text=input_text, routes=simple_routes)
355
+ # Combine base prompt with custom instructions
356
+ prompt = f"{base_prompt}\n\nAdditional Instructions:\n{formatted_custom}"
357
+ else:
358
+ self.status = "Using default prompt for LLM categorization (default check)"
359
+ prompt = base_prompt
360
+
361
+ # Log the final prompt being sent to LLM for default check
362
+ self.status = f"Default check - Prompt sent to LLM:\n{prompt}"
363
+
364
+ # Use the LLM to categorize
365
+ if hasattr(llm, "invoke"):
366
+ response = llm.invoke(prompt)
367
+ if hasattr(response, "content"):
368
+ categorization = response.content.strip().strip('"')
369
+ else:
370
+ categorization = str(response).strip().strip('"')
371
+ else:
372
+ categorization = str(llm(prompt)).strip().strip('"')
373
+
374
+ # Log the categorization process for default check
375
+ self.status = f"Default check - LLM response: '{categorization}'"
376
+
377
+ # Check if LLM response matches any category
378
+ for i, category in enumerate(categories):
379
+ route_category = category.get("route_category", "")
380
+
381
+ # Log each comparison attempt
382
+ self.status = (
383
+ f"Default check - Comparing '{categorization}' with category {i + 1}: "
384
+ f"route_category='{route_category}'"
385
+ )
386
+
387
+ if categorization.lower() == route_category.lower():
388
+ has_match = True
389
+ self.status = f"Default check - MATCH FOUND! Category {i + 1} matched with '{categorization}'"
390
+ break
391
+
392
+ if not has_match:
393
+ self.status = (
394
+ f"Default check - No match found for '{categorization}'. "
395
+ f"Available categories: "
396
+ f"{[category.get('route_category', '') for category in categories]}"
397
+ )
398
+
399
+ except RuntimeError:
400
+ pass # If there's an error, treat as no match
401
+
402
+ if has_match:
403
+ # A case matches, stop this output
404
+ self.stop("default_result")
405
+ return Message(text="")
406
+
407
+ # No case matches, check for override output first, then use input as default
408
+ override_output = getattr(self, "message", None)
409
+ if (
410
+ override_output
411
+ and hasattr(override_output, "text")
412
+ and override_output.text
413
+ and str(override_output.text).strip()
414
+ ):
415
+ self.status = "Routed to Else (no match) - using override output"
416
+ return Message(text=str(override_output.text))
417
+ if override_output and isinstance(override_output, str) and override_output.strip():
418
+ self.status = "Routed to Else (no match) - using override output"
419
+ return Message(text=str(override_output))
420
+ self.status = "Routed to Else (no match) - using input as default"
421
+ return Message(text=input_text)