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 contextlib import contextmanager
2
+
3
+ import pandas as pd
4
+ from googleapiclient.discovery import build
5
+ from googleapiclient.errors import HttpError
6
+
7
+ from lfx.custom.custom_component.component import Component
8
+ from lfx.inputs.inputs import BoolInput, DropdownInput, IntInput, MessageTextInput, SecretStrInput
9
+ from lfx.schema.dataframe import DataFrame
10
+ from lfx.template.field.base import Output
11
+
12
+
13
+ class YouTubeCommentsComponent(Component):
14
+ """A component that retrieves comments from YouTube videos."""
15
+
16
+ display_name: str = "YouTube Comments"
17
+ description: str = "Retrieves and analyzes comments from YouTube videos."
18
+ icon: str = "YouTube"
19
+
20
+ # Constants
21
+ COMMENTS_DISABLED_STATUS = 403
22
+ NOT_FOUND_STATUS = 404
23
+ API_MAX_RESULTS = 100
24
+
25
+ inputs = [
26
+ MessageTextInput(
27
+ name="video_url",
28
+ display_name="Video URL",
29
+ info="The URL of the YouTube video to get comments from.",
30
+ tool_mode=True,
31
+ required=True,
32
+ ),
33
+ SecretStrInput(
34
+ name="api_key",
35
+ display_name="YouTube API Key",
36
+ info="Your YouTube Data API key.",
37
+ required=True,
38
+ ),
39
+ IntInput(
40
+ name="max_results",
41
+ display_name="Max Results",
42
+ value=20,
43
+ info="The maximum number of comments to return.",
44
+ ),
45
+ DropdownInput(
46
+ name="sort_by",
47
+ display_name="Sort By",
48
+ options=["time", "relevance"],
49
+ value="relevance",
50
+ info="Sort comments by time or relevance.",
51
+ ),
52
+ BoolInput(
53
+ name="include_replies",
54
+ display_name="Include Replies",
55
+ value=False,
56
+ info="Whether to include replies to comments.",
57
+ advanced=True,
58
+ ),
59
+ BoolInput(
60
+ name="include_metrics",
61
+ display_name="Include Metrics",
62
+ value=True,
63
+ info="Include metrics like like count and reply count.",
64
+ advanced=True,
65
+ ),
66
+ ]
67
+
68
+ outputs = [
69
+ Output(name="comments", display_name="Comments", method="get_video_comments"),
70
+ ]
71
+
72
+ def _extract_video_id(self, video_url: str) -> str:
73
+ """Extracts the video ID from a YouTube URL."""
74
+ import re
75
+
76
+ patterns = [
77
+ r"(?:youtube\.com\/watch\?v=|youtu.be\/|youtube.com\/embed\/)([^&\n?#]+)",
78
+ r"youtube.com\/shorts\/([^&\n?#]+)",
79
+ ]
80
+
81
+ for pattern in patterns:
82
+ match = re.search(pattern, video_url)
83
+ if match:
84
+ return match.group(1)
85
+
86
+ return video_url.strip()
87
+
88
+ def _process_reply(self, reply: dict, parent_id: str, *, include_metrics: bool = True) -> dict:
89
+ """Process a single reply comment."""
90
+ reply_snippet = reply["snippet"]
91
+ reply_data = {
92
+ "comment_id": reply["id"],
93
+ "parent_comment_id": parent_id,
94
+ "author": reply_snippet["authorDisplayName"],
95
+ "text": reply_snippet["textDisplay"],
96
+ "published_at": reply_snippet["publishedAt"],
97
+ "is_reply": True,
98
+ }
99
+ if include_metrics:
100
+ reply_data["like_count"] = reply_snippet["likeCount"]
101
+ reply_data["reply_count"] = 0 # Replies can't have replies
102
+
103
+ return reply_data
104
+
105
+ def _process_comment(
106
+ self, item: dict, *, include_metrics: bool = True, include_replies: bool = False
107
+ ) -> list[dict]:
108
+ """Process a single comment thread."""
109
+ comment = item["snippet"]["topLevelComment"]["snippet"]
110
+ comment_id = item["snippet"]["topLevelComment"]["id"]
111
+
112
+ # Basic comment data
113
+ processed_comments = [
114
+ {
115
+ "comment_id": comment_id,
116
+ "parent_comment_id": "", # Empty for top-level comments
117
+ "author": comment["authorDisplayName"],
118
+ "author_channel_url": comment.get("authorChannelUrl", ""),
119
+ "text": comment["textDisplay"],
120
+ "published_at": comment["publishedAt"],
121
+ "updated_at": comment["updatedAt"],
122
+ "is_reply": False,
123
+ }
124
+ ]
125
+
126
+ # Add metrics if requested
127
+ if include_metrics:
128
+ processed_comments[0].update(
129
+ {
130
+ "like_count": comment["likeCount"],
131
+ "reply_count": item["snippet"]["totalReplyCount"],
132
+ }
133
+ )
134
+
135
+ # Add replies if requested
136
+ if include_replies and item["snippet"]["totalReplyCount"] > 0 and "replies" in item:
137
+ for reply in item["replies"]["comments"]:
138
+ reply_data = self._process_reply(reply, parent_id=comment_id, include_metrics=include_metrics)
139
+ processed_comments.append(reply_data)
140
+
141
+ return processed_comments
142
+
143
+ @contextmanager
144
+ def youtube_client(self):
145
+ """Context manager for YouTube API client."""
146
+ client = build("youtube", "v3", developerKey=self.api_key)
147
+ try:
148
+ yield client
149
+ finally:
150
+ client.close()
151
+
152
+ def get_video_comments(self) -> DataFrame:
153
+ """Retrieves comments from a YouTube video and returns as DataFrame."""
154
+ try:
155
+ # Extract video ID from URL
156
+ video_id = self._extract_video_id(self.video_url)
157
+
158
+ # Use context manager for YouTube API client
159
+ with self.youtube_client() as youtube:
160
+ comments_data = []
161
+ results_count = 0
162
+ request = youtube.commentThreads().list(
163
+ part="snippet,replies",
164
+ videoId=video_id,
165
+ maxResults=min(self.API_MAX_RESULTS, self.max_results),
166
+ order=self.sort_by,
167
+ textFormat="plainText",
168
+ )
169
+
170
+ while request and results_count < self.max_results:
171
+ response = request.execute()
172
+
173
+ for item in response.get("items", []):
174
+ if results_count >= self.max_results:
175
+ break
176
+
177
+ comments = self._process_comment(
178
+ item, include_metrics=self.include_metrics, include_replies=self.include_replies
179
+ )
180
+ comments_data.extend(comments)
181
+ results_count += 1
182
+
183
+ # Get the next page if available and needed
184
+ if "nextPageToken" in response and results_count < self.max_results:
185
+ request = youtube.commentThreads().list(
186
+ part="snippet,replies",
187
+ videoId=video_id,
188
+ maxResults=min(self.API_MAX_RESULTS, self.max_results - results_count),
189
+ order=self.sort_by,
190
+ textFormat="plainText",
191
+ pageToken=response["nextPageToken"],
192
+ )
193
+ else:
194
+ request = None
195
+
196
+ # Convert to DataFrame
197
+ comments_df = pd.DataFrame(comments_data)
198
+
199
+ # Add video metadata
200
+ comments_df["video_id"] = video_id
201
+ comments_df["video_url"] = self.video_url
202
+
203
+ # Sort columns for better organization
204
+ column_order = [
205
+ "video_id",
206
+ "video_url",
207
+ "comment_id",
208
+ "parent_comment_id",
209
+ "is_reply",
210
+ "author",
211
+ "author_channel_url",
212
+ "text",
213
+ "published_at",
214
+ "updated_at",
215
+ ]
216
+
217
+ if self.include_metrics:
218
+ column_order.extend(["like_count", "reply_count"])
219
+
220
+ comments_df = comments_df[column_order]
221
+
222
+ return DataFrame(comments_df)
223
+
224
+ except HttpError as e:
225
+ error_message = f"YouTube API error: {e!s}"
226
+ if e.resp.status == self.COMMENTS_DISABLED_STATUS:
227
+ error_message = "Comments are disabled for this video or API quota exceeded."
228
+ elif e.resp.status == self.NOT_FOUND_STATUS:
229
+ error_message = "Video not found."
230
+
231
+ return DataFrame(pd.DataFrame({"error": [error_message]}))
@@ -0,0 +1,33 @@
1
+ from pytube import Playlist # Ensure you have pytube installed
2
+
3
+ from lfx.custom.custom_component.component import Component
4
+ from lfx.inputs.inputs import MessageTextInput
5
+ from lfx.schema.data import Data
6
+ from lfx.schema.dataframe import DataFrame
7
+ from lfx.template.field.base import Output
8
+
9
+
10
+ class YouTubePlaylistComponent(Component):
11
+ display_name = "YouTube Playlist"
12
+ description = "Extracts all video URLs from a YouTube playlist."
13
+ icon = "YouTube" # Replace with a suitable icon
14
+
15
+ inputs = [
16
+ MessageTextInput(
17
+ name="playlist_url",
18
+ display_name="Playlist URL",
19
+ info="URL of the YouTube playlist.",
20
+ required=True,
21
+ ),
22
+ ]
23
+
24
+ outputs = [
25
+ Output(display_name="Video URLs", name="video_urls", method="extract_video_urls"),
26
+ ]
27
+
28
+ def extract_video_urls(self) -> DataFrame:
29
+ playlist_url = self.playlist_url
30
+ playlist = Playlist(playlist_url)
31
+ video_urls = [video.watch_url for video in playlist.videos]
32
+
33
+ return DataFrame([Data(data={"video_url": url}) for url in video_urls])
@@ -0,0 +1,120 @@
1
+ from contextlib import contextmanager
2
+
3
+ import pandas as pd
4
+ from googleapiclient.discovery import build
5
+ from googleapiclient.errors import HttpError
6
+
7
+ from lfx.custom.custom_component.component import Component
8
+ from lfx.inputs.inputs import BoolInput, DropdownInput, IntInput, MessageTextInput, SecretStrInput
9
+ from lfx.schema.dataframe import DataFrame
10
+ from lfx.template.field.base import Output
11
+
12
+
13
+ class YouTubeSearchComponent(Component):
14
+ """A component that searches YouTube videos."""
15
+
16
+ display_name: str = "YouTube Search"
17
+ description: str = "Searches YouTube videos based on query."
18
+ icon: str = "YouTube"
19
+
20
+ inputs = [
21
+ MessageTextInput(
22
+ name="query",
23
+ display_name="Search Query",
24
+ info="The search query to look for on YouTube.",
25
+ tool_mode=True,
26
+ required=True,
27
+ ),
28
+ SecretStrInput(
29
+ name="api_key",
30
+ display_name="YouTube API Key",
31
+ info="Your YouTube Data API key.",
32
+ required=True,
33
+ ),
34
+ IntInput(
35
+ name="max_results",
36
+ display_name="Max Results",
37
+ value=10,
38
+ info="The maximum number of results to return.",
39
+ ),
40
+ DropdownInput(
41
+ name="order",
42
+ display_name="Sort Order",
43
+ options=["relevance", "date", "rating", "title", "viewCount"],
44
+ value="relevance",
45
+ info="Sort order for the search results.",
46
+ ),
47
+ BoolInput(
48
+ name="include_metadata",
49
+ display_name="Include Metadata",
50
+ value=True,
51
+ info="Include video metadata like description and statistics.",
52
+ advanced=True,
53
+ ),
54
+ ]
55
+
56
+ outputs = [
57
+ Output(name="results", display_name="Search Results", method="search_videos"),
58
+ ]
59
+
60
+ @contextmanager
61
+ def youtube_client(self):
62
+ """Context manager for YouTube API client."""
63
+ client = build("youtube", "v3", developerKey=self.api_key)
64
+ try:
65
+ yield client
66
+ finally:
67
+ client.close()
68
+
69
+ def search_videos(self) -> DataFrame:
70
+ """Searches YouTube videos and returns results as DataFrame."""
71
+ try:
72
+ with self.youtube_client() as youtube:
73
+ search_response = (
74
+ youtube.search()
75
+ .list(
76
+ q=self.query,
77
+ part="id,snippet",
78
+ maxResults=self.max_results,
79
+ order=self.order,
80
+ type="video",
81
+ )
82
+ .execute()
83
+ )
84
+
85
+ results = []
86
+ for search_result in search_response.get("items", []):
87
+ video_id = search_result["id"]["videoId"]
88
+ snippet = search_result["snippet"]
89
+
90
+ result = {
91
+ "video_id": video_id,
92
+ "title": snippet["title"],
93
+ "description": snippet["description"],
94
+ "published_at": snippet["publishedAt"],
95
+ "channel_title": snippet["channelTitle"],
96
+ "thumbnail_url": snippet["thumbnails"]["default"]["url"],
97
+ }
98
+
99
+ if self.include_metadata:
100
+ # Get video details for additional metadata
101
+ video_response = youtube.videos().list(part="statistics,contentDetails", id=video_id).execute()
102
+
103
+ if video_response.get("items"):
104
+ video_details = video_response["items"][0]
105
+ result.update(
106
+ {
107
+ "view_count": int(video_details["statistics"]["viewCount"]),
108
+ "like_count": int(video_details["statistics"].get("likeCount", 0)),
109
+ "comment_count": int(video_details["statistics"].get("commentCount", 0)),
110
+ "duration": video_details["contentDetails"]["duration"],
111
+ }
112
+ )
113
+
114
+ results.append(result)
115
+
116
+ return DataFrame(pd.DataFrame(results))
117
+
118
+ except HttpError as e:
119
+ error_message = f"YouTube API error: {e!s}"
120
+ return DataFrame(pd.DataFrame({"error": [error_message]}))
@@ -0,0 +1,285 @@
1
+ from contextlib import contextmanager
2
+
3
+ import pandas as pd
4
+ from googleapiclient.discovery import build
5
+ from googleapiclient.errors import HttpError
6
+
7
+ from lfx.custom.custom_component.component import Component
8
+ from lfx.inputs.inputs import BoolInput, DropdownInput, IntInput, SecretStrInput
9
+ from lfx.log.logger import logger
10
+ from lfx.schema.dataframe import DataFrame
11
+ from lfx.template.field.base import Output
12
+
13
+ HTTP_FORBIDDEN = 403
14
+ HTTP_NOT_FOUND = 404
15
+ MAX_API_RESULTS = 50
16
+
17
+
18
+ class YouTubeTrendingComponent(Component):
19
+ """A component that retrieves trending videos from YouTube."""
20
+
21
+ display_name: str = "YouTube Trending"
22
+ description: str = "Retrieves trending videos from YouTube with filtering options."
23
+ icon: str = "YouTube"
24
+
25
+ # Dictionary of country codes and names
26
+ COUNTRY_CODES = {
27
+ "Global": "US", # Default to US for global
28
+ "United States": "US",
29
+ "Brazil": "BR",
30
+ "United Kingdom": "GB",
31
+ "India": "IN",
32
+ "Japan": "JP",
33
+ "South Korea": "KR",
34
+ "Germany": "DE",
35
+ "France": "FR",
36
+ "Canada": "CA",
37
+ "Australia": "AU",
38
+ "Spain": "ES",
39
+ "Italy": "IT",
40
+ "Mexico": "MX",
41
+ "Russia": "RU",
42
+ "Netherlands": "NL",
43
+ "Poland": "PL",
44
+ "Argentina": "AR",
45
+ }
46
+
47
+ # Dictionary of video categories
48
+ VIDEO_CATEGORIES = {
49
+ "All": "0",
50
+ "Film & Animation": "1",
51
+ "Autos & Vehicles": "2",
52
+ "Music": "10",
53
+ "Pets & Animals": "15",
54
+ "Sports": "17",
55
+ "Travel & Events": "19",
56
+ "Gaming": "20",
57
+ "People & Blogs": "22",
58
+ "Comedy": "23",
59
+ "Entertainment": "24",
60
+ "News & Politics": "25",
61
+ "Education": "27",
62
+ "Science & Technology": "28",
63
+ "Nonprofits & Activism": "29",
64
+ }
65
+
66
+ inputs = [
67
+ SecretStrInput(
68
+ name="api_key",
69
+ display_name="YouTube API Key",
70
+ info="Your YouTube Data API key.",
71
+ required=True,
72
+ ),
73
+ DropdownInput(
74
+ name="region",
75
+ display_name="Region",
76
+ options=list(COUNTRY_CODES.keys()),
77
+ value="Global",
78
+ info="The region to get trending videos from.",
79
+ ),
80
+ DropdownInput(
81
+ name="category",
82
+ display_name="Category",
83
+ options=list(VIDEO_CATEGORIES.keys()),
84
+ value="All",
85
+ info="The category of videos to retrieve.",
86
+ ),
87
+ IntInput(
88
+ name="max_results",
89
+ display_name="Max Results",
90
+ value=10,
91
+ info="Maximum number of trending videos to return (1-50).",
92
+ ),
93
+ BoolInput(
94
+ name="include_statistics",
95
+ display_name="Include Statistics",
96
+ value=True,
97
+ info="Include video statistics (views, likes, comments).",
98
+ ),
99
+ BoolInput(
100
+ name="include_content_details",
101
+ display_name="Include Content Details",
102
+ value=True,
103
+ info="Include video duration and quality info.",
104
+ advanced=True,
105
+ ),
106
+ BoolInput(
107
+ name="include_thumbnails",
108
+ display_name="Include Thumbnails",
109
+ value=True,
110
+ info="Include video thumbnail URLs.",
111
+ advanced=True,
112
+ ),
113
+ ]
114
+
115
+ outputs = [
116
+ Output(name="trending_videos", display_name="Trending Videos", method="get_trending_videos"),
117
+ ]
118
+
119
+ max_results: int
120
+
121
+ def _format_duration(self, duration: str) -> str:
122
+ """Formats ISO 8601 duration to readable format."""
123
+ import re
124
+
125
+ # Remove 'PT' from the start of duration
126
+ duration = duration[2:]
127
+
128
+ hours = 0
129
+ minutes = 0
130
+ seconds = 0
131
+
132
+ # Extract hours, minutes and seconds
133
+ time_dict = {}
134
+ for time_unit in ["H", "M", "S"]:
135
+ match = re.search(r"(\d+)" + time_unit, duration)
136
+ if match:
137
+ time_dict[time_unit] = int(match.group(1))
138
+
139
+ if "H" in time_dict:
140
+ hours = time_dict["H"]
141
+ if "M" in time_dict:
142
+ minutes = time_dict["M"]
143
+ if "S" in time_dict:
144
+ seconds = time_dict["S"]
145
+
146
+ # Format the time string
147
+ if hours > 0:
148
+ return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
149
+ return f"{minutes:02d}:{seconds:02d}"
150
+
151
+ @contextmanager
152
+ def youtube_client(self):
153
+ """Context manager for YouTube API client."""
154
+ client = build("youtube", "v3", developerKey=self.api_key)
155
+ try:
156
+ yield client
157
+ finally:
158
+ client.close()
159
+
160
+ def get_trending_videos(self) -> DataFrame:
161
+ """Retrieves trending videos from YouTube and returns as DataFrame."""
162
+ try:
163
+ # Validate max_results
164
+ if not 1 <= self.max_results <= MAX_API_RESULTS:
165
+ self.max_results = min(max(1, self.max_results), MAX_API_RESULTS)
166
+
167
+ # Use context manager for YouTube API client
168
+ with self.youtube_client() as youtube:
169
+ # Get country code
170
+ region_code = self.COUNTRY_CODES[self.region]
171
+
172
+ # Prepare API request parts
173
+ parts = ["snippet"]
174
+ if self.include_statistics:
175
+ parts.append("statistics")
176
+ if self.include_content_details:
177
+ parts.append("contentDetails")
178
+
179
+ # Prepare API request parameters
180
+ request_params = {
181
+ "part": ",".join(parts),
182
+ "chart": "mostPopular",
183
+ "regionCode": region_code,
184
+ "maxResults": self.max_results,
185
+ }
186
+
187
+ # Add category filter if not "All"
188
+ if self.category != "All":
189
+ request_params["videoCategoryId"] = self.VIDEO_CATEGORIES[self.category]
190
+
191
+ # Get trending videos
192
+ request = youtube.videos().list(**request_params)
193
+ response = request.execute()
194
+
195
+ videos_data = []
196
+ for item in response.get("items", []):
197
+ video_data = {
198
+ "video_id": item["id"],
199
+ "title": item["snippet"]["title"],
200
+ "description": item["snippet"]["description"],
201
+ "channel_id": item["snippet"]["channelId"],
202
+ "channel_title": item["snippet"]["channelTitle"],
203
+ "published_at": item["snippet"]["publishedAt"],
204
+ "url": f"https://www.youtube.com/watch?v={item['id']}",
205
+ "region": self.region,
206
+ "category": self.category,
207
+ }
208
+
209
+ # Add thumbnails if requested
210
+ if self.include_thumbnails:
211
+ for size, thumb in item["snippet"]["thumbnails"].items():
212
+ video_data[f"thumbnail_{size}_url"] = thumb["url"]
213
+ video_data[f"thumbnail_{size}_width"] = thumb.get("width", 0)
214
+ video_data[f"thumbnail_{size}_height"] = thumb.get("height", 0)
215
+
216
+ # Add statistics if requested
217
+ if self.include_statistics and "statistics" in item:
218
+ video_data.update(
219
+ {
220
+ "view_count": int(item["statistics"].get("viewCount", 0)),
221
+ "like_count": int(item["statistics"].get("likeCount", 0)),
222
+ "comment_count": int(item["statistics"].get("commentCount", 0)),
223
+ }
224
+ )
225
+
226
+ # Add content details if requested
227
+ if self.include_content_details and "contentDetails" in item:
228
+ content_details = item["contentDetails"]
229
+ video_data.update(
230
+ {
231
+ "duration": self._format_duration(content_details["duration"]),
232
+ "definition": content_details.get("definition", "hd").upper(),
233
+ "has_captions": content_details.get("caption", "false") == "true",
234
+ "licensed_content": content_details.get("licensedContent", False),
235
+ "projection": content_details.get("projection", "rectangular"),
236
+ }
237
+ )
238
+
239
+ videos_data.append(video_data)
240
+
241
+ # Convert to DataFrame
242
+ videos_df = pd.DataFrame(videos_data)
243
+
244
+ # Organize columns
245
+ column_order = [
246
+ "video_id",
247
+ "title",
248
+ "channel_id",
249
+ "channel_title",
250
+ "category",
251
+ "region",
252
+ "published_at",
253
+ "url",
254
+ "description",
255
+ ]
256
+
257
+ if self.include_statistics:
258
+ column_order.extend(["view_count", "like_count", "comment_count"])
259
+
260
+ if self.include_content_details:
261
+ column_order.extend(["duration", "definition", "has_captions", "licensed_content", "projection"])
262
+
263
+ # Add thumbnail columns at the end if included
264
+ if self.include_thumbnails:
265
+ thumbnail_cols = [col for col in videos_df.columns if col.startswith("thumbnail_")]
266
+ column_order.extend(sorted(thumbnail_cols))
267
+
268
+ # Reorder columns, including any that might not be in column_order
269
+ remaining_cols = [col for col in videos_df.columns if col not in column_order]
270
+ videos_df = videos_df[column_order + remaining_cols]
271
+
272
+ return DataFrame(videos_df)
273
+
274
+ except HttpError as e:
275
+ error_message = f"YouTube API error: {e}"
276
+ if e.resp.status == HTTP_FORBIDDEN:
277
+ error_message = "API quota exceeded or access forbidden."
278
+ elif e.resp.status == HTTP_NOT_FOUND:
279
+ error_message = "Resource not found."
280
+
281
+ return DataFrame(pd.DataFrame({"error": [error_message]}))
282
+
283
+ except Exception as e: # noqa: BLE001
284
+ logger.exception("An unexpected error occurred:")
285
+ return DataFrame(pd.DataFrame({"error": [str(e)]}))