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,231 @@
|
|
1
|
+
from collections.abc import Callable
|
2
|
+
from typing import Any, cast
|
3
|
+
|
4
|
+
import litellm
|
5
|
+
from pydantic import SecretStr
|
6
|
+
|
7
|
+
from lfx.custom.custom_component.component import Component
|
8
|
+
from lfx.inputs.inputs import HandleInput, InputTypes
|
9
|
+
from lfx.io import BoolInput, IntInput, Output
|
10
|
+
from lfx.schema.data import Data
|
11
|
+
from lfx.schema.message import Message
|
12
|
+
from lfx.utils.constants import MESSAGE_SENDER_AI
|
13
|
+
|
14
|
+
|
15
|
+
def _find_api_key(model):
|
16
|
+
"""Attempts to find the API key attribute for a LangChain LLM model instance using partial matching.
|
17
|
+
|
18
|
+
Args:
|
19
|
+
model: LangChain LLM model instance.
|
20
|
+
|
21
|
+
Returns:
|
22
|
+
The API key if found, otherwise None.
|
23
|
+
"""
|
24
|
+
# Define the possible API key attribute patterns
|
25
|
+
key_patterns = ["key", "token"]
|
26
|
+
|
27
|
+
# Iterate over the model attributes
|
28
|
+
for attr in dir(model):
|
29
|
+
attr_lower = attr.lower()
|
30
|
+
|
31
|
+
# Check if the attribute name contains any of the key patterns
|
32
|
+
if any(pattern in attr_lower for pattern in key_patterns):
|
33
|
+
value = getattr(model, attr, None)
|
34
|
+
|
35
|
+
# Check if the value is a non-empty string
|
36
|
+
if isinstance(value, str):
|
37
|
+
return value
|
38
|
+
if isinstance(value, SecretStr):
|
39
|
+
return value.get_secret_value()
|
40
|
+
|
41
|
+
return None
|
42
|
+
|
43
|
+
|
44
|
+
def convert_llm(llm: Any, excluded_keys=None):
|
45
|
+
"""Converts a LangChain LLM object to a CrewAI-compatible LLM object.
|
46
|
+
|
47
|
+
Args:
|
48
|
+
llm: A LangChain LLM object.
|
49
|
+
excluded_keys: A set of keys to exclude from the conversion.
|
50
|
+
|
51
|
+
Returns:
|
52
|
+
A CrewAI-compatible LLM object
|
53
|
+
"""
|
54
|
+
try:
|
55
|
+
from crewai import LLM
|
56
|
+
except ImportError as e:
|
57
|
+
msg = "CrewAI is not installed. Please install it with `uv pip install crewai`."
|
58
|
+
raise ImportError(msg) from e
|
59
|
+
|
60
|
+
if not llm:
|
61
|
+
return None
|
62
|
+
|
63
|
+
# Check if this is already an LLM object
|
64
|
+
if isinstance(llm, LLM):
|
65
|
+
return llm
|
66
|
+
|
67
|
+
# Check if we should use model_name model, or something else
|
68
|
+
if hasattr(llm, "model_name") and llm.model_name:
|
69
|
+
model_name = llm.model_name
|
70
|
+
elif hasattr(llm, "model") and llm.model:
|
71
|
+
model_name = llm.model
|
72
|
+
elif hasattr(llm, "deployment_name") and llm.deployment_name:
|
73
|
+
model_name = llm.deployment_name
|
74
|
+
else:
|
75
|
+
msg = "Could not find model name in the LLM object"
|
76
|
+
raise ValueError(msg)
|
77
|
+
|
78
|
+
# Normalize to the LLM model name
|
79
|
+
# Remove langchain_ prefix if present
|
80
|
+
provider = llm.get_lc_namespace()[0]
|
81
|
+
api_base = None
|
82
|
+
if provider.startswith("langchain_"):
|
83
|
+
provider = provider[10:]
|
84
|
+
model_name = f"{provider}/{model_name}"
|
85
|
+
elif hasattr(llm, "azure_endpoint"):
|
86
|
+
api_base = llm.azure_endpoint
|
87
|
+
model_name = f"azure/{model_name}"
|
88
|
+
|
89
|
+
# Retrieve the API Key from the LLM
|
90
|
+
if excluded_keys is None:
|
91
|
+
excluded_keys = {"model", "model_name", "_type", "api_key", "azure_deployment"}
|
92
|
+
|
93
|
+
# Find the API key in the LLM
|
94
|
+
api_key = _find_api_key(llm)
|
95
|
+
|
96
|
+
# Convert Langchain LLM to CrewAI-compatible LLM object
|
97
|
+
return LLM(
|
98
|
+
model=model_name,
|
99
|
+
api_key=api_key,
|
100
|
+
api_base=api_base,
|
101
|
+
**{k: v for k, v in llm.dict().items() if k not in excluded_keys},
|
102
|
+
)
|
103
|
+
|
104
|
+
|
105
|
+
def convert_tools(tools):
|
106
|
+
"""Converts LangChain tools to CrewAI-compatible tools.
|
107
|
+
|
108
|
+
Args:
|
109
|
+
tools: A LangChain tools list.
|
110
|
+
|
111
|
+
Returns:
|
112
|
+
A CrewAI-compatible tools list.
|
113
|
+
"""
|
114
|
+
try:
|
115
|
+
from crewai.tools.base_tool import Tool
|
116
|
+
except ImportError as e:
|
117
|
+
msg = "CrewAI is not installed. Please install it with `uv pip install crewai`."
|
118
|
+
raise ImportError(msg) from e
|
119
|
+
|
120
|
+
if not tools:
|
121
|
+
return []
|
122
|
+
|
123
|
+
return [Tool.from_langchain(tool) for tool in tools]
|
124
|
+
|
125
|
+
|
126
|
+
class BaseCrewComponent(Component):
|
127
|
+
description: str = (
|
128
|
+
"Represents a group of agents, defining how they should collaborate and the tasks they should perform."
|
129
|
+
)
|
130
|
+
icon = "CrewAI"
|
131
|
+
|
132
|
+
_base_inputs: list[InputTypes] = [
|
133
|
+
IntInput(name="verbose", display_name="Verbose", value=0, advanced=True),
|
134
|
+
BoolInput(name="memory", display_name="Memory", value=False, advanced=True),
|
135
|
+
BoolInput(name="use_cache", display_name="Cache", value=True, advanced=True),
|
136
|
+
IntInput(name="max_rpm", display_name="Max RPM", value=100, advanced=True),
|
137
|
+
BoolInput(name="share_crew", display_name="Share Crew", value=False, advanced=True),
|
138
|
+
HandleInput(
|
139
|
+
name="function_calling_llm",
|
140
|
+
display_name="Function Calling LLM",
|
141
|
+
input_types=["LanguageModel"],
|
142
|
+
info="Turns the ReAct CrewAI agent into a function-calling agent",
|
143
|
+
required=False,
|
144
|
+
advanced=True,
|
145
|
+
),
|
146
|
+
]
|
147
|
+
|
148
|
+
outputs = [
|
149
|
+
Output(display_name="Output", name="output", method="build_output"),
|
150
|
+
]
|
151
|
+
|
152
|
+
# Model properties to exclude when creating a CrewAI LLM object
|
153
|
+
manager_llm = None
|
154
|
+
|
155
|
+
def task_is_valid(self, task_data: Data, crew_type) -> bool:
|
156
|
+
return "task_type" in task_data and task_data.task_type == crew_type
|
157
|
+
|
158
|
+
def get_tasks_and_agents(self, agents_list=None) -> tuple[list, list]:
|
159
|
+
# Allow passing a custom list of agents
|
160
|
+
if not agents_list:
|
161
|
+
agents_list = self.agents or []
|
162
|
+
|
163
|
+
# Set all the agents llm attribute to the crewai llm
|
164
|
+
for agent in agents_list:
|
165
|
+
# Convert Agent LLM and Tools to proper format
|
166
|
+
agent.llm = convert_llm(agent.llm)
|
167
|
+
agent.tools = convert_tools(agent.tools)
|
168
|
+
|
169
|
+
return self.tasks, agents_list
|
170
|
+
|
171
|
+
def get_manager_llm(self):
|
172
|
+
if not self.manager_llm:
|
173
|
+
return None
|
174
|
+
|
175
|
+
self.manager_llm = convert_llm(self.manager_llm)
|
176
|
+
|
177
|
+
return self.manager_llm
|
178
|
+
|
179
|
+
def build_crew(self):
|
180
|
+
msg = "build_crew must be implemented in subclasses"
|
181
|
+
raise NotImplementedError(msg)
|
182
|
+
|
183
|
+
def get_task_callback(
|
184
|
+
self,
|
185
|
+
) -> Callable:
|
186
|
+
try:
|
187
|
+
from crewai.task import TaskOutput
|
188
|
+
except ImportError as e:
|
189
|
+
msg = "CrewAI is not installed. Please install it with `uv pip install crewai`."
|
190
|
+
raise ImportError(msg) from e
|
191
|
+
|
192
|
+
def task_callback(task_output: TaskOutput) -> None:
|
193
|
+
vertex_id = self._vertex.id if self._vertex else self.display_name or self.__class__.__name__
|
194
|
+
self.log(task_output.model_dump(), name=f"Task (Agent: {task_output.agent}) - {vertex_id}")
|
195
|
+
|
196
|
+
return task_callback
|
197
|
+
|
198
|
+
def get_step_callback(
|
199
|
+
self,
|
200
|
+
) -> Callable:
|
201
|
+
try:
|
202
|
+
from langchain_core.agents import AgentFinish
|
203
|
+
except ImportError as e:
|
204
|
+
msg = "langchain_core is not installed. Please install it with `uv pip install langchain-core`."
|
205
|
+
raise ImportError(msg) from e
|
206
|
+
|
207
|
+
def step_callback(agent_output) -> None:
|
208
|
+
id_ = self._vertex.id if self._vertex else self.display_name
|
209
|
+
if isinstance(agent_output, AgentFinish):
|
210
|
+
messages = agent_output.messages
|
211
|
+
self.log(cast("dict", messages[0].to_json()), name=f"Finish (Agent: {id_})")
|
212
|
+
elif isinstance(agent_output, list):
|
213
|
+
messages_dict_ = {f"Action {i}": action.messages for i, (action, _) in enumerate(agent_output)}
|
214
|
+
# Serialize the messages with to_json() to avoid issues with circular references
|
215
|
+
serializable_dict = {k: [m.to_json() for m in v] for k, v in messages_dict_.items()}
|
216
|
+
messages_dict = {k: v[0] if len(v) == 1 else v for k, v in serializable_dict.items()}
|
217
|
+
self.log(messages_dict, name=f"Step (Agent: {id_})")
|
218
|
+
|
219
|
+
return step_callback
|
220
|
+
|
221
|
+
async def build_output(self) -> Message:
|
222
|
+
try:
|
223
|
+
crew = self.build_crew()
|
224
|
+
result = await crew.kickoff_async()
|
225
|
+
message = Message(text=result.raw, sender=MESSAGE_SENDER_AI)
|
226
|
+
except litellm.exceptions.BadRequestError as e:
|
227
|
+
raise ValueError(e) from e
|
228
|
+
|
229
|
+
self.status = message
|
230
|
+
|
231
|
+
return message
|
@@ -0,0 +1,23 @@
|
|
1
|
+
XML_AGENT_PROMPT = """You are a helpful assistant. Help the user answer any questions.
|
2
|
+
|
3
|
+
You have access to the following tools:
|
4
|
+
|
5
|
+
{tools}
|
6
|
+
|
7
|
+
In order to use a tool, you can use <tool></tool> and <tool_input></tool_input> tags. You will then get back a response in the form <observation></observation>
|
8
|
+
For example, if you have a tool called 'search' that could run a google search, in order to search for the weather in SF you would respond:
|
9
|
+
|
10
|
+
<tool>search</tool><tool_input>weather in SF</tool_input>
|
11
|
+
<observation>64 degrees</observation>
|
12
|
+
|
13
|
+
When you are done, respond with a final answer between <final_answer></final_answer>. For example:
|
14
|
+
|
15
|
+
<final_answer>The weather in SF is 64 degrees</final_answer>
|
16
|
+
|
17
|
+
Begin!
|
18
|
+
|
19
|
+
Previous Conversation:
|
20
|
+
{chat_history}
|
21
|
+
|
22
|
+
Question: {input}
|
23
|
+
{agent_scratchpad}""" # noqa: E501
|
@@ -0,0 +1,15 @@
|
|
1
|
+
from anthropic import BadRequestError as AnthropicBadRequestError
|
2
|
+
from cohere import BadRequestError as CohereBadRequestError
|
3
|
+
from httpx import HTTPStatusError
|
4
|
+
|
5
|
+
from lfx.schema.message import Message
|
6
|
+
|
7
|
+
|
8
|
+
class CustomBadRequestError(AnthropicBadRequestError, CohereBadRequestError, HTTPStatusError):
|
9
|
+
def __init__(self, agent_message: Message | None, message: str):
|
10
|
+
super().__init__(message)
|
11
|
+
self.message = message
|
12
|
+
self.agent_message = agent_message
|
13
|
+
|
14
|
+
def __str__(self):
|
15
|
+
return f"{self.message}"
|
@@ -0,0 +1,346 @@
|
|
1
|
+
# Add helper functions for each event type
|
2
|
+
from collections.abc import AsyncIterator
|
3
|
+
from time import perf_counter
|
4
|
+
from typing import Any, Protocol
|
5
|
+
|
6
|
+
from langchain_core.agents import AgentFinish
|
7
|
+
from langchain_core.messages import AIMessageChunk, BaseMessage
|
8
|
+
from typing_extensions import TypedDict
|
9
|
+
|
10
|
+
from lfx.schema.content_block import ContentBlock
|
11
|
+
from lfx.schema.content_types import TextContent, ToolContent
|
12
|
+
from lfx.schema.log import SendMessageFunctionType
|
13
|
+
from lfx.schema.message import Message
|
14
|
+
|
15
|
+
|
16
|
+
class ExceptionWithMessageError(Exception):
|
17
|
+
def __init__(self, agent_message: Message, message: str):
|
18
|
+
self.agent_message = agent_message
|
19
|
+
super().__init__(message)
|
20
|
+
self.message = message
|
21
|
+
|
22
|
+
def __str__(self):
|
23
|
+
return (
|
24
|
+
f"Agent message: {self.agent_message.text} \nError: {self.message}."
|
25
|
+
if self.agent_message.error or self.agent_message.text
|
26
|
+
else f"{self.message}."
|
27
|
+
)
|
28
|
+
|
29
|
+
|
30
|
+
class InputDict(TypedDict):
|
31
|
+
input: str
|
32
|
+
chat_history: list[BaseMessage]
|
33
|
+
|
34
|
+
|
35
|
+
def _build_agent_input_text_content(agent_input_dict: InputDict) -> str:
|
36
|
+
final_input = agent_input_dict.get("input", "")
|
37
|
+
return f"**Input**: {final_input}"
|
38
|
+
|
39
|
+
|
40
|
+
def _calculate_duration(start_time: float) -> int:
|
41
|
+
"""Calculate duration in milliseconds from start time to now."""
|
42
|
+
# Handle the calculation
|
43
|
+
current_time = perf_counter()
|
44
|
+
if isinstance(start_time, int):
|
45
|
+
# If we got an integer, treat it as milliseconds
|
46
|
+
duration = current_time - (start_time / 1000)
|
47
|
+
result = int(duration * 1000)
|
48
|
+
else:
|
49
|
+
# If we got a float, treat it as perf_counter time
|
50
|
+
result = int((current_time - start_time) * 1000)
|
51
|
+
|
52
|
+
return result
|
53
|
+
|
54
|
+
|
55
|
+
async def handle_on_chain_start(
|
56
|
+
event: dict[str, Any], agent_message: Message, send_message_method: SendMessageFunctionType, start_time: float
|
57
|
+
) -> tuple[Message, float]:
|
58
|
+
# Create content blocks if they don't exist
|
59
|
+
if not agent_message.content_blocks:
|
60
|
+
agent_message.content_blocks = [ContentBlock(title="Agent Steps", contents=[])]
|
61
|
+
|
62
|
+
if event["data"].get("input"):
|
63
|
+
input_data = event["data"].get("input")
|
64
|
+
if isinstance(input_data, dict) and "input" in input_data:
|
65
|
+
# Cast the input_data to InputDict
|
66
|
+
input_message = input_data.get("input", "")
|
67
|
+
if isinstance(input_message, BaseMessage):
|
68
|
+
input_message = input_message.text()
|
69
|
+
elif not isinstance(input_message, str):
|
70
|
+
input_message = str(input_message)
|
71
|
+
|
72
|
+
input_dict: InputDict = {
|
73
|
+
"input": input_message,
|
74
|
+
"chat_history": input_data.get("chat_history", []),
|
75
|
+
}
|
76
|
+
text_content = TextContent(
|
77
|
+
type="text",
|
78
|
+
text=_build_agent_input_text_content(input_dict),
|
79
|
+
duration=_calculate_duration(start_time),
|
80
|
+
header={"title": "Input", "icon": "MessageSquare"},
|
81
|
+
)
|
82
|
+
agent_message.content_blocks[0].contents.append(text_content)
|
83
|
+
agent_message = await send_message_method(message=agent_message)
|
84
|
+
start_time = perf_counter()
|
85
|
+
return agent_message, start_time
|
86
|
+
|
87
|
+
|
88
|
+
def _extract_output_text(output: str | list) -> str:
|
89
|
+
if isinstance(output, str):
|
90
|
+
return output
|
91
|
+
if isinstance(output, list) and len(output) == 0:
|
92
|
+
return ""
|
93
|
+
if not isinstance(output, list) or len(output) != 1:
|
94
|
+
msg = f"Output is not a string or list of dictionaries with 'text' key: {output}"
|
95
|
+
raise TypeError(msg)
|
96
|
+
|
97
|
+
item = output[0]
|
98
|
+
if isinstance(item, str):
|
99
|
+
return item
|
100
|
+
if isinstance(item, dict):
|
101
|
+
if "text" in item:
|
102
|
+
return item["text"]
|
103
|
+
# If the item's type is "tool_use", return an empty string.
|
104
|
+
# This likely indicates that "tool_use" outputs are not meant to be displayed as text.
|
105
|
+
if item.get("type") == "tool_use":
|
106
|
+
return ""
|
107
|
+
if isinstance(item, dict):
|
108
|
+
if "text" in item:
|
109
|
+
return item["text"]
|
110
|
+
# If the item's type is "tool_use", return an empty string.
|
111
|
+
# This likely indicates that "tool_use" outputs are not meant to be displayed as text.
|
112
|
+
if item.get("type") == "tool_use":
|
113
|
+
return ""
|
114
|
+
# This is a workaround to deal with function calling by Anthropic
|
115
|
+
# since the same data comes in the tool_output we don't need to stream it here
|
116
|
+
# although it would be nice to
|
117
|
+
if "partial_json" in item:
|
118
|
+
return ""
|
119
|
+
msg = f"Output is not a string or list of dictionaries with 'text' key: {output}"
|
120
|
+
raise TypeError(msg)
|
121
|
+
|
122
|
+
|
123
|
+
async def handle_on_chain_end(
|
124
|
+
event: dict[str, Any], agent_message: Message, send_message_method: SendMessageFunctionType, start_time: float
|
125
|
+
) -> tuple[Message, float]:
|
126
|
+
data_output = event["data"].get("output")
|
127
|
+
if data_output and isinstance(data_output, AgentFinish) and data_output.return_values.get("output"):
|
128
|
+
output = data_output.return_values.get("output")
|
129
|
+
|
130
|
+
agent_message.text = _extract_output_text(output)
|
131
|
+
agent_message.properties.state = "complete"
|
132
|
+
# Add duration to the last content if it exists
|
133
|
+
if agent_message.content_blocks:
|
134
|
+
duration = _calculate_duration(start_time)
|
135
|
+
text_content = TextContent(
|
136
|
+
type="text",
|
137
|
+
text=agent_message.text,
|
138
|
+
duration=duration,
|
139
|
+
header={"title": "Output", "icon": "MessageSquare"},
|
140
|
+
)
|
141
|
+
agent_message.content_blocks[0].contents.append(text_content)
|
142
|
+
agent_message = await send_message_method(message=agent_message)
|
143
|
+
start_time = perf_counter()
|
144
|
+
return agent_message, start_time
|
145
|
+
|
146
|
+
|
147
|
+
async def handle_on_tool_start(
|
148
|
+
event: dict[str, Any],
|
149
|
+
agent_message: Message,
|
150
|
+
tool_blocks_map: dict[str, ToolContent],
|
151
|
+
send_message_method: SendMessageFunctionType,
|
152
|
+
start_time: float,
|
153
|
+
) -> tuple[Message, float]:
|
154
|
+
tool_name = event["name"]
|
155
|
+
tool_input = event["data"].get("input")
|
156
|
+
run_id = event.get("run_id", "")
|
157
|
+
tool_key = f"{tool_name}_{run_id}"
|
158
|
+
|
159
|
+
# Create content blocks if they don't exist
|
160
|
+
if not agent_message.content_blocks:
|
161
|
+
agent_message.content_blocks = [ContentBlock(title="Agent Steps", contents=[])]
|
162
|
+
|
163
|
+
duration = _calculate_duration(start_time)
|
164
|
+
new_start_time = perf_counter() # Get new start time for next operation
|
165
|
+
|
166
|
+
# Create new tool content with the input exactly as received
|
167
|
+
tool_content = ToolContent(
|
168
|
+
type="tool_use",
|
169
|
+
name=tool_name,
|
170
|
+
tool_input=tool_input,
|
171
|
+
output=None,
|
172
|
+
error=None,
|
173
|
+
header={"title": f"Accessing **{tool_name}**", "icon": "Hammer"},
|
174
|
+
duration=duration, # Store the actual duration
|
175
|
+
)
|
176
|
+
|
177
|
+
# Store in map and append to message
|
178
|
+
tool_blocks_map[tool_key] = tool_content
|
179
|
+
agent_message.content_blocks[0].contents.append(tool_content)
|
180
|
+
|
181
|
+
agent_message = await send_message_method(message=agent_message)
|
182
|
+
if agent_message.content_blocks and agent_message.content_blocks[0].contents:
|
183
|
+
tool_blocks_map[tool_key] = agent_message.content_blocks[0].contents[-1]
|
184
|
+
return agent_message, new_start_time
|
185
|
+
|
186
|
+
|
187
|
+
async def handle_on_tool_end(
|
188
|
+
event: dict[str, Any],
|
189
|
+
agent_message: Message,
|
190
|
+
tool_blocks_map: dict[str, ToolContent],
|
191
|
+
send_message_method: SendMessageFunctionType,
|
192
|
+
start_time: float,
|
193
|
+
) -> tuple[Message, float]:
|
194
|
+
run_id = event.get("run_id", "")
|
195
|
+
tool_name = event.get("name", "")
|
196
|
+
tool_key = f"{tool_name}_{run_id}"
|
197
|
+
tool_content = tool_blocks_map.get(tool_key)
|
198
|
+
|
199
|
+
if tool_content and isinstance(tool_content, ToolContent):
|
200
|
+
# Call send_message_method first to get the updated message structure
|
201
|
+
agent_message = await send_message_method(message=agent_message)
|
202
|
+
new_start_time = perf_counter()
|
203
|
+
|
204
|
+
# Now find and update the tool content in the current message
|
205
|
+
duration = _calculate_duration(start_time)
|
206
|
+
tool_key = f"{tool_name}_{run_id}"
|
207
|
+
|
208
|
+
# Find the corresponding tool content in the updated message
|
209
|
+
updated_tool_content = None
|
210
|
+
if agent_message.content_blocks and agent_message.content_blocks[0].contents:
|
211
|
+
for content in agent_message.content_blocks[0].contents:
|
212
|
+
if (
|
213
|
+
isinstance(content, ToolContent)
|
214
|
+
and content.name == tool_name
|
215
|
+
and content.tool_input == tool_content.tool_input
|
216
|
+
):
|
217
|
+
updated_tool_content = content
|
218
|
+
break
|
219
|
+
|
220
|
+
# Update the tool content that's actually in the message
|
221
|
+
if updated_tool_content:
|
222
|
+
updated_tool_content.duration = duration
|
223
|
+
updated_tool_content.header = {"title": f"Executed **{updated_tool_content.name}**", "icon": "Hammer"}
|
224
|
+
updated_tool_content.output = event["data"].get("output")
|
225
|
+
|
226
|
+
# Update the map reference
|
227
|
+
tool_blocks_map[tool_key] = updated_tool_content
|
228
|
+
|
229
|
+
return agent_message, new_start_time
|
230
|
+
return agent_message, start_time
|
231
|
+
|
232
|
+
|
233
|
+
async def handle_on_tool_error(
|
234
|
+
event: dict[str, Any],
|
235
|
+
agent_message: Message,
|
236
|
+
tool_blocks_map: dict[str, ToolContent],
|
237
|
+
send_message_method: SendMessageFunctionType,
|
238
|
+
start_time: float,
|
239
|
+
) -> tuple[Message, float]:
|
240
|
+
run_id = event.get("run_id", "")
|
241
|
+
tool_name = event.get("name", "")
|
242
|
+
tool_key = f"{tool_name}_{run_id}"
|
243
|
+
tool_content = tool_blocks_map.get(tool_key)
|
244
|
+
|
245
|
+
if tool_content and isinstance(tool_content, ToolContent):
|
246
|
+
tool_content.error = event["data"].get("error", "Unknown error")
|
247
|
+
tool_content.duration = _calculate_duration(start_time)
|
248
|
+
tool_content.header = {"title": f"Error using **{tool_content.name}**", "icon": "Hammer"}
|
249
|
+
agent_message = await send_message_method(message=agent_message)
|
250
|
+
start_time = perf_counter()
|
251
|
+
return agent_message, start_time
|
252
|
+
|
253
|
+
|
254
|
+
async def handle_on_chain_stream(
|
255
|
+
event: dict[str, Any],
|
256
|
+
agent_message: Message,
|
257
|
+
send_message_method: SendMessageFunctionType,
|
258
|
+
start_time: float,
|
259
|
+
) -> tuple[Message, float]:
|
260
|
+
data_chunk = event["data"].get("chunk", {})
|
261
|
+
if isinstance(data_chunk, dict) and data_chunk.get("output"):
|
262
|
+
output = data_chunk.get("output")
|
263
|
+
if output and isinstance(output, str | list):
|
264
|
+
agent_message.text = _extract_output_text(output)
|
265
|
+
agent_message.properties.state = "complete"
|
266
|
+
agent_message = await send_message_method(message=agent_message)
|
267
|
+
start_time = perf_counter()
|
268
|
+
elif isinstance(data_chunk, AIMessageChunk):
|
269
|
+
output_text = _extract_output_text(data_chunk.content)
|
270
|
+
if output_text and isinstance(agent_message.text, str):
|
271
|
+
agent_message.text += output_text
|
272
|
+
agent_message.properties.state = "partial"
|
273
|
+
agent_message = await send_message_method(message=agent_message)
|
274
|
+
if not agent_message.text:
|
275
|
+
start_time = perf_counter()
|
276
|
+
return agent_message, start_time
|
277
|
+
|
278
|
+
|
279
|
+
class ToolEventHandler(Protocol):
|
280
|
+
async def __call__(
|
281
|
+
self,
|
282
|
+
event: dict[str, Any],
|
283
|
+
agent_message: Message,
|
284
|
+
tool_blocks_map: dict[str, ContentBlock],
|
285
|
+
send_message_method: SendMessageFunctionType,
|
286
|
+
start_time: float,
|
287
|
+
) -> tuple[Message, float]: ...
|
288
|
+
|
289
|
+
|
290
|
+
class ChainEventHandler(Protocol):
|
291
|
+
async def __call__(
|
292
|
+
self,
|
293
|
+
event: dict[str, Any],
|
294
|
+
agent_message: Message,
|
295
|
+
send_message_method: SendMessageFunctionType,
|
296
|
+
start_time: float,
|
297
|
+
) -> tuple[Message, float]: ...
|
298
|
+
|
299
|
+
|
300
|
+
EventHandler = ToolEventHandler | ChainEventHandler
|
301
|
+
|
302
|
+
# Define separate mappings of event types to their respective handler functions
|
303
|
+
CHAIN_EVENT_HANDLERS: dict[str, ChainEventHandler] = {
|
304
|
+
"on_chain_start": handle_on_chain_start,
|
305
|
+
"on_chain_end": handle_on_chain_end,
|
306
|
+
"on_chain_stream": handle_on_chain_stream,
|
307
|
+
"on_chat_model_stream": handle_on_chain_stream,
|
308
|
+
}
|
309
|
+
|
310
|
+
TOOL_EVENT_HANDLERS: dict[str, ToolEventHandler] = {
|
311
|
+
"on_tool_start": handle_on_tool_start,
|
312
|
+
"on_tool_end": handle_on_tool_end,
|
313
|
+
"on_tool_error": handle_on_tool_error,
|
314
|
+
}
|
315
|
+
|
316
|
+
|
317
|
+
async def process_agent_events(
|
318
|
+
agent_executor: AsyncIterator[dict[str, Any]],
|
319
|
+
agent_message: Message,
|
320
|
+
send_message_method: SendMessageFunctionType,
|
321
|
+
) -> Message:
|
322
|
+
"""Process agent events and return the final output."""
|
323
|
+
if isinstance(agent_message.properties, dict):
|
324
|
+
agent_message.properties.update({"icon": "Bot", "state": "partial"})
|
325
|
+
else:
|
326
|
+
agent_message.properties.icon = "Bot"
|
327
|
+
agent_message.properties.state = "partial"
|
328
|
+
# Store the initial message
|
329
|
+
agent_message = await send_message_method(message=agent_message)
|
330
|
+
try:
|
331
|
+
# Create a mapping of run_ids to tool contents
|
332
|
+
tool_blocks_map: dict[str, ToolContent] = {}
|
333
|
+
start_time = perf_counter()
|
334
|
+
async for event in agent_executor:
|
335
|
+
if event["event"] in TOOL_EVENT_HANDLERS:
|
336
|
+
tool_handler = TOOL_EVENT_HANDLERS[event["event"]]
|
337
|
+
agent_message, start_time = await tool_handler(
|
338
|
+
event, agent_message, tool_blocks_map, send_message_method, start_time
|
339
|
+
)
|
340
|
+
elif event["event"] in CHAIN_EVENT_HANDLERS:
|
341
|
+
chain_handler = CHAIN_EVENT_HANDLERS[event["event"]]
|
342
|
+
agent_message, start_time = await chain_handler(event, agent_message, send_message_method, start_time)
|
343
|
+
agent_message.properties.state = "complete"
|
344
|
+
except Exception as e:
|
345
|
+
raise ExceptionWithMessageError(agent_message, str(e)) from e
|
346
|
+
return await Message.create(**agent_message.model_dump())
|