lfx-nightly 0.1.11.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lfx/__init__.py +0 -0
- lfx/__main__.py +25 -0
- lfx/base/__init__.py +0 -0
- lfx/base/agents/__init__.py +0 -0
- lfx/base/agents/agent.py +268 -0
- lfx/base/agents/callback.py +130 -0
- lfx/base/agents/context.py +109 -0
- lfx/base/agents/crewai/__init__.py +0 -0
- lfx/base/agents/crewai/crew.py +231 -0
- lfx/base/agents/crewai/tasks.py +12 -0
- lfx/base/agents/default_prompts.py +23 -0
- lfx/base/agents/errors.py +15 -0
- lfx/base/agents/events.py +346 -0
- lfx/base/agents/utils.py +205 -0
- lfx/base/astra_assistants/__init__.py +0 -0
- lfx/base/astra_assistants/util.py +171 -0
- lfx/base/chains/__init__.py +0 -0
- lfx/base/chains/model.py +19 -0
- lfx/base/composio/__init__.py +0 -0
- lfx/base/composio/composio_base.py +1291 -0
- lfx/base/compressors/__init__.py +0 -0
- lfx/base/compressors/model.py +60 -0
- lfx/base/constants.py +46 -0
- lfx/base/curl/__init__.py +0 -0
- lfx/base/curl/parse.py +188 -0
- lfx/base/data/__init__.py +5 -0
- lfx/base/data/base_file.py +685 -0
- lfx/base/data/docling_utils.py +245 -0
- lfx/base/data/utils.py +198 -0
- lfx/base/document_transformers/__init__.py +0 -0
- lfx/base/document_transformers/model.py +43 -0
- lfx/base/embeddings/__init__.py +0 -0
- lfx/base/embeddings/aiml_embeddings.py +62 -0
- lfx/base/embeddings/model.py +26 -0
- lfx/base/flow_processing/__init__.py +0 -0
- lfx/base/flow_processing/utils.py +86 -0
- lfx/base/huggingface/__init__.py +0 -0
- lfx/base/huggingface/model_bridge.py +133 -0
- lfx/base/io/__init__.py +0 -0
- lfx/base/io/chat.py +20 -0
- lfx/base/io/text.py +22 -0
- lfx/base/langchain_utilities/__init__.py +0 -0
- lfx/base/langchain_utilities/model.py +35 -0
- lfx/base/langchain_utilities/spider_constants.py +1 -0
- lfx/base/langwatch/__init__.py +0 -0
- lfx/base/langwatch/utils.py +18 -0
- lfx/base/mcp/__init__.py +0 -0
- lfx/base/mcp/constants.py +2 -0
- lfx/base/mcp/util.py +1398 -0
- lfx/base/memory/__init__.py +0 -0
- lfx/base/memory/memory.py +49 -0
- lfx/base/memory/model.py +38 -0
- lfx/base/models/__init__.py +3 -0
- lfx/base/models/aiml_constants.py +51 -0
- lfx/base/models/anthropic_constants.py +47 -0
- lfx/base/models/aws_constants.py +151 -0
- lfx/base/models/chat_result.py +76 -0
- lfx/base/models/google_generative_ai_constants.py +70 -0
- lfx/base/models/groq_constants.py +134 -0
- lfx/base/models/model.py +375 -0
- lfx/base/models/model_input_constants.py +307 -0
- lfx/base/models/model_metadata.py +41 -0
- lfx/base/models/model_utils.py +8 -0
- lfx/base/models/novita_constants.py +35 -0
- lfx/base/models/ollama_constants.py +49 -0
- lfx/base/models/openai_constants.py +122 -0
- lfx/base/models/sambanova_constants.py +18 -0
- lfx/base/processing/__init__.py +0 -0
- lfx/base/prompts/__init__.py +0 -0
- lfx/base/prompts/api_utils.py +224 -0
- lfx/base/prompts/utils.py +61 -0
- lfx/base/textsplitters/__init__.py +0 -0
- lfx/base/textsplitters/model.py +28 -0
- lfx/base/tools/__init__.py +0 -0
- lfx/base/tools/base.py +26 -0
- lfx/base/tools/component_tool.py +325 -0
- lfx/base/tools/constants.py +49 -0
- lfx/base/tools/flow_tool.py +132 -0
- lfx/base/tools/run_flow.py +224 -0
- lfx/base/vectorstores/__init__.py +0 -0
- lfx/base/vectorstores/model.py +193 -0
- lfx/base/vectorstores/utils.py +22 -0
- lfx/base/vectorstores/vector_store_connection_decorator.py +52 -0
- lfx/cli/__init__.py +5 -0
- lfx/cli/commands.py +319 -0
- lfx/cli/common.py +650 -0
- lfx/cli/run.py +441 -0
- lfx/cli/script_loader.py +247 -0
- lfx/cli/serve_app.py +546 -0
- lfx/cli/validation.py +69 -0
- lfx/components/FAISS/__init__.py +34 -0
- lfx/components/FAISS/faiss.py +111 -0
- lfx/components/Notion/__init__.py +19 -0
- lfx/components/Notion/add_content_to_page.py +269 -0
- lfx/components/Notion/create_page.py +94 -0
- lfx/components/Notion/list_database_properties.py +68 -0
- lfx/components/Notion/list_pages.py +122 -0
- lfx/components/Notion/list_users.py +77 -0
- lfx/components/Notion/page_content_viewer.py +93 -0
- lfx/components/Notion/search.py +111 -0
- lfx/components/Notion/update_page_property.py +114 -0
- lfx/components/__init__.py +411 -0
- lfx/components/_importing.py +42 -0
- lfx/components/agentql/__init__.py +3 -0
- lfx/components/agentql/agentql_api.py +151 -0
- lfx/components/agents/__init__.py +34 -0
- lfx/components/agents/agent.py +558 -0
- lfx/components/agents/mcp_component.py +501 -0
- lfx/components/aiml/__init__.py +37 -0
- lfx/components/aiml/aiml.py +112 -0
- lfx/components/aiml/aiml_embeddings.py +37 -0
- lfx/components/amazon/__init__.py +36 -0
- lfx/components/amazon/amazon_bedrock_embedding.py +109 -0
- lfx/components/amazon/amazon_bedrock_model.py +124 -0
- lfx/components/amazon/s3_bucket_uploader.py +211 -0
- lfx/components/anthropic/__init__.py +34 -0
- lfx/components/anthropic/anthropic.py +187 -0
- lfx/components/apify/__init__.py +5 -0
- lfx/components/apify/apify_actor.py +325 -0
- lfx/components/arxiv/__init__.py +3 -0
- lfx/components/arxiv/arxiv.py +163 -0
- lfx/components/assemblyai/__init__.py +46 -0
- lfx/components/assemblyai/assemblyai_get_subtitles.py +83 -0
- lfx/components/assemblyai/assemblyai_lemur.py +183 -0
- lfx/components/assemblyai/assemblyai_list_transcripts.py +95 -0
- lfx/components/assemblyai/assemblyai_poll_transcript.py +72 -0
- lfx/components/assemblyai/assemblyai_start_transcript.py +188 -0
- lfx/components/azure/__init__.py +37 -0
- lfx/components/azure/azure_openai.py +95 -0
- lfx/components/azure/azure_openai_embeddings.py +83 -0
- lfx/components/baidu/__init__.py +32 -0
- lfx/components/baidu/baidu_qianfan_chat.py +113 -0
- lfx/components/bing/__init__.py +3 -0
- lfx/components/bing/bing_search_api.py +61 -0
- lfx/components/cassandra/__init__.py +40 -0
- lfx/components/cassandra/cassandra.py +264 -0
- lfx/components/cassandra/cassandra_chat.py +92 -0
- lfx/components/cassandra/cassandra_graph.py +238 -0
- lfx/components/chains/__init__.py +3 -0
- lfx/components/chroma/__init__.py +34 -0
- lfx/components/chroma/chroma.py +167 -0
- lfx/components/cleanlab/__init__.py +40 -0
- lfx/components/cleanlab/cleanlab_evaluator.py +155 -0
- lfx/components/cleanlab/cleanlab_rag_evaluator.py +254 -0
- lfx/components/cleanlab/cleanlab_remediator.py +131 -0
- lfx/components/clickhouse/__init__.py +34 -0
- lfx/components/clickhouse/clickhouse.py +135 -0
- lfx/components/cloudflare/__init__.py +32 -0
- lfx/components/cloudflare/cloudflare.py +81 -0
- lfx/components/cohere/__init__.py +40 -0
- lfx/components/cohere/cohere_embeddings.py +81 -0
- lfx/components/cohere/cohere_models.py +46 -0
- lfx/components/cohere/cohere_rerank.py +51 -0
- lfx/components/composio/__init__.py +74 -0
- lfx/components/composio/composio_api.py +268 -0
- lfx/components/composio/dropbox_compnent.py +11 -0
- lfx/components/composio/github_composio.py +11 -0
- lfx/components/composio/gmail_composio.py +38 -0
- lfx/components/composio/googlecalendar_composio.py +11 -0
- lfx/components/composio/googlemeet_composio.py +11 -0
- lfx/components/composio/googletasks_composio.py +8 -0
- lfx/components/composio/linear_composio.py +11 -0
- lfx/components/composio/outlook_composio.py +11 -0
- lfx/components/composio/reddit_composio.py +11 -0
- lfx/components/composio/slack_composio.py +582 -0
- lfx/components/composio/slackbot_composio.py +11 -0
- lfx/components/composio/supabase_composio.py +11 -0
- lfx/components/composio/todoist_composio.py +11 -0
- lfx/components/composio/youtube_composio.py +11 -0
- lfx/components/confluence/__init__.py +3 -0
- lfx/components/confluence/confluence.py +84 -0
- lfx/components/couchbase/__init__.py +34 -0
- lfx/components/couchbase/couchbase.py +102 -0
- lfx/components/crewai/__init__.py +49 -0
- lfx/components/crewai/crewai.py +107 -0
- lfx/components/crewai/hierarchical_crew.py +46 -0
- lfx/components/crewai/hierarchical_task.py +44 -0
- lfx/components/crewai/sequential_crew.py +52 -0
- lfx/components/crewai/sequential_task.py +73 -0
- lfx/components/crewai/sequential_task_agent.py +143 -0
- lfx/components/custom_component/__init__.py +34 -0
- lfx/components/custom_component/custom_component.py +31 -0
- lfx/components/data/__init__.py +64 -0
- lfx/components/data/api_request.py +544 -0
- lfx/components/data/csv_to_data.py +95 -0
- lfx/components/data/directory.py +113 -0
- lfx/components/data/file.py +577 -0
- lfx/components/data/json_to_data.py +98 -0
- lfx/components/data/news_search.py +164 -0
- lfx/components/data/rss.py +69 -0
- lfx/components/data/sql_executor.py +101 -0
- lfx/components/data/url.py +311 -0
- lfx/components/data/web_search.py +112 -0
- lfx/components/data/webhook.py +56 -0
- lfx/components/datastax/__init__.py +70 -0
- lfx/components/datastax/astra_assistant_manager.py +306 -0
- lfx/components/datastax/astra_db.py +75 -0
- lfx/components/datastax/astra_vectorize.py +124 -0
- lfx/components/datastax/astradb.py +1285 -0
- lfx/components/datastax/astradb_cql.py +314 -0
- lfx/components/datastax/astradb_graph.py +330 -0
- lfx/components/datastax/astradb_tool.py +414 -0
- lfx/components/datastax/astradb_vectorstore.py +1285 -0
- lfx/components/datastax/cassandra.py +92 -0
- lfx/components/datastax/create_assistant.py +58 -0
- lfx/components/datastax/create_thread.py +32 -0
- lfx/components/datastax/dotenv.py +35 -0
- lfx/components/datastax/get_assistant.py +37 -0
- lfx/components/datastax/getenvvar.py +30 -0
- lfx/components/datastax/graph_rag.py +141 -0
- lfx/components/datastax/hcd.py +314 -0
- lfx/components/datastax/list_assistants.py +25 -0
- lfx/components/datastax/run.py +89 -0
- lfx/components/deactivated/__init__.py +15 -0
- lfx/components/deactivated/amazon_kendra.py +66 -0
- lfx/components/deactivated/chat_litellm_model.py +158 -0
- lfx/components/deactivated/code_block_extractor.py +26 -0
- lfx/components/deactivated/documents_to_data.py +22 -0
- lfx/components/deactivated/embed.py +16 -0
- lfx/components/deactivated/extract_key_from_data.py +46 -0
- lfx/components/deactivated/json_document_builder.py +57 -0
- lfx/components/deactivated/list_flows.py +20 -0
- lfx/components/deactivated/mcp_sse.py +61 -0
- lfx/components/deactivated/mcp_stdio.py +62 -0
- lfx/components/deactivated/merge_data.py +93 -0
- lfx/components/deactivated/message.py +37 -0
- lfx/components/deactivated/metal.py +54 -0
- lfx/components/deactivated/multi_query.py +59 -0
- lfx/components/deactivated/retriever.py +43 -0
- lfx/components/deactivated/selective_passthrough.py +77 -0
- lfx/components/deactivated/should_run_next.py +40 -0
- lfx/components/deactivated/split_text.py +63 -0
- lfx/components/deactivated/store_message.py +24 -0
- lfx/components/deactivated/sub_flow.py +124 -0
- lfx/components/deactivated/vectara_self_query.py +76 -0
- lfx/components/deactivated/vector_store.py +24 -0
- lfx/components/deepseek/__init__.py +34 -0
- lfx/components/deepseek/deepseek.py +136 -0
- lfx/components/docling/__init__.py +43 -0
- lfx/components/docling/chunk_docling_document.py +186 -0
- lfx/components/docling/docling_inline.py +231 -0
- lfx/components/docling/docling_remote.py +193 -0
- lfx/components/docling/export_docling_document.py +117 -0
- lfx/components/documentloaders/__init__.py +3 -0
- lfx/components/duckduckgo/__init__.py +3 -0
- lfx/components/duckduckgo/duck_duck_go_search_run.py +92 -0
- lfx/components/elastic/__init__.py +37 -0
- lfx/components/elastic/elasticsearch.py +267 -0
- lfx/components/elastic/opensearch.py +243 -0
- lfx/components/embeddings/__init__.py +37 -0
- lfx/components/embeddings/similarity.py +76 -0
- lfx/components/embeddings/text_embedder.py +64 -0
- lfx/components/exa/__init__.py +3 -0
- lfx/components/exa/exa_search.py +68 -0
- lfx/components/firecrawl/__init__.py +43 -0
- lfx/components/firecrawl/firecrawl_crawl_api.py +88 -0
- lfx/components/firecrawl/firecrawl_extract_api.py +136 -0
- lfx/components/firecrawl/firecrawl_map_api.py +89 -0
- lfx/components/firecrawl/firecrawl_scrape_api.py +73 -0
- lfx/components/git/__init__.py +4 -0
- lfx/components/git/git.py +262 -0
- lfx/components/git/gitextractor.py +196 -0
- lfx/components/glean/__init__.py +3 -0
- lfx/components/glean/glean_search_api.py +173 -0
- lfx/components/google/__init__.py +17 -0
- lfx/components/google/gmail.py +192 -0
- lfx/components/google/google_bq_sql_executor.py +157 -0
- lfx/components/google/google_drive.py +92 -0
- lfx/components/google/google_drive_search.py +152 -0
- lfx/components/google/google_generative_ai.py +147 -0
- lfx/components/google/google_generative_ai_embeddings.py +141 -0
- lfx/components/google/google_oauth_token.py +89 -0
- lfx/components/google/google_search_api_core.py +68 -0
- lfx/components/google/google_serper_api_core.py +74 -0
- lfx/components/groq/__init__.py +34 -0
- lfx/components/groq/groq.py +136 -0
- lfx/components/helpers/__init__.py +52 -0
- lfx/components/helpers/calculator_core.py +89 -0
- lfx/components/helpers/create_list.py +40 -0
- lfx/components/helpers/current_date.py +42 -0
- lfx/components/helpers/id_generator.py +42 -0
- lfx/components/helpers/memory.py +251 -0
- lfx/components/helpers/output_parser.py +45 -0
- lfx/components/helpers/store_message.py +90 -0
- lfx/components/homeassistant/__init__.py +7 -0
- lfx/components/homeassistant/home_assistant_control.py +152 -0
- lfx/components/homeassistant/list_home_assistant_states.py +137 -0
- lfx/components/huggingface/__init__.py +37 -0
- lfx/components/huggingface/huggingface.py +197 -0
- lfx/components/huggingface/huggingface_inference_api.py +106 -0
- lfx/components/ibm/__init__.py +34 -0
- lfx/components/ibm/watsonx.py +203 -0
- lfx/components/ibm/watsonx_embeddings.py +135 -0
- lfx/components/icosacomputing/__init__.py +5 -0
- lfx/components/icosacomputing/combinatorial_reasoner.py +84 -0
- lfx/components/input_output/__init__.py +38 -0
- lfx/components/input_output/chat.py +120 -0
- lfx/components/input_output/chat_output.py +200 -0
- lfx/components/input_output/text.py +27 -0
- lfx/components/input_output/text_output.py +29 -0
- lfx/components/jigsawstack/__init__.py +23 -0
- lfx/components/jigsawstack/ai_scrape.py +126 -0
- lfx/components/jigsawstack/ai_web_search.py +136 -0
- lfx/components/jigsawstack/file_read.py +115 -0
- lfx/components/jigsawstack/file_upload.py +94 -0
- lfx/components/jigsawstack/image_generation.py +205 -0
- lfx/components/jigsawstack/nsfw.py +60 -0
- lfx/components/jigsawstack/object_detection.py +124 -0
- lfx/components/jigsawstack/sentiment.py +112 -0
- lfx/components/jigsawstack/text_to_sql.py +90 -0
- lfx/components/jigsawstack/text_translate.py +77 -0
- lfx/components/jigsawstack/vocr.py +107 -0
- lfx/components/langchain_utilities/__init__.py +109 -0
- lfx/components/langchain_utilities/character.py +53 -0
- lfx/components/langchain_utilities/conversation.py +59 -0
- lfx/components/langchain_utilities/csv_agent.py +107 -0
- lfx/components/langchain_utilities/fake_embeddings.py +26 -0
- lfx/components/langchain_utilities/html_link_extractor.py +35 -0
- lfx/components/langchain_utilities/json_agent.py +45 -0
- lfx/components/langchain_utilities/langchain_hub.py +126 -0
- lfx/components/langchain_utilities/language_recursive.py +49 -0
- lfx/components/langchain_utilities/language_semantic.py +138 -0
- lfx/components/langchain_utilities/llm_checker.py +39 -0
- lfx/components/langchain_utilities/llm_math.py +42 -0
- lfx/components/langchain_utilities/natural_language.py +61 -0
- lfx/components/langchain_utilities/openai_tools.py +53 -0
- lfx/components/langchain_utilities/openapi.py +48 -0
- lfx/components/langchain_utilities/recursive_character.py +60 -0
- lfx/components/langchain_utilities/retrieval_qa.py +83 -0
- lfx/components/langchain_utilities/runnable_executor.py +137 -0
- lfx/components/langchain_utilities/self_query.py +80 -0
- lfx/components/langchain_utilities/spider.py +142 -0
- lfx/components/langchain_utilities/sql.py +40 -0
- lfx/components/langchain_utilities/sql_database.py +35 -0
- lfx/components/langchain_utilities/sql_generator.py +78 -0
- lfx/components/langchain_utilities/tool_calling.py +59 -0
- lfx/components/langchain_utilities/vector_store_info.py +49 -0
- lfx/components/langchain_utilities/vector_store_router.py +33 -0
- lfx/components/langchain_utilities/xml_agent.py +71 -0
- lfx/components/langwatch/__init__.py +3 -0
- lfx/components/langwatch/langwatch.py +278 -0
- lfx/components/link_extractors/__init__.py +3 -0
- lfx/components/lmstudio/__init__.py +34 -0
- lfx/components/lmstudio/lmstudioembeddings.py +89 -0
- lfx/components/lmstudio/lmstudiomodel.py +129 -0
- lfx/components/logic/__init__.py +52 -0
- lfx/components/logic/conditional_router.py +171 -0
- lfx/components/logic/data_conditional_router.py +125 -0
- lfx/components/logic/flow_tool.py +110 -0
- lfx/components/logic/listen.py +29 -0
- lfx/components/logic/loop.py +125 -0
- lfx/components/logic/notify.py +88 -0
- lfx/components/logic/pass_message.py +35 -0
- lfx/components/logic/run_flow.py +71 -0
- lfx/components/logic/sub_flow.py +114 -0
- lfx/components/maritalk/__init__.py +32 -0
- lfx/components/maritalk/maritalk.py +52 -0
- lfx/components/mem0/__init__.py +3 -0
- lfx/components/mem0/mem0_chat_memory.py +136 -0
- lfx/components/milvus/__init__.py +34 -0
- lfx/components/milvus/milvus.py +115 -0
- lfx/components/mistral/__init__.py +37 -0
- lfx/components/mistral/mistral.py +114 -0
- lfx/components/mistral/mistral_embeddings.py +58 -0
- lfx/components/models/__init__.py +34 -0
- lfx/components/models/embedding_model.py +114 -0
- lfx/components/models/language_model.py +144 -0
- lfx/components/mongodb/__init__.py +34 -0
- lfx/components/mongodb/mongodb_atlas.py +213 -0
- lfx/components/needle/__init__.py +3 -0
- lfx/components/needle/needle.py +104 -0
- lfx/components/notdiamond/__init__.py +34 -0
- lfx/components/notdiamond/notdiamond.py +228 -0
- lfx/components/novita/__init__.py +32 -0
- lfx/components/novita/novita.py +130 -0
- lfx/components/nvidia/__init__.py +57 -0
- lfx/components/nvidia/nvidia.py +157 -0
- lfx/components/nvidia/nvidia_embedding.py +77 -0
- lfx/components/nvidia/nvidia_ingest.py +317 -0
- lfx/components/nvidia/nvidia_rerank.py +63 -0
- lfx/components/nvidia/system_assist.py +65 -0
- lfx/components/olivya/__init__.py +3 -0
- lfx/components/olivya/olivya.py +116 -0
- lfx/components/ollama/__init__.py +37 -0
- lfx/components/ollama/ollama.py +330 -0
- lfx/components/ollama/ollama_embeddings.py +106 -0
- lfx/components/openai/__init__.py +37 -0
- lfx/components/openai/openai.py +100 -0
- lfx/components/openai/openai_chat_model.py +176 -0
- lfx/components/openrouter/__init__.py +32 -0
- lfx/components/openrouter/openrouter.py +202 -0
- lfx/components/output_parsers/__init__.py +3 -0
- lfx/components/perplexity/__init__.py +34 -0
- lfx/components/perplexity/perplexity.py +75 -0
- lfx/components/pgvector/__init__.py +34 -0
- lfx/components/pgvector/pgvector.py +72 -0
- lfx/components/pinecone/__init__.py +34 -0
- lfx/components/pinecone/pinecone.py +134 -0
- lfx/components/processing/__init__.py +117 -0
- lfx/components/processing/alter_metadata.py +108 -0
- lfx/components/processing/batch_run.py +205 -0
- lfx/components/processing/combine_text.py +39 -0
- lfx/components/processing/converter.py +159 -0
- lfx/components/processing/create_data.py +110 -0
- lfx/components/processing/data_operations.py +438 -0
- lfx/components/processing/data_to_dataframe.py +70 -0
- lfx/components/processing/dataframe_operations.py +313 -0
- lfx/components/processing/extract_key.py +53 -0
- lfx/components/processing/filter_data.py +42 -0
- lfx/components/processing/filter_data_values.py +88 -0
- lfx/components/processing/json_cleaner.py +103 -0
- lfx/components/processing/lambda_filter.py +154 -0
- lfx/components/processing/llm_router.py +499 -0
- lfx/components/processing/merge_data.py +90 -0
- lfx/components/processing/message_to_data.py +36 -0
- lfx/components/processing/parse_data.py +70 -0
- lfx/components/processing/parse_dataframe.py +68 -0
- lfx/components/processing/parse_json_data.py +90 -0
- lfx/components/processing/parser.py +143 -0
- lfx/components/processing/prompt.py +67 -0
- lfx/components/processing/python_repl_core.py +98 -0
- lfx/components/processing/regex.py +82 -0
- lfx/components/processing/save_file.py +225 -0
- lfx/components/processing/select_data.py +48 -0
- lfx/components/processing/split_text.py +141 -0
- lfx/components/processing/structured_output.py +202 -0
- lfx/components/processing/update_data.py +160 -0
- lfx/components/prototypes/__init__.py +34 -0
- lfx/components/prototypes/python_function.py +73 -0
- lfx/components/qdrant/__init__.py +34 -0
- lfx/components/qdrant/qdrant.py +109 -0
- lfx/components/redis/__init__.py +37 -0
- lfx/components/redis/redis.py +89 -0
- lfx/components/redis/redis_chat.py +43 -0
- lfx/components/sambanova/__init__.py +32 -0
- lfx/components/sambanova/sambanova.py +84 -0
- lfx/components/scrapegraph/__init__.py +40 -0
- lfx/components/scrapegraph/scrapegraph_markdownify_api.py +64 -0
- lfx/components/scrapegraph/scrapegraph_search_api.py +64 -0
- lfx/components/scrapegraph/scrapegraph_smart_scraper_api.py +71 -0
- lfx/components/searchapi/__init__.py +34 -0
- lfx/components/searchapi/search.py +79 -0
- lfx/components/serpapi/__init__.py +3 -0
- lfx/components/serpapi/serp.py +115 -0
- lfx/components/supabase/__init__.py +34 -0
- lfx/components/supabase/supabase.py +76 -0
- lfx/components/tavily/__init__.py +4 -0
- lfx/components/tavily/tavily_extract.py +117 -0
- lfx/components/tavily/tavily_search.py +212 -0
- lfx/components/textsplitters/__init__.py +3 -0
- lfx/components/toolkits/__init__.py +3 -0
- lfx/components/tools/__init__.py +72 -0
- lfx/components/tools/calculator.py +108 -0
- lfx/components/tools/google_search_api.py +45 -0
- lfx/components/tools/google_serper_api.py +115 -0
- lfx/components/tools/python_code_structured_tool.py +327 -0
- lfx/components/tools/python_repl.py +97 -0
- lfx/components/tools/search_api.py +87 -0
- lfx/components/tools/searxng.py +145 -0
- lfx/components/tools/serp_api.py +119 -0
- lfx/components/tools/tavily_search_tool.py +344 -0
- lfx/components/tools/wikidata_api.py +102 -0
- lfx/components/tools/wikipedia_api.py +49 -0
- lfx/components/tools/yahoo_finance.py +129 -0
- lfx/components/twelvelabs/__init__.py +52 -0
- lfx/components/twelvelabs/convert_astra_results.py +84 -0
- lfx/components/twelvelabs/pegasus_index.py +311 -0
- lfx/components/twelvelabs/split_video.py +291 -0
- lfx/components/twelvelabs/text_embeddings.py +57 -0
- lfx/components/twelvelabs/twelvelabs_pegasus.py +408 -0
- lfx/components/twelvelabs/video_embeddings.py +100 -0
- lfx/components/twelvelabs/video_file.py +179 -0
- lfx/components/unstructured/__init__.py +3 -0
- lfx/components/unstructured/unstructured.py +121 -0
- lfx/components/upstash/__init__.py +34 -0
- lfx/components/upstash/upstash.py +124 -0
- lfx/components/vectara/__init__.py +37 -0
- lfx/components/vectara/vectara.py +97 -0
- lfx/components/vectara/vectara_rag.py +164 -0
- lfx/components/vectorstores/__init__.py +40 -0
- lfx/components/vectorstores/astradb.py +1285 -0
- lfx/components/vectorstores/astradb_graph.py +319 -0
- lfx/components/vectorstores/cassandra.py +264 -0
- lfx/components/vectorstores/cassandra_graph.py +238 -0
- lfx/components/vectorstores/chroma.py +167 -0
- lfx/components/vectorstores/clickhouse.py +135 -0
- lfx/components/vectorstores/couchbase.py +102 -0
- lfx/components/vectorstores/elasticsearch.py +267 -0
- lfx/components/vectorstores/faiss.py +111 -0
- lfx/components/vectorstores/graph_rag.py +141 -0
- lfx/components/vectorstores/hcd.py +314 -0
- lfx/components/vectorstores/local_db.py +261 -0
- lfx/components/vectorstores/milvus.py +115 -0
- lfx/components/vectorstores/mongodb_atlas.py +213 -0
- lfx/components/vectorstores/opensearch.py +243 -0
- lfx/components/vectorstores/pgvector.py +72 -0
- lfx/components/vectorstores/pinecone.py +134 -0
- lfx/components/vectorstores/qdrant.py +109 -0
- lfx/components/vectorstores/supabase.py +76 -0
- lfx/components/vectorstores/upstash.py +124 -0
- lfx/components/vectorstores/vectara.py +97 -0
- lfx/components/vectorstores/vectara_rag.py +164 -0
- lfx/components/vectorstores/weaviate.py +89 -0
- lfx/components/vertexai/__init__.py +37 -0
- lfx/components/vertexai/vertexai.py +71 -0
- lfx/components/vertexai/vertexai_embeddings.py +67 -0
- lfx/components/weaviate/__init__.py +34 -0
- lfx/components/weaviate/weaviate.py +89 -0
- lfx/components/wikipedia/__init__.py +4 -0
- lfx/components/wikipedia/wikidata.py +86 -0
- lfx/components/wikipedia/wikipedia.py +53 -0
- lfx/components/wolframalpha/__init__.py +3 -0
- lfx/components/wolframalpha/wolfram_alpha_api.py +54 -0
- lfx/components/xai/__init__.py +32 -0
- lfx/components/xai/xai.py +167 -0
- lfx/components/yahoosearch/__init__.py +3 -0
- lfx/components/yahoosearch/yahoo.py +137 -0
- lfx/components/youtube/__init__.py +52 -0
- lfx/components/youtube/channel.py +227 -0
- lfx/components/youtube/comments.py +231 -0
- lfx/components/youtube/playlist.py +33 -0
- lfx/components/youtube/search.py +120 -0
- lfx/components/youtube/trending.py +285 -0
- lfx/components/youtube/video_details.py +263 -0
- lfx/components/youtube/youtube_transcripts.py +118 -0
- lfx/components/zep/__init__.py +3 -0
- lfx/components/zep/zep.py +44 -0
- lfx/constants.py +6 -0
- lfx/custom/__init__.py +7 -0
- lfx/custom/attributes.py +86 -0
- lfx/custom/code_parser/__init__.py +3 -0
- lfx/custom/code_parser/code_parser.py +361 -0
- lfx/custom/custom_component/__init__.py +0 -0
- lfx/custom/custom_component/base_component.py +128 -0
- lfx/custom/custom_component/component.py +1808 -0
- lfx/custom/custom_component/component_with_cache.py +8 -0
- lfx/custom/custom_component/custom_component.py +588 -0
- lfx/custom/dependency_analyzer.py +165 -0
- lfx/custom/directory_reader/__init__.py +3 -0
- lfx/custom/directory_reader/directory_reader.py +359 -0
- lfx/custom/directory_reader/utils.py +171 -0
- lfx/custom/eval.py +12 -0
- lfx/custom/schema.py +32 -0
- lfx/custom/tree_visitor.py +21 -0
- lfx/custom/utils.py +877 -0
- lfx/custom/validate.py +488 -0
- lfx/events/__init__.py +1 -0
- lfx/events/event_manager.py +110 -0
- lfx/exceptions/__init__.py +0 -0
- lfx/exceptions/component.py +15 -0
- lfx/field_typing/__init__.py +91 -0
- lfx/field_typing/constants.py +215 -0
- lfx/field_typing/range_spec.py +35 -0
- lfx/graph/__init__.py +6 -0
- lfx/graph/edge/__init__.py +0 -0
- lfx/graph/edge/base.py +277 -0
- lfx/graph/edge/schema.py +119 -0
- lfx/graph/edge/utils.py +0 -0
- lfx/graph/graph/__init__.py +0 -0
- lfx/graph/graph/ascii.py +202 -0
- lfx/graph/graph/base.py +2238 -0
- lfx/graph/graph/constants.py +63 -0
- lfx/graph/graph/runnable_vertices_manager.py +133 -0
- lfx/graph/graph/schema.py +52 -0
- lfx/graph/graph/state_model.py +66 -0
- lfx/graph/graph/utils.py +1024 -0
- lfx/graph/schema.py +75 -0
- lfx/graph/state/__init__.py +0 -0
- lfx/graph/state/model.py +237 -0
- lfx/graph/utils.py +200 -0
- lfx/graph/vertex/__init__.py +0 -0
- lfx/graph/vertex/base.py +823 -0
- lfx/graph/vertex/constants.py +0 -0
- lfx/graph/vertex/exceptions.py +4 -0
- lfx/graph/vertex/param_handler.py +264 -0
- lfx/graph/vertex/schema.py +26 -0
- lfx/graph/vertex/utils.py +19 -0
- lfx/graph/vertex/vertex_types.py +489 -0
- lfx/helpers/__init__.py +1 -0
- lfx/helpers/base_model.py +71 -0
- lfx/helpers/custom.py +13 -0
- lfx/helpers/data.py +167 -0
- lfx/helpers/flow.py +194 -0
- lfx/inputs/__init__.py +68 -0
- lfx/inputs/constants.py +2 -0
- lfx/inputs/input_mixin.py +328 -0
- lfx/inputs/inputs.py +714 -0
- lfx/inputs/validators.py +19 -0
- lfx/interface/__init__.py +6 -0
- lfx/interface/components.py +489 -0
- lfx/interface/importing/__init__.py +5 -0
- lfx/interface/importing/utils.py +39 -0
- lfx/interface/initialize/__init__.py +3 -0
- lfx/interface/initialize/loading.py +224 -0
- lfx/interface/listing.py +26 -0
- lfx/interface/run.py +16 -0
- lfx/interface/utils.py +111 -0
- lfx/io/__init__.py +63 -0
- lfx/io/schema.py +289 -0
- lfx/load/__init__.py +8 -0
- lfx/load/load.py +256 -0
- lfx/load/utils.py +99 -0
- lfx/log/__init__.py +5 -0
- lfx/log/logger.py +385 -0
- lfx/memory/__init__.py +90 -0
- lfx/memory/stubs.py +283 -0
- lfx/processing/__init__.py +1 -0
- lfx/processing/process.py +238 -0
- lfx/processing/utils.py +25 -0
- lfx/py.typed +0 -0
- lfx/schema/__init__.py +66 -0
- lfx/schema/artifact.py +83 -0
- lfx/schema/content_block.py +62 -0
- lfx/schema/content_types.py +91 -0
- lfx/schema/data.py +308 -0
- lfx/schema/dataframe.py +210 -0
- lfx/schema/dotdict.py +74 -0
- lfx/schema/encoders.py +13 -0
- lfx/schema/graph.py +47 -0
- lfx/schema/image.py +131 -0
- lfx/schema/json_schema.py +141 -0
- lfx/schema/log.py +61 -0
- lfx/schema/message.py +473 -0
- lfx/schema/openai_responses_schemas.py +74 -0
- lfx/schema/properties.py +41 -0
- lfx/schema/schema.py +171 -0
- lfx/schema/serialize.py +13 -0
- lfx/schema/table.py +140 -0
- lfx/schema/validators.py +114 -0
- lfx/serialization/__init__.py +5 -0
- lfx/serialization/constants.py +2 -0
- lfx/serialization/serialization.py +314 -0
- lfx/services/__init__.py +23 -0
- lfx/services/base.py +28 -0
- lfx/services/cache/__init__.py +6 -0
- lfx/services/cache/base.py +183 -0
- lfx/services/cache/service.py +166 -0
- lfx/services/cache/utils.py +169 -0
- lfx/services/chat/__init__.py +1 -0
- lfx/services/chat/config.py +2 -0
- lfx/services/chat/schema.py +10 -0
- lfx/services/deps.py +129 -0
- lfx/services/factory.py +19 -0
- lfx/services/initialize.py +19 -0
- lfx/services/interfaces.py +103 -0
- lfx/services/manager.py +172 -0
- lfx/services/schema.py +20 -0
- lfx/services/session.py +82 -0
- lfx/services/settings/__init__.py +3 -0
- lfx/services/settings/auth.py +130 -0
- lfx/services/settings/base.py +539 -0
- lfx/services/settings/constants.py +31 -0
- lfx/services/settings/factory.py +23 -0
- lfx/services/settings/feature_flags.py +12 -0
- lfx/services/settings/service.py +35 -0
- lfx/services/settings/utils.py +40 -0
- lfx/services/shared_component_cache/__init__.py +1 -0
- lfx/services/shared_component_cache/factory.py +30 -0
- lfx/services/shared_component_cache/service.py +9 -0
- lfx/services/storage/__init__.py +5 -0
- lfx/services/storage/local.py +155 -0
- lfx/services/storage/service.py +54 -0
- lfx/services/tracing/__init__.py +1 -0
- lfx/services/tracing/service.py +21 -0
- lfx/settings.py +6 -0
- lfx/template/__init__.py +6 -0
- lfx/template/field/__init__.py +0 -0
- lfx/template/field/base.py +257 -0
- lfx/template/field/prompt.py +15 -0
- lfx/template/frontend_node/__init__.py +6 -0
- lfx/template/frontend_node/base.py +212 -0
- lfx/template/frontend_node/constants.py +65 -0
- lfx/template/frontend_node/custom_components.py +79 -0
- lfx/template/template/__init__.py +0 -0
- lfx/template/template/base.py +100 -0
- lfx/template/utils.py +217 -0
- lfx/type_extraction/__init__.py +19 -0
- lfx/type_extraction/type_extraction.py +75 -0
- lfx/type_extraction.py +80 -0
- lfx/utils/__init__.py +1 -0
- lfx/utils/async_helpers.py +42 -0
- lfx/utils/component_utils.py +154 -0
- lfx/utils/concurrency.py +60 -0
- lfx/utils/connection_string_parser.py +11 -0
- lfx/utils/constants.py +205 -0
- lfx/utils/data_structure.py +212 -0
- lfx/utils/exceptions.py +22 -0
- lfx/utils/helpers.py +28 -0
- lfx/utils/image.py +73 -0
- lfx/utils/lazy_load.py +15 -0
- lfx/utils/request_utils.py +18 -0
- lfx/utils/schemas.py +139 -0
- lfx/utils/util.py +481 -0
- lfx/utils/util_strings.py +56 -0
- lfx/utils/version.py +24 -0
- lfx_nightly-0.1.11.dev0.dist-info/METADATA +293 -0
- lfx_nightly-0.1.11.dev0.dist-info/RECORD +699 -0
- lfx_nightly-0.1.11.dev0.dist-info/WHEEL +4 -0
- lfx_nightly-0.1.11.dev0.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
import ast
|
2
|
+
import operator
|
3
|
+
|
4
|
+
import pytest
|
5
|
+
from langchain_core.tools import ToolException
|
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 MessageTextInput
|
11
|
+
from lfx.log.logger import logger
|
12
|
+
from lfx.schema.data import Data
|
13
|
+
|
14
|
+
|
15
|
+
class CalculatorToolComponent(LCToolComponent):
|
16
|
+
display_name = "Calculator [DEPRECATED]"
|
17
|
+
description = "Perform basic arithmetic operations on a given expression."
|
18
|
+
icon = "calculator"
|
19
|
+
name = "CalculatorTool"
|
20
|
+
legacy = True
|
21
|
+
|
22
|
+
inputs = [
|
23
|
+
MessageTextInput(
|
24
|
+
name="expression",
|
25
|
+
display_name="Expression",
|
26
|
+
info="The arithmetic expression to evaluate (e.g., '4*4*(33/22)+12-20').",
|
27
|
+
),
|
28
|
+
]
|
29
|
+
|
30
|
+
class CalculatorToolSchema(BaseModel):
|
31
|
+
expression: str = Field(..., description="The arithmetic expression to evaluate.")
|
32
|
+
|
33
|
+
def run_model(self) -> list[Data]:
|
34
|
+
return self._evaluate_expression(self.expression)
|
35
|
+
|
36
|
+
def build_tool(self) -> Tool:
|
37
|
+
try:
|
38
|
+
from langchain.tools import StructuredTool
|
39
|
+
except Exception: # noqa: BLE001
|
40
|
+
pytest.skip("langchain is not available")
|
41
|
+
|
42
|
+
return StructuredTool.from_function(
|
43
|
+
name="calculator",
|
44
|
+
description="Evaluate basic arithmetic expressions. Input should be a string containing the expression.",
|
45
|
+
func=self._eval_expr_with_error,
|
46
|
+
args_schema=self.CalculatorToolSchema,
|
47
|
+
)
|
48
|
+
|
49
|
+
def _eval_expr(self, node):
|
50
|
+
if isinstance(node, ast.Num):
|
51
|
+
return node.n
|
52
|
+
if isinstance(node, ast.BinOp):
|
53
|
+
left_val = self._eval_expr(node.left)
|
54
|
+
right_val = self._eval_expr(node.right)
|
55
|
+
return self.operators[type(node.op)](left_val, right_val)
|
56
|
+
if isinstance(node, ast.UnaryOp):
|
57
|
+
operand_val = self._eval_expr(node.operand)
|
58
|
+
return self.operators[type(node.op)](operand_val)
|
59
|
+
if isinstance(node, ast.Call):
|
60
|
+
msg = (
|
61
|
+
"Function calls like sqrt(), sin(), cos() etc. are not supported. "
|
62
|
+
"Only basic arithmetic operations (+, -, *, /, **) are allowed."
|
63
|
+
)
|
64
|
+
raise TypeError(msg)
|
65
|
+
msg = f"Unsupported operation or expression type: {type(node).__name__}"
|
66
|
+
raise TypeError(msg)
|
67
|
+
|
68
|
+
def _eval_expr_with_error(self, expression: str) -> list[Data]:
|
69
|
+
try:
|
70
|
+
return self._evaluate_expression(expression)
|
71
|
+
except Exception as e:
|
72
|
+
raise ToolException(str(e)) from e
|
73
|
+
|
74
|
+
def _evaluate_expression(self, expression: str) -> list[Data]:
|
75
|
+
try:
|
76
|
+
# Parse the expression and evaluate it
|
77
|
+
tree = ast.parse(expression, mode="eval")
|
78
|
+
result = self._eval_expr(tree.body)
|
79
|
+
|
80
|
+
# Format the result to a reasonable number of decimal places
|
81
|
+
formatted_result = f"{result:.6f}".rstrip("0").rstrip(".")
|
82
|
+
|
83
|
+
self.status = formatted_result
|
84
|
+
return [Data(data={"result": formatted_result})]
|
85
|
+
|
86
|
+
except (SyntaxError, TypeError, KeyError) as e:
|
87
|
+
error_message = f"Invalid expression: {e}"
|
88
|
+
self.status = error_message
|
89
|
+
return [Data(data={"error": error_message, "input": expression})]
|
90
|
+
except ZeroDivisionError:
|
91
|
+
error_message = "Error: Division by zero"
|
92
|
+
self.status = error_message
|
93
|
+
return [Data(data={"error": error_message, "input": expression})]
|
94
|
+
except Exception as e: # noqa: BLE001
|
95
|
+
logger.debug("Error evaluating expression", exc_info=True)
|
96
|
+
error_message = f"Error: {e}"
|
97
|
+
self.status = error_message
|
98
|
+
return [Data(data={"error": error_message, "input": expression})]
|
99
|
+
|
100
|
+
def __init__(self, *args, **kwargs):
|
101
|
+
super().__init__(*args, **kwargs)
|
102
|
+
self.operators = {
|
103
|
+
ast.Add: operator.add,
|
104
|
+
ast.Sub: operator.sub,
|
105
|
+
ast.Mult: operator.mul,
|
106
|
+
ast.Div: operator.truediv,
|
107
|
+
ast.Pow: operator.pow,
|
108
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
from langchain_core.tools import Tool
|
2
|
+
|
3
|
+
from lfx.base.langchain_utilities.model import LCToolComponent
|
4
|
+
from lfx.inputs.inputs import IntInput, MultilineInput, SecretStrInput
|
5
|
+
from lfx.schema.data import Data
|
6
|
+
|
7
|
+
|
8
|
+
class GoogleSearchAPIComponent(LCToolComponent):
|
9
|
+
display_name = "Google Search API [DEPRECATED]"
|
10
|
+
description = "Call Google Search API."
|
11
|
+
name = "GoogleSearchAPI"
|
12
|
+
icon = "Google"
|
13
|
+
legacy = True
|
14
|
+
inputs = [
|
15
|
+
SecretStrInput(name="google_api_key", display_name="Google API Key", required=True),
|
16
|
+
SecretStrInput(name="google_cse_id", display_name="Google CSE ID", required=True),
|
17
|
+
MultilineInput(
|
18
|
+
name="input_value",
|
19
|
+
display_name="Input",
|
20
|
+
),
|
21
|
+
IntInput(name="k", display_name="Number of results", value=4, required=True),
|
22
|
+
]
|
23
|
+
|
24
|
+
def run_model(self) -> Data | list[Data]:
|
25
|
+
wrapper = self._build_wrapper()
|
26
|
+
results = wrapper.results(query=self.input_value, num_results=self.k)
|
27
|
+
data = [Data(data=result, text=result["snippet"]) for result in results]
|
28
|
+
self.status = data
|
29
|
+
return data
|
30
|
+
|
31
|
+
def build_tool(self) -> Tool:
|
32
|
+
wrapper = self._build_wrapper()
|
33
|
+
return Tool(
|
34
|
+
name="google_search",
|
35
|
+
description="Search Google for recent results.",
|
36
|
+
func=wrapper.run,
|
37
|
+
)
|
38
|
+
|
39
|
+
def _build_wrapper(self):
|
40
|
+
try:
|
41
|
+
from langchain_google_community import GoogleSearchAPIWrapper
|
42
|
+
except ImportError as e:
|
43
|
+
msg = "Please install langchain-google-community to use GoogleSearchAPIWrapper."
|
44
|
+
raise ImportError(msg) from e
|
45
|
+
return GoogleSearchAPIWrapper(google_api_key=self.google_api_key, google_cse_id=self.google_cse_id, k=self.k)
|
@@ -0,0 +1,115 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
from langchain.tools import StructuredTool
|
4
|
+
from langchain_community.utilities.google_serper import GoogleSerperAPIWrapper
|
5
|
+
from pydantic import BaseModel, Field
|
6
|
+
|
7
|
+
from lfx.base.langchain_utilities.model import LCToolComponent
|
8
|
+
from lfx.field_typing import Tool
|
9
|
+
from lfx.inputs.inputs import (
|
10
|
+
DictInput,
|
11
|
+
DropdownInput,
|
12
|
+
IntInput,
|
13
|
+
MultilineInput,
|
14
|
+
SecretStrInput,
|
15
|
+
)
|
16
|
+
from lfx.schema.data import Data
|
17
|
+
|
18
|
+
|
19
|
+
class QuerySchema(BaseModel):
|
20
|
+
query: str = Field(..., description="The query to search for.")
|
21
|
+
query_type: str = Field(
|
22
|
+
"search",
|
23
|
+
description="The type of search to perform (e.g., 'news' or 'search').",
|
24
|
+
)
|
25
|
+
k: int = Field(4, description="The number of results to return.")
|
26
|
+
query_params: dict[str, Any] = Field({}, description="Additional query parameters to pass to the API.")
|
27
|
+
|
28
|
+
|
29
|
+
class GoogleSerperAPIComponent(LCToolComponent):
|
30
|
+
display_name = "Google Serper API [DEPRECATED]"
|
31
|
+
description = "Call the Serper.dev Google Search API."
|
32
|
+
name = "GoogleSerperAPI"
|
33
|
+
icon = "Google"
|
34
|
+
legacy = True
|
35
|
+
inputs = [
|
36
|
+
SecretStrInput(name="serper_api_key", display_name="Serper API Key", required=True),
|
37
|
+
MultilineInput(
|
38
|
+
name="query",
|
39
|
+
display_name="Query",
|
40
|
+
),
|
41
|
+
IntInput(name="k", display_name="Number of results", value=4, required=True),
|
42
|
+
DropdownInput(
|
43
|
+
name="query_type",
|
44
|
+
display_name="Query Type",
|
45
|
+
required=False,
|
46
|
+
options=["news", "search"],
|
47
|
+
value="search",
|
48
|
+
),
|
49
|
+
DictInput(
|
50
|
+
name="query_params",
|
51
|
+
display_name="Query Params",
|
52
|
+
required=False,
|
53
|
+
value={
|
54
|
+
"gl": "us",
|
55
|
+
"hl": "en",
|
56
|
+
},
|
57
|
+
list=True,
|
58
|
+
),
|
59
|
+
]
|
60
|
+
|
61
|
+
def run_model(self) -> Data | list[Data]:
|
62
|
+
wrapper = self._build_wrapper(self.k, self.query_type, self.query_params)
|
63
|
+
results = wrapper.results(query=self.query)
|
64
|
+
|
65
|
+
# Adjust the extraction based on the `type`
|
66
|
+
if self.query_type == "search":
|
67
|
+
list_results = results.get("organic", [])
|
68
|
+
elif self.query_type == "news":
|
69
|
+
list_results = results.get("news", [])
|
70
|
+
else:
|
71
|
+
list_results = []
|
72
|
+
|
73
|
+
data_list = []
|
74
|
+
for result in list_results:
|
75
|
+
result["text"] = result.pop("snippet", "")
|
76
|
+
data_list.append(Data(data=result))
|
77
|
+
self.status = data_list
|
78
|
+
return data_list
|
79
|
+
|
80
|
+
def build_tool(self) -> Tool:
|
81
|
+
return StructuredTool.from_function(
|
82
|
+
name="google_search",
|
83
|
+
description="Search Google for recent results.",
|
84
|
+
func=self._search,
|
85
|
+
args_schema=self.QuerySchema,
|
86
|
+
)
|
87
|
+
|
88
|
+
def _build_wrapper(
|
89
|
+
self,
|
90
|
+
k: int = 5,
|
91
|
+
query_type: str = "search",
|
92
|
+
query_params: dict | None = None,
|
93
|
+
) -> GoogleSerperAPIWrapper:
|
94
|
+
wrapper_args = {
|
95
|
+
"serper_api_key": self.serper_api_key,
|
96
|
+
"k": k,
|
97
|
+
"type": query_type,
|
98
|
+
}
|
99
|
+
|
100
|
+
# Add query_params if provided
|
101
|
+
if query_params:
|
102
|
+
wrapper_args.update(query_params) # Merge with additional query params
|
103
|
+
|
104
|
+
# Dynamically pass parameters to the wrapper
|
105
|
+
return GoogleSerperAPIWrapper(**wrapper_args)
|
106
|
+
|
107
|
+
def _search(
|
108
|
+
self,
|
109
|
+
query: str,
|
110
|
+
k: int = 5,
|
111
|
+
query_type: str = "search",
|
112
|
+
query_params: dict | None = None,
|
113
|
+
) -> dict:
|
114
|
+
wrapper = self._build_wrapper(k, query_type, query_params)
|
115
|
+
return wrapper.results(query=query)
|
@@ -0,0 +1,327 @@
|
|
1
|
+
import ast
|
2
|
+
import json
|
3
|
+
from typing import Any
|
4
|
+
|
5
|
+
from langchain.agents import Tool
|
6
|
+
from langchain_core.tools import StructuredTool
|
7
|
+
from pydantic.v1 import Field, create_model
|
8
|
+
from pydantic.v1.fields import Undefined
|
9
|
+
from typing_extensions import override
|
10
|
+
|
11
|
+
from lfx.base.langchain_utilities.model import LCToolComponent
|
12
|
+
from lfx.inputs.inputs import BoolInput, DropdownInput, FieldTypes, HandleInput, MessageTextInput, MultilineInput
|
13
|
+
from lfx.io import Output
|
14
|
+
from lfx.log.logger import logger
|
15
|
+
from lfx.schema.data import Data
|
16
|
+
from lfx.schema.dotdict import dotdict
|
17
|
+
|
18
|
+
|
19
|
+
class PythonCodeStructuredTool(LCToolComponent):
|
20
|
+
DEFAULT_KEYS = [
|
21
|
+
"code",
|
22
|
+
"_type",
|
23
|
+
"text_key",
|
24
|
+
"tool_code",
|
25
|
+
"tool_name",
|
26
|
+
"tool_description",
|
27
|
+
"return_direct",
|
28
|
+
"tool_function",
|
29
|
+
"global_variables",
|
30
|
+
"_classes",
|
31
|
+
"_functions",
|
32
|
+
]
|
33
|
+
display_name = "Python Code Structured"
|
34
|
+
description = "structuredtool dataclass code to tool"
|
35
|
+
documentation = "https://python.langchain.com/docs/modules/tools/custom_tools/#structuredtool-dataclass"
|
36
|
+
name = "PythonCodeStructuredTool"
|
37
|
+
icon = "Python"
|
38
|
+
field_order = ["name", "description", "tool_code", "return_direct", "tool_function"]
|
39
|
+
legacy: bool = True
|
40
|
+
|
41
|
+
inputs = [
|
42
|
+
MultilineInput(
|
43
|
+
name="tool_code",
|
44
|
+
display_name="Tool Code",
|
45
|
+
info="Enter the dataclass code.",
|
46
|
+
placeholder="def my_function(args):\n pass",
|
47
|
+
required=True,
|
48
|
+
real_time_refresh=True,
|
49
|
+
refresh_button=True,
|
50
|
+
),
|
51
|
+
MessageTextInput(
|
52
|
+
name="tool_name",
|
53
|
+
display_name="Tool Name",
|
54
|
+
info="Enter the name of the tool.",
|
55
|
+
required=True,
|
56
|
+
),
|
57
|
+
MessageTextInput(
|
58
|
+
name="tool_description",
|
59
|
+
display_name="Description",
|
60
|
+
info="Enter the description of the tool.",
|
61
|
+
required=True,
|
62
|
+
),
|
63
|
+
BoolInput(
|
64
|
+
name="return_direct",
|
65
|
+
display_name="Return Directly",
|
66
|
+
info="Should the tool return the function output directly?",
|
67
|
+
),
|
68
|
+
DropdownInput(
|
69
|
+
name="tool_function",
|
70
|
+
display_name="Tool Function",
|
71
|
+
info="Select the function for additional expressions.",
|
72
|
+
options=[],
|
73
|
+
required=True,
|
74
|
+
real_time_refresh=True,
|
75
|
+
refresh_button=True,
|
76
|
+
),
|
77
|
+
HandleInput(
|
78
|
+
name="global_variables",
|
79
|
+
display_name="Global Variables",
|
80
|
+
info="Enter the global variables or Create Data Component.",
|
81
|
+
input_types=["Data"],
|
82
|
+
field_type=FieldTypes.DICT,
|
83
|
+
is_list=True,
|
84
|
+
),
|
85
|
+
MessageTextInput(name="_classes", display_name="Classes", advanced=True),
|
86
|
+
MessageTextInput(name="_functions", display_name="Functions", advanced=True),
|
87
|
+
]
|
88
|
+
|
89
|
+
outputs = [
|
90
|
+
Output(display_name="Tool", name="result_tool", method="build_tool"),
|
91
|
+
]
|
92
|
+
|
93
|
+
@override
|
94
|
+
async def update_build_config(
|
95
|
+
self, build_config: dotdict, field_value: Any, field_name: str | None = None
|
96
|
+
) -> dotdict:
|
97
|
+
if field_name is None:
|
98
|
+
return build_config
|
99
|
+
|
100
|
+
if field_name not in {"tool_code", "tool_function"}:
|
101
|
+
return build_config
|
102
|
+
|
103
|
+
try:
|
104
|
+
named_functions = {}
|
105
|
+
[classes, functions] = self._parse_code(build_config["tool_code"]["value"])
|
106
|
+
existing_fields = {}
|
107
|
+
if len(build_config) > len(self.DEFAULT_KEYS):
|
108
|
+
for key in build_config.copy():
|
109
|
+
if key not in self.DEFAULT_KEYS:
|
110
|
+
existing_fields[key] = build_config.pop(key)
|
111
|
+
|
112
|
+
names = []
|
113
|
+
for func in functions:
|
114
|
+
named_functions[func["name"]] = func
|
115
|
+
names.append(func["name"])
|
116
|
+
|
117
|
+
for arg in func["args"]:
|
118
|
+
field_name = f"{func['name']}|{arg['name']}"
|
119
|
+
if field_name in existing_fields:
|
120
|
+
build_config[field_name] = existing_fields[field_name]
|
121
|
+
continue
|
122
|
+
|
123
|
+
field = MessageTextInput(
|
124
|
+
display_name=f"{arg['name']}: Description",
|
125
|
+
name=field_name,
|
126
|
+
info=f"Enter the description for {arg['name']}",
|
127
|
+
required=True,
|
128
|
+
)
|
129
|
+
build_config[field_name] = field.to_dict()
|
130
|
+
build_config["_functions"]["value"] = json.dumps(named_functions)
|
131
|
+
build_config["_classes"]["value"] = json.dumps(classes)
|
132
|
+
build_config["tool_function"]["options"] = names
|
133
|
+
except Exception as e: # noqa: BLE001
|
134
|
+
self.status = f"Failed to extract names: {e}"
|
135
|
+
logger.debug(self.status, exc_info=True)
|
136
|
+
build_config["tool_function"]["options"] = ["Failed to parse", str(e)]
|
137
|
+
return build_config
|
138
|
+
|
139
|
+
async def build_tool(self) -> Tool:
|
140
|
+
local_namespace = {} # type: ignore[var-annotated]
|
141
|
+
modules = self._find_imports(self.tool_code)
|
142
|
+
import_code = ""
|
143
|
+
for module in modules["imports"]:
|
144
|
+
import_code += f"global {module}\nimport {module}\n"
|
145
|
+
for from_module in modules["from_imports"]:
|
146
|
+
for alias in from_module.names:
|
147
|
+
import_code += f"global {alias.name}\n"
|
148
|
+
import_code += (
|
149
|
+
f"from {from_module.module} import {', '.join([alias.name for alias in from_module.names])}\n"
|
150
|
+
)
|
151
|
+
exec(import_code, globals())
|
152
|
+
exec(self.tool_code, globals(), local_namespace)
|
153
|
+
|
154
|
+
class PythonCodeToolFunc:
|
155
|
+
params: dict = {}
|
156
|
+
|
157
|
+
def run(**kwargs):
|
158
|
+
for key, arg in kwargs.items():
|
159
|
+
if key not in PythonCodeToolFunc.params:
|
160
|
+
PythonCodeToolFunc.params[key] = arg
|
161
|
+
return local_namespace[self.tool_function](**PythonCodeToolFunc.params)
|
162
|
+
|
163
|
+
globals_ = globals()
|
164
|
+
local = {}
|
165
|
+
local[self.tool_function] = PythonCodeToolFunc
|
166
|
+
globals_.update(local)
|
167
|
+
|
168
|
+
if isinstance(self.global_variables, list):
|
169
|
+
for data in self.global_variables:
|
170
|
+
if isinstance(data, Data):
|
171
|
+
globals_.update(data.data)
|
172
|
+
elif isinstance(self.global_variables, dict):
|
173
|
+
globals_.update(self.global_variables)
|
174
|
+
|
175
|
+
classes = json.loads(self._attributes["_classes"])
|
176
|
+
for class_dict in classes:
|
177
|
+
exec("\n".join(class_dict["code"]), globals_)
|
178
|
+
|
179
|
+
named_functions = json.loads(self._attributes["_functions"])
|
180
|
+
schema_fields = {}
|
181
|
+
|
182
|
+
for attr in self._attributes:
|
183
|
+
if attr in self.DEFAULT_KEYS:
|
184
|
+
continue
|
185
|
+
|
186
|
+
func_name = attr.split("|")[0]
|
187
|
+
field_name = attr.split("|")[1]
|
188
|
+
func_arg = self._find_arg(named_functions, func_name, field_name)
|
189
|
+
if func_arg is None:
|
190
|
+
msg = f"Failed to find arg: {field_name}"
|
191
|
+
raise ValueError(msg)
|
192
|
+
|
193
|
+
field_annotation = func_arg["annotation"]
|
194
|
+
field_description = self._get_value(self._attributes[attr], str)
|
195
|
+
|
196
|
+
if field_annotation:
|
197
|
+
exec(f"temp_annotation_type = {field_annotation}", globals_)
|
198
|
+
schema_annotation = globals_["temp_annotation_type"]
|
199
|
+
else:
|
200
|
+
schema_annotation = Any
|
201
|
+
schema_fields[field_name] = (
|
202
|
+
schema_annotation,
|
203
|
+
Field(
|
204
|
+
default=func_arg.get("default", Undefined),
|
205
|
+
description=field_description,
|
206
|
+
),
|
207
|
+
)
|
208
|
+
|
209
|
+
if "temp_annotation_type" in globals_:
|
210
|
+
globals_.pop("temp_annotation_type")
|
211
|
+
|
212
|
+
python_code_tool_schema = None
|
213
|
+
if schema_fields:
|
214
|
+
python_code_tool_schema = create_model("PythonCodeToolSchema", **schema_fields)
|
215
|
+
|
216
|
+
return StructuredTool.from_function(
|
217
|
+
func=local[self.tool_function].run,
|
218
|
+
args_schema=python_code_tool_schema,
|
219
|
+
name=self.tool_name,
|
220
|
+
description=self.tool_description,
|
221
|
+
return_direct=self.return_direct,
|
222
|
+
)
|
223
|
+
|
224
|
+
async def update_frontend_node(self, new_frontend_node: dict, current_frontend_node: dict):
|
225
|
+
"""This function is called after the code validation is done."""
|
226
|
+
frontend_node = await super().update_frontend_node(new_frontend_node, current_frontend_node)
|
227
|
+
frontend_node["template"] = await self.update_build_config(
|
228
|
+
frontend_node["template"],
|
229
|
+
frontend_node["template"]["tool_code"]["value"],
|
230
|
+
"tool_code",
|
231
|
+
)
|
232
|
+
frontend_node = await super().update_frontend_node(new_frontend_node, current_frontend_node)
|
233
|
+
for key in frontend_node["template"]:
|
234
|
+
if key in self.DEFAULT_KEYS:
|
235
|
+
continue
|
236
|
+
frontend_node["template"] = await self.update_build_config(
|
237
|
+
frontend_node["template"], frontend_node["template"][key]["value"], key
|
238
|
+
)
|
239
|
+
frontend_node = await super().update_frontend_node(new_frontend_node, current_frontend_node)
|
240
|
+
return frontend_node
|
241
|
+
|
242
|
+
def _parse_code(self, code: str) -> tuple[list[dict], list[dict]]:
|
243
|
+
parsed_code = ast.parse(code)
|
244
|
+
lines = code.split("\n")
|
245
|
+
classes = []
|
246
|
+
functions = []
|
247
|
+
for node in parsed_code.body:
|
248
|
+
if isinstance(node, ast.ClassDef):
|
249
|
+
class_lines = lines[node.lineno - 1 : node.end_lineno]
|
250
|
+
class_lines[-1] = class_lines[-1][: node.end_col_offset]
|
251
|
+
class_lines[0] = class_lines[0][node.col_offset :]
|
252
|
+
classes.append(
|
253
|
+
{
|
254
|
+
"name": node.name,
|
255
|
+
"code": class_lines,
|
256
|
+
}
|
257
|
+
)
|
258
|
+
continue
|
259
|
+
|
260
|
+
if not isinstance(node, ast.FunctionDef):
|
261
|
+
continue
|
262
|
+
|
263
|
+
func = {"name": node.name, "args": []}
|
264
|
+
for arg in node.args.args:
|
265
|
+
if arg.lineno != arg.end_lineno:
|
266
|
+
msg = "Multiline arguments are not supported"
|
267
|
+
raise ValueError(msg)
|
268
|
+
|
269
|
+
func_arg = {
|
270
|
+
"name": arg.arg,
|
271
|
+
"annotation": None,
|
272
|
+
}
|
273
|
+
|
274
|
+
for default in node.args.defaults:
|
275
|
+
if (
|
276
|
+
arg.lineno > default.lineno
|
277
|
+
or arg.col_offset > default.col_offset
|
278
|
+
or (
|
279
|
+
arg.end_lineno is not None
|
280
|
+
and default.end_lineno is not None
|
281
|
+
and arg.end_lineno < default.end_lineno
|
282
|
+
)
|
283
|
+
or (
|
284
|
+
arg.end_col_offset is not None
|
285
|
+
and default.end_col_offset is not None
|
286
|
+
and arg.end_col_offset < default.end_col_offset
|
287
|
+
)
|
288
|
+
):
|
289
|
+
continue
|
290
|
+
|
291
|
+
if isinstance(default, ast.Name):
|
292
|
+
func_arg["default"] = default.id
|
293
|
+
elif isinstance(default, ast.Constant):
|
294
|
+
func_arg["default"] = str(default.value) if default.value is not None else None
|
295
|
+
|
296
|
+
if arg.annotation:
|
297
|
+
annotation_line = lines[arg.annotation.lineno - 1]
|
298
|
+
annotation_line = annotation_line[: arg.annotation.end_col_offset]
|
299
|
+
annotation_line = annotation_line[arg.annotation.col_offset :]
|
300
|
+
func_arg["annotation"] = annotation_line
|
301
|
+
if isinstance(func_arg["annotation"], str) and func_arg["annotation"].count("=") > 0:
|
302
|
+
func_arg["annotation"] = "=".join(func_arg["annotation"].split("=")[:-1]).strip()
|
303
|
+
if isinstance(func["args"], list):
|
304
|
+
func["args"].append(func_arg)
|
305
|
+
functions.append(func)
|
306
|
+
|
307
|
+
return classes, functions
|
308
|
+
|
309
|
+
def _find_imports(self, code: str) -> dotdict:
|
310
|
+
imports: list[str] = []
|
311
|
+
from_imports = []
|
312
|
+
parsed_code = ast.parse(code)
|
313
|
+
for node in parsed_code.body:
|
314
|
+
if isinstance(node, ast.Import):
|
315
|
+
imports.extend(alias.name for alias in node.names)
|
316
|
+
elif isinstance(node, ast.ImportFrom):
|
317
|
+
from_imports.append(node)
|
318
|
+
return dotdict({"imports": imports, "from_imports": from_imports})
|
319
|
+
|
320
|
+
def _get_value(self, value: Any, annotation: Any) -> Any:
|
321
|
+
return value if isinstance(value, annotation) else value["value"]
|
322
|
+
|
323
|
+
def _find_arg(self, named_functions: dict, func_name: str, arg_name: str) -> dict | None:
|
324
|
+
for arg in named_functions[func_name]["args"]:
|
325
|
+
if arg["name"] == arg_name:
|
326
|
+
return arg
|
327
|
+
return None
|
@@ -0,0 +1,97 @@
|
|
1
|
+
import importlib
|
2
|
+
|
3
|
+
from langchain.tools import StructuredTool
|
4
|
+
from langchain_core.tools import ToolException
|
5
|
+
from langchain_experimental.utilities import PythonREPL
|
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 StrInput
|
11
|
+
from lfx.log.logger import logger
|
12
|
+
from lfx.schema.data import Data
|
13
|
+
|
14
|
+
|
15
|
+
class PythonREPLToolComponent(LCToolComponent):
|
16
|
+
display_name = "Python REPL [DEPRECATED]"
|
17
|
+
description = "A tool for running Python code in a REPL environment."
|
18
|
+
name = "PythonREPLTool"
|
19
|
+
icon = "Python"
|
20
|
+
legacy = True
|
21
|
+
|
22
|
+
inputs = [
|
23
|
+
StrInput(
|
24
|
+
name="name",
|
25
|
+
display_name="Tool Name",
|
26
|
+
info="The name of the tool.",
|
27
|
+
value="python_repl",
|
28
|
+
),
|
29
|
+
StrInput(
|
30
|
+
name="description",
|
31
|
+
display_name="Tool Description",
|
32
|
+
info="A description of the tool.",
|
33
|
+
value="A Python shell. Use this to execute python commands. "
|
34
|
+
"Input should be a valid python command. "
|
35
|
+
"If you want to see the output of a value, you should print it out with `print(...)`.",
|
36
|
+
),
|
37
|
+
StrInput(
|
38
|
+
name="global_imports",
|
39
|
+
display_name="Global Imports",
|
40
|
+
info="A comma-separated list of modules to import globally, e.g. 'math,numpy'.",
|
41
|
+
value="math",
|
42
|
+
),
|
43
|
+
StrInput(
|
44
|
+
name="code",
|
45
|
+
display_name="Python Code",
|
46
|
+
info="The Python code to execute.",
|
47
|
+
value="print('Hello, World!')",
|
48
|
+
),
|
49
|
+
]
|
50
|
+
|
51
|
+
class PythonREPLSchema(BaseModel):
|
52
|
+
code: str = Field(..., description="The Python code to execute.")
|
53
|
+
|
54
|
+
def get_globals(self, global_imports: str | list[str]) -> dict:
|
55
|
+
global_dict = {}
|
56
|
+
if isinstance(global_imports, str):
|
57
|
+
modules = [module.strip() for module in global_imports.split(",")]
|
58
|
+
elif isinstance(global_imports, list):
|
59
|
+
modules = global_imports
|
60
|
+
else:
|
61
|
+
msg = "global_imports must be either a string or a list"
|
62
|
+
raise TypeError(msg)
|
63
|
+
|
64
|
+
for module in modules:
|
65
|
+
try:
|
66
|
+
imported_module = importlib.import_module(module)
|
67
|
+
global_dict[imported_module.__name__] = imported_module
|
68
|
+
except ImportError as e:
|
69
|
+
msg = f"Could not import module {module}"
|
70
|
+
raise ImportError(msg) from e
|
71
|
+
return global_dict
|
72
|
+
|
73
|
+
def build_tool(self) -> Tool:
|
74
|
+
globals_ = self.get_globals(self.global_imports)
|
75
|
+
python_repl = PythonREPL(_globals=globals_)
|
76
|
+
|
77
|
+
def run_python_code(code: str) -> str:
|
78
|
+
try:
|
79
|
+
return python_repl.run(code)
|
80
|
+
except Exception as e:
|
81
|
+
logger.debug("Error running Python code", exc_info=True)
|
82
|
+
raise ToolException(str(e)) from e
|
83
|
+
|
84
|
+
tool = StructuredTool.from_function(
|
85
|
+
name=self.name,
|
86
|
+
description=self.description,
|
87
|
+
func=run_python_code,
|
88
|
+
args_schema=self.PythonREPLSchema,
|
89
|
+
)
|
90
|
+
|
91
|
+
self.status = f"Python REPL Tool created with global imports: {self.global_imports}"
|
92
|
+
return tool
|
93
|
+
|
94
|
+
def run_model(self) -> list[Data]:
|
95
|
+
tool = self.build_tool()
|
96
|
+
result = tool.run(self.code)
|
97
|
+
return [Data(data={"result": result})]
|