lfx-nightly 0.1.11.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (699) hide show
  1. lfx/__init__.py +0 -0
  2. lfx/__main__.py +25 -0
  3. lfx/base/__init__.py +0 -0
  4. lfx/base/agents/__init__.py +0 -0
  5. lfx/base/agents/agent.py +268 -0
  6. lfx/base/agents/callback.py +130 -0
  7. lfx/base/agents/context.py +109 -0
  8. lfx/base/agents/crewai/__init__.py +0 -0
  9. lfx/base/agents/crewai/crew.py +231 -0
  10. lfx/base/agents/crewai/tasks.py +12 -0
  11. lfx/base/agents/default_prompts.py +23 -0
  12. lfx/base/agents/errors.py +15 -0
  13. lfx/base/agents/events.py +346 -0
  14. lfx/base/agents/utils.py +205 -0
  15. lfx/base/astra_assistants/__init__.py +0 -0
  16. lfx/base/astra_assistants/util.py +171 -0
  17. lfx/base/chains/__init__.py +0 -0
  18. lfx/base/chains/model.py +19 -0
  19. lfx/base/composio/__init__.py +0 -0
  20. lfx/base/composio/composio_base.py +1291 -0
  21. lfx/base/compressors/__init__.py +0 -0
  22. lfx/base/compressors/model.py +60 -0
  23. lfx/base/constants.py +46 -0
  24. lfx/base/curl/__init__.py +0 -0
  25. lfx/base/curl/parse.py +188 -0
  26. lfx/base/data/__init__.py +5 -0
  27. lfx/base/data/base_file.py +685 -0
  28. lfx/base/data/docling_utils.py +245 -0
  29. lfx/base/data/utils.py +198 -0
  30. lfx/base/document_transformers/__init__.py +0 -0
  31. lfx/base/document_transformers/model.py +43 -0
  32. lfx/base/embeddings/__init__.py +0 -0
  33. lfx/base/embeddings/aiml_embeddings.py +62 -0
  34. lfx/base/embeddings/model.py +26 -0
  35. lfx/base/flow_processing/__init__.py +0 -0
  36. lfx/base/flow_processing/utils.py +86 -0
  37. lfx/base/huggingface/__init__.py +0 -0
  38. lfx/base/huggingface/model_bridge.py +133 -0
  39. lfx/base/io/__init__.py +0 -0
  40. lfx/base/io/chat.py +20 -0
  41. lfx/base/io/text.py +22 -0
  42. lfx/base/langchain_utilities/__init__.py +0 -0
  43. lfx/base/langchain_utilities/model.py +35 -0
  44. lfx/base/langchain_utilities/spider_constants.py +1 -0
  45. lfx/base/langwatch/__init__.py +0 -0
  46. lfx/base/langwatch/utils.py +18 -0
  47. lfx/base/mcp/__init__.py +0 -0
  48. lfx/base/mcp/constants.py +2 -0
  49. lfx/base/mcp/util.py +1398 -0
  50. lfx/base/memory/__init__.py +0 -0
  51. lfx/base/memory/memory.py +49 -0
  52. lfx/base/memory/model.py +38 -0
  53. lfx/base/models/__init__.py +3 -0
  54. lfx/base/models/aiml_constants.py +51 -0
  55. lfx/base/models/anthropic_constants.py +47 -0
  56. lfx/base/models/aws_constants.py +151 -0
  57. lfx/base/models/chat_result.py +76 -0
  58. lfx/base/models/google_generative_ai_constants.py +70 -0
  59. lfx/base/models/groq_constants.py +134 -0
  60. lfx/base/models/model.py +375 -0
  61. lfx/base/models/model_input_constants.py +307 -0
  62. lfx/base/models/model_metadata.py +41 -0
  63. lfx/base/models/model_utils.py +8 -0
  64. lfx/base/models/novita_constants.py +35 -0
  65. lfx/base/models/ollama_constants.py +49 -0
  66. lfx/base/models/openai_constants.py +122 -0
  67. lfx/base/models/sambanova_constants.py +18 -0
  68. lfx/base/processing/__init__.py +0 -0
  69. lfx/base/prompts/__init__.py +0 -0
  70. lfx/base/prompts/api_utils.py +224 -0
  71. lfx/base/prompts/utils.py +61 -0
  72. lfx/base/textsplitters/__init__.py +0 -0
  73. lfx/base/textsplitters/model.py +28 -0
  74. lfx/base/tools/__init__.py +0 -0
  75. lfx/base/tools/base.py +26 -0
  76. lfx/base/tools/component_tool.py +325 -0
  77. lfx/base/tools/constants.py +49 -0
  78. lfx/base/tools/flow_tool.py +132 -0
  79. lfx/base/tools/run_flow.py +224 -0
  80. lfx/base/vectorstores/__init__.py +0 -0
  81. lfx/base/vectorstores/model.py +193 -0
  82. lfx/base/vectorstores/utils.py +22 -0
  83. lfx/base/vectorstores/vector_store_connection_decorator.py +52 -0
  84. lfx/cli/__init__.py +5 -0
  85. lfx/cli/commands.py +319 -0
  86. lfx/cli/common.py +650 -0
  87. lfx/cli/run.py +441 -0
  88. lfx/cli/script_loader.py +247 -0
  89. lfx/cli/serve_app.py +546 -0
  90. lfx/cli/validation.py +69 -0
  91. lfx/components/FAISS/__init__.py +34 -0
  92. lfx/components/FAISS/faiss.py +111 -0
  93. lfx/components/Notion/__init__.py +19 -0
  94. lfx/components/Notion/add_content_to_page.py +269 -0
  95. lfx/components/Notion/create_page.py +94 -0
  96. lfx/components/Notion/list_database_properties.py +68 -0
  97. lfx/components/Notion/list_pages.py +122 -0
  98. lfx/components/Notion/list_users.py +77 -0
  99. lfx/components/Notion/page_content_viewer.py +93 -0
  100. lfx/components/Notion/search.py +111 -0
  101. lfx/components/Notion/update_page_property.py +114 -0
  102. lfx/components/__init__.py +411 -0
  103. lfx/components/_importing.py +42 -0
  104. lfx/components/agentql/__init__.py +3 -0
  105. lfx/components/agentql/agentql_api.py +151 -0
  106. lfx/components/agents/__init__.py +34 -0
  107. lfx/components/agents/agent.py +558 -0
  108. lfx/components/agents/mcp_component.py +501 -0
  109. lfx/components/aiml/__init__.py +37 -0
  110. lfx/components/aiml/aiml.py +112 -0
  111. lfx/components/aiml/aiml_embeddings.py +37 -0
  112. lfx/components/amazon/__init__.py +36 -0
  113. lfx/components/amazon/amazon_bedrock_embedding.py +109 -0
  114. lfx/components/amazon/amazon_bedrock_model.py +124 -0
  115. lfx/components/amazon/s3_bucket_uploader.py +211 -0
  116. lfx/components/anthropic/__init__.py +34 -0
  117. lfx/components/anthropic/anthropic.py +187 -0
  118. lfx/components/apify/__init__.py +5 -0
  119. lfx/components/apify/apify_actor.py +325 -0
  120. lfx/components/arxiv/__init__.py +3 -0
  121. lfx/components/arxiv/arxiv.py +163 -0
  122. lfx/components/assemblyai/__init__.py +46 -0
  123. lfx/components/assemblyai/assemblyai_get_subtitles.py +83 -0
  124. lfx/components/assemblyai/assemblyai_lemur.py +183 -0
  125. lfx/components/assemblyai/assemblyai_list_transcripts.py +95 -0
  126. lfx/components/assemblyai/assemblyai_poll_transcript.py +72 -0
  127. lfx/components/assemblyai/assemblyai_start_transcript.py +188 -0
  128. lfx/components/azure/__init__.py +37 -0
  129. lfx/components/azure/azure_openai.py +95 -0
  130. lfx/components/azure/azure_openai_embeddings.py +83 -0
  131. lfx/components/baidu/__init__.py +32 -0
  132. lfx/components/baidu/baidu_qianfan_chat.py +113 -0
  133. lfx/components/bing/__init__.py +3 -0
  134. lfx/components/bing/bing_search_api.py +61 -0
  135. lfx/components/cassandra/__init__.py +40 -0
  136. lfx/components/cassandra/cassandra.py +264 -0
  137. lfx/components/cassandra/cassandra_chat.py +92 -0
  138. lfx/components/cassandra/cassandra_graph.py +238 -0
  139. lfx/components/chains/__init__.py +3 -0
  140. lfx/components/chroma/__init__.py +34 -0
  141. lfx/components/chroma/chroma.py +167 -0
  142. lfx/components/cleanlab/__init__.py +40 -0
  143. lfx/components/cleanlab/cleanlab_evaluator.py +155 -0
  144. lfx/components/cleanlab/cleanlab_rag_evaluator.py +254 -0
  145. lfx/components/cleanlab/cleanlab_remediator.py +131 -0
  146. lfx/components/clickhouse/__init__.py +34 -0
  147. lfx/components/clickhouse/clickhouse.py +135 -0
  148. lfx/components/cloudflare/__init__.py +32 -0
  149. lfx/components/cloudflare/cloudflare.py +81 -0
  150. lfx/components/cohere/__init__.py +40 -0
  151. lfx/components/cohere/cohere_embeddings.py +81 -0
  152. lfx/components/cohere/cohere_models.py +46 -0
  153. lfx/components/cohere/cohere_rerank.py +51 -0
  154. lfx/components/composio/__init__.py +74 -0
  155. lfx/components/composio/composio_api.py +268 -0
  156. lfx/components/composio/dropbox_compnent.py +11 -0
  157. lfx/components/composio/github_composio.py +11 -0
  158. lfx/components/composio/gmail_composio.py +38 -0
  159. lfx/components/composio/googlecalendar_composio.py +11 -0
  160. lfx/components/composio/googlemeet_composio.py +11 -0
  161. lfx/components/composio/googletasks_composio.py +8 -0
  162. lfx/components/composio/linear_composio.py +11 -0
  163. lfx/components/composio/outlook_composio.py +11 -0
  164. lfx/components/composio/reddit_composio.py +11 -0
  165. lfx/components/composio/slack_composio.py +582 -0
  166. lfx/components/composio/slackbot_composio.py +11 -0
  167. lfx/components/composio/supabase_composio.py +11 -0
  168. lfx/components/composio/todoist_composio.py +11 -0
  169. lfx/components/composio/youtube_composio.py +11 -0
  170. lfx/components/confluence/__init__.py +3 -0
  171. lfx/components/confluence/confluence.py +84 -0
  172. lfx/components/couchbase/__init__.py +34 -0
  173. lfx/components/couchbase/couchbase.py +102 -0
  174. lfx/components/crewai/__init__.py +49 -0
  175. lfx/components/crewai/crewai.py +107 -0
  176. lfx/components/crewai/hierarchical_crew.py +46 -0
  177. lfx/components/crewai/hierarchical_task.py +44 -0
  178. lfx/components/crewai/sequential_crew.py +52 -0
  179. lfx/components/crewai/sequential_task.py +73 -0
  180. lfx/components/crewai/sequential_task_agent.py +143 -0
  181. lfx/components/custom_component/__init__.py +34 -0
  182. lfx/components/custom_component/custom_component.py +31 -0
  183. lfx/components/data/__init__.py +64 -0
  184. lfx/components/data/api_request.py +544 -0
  185. lfx/components/data/csv_to_data.py +95 -0
  186. lfx/components/data/directory.py +113 -0
  187. lfx/components/data/file.py +577 -0
  188. lfx/components/data/json_to_data.py +98 -0
  189. lfx/components/data/news_search.py +164 -0
  190. lfx/components/data/rss.py +69 -0
  191. lfx/components/data/sql_executor.py +101 -0
  192. lfx/components/data/url.py +311 -0
  193. lfx/components/data/web_search.py +112 -0
  194. lfx/components/data/webhook.py +56 -0
  195. lfx/components/datastax/__init__.py +70 -0
  196. lfx/components/datastax/astra_assistant_manager.py +306 -0
  197. lfx/components/datastax/astra_db.py +75 -0
  198. lfx/components/datastax/astra_vectorize.py +124 -0
  199. lfx/components/datastax/astradb.py +1285 -0
  200. lfx/components/datastax/astradb_cql.py +314 -0
  201. lfx/components/datastax/astradb_graph.py +330 -0
  202. lfx/components/datastax/astradb_tool.py +414 -0
  203. lfx/components/datastax/astradb_vectorstore.py +1285 -0
  204. lfx/components/datastax/cassandra.py +92 -0
  205. lfx/components/datastax/create_assistant.py +58 -0
  206. lfx/components/datastax/create_thread.py +32 -0
  207. lfx/components/datastax/dotenv.py +35 -0
  208. lfx/components/datastax/get_assistant.py +37 -0
  209. lfx/components/datastax/getenvvar.py +30 -0
  210. lfx/components/datastax/graph_rag.py +141 -0
  211. lfx/components/datastax/hcd.py +314 -0
  212. lfx/components/datastax/list_assistants.py +25 -0
  213. lfx/components/datastax/run.py +89 -0
  214. lfx/components/deactivated/__init__.py +15 -0
  215. lfx/components/deactivated/amazon_kendra.py +66 -0
  216. lfx/components/deactivated/chat_litellm_model.py +158 -0
  217. lfx/components/deactivated/code_block_extractor.py +26 -0
  218. lfx/components/deactivated/documents_to_data.py +22 -0
  219. lfx/components/deactivated/embed.py +16 -0
  220. lfx/components/deactivated/extract_key_from_data.py +46 -0
  221. lfx/components/deactivated/json_document_builder.py +57 -0
  222. lfx/components/deactivated/list_flows.py +20 -0
  223. lfx/components/deactivated/mcp_sse.py +61 -0
  224. lfx/components/deactivated/mcp_stdio.py +62 -0
  225. lfx/components/deactivated/merge_data.py +93 -0
  226. lfx/components/deactivated/message.py +37 -0
  227. lfx/components/deactivated/metal.py +54 -0
  228. lfx/components/deactivated/multi_query.py +59 -0
  229. lfx/components/deactivated/retriever.py +43 -0
  230. lfx/components/deactivated/selective_passthrough.py +77 -0
  231. lfx/components/deactivated/should_run_next.py +40 -0
  232. lfx/components/deactivated/split_text.py +63 -0
  233. lfx/components/deactivated/store_message.py +24 -0
  234. lfx/components/deactivated/sub_flow.py +124 -0
  235. lfx/components/deactivated/vectara_self_query.py +76 -0
  236. lfx/components/deactivated/vector_store.py +24 -0
  237. lfx/components/deepseek/__init__.py +34 -0
  238. lfx/components/deepseek/deepseek.py +136 -0
  239. lfx/components/docling/__init__.py +43 -0
  240. lfx/components/docling/chunk_docling_document.py +186 -0
  241. lfx/components/docling/docling_inline.py +231 -0
  242. lfx/components/docling/docling_remote.py +193 -0
  243. lfx/components/docling/export_docling_document.py +117 -0
  244. lfx/components/documentloaders/__init__.py +3 -0
  245. lfx/components/duckduckgo/__init__.py +3 -0
  246. lfx/components/duckduckgo/duck_duck_go_search_run.py +92 -0
  247. lfx/components/elastic/__init__.py +37 -0
  248. lfx/components/elastic/elasticsearch.py +267 -0
  249. lfx/components/elastic/opensearch.py +243 -0
  250. lfx/components/embeddings/__init__.py +37 -0
  251. lfx/components/embeddings/similarity.py +76 -0
  252. lfx/components/embeddings/text_embedder.py +64 -0
  253. lfx/components/exa/__init__.py +3 -0
  254. lfx/components/exa/exa_search.py +68 -0
  255. lfx/components/firecrawl/__init__.py +43 -0
  256. lfx/components/firecrawl/firecrawl_crawl_api.py +88 -0
  257. lfx/components/firecrawl/firecrawl_extract_api.py +136 -0
  258. lfx/components/firecrawl/firecrawl_map_api.py +89 -0
  259. lfx/components/firecrawl/firecrawl_scrape_api.py +73 -0
  260. lfx/components/git/__init__.py +4 -0
  261. lfx/components/git/git.py +262 -0
  262. lfx/components/git/gitextractor.py +196 -0
  263. lfx/components/glean/__init__.py +3 -0
  264. lfx/components/glean/glean_search_api.py +173 -0
  265. lfx/components/google/__init__.py +17 -0
  266. lfx/components/google/gmail.py +192 -0
  267. lfx/components/google/google_bq_sql_executor.py +157 -0
  268. lfx/components/google/google_drive.py +92 -0
  269. lfx/components/google/google_drive_search.py +152 -0
  270. lfx/components/google/google_generative_ai.py +147 -0
  271. lfx/components/google/google_generative_ai_embeddings.py +141 -0
  272. lfx/components/google/google_oauth_token.py +89 -0
  273. lfx/components/google/google_search_api_core.py +68 -0
  274. lfx/components/google/google_serper_api_core.py +74 -0
  275. lfx/components/groq/__init__.py +34 -0
  276. lfx/components/groq/groq.py +136 -0
  277. lfx/components/helpers/__init__.py +52 -0
  278. lfx/components/helpers/calculator_core.py +89 -0
  279. lfx/components/helpers/create_list.py +40 -0
  280. lfx/components/helpers/current_date.py +42 -0
  281. lfx/components/helpers/id_generator.py +42 -0
  282. lfx/components/helpers/memory.py +251 -0
  283. lfx/components/helpers/output_parser.py +45 -0
  284. lfx/components/helpers/store_message.py +90 -0
  285. lfx/components/homeassistant/__init__.py +7 -0
  286. lfx/components/homeassistant/home_assistant_control.py +152 -0
  287. lfx/components/homeassistant/list_home_assistant_states.py +137 -0
  288. lfx/components/huggingface/__init__.py +37 -0
  289. lfx/components/huggingface/huggingface.py +197 -0
  290. lfx/components/huggingface/huggingface_inference_api.py +106 -0
  291. lfx/components/ibm/__init__.py +34 -0
  292. lfx/components/ibm/watsonx.py +203 -0
  293. lfx/components/ibm/watsonx_embeddings.py +135 -0
  294. lfx/components/icosacomputing/__init__.py +5 -0
  295. lfx/components/icosacomputing/combinatorial_reasoner.py +84 -0
  296. lfx/components/input_output/__init__.py +38 -0
  297. lfx/components/input_output/chat.py +120 -0
  298. lfx/components/input_output/chat_output.py +200 -0
  299. lfx/components/input_output/text.py +27 -0
  300. lfx/components/input_output/text_output.py +29 -0
  301. lfx/components/jigsawstack/__init__.py +23 -0
  302. lfx/components/jigsawstack/ai_scrape.py +126 -0
  303. lfx/components/jigsawstack/ai_web_search.py +136 -0
  304. lfx/components/jigsawstack/file_read.py +115 -0
  305. lfx/components/jigsawstack/file_upload.py +94 -0
  306. lfx/components/jigsawstack/image_generation.py +205 -0
  307. lfx/components/jigsawstack/nsfw.py +60 -0
  308. lfx/components/jigsawstack/object_detection.py +124 -0
  309. lfx/components/jigsawstack/sentiment.py +112 -0
  310. lfx/components/jigsawstack/text_to_sql.py +90 -0
  311. lfx/components/jigsawstack/text_translate.py +77 -0
  312. lfx/components/jigsawstack/vocr.py +107 -0
  313. lfx/components/langchain_utilities/__init__.py +109 -0
  314. lfx/components/langchain_utilities/character.py +53 -0
  315. lfx/components/langchain_utilities/conversation.py +59 -0
  316. lfx/components/langchain_utilities/csv_agent.py +107 -0
  317. lfx/components/langchain_utilities/fake_embeddings.py +26 -0
  318. lfx/components/langchain_utilities/html_link_extractor.py +35 -0
  319. lfx/components/langchain_utilities/json_agent.py +45 -0
  320. lfx/components/langchain_utilities/langchain_hub.py +126 -0
  321. lfx/components/langchain_utilities/language_recursive.py +49 -0
  322. lfx/components/langchain_utilities/language_semantic.py +138 -0
  323. lfx/components/langchain_utilities/llm_checker.py +39 -0
  324. lfx/components/langchain_utilities/llm_math.py +42 -0
  325. lfx/components/langchain_utilities/natural_language.py +61 -0
  326. lfx/components/langchain_utilities/openai_tools.py +53 -0
  327. lfx/components/langchain_utilities/openapi.py +48 -0
  328. lfx/components/langchain_utilities/recursive_character.py +60 -0
  329. lfx/components/langchain_utilities/retrieval_qa.py +83 -0
  330. lfx/components/langchain_utilities/runnable_executor.py +137 -0
  331. lfx/components/langchain_utilities/self_query.py +80 -0
  332. lfx/components/langchain_utilities/spider.py +142 -0
  333. lfx/components/langchain_utilities/sql.py +40 -0
  334. lfx/components/langchain_utilities/sql_database.py +35 -0
  335. lfx/components/langchain_utilities/sql_generator.py +78 -0
  336. lfx/components/langchain_utilities/tool_calling.py +59 -0
  337. lfx/components/langchain_utilities/vector_store_info.py +49 -0
  338. lfx/components/langchain_utilities/vector_store_router.py +33 -0
  339. lfx/components/langchain_utilities/xml_agent.py +71 -0
  340. lfx/components/langwatch/__init__.py +3 -0
  341. lfx/components/langwatch/langwatch.py +278 -0
  342. lfx/components/link_extractors/__init__.py +3 -0
  343. lfx/components/lmstudio/__init__.py +34 -0
  344. lfx/components/lmstudio/lmstudioembeddings.py +89 -0
  345. lfx/components/lmstudio/lmstudiomodel.py +129 -0
  346. lfx/components/logic/__init__.py +52 -0
  347. lfx/components/logic/conditional_router.py +171 -0
  348. lfx/components/logic/data_conditional_router.py +125 -0
  349. lfx/components/logic/flow_tool.py +110 -0
  350. lfx/components/logic/listen.py +29 -0
  351. lfx/components/logic/loop.py +125 -0
  352. lfx/components/logic/notify.py +88 -0
  353. lfx/components/logic/pass_message.py +35 -0
  354. lfx/components/logic/run_flow.py +71 -0
  355. lfx/components/logic/sub_flow.py +114 -0
  356. lfx/components/maritalk/__init__.py +32 -0
  357. lfx/components/maritalk/maritalk.py +52 -0
  358. lfx/components/mem0/__init__.py +3 -0
  359. lfx/components/mem0/mem0_chat_memory.py +136 -0
  360. lfx/components/milvus/__init__.py +34 -0
  361. lfx/components/milvus/milvus.py +115 -0
  362. lfx/components/mistral/__init__.py +37 -0
  363. lfx/components/mistral/mistral.py +114 -0
  364. lfx/components/mistral/mistral_embeddings.py +58 -0
  365. lfx/components/models/__init__.py +34 -0
  366. lfx/components/models/embedding_model.py +114 -0
  367. lfx/components/models/language_model.py +144 -0
  368. lfx/components/mongodb/__init__.py +34 -0
  369. lfx/components/mongodb/mongodb_atlas.py +213 -0
  370. lfx/components/needle/__init__.py +3 -0
  371. lfx/components/needle/needle.py +104 -0
  372. lfx/components/notdiamond/__init__.py +34 -0
  373. lfx/components/notdiamond/notdiamond.py +228 -0
  374. lfx/components/novita/__init__.py +32 -0
  375. lfx/components/novita/novita.py +130 -0
  376. lfx/components/nvidia/__init__.py +57 -0
  377. lfx/components/nvidia/nvidia.py +157 -0
  378. lfx/components/nvidia/nvidia_embedding.py +77 -0
  379. lfx/components/nvidia/nvidia_ingest.py +317 -0
  380. lfx/components/nvidia/nvidia_rerank.py +63 -0
  381. lfx/components/nvidia/system_assist.py +65 -0
  382. lfx/components/olivya/__init__.py +3 -0
  383. lfx/components/olivya/olivya.py +116 -0
  384. lfx/components/ollama/__init__.py +37 -0
  385. lfx/components/ollama/ollama.py +330 -0
  386. lfx/components/ollama/ollama_embeddings.py +106 -0
  387. lfx/components/openai/__init__.py +37 -0
  388. lfx/components/openai/openai.py +100 -0
  389. lfx/components/openai/openai_chat_model.py +176 -0
  390. lfx/components/openrouter/__init__.py +32 -0
  391. lfx/components/openrouter/openrouter.py +202 -0
  392. lfx/components/output_parsers/__init__.py +3 -0
  393. lfx/components/perplexity/__init__.py +34 -0
  394. lfx/components/perplexity/perplexity.py +75 -0
  395. lfx/components/pgvector/__init__.py +34 -0
  396. lfx/components/pgvector/pgvector.py +72 -0
  397. lfx/components/pinecone/__init__.py +34 -0
  398. lfx/components/pinecone/pinecone.py +134 -0
  399. lfx/components/processing/__init__.py +117 -0
  400. lfx/components/processing/alter_metadata.py +108 -0
  401. lfx/components/processing/batch_run.py +205 -0
  402. lfx/components/processing/combine_text.py +39 -0
  403. lfx/components/processing/converter.py +159 -0
  404. lfx/components/processing/create_data.py +110 -0
  405. lfx/components/processing/data_operations.py +438 -0
  406. lfx/components/processing/data_to_dataframe.py +70 -0
  407. lfx/components/processing/dataframe_operations.py +313 -0
  408. lfx/components/processing/extract_key.py +53 -0
  409. lfx/components/processing/filter_data.py +42 -0
  410. lfx/components/processing/filter_data_values.py +88 -0
  411. lfx/components/processing/json_cleaner.py +103 -0
  412. lfx/components/processing/lambda_filter.py +154 -0
  413. lfx/components/processing/llm_router.py +499 -0
  414. lfx/components/processing/merge_data.py +90 -0
  415. lfx/components/processing/message_to_data.py +36 -0
  416. lfx/components/processing/parse_data.py +70 -0
  417. lfx/components/processing/parse_dataframe.py +68 -0
  418. lfx/components/processing/parse_json_data.py +90 -0
  419. lfx/components/processing/parser.py +143 -0
  420. lfx/components/processing/prompt.py +67 -0
  421. lfx/components/processing/python_repl_core.py +98 -0
  422. lfx/components/processing/regex.py +82 -0
  423. lfx/components/processing/save_file.py +225 -0
  424. lfx/components/processing/select_data.py +48 -0
  425. lfx/components/processing/split_text.py +141 -0
  426. lfx/components/processing/structured_output.py +202 -0
  427. lfx/components/processing/update_data.py +160 -0
  428. lfx/components/prototypes/__init__.py +34 -0
  429. lfx/components/prototypes/python_function.py +73 -0
  430. lfx/components/qdrant/__init__.py +34 -0
  431. lfx/components/qdrant/qdrant.py +109 -0
  432. lfx/components/redis/__init__.py +37 -0
  433. lfx/components/redis/redis.py +89 -0
  434. lfx/components/redis/redis_chat.py +43 -0
  435. lfx/components/sambanova/__init__.py +32 -0
  436. lfx/components/sambanova/sambanova.py +84 -0
  437. lfx/components/scrapegraph/__init__.py +40 -0
  438. lfx/components/scrapegraph/scrapegraph_markdownify_api.py +64 -0
  439. lfx/components/scrapegraph/scrapegraph_search_api.py +64 -0
  440. lfx/components/scrapegraph/scrapegraph_smart_scraper_api.py +71 -0
  441. lfx/components/searchapi/__init__.py +34 -0
  442. lfx/components/searchapi/search.py +79 -0
  443. lfx/components/serpapi/__init__.py +3 -0
  444. lfx/components/serpapi/serp.py +115 -0
  445. lfx/components/supabase/__init__.py +34 -0
  446. lfx/components/supabase/supabase.py +76 -0
  447. lfx/components/tavily/__init__.py +4 -0
  448. lfx/components/tavily/tavily_extract.py +117 -0
  449. lfx/components/tavily/tavily_search.py +212 -0
  450. lfx/components/textsplitters/__init__.py +3 -0
  451. lfx/components/toolkits/__init__.py +3 -0
  452. lfx/components/tools/__init__.py +72 -0
  453. lfx/components/tools/calculator.py +108 -0
  454. lfx/components/tools/google_search_api.py +45 -0
  455. lfx/components/tools/google_serper_api.py +115 -0
  456. lfx/components/tools/python_code_structured_tool.py +327 -0
  457. lfx/components/tools/python_repl.py +97 -0
  458. lfx/components/tools/search_api.py +87 -0
  459. lfx/components/tools/searxng.py +145 -0
  460. lfx/components/tools/serp_api.py +119 -0
  461. lfx/components/tools/tavily_search_tool.py +344 -0
  462. lfx/components/tools/wikidata_api.py +102 -0
  463. lfx/components/tools/wikipedia_api.py +49 -0
  464. lfx/components/tools/yahoo_finance.py +129 -0
  465. lfx/components/twelvelabs/__init__.py +52 -0
  466. lfx/components/twelvelabs/convert_astra_results.py +84 -0
  467. lfx/components/twelvelabs/pegasus_index.py +311 -0
  468. lfx/components/twelvelabs/split_video.py +291 -0
  469. lfx/components/twelvelabs/text_embeddings.py +57 -0
  470. lfx/components/twelvelabs/twelvelabs_pegasus.py +408 -0
  471. lfx/components/twelvelabs/video_embeddings.py +100 -0
  472. lfx/components/twelvelabs/video_file.py +179 -0
  473. lfx/components/unstructured/__init__.py +3 -0
  474. lfx/components/unstructured/unstructured.py +121 -0
  475. lfx/components/upstash/__init__.py +34 -0
  476. lfx/components/upstash/upstash.py +124 -0
  477. lfx/components/vectara/__init__.py +37 -0
  478. lfx/components/vectara/vectara.py +97 -0
  479. lfx/components/vectara/vectara_rag.py +164 -0
  480. lfx/components/vectorstores/__init__.py +40 -0
  481. lfx/components/vectorstores/astradb.py +1285 -0
  482. lfx/components/vectorstores/astradb_graph.py +319 -0
  483. lfx/components/vectorstores/cassandra.py +264 -0
  484. lfx/components/vectorstores/cassandra_graph.py +238 -0
  485. lfx/components/vectorstores/chroma.py +167 -0
  486. lfx/components/vectorstores/clickhouse.py +135 -0
  487. lfx/components/vectorstores/couchbase.py +102 -0
  488. lfx/components/vectorstores/elasticsearch.py +267 -0
  489. lfx/components/vectorstores/faiss.py +111 -0
  490. lfx/components/vectorstores/graph_rag.py +141 -0
  491. lfx/components/vectorstores/hcd.py +314 -0
  492. lfx/components/vectorstores/local_db.py +261 -0
  493. lfx/components/vectorstores/milvus.py +115 -0
  494. lfx/components/vectorstores/mongodb_atlas.py +213 -0
  495. lfx/components/vectorstores/opensearch.py +243 -0
  496. lfx/components/vectorstores/pgvector.py +72 -0
  497. lfx/components/vectorstores/pinecone.py +134 -0
  498. lfx/components/vectorstores/qdrant.py +109 -0
  499. lfx/components/vectorstores/supabase.py +76 -0
  500. lfx/components/vectorstores/upstash.py +124 -0
  501. lfx/components/vectorstores/vectara.py +97 -0
  502. lfx/components/vectorstores/vectara_rag.py +164 -0
  503. lfx/components/vectorstores/weaviate.py +89 -0
  504. lfx/components/vertexai/__init__.py +37 -0
  505. lfx/components/vertexai/vertexai.py +71 -0
  506. lfx/components/vertexai/vertexai_embeddings.py +67 -0
  507. lfx/components/weaviate/__init__.py +34 -0
  508. lfx/components/weaviate/weaviate.py +89 -0
  509. lfx/components/wikipedia/__init__.py +4 -0
  510. lfx/components/wikipedia/wikidata.py +86 -0
  511. lfx/components/wikipedia/wikipedia.py +53 -0
  512. lfx/components/wolframalpha/__init__.py +3 -0
  513. lfx/components/wolframalpha/wolfram_alpha_api.py +54 -0
  514. lfx/components/xai/__init__.py +32 -0
  515. lfx/components/xai/xai.py +167 -0
  516. lfx/components/yahoosearch/__init__.py +3 -0
  517. lfx/components/yahoosearch/yahoo.py +137 -0
  518. lfx/components/youtube/__init__.py +52 -0
  519. lfx/components/youtube/channel.py +227 -0
  520. lfx/components/youtube/comments.py +231 -0
  521. lfx/components/youtube/playlist.py +33 -0
  522. lfx/components/youtube/search.py +120 -0
  523. lfx/components/youtube/trending.py +285 -0
  524. lfx/components/youtube/video_details.py +263 -0
  525. lfx/components/youtube/youtube_transcripts.py +118 -0
  526. lfx/components/zep/__init__.py +3 -0
  527. lfx/components/zep/zep.py +44 -0
  528. lfx/constants.py +6 -0
  529. lfx/custom/__init__.py +7 -0
  530. lfx/custom/attributes.py +86 -0
  531. lfx/custom/code_parser/__init__.py +3 -0
  532. lfx/custom/code_parser/code_parser.py +361 -0
  533. lfx/custom/custom_component/__init__.py +0 -0
  534. lfx/custom/custom_component/base_component.py +128 -0
  535. lfx/custom/custom_component/component.py +1808 -0
  536. lfx/custom/custom_component/component_with_cache.py +8 -0
  537. lfx/custom/custom_component/custom_component.py +588 -0
  538. lfx/custom/dependency_analyzer.py +165 -0
  539. lfx/custom/directory_reader/__init__.py +3 -0
  540. lfx/custom/directory_reader/directory_reader.py +359 -0
  541. lfx/custom/directory_reader/utils.py +171 -0
  542. lfx/custom/eval.py +12 -0
  543. lfx/custom/schema.py +32 -0
  544. lfx/custom/tree_visitor.py +21 -0
  545. lfx/custom/utils.py +877 -0
  546. lfx/custom/validate.py +488 -0
  547. lfx/events/__init__.py +1 -0
  548. lfx/events/event_manager.py +110 -0
  549. lfx/exceptions/__init__.py +0 -0
  550. lfx/exceptions/component.py +15 -0
  551. lfx/field_typing/__init__.py +91 -0
  552. lfx/field_typing/constants.py +215 -0
  553. lfx/field_typing/range_spec.py +35 -0
  554. lfx/graph/__init__.py +6 -0
  555. lfx/graph/edge/__init__.py +0 -0
  556. lfx/graph/edge/base.py +277 -0
  557. lfx/graph/edge/schema.py +119 -0
  558. lfx/graph/edge/utils.py +0 -0
  559. lfx/graph/graph/__init__.py +0 -0
  560. lfx/graph/graph/ascii.py +202 -0
  561. lfx/graph/graph/base.py +2238 -0
  562. lfx/graph/graph/constants.py +63 -0
  563. lfx/graph/graph/runnable_vertices_manager.py +133 -0
  564. lfx/graph/graph/schema.py +52 -0
  565. lfx/graph/graph/state_model.py +66 -0
  566. lfx/graph/graph/utils.py +1024 -0
  567. lfx/graph/schema.py +75 -0
  568. lfx/graph/state/__init__.py +0 -0
  569. lfx/graph/state/model.py +237 -0
  570. lfx/graph/utils.py +200 -0
  571. lfx/graph/vertex/__init__.py +0 -0
  572. lfx/graph/vertex/base.py +823 -0
  573. lfx/graph/vertex/constants.py +0 -0
  574. lfx/graph/vertex/exceptions.py +4 -0
  575. lfx/graph/vertex/param_handler.py +264 -0
  576. lfx/graph/vertex/schema.py +26 -0
  577. lfx/graph/vertex/utils.py +19 -0
  578. lfx/graph/vertex/vertex_types.py +489 -0
  579. lfx/helpers/__init__.py +1 -0
  580. lfx/helpers/base_model.py +71 -0
  581. lfx/helpers/custom.py +13 -0
  582. lfx/helpers/data.py +167 -0
  583. lfx/helpers/flow.py +194 -0
  584. lfx/inputs/__init__.py +68 -0
  585. lfx/inputs/constants.py +2 -0
  586. lfx/inputs/input_mixin.py +328 -0
  587. lfx/inputs/inputs.py +714 -0
  588. lfx/inputs/validators.py +19 -0
  589. lfx/interface/__init__.py +6 -0
  590. lfx/interface/components.py +489 -0
  591. lfx/interface/importing/__init__.py +5 -0
  592. lfx/interface/importing/utils.py +39 -0
  593. lfx/interface/initialize/__init__.py +3 -0
  594. lfx/interface/initialize/loading.py +224 -0
  595. lfx/interface/listing.py +26 -0
  596. lfx/interface/run.py +16 -0
  597. lfx/interface/utils.py +111 -0
  598. lfx/io/__init__.py +63 -0
  599. lfx/io/schema.py +289 -0
  600. lfx/load/__init__.py +8 -0
  601. lfx/load/load.py +256 -0
  602. lfx/load/utils.py +99 -0
  603. lfx/log/__init__.py +5 -0
  604. lfx/log/logger.py +385 -0
  605. lfx/memory/__init__.py +90 -0
  606. lfx/memory/stubs.py +283 -0
  607. lfx/processing/__init__.py +1 -0
  608. lfx/processing/process.py +238 -0
  609. lfx/processing/utils.py +25 -0
  610. lfx/py.typed +0 -0
  611. lfx/schema/__init__.py +66 -0
  612. lfx/schema/artifact.py +83 -0
  613. lfx/schema/content_block.py +62 -0
  614. lfx/schema/content_types.py +91 -0
  615. lfx/schema/data.py +308 -0
  616. lfx/schema/dataframe.py +210 -0
  617. lfx/schema/dotdict.py +74 -0
  618. lfx/schema/encoders.py +13 -0
  619. lfx/schema/graph.py +47 -0
  620. lfx/schema/image.py +131 -0
  621. lfx/schema/json_schema.py +141 -0
  622. lfx/schema/log.py +61 -0
  623. lfx/schema/message.py +473 -0
  624. lfx/schema/openai_responses_schemas.py +74 -0
  625. lfx/schema/properties.py +41 -0
  626. lfx/schema/schema.py +171 -0
  627. lfx/schema/serialize.py +13 -0
  628. lfx/schema/table.py +140 -0
  629. lfx/schema/validators.py +114 -0
  630. lfx/serialization/__init__.py +5 -0
  631. lfx/serialization/constants.py +2 -0
  632. lfx/serialization/serialization.py +314 -0
  633. lfx/services/__init__.py +23 -0
  634. lfx/services/base.py +28 -0
  635. lfx/services/cache/__init__.py +6 -0
  636. lfx/services/cache/base.py +183 -0
  637. lfx/services/cache/service.py +166 -0
  638. lfx/services/cache/utils.py +169 -0
  639. lfx/services/chat/__init__.py +1 -0
  640. lfx/services/chat/config.py +2 -0
  641. lfx/services/chat/schema.py +10 -0
  642. lfx/services/deps.py +129 -0
  643. lfx/services/factory.py +19 -0
  644. lfx/services/initialize.py +19 -0
  645. lfx/services/interfaces.py +103 -0
  646. lfx/services/manager.py +172 -0
  647. lfx/services/schema.py +20 -0
  648. lfx/services/session.py +82 -0
  649. lfx/services/settings/__init__.py +3 -0
  650. lfx/services/settings/auth.py +130 -0
  651. lfx/services/settings/base.py +539 -0
  652. lfx/services/settings/constants.py +31 -0
  653. lfx/services/settings/factory.py +23 -0
  654. lfx/services/settings/feature_flags.py +12 -0
  655. lfx/services/settings/service.py +35 -0
  656. lfx/services/settings/utils.py +40 -0
  657. lfx/services/shared_component_cache/__init__.py +1 -0
  658. lfx/services/shared_component_cache/factory.py +30 -0
  659. lfx/services/shared_component_cache/service.py +9 -0
  660. lfx/services/storage/__init__.py +5 -0
  661. lfx/services/storage/local.py +155 -0
  662. lfx/services/storage/service.py +54 -0
  663. lfx/services/tracing/__init__.py +1 -0
  664. lfx/services/tracing/service.py +21 -0
  665. lfx/settings.py +6 -0
  666. lfx/template/__init__.py +6 -0
  667. lfx/template/field/__init__.py +0 -0
  668. lfx/template/field/base.py +257 -0
  669. lfx/template/field/prompt.py +15 -0
  670. lfx/template/frontend_node/__init__.py +6 -0
  671. lfx/template/frontend_node/base.py +212 -0
  672. lfx/template/frontend_node/constants.py +65 -0
  673. lfx/template/frontend_node/custom_components.py +79 -0
  674. lfx/template/template/__init__.py +0 -0
  675. lfx/template/template/base.py +100 -0
  676. lfx/template/utils.py +217 -0
  677. lfx/type_extraction/__init__.py +19 -0
  678. lfx/type_extraction/type_extraction.py +75 -0
  679. lfx/type_extraction.py +80 -0
  680. lfx/utils/__init__.py +1 -0
  681. lfx/utils/async_helpers.py +42 -0
  682. lfx/utils/component_utils.py +154 -0
  683. lfx/utils/concurrency.py +60 -0
  684. lfx/utils/connection_string_parser.py +11 -0
  685. lfx/utils/constants.py +205 -0
  686. lfx/utils/data_structure.py +212 -0
  687. lfx/utils/exceptions.py +22 -0
  688. lfx/utils/helpers.py +28 -0
  689. lfx/utils/image.py +73 -0
  690. lfx/utils/lazy_load.py +15 -0
  691. lfx/utils/request_utils.py +18 -0
  692. lfx/utils/schemas.py +139 -0
  693. lfx/utils/util.py +481 -0
  694. lfx/utils/util_strings.py +56 -0
  695. lfx/utils/version.py +24 -0
  696. lfx_nightly-0.1.11.dev0.dist-info/METADATA +293 -0
  697. lfx_nightly-0.1.11.dev0.dist-info/RECORD +699 -0
  698. lfx_nightly-0.1.11.dev0.dist-info/WHEEL +4 -0
  699. lfx_nightly-0.1.11.dev0.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,231 @@
1
+ from collections.abc import Callable
2
+ from typing import Any, cast
3
+
4
+ import litellm
5
+ from pydantic import SecretStr
6
+
7
+ from lfx.custom.custom_component.component import Component
8
+ from lfx.inputs.inputs import HandleInput, InputTypes
9
+ from lfx.io import BoolInput, IntInput, Output
10
+ from lfx.schema.data import Data
11
+ from lfx.schema.message import Message
12
+ from lfx.utils.constants import MESSAGE_SENDER_AI
13
+
14
+
15
+ def _find_api_key(model):
16
+ """Attempts to find the API key attribute for a LangChain LLM model instance using partial matching.
17
+
18
+ Args:
19
+ model: LangChain LLM model instance.
20
+
21
+ Returns:
22
+ The API key if found, otherwise None.
23
+ """
24
+ # Define the possible API key attribute patterns
25
+ key_patterns = ["key", "token"]
26
+
27
+ # Iterate over the model attributes
28
+ for attr in dir(model):
29
+ attr_lower = attr.lower()
30
+
31
+ # Check if the attribute name contains any of the key patterns
32
+ if any(pattern in attr_lower for pattern in key_patterns):
33
+ value = getattr(model, attr, None)
34
+
35
+ # Check if the value is a non-empty string
36
+ if isinstance(value, str):
37
+ return value
38
+ if isinstance(value, SecretStr):
39
+ return value.get_secret_value()
40
+
41
+ return None
42
+
43
+
44
+ def convert_llm(llm: Any, excluded_keys=None):
45
+ """Converts a LangChain LLM object to a CrewAI-compatible LLM object.
46
+
47
+ Args:
48
+ llm: A LangChain LLM object.
49
+ excluded_keys: A set of keys to exclude from the conversion.
50
+
51
+ Returns:
52
+ A CrewAI-compatible LLM object
53
+ """
54
+ try:
55
+ from crewai import LLM
56
+ except ImportError as e:
57
+ msg = "CrewAI is not installed. Please install it with `uv pip install crewai`."
58
+ raise ImportError(msg) from e
59
+
60
+ if not llm:
61
+ return None
62
+
63
+ # Check if this is already an LLM object
64
+ if isinstance(llm, LLM):
65
+ return llm
66
+
67
+ # Check if we should use model_name model, or something else
68
+ if hasattr(llm, "model_name") and llm.model_name:
69
+ model_name = llm.model_name
70
+ elif hasattr(llm, "model") and llm.model:
71
+ model_name = llm.model
72
+ elif hasattr(llm, "deployment_name") and llm.deployment_name:
73
+ model_name = llm.deployment_name
74
+ else:
75
+ msg = "Could not find model name in the LLM object"
76
+ raise ValueError(msg)
77
+
78
+ # Normalize to the LLM model name
79
+ # Remove langchain_ prefix if present
80
+ provider = llm.get_lc_namespace()[0]
81
+ api_base = None
82
+ if provider.startswith("langchain_"):
83
+ provider = provider[10:]
84
+ model_name = f"{provider}/{model_name}"
85
+ elif hasattr(llm, "azure_endpoint"):
86
+ api_base = llm.azure_endpoint
87
+ model_name = f"azure/{model_name}"
88
+
89
+ # Retrieve the API Key from the LLM
90
+ if excluded_keys is None:
91
+ excluded_keys = {"model", "model_name", "_type", "api_key", "azure_deployment"}
92
+
93
+ # Find the API key in the LLM
94
+ api_key = _find_api_key(llm)
95
+
96
+ # Convert Langchain LLM to CrewAI-compatible LLM object
97
+ return LLM(
98
+ model=model_name,
99
+ api_key=api_key,
100
+ api_base=api_base,
101
+ **{k: v for k, v in llm.dict().items() if k not in excluded_keys},
102
+ )
103
+
104
+
105
+ def convert_tools(tools):
106
+ """Converts LangChain tools to CrewAI-compatible tools.
107
+
108
+ Args:
109
+ tools: A LangChain tools list.
110
+
111
+ Returns:
112
+ A CrewAI-compatible tools list.
113
+ """
114
+ try:
115
+ from crewai.tools.base_tool import Tool
116
+ except ImportError as e:
117
+ msg = "CrewAI is not installed. Please install it with `uv pip install crewai`."
118
+ raise ImportError(msg) from e
119
+
120
+ if not tools:
121
+ return []
122
+
123
+ return [Tool.from_langchain(tool) for tool in tools]
124
+
125
+
126
+ class BaseCrewComponent(Component):
127
+ description: str = (
128
+ "Represents a group of agents, defining how they should collaborate and the tasks they should perform."
129
+ )
130
+ icon = "CrewAI"
131
+
132
+ _base_inputs: list[InputTypes] = [
133
+ IntInput(name="verbose", display_name="Verbose", value=0, advanced=True),
134
+ BoolInput(name="memory", display_name="Memory", value=False, advanced=True),
135
+ BoolInput(name="use_cache", display_name="Cache", value=True, advanced=True),
136
+ IntInput(name="max_rpm", display_name="Max RPM", value=100, advanced=True),
137
+ BoolInput(name="share_crew", display_name="Share Crew", value=False, advanced=True),
138
+ HandleInput(
139
+ name="function_calling_llm",
140
+ display_name="Function Calling LLM",
141
+ input_types=["LanguageModel"],
142
+ info="Turns the ReAct CrewAI agent into a function-calling agent",
143
+ required=False,
144
+ advanced=True,
145
+ ),
146
+ ]
147
+
148
+ outputs = [
149
+ Output(display_name="Output", name="output", method="build_output"),
150
+ ]
151
+
152
+ # Model properties to exclude when creating a CrewAI LLM object
153
+ manager_llm = None
154
+
155
+ def task_is_valid(self, task_data: Data, crew_type) -> bool:
156
+ return "task_type" in task_data and task_data.task_type == crew_type
157
+
158
+ def get_tasks_and_agents(self, agents_list=None) -> tuple[list, list]:
159
+ # Allow passing a custom list of agents
160
+ if not agents_list:
161
+ agents_list = self.agents or []
162
+
163
+ # Set all the agents llm attribute to the crewai llm
164
+ for agent in agents_list:
165
+ # Convert Agent LLM and Tools to proper format
166
+ agent.llm = convert_llm(agent.llm)
167
+ agent.tools = convert_tools(agent.tools)
168
+
169
+ return self.tasks, agents_list
170
+
171
+ def get_manager_llm(self):
172
+ if not self.manager_llm:
173
+ return None
174
+
175
+ self.manager_llm = convert_llm(self.manager_llm)
176
+
177
+ return self.manager_llm
178
+
179
+ def build_crew(self):
180
+ msg = "build_crew must be implemented in subclasses"
181
+ raise NotImplementedError(msg)
182
+
183
+ def get_task_callback(
184
+ self,
185
+ ) -> Callable:
186
+ try:
187
+ from crewai.task import TaskOutput
188
+ except ImportError as e:
189
+ msg = "CrewAI is not installed. Please install it with `uv pip install crewai`."
190
+ raise ImportError(msg) from e
191
+
192
+ def task_callback(task_output: TaskOutput) -> None:
193
+ vertex_id = self._vertex.id if self._vertex else self.display_name or self.__class__.__name__
194
+ self.log(task_output.model_dump(), name=f"Task (Agent: {task_output.agent}) - {vertex_id}")
195
+
196
+ return task_callback
197
+
198
+ def get_step_callback(
199
+ self,
200
+ ) -> Callable:
201
+ try:
202
+ from langchain_core.agents import AgentFinish
203
+ except ImportError as e:
204
+ msg = "langchain_core is not installed. Please install it with `uv pip install langchain-core`."
205
+ raise ImportError(msg) from e
206
+
207
+ def step_callback(agent_output) -> None:
208
+ id_ = self._vertex.id if self._vertex else self.display_name
209
+ if isinstance(agent_output, AgentFinish):
210
+ messages = agent_output.messages
211
+ self.log(cast("dict", messages[0].to_json()), name=f"Finish (Agent: {id_})")
212
+ elif isinstance(agent_output, list):
213
+ messages_dict_ = {f"Action {i}": action.messages for i, (action, _) in enumerate(agent_output)}
214
+ # Serialize the messages with to_json() to avoid issues with circular references
215
+ serializable_dict = {k: [m.to_json() for m in v] for k, v in messages_dict_.items()}
216
+ messages_dict = {k: v[0] if len(v) == 1 else v for k, v in serializable_dict.items()}
217
+ self.log(messages_dict, name=f"Step (Agent: {id_})")
218
+
219
+ return step_callback
220
+
221
+ async def build_output(self) -> Message:
222
+ try:
223
+ crew = self.build_crew()
224
+ result = await crew.kickoff_async()
225
+ message = Message(text=result.raw, sender=MESSAGE_SENDER_AI)
226
+ except litellm.exceptions.BadRequestError as e:
227
+ raise ValueError(e) from e
228
+
229
+ self.status = message
230
+
231
+ return message
@@ -0,0 +1,12 @@
1
+ try:
2
+ from crewai import Task
3
+ except ImportError:
4
+ Task = object
5
+
6
+
7
+ class SequentialTask(Task):
8
+ pass
9
+
10
+
11
+ class HierarchicalTask(Task):
12
+ pass
@@ -0,0 +1,23 @@
1
+ XML_AGENT_PROMPT = """You are a helpful assistant. Help the user answer any questions.
2
+
3
+ You have access to the following tools:
4
+
5
+ {tools}
6
+
7
+ In order to use a tool, you can use <tool></tool> and <tool_input></tool_input> tags. You will then get back a response in the form <observation></observation>
8
+ For example, if you have a tool called 'search' that could run a google search, in order to search for the weather in SF you would respond:
9
+
10
+ <tool>search</tool><tool_input>weather in SF</tool_input>
11
+ <observation>64 degrees</observation>
12
+
13
+ When you are done, respond with a final answer between <final_answer></final_answer>. For example:
14
+
15
+ <final_answer>The weather in SF is 64 degrees</final_answer>
16
+
17
+ Begin!
18
+
19
+ Previous Conversation:
20
+ {chat_history}
21
+
22
+ Question: {input}
23
+ {agent_scratchpad}""" # noqa: E501
@@ -0,0 +1,15 @@
1
+ from anthropic import BadRequestError as AnthropicBadRequestError
2
+ from cohere import BadRequestError as CohereBadRequestError
3
+ from httpx import HTTPStatusError
4
+
5
+ from lfx.schema.message import Message
6
+
7
+
8
+ class CustomBadRequestError(AnthropicBadRequestError, CohereBadRequestError, HTTPStatusError):
9
+ def __init__(self, agent_message: Message | None, message: str):
10
+ super().__init__(message)
11
+ self.message = message
12
+ self.agent_message = agent_message
13
+
14
+ def __str__(self):
15
+ return f"{self.message}"
@@ -0,0 +1,346 @@
1
+ # Add helper functions for each event type
2
+ from collections.abc import AsyncIterator
3
+ from time import perf_counter
4
+ from typing import Any, Protocol
5
+
6
+ from langchain_core.agents import AgentFinish
7
+ from langchain_core.messages import AIMessageChunk, BaseMessage
8
+ from typing_extensions import TypedDict
9
+
10
+ from lfx.schema.content_block import ContentBlock
11
+ from lfx.schema.content_types import TextContent, ToolContent
12
+ from lfx.schema.log import SendMessageFunctionType
13
+ from lfx.schema.message import Message
14
+
15
+
16
+ class ExceptionWithMessageError(Exception):
17
+ def __init__(self, agent_message: Message, message: str):
18
+ self.agent_message = agent_message
19
+ super().__init__(message)
20
+ self.message = message
21
+
22
+ def __str__(self):
23
+ return (
24
+ f"Agent message: {self.agent_message.text} \nError: {self.message}."
25
+ if self.agent_message.error or self.agent_message.text
26
+ else f"{self.message}."
27
+ )
28
+
29
+
30
+ class InputDict(TypedDict):
31
+ input: str
32
+ chat_history: list[BaseMessage]
33
+
34
+
35
+ def _build_agent_input_text_content(agent_input_dict: InputDict) -> str:
36
+ final_input = agent_input_dict.get("input", "")
37
+ return f"**Input**: {final_input}"
38
+
39
+
40
+ def _calculate_duration(start_time: float) -> int:
41
+ """Calculate duration in milliseconds from start time to now."""
42
+ # Handle the calculation
43
+ current_time = perf_counter()
44
+ if isinstance(start_time, int):
45
+ # If we got an integer, treat it as milliseconds
46
+ duration = current_time - (start_time / 1000)
47
+ result = int(duration * 1000)
48
+ else:
49
+ # If we got a float, treat it as perf_counter time
50
+ result = int((current_time - start_time) * 1000)
51
+
52
+ return result
53
+
54
+
55
+ async def handle_on_chain_start(
56
+ event: dict[str, Any], agent_message: Message, send_message_method: SendMessageFunctionType, start_time: float
57
+ ) -> tuple[Message, float]:
58
+ # Create content blocks if they don't exist
59
+ if not agent_message.content_blocks:
60
+ agent_message.content_blocks = [ContentBlock(title="Agent Steps", contents=[])]
61
+
62
+ if event["data"].get("input"):
63
+ input_data = event["data"].get("input")
64
+ if isinstance(input_data, dict) and "input" in input_data:
65
+ # Cast the input_data to InputDict
66
+ input_message = input_data.get("input", "")
67
+ if isinstance(input_message, BaseMessage):
68
+ input_message = input_message.text()
69
+ elif not isinstance(input_message, str):
70
+ input_message = str(input_message)
71
+
72
+ input_dict: InputDict = {
73
+ "input": input_message,
74
+ "chat_history": input_data.get("chat_history", []),
75
+ }
76
+ text_content = TextContent(
77
+ type="text",
78
+ text=_build_agent_input_text_content(input_dict),
79
+ duration=_calculate_duration(start_time),
80
+ header={"title": "Input", "icon": "MessageSquare"},
81
+ )
82
+ agent_message.content_blocks[0].contents.append(text_content)
83
+ agent_message = await send_message_method(message=agent_message)
84
+ start_time = perf_counter()
85
+ return agent_message, start_time
86
+
87
+
88
+ def _extract_output_text(output: str | list) -> str:
89
+ if isinstance(output, str):
90
+ return output
91
+ if isinstance(output, list) and len(output) == 0:
92
+ return ""
93
+ if not isinstance(output, list) or len(output) != 1:
94
+ msg = f"Output is not a string or list of dictionaries with 'text' key: {output}"
95
+ raise TypeError(msg)
96
+
97
+ item = output[0]
98
+ if isinstance(item, str):
99
+ return item
100
+ if isinstance(item, dict):
101
+ if "text" in item:
102
+ return item["text"]
103
+ # If the item's type is "tool_use", return an empty string.
104
+ # This likely indicates that "tool_use" outputs are not meant to be displayed as text.
105
+ if item.get("type") == "tool_use":
106
+ return ""
107
+ if isinstance(item, dict):
108
+ if "text" in item:
109
+ return item["text"]
110
+ # If the item's type is "tool_use", return an empty string.
111
+ # This likely indicates that "tool_use" outputs are not meant to be displayed as text.
112
+ if item.get("type") == "tool_use":
113
+ return ""
114
+ # This is a workaround to deal with function calling by Anthropic
115
+ # since the same data comes in the tool_output we don't need to stream it here
116
+ # although it would be nice to
117
+ if "partial_json" in item:
118
+ return ""
119
+ msg = f"Output is not a string or list of dictionaries with 'text' key: {output}"
120
+ raise TypeError(msg)
121
+
122
+
123
+ async def handle_on_chain_end(
124
+ event: dict[str, Any], agent_message: Message, send_message_method: SendMessageFunctionType, start_time: float
125
+ ) -> tuple[Message, float]:
126
+ data_output = event["data"].get("output")
127
+ if data_output and isinstance(data_output, AgentFinish) and data_output.return_values.get("output"):
128
+ output = data_output.return_values.get("output")
129
+
130
+ agent_message.text = _extract_output_text(output)
131
+ agent_message.properties.state = "complete"
132
+ # Add duration to the last content if it exists
133
+ if agent_message.content_blocks:
134
+ duration = _calculate_duration(start_time)
135
+ text_content = TextContent(
136
+ type="text",
137
+ text=agent_message.text,
138
+ duration=duration,
139
+ header={"title": "Output", "icon": "MessageSquare"},
140
+ )
141
+ agent_message.content_blocks[0].contents.append(text_content)
142
+ agent_message = await send_message_method(message=agent_message)
143
+ start_time = perf_counter()
144
+ return agent_message, start_time
145
+
146
+
147
+ async def handle_on_tool_start(
148
+ event: dict[str, Any],
149
+ agent_message: Message,
150
+ tool_blocks_map: dict[str, ToolContent],
151
+ send_message_method: SendMessageFunctionType,
152
+ start_time: float,
153
+ ) -> tuple[Message, float]:
154
+ tool_name = event["name"]
155
+ tool_input = event["data"].get("input")
156
+ run_id = event.get("run_id", "")
157
+ tool_key = f"{tool_name}_{run_id}"
158
+
159
+ # Create content blocks if they don't exist
160
+ if not agent_message.content_blocks:
161
+ agent_message.content_blocks = [ContentBlock(title="Agent Steps", contents=[])]
162
+
163
+ duration = _calculate_duration(start_time)
164
+ new_start_time = perf_counter() # Get new start time for next operation
165
+
166
+ # Create new tool content with the input exactly as received
167
+ tool_content = ToolContent(
168
+ type="tool_use",
169
+ name=tool_name,
170
+ tool_input=tool_input,
171
+ output=None,
172
+ error=None,
173
+ header={"title": f"Accessing **{tool_name}**", "icon": "Hammer"},
174
+ duration=duration, # Store the actual duration
175
+ )
176
+
177
+ # Store in map and append to message
178
+ tool_blocks_map[tool_key] = tool_content
179
+ agent_message.content_blocks[0].contents.append(tool_content)
180
+
181
+ agent_message = await send_message_method(message=agent_message)
182
+ if agent_message.content_blocks and agent_message.content_blocks[0].contents:
183
+ tool_blocks_map[tool_key] = agent_message.content_blocks[0].contents[-1]
184
+ return agent_message, new_start_time
185
+
186
+
187
+ async def handle_on_tool_end(
188
+ event: dict[str, Any],
189
+ agent_message: Message,
190
+ tool_blocks_map: dict[str, ToolContent],
191
+ send_message_method: SendMessageFunctionType,
192
+ start_time: float,
193
+ ) -> tuple[Message, float]:
194
+ run_id = event.get("run_id", "")
195
+ tool_name = event.get("name", "")
196
+ tool_key = f"{tool_name}_{run_id}"
197
+ tool_content = tool_blocks_map.get(tool_key)
198
+
199
+ if tool_content and isinstance(tool_content, ToolContent):
200
+ # Call send_message_method first to get the updated message structure
201
+ agent_message = await send_message_method(message=agent_message)
202
+ new_start_time = perf_counter()
203
+
204
+ # Now find and update the tool content in the current message
205
+ duration = _calculate_duration(start_time)
206
+ tool_key = f"{tool_name}_{run_id}"
207
+
208
+ # Find the corresponding tool content in the updated message
209
+ updated_tool_content = None
210
+ if agent_message.content_blocks and agent_message.content_blocks[0].contents:
211
+ for content in agent_message.content_blocks[0].contents:
212
+ if (
213
+ isinstance(content, ToolContent)
214
+ and content.name == tool_name
215
+ and content.tool_input == tool_content.tool_input
216
+ ):
217
+ updated_tool_content = content
218
+ break
219
+
220
+ # Update the tool content that's actually in the message
221
+ if updated_tool_content:
222
+ updated_tool_content.duration = duration
223
+ updated_tool_content.header = {"title": f"Executed **{updated_tool_content.name}**", "icon": "Hammer"}
224
+ updated_tool_content.output = event["data"].get("output")
225
+
226
+ # Update the map reference
227
+ tool_blocks_map[tool_key] = updated_tool_content
228
+
229
+ return agent_message, new_start_time
230
+ return agent_message, start_time
231
+
232
+
233
+ async def handle_on_tool_error(
234
+ event: dict[str, Any],
235
+ agent_message: Message,
236
+ tool_blocks_map: dict[str, ToolContent],
237
+ send_message_method: SendMessageFunctionType,
238
+ start_time: float,
239
+ ) -> tuple[Message, float]:
240
+ run_id = event.get("run_id", "")
241
+ tool_name = event.get("name", "")
242
+ tool_key = f"{tool_name}_{run_id}"
243
+ tool_content = tool_blocks_map.get(tool_key)
244
+
245
+ if tool_content and isinstance(tool_content, ToolContent):
246
+ tool_content.error = event["data"].get("error", "Unknown error")
247
+ tool_content.duration = _calculate_duration(start_time)
248
+ tool_content.header = {"title": f"Error using **{tool_content.name}**", "icon": "Hammer"}
249
+ agent_message = await send_message_method(message=agent_message)
250
+ start_time = perf_counter()
251
+ return agent_message, start_time
252
+
253
+
254
+ async def handle_on_chain_stream(
255
+ event: dict[str, Any],
256
+ agent_message: Message,
257
+ send_message_method: SendMessageFunctionType,
258
+ start_time: float,
259
+ ) -> tuple[Message, float]:
260
+ data_chunk = event["data"].get("chunk", {})
261
+ if isinstance(data_chunk, dict) and data_chunk.get("output"):
262
+ output = data_chunk.get("output")
263
+ if output and isinstance(output, str | list):
264
+ agent_message.text = _extract_output_text(output)
265
+ agent_message.properties.state = "complete"
266
+ agent_message = await send_message_method(message=agent_message)
267
+ start_time = perf_counter()
268
+ elif isinstance(data_chunk, AIMessageChunk):
269
+ output_text = _extract_output_text(data_chunk.content)
270
+ if output_text and isinstance(agent_message.text, str):
271
+ agent_message.text += output_text
272
+ agent_message.properties.state = "partial"
273
+ agent_message = await send_message_method(message=agent_message)
274
+ if not agent_message.text:
275
+ start_time = perf_counter()
276
+ return agent_message, start_time
277
+
278
+
279
+ class ToolEventHandler(Protocol):
280
+ async def __call__(
281
+ self,
282
+ event: dict[str, Any],
283
+ agent_message: Message,
284
+ tool_blocks_map: dict[str, ContentBlock],
285
+ send_message_method: SendMessageFunctionType,
286
+ start_time: float,
287
+ ) -> tuple[Message, float]: ...
288
+
289
+
290
+ class ChainEventHandler(Protocol):
291
+ async def __call__(
292
+ self,
293
+ event: dict[str, Any],
294
+ agent_message: Message,
295
+ send_message_method: SendMessageFunctionType,
296
+ start_time: float,
297
+ ) -> tuple[Message, float]: ...
298
+
299
+
300
+ EventHandler = ToolEventHandler | ChainEventHandler
301
+
302
+ # Define separate mappings of event types to their respective handler functions
303
+ CHAIN_EVENT_HANDLERS: dict[str, ChainEventHandler] = {
304
+ "on_chain_start": handle_on_chain_start,
305
+ "on_chain_end": handle_on_chain_end,
306
+ "on_chain_stream": handle_on_chain_stream,
307
+ "on_chat_model_stream": handle_on_chain_stream,
308
+ }
309
+
310
+ TOOL_EVENT_HANDLERS: dict[str, ToolEventHandler] = {
311
+ "on_tool_start": handle_on_tool_start,
312
+ "on_tool_end": handle_on_tool_end,
313
+ "on_tool_error": handle_on_tool_error,
314
+ }
315
+
316
+
317
+ async def process_agent_events(
318
+ agent_executor: AsyncIterator[dict[str, Any]],
319
+ agent_message: Message,
320
+ send_message_method: SendMessageFunctionType,
321
+ ) -> Message:
322
+ """Process agent events and return the final output."""
323
+ if isinstance(agent_message.properties, dict):
324
+ agent_message.properties.update({"icon": "Bot", "state": "partial"})
325
+ else:
326
+ agent_message.properties.icon = "Bot"
327
+ agent_message.properties.state = "partial"
328
+ # Store the initial message
329
+ agent_message = await send_message_method(message=agent_message)
330
+ try:
331
+ # Create a mapping of run_ids to tool contents
332
+ tool_blocks_map: dict[str, ToolContent] = {}
333
+ start_time = perf_counter()
334
+ async for event in agent_executor:
335
+ if event["event"] in TOOL_EVENT_HANDLERS:
336
+ tool_handler = TOOL_EVENT_HANDLERS[event["event"]]
337
+ agent_message, start_time = await tool_handler(
338
+ event, agent_message, tool_blocks_map, send_message_method, start_time
339
+ )
340
+ elif event["event"] in CHAIN_EVENT_HANDLERS:
341
+ chain_handler = CHAIN_EVENT_HANDLERS[event["event"]]
342
+ agent_message, start_time = await chain_handler(event, agent_message, send_message_method, start_time)
343
+ agent_message.properties.state = "complete"
344
+ except Exception as e:
345
+ raise ExceptionWithMessageError(agent_message, str(e)) from e
346
+ return await Message.create(**agent_message.model_dump())