lfx-nightly 0.2.0.dev25__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of lfx-nightly might be problematic. Click here for more details.
- lfx/__init__.py +0 -0
- lfx/__main__.py +25 -0
- lfx/_assets/component_index.json +1 -0
- lfx/base/__init__.py +0 -0
- lfx/base/agents/__init__.py +0 -0
- lfx/base/agents/agent.py +375 -0
- lfx/base/agents/altk_base_agent.py +380 -0
- lfx/base/agents/altk_tool_wrappers.py +565 -0
- lfx/base/agents/callback.py +130 -0
- lfx/base/agents/context.py +109 -0
- lfx/base/agents/crewai/__init__.py +0 -0
- lfx/base/agents/crewai/crew.py +231 -0
- lfx/base/agents/crewai/tasks.py +12 -0
- lfx/base/agents/default_prompts.py +23 -0
- lfx/base/agents/errors.py +15 -0
- lfx/base/agents/events.py +430 -0
- lfx/base/agents/utils.py +237 -0
- lfx/base/astra_assistants/__init__.py +0 -0
- lfx/base/astra_assistants/util.py +171 -0
- lfx/base/chains/__init__.py +0 -0
- lfx/base/chains/model.py +19 -0
- lfx/base/composio/__init__.py +0 -0
- lfx/base/composio/composio_base.py +2584 -0
- lfx/base/compressors/__init__.py +0 -0
- lfx/base/compressors/model.py +60 -0
- lfx/base/constants.py +46 -0
- lfx/base/curl/__init__.py +0 -0
- lfx/base/curl/parse.py +188 -0
- lfx/base/data/__init__.py +5 -0
- lfx/base/data/base_file.py +810 -0
- lfx/base/data/docling_utils.py +338 -0
- lfx/base/data/storage_utils.py +192 -0
- lfx/base/data/utils.py +362 -0
- lfx/base/datastax/__init__.py +5 -0
- lfx/base/datastax/astradb_base.py +896 -0
- lfx/base/document_transformers/__init__.py +0 -0
- lfx/base/document_transformers/model.py +43 -0
- lfx/base/embeddings/__init__.py +0 -0
- lfx/base/embeddings/aiml_embeddings.py +62 -0
- lfx/base/embeddings/embeddings_class.py +113 -0
- lfx/base/embeddings/model.py +26 -0
- lfx/base/flow_processing/__init__.py +0 -0
- lfx/base/flow_processing/utils.py +86 -0
- lfx/base/huggingface/__init__.py +0 -0
- lfx/base/huggingface/model_bridge.py +133 -0
- lfx/base/io/__init__.py +0 -0
- lfx/base/io/chat.py +21 -0
- lfx/base/io/text.py +22 -0
- lfx/base/knowledge_bases/__init__.py +3 -0
- lfx/base/knowledge_bases/knowledge_base_utils.py +137 -0
- lfx/base/langchain_utilities/__init__.py +0 -0
- lfx/base/langchain_utilities/model.py +35 -0
- lfx/base/langchain_utilities/spider_constants.py +1 -0
- lfx/base/langwatch/__init__.py +0 -0
- lfx/base/langwatch/utils.py +18 -0
- lfx/base/mcp/__init__.py +0 -0
- lfx/base/mcp/constants.py +2 -0
- lfx/base/mcp/util.py +1659 -0
- lfx/base/memory/__init__.py +0 -0
- lfx/base/memory/memory.py +49 -0
- lfx/base/memory/model.py +38 -0
- lfx/base/models/__init__.py +3 -0
- lfx/base/models/aiml_constants.py +51 -0
- lfx/base/models/anthropic_constants.py +51 -0
- lfx/base/models/aws_constants.py +151 -0
- lfx/base/models/chat_result.py +76 -0
- lfx/base/models/cometapi_constants.py +54 -0
- lfx/base/models/google_generative_ai_constants.py +70 -0
- lfx/base/models/google_generative_ai_model.py +38 -0
- lfx/base/models/groq_constants.py +150 -0
- lfx/base/models/groq_model_discovery.py +265 -0
- lfx/base/models/model.py +375 -0
- lfx/base/models/model_input_constants.py +378 -0
- lfx/base/models/model_metadata.py +41 -0
- lfx/base/models/model_utils.py +108 -0
- lfx/base/models/novita_constants.py +35 -0
- lfx/base/models/ollama_constants.py +52 -0
- lfx/base/models/openai_constants.py +129 -0
- lfx/base/models/sambanova_constants.py +18 -0
- lfx/base/models/watsonx_constants.py +36 -0
- lfx/base/processing/__init__.py +0 -0
- lfx/base/prompts/__init__.py +0 -0
- lfx/base/prompts/api_utils.py +224 -0
- lfx/base/prompts/utils.py +61 -0
- lfx/base/textsplitters/__init__.py +0 -0
- lfx/base/textsplitters/model.py +28 -0
- lfx/base/tools/__init__.py +0 -0
- lfx/base/tools/base.py +26 -0
- lfx/base/tools/component_tool.py +325 -0
- lfx/base/tools/constants.py +49 -0
- lfx/base/tools/flow_tool.py +132 -0
- lfx/base/tools/run_flow.py +698 -0
- lfx/base/vectorstores/__init__.py +0 -0
- lfx/base/vectorstores/model.py +193 -0
- lfx/base/vectorstores/utils.py +22 -0
- lfx/base/vectorstores/vector_store_connection_decorator.py +52 -0
- lfx/cli/__init__.py +5 -0
- lfx/cli/commands.py +327 -0
- lfx/cli/common.py +650 -0
- lfx/cli/run.py +506 -0
- lfx/cli/script_loader.py +289 -0
- lfx/cli/serve_app.py +546 -0
- lfx/cli/validation.py +69 -0
- lfx/components/FAISS/__init__.py +34 -0
- lfx/components/FAISS/faiss.py +111 -0
- lfx/components/Notion/__init__.py +19 -0
- lfx/components/Notion/add_content_to_page.py +269 -0
- lfx/components/Notion/create_page.py +94 -0
- lfx/components/Notion/list_database_properties.py +68 -0
- lfx/components/Notion/list_pages.py +122 -0
- lfx/components/Notion/list_users.py +77 -0
- lfx/components/Notion/page_content_viewer.py +93 -0
- lfx/components/Notion/search.py +111 -0
- lfx/components/Notion/update_page_property.py +114 -0
- lfx/components/__init__.py +428 -0
- lfx/components/_importing.py +42 -0
- lfx/components/agentql/__init__.py +3 -0
- lfx/components/agentql/agentql_api.py +151 -0
- lfx/components/aiml/__init__.py +37 -0
- lfx/components/aiml/aiml.py +115 -0
- lfx/components/aiml/aiml_embeddings.py +37 -0
- lfx/components/altk/__init__.py +34 -0
- lfx/components/altk/altk_agent.py +193 -0
- lfx/components/amazon/__init__.py +36 -0
- lfx/components/amazon/amazon_bedrock_converse.py +195 -0
- lfx/components/amazon/amazon_bedrock_embedding.py +109 -0
- lfx/components/amazon/amazon_bedrock_model.py +130 -0
- lfx/components/amazon/s3_bucket_uploader.py +211 -0
- lfx/components/anthropic/__init__.py +34 -0
- lfx/components/anthropic/anthropic.py +187 -0
- lfx/components/apify/__init__.py +5 -0
- lfx/components/apify/apify_actor.py +325 -0
- lfx/components/arxiv/__init__.py +3 -0
- lfx/components/arxiv/arxiv.py +169 -0
- lfx/components/assemblyai/__init__.py +46 -0
- lfx/components/assemblyai/assemblyai_get_subtitles.py +83 -0
- lfx/components/assemblyai/assemblyai_lemur.py +183 -0
- lfx/components/assemblyai/assemblyai_list_transcripts.py +95 -0
- lfx/components/assemblyai/assemblyai_poll_transcript.py +72 -0
- lfx/components/assemblyai/assemblyai_start_transcript.py +188 -0
- lfx/components/azure/__init__.py +37 -0
- lfx/components/azure/azure_openai.py +95 -0
- lfx/components/azure/azure_openai_embeddings.py +83 -0
- lfx/components/baidu/__init__.py +32 -0
- lfx/components/baidu/baidu_qianfan_chat.py +113 -0
- lfx/components/bing/__init__.py +3 -0
- lfx/components/bing/bing_search_api.py +61 -0
- lfx/components/cassandra/__init__.py +40 -0
- lfx/components/cassandra/cassandra.py +264 -0
- lfx/components/cassandra/cassandra_chat.py +92 -0
- lfx/components/cassandra/cassandra_graph.py +238 -0
- lfx/components/chains/__init__.py +3 -0
- lfx/components/chroma/__init__.py +34 -0
- lfx/components/chroma/chroma.py +169 -0
- lfx/components/cleanlab/__init__.py +40 -0
- lfx/components/cleanlab/cleanlab_evaluator.py +155 -0
- lfx/components/cleanlab/cleanlab_rag_evaluator.py +254 -0
- lfx/components/cleanlab/cleanlab_remediator.py +131 -0
- lfx/components/clickhouse/__init__.py +34 -0
- lfx/components/clickhouse/clickhouse.py +135 -0
- lfx/components/cloudflare/__init__.py +32 -0
- lfx/components/cloudflare/cloudflare.py +81 -0
- lfx/components/cohere/__init__.py +40 -0
- lfx/components/cohere/cohere_embeddings.py +81 -0
- lfx/components/cohere/cohere_models.py +46 -0
- lfx/components/cohere/cohere_rerank.py +51 -0
- lfx/components/cometapi/__init__.py +32 -0
- lfx/components/cometapi/cometapi.py +166 -0
- lfx/components/composio/__init__.py +222 -0
- lfx/components/composio/agentql_composio.py +11 -0
- lfx/components/composio/agiled_composio.py +11 -0
- lfx/components/composio/airtable_composio.py +11 -0
- lfx/components/composio/apollo_composio.py +11 -0
- lfx/components/composio/asana_composio.py +11 -0
- lfx/components/composio/attio_composio.py +11 -0
- lfx/components/composio/bitbucket_composio.py +11 -0
- lfx/components/composio/bolna_composio.py +11 -0
- lfx/components/composio/brightdata_composio.py +11 -0
- lfx/components/composio/calendly_composio.py +11 -0
- lfx/components/composio/canva_composio.py +11 -0
- lfx/components/composio/canvas_composio.py +11 -0
- lfx/components/composio/coda_composio.py +11 -0
- lfx/components/composio/composio_api.py +278 -0
- lfx/components/composio/contentful_composio.py +11 -0
- lfx/components/composio/digicert_composio.py +11 -0
- lfx/components/composio/discord_composio.py +11 -0
- lfx/components/composio/dropbox_compnent.py +11 -0
- lfx/components/composio/elevenlabs_composio.py +11 -0
- lfx/components/composio/exa_composio.py +11 -0
- lfx/components/composio/figma_composio.py +11 -0
- lfx/components/composio/finage_composio.py +11 -0
- lfx/components/composio/firecrawl_composio.py +11 -0
- lfx/components/composio/fireflies_composio.py +11 -0
- lfx/components/composio/fixer_composio.py +11 -0
- lfx/components/composio/flexisign_composio.py +11 -0
- lfx/components/composio/freshdesk_composio.py +11 -0
- lfx/components/composio/github_composio.py +11 -0
- lfx/components/composio/gmail_composio.py +38 -0
- lfx/components/composio/googlebigquery_composio.py +11 -0
- lfx/components/composio/googlecalendar_composio.py +11 -0
- lfx/components/composio/googleclassroom_composio.py +11 -0
- lfx/components/composio/googledocs_composio.py +11 -0
- lfx/components/composio/googlemeet_composio.py +11 -0
- lfx/components/composio/googlesheets_composio.py +11 -0
- lfx/components/composio/googletasks_composio.py +8 -0
- lfx/components/composio/heygen_composio.py +11 -0
- lfx/components/composio/instagram_composio.py +11 -0
- lfx/components/composio/jira_composio.py +11 -0
- lfx/components/composio/jotform_composio.py +11 -0
- lfx/components/composio/klaviyo_composio.py +11 -0
- lfx/components/composio/linear_composio.py +11 -0
- lfx/components/composio/listennotes_composio.py +11 -0
- lfx/components/composio/mem0_composio.py +11 -0
- lfx/components/composio/miro_composio.py +11 -0
- lfx/components/composio/missive_composio.py +11 -0
- lfx/components/composio/notion_composio.py +11 -0
- lfx/components/composio/onedrive_composio.py +11 -0
- lfx/components/composio/outlook_composio.py +11 -0
- lfx/components/composio/pandadoc_composio.py +11 -0
- lfx/components/composio/peopledatalabs_composio.py +11 -0
- lfx/components/composio/perplexityai_composio.py +11 -0
- lfx/components/composio/reddit_composio.py +11 -0
- lfx/components/composio/serpapi_composio.py +11 -0
- lfx/components/composio/slack_composio.py +11 -0
- lfx/components/composio/slackbot_composio.py +11 -0
- lfx/components/composio/snowflake_composio.py +11 -0
- lfx/components/composio/supabase_composio.py +11 -0
- lfx/components/composio/tavily_composio.py +11 -0
- lfx/components/composio/timelinesai_composio.py +11 -0
- lfx/components/composio/todoist_composio.py +11 -0
- lfx/components/composio/wrike_composio.py +11 -0
- lfx/components/composio/youtube_composio.py +11 -0
- lfx/components/confluence/__init__.py +3 -0
- lfx/components/confluence/confluence.py +84 -0
- lfx/components/couchbase/__init__.py +34 -0
- lfx/components/couchbase/couchbase.py +102 -0
- lfx/components/crewai/__init__.py +49 -0
- lfx/components/crewai/crewai.py +108 -0
- lfx/components/crewai/hierarchical_crew.py +47 -0
- lfx/components/crewai/hierarchical_task.py +45 -0
- lfx/components/crewai/sequential_crew.py +53 -0
- lfx/components/crewai/sequential_task.py +74 -0
- lfx/components/crewai/sequential_task_agent.py +144 -0
- lfx/components/cuga/__init__.py +34 -0
- lfx/components/cuga/cuga_agent.py +730 -0
- lfx/components/custom_component/__init__.py +34 -0
- lfx/components/custom_component/custom_component.py +31 -0
- lfx/components/data/__init__.py +114 -0
- lfx/components/data_source/__init__.py +58 -0
- lfx/components/data_source/api_request.py +577 -0
- lfx/components/data_source/csv_to_data.py +101 -0
- lfx/components/data_source/json_to_data.py +106 -0
- lfx/components/data_source/mock_data.py +398 -0
- lfx/components/data_source/news_search.py +166 -0
- lfx/components/data_source/rss.py +71 -0
- lfx/components/data_source/sql_executor.py +101 -0
- lfx/components/data_source/url.py +311 -0
- lfx/components/data_source/web_search.py +326 -0
- lfx/components/datastax/__init__.py +76 -0
- lfx/components/datastax/astradb_assistant_manager.py +307 -0
- lfx/components/datastax/astradb_chatmemory.py +40 -0
- lfx/components/datastax/astradb_cql.py +288 -0
- lfx/components/datastax/astradb_graph.py +217 -0
- lfx/components/datastax/astradb_tool.py +378 -0
- lfx/components/datastax/astradb_vectorize.py +122 -0
- lfx/components/datastax/astradb_vectorstore.py +449 -0
- lfx/components/datastax/create_assistant.py +59 -0
- lfx/components/datastax/create_thread.py +33 -0
- lfx/components/datastax/dotenv.py +36 -0
- lfx/components/datastax/get_assistant.py +38 -0
- lfx/components/datastax/getenvvar.py +31 -0
- lfx/components/datastax/graph_rag.py +141 -0
- lfx/components/datastax/hcd.py +315 -0
- lfx/components/datastax/list_assistants.py +26 -0
- lfx/components/datastax/run.py +90 -0
- lfx/components/deactivated/__init__.py +15 -0
- lfx/components/deactivated/amazon_kendra.py +66 -0
- lfx/components/deactivated/chat_litellm_model.py +158 -0
- lfx/components/deactivated/code_block_extractor.py +26 -0
- lfx/components/deactivated/documents_to_data.py +22 -0
- lfx/components/deactivated/embed.py +16 -0
- lfx/components/deactivated/extract_key_from_data.py +46 -0
- lfx/components/deactivated/json_document_builder.py +57 -0
- lfx/components/deactivated/list_flows.py +20 -0
- lfx/components/deactivated/mcp_sse.py +61 -0
- lfx/components/deactivated/mcp_stdio.py +62 -0
- lfx/components/deactivated/merge_data.py +93 -0
- lfx/components/deactivated/message.py +37 -0
- lfx/components/deactivated/metal.py +54 -0
- lfx/components/deactivated/multi_query.py +59 -0
- lfx/components/deactivated/retriever.py +43 -0
- lfx/components/deactivated/selective_passthrough.py +77 -0
- lfx/components/deactivated/should_run_next.py +40 -0
- lfx/components/deactivated/split_text.py +63 -0
- lfx/components/deactivated/store_message.py +24 -0
- lfx/components/deactivated/sub_flow.py +124 -0
- lfx/components/deactivated/vectara_self_query.py +76 -0
- lfx/components/deactivated/vector_store.py +24 -0
- lfx/components/deepseek/__init__.py +34 -0
- lfx/components/deepseek/deepseek.py +136 -0
- lfx/components/docling/__init__.py +43 -0
- lfx/components/docling/chunk_docling_document.py +186 -0
- lfx/components/docling/docling_inline.py +238 -0
- lfx/components/docling/docling_remote.py +195 -0
- lfx/components/docling/export_docling_document.py +117 -0
- lfx/components/documentloaders/__init__.py +3 -0
- lfx/components/duckduckgo/__init__.py +3 -0
- lfx/components/duckduckgo/duck_duck_go_search_run.py +92 -0
- lfx/components/elastic/__init__.py +37 -0
- lfx/components/elastic/elasticsearch.py +267 -0
- lfx/components/elastic/opensearch.py +789 -0
- lfx/components/elastic/opensearch_multimodal.py +1575 -0
- lfx/components/embeddings/__init__.py +37 -0
- lfx/components/embeddings/similarity.py +77 -0
- lfx/components/embeddings/text_embedder.py +65 -0
- lfx/components/exa/__init__.py +3 -0
- lfx/components/exa/exa_search.py +68 -0
- lfx/components/files_and_knowledge/__init__.py +47 -0
- lfx/components/files_and_knowledge/directory.py +113 -0
- lfx/components/files_and_knowledge/file.py +841 -0
- lfx/components/files_and_knowledge/ingestion.py +694 -0
- lfx/components/files_and_knowledge/retrieval.py +264 -0
- lfx/components/files_and_knowledge/save_file.py +746 -0
- lfx/components/firecrawl/__init__.py +43 -0
- lfx/components/firecrawl/firecrawl_crawl_api.py +88 -0
- lfx/components/firecrawl/firecrawl_extract_api.py +136 -0
- lfx/components/firecrawl/firecrawl_map_api.py +89 -0
- lfx/components/firecrawl/firecrawl_scrape_api.py +73 -0
- lfx/components/flow_controls/__init__.py +58 -0
- lfx/components/flow_controls/conditional_router.py +208 -0
- lfx/components/flow_controls/data_conditional_router.py +126 -0
- lfx/components/flow_controls/flow_tool.py +111 -0
- lfx/components/flow_controls/listen.py +29 -0
- lfx/components/flow_controls/loop.py +163 -0
- lfx/components/flow_controls/notify.py +88 -0
- lfx/components/flow_controls/pass_message.py +36 -0
- lfx/components/flow_controls/run_flow.py +108 -0
- lfx/components/flow_controls/sub_flow.py +115 -0
- lfx/components/git/__init__.py +4 -0
- lfx/components/git/git.py +262 -0
- lfx/components/git/gitextractor.py +196 -0
- lfx/components/glean/__init__.py +3 -0
- lfx/components/glean/glean_search_api.py +173 -0
- lfx/components/google/__init__.py +17 -0
- lfx/components/google/gmail.py +193 -0
- lfx/components/google/google_bq_sql_executor.py +157 -0
- lfx/components/google/google_drive.py +92 -0
- lfx/components/google/google_drive_search.py +152 -0
- lfx/components/google/google_generative_ai.py +144 -0
- lfx/components/google/google_generative_ai_embeddings.py +141 -0
- lfx/components/google/google_oauth_token.py +89 -0
- lfx/components/google/google_search_api_core.py +68 -0
- lfx/components/google/google_serper_api_core.py +74 -0
- lfx/components/groq/__init__.py +34 -0
- lfx/components/groq/groq.py +143 -0
- lfx/components/helpers/__init__.py +154 -0
- lfx/components/homeassistant/__init__.py +7 -0
- lfx/components/homeassistant/home_assistant_control.py +152 -0
- lfx/components/homeassistant/list_home_assistant_states.py +137 -0
- lfx/components/huggingface/__init__.py +37 -0
- lfx/components/huggingface/huggingface.py +199 -0
- lfx/components/huggingface/huggingface_inference_api.py +106 -0
- lfx/components/ibm/__init__.py +34 -0
- lfx/components/ibm/watsonx.py +207 -0
- lfx/components/ibm/watsonx_embeddings.py +135 -0
- lfx/components/icosacomputing/__init__.py +5 -0
- lfx/components/icosacomputing/combinatorial_reasoner.py +84 -0
- lfx/components/input_output/__init__.py +40 -0
- lfx/components/input_output/chat.py +109 -0
- lfx/components/input_output/chat_output.py +184 -0
- lfx/components/input_output/text.py +27 -0
- lfx/components/input_output/text_output.py +29 -0
- lfx/components/input_output/webhook.py +56 -0
- lfx/components/jigsawstack/__init__.py +23 -0
- lfx/components/jigsawstack/ai_scrape.py +126 -0
- lfx/components/jigsawstack/ai_web_search.py +136 -0
- lfx/components/jigsawstack/file_read.py +115 -0
- lfx/components/jigsawstack/file_upload.py +94 -0
- lfx/components/jigsawstack/image_generation.py +205 -0
- lfx/components/jigsawstack/nsfw.py +60 -0
- lfx/components/jigsawstack/object_detection.py +124 -0
- lfx/components/jigsawstack/sentiment.py +112 -0
- lfx/components/jigsawstack/text_to_sql.py +90 -0
- lfx/components/jigsawstack/text_translate.py +77 -0
- lfx/components/jigsawstack/vocr.py +107 -0
- lfx/components/knowledge_bases/__init__.py +89 -0
- lfx/components/langchain_utilities/__init__.py +109 -0
- lfx/components/langchain_utilities/character.py +53 -0
- lfx/components/langchain_utilities/conversation.py +59 -0
- lfx/components/langchain_utilities/csv_agent.py +175 -0
- lfx/components/langchain_utilities/fake_embeddings.py +26 -0
- lfx/components/langchain_utilities/html_link_extractor.py +35 -0
- lfx/components/langchain_utilities/json_agent.py +100 -0
- lfx/components/langchain_utilities/langchain_hub.py +126 -0
- lfx/components/langchain_utilities/language_recursive.py +49 -0
- lfx/components/langchain_utilities/language_semantic.py +138 -0
- lfx/components/langchain_utilities/llm_checker.py +39 -0
- lfx/components/langchain_utilities/llm_math.py +42 -0
- lfx/components/langchain_utilities/natural_language.py +61 -0
- lfx/components/langchain_utilities/openai_tools.py +53 -0
- lfx/components/langchain_utilities/openapi.py +48 -0
- lfx/components/langchain_utilities/recursive_character.py +60 -0
- lfx/components/langchain_utilities/retrieval_qa.py +83 -0
- lfx/components/langchain_utilities/runnable_executor.py +137 -0
- lfx/components/langchain_utilities/self_query.py +80 -0
- lfx/components/langchain_utilities/spider.py +142 -0
- lfx/components/langchain_utilities/sql.py +40 -0
- lfx/components/langchain_utilities/sql_database.py +35 -0
- lfx/components/langchain_utilities/sql_generator.py +78 -0
- lfx/components/langchain_utilities/tool_calling.py +59 -0
- lfx/components/langchain_utilities/vector_store_info.py +49 -0
- lfx/components/langchain_utilities/vector_store_router.py +33 -0
- lfx/components/langchain_utilities/xml_agent.py +71 -0
- lfx/components/langwatch/__init__.py +3 -0
- lfx/components/langwatch/langwatch.py +278 -0
- lfx/components/link_extractors/__init__.py +3 -0
- lfx/components/llm_operations/__init__.py +46 -0
- lfx/components/llm_operations/batch_run.py +205 -0
- lfx/components/llm_operations/lambda_filter.py +218 -0
- lfx/components/llm_operations/llm_conditional_router.py +421 -0
- lfx/components/llm_operations/llm_selector.py +499 -0
- lfx/components/llm_operations/structured_output.py +244 -0
- lfx/components/lmstudio/__init__.py +34 -0
- lfx/components/lmstudio/lmstudioembeddings.py +89 -0
- lfx/components/lmstudio/lmstudiomodel.py +133 -0
- lfx/components/logic/__init__.py +181 -0
- lfx/components/maritalk/__init__.py +32 -0
- lfx/components/maritalk/maritalk.py +52 -0
- lfx/components/mem0/__init__.py +3 -0
- lfx/components/mem0/mem0_chat_memory.py +147 -0
- lfx/components/milvus/__init__.py +34 -0
- lfx/components/milvus/milvus.py +115 -0
- lfx/components/mistral/__init__.py +37 -0
- lfx/components/mistral/mistral.py +114 -0
- lfx/components/mistral/mistral_embeddings.py +58 -0
- lfx/components/models/__init__.py +89 -0
- lfx/components/models_and_agents/__init__.py +49 -0
- lfx/components/models_and_agents/agent.py +644 -0
- lfx/components/models_and_agents/embedding_model.py +423 -0
- lfx/components/models_and_agents/language_model.py +398 -0
- lfx/components/models_and_agents/mcp_component.py +594 -0
- lfx/components/models_and_agents/memory.py +268 -0
- lfx/components/models_and_agents/prompt.py +67 -0
- lfx/components/mongodb/__init__.py +34 -0
- lfx/components/mongodb/mongodb_atlas.py +213 -0
- lfx/components/needle/__init__.py +3 -0
- lfx/components/needle/needle.py +104 -0
- lfx/components/notdiamond/__init__.py +34 -0
- lfx/components/notdiamond/notdiamond.py +228 -0
- lfx/components/novita/__init__.py +32 -0
- lfx/components/novita/novita.py +130 -0
- lfx/components/nvidia/__init__.py +57 -0
- lfx/components/nvidia/nvidia.py +151 -0
- lfx/components/nvidia/nvidia_embedding.py +77 -0
- lfx/components/nvidia/nvidia_ingest.py +317 -0
- lfx/components/nvidia/nvidia_rerank.py +63 -0
- lfx/components/nvidia/system_assist.py +65 -0
- lfx/components/olivya/__init__.py +3 -0
- lfx/components/olivya/olivya.py +116 -0
- lfx/components/ollama/__init__.py +37 -0
- lfx/components/ollama/ollama.py +548 -0
- lfx/components/ollama/ollama_embeddings.py +103 -0
- lfx/components/openai/__init__.py +37 -0
- lfx/components/openai/openai.py +100 -0
- lfx/components/openai/openai_chat_model.py +176 -0
- lfx/components/openrouter/__init__.py +32 -0
- lfx/components/openrouter/openrouter.py +104 -0
- lfx/components/output_parsers/__init__.py +3 -0
- lfx/components/perplexity/__init__.py +34 -0
- lfx/components/perplexity/perplexity.py +75 -0
- lfx/components/pgvector/__init__.py +34 -0
- lfx/components/pgvector/pgvector.py +72 -0
- lfx/components/pinecone/__init__.py +34 -0
- lfx/components/pinecone/pinecone.py +134 -0
- lfx/components/processing/__init__.py +72 -0
- lfx/components/processing/alter_metadata.py +109 -0
- lfx/components/processing/combine_text.py +40 -0
- lfx/components/processing/converter.py +248 -0
- lfx/components/processing/create_data.py +111 -0
- lfx/components/processing/create_list.py +40 -0
- lfx/components/processing/data_operations.py +528 -0
- lfx/components/processing/data_to_dataframe.py +71 -0
- lfx/components/processing/dataframe_operations.py +313 -0
- lfx/components/processing/dataframe_to_toolset.py +259 -0
- lfx/components/processing/dynamic_create_data.py +357 -0
- lfx/components/processing/extract_key.py +54 -0
- lfx/components/processing/filter_data.py +43 -0
- lfx/components/processing/filter_data_values.py +89 -0
- lfx/components/processing/json_cleaner.py +104 -0
- lfx/components/processing/merge_data.py +91 -0
- lfx/components/processing/message_to_data.py +37 -0
- lfx/components/processing/output_parser.py +46 -0
- lfx/components/processing/parse_data.py +71 -0
- lfx/components/processing/parse_dataframe.py +69 -0
- lfx/components/processing/parse_json_data.py +91 -0
- lfx/components/processing/parser.py +148 -0
- lfx/components/processing/regex.py +83 -0
- lfx/components/processing/select_data.py +49 -0
- lfx/components/processing/split_text.py +141 -0
- lfx/components/processing/store_message.py +91 -0
- lfx/components/processing/update_data.py +161 -0
- lfx/components/prototypes/__init__.py +35 -0
- lfx/components/prototypes/python_function.py +73 -0
- lfx/components/qdrant/__init__.py +34 -0
- lfx/components/qdrant/qdrant.py +109 -0
- lfx/components/redis/__init__.py +37 -0
- lfx/components/redis/redis.py +89 -0
- lfx/components/redis/redis_chat.py +43 -0
- lfx/components/sambanova/__init__.py +32 -0
- lfx/components/sambanova/sambanova.py +84 -0
- lfx/components/scrapegraph/__init__.py +40 -0
- lfx/components/scrapegraph/scrapegraph_markdownify_api.py +64 -0
- lfx/components/scrapegraph/scrapegraph_search_api.py +64 -0
- lfx/components/scrapegraph/scrapegraph_smart_scraper_api.py +71 -0
- lfx/components/searchapi/__init__.py +34 -0
- lfx/components/searchapi/search.py +79 -0
- lfx/components/serpapi/__init__.py +3 -0
- lfx/components/serpapi/serp.py +115 -0
- lfx/components/supabase/__init__.py +34 -0
- lfx/components/supabase/supabase.py +76 -0
- lfx/components/tavily/__init__.py +4 -0
- lfx/components/tavily/tavily_extract.py +117 -0
- lfx/components/tavily/tavily_search.py +212 -0
- lfx/components/textsplitters/__init__.py +3 -0
- lfx/components/toolkits/__init__.py +3 -0
- lfx/components/tools/__init__.py +66 -0
- lfx/components/tools/calculator.py +109 -0
- lfx/components/tools/google_search_api.py +45 -0
- lfx/components/tools/google_serper_api.py +115 -0
- lfx/components/tools/python_code_structured_tool.py +328 -0
- lfx/components/tools/python_repl.py +98 -0
- lfx/components/tools/search_api.py +88 -0
- lfx/components/tools/searxng.py +145 -0
- lfx/components/tools/serp_api.py +120 -0
- lfx/components/tools/tavily_search_tool.py +345 -0
- lfx/components/tools/wikidata_api.py +103 -0
- lfx/components/tools/wikipedia_api.py +50 -0
- lfx/components/tools/yahoo_finance.py +130 -0
- lfx/components/twelvelabs/__init__.py +52 -0
- lfx/components/twelvelabs/convert_astra_results.py +84 -0
- lfx/components/twelvelabs/pegasus_index.py +311 -0
- lfx/components/twelvelabs/split_video.py +301 -0
- lfx/components/twelvelabs/text_embeddings.py +57 -0
- lfx/components/twelvelabs/twelvelabs_pegasus.py +408 -0
- lfx/components/twelvelabs/video_embeddings.py +100 -0
- lfx/components/twelvelabs/video_file.py +191 -0
- lfx/components/unstructured/__init__.py +3 -0
- lfx/components/unstructured/unstructured.py +121 -0
- lfx/components/upstash/__init__.py +34 -0
- lfx/components/upstash/upstash.py +124 -0
- lfx/components/utilities/__init__.py +43 -0
- lfx/components/utilities/calculator_core.py +89 -0
- lfx/components/utilities/current_date.py +42 -0
- lfx/components/utilities/id_generator.py +42 -0
- lfx/components/utilities/python_repl_core.py +98 -0
- lfx/components/vectara/__init__.py +37 -0
- lfx/components/vectara/vectara.py +97 -0
- lfx/components/vectara/vectara_rag.py +164 -0
- lfx/components/vectorstores/__init__.py +34 -0
- lfx/components/vectorstores/local_db.py +270 -0
- lfx/components/vertexai/__init__.py +37 -0
- lfx/components/vertexai/vertexai.py +71 -0
- lfx/components/vertexai/vertexai_embeddings.py +67 -0
- lfx/components/vlmrun/__init__.py +34 -0
- lfx/components/vlmrun/vlmrun_transcription.py +224 -0
- lfx/components/weaviate/__init__.py +34 -0
- lfx/components/weaviate/weaviate.py +89 -0
- lfx/components/wikipedia/__init__.py +4 -0
- lfx/components/wikipedia/wikidata.py +86 -0
- lfx/components/wikipedia/wikipedia.py +53 -0
- lfx/components/wolframalpha/__init__.py +3 -0
- lfx/components/wolframalpha/wolfram_alpha_api.py +54 -0
- lfx/components/xai/__init__.py +32 -0
- lfx/components/xai/xai.py +167 -0
- lfx/components/yahoosearch/__init__.py +3 -0
- lfx/components/yahoosearch/yahoo.py +137 -0
- lfx/components/youtube/__init__.py +52 -0
- lfx/components/youtube/channel.py +227 -0
- lfx/components/youtube/comments.py +231 -0
- lfx/components/youtube/playlist.py +33 -0
- lfx/components/youtube/search.py +120 -0
- lfx/components/youtube/trending.py +285 -0
- lfx/components/youtube/video_details.py +263 -0
- lfx/components/youtube/youtube_transcripts.py +206 -0
- lfx/components/zep/__init__.py +3 -0
- lfx/components/zep/zep.py +45 -0
- lfx/constants.py +6 -0
- lfx/custom/__init__.py +7 -0
- lfx/custom/attributes.py +87 -0
- lfx/custom/code_parser/__init__.py +3 -0
- lfx/custom/code_parser/code_parser.py +361 -0
- lfx/custom/custom_component/__init__.py +0 -0
- lfx/custom/custom_component/base_component.py +128 -0
- lfx/custom/custom_component/component.py +1890 -0
- lfx/custom/custom_component/component_with_cache.py +8 -0
- lfx/custom/custom_component/custom_component.py +650 -0
- lfx/custom/dependency_analyzer.py +165 -0
- lfx/custom/directory_reader/__init__.py +3 -0
- lfx/custom/directory_reader/directory_reader.py +359 -0
- lfx/custom/directory_reader/utils.py +171 -0
- lfx/custom/eval.py +12 -0
- lfx/custom/schema.py +32 -0
- lfx/custom/tree_visitor.py +21 -0
- lfx/custom/utils.py +877 -0
- lfx/custom/validate.py +523 -0
- lfx/events/__init__.py +1 -0
- lfx/events/event_manager.py +110 -0
- lfx/exceptions/__init__.py +0 -0
- lfx/exceptions/component.py +15 -0
- lfx/field_typing/__init__.py +91 -0
- lfx/field_typing/constants.py +216 -0
- lfx/field_typing/range_spec.py +35 -0
- lfx/graph/__init__.py +6 -0
- lfx/graph/edge/__init__.py +0 -0
- lfx/graph/edge/base.py +300 -0
- lfx/graph/edge/schema.py +119 -0
- lfx/graph/edge/utils.py +0 -0
- lfx/graph/graph/__init__.py +0 -0
- lfx/graph/graph/ascii.py +202 -0
- lfx/graph/graph/base.py +2298 -0
- lfx/graph/graph/constants.py +63 -0
- lfx/graph/graph/runnable_vertices_manager.py +133 -0
- lfx/graph/graph/schema.py +53 -0
- lfx/graph/graph/state_model.py +66 -0
- lfx/graph/graph/utils.py +1024 -0
- lfx/graph/schema.py +75 -0
- lfx/graph/state/__init__.py +0 -0
- lfx/graph/state/model.py +250 -0
- lfx/graph/utils.py +206 -0
- lfx/graph/vertex/__init__.py +0 -0
- lfx/graph/vertex/base.py +826 -0
- lfx/graph/vertex/constants.py +0 -0
- lfx/graph/vertex/exceptions.py +4 -0
- lfx/graph/vertex/param_handler.py +316 -0
- lfx/graph/vertex/schema.py +26 -0
- lfx/graph/vertex/utils.py +19 -0
- lfx/graph/vertex/vertex_types.py +489 -0
- lfx/helpers/__init__.py +141 -0
- lfx/helpers/base_model.py +71 -0
- lfx/helpers/custom.py +13 -0
- lfx/helpers/data.py +167 -0
- lfx/helpers/flow.py +308 -0
- lfx/inputs/__init__.py +68 -0
- lfx/inputs/constants.py +2 -0
- lfx/inputs/input_mixin.py +352 -0
- lfx/inputs/inputs.py +718 -0
- lfx/inputs/validators.py +19 -0
- lfx/interface/__init__.py +6 -0
- lfx/interface/components.py +897 -0
- lfx/interface/importing/__init__.py +5 -0
- lfx/interface/importing/utils.py +39 -0
- lfx/interface/initialize/__init__.py +3 -0
- lfx/interface/initialize/loading.py +317 -0
- lfx/interface/listing.py +26 -0
- lfx/interface/run.py +16 -0
- lfx/interface/utils.py +111 -0
- lfx/io/__init__.py +63 -0
- lfx/io/schema.py +295 -0
- lfx/load/__init__.py +8 -0
- lfx/load/load.py +256 -0
- lfx/load/utils.py +99 -0
- lfx/log/__init__.py +5 -0
- lfx/log/logger.py +411 -0
- lfx/logging/__init__.py +11 -0
- lfx/logging/logger.py +24 -0
- lfx/memory/__init__.py +70 -0
- lfx/memory/stubs.py +302 -0
- lfx/processing/__init__.py +1 -0
- lfx/processing/process.py +238 -0
- lfx/processing/utils.py +25 -0
- lfx/py.typed +0 -0
- lfx/schema/__init__.py +66 -0
- lfx/schema/artifact.py +83 -0
- lfx/schema/content_block.py +62 -0
- lfx/schema/content_types.py +91 -0
- lfx/schema/cross_module.py +80 -0
- lfx/schema/data.py +309 -0
- lfx/schema/dataframe.py +210 -0
- lfx/schema/dotdict.py +74 -0
- lfx/schema/encoders.py +13 -0
- lfx/schema/graph.py +47 -0
- lfx/schema/image.py +184 -0
- lfx/schema/json_schema.py +186 -0
- lfx/schema/log.py +62 -0
- lfx/schema/message.py +493 -0
- lfx/schema/openai_responses_schemas.py +74 -0
- lfx/schema/properties.py +41 -0
- lfx/schema/schema.py +180 -0
- lfx/schema/serialize.py +13 -0
- lfx/schema/table.py +142 -0
- lfx/schema/validators.py +114 -0
- lfx/serialization/__init__.py +5 -0
- lfx/serialization/constants.py +2 -0
- lfx/serialization/serialization.py +314 -0
- lfx/services/__init__.py +26 -0
- lfx/services/base.py +28 -0
- lfx/services/cache/__init__.py +6 -0
- lfx/services/cache/base.py +183 -0
- lfx/services/cache/service.py +166 -0
- lfx/services/cache/utils.py +169 -0
- lfx/services/chat/__init__.py +1 -0
- lfx/services/chat/config.py +2 -0
- lfx/services/chat/schema.py +10 -0
- lfx/services/database/__init__.py +5 -0
- lfx/services/database/service.py +25 -0
- lfx/services/deps.py +194 -0
- lfx/services/factory.py +19 -0
- lfx/services/initialize.py +19 -0
- lfx/services/interfaces.py +103 -0
- lfx/services/manager.py +185 -0
- lfx/services/mcp_composer/__init__.py +6 -0
- lfx/services/mcp_composer/factory.py +16 -0
- lfx/services/mcp_composer/service.py +1441 -0
- lfx/services/schema.py +21 -0
- lfx/services/session.py +87 -0
- lfx/services/settings/__init__.py +3 -0
- lfx/services/settings/auth.py +133 -0
- lfx/services/settings/base.py +668 -0
- lfx/services/settings/constants.py +43 -0
- lfx/services/settings/factory.py +23 -0
- lfx/services/settings/feature_flags.py +11 -0
- lfx/services/settings/service.py +35 -0
- lfx/services/settings/utils.py +40 -0
- lfx/services/shared_component_cache/__init__.py +1 -0
- lfx/services/shared_component_cache/factory.py +30 -0
- lfx/services/shared_component_cache/service.py +9 -0
- lfx/services/storage/__init__.py +5 -0
- lfx/services/storage/local.py +185 -0
- lfx/services/storage/service.py +177 -0
- lfx/services/tracing/__init__.py +1 -0
- lfx/services/tracing/service.py +21 -0
- lfx/settings.py +6 -0
- lfx/template/__init__.py +6 -0
- lfx/template/field/__init__.py +0 -0
- lfx/template/field/base.py +260 -0
- lfx/template/field/prompt.py +15 -0
- lfx/template/frontend_node/__init__.py +6 -0
- lfx/template/frontend_node/base.py +214 -0
- lfx/template/frontend_node/constants.py +65 -0
- lfx/template/frontend_node/custom_components.py +79 -0
- lfx/template/template/__init__.py +0 -0
- lfx/template/template/base.py +100 -0
- lfx/template/utils.py +217 -0
- lfx/type_extraction/__init__.py +19 -0
- lfx/type_extraction/type_extraction.py +75 -0
- lfx/type_extraction.py +80 -0
- lfx/utils/__init__.py +1 -0
- lfx/utils/async_helpers.py +42 -0
- lfx/utils/component_utils.py +154 -0
- lfx/utils/concurrency.py +60 -0
- lfx/utils/connection_string_parser.py +11 -0
- lfx/utils/constants.py +233 -0
- lfx/utils/data_structure.py +212 -0
- lfx/utils/exceptions.py +22 -0
- lfx/utils/helpers.py +34 -0
- lfx/utils/image.py +79 -0
- lfx/utils/langflow_utils.py +52 -0
- lfx/utils/lazy_load.py +15 -0
- lfx/utils/request_utils.py +18 -0
- lfx/utils/schemas.py +139 -0
- lfx/utils/ssrf_protection.py +384 -0
- lfx/utils/util.py +626 -0
- lfx/utils/util_strings.py +56 -0
- lfx/utils/validate_cloud.py +26 -0
- lfx/utils/version.py +24 -0
- lfx_nightly-0.2.0.dev25.dist-info/METADATA +312 -0
- lfx_nightly-0.2.0.dev25.dist-info/RECORD +769 -0
- lfx_nightly-0.2.0.dev25.dist-info/WHEEL +4 -0
- lfx_nightly-0.2.0.dev25.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import requests
|
|
5
|
+
from langchain.tools import StructuredTool
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
from lfx.base.langchain_utilities.model import LCToolComponent
|
|
9
|
+
from lfx.field_typing import Tool
|
|
10
|
+
from lfx.inputs.inputs import SecretStrInput, StrInput
|
|
11
|
+
from lfx.schema.data import Data
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class HomeAssistantControl(LCToolComponent):
|
|
15
|
+
"""This tool is used to control Home Assistant devices.
|
|
16
|
+
|
|
17
|
+
A very simple tool to control Home Assistant devices.
|
|
18
|
+
- The agent only needs to provide action (turn_on, turn_off, toggle) + entity_id (e.g., switch.xxx, light.xxx).
|
|
19
|
+
- The domain (e.g., 'switch', 'light') is automatically extracted from entity_id.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
display_name: str = "Home Assistant Control"
|
|
23
|
+
description: str = (
|
|
24
|
+
"A very simple tool to control Home Assistant devices. "
|
|
25
|
+
"Only action (turn_on, turn_off, toggle) and entity_id need to be provided."
|
|
26
|
+
)
|
|
27
|
+
documentation: str = "https://developers.home-assistant.io/docs/api/rest/"
|
|
28
|
+
icon: str = "HomeAssistant"
|
|
29
|
+
|
|
30
|
+
# --- Input fields for LangFlow UI (token, URL) ---
|
|
31
|
+
inputs = [
|
|
32
|
+
SecretStrInput(
|
|
33
|
+
name="ha_token",
|
|
34
|
+
display_name="Home Assistant Token",
|
|
35
|
+
info="Home Assistant Long-Lived Access Token",
|
|
36
|
+
required=True,
|
|
37
|
+
),
|
|
38
|
+
StrInput(
|
|
39
|
+
name="base_url",
|
|
40
|
+
display_name="Home Assistant URL",
|
|
41
|
+
info="e.g., http://192.168.0.10:8123",
|
|
42
|
+
required=True,
|
|
43
|
+
),
|
|
44
|
+
StrInput(
|
|
45
|
+
name="default_action",
|
|
46
|
+
display_name="Default Action (Optional)",
|
|
47
|
+
info="One of turn_on, turn_off, toggle",
|
|
48
|
+
required=False,
|
|
49
|
+
),
|
|
50
|
+
StrInput(
|
|
51
|
+
name="default_entity_id",
|
|
52
|
+
display_name="Default Entity ID (Optional)",
|
|
53
|
+
info="Default entity ID to control (e.g., switch.unknown_switch_3)",
|
|
54
|
+
required=False,
|
|
55
|
+
),
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
# --- Parameters exposed to the agent (Pydantic schema) ---
|
|
59
|
+
class ToolSchema(BaseModel):
|
|
60
|
+
"""Parameters to be passed by the agent: action, entity_id only."""
|
|
61
|
+
|
|
62
|
+
action: str = Field(..., description="Home Assistant service name. (One of turn_on, turn_off, toggle)")
|
|
63
|
+
entity_id: str = Field(
|
|
64
|
+
...,
|
|
65
|
+
description="Entity ID to control (e.g., switch.xxx, light.xxx, cover.xxx, etc.)."
|
|
66
|
+
"Do not infer; use the list_homeassistant_states tool to retrieve it.",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def run_model(self) -> Data:
|
|
70
|
+
"""Used when the 'Run' button is clicked in LangFlow.
|
|
71
|
+
|
|
72
|
+
- Uses default_action and default_entity_id entered in the UI.
|
|
73
|
+
"""
|
|
74
|
+
action = self.default_action or "turn_off"
|
|
75
|
+
entity_id = self.default_entity_id or "switch.unknown_switch_3"
|
|
76
|
+
|
|
77
|
+
result = self._control_device(
|
|
78
|
+
ha_token=self.ha_token,
|
|
79
|
+
base_url=self.base_url,
|
|
80
|
+
action=action,
|
|
81
|
+
entity_id=entity_id,
|
|
82
|
+
)
|
|
83
|
+
return self._make_data_response(result)
|
|
84
|
+
|
|
85
|
+
def build_tool(self) -> Tool:
|
|
86
|
+
"""Returns a tool to be used by the agent (LLM).
|
|
87
|
+
|
|
88
|
+
- The agent can only pass action and entity_id as arguments.
|
|
89
|
+
"""
|
|
90
|
+
return StructuredTool.from_function(
|
|
91
|
+
name="home_assistant_control",
|
|
92
|
+
description=(
|
|
93
|
+
"A tool to control Home Assistant devices easily. "
|
|
94
|
+
"Parameters: action ('turn_on'/'turn_off'/'toggle'), entity_id ('switch.xxx', etc.)."
|
|
95
|
+
"Entity ID must be obtained using the list_homeassistant_states tool and not guessed."
|
|
96
|
+
),
|
|
97
|
+
func=self._control_device_for_tool, # Wrapper function below
|
|
98
|
+
args_schema=self.ToolSchema,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
def _control_device_for_tool(self, action: str, entity_id: str) -> dict[str, Any] | str:
|
|
102
|
+
"""Function called by the agent.
|
|
103
|
+
|
|
104
|
+
-> Internally calls _control_device.
|
|
105
|
+
"""
|
|
106
|
+
return self._control_device(
|
|
107
|
+
ha_token=self.ha_token,
|
|
108
|
+
base_url=self.base_url,
|
|
109
|
+
action=action,
|
|
110
|
+
entity_id=entity_id,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
def _control_device(
|
|
114
|
+
self,
|
|
115
|
+
ha_token: str,
|
|
116
|
+
base_url: str,
|
|
117
|
+
action: str,
|
|
118
|
+
entity_id: str,
|
|
119
|
+
) -> dict[str, Any] | str:
|
|
120
|
+
"""Actual logic to call the Home Assistant service.
|
|
121
|
+
|
|
122
|
+
The domain is extracted from the beginning of the entity_id.
|
|
123
|
+
Example: entity_id="switch.unknown_switch_3" -> domain="switch".
|
|
124
|
+
"""
|
|
125
|
+
try:
|
|
126
|
+
domain = entity_id.split(".")[0] # switch, light, cover, etc.
|
|
127
|
+
url = f"{base_url}/api/services/{domain}/{action}"
|
|
128
|
+
|
|
129
|
+
headers = {
|
|
130
|
+
"Authorization": f"Bearer {ha_token}",
|
|
131
|
+
"Content-Type": "application/json",
|
|
132
|
+
}
|
|
133
|
+
payload = {"entity_id": entity_id}
|
|
134
|
+
|
|
135
|
+
response = requests.post(url, headers=headers, json=payload, timeout=10)
|
|
136
|
+
response.raise_for_status()
|
|
137
|
+
|
|
138
|
+
return response.json() # HA response JSON on success
|
|
139
|
+
except requests.exceptions.RequestException as e:
|
|
140
|
+
return f"Error: Failed to call service. {e}"
|
|
141
|
+
except Exception as e: # noqa: BLE001
|
|
142
|
+
return f"An unexpected error occurred: {e}"
|
|
143
|
+
|
|
144
|
+
def _make_data_response(self, result: dict[str, Any] | str) -> Data:
|
|
145
|
+
"""Returns a response in the LangFlow Data format."""
|
|
146
|
+
if isinstance(result, str):
|
|
147
|
+
# Handle error messages
|
|
148
|
+
return Data(text=result)
|
|
149
|
+
|
|
150
|
+
# Convert dict to JSON string
|
|
151
|
+
formatted_json = json.dumps(result, indent=2, ensure_ascii=False)
|
|
152
|
+
return Data(data=result, text=formatted_json)
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import requests
|
|
5
|
+
from langchain.tools import StructuredTool
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
from lfx.base.langchain_utilities.model import LCToolComponent
|
|
9
|
+
from lfx.field_typing import Tool
|
|
10
|
+
from lfx.inputs.inputs import SecretStrInput, StrInput
|
|
11
|
+
from lfx.schema.data import Data
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ListHomeAssistantStates(LCToolComponent):
|
|
15
|
+
display_name: str = "List Home Assistant States"
|
|
16
|
+
description: str = (
|
|
17
|
+
"Retrieve states from Home Assistant. "
|
|
18
|
+
"The agent only needs to specify 'filter_domain' (optional). "
|
|
19
|
+
"Token and base_url are not exposed to the agent."
|
|
20
|
+
)
|
|
21
|
+
documentation: str = "https://developers.home-assistant.io/docs/api/rest/"
|
|
22
|
+
icon = "HomeAssistant"
|
|
23
|
+
|
|
24
|
+
# 1) Define fields to be received in LangFlow UI
|
|
25
|
+
inputs = [
|
|
26
|
+
SecretStrInput(
|
|
27
|
+
name="ha_token",
|
|
28
|
+
display_name="Home Assistant Token",
|
|
29
|
+
info="Home Assistant Long-Lived Access Token",
|
|
30
|
+
required=True,
|
|
31
|
+
),
|
|
32
|
+
StrInput(
|
|
33
|
+
name="base_url",
|
|
34
|
+
display_name="Home Assistant URL",
|
|
35
|
+
info="e.g., http://192.168.0.10:8123",
|
|
36
|
+
required=True,
|
|
37
|
+
),
|
|
38
|
+
StrInput(
|
|
39
|
+
name="filter_domain",
|
|
40
|
+
display_name="Default Filter Domain (Optional)",
|
|
41
|
+
info="light, switch, sensor, etc. (Leave empty to fetch all)",
|
|
42
|
+
required=False,
|
|
43
|
+
),
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
# 2) Pydantic schema containing only parameters exposed to the agent
|
|
47
|
+
class ToolSchema(BaseModel):
|
|
48
|
+
"""Parameters to be passed by the agent: filter_domain only."""
|
|
49
|
+
|
|
50
|
+
filter_domain: str = Field("", description="Filter domain (e.g., 'light'). If empty, returns all.")
|
|
51
|
+
|
|
52
|
+
def run_model(self) -> Data:
|
|
53
|
+
"""Execute the LangFlow component.
|
|
54
|
+
|
|
55
|
+
Uses self.ha_token, self.base_url, self.filter_domain as entered in the UI.
|
|
56
|
+
Triggered when 'Run' is clicked directly without an agent.
|
|
57
|
+
"""
|
|
58
|
+
filter_domain = self.filter_domain or "" # Use "" for fetching all states
|
|
59
|
+
result = self._list_states(
|
|
60
|
+
ha_token=self.ha_token,
|
|
61
|
+
base_url=self.base_url,
|
|
62
|
+
filter_domain=filter_domain,
|
|
63
|
+
)
|
|
64
|
+
return self._make_data_response(result)
|
|
65
|
+
|
|
66
|
+
def build_tool(self) -> Tool:
|
|
67
|
+
"""Build a tool object to be used by the agent.
|
|
68
|
+
|
|
69
|
+
The agent can only pass 'filter_domain' as a parameter.
|
|
70
|
+
'ha_token' and 'base_url' are not exposed (stored as self attributes).
|
|
71
|
+
"""
|
|
72
|
+
return StructuredTool.from_function(
|
|
73
|
+
name="list_homeassistant_states",
|
|
74
|
+
description=(
|
|
75
|
+
"Retrieve states from Home Assistant. "
|
|
76
|
+
"You can provide filter_domain='light', 'switch', etc. to narrow results."
|
|
77
|
+
),
|
|
78
|
+
func=self._list_states_for_tool, # Wrapper function below
|
|
79
|
+
args_schema=self.ToolSchema, # Requires only filter_domain
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def _list_states_for_tool(self, filter_domain: str = "") -> list[Any] | str:
|
|
83
|
+
"""Execute the tool when called by the agent.
|
|
84
|
+
|
|
85
|
+
'ha_token' and 'base_url' are stored in self (not exposed).
|
|
86
|
+
"""
|
|
87
|
+
return self._list_states(
|
|
88
|
+
ha_token=self.ha_token,
|
|
89
|
+
base_url=self.base_url,
|
|
90
|
+
filter_domain=filter_domain,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def _list_states(
|
|
94
|
+
self,
|
|
95
|
+
ha_token: str,
|
|
96
|
+
base_url: str,
|
|
97
|
+
filter_domain: str = "",
|
|
98
|
+
) -> list[Any] | str:
|
|
99
|
+
"""Call the Home Assistant /api/states endpoint."""
|
|
100
|
+
try:
|
|
101
|
+
headers = {
|
|
102
|
+
"Authorization": f"Bearer {ha_token}",
|
|
103
|
+
"Content-Type": "application/json",
|
|
104
|
+
}
|
|
105
|
+
url = f"{base_url}/api/states"
|
|
106
|
+
response = requests.get(url, headers=headers, timeout=10)
|
|
107
|
+
response.raise_for_status()
|
|
108
|
+
|
|
109
|
+
all_states = response.json()
|
|
110
|
+
if filter_domain:
|
|
111
|
+
return [st for st in all_states if st.get("entity_id", "").startswith(f"{filter_domain}.")]
|
|
112
|
+
|
|
113
|
+
except requests.exceptions.RequestException as e:
|
|
114
|
+
return f"Error: Failed to fetch states. {e}"
|
|
115
|
+
except (ValueError, TypeError) as e:
|
|
116
|
+
return f"Error processing response: {e}"
|
|
117
|
+
return all_states
|
|
118
|
+
|
|
119
|
+
def _make_data_response(self, result: list[Any] | str | dict) -> Data:
|
|
120
|
+
"""Format the response into a Data object."""
|
|
121
|
+
try:
|
|
122
|
+
if isinstance(result, list):
|
|
123
|
+
# Wrap list data into a dictionary and convert to text
|
|
124
|
+
wrapped_result = {"result": result}
|
|
125
|
+
return Data(data=wrapped_result, text=json.dumps(wrapped_result, indent=2, ensure_ascii=False))
|
|
126
|
+
if isinstance(result, dict):
|
|
127
|
+
# Return dictionary as-is
|
|
128
|
+
return Data(data=result, text=json.dumps(result, indent=2, ensure_ascii=False))
|
|
129
|
+
if isinstance(result, str):
|
|
130
|
+
# Return error messages or strings
|
|
131
|
+
return Data(data={}, text=result)
|
|
132
|
+
|
|
133
|
+
# Handle unexpected data types
|
|
134
|
+
return Data(data={}, text="Error: Unexpected response format.")
|
|
135
|
+
except (TypeError, ValueError) as e:
|
|
136
|
+
# Handle specific exceptions during formatting
|
|
137
|
+
return Data(data={}, text=f"Error: Failed to process response. Details: {e!s}")
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from lfx.components._importing import import_mod
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from .huggingface import HuggingFaceEndpointsComponent
|
|
9
|
+
from .huggingface_inference_api import HuggingFaceInferenceAPIEmbeddingsComponent
|
|
10
|
+
|
|
11
|
+
_dynamic_imports = {
|
|
12
|
+
"HuggingFaceEndpointsComponent": "huggingface",
|
|
13
|
+
"HuggingFaceInferenceAPIEmbeddingsComponent": "huggingface_inference_api",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"HuggingFaceEndpointsComponent",
|
|
18
|
+
"HuggingFaceInferenceAPIEmbeddingsComponent",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def __getattr__(attr_name: str) -> Any:
|
|
23
|
+
"""Lazily import huggingface components on attribute access."""
|
|
24
|
+
if attr_name not in _dynamic_imports:
|
|
25
|
+
msg = f"module '{__name__}' has no attribute '{attr_name}'"
|
|
26
|
+
raise AttributeError(msg)
|
|
27
|
+
try:
|
|
28
|
+
result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
|
|
29
|
+
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
|
30
|
+
msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
|
|
31
|
+
raise AttributeError(msg) from e
|
|
32
|
+
globals()[attr_name] = result
|
|
33
|
+
return result
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def __dir__() -> list[str]:
|
|
37
|
+
return list(__all__)
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from langchain_community.llms.huggingface_endpoint import HuggingFaceEndpoint
|
|
4
|
+
from tenacity import retry, stop_after_attempt, wait_fixed
|
|
5
|
+
|
|
6
|
+
from lfx.base.models.model import LCModelComponent
|
|
7
|
+
from lfx.field_typing import LanguageModel
|
|
8
|
+
from lfx.field_typing.range_spec import RangeSpec
|
|
9
|
+
from lfx.io import DictInput, DropdownInput, FloatInput, IntInput, SecretStrInput, SliderInput, StrInput
|
|
10
|
+
|
|
11
|
+
# TODO: langchain_community.llms.huggingface_endpoint is depreciated.
|
|
12
|
+
# Need to update to langchain_huggingface, but have dependency with langchain_core 0.3.0
|
|
13
|
+
|
|
14
|
+
# Constants
|
|
15
|
+
DEFAULT_MODEL = "meta-llama/Llama-3.3-70B-Instruct"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class HuggingFaceEndpointsComponent(LCModelComponent):
|
|
19
|
+
display_name: str = "Hugging Face"
|
|
20
|
+
description: str = "Generate text using Hugging Face Inference APIs."
|
|
21
|
+
icon = "HuggingFace"
|
|
22
|
+
name = "HuggingFaceModel"
|
|
23
|
+
|
|
24
|
+
inputs = [
|
|
25
|
+
*LCModelComponent.get_base_inputs(),
|
|
26
|
+
DropdownInput(
|
|
27
|
+
name="model_id",
|
|
28
|
+
display_name="Model ID",
|
|
29
|
+
info="Select a model from Hugging Face Hub",
|
|
30
|
+
options=[
|
|
31
|
+
DEFAULT_MODEL,
|
|
32
|
+
"mistralai/Mixtral-8x7B-Instruct-v0.1",
|
|
33
|
+
"mistralai/Mistral-7B-Instruct-v0.3",
|
|
34
|
+
"meta-llama/Llama-3.1-8B-Instruct",
|
|
35
|
+
"Qwen/Qwen2.5-Coder-32B-Instruct",
|
|
36
|
+
"Qwen/QwQ-32B-Preview",
|
|
37
|
+
"openai-community/gpt2",
|
|
38
|
+
"custom",
|
|
39
|
+
],
|
|
40
|
+
value=DEFAULT_MODEL,
|
|
41
|
+
required=True,
|
|
42
|
+
real_time_refresh=True,
|
|
43
|
+
),
|
|
44
|
+
StrInput(
|
|
45
|
+
name="custom_model",
|
|
46
|
+
display_name="Custom Model ID",
|
|
47
|
+
info="Enter a custom model ID from Hugging Face Hub",
|
|
48
|
+
value="",
|
|
49
|
+
show=False,
|
|
50
|
+
required=True,
|
|
51
|
+
),
|
|
52
|
+
IntInput(
|
|
53
|
+
name="max_new_tokens", display_name="Max New Tokens", value=512, info="Maximum number of generated tokens"
|
|
54
|
+
),
|
|
55
|
+
IntInput(
|
|
56
|
+
name="top_k",
|
|
57
|
+
display_name="Top K",
|
|
58
|
+
advanced=True,
|
|
59
|
+
info="The number of highest probability vocabulary tokens to keep for top-k-filtering",
|
|
60
|
+
),
|
|
61
|
+
FloatInput(
|
|
62
|
+
name="top_p",
|
|
63
|
+
display_name="Top P",
|
|
64
|
+
value=0.95,
|
|
65
|
+
advanced=True,
|
|
66
|
+
info=(
|
|
67
|
+
"If set to < 1, only the smallest set of most probable tokens with "
|
|
68
|
+
"probabilities that add up to `top_p` or higher are kept for generation"
|
|
69
|
+
),
|
|
70
|
+
),
|
|
71
|
+
FloatInput(
|
|
72
|
+
name="typical_p",
|
|
73
|
+
display_name="Typical P",
|
|
74
|
+
value=0.95,
|
|
75
|
+
advanced=True,
|
|
76
|
+
info="Typical Decoding mass.",
|
|
77
|
+
),
|
|
78
|
+
SliderInput(
|
|
79
|
+
name="temperature",
|
|
80
|
+
display_name="Temperature",
|
|
81
|
+
value=0.8,
|
|
82
|
+
range_spec=RangeSpec(min=0, max=2, step=0.01),
|
|
83
|
+
info="The value used to module the logits distribution",
|
|
84
|
+
advanced=True,
|
|
85
|
+
),
|
|
86
|
+
FloatInput(
|
|
87
|
+
name="repetition_penalty",
|
|
88
|
+
display_name="Repetition Penalty",
|
|
89
|
+
info="The parameter for repetition penalty. 1.0 means no penalty.",
|
|
90
|
+
advanced=True,
|
|
91
|
+
),
|
|
92
|
+
StrInput(
|
|
93
|
+
name="inference_endpoint",
|
|
94
|
+
display_name="Inference Endpoint",
|
|
95
|
+
value="https://api-inference.huggingface.co/models/",
|
|
96
|
+
info="Custom inference endpoint URL.",
|
|
97
|
+
required=True,
|
|
98
|
+
),
|
|
99
|
+
DropdownInput(
|
|
100
|
+
name="task",
|
|
101
|
+
display_name="Task",
|
|
102
|
+
options=["text2text-generation", "text-generation", "summarization", "translation"],
|
|
103
|
+
value="text-generation",
|
|
104
|
+
advanced=True,
|
|
105
|
+
info="The task to call the model with. Should be a task that returns `generated_text` or `summary_text`.",
|
|
106
|
+
),
|
|
107
|
+
SecretStrInput(
|
|
108
|
+
name="huggingfacehub_api_token", display_name="HuggingFace HubAPI Token", password=True, required=True
|
|
109
|
+
),
|
|
110
|
+
DictInput(name="model_kwargs", display_name="Model Keyword Arguments", advanced=True),
|
|
111
|
+
IntInput(name="retry_attempts", display_name="Retry Attempts", value=1, advanced=True),
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
def get_api_url(self) -> str:
|
|
115
|
+
if "huggingface" in self.inference_endpoint.lower():
|
|
116
|
+
if self.model_id == "custom":
|
|
117
|
+
if not self.custom_model:
|
|
118
|
+
error_msg = "Custom model ID is required when 'custom' is selected"
|
|
119
|
+
raise ValueError(error_msg)
|
|
120
|
+
return f"{self.inference_endpoint}{self.custom_model}"
|
|
121
|
+
return f"{self.inference_endpoint}{self.model_id}"
|
|
122
|
+
return self.inference_endpoint
|
|
123
|
+
|
|
124
|
+
async def update_build_config(self, build_config: dict, field_value: Any, field_name: str | None = None) -> dict:
|
|
125
|
+
"""Update build configuration based on field updates."""
|
|
126
|
+
try:
|
|
127
|
+
if field_name is None or field_name == "model_id":
|
|
128
|
+
# If model_id is custom, show custom model field
|
|
129
|
+
if field_value == "custom":
|
|
130
|
+
build_config["custom_model"]["show"] = True
|
|
131
|
+
build_config["custom_model"]["required"] = True
|
|
132
|
+
else:
|
|
133
|
+
build_config["custom_model"]["show"] = False
|
|
134
|
+
build_config["custom_model"]["value"] = ""
|
|
135
|
+
|
|
136
|
+
except (KeyError, AttributeError) as e:
|
|
137
|
+
self.log(f"Error updating build config: {e!s}")
|
|
138
|
+
return build_config
|
|
139
|
+
|
|
140
|
+
def create_huggingface_endpoint(
|
|
141
|
+
self,
|
|
142
|
+
task: str | None,
|
|
143
|
+
huggingfacehub_api_token: str | None,
|
|
144
|
+
model_kwargs: dict[str, Any],
|
|
145
|
+
max_new_tokens: int,
|
|
146
|
+
top_k: int | None,
|
|
147
|
+
top_p: float,
|
|
148
|
+
typical_p: float | None,
|
|
149
|
+
temperature: float | None,
|
|
150
|
+
repetition_penalty: float | None,
|
|
151
|
+
) -> HuggingFaceEndpoint:
|
|
152
|
+
retry_attempts = self.retry_attempts
|
|
153
|
+
endpoint_url = self.get_api_url()
|
|
154
|
+
|
|
155
|
+
@retry(stop=stop_after_attempt(retry_attempts), wait=wait_fixed(2))
|
|
156
|
+
def _attempt_create():
|
|
157
|
+
return HuggingFaceEndpoint(
|
|
158
|
+
endpoint_url=endpoint_url,
|
|
159
|
+
task=task,
|
|
160
|
+
huggingfacehub_api_token=huggingfacehub_api_token,
|
|
161
|
+
model_kwargs=model_kwargs,
|
|
162
|
+
max_new_tokens=max_new_tokens,
|
|
163
|
+
top_k=top_k,
|
|
164
|
+
top_p=top_p,
|
|
165
|
+
typical_p=typical_p,
|
|
166
|
+
temperature=temperature,
|
|
167
|
+
repetition_penalty=repetition_penalty,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
return _attempt_create()
|
|
171
|
+
|
|
172
|
+
def build_model(self) -> LanguageModel:
|
|
173
|
+
task = self.task or None
|
|
174
|
+
huggingfacehub_api_token = self.huggingfacehub_api_token
|
|
175
|
+
model_kwargs = self.model_kwargs or {}
|
|
176
|
+
max_new_tokens = self.max_new_tokens
|
|
177
|
+
top_k = self.top_k or None
|
|
178
|
+
top_p = self.top_p
|
|
179
|
+
typical_p = self.typical_p or None
|
|
180
|
+
temperature = self.temperature or 0.8
|
|
181
|
+
repetition_penalty = self.repetition_penalty or None
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
llm = self.create_huggingface_endpoint(
|
|
185
|
+
task=task,
|
|
186
|
+
huggingfacehub_api_token=huggingfacehub_api_token,
|
|
187
|
+
model_kwargs=model_kwargs,
|
|
188
|
+
max_new_tokens=max_new_tokens,
|
|
189
|
+
top_k=top_k,
|
|
190
|
+
top_p=top_p,
|
|
191
|
+
typical_p=typical_p,
|
|
192
|
+
temperature=temperature,
|
|
193
|
+
repetition_penalty=repetition_penalty,
|
|
194
|
+
)
|
|
195
|
+
except Exception as e:
|
|
196
|
+
msg = "Could not connect to Hugging Face Endpoints API."
|
|
197
|
+
raise ValueError(msg) from e
|
|
198
|
+
|
|
199
|
+
return llm
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from urllib.parse import urlparse
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
from langchain_community.embeddings.huggingface import HuggingFaceInferenceAPIEmbeddings
|
|
5
|
+
|
|
6
|
+
# Next update: use langchain_huggingface
|
|
7
|
+
from pydantic import SecretStr
|
|
8
|
+
from tenacity import retry, stop_after_attempt, wait_fixed
|
|
9
|
+
|
|
10
|
+
from lfx.base.embeddings.model import LCEmbeddingsModel
|
|
11
|
+
from lfx.field_typing import Embeddings
|
|
12
|
+
from lfx.io import MessageTextInput, Output, SecretStrInput
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class HuggingFaceInferenceAPIEmbeddingsComponent(LCEmbeddingsModel):
|
|
16
|
+
display_name = "Hugging Face Embeddings Inference"
|
|
17
|
+
description = "Generate embeddings using Hugging Face Text Embeddings Inference (TEI)"
|
|
18
|
+
documentation = "https://huggingface.co/docs/text-embeddings-inference/index"
|
|
19
|
+
icon = "HuggingFace"
|
|
20
|
+
name = "HuggingFaceInferenceAPIEmbeddings"
|
|
21
|
+
|
|
22
|
+
inputs = [
|
|
23
|
+
SecretStrInput(
|
|
24
|
+
name="api_key",
|
|
25
|
+
display_name="HuggingFace API Key",
|
|
26
|
+
advanced=False,
|
|
27
|
+
info="Required for non-local inference endpoints. Local inference does not require an API Key.",
|
|
28
|
+
),
|
|
29
|
+
MessageTextInput(
|
|
30
|
+
name="inference_endpoint",
|
|
31
|
+
display_name="Inference Endpoint",
|
|
32
|
+
required=True,
|
|
33
|
+
value="https://api-inference.huggingface.co/models/",
|
|
34
|
+
info="Custom inference endpoint URL.",
|
|
35
|
+
),
|
|
36
|
+
MessageTextInput(
|
|
37
|
+
name="model_name",
|
|
38
|
+
display_name="Model Name",
|
|
39
|
+
value="BAAI/bge-large-en-v1.5",
|
|
40
|
+
info="The name of the model to use for text embeddings.",
|
|
41
|
+
required=True,
|
|
42
|
+
),
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
outputs = [
|
|
46
|
+
Output(display_name="Embeddings", name="embeddings", method="build_embeddings"),
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
def validate_inference_endpoint(self, inference_endpoint: str) -> bool:
|
|
50
|
+
parsed_url = urlparse(inference_endpoint)
|
|
51
|
+
if not all([parsed_url.scheme, parsed_url.netloc]):
|
|
52
|
+
msg = (
|
|
53
|
+
f"Invalid inference endpoint format: '{self.inference_endpoint}'. "
|
|
54
|
+
"Please ensure the URL includes both a scheme (e.g., 'http://' or 'https://') and a domain name. "
|
|
55
|
+
"Example: 'http://localhost:8080' or 'https://api.example.com'"
|
|
56
|
+
)
|
|
57
|
+
raise ValueError(msg)
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
response = requests.get(f"{inference_endpoint}/health", timeout=5)
|
|
61
|
+
except requests.RequestException as e:
|
|
62
|
+
msg = (
|
|
63
|
+
f"Inference endpoint '{inference_endpoint}' is not responding. "
|
|
64
|
+
"Please ensure the URL is correct and the service is running."
|
|
65
|
+
)
|
|
66
|
+
raise ValueError(msg) from e
|
|
67
|
+
|
|
68
|
+
if response.status_code != requests.codes.ok:
|
|
69
|
+
msg = f"Hugging Face health check failed: {response.status_code}"
|
|
70
|
+
raise ValueError(msg)
|
|
71
|
+
# returning True to solve linting error
|
|
72
|
+
return True
|
|
73
|
+
|
|
74
|
+
def get_api_url(self) -> str:
|
|
75
|
+
if "huggingface" in self.inference_endpoint.lower():
|
|
76
|
+
return f"{self.inference_endpoint}"
|
|
77
|
+
return self.inference_endpoint
|
|
78
|
+
|
|
79
|
+
@retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
|
|
80
|
+
def create_huggingface_embeddings(
|
|
81
|
+
self, api_key: SecretStr, api_url: str, model_name: str
|
|
82
|
+
) -> HuggingFaceInferenceAPIEmbeddings:
|
|
83
|
+
return HuggingFaceInferenceAPIEmbeddings(api_key=api_key, api_url=api_url, model_name=model_name)
|
|
84
|
+
|
|
85
|
+
def build_embeddings(self) -> Embeddings:
|
|
86
|
+
api_url = self.get_api_url()
|
|
87
|
+
|
|
88
|
+
is_local_url = (
|
|
89
|
+
api_url.startswith(("http://localhost", "http://127.0.0.1", "http://0.0.0.0", "http://docker"))
|
|
90
|
+
or "huggingface.co" not in api_url.lower()
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if not self.api_key and is_local_url:
|
|
94
|
+
self.validate_inference_endpoint(api_url)
|
|
95
|
+
api_key = SecretStr("APIKeyForLocalDeployment")
|
|
96
|
+
elif not self.api_key:
|
|
97
|
+
msg = "API Key is required for non-local inference endpoints"
|
|
98
|
+
raise ValueError(msg)
|
|
99
|
+
else:
|
|
100
|
+
api_key = SecretStr(self.api_key).get_secret_value()
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
return self.create_huggingface_embeddings(api_key, api_url, self.model_name)
|
|
104
|
+
except Exception as e:
|
|
105
|
+
msg = "Could not connect to Hugging Face Inference API."
|
|
106
|
+
raise ValueError(msg) from e
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from lfx.components._importing import import_mod
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from lfx.components.ibm.watsonx import WatsonxAIComponent
|
|
9
|
+
from lfx.components.ibm.watsonx_embeddings import WatsonxEmbeddingsComponent
|
|
10
|
+
|
|
11
|
+
_dynamic_imports = {
|
|
12
|
+
"WatsonxAIComponent": "watsonx",
|
|
13
|
+
"WatsonxEmbeddingsComponent": "watsonx_embeddings",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
__all__ = ["WatsonxAIComponent", "WatsonxEmbeddingsComponent"]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def __getattr__(attr_name: str) -> Any:
|
|
20
|
+
"""Lazily import ibm components on attribute access."""
|
|
21
|
+
if attr_name not in _dynamic_imports:
|
|
22
|
+
msg = f"module '{__name__}' has no attribute '{attr_name}'"
|
|
23
|
+
raise AttributeError(msg)
|
|
24
|
+
try:
|
|
25
|
+
result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
|
|
26
|
+
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
|
27
|
+
msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
|
|
28
|
+
raise AttributeError(msg) from e
|
|
29
|
+
globals()[attr_name] = result
|
|
30
|
+
return result
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def __dir__() -> list[str]:
|
|
34
|
+
return list(__all__)
|