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,338 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
import signal
|
|
3
|
+
import sys
|
|
4
|
+
import traceback
|
|
5
|
+
from contextlib import suppress
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from docling_core.types.doc import DoclingDocument
|
|
9
|
+
from pydantic import BaseModel, SecretStr, TypeAdapter
|
|
10
|
+
|
|
11
|
+
from lfx.log.logger import logger
|
|
12
|
+
from lfx.schema.data import Data
|
|
13
|
+
from lfx.schema.dataframe import DataFrame
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from langchain_core.language_models.chat_models import BaseChatModel
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DoclingDependencyError(Exception):
|
|
20
|
+
"""Custom exception for missing Docling dependencies."""
|
|
21
|
+
|
|
22
|
+
def __init__(self, dependency_name: str, install_command: str):
|
|
23
|
+
self.dependency_name = dependency_name
|
|
24
|
+
self.install_command = install_command
|
|
25
|
+
super().__init__(f"{dependency_name} is not correctly installed. {install_command}")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def extract_docling_documents(data_inputs: Data | list[Data] | DataFrame, doc_key: str) -> list[DoclingDocument]:
|
|
29
|
+
documents: list[DoclingDocument] = []
|
|
30
|
+
if isinstance(data_inputs, DataFrame):
|
|
31
|
+
if not len(data_inputs):
|
|
32
|
+
msg = "DataFrame is empty"
|
|
33
|
+
raise TypeError(msg)
|
|
34
|
+
|
|
35
|
+
if doc_key not in data_inputs.columns:
|
|
36
|
+
msg = f"Column '{doc_key}' not found in DataFrame"
|
|
37
|
+
raise TypeError(msg)
|
|
38
|
+
try:
|
|
39
|
+
documents = data_inputs[doc_key].tolist()
|
|
40
|
+
except Exception as e:
|
|
41
|
+
msg = f"Error extracting DoclingDocument from DataFrame: {e}"
|
|
42
|
+
raise TypeError(msg) from e
|
|
43
|
+
else:
|
|
44
|
+
if not data_inputs:
|
|
45
|
+
msg = "No data inputs provided"
|
|
46
|
+
raise TypeError(msg)
|
|
47
|
+
|
|
48
|
+
if isinstance(data_inputs, Data):
|
|
49
|
+
if doc_key not in data_inputs.data:
|
|
50
|
+
msg = (
|
|
51
|
+
f"'{doc_key}' field not available in the input Data. "
|
|
52
|
+
"Check that your input is a DoclingDocument. "
|
|
53
|
+
"You can use the Docling component to convert your input to a DoclingDocument."
|
|
54
|
+
)
|
|
55
|
+
raise TypeError(msg)
|
|
56
|
+
documents = [data_inputs.data[doc_key]]
|
|
57
|
+
else:
|
|
58
|
+
try:
|
|
59
|
+
documents = [
|
|
60
|
+
input_.data[doc_key]
|
|
61
|
+
for input_ in data_inputs
|
|
62
|
+
if isinstance(input_, Data)
|
|
63
|
+
and doc_key in input_.data
|
|
64
|
+
and isinstance(input_.data[doc_key], DoclingDocument)
|
|
65
|
+
]
|
|
66
|
+
if not documents:
|
|
67
|
+
msg = f"No valid Data inputs found in {type(data_inputs)}"
|
|
68
|
+
raise TypeError(msg)
|
|
69
|
+
except AttributeError as e:
|
|
70
|
+
msg = f"Invalid input type in collection: {e}"
|
|
71
|
+
raise TypeError(msg) from e
|
|
72
|
+
return documents
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _unwrap_secrets(obj):
|
|
76
|
+
if isinstance(obj, SecretStr):
|
|
77
|
+
return obj.get_secret_value()
|
|
78
|
+
if isinstance(obj, dict):
|
|
79
|
+
return {k: _unwrap_secrets(v) for k, v in obj.items()}
|
|
80
|
+
if isinstance(obj, list):
|
|
81
|
+
return [_unwrap_secrets(v) for v in obj]
|
|
82
|
+
return obj
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _dump_with_secrets(model: BaseModel):
|
|
86
|
+
return _unwrap_secrets(model.model_dump(mode="python", round_trip=True))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _serialize_pydantic_model(model: BaseModel):
|
|
90
|
+
return {
|
|
91
|
+
"__class_path__": f"{model.__class__.__module__}.{model.__class__.__name__}",
|
|
92
|
+
"config": _dump_with_secrets(model),
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _deserialize_pydantic_model(data: dict):
|
|
97
|
+
module_name, class_name = data["__class_path__"].rsplit(".", 1)
|
|
98
|
+
module = importlib.import_module(module_name)
|
|
99
|
+
cls = getattr(module, class_name)
|
|
100
|
+
adapter = TypeAdapter(cls)
|
|
101
|
+
return adapter.validate_python(data["config"])
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def docling_worker(
|
|
105
|
+
*,
|
|
106
|
+
file_paths: list[str],
|
|
107
|
+
queue,
|
|
108
|
+
pipeline: str,
|
|
109
|
+
ocr_engine: str,
|
|
110
|
+
do_picture_classification: bool,
|
|
111
|
+
pic_desc_config: dict | None,
|
|
112
|
+
pic_desc_prompt: str,
|
|
113
|
+
):
|
|
114
|
+
"""Worker function for processing files with Docling in a separate process."""
|
|
115
|
+
# Signal handling for graceful shutdown
|
|
116
|
+
shutdown_requested = False
|
|
117
|
+
|
|
118
|
+
def signal_handler(signum: int, frame) -> None: # noqa: ARG001
|
|
119
|
+
"""Handle shutdown signals gracefully."""
|
|
120
|
+
nonlocal shutdown_requested
|
|
121
|
+
signal_names: dict[int, str] = {signal.SIGTERM: "SIGTERM", signal.SIGINT: "SIGINT"}
|
|
122
|
+
signal_name = signal_names.get(signum, f"signal {signum}")
|
|
123
|
+
|
|
124
|
+
logger.debug(f"Docling worker received {signal_name}, initiating graceful shutdown...")
|
|
125
|
+
shutdown_requested = True
|
|
126
|
+
|
|
127
|
+
# Send shutdown notification to parent process
|
|
128
|
+
with suppress(Exception):
|
|
129
|
+
queue.put({"error": f"Worker interrupted by {signal_name}", "shutdown": True})
|
|
130
|
+
|
|
131
|
+
# Exit gracefully
|
|
132
|
+
sys.exit(0)
|
|
133
|
+
|
|
134
|
+
def check_shutdown() -> None:
|
|
135
|
+
"""Check if shutdown was requested and exit if so."""
|
|
136
|
+
if shutdown_requested:
|
|
137
|
+
logger.info("Shutdown requested, exiting worker...")
|
|
138
|
+
|
|
139
|
+
with suppress(Exception):
|
|
140
|
+
queue.put({"error": "Worker shutdown requested", "shutdown": True})
|
|
141
|
+
|
|
142
|
+
sys.exit(0)
|
|
143
|
+
|
|
144
|
+
# Register signal handlers early
|
|
145
|
+
try:
|
|
146
|
+
signal.signal(signal.SIGTERM, signal_handler)
|
|
147
|
+
signal.signal(signal.SIGINT, signal_handler)
|
|
148
|
+
logger.debug("Signal handlers registered for graceful shutdown")
|
|
149
|
+
except (OSError, ValueError) as e:
|
|
150
|
+
# Some signals might not be available on all platforms
|
|
151
|
+
logger.warning(f"Warning: Could not register signal handlers: {e}")
|
|
152
|
+
|
|
153
|
+
# Check for shutdown before heavy imports
|
|
154
|
+
check_shutdown()
|
|
155
|
+
|
|
156
|
+
try:
|
|
157
|
+
from docling.datamodel.base_models import ConversionStatus, InputFormat
|
|
158
|
+
from docling.datamodel.pipeline_options import OcrOptions, PdfPipelineOptions, VlmPipelineOptions
|
|
159
|
+
from docling.document_converter import DocumentConverter, FormatOption, PdfFormatOption
|
|
160
|
+
from docling.models.factories import get_ocr_factory
|
|
161
|
+
from docling.pipeline.vlm_pipeline import VlmPipeline
|
|
162
|
+
from langchain_docling.picture_description import PictureDescriptionLangChainOptions
|
|
163
|
+
|
|
164
|
+
# Check for shutdown after imports
|
|
165
|
+
check_shutdown()
|
|
166
|
+
logger.debug("Docling dependencies loaded successfully")
|
|
167
|
+
|
|
168
|
+
except ModuleNotFoundError:
|
|
169
|
+
msg = (
|
|
170
|
+
"Docling is an optional dependency of Langflow. "
|
|
171
|
+
"Install with `uv pip install 'langflow[docling]'` "
|
|
172
|
+
"or refer to the documentation"
|
|
173
|
+
)
|
|
174
|
+
queue.put({"error": msg})
|
|
175
|
+
return
|
|
176
|
+
except ImportError as e:
|
|
177
|
+
# A different import failed (e.g., a transitive dependency); preserve details.
|
|
178
|
+
queue.put({"error": f"Failed to import a Docling dependency: {e}"})
|
|
179
|
+
return
|
|
180
|
+
except KeyboardInterrupt:
|
|
181
|
+
logger.warning("KeyboardInterrupt during imports, exiting...")
|
|
182
|
+
queue.put({"error": "Worker interrupted during imports", "shutdown": True})
|
|
183
|
+
return
|
|
184
|
+
|
|
185
|
+
# Configure the standard PDF pipeline
|
|
186
|
+
def _get_standard_opts() -> PdfPipelineOptions:
|
|
187
|
+
check_shutdown() # Check before heavy operations
|
|
188
|
+
|
|
189
|
+
pipeline_options = PdfPipelineOptions()
|
|
190
|
+
pipeline_options.do_ocr = ocr_engine not in {"", "None"}
|
|
191
|
+
if pipeline_options.do_ocr:
|
|
192
|
+
ocr_factory = get_ocr_factory(
|
|
193
|
+
allow_external_plugins=False,
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
ocr_options: OcrOptions = ocr_factory.create_options(
|
|
197
|
+
kind=ocr_engine,
|
|
198
|
+
)
|
|
199
|
+
pipeline_options.ocr_options = ocr_options
|
|
200
|
+
|
|
201
|
+
pipeline_options.do_picture_classification = do_picture_classification
|
|
202
|
+
|
|
203
|
+
if pic_desc_config:
|
|
204
|
+
pic_desc_llm: BaseChatModel = _deserialize_pydantic_model(pic_desc_config)
|
|
205
|
+
|
|
206
|
+
logger.info("Docling enabling the picture description stage.")
|
|
207
|
+
pipeline_options.do_picture_description = True
|
|
208
|
+
pipeline_options.allow_external_plugins = True
|
|
209
|
+
pipeline_options.picture_description_options = PictureDescriptionLangChainOptions(
|
|
210
|
+
llm=pic_desc_llm,
|
|
211
|
+
prompt=pic_desc_prompt,
|
|
212
|
+
)
|
|
213
|
+
return pipeline_options
|
|
214
|
+
|
|
215
|
+
# Configure the VLM pipeline
|
|
216
|
+
def _get_vlm_opts() -> VlmPipelineOptions:
|
|
217
|
+
check_shutdown() # Check before heavy operations
|
|
218
|
+
return VlmPipelineOptions()
|
|
219
|
+
|
|
220
|
+
# Configure the main format options and create the DocumentConverter()
|
|
221
|
+
def _get_converter() -> DocumentConverter:
|
|
222
|
+
check_shutdown() # Check before heavy operations
|
|
223
|
+
|
|
224
|
+
if pipeline == "standard":
|
|
225
|
+
pdf_format_option = PdfFormatOption(
|
|
226
|
+
pipeline_options=_get_standard_opts(),
|
|
227
|
+
)
|
|
228
|
+
elif pipeline == "vlm":
|
|
229
|
+
pdf_format_option = PdfFormatOption(pipeline_cls=VlmPipeline, pipeline_options=_get_vlm_opts())
|
|
230
|
+
else:
|
|
231
|
+
msg = f"Unknown pipeline: {pipeline!r}"
|
|
232
|
+
raise ValueError(msg)
|
|
233
|
+
|
|
234
|
+
format_options: dict[InputFormat, FormatOption] = {
|
|
235
|
+
InputFormat.PDF: pdf_format_option,
|
|
236
|
+
InputFormat.IMAGE: pdf_format_option,
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return DocumentConverter(format_options=format_options)
|
|
240
|
+
|
|
241
|
+
try:
|
|
242
|
+
# Check for shutdown before creating converter (can be slow)
|
|
243
|
+
check_shutdown()
|
|
244
|
+
logger.info(f"Initializing {pipeline} pipeline with OCR: {ocr_engine or 'disabled'}")
|
|
245
|
+
|
|
246
|
+
converter = _get_converter()
|
|
247
|
+
|
|
248
|
+
# Check for shutdown before processing files
|
|
249
|
+
check_shutdown()
|
|
250
|
+
logger.info(f"Starting to process {len(file_paths)} files...")
|
|
251
|
+
|
|
252
|
+
# Process files with periodic shutdown checks
|
|
253
|
+
results = []
|
|
254
|
+
for i, file_path in enumerate(file_paths):
|
|
255
|
+
# Check for shutdown before processing each file
|
|
256
|
+
check_shutdown()
|
|
257
|
+
|
|
258
|
+
logger.debug(f"Processing file {i + 1}/{len(file_paths)}: {file_path}")
|
|
259
|
+
|
|
260
|
+
try:
|
|
261
|
+
single_result = converter.convert_all([file_path])
|
|
262
|
+
results.extend(single_result)
|
|
263
|
+
check_shutdown()
|
|
264
|
+
|
|
265
|
+
except ImportError as import_error:
|
|
266
|
+
# Simply pass ImportError to main process for handling
|
|
267
|
+
queue.put(
|
|
268
|
+
{"error": str(import_error), "error_type": "import_error", "original_exception": "ImportError"}
|
|
269
|
+
)
|
|
270
|
+
return
|
|
271
|
+
|
|
272
|
+
except (OSError, ValueError, RuntimeError) as file_error:
|
|
273
|
+
error_msg = str(file_error)
|
|
274
|
+
|
|
275
|
+
# Check for specific dependency errors and identify the dependency name
|
|
276
|
+
dependency_name = None
|
|
277
|
+
if "ocrmac is not correctly installed" in error_msg:
|
|
278
|
+
dependency_name = "ocrmac"
|
|
279
|
+
elif "easyocr" in error_msg and "not installed" in error_msg:
|
|
280
|
+
dependency_name = "easyocr"
|
|
281
|
+
elif "tesserocr" in error_msg and "not installed" in error_msg:
|
|
282
|
+
dependency_name = "tesserocr"
|
|
283
|
+
elif "rapidocr" in error_msg and "not installed" in error_msg:
|
|
284
|
+
dependency_name = "rapidocr"
|
|
285
|
+
|
|
286
|
+
if dependency_name:
|
|
287
|
+
queue.put(
|
|
288
|
+
{
|
|
289
|
+
"error": error_msg,
|
|
290
|
+
"error_type": "dependency_error",
|
|
291
|
+
"dependency_name": dependency_name,
|
|
292
|
+
"original_exception": type(file_error).__name__,
|
|
293
|
+
}
|
|
294
|
+
)
|
|
295
|
+
return
|
|
296
|
+
|
|
297
|
+
# If not a dependency error, log and continue with other files
|
|
298
|
+
logger.error(f"Error processing file {file_path}: {file_error}")
|
|
299
|
+
check_shutdown()
|
|
300
|
+
|
|
301
|
+
except Exception as file_error: # noqa: BLE001
|
|
302
|
+
logger.error(f"Unexpected error processing file {file_path}: {file_error}")
|
|
303
|
+
check_shutdown()
|
|
304
|
+
|
|
305
|
+
# Final shutdown check before sending results
|
|
306
|
+
check_shutdown()
|
|
307
|
+
|
|
308
|
+
# Process the results while maintaining the original structure
|
|
309
|
+
processed_data = [
|
|
310
|
+
{"document": res.document, "file_path": str(res.input.file), "status": res.status.name}
|
|
311
|
+
if res.status == ConversionStatus.SUCCESS
|
|
312
|
+
else None
|
|
313
|
+
for res in results
|
|
314
|
+
]
|
|
315
|
+
|
|
316
|
+
logger.info(f"Successfully processed {len([d for d in processed_data if d])} files")
|
|
317
|
+
queue.put(processed_data)
|
|
318
|
+
|
|
319
|
+
except KeyboardInterrupt:
|
|
320
|
+
logger.warning("KeyboardInterrupt during processing, exiting gracefully...")
|
|
321
|
+
queue.put({"error": "Worker interrupted during processing", "shutdown": True})
|
|
322
|
+
return
|
|
323
|
+
except Exception as e: # noqa: BLE001
|
|
324
|
+
if shutdown_requested:
|
|
325
|
+
logger.exception("Exception occurred during shutdown, exiting...")
|
|
326
|
+
return
|
|
327
|
+
|
|
328
|
+
# Send any processing error to the main process with traceback
|
|
329
|
+
error_info = {"error": str(e), "traceback": traceback.format_exc()}
|
|
330
|
+
logger.error(f"Error in worker: {error_info}")
|
|
331
|
+
queue.put(error_info)
|
|
332
|
+
finally:
|
|
333
|
+
logger.info("Docling worker finishing...")
|
|
334
|
+
# Ensure we don't leave any hanging processes
|
|
335
|
+
if shutdown_requested:
|
|
336
|
+
logger.debug("Worker shutdown completed")
|
|
337
|
+
else:
|
|
338
|
+
logger.debug("Worker completed normally")
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""Storage-aware file utilities for components.
|
|
2
|
+
|
|
3
|
+
This module provides utilities that work with both local files and remote files
|
|
4
|
+
stored in the storage service.
|
|
5
|
+
|
|
6
|
+
TODO: Can abstract these into the storage service interface and update
|
|
7
|
+
implementations.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import TYPE_CHECKING
|
|
14
|
+
|
|
15
|
+
from lfx.services.deps import get_settings_service, get_storage_service
|
|
16
|
+
from lfx.utils.async_helpers import run_until_complete
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from collections.abc import Callable
|
|
20
|
+
|
|
21
|
+
from lfx.services.storage.service import StorageService
|
|
22
|
+
|
|
23
|
+
# Constants for path parsing
|
|
24
|
+
EXPECTED_PATH_PARTS = 2 # Path format: "flow_id/filename"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def parse_storage_path(path: str) -> tuple[str, str] | None:
|
|
28
|
+
"""Parse a storage service path into flow_id and filename.
|
|
29
|
+
|
|
30
|
+
Storage service paths follow the format: flow_id/filename
|
|
31
|
+
This should only be called when storage_type == "s3".
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
path: The storage service path in format "flow_id/filename"
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
tuple[str, str] | None: (flow_id, filename) or None if invalid format
|
|
38
|
+
"""
|
|
39
|
+
if not path or "/" not in path:
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
parts = path.split("/", 1)
|
|
43
|
+
if len(parts) != EXPECTED_PATH_PARTS or not parts[0] or not parts[1]:
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
return parts[0], parts[1]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
async def read_file_bytes(
|
|
50
|
+
file_path: str,
|
|
51
|
+
storage_service: StorageService | None = None,
|
|
52
|
+
resolve_path: Callable[[str], str] | None = None,
|
|
53
|
+
) -> bytes:
|
|
54
|
+
"""Read file bytes from either storage service or local filesystem.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
file_path: Path to the file (S3 key format "flow_id/filename" or local path)
|
|
58
|
+
storage_service: Optional storage service instance (will get from deps if not provided)
|
|
59
|
+
resolve_path: Optional function to resolve relative paths to absolute paths
|
|
60
|
+
(typically Component.resolve_path). Only used for local storage.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
bytes: The file content
|
|
64
|
+
|
|
65
|
+
Raises:
|
|
66
|
+
FileNotFoundError: If the file doesn't exist
|
|
67
|
+
"""
|
|
68
|
+
settings = get_settings_service().settings
|
|
69
|
+
|
|
70
|
+
if settings.storage_type == "s3":
|
|
71
|
+
parsed = parse_storage_path(file_path)
|
|
72
|
+
if not parsed:
|
|
73
|
+
msg = f"Invalid S3 path format: {file_path}. Expected 'flow_id/filename'"
|
|
74
|
+
raise ValueError(msg)
|
|
75
|
+
|
|
76
|
+
if storage_service is None:
|
|
77
|
+
storage_service = get_storage_service()
|
|
78
|
+
|
|
79
|
+
flow_id, filename = parsed
|
|
80
|
+
return await storage_service.get_file(flow_id, filename)
|
|
81
|
+
|
|
82
|
+
# For local storage, resolve path if resolver provided
|
|
83
|
+
if resolve_path:
|
|
84
|
+
file_path = resolve_path(file_path)
|
|
85
|
+
|
|
86
|
+
path_obj = Path(file_path)
|
|
87
|
+
if not path_obj.exists():
|
|
88
|
+
msg = f"File not found: {file_path}"
|
|
89
|
+
raise FileNotFoundError(msg)
|
|
90
|
+
|
|
91
|
+
return path_obj.read_bytes()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
async def read_file_text(
|
|
95
|
+
file_path: str,
|
|
96
|
+
encoding: str = "utf-8",
|
|
97
|
+
storage_service: StorageService | None = None,
|
|
98
|
+
resolve_path: Callable[[str], str] | None = None,
|
|
99
|
+
newline: str | None = None,
|
|
100
|
+
) -> str:
|
|
101
|
+
r"""Read file text from either storage service or local filesystem.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
file_path: Path to the file (storage service path or local path)
|
|
105
|
+
encoding: Text encoding to use
|
|
106
|
+
storage_service: Optional storage service instance
|
|
107
|
+
resolve_path: Optional function to resolve relative paths to absolute paths
|
|
108
|
+
(typically Component.resolve_path). Only used for local storage.
|
|
109
|
+
newline: Newline mode (None for default, "" for universal newlines like CSV).
|
|
110
|
+
When set to "", normalizes all line endings to \\n for consistency.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
str: The file content as text
|
|
114
|
+
|
|
115
|
+
Raises:
|
|
116
|
+
FileNotFoundError: If the file doesn't exist
|
|
117
|
+
"""
|
|
118
|
+
settings = get_settings_service().settings
|
|
119
|
+
|
|
120
|
+
if settings.storage_type == "s3":
|
|
121
|
+
content = await read_file_bytes(file_path, storage_service, resolve_path)
|
|
122
|
+
text = content.decode(encoding)
|
|
123
|
+
# Normalize newlines for S3 when newline="" is specified (universal newline mode)
|
|
124
|
+
if newline == "":
|
|
125
|
+
# Convert all line endings to \n (matches Python's universal newline mode)
|
|
126
|
+
text = text.replace("\r\n", "\n").replace("\r", "\n")
|
|
127
|
+
return text
|
|
128
|
+
# For local storage, resolve path if resolver provided
|
|
129
|
+
if resolve_path:
|
|
130
|
+
file_path = resolve_path(file_path)
|
|
131
|
+
|
|
132
|
+
path_obj = Path(file_path)
|
|
133
|
+
if newline is not None:
|
|
134
|
+
with path_obj.open(newline=newline, encoding=encoding) as f: # noqa: ASYNC230
|
|
135
|
+
return f.read()
|
|
136
|
+
return path_obj.read_text(encoding=encoding)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def get_file_size(file_path: str, storage_service: StorageService | None = None) -> int:
|
|
140
|
+
"""Get file size from either storage service or local filesystem.
|
|
141
|
+
|
|
142
|
+
Note: This is a sync wrapper - for async code, use the storage service directly.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
file_path: Path to the file (S3 key format "flow_id/filename" or absolute local path)
|
|
146
|
+
storage_service: Optional storage service instance
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
int: File size in bytes
|
|
150
|
+
|
|
151
|
+
Raises:
|
|
152
|
+
FileNotFoundError: If the file doesn't exist
|
|
153
|
+
"""
|
|
154
|
+
settings = get_settings_service().settings
|
|
155
|
+
|
|
156
|
+
if settings.storage_type == "s3":
|
|
157
|
+
parsed = parse_storage_path(file_path)
|
|
158
|
+
if not parsed:
|
|
159
|
+
msg = f"Invalid S3 path format: {file_path}. Expected 'flow_id/filename'"
|
|
160
|
+
raise ValueError(msg)
|
|
161
|
+
|
|
162
|
+
if storage_service is None:
|
|
163
|
+
storage_service = get_storage_service()
|
|
164
|
+
|
|
165
|
+
flow_id, filename = parsed
|
|
166
|
+
return run_until_complete(storage_service.get_file_size(flow_id, filename))
|
|
167
|
+
|
|
168
|
+
# Local file system
|
|
169
|
+
path_obj = Path(file_path)
|
|
170
|
+
if not path_obj.exists():
|
|
171
|
+
msg = f"File not found: {file_path}"
|
|
172
|
+
raise FileNotFoundError(msg)
|
|
173
|
+
|
|
174
|
+
return path_obj.stat().st_size
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def file_exists(file_path: str, storage_service: StorageService | None = None) -> bool:
|
|
178
|
+
"""Check if a file exists in either storage service or local filesystem.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
file_path: Path to the file (S3 key format "flow_id/filename" or absolute local path)
|
|
182
|
+
storage_service: Optional storage service instance
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
bool: True if the file exists
|
|
186
|
+
"""
|
|
187
|
+
try:
|
|
188
|
+
get_file_size(file_path, storage_service)
|
|
189
|
+
except (FileNotFoundError, ValueError):
|
|
190
|
+
return False
|
|
191
|
+
else:
|
|
192
|
+
return True
|