lfx-nightly 0.1.11.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lfx/__init__.py +0 -0
- lfx/__main__.py +25 -0
- lfx/base/__init__.py +0 -0
- lfx/base/agents/__init__.py +0 -0
- lfx/base/agents/agent.py +268 -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 +346 -0
- lfx/base/agents/utils.py +205 -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 +1291 -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 +685 -0
- lfx/base/data/docling_utils.py +245 -0
- lfx/base/data/utils.py +198 -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/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 +20 -0
- lfx/base/io/text.py +22 -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 +1398 -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 +47 -0
- lfx/base/models/aws_constants.py +151 -0
- lfx/base/models/chat_result.py +76 -0
- lfx/base/models/google_generative_ai_constants.py +70 -0
- lfx/base/models/groq_constants.py +134 -0
- lfx/base/models/model.py +375 -0
- lfx/base/models/model_input_constants.py +307 -0
- lfx/base/models/model_metadata.py +41 -0
- lfx/base/models/model_utils.py +8 -0
- lfx/base/models/novita_constants.py +35 -0
- lfx/base/models/ollama_constants.py +49 -0
- lfx/base/models/openai_constants.py +122 -0
- lfx/base/models/sambanova_constants.py +18 -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 +224 -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 +319 -0
- lfx/cli/common.py +650 -0
- lfx/cli/run.py +441 -0
- lfx/cli/script_loader.py +247 -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 +411 -0
- lfx/components/_importing.py +42 -0
- lfx/components/agentql/__init__.py +3 -0
- lfx/components/agentql/agentql_api.py +151 -0
- lfx/components/agents/__init__.py +34 -0
- lfx/components/agents/agent.py +558 -0
- lfx/components/agents/mcp_component.py +501 -0
- lfx/components/aiml/__init__.py +37 -0
- lfx/components/aiml/aiml.py +112 -0
- lfx/components/aiml/aiml_embeddings.py +37 -0
- lfx/components/amazon/__init__.py +36 -0
- lfx/components/amazon/amazon_bedrock_embedding.py +109 -0
- lfx/components/amazon/amazon_bedrock_model.py +124 -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 +163 -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 +167 -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/composio/__init__.py +74 -0
- lfx/components/composio/composio_api.py +268 -0
- lfx/components/composio/dropbox_compnent.py +11 -0
- lfx/components/composio/github_composio.py +11 -0
- lfx/components/composio/gmail_composio.py +38 -0
- lfx/components/composio/googlecalendar_composio.py +11 -0
- lfx/components/composio/googlemeet_composio.py +11 -0
- lfx/components/composio/googletasks_composio.py +8 -0
- lfx/components/composio/linear_composio.py +11 -0
- lfx/components/composio/outlook_composio.py +11 -0
- lfx/components/composio/reddit_composio.py +11 -0
- lfx/components/composio/slack_composio.py +582 -0
- lfx/components/composio/slackbot_composio.py +11 -0
- lfx/components/composio/supabase_composio.py +11 -0
- lfx/components/composio/todoist_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 +107 -0
- lfx/components/crewai/hierarchical_crew.py +46 -0
- lfx/components/crewai/hierarchical_task.py +44 -0
- lfx/components/crewai/sequential_crew.py +52 -0
- lfx/components/crewai/sequential_task.py +73 -0
- lfx/components/crewai/sequential_task_agent.py +143 -0
- lfx/components/custom_component/__init__.py +34 -0
- lfx/components/custom_component/custom_component.py +31 -0
- lfx/components/data/__init__.py +64 -0
- lfx/components/data/api_request.py +544 -0
- lfx/components/data/csv_to_data.py +95 -0
- lfx/components/data/directory.py +113 -0
- lfx/components/data/file.py +577 -0
- lfx/components/data/json_to_data.py +98 -0
- lfx/components/data/news_search.py +164 -0
- lfx/components/data/rss.py +69 -0
- lfx/components/data/sql_executor.py +101 -0
- lfx/components/data/url.py +311 -0
- lfx/components/data/web_search.py +112 -0
- lfx/components/data/webhook.py +56 -0
- lfx/components/datastax/__init__.py +70 -0
- lfx/components/datastax/astra_assistant_manager.py +306 -0
- lfx/components/datastax/astra_db.py +75 -0
- lfx/components/datastax/astra_vectorize.py +124 -0
- lfx/components/datastax/astradb.py +1285 -0
- lfx/components/datastax/astradb_cql.py +314 -0
- lfx/components/datastax/astradb_graph.py +330 -0
- lfx/components/datastax/astradb_tool.py +414 -0
- lfx/components/datastax/astradb_vectorstore.py +1285 -0
- lfx/components/datastax/cassandra.py +92 -0
- lfx/components/datastax/create_assistant.py +58 -0
- lfx/components/datastax/create_thread.py +32 -0
- lfx/components/datastax/dotenv.py +35 -0
- lfx/components/datastax/get_assistant.py +37 -0
- lfx/components/datastax/getenvvar.py +30 -0
- lfx/components/datastax/graph_rag.py +141 -0
- lfx/components/datastax/hcd.py +314 -0
- lfx/components/datastax/list_assistants.py +25 -0
- lfx/components/datastax/run.py +89 -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 +231 -0
- lfx/components/docling/docling_remote.py +193 -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 +243 -0
- lfx/components/embeddings/__init__.py +37 -0
- lfx/components/embeddings/similarity.py +76 -0
- lfx/components/embeddings/text_embedder.py +64 -0
- lfx/components/exa/__init__.py +3 -0
- lfx/components/exa/exa_search.py +68 -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/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 +192 -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 +147 -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 +136 -0
- lfx/components/helpers/__init__.py +52 -0
- lfx/components/helpers/calculator_core.py +89 -0
- lfx/components/helpers/create_list.py +40 -0
- lfx/components/helpers/current_date.py +42 -0
- lfx/components/helpers/id_generator.py +42 -0
- lfx/components/helpers/memory.py +251 -0
- lfx/components/helpers/output_parser.py +45 -0
- lfx/components/helpers/store_message.py +90 -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 +197 -0
- lfx/components/huggingface/huggingface_inference_api.py +106 -0
- lfx/components/ibm/__init__.py +34 -0
- lfx/components/ibm/watsonx.py +203 -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 +38 -0
- lfx/components/input_output/chat.py +120 -0
- lfx/components/input_output/chat_output.py +200 -0
- lfx/components/input_output/text.py +27 -0
- lfx/components/input_output/text_output.py +29 -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/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 +107 -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 +45 -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/lmstudio/__init__.py +34 -0
- lfx/components/lmstudio/lmstudioembeddings.py +89 -0
- lfx/components/lmstudio/lmstudiomodel.py +129 -0
- lfx/components/logic/__init__.py +52 -0
- lfx/components/logic/conditional_router.py +171 -0
- lfx/components/logic/data_conditional_router.py +125 -0
- lfx/components/logic/flow_tool.py +110 -0
- lfx/components/logic/listen.py +29 -0
- lfx/components/logic/loop.py +125 -0
- lfx/components/logic/notify.py +88 -0
- lfx/components/logic/pass_message.py +35 -0
- lfx/components/logic/run_flow.py +71 -0
- lfx/components/logic/sub_flow.py +114 -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 +136 -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 +34 -0
- lfx/components/models/embedding_model.py +114 -0
- lfx/components/models/language_model.py +144 -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 +157 -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 +330 -0
- lfx/components/ollama/ollama_embeddings.py +106 -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 +202 -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 +117 -0
- lfx/components/processing/alter_metadata.py +108 -0
- lfx/components/processing/batch_run.py +205 -0
- lfx/components/processing/combine_text.py +39 -0
- lfx/components/processing/converter.py +159 -0
- lfx/components/processing/create_data.py +110 -0
- lfx/components/processing/data_operations.py +438 -0
- lfx/components/processing/data_to_dataframe.py +70 -0
- lfx/components/processing/dataframe_operations.py +313 -0
- lfx/components/processing/extract_key.py +53 -0
- lfx/components/processing/filter_data.py +42 -0
- lfx/components/processing/filter_data_values.py +88 -0
- lfx/components/processing/json_cleaner.py +103 -0
- lfx/components/processing/lambda_filter.py +154 -0
- lfx/components/processing/llm_router.py +499 -0
- lfx/components/processing/merge_data.py +90 -0
- lfx/components/processing/message_to_data.py +36 -0
- lfx/components/processing/parse_data.py +70 -0
- lfx/components/processing/parse_dataframe.py +68 -0
- lfx/components/processing/parse_json_data.py +90 -0
- lfx/components/processing/parser.py +143 -0
- lfx/components/processing/prompt.py +67 -0
- lfx/components/processing/python_repl_core.py +98 -0
- lfx/components/processing/regex.py +82 -0
- lfx/components/processing/save_file.py +225 -0
- lfx/components/processing/select_data.py +48 -0
- lfx/components/processing/split_text.py +141 -0
- lfx/components/processing/structured_output.py +202 -0
- lfx/components/processing/update_data.py +160 -0
- lfx/components/prototypes/__init__.py +34 -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 +72 -0
- lfx/components/tools/calculator.py +108 -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 +327 -0
- lfx/components/tools/python_repl.py +97 -0
- lfx/components/tools/search_api.py +87 -0
- lfx/components/tools/searxng.py +145 -0
- lfx/components/tools/serp_api.py +119 -0
- lfx/components/tools/tavily_search_tool.py +344 -0
- lfx/components/tools/wikidata_api.py +102 -0
- lfx/components/tools/wikipedia_api.py +49 -0
- lfx/components/tools/yahoo_finance.py +129 -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 +291 -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 +179 -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/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 +40 -0
- lfx/components/vectorstores/astradb.py +1285 -0
- lfx/components/vectorstores/astradb_graph.py +319 -0
- lfx/components/vectorstores/cassandra.py +264 -0
- lfx/components/vectorstores/cassandra_graph.py +238 -0
- lfx/components/vectorstores/chroma.py +167 -0
- lfx/components/vectorstores/clickhouse.py +135 -0
- lfx/components/vectorstores/couchbase.py +102 -0
- lfx/components/vectorstores/elasticsearch.py +267 -0
- lfx/components/vectorstores/faiss.py +111 -0
- lfx/components/vectorstores/graph_rag.py +141 -0
- lfx/components/vectorstores/hcd.py +314 -0
- lfx/components/vectorstores/local_db.py +261 -0
- lfx/components/vectorstores/milvus.py +115 -0
- lfx/components/vectorstores/mongodb_atlas.py +213 -0
- lfx/components/vectorstores/opensearch.py +243 -0
- lfx/components/vectorstores/pgvector.py +72 -0
- lfx/components/vectorstores/pinecone.py +134 -0
- lfx/components/vectorstores/qdrant.py +109 -0
- lfx/components/vectorstores/supabase.py +76 -0
- lfx/components/vectorstores/upstash.py +124 -0
- lfx/components/vectorstores/vectara.py +97 -0
- lfx/components/vectorstores/vectara_rag.py +164 -0
- lfx/components/vectorstores/weaviate.py +89 -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/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 +118 -0
- lfx/components/zep/__init__.py +3 -0
- lfx/components/zep/zep.py +44 -0
- lfx/constants.py +6 -0
- lfx/custom/__init__.py +7 -0
- lfx/custom/attributes.py +86 -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 +1808 -0
- lfx/custom/custom_component/component_with_cache.py +8 -0
- lfx/custom/custom_component/custom_component.py +588 -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 +488 -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 +215 -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 +277 -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 +2238 -0
- lfx/graph/graph/constants.py +63 -0
- lfx/graph/graph/runnable_vertices_manager.py +133 -0
- lfx/graph/graph/schema.py +52 -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 +237 -0
- lfx/graph/utils.py +200 -0
- lfx/graph/vertex/__init__.py +0 -0
- lfx/graph/vertex/base.py +823 -0
- lfx/graph/vertex/constants.py +0 -0
- lfx/graph/vertex/exceptions.py +4 -0
- lfx/graph/vertex/param_handler.py +264 -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 +1 -0
- lfx/helpers/base_model.py +71 -0
- lfx/helpers/custom.py +13 -0
- lfx/helpers/data.py +167 -0
- lfx/helpers/flow.py +194 -0
- lfx/inputs/__init__.py +68 -0
- lfx/inputs/constants.py +2 -0
- lfx/inputs/input_mixin.py +328 -0
- lfx/inputs/inputs.py +714 -0
- lfx/inputs/validators.py +19 -0
- lfx/interface/__init__.py +6 -0
- lfx/interface/components.py +489 -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 +224 -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 +289 -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 +385 -0
- lfx/memory/__init__.py +90 -0
- lfx/memory/stubs.py +283 -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/data.py +308 -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 +131 -0
- lfx/schema/json_schema.py +141 -0
- lfx/schema/log.py +61 -0
- lfx/schema/message.py +473 -0
- lfx/schema/openai_responses_schemas.py +74 -0
- lfx/schema/properties.py +41 -0
- lfx/schema/schema.py +171 -0
- lfx/schema/serialize.py +13 -0
- lfx/schema/table.py +140 -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 +23 -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/deps.py +129 -0
- lfx/services/factory.py +19 -0
- lfx/services/initialize.py +19 -0
- lfx/services/interfaces.py +103 -0
- lfx/services/manager.py +172 -0
- lfx/services/schema.py +20 -0
- lfx/services/session.py +82 -0
- lfx/services/settings/__init__.py +3 -0
- lfx/services/settings/auth.py +130 -0
- lfx/services/settings/base.py +539 -0
- lfx/services/settings/constants.py +31 -0
- lfx/services/settings/factory.py +23 -0
- lfx/services/settings/feature_flags.py +12 -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 +155 -0
- lfx/services/storage/service.py +54 -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 +257 -0
- lfx/template/field/prompt.py +15 -0
- lfx/template/frontend_node/__init__.py +6 -0
- lfx/template/frontend_node/base.py +212 -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 +205 -0
- lfx/utils/data_structure.py +212 -0
- lfx/utils/exceptions.py +22 -0
- lfx/utils/helpers.py +28 -0
- lfx/utils/image.py +73 -0
- lfx/utils/lazy_load.py +15 -0
- lfx/utils/request_utils.py +18 -0
- lfx/utils/schemas.py +139 -0
- lfx/utils/util.py +481 -0
- lfx/utils/util_strings.py +56 -0
- lfx/utils/version.py +24 -0
- lfx_nightly-0.1.11.dev0.dist-info/METADATA +293 -0
- lfx_nightly-0.1.11.dev0.dist-info/RECORD +699 -0
- lfx_nightly-0.1.11.dev0.dist-info/WHEEL +4 -0
- lfx_nightly-0.1.11.dev0.dist-info/entry_points.txt +2 -0
lfx/graph/vertex/base.py
ADDED
@@ -0,0 +1,823 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import asyncio
|
4
|
+
import inspect
|
5
|
+
import traceback
|
6
|
+
import types
|
7
|
+
from collections.abc import AsyncIterator, Callable, Iterator, Mapping
|
8
|
+
from enum import Enum
|
9
|
+
from typing import TYPE_CHECKING, Any
|
10
|
+
|
11
|
+
from lfx.exceptions.component import ComponentBuildError
|
12
|
+
from lfx.graph.schema import INPUT_COMPONENTS, OUTPUT_COMPONENTS, InterfaceComponentTypes, ResultData
|
13
|
+
from lfx.graph.utils import UnbuiltObject, UnbuiltResult, log_transaction
|
14
|
+
from lfx.graph.vertex.param_handler import ParameterHandler
|
15
|
+
from lfx.interface import initialize
|
16
|
+
from lfx.interface.listing import lazy_load_dict
|
17
|
+
from lfx.log.logger import logger
|
18
|
+
from lfx.schema.artifact import ArtifactType
|
19
|
+
from lfx.schema.data import Data
|
20
|
+
from lfx.schema.message import Message
|
21
|
+
from lfx.schema.schema import INPUT_FIELD_NAME, OutputValue, build_output_logs
|
22
|
+
from lfx.utils.schemas import ChatOutputResponse
|
23
|
+
from lfx.utils.util import sync_to_async
|
24
|
+
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
from uuid import UUID
|
27
|
+
|
28
|
+
from lfx.custom.custom_component.component import Component
|
29
|
+
from lfx.events.event_manager import EventManager
|
30
|
+
from lfx.graph.edge.base import CycleEdge, Edge
|
31
|
+
from lfx.graph.graph.base import Graph
|
32
|
+
from lfx.graph.vertex.schema import NodeData
|
33
|
+
|
34
|
+
# Simple log type for tracing
|
35
|
+
Log = dict
|
36
|
+
|
37
|
+
|
38
|
+
class VertexStates(str, Enum):
|
39
|
+
"""Vertex are related to it being active, inactive, or in an error state."""
|
40
|
+
|
41
|
+
ACTIVE = "ACTIVE"
|
42
|
+
INACTIVE = "INACTIVE"
|
43
|
+
ERROR = "ERROR"
|
44
|
+
|
45
|
+
|
46
|
+
class Vertex:
|
47
|
+
def __init__(
|
48
|
+
self,
|
49
|
+
data: NodeData,
|
50
|
+
graph: Graph,
|
51
|
+
*,
|
52
|
+
base_type: str | None = None,
|
53
|
+
is_task: bool = False,
|
54
|
+
params: dict | None = None,
|
55
|
+
) -> None:
|
56
|
+
# is_external means that the Vertex send or receives data from
|
57
|
+
# an external source (e.g the chat)
|
58
|
+
self._lock: asyncio.Lock | None = None
|
59
|
+
self.will_stream = False
|
60
|
+
self.updated_raw_params = False
|
61
|
+
self.id: str = data["id"]
|
62
|
+
self.base_name = self.id.split("-")[0]
|
63
|
+
self.is_state = False
|
64
|
+
# TODO: This won't be enough in the long term
|
65
|
+
# we need to have a better way to determine if a vertex is an input or an output
|
66
|
+
type_strings = [self.id.split("-")[0], data["data"]["type"]]
|
67
|
+
self.is_input = any(input_component_name in type_strings for input_component_name in INPUT_COMPONENTS)
|
68
|
+
self.is_output = any(output_component_name in type_strings for output_component_name in OUTPUT_COMPONENTS)
|
69
|
+
self._is_loop = None
|
70
|
+
self.has_session_id = None
|
71
|
+
self.custom_component = None
|
72
|
+
self.has_external_input = False
|
73
|
+
self.has_external_output = False
|
74
|
+
self.graph = graph
|
75
|
+
self.full_data = data.copy()
|
76
|
+
self.base_type: str | None = base_type
|
77
|
+
self.outputs: list[dict] = []
|
78
|
+
self.parse_data()
|
79
|
+
self.built_object: Any = UnbuiltObject()
|
80
|
+
self.built_result: Any = None
|
81
|
+
self.built = False
|
82
|
+
self._successors_ids: list[str] | None = None
|
83
|
+
self.artifacts: dict[str, Any] = {}
|
84
|
+
self.artifacts_raw: dict[str, Any] | None = {}
|
85
|
+
self.artifacts_type: dict[str, str] = {}
|
86
|
+
self.steps: list[Callable] = [self._build]
|
87
|
+
self.steps_ran: list[Callable] = []
|
88
|
+
self.task_id: str | None = None
|
89
|
+
self.is_task = is_task
|
90
|
+
self.params = params or {}
|
91
|
+
self.parent_node_id: str | None = self.full_data.get("parent_node_id")
|
92
|
+
self.load_from_db_fields: list[str] = []
|
93
|
+
self.parent_is_top_level = False
|
94
|
+
self.layer = None
|
95
|
+
self.result: ResultData | None = None
|
96
|
+
self.results: dict[str, Any] = {}
|
97
|
+
self.outputs_logs: dict[str, OutputValue] = {}
|
98
|
+
self.logs: dict[str, list[Log]] = {}
|
99
|
+
self.has_cycle_edges = False
|
100
|
+
try:
|
101
|
+
self.is_interface_component = self.vertex_type in InterfaceComponentTypes
|
102
|
+
except ValueError:
|
103
|
+
self.is_interface_component = False
|
104
|
+
|
105
|
+
self.use_result = False
|
106
|
+
self.build_times: list[float] = []
|
107
|
+
self.state = VertexStates.ACTIVE
|
108
|
+
self.log_transaction_tasks: set[asyncio.Task] = set()
|
109
|
+
self.output_names: list[str] = [
|
110
|
+
output["name"] for output in self.outputs if isinstance(output, dict) and "name" in output
|
111
|
+
]
|
112
|
+
self._incoming_edges: list[CycleEdge] | None = None
|
113
|
+
self._outgoing_edges: list[CycleEdge] | None = None
|
114
|
+
|
115
|
+
@property
|
116
|
+
def lock(self):
|
117
|
+
"""Lazy initialization of asyncio.Lock."""
|
118
|
+
if self._lock is None:
|
119
|
+
self._lock = asyncio.Lock()
|
120
|
+
return self._lock
|
121
|
+
|
122
|
+
@property
|
123
|
+
def is_loop(self) -> bool:
|
124
|
+
"""Check if any output allows looping."""
|
125
|
+
if self._is_loop is None:
|
126
|
+
self._is_loop = any(output.get("allows_loop", False) for output in self.outputs)
|
127
|
+
return self._is_loop
|
128
|
+
|
129
|
+
def set_input_value(self, name: str, value: Any) -> None:
|
130
|
+
if self.custom_component is None:
|
131
|
+
msg = f"Vertex {self.id} does not have a component instance."
|
132
|
+
raise ValueError(msg)
|
133
|
+
self.custom_component.set_input_value(name, value)
|
134
|
+
|
135
|
+
def to_data(self):
|
136
|
+
return self.full_data
|
137
|
+
|
138
|
+
def add_component_instance(self, component_instance: Component) -> None:
|
139
|
+
component_instance.set_vertex(self)
|
140
|
+
self.custom_component = component_instance
|
141
|
+
|
142
|
+
def add_result(self, name: str, result: Any) -> None:
|
143
|
+
self.results[name] = result
|
144
|
+
|
145
|
+
def set_state(self, state: str) -> None:
|
146
|
+
self.state = VertexStates[state]
|
147
|
+
if self.state == VertexStates.INACTIVE and self.graph.in_degree_map[self.id] <= 1:
|
148
|
+
# If the vertex is inactive and has only one in degree
|
149
|
+
# it means that it is not a merge point in the graph
|
150
|
+
self.graph.inactivated_vertices.add(self.id)
|
151
|
+
elif self.state == VertexStates.ACTIVE and self.id in self.graph.inactivated_vertices:
|
152
|
+
self.graph.inactivated_vertices.remove(self.id)
|
153
|
+
|
154
|
+
def is_active(self):
|
155
|
+
return self.state == VertexStates.ACTIVE
|
156
|
+
|
157
|
+
@property
|
158
|
+
def avg_build_time(self):
|
159
|
+
return sum(self.build_times) / len(self.build_times) if self.build_times else 0
|
160
|
+
|
161
|
+
def add_build_time(self, time) -> None:
|
162
|
+
self.build_times.append(time)
|
163
|
+
|
164
|
+
def set_result(self, result: ResultData) -> None:
|
165
|
+
self.result = result
|
166
|
+
|
167
|
+
def get_built_result(self):
|
168
|
+
# If the Vertex.type is a power component
|
169
|
+
# then we need to return the built object
|
170
|
+
# instead of the result dict
|
171
|
+
if self.is_interface_component and not isinstance(self.built_object, UnbuiltObject):
|
172
|
+
result = self.built_object
|
173
|
+
# if it is not a dict or a string and hasattr model_dump then
|
174
|
+
# return the model_dump
|
175
|
+
if not isinstance(result, dict | str) and hasattr(result, "content"):
|
176
|
+
return result.content
|
177
|
+
return result
|
178
|
+
if isinstance(self.built_object, str):
|
179
|
+
self.built_result = self.built_object
|
180
|
+
|
181
|
+
if isinstance(self.built_result, UnbuiltResult):
|
182
|
+
return {}
|
183
|
+
return self.built_result if isinstance(self.built_result, dict) else {"result": self.built_result}
|
184
|
+
|
185
|
+
def set_artifacts(self) -> None:
|
186
|
+
pass
|
187
|
+
|
188
|
+
@property
|
189
|
+
def edges(self) -> list[CycleEdge]:
|
190
|
+
return self.graph.get_vertex_edges(self.id)
|
191
|
+
|
192
|
+
@property
|
193
|
+
def outgoing_edges(self) -> list[CycleEdge]:
|
194
|
+
if self._outgoing_edges is None:
|
195
|
+
self._outgoing_edges = [edge for edge in self.edges if edge.source_id == self.id]
|
196
|
+
return self._outgoing_edges
|
197
|
+
|
198
|
+
@property
|
199
|
+
def incoming_edges(self) -> list[CycleEdge]:
|
200
|
+
if self._incoming_edges is None:
|
201
|
+
self._incoming_edges = [edge for edge in self.edges if edge.target_id == self.id]
|
202
|
+
return self._incoming_edges
|
203
|
+
|
204
|
+
# Get edge connected to an output of a certain name
|
205
|
+
def get_incoming_edge_by_target_param(self, target_param: str) -> str | None:
|
206
|
+
return next((edge.source_id for edge in self.incoming_edges if edge.target_param == target_param), None)
|
207
|
+
|
208
|
+
@property
|
209
|
+
def edges_source_names(self) -> set[str | None]:
|
210
|
+
return {edge.source_handle.name for edge in self.edges}
|
211
|
+
|
212
|
+
@property
|
213
|
+
def predecessors(self) -> list[Vertex]:
|
214
|
+
return self.graph.get_predecessors(self)
|
215
|
+
|
216
|
+
@property
|
217
|
+
def successors(self) -> list[Vertex]:
|
218
|
+
return self.graph.get_successors(self)
|
219
|
+
|
220
|
+
@property
|
221
|
+
def successors_ids(self) -> list[str]:
|
222
|
+
return self.graph.successor_map.get(self.id, [])
|
223
|
+
|
224
|
+
def __getstate__(self):
|
225
|
+
state = self.__dict__.copy()
|
226
|
+
state["_lock"] = None # Locks are not serializable
|
227
|
+
state["built_object"] = None if isinstance(self.built_object, UnbuiltObject) else self.built_object
|
228
|
+
state["built_result"] = None if isinstance(self.built_result, UnbuiltResult) else self.built_result
|
229
|
+
return state
|
230
|
+
|
231
|
+
def __setstate__(self, state):
|
232
|
+
self.__dict__.update(state)
|
233
|
+
self._lock = asyncio.Lock() # Reinitialize the lock
|
234
|
+
self.built_object = state.get("built_object") or UnbuiltObject()
|
235
|
+
self.built_result = state.get("built_result") or UnbuiltResult()
|
236
|
+
|
237
|
+
def set_top_level(self, top_level_vertices: list[str]) -> None:
|
238
|
+
self.parent_is_top_level = self.parent_node_id in top_level_vertices
|
239
|
+
|
240
|
+
def parse_data(self) -> None:
|
241
|
+
self.data = self.full_data["data"]
|
242
|
+
if self.data["node"]["template"]["_type"] == "Component":
|
243
|
+
if "outputs" not in self.data["node"]:
|
244
|
+
msg = f"Outputs not found for {self.display_name}"
|
245
|
+
raise ValueError(msg)
|
246
|
+
self.outputs = self.data["node"]["outputs"]
|
247
|
+
else:
|
248
|
+
self.outputs = self.data["node"].get("outputs", [])
|
249
|
+
self.output = self.data["node"]["base_classes"]
|
250
|
+
|
251
|
+
self.display_name: str = self.data["node"].get("display_name", self.id.split("-")[0])
|
252
|
+
self.icon: str = self.data["node"].get("icon", self.id.split("-")[0])
|
253
|
+
|
254
|
+
self.description: str = self.data["node"].get("description", "")
|
255
|
+
self.frozen: bool = self.data["node"].get("frozen", False)
|
256
|
+
|
257
|
+
self.is_input = self.data["node"].get("is_input") or self.is_input
|
258
|
+
self.is_output = self.data["node"].get("is_output") or self.is_output
|
259
|
+
template_dicts = {key: value for key, value in self.data["node"]["template"].items() if isinstance(value, dict)}
|
260
|
+
|
261
|
+
self.has_session_id = "session_id" in template_dicts
|
262
|
+
|
263
|
+
self.required_inputs: list[str] = []
|
264
|
+
self.optional_inputs: list[str] = []
|
265
|
+
for value_dict in template_dicts.values():
|
266
|
+
list_to_append = self.required_inputs if value_dict.get("required") else self.optional_inputs
|
267
|
+
|
268
|
+
if "type" in value_dict:
|
269
|
+
list_to_append.append(value_dict["type"])
|
270
|
+
if "input_types" in value_dict:
|
271
|
+
list_to_append.extend(value_dict["input_types"])
|
272
|
+
|
273
|
+
template_dict = self.data["node"]["template"]
|
274
|
+
self.vertex_type = (
|
275
|
+
self.data["type"]
|
276
|
+
if "Tool" not in [type_ for out in self.outputs for type_ in out["types"]]
|
277
|
+
or template_dict["_type"].islower()
|
278
|
+
else template_dict["_type"]
|
279
|
+
)
|
280
|
+
|
281
|
+
if self.base_type is None:
|
282
|
+
for base_type, value in lazy_load_dict.all_types_dict.items():
|
283
|
+
if self.vertex_type in value:
|
284
|
+
self.base_type = base_type
|
285
|
+
break
|
286
|
+
|
287
|
+
def get_value_from_output_names(self, key: str):
|
288
|
+
if key in self.output_names:
|
289
|
+
return self.graph.get_vertex(key)
|
290
|
+
return None
|
291
|
+
|
292
|
+
def get_value_from_template_dict(self, key: str):
|
293
|
+
template_dict = self.data.get("node", {}).get("template", {})
|
294
|
+
|
295
|
+
if key not in template_dict:
|
296
|
+
msg = f"Key {key} not found in template dict"
|
297
|
+
raise ValueError(msg)
|
298
|
+
return template_dict.get(key, {}).get("value")
|
299
|
+
|
300
|
+
def _set_params_from_normal_edge(self, params: dict, edge: Edge, template_dict: dict):
|
301
|
+
param_key = edge.target_param
|
302
|
+
|
303
|
+
# If the param_key is in the template_dict and the edge.target_id is the current node
|
304
|
+
# We check this to make sure params with the same name but different target_id
|
305
|
+
# don't get overwritten
|
306
|
+
if param_key in template_dict and edge.target_id == self.id:
|
307
|
+
if template_dict[param_key].get("list"):
|
308
|
+
if param_key not in params:
|
309
|
+
params[param_key] = []
|
310
|
+
params[param_key].append(self.graph.get_vertex(edge.source_id))
|
311
|
+
elif edge.target_id == self.id:
|
312
|
+
if isinstance(template_dict[param_key].get("value"), dict):
|
313
|
+
# we don't know the key of the dict but we need to set the value
|
314
|
+
# to the vertex that is the source of the edge
|
315
|
+
param_dict = template_dict[param_key]["value"]
|
316
|
+
if not param_dict or len(param_dict) != 1:
|
317
|
+
params[param_key] = self.graph.get_vertex(edge.source_id)
|
318
|
+
else:
|
319
|
+
params[param_key] = {key: self.graph.get_vertex(edge.source_id) for key in param_dict}
|
320
|
+
|
321
|
+
else:
|
322
|
+
params[param_key] = self.graph.get_vertex(edge.source_id)
|
323
|
+
elif param_key in self.output_names:
|
324
|
+
# if the loop is run the param_key item will be set over here
|
325
|
+
# validate the edge
|
326
|
+
params[param_key] = self.graph.get_vertex(edge.source_id)
|
327
|
+
return params
|
328
|
+
|
329
|
+
def build_params(self) -> None:
|
330
|
+
"""Build parameters for the vertex using the ParameterHandler."""
|
331
|
+
if self.graph is None:
|
332
|
+
msg = "Graph not found"
|
333
|
+
raise ValueError(msg)
|
334
|
+
|
335
|
+
if self.updated_raw_params:
|
336
|
+
self.updated_raw_params = False
|
337
|
+
return
|
338
|
+
|
339
|
+
# Create parameter handler with lazy storage service initialization
|
340
|
+
param_handler = ParameterHandler(self, storage_service=None)
|
341
|
+
|
342
|
+
# Process edge parameters
|
343
|
+
edge_params = param_handler.process_edge_parameters(self.edges)
|
344
|
+
|
345
|
+
# Process field parameters
|
346
|
+
field_params, load_from_db_fields = param_handler.process_field_parameters()
|
347
|
+
|
348
|
+
# Combine parameters, edge_params take precedence
|
349
|
+
self.params = {**field_params, **edge_params}
|
350
|
+
self.load_from_db_fields = load_from_db_fields
|
351
|
+
self.raw_params = self.params.copy()
|
352
|
+
|
353
|
+
def update_raw_params(self, new_params: Mapping[str, str | list[str]], *, overwrite: bool = False) -> None:
|
354
|
+
"""Update the raw parameters of the vertex with the given new parameters.
|
355
|
+
|
356
|
+
Args:
|
357
|
+
new_params (Dict[str, Any]): The new parameters to update.
|
358
|
+
overwrite (bool, optional): Whether to overwrite the existing parameters.
|
359
|
+
Defaults to False.
|
360
|
+
|
361
|
+
Raises:
|
362
|
+
ValueError: If any key in new_params is not found in self.raw_params.
|
363
|
+
"""
|
364
|
+
# First check if the input_value in raw_params is not a vertex
|
365
|
+
if not new_params:
|
366
|
+
return
|
367
|
+
if any(isinstance(self.raw_params.get(key), Vertex) for key in new_params):
|
368
|
+
return
|
369
|
+
if not overwrite:
|
370
|
+
for key in new_params.copy(): # type: ignore[attr-defined]
|
371
|
+
if key not in self.raw_params:
|
372
|
+
new_params.pop(key) # type: ignore[attr-defined]
|
373
|
+
self.raw_params.update(new_params)
|
374
|
+
self.params = self.raw_params.copy()
|
375
|
+
self.updated_raw_params = True
|
376
|
+
|
377
|
+
def instantiate_component(self, user_id=None) -> None:
|
378
|
+
if not self.custom_component:
|
379
|
+
self.custom_component, _ = initialize.loading.instantiate_class(
|
380
|
+
user_id=user_id,
|
381
|
+
vertex=self,
|
382
|
+
)
|
383
|
+
|
384
|
+
async def _build(
|
385
|
+
self,
|
386
|
+
fallback_to_env_vars,
|
387
|
+
user_id=None,
|
388
|
+
event_manager: EventManager | None = None,
|
389
|
+
) -> None:
|
390
|
+
"""Initiate the build process."""
|
391
|
+
await logger.adebug(f"Building {self.display_name}")
|
392
|
+
await self._build_each_vertex_in_params_dict()
|
393
|
+
|
394
|
+
if self.base_type is None:
|
395
|
+
msg = f"Base type for vertex {self.display_name} not found"
|
396
|
+
raise ValueError(msg)
|
397
|
+
|
398
|
+
if not self.custom_component:
|
399
|
+
custom_component, custom_params = initialize.loading.instantiate_class(
|
400
|
+
user_id=user_id, vertex=self, event_manager=event_manager
|
401
|
+
)
|
402
|
+
else:
|
403
|
+
custom_component = self.custom_component
|
404
|
+
if hasattr(self.custom_component, "set_event_manager"):
|
405
|
+
self.custom_component.set_event_manager(event_manager)
|
406
|
+
custom_params = initialize.loading.get_params(self.params)
|
407
|
+
|
408
|
+
await self._build_results(
|
409
|
+
custom_component=custom_component,
|
410
|
+
custom_params=custom_params,
|
411
|
+
fallback_to_env_vars=fallback_to_env_vars,
|
412
|
+
base_type=self.base_type,
|
413
|
+
)
|
414
|
+
|
415
|
+
self._validate_built_object()
|
416
|
+
|
417
|
+
self.built = True
|
418
|
+
|
419
|
+
def extract_messages_from_artifacts(self, artifacts: dict[str, Any]) -> list[dict]:
|
420
|
+
"""Extracts messages from the artifacts.
|
421
|
+
|
422
|
+
Args:
|
423
|
+
artifacts (Dict[str, Any]): The artifacts to extract messages from.
|
424
|
+
|
425
|
+
Returns:
|
426
|
+
List[str]: The extracted messages.
|
427
|
+
"""
|
428
|
+
try:
|
429
|
+
text = artifacts["text"]
|
430
|
+
sender = artifacts.get("sender")
|
431
|
+
sender_name = artifacts.get("sender_name")
|
432
|
+
session_id = artifacts.get("session_id")
|
433
|
+
stream_url = artifacts.get("stream_url")
|
434
|
+
files = [{"path": file} if isinstance(file, str) else file for file in artifacts.get("files", [])]
|
435
|
+
component_id = self.id
|
436
|
+
type_ = self.artifacts_type
|
437
|
+
|
438
|
+
if isinstance(sender_name, Data | Message):
|
439
|
+
sender_name = sender_name.get_text()
|
440
|
+
|
441
|
+
messages = [
|
442
|
+
ChatOutputResponse(
|
443
|
+
message=text,
|
444
|
+
sender=sender,
|
445
|
+
sender_name=sender_name,
|
446
|
+
session_id=session_id,
|
447
|
+
stream_url=stream_url,
|
448
|
+
files=files,
|
449
|
+
component_id=component_id,
|
450
|
+
type=type_,
|
451
|
+
).model_dump(exclude_none=True)
|
452
|
+
]
|
453
|
+
except KeyError:
|
454
|
+
messages = []
|
455
|
+
|
456
|
+
return messages
|
457
|
+
|
458
|
+
def finalize_build(self) -> None:
|
459
|
+
result_dict = self.get_built_result()
|
460
|
+
# We need to set the artifacts to pass information
|
461
|
+
# to the frontend
|
462
|
+
self.set_artifacts()
|
463
|
+
artifacts = self.artifacts_raw
|
464
|
+
messages = self.extract_messages_from_artifacts(artifacts) if isinstance(artifacts, dict) else []
|
465
|
+
result_dict = ResultData(
|
466
|
+
results=result_dict,
|
467
|
+
artifacts=artifacts,
|
468
|
+
outputs=self.outputs_logs,
|
469
|
+
logs=self.logs,
|
470
|
+
messages=messages,
|
471
|
+
component_display_name=self.display_name,
|
472
|
+
component_id=self.id,
|
473
|
+
)
|
474
|
+
self.set_result(result_dict)
|
475
|
+
|
476
|
+
async def _build_each_vertex_in_params_dict(self) -> None:
|
477
|
+
"""Iterates over each vertex in the params dictionary and builds it."""
|
478
|
+
for key, value in self.raw_params.items():
|
479
|
+
if self._is_vertex(value):
|
480
|
+
if value == self:
|
481
|
+
del self.params[key]
|
482
|
+
continue
|
483
|
+
await self._build_vertex_and_update_params(
|
484
|
+
key,
|
485
|
+
value,
|
486
|
+
)
|
487
|
+
elif isinstance(value, list) and self._is_list_of_vertices(value):
|
488
|
+
await self._build_list_of_vertices_and_update_params(key, value)
|
489
|
+
elif isinstance(value, dict):
|
490
|
+
await self._build_dict_and_update_params(
|
491
|
+
key,
|
492
|
+
value,
|
493
|
+
)
|
494
|
+
elif key not in self.params or self.updated_raw_params:
|
495
|
+
self.params[key] = value
|
496
|
+
|
497
|
+
async def _build_dict_and_update_params(
|
498
|
+
self,
|
499
|
+
key,
|
500
|
+
vertices_dict: dict[str, Vertex],
|
501
|
+
) -> None:
|
502
|
+
"""Iterates over a dictionary of vertices, builds each and updates the params dictionary."""
|
503
|
+
for sub_key, value in vertices_dict.items():
|
504
|
+
if not self._is_vertex(value):
|
505
|
+
self.params[key][sub_key] = value
|
506
|
+
else:
|
507
|
+
result = await value.get_result(self, target_handle_name=key)
|
508
|
+
self.params[key][sub_key] = result
|
509
|
+
|
510
|
+
@staticmethod
|
511
|
+
def _is_vertex(value):
|
512
|
+
"""Checks if the provided value is an instance of Vertex."""
|
513
|
+
return isinstance(value, Vertex)
|
514
|
+
|
515
|
+
def _is_list_of_vertices(self, value):
|
516
|
+
"""Checks if the provided value is a list of Vertex instances."""
|
517
|
+
return all(self._is_vertex(vertex) for vertex in value)
|
518
|
+
|
519
|
+
async def get_result(self, requester: Vertex, target_handle_name: str | None = None) -> Any:
|
520
|
+
"""Retrieves the result of the vertex.
|
521
|
+
|
522
|
+
This is a read-only method so it raises an error if the vertex has not been built yet.
|
523
|
+
|
524
|
+
Returns:
|
525
|
+
The result of the vertex.
|
526
|
+
"""
|
527
|
+
async with self.lock:
|
528
|
+
return await self._get_result(requester, target_handle_name)
|
529
|
+
|
530
|
+
async def _log_transaction_async(
|
531
|
+
self,
|
532
|
+
flow_id: str | UUID,
|
533
|
+
source: Vertex,
|
534
|
+
status,
|
535
|
+
target: Vertex | None = None,
|
536
|
+
error=None,
|
537
|
+
) -> None:
|
538
|
+
"""Log a transaction asynchronously with proper task handling and cancellation.
|
539
|
+
|
540
|
+
Args:
|
541
|
+
flow_id: The ID of the flow
|
542
|
+
source: Source vertex
|
543
|
+
status: Transaction status
|
544
|
+
target: Optional target vertex
|
545
|
+
error: Optional error information
|
546
|
+
"""
|
547
|
+
if self.log_transaction_tasks:
|
548
|
+
# Safely await and remove completed tasks
|
549
|
+
task = self.log_transaction_tasks.pop()
|
550
|
+
await task
|
551
|
+
|
552
|
+
# Create and track new task
|
553
|
+
task = asyncio.create_task(log_transaction(flow_id, source, status, target, error))
|
554
|
+
self.log_transaction_tasks.add(task)
|
555
|
+
task.add_done_callback(self.log_transaction_tasks.discard)
|
556
|
+
|
557
|
+
async def _get_result(
|
558
|
+
self,
|
559
|
+
requester: Vertex,
|
560
|
+
target_handle_name: str | None = None, # noqa: ARG002
|
561
|
+
) -> Any:
|
562
|
+
"""Retrieves the result of the built component.
|
563
|
+
|
564
|
+
If the component has not been built yet, a ValueError is raised.
|
565
|
+
|
566
|
+
Returns:
|
567
|
+
The built result if use_result is True, else the built object.
|
568
|
+
"""
|
569
|
+
flow_id = self.graph.flow_id
|
570
|
+
if not self.built:
|
571
|
+
if flow_id:
|
572
|
+
await self._log_transaction_async(str(flow_id), source=self, target=requester, status="error")
|
573
|
+
msg = f"Component {self.display_name} has not been built yet"
|
574
|
+
raise ValueError(msg)
|
575
|
+
|
576
|
+
result = self.built_result if self.use_result else self.built_object
|
577
|
+
if flow_id:
|
578
|
+
await self._log_transaction_async(str(flow_id), source=self, target=requester, status="success")
|
579
|
+
return result
|
580
|
+
|
581
|
+
async def _build_vertex_and_update_params(self, key, vertex: Vertex) -> None:
|
582
|
+
"""Builds a given vertex and updates the params dictionary accordingly."""
|
583
|
+
result = await vertex.get_result(self, target_handle_name=key)
|
584
|
+
self._handle_func(key, result)
|
585
|
+
if isinstance(result, list):
|
586
|
+
self._extend_params_list_with_result(key, result)
|
587
|
+
self.params[key] = result
|
588
|
+
|
589
|
+
async def _build_list_of_vertices_and_update_params(
|
590
|
+
self,
|
591
|
+
key,
|
592
|
+
vertices: list[Vertex],
|
593
|
+
) -> None:
|
594
|
+
"""Iterates over a list of vertices, builds each and updates the params dictionary."""
|
595
|
+
self.params[key] = []
|
596
|
+
for vertex in vertices:
|
597
|
+
result = await vertex.get_result(self, target_handle_name=key)
|
598
|
+
# Weird check to see if the params[key] is a list
|
599
|
+
# because sometimes it is a Data and breaks the code
|
600
|
+
if not isinstance(self.params[key], list):
|
601
|
+
self.params[key] = [self.params[key]]
|
602
|
+
|
603
|
+
if isinstance(result, list):
|
604
|
+
self.params[key].extend(result)
|
605
|
+
else:
|
606
|
+
try:
|
607
|
+
if self.params[key] == result:
|
608
|
+
continue
|
609
|
+
|
610
|
+
self.params[key].append(result)
|
611
|
+
except AttributeError as e:
|
612
|
+
await logger.aexception(e)
|
613
|
+
msg = (
|
614
|
+
f"Params {key} ({self.params[key]}) is not a list and cannot be extended with {result}"
|
615
|
+
f"Error building Component {self.display_name}: \n\n{e}"
|
616
|
+
)
|
617
|
+
raise ValueError(msg) from e
|
618
|
+
|
619
|
+
def _handle_func(self, key, result) -> None:
|
620
|
+
"""Handles 'func' key by checking if the result is a function and setting it as coroutine."""
|
621
|
+
if key == "func":
|
622
|
+
if not isinstance(result, types.FunctionType):
|
623
|
+
if hasattr(result, "run"):
|
624
|
+
result = result.run
|
625
|
+
elif hasattr(result, "get_function"):
|
626
|
+
result = result.get_function()
|
627
|
+
elif inspect.iscoroutinefunction(result):
|
628
|
+
self.params["coroutine"] = result
|
629
|
+
else:
|
630
|
+
self.params["coroutine"] = sync_to_async(result)
|
631
|
+
|
632
|
+
def _extend_params_list_with_result(self, key, result) -> None:
|
633
|
+
"""Extends a list in the params dictionary with the given result if it exists."""
|
634
|
+
if isinstance(self.params[key], list):
|
635
|
+
self.params[key].extend(result)
|
636
|
+
|
637
|
+
async def _build_results(
|
638
|
+
self,
|
639
|
+
custom_component,
|
640
|
+
custom_params,
|
641
|
+
base_type: str,
|
642
|
+
*,
|
643
|
+
fallback_to_env_vars=False,
|
644
|
+
) -> None:
|
645
|
+
try:
|
646
|
+
result = await initialize.loading.get_instance_results(
|
647
|
+
custom_component=custom_component,
|
648
|
+
custom_params=custom_params,
|
649
|
+
vertex=self,
|
650
|
+
fallback_to_env_vars=fallback_to_env_vars,
|
651
|
+
base_type=base_type,
|
652
|
+
)
|
653
|
+
|
654
|
+
self.outputs_logs = build_output_logs(self, result)
|
655
|
+
|
656
|
+
self._update_built_object_and_artifacts(result)
|
657
|
+
except Exception as exc:
|
658
|
+
tb = traceback.format_exc()
|
659
|
+
await logger.aexception(exc)
|
660
|
+
msg = f"Error building Component {self.display_name}: \n\n{exc}"
|
661
|
+
raise ComponentBuildError(msg, tb) from exc
|
662
|
+
|
663
|
+
def _update_built_object_and_artifacts(self, result: Any | tuple[Any, dict] | tuple[Component, Any, dict]) -> None:
|
664
|
+
"""Updates the built object and its artifacts."""
|
665
|
+
if isinstance(result, tuple):
|
666
|
+
if len(result) == 2: # noqa: PLR2004
|
667
|
+
self.built_object, self.artifacts = result
|
668
|
+
elif len(result) == 3: # noqa: PLR2004
|
669
|
+
self.custom_component, self.built_object, self.artifacts = result
|
670
|
+
self.logs = self.custom_component.get_output_logs()
|
671
|
+
self.artifacts_raw = self.artifacts.get("raw", None)
|
672
|
+
self.artifacts_type = {
|
673
|
+
self.outputs[0]["name"]: self.artifacts.get("type", None) or ArtifactType.UNKNOWN.value
|
674
|
+
}
|
675
|
+
self.artifacts = {self.outputs[0]["name"]: self.artifacts}
|
676
|
+
else:
|
677
|
+
self.built_object = result
|
678
|
+
|
679
|
+
def _validate_built_object(self) -> None:
|
680
|
+
"""Checks if the built object is None and raises a ValueError if so."""
|
681
|
+
if isinstance(self.built_object, UnbuiltObject):
|
682
|
+
msg = f"{self.display_name}: {self.built_object_repr()}"
|
683
|
+
raise TypeError(msg)
|
684
|
+
if self.built_object is None:
|
685
|
+
message = f"{self.display_name} returned None."
|
686
|
+
if self.base_type == "custom_components":
|
687
|
+
message += " Make sure your build method returns a component."
|
688
|
+
|
689
|
+
logger.warning(message)
|
690
|
+
elif isinstance(self.built_object, Iterator | AsyncIterator):
|
691
|
+
if self.display_name == "Text Output":
|
692
|
+
msg = f"You are trying to stream to a {self.display_name}. Try using a Chat Output instead."
|
693
|
+
raise ValueError(msg)
|
694
|
+
|
695
|
+
def _reset(self) -> None:
|
696
|
+
self.built = False
|
697
|
+
self.built_object = UnbuiltObject()
|
698
|
+
self.built_result = UnbuiltResult()
|
699
|
+
self.artifacts = {}
|
700
|
+
self.steps_ran = []
|
701
|
+
self.build_params()
|
702
|
+
|
703
|
+
def _is_chat_input(self) -> bool:
|
704
|
+
return False
|
705
|
+
|
706
|
+
def build_inactive(self) -> None:
|
707
|
+
# Just set the results to None
|
708
|
+
self.built = True
|
709
|
+
self.built_object = None
|
710
|
+
self.built_result = None
|
711
|
+
|
712
|
+
async def build(
|
713
|
+
self,
|
714
|
+
user_id=None,
|
715
|
+
inputs: dict[str, Any] | None = None,
|
716
|
+
files: list[str] | None = None,
|
717
|
+
requester: Vertex | None = None,
|
718
|
+
event_manager: EventManager | None = None,
|
719
|
+
**kwargs,
|
720
|
+
) -> Any:
|
721
|
+
# Add lazy loading check at the beginning
|
722
|
+
# Check if we need to fully load this component first
|
723
|
+
from lfx.interface.components import ensure_component_loaded
|
724
|
+
from lfx.services.deps import get_settings_service
|
725
|
+
|
726
|
+
settings_service = get_settings_service()
|
727
|
+
if settings_service and settings_service.settings.lazy_load_components:
|
728
|
+
component_name = self.id.split("-")[0]
|
729
|
+
await ensure_component_loaded(self.vertex_type, component_name, settings_service)
|
730
|
+
|
731
|
+
# Continue with the original implementation
|
732
|
+
async with self.lock:
|
733
|
+
if self.state == VertexStates.INACTIVE:
|
734
|
+
# If the vertex is inactive, return None
|
735
|
+
self.build_inactive()
|
736
|
+
return None
|
737
|
+
|
738
|
+
if self.frozen and self.built:
|
739
|
+
return await self.get_requester_result(requester)
|
740
|
+
if self.built and requester is not None:
|
741
|
+
# This means that the vertex has already been built
|
742
|
+
# and we are just getting the result for the requester
|
743
|
+
return await self.get_requester_result(requester)
|
744
|
+
self._reset()
|
745
|
+
# inject session_id if it is not None
|
746
|
+
if inputs is not None and "session" in inputs and inputs["session"] is not None and self.has_session_id:
|
747
|
+
session_id_value = self.get_value_from_template_dict("session_id")
|
748
|
+
if session_id_value == "":
|
749
|
+
self.update_raw_params({"session_id": inputs["session"]}, overwrite=True)
|
750
|
+
if self._is_chat_input() and (inputs or files):
|
751
|
+
chat_input = {}
|
752
|
+
if (
|
753
|
+
inputs
|
754
|
+
and isinstance(inputs, dict)
|
755
|
+
and "input_value" in inputs
|
756
|
+
and inputs.get("input_value") is not None
|
757
|
+
):
|
758
|
+
chat_input.update({"input_value": inputs.get(INPUT_FIELD_NAME, "")})
|
759
|
+
if files:
|
760
|
+
chat_input.update({"files": files})
|
761
|
+
|
762
|
+
self.update_raw_params(chat_input, overwrite=True)
|
763
|
+
|
764
|
+
# Run steps
|
765
|
+
for step in self.steps:
|
766
|
+
if step not in self.steps_ran:
|
767
|
+
await step(user_id=user_id, event_manager=event_manager, **kwargs)
|
768
|
+
self.steps_ran.append(step)
|
769
|
+
|
770
|
+
self.finalize_build()
|
771
|
+
|
772
|
+
return await self.get_requester_result(requester)
|
773
|
+
|
774
|
+
async def get_requester_result(self, requester: Vertex | None):
|
775
|
+
# If the requester is None, this means that
|
776
|
+
# the Vertex is the root of the graph
|
777
|
+
if requester is None:
|
778
|
+
return self.built_object
|
779
|
+
|
780
|
+
# Get the requester edge
|
781
|
+
requester_edge = next((edge for edge in self.edges if edge.target_id == requester.id), None)
|
782
|
+
# Return the result of the requester edge
|
783
|
+
return (
|
784
|
+
None
|
785
|
+
if requester_edge is None
|
786
|
+
else await requester_edge.get_result_from_source(source=self, target=requester)
|
787
|
+
)
|
788
|
+
|
789
|
+
def add_edge(self, edge: CycleEdge) -> None:
|
790
|
+
if edge not in self.edges:
|
791
|
+
self.edges.append(edge)
|
792
|
+
|
793
|
+
def __repr__(self) -> str:
|
794
|
+
return f"Vertex(display_name={self.display_name}, id={self.id}, data={self.data})"
|
795
|
+
|
796
|
+
def __eq__(self, /, other: object) -> bool:
|
797
|
+
try:
|
798
|
+
if not isinstance(other, Vertex):
|
799
|
+
return False
|
800
|
+
# We should create a more robust comparison
|
801
|
+
# for the Vertex class
|
802
|
+
ids_are_equal = self.id == other.id
|
803
|
+
# self.data is a dict and we need to compare them
|
804
|
+
# to check if they are equal
|
805
|
+
data_are_equal = self.data == other.data
|
806
|
+
except AttributeError:
|
807
|
+
return False
|
808
|
+
else:
|
809
|
+
return ids_are_equal and data_are_equal
|
810
|
+
|
811
|
+
def __hash__(self) -> int:
|
812
|
+
return id(self)
|
813
|
+
|
814
|
+
def built_object_repr(self) -> str:
|
815
|
+
# Add a message with an emoji, stars for success,
|
816
|
+
return "Built successfully ✨" if self.built_object is not None else "Failed to build 😵💫"
|
817
|
+
|
818
|
+
def apply_on_outputs(self, func: Callable[[Any], Any]) -> None:
|
819
|
+
"""Applies a function to the outputs of the vertex."""
|
820
|
+
if not self.custom_component or not self.custom_component.outputs:
|
821
|
+
return
|
822
|
+
# Apply the function to each output
|
823
|
+
[func(output) for output in self.custom_component.get_outputs_map().values()]
|