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,193 @@
|
|
|
1
|
+
from abc import abstractmethod
|
|
2
|
+
from functools import wraps
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from lfx.custom.custom_component.component import Component
|
|
6
|
+
from lfx.field_typing import Text, VectorStore
|
|
7
|
+
from lfx.helpers.data import docs_to_data
|
|
8
|
+
from lfx.inputs.inputs import BoolInput
|
|
9
|
+
from lfx.io import HandleInput, Output, QueryInput
|
|
10
|
+
from lfx.schema.data import Data
|
|
11
|
+
from lfx.schema.dataframe import DataFrame
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from langchain_core.documents import Document
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def check_cached_vector_store(f):
|
|
18
|
+
"""Decorator to check for cached vector stores, and returns them if they exist.
|
|
19
|
+
|
|
20
|
+
Note: caching only occurs during the execution of a component - they do not persist
|
|
21
|
+
across separate invocations of the component. This method exists so that components with
|
|
22
|
+
multiple output methods share the same vector store during the same invocation of the
|
|
23
|
+
component.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
@wraps(f)
|
|
27
|
+
def check_cached(self, *args, **kwargs):
|
|
28
|
+
should_cache = getattr(self, "should_cache_vector_store", True)
|
|
29
|
+
|
|
30
|
+
if should_cache and self._cached_vector_store is not None:
|
|
31
|
+
return self._cached_vector_store
|
|
32
|
+
|
|
33
|
+
result = f(self, *args, **kwargs)
|
|
34
|
+
self._cached_vector_store = result
|
|
35
|
+
return result
|
|
36
|
+
|
|
37
|
+
check_cached.is_cached_vector_store_checked = True
|
|
38
|
+
return check_cached
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class LCVectorStoreComponent(Component):
|
|
42
|
+
# Used to ensure a single vector store is built for each run of the flow
|
|
43
|
+
_cached_vector_store: VectorStore | None = None
|
|
44
|
+
|
|
45
|
+
def __init_subclass__(cls, **kwargs):
|
|
46
|
+
"""Enforces the check cached decorator on all subclasses."""
|
|
47
|
+
super().__init_subclass__(**kwargs)
|
|
48
|
+
if hasattr(cls, "build_vector_store"):
|
|
49
|
+
method = cls.build_vector_store
|
|
50
|
+
if not hasattr(method, "is_cached_vector_store_checked"):
|
|
51
|
+
msg = (
|
|
52
|
+
f"The method 'build_vector_store' in class {cls.__name__} "
|
|
53
|
+
"must be decorated with @check_cached_vector_store"
|
|
54
|
+
)
|
|
55
|
+
raise TypeError(msg)
|
|
56
|
+
|
|
57
|
+
trace_type = "retriever"
|
|
58
|
+
|
|
59
|
+
inputs = [
|
|
60
|
+
HandleInput(
|
|
61
|
+
name="ingest_data",
|
|
62
|
+
display_name="Ingest Data",
|
|
63
|
+
input_types=["Data", "DataFrame"],
|
|
64
|
+
is_list=True,
|
|
65
|
+
),
|
|
66
|
+
QueryInput(
|
|
67
|
+
name="search_query",
|
|
68
|
+
display_name="Search Query",
|
|
69
|
+
info="Enter a query to run a similarity search.",
|
|
70
|
+
placeholder="Enter a query...",
|
|
71
|
+
tool_mode=True,
|
|
72
|
+
),
|
|
73
|
+
BoolInput(
|
|
74
|
+
name="should_cache_vector_store",
|
|
75
|
+
display_name="Cache Vector Store",
|
|
76
|
+
value=True,
|
|
77
|
+
advanced=True,
|
|
78
|
+
info="If True, the vector store will be cached for the current build of the component. "
|
|
79
|
+
"This is useful for components that have multiple output methods and want to share the same vector store.",
|
|
80
|
+
),
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
outputs = [
|
|
84
|
+
Output(
|
|
85
|
+
display_name="Search Results",
|
|
86
|
+
name="search_results",
|
|
87
|
+
method="search_documents",
|
|
88
|
+
),
|
|
89
|
+
Output(display_name="DataFrame", name="dataframe", method="as_dataframe"),
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
def _validate_outputs(self) -> None:
|
|
93
|
+
# At least these three outputs must be defined
|
|
94
|
+
required_output_methods = [
|
|
95
|
+
"search_documents",
|
|
96
|
+
"build_vector_store",
|
|
97
|
+
]
|
|
98
|
+
output_names = [output.name for output in self.outputs]
|
|
99
|
+
for method_name in required_output_methods:
|
|
100
|
+
if method_name not in output_names:
|
|
101
|
+
msg = f"Output with name '{method_name}' must be defined."
|
|
102
|
+
raise ValueError(msg)
|
|
103
|
+
if not hasattr(self, method_name):
|
|
104
|
+
msg = f"Method '{method_name}' must be defined."
|
|
105
|
+
raise ValueError(msg)
|
|
106
|
+
|
|
107
|
+
def _prepare_ingest_data(self) -> list[Any]:
|
|
108
|
+
"""Prepares ingest_data by converting DataFrame to Data if needed."""
|
|
109
|
+
ingest_data: list | Data | DataFrame = self.ingest_data
|
|
110
|
+
if not ingest_data:
|
|
111
|
+
return []
|
|
112
|
+
|
|
113
|
+
if not isinstance(ingest_data, list):
|
|
114
|
+
ingest_data = [ingest_data]
|
|
115
|
+
|
|
116
|
+
result = []
|
|
117
|
+
|
|
118
|
+
for _input in ingest_data:
|
|
119
|
+
if isinstance(_input, DataFrame):
|
|
120
|
+
result.extend(_input.to_data_list())
|
|
121
|
+
else:
|
|
122
|
+
result.append(_input)
|
|
123
|
+
return result
|
|
124
|
+
|
|
125
|
+
def search_with_vector_store(
|
|
126
|
+
self,
|
|
127
|
+
input_value: Text,
|
|
128
|
+
search_type: str,
|
|
129
|
+
vector_store: VectorStore,
|
|
130
|
+
k=10,
|
|
131
|
+
**kwargs,
|
|
132
|
+
) -> list[Data]:
|
|
133
|
+
"""Search for data in the vector store based on the input value and search type.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
input_value (Text): The input value to search for.
|
|
137
|
+
search_type (str): The type of search to perform.
|
|
138
|
+
vector_store (VectorStore): The vector store to search in.
|
|
139
|
+
k (int): The number of results to return.
|
|
140
|
+
**kwargs: Additional keyword arguments to pass to the vector store search method.
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
List[Data]: A list of data matching the search criteria.
|
|
144
|
+
|
|
145
|
+
Raises:
|
|
146
|
+
ValueError: If invalid inputs are provided.
|
|
147
|
+
"""
|
|
148
|
+
docs: list[Document] = []
|
|
149
|
+
if input_value and isinstance(input_value, str) and hasattr(vector_store, "search"):
|
|
150
|
+
docs = vector_store.search(query=input_value, search_type=search_type.lower(), k=k, **kwargs)
|
|
151
|
+
else:
|
|
152
|
+
msg = "Invalid inputs provided."
|
|
153
|
+
raise ValueError(msg)
|
|
154
|
+
data = docs_to_data(docs)
|
|
155
|
+
self.status = data
|
|
156
|
+
return data
|
|
157
|
+
|
|
158
|
+
def search_documents(self) -> list[Data]:
|
|
159
|
+
"""Search for documents in the vector store."""
|
|
160
|
+
if self._cached_vector_store is not None:
|
|
161
|
+
vector_store = self._cached_vector_store
|
|
162
|
+
else:
|
|
163
|
+
vector_store = self.build_vector_store()
|
|
164
|
+
self._cached_vector_store = vector_store
|
|
165
|
+
|
|
166
|
+
search_query: str = self.search_query
|
|
167
|
+
if not search_query:
|
|
168
|
+
self.status = ""
|
|
169
|
+
return []
|
|
170
|
+
|
|
171
|
+
self.log(f"Search input: {search_query}")
|
|
172
|
+
self.log(f"Search type: {self.search_type}")
|
|
173
|
+
self.log(f"Number of results: {self.number_of_results}")
|
|
174
|
+
|
|
175
|
+
search_results = self.search_with_vector_store(
|
|
176
|
+
search_query, self.search_type, vector_store, k=self.number_of_results
|
|
177
|
+
)
|
|
178
|
+
self.status = search_results
|
|
179
|
+
return search_results
|
|
180
|
+
|
|
181
|
+
def as_dataframe(self) -> DataFrame:
|
|
182
|
+
return DataFrame(self.search_documents())
|
|
183
|
+
|
|
184
|
+
def get_retriever_kwargs(self):
|
|
185
|
+
"""Get the retriever kwargs. Implementations can override this method to provide custom retriever kwargs."""
|
|
186
|
+
return {}
|
|
187
|
+
|
|
188
|
+
@abstractmethod
|
|
189
|
+
@check_cached_vector_store
|
|
190
|
+
def build_vector_store(self) -> VectorStore:
|
|
191
|
+
"""Builds the Vector Store object."""
|
|
192
|
+
msg = "build_vector_store method must be implemented."
|
|
193
|
+
raise NotImplementedError(msg)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from lfx.schema.data import Data
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def chroma_collection_to_data(collection_dict: dict):
|
|
5
|
+
"""Converts a collection of chroma vectors into a list of data.
|
|
6
|
+
|
|
7
|
+
Args:
|
|
8
|
+
collection_dict (dict): A dictionary containing the collection of chroma vectors.
|
|
9
|
+
|
|
10
|
+
Returns:
|
|
11
|
+
list: A list of data, where each record represents a document in the collection.
|
|
12
|
+
"""
|
|
13
|
+
data = []
|
|
14
|
+
for i, doc in enumerate(collection_dict["documents"]):
|
|
15
|
+
data_dict = {
|
|
16
|
+
"id": collection_dict["ids"][i],
|
|
17
|
+
"text": doc,
|
|
18
|
+
}
|
|
19
|
+
if ("metadatas" in collection_dict) and collection_dict["metadatas"][i]:
|
|
20
|
+
data_dict.update(collection_dict["metadatas"][i].items())
|
|
21
|
+
data.append(Data(**data_dict))
|
|
22
|
+
return data
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from langchain_core.vectorstores import VectorStore
|
|
2
|
+
|
|
3
|
+
from lfx.io import Output
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def vector_store_connection(cls):
|
|
7
|
+
"""A decorator that adds vector store connection functionality to a class.
|
|
8
|
+
|
|
9
|
+
This decorator performs the following actions:
|
|
10
|
+
1. Adds a `decorated` attribute to the class and sets it to True.
|
|
11
|
+
2. Checks if the class has an `outputs` attribute:
|
|
12
|
+
- If it does, it makes a copy of the `outputs` attribute to avoid modifying the base class attribute.
|
|
13
|
+
- It then checks if "vectorstoreconnection" is not already in the output names.
|
|
14
|
+
- If not, it adds a new `Output` entry for "Vector Store Connection" to the `outputs` attribute.
|
|
15
|
+
3. Adds an `as_vector_store` method to the class, which returns the result of the `build_vector_store` method.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
cls (type): The class to be decorated.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
type: The decorated class with added vector store connection functionality.
|
|
22
|
+
"""
|
|
23
|
+
cls.decorated = True # Add an attribute to the class
|
|
24
|
+
|
|
25
|
+
if hasattr(cls, "outputs"):
|
|
26
|
+
cls.outputs = cls.outputs.copy() # Make a copy to avoid modifying the base class attribute
|
|
27
|
+
output_names = [output.name for output in cls.outputs]
|
|
28
|
+
|
|
29
|
+
if "vectorstoreconnection" not in output_names:
|
|
30
|
+
cls.outputs.extend(
|
|
31
|
+
[
|
|
32
|
+
Output(
|
|
33
|
+
display_name="Vector Store Connection",
|
|
34
|
+
hidden=False,
|
|
35
|
+
name="vectorstoreconnection",
|
|
36
|
+
method="as_vector_store",
|
|
37
|
+
group_outputs=False,
|
|
38
|
+
)
|
|
39
|
+
]
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def as_vector_store(self) -> VectorStore:
|
|
43
|
+
"""Converts the current instance to a VectorStore object.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
VectorStore: The resulting VectorStore object.
|
|
47
|
+
"""
|
|
48
|
+
return self.build_vector_store()
|
|
49
|
+
|
|
50
|
+
cls.as_vector_store = as_vector_store # Ensures that the method is added to the class
|
|
51
|
+
|
|
52
|
+
return cls
|
lfx/cli/__init__.py
ADDED
lfx/cli/commands.py
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
"""CLI commands for LFX."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import tempfile
|
|
9
|
+
from functools import partial
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
import typer
|
|
13
|
+
import uvicorn
|
|
14
|
+
from asyncer import syncify
|
|
15
|
+
from dotenv import load_dotenv
|
|
16
|
+
from rich.console import Console
|
|
17
|
+
from rich.panel import Panel
|
|
18
|
+
|
|
19
|
+
from lfx.cli.common import (
|
|
20
|
+
create_verbose_printer,
|
|
21
|
+
flow_id_from_path,
|
|
22
|
+
get_api_key,
|
|
23
|
+
get_best_access_host,
|
|
24
|
+
get_free_port,
|
|
25
|
+
is_port_in_use,
|
|
26
|
+
load_graph_from_path,
|
|
27
|
+
)
|
|
28
|
+
from lfx.cli.serve_app import FlowMeta, create_multi_serve_app
|
|
29
|
+
|
|
30
|
+
# Initialize console
|
|
31
|
+
console = Console()
|
|
32
|
+
|
|
33
|
+
# Constants
|
|
34
|
+
API_KEY_MASK_LENGTH = 8
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@partial(syncify, raise_sync_error=False)
|
|
38
|
+
async def serve_command(
|
|
39
|
+
script_path: str | None = typer.Argument(
|
|
40
|
+
None,
|
|
41
|
+
help=(
|
|
42
|
+
"Path to JSON flow (.json) or Python script (.py) file or stdin input. "
|
|
43
|
+
"Optional when using --flow-json or --stdin."
|
|
44
|
+
),
|
|
45
|
+
),
|
|
46
|
+
host: str = typer.Option("127.0.0.1", "--host", "-h", help="Host to bind the server to"),
|
|
47
|
+
port: int = typer.Option(8000, "--port", "-p", help="Port to bind the server to"),
|
|
48
|
+
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show diagnostic output and execution details"), # noqa: FBT001, FBT003
|
|
49
|
+
env_file: Path | None = typer.Option(
|
|
50
|
+
None,
|
|
51
|
+
"--env-file",
|
|
52
|
+
help="Path to the .env file containing environment variables",
|
|
53
|
+
),
|
|
54
|
+
log_level: str = typer.Option(
|
|
55
|
+
"warning",
|
|
56
|
+
"--log-level",
|
|
57
|
+
help="Logging level. One of: debug, info, warning, error, critical",
|
|
58
|
+
),
|
|
59
|
+
flow_json: str | None = typer.Option(
|
|
60
|
+
None,
|
|
61
|
+
"--flow-json",
|
|
62
|
+
help="Inline JSON flow content as a string (alternative to script_path)",
|
|
63
|
+
),
|
|
64
|
+
*,
|
|
65
|
+
stdin: bool = typer.Option(
|
|
66
|
+
False, # noqa: FBT003
|
|
67
|
+
"--stdin",
|
|
68
|
+
help="Read JSON flow content from stdin (alternative to script_path)",
|
|
69
|
+
),
|
|
70
|
+
check_variables: bool = typer.Option(
|
|
71
|
+
True, # noqa: FBT003
|
|
72
|
+
"--check-variables/--no-check-variables",
|
|
73
|
+
help="Check global variables for environment compatibility",
|
|
74
|
+
),
|
|
75
|
+
) -> None:
|
|
76
|
+
"""Serve LFX flows as a web API.
|
|
77
|
+
|
|
78
|
+
Supports single files, inline JSON, and stdin input.
|
|
79
|
+
|
|
80
|
+
Examples:
|
|
81
|
+
# Serve from file
|
|
82
|
+
lfx serve my_flow.json
|
|
83
|
+
|
|
84
|
+
# Serve inline JSON
|
|
85
|
+
lfx serve --flow-json '{"nodes": [...], "edges": [...]}'
|
|
86
|
+
|
|
87
|
+
# Serve from stdin
|
|
88
|
+
cat my_flow.json | lfx serve --stdin
|
|
89
|
+
echo '{"nodes": [...]}' | lfx serve --stdin
|
|
90
|
+
"""
|
|
91
|
+
# Configure logging with the specified level and import logger
|
|
92
|
+
from lfx.log.logger import configure, logger
|
|
93
|
+
|
|
94
|
+
configure(log_level=log_level)
|
|
95
|
+
|
|
96
|
+
verbose_print = create_verbose_printer(verbose=verbose)
|
|
97
|
+
|
|
98
|
+
# Validate input sources - exactly one must be provided
|
|
99
|
+
input_sources = [script_path is not None, flow_json is not None, stdin]
|
|
100
|
+
if sum(input_sources) != 1:
|
|
101
|
+
if sum(input_sources) == 0:
|
|
102
|
+
verbose_print("Error: Must provide either script_path, --flow-json, or --stdin")
|
|
103
|
+
else:
|
|
104
|
+
verbose_print("Error: Cannot use script_path, --flow-json, and --stdin together. Choose exactly one.")
|
|
105
|
+
raise typer.Exit(1)
|
|
106
|
+
|
|
107
|
+
# Load environment variables from .env file if provided
|
|
108
|
+
if env_file:
|
|
109
|
+
if not env_file.exists():
|
|
110
|
+
verbose_print(f"Error: Environment file '{env_file}' does not exist.")
|
|
111
|
+
raise typer.Exit(1)
|
|
112
|
+
|
|
113
|
+
verbose_print(f"Loading environment variables from: {env_file}")
|
|
114
|
+
load_dotenv(env_file)
|
|
115
|
+
|
|
116
|
+
# Validate API key
|
|
117
|
+
try:
|
|
118
|
+
api_key = get_api_key()
|
|
119
|
+
verbose_print("ā LANGFLOW_API_KEY is configured")
|
|
120
|
+
except ValueError as e:
|
|
121
|
+
typer.echo(f"ā {e}", err=True)
|
|
122
|
+
typer.echo("Set the LANGFLOW_API_KEY environment variable before serving.", err=True)
|
|
123
|
+
raise typer.Exit(1) from e
|
|
124
|
+
|
|
125
|
+
# Validate log level
|
|
126
|
+
valid_log_levels = {"debug", "info", "warning", "error", "critical"}
|
|
127
|
+
if log_level.lower() not in valid_log_levels:
|
|
128
|
+
verbose_print(f"Error: Invalid log level '{log_level}'. Must be one of: {', '.join(sorted(valid_log_levels))}")
|
|
129
|
+
raise typer.Exit(1)
|
|
130
|
+
|
|
131
|
+
# Configure logging with the specified level
|
|
132
|
+
# Disable pretty logs for serve command to avoid ANSI codes in API responses
|
|
133
|
+
os.environ["LANGFLOW_PRETTY_LOGS"] = "false"
|
|
134
|
+
verbose_print(f"Configuring logging with level: {log_level}")
|
|
135
|
+
from lfx.log.logger import configure
|
|
136
|
+
|
|
137
|
+
configure(log_level=log_level)
|
|
138
|
+
|
|
139
|
+
# ------------------------------------------------------------------
|
|
140
|
+
# Handle inline JSON content or stdin input
|
|
141
|
+
# ------------------------------------------------------------------
|
|
142
|
+
temp_file_to_cleanup = None
|
|
143
|
+
|
|
144
|
+
if flow_json is not None:
|
|
145
|
+
logger.info("Processing inline JSON content...")
|
|
146
|
+
try:
|
|
147
|
+
# Validate JSON syntax
|
|
148
|
+
json_data = json.loads(flow_json)
|
|
149
|
+
logger.info("JSON content is valid")
|
|
150
|
+
|
|
151
|
+
# Create a temporary file with the JSON content
|
|
152
|
+
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as temp_file:
|
|
153
|
+
json.dump(json_data, temp_file, indent=2)
|
|
154
|
+
temp_file_to_cleanup = temp_file.name
|
|
155
|
+
|
|
156
|
+
script_path = temp_file_to_cleanup
|
|
157
|
+
logger.info(f"Created temporary file: {script_path}")
|
|
158
|
+
|
|
159
|
+
except json.JSONDecodeError as e:
|
|
160
|
+
typer.echo(f"Error: Invalid JSON content: {e}", err=True)
|
|
161
|
+
raise typer.Exit(1) from e
|
|
162
|
+
except Exception as e:
|
|
163
|
+
verbose_print(f"Error processing JSON content: {e}")
|
|
164
|
+
raise typer.Exit(1) from e
|
|
165
|
+
|
|
166
|
+
elif stdin:
|
|
167
|
+
logger.info("Reading JSON content from stdin...")
|
|
168
|
+
try:
|
|
169
|
+
# Read all content from stdin
|
|
170
|
+
stdin_content = sys.stdin.read().strip()
|
|
171
|
+
if not stdin_content:
|
|
172
|
+
logger.error("No content received from stdin")
|
|
173
|
+
raise typer.Exit(1)
|
|
174
|
+
|
|
175
|
+
# Validate JSON syntax
|
|
176
|
+
json_data = json.loads(stdin_content)
|
|
177
|
+
logger.info("JSON content from stdin is valid")
|
|
178
|
+
|
|
179
|
+
# Create a temporary file with the JSON content
|
|
180
|
+
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as temp_file:
|
|
181
|
+
json.dump(json_data, temp_file, indent=2)
|
|
182
|
+
temp_file_to_cleanup = temp_file.name
|
|
183
|
+
|
|
184
|
+
script_path = temp_file_to_cleanup
|
|
185
|
+
logger.info(f"Created temporary file from stdin: {script_path}")
|
|
186
|
+
|
|
187
|
+
except json.JSONDecodeError as e:
|
|
188
|
+
verbose_print(f"Error: Invalid JSON content from stdin: {e}")
|
|
189
|
+
raise typer.Exit(1) from e
|
|
190
|
+
except Exception as e:
|
|
191
|
+
verbose_print(f"Error reading from stdin: {e}")
|
|
192
|
+
raise typer.Exit(1) from e
|
|
193
|
+
|
|
194
|
+
try:
|
|
195
|
+
# Load the graph
|
|
196
|
+
if script_path is None:
|
|
197
|
+
verbose_print("Error: script_path is None after input validation")
|
|
198
|
+
raise typer.Exit(1)
|
|
199
|
+
|
|
200
|
+
resolved_path = Path(script_path).resolve()
|
|
201
|
+
|
|
202
|
+
if not resolved_path.exists():
|
|
203
|
+
typer.echo(f"Error: File '{resolved_path}' does not exist.", err=True)
|
|
204
|
+
raise typer.Exit(1)
|
|
205
|
+
|
|
206
|
+
if resolved_path.suffix == ".json":
|
|
207
|
+
graph = await load_graph_from_path(resolved_path, resolved_path.suffix, verbose_print, verbose=verbose)
|
|
208
|
+
elif resolved_path.suffix == ".py":
|
|
209
|
+
verbose_print("Loading graph from Python script...")
|
|
210
|
+
from lfx.cli.script_loader import load_graph_from_script
|
|
211
|
+
|
|
212
|
+
graph = await load_graph_from_script(resolved_path)
|
|
213
|
+
verbose_print("ā Graph loaded from Python script")
|
|
214
|
+
else:
|
|
215
|
+
err_msg = "Error: Only JSON flow files (.json) or Python scripts (.py) are supported. "
|
|
216
|
+
err_msg += f"Got: {resolved_path.suffix}"
|
|
217
|
+
verbose_print(err_msg)
|
|
218
|
+
raise typer.Exit(1)
|
|
219
|
+
|
|
220
|
+
# Prepare the graph
|
|
221
|
+
logger.info("Preparing graph for serving...")
|
|
222
|
+
try:
|
|
223
|
+
graph.prepare()
|
|
224
|
+
logger.info("Graph prepared successfully")
|
|
225
|
+
|
|
226
|
+
# Validate global variables for environment compatibility
|
|
227
|
+
if check_variables:
|
|
228
|
+
from lfx.cli.validation import validate_global_variables_for_env
|
|
229
|
+
|
|
230
|
+
validation_errors = validate_global_variables_for_env(graph)
|
|
231
|
+
if validation_errors:
|
|
232
|
+
logger.error("Global variable validation failed:")
|
|
233
|
+
for error in validation_errors:
|
|
234
|
+
logger.error(f" - {error}")
|
|
235
|
+
raise typer.Exit(1)
|
|
236
|
+
else:
|
|
237
|
+
logger.info("Global variable validation skipped")
|
|
238
|
+
except Exception as e:
|
|
239
|
+
verbose_print(f"ā Failed to prepare graph: {e}")
|
|
240
|
+
raise typer.Exit(1) from e
|
|
241
|
+
|
|
242
|
+
# Check if port is in use
|
|
243
|
+
if is_port_in_use(port, host):
|
|
244
|
+
available_port = get_free_port(port)
|
|
245
|
+
if verbose:
|
|
246
|
+
verbose_print(f"Port {port} is in use, using port {available_port} instead")
|
|
247
|
+
port = available_port
|
|
248
|
+
|
|
249
|
+
# Create single-flow metadata
|
|
250
|
+
flow_id = flow_id_from_path(resolved_path, resolved_path.parent)
|
|
251
|
+
graph.flow_id = flow_id # annotate graph for reference
|
|
252
|
+
|
|
253
|
+
title = resolved_path.stem
|
|
254
|
+
description = None
|
|
255
|
+
|
|
256
|
+
metas = {
|
|
257
|
+
flow_id: FlowMeta(
|
|
258
|
+
id=flow_id,
|
|
259
|
+
relative_path=str(resolved_path.name),
|
|
260
|
+
title=title,
|
|
261
|
+
description=description,
|
|
262
|
+
)
|
|
263
|
+
}
|
|
264
|
+
graphs = {flow_id: graph}
|
|
265
|
+
|
|
266
|
+
source_display = "inline JSON" if flow_json else "stdin" if stdin else str(resolved_path)
|
|
267
|
+
verbose_print(f"ā Prepared single flow '{title}' from {source_display} (id={flow_id})")
|
|
268
|
+
|
|
269
|
+
# Create FastAPI app
|
|
270
|
+
serve_app = create_multi_serve_app(
|
|
271
|
+
root_dir=resolved_path.parent,
|
|
272
|
+
graphs=graphs,
|
|
273
|
+
metas=metas,
|
|
274
|
+
verbose_print=verbose_print,
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
verbose_print("š Starting single-flow server...")
|
|
278
|
+
|
|
279
|
+
protocol = "http"
|
|
280
|
+
access_host = get_best_access_host(host)
|
|
281
|
+
|
|
282
|
+
masked_key = f"{api_key[:API_KEY_MASK_LENGTH]}..." if len(api_key) > API_KEY_MASK_LENGTH else "***"
|
|
283
|
+
|
|
284
|
+
console.print()
|
|
285
|
+
console.print(
|
|
286
|
+
Panel.fit(
|
|
287
|
+
f"[bold green]šÆ Single Flow Served Successfully![/bold green]\n\n"
|
|
288
|
+
f"[bold]Source:[/bold] {source_display}\n"
|
|
289
|
+
f"[bold]Server:[/bold] {protocol}://{access_host}:{port}\n"
|
|
290
|
+
f"[bold]API Key:[/bold] {masked_key}\n\n"
|
|
291
|
+
f"[dim]Send POST requests to:[/dim]\n"
|
|
292
|
+
f"[blue]{protocol}://{access_host}:{port}/flows/{flow_id}/run[/blue]\n\n"
|
|
293
|
+
f"[dim]With headers:[/dim]\n"
|
|
294
|
+
f"[blue]x-api-key: {masked_key}[/blue]\n\n"
|
|
295
|
+
f"[dim]Or query parameter:[/dim]\n"
|
|
296
|
+
f"[blue]?x-api-key={masked_key}[/blue]\n\n"
|
|
297
|
+
f"[dim]Request body:[/dim]\n"
|
|
298
|
+
f"[blue]{{'input_value': 'Your input message'}}[/blue]",
|
|
299
|
+
title="[bold blue]LFX Server[/bold blue]",
|
|
300
|
+
border_style="blue",
|
|
301
|
+
)
|
|
302
|
+
)
|
|
303
|
+
console.print()
|
|
304
|
+
|
|
305
|
+
# Start the server
|
|
306
|
+
try:
|
|
307
|
+
uvicorn.run(
|
|
308
|
+
serve_app,
|
|
309
|
+
host=host,
|
|
310
|
+
port=port,
|
|
311
|
+
log_level=log_level,
|
|
312
|
+
)
|
|
313
|
+
except KeyboardInterrupt:
|
|
314
|
+
verbose_print("\nš Server stopped")
|
|
315
|
+
raise typer.Exit(0) from None
|
|
316
|
+
except Exception as e:
|
|
317
|
+
verbose_print(f"ā Failed to start server: {e}")
|
|
318
|
+
raise typer.Exit(1) from e
|
|
319
|
+
|
|
320
|
+
finally:
|
|
321
|
+
# Clean up temporary file if created
|
|
322
|
+
if temp_file_to_cleanup:
|
|
323
|
+
try:
|
|
324
|
+
Path(temp_file_to_cleanup).unlink()
|
|
325
|
+
verbose_print(f"ā Cleaned up temporary file: {temp_file_to_cleanup}")
|
|
326
|
+
except OSError as e:
|
|
327
|
+
verbose_print(f"Warning: Failed to clean up temporary file {temp_file_to_cleanup}: {e}")
|