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,268 @@
|
|
|
1
|
+
from typing import Any, cast
|
|
2
|
+
|
|
3
|
+
from lfx.custom.custom_component.component import Component
|
|
4
|
+
from lfx.helpers.data import data_to_text
|
|
5
|
+
from lfx.inputs.inputs import DropdownInput, HandleInput, IntInput, MessageTextInput, MultilineInput, TabInput
|
|
6
|
+
from lfx.memory import aget_messages, astore_message
|
|
7
|
+
from lfx.schema.data import Data
|
|
8
|
+
from lfx.schema.dataframe import DataFrame
|
|
9
|
+
from lfx.schema.dotdict import dotdict
|
|
10
|
+
from lfx.schema.message import Message
|
|
11
|
+
from lfx.template.field.base import Output
|
|
12
|
+
from lfx.utils.component_utils import set_current_fields, set_field_display
|
|
13
|
+
from lfx.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_NAME_AI, MESSAGE_SENDER_USER
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MemoryComponent(Component):
|
|
17
|
+
display_name = "Message History"
|
|
18
|
+
description = "Stores or retrieves stored chat messages from Langflow tables or an external memory."
|
|
19
|
+
documentation: str = "https://docs.langflow.org/message-history"
|
|
20
|
+
icon = "message-square-more"
|
|
21
|
+
name = "Memory"
|
|
22
|
+
default_keys = ["mode", "memory", "session_id", "context_id"]
|
|
23
|
+
mode_config = {
|
|
24
|
+
"Store": ["message", "memory", "sender", "sender_name", "session_id", "context_id"],
|
|
25
|
+
"Retrieve": ["n_messages", "order", "template", "memory", "session_id", "context_id"],
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
inputs = [
|
|
29
|
+
TabInput(
|
|
30
|
+
name="mode",
|
|
31
|
+
display_name="Mode",
|
|
32
|
+
options=["Retrieve", "Store"],
|
|
33
|
+
value="Retrieve",
|
|
34
|
+
info="Operation mode: Store messages or Retrieve messages.",
|
|
35
|
+
real_time_refresh=True,
|
|
36
|
+
),
|
|
37
|
+
MessageTextInput(
|
|
38
|
+
name="message",
|
|
39
|
+
display_name="Message",
|
|
40
|
+
info="The chat message to be stored.",
|
|
41
|
+
tool_mode=True,
|
|
42
|
+
dynamic=True,
|
|
43
|
+
show=False,
|
|
44
|
+
),
|
|
45
|
+
HandleInput(
|
|
46
|
+
name="memory",
|
|
47
|
+
display_name="External Memory",
|
|
48
|
+
input_types=["Memory"],
|
|
49
|
+
info="Retrieve messages from an external memory. If empty, it will use the Langflow tables.",
|
|
50
|
+
advanced=True,
|
|
51
|
+
),
|
|
52
|
+
DropdownInput(
|
|
53
|
+
name="sender_type",
|
|
54
|
+
display_name="Sender Type",
|
|
55
|
+
options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER, "Machine and User"],
|
|
56
|
+
value="Machine and User",
|
|
57
|
+
info="Filter by sender type.",
|
|
58
|
+
advanced=True,
|
|
59
|
+
),
|
|
60
|
+
MessageTextInput(
|
|
61
|
+
name="sender",
|
|
62
|
+
display_name="Sender",
|
|
63
|
+
info="The sender of the message. Might be Machine or User. "
|
|
64
|
+
"If empty, the current sender parameter will be used.",
|
|
65
|
+
advanced=True,
|
|
66
|
+
),
|
|
67
|
+
MessageTextInput(
|
|
68
|
+
name="sender_name",
|
|
69
|
+
display_name="Sender Name",
|
|
70
|
+
info="Filter by sender name.",
|
|
71
|
+
advanced=True,
|
|
72
|
+
show=False,
|
|
73
|
+
),
|
|
74
|
+
IntInput(
|
|
75
|
+
name="n_messages",
|
|
76
|
+
display_name="Number of Messages",
|
|
77
|
+
value=100,
|
|
78
|
+
info="Number of messages to retrieve.",
|
|
79
|
+
advanced=True,
|
|
80
|
+
show=True,
|
|
81
|
+
),
|
|
82
|
+
MessageTextInput(
|
|
83
|
+
name="session_id",
|
|
84
|
+
display_name="Session ID",
|
|
85
|
+
info="The session ID of the chat. If empty, the current session ID parameter will be used.",
|
|
86
|
+
value="",
|
|
87
|
+
advanced=True,
|
|
88
|
+
),
|
|
89
|
+
MessageTextInput(
|
|
90
|
+
name="context_id",
|
|
91
|
+
display_name="Context ID",
|
|
92
|
+
info="The context ID of the chat. Adds an extra layer to the local memory.",
|
|
93
|
+
value="",
|
|
94
|
+
advanced=True,
|
|
95
|
+
),
|
|
96
|
+
DropdownInput(
|
|
97
|
+
name="order",
|
|
98
|
+
display_name="Order",
|
|
99
|
+
options=["Ascending", "Descending"],
|
|
100
|
+
value="Ascending",
|
|
101
|
+
info="Order of the messages.",
|
|
102
|
+
advanced=True,
|
|
103
|
+
tool_mode=True,
|
|
104
|
+
required=True,
|
|
105
|
+
),
|
|
106
|
+
MultilineInput(
|
|
107
|
+
name="template",
|
|
108
|
+
display_name="Template",
|
|
109
|
+
info="The template to use for formatting the data. "
|
|
110
|
+
"It can contain the keys {text}, {sender} or any other key in the message data.",
|
|
111
|
+
value="{sender_name}: {text}",
|
|
112
|
+
advanced=True,
|
|
113
|
+
show=False,
|
|
114
|
+
),
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
outputs = [
|
|
118
|
+
Output(display_name="Message", name="messages_text", method="retrieve_messages_as_text", dynamic=True),
|
|
119
|
+
Output(display_name="Dataframe", name="dataframe", method="retrieve_messages_dataframe", dynamic=True),
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
def update_outputs(self, frontend_node: dict, field_name: str, field_value: Any) -> dict:
|
|
123
|
+
"""Dynamically show only the relevant output based on the selected output type."""
|
|
124
|
+
if field_name == "mode":
|
|
125
|
+
# Start with empty outputs
|
|
126
|
+
frontend_node["outputs"] = []
|
|
127
|
+
if field_value == "Store":
|
|
128
|
+
frontend_node["outputs"] = [
|
|
129
|
+
Output(
|
|
130
|
+
display_name="Stored Messages",
|
|
131
|
+
name="stored_messages",
|
|
132
|
+
method="store_message",
|
|
133
|
+
hidden=True,
|
|
134
|
+
dynamic=True,
|
|
135
|
+
)
|
|
136
|
+
]
|
|
137
|
+
if field_value == "Retrieve":
|
|
138
|
+
frontend_node["outputs"] = [
|
|
139
|
+
Output(
|
|
140
|
+
display_name="Messages", name="messages_text", method="retrieve_messages_as_text", dynamic=True
|
|
141
|
+
),
|
|
142
|
+
Output(
|
|
143
|
+
display_name="Dataframe", name="dataframe", method="retrieve_messages_dataframe", dynamic=True
|
|
144
|
+
),
|
|
145
|
+
]
|
|
146
|
+
return frontend_node
|
|
147
|
+
|
|
148
|
+
async def store_message(self) -> Message:
|
|
149
|
+
message = Message(text=self.message) if isinstance(self.message, str) else self.message
|
|
150
|
+
|
|
151
|
+
message.context_id = self.context_id or message.context_id
|
|
152
|
+
message.session_id = self.session_id or message.session_id
|
|
153
|
+
message.sender = self.sender or message.sender or MESSAGE_SENDER_AI
|
|
154
|
+
message.sender_name = self.sender_name or message.sender_name or MESSAGE_SENDER_NAME_AI
|
|
155
|
+
|
|
156
|
+
stored_messages: list[Message] = []
|
|
157
|
+
|
|
158
|
+
if self.memory:
|
|
159
|
+
self.memory.context_id = message.context_id
|
|
160
|
+
self.memory.session_id = message.session_id
|
|
161
|
+
lc_message = message.to_lc_message()
|
|
162
|
+
await self.memory.aadd_messages([lc_message])
|
|
163
|
+
|
|
164
|
+
stored_messages = await self.memory.aget_messages() or []
|
|
165
|
+
|
|
166
|
+
stored_messages = [Message.from_lc_message(m) for m in stored_messages] if stored_messages else []
|
|
167
|
+
|
|
168
|
+
if message.sender:
|
|
169
|
+
stored_messages = [m for m in stored_messages if m.sender == message.sender]
|
|
170
|
+
else:
|
|
171
|
+
await astore_message(message, flow_id=self.graph.flow_id)
|
|
172
|
+
stored_messages = (
|
|
173
|
+
await aget_messages(
|
|
174
|
+
session_id=message.session_id,
|
|
175
|
+
context_id=message.context_id,
|
|
176
|
+
sender_name=message.sender_name,
|
|
177
|
+
sender=message.sender,
|
|
178
|
+
)
|
|
179
|
+
or []
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
if not stored_messages:
|
|
183
|
+
msg = "No messages were stored. Please ensure that the session ID and sender are properly set."
|
|
184
|
+
raise ValueError(msg)
|
|
185
|
+
|
|
186
|
+
stored_message = stored_messages[0]
|
|
187
|
+
self.status = stored_message
|
|
188
|
+
return stored_message
|
|
189
|
+
|
|
190
|
+
async def retrieve_messages(self) -> Data:
|
|
191
|
+
sender_type = self.sender_type
|
|
192
|
+
sender_name = self.sender_name
|
|
193
|
+
session_id = self.session_id
|
|
194
|
+
context_id = self.context_id
|
|
195
|
+
n_messages = self.n_messages
|
|
196
|
+
order = "DESC" if self.order == "Descending" else "ASC"
|
|
197
|
+
|
|
198
|
+
if sender_type == "Machine and User":
|
|
199
|
+
sender_type = None
|
|
200
|
+
|
|
201
|
+
if self.memory and not hasattr(self.memory, "aget_messages"):
|
|
202
|
+
memory_name = type(self.memory).__name__
|
|
203
|
+
err_msg = f"External Memory object ({memory_name}) must have 'aget_messages' method."
|
|
204
|
+
raise AttributeError(err_msg)
|
|
205
|
+
# Check if n_messages is None or 0
|
|
206
|
+
if n_messages == 0:
|
|
207
|
+
stored = []
|
|
208
|
+
elif self.memory:
|
|
209
|
+
# override session_id
|
|
210
|
+
self.memory.session_id = session_id
|
|
211
|
+
self.memory.context_id = context_id
|
|
212
|
+
|
|
213
|
+
stored = await self.memory.aget_messages()
|
|
214
|
+
# langchain memories are supposed to return messages in ascending order
|
|
215
|
+
|
|
216
|
+
if n_messages:
|
|
217
|
+
stored = stored[-n_messages:] # Get last N messages first
|
|
218
|
+
|
|
219
|
+
if order == "DESC":
|
|
220
|
+
stored = stored[::-1] # Then reverse if needed
|
|
221
|
+
|
|
222
|
+
stored = [Message.from_lc_message(m) for m in stored]
|
|
223
|
+
if sender_type:
|
|
224
|
+
expected_type = MESSAGE_SENDER_AI if sender_type == MESSAGE_SENDER_AI else MESSAGE_SENDER_USER
|
|
225
|
+
stored = [m for m in stored if m.type == expected_type]
|
|
226
|
+
else:
|
|
227
|
+
# For internal memory, we always fetch the last N messages by ordering by DESC
|
|
228
|
+
stored = await aget_messages(
|
|
229
|
+
sender=sender_type,
|
|
230
|
+
sender_name=sender_name,
|
|
231
|
+
session_id=session_id,
|
|
232
|
+
context_id=context_id,
|
|
233
|
+
limit=10000,
|
|
234
|
+
order=order,
|
|
235
|
+
)
|
|
236
|
+
if n_messages:
|
|
237
|
+
stored = stored[-n_messages:] # Get last N messages
|
|
238
|
+
|
|
239
|
+
# self.status = stored
|
|
240
|
+
return cast("Data", stored)
|
|
241
|
+
|
|
242
|
+
async def retrieve_messages_as_text(self) -> Message:
|
|
243
|
+
stored_text = data_to_text(self.template, await self.retrieve_messages())
|
|
244
|
+
# self.status = stored_text
|
|
245
|
+
return Message(text=stored_text)
|
|
246
|
+
|
|
247
|
+
async def retrieve_messages_dataframe(self) -> DataFrame:
|
|
248
|
+
"""Convert the retrieved messages into a DataFrame.
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
DataFrame: A DataFrame containing the message data.
|
|
252
|
+
"""
|
|
253
|
+
messages = await self.retrieve_messages()
|
|
254
|
+
return DataFrame(messages)
|
|
255
|
+
|
|
256
|
+
def update_build_config(
|
|
257
|
+
self,
|
|
258
|
+
build_config: dotdict,
|
|
259
|
+
field_value: Any, # noqa: ARG002
|
|
260
|
+
field_name: str | None = None, # noqa: ARG002
|
|
261
|
+
) -> dotdict:
|
|
262
|
+
return set_current_fields(
|
|
263
|
+
build_config=build_config,
|
|
264
|
+
action_fields=self.mode_config,
|
|
265
|
+
selected_action=build_config["mode"]["value"],
|
|
266
|
+
default_fields=self.default_keys,
|
|
267
|
+
func=set_field_display,
|
|
268
|
+
)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from lfx.base.prompts.api_utils import process_prompt_template
|
|
2
|
+
from lfx.custom.custom_component.component import Component
|
|
3
|
+
from lfx.inputs.inputs import DefaultPromptField
|
|
4
|
+
from lfx.io import MessageTextInput, Output, PromptInput
|
|
5
|
+
from lfx.schema.message import Message
|
|
6
|
+
from lfx.template.utils import update_template_values
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PromptComponent(Component):
|
|
10
|
+
display_name: str = "Prompt Template"
|
|
11
|
+
description: str = "Create a prompt template with dynamic variables."
|
|
12
|
+
documentation: str = "https://docs.langflow.org/components-prompts"
|
|
13
|
+
icon = "braces"
|
|
14
|
+
trace_type = "prompt"
|
|
15
|
+
name = "Prompt Template"
|
|
16
|
+
priority = 0 # Set priority to 0 to make it appear first
|
|
17
|
+
|
|
18
|
+
inputs = [
|
|
19
|
+
PromptInput(name="template", display_name="Template"),
|
|
20
|
+
MessageTextInput(
|
|
21
|
+
name="tool_placeholder",
|
|
22
|
+
display_name="Tool Placeholder",
|
|
23
|
+
tool_mode=True,
|
|
24
|
+
advanced=True,
|
|
25
|
+
info="A placeholder input for tool mode.",
|
|
26
|
+
),
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
outputs = [
|
|
30
|
+
Output(display_name="Prompt", name="prompt", method="build_prompt"),
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
async def build_prompt(self) -> Message:
|
|
34
|
+
prompt = Message.from_template(**self._attributes)
|
|
35
|
+
self.status = prompt.text
|
|
36
|
+
return prompt
|
|
37
|
+
|
|
38
|
+
def _update_template(self, frontend_node: dict):
|
|
39
|
+
prompt_template = frontend_node["template"]["template"]["value"]
|
|
40
|
+
custom_fields = frontend_node["custom_fields"]
|
|
41
|
+
frontend_node_template = frontend_node["template"]
|
|
42
|
+
_ = process_prompt_template(
|
|
43
|
+
template=prompt_template,
|
|
44
|
+
name="template",
|
|
45
|
+
custom_fields=custom_fields,
|
|
46
|
+
frontend_node_template=frontend_node_template,
|
|
47
|
+
)
|
|
48
|
+
return frontend_node
|
|
49
|
+
|
|
50
|
+
async def update_frontend_node(self, new_frontend_node: dict, current_frontend_node: dict):
|
|
51
|
+
"""This function is called after the code validation is done."""
|
|
52
|
+
frontend_node = await super().update_frontend_node(new_frontend_node, current_frontend_node)
|
|
53
|
+
template = frontend_node["template"]["template"]["value"]
|
|
54
|
+
# Kept it duplicated for backwards compatibility
|
|
55
|
+
_ = process_prompt_template(
|
|
56
|
+
template=template,
|
|
57
|
+
name="template",
|
|
58
|
+
custom_fields=frontend_node["custom_fields"],
|
|
59
|
+
frontend_node_template=frontend_node["template"],
|
|
60
|
+
)
|
|
61
|
+
# Now that template is updated, we need to grab any values that were set in the current_frontend_node
|
|
62
|
+
# and update the frontend_node with those values
|
|
63
|
+
update_template_values(new_template=frontend_node, previous_template=current_frontend_node["template"])
|
|
64
|
+
return frontend_node
|
|
65
|
+
|
|
66
|
+
def _get_fallback_input(self, **kwargs):
|
|
67
|
+
return DefaultPromptField(**kwargs)
|
|
@@ -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 .mongodb_atlas import MongoVectorStoreComponent
|
|
9
|
+
|
|
10
|
+
_dynamic_imports = {
|
|
11
|
+
"MongoVectorStoreComponent": "mongodb_atlas",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"MongoVectorStoreComponent",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def __getattr__(attr_name: str) -> Any:
|
|
20
|
+
"""Lazily import MongoDB 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__)
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import tempfile
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
import certifi
|
|
5
|
+
from langchain_community.vectorstores import MongoDBAtlasVectorSearch
|
|
6
|
+
from pymongo.collection import Collection
|
|
7
|
+
from pymongo.operations import SearchIndexModel
|
|
8
|
+
|
|
9
|
+
from lfx.base.vectorstores.model import LCVectorStoreComponent, check_cached_vector_store
|
|
10
|
+
from lfx.helpers.data import docs_to_data
|
|
11
|
+
from lfx.io import BoolInput, DropdownInput, HandleInput, IntInput, SecretStrInput, StrInput
|
|
12
|
+
from lfx.schema.data import Data
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MongoVectorStoreComponent(LCVectorStoreComponent):
|
|
16
|
+
display_name = "MongoDB Atlas"
|
|
17
|
+
description = "MongoDB Atlas Vector Store with search capabilities"
|
|
18
|
+
name = "MongoDBAtlasVector"
|
|
19
|
+
icon = "MongoDB"
|
|
20
|
+
INSERT_MODES = ["append", "overwrite"]
|
|
21
|
+
SIMILARITY_OPTIONS = ["cosine", "euclidean", "dotProduct"]
|
|
22
|
+
QUANTIZATION_OPTIONS = ["scalar", "binary"]
|
|
23
|
+
inputs = [
|
|
24
|
+
SecretStrInput(name="mongodb_atlas_cluster_uri", display_name="MongoDB Atlas Cluster URI", required=True),
|
|
25
|
+
BoolInput(name="enable_mtls", display_name="Enable mTLS", value=False, advanced=True, required=True),
|
|
26
|
+
SecretStrInput(
|
|
27
|
+
name="mongodb_atlas_client_cert",
|
|
28
|
+
display_name="MongoDB Atlas Combined Client Certificate",
|
|
29
|
+
required=False,
|
|
30
|
+
info="Client Certificate combined with the private key in the following format:\n "
|
|
31
|
+
"-----BEGIN PRIVATE KEY-----\n...\n -----END PRIVATE KEY-----\n-----BEGIN CERTIFICATE-----\n"
|
|
32
|
+
"...\n-----END CERTIFICATE-----\n",
|
|
33
|
+
),
|
|
34
|
+
StrInput(name="db_name", display_name="Database Name", required=True),
|
|
35
|
+
StrInput(name="collection_name", display_name="Collection Name", required=True),
|
|
36
|
+
StrInput(
|
|
37
|
+
name="index_name",
|
|
38
|
+
display_name="Index Name",
|
|
39
|
+
required=True,
|
|
40
|
+
info="The name of Atlas Search index, it should be a Vector Search.",
|
|
41
|
+
),
|
|
42
|
+
*LCVectorStoreComponent.inputs,
|
|
43
|
+
DropdownInput(
|
|
44
|
+
name="insert_mode",
|
|
45
|
+
display_name="Insert Mode",
|
|
46
|
+
options=INSERT_MODES,
|
|
47
|
+
value=INSERT_MODES[0],
|
|
48
|
+
info="How to insert new documents into the collection.",
|
|
49
|
+
advanced=True,
|
|
50
|
+
),
|
|
51
|
+
HandleInput(name="embedding", display_name="Embedding", input_types=["Embeddings"]),
|
|
52
|
+
IntInput(
|
|
53
|
+
name="number_of_results",
|
|
54
|
+
display_name="Number of Results",
|
|
55
|
+
info="Number of results to return.",
|
|
56
|
+
value=4,
|
|
57
|
+
advanced=True,
|
|
58
|
+
),
|
|
59
|
+
StrInput(
|
|
60
|
+
name="index_field",
|
|
61
|
+
display_name="Index Field",
|
|
62
|
+
advanced=True,
|
|
63
|
+
required=True,
|
|
64
|
+
info="The field to index.",
|
|
65
|
+
value="embedding",
|
|
66
|
+
),
|
|
67
|
+
StrInput(
|
|
68
|
+
name="filter_field", display_name="Filter Field", advanced=True, info="The field to filter the index."
|
|
69
|
+
),
|
|
70
|
+
IntInput(
|
|
71
|
+
name="number_dimensions",
|
|
72
|
+
display_name="Number of Dimensions",
|
|
73
|
+
info="Embedding Context Length.",
|
|
74
|
+
value=1536,
|
|
75
|
+
advanced=True,
|
|
76
|
+
required=True,
|
|
77
|
+
),
|
|
78
|
+
DropdownInput(
|
|
79
|
+
name="similarity",
|
|
80
|
+
display_name="Similarity",
|
|
81
|
+
options=SIMILARITY_OPTIONS,
|
|
82
|
+
value=SIMILARITY_OPTIONS[0],
|
|
83
|
+
info="The method used to measure the similarity between vectors.",
|
|
84
|
+
advanced=True,
|
|
85
|
+
),
|
|
86
|
+
DropdownInput(
|
|
87
|
+
name="quantization",
|
|
88
|
+
display_name="Quantization",
|
|
89
|
+
options=QUANTIZATION_OPTIONS,
|
|
90
|
+
value=None,
|
|
91
|
+
info="Quantization reduces memory costs converting 32-bit floats to smaller data types",
|
|
92
|
+
advanced=True,
|
|
93
|
+
),
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
@check_cached_vector_store
|
|
97
|
+
def build_vector_store(self) -> MongoDBAtlasVectorSearch:
|
|
98
|
+
try:
|
|
99
|
+
from pymongo import MongoClient
|
|
100
|
+
except ImportError as e:
|
|
101
|
+
msg = "Please install pymongo to use MongoDB Atlas Vector Store"
|
|
102
|
+
raise ImportError(msg) from e
|
|
103
|
+
|
|
104
|
+
# Create temporary files for the client certificate
|
|
105
|
+
if self.enable_mtls:
|
|
106
|
+
client_cert_path = None
|
|
107
|
+
try:
|
|
108
|
+
client_cert = self.mongodb_atlas_client_cert.replace(" ", "\n")
|
|
109
|
+
client_cert = client_cert.replace("-----BEGIN\nPRIVATE\nKEY-----", "-----BEGIN PRIVATE KEY-----")
|
|
110
|
+
client_cert = client_cert.replace(
|
|
111
|
+
"-----END\nPRIVATE\nKEY-----\n-----BEGIN\nCERTIFICATE-----",
|
|
112
|
+
"-----END PRIVATE KEY-----\n-----BEGIN CERTIFICATE-----",
|
|
113
|
+
)
|
|
114
|
+
client_cert = client_cert.replace("-----END\nCERTIFICATE-----", "-----END CERTIFICATE-----")
|
|
115
|
+
with tempfile.NamedTemporaryFile(delete=False) as client_cert_file:
|
|
116
|
+
client_cert_file.write(client_cert.encode("utf-8"))
|
|
117
|
+
client_cert_path = client_cert_file.name
|
|
118
|
+
|
|
119
|
+
except Exception as e:
|
|
120
|
+
msg = f"Failed to write certificate to temporary file: {e}"
|
|
121
|
+
raise ValueError(msg) from e
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
mongo_client: MongoClient = (
|
|
125
|
+
MongoClient(
|
|
126
|
+
self.mongodb_atlas_cluster_uri,
|
|
127
|
+
tls=True,
|
|
128
|
+
tlsCertificateKeyFile=client_cert_path,
|
|
129
|
+
tlsCAFile=certifi.where(),
|
|
130
|
+
)
|
|
131
|
+
if self.enable_mtls
|
|
132
|
+
else MongoClient(self.mongodb_atlas_cluster_uri)
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
collection = mongo_client[self.db_name][self.collection_name]
|
|
136
|
+
|
|
137
|
+
except Exception as e:
|
|
138
|
+
msg = f"Failed to connect to MongoDB Atlas: {e}"
|
|
139
|
+
raise ValueError(msg) from e
|
|
140
|
+
|
|
141
|
+
# Convert DataFrame to Data if needed using parent's method
|
|
142
|
+
self.ingest_data = self._prepare_ingest_data()
|
|
143
|
+
|
|
144
|
+
documents = []
|
|
145
|
+
for _input in self.ingest_data or []:
|
|
146
|
+
if isinstance(_input, Data):
|
|
147
|
+
documents.append(_input.to_lc_document())
|
|
148
|
+
else:
|
|
149
|
+
documents.append(_input)
|
|
150
|
+
|
|
151
|
+
if documents:
|
|
152
|
+
self.__insert_mode(collection)
|
|
153
|
+
|
|
154
|
+
return MongoDBAtlasVectorSearch.from_documents(
|
|
155
|
+
documents=documents, embedding=self.embedding, collection=collection, index_name=self.index_name
|
|
156
|
+
)
|
|
157
|
+
return MongoDBAtlasVectorSearch(embedding=self.embedding, collection=collection, index_name=self.index_name)
|
|
158
|
+
|
|
159
|
+
def search_documents(self) -> list[Data]:
|
|
160
|
+
from bson.objectid import ObjectId
|
|
161
|
+
|
|
162
|
+
vector_store = self.build_vector_store()
|
|
163
|
+
|
|
164
|
+
self.verify_search_index(vector_store._collection)
|
|
165
|
+
|
|
166
|
+
if self.search_query and isinstance(self.search_query, str):
|
|
167
|
+
docs = vector_store.similarity_search(
|
|
168
|
+
query=self.search_query,
|
|
169
|
+
k=self.number_of_results,
|
|
170
|
+
)
|
|
171
|
+
for doc in docs:
|
|
172
|
+
doc.metadata = {
|
|
173
|
+
key: str(value) if isinstance(value, ObjectId) else value for key, value in doc.metadata.items()
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
data = docs_to_data(docs)
|
|
177
|
+
self.status = data
|
|
178
|
+
return data
|
|
179
|
+
return []
|
|
180
|
+
|
|
181
|
+
def __insert_mode(self, collection: Collection) -> None:
|
|
182
|
+
if self.insert_mode == "overwrite":
|
|
183
|
+
collection.delete_many({}) # Delete all documents while preserving collection structure
|
|
184
|
+
|
|
185
|
+
def verify_search_index(self, collection: Collection) -> None:
|
|
186
|
+
"""Verify if the search index exists, if not, create it.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
collection (Collection): The collection to verify the search index on.
|
|
190
|
+
"""
|
|
191
|
+
indexes = collection.list_search_indexes()
|
|
192
|
+
|
|
193
|
+
index_names_types = {idx["name"]: idx["type"] for idx in indexes}
|
|
194
|
+
index_names = list(index_names_types.keys())
|
|
195
|
+
index_type = index_names_types.get(self.index_name)
|
|
196
|
+
if self.index_name not in index_names and index_type != "vectorSearch":
|
|
197
|
+
collection.create_search_index(self.__create_index_definition())
|
|
198
|
+
|
|
199
|
+
time.sleep(20) # Give some time for index to be ready
|
|
200
|
+
|
|
201
|
+
def __create_index_definition(self) -> SearchIndexModel:
|
|
202
|
+
fields = [
|
|
203
|
+
{
|
|
204
|
+
"type": "vector",
|
|
205
|
+
"path": self.index_field,
|
|
206
|
+
"numDimensions": self.number_dimensions,
|
|
207
|
+
"similarity": self.similarity,
|
|
208
|
+
"quantization": self.quantization,
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
if self.filter_field:
|
|
212
|
+
fields.append({"type": "filter", "path": self.filter_field})
|
|
213
|
+
return SearchIndexModel(definition={"fields": fields}, name=self.index_name, type="vectorSearch")
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from langchain_community.retrievers.needle import NeedleRetriever
|
|
2
|
+
|
|
3
|
+
from lfx.custom.custom_component.component import Component
|
|
4
|
+
from lfx.io import IntInput, MessageTextInput, Output, SecretStrInput
|
|
5
|
+
from lfx.schema.message import Message
|
|
6
|
+
from lfx.utils.constants import MESSAGE_SENDER_AI
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class NeedleComponent(Component):
|
|
10
|
+
display_name = "Needle Retriever"
|
|
11
|
+
description = "A retriever that uses the Needle API to search collections."
|
|
12
|
+
documentation = "https://docs.needle-ai.com"
|
|
13
|
+
icon = "Needle"
|
|
14
|
+
name = "needle"
|
|
15
|
+
|
|
16
|
+
inputs = [
|
|
17
|
+
SecretStrInput(
|
|
18
|
+
name="needle_api_key",
|
|
19
|
+
display_name="Needle API Key",
|
|
20
|
+
info="Your Needle API key.",
|
|
21
|
+
required=True,
|
|
22
|
+
),
|
|
23
|
+
MessageTextInput(
|
|
24
|
+
name="collection_id",
|
|
25
|
+
display_name="Collection ID",
|
|
26
|
+
info="The ID of the Needle collection.",
|
|
27
|
+
required=True,
|
|
28
|
+
),
|
|
29
|
+
MessageTextInput(
|
|
30
|
+
name="query",
|
|
31
|
+
display_name="User Query",
|
|
32
|
+
info="Enter your question here. In tool mode, you can also specify top_k parameter (min: 20).",
|
|
33
|
+
required=True,
|
|
34
|
+
tool_mode=True,
|
|
35
|
+
),
|
|
36
|
+
IntInput(
|
|
37
|
+
name="top_k",
|
|
38
|
+
display_name="Top K Results",
|
|
39
|
+
info="Number of search results to return (min: 20).",
|
|
40
|
+
value=20,
|
|
41
|
+
required=True,
|
|
42
|
+
),
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
outputs = [Output(display_name="Result", name="result", type_="Message", method="run")]
|
|
46
|
+
|
|
47
|
+
def run(self) -> Message:
|
|
48
|
+
# Extract query and top_k
|
|
49
|
+
query_input = self.query
|
|
50
|
+
actual_query = query_input.get("query", "") if isinstance(query_input, dict) else query_input
|
|
51
|
+
|
|
52
|
+
# Parse top_k from tool input or use default, always enforcing minimum of 20
|
|
53
|
+
try:
|
|
54
|
+
if isinstance(query_input, dict) and "top_k" in query_input:
|
|
55
|
+
agent_top_k = query_input.get("top_k")
|
|
56
|
+
# Check if agent_top_k is not None before converting to int
|
|
57
|
+
top_k = max(20, int(agent_top_k)) if agent_top_k is not None else max(20, self.top_k)
|
|
58
|
+
else:
|
|
59
|
+
top_k = max(20, self.top_k)
|
|
60
|
+
except (ValueError, TypeError):
|
|
61
|
+
top_k = max(20, self.top_k)
|
|
62
|
+
|
|
63
|
+
# Validate required inputs
|
|
64
|
+
if not self.needle_api_key or not self.needle_api_key.strip():
|
|
65
|
+
error_msg = "The Needle API key cannot be empty."
|
|
66
|
+
raise ValueError(error_msg)
|
|
67
|
+
if not self.collection_id or not self.collection_id.strip():
|
|
68
|
+
error_msg = "The Collection ID cannot be empty."
|
|
69
|
+
raise ValueError(error_msg)
|
|
70
|
+
if not actual_query or not actual_query.strip():
|
|
71
|
+
error_msg = "The query cannot be empty."
|
|
72
|
+
raise ValueError(error_msg)
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
# Initialize the retriever and get documents
|
|
76
|
+
retriever = NeedleRetriever(
|
|
77
|
+
needle_api_key=self.needle_api_key,
|
|
78
|
+
collection_id=self.collection_id,
|
|
79
|
+
top_k=top_k,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
docs = retriever.get_relevant_documents(actual_query)
|
|
83
|
+
|
|
84
|
+
# Format the response
|
|
85
|
+
if not docs:
|
|
86
|
+
text_content = "No relevant documents found for the query."
|
|
87
|
+
else:
|
|
88
|
+
context = "\n\n".join([f"Document {i + 1}:\n{doc.page_content}" for i, doc in enumerate(docs)])
|
|
89
|
+
text_content = f"Question: {actual_query}\n\nContext:\n{context}"
|
|
90
|
+
|
|
91
|
+
# Return formatted message
|
|
92
|
+
return Message(
|
|
93
|
+
text=text_content,
|
|
94
|
+
type="assistant",
|
|
95
|
+
sender=MESSAGE_SENDER_AI,
|
|
96
|
+
additional_kwargs={
|
|
97
|
+
"source_documents": [{"page_content": doc.page_content, "metadata": doc.metadata} for doc in docs],
|
|
98
|
+
"top_k_used": top_k,
|
|
99
|
+
},
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
except Exception as e:
|
|
103
|
+
error_msg = f"Error processing query: {e!s}"
|
|
104
|
+
raise ValueError(error_msg) from e
|