lfx-nightly 0.2.0.dev25__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of lfx-nightly might be problematic. Click here for more details.
- lfx/__init__.py +0 -0
- lfx/__main__.py +25 -0
- lfx/_assets/component_index.json +1 -0
- lfx/base/__init__.py +0 -0
- lfx/base/agents/__init__.py +0 -0
- lfx/base/agents/agent.py +375 -0
- lfx/base/agents/altk_base_agent.py +380 -0
- lfx/base/agents/altk_tool_wrappers.py +565 -0
- lfx/base/agents/callback.py +130 -0
- lfx/base/agents/context.py +109 -0
- lfx/base/agents/crewai/__init__.py +0 -0
- lfx/base/agents/crewai/crew.py +231 -0
- lfx/base/agents/crewai/tasks.py +12 -0
- lfx/base/agents/default_prompts.py +23 -0
- lfx/base/agents/errors.py +15 -0
- lfx/base/agents/events.py +430 -0
- lfx/base/agents/utils.py +237 -0
- lfx/base/astra_assistants/__init__.py +0 -0
- lfx/base/astra_assistants/util.py +171 -0
- lfx/base/chains/__init__.py +0 -0
- lfx/base/chains/model.py +19 -0
- lfx/base/composio/__init__.py +0 -0
- lfx/base/composio/composio_base.py +2584 -0
- lfx/base/compressors/__init__.py +0 -0
- lfx/base/compressors/model.py +60 -0
- lfx/base/constants.py +46 -0
- lfx/base/curl/__init__.py +0 -0
- lfx/base/curl/parse.py +188 -0
- lfx/base/data/__init__.py +5 -0
- lfx/base/data/base_file.py +810 -0
- lfx/base/data/docling_utils.py +338 -0
- lfx/base/data/storage_utils.py +192 -0
- lfx/base/data/utils.py +362 -0
- lfx/base/datastax/__init__.py +5 -0
- lfx/base/datastax/astradb_base.py +896 -0
- lfx/base/document_transformers/__init__.py +0 -0
- lfx/base/document_transformers/model.py +43 -0
- lfx/base/embeddings/__init__.py +0 -0
- lfx/base/embeddings/aiml_embeddings.py +62 -0
- lfx/base/embeddings/embeddings_class.py +113 -0
- lfx/base/embeddings/model.py +26 -0
- lfx/base/flow_processing/__init__.py +0 -0
- lfx/base/flow_processing/utils.py +86 -0
- lfx/base/huggingface/__init__.py +0 -0
- lfx/base/huggingface/model_bridge.py +133 -0
- lfx/base/io/__init__.py +0 -0
- lfx/base/io/chat.py +21 -0
- lfx/base/io/text.py +22 -0
- lfx/base/knowledge_bases/__init__.py +3 -0
- lfx/base/knowledge_bases/knowledge_base_utils.py +137 -0
- lfx/base/langchain_utilities/__init__.py +0 -0
- lfx/base/langchain_utilities/model.py +35 -0
- lfx/base/langchain_utilities/spider_constants.py +1 -0
- lfx/base/langwatch/__init__.py +0 -0
- lfx/base/langwatch/utils.py +18 -0
- lfx/base/mcp/__init__.py +0 -0
- lfx/base/mcp/constants.py +2 -0
- lfx/base/mcp/util.py +1659 -0
- lfx/base/memory/__init__.py +0 -0
- lfx/base/memory/memory.py +49 -0
- lfx/base/memory/model.py +38 -0
- lfx/base/models/__init__.py +3 -0
- lfx/base/models/aiml_constants.py +51 -0
- lfx/base/models/anthropic_constants.py +51 -0
- lfx/base/models/aws_constants.py +151 -0
- lfx/base/models/chat_result.py +76 -0
- lfx/base/models/cometapi_constants.py +54 -0
- lfx/base/models/google_generative_ai_constants.py +70 -0
- lfx/base/models/google_generative_ai_model.py +38 -0
- lfx/base/models/groq_constants.py +150 -0
- lfx/base/models/groq_model_discovery.py +265 -0
- lfx/base/models/model.py +375 -0
- lfx/base/models/model_input_constants.py +378 -0
- lfx/base/models/model_metadata.py +41 -0
- lfx/base/models/model_utils.py +108 -0
- lfx/base/models/novita_constants.py +35 -0
- lfx/base/models/ollama_constants.py +52 -0
- lfx/base/models/openai_constants.py +129 -0
- lfx/base/models/sambanova_constants.py +18 -0
- lfx/base/models/watsonx_constants.py +36 -0
- lfx/base/processing/__init__.py +0 -0
- lfx/base/prompts/__init__.py +0 -0
- lfx/base/prompts/api_utils.py +224 -0
- lfx/base/prompts/utils.py +61 -0
- lfx/base/textsplitters/__init__.py +0 -0
- lfx/base/textsplitters/model.py +28 -0
- lfx/base/tools/__init__.py +0 -0
- lfx/base/tools/base.py +26 -0
- lfx/base/tools/component_tool.py +325 -0
- lfx/base/tools/constants.py +49 -0
- lfx/base/tools/flow_tool.py +132 -0
- lfx/base/tools/run_flow.py +698 -0
- lfx/base/vectorstores/__init__.py +0 -0
- lfx/base/vectorstores/model.py +193 -0
- lfx/base/vectorstores/utils.py +22 -0
- lfx/base/vectorstores/vector_store_connection_decorator.py +52 -0
- lfx/cli/__init__.py +5 -0
- lfx/cli/commands.py +327 -0
- lfx/cli/common.py +650 -0
- lfx/cli/run.py +506 -0
- lfx/cli/script_loader.py +289 -0
- lfx/cli/serve_app.py +546 -0
- lfx/cli/validation.py +69 -0
- lfx/components/FAISS/__init__.py +34 -0
- lfx/components/FAISS/faiss.py +111 -0
- lfx/components/Notion/__init__.py +19 -0
- lfx/components/Notion/add_content_to_page.py +269 -0
- lfx/components/Notion/create_page.py +94 -0
- lfx/components/Notion/list_database_properties.py +68 -0
- lfx/components/Notion/list_pages.py +122 -0
- lfx/components/Notion/list_users.py +77 -0
- lfx/components/Notion/page_content_viewer.py +93 -0
- lfx/components/Notion/search.py +111 -0
- lfx/components/Notion/update_page_property.py +114 -0
- lfx/components/__init__.py +428 -0
- lfx/components/_importing.py +42 -0
- lfx/components/agentql/__init__.py +3 -0
- lfx/components/agentql/agentql_api.py +151 -0
- lfx/components/aiml/__init__.py +37 -0
- lfx/components/aiml/aiml.py +115 -0
- lfx/components/aiml/aiml_embeddings.py +37 -0
- lfx/components/altk/__init__.py +34 -0
- lfx/components/altk/altk_agent.py +193 -0
- lfx/components/amazon/__init__.py +36 -0
- lfx/components/amazon/amazon_bedrock_converse.py +195 -0
- lfx/components/amazon/amazon_bedrock_embedding.py +109 -0
- lfx/components/amazon/amazon_bedrock_model.py +130 -0
- lfx/components/amazon/s3_bucket_uploader.py +211 -0
- lfx/components/anthropic/__init__.py +34 -0
- lfx/components/anthropic/anthropic.py +187 -0
- lfx/components/apify/__init__.py +5 -0
- lfx/components/apify/apify_actor.py +325 -0
- lfx/components/arxiv/__init__.py +3 -0
- lfx/components/arxiv/arxiv.py +169 -0
- lfx/components/assemblyai/__init__.py +46 -0
- lfx/components/assemblyai/assemblyai_get_subtitles.py +83 -0
- lfx/components/assemblyai/assemblyai_lemur.py +183 -0
- lfx/components/assemblyai/assemblyai_list_transcripts.py +95 -0
- lfx/components/assemblyai/assemblyai_poll_transcript.py +72 -0
- lfx/components/assemblyai/assemblyai_start_transcript.py +188 -0
- lfx/components/azure/__init__.py +37 -0
- lfx/components/azure/azure_openai.py +95 -0
- lfx/components/azure/azure_openai_embeddings.py +83 -0
- lfx/components/baidu/__init__.py +32 -0
- lfx/components/baidu/baidu_qianfan_chat.py +113 -0
- lfx/components/bing/__init__.py +3 -0
- lfx/components/bing/bing_search_api.py +61 -0
- lfx/components/cassandra/__init__.py +40 -0
- lfx/components/cassandra/cassandra.py +264 -0
- lfx/components/cassandra/cassandra_chat.py +92 -0
- lfx/components/cassandra/cassandra_graph.py +238 -0
- lfx/components/chains/__init__.py +3 -0
- lfx/components/chroma/__init__.py +34 -0
- lfx/components/chroma/chroma.py +169 -0
- lfx/components/cleanlab/__init__.py +40 -0
- lfx/components/cleanlab/cleanlab_evaluator.py +155 -0
- lfx/components/cleanlab/cleanlab_rag_evaluator.py +254 -0
- lfx/components/cleanlab/cleanlab_remediator.py +131 -0
- lfx/components/clickhouse/__init__.py +34 -0
- lfx/components/clickhouse/clickhouse.py +135 -0
- lfx/components/cloudflare/__init__.py +32 -0
- lfx/components/cloudflare/cloudflare.py +81 -0
- lfx/components/cohere/__init__.py +40 -0
- lfx/components/cohere/cohere_embeddings.py +81 -0
- lfx/components/cohere/cohere_models.py +46 -0
- lfx/components/cohere/cohere_rerank.py +51 -0
- lfx/components/cometapi/__init__.py +32 -0
- lfx/components/cometapi/cometapi.py +166 -0
- lfx/components/composio/__init__.py +222 -0
- lfx/components/composio/agentql_composio.py +11 -0
- lfx/components/composio/agiled_composio.py +11 -0
- lfx/components/composio/airtable_composio.py +11 -0
- lfx/components/composio/apollo_composio.py +11 -0
- lfx/components/composio/asana_composio.py +11 -0
- lfx/components/composio/attio_composio.py +11 -0
- lfx/components/composio/bitbucket_composio.py +11 -0
- lfx/components/composio/bolna_composio.py +11 -0
- lfx/components/composio/brightdata_composio.py +11 -0
- lfx/components/composio/calendly_composio.py +11 -0
- lfx/components/composio/canva_composio.py +11 -0
- lfx/components/composio/canvas_composio.py +11 -0
- lfx/components/composio/coda_composio.py +11 -0
- lfx/components/composio/composio_api.py +278 -0
- lfx/components/composio/contentful_composio.py +11 -0
- lfx/components/composio/digicert_composio.py +11 -0
- lfx/components/composio/discord_composio.py +11 -0
- lfx/components/composio/dropbox_compnent.py +11 -0
- lfx/components/composio/elevenlabs_composio.py +11 -0
- lfx/components/composio/exa_composio.py +11 -0
- lfx/components/composio/figma_composio.py +11 -0
- lfx/components/composio/finage_composio.py +11 -0
- lfx/components/composio/firecrawl_composio.py +11 -0
- lfx/components/composio/fireflies_composio.py +11 -0
- lfx/components/composio/fixer_composio.py +11 -0
- lfx/components/composio/flexisign_composio.py +11 -0
- lfx/components/composio/freshdesk_composio.py +11 -0
- lfx/components/composio/github_composio.py +11 -0
- lfx/components/composio/gmail_composio.py +38 -0
- lfx/components/composio/googlebigquery_composio.py +11 -0
- lfx/components/composio/googlecalendar_composio.py +11 -0
- lfx/components/composio/googleclassroom_composio.py +11 -0
- lfx/components/composio/googledocs_composio.py +11 -0
- lfx/components/composio/googlemeet_composio.py +11 -0
- lfx/components/composio/googlesheets_composio.py +11 -0
- lfx/components/composio/googletasks_composio.py +8 -0
- lfx/components/composio/heygen_composio.py +11 -0
- lfx/components/composio/instagram_composio.py +11 -0
- lfx/components/composio/jira_composio.py +11 -0
- lfx/components/composio/jotform_composio.py +11 -0
- lfx/components/composio/klaviyo_composio.py +11 -0
- lfx/components/composio/linear_composio.py +11 -0
- lfx/components/composio/listennotes_composio.py +11 -0
- lfx/components/composio/mem0_composio.py +11 -0
- lfx/components/composio/miro_composio.py +11 -0
- lfx/components/composio/missive_composio.py +11 -0
- lfx/components/composio/notion_composio.py +11 -0
- lfx/components/composio/onedrive_composio.py +11 -0
- lfx/components/composio/outlook_composio.py +11 -0
- lfx/components/composio/pandadoc_composio.py +11 -0
- lfx/components/composio/peopledatalabs_composio.py +11 -0
- lfx/components/composio/perplexityai_composio.py +11 -0
- lfx/components/composio/reddit_composio.py +11 -0
- lfx/components/composio/serpapi_composio.py +11 -0
- lfx/components/composio/slack_composio.py +11 -0
- lfx/components/composio/slackbot_composio.py +11 -0
- lfx/components/composio/snowflake_composio.py +11 -0
- lfx/components/composio/supabase_composio.py +11 -0
- lfx/components/composio/tavily_composio.py +11 -0
- lfx/components/composio/timelinesai_composio.py +11 -0
- lfx/components/composio/todoist_composio.py +11 -0
- lfx/components/composio/wrike_composio.py +11 -0
- lfx/components/composio/youtube_composio.py +11 -0
- lfx/components/confluence/__init__.py +3 -0
- lfx/components/confluence/confluence.py +84 -0
- lfx/components/couchbase/__init__.py +34 -0
- lfx/components/couchbase/couchbase.py +102 -0
- lfx/components/crewai/__init__.py +49 -0
- lfx/components/crewai/crewai.py +108 -0
- lfx/components/crewai/hierarchical_crew.py +47 -0
- lfx/components/crewai/hierarchical_task.py +45 -0
- lfx/components/crewai/sequential_crew.py +53 -0
- lfx/components/crewai/sequential_task.py +74 -0
- lfx/components/crewai/sequential_task_agent.py +144 -0
- lfx/components/cuga/__init__.py +34 -0
- lfx/components/cuga/cuga_agent.py +730 -0
- lfx/components/custom_component/__init__.py +34 -0
- lfx/components/custom_component/custom_component.py +31 -0
- lfx/components/data/__init__.py +114 -0
- lfx/components/data_source/__init__.py +58 -0
- lfx/components/data_source/api_request.py +577 -0
- lfx/components/data_source/csv_to_data.py +101 -0
- lfx/components/data_source/json_to_data.py +106 -0
- lfx/components/data_source/mock_data.py +398 -0
- lfx/components/data_source/news_search.py +166 -0
- lfx/components/data_source/rss.py +71 -0
- lfx/components/data_source/sql_executor.py +101 -0
- lfx/components/data_source/url.py +311 -0
- lfx/components/data_source/web_search.py +326 -0
- lfx/components/datastax/__init__.py +76 -0
- lfx/components/datastax/astradb_assistant_manager.py +307 -0
- lfx/components/datastax/astradb_chatmemory.py +40 -0
- lfx/components/datastax/astradb_cql.py +288 -0
- lfx/components/datastax/astradb_graph.py +217 -0
- lfx/components/datastax/astradb_tool.py +378 -0
- lfx/components/datastax/astradb_vectorize.py +122 -0
- lfx/components/datastax/astradb_vectorstore.py +449 -0
- lfx/components/datastax/create_assistant.py +59 -0
- lfx/components/datastax/create_thread.py +33 -0
- lfx/components/datastax/dotenv.py +36 -0
- lfx/components/datastax/get_assistant.py +38 -0
- lfx/components/datastax/getenvvar.py +31 -0
- lfx/components/datastax/graph_rag.py +141 -0
- lfx/components/datastax/hcd.py +315 -0
- lfx/components/datastax/list_assistants.py +26 -0
- lfx/components/datastax/run.py +90 -0
- lfx/components/deactivated/__init__.py +15 -0
- lfx/components/deactivated/amazon_kendra.py +66 -0
- lfx/components/deactivated/chat_litellm_model.py +158 -0
- lfx/components/deactivated/code_block_extractor.py +26 -0
- lfx/components/deactivated/documents_to_data.py +22 -0
- lfx/components/deactivated/embed.py +16 -0
- lfx/components/deactivated/extract_key_from_data.py +46 -0
- lfx/components/deactivated/json_document_builder.py +57 -0
- lfx/components/deactivated/list_flows.py +20 -0
- lfx/components/deactivated/mcp_sse.py +61 -0
- lfx/components/deactivated/mcp_stdio.py +62 -0
- lfx/components/deactivated/merge_data.py +93 -0
- lfx/components/deactivated/message.py +37 -0
- lfx/components/deactivated/metal.py +54 -0
- lfx/components/deactivated/multi_query.py +59 -0
- lfx/components/deactivated/retriever.py +43 -0
- lfx/components/deactivated/selective_passthrough.py +77 -0
- lfx/components/deactivated/should_run_next.py +40 -0
- lfx/components/deactivated/split_text.py +63 -0
- lfx/components/deactivated/store_message.py +24 -0
- lfx/components/deactivated/sub_flow.py +124 -0
- lfx/components/deactivated/vectara_self_query.py +76 -0
- lfx/components/deactivated/vector_store.py +24 -0
- lfx/components/deepseek/__init__.py +34 -0
- lfx/components/deepseek/deepseek.py +136 -0
- lfx/components/docling/__init__.py +43 -0
- lfx/components/docling/chunk_docling_document.py +186 -0
- lfx/components/docling/docling_inline.py +238 -0
- lfx/components/docling/docling_remote.py +195 -0
- lfx/components/docling/export_docling_document.py +117 -0
- lfx/components/documentloaders/__init__.py +3 -0
- lfx/components/duckduckgo/__init__.py +3 -0
- lfx/components/duckduckgo/duck_duck_go_search_run.py +92 -0
- lfx/components/elastic/__init__.py +37 -0
- lfx/components/elastic/elasticsearch.py +267 -0
- lfx/components/elastic/opensearch.py +789 -0
- lfx/components/elastic/opensearch_multimodal.py +1575 -0
- lfx/components/embeddings/__init__.py +37 -0
- lfx/components/embeddings/similarity.py +77 -0
- lfx/components/embeddings/text_embedder.py +65 -0
- lfx/components/exa/__init__.py +3 -0
- lfx/components/exa/exa_search.py +68 -0
- lfx/components/files_and_knowledge/__init__.py +47 -0
- lfx/components/files_and_knowledge/directory.py +113 -0
- lfx/components/files_and_knowledge/file.py +841 -0
- lfx/components/files_and_knowledge/ingestion.py +694 -0
- lfx/components/files_and_knowledge/retrieval.py +264 -0
- lfx/components/files_and_knowledge/save_file.py +746 -0
- lfx/components/firecrawl/__init__.py +43 -0
- lfx/components/firecrawl/firecrawl_crawl_api.py +88 -0
- lfx/components/firecrawl/firecrawl_extract_api.py +136 -0
- lfx/components/firecrawl/firecrawl_map_api.py +89 -0
- lfx/components/firecrawl/firecrawl_scrape_api.py +73 -0
- lfx/components/flow_controls/__init__.py +58 -0
- lfx/components/flow_controls/conditional_router.py +208 -0
- lfx/components/flow_controls/data_conditional_router.py +126 -0
- lfx/components/flow_controls/flow_tool.py +111 -0
- lfx/components/flow_controls/listen.py +29 -0
- lfx/components/flow_controls/loop.py +163 -0
- lfx/components/flow_controls/notify.py +88 -0
- lfx/components/flow_controls/pass_message.py +36 -0
- lfx/components/flow_controls/run_flow.py +108 -0
- lfx/components/flow_controls/sub_flow.py +115 -0
- lfx/components/git/__init__.py +4 -0
- lfx/components/git/git.py +262 -0
- lfx/components/git/gitextractor.py +196 -0
- lfx/components/glean/__init__.py +3 -0
- lfx/components/glean/glean_search_api.py +173 -0
- lfx/components/google/__init__.py +17 -0
- lfx/components/google/gmail.py +193 -0
- lfx/components/google/google_bq_sql_executor.py +157 -0
- lfx/components/google/google_drive.py +92 -0
- lfx/components/google/google_drive_search.py +152 -0
- lfx/components/google/google_generative_ai.py +144 -0
- lfx/components/google/google_generative_ai_embeddings.py +141 -0
- lfx/components/google/google_oauth_token.py +89 -0
- lfx/components/google/google_search_api_core.py +68 -0
- lfx/components/google/google_serper_api_core.py +74 -0
- lfx/components/groq/__init__.py +34 -0
- lfx/components/groq/groq.py +143 -0
- lfx/components/helpers/__init__.py +154 -0
- lfx/components/homeassistant/__init__.py +7 -0
- lfx/components/homeassistant/home_assistant_control.py +152 -0
- lfx/components/homeassistant/list_home_assistant_states.py +137 -0
- lfx/components/huggingface/__init__.py +37 -0
- lfx/components/huggingface/huggingface.py +199 -0
- lfx/components/huggingface/huggingface_inference_api.py +106 -0
- lfx/components/ibm/__init__.py +34 -0
- lfx/components/ibm/watsonx.py +207 -0
- lfx/components/ibm/watsonx_embeddings.py +135 -0
- lfx/components/icosacomputing/__init__.py +5 -0
- lfx/components/icosacomputing/combinatorial_reasoner.py +84 -0
- lfx/components/input_output/__init__.py +40 -0
- lfx/components/input_output/chat.py +109 -0
- lfx/components/input_output/chat_output.py +184 -0
- lfx/components/input_output/text.py +27 -0
- lfx/components/input_output/text_output.py +29 -0
- lfx/components/input_output/webhook.py +56 -0
- lfx/components/jigsawstack/__init__.py +23 -0
- lfx/components/jigsawstack/ai_scrape.py +126 -0
- lfx/components/jigsawstack/ai_web_search.py +136 -0
- lfx/components/jigsawstack/file_read.py +115 -0
- lfx/components/jigsawstack/file_upload.py +94 -0
- lfx/components/jigsawstack/image_generation.py +205 -0
- lfx/components/jigsawstack/nsfw.py +60 -0
- lfx/components/jigsawstack/object_detection.py +124 -0
- lfx/components/jigsawstack/sentiment.py +112 -0
- lfx/components/jigsawstack/text_to_sql.py +90 -0
- lfx/components/jigsawstack/text_translate.py +77 -0
- lfx/components/jigsawstack/vocr.py +107 -0
- lfx/components/knowledge_bases/__init__.py +89 -0
- lfx/components/langchain_utilities/__init__.py +109 -0
- lfx/components/langchain_utilities/character.py +53 -0
- lfx/components/langchain_utilities/conversation.py +59 -0
- lfx/components/langchain_utilities/csv_agent.py +175 -0
- lfx/components/langchain_utilities/fake_embeddings.py +26 -0
- lfx/components/langchain_utilities/html_link_extractor.py +35 -0
- lfx/components/langchain_utilities/json_agent.py +100 -0
- lfx/components/langchain_utilities/langchain_hub.py +126 -0
- lfx/components/langchain_utilities/language_recursive.py +49 -0
- lfx/components/langchain_utilities/language_semantic.py +138 -0
- lfx/components/langchain_utilities/llm_checker.py +39 -0
- lfx/components/langchain_utilities/llm_math.py +42 -0
- lfx/components/langchain_utilities/natural_language.py +61 -0
- lfx/components/langchain_utilities/openai_tools.py +53 -0
- lfx/components/langchain_utilities/openapi.py +48 -0
- lfx/components/langchain_utilities/recursive_character.py +60 -0
- lfx/components/langchain_utilities/retrieval_qa.py +83 -0
- lfx/components/langchain_utilities/runnable_executor.py +137 -0
- lfx/components/langchain_utilities/self_query.py +80 -0
- lfx/components/langchain_utilities/spider.py +142 -0
- lfx/components/langchain_utilities/sql.py +40 -0
- lfx/components/langchain_utilities/sql_database.py +35 -0
- lfx/components/langchain_utilities/sql_generator.py +78 -0
- lfx/components/langchain_utilities/tool_calling.py +59 -0
- lfx/components/langchain_utilities/vector_store_info.py +49 -0
- lfx/components/langchain_utilities/vector_store_router.py +33 -0
- lfx/components/langchain_utilities/xml_agent.py +71 -0
- lfx/components/langwatch/__init__.py +3 -0
- lfx/components/langwatch/langwatch.py +278 -0
- lfx/components/link_extractors/__init__.py +3 -0
- lfx/components/llm_operations/__init__.py +46 -0
- lfx/components/llm_operations/batch_run.py +205 -0
- lfx/components/llm_operations/lambda_filter.py +218 -0
- lfx/components/llm_operations/llm_conditional_router.py +421 -0
- lfx/components/llm_operations/llm_selector.py +499 -0
- lfx/components/llm_operations/structured_output.py +244 -0
- lfx/components/lmstudio/__init__.py +34 -0
- lfx/components/lmstudio/lmstudioembeddings.py +89 -0
- lfx/components/lmstudio/lmstudiomodel.py +133 -0
- lfx/components/logic/__init__.py +181 -0
- lfx/components/maritalk/__init__.py +32 -0
- lfx/components/maritalk/maritalk.py +52 -0
- lfx/components/mem0/__init__.py +3 -0
- lfx/components/mem0/mem0_chat_memory.py +147 -0
- lfx/components/milvus/__init__.py +34 -0
- lfx/components/milvus/milvus.py +115 -0
- lfx/components/mistral/__init__.py +37 -0
- lfx/components/mistral/mistral.py +114 -0
- lfx/components/mistral/mistral_embeddings.py +58 -0
- lfx/components/models/__init__.py +89 -0
- lfx/components/models_and_agents/__init__.py +49 -0
- lfx/components/models_and_agents/agent.py +644 -0
- lfx/components/models_and_agents/embedding_model.py +423 -0
- lfx/components/models_and_agents/language_model.py +398 -0
- lfx/components/models_and_agents/mcp_component.py +594 -0
- lfx/components/models_and_agents/memory.py +268 -0
- lfx/components/models_and_agents/prompt.py +67 -0
- lfx/components/mongodb/__init__.py +34 -0
- lfx/components/mongodb/mongodb_atlas.py +213 -0
- lfx/components/needle/__init__.py +3 -0
- lfx/components/needle/needle.py +104 -0
- lfx/components/notdiamond/__init__.py +34 -0
- lfx/components/notdiamond/notdiamond.py +228 -0
- lfx/components/novita/__init__.py +32 -0
- lfx/components/novita/novita.py +130 -0
- lfx/components/nvidia/__init__.py +57 -0
- lfx/components/nvidia/nvidia.py +151 -0
- lfx/components/nvidia/nvidia_embedding.py +77 -0
- lfx/components/nvidia/nvidia_ingest.py +317 -0
- lfx/components/nvidia/nvidia_rerank.py +63 -0
- lfx/components/nvidia/system_assist.py +65 -0
- lfx/components/olivya/__init__.py +3 -0
- lfx/components/olivya/olivya.py +116 -0
- lfx/components/ollama/__init__.py +37 -0
- lfx/components/ollama/ollama.py +548 -0
- lfx/components/ollama/ollama_embeddings.py +103 -0
- lfx/components/openai/__init__.py +37 -0
- lfx/components/openai/openai.py +100 -0
- lfx/components/openai/openai_chat_model.py +176 -0
- lfx/components/openrouter/__init__.py +32 -0
- lfx/components/openrouter/openrouter.py +104 -0
- lfx/components/output_parsers/__init__.py +3 -0
- lfx/components/perplexity/__init__.py +34 -0
- lfx/components/perplexity/perplexity.py +75 -0
- lfx/components/pgvector/__init__.py +34 -0
- lfx/components/pgvector/pgvector.py +72 -0
- lfx/components/pinecone/__init__.py +34 -0
- lfx/components/pinecone/pinecone.py +134 -0
- lfx/components/processing/__init__.py +72 -0
- lfx/components/processing/alter_metadata.py +109 -0
- lfx/components/processing/combine_text.py +40 -0
- lfx/components/processing/converter.py +248 -0
- lfx/components/processing/create_data.py +111 -0
- lfx/components/processing/create_list.py +40 -0
- lfx/components/processing/data_operations.py +528 -0
- lfx/components/processing/data_to_dataframe.py +71 -0
- lfx/components/processing/dataframe_operations.py +313 -0
- lfx/components/processing/dataframe_to_toolset.py +259 -0
- lfx/components/processing/dynamic_create_data.py +357 -0
- lfx/components/processing/extract_key.py +54 -0
- lfx/components/processing/filter_data.py +43 -0
- lfx/components/processing/filter_data_values.py +89 -0
- lfx/components/processing/json_cleaner.py +104 -0
- lfx/components/processing/merge_data.py +91 -0
- lfx/components/processing/message_to_data.py +37 -0
- lfx/components/processing/output_parser.py +46 -0
- lfx/components/processing/parse_data.py +71 -0
- lfx/components/processing/parse_dataframe.py +69 -0
- lfx/components/processing/parse_json_data.py +91 -0
- lfx/components/processing/parser.py +148 -0
- lfx/components/processing/regex.py +83 -0
- lfx/components/processing/select_data.py +49 -0
- lfx/components/processing/split_text.py +141 -0
- lfx/components/processing/store_message.py +91 -0
- lfx/components/processing/update_data.py +161 -0
- lfx/components/prototypes/__init__.py +35 -0
- lfx/components/prototypes/python_function.py +73 -0
- lfx/components/qdrant/__init__.py +34 -0
- lfx/components/qdrant/qdrant.py +109 -0
- lfx/components/redis/__init__.py +37 -0
- lfx/components/redis/redis.py +89 -0
- lfx/components/redis/redis_chat.py +43 -0
- lfx/components/sambanova/__init__.py +32 -0
- lfx/components/sambanova/sambanova.py +84 -0
- lfx/components/scrapegraph/__init__.py +40 -0
- lfx/components/scrapegraph/scrapegraph_markdownify_api.py +64 -0
- lfx/components/scrapegraph/scrapegraph_search_api.py +64 -0
- lfx/components/scrapegraph/scrapegraph_smart_scraper_api.py +71 -0
- lfx/components/searchapi/__init__.py +34 -0
- lfx/components/searchapi/search.py +79 -0
- lfx/components/serpapi/__init__.py +3 -0
- lfx/components/serpapi/serp.py +115 -0
- lfx/components/supabase/__init__.py +34 -0
- lfx/components/supabase/supabase.py +76 -0
- lfx/components/tavily/__init__.py +4 -0
- lfx/components/tavily/tavily_extract.py +117 -0
- lfx/components/tavily/tavily_search.py +212 -0
- lfx/components/textsplitters/__init__.py +3 -0
- lfx/components/toolkits/__init__.py +3 -0
- lfx/components/tools/__init__.py +66 -0
- lfx/components/tools/calculator.py +109 -0
- lfx/components/tools/google_search_api.py +45 -0
- lfx/components/tools/google_serper_api.py +115 -0
- lfx/components/tools/python_code_structured_tool.py +328 -0
- lfx/components/tools/python_repl.py +98 -0
- lfx/components/tools/search_api.py +88 -0
- lfx/components/tools/searxng.py +145 -0
- lfx/components/tools/serp_api.py +120 -0
- lfx/components/tools/tavily_search_tool.py +345 -0
- lfx/components/tools/wikidata_api.py +103 -0
- lfx/components/tools/wikipedia_api.py +50 -0
- lfx/components/tools/yahoo_finance.py +130 -0
- lfx/components/twelvelabs/__init__.py +52 -0
- lfx/components/twelvelabs/convert_astra_results.py +84 -0
- lfx/components/twelvelabs/pegasus_index.py +311 -0
- lfx/components/twelvelabs/split_video.py +301 -0
- lfx/components/twelvelabs/text_embeddings.py +57 -0
- lfx/components/twelvelabs/twelvelabs_pegasus.py +408 -0
- lfx/components/twelvelabs/video_embeddings.py +100 -0
- lfx/components/twelvelabs/video_file.py +191 -0
- lfx/components/unstructured/__init__.py +3 -0
- lfx/components/unstructured/unstructured.py +121 -0
- lfx/components/upstash/__init__.py +34 -0
- lfx/components/upstash/upstash.py +124 -0
- lfx/components/utilities/__init__.py +43 -0
- lfx/components/utilities/calculator_core.py +89 -0
- lfx/components/utilities/current_date.py +42 -0
- lfx/components/utilities/id_generator.py +42 -0
- lfx/components/utilities/python_repl_core.py +98 -0
- lfx/components/vectara/__init__.py +37 -0
- lfx/components/vectara/vectara.py +97 -0
- lfx/components/vectara/vectara_rag.py +164 -0
- lfx/components/vectorstores/__init__.py +34 -0
- lfx/components/vectorstores/local_db.py +270 -0
- lfx/components/vertexai/__init__.py +37 -0
- lfx/components/vertexai/vertexai.py +71 -0
- lfx/components/vertexai/vertexai_embeddings.py +67 -0
- lfx/components/vlmrun/__init__.py +34 -0
- lfx/components/vlmrun/vlmrun_transcription.py +224 -0
- lfx/components/weaviate/__init__.py +34 -0
- lfx/components/weaviate/weaviate.py +89 -0
- lfx/components/wikipedia/__init__.py +4 -0
- lfx/components/wikipedia/wikidata.py +86 -0
- lfx/components/wikipedia/wikipedia.py +53 -0
- lfx/components/wolframalpha/__init__.py +3 -0
- lfx/components/wolframalpha/wolfram_alpha_api.py +54 -0
- lfx/components/xai/__init__.py +32 -0
- lfx/components/xai/xai.py +167 -0
- lfx/components/yahoosearch/__init__.py +3 -0
- lfx/components/yahoosearch/yahoo.py +137 -0
- lfx/components/youtube/__init__.py +52 -0
- lfx/components/youtube/channel.py +227 -0
- lfx/components/youtube/comments.py +231 -0
- lfx/components/youtube/playlist.py +33 -0
- lfx/components/youtube/search.py +120 -0
- lfx/components/youtube/trending.py +285 -0
- lfx/components/youtube/video_details.py +263 -0
- lfx/components/youtube/youtube_transcripts.py +206 -0
- lfx/components/zep/__init__.py +3 -0
- lfx/components/zep/zep.py +45 -0
- lfx/constants.py +6 -0
- lfx/custom/__init__.py +7 -0
- lfx/custom/attributes.py +87 -0
- lfx/custom/code_parser/__init__.py +3 -0
- lfx/custom/code_parser/code_parser.py +361 -0
- lfx/custom/custom_component/__init__.py +0 -0
- lfx/custom/custom_component/base_component.py +128 -0
- lfx/custom/custom_component/component.py +1890 -0
- lfx/custom/custom_component/component_with_cache.py +8 -0
- lfx/custom/custom_component/custom_component.py +650 -0
- lfx/custom/dependency_analyzer.py +165 -0
- lfx/custom/directory_reader/__init__.py +3 -0
- lfx/custom/directory_reader/directory_reader.py +359 -0
- lfx/custom/directory_reader/utils.py +171 -0
- lfx/custom/eval.py +12 -0
- lfx/custom/schema.py +32 -0
- lfx/custom/tree_visitor.py +21 -0
- lfx/custom/utils.py +877 -0
- lfx/custom/validate.py +523 -0
- lfx/events/__init__.py +1 -0
- lfx/events/event_manager.py +110 -0
- lfx/exceptions/__init__.py +0 -0
- lfx/exceptions/component.py +15 -0
- lfx/field_typing/__init__.py +91 -0
- lfx/field_typing/constants.py +216 -0
- lfx/field_typing/range_spec.py +35 -0
- lfx/graph/__init__.py +6 -0
- lfx/graph/edge/__init__.py +0 -0
- lfx/graph/edge/base.py +300 -0
- lfx/graph/edge/schema.py +119 -0
- lfx/graph/edge/utils.py +0 -0
- lfx/graph/graph/__init__.py +0 -0
- lfx/graph/graph/ascii.py +202 -0
- lfx/graph/graph/base.py +2298 -0
- lfx/graph/graph/constants.py +63 -0
- lfx/graph/graph/runnable_vertices_manager.py +133 -0
- lfx/graph/graph/schema.py +53 -0
- lfx/graph/graph/state_model.py +66 -0
- lfx/graph/graph/utils.py +1024 -0
- lfx/graph/schema.py +75 -0
- lfx/graph/state/__init__.py +0 -0
- lfx/graph/state/model.py +250 -0
- lfx/graph/utils.py +206 -0
- lfx/graph/vertex/__init__.py +0 -0
- lfx/graph/vertex/base.py +826 -0
- lfx/graph/vertex/constants.py +0 -0
- lfx/graph/vertex/exceptions.py +4 -0
- lfx/graph/vertex/param_handler.py +316 -0
- lfx/graph/vertex/schema.py +26 -0
- lfx/graph/vertex/utils.py +19 -0
- lfx/graph/vertex/vertex_types.py +489 -0
- lfx/helpers/__init__.py +141 -0
- lfx/helpers/base_model.py +71 -0
- lfx/helpers/custom.py +13 -0
- lfx/helpers/data.py +167 -0
- lfx/helpers/flow.py +308 -0
- lfx/inputs/__init__.py +68 -0
- lfx/inputs/constants.py +2 -0
- lfx/inputs/input_mixin.py +352 -0
- lfx/inputs/inputs.py +718 -0
- lfx/inputs/validators.py +19 -0
- lfx/interface/__init__.py +6 -0
- lfx/interface/components.py +897 -0
- lfx/interface/importing/__init__.py +5 -0
- lfx/interface/importing/utils.py +39 -0
- lfx/interface/initialize/__init__.py +3 -0
- lfx/interface/initialize/loading.py +317 -0
- lfx/interface/listing.py +26 -0
- lfx/interface/run.py +16 -0
- lfx/interface/utils.py +111 -0
- lfx/io/__init__.py +63 -0
- lfx/io/schema.py +295 -0
- lfx/load/__init__.py +8 -0
- lfx/load/load.py +256 -0
- lfx/load/utils.py +99 -0
- lfx/log/__init__.py +5 -0
- lfx/log/logger.py +411 -0
- lfx/logging/__init__.py +11 -0
- lfx/logging/logger.py +24 -0
- lfx/memory/__init__.py +70 -0
- lfx/memory/stubs.py +302 -0
- lfx/processing/__init__.py +1 -0
- lfx/processing/process.py +238 -0
- lfx/processing/utils.py +25 -0
- lfx/py.typed +0 -0
- lfx/schema/__init__.py +66 -0
- lfx/schema/artifact.py +83 -0
- lfx/schema/content_block.py +62 -0
- lfx/schema/content_types.py +91 -0
- lfx/schema/cross_module.py +80 -0
- lfx/schema/data.py +309 -0
- lfx/schema/dataframe.py +210 -0
- lfx/schema/dotdict.py +74 -0
- lfx/schema/encoders.py +13 -0
- lfx/schema/graph.py +47 -0
- lfx/schema/image.py +184 -0
- lfx/schema/json_schema.py +186 -0
- lfx/schema/log.py +62 -0
- lfx/schema/message.py +493 -0
- lfx/schema/openai_responses_schemas.py +74 -0
- lfx/schema/properties.py +41 -0
- lfx/schema/schema.py +180 -0
- lfx/schema/serialize.py +13 -0
- lfx/schema/table.py +142 -0
- lfx/schema/validators.py +114 -0
- lfx/serialization/__init__.py +5 -0
- lfx/serialization/constants.py +2 -0
- lfx/serialization/serialization.py +314 -0
- lfx/services/__init__.py +26 -0
- lfx/services/base.py +28 -0
- lfx/services/cache/__init__.py +6 -0
- lfx/services/cache/base.py +183 -0
- lfx/services/cache/service.py +166 -0
- lfx/services/cache/utils.py +169 -0
- lfx/services/chat/__init__.py +1 -0
- lfx/services/chat/config.py +2 -0
- lfx/services/chat/schema.py +10 -0
- lfx/services/database/__init__.py +5 -0
- lfx/services/database/service.py +25 -0
- lfx/services/deps.py +194 -0
- lfx/services/factory.py +19 -0
- lfx/services/initialize.py +19 -0
- lfx/services/interfaces.py +103 -0
- lfx/services/manager.py +185 -0
- lfx/services/mcp_composer/__init__.py +6 -0
- lfx/services/mcp_composer/factory.py +16 -0
- lfx/services/mcp_composer/service.py +1441 -0
- lfx/services/schema.py +21 -0
- lfx/services/session.py +87 -0
- lfx/services/settings/__init__.py +3 -0
- lfx/services/settings/auth.py +133 -0
- lfx/services/settings/base.py +668 -0
- lfx/services/settings/constants.py +43 -0
- lfx/services/settings/factory.py +23 -0
- lfx/services/settings/feature_flags.py +11 -0
- lfx/services/settings/service.py +35 -0
- lfx/services/settings/utils.py +40 -0
- lfx/services/shared_component_cache/__init__.py +1 -0
- lfx/services/shared_component_cache/factory.py +30 -0
- lfx/services/shared_component_cache/service.py +9 -0
- lfx/services/storage/__init__.py +5 -0
- lfx/services/storage/local.py +185 -0
- lfx/services/storage/service.py +177 -0
- lfx/services/tracing/__init__.py +1 -0
- lfx/services/tracing/service.py +21 -0
- lfx/settings.py +6 -0
- lfx/template/__init__.py +6 -0
- lfx/template/field/__init__.py +0 -0
- lfx/template/field/base.py +260 -0
- lfx/template/field/prompt.py +15 -0
- lfx/template/frontend_node/__init__.py +6 -0
- lfx/template/frontend_node/base.py +214 -0
- lfx/template/frontend_node/constants.py +65 -0
- lfx/template/frontend_node/custom_components.py +79 -0
- lfx/template/template/__init__.py +0 -0
- lfx/template/template/base.py +100 -0
- lfx/template/utils.py +217 -0
- lfx/type_extraction/__init__.py +19 -0
- lfx/type_extraction/type_extraction.py +75 -0
- lfx/type_extraction.py +80 -0
- lfx/utils/__init__.py +1 -0
- lfx/utils/async_helpers.py +42 -0
- lfx/utils/component_utils.py +154 -0
- lfx/utils/concurrency.py +60 -0
- lfx/utils/connection_string_parser.py +11 -0
- lfx/utils/constants.py +233 -0
- lfx/utils/data_structure.py +212 -0
- lfx/utils/exceptions.py +22 -0
- lfx/utils/helpers.py +34 -0
- lfx/utils/image.py +79 -0
- lfx/utils/langflow_utils.py +52 -0
- lfx/utils/lazy_load.py +15 -0
- lfx/utils/request_utils.py +18 -0
- lfx/utils/schemas.py +139 -0
- lfx/utils/ssrf_protection.py +384 -0
- lfx/utils/util.py +626 -0
- lfx/utils/util_strings.py +56 -0
- lfx/utils/validate_cloud.py +26 -0
- lfx/utils/version.py +24 -0
- lfx_nightly-0.2.0.dev25.dist-info/METADATA +312 -0
- lfx_nightly-0.2.0.dev25.dist-info/RECORD +769 -0
- lfx_nightly-0.2.0.dev25.dist-info/WHEEL +4 -0
- lfx_nightly-0.2.0.dev25.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import string
|
|
3
|
+
from typing import Any, cast
|
|
4
|
+
|
|
5
|
+
from apify_client import ApifyClient
|
|
6
|
+
from langchain_community.document_loaders.apify_dataset import ApifyDatasetLoader
|
|
7
|
+
from langchain_core.tools import BaseTool
|
|
8
|
+
from pydantic import BaseModel, Field, field_serializer
|
|
9
|
+
|
|
10
|
+
from lfx.custom.custom_component.component import Component
|
|
11
|
+
from lfx.field_typing import Tool
|
|
12
|
+
from lfx.inputs.inputs import BoolInput
|
|
13
|
+
from lfx.io import MultilineInput, Output, SecretStrInput, StrInput
|
|
14
|
+
from lfx.schema.data import Data
|
|
15
|
+
|
|
16
|
+
MAX_DESCRIPTION_LEN = 250
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ApifyActorsComponent(Component):
|
|
20
|
+
display_name = "Apify Actors"
|
|
21
|
+
description = (
|
|
22
|
+
"Use Apify Actors to extract data from hundreds of places fast. "
|
|
23
|
+
"This component can be used in a flow to retrieve data or as a tool with an agent."
|
|
24
|
+
)
|
|
25
|
+
documentation: str = "https://docs.langflow.org/bundles-apify"
|
|
26
|
+
icon = "Apify"
|
|
27
|
+
name = "ApifyActors"
|
|
28
|
+
|
|
29
|
+
inputs = [
|
|
30
|
+
SecretStrInput(
|
|
31
|
+
name="apify_token",
|
|
32
|
+
display_name="Apify Token",
|
|
33
|
+
info="The API token for the Apify account.",
|
|
34
|
+
required=True,
|
|
35
|
+
password=True,
|
|
36
|
+
),
|
|
37
|
+
StrInput(
|
|
38
|
+
name="actor_id",
|
|
39
|
+
display_name="Actor",
|
|
40
|
+
info=(
|
|
41
|
+
"Actor name from Apify store to run. For example 'apify/website-content-crawler' "
|
|
42
|
+
"to use the Website Content Crawler Actor."
|
|
43
|
+
),
|
|
44
|
+
value="apify/website-content-crawler",
|
|
45
|
+
required=True,
|
|
46
|
+
),
|
|
47
|
+
# multiline input is more pleasant to use than the nested dict input
|
|
48
|
+
MultilineInput(
|
|
49
|
+
name="run_input",
|
|
50
|
+
display_name="Run input",
|
|
51
|
+
info=(
|
|
52
|
+
'The JSON input for the Actor run. For example for the "apify/website-content-crawler" Actor: '
|
|
53
|
+
'{"startUrls":[{"url":"https://docs.apify.com/academy/web-scraping-for-beginners"}],"maxCrawlDepth":0}'
|
|
54
|
+
),
|
|
55
|
+
value='{"startUrls":[{"url":"https://docs.apify.com/academy/web-scraping-for-beginners"}],"maxCrawlDepth":0}',
|
|
56
|
+
required=True,
|
|
57
|
+
),
|
|
58
|
+
MultilineInput(
|
|
59
|
+
name="dataset_fields",
|
|
60
|
+
display_name="Output fields",
|
|
61
|
+
info=(
|
|
62
|
+
"Fields to extract from the dataset, split by commas. "
|
|
63
|
+
"Other fields will be ignored. Dots in nested structures will be replaced by underscores. "
|
|
64
|
+
"Sample input: 'text, metadata.title'. "
|
|
65
|
+
"Sample output: {'text': 'page content here', 'metadata_title': 'page title here'}. "
|
|
66
|
+
"For example, for the 'apify/website-content-crawler' Actor, you can extract the 'markdown' field, "
|
|
67
|
+
"which is the content of the website in markdown format."
|
|
68
|
+
),
|
|
69
|
+
),
|
|
70
|
+
BoolInput(
|
|
71
|
+
name="flatten_dataset",
|
|
72
|
+
display_name="Flatten output",
|
|
73
|
+
info=(
|
|
74
|
+
"The output dataset will be converted from a nested format to a flat structure. "
|
|
75
|
+
"Dots in nested structure will be replaced by underscores. "
|
|
76
|
+
"This is useful for further processing of the Data object. "
|
|
77
|
+
"For example, {'a': {'b': 1}} will be flattened to {'a_b': 1}."
|
|
78
|
+
),
|
|
79
|
+
),
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
outputs = [
|
|
83
|
+
Output(display_name="Output", name="output", type_=list[Data], method="run_model"),
|
|
84
|
+
Output(display_name="Tool", name="tool", type_=Tool, method="build_tool"),
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
88
|
+
super().__init__(*args, **kwargs)
|
|
89
|
+
self._apify_client: ApifyClient | None = None
|
|
90
|
+
|
|
91
|
+
def run_model(self) -> list[Data]:
|
|
92
|
+
"""Run the Actor and return node output."""
|
|
93
|
+
input_ = json.loads(self.run_input)
|
|
94
|
+
fields = ApifyActorsComponent.parse_dataset_fields(self.dataset_fields) if self.dataset_fields else None
|
|
95
|
+
res = self.run_actor(self.actor_id, input_, fields=fields)
|
|
96
|
+
if self.flatten_dataset:
|
|
97
|
+
res = [ApifyActorsComponent.flatten(item) for item in res]
|
|
98
|
+
data = [Data(data=item) for item in res]
|
|
99
|
+
|
|
100
|
+
self.status = data
|
|
101
|
+
return data
|
|
102
|
+
|
|
103
|
+
def build_tool(self) -> Tool:
|
|
104
|
+
"""Build a tool for an agent that runs the Apify Actor."""
|
|
105
|
+
actor_id = self.actor_id
|
|
106
|
+
|
|
107
|
+
build = self._get_actor_latest_build(actor_id)
|
|
108
|
+
readme = build.get("readme", "")[:250] + "..."
|
|
109
|
+
if not (input_schema_str := build.get("inputSchema")):
|
|
110
|
+
msg = "Input schema not found"
|
|
111
|
+
raise ValueError(msg)
|
|
112
|
+
input_schema = json.loads(input_schema_str)
|
|
113
|
+
properties, required = ApifyActorsComponent.get_actor_input_schema_from_build(input_schema)
|
|
114
|
+
properties = {"run_input": properties}
|
|
115
|
+
|
|
116
|
+
# works from input schema
|
|
117
|
+
info_ = [
|
|
118
|
+
(
|
|
119
|
+
"JSON encoded as a string with input schema (STRICTLY FOLLOW JSON FORMAT AND SCHEMA):\n\n"
|
|
120
|
+
f"{json.dumps(properties, separators=(',', ':'))}"
|
|
121
|
+
)
|
|
122
|
+
]
|
|
123
|
+
if required:
|
|
124
|
+
info_.append("\n\nRequired fields:\n" + "\n".join(required))
|
|
125
|
+
|
|
126
|
+
info = "".join(info_)
|
|
127
|
+
|
|
128
|
+
input_model_cls = ApifyActorsComponent.create_input_model_class(info)
|
|
129
|
+
tool_cls = ApifyActorsComponent.create_tool_class(self, readme, input_model_cls, actor_id)
|
|
130
|
+
|
|
131
|
+
return cast("Tool", tool_cls())
|
|
132
|
+
|
|
133
|
+
@staticmethod
|
|
134
|
+
def create_tool_class(
|
|
135
|
+
parent: "ApifyActorsComponent", readme: str, input_model: type[BaseModel], actor_id: str
|
|
136
|
+
) -> type[BaseTool]:
|
|
137
|
+
"""Create a tool class that runs an Apify Actor."""
|
|
138
|
+
|
|
139
|
+
class ApifyActorRun(BaseTool):
|
|
140
|
+
"""Tool that runs Apify Actors."""
|
|
141
|
+
|
|
142
|
+
name: str = f"apify_actor_{ApifyActorsComponent.actor_id_to_tool_name(actor_id)}"
|
|
143
|
+
description: str = (
|
|
144
|
+
"Run an Apify Actor with the given input. "
|
|
145
|
+
"Here is a part of the currently loaded Actor README:\n\n"
|
|
146
|
+
f"{readme}\n\n"
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
args_schema: type[BaseModel] = input_model
|
|
150
|
+
|
|
151
|
+
@field_serializer("args_schema")
|
|
152
|
+
def serialize_args_schema(self, args_schema):
|
|
153
|
+
return args_schema.schema()
|
|
154
|
+
|
|
155
|
+
def _run(self, run_input: str | dict) -> str:
|
|
156
|
+
"""Use the Apify Actor."""
|
|
157
|
+
input_dict = json.loads(run_input) if isinstance(run_input, str) else run_input
|
|
158
|
+
|
|
159
|
+
# retrieve if nested, just in case
|
|
160
|
+
input_dict = input_dict.get("run_input", input_dict)
|
|
161
|
+
|
|
162
|
+
res = parent.run_actor(actor_id, input_dict)
|
|
163
|
+
return "\n\n".join([ApifyActorsComponent.dict_to_json_str(item) for item in res])
|
|
164
|
+
|
|
165
|
+
return ApifyActorRun
|
|
166
|
+
|
|
167
|
+
@staticmethod
|
|
168
|
+
def create_input_model_class(description: str) -> type[BaseModel]:
|
|
169
|
+
"""Create a Pydantic model class for the Actor input."""
|
|
170
|
+
|
|
171
|
+
class ActorInput(BaseModel):
|
|
172
|
+
"""Input for the Apify Actor tool."""
|
|
173
|
+
|
|
174
|
+
run_input: str = Field(..., description=description)
|
|
175
|
+
|
|
176
|
+
return ActorInput
|
|
177
|
+
|
|
178
|
+
def _get_apify_client(self) -> ApifyClient:
|
|
179
|
+
"""Get the Apify client.
|
|
180
|
+
|
|
181
|
+
Is created if not exists or token changes.
|
|
182
|
+
"""
|
|
183
|
+
if not self.apify_token:
|
|
184
|
+
msg = "API token is required."
|
|
185
|
+
raise ValueError(msg)
|
|
186
|
+
# when token changes, create a new client
|
|
187
|
+
if self._apify_client is None or self._apify_client.token != self.apify_token:
|
|
188
|
+
self._apify_client = ApifyClient(self.apify_token)
|
|
189
|
+
if httpx_client := self._apify_client.http_client.httpx_client:
|
|
190
|
+
httpx_client.headers["user-agent"] += "; Origin/langflow"
|
|
191
|
+
return self._apify_client
|
|
192
|
+
|
|
193
|
+
def _get_actor_latest_build(self, actor_id: str) -> dict:
|
|
194
|
+
"""Get the latest build of an Actor from the default build tag."""
|
|
195
|
+
client = self._get_apify_client()
|
|
196
|
+
actor = client.actor(actor_id=actor_id)
|
|
197
|
+
if not (actor_info := actor.get()):
|
|
198
|
+
msg = f"Actor {actor_id} not found."
|
|
199
|
+
raise ValueError(msg)
|
|
200
|
+
|
|
201
|
+
default_build_tag = actor_info.get("defaultRunOptions", {}).get("build")
|
|
202
|
+
latest_build_id = actor_info.get("taggedBuilds", {}).get(default_build_tag, {}).get("buildId")
|
|
203
|
+
|
|
204
|
+
if (build := client.build(latest_build_id).get()) is None:
|
|
205
|
+
msg = f"Build {latest_build_id} not found."
|
|
206
|
+
raise ValueError(msg)
|
|
207
|
+
|
|
208
|
+
return build
|
|
209
|
+
|
|
210
|
+
@staticmethod
|
|
211
|
+
def get_actor_input_schema_from_build(input_schema: dict) -> tuple[dict, list[str]]:
|
|
212
|
+
"""Get the input schema from the Actor build.
|
|
213
|
+
|
|
214
|
+
Trim the description to 250 characters.
|
|
215
|
+
"""
|
|
216
|
+
properties = input_schema.get("properties", {})
|
|
217
|
+
required = input_schema.get("required", [])
|
|
218
|
+
|
|
219
|
+
properties_out: dict = {}
|
|
220
|
+
for item, meta in properties.items():
|
|
221
|
+
properties_out[item] = {}
|
|
222
|
+
if desc := meta.get("description"):
|
|
223
|
+
properties_out[item]["description"] = (
|
|
224
|
+
desc[:MAX_DESCRIPTION_LEN] + "..." if len(desc) > MAX_DESCRIPTION_LEN else desc
|
|
225
|
+
)
|
|
226
|
+
for key_name in ("type", "default", "prefill", "enum"):
|
|
227
|
+
if value := meta.get(key_name):
|
|
228
|
+
properties_out[item][key_name] = value
|
|
229
|
+
|
|
230
|
+
return properties_out, required
|
|
231
|
+
|
|
232
|
+
def _get_run_dataset_id(self, run_id: str) -> str:
|
|
233
|
+
"""Get the dataset id from the run id."""
|
|
234
|
+
client = self._get_apify_client()
|
|
235
|
+
run = client.run(run_id=run_id)
|
|
236
|
+
if (dataset := run.dataset().get()) is None:
|
|
237
|
+
msg = "Dataset not found"
|
|
238
|
+
raise ValueError(msg)
|
|
239
|
+
if (did := dataset.get("id")) is None:
|
|
240
|
+
msg = "Dataset id not found"
|
|
241
|
+
raise ValueError(msg)
|
|
242
|
+
return did
|
|
243
|
+
|
|
244
|
+
@staticmethod
|
|
245
|
+
def dict_to_json_str(d: dict) -> str:
|
|
246
|
+
"""Convert a dictionary to a JSON string."""
|
|
247
|
+
return json.dumps(d, separators=(",", ":"), default=lambda _: "<n/a>")
|
|
248
|
+
|
|
249
|
+
@staticmethod
|
|
250
|
+
def actor_id_to_tool_name(actor_id: str) -> str:
|
|
251
|
+
"""Turn actor_id into a valid tool name.
|
|
252
|
+
|
|
253
|
+
Tool name must only contain letters, numbers, underscores, dashes,
|
|
254
|
+
and cannot contain spaces.
|
|
255
|
+
"""
|
|
256
|
+
valid_chars = string.ascii_letters + string.digits + "_-"
|
|
257
|
+
return "".join(char if char in valid_chars else "_" for char in actor_id)
|
|
258
|
+
|
|
259
|
+
def run_actor(self, actor_id: str, run_input: dict, fields: list[str] | None = None) -> list[dict]:
|
|
260
|
+
"""Run an Apify Actor and return the output dataset.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
actor_id: Actor name from Apify store to run.
|
|
264
|
+
run_input: JSON input for the Actor.
|
|
265
|
+
fields: List of fields to extract from the dataset. Other fields will be ignored.
|
|
266
|
+
"""
|
|
267
|
+
client = self._get_apify_client()
|
|
268
|
+
if (details := client.actor(actor_id=actor_id).call(run_input=run_input, wait_secs=1)) is None:
|
|
269
|
+
msg = "Actor run details not found"
|
|
270
|
+
raise ValueError(msg)
|
|
271
|
+
if (run_id := details.get("id")) is None:
|
|
272
|
+
msg = "Run id not found"
|
|
273
|
+
raise ValueError(msg)
|
|
274
|
+
|
|
275
|
+
if (run_client := client.run(run_id)) is None:
|
|
276
|
+
msg = "Run client not found"
|
|
277
|
+
raise ValueError(msg)
|
|
278
|
+
|
|
279
|
+
# stream logs
|
|
280
|
+
with run_client.log().stream() as response:
|
|
281
|
+
if response:
|
|
282
|
+
for line in response.iter_lines():
|
|
283
|
+
self.log(line)
|
|
284
|
+
run_client.wait_for_finish()
|
|
285
|
+
|
|
286
|
+
dataset_id = self._get_run_dataset_id(run_id)
|
|
287
|
+
|
|
288
|
+
loader = ApifyDatasetLoader(
|
|
289
|
+
dataset_id=dataset_id,
|
|
290
|
+
dataset_mapping_function=lambda item: item
|
|
291
|
+
if not fields
|
|
292
|
+
else {k.replace(".", "_"): ApifyActorsComponent.get_nested_value(item, k) for k in fields},
|
|
293
|
+
)
|
|
294
|
+
return loader.load()
|
|
295
|
+
|
|
296
|
+
@staticmethod
|
|
297
|
+
def get_nested_value(data: dict[str, Any], key: str) -> Any:
|
|
298
|
+
"""Get a nested value from a dictionary."""
|
|
299
|
+
keys = key.split(".")
|
|
300
|
+
value = data
|
|
301
|
+
for k in keys:
|
|
302
|
+
if not isinstance(value, dict) or k not in value:
|
|
303
|
+
return None
|
|
304
|
+
value = value[k]
|
|
305
|
+
return value
|
|
306
|
+
|
|
307
|
+
@staticmethod
|
|
308
|
+
def parse_dataset_fields(dataset_fields: str) -> list[str]:
|
|
309
|
+
"""Convert a string of comma-separated fields into a list of fields."""
|
|
310
|
+
dataset_fields = dataset_fields.replace("'", "").replace('"', "").replace("`", "")
|
|
311
|
+
return [field.strip() for field in dataset_fields.split(",")]
|
|
312
|
+
|
|
313
|
+
@staticmethod
|
|
314
|
+
def flatten(d: dict) -> dict:
|
|
315
|
+
"""Flatten a nested dictionary."""
|
|
316
|
+
|
|
317
|
+
def items():
|
|
318
|
+
for key, value in d.items():
|
|
319
|
+
if isinstance(value, dict):
|
|
320
|
+
for subkey, subvalue in ApifyActorsComponent.flatten(value).items():
|
|
321
|
+
yield key + "_" + subkey, subvalue
|
|
322
|
+
else:
|
|
323
|
+
yield key, value
|
|
324
|
+
|
|
325
|
+
return dict(items())
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import urllib.request
|
|
2
|
+
from urllib.parse import urlparse
|
|
3
|
+
from xml.etree.ElementTree import Element
|
|
4
|
+
|
|
5
|
+
from defusedxml.ElementTree import fromstring
|
|
6
|
+
|
|
7
|
+
from lfx.custom.custom_component.component import Component
|
|
8
|
+
from lfx.io import DropdownInput, IntInput, MessageTextInput, Output
|
|
9
|
+
from lfx.schema.data import Data
|
|
10
|
+
from lfx.schema.dataframe import DataFrame
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ArXivComponent(Component):
|
|
14
|
+
display_name = "arXiv"
|
|
15
|
+
description = "Search and retrieve papers from arXiv.org"
|
|
16
|
+
icon = "arXiv"
|
|
17
|
+
|
|
18
|
+
inputs = [
|
|
19
|
+
MessageTextInput(
|
|
20
|
+
name="search_query",
|
|
21
|
+
display_name="Search Query",
|
|
22
|
+
info="The search query for arXiv papers (e.g., 'quantum computing')",
|
|
23
|
+
tool_mode=True,
|
|
24
|
+
),
|
|
25
|
+
DropdownInput(
|
|
26
|
+
name="search_type",
|
|
27
|
+
display_name="Search Field",
|
|
28
|
+
info="The field to search in",
|
|
29
|
+
options=["all", "title", "abstract", "author", "cat"], # cat is for category
|
|
30
|
+
value="all",
|
|
31
|
+
),
|
|
32
|
+
IntInput(
|
|
33
|
+
name="max_results",
|
|
34
|
+
display_name="Max Results",
|
|
35
|
+
info="Maximum number of results to return",
|
|
36
|
+
value=10,
|
|
37
|
+
),
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
outputs = [
|
|
41
|
+
Output(display_name="DataFrame", name="dataframe", method="search_papers_dataframe"),
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
def build_query_url(self) -> str:
|
|
45
|
+
"""Build the arXiv API query URL."""
|
|
46
|
+
base_url = "http://export.arxiv.org/api/query?"
|
|
47
|
+
|
|
48
|
+
# Build the search query based on search type
|
|
49
|
+
if self.search_type == "all":
|
|
50
|
+
search_query = self.search_query # No prefix for all fields
|
|
51
|
+
else:
|
|
52
|
+
# Map dropdown values to ArXiv API prefixes
|
|
53
|
+
prefix_map = {"title": "ti", "abstract": "abs", "author": "au", "cat": "cat"}
|
|
54
|
+
prefix = prefix_map.get(self.search_type, "")
|
|
55
|
+
search_query = f"{prefix}:{self.search_query}"
|
|
56
|
+
|
|
57
|
+
# URL parameters
|
|
58
|
+
params = {
|
|
59
|
+
"search_query": search_query,
|
|
60
|
+
"max_results": str(self.max_results),
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
# Convert params to URL query string
|
|
64
|
+
query_string = "&".join([f"{k}={urllib.parse.quote(str(v))}" for k, v in params.items()])
|
|
65
|
+
|
|
66
|
+
return base_url + query_string
|
|
67
|
+
|
|
68
|
+
def parse_atom_response(self, response_text: str) -> list[dict]:
|
|
69
|
+
"""Parse the Atom XML response from arXiv."""
|
|
70
|
+
# Parse XML safely using defusedxml
|
|
71
|
+
root = fromstring(response_text)
|
|
72
|
+
|
|
73
|
+
# Define namespace dictionary for XML parsing
|
|
74
|
+
ns = {"atom": "http://www.w3.org/2005/Atom", "arxiv": "http://arxiv.org/schemas/atom"}
|
|
75
|
+
|
|
76
|
+
papers = []
|
|
77
|
+
# Process each entry (paper)
|
|
78
|
+
for entry in root.findall("atom:entry", ns):
|
|
79
|
+
paper = {
|
|
80
|
+
"id": self._get_text(entry, "atom:id", ns),
|
|
81
|
+
"title": self._get_text(entry, "atom:title", ns),
|
|
82
|
+
"summary": self._get_text(entry, "atom:summary", ns),
|
|
83
|
+
"published": self._get_text(entry, "atom:published", ns),
|
|
84
|
+
"updated": self._get_text(entry, "atom:updated", ns),
|
|
85
|
+
"authors": [author.find("atom:name", ns).text for author in entry.findall("atom:author", ns)],
|
|
86
|
+
"arxiv_url": self._get_link(entry, "alternate", ns),
|
|
87
|
+
"pdf_url": self._get_link(entry, "related", ns),
|
|
88
|
+
"comment": self._get_text(entry, "arxiv:comment", ns),
|
|
89
|
+
"journal_ref": self._get_text(entry, "arxiv:journal_ref", ns),
|
|
90
|
+
"primary_category": self._get_category(entry, ns),
|
|
91
|
+
"categories": [cat.get("term") for cat in entry.findall("atom:category", ns)],
|
|
92
|
+
}
|
|
93
|
+
papers.append(paper)
|
|
94
|
+
|
|
95
|
+
return papers
|
|
96
|
+
|
|
97
|
+
def _get_text(self, element: Element, path: str, ns: dict) -> str | None:
|
|
98
|
+
"""Safely extract text from an XML element."""
|
|
99
|
+
el = element.find(path, ns)
|
|
100
|
+
return el.text.strip() if el is not None and el.text else None
|
|
101
|
+
|
|
102
|
+
def _get_link(self, element: Element, rel: str, ns: dict) -> str | None:
|
|
103
|
+
"""Get link URL based on relation type."""
|
|
104
|
+
for link in element.findall("atom:link", ns):
|
|
105
|
+
if link.get("rel") == rel:
|
|
106
|
+
return link.get("href")
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
def _get_category(self, element: Element, ns: dict) -> str | None:
|
|
110
|
+
"""Get primary category."""
|
|
111
|
+
cat = element.find("arxiv:primary_category", ns)
|
|
112
|
+
return cat.get("term") if cat is not None else None
|
|
113
|
+
|
|
114
|
+
def run_model(self) -> DataFrame:
|
|
115
|
+
return self.search_papers_dataframe()
|
|
116
|
+
|
|
117
|
+
def search_papers(self) -> list[Data]:
|
|
118
|
+
"""Search arXiv and return results."""
|
|
119
|
+
try:
|
|
120
|
+
# Build the query URL
|
|
121
|
+
url = self.build_query_url()
|
|
122
|
+
|
|
123
|
+
# Validate URL scheme and host
|
|
124
|
+
parsed_url = urlparse(url)
|
|
125
|
+
if parsed_url.scheme not in {"http", "https"}:
|
|
126
|
+
error_msg = f"Invalid URL scheme: {parsed_url.scheme}"
|
|
127
|
+
raise ValueError(error_msg)
|
|
128
|
+
if parsed_url.hostname != "export.arxiv.org":
|
|
129
|
+
error_msg = f"Invalid host: {parsed_url.hostname}"
|
|
130
|
+
raise ValueError(error_msg)
|
|
131
|
+
|
|
132
|
+
# Create a custom opener that only allows http/https schemes
|
|
133
|
+
class RestrictedHTTPHandler(urllib.request.HTTPHandler):
|
|
134
|
+
def http_open(self, req):
|
|
135
|
+
return super().http_open(req)
|
|
136
|
+
|
|
137
|
+
class RestrictedHTTPSHandler(urllib.request.HTTPSHandler):
|
|
138
|
+
def https_open(self, req):
|
|
139
|
+
return super().https_open(req)
|
|
140
|
+
|
|
141
|
+
# Build opener with restricted handlers
|
|
142
|
+
opener = urllib.request.build_opener(RestrictedHTTPHandler, RestrictedHTTPSHandler)
|
|
143
|
+
urllib.request.install_opener(opener)
|
|
144
|
+
|
|
145
|
+
# Make the request with validated URL using restricted opener
|
|
146
|
+
response = opener.open(url)
|
|
147
|
+
response_text = response.read().decode("utf-8")
|
|
148
|
+
|
|
149
|
+
# Parse the response
|
|
150
|
+
papers = self.parse_atom_response(response_text)
|
|
151
|
+
|
|
152
|
+
# Convert to Data objects
|
|
153
|
+
results = [Data(data=paper) for paper in papers]
|
|
154
|
+
self.status = results
|
|
155
|
+
except (urllib.error.URLError, ValueError) as e:
|
|
156
|
+
error_data = Data(data={"error": f"Request error: {e!s}"})
|
|
157
|
+
self.status = error_data
|
|
158
|
+
return [error_data]
|
|
159
|
+
else:
|
|
160
|
+
return results
|
|
161
|
+
|
|
162
|
+
def search_papers_dataframe(self) -> DataFrame:
|
|
163
|
+
"""Convert the Arxiv search results to a DataFrame.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
DataFrame: A DataFrame containing the search results.
|
|
167
|
+
"""
|
|
168
|
+
data = self.search_papers()
|
|
169
|
+
return DataFrame(data)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from lfx.components._importing import import_mod
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from .assemblyai_get_subtitles import AssemblyAIGetSubtitles
|
|
9
|
+
from .assemblyai_lemur import AssemblyAILeMUR
|
|
10
|
+
from .assemblyai_list_transcripts import AssemblyAIListTranscripts
|
|
11
|
+
from .assemblyai_poll_transcript import AssemblyAITranscriptionJobPoller
|
|
12
|
+
from .assemblyai_start_transcript import AssemblyAITranscriptionJobCreator
|
|
13
|
+
|
|
14
|
+
_dynamic_imports = {
|
|
15
|
+
"AssemblyAIGetSubtitles": "assemblyai_get_subtitles",
|
|
16
|
+
"AssemblyAILeMUR": "assemblyai_lemur",
|
|
17
|
+
"AssemblyAIListTranscripts": "assemblyai_list_transcripts",
|
|
18
|
+
"AssemblyAITranscriptionJobCreator": "assemblyai_start_transcript",
|
|
19
|
+
"AssemblyAITranscriptionJobPoller": "assemblyai_poll_transcript",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"AssemblyAIGetSubtitles",
|
|
24
|
+
"AssemblyAILeMUR",
|
|
25
|
+
"AssemblyAIListTranscripts",
|
|
26
|
+
"AssemblyAITranscriptionJobCreator",
|
|
27
|
+
"AssemblyAITranscriptionJobPoller",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def __getattr__(attr_name: str) -> Any:
|
|
32
|
+
"""Lazily import assemblyai components on attribute access."""
|
|
33
|
+
if attr_name not in _dynamic_imports:
|
|
34
|
+
msg = f"module '{__name__}' has no attribute '{attr_name}'"
|
|
35
|
+
raise AttributeError(msg)
|
|
36
|
+
try:
|
|
37
|
+
result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
|
|
38
|
+
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
|
39
|
+
msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
|
|
40
|
+
raise AttributeError(msg) from e
|
|
41
|
+
globals()[attr_name] = result
|
|
42
|
+
return result
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def __dir__() -> list[str]:
|
|
46
|
+
return list(__all__)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import assemblyai as aai
|
|
2
|
+
|
|
3
|
+
from lfx.custom.custom_component.component import Component
|
|
4
|
+
from lfx.io import DataInput, DropdownInput, IntInput, Output, SecretStrInput
|
|
5
|
+
from lfx.log.logger import logger
|
|
6
|
+
from lfx.schema.data import Data
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AssemblyAIGetSubtitles(Component):
|
|
10
|
+
display_name = "AssemblyAI Get Subtitles"
|
|
11
|
+
description = "Export your transcript in SRT or VTT format for subtitles and closed captions"
|
|
12
|
+
documentation = "https://www.assemblyai.com/docs"
|
|
13
|
+
icon = "AssemblyAI"
|
|
14
|
+
|
|
15
|
+
inputs = [
|
|
16
|
+
SecretStrInput(
|
|
17
|
+
name="api_key",
|
|
18
|
+
display_name="Assembly API Key",
|
|
19
|
+
info="Your AssemblyAI API key. You can get one from https://www.assemblyai.com/",
|
|
20
|
+
required=True,
|
|
21
|
+
),
|
|
22
|
+
DataInput(
|
|
23
|
+
name="transcription_result",
|
|
24
|
+
display_name="Transcription Result",
|
|
25
|
+
info="The transcription result from AssemblyAI",
|
|
26
|
+
required=True,
|
|
27
|
+
),
|
|
28
|
+
DropdownInput(
|
|
29
|
+
name="subtitle_format",
|
|
30
|
+
display_name="Subtitle Format",
|
|
31
|
+
options=["srt", "vtt"],
|
|
32
|
+
value="srt",
|
|
33
|
+
info="The format of the captions (SRT or VTT)",
|
|
34
|
+
),
|
|
35
|
+
IntInput(
|
|
36
|
+
name="chars_per_caption",
|
|
37
|
+
display_name="Characters per Caption",
|
|
38
|
+
info="The maximum number of characters per caption (0 for no limit)",
|
|
39
|
+
value=0,
|
|
40
|
+
advanced=True,
|
|
41
|
+
),
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
outputs = [
|
|
45
|
+
Output(display_name="Subtitles", name="subtitles", method="get_subtitles"),
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
def get_subtitles(self) -> Data:
|
|
49
|
+
aai.settings.api_key = self.api_key
|
|
50
|
+
|
|
51
|
+
# check if it's an error message from the previous step
|
|
52
|
+
if self.transcription_result.data.get("error"):
|
|
53
|
+
self.status = self.transcription_result.data["error"]
|
|
54
|
+
return self.transcription_result
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
transcript_id = self.transcription_result.data["id"]
|
|
58
|
+
transcript = aai.Transcript.get_by_id(transcript_id)
|
|
59
|
+
except Exception as e: # noqa: BLE001
|
|
60
|
+
error = f"Getting transcription failed: {e}"
|
|
61
|
+
logger.debug(error, exc_info=True)
|
|
62
|
+
self.status = error
|
|
63
|
+
return Data(data={"error": error})
|
|
64
|
+
|
|
65
|
+
if transcript.status == aai.TranscriptStatus.completed:
|
|
66
|
+
subtitles = None
|
|
67
|
+
chars_per_caption = self.chars_per_caption if self.chars_per_caption > 0 else None
|
|
68
|
+
if self.subtitle_format == "srt":
|
|
69
|
+
subtitles = transcript.export_subtitles_srt(chars_per_caption)
|
|
70
|
+
else:
|
|
71
|
+
subtitles = transcript.export_subtitles_vtt(chars_per_caption)
|
|
72
|
+
|
|
73
|
+
result = Data(
|
|
74
|
+
subtitles=subtitles,
|
|
75
|
+
format=self.subtitle_format,
|
|
76
|
+
transcript_id=transcript_id,
|
|
77
|
+
chars_per_caption=chars_per_caption,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
self.status = result
|
|
81
|
+
return result
|
|
82
|
+
self.status = transcript.error
|
|
83
|
+
return Data(data={"error": transcript.error})
|