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
@@ -0,0 +1,489 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import contextlib
|
4
|
+
import json
|
5
|
+
from collections.abc import AsyncIterator, Generator, Iterator
|
6
|
+
from typing import TYPE_CHECKING, Any, cast
|
7
|
+
|
8
|
+
import yaml
|
9
|
+
from langchain_core.messages import AIMessage, AIMessageChunk
|
10
|
+
|
11
|
+
from lfx.graph.schema import CHAT_COMPONENTS, RECORDS_COMPONENTS, InterfaceComponentTypes, ResultData
|
12
|
+
from lfx.graph.utils import UnbuiltObject, log_vertex_build, rewrite_file_path
|
13
|
+
from lfx.graph.vertex.base import Vertex
|
14
|
+
from lfx.graph.vertex.exceptions import NoComponentInstanceError
|
15
|
+
from lfx.log.logger import logger
|
16
|
+
from lfx.schema.artifact import ArtifactType
|
17
|
+
from lfx.schema.data import Data
|
18
|
+
from lfx.schema.message import Message
|
19
|
+
from lfx.schema.schema import INPUT_FIELD_NAME
|
20
|
+
from lfx.serialization.serialization import serialize
|
21
|
+
from lfx.template.field.base import UNDEFINED, Output
|
22
|
+
from lfx.utils.schemas import ChatOutputResponse, DataOutputResponse
|
23
|
+
from lfx.utils.util import unescape_string
|
24
|
+
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
from lfx.graph.edge.base import CycleEdge
|
27
|
+
from lfx.graph.vertex.schema import NodeData
|
28
|
+
from lfx.inputs.inputs import InputTypes
|
29
|
+
|
30
|
+
|
31
|
+
class CustomComponentVertex(Vertex):
|
32
|
+
def __init__(self, data: NodeData, graph):
|
33
|
+
super().__init__(data, graph=graph, base_type="custom_components")
|
34
|
+
|
35
|
+
def built_object_repr(self):
|
36
|
+
if self.artifacts and "repr" in self.artifacts:
|
37
|
+
return self.artifacts["repr"] or super().built_object_repr()
|
38
|
+
return None
|
39
|
+
|
40
|
+
|
41
|
+
class ComponentVertex(Vertex):
|
42
|
+
def __init__(self, data: NodeData, graph):
|
43
|
+
super().__init__(data, graph=graph, base_type="component")
|
44
|
+
|
45
|
+
def get_input(self, name: str) -> InputTypes:
|
46
|
+
if self.custom_component is None:
|
47
|
+
msg = f"Vertex {self.id} does not have a component instance."
|
48
|
+
raise ValueError(msg)
|
49
|
+
return self.custom_component.get_input(name)
|
50
|
+
|
51
|
+
def get_output(self, name: str) -> Output:
|
52
|
+
if self.custom_component is None:
|
53
|
+
raise NoComponentInstanceError(self.id)
|
54
|
+
return self.custom_component.get_output(name)
|
55
|
+
|
56
|
+
def built_object_repr(self):
|
57
|
+
if self.artifacts and "repr" in self.artifacts:
|
58
|
+
return self.artifacts["repr"] or super().built_object_repr()
|
59
|
+
return None
|
60
|
+
|
61
|
+
def _update_built_object_and_artifacts(self, result) -> None:
|
62
|
+
"""Updates the built object and its artifacts."""
|
63
|
+
if isinstance(result, tuple):
|
64
|
+
if len(result) == 2: # noqa: PLR2004
|
65
|
+
self.built_object, self.artifacts = result
|
66
|
+
elif len(result) == 3: # noqa: PLR2004
|
67
|
+
self.custom_component, self.built_object, self.artifacts = result
|
68
|
+
self.logs = self.custom_component._output_logs
|
69
|
+
for key in self.artifacts:
|
70
|
+
if self.artifacts_raw is None:
|
71
|
+
self.artifacts_raw = {}
|
72
|
+
self.artifacts_raw[key] = self.artifacts[key].get("raw", None)
|
73
|
+
self.artifacts_type[key] = self.artifacts[key].get("type", None) or ArtifactType.UNKNOWN.value
|
74
|
+
else:
|
75
|
+
self.built_object = result
|
76
|
+
|
77
|
+
for key, value in self.built_object.items():
|
78
|
+
self.add_result(key, value)
|
79
|
+
|
80
|
+
def get_edge_with_target(self, target_id: str) -> Generator[CycleEdge]:
|
81
|
+
"""Get the edge with the target id.
|
82
|
+
|
83
|
+
Args:
|
84
|
+
target_id: The target id of the edge.
|
85
|
+
|
86
|
+
Returns:
|
87
|
+
The edge with the target id.
|
88
|
+
"""
|
89
|
+
for edge in self.edges:
|
90
|
+
if edge.target_id == target_id:
|
91
|
+
yield edge
|
92
|
+
|
93
|
+
async def _get_result(self, requester: Vertex, target_handle_name: str | None = None) -> Any:
|
94
|
+
"""Retrieves the result of the built component.
|
95
|
+
|
96
|
+
If the component has not been built yet, a ValueError is raised.
|
97
|
+
|
98
|
+
Returns:
|
99
|
+
The built result if use_result is True, else the built object.
|
100
|
+
"""
|
101
|
+
flow_id = self.graph.flow_id
|
102
|
+
if not self.built:
|
103
|
+
default_value: Any = UNDEFINED
|
104
|
+
for edge in self.get_edge_with_target(requester.id):
|
105
|
+
# We need to check if the edge is a normal edge
|
106
|
+
if edge.is_cycle and edge.target_param:
|
107
|
+
if edge.target_param in requester.output_names:
|
108
|
+
default_value = None
|
109
|
+
else:
|
110
|
+
default_value = requester.get_value_from_template_dict(edge.target_param)
|
111
|
+
|
112
|
+
if flow_id:
|
113
|
+
await self._log_transaction_async(source=self, target=requester, flow_id=str(flow_id), status="error")
|
114
|
+
if default_value is not UNDEFINED:
|
115
|
+
return default_value
|
116
|
+
msg = f"Component {self.display_name} has not been built yet"
|
117
|
+
raise ValueError(msg)
|
118
|
+
|
119
|
+
if requester is None:
|
120
|
+
msg = "Requester Vertex is None"
|
121
|
+
raise ValueError(msg)
|
122
|
+
|
123
|
+
edges = self.get_edge_with_target(requester.id)
|
124
|
+
result = UNDEFINED
|
125
|
+
for edge in edges:
|
126
|
+
if (
|
127
|
+
edge is not None
|
128
|
+
and edge.source_handle.name in self.results
|
129
|
+
and edge.target_handle.field_name == target_handle_name
|
130
|
+
):
|
131
|
+
# Get the result from the output instead of the results dict
|
132
|
+
try:
|
133
|
+
output = self.get_output(edge.source_handle.name)
|
134
|
+
|
135
|
+
if output.value is UNDEFINED:
|
136
|
+
result = self.results[edge.source_handle.name]
|
137
|
+
else:
|
138
|
+
result = cast("Any", output.value)
|
139
|
+
except NoComponentInstanceError:
|
140
|
+
result = self.results[edge.source_handle.name]
|
141
|
+
break
|
142
|
+
if result is UNDEFINED:
|
143
|
+
if edge is None:
|
144
|
+
msg = f"Edge not found between {self.display_name} and {requester.display_name}"
|
145
|
+
raise ValueError(msg)
|
146
|
+
if edge.source_handle.name not in self.results:
|
147
|
+
msg = f"Result not found for {edge.source_handle.name}. Results: {self.results}"
|
148
|
+
raise ValueError(msg)
|
149
|
+
msg = f"Result not found for {edge.source_handle.name} in {edge}"
|
150
|
+
raise ValueError(msg)
|
151
|
+
if flow_id:
|
152
|
+
await self._log_transaction_async(source=self, target=requester, flow_id=str(flow_id), status="success")
|
153
|
+
return result
|
154
|
+
|
155
|
+
def extract_messages_from_artifacts(self, artifacts: dict[str, Any]) -> list[dict]:
|
156
|
+
"""Extracts messages from the artifacts.
|
157
|
+
|
158
|
+
Args:
|
159
|
+
artifacts (Dict[str, Any]): The artifacts to extract messages from.
|
160
|
+
|
161
|
+
Returns:
|
162
|
+
List[str]: The extracted messages.
|
163
|
+
"""
|
164
|
+
messages = []
|
165
|
+
for key, artifact in artifacts.items():
|
166
|
+
if any(
|
167
|
+
k not in artifact for k in ["text", "sender", "sender_name", "session_id", "stream_url"]
|
168
|
+
) and not isinstance(artifact, Message):
|
169
|
+
continue
|
170
|
+
message_dict = artifact if isinstance(artifact, dict) else artifact.model_dump()
|
171
|
+
if not message_dict.get("text"):
|
172
|
+
continue
|
173
|
+
with contextlib.suppress(KeyError):
|
174
|
+
messages.append(
|
175
|
+
ChatOutputResponse(
|
176
|
+
message=message_dict["text"],
|
177
|
+
sender=message_dict.get("sender"),
|
178
|
+
sender_name=message_dict.get("sender_name"),
|
179
|
+
session_id=message_dict.get("session_id"),
|
180
|
+
stream_url=message_dict.get("stream_url"),
|
181
|
+
files=[
|
182
|
+
{"path": file} if isinstance(file, str) else file for file in message_dict.get("files", [])
|
183
|
+
],
|
184
|
+
component_id=self.id,
|
185
|
+
type=self.artifacts_type[key],
|
186
|
+
).model_dump(exclude_none=True)
|
187
|
+
)
|
188
|
+
return messages
|
189
|
+
|
190
|
+
def finalize_build(self) -> None:
|
191
|
+
result_dict = self.get_built_result()
|
192
|
+
# We need to set the artifacts to pass information
|
193
|
+
# to the frontend
|
194
|
+
messages = self.extract_messages_from_artifacts(result_dict)
|
195
|
+
result_dict = ResultData(
|
196
|
+
results=result_dict,
|
197
|
+
artifacts=self.artifacts,
|
198
|
+
outputs=self.outputs_logs,
|
199
|
+
logs=self.logs,
|
200
|
+
messages=messages,
|
201
|
+
component_display_name=self.display_name,
|
202
|
+
component_id=self.id,
|
203
|
+
)
|
204
|
+
self.set_result(result_dict)
|
205
|
+
|
206
|
+
|
207
|
+
class InterfaceVertex(ComponentVertex):
|
208
|
+
def __init__(self, data: NodeData, graph):
|
209
|
+
super().__init__(data, graph=graph)
|
210
|
+
self.added_message = None
|
211
|
+
self.steps = [self._build, self._run]
|
212
|
+
self.is_interface_component = True
|
213
|
+
|
214
|
+
def build_stream_url(self) -> str:
|
215
|
+
return f"/api/v1/build/{self.graph.flow_id}/{self.id}/stream"
|
216
|
+
|
217
|
+
def built_object_repr(self):
|
218
|
+
if self.task_id and self.is_task:
|
219
|
+
if task := self.get_task():
|
220
|
+
return str(task.info)
|
221
|
+
return f"Task {self.task_id} is not running"
|
222
|
+
if self.artifacts:
|
223
|
+
# dump as a yaml string
|
224
|
+
if isinstance(self.artifacts, dict):
|
225
|
+
artifacts_ = [self.artifacts]
|
226
|
+
elif hasattr(self.artifacts, "data"):
|
227
|
+
artifacts_ = self.artifacts.data
|
228
|
+
else:
|
229
|
+
artifacts_ = self.artifacts
|
230
|
+
artifacts = []
|
231
|
+
for artifact in artifacts_:
|
232
|
+
# artifacts = {k.title().replace("_", " "): v for k, v in self.artifacts.items() if v is not None}
|
233
|
+
artifact_ = {k.title().replace("_", " "): v for k, v in artifact.items() if v is not None}
|
234
|
+
artifacts.append(artifact_)
|
235
|
+
return yaml.dump(artifacts, default_flow_style=False, allow_unicode=True)
|
236
|
+
return super().built_object_repr()
|
237
|
+
|
238
|
+
def _process_chat_component(self):
|
239
|
+
"""Process the chat component and return the message.
|
240
|
+
|
241
|
+
This method processes the chat component by extracting the necessary parameters
|
242
|
+
such as sender, sender_name, and message from the `params` dictionary. It then
|
243
|
+
performs additional operations based on the type of the `built_object` attribute.
|
244
|
+
If `built_object` is an instance of `AIMessage`, it creates a `ChatOutputResponse`
|
245
|
+
object using the `from_message` method. If `built_object` is not an instance of
|
246
|
+
`UnbuiltObject`, it checks the type of `built_object` and performs specific
|
247
|
+
operations accordingly. If `built_object` is a dictionary, it converts it into a
|
248
|
+
code block. If `built_object` is an instance of `Data`, it assigns the `text`
|
249
|
+
attribute to the `message` variable. If `message` is an instance of `AsyncIterator`
|
250
|
+
or `Iterator`, it builds a stream URL and sets `message` to an empty string. If
|
251
|
+
`built_object` is not a string, it converts it to a string. If `message` is a
|
252
|
+
generator or iterator, it assigns it to the `message` variable. Finally, it creates
|
253
|
+
a `ChatOutputResponse` object using the extracted parameters and assigns it to the
|
254
|
+
`artifacts` attribute. If `artifacts` is not None, it calls the `model_dump` method
|
255
|
+
on it and assigns the result to the `artifacts` attribute. It then returns the
|
256
|
+
`message` variable.
|
257
|
+
|
258
|
+
Returns:
|
259
|
+
str: The processed message.
|
260
|
+
"""
|
261
|
+
artifacts = None
|
262
|
+
sender = self.params.get("sender", None)
|
263
|
+
sender_name = self.params.get("sender_name", None)
|
264
|
+
message = self.params.get(INPUT_FIELD_NAME, None)
|
265
|
+
files = self.params.get("files", [])
|
266
|
+
treat_file_path = files is not None and not isinstance(files, list) and isinstance(files, str)
|
267
|
+
if treat_file_path:
|
268
|
+
self.params["files"] = rewrite_file_path(files)
|
269
|
+
files = [{"path": file} if isinstance(file, str) else file for file in self.params.get("files", [])]
|
270
|
+
if isinstance(message, str):
|
271
|
+
message = unescape_string(message)
|
272
|
+
stream_url = None
|
273
|
+
if "text" in self.results:
|
274
|
+
text_output = self.results["text"]
|
275
|
+
elif "message" in self.results:
|
276
|
+
text_output = self.results["message"].text
|
277
|
+
else:
|
278
|
+
text_output = message
|
279
|
+
if isinstance(text_output, AIMessage | AIMessageChunk):
|
280
|
+
artifacts = ChatOutputResponse.from_message(
|
281
|
+
text_output,
|
282
|
+
sender=sender,
|
283
|
+
sender_name=sender_name,
|
284
|
+
)
|
285
|
+
elif not isinstance(text_output, UnbuiltObject):
|
286
|
+
if isinstance(text_output, dict):
|
287
|
+
# Turn the dict into a pleasing to
|
288
|
+
# read JSON inside a code block
|
289
|
+
message = dict_to_codeblock(text_output)
|
290
|
+
elif isinstance(text_output, Data):
|
291
|
+
message = text_output.text
|
292
|
+
elif isinstance(message, AsyncIterator | Iterator):
|
293
|
+
stream_url = self.build_stream_url()
|
294
|
+
message = ""
|
295
|
+
self.results["text"] = message
|
296
|
+
self.results["message"].text = message
|
297
|
+
self.built_object = self.results
|
298
|
+
elif not isinstance(text_output, str):
|
299
|
+
message = str(text_output)
|
300
|
+
# if the message is a generator or iterator
|
301
|
+
# it means that it is a stream of messages
|
302
|
+
|
303
|
+
else:
|
304
|
+
message = text_output
|
305
|
+
|
306
|
+
if hasattr(sender_name, "get_text"):
|
307
|
+
sender_name = sender_name.get_text()
|
308
|
+
|
309
|
+
artifact_type = ArtifactType.STREAM if stream_url is not None else ArtifactType.OBJECT
|
310
|
+
artifacts = ChatOutputResponse(
|
311
|
+
message=message,
|
312
|
+
sender=sender,
|
313
|
+
sender_name=sender_name,
|
314
|
+
stream_url=stream_url,
|
315
|
+
files=files,
|
316
|
+
type=artifact_type,
|
317
|
+
)
|
318
|
+
|
319
|
+
self.will_stream = stream_url is not None
|
320
|
+
if artifacts:
|
321
|
+
self.artifacts = artifacts.model_dump(exclude_none=True)
|
322
|
+
|
323
|
+
return message
|
324
|
+
|
325
|
+
def _process_data_component(self):
|
326
|
+
"""Process the record component of the vertex.
|
327
|
+
|
328
|
+
If the built object is an instance of `Data`, it calls the `model_dump` method
|
329
|
+
and assigns the result to the `artifacts` attribute.
|
330
|
+
|
331
|
+
If the built object is a list, it iterates over each element and checks if it is
|
332
|
+
an instance of `Data`. If it is, it calls the `model_dump` method and appends
|
333
|
+
the result to the `artifacts` list. If it is not, it raises a `ValueError` if the
|
334
|
+
`ignore_errors` parameter is set to `False`, or logs an error message if it is set
|
335
|
+
to `True`.
|
336
|
+
|
337
|
+
Returns:
|
338
|
+
The built object.
|
339
|
+
|
340
|
+
Raises:
|
341
|
+
ValueError: If an element in the list is not an instance of `Data` and
|
342
|
+
`ignore_errors` is set to `False`.
|
343
|
+
"""
|
344
|
+
if isinstance(self.built_object, Data):
|
345
|
+
artifacts = [self.built_object.data]
|
346
|
+
elif isinstance(self.built_object, list):
|
347
|
+
artifacts = []
|
348
|
+
ignore_errors = self.params.get("ignore_errors", False)
|
349
|
+
for value in self.built_object:
|
350
|
+
if isinstance(value, Data):
|
351
|
+
artifacts.append(value.data)
|
352
|
+
elif ignore_errors:
|
353
|
+
logger.error(f"Data expected, but got {value} of type {type(value)}")
|
354
|
+
else:
|
355
|
+
msg = f"Data expected, but got {value} of type {type(value)}"
|
356
|
+
raise ValueError(msg)
|
357
|
+
self.artifacts = DataOutputResponse(data=artifacts)
|
358
|
+
return self.built_object
|
359
|
+
|
360
|
+
async def _run(self, *args, **kwargs) -> None: # noqa: ARG002
|
361
|
+
if self.vertex_type in CHAT_COMPONENTS:
|
362
|
+
message = self._process_chat_component()
|
363
|
+
elif self.vertex_type in RECORDS_COMPONENTS:
|
364
|
+
message = self._process_data_component()
|
365
|
+
if isinstance(self.built_object, AsyncIterator | Iterator):
|
366
|
+
if self.params.get("return_data", False):
|
367
|
+
self.built_object = Data(text=message, data=self.artifacts)
|
368
|
+
else:
|
369
|
+
self.built_object = message
|
370
|
+
self.built_result = self.built_object
|
371
|
+
|
372
|
+
async def stream(self):
|
373
|
+
iterator = self.params.get(INPUT_FIELD_NAME, None)
|
374
|
+
if not isinstance(iterator, AsyncIterator | Iterator):
|
375
|
+
msg = "The message must be an iterator or an async iterator."
|
376
|
+
raise TypeError(msg)
|
377
|
+
is_async = isinstance(iterator, AsyncIterator)
|
378
|
+
complete_message = ""
|
379
|
+
if is_async:
|
380
|
+
async for message in iterator:
|
381
|
+
message_ = message.content if hasattr(message, "content") else message
|
382
|
+
message_ = message_.text if hasattr(message_, "text") else message_
|
383
|
+
yield message_
|
384
|
+
complete_message += message_
|
385
|
+
else:
|
386
|
+
for message in iterator:
|
387
|
+
message_ = message.content if hasattr(message, "content") else message
|
388
|
+
message_ = message_.text if hasattr(message_, "text") else message_
|
389
|
+
yield message_
|
390
|
+
complete_message += message_
|
391
|
+
|
392
|
+
files = self.params.get("files", [])
|
393
|
+
|
394
|
+
treat_file_path = files is not None and not isinstance(files, list) and isinstance(files, str)
|
395
|
+
if treat_file_path:
|
396
|
+
self.params["files"] = rewrite_file_path(files)
|
397
|
+
|
398
|
+
if hasattr(self.params.get("sender_name"), "get_text"):
|
399
|
+
sender_name = self.params.get("sender_name").get_text()
|
400
|
+
else:
|
401
|
+
sender_name = self.params.get("sender_name")
|
402
|
+
self.artifacts = ChatOutputResponse(
|
403
|
+
message=complete_message,
|
404
|
+
sender=self.params.get("sender", ""),
|
405
|
+
sender_name=sender_name,
|
406
|
+
files=[{"path": file} if isinstance(file, str) else file for file in self.params.get("files", [])],
|
407
|
+
type=ArtifactType.OBJECT.value,
|
408
|
+
).model_dump()
|
409
|
+
|
410
|
+
message = await Message.create(
|
411
|
+
text=complete_message,
|
412
|
+
sender=self.params.get("sender", ""),
|
413
|
+
sender_name=self.params.get("sender_name", ""),
|
414
|
+
files=self.params.get("files", []),
|
415
|
+
flow_id=self.graph.flow_id,
|
416
|
+
session_id=self.params.get("session_id", ""),
|
417
|
+
)
|
418
|
+
self.params[INPUT_FIELD_NAME] = complete_message
|
419
|
+
if isinstance(self.built_object, dict):
|
420
|
+
for key, value in self.built_object.items():
|
421
|
+
if hasattr(value, "text") and (isinstance(value.text, AsyncIterator | Iterator) or value.text == ""):
|
422
|
+
self.built_object[key] = message
|
423
|
+
else:
|
424
|
+
self.built_object = message
|
425
|
+
self.artifacts_type = ArtifactType.MESSAGE
|
426
|
+
|
427
|
+
# Update artifacts with the message
|
428
|
+
# and remove the stream_url
|
429
|
+
self.finalize_build()
|
430
|
+
await logger.adebug(f"Streamed message: {complete_message}")
|
431
|
+
# Set the result in the vertex of origin
|
432
|
+
edges = self.get_edge_with_target(self.id)
|
433
|
+
for edge in edges:
|
434
|
+
origin_vertex = self.graph.get_vertex(edge.source_id)
|
435
|
+
for key, value in origin_vertex.results.items():
|
436
|
+
if isinstance(value, AsyncIterator | Iterator):
|
437
|
+
origin_vertex.results[key] = complete_message
|
438
|
+
if (
|
439
|
+
self.custom_component
|
440
|
+
and hasattr(self.custom_component, "should_store_message")
|
441
|
+
and hasattr(self.custom_component, "store_message")
|
442
|
+
):
|
443
|
+
await self.custom_component.store_message(message)
|
444
|
+
await log_vertex_build(
|
445
|
+
flow_id=self.graph.flow_id,
|
446
|
+
vertex_id=self.id,
|
447
|
+
valid=True,
|
448
|
+
params=self.built_object_repr(),
|
449
|
+
data=self.result,
|
450
|
+
artifacts=self.artifacts,
|
451
|
+
)
|
452
|
+
|
453
|
+
self._validate_built_object()
|
454
|
+
self.built = True
|
455
|
+
|
456
|
+
async def consume_async_generator(self) -> None:
|
457
|
+
async for _ in self.stream():
|
458
|
+
pass
|
459
|
+
|
460
|
+
def _is_chat_input(self):
|
461
|
+
return self.vertex_type == InterfaceComponentTypes.ChatInput and self.is_input
|
462
|
+
|
463
|
+
|
464
|
+
class StateVertex(ComponentVertex):
|
465
|
+
def __init__(self, data: NodeData, graph):
|
466
|
+
"""Initializes a StateVertex with the provided node data and graph.
|
467
|
+
|
468
|
+
Sets up the build steps and marks the vertex as a state vertex.
|
469
|
+
"""
|
470
|
+
super().__init__(data, graph=graph)
|
471
|
+
self.steps = [self._build]
|
472
|
+
self.is_state = True
|
473
|
+
|
474
|
+
def built_object_repr(self):
|
475
|
+
"""Returns a string representation of the built object from the artifacts if available.
|
476
|
+
|
477
|
+
If the artifacts dictionary contains a non-empty "repr" key, its value is returned.
|
478
|
+
If the "repr" value is falsy, falls back to the superclass representation.
|
479
|
+
Returns None if no representation is available.
|
480
|
+
"""
|
481
|
+
if self.artifacts and "repr" in self.artifacts:
|
482
|
+
return self.artifacts["repr"] or super().built_object_repr()
|
483
|
+
return None
|
484
|
+
|
485
|
+
|
486
|
+
def dict_to_codeblock(d: dict) -> str:
|
487
|
+
serialized = {key: serialize(val) for key, val in d.items()}
|
488
|
+
json_str = json.dumps(serialized, indent=4)
|
489
|
+
return f"```json\n{json_str}\n```"
|
lfx/helpers/__init__.py
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
"""Helpers module for lfx package."""
|
@@ -0,0 +1,71 @@
|
|
1
|
+
from typing import Any, TypedDict
|
2
|
+
|
3
|
+
from pydantic import BaseModel as PydanticBaseModel
|
4
|
+
from pydantic import ConfigDict, Field, create_model
|
5
|
+
|
6
|
+
TRUE_VALUES = ["true", "1", "t", "y", "yes"]
|
7
|
+
|
8
|
+
|
9
|
+
class SchemaField(TypedDict):
|
10
|
+
name: str
|
11
|
+
type: str
|
12
|
+
description: str
|
13
|
+
multiple: bool
|
14
|
+
|
15
|
+
|
16
|
+
class BaseModel(PydanticBaseModel):
|
17
|
+
model_config = ConfigDict(populate_by_name=True)
|
18
|
+
|
19
|
+
|
20
|
+
def _get_type_annotation(type_str: str, *, multiple: bool) -> type:
|
21
|
+
type_mapping = {
|
22
|
+
"str": str,
|
23
|
+
"int": int,
|
24
|
+
"float": float,
|
25
|
+
"bool": bool,
|
26
|
+
"boolean": bool,
|
27
|
+
"list": list[Any],
|
28
|
+
"dict": dict[str, Any],
|
29
|
+
"number": float,
|
30
|
+
"text": str,
|
31
|
+
}
|
32
|
+
try:
|
33
|
+
base_type = type_mapping[type_str]
|
34
|
+
except KeyError as e:
|
35
|
+
msg = f"Invalid type: {type_str}"
|
36
|
+
raise ValueError(msg) from e
|
37
|
+
if multiple:
|
38
|
+
return list[base_type] # type: ignore[valid-type]
|
39
|
+
return base_type # type: ignore[return-value]
|
40
|
+
|
41
|
+
|
42
|
+
def build_model_from_schema(schema: list[SchemaField]) -> type[PydanticBaseModel]:
|
43
|
+
fields = {}
|
44
|
+
for field in schema:
|
45
|
+
field_name = field["name"]
|
46
|
+
field_type_str = field["type"]
|
47
|
+
description = field.get("description", "")
|
48
|
+
multiple = field.get("multiple", False)
|
49
|
+
multiple = coalesce_bool(multiple)
|
50
|
+
field_type_annotation = _get_type_annotation(field_type_str, multiple=multiple)
|
51
|
+
fields[field_name] = (field_type_annotation, Field(description=description))
|
52
|
+
return create_model("OutputModel", **fields)
|
53
|
+
|
54
|
+
|
55
|
+
def coalesce_bool(value: Any) -> bool:
|
56
|
+
"""Coalesces the given value into a boolean.
|
57
|
+
|
58
|
+
Args:
|
59
|
+
value (Any): The value to be coalesced.
|
60
|
+
|
61
|
+
Returns:
|
62
|
+
bool: The coalesced boolean value.
|
63
|
+
|
64
|
+
"""
|
65
|
+
if isinstance(value, bool):
|
66
|
+
return value
|
67
|
+
if isinstance(value, str):
|
68
|
+
return value.lower() in TRUE_VALUES
|
69
|
+
if isinstance(value, int):
|
70
|
+
return bool(value)
|
71
|
+
return False
|
lfx/helpers/custom.py
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
|
4
|
+
def format_type(type_: Any) -> str:
|
5
|
+
if type_ is str:
|
6
|
+
type_ = "Text"
|
7
|
+
elif hasattr(type_, "__name__"):
|
8
|
+
type_ = type_.__name__
|
9
|
+
elif hasattr(type_, "__class__"):
|
10
|
+
type_ = type_.__class__.__name__
|
11
|
+
else:
|
12
|
+
type_ = str(type_)
|
13
|
+
return type_
|