lfx-nightly 0.2.0.dev25__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of lfx-nightly might be problematic. Click here for more details.
- lfx/__init__.py +0 -0
- lfx/__main__.py +25 -0
- lfx/_assets/component_index.json +1 -0
- lfx/base/__init__.py +0 -0
- lfx/base/agents/__init__.py +0 -0
- lfx/base/agents/agent.py +375 -0
- lfx/base/agents/altk_base_agent.py +380 -0
- lfx/base/agents/altk_tool_wrappers.py +565 -0
- lfx/base/agents/callback.py +130 -0
- lfx/base/agents/context.py +109 -0
- lfx/base/agents/crewai/__init__.py +0 -0
- lfx/base/agents/crewai/crew.py +231 -0
- lfx/base/agents/crewai/tasks.py +12 -0
- lfx/base/agents/default_prompts.py +23 -0
- lfx/base/agents/errors.py +15 -0
- lfx/base/agents/events.py +430 -0
- lfx/base/agents/utils.py +237 -0
- lfx/base/astra_assistants/__init__.py +0 -0
- lfx/base/astra_assistants/util.py +171 -0
- lfx/base/chains/__init__.py +0 -0
- lfx/base/chains/model.py +19 -0
- lfx/base/composio/__init__.py +0 -0
- lfx/base/composio/composio_base.py +2584 -0
- lfx/base/compressors/__init__.py +0 -0
- lfx/base/compressors/model.py +60 -0
- lfx/base/constants.py +46 -0
- lfx/base/curl/__init__.py +0 -0
- lfx/base/curl/parse.py +188 -0
- lfx/base/data/__init__.py +5 -0
- lfx/base/data/base_file.py +810 -0
- lfx/base/data/docling_utils.py +338 -0
- lfx/base/data/storage_utils.py +192 -0
- lfx/base/data/utils.py +362 -0
- lfx/base/datastax/__init__.py +5 -0
- lfx/base/datastax/astradb_base.py +896 -0
- lfx/base/document_transformers/__init__.py +0 -0
- lfx/base/document_transformers/model.py +43 -0
- lfx/base/embeddings/__init__.py +0 -0
- lfx/base/embeddings/aiml_embeddings.py +62 -0
- lfx/base/embeddings/embeddings_class.py +113 -0
- lfx/base/embeddings/model.py +26 -0
- lfx/base/flow_processing/__init__.py +0 -0
- lfx/base/flow_processing/utils.py +86 -0
- lfx/base/huggingface/__init__.py +0 -0
- lfx/base/huggingface/model_bridge.py +133 -0
- lfx/base/io/__init__.py +0 -0
- lfx/base/io/chat.py +21 -0
- lfx/base/io/text.py +22 -0
- lfx/base/knowledge_bases/__init__.py +3 -0
- lfx/base/knowledge_bases/knowledge_base_utils.py +137 -0
- lfx/base/langchain_utilities/__init__.py +0 -0
- lfx/base/langchain_utilities/model.py +35 -0
- lfx/base/langchain_utilities/spider_constants.py +1 -0
- lfx/base/langwatch/__init__.py +0 -0
- lfx/base/langwatch/utils.py +18 -0
- lfx/base/mcp/__init__.py +0 -0
- lfx/base/mcp/constants.py +2 -0
- lfx/base/mcp/util.py +1659 -0
- lfx/base/memory/__init__.py +0 -0
- lfx/base/memory/memory.py +49 -0
- lfx/base/memory/model.py +38 -0
- lfx/base/models/__init__.py +3 -0
- lfx/base/models/aiml_constants.py +51 -0
- lfx/base/models/anthropic_constants.py +51 -0
- lfx/base/models/aws_constants.py +151 -0
- lfx/base/models/chat_result.py +76 -0
- lfx/base/models/cometapi_constants.py +54 -0
- lfx/base/models/google_generative_ai_constants.py +70 -0
- lfx/base/models/google_generative_ai_model.py +38 -0
- lfx/base/models/groq_constants.py +150 -0
- lfx/base/models/groq_model_discovery.py +265 -0
- lfx/base/models/model.py +375 -0
- lfx/base/models/model_input_constants.py +378 -0
- lfx/base/models/model_metadata.py +41 -0
- lfx/base/models/model_utils.py +108 -0
- lfx/base/models/novita_constants.py +35 -0
- lfx/base/models/ollama_constants.py +52 -0
- lfx/base/models/openai_constants.py +129 -0
- lfx/base/models/sambanova_constants.py +18 -0
- lfx/base/models/watsonx_constants.py +36 -0
- lfx/base/processing/__init__.py +0 -0
- lfx/base/prompts/__init__.py +0 -0
- lfx/base/prompts/api_utils.py +224 -0
- lfx/base/prompts/utils.py +61 -0
- lfx/base/textsplitters/__init__.py +0 -0
- lfx/base/textsplitters/model.py +28 -0
- lfx/base/tools/__init__.py +0 -0
- lfx/base/tools/base.py +26 -0
- lfx/base/tools/component_tool.py +325 -0
- lfx/base/tools/constants.py +49 -0
- lfx/base/tools/flow_tool.py +132 -0
- lfx/base/tools/run_flow.py +698 -0
- lfx/base/vectorstores/__init__.py +0 -0
- lfx/base/vectorstores/model.py +193 -0
- lfx/base/vectorstores/utils.py +22 -0
- lfx/base/vectorstores/vector_store_connection_decorator.py +52 -0
- lfx/cli/__init__.py +5 -0
- lfx/cli/commands.py +327 -0
- lfx/cli/common.py +650 -0
- lfx/cli/run.py +506 -0
- lfx/cli/script_loader.py +289 -0
- lfx/cli/serve_app.py +546 -0
- lfx/cli/validation.py +69 -0
- lfx/components/FAISS/__init__.py +34 -0
- lfx/components/FAISS/faiss.py +111 -0
- lfx/components/Notion/__init__.py +19 -0
- lfx/components/Notion/add_content_to_page.py +269 -0
- lfx/components/Notion/create_page.py +94 -0
- lfx/components/Notion/list_database_properties.py +68 -0
- lfx/components/Notion/list_pages.py +122 -0
- lfx/components/Notion/list_users.py +77 -0
- lfx/components/Notion/page_content_viewer.py +93 -0
- lfx/components/Notion/search.py +111 -0
- lfx/components/Notion/update_page_property.py +114 -0
- lfx/components/__init__.py +428 -0
- lfx/components/_importing.py +42 -0
- lfx/components/agentql/__init__.py +3 -0
- lfx/components/agentql/agentql_api.py +151 -0
- lfx/components/aiml/__init__.py +37 -0
- lfx/components/aiml/aiml.py +115 -0
- lfx/components/aiml/aiml_embeddings.py +37 -0
- lfx/components/altk/__init__.py +34 -0
- lfx/components/altk/altk_agent.py +193 -0
- lfx/components/amazon/__init__.py +36 -0
- lfx/components/amazon/amazon_bedrock_converse.py +195 -0
- lfx/components/amazon/amazon_bedrock_embedding.py +109 -0
- lfx/components/amazon/amazon_bedrock_model.py +130 -0
- lfx/components/amazon/s3_bucket_uploader.py +211 -0
- lfx/components/anthropic/__init__.py +34 -0
- lfx/components/anthropic/anthropic.py +187 -0
- lfx/components/apify/__init__.py +5 -0
- lfx/components/apify/apify_actor.py +325 -0
- lfx/components/arxiv/__init__.py +3 -0
- lfx/components/arxiv/arxiv.py +169 -0
- lfx/components/assemblyai/__init__.py +46 -0
- lfx/components/assemblyai/assemblyai_get_subtitles.py +83 -0
- lfx/components/assemblyai/assemblyai_lemur.py +183 -0
- lfx/components/assemblyai/assemblyai_list_transcripts.py +95 -0
- lfx/components/assemblyai/assemblyai_poll_transcript.py +72 -0
- lfx/components/assemblyai/assemblyai_start_transcript.py +188 -0
- lfx/components/azure/__init__.py +37 -0
- lfx/components/azure/azure_openai.py +95 -0
- lfx/components/azure/azure_openai_embeddings.py +83 -0
- lfx/components/baidu/__init__.py +32 -0
- lfx/components/baidu/baidu_qianfan_chat.py +113 -0
- lfx/components/bing/__init__.py +3 -0
- lfx/components/bing/bing_search_api.py +61 -0
- lfx/components/cassandra/__init__.py +40 -0
- lfx/components/cassandra/cassandra.py +264 -0
- lfx/components/cassandra/cassandra_chat.py +92 -0
- lfx/components/cassandra/cassandra_graph.py +238 -0
- lfx/components/chains/__init__.py +3 -0
- lfx/components/chroma/__init__.py +34 -0
- lfx/components/chroma/chroma.py +169 -0
- lfx/components/cleanlab/__init__.py +40 -0
- lfx/components/cleanlab/cleanlab_evaluator.py +155 -0
- lfx/components/cleanlab/cleanlab_rag_evaluator.py +254 -0
- lfx/components/cleanlab/cleanlab_remediator.py +131 -0
- lfx/components/clickhouse/__init__.py +34 -0
- lfx/components/clickhouse/clickhouse.py +135 -0
- lfx/components/cloudflare/__init__.py +32 -0
- lfx/components/cloudflare/cloudflare.py +81 -0
- lfx/components/cohere/__init__.py +40 -0
- lfx/components/cohere/cohere_embeddings.py +81 -0
- lfx/components/cohere/cohere_models.py +46 -0
- lfx/components/cohere/cohere_rerank.py +51 -0
- lfx/components/cometapi/__init__.py +32 -0
- lfx/components/cometapi/cometapi.py +166 -0
- lfx/components/composio/__init__.py +222 -0
- lfx/components/composio/agentql_composio.py +11 -0
- lfx/components/composio/agiled_composio.py +11 -0
- lfx/components/composio/airtable_composio.py +11 -0
- lfx/components/composio/apollo_composio.py +11 -0
- lfx/components/composio/asana_composio.py +11 -0
- lfx/components/composio/attio_composio.py +11 -0
- lfx/components/composio/bitbucket_composio.py +11 -0
- lfx/components/composio/bolna_composio.py +11 -0
- lfx/components/composio/brightdata_composio.py +11 -0
- lfx/components/composio/calendly_composio.py +11 -0
- lfx/components/composio/canva_composio.py +11 -0
- lfx/components/composio/canvas_composio.py +11 -0
- lfx/components/composio/coda_composio.py +11 -0
- lfx/components/composio/composio_api.py +278 -0
- lfx/components/composio/contentful_composio.py +11 -0
- lfx/components/composio/digicert_composio.py +11 -0
- lfx/components/composio/discord_composio.py +11 -0
- lfx/components/composio/dropbox_compnent.py +11 -0
- lfx/components/composio/elevenlabs_composio.py +11 -0
- lfx/components/composio/exa_composio.py +11 -0
- lfx/components/composio/figma_composio.py +11 -0
- lfx/components/composio/finage_composio.py +11 -0
- lfx/components/composio/firecrawl_composio.py +11 -0
- lfx/components/composio/fireflies_composio.py +11 -0
- lfx/components/composio/fixer_composio.py +11 -0
- lfx/components/composio/flexisign_composio.py +11 -0
- lfx/components/composio/freshdesk_composio.py +11 -0
- lfx/components/composio/github_composio.py +11 -0
- lfx/components/composio/gmail_composio.py +38 -0
- lfx/components/composio/googlebigquery_composio.py +11 -0
- lfx/components/composio/googlecalendar_composio.py +11 -0
- lfx/components/composio/googleclassroom_composio.py +11 -0
- lfx/components/composio/googledocs_composio.py +11 -0
- lfx/components/composio/googlemeet_composio.py +11 -0
- lfx/components/composio/googlesheets_composio.py +11 -0
- lfx/components/composio/googletasks_composio.py +8 -0
- lfx/components/composio/heygen_composio.py +11 -0
- lfx/components/composio/instagram_composio.py +11 -0
- lfx/components/composio/jira_composio.py +11 -0
- lfx/components/composio/jotform_composio.py +11 -0
- lfx/components/composio/klaviyo_composio.py +11 -0
- lfx/components/composio/linear_composio.py +11 -0
- lfx/components/composio/listennotes_composio.py +11 -0
- lfx/components/composio/mem0_composio.py +11 -0
- lfx/components/composio/miro_composio.py +11 -0
- lfx/components/composio/missive_composio.py +11 -0
- lfx/components/composio/notion_composio.py +11 -0
- lfx/components/composio/onedrive_composio.py +11 -0
- lfx/components/composio/outlook_composio.py +11 -0
- lfx/components/composio/pandadoc_composio.py +11 -0
- lfx/components/composio/peopledatalabs_composio.py +11 -0
- lfx/components/composio/perplexityai_composio.py +11 -0
- lfx/components/composio/reddit_composio.py +11 -0
- lfx/components/composio/serpapi_composio.py +11 -0
- lfx/components/composio/slack_composio.py +11 -0
- lfx/components/composio/slackbot_composio.py +11 -0
- lfx/components/composio/snowflake_composio.py +11 -0
- lfx/components/composio/supabase_composio.py +11 -0
- lfx/components/composio/tavily_composio.py +11 -0
- lfx/components/composio/timelinesai_composio.py +11 -0
- lfx/components/composio/todoist_composio.py +11 -0
- lfx/components/composio/wrike_composio.py +11 -0
- lfx/components/composio/youtube_composio.py +11 -0
- lfx/components/confluence/__init__.py +3 -0
- lfx/components/confluence/confluence.py +84 -0
- lfx/components/couchbase/__init__.py +34 -0
- lfx/components/couchbase/couchbase.py +102 -0
- lfx/components/crewai/__init__.py +49 -0
- lfx/components/crewai/crewai.py +108 -0
- lfx/components/crewai/hierarchical_crew.py +47 -0
- lfx/components/crewai/hierarchical_task.py +45 -0
- lfx/components/crewai/sequential_crew.py +53 -0
- lfx/components/crewai/sequential_task.py +74 -0
- lfx/components/crewai/sequential_task_agent.py +144 -0
- lfx/components/cuga/__init__.py +34 -0
- lfx/components/cuga/cuga_agent.py +730 -0
- lfx/components/custom_component/__init__.py +34 -0
- lfx/components/custom_component/custom_component.py +31 -0
- lfx/components/data/__init__.py +114 -0
- lfx/components/data_source/__init__.py +58 -0
- lfx/components/data_source/api_request.py +577 -0
- lfx/components/data_source/csv_to_data.py +101 -0
- lfx/components/data_source/json_to_data.py +106 -0
- lfx/components/data_source/mock_data.py +398 -0
- lfx/components/data_source/news_search.py +166 -0
- lfx/components/data_source/rss.py +71 -0
- lfx/components/data_source/sql_executor.py +101 -0
- lfx/components/data_source/url.py +311 -0
- lfx/components/data_source/web_search.py +326 -0
- lfx/components/datastax/__init__.py +76 -0
- lfx/components/datastax/astradb_assistant_manager.py +307 -0
- lfx/components/datastax/astradb_chatmemory.py +40 -0
- lfx/components/datastax/astradb_cql.py +288 -0
- lfx/components/datastax/astradb_graph.py +217 -0
- lfx/components/datastax/astradb_tool.py +378 -0
- lfx/components/datastax/astradb_vectorize.py +122 -0
- lfx/components/datastax/astradb_vectorstore.py +449 -0
- lfx/components/datastax/create_assistant.py +59 -0
- lfx/components/datastax/create_thread.py +33 -0
- lfx/components/datastax/dotenv.py +36 -0
- lfx/components/datastax/get_assistant.py +38 -0
- lfx/components/datastax/getenvvar.py +31 -0
- lfx/components/datastax/graph_rag.py +141 -0
- lfx/components/datastax/hcd.py +315 -0
- lfx/components/datastax/list_assistants.py +26 -0
- lfx/components/datastax/run.py +90 -0
- lfx/components/deactivated/__init__.py +15 -0
- lfx/components/deactivated/amazon_kendra.py +66 -0
- lfx/components/deactivated/chat_litellm_model.py +158 -0
- lfx/components/deactivated/code_block_extractor.py +26 -0
- lfx/components/deactivated/documents_to_data.py +22 -0
- lfx/components/deactivated/embed.py +16 -0
- lfx/components/deactivated/extract_key_from_data.py +46 -0
- lfx/components/deactivated/json_document_builder.py +57 -0
- lfx/components/deactivated/list_flows.py +20 -0
- lfx/components/deactivated/mcp_sse.py +61 -0
- lfx/components/deactivated/mcp_stdio.py +62 -0
- lfx/components/deactivated/merge_data.py +93 -0
- lfx/components/deactivated/message.py +37 -0
- lfx/components/deactivated/metal.py +54 -0
- lfx/components/deactivated/multi_query.py +59 -0
- lfx/components/deactivated/retriever.py +43 -0
- lfx/components/deactivated/selective_passthrough.py +77 -0
- lfx/components/deactivated/should_run_next.py +40 -0
- lfx/components/deactivated/split_text.py +63 -0
- lfx/components/deactivated/store_message.py +24 -0
- lfx/components/deactivated/sub_flow.py +124 -0
- lfx/components/deactivated/vectara_self_query.py +76 -0
- lfx/components/deactivated/vector_store.py +24 -0
- lfx/components/deepseek/__init__.py +34 -0
- lfx/components/deepseek/deepseek.py +136 -0
- lfx/components/docling/__init__.py +43 -0
- lfx/components/docling/chunk_docling_document.py +186 -0
- lfx/components/docling/docling_inline.py +238 -0
- lfx/components/docling/docling_remote.py +195 -0
- lfx/components/docling/export_docling_document.py +117 -0
- lfx/components/documentloaders/__init__.py +3 -0
- lfx/components/duckduckgo/__init__.py +3 -0
- lfx/components/duckduckgo/duck_duck_go_search_run.py +92 -0
- lfx/components/elastic/__init__.py +37 -0
- lfx/components/elastic/elasticsearch.py +267 -0
- lfx/components/elastic/opensearch.py +789 -0
- lfx/components/elastic/opensearch_multimodal.py +1575 -0
- lfx/components/embeddings/__init__.py +37 -0
- lfx/components/embeddings/similarity.py +77 -0
- lfx/components/embeddings/text_embedder.py +65 -0
- lfx/components/exa/__init__.py +3 -0
- lfx/components/exa/exa_search.py +68 -0
- lfx/components/files_and_knowledge/__init__.py +47 -0
- lfx/components/files_and_knowledge/directory.py +113 -0
- lfx/components/files_and_knowledge/file.py +841 -0
- lfx/components/files_and_knowledge/ingestion.py +694 -0
- lfx/components/files_and_knowledge/retrieval.py +264 -0
- lfx/components/files_and_knowledge/save_file.py +746 -0
- lfx/components/firecrawl/__init__.py +43 -0
- lfx/components/firecrawl/firecrawl_crawl_api.py +88 -0
- lfx/components/firecrawl/firecrawl_extract_api.py +136 -0
- lfx/components/firecrawl/firecrawl_map_api.py +89 -0
- lfx/components/firecrawl/firecrawl_scrape_api.py +73 -0
- lfx/components/flow_controls/__init__.py +58 -0
- lfx/components/flow_controls/conditional_router.py +208 -0
- lfx/components/flow_controls/data_conditional_router.py +126 -0
- lfx/components/flow_controls/flow_tool.py +111 -0
- lfx/components/flow_controls/listen.py +29 -0
- lfx/components/flow_controls/loop.py +163 -0
- lfx/components/flow_controls/notify.py +88 -0
- lfx/components/flow_controls/pass_message.py +36 -0
- lfx/components/flow_controls/run_flow.py +108 -0
- lfx/components/flow_controls/sub_flow.py +115 -0
- lfx/components/git/__init__.py +4 -0
- lfx/components/git/git.py +262 -0
- lfx/components/git/gitextractor.py +196 -0
- lfx/components/glean/__init__.py +3 -0
- lfx/components/glean/glean_search_api.py +173 -0
- lfx/components/google/__init__.py +17 -0
- lfx/components/google/gmail.py +193 -0
- lfx/components/google/google_bq_sql_executor.py +157 -0
- lfx/components/google/google_drive.py +92 -0
- lfx/components/google/google_drive_search.py +152 -0
- lfx/components/google/google_generative_ai.py +144 -0
- lfx/components/google/google_generative_ai_embeddings.py +141 -0
- lfx/components/google/google_oauth_token.py +89 -0
- lfx/components/google/google_search_api_core.py +68 -0
- lfx/components/google/google_serper_api_core.py +74 -0
- lfx/components/groq/__init__.py +34 -0
- lfx/components/groq/groq.py +143 -0
- lfx/components/helpers/__init__.py +154 -0
- lfx/components/homeassistant/__init__.py +7 -0
- lfx/components/homeassistant/home_assistant_control.py +152 -0
- lfx/components/homeassistant/list_home_assistant_states.py +137 -0
- lfx/components/huggingface/__init__.py +37 -0
- lfx/components/huggingface/huggingface.py +199 -0
- lfx/components/huggingface/huggingface_inference_api.py +106 -0
- lfx/components/ibm/__init__.py +34 -0
- lfx/components/ibm/watsonx.py +207 -0
- lfx/components/ibm/watsonx_embeddings.py +135 -0
- lfx/components/icosacomputing/__init__.py +5 -0
- lfx/components/icosacomputing/combinatorial_reasoner.py +84 -0
- lfx/components/input_output/__init__.py +40 -0
- lfx/components/input_output/chat.py +109 -0
- lfx/components/input_output/chat_output.py +184 -0
- lfx/components/input_output/text.py +27 -0
- lfx/components/input_output/text_output.py +29 -0
- lfx/components/input_output/webhook.py +56 -0
- lfx/components/jigsawstack/__init__.py +23 -0
- lfx/components/jigsawstack/ai_scrape.py +126 -0
- lfx/components/jigsawstack/ai_web_search.py +136 -0
- lfx/components/jigsawstack/file_read.py +115 -0
- lfx/components/jigsawstack/file_upload.py +94 -0
- lfx/components/jigsawstack/image_generation.py +205 -0
- lfx/components/jigsawstack/nsfw.py +60 -0
- lfx/components/jigsawstack/object_detection.py +124 -0
- lfx/components/jigsawstack/sentiment.py +112 -0
- lfx/components/jigsawstack/text_to_sql.py +90 -0
- lfx/components/jigsawstack/text_translate.py +77 -0
- lfx/components/jigsawstack/vocr.py +107 -0
- lfx/components/knowledge_bases/__init__.py +89 -0
- lfx/components/langchain_utilities/__init__.py +109 -0
- lfx/components/langchain_utilities/character.py +53 -0
- lfx/components/langchain_utilities/conversation.py +59 -0
- lfx/components/langchain_utilities/csv_agent.py +175 -0
- lfx/components/langchain_utilities/fake_embeddings.py +26 -0
- lfx/components/langchain_utilities/html_link_extractor.py +35 -0
- lfx/components/langchain_utilities/json_agent.py +100 -0
- lfx/components/langchain_utilities/langchain_hub.py +126 -0
- lfx/components/langchain_utilities/language_recursive.py +49 -0
- lfx/components/langchain_utilities/language_semantic.py +138 -0
- lfx/components/langchain_utilities/llm_checker.py +39 -0
- lfx/components/langchain_utilities/llm_math.py +42 -0
- lfx/components/langchain_utilities/natural_language.py +61 -0
- lfx/components/langchain_utilities/openai_tools.py +53 -0
- lfx/components/langchain_utilities/openapi.py +48 -0
- lfx/components/langchain_utilities/recursive_character.py +60 -0
- lfx/components/langchain_utilities/retrieval_qa.py +83 -0
- lfx/components/langchain_utilities/runnable_executor.py +137 -0
- lfx/components/langchain_utilities/self_query.py +80 -0
- lfx/components/langchain_utilities/spider.py +142 -0
- lfx/components/langchain_utilities/sql.py +40 -0
- lfx/components/langchain_utilities/sql_database.py +35 -0
- lfx/components/langchain_utilities/sql_generator.py +78 -0
- lfx/components/langchain_utilities/tool_calling.py +59 -0
- lfx/components/langchain_utilities/vector_store_info.py +49 -0
- lfx/components/langchain_utilities/vector_store_router.py +33 -0
- lfx/components/langchain_utilities/xml_agent.py +71 -0
- lfx/components/langwatch/__init__.py +3 -0
- lfx/components/langwatch/langwatch.py +278 -0
- lfx/components/link_extractors/__init__.py +3 -0
- lfx/components/llm_operations/__init__.py +46 -0
- lfx/components/llm_operations/batch_run.py +205 -0
- lfx/components/llm_operations/lambda_filter.py +218 -0
- lfx/components/llm_operations/llm_conditional_router.py +421 -0
- lfx/components/llm_operations/llm_selector.py +499 -0
- lfx/components/llm_operations/structured_output.py +244 -0
- lfx/components/lmstudio/__init__.py +34 -0
- lfx/components/lmstudio/lmstudioembeddings.py +89 -0
- lfx/components/lmstudio/lmstudiomodel.py +133 -0
- lfx/components/logic/__init__.py +181 -0
- lfx/components/maritalk/__init__.py +32 -0
- lfx/components/maritalk/maritalk.py +52 -0
- lfx/components/mem0/__init__.py +3 -0
- lfx/components/mem0/mem0_chat_memory.py +147 -0
- lfx/components/milvus/__init__.py +34 -0
- lfx/components/milvus/milvus.py +115 -0
- lfx/components/mistral/__init__.py +37 -0
- lfx/components/mistral/mistral.py +114 -0
- lfx/components/mistral/mistral_embeddings.py +58 -0
- lfx/components/models/__init__.py +89 -0
- lfx/components/models_and_agents/__init__.py +49 -0
- lfx/components/models_and_agents/agent.py +644 -0
- lfx/components/models_and_agents/embedding_model.py +423 -0
- lfx/components/models_and_agents/language_model.py +398 -0
- lfx/components/models_and_agents/mcp_component.py +594 -0
- lfx/components/models_and_agents/memory.py +268 -0
- lfx/components/models_and_agents/prompt.py +67 -0
- lfx/components/mongodb/__init__.py +34 -0
- lfx/components/mongodb/mongodb_atlas.py +213 -0
- lfx/components/needle/__init__.py +3 -0
- lfx/components/needle/needle.py +104 -0
- lfx/components/notdiamond/__init__.py +34 -0
- lfx/components/notdiamond/notdiamond.py +228 -0
- lfx/components/novita/__init__.py +32 -0
- lfx/components/novita/novita.py +130 -0
- lfx/components/nvidia/__init__.py +57 -0
- lfx/components/nvidia/nvidia.py +151 -0
- lfx/components/nvidia/nvidia_embedding.py +77 -0
- lfx/components/nvidia/nvidia_ingest.py +317 -0
- lfx/components/nvidia/nvidia_rerank.py +63 -0
- lfx/components/nvidia/system_assist.py +65 -0
- lfx/components/olivya/__init__.py +3 -0
- lfx/components/olivya/olivya.py +116 -0
- lfx/components/ollama/__init__.py +37 -0
- lfx/components/ollama/ollama.py +548 -0
- lfx/components/ollama/ollama_embeddings.py +103 -0
- lfx/components/openai/__init__.py +37 -0
- lfx/components/openai/openai.py +100 -0
- lfx/components/openai/openai_chat_model.py +176 -0
- lfx/components/openrouter/__init__.py +32 -0
- lfx/components/openrouter/openrouter.py +104 -0
- lfx/components/output_parsers/__init__.py +3 -0
- lfx/components/perplexity/__init__.py +34 -0
- lfx/components/perplexity/perplexity.py +75 -0
- lfx/components/pgvector/__init__.py +34 -0
- lfx/components/pgvector/pgvector.py +72 -0
- lfx/components/pinecone/__init__.py +34 -0
- lfx/components/pinecone/pinecone.py +134 -0
- lfx/components/processing/__init__.py +72 -0
- lfx/components/processing/alter_metadata.py +109 -0
- lfx/components/processing/combine_text.py +40 -0
- lfx/components/processing/converter.py +248 -0
- lfx/components/processing/create_data.py +111 -0
- lfx/components/processing/create_list.py +40 -0
- lfx/components/processing/data_operations.py +528 -0
- lfx/components/processing/data_to_dataframe.py +71 -0
- lfx/components/processing/dataframe_operations.py +313 -0
- lfx/components/processing/dataframe_to_toolset.py +259 -0
- lfx/components/processing/dynamic_create_data.py +357 -0
- lfx/components/processing/extract_key.py +54 -0
- lfx/components/processing/filter_data.py +43 -0
- lfx/components/processing/filter_data_values.py +89 -0
- lfx/components/processing/json_cleaner.py +104 -0
- lfx/components/processing/merge_data.py +91 -0
- lfx/components/processing/message_to_data.py +37 -0
- lfx/components/processing/output_parser.py +46 -0
- lfx/components/processing/parse_data.py +71 -0
- lfx/components/processing/parse_dataframe.py +69 -0
- lfx/components/processing/parse_json_data.py +91 -0
- lfx/components/processing/parser.py +148 -0
- lfx/components/processing/regex.py +83 -0
- lfx/components/processing/select_data.py +49 -0
- lfx/components/processing/split_text.py +141 -0
- lfx/components/processing/store_message.py +91 -0
- lfx/components/processing/update_data.py +161 -0
- lfx/components/prototypes/__init__.py +35 -0
- lfx/components/prototypes/python_function.py +73 -0
- lfx/components/qdrant/__init__.py +34 -0
- lfx/components/qdrant/qdrant.py +109 -0
- lfx/components/redis/__init__.py +37 -0
- lfx/components/redis/redis.py +89 -0
- lfx/components/redis/redis_chat.py +43 -0
- lfx/components/sambanova/__init__.py +32 -0
- lfx/components/sambanova/sambanova.py +84 -0
- lfx/components/scrapegraph/__init__.py +40 -0
- lfx/components/scrapegraph/scrapegraph_markdownify_api.py +64 -0
- lfx/components/scrapegraph/scrapegraph_search_api.py +64 -0
- lfx/components/scrapegraph/scrapegraph_smart_scraper_api.py +71 -0
- lfx/components/searchapi/__init__.py +34 -0
- lfx/components/searchapi/search.py +79 -0
- lfx/components/serpapi/__init__.py +3 -0
- lfx/components/serpapi/serp.py +115 -0
- lfx/components/supabase/__init__.py +34 -0
- lfx/components/supabase/supabase.py +76 -0
- lfx/components/tavily/__init__.py +4 -0
- lfx/components/tavily/tavily_extract.py +117 -0
- lfx/components/tavily/tavily_search.py +212 -0
- lfx/components/textsplitters/__init__.py +3 -0
- lfx/components/toolkits/__init__.py +3 -0
- lfx/components/tools/__init__.py +66 -0
- lfx/components/tools/calculator.py +109 -0
- lfx/components/tools/google_search_api.py +45 -0
- lfx/components/tools/google_serper_api.py +115 -0
- lfx/components/tools/python_code_structured_tool.py +328 -0
- lfx/components/tools/python_repl.py +98 -0
- lfx/components/tools/search_api.py +88 -0
- lfx/components/tools/searxng.py +145 -0
- lfx/components/tools/serp_api.py +120 -0
- lfx/components/tools/tavily_search_tool.py +345 -0
- lfx/components/tools/wikidata_api.py +103 -0
- lfx/components/tools/wikipedia_api.py +50 -0
- lfx/components/tools/yahoo_finance.py +130 -0
- lfx/components/twelvelabs/__init__.py +52 -0
- lfx/components/twelvelabs/convert_astra_results.py +84 -0
- lfx/components/twelvelabs/pegasus_index.py +311 -0
- lfx/components/twelvelabs/split_video.py +301 -0
- lfx/components/twelvelabs/text_embeddings.py +57 -0
- lfx/components/twelvelabs/twelvelabs_pegasus.py +408 -0
- lfx/components/twelvelabs/video_embeddings.py +100 -0
- lfx/components/twelvelabs/video_file.py +191 -0
- lfx/components/unstructured/__init__.py +3 -0
- lfx/components/unstructured/unstructured.py +121 -0
- lfx/components/upstash/__init__.py +34 -0
- lfx/components/upstash/upstash.py +124 -0
- lfx/components/utilities/__init__.py +43 -0
- lfx/components/utilities/calculator_core.py +89 -0
- lfx/components/utilities/current_date.py +42 -0
- lfx/components/utilities/id_generator.py +42 -0
- lfx/components/utilities/python_repl_core.py +98 -0
- lfx/components/vectara/__init__.py +37 -0
- lfx/components/vectara/vectara.py +97 -0
- lfx/components/vectara/vectara_rag.py +164 -0
- lfx/components/vectorstores/__init__.py +34 -0
- lfx/components/vectorstores/local_db.py +270 -0
- lfx/components/vertexai/__init__.py +37 -0
- lfx/components/vertexai/vertexai.py +71 -0
- lfx/components/vertexai/vertexai_embeddings.py +67 -0
- lfx/components/vlmrun/__init__.py +34 -0
- lfx/components/vlmrun/vlmrun_transcription.py +224 -0
- lfx/components/weaviate/__init__.py +34 -0
- lfx/components/weaviate/weaviate.py +89 -0
- lfx/components/wikipedia/__init__.py +4 -0
- lfx/components/wikipedia/wikidata.py +86 -0
- lfx/components/wikipedia/wikipedia.py +53 -0
- lfx/components/wolframalpha/__init__.py +3 -0
- lfx/components/wolframalpha/wolfram_alpha_api.py +54 -0
- lfx/components/xai/__init__.py +32 -0
- lfx/components/xai/xai.py +167 -0
- lfx/components/yahoosearch/__init__.py +3 -0
- lfx/components/yahoosearch/yahoo.py +137 -0
- lfx/components/youtube/__init__.py +52 -0
- lfx/components/youtube/channel.py +227 -0
- lfx/components/youtube/comments.py +231 -0
- lfx/components/youtube/playlist.py +33 -0
- lfx/components/youtube/search.py +120 -0
- lfx/components/youtube/trending.py +285 -0
- lfx/components/youtube/video_details.py +263 -0
- lfx/components/youtube/youtube_transcripts.py +206 -0
- lfx/components/zep/__init__.py +3 -0
- lfx/components/zep/zep.py +45 -0
- lfx/constants.py +6 -0
- lfx/custom/__init__.py +7 -0
- lfx/custom/attributes.py +87 -0
- lfx/custom/code_parser/__init__.py +3 -0
- lfx/custom/code_parser/code_parser.py +361 -0
- lfx/custom/custom_component/__init__.py +0 -0
- lfx/custom/custom_component/base_component.py +128 -0
- lfx/custom/custom_component/component.py +1890 -0
- lfx/custom/custom_component/component_with_cache.py +8 -0
- lfx/custom/custom_component/custom_component.py +650 -0
- lfx/custom/dependency_analyzer.py +165 -0
- lfx/custom/directory_reader/__init__.py +3 -0
- lfx/custom/directory_reader/directory_reader.py +359 -0
- lfx/custom/directory_reader/utils.py +171 -0
- lfx/custom/eval.py +12 -0
- lfx/custom/schema.py +32 -0
- lfx/custom/tree_visitor.py +21 -0
- lfx/custom/utils.py +877 -0
- lfx/custom/validate.py +523 -0
- lfx/events/__init__.py +1 -0
- lfx/events/event_manager.py +110 -0
- lfx/exceptions/__init__.py +0 -0
- lfx/exceptions/component.py +15 -0
- lfx/field_typing/__init__.py +91 -0
- lfx/field_typing/constants.py +216 -0
- lfx/field_typing/range_spec.py +35 -0
- lfx/graph/__init__.py +6 -0
- lfx/graph/edge/__init__.py +0 -0
- lfx/graph/edge/base.py +300 -0
- lfx/graph/edge/schema.py +119 -0
- lfx/graph/edge/utils.py +0 -0
- lfx/graph/graph/__init__.py +0 -0
- lfx/graph/graph/ascii.py +202 -0
- lfx/graph/graph/base.py +2298 -0
- lfx/graph/graph/constants.py +63 -0
- lfx/graph/graph/runnable_vertices_manager.py +133 -0
- lfx/graph/graph/schema.py +53 -0
- lfx/graph/graph/state_model.py +66 -0
- lfx/graph/graph/utils.py +1024 -0
- lfx/graph/schema.py +75 -0
- lfx/graph/state/__init__.py +0 -0
- lfx/graph/state/model.py +250 -0
- lfx/graph/utils.py +206 -0
- lfx/graph/vertex/__init__.py +0 -0
- lfx/graph/vertex/base.py +826 -0
- lfx/graph/vertex/constants.py +0 -0
- lfx/graph/vertex/exceptions.py +4 -0
- lfx/graph/vertex/param_handler.py +316 -0
- lfx/graph/vertex/schema.py +26 -0
- lfx/graph/vertex/utils.py +19 -0
- lfx/graph/vertex/vertex_types.py +489 -0
- lfx/helpers/__init__.py +141 -0
- lfx/helpers/base_model.py +71 -0
- lfx/helpers/custom.py +13 -0
- lfx/helpers/data.py +167 -0
- lfx/helpers/flow.py +308 -0
- lfx/inputs/__init__.py +68 -0
- lfx/inputs/constants.py +2 -0
- lfx/inputs/input_mixin.py +352 -0
- lfx/inputs/inputs.py +718 -0
- lfx/inputs/validators.py +19 -0
- lfx/interface/__init__.py +6 -0
- lfx/interface/components.py +897 -0
- lfx/interface/importing/__init__.py +5 -0
- lfx/interface/importing/utils.py +39 -0
- lfx/interface/initialize/__init__.py +3 -0
- lfx/interface/initialize/loading.py +317 -0
- lfx/interface/listing.py +26 -0
- lfx/interface/run.py +16 -0
- lfx/interface/utils.py +111 -0
- lfx/io/__init__.py +63 -0
- lfx/io/schema.py +295 -0
- lfx/load/__init__.py +8 -0
- lfx/load/load.py +256 -0
- lfx/load/utils.py +99 -0
- lfx/log/__init__.py +5 -0
- lfx/log/logger.py +411 -0
- lfx/logging/__init__.py +11 -0
- lfx/logging/logger.py +24 -0
- lfx/memory/__init__.py +70 -0
- lfx/memory/stubs.py +302 -0
- lfx/processing/__init__.py +1 -0
- lfx/processing/process.py +238 -0
- lfx/processing/utils.py +25 -0
- lfx/py.typed +0 -0
- lfx/schema/__init__.py +66 -0
- lfx/schema/artifact.py +83 -0
- lfx/schema/content_block.py +62 -0
- lfx/schema/content_types.py +91 -0
- lfx/schema/cross_module.py +80 -0
- lfx/schema/data.py +309 -0
- lfx/schema/dataframe.py +210 -0
- lfx/schema/dotdict.py +74 -0
- lfx/schema/encoders.py +13 -0
- lfx/schema/graph.py +47 -0
- lfx/schema/image.py +184 -0
- lfx/schema/json_schema.py +186 -0
- lfx/schema/log.py +62 -0
- lfx/schema/message.py +493 -0
- lfx/schema/openai_responses_schemas.py +74 -0
- lfx/schema/properties.py +41 -0
- lfx/schema/schema.py +180 -0
- lfx/schema/serialize.py +13 -0
- lfx/schema/table.py +142 -0
- lfx/schema/validators.py +114 -0
- lfx/serialization/__init__.py +5 -0
- lfx/serialization/constants.py +2 -0
- lfx/serialization/serialization.py +314 -0
- lfx/services/__init__.py +26 -0
- lfx/services/base.py +28 -0
- lfx/services/cache/__init__.py +6 -0
- lfx/services/cache/base.py +183 -0
- lfx/services/cache/service.py +166 -0
- lfx/services/cache/utils.py +169 -0
- lfx/services/chat/__init__.py +1 -0
- lfx/services/chat/config.py +2 -0
- lfx/services/chat/schema.py +10 -0
- lfx/services/database/__init__.py +5 -0
- lfx/services/database/service.py +25 -0
- lfx/services/deps.py +194 -0
- lfx/services/factory.py +19 -0
- lfx/services/initialize.py +19 -0
- lfx/services/interfaces.py +103 -0
- lfx/services/manager.py +185 -0
- lfx/services/mcp_composer/__init__.py +6 -0
- lfx/services/mcp_composer/factory.py +16 -0
- lfx/services/mcp_composer/service.py +1441 -0
- lfx/services/schema.py +21 -0
- lfx/services/session.py +87 -0
- lfx/services/settings/__init__.py +3 -0
- lfx/services/settings/auth.py +133 -0
- lfx/services/settings/base.py +668 -0
- lfx/services/settings/constants.py +43 -0
- lfx/services/settings/factory.py +23 -0
- lfx/services/settings/feature_flags.py +11 -0
- lfx/services/settings/service.py +35 -0
- lfx/services/settings/utils.py +40 -0
- lfx/services/shared_component_cache/__init__.py +1 -0
- lfx/services/shared_component_cache/factory.py +30 -0
- lfx/services/shared_component_cache/service.py +9 -0
- lfx/services/storage/__init__.py +5 -0
- lfx/services/storage/local.py +185 -0
- lfx/services/storage/service.py +177 -0
- lfx/services/tracing/__init__.py +1 -0
- lfx/services/tracing/service.py +21 -0
- lfx/settings.py +6 -0
- lfx/template/__init__.py +6 -0
- lfx/template/field/__init__.py +0 -0
- lfx/template/field/base.py +260 -0
- lfx/template/field/prompt.py +15 -0
- lfx/template/frontend_node/__init__.py +6 -0
- lfx/template/frontend_node/base.py +214 -0
- lfx/template/frontend_node/constants.py +65 -0
- lfx/template/frontend_node/custom_components.py +79 -0
- lfx/template/template/__init__.py +0 -0
- lfx/template/template/base.py +100 -0
- lfx/template/utils.py +217 -0
- lfx/type_extraction/__init__.py +19 -0
- lfx/type_extraction/type_extraction.py +75 -0
- lfx/type_extraction.py +80 -0
- lfx/utils/__init__.py +1 -0
- lfx/utils/async_helpers.py +42 -0
- lfx/utils/component_utils.py +154 -0
- lfx/utils/concurrency.py +60 -0
- lfx/utils/connection_string_parser.py +11 -0
- lfx/utils/constants.py +233 -0
- lfx/utils/data_structure.py +212 -0
- lfx/utils/exceptions.py +22 -0
- lfx/utils/helpers.py +34 -0
- lfx/utils/image.py +79 -0
- lfx/utils/langflow_utils.py +52 -0
- lfx/utils/lazy_load.py +15 -0
- lfx/utils/request_utils.py +18 -0
- lfx/utils/schemas.py +139 -0
- lfx/utils/ssrf_protection.py +384 -0
- lfx/utils/util.py +626 -0
- lfx/utils/util_strings.py +56 -0
- lfx/utils/validate_cloud.py +26 -0
- lfx/utils/version.py +24 -0
- lfx_nightly-0.2.0.dev25.dist-info/METADATA +312 -0
- lfx_nightly-0.2.0.dev25.dist-info/RECORD +769 -0
- lfx_nightly-0.2.0.dev25.dist-info/WHEEL +4 -0
- lfx_nightly-0.2.0.dev25.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from json_repair import repair_json
|
|
5
|
+
|
|
6
|
+
from lfx.base.data.storage_utils import read_file_text
|
|
7
|
+
from lfx.custom.custom_component.component import Component
|
|
8
|
+
from lfx.io import FileInput, MessageTextInput, MultilineInput, Output
|
|
9
|
+
from lfx.schema.data import Data
|
|
10
|
+
from lfx.utils.async_helpers import run_until_complete
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class JSONToDataComponent(Component):
|
|
14
|
+
display_name = "Load JSON"
|
|
15
|
+
description = (
|
|
16
|
+
"Convert a JSON file, JSON from a file path, or a JSON string to a Data object or a list of Data objects"
|
|
17
|
+
)
|
|
18
|
+
icon = "braces"
|
|
19
|
+
name = "JSONtoData"
|
|
20
|
+
legacy = True
|
|
21
|
+
replacement = ["data.File"]
|
|
22
|
+
|
|
23
|
+
inputs = [
|
|
24
|
+
FileInput(
|
|
25
|
+
name="json_file",
|
|
26
|
+
display_name="JSON File",
|
|
27
|
+
file_types=["json"],
|
|
28
|
+
info="Upload a JSON file to convert to a Data object or list of Data objects",
|
|
29
|
+
),
|
|
30
|
+
MessageTextInput(
|
|
31
|
+
name="json_path",
|
|
32
|
+
display_name="JSON File Path",
|
|
33
|
+
info="Provide the path to the JSON file as pure text",
|
|
34
|
+
),
|
|
35
|
+
MultilineInput(
|
|
36
|
+
name="json_string",
|
|
37
|
+
display_name="JSON String",
|
|
38
|
+
info="Enter a valid JSON string (object or array) to convert to a Data object or list of Data objects",
|
|
39
|
+
),
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
outputs = [
|
|
43
|
+
Output(name="data", display_name="Data", method="convert_json_to_data"),
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
def convert_json_to_data(self) -> Data | list[Data]:
|
|
47
|
+
if sum(bool(field) for field in [self.json_file, self.json_path, self.json_string]) != 1:
|
|
48
|
+
msg = "Please provide exactly one of: JSON file, file path, or JSON string."
|
|
49
|
+
self.status = msg
|
|
50
|
+
raise ValueError(msg)
|
|
51
|
+
|
|
52
|
+
json_data = None
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
if self.json_file:
|
|
56
|
+
# FileInput always provides a local file path
|
|
57
|
+
file_path = self.json_file
|
|
58
|
+
if not file_path.lower().endswith(".json"):
|
|
59
|
+
self.status = "The provided file must be a JSON file."
|
|
60
|
+
else:
|
|
61
|
+
# Resolve to absolute path and read from local filesystem
|
|
62
|
+
resolved_path = self.resolve_path(file_path)
|
|
63
|
+
json_data = Path(resolved_path).read_text(encoding="utf-8")
|
|
64
|
+
|
|
65
|
+
elif self.json_path:
|
|
66
|
+
# User-provided text path - could be local or S3 key
|
|
67
|
+
file_path = self.json_path
|
|
68
|
+
if not file_path.lower().endswith(".json"):
|
|
69
|
+
self.status = "The provided path must be to a JSON file."
|
|
70
|
+
else:
|
|
71
|
+
json_data = run_until_complete(
|
|
72
|
+
read_file_text(file_path, encoding="utf-8", resolve_path=self.resolve_path)
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
else:
|
|
76
|
+
json_data = self.json_string
|
|
77
|
+
|
|
78
|
+
if json_data:
|
|
79
|
+
# Try to parse the JSON string
|
|
80
|
+
try:
|
|
81
|
+
parsed_data = json.loads(json_data)
|
|
82
|
+
except json.JSONDecodeError:
|
|
83
|
+
# If JSON parsing fails, try to repair the JSON string
|
|
84
|
+
repaired_json_string = repair_json(json_data)
|
|
85
|
+
parsed_data = json.loads(repaired_json_string)
|
|
86
|
+
|
|
87
|
+
# Check if the parsed data is a list
|
|
88
|
+
if isinstance(parsed_data, list):
|
|
89
|
+
result = [Data(data=item) for item in parsed_data]
|
|
90
|
+
else:
|
|
91
|
+
result = Data(data=parsed_data)
|
|
92
|
+
self.status = result
|
|
93
|
+
return result
|
|
94
|
+
|
|
95
|
+
except (json.JSONDecodeError, SyntaxError, ValueError) as e:
|
|
96
|
+
error_message = f"Invalid JSON or Python literal: {e}"
|
|
97
|
+
self.status = error_message
|
|
98
|
+
raise ValueError(error_message) from e
|
|
99
|
+
|
|
100
|
+
except Exception as e:
|
|
101
|
+
error_message = f"An error occurred: {e}"
|
|
102
|
+
self.status = error_message
|
|
103
|
+
raise ValueError(error_message) from e
|
|
104
|
+
|
|
105
|
+
# An error occurred
|
|
106
|
+
raise ValueError(self.status)
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
import secrets
|
|
2
|
+
from datetime import datetime, timedelta, timezone
|
|
3
|
+
|
|
4
|
+
from lfx.custom.custom_component.component import Component
|
|
5
|
+
from lfx.io import Output
|
|
6
|
+
from lfx.schema import Data, DataFrame
|
|
7
|
+
from lfx.schema.message import Message
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class MockDataGeneratorComponent(Component):
|
|
11
|
+
"""Mock Data Generator Component.
|
|
12
|
+
|
|
13
|
+
Generates sample data for testing and development purposes. Supports three main
|
|
14
|
+
Langflow output types: Message (text), Data (JSON), and DataFrame (tabular data).
|
|
15
|
+
|
|
16
|
+
This component is useful for:
|
|
17
|
+
- Testing workflows without real data sources
|
|
18
|
+
- Prototyping data processing pipelines
|
|
19
|
+
- Creating sample data for demonstrations
|
|
20
|
+
- Development and debugging of Langflow components
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
display_name = "Mock Data"
|
|
24
|
+
description = "Generate mock data for testing and development."
|
|
25
|
+
icon = "database"
|
|
26
|
+
name = "MockDataGenerator"
|
|
27
|
+
|
|
28
|
+
inputs = []
|
|
29
|
+
|
|
30
|
+
outputs = [
|
|
31
|
+
Output(display_name="Result", name="dataframe_output", method="generate_dataframe_output"),
|
|
32
|
+
Output(display_name="Result", name="message_output", method="generate_message_output"),
|
|
33
|
+
Output(display_name="Result", name="data_output", method="generate_data_output"),
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
def build(self) -> DataFrame:
|
|
37
|
+
"""Default build method - returns DataFrame when component is standalone."""
|
|
38
|
+
return self.generate_dataframe_output()
|
|
39
|
+
|
|
40
|
+
def generate_message_output(self) -> Message:
|
|
41
|
+
"""Generate Message output specifically.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Message: A Message object containing Lorem Ipsum text
|
|
45
|
+
"""
|
|
46
|
+
try:
|
|
47
|
+
self.log("Generating Message mock data")
|
|
48
|
+
message = self._generate_message()
|
|
49
|
+
self.status = f"Generated Lorem Ipsum message ({len(message.text)} characters)"
|
|
50
|
+
except (ValueError, TypeError) as e:
|
|
51
|
+
error_msg = f"Error generating Message data: {e!s}"
|
|
52
|
+
self.log(error_msg)
|
|
53
|
+
self.status = f"Error: {error_msg}"
|
|
54
|
+
return Message(text=f"Error: {error_msg}")
|
|
55
|
+
else:
|
|
56
|
+
return message
|
|
57
|
+
|
|
58
|
+
def generate_data_output(self) -> Data:
|
|
59
|
+
"""Generate Data output specifically.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Data: A Data object containing sample JSON data (1 record)
|
|
63
|
+
"""
|
|
64
|
+
try:
|
|
65
|
+
record_count = 1 # Fixed to 1 record for Data output
|
|
66
|
+
self.log(f"Generating Data mock data with {record_count} record")
|
|
67
|
+
data = self._generate_data(record_count)
|
|
68
|
+
self.status = f"Generated JSON data with {len(data.data.get('records', []))} record(s)"
|
|
69
|
+
except (ValueError, TypeError) as e:
|
|
70
|
+
error_msg = f"Error generating Data: {e!s}"
|
|
71
|
+
self.log(error_msg)
|
|
72
|
+
self.status = f"Error: {error_msg}"
|
|
73
|
+
return Data(data={"error": error_msg, "success": False})
|
|
74
|
+
else:
|
|
75
|
+
return data
|
|
76
|
+
|
|
77
|
+
def generate_dataframe_output(self) -> DataFrame:
|
|
78
|
+
"""Generate DataFrame output specifically.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
DataFrame: A Langflow DataFrame with sample data (50 records)
|
|
82
|
+
"""
|
|
83
|
+
try:
|
|
84
|
+
record_count = 50 # Fixed to 50 records for DataFrame output
|
|
85
|
+
self.log(f"Generating DataFrame mock data with {record_count} records")
|
|
86
|
+
return self._generate_dataframe(record_count)
|
|
87
|
+
except (ValueError, TypeError) as e:
|
|
88
|
+
error_msg = f"Error generating DataFrame: {e!s}"
|
|
89
|
+
self.log(error_msg)
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
import pandas as pd
|
|
93
|
+
|
|
94
|
+
error_df = pd.DataFrame({"error": [error_msg]})
|
|
95
|
+
return DataFrame(error_df)
|
|
96
|
+
except ImportError:
|
|
97
|
+
# Even without pandas, return DataFrame wrapper
|
|
98
|
+
return DataFrame({"error": [error_msg]})
|
|
99
|
+
|
|
100
|
+
def _generate_message(self) -> Message:
|
|
101
|
+
"""Generate a sample Message with Lorem Ipsum text.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
Message: A Message object containing Lorem Ipsum text
|
|
105
|
+
"""
|
|
106
|
+
lorem_ipsum_texts = [
|
|
107
|
+
(
|
|
108
|
+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor "
|
|
109
|
+
"incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "
|
|
110
|
+
"exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
|
111
|
+
),
|
|
112
|
+
(
|
|
113
|
+
"Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "
|
|
114
|
+
"pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
|
|
115
|
+
"mollit anim id est laborum."
|
|
116
|
+
),
|
|
117
|
+
(
|
|
118
|
+
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, "
|
|
119
|
+
"totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto "
|
|
120
|
+
"beatae vitae dicta sunt explicabo."
|
|
121
|
+
),
|
|
122
|
+
(
|
|
123
|
+
"Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, "
|
|
124
|
+
"sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt."
|
|
125
|
+
),
|
|
126
|
+
(
|
|
127
|
+
"Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, "
|
|
128
|
+
"adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore "
|
|
129
|
+
"magnam aliquam quaerat voluptatem."
|
|
130
|
+
),
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
selected_text = secrets.choice(lorem_ipsum_texts)
|
|
134
|
+
return Message(text=selected_text)
|
|
135
|
+
|
|
136
|
+
def _generate_data(self, record_count: int) -> Data:
|
|
137
|
+
"""Generate sample Data with JSON structure.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
record_count: Number of records to generate
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Data: A Data object containing sample JSON data
|
|
144
|
+
"""
|
|
145
|
+
# Sample data categories
|
|
146
|
+
companies = [
|
|
147
|
+
"TechCorp",
|
|
148
|
+
"DataSystems",
|
|
149
|
+
"CloudWorks",
|
|
150
|
+
"InnovateLab",
|
|
151
|
+
"DigitalFlow",
|
|
152
|
+
"SmartSolutions",
|
|
153
|
+
"FutureTech",
|
|
154
|
+
"NextGen",
|
|
155
|
+
]
|
|
156
|
+
departments = ["Engineering", "Sales", "Marketing", "HR", "Finance", "Operations", "Support", "Research"]
|
|
157
|
+
statuses = ["active", "pending", "completed", "cancelled", "in_progress"]
|
|
158
|
+
categories = ["A", "B", "C", "D"]
|
|
159
|
+
|
|
160
|
+
# Generate sample records
|
|
161
|
+
records = []
|
|
162
|
+
base_date = datetime.now(tz=timezone.utc) - timedelta(days=365)
|
|
163
|
+
|
|
164
|
+
for i in range(record_count):
|
|
165
|
+
record = {
|
|
166
|
+
"id": f"REC-{1000 + i}",
|
|
167
|
+
"name": f"Sample Record {i + 1}",
|
|
168
|
+
"company": secrets.choice(companies),
|
|
169
|
+
"department": secrets.choice(departments),
|
|
170
|
+
"status": secrets.choice(statuses),
|
|
171
|
+
"category": secrets.choice(categories),
|
|
172
|
+
"value": round(secrets.randbelow(9901) + 100 + secrets.randbelow(100) / 100, 2),
|
|
173
|
+
"quantity": secrets.randbelow(100) + 1,
|
|
174
|
+
"rating": round(secrets.randbelow(41) / 10 + 1, 1),
|
|
175
|
+
"is_active": secrets.choice([True, False]),
|
|
176
|
+
"created_date": (base_date + timedelta(days=secrets.randbelow(366))).isoformat(),
|
|
177
|
+
"tags": [
|
|
178
|
+
secrets.choice(
|
|
179
|
+
[
|
|
180
|
+
"important",
|
|
181
|
+
"urgent",
|
|
182
|
+
"review",
|
|
183
|
+
"approved",
|
|
184
|
+
"draft",
|
|
185
|
+
"final",
|
|
186
|
+
]
|
|
187
|
+
)
|
|
188
|
+
for _ in range(secrets.randbelow(3) + 1)
|
|
189
|
+
],
|
|
190
|
+
}
|
|
191
|
+
records.append(record)
|
|
192
|
+
|
|
193
|
+
# Create the main data structure
|
|
194
|
+
data_structure = {
|
|
195
|
+
"records": records,
|
|
196
|
+
"summary": {
|
|
197
|
+
"total_count": record_count,
|
|
198
|
+
"active_count": sum(1 for r in records if r["is_active"]),
|
|
199
|
+
"total_value": sum(r["value"] for r in records),
|
|
200
|
+
"average_rating": round(sum(r["rating"] for r in records) / record_count, 2),
|
|
201
|
+
"categories": list({r["category"] for r in records}),
|
|
202
|
+
"companies": list({r["company"] for r in records}),
|
|
203
|
+
},
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return Data(data=data_structure)
|
|
207
|
+
|
|
208
|
+
def _generate_dataframe(self, record_count: int) -> DataFrame:
|
|
209
|
+
"""Generate sample DataFrame with realistic business data.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
record_count: Number of rows to generate
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
DataFrame: A Langflow DataFrame with sample data
|
|
216
|
+
"""
|
|
217
|
+
try:
|
|
218
|
+
import pandas as pd
|
|
219
|
+
|
|
220
|
+
self.log(f"pandas imported successfully, version: {pd.__version__}")
|
|
221
|
+
except ImportError as e:
|
|
222
|
+
self.log(f"pandas not available: {e!s}, creating simple DataFrame fallback")
|
|
223
|
+
# Create a simple DataFrame-like structure without pandas
|
|
224
|
+
data_result = self._generate_data(record_count)
|
|
225
|
+
# Convert Data to simple DataFrame format
|
|
226
|
+
try:
|
|
227
|
+
# Create a basic DataFrame structure from the Data
|
|
228
|
+
records = data_result.data.get("records", [])
|
|
229
|
+
if records:
|
|
230
|
+
# Use first record to get column names
|
|
231
|
+
columns = list(records[0].keys()) if records else ["error"]
|
|
232
|
+
rows = [list(record.values()) for record in records]
|
|
233
|
+
else:
|
|
234
|
+
columns = ["error"]
|
|
235
|
+
rows = [["pandas not available"]]
|
|
236
|
+
|
|
237
|
+
# Create a simple dict-based DataFrame representation
|
|
238
|
+
simple_df_data = {
|
|
239
|
+
col: [row[i] if i < len(row) else None for row in rows] for i, col in enumerate(columns)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
# Return as DataFrame wrapper (Langflow will handle the display)
|
|
243
|
+
return DataFrame(simple_df_data)
|
|
244
|
+
except (ValueError, TypeError):
|
|
245
|
+
# Ultimate fallback - return the Data as DataFrame
|
|
246
|
+
return DataFrame({"data": [str(data_result.data)]})
|
|
247
|
+
|
|
248
|
+
try:
|
|
249
|
+
self.log(f"Starting DataFrame generation with {record_count} records")
|
|
250
|
+
|
|
251
|
+
# Sample data for realistic business dataset
|
|
252
|
+
first_names = [
|
|
253
|
+
"John",
|
|
254
|
+
"Jane",
|
|
255
|
+
"Michael",
|
|
256
|
+
"Sarah",
|
|
257
|
+
"David",
|
|
258
|
+
"Emily",
|
|
259
|
+
"Robert",
|
|
260
|
+
"Lisa",
|
|
261
|
+
"William",
|
|
262
|
+
"Jennifer",
|
|
263
|
+
]
|
|
264
|
+
last_names = [
|
|
265
|
+
"Smith",
|
|
266
|
+
"Johnson",
|
|
267
|
+
"Williams",
|
|
268
|
+
"Brown",
|
|
269
|
+
"Jones",
|
|
270
|
+
"Garcia",
|
|
271
|
+
"Miller",
|
|
272
|
+
"Davis",
|
|
273
|
+
"Rodriguez",
|
|
274
|
+
"Martinez",
|
|
275
|
+
]
|
|
276
|
+
cities = [
|
|
277
|
+
"New York",
|
|
278
|
+
"Los Angeles",
|
|
279
|
+
"Chicago",
|
|
280
|
+
"Houston",
|
|
281
|
+
"Phoenix",
|
|
282
|
+
"Philadelphia",
|
|
283
|
+
"San Antonio",
|
|
284
|
+
"San Diego",
|
|
285
|
+
"Dallas",
|
|
286
|
+
"San Jose",
|
|
287
|
+
]
|
|
288
|
+
countries = ["USA", "Canada", "UK", "Germany", "France", "Australia", "Japan", "Brazil", "India", "Mexico"]
|
|
289
|
+
products = [
|
|
290
|
+
"Product A",
|
|
291
|
+
"Product B",
|
|
292
|
+
"Product C",
|
|
293
|
+
"Product D",
|
|
294
|
+
"Product E",
|
|
295
|
+
"Service X",
|
|
296
|
+
"Service Y",
|
|
297
|
+
"Service Z",
|
|
298
|
+
]
|
|
299
|
+
|
|
300
|
+
# Generate DataFrame data
|
|
301
|
+
data = []
|
|
302
|
+
base_date = datetime.now(tz=timezone.utc) - timedelta(days=365)
|
|
303
|
+
|
|
304
|
+
self.log("Generating row data...")
|
|
305
|
+
for i in range(record_count):
|
|
306
|
+
row = {
|
|
307
|
+
"customer_id": f"CUST-{10000 + i}",
|
|
308
|
+
"first_name": secrets.choice(first_names),
|
|
309
|
+
"last_name": secrets.choice(last_names),
|
|
310
|
+
"email": f"user{i + 1}@example.com",
|
|
311
|
+
"age": secrets.randbelow(63) + 18,
|
|
312
|
+
"city": secrets.choice(cities),
|
|
313
|
+
"country": secrets.choice(countries),
|
|
314
|
+
"product": secrets.choice(products),
|
|
315
|
+
"order_date": (base_date + timedelta(days=secrets.randbelow(366))).strftime("%Y-%m-%d"),
|
|
316
|
+
"order_value": round(secrets.randbelow(991) + 10 + secrets.randbelow(100) / 100, 2),
|
|
317
|
+
"quantity": secrets.randbelow(10) + 1,
|
|
318
|
+
"discount": round(secrets.randbelow(31) / 100, 2),
|
|
319
|
+
"is_premium": secrets.choice([True, False]),
|
|
320
|
+
"satisfaction_score": secrets.randbelow(10) + 1,
|
|
321
|
+
"last_contact": (base_date + timedelta(days=secrets.randbelow(366))).strftime("%Y-%m-%d"),
|
|
322
|
+
}
|
|
323
|
+
data.append(row)
|
|
324
|
+
# Create DataFrame
|
|
325
|
+
self.log("Creating pandas DataFrame...")
|
|
326
|
+
df = pd.DataFrame(data)
|
|
327
|
+
self.log(f"DataFrame created with shape: {df.shape}")
|
|
328
|
+
|
|
329
|
+
# Add calculated columns
|
|
330
|
+
self.log("Adding calculated columns...")
|
|
331
|
+
df["full_name"] = df["first_name"] + " " + df["last_name"]
|
|
332
|
+
df["discounted_value"] = df["order_value"] * (1 - df["discount"])
|
|
333
|
+
df["total_value"] = df["discounted_value"] * df["quantity"]
|
|
334
|
+
|
|
335
|
+
# Age group boundaries as constants
|
|
336
|
+
age_group_18_25 = 25
|
|
337
|
+
age_group_26_35 = 35
|
|
338
|
+
age_group_36_50 = 50
|
|
339
|
+
age_group_51_65 = 65
|
|
340
|
+
|
|
341
|
+
# Create age groups with better error handling
|
|
342
|
+
try:
|
|
343
|
+
df["age_group"] = pd.cut(
|
|
344
|
+
df["age"],
|
|
345
|
+
bins=[
|
|
346
|
+
0,
|
|
347
|
+
age_group_18_25,
|
|
348
|
+
age_group_26_35,
|
|
349
|
+
age_group_36_50,
|
|
350
|
+
age_group_51_65,
|
|
351
|
+
100,
|
|
352
|
+
],
|
|
353
|
+
labels=[
|
|
354
|
+
"18-25",
|
|
355
|
+
"26-35",
|
|
356
|
+
"36-50",
|
|
357
|
+
"51-65",
|
|
358
|
+
"65+",
|
|
359
|
+
],
|
|
360
|
+
)
|
|
361
|
+
except (ValueError, TypeError) as e:
|
|
362
|
+
self.log(f"Error creating age groups with pd.cut: {e!s}, using simple categorization")
|
|
363
|
+
df["age_group"] = df["age"].apply(
|
|
364
|
+
lambda x: "18-25"
|
|
365
|
+
if x <= age_group_18_25
|
|
366
|
+
else "26-35"
|
|
367
|
+
if x <= age_group_26_35
|
|
368
|
+
else "36-50"
|
|
369
|
+
if x <= age_group_36_50
|
|
370
|
+
else "51-65"
|
|
371
|
+
if x <= age_group_51_65
|
|
372
|
+
else "65+"
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
self.log(f"Successfully generated DataFrame with shape: {df.shape}, columns: {list(df.columns)}")
|
|
376
|
+
# CRITICAL: Use DataFrame wrapper from Langflow
|
|
377
|
+
# DO NOT set self.status when returning DataFrames - it interferes with display
|
|
378
|
+
return DataFrame(df)
|
|
379
|
+
|
|
380
|
+
except (ValueError, TypeError) as e:
|
|
381
|
+
error_msg = f"Error generating DataFrame: {e!s}"
|
|
382
|
+
self.log(error_msg)
|
|
383
|
+
# DO NOT set self.status when returning DataFrames - it interferes with display
|
|
384
|
+
# Return a fallback DataFrame with error info using Langflow wrapper
|
|
385
|
+
try:
|
|
386
|
+
error_df = pd.DataFrame(
|
|
387
|
+
{
|
|
388
|
+
"error": [error_msg],
|
|
389
|
+
"timestamp": [datetime.now(tz=timezone.utc).isoformat()],
|
|
390
|
+
"attempted_records": [record_count],
|
|
391
|
+
}
|
|
392
|
+
)
|
|
393
|
+
return DataFrame(error_df)
|
|
394
|
+
except (ValueError, TypeError) as fallback_error:
|
|
395
|
+
# Last resort: return simple error DataFrame
|
|
396
|
+
self.log(f"Fallback also failed: {fallback_error!s}")
|
|
397
|
+
simple_error_df = pd.DataFrame({"error": [error_msg]})
|
|
398
|
+
return DataFrame(simple_error_df)
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
from urllib.parse import quote_plus
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import requests
|
|
5
|
+
from bs4 import BeautifulSoup
|
|
6
|
+
|
|
7
|
+
from lfx.custom import Component
|
|
8
|
+
from lfx.io import IntInput, MessageTextInput, Output
|
|
9
|
+
from lfx.schema import DataFrame
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class NewsSearchComponent(Component):
|
|
13
|
+
display_name = "News Search"
|
|
14
|
+
description = "Searches Google News via RSS. Returns clean article data."
|
|
15
|
+
documentation: str = "https://docs.langflow.org/web-search"
|
|
16
|
+
icon = "newspaper"
|
|
17
|
+
name = "NewsSearch"
|
|
18
|
+
legacy = True
|
|
19
|
+
replacement = "data.WebSearch"
|
|
20
|
+
|
|
21
|
+
inputs = [
|
|
22
|
+
MessageTextInput(
|
|
23
|
+
name="query",
|
|
24
|
+
display_name="Search Query",
|
|
25
|
+
info="Search keywords for news articles.",
|
|
26
|
+
tool_mode=True,
|
|
27
|
+
required=True,
|
|
28
|
+
),
|
|
29
|
+
MessageTextInput(
|
|
30
|
+
name="hl",
|
|
31
|
+
display_name="Language (hl)",
|
|
32
|
+
info="Language code, e.g. en-US, fr, de. Default: en-US.",
|
|
33
|
+
tool_mode=False,
|
|
34
|
+
input_types=[],
|
|
35
|
+
required=False,
|
|
36
|
+
advanced=True,
|
|
37
|
+
),
|
|
38
|
+
MessageTextInput(
|
|
39
|
+
name="gl",
|
|
40
|
+
display_name="Country (gl)",
|
|
41
|
+
info="Country code, e.g. US, FR, DE. Default: US.",
|
|
42
|
+
tool_mode=False,
|
|
43
|
+
input_types=[],
|
|
44
|
+
required=False,
|
|
45
|
+
advanced=True,
|
|
46
|
+
),
|
|
47
|
+
MessageTextInput(
|
|
48
|
+
name="ceid",
|
|
49
|
+
display_name="Country:Language (ceid)",
|
|
50
|
+
info="e.g. US:en, FR:fr. Default: US:en.",
|
|
51
|
+
tool_mode=False,
|
|
52
|
+
value="US:en",
|
|
53
|
+
input_types=[],
|
|
54
|
+
required=False,
|
|
55
|
+
advanced=True,
|
|
56
|
+
),
|
|
57
|
+
MessageTextInput(
|
|
58
|
+
name="topic",
|
|
59
|
+
display_name="Topic",
|
|
60
|
+
info="One of: WORLD, NATION, BUSINESS, TECHNOLOGY, ENTERTAINMENT, SCIENCE, SPORTS, HEALTH.",
|
|
61
|
+
tool_mode=False,
|
|
62
|
+
input_types=[],
|
|
63
|
+
required=False,
|
|
64
|
+
advanced=True,
|
|
65
|
+
),
|
|
66
|
+
MessageTextInput(
|
|
67
|
+
name="location",
|
|
68
|
+
display_name="Location (Geo)",
|
|
69
|
+
info="City, state, or country for location-based news. Leave blank for keyword search.",
|
|
70
|
+
tool_mode=False,
|
|
71
|
+
input_types=[],
|
|
72
|
+
required=False,
|
|
73
|
+
advanced=True,
|
|
74
|
+
),
|
|
75
|
+
IntInput(
|
|
76
|
+
name="timeout",
|
|
77
|
+
display_name="Timeout",
|
|
78
|
+
info="Timeout for the request in seconds.",
|
|
79
|
+
value=5,
|
|
80
|
+
required=False,
|
|
81
|
+
advanced=True,
|
|
82
|
+
),
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
outputs = [Output(name="articles", display_name="News Articles", method="search_news")]
|
|
86
|
+
|
|
87
|
+
def search_news(self) -> DataFrame:
|
|
88
|
+
# Defaults
|
|
89
|
+
hl = getattr(self, "hl", None) or "en-US"
|
|
90
|
+
gl = getattr(self, "gl", None) or "US"
|
|
91
|
+
ceid = getattr(self, "ceid", None) or f"{gl}:{hl.split('-')[0]}"
|
|
92
|
+
topic = getattr(self, "topic", None)
|
|
93
|
+
location = getattr(self, "location", None)
|
|
94
|
+
query = getattr(self, "query", None)
|
|
95
|
+
|
|
96
|
+
# Build base URL
|
|
97
|
+
if topic:
|
|
98
|
+
# Topic-based feed
|
|
99
|
+
base_url = f"https://news.google.com/rss/headlines/section/topic/{quote_plus(topic.upper())}"
|
|
100
|
+
params = f"?hl={hl}&gl={gl}&ceid={ceid}"
|
|
101
|
+
rss_url = base_url + params
|
|
102
|
+
elif location:
|
|
103
|
+
# Location-based feed
|
|
104
|
+
base_url = f"https://news.google.com/rss/headlines/section/geo/{quote_plus(location)}"
|
|
105
|
+
params = f"?hl={hl}&gl={gl}&ceid={ceid}"
|
|
106
|
+
rss_url = base_url + params
|
|
107
|
+
elif query:
|
|
108
|
+
# Keyword search feed
|
|
109
|
+
base_url = "https://news.google.com/rss/search?q="
|
|
110
|
+
query_parts = [query]
|
|
111
|
+
query_encoded = quote_plus(" ".join(query_parts))
|
|
112
|
+
params = f"&hl={hl}&gl={gl}&ceid={ceid}"
|
|
113
|
+
rss_url = f"{base_url}{query_encoded}{params}"
|
|
114
|
+
else:
|
|
115
|
+
self.status = "No search query, topic, or location provided."
|
|
116
|
+
self.log(self.status)
|
|
117
|
+
return DataFrame(
|
|
118
|
+
pd.DataFrame(
|
|
119
|
+
[
|
|
120
|
+
{
|
|
121
|
+
"title": "Error",
|
|
122
|
+
"link": "",
|
|
123
|
+
"published": "",
|
|
124
|
+
"summary": "No search query, topic, or location provided.",
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
try:
|
|
131
|
+
response = requests.get(rss_url, timeout=self.timeout)
|
|
132
|
+
response.raise_for_status()
|
|
133
|
+
soup = BeautifulSoup(response.content, "xml")
|
|
134
|
+
items = soup.find_all("item")
|
|
135
|
+
except requests.RequestException as e:
|
|
136
|
+
self.status = f"Failed to fetch news: {e}"
|
|
137
|
+
self.log(self.status)
|
|
138
|
+
return DataFrame(pd.DataFrame([{"title": "Error", "link": "", "published": "", "summary": str(e)}]))
|
|
139
|
+
except (AttributeError, ValueError, TypeError) as e:
|
|
140
|
+
self.status = f"Unexpected error: {e!s}"
|
|
141
|
+
self.log(self.status)
|
|
142
|
+
return DataFrame(pd.DataFrame([{"title": "Error", "link": "", "published": "", "summary": str(e)}]))
|
|
143
|
+
|
|
144
|
+
if not items:
|
|
145
|
+
self.status = "No news articles found."
|
|
146
|
+
self.log(self.status)
|
|
147
|
+
return DataFrame(pd.DataFrame([{"title": "No articles found", "link": "", "published": "", "summary": ""}]))
|
|
148
|
+
|
|
149
|
+
articles = []
|
|
150
|
+
for item in items:
|
|
151
|
+
try:
|
|
152
|
+
title = self.clean_html(item.title.text if item.title else "")
|
|
153
|
+
link = item.link.text if item.link else ""
|
|
154
|
+
published = item.pubDate.text if item.pubDate else ""
|
|
155
|
+
summary = self.clean_html(item.description.text if item.description else "")
|
|
156
|
+
articles.append({"title": title, "link": link, "published": published, "summary": summary})
|
|
157
|
+
except (AttributeError, ValueError, TypeError) as e:
|
|
158
|
+
self.log(f"Error parsing article: {e!s}")
|
|
159
|
+
continue
|
|
160
|
+
|
|
161
|
+
df_articles = pd.DataFrame(articles)
|
|
162
|
+
self.log(f"Found {len(df_articles)} articles.")
|
|
163
|
+
return DataFrame(df_articles)
|
|
164
|
+
|
|
165
|
+
def clean_html(self, html_string: str) -> str:
|
|
166
|
+
return BeautifulSoup(html_string, "html.parser").get_text(separator=" ", strip=True)
|