langflow-base-nightly 0.5.0.dev38__py3-none-any.whl → 0.5.1.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.
- langflow/alembic/versions/0882f9657f22_encrypt_existing_mcp_auth_settings_.py +122 -0
- langflow/api/router.py +2 -0
- langflow/api/v1/__init__.py +2 -0
- langflow/api/v1/endpoints.py +7 -1
- langflow/api/v1/mcp_projects.py +373 -52
- langflow/api/v1/openai_responses.py +545 -0
- langflow/api/v1/schemas.py +1 -2
- langflow/components/FAISS/__init__.py +34 -0
- langflow/components/agents/agent.py +246 -52
- langflow/components/cassandra/__init__.py +40 -0
- langflow/components/chroma/__init__.py +34 -0
- langflow/components/clickhouse/__init__.py +34 -0
- langflow/components/couchbase/__init__.py +34 -0
- langflow/components/data/file.py +302 -376
- langflow/components/datastax/__init__.py +3 -3
- langflow/components/docling/docling_inline.py +56 -4
- langflow/components/elastic/__init__.py +37 -0
- langflow/components/milvus/__init__.py +34 -0
- langflow/components/mongodb/__init__.py +34 -0
- langflow/components/nvidia/nvidia_ingest.py +3 -2
- langflow/components/ollama/ollama.py +1 -0
- langflow/components/perplexity/perplexity.py +3 -13
- langflow/components/pgvector/__init__.py +34 -0
- langflow/components/pinecone/__init__.py +34 -0
- langflow/components/qdrant/__init__.py +34 -0
- langflow/components/redis/__init__.py +36 -2
- langflow/components/redis/redis.py +75 -29
- langflow/components/redis/redis_chat.py +43 -0
- langflow/components/supabase/__init__.py +37 -0
- langflow/components/upstash/__init__.py +34 -0
- langflow/components/vectara/__init__.py +37 -0
- langflow/components/vectorstores/__init__.py +0 -69
- langflow/components/vectorstores/local_db.py +1 -0
- langflow/components/weaviate/__init__.py +34 -0
- langflow/components/youtube/channel.py +1 -1
- langflow/custom/custom_component/custom_component.py +11 -0
- langflow/custom/dependency_analyzer.py +165 -0
- langflow/custom/utils.py +34 -16
- langflow/frontend/assets/{SlackIcon-BhW6H3JR.js → SlackIcon-Cr3Q15Px.js} +1 -1
- langflow/frontend/assets/{Wikipedia-Dx5jbiy3.js → Wikipedia-GxM5sPdM.js} +1 -1
- langflow/frontend/assets/{Wolfram-CIyonzwo.js → Wolfram-BN3-VOCA.js} +1 -1
- langflow/frontend/assets/{index-DOEvKC2X.js → index-28oOcafk.js} +1 -1
- langflow/frontend/assets/{index-Bhv79Zso.js → index-2wSXqBtB.js} +1 -1
- langflow/frontend/assets/{index-BRmSeoWR.js → index-3wW7BClE.js} +1 -1
- langflow/frontend/assets/{index-eUkS6iJM.js → index-6pyH3ZJB.js} +1 -1
- langflow/frontend/assets/{index-Cr5v2ave.js → index-AWCSdofD.js} +1 -1
- langflow/frontend/assets/{index-C27Jj_26.js → index-B2Zgv_xv.js} +1 -1
- langflow/frontend/assets/{index-BKKrUElc.js → index-B2ptVQGM.js} +1 -1
- langflow/frontend/assets/{index-BnAFhkSN.js → index-B3TANVes.js} +1 -1
- langflow/frontend/assets/{index-hZUcL0MZ.js → index-B4yCvZKV.js} +1 -1
- langflow/frontend/assets/{index-BPR2mEFC.js → index-BC65VuWx.js} +1 -1
- langflow/frontend/assets/{index-CgU7KF4I.js → index-BCDSei1q.js} +1 -1
- langflow/frontend/assets/{index-CzHzeZuA.js → index-BJy50PvP.js} +1 -1
- langflow/frontend/assets/{index-DkGhPNeA.js → index-BKseQQ2I.js} +1 -1
- langflow/frontend/assets/{index-BVFaF7HW.js → index-BLTxEeTi.js} +1 -1
- langflow/frontend/assets/{index-cEXY6V06.js → index-BRg1f4Mu.js} +1 -1
- langflow/frontend/assets/{index-C2eQmQsn.js → index-BS8Vo8nc.js} +1 -1
- langflow/frontend/assets/{index-gdb7XMS8.js → index-BTKOU4xC.js} +1 -1
- langflow/frontend/assets/{index-U9GWm1eH.js → index-BVwJDmw-.js} +1 -1
- langflow/frontend/assets/{index-BWt5xGeA.js → index-BWYuQ2Sj.js} +1 -1
- langflow/frontend/assets/{index-Dx-Z87KT.js → index-BWdLILDG.js} +1 -1
- langflow/frontend/assets/{index-paQEWYGT.js → index-BZcw4827.js} +1 -1
- langflow/frontend/assets/{index-BDQrd7Tj.js → index-Bbi87Ve4.js} +1 -1
- langflow/frontend/assets/{index-vJOO5U8M.js → index-Bf0IYKLd.js} +1 -1
- langflow/frontend/assets/{index-1Q3VBqKn.js → index-Bg5nrMRh.js} +1 -1
- langflow/frontend/assets/{index-BFQ8KFK0.js → index-BiC280Nx.js} +1 -1
- langflow/frontend/assets/{index-CFNTYfFK.js → index-BiKKN6FR.js} +1 -1
- langflow/frontend/assets/{index-BPfdqCc_.js → index-Bief6eyJ.js} +1 -1
- langflow/frontend/assets/{index-Cxy9sEpy.js → index-BkXec1Yf.js} +1 -1
- langflow/frontend/assets/{index-D4tjMhfY.js → index-Bnl6QHtP.js} +1 -1
- langflow/frontend/assets/{index-BD7Io1hL.js → index-BpxbUiZD.js} +1978 -1978
- langflow/frontend/assets/{index-Ch5r0oW6.js → index-BrJV8psX.js} +1 -1
- langflow/frontend/assets/{index-DOQDkSoK.js → index-BwLWcUXL.js} +1 -1
- langflow/frontend/assets/{index-CMHpjHZl.js → index-Bx7dBY26.js} +1 -1
- langflow/frontend/assets/{index-CbnWRlYY.js → index-C-EdnFdA.js} +1 -1
- langflow/frontend/assets/{index-DljpLeCW.js → index-C-Xfg4cD.js} +1 -1
- langflow/frontend/assets/{index-Bwi4flFg.js → index-C1f2wMat.js} +1 -1
- langflow/frontend/assets/index-C1xroOlH.css +1 -0
- langflow/frontend/assets/{index-D6CSIrp1.js → index-C3KequvP.js} +1 -1
- langflow/frontend/assets/{index-BYjw7Gk3.js → index-C3ZjKdCD.js} +1 -1
- langflow/frontend/assets/{index-DIKUsGLF.js → index-C3l0zYn0.js} +1 -1
- langflow/frontend/assets/{index-CfPBgkqg.js → index-C3yvArUT.js} +1 -1
- langflow/frontend/assets/{index-CsLQiWNf.js → index-C9Cxnkl8.js} +1 -1
- langflow/frontend/assets/{index-mzl9ULw5.js → index-CBc8fEAE.js} +1 -1
- langflow/frontend/assets/{index-CEJNWPhA.js → index-CBvrGgID.js} +1 -1
- langflow/frontend/assets/{index-DwfHWnX7.js → index-CD-PqGCY.js} +1 -1
- langflow/frontend/assets/{index-dyXKnkMi.js → index-CGO1CiUr.js} +1 -1
- langflow/frontend/assets/{index-Dka_Rk4-.js → index-CH5UVA9b.js} +1 -1
- langflow/frontend/assets/{index-uiKla4UR.js → index-CLJeJYjH.js} +1 -1
- langflow/frontend/assets/{index-D9kwEzPB.js → index-CMZ79X-Y.js} +1 -1
- langflow/frontend/assets/{index-BrVhdPZb.js → index-CMzfJKiW.js} +1 -1
- langflow/frontend/assets/{index-Bct1s6__.js → index-CNw1H-Wc.js} +1 -1
- langflow/frontend/assets/{index-B7uEuOPK.js → index-CPHEscq9.js} +1 -1
- langflow/frontend/assets/{index-ekfMOqrF.js → index-CRPKJZw9.js} +1 -1
- langflow/frontend/assets/{index-G4ro0MjT.js → index-CRPyCfYy.js} +1 -1
- langflow/frontend/assets/{index-CSu8KHOi.js → index-CRcMqCIj.js} +1 -1
- langflow/frontend/assets/{index-DsoX2o1S.js → index-CUVDws8F.js} +1 -1
- langflow/frontend/assets/{index-r_8gs4nL.js → index-CVWQfRYZ.js} +1 -1
- langflow/frontend/assets/{index-7hzXChQz.js → index-CVl6MbaM.js} +1 -1
- langflow/frontend/assets/{index-B8UR8v-Q.js → index-CVwWoX99.js} +1 -1
- langflow/frontend/assets/{index-Dda2u_yz.js → index-CWPzZtSx.js} +1 -1
- langflow/frontend/assets/{index-BKeZt2hQ.js → index-CZqRL9DE.js} +1 -1
- langflow/frontend/assets/{index-DHngW1k8.js → index-CdIf07Rw.js} +1 -1
- langflow/frontend/assets/{index-C--IDAyc.js → index-Cewy7JZE.js} +1 -1
- langflow/frontend/assets/{index-DZP_SaHb.js → index-CfwLpbMM.js} +1 -1
- langflow/frontend/assets/{index-CuCM7Wu7.js → index-CiR1dxI4.js} +1 -1
- langflow/frontend/assets/{index-Xi4TplbI.js → index-CiixOzDG.js} +1 -1
- langflow/frontend/assets/{index-BLYw9MK2.js → index-ClsuDmR6.js} +1 -1
- langflow/frontend/assets/{index-DMCWDJOl.js → index-CmEYYRN1.js} +1 -1
- langflow/frontend/assets/{index-CrAF-31Y.js → index-Co20d-eQ.js} +1 -1
- langflow/frontend/assets/{index-DXAfIEvs.js → index-CpzXS6md.js} +1 -1
- langflow/frontend/assets/{index-BmYJJ5YS.js → index-Cqpzl1J4.js} +1 -1
- langflow/frontend/assets/{index-KWY77KfV.js → index-CtVIONP2.js} +1 -1
- langflow/frontend/assets/{index-B3KCdQ91.js → index-CuFXdTx4.js} +1 -1
- langflow/frontend/assets/{index-p2kStSPe.js → index-Cyd2HtHK.js} +1 -1
- langflow/frontend/assets/{index-CkjwSTSM.js → index-D-1tA8Dt.js} +1 -1
- langflow/frontend/assets/{index-BFf0HTFI.js → index-D-KY3kkq.js} +1 -1
- langflow/frontend/assets/{index-BYhcGLTV.js → index-D-_B1a8v.js} +1 -1
- langflow/frontend/assets/{index-Dr6pVDPI.js → index-D14EWPyZ.js} +1 -1
- langflow/frontend/assets/{index-BDuk0d7P.js → index-D2N3l-cw.js} +1 -1
- langflow/frontend/assets/{index-BvGQfVBD.js → index-D5ETnvJa.js} +1 -1
- langflow/frontend/assets/{index-D1oynC8a.js → index-D7kquVv2.js} +1 -1
- langflow/frontend/assets/{index-B1XqWJhG.js → index-DA6-bvgN.js} +1 -1
- langflow/frontend/assets/{index-DzIv3RyR.js → index-DDWBeudF.js} +1 -1
- langflow/frontend/assets/{index-BKlQbl-6.js → index-DDcMAaG4.js} +1 -1
- langflow/frontend/assets/{index-CkK25zZO.js → index-DHgomBdh.js} +1 -1
- langflow/frontend/assets/{index-Bj3lSwvZ.js → index-DJP-ss47.js} +1 -1
- langflow/frontend/assets/{index-DDXsm8tz.js → index-DQ7VYqQc.js} +1 -1
- langflow/frontend/assets/{index-BNQIbda3.js → index-DTqbvGC0.js} +1 -1
- langflow/frontend/assets/{index-BzoRPtTY.js → index-DUpri6zF.js} +1 -1
- langflow/frontend/assets/{index-35sspuLu.js → index-DV3utZDZ.js} +1 -1
- langflow/frontend/assets/{index-BpmqDOeZ.js → index-DXRfN4HV.js} +1 -1
- langflow/frontend/assets/{index-C0E3_MIK.js → index-Db9dYSzy.js} +1 -1
- langflow/frontend/assets/{index-C8K0r39B.js → index-DdtMEn6I.js} +1 -1
- langflow/frontend/assets/{index-BLsVo9iW.js → index-DfDhMHgQ.js} +1 -1
- langflow/frontend/assets/{index-BZFljdMa.js → index-Dfe7qfvf.js} +1 -1
- langflow/frontend/assets/{index-CyP3py8K.js → index-DhtZ5hx8.js} +1 -1
- langflow/frontend/assets/{index-w72fDjpG.js → index-DiB3CTo8.js} +1 -1
- langflow/frontend/assets/{index-CY7_TBTC.js → index-DiGWASY5.js} +1 -1
- langflow/frontend/assets/{index-CmSFKgiD.js → index-Dl5amdBz.js} +1 -1
- langflow/frontend/assets/{index-B0m53xKd.js → index-DlD4dXlZ.js} +1 -1
- langflow/frontend/assets/{index-DnVYJtVO.js → index-DmeiHnfl.js} +1 -1
- langflow/frontend/assets/index-Dmu-X5-4.js +1 -0
- langflow/frontend/assets/{index-CWYiSeWV.js → index-DpVWih90.js} +1 -1
- langflow/frontend/assets/{index-CjsommIr.js → index-DrDrcajG.js} +1 -1
- langflow/frontend/assets/{index-Un9pWxnP.js → index-Du-pc0KE.js} +1 -1
- langflow/frontend/assets/{index-oxHBZk2v.js → index-DwPkMTaY.js} +1 -1
- langflow/frontend/assets/{index-CgwykVGh.js → index-DwQEZe3C.js} +1 -1
- langflow/frontend/assets/{index-BmIx1cws.js → index-DyJFTK24.js} +1 -1
- langflow/frontend/assets/{index-0XQqYgdG.js → index-J38wh62w.js} +1 -1
- langflow/frontend/assets/{index-H7J7w7fa.js → index-Kwdl-e29.js} +1 -1
- langflow/frontend/assets/{index-CUKmGsI6.js → index-OwPvCmpW.js} +1 -1
- langflow/frontend/assets/{index-zV82kQ6k.js → index-Tw3Os-DN.js} +1 -1
- langflow/frontend/assets/{index-8cuhogZP.js → index-X0guhYF8.js} +1 -1
- langflow/frontend/assets/{index-BUse-kxM.js → index-dJWNxIRH.js} +1 -1
- langflow/frontend/assets/{index-DyqITq51.js → index-dcJ8-agu.js} +1 -1
- langflow/frontend/assets/{index-Cg53lrYh.js → index-eo2mAtL-.js} +1 -1
- langflow/frontend/assets/{index-DqbzUcI5.js → index-hG24k5xJ.js} +1 -1
- langflow/frontend/assets/{index-BQrVDjR1.js → index-h_aSZHf3.js} +1 -1
- langflow/frontend/assets/{index-kkA-qHB_.js → index-hbndqB9B.js} +1 -1
- langflow/frontend/assets/{index-DZxUIhWh.js → index-iJngutFo.js} +1 -1
- langflow/frontend/assets/{index-Dg8N3NSO.js → index-lTpteg8t.js} +1 -1
- langflow/frontend/assets/{index-DDhJVVel.js → index-lZX9AvZW.js} +1 -1
- langflow/frontend/assets/{index-BHhnpSkW.js → index-m8QA6VNM.js} +1 -1
- langflow/frontend/assets/{index-Bk4mTwnI.js → index-o0D2S7xW.js} +1 -1
- langflow/frontend/assets/{index-DJESSNJi.js → index-ovFJ_0J6.js} +1 -1
- langflow/frontend/assets/{index-DH6o91_s.js → index-pYJJOcma.js} +1 -1
- langflow/frontend/assets/{index-Bo-ww0Bb.js → index-sI75DsdM.js} +1 -1
- langflow/frontend/assets/{index-BcAgItH4.js → index-xvFOmxx4.js} +1 -1
- langflow/frontend/assets/{index-_cbGmjF4.js → index-z3SRY-mX.js} +1 -1
- langflow/frontend/assets/lazyIconImports-D97HEZkE.js +2 -0
- langflow/frontend/assets/{use-post-add-user-CvtuazTg.js → use-post-add-user-C0MdTpQ5.js} +1 -1
- langflow/frontend/index.html +2 -2
- langflow/graph/graph/base.py +4 -2
- langflow/initial_setup/starter_projects/Basic Prompt Chaining.json +26 -0
- langflow/initial_setup/starter_projects/Basic Prompting.json +26 -0
- langflow/initial_setup/starter_projects/Blog Writer.json +56 -0
- langflow/initial_setup/starter_projects/Custom Component Generator.json +35 -0
- langflow/initial_setup/starter_projects/Document Q&A.json +27 -1
- langflow/initial_setup/starter_projects/Financial Report Parser.json +43 -0
- langflow/initial_setup/starter_projects/Hybrid Search RAG.json +83 -1
- langflow/initial_setup/starter_projects/Image Sentiment Analysis.json +43 -0
- langflow/initial_setup/starter_projects/Instagram Copywriter.json +49 -1
- langflow/initial_setup/starter_projects/Invoice Summarizer.json +40 -1
- langflow/initial_setup/starter_projects/Knowledge Ingestion.json +71 -0
- langflow/initial_setup/starter_projects/Knowledge Retrieval.json +63 -0
- langflow/initial_setup/starter_projects/Market Research.json +57 -1
- langflow/initial_setup/starter_projects/Meeting Summary.json +95 -0
- langflow/initial_setup/starter_projects/Memory Chatbot.json +35 -0
- langflow/initial_setup/starter_projects/News Aggregator.json +61 -1
- langflow/initial_setup/starter_projects/Nvidia Remix.json +67 -2
- langflow/initial_setup/starter_projects/Pok/303/251dex Agent.json" +48 -1
- langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json +44 -1
- langflow/initial_setup/starter_projects/Price Deal Finder.json +53 -1
- langflow/initial_setup/starter_projects/Research Agent.json +40 -1
- langflow/initial_setup/starter_projects/Research Translation Loop.json +66 -0
- langflow/initial_setup/starter_projects/SEO Keyword Generator.json +17 -0
- langflow/initial_setup/starter_projects/SaaS Pricing.json +27 -1
- langflow/initial_setup/starter_projects/Search agent.json +40 -1
- langflow/initial_setup/starter_projects/Sequential Tasks Agents.json +72 -3
- langflow/initial_setup/starter_projects/Simple Agent.json +57 -1
- langflow/initial_setup/starter_projects/Social Media Agent.json +77 -1
- langflow/initial_setup/starter_projects/Text Sentiment Analysis.json +35 -1
- langflow/initial_setup/starter_projects/Travel Planning Agents.json +51 -3
- langflow/initial_setup/starter_projects/Twitter Thread Generator.json +80 -0
- langflow/initial_setup/starter_projects/Vector Store RAG.json +110 -3
- langflow/initial_setup/starter_projects/Youtube Analysis.json +82 -1
- langflow/initial_setup/starter_projects/vector_store_rag.py +1 -1
- langflow/processing/process.py +3 -0
- langflow/schema/openai_responses_schemas.py +74 -0
- langflow/services/auth/mcp_encryption.py +104 -0
- langflow/services/settings/feature_flags.py +1 -1
- {langflow_base_nightly-0.5.0.dev38.dist-info → langflow_base_nightly-0.5.1.dev0.dist-info}/METADATA +1 -1
- {langflow_base_nightly-0.5.0.dev38.dist-info → langflow_base_nightly-0.5.1.dev0.dist-info}/RECORD +239 -219
- langflow/components/vectorstores/redis.py +0 -89
- langflow/frontend/assets/index-BWgIWfv2.js +0 -1
- langflow/frontend/assets/index-CqS7zir1.css +0 -1
- langflow/frontend/assets/lazyIconImports-DTNgvPE-.js +0 -2
- /langflow/components/{vectorstores → FAISS}/faiss.py +0 -0
- /langflow/components/{vectorstores → cassandra}/cassandra.py +0 -0
- /langflow/components/{datastax/cassandra.py → cassandra/cassandra_chat.py} +0 -0
- /langflow/components/{vectorstores → cassandra}/cassandra_graph.py +0 -0
- /langflow/components/{vectorstores → chroma}/chroma.py +0 -0
- /langflow/components/{vectorstores → clickhouse}/clickhouse.py +0 -0
- /langflow/components/{vectorstores → couchbase}/couchbase.py +0 -0
- /langflow/components/{vectorstores → datastax}/astradb.py +0 -0
- /langflow/components/{vectorstores → datastax}/astradb_graph.py +0 -0
- /langflow/components/{vectorstores → datastax}/graph_rag.py +0 -0
- /langflow/components/{vectorstores → datastax}/hcd.py +0 -0
- /langflow/components/{vectorstores → elastic}/elasticsearch.py +0 -0
- /langflow/components/{vectorstores → elastic}/opensearch.py +0 -0
- /langflow/components/{vectorstores → milvus}/milvus.py +0 -0
- /langflow/components/{vectorstores → mongodb}/mongodb_atlas.py +0 -0
- /langflow/components/{vectorstores → pgvector}/pgvector.py +0 -0
- /langflow/components/{vectorstores → pinecone}/pinecone.py +0 -0
- /langflow/components/{vectorstores → qdrant}/qdrant.py +0 -0
- /langflow/components/{vectorstores → supabase}/supabase.py +0 -0
- /langflow/components/{vectorstores → upstash}/upstash.py +0 -0
- /langflow/components/{vectorstores → vectara}/vectara.py +0 -0
- /langflow/components/{vectorstores → vectara}/vectara_rag.py +0 -0
- /langflow/components/{vectorstores → weaviate}/weaviate.py +0 -0
- {langflow_base_nightly-0.5.0.dev38.dist-info → langflow_base_nightly-0.5.1.dev0.dist-info}/WHEEL +0 -0
- {langflow_base_nightly-0.5.0.dev38.dist-info → langflow_base_nightly-0.5.1.dev0.dist-info}/entry_points.txt +0 -0
|
@@ -2,6 +2,7 @@ import json
|
|
|
2
2
|
import re
|
|
3
3
|
|
|
4
4
|
from langchain_core.tools import StructuredTool
|
|
5
|
+
from pydantic import ValidationError
|
|
5
6
|
|
|
6
7
|
from langflow.base.agents.agent import LCToolsAgentComponent
|
|
7
8
|
from langflow.base.agents.events import ExceptionWithMessageError
|
|
@@ -19,11 +20,13 @@ from langflow.components.langchain_utilities.tool_calling import ToolCallingAgen
|
|
|
19
20
|
from langflow.custom.custom_component.component import _get_component_toolkit
|
|
20
21
|
from langflow.custom.utils import update_component_build_config
|
|
21
22
|
from langflow.field_typing import Tool
|
|
22
|
-
from langflow.
|
|
23
|
+
from langflow.helpers.base_model import build_model_from_schema
|
|
24
|
+
from langflow.io import BoolInput, DropdownInput, IntInput, MultilineInput, Output, TableInput
|
|
23
25
|
from langflow.logging import logger
|
|
24
26
|
from langflow.schema.data import Data
|
|
25
27
|
from langflow.schema.dotdict import dotdict
|
|
26
28
|
from langflow.schema.message import Message
|
|
29
|
+
from langflow.schema.table import EditMode
|
|
27
30
|
|
|
28
31
|
|
|
29
32
|
def set_advanced_true(component_input):
|
|
@@ -78,6 +81,67 @@ class AgentComponent(ToolCallingAgentComponent):
|
|
|
78
81
|
advanced=True,
|
|
79
82
|
show=True,
|
|
80
83
|
),
|
|
84
|
+
MultilineInput(
|
|
85
|
+
name="format_instructions",
|
|
86
|
+
display_name="Output Format Instructions",
|
|
87
|
+
info="Generic Template for structured output formatting. Valid only with Structured response.",
|
|
88
|
+
value=(
|
|
89
|
+
"You are an AI that extracts structured JSON objects from unstructured text. "
|
|
90
|
+
"Use a predefined schema with expected types (str, int, float, bool, dict). "
|
|
91
|
+
"Extract ALL relevant instances that match the schema - if multiple patterns exist, capture them all. "
|
|
92
|
+
"Fill missing or ambiguous values with defaults: null for missing values. "
|
|
93
|
+
"Remove exact duplicates but keep variations that have different field values. "
|
|
94
|
+
"Always return valid JSON in the expected format, never throw errors. "
|
|
95
|
+
"If multiple objects can be extracted, return them all in the structured format."
|
|
96
|
+
),
|
|
97
|
+
advanced=True,
|
|
98
|
+
),
|
|
99
|
+
TableInput(
|
|
100
|
+
name="output_schema",
|
|
101
|
+
display_name="Output Schema",
|
|
102
|
+
info=(
|
|
103
|
+
"Schema Validation: Define the structure and data types for structured output. "
|
|
104
|
+
"No validation if no output schema."
|
|
105
|
+
),
|
|
106
|
+
advanced=True,
|
|
107
|
+
required=False,
|
|
108
|
+
value=[],
|
|
109
|
+
table_schema=[
|
|
110
|
+
{
|
|
111
|
+
"name": "name",
|
|
112
|
+
"display_name": "Name",
|
|
113
|
+
"type": "str",
|
|
114
|
+
"description": "Specify the name of the output field.",
|
|
115
|
+
"default": "field",
|
|
116
|
+
"edit_mode": EditMode.INLINE,
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"name": "description",
|
|
120
|
+
"display_name": "Description",
|
|
121
|
+
"type": "str",
|
|
122
|
+
"description": "Describe the purpose of the output field.",
|
|
123
|
+
"default": "description of field",
|
|
124
|
+
"edit_mode": EditMode.POPOVER,
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"name": "type",
|
|
128
|
+
"display_name": "Type",
|
|
129
|
+
"type": "str",
|
|
130
|
+
"edit_mode": EditMode.INLINE,
|
|
131
|
+
"description": ("Indicate the data type of the output field (e.g., str, int, float, bool, dict)."),
|
|
132
|
+
"options": ["str", "int", "float", "bool", "dict"],
|
|
133
|
+
"default": "str",
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "multiple",
|
|
137
|
+
"display_name": "As List",
|
|
138
|
+
"type": "boolean",
|
|
139
|
+
"description": "Set to True if this output field should be a list of the specified type.",
|
|
140
|
+
"default": "False",
|
|
141
|
+
"edit_mode": EditMode.INLINE,
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
),
|
|
81
145
|
*LCToolsAgentComponent._base_inputs,
|
|
82
146
|
# removed memory inputs from agent component
|
|
83
147
|
# *memory_inputs,
|
|
@@ -94,31 +158,33 @@ class AgentComponent(ToolCallingAgentComponent):
|
|
|
94
158
|
Output(name="structured_response", display_name="Structured Response", method="json_response", tool_mode=False),
|
|
95
159
|
]
|
|
96
160
|
|
|
161
|
+
async def get_agent_requirements(self):
|
|
162
|
+
"""Get the agent requirements for the agent."""
|
|
163
|
+
llm_model, display_name = await self.get_llm()
|
|
164
|
+
if llm_model is None:
|
|
165
|
+
msg = "No language model selected. Please choose a model to proceed."
|
|
166
|
+
raise ValueError(msg)
|
|
167
|
+
self.model_name = get_model_name(llm_model, display_name=display_name)
|
|
168
|
+
|
|
169
|
+
# Get memory data
|
|
170
|
+
self.chat_history = await self.get_memory_data()
|
|
171
|
+
if isinstance(self.chat_history, Message):
|
|
172
|
+
self.chat_history = [self.chat_history]
|
|
173
|
+
|
|
174
|
+
# Add current date tool if enabled
|
|
175
|
+
if self.add_current_date_tool:
|
|
176
|
+
if not isinstance(self.tools, list): # type: ignore[has-type]
|
|
177
|
+
self.tools = []
|
|
178
|
+
current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)
|
|
179
|
+
if not isinstance(current_date_tool, StructuredTool):
|
|
180
|
+
msg = "CurrentDateComponent must be converted to a StructuredTool"
|
|
181
|
+
raise TypeError(msg)
|
|
182
|
+
self.tools.append(current_date_tool)
|
|
183
|
+
return llm_model, self.chat_history, self.tools
|
|
184
|
+
|
|
97
185
|
async def message_response(self) -> Message:
|
|
98
186
|
try:
|
|
99
|
-
|
|
100
|
-
llm_model, display_name = self.get_llm()
|
|
101
|
-
if llm_model is None:
|
|
102
|
-
msg = "No language model selected. Please choose a model to proceed."
|
|
103
|
-
raise ValueError(msg)
|
|
104
|
-
self.model_name = get_model_name(llm_model, display_name=display_name)
|
|
105
|
-
|
|
106
|
-
# Get memory data
|
|
107
|
-
self.chat_history = await self.get_memory_data()
|
|
108
|
-
if isinstance(self.chat_history, Message):
|
|
109
|
-
self.chat_history = [self.chat_history]
|
|
110
|
-
|
|
111
|
-
# Add current date tool if enabled
|
|
112
|
-
if self.add_current_date_tool:
|
|
113
|
-
if not isinstance(self.tools, list): # type: ignore[has-type]
|
|
114
|
-
self.tools = []
|
|
115
|
-
current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)
|
|
116
|
-
if not isinstance(current_date_tool, StructuredTool):
|
|
117
|
-
msg = "CurrentDateComponent must be converted to a StructuredTool"
|
|
118
|
-
raise TypeError(msg)
|
|
119
|
-
self.tools.append(current_date_tool)
|
|
120
|
-
# note the tools are not required to run the agent, hence the validation removed.
|
|
121
|
-
|
|
187
|
+
llm_model, self.chat_history, self.tools = await self.get_agent_requirements()
|
|
122
188
|
# Set up and run agent
|
|
123
189
|
self.set(
|
|
124
190
|
llm=llm_model,
|
|
@@ -132,7 +198,6 @@ class AgentComponent(ToolCallingAgentComponent):
|
|
|
132
198
|
|
|
133
199
|
# Store result for potential JSON output
|
|
134
200
|
self._agent_result = result
|
|
135
|
-
# return result
|
|
136
201
|
|
|
137
202
|
except (ValueError, TypeError, KeyError) as e:
|
|
138
203
|
await logger.aerror(f"{type(e).__name__}: {e!s}")
|
|
@@ -140,44 +205,173 @@ class AgentComponent(ToolCallingAgentComponent):
|
|
|
140
205
|
except ExceptionWithMessageError as e:
|
|
141
206
|
await logger.aerror(f"ExceptionWithMessageError occurred: {e}")
|
|
142
207
|
raise
|
|
208
|
+
# Avoid catching blind Exception; let truly unexpected exceptions propagate
|
|
143
209
|
except Exception as e:
|
|
144
210
|
await logger.aerror(f"Unexpected error: {e!s}")
|
|
145
211
|
raise
|
|
146
212
|
else:
|
|
147
213
|
return result
|
|
148
214
|
|
|
149
|
-
|
|
150
|
-
"""
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
215
|
+
def _preprocess_schema(self, schema):
|
|
216
|
+
"""Preprocess schema to ensure correct data types for build_model_from_schema."""
|
|
217
|
+
processed_schema = []
|
|
218
|
+
for field in schema:
|
|
219
|
+
processed_field = {
|
|
220
|
+
"name": str(field.get("name", "field")),
|
|
221
|
+
"type": str(field.get("type", "str")),
|
|
222
|
+
"description": str(field.get("description", "")),
|
|
223
|
+
"multiple": field.get("multiple", False),
|
|
224
|
+
}
|
|
225
|
+
# Ensure multiple is handled correctly
|
|
226
|
+
if isinstance(processed_field["multiple"], str):
|
|
227
|
+
processed_field["multiple"] = processed_field["multiple"].lower() in ["true", "1", "t", "y", "yes"]
|
|
228
|
+
processed_schema.append(processed_field)
|
|
229
|
+
return processed_schema
|
|
230
|
+
|
|
231
|
+
async def build_structured_output_base(self, content: str):
|
|
232
|
+
"""Build structured output with optional BaseModel validation."""
|
|
233
|
+
json_pattern = r"\{.*\}"
|
|
234
|
+
schema_error_msg = "Try setting an output schema"
|
|
235
|
+
|
|
236
|
+
# Try to parse content as JSON first
|
|
237
|
+
json_data = None
|
|
166
238
|
try:
|
|
167
239
|
json_data = json.loads(content)
|
|
168
|
-
return Data(data=json_data)
|
|
169
240
|
except json.JSONDecodeError:
|
|
170
|
-
|
|
171
|
-
json_match = re.search(r"\{.*\}", content, re.DOTALL)
|
|
241
|
+
json_match = re.search(json_pattern, content, re.DOTALL)
|
|
172
242
|
if json_match:
|
|
173
243
|
try:
|
|
174
244
|
json_data = json.loads(json_match.group())
|
|
175
|
-
return Data(data=json_data)
|
|
176
245
|
except json.JSONDecodeError:
|
|
177
|
-
|
|
246
|
+
return {"content": content, "error": schema_error_msg}
|
|
247
|
+
else:
|
|
248
|
+
return {"content": content, "error": schema_error_msg}
|
|
249
|
+
|
|
250
|
+
# If no output schema provided, return parsed JSON without validation
|
|
251
|
+
if not hasattr(self, "output_schema") or not self.output_schema or len(self.output_schema) == 0:
|
|
252
|
+
return json_data
|
|
253
|
+
|
|
254
|
+
# Use BaseModel validation with schema
|
|
255
|
+
try:
|
|
256
|
+
processed_schema = self._preprocess_schema(self.output_schema)
|
|
257
|
+
output_model = build_model_from_schema(processed_schema)
|
|
258
|
+
|
|
259
|
+
# Validate against the schema
|
|
260
|
+
if isinstance(json_data, list):
|
|
261
|
+
# Multiple objects
|
|
262
|
+
validated_objects = []
|
|
263
|
+
for item in json_data:
|
|
264
|
+
try:
|
|
265
|
+
validated_obj = output_model.model_validate(item)
|
|
266
|
+
validated_objects.append(validated_obj.model_dump())
|
|
267
|
+
except ValidationError as e:
|
|
268
|
+
await logger.aerror(f"Validation error for item: {e}")
|
|
269
|
+
# Include invalid items with error info
|
|
270
|
+
validated_objects.append({"data": item, "validation_error": str(e)})
|
|
271
|
+
return validated_objects
|
|
272
|
+
|
|
273
|
+
# Single object
|
|
274
|
+
try:
|
|
275
|
+
validated_obj = output_model.model_validate(json_data)
|
|
276
|
+
return [validated_obj.model_dump()] # Return as list for consistency
|
|
277
|
+
except ValidationError as e:
|
|
278
|
+
await logger.aerror(f"Validation error: {e}")
|
|
279
|
+
return [{"data": json_data, "validation_error": str(e)}]
|
|
280
|
+
|
|
281
|
+
except (TypeError, ValueError) as e:
|
|
282
|
+
await logger.aerror(f"Error building structured output: {e}")
|
|
283
|
+
# Fallback to parsed JSON without validation
|
|
284
|
+
return json_data
|
|
285
|
+
|
|
286
|
+
async def json_response(self) -> Data:
|
|
287
|
+
"""Convert agent response to structured JSON Data output with schema validation."""
|
|
288
|
+
# Always use structured chat agent for JSON response mode for better JSON formatting
|
|
289
|
+
try:
|
|
290
|
+
system_components = []
|
|
291
|
+
|
|
292
|
+
# 1. Agent Instructions (system_prompt)
|
|
293
|
+
agent_instructions = getattr(self, "system_prompt", "") or ""
|
|
294
|
+
if agent_instructions:
|
|
295
|
+
system_components.append(f"{agent_instructions}")
|
|
296
|
+
|
|
297
|
+
# 2. Format Instructions
|
|
298
|
+
format_instructions = getattr(self, "format_instructions", "") or ""
|
|
299
|
+
if format_instructions:
|
|
300
|
+
system_components.append(f"Format instructions: {format_instructions}")
|
|
178
301
|
|
|
179
|
-
#
|
|
180
|
-
|
|
302
|
+
# 3. Schema Information from BaseModel
|
|
303
|
+
if hasattr(self, "output_schema") and self.output_schema and len(self.output_schema) > 0:
|
|
304
|
+
try:
|
|
305
|
+
processed_schema = self._preprocess_schema(self.output_schema)
|
|
306
|
+
output_model = build_model_from_schema(processed_schema)
|
|
307
|
+
schema_dict = output_model.model_json_schema()
|
|
308
|
+
schema_info = (
|
|
309
|
+
"You are given some text that may include format instructions, "
|
|
310
|
+
"explanations, or other content alongside a JSON schema.\n\n"
|
|
311
|
+
"Your task:\n"
|
|
312
|
+
"- Extract only the JSON schema.\n"
|
|
313
|
+
"- Return it as valid JSON.\n"
|
|
314
|
+
"- Do not include format instructions, explanations, or extra text.\n\n"
|
|
315
|
+
"Input:\n"
|
|
316
|
+
f"{json.dumps(schema_dict, indent=2)}\n\n"
|
|
317
|
+
"Output (only JSON schema):"
|
|
318
|
+
)
|
|
319
|
+
system_components.append(schema_info)
|
|
320
|
+
except (ValidationError, ValueError, TypeError, KeyError) as e:
|
|
321
|
+
await logger.aerror(f"Could not build schema for prompt: {e}", exc_info=True)
|
|
322
|
+
|
|
323
|
+
# Combine all components
|
|
324
|
+
combined_instructions = "\n\n".join(system_components) if system_components else ""
|
|
325
|
+
llm_model, self.chat_history, self.tools = await self.get_agent_requirements()
|
|
326
|
+
self.set(
|
|
327
|
+
llm=llm_model,
|
|
328
|
+
tools=self.tools or [],
|
|
329
|
+
chat_history=self.chat_history,
|
|
330
|
+
input_value=self.input_value,
|
|
331
|
+
system_prompt=combined_instructions,
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
# Create and run structured chat agent
|
|
335
|
+
try:
|
|
336
|
+
structured_agent = self.create_agent_runnable()
|
|
337
|
+
except (NotImplementedError, ValueError, TypeError) as e:
|
|
338
|
+
await logger.aerror(f"Error with structured chat agent: {e}")
|
|
339
|
+
raise
|
|
340
|
+
try:
|
|
341
|
+
result = await self.run_agent(structured_agent)
|
|
342
|
+
except (ExceptionWithMessageError, ValueError, TypeError, RuntimeError) as e:
|
|
343
|
+
await logger.aerror(f"Error with structured agent result: {e}")
|
|
344
|
+
raise
|
|
345
|
+
# Extract content from structured agent result
|
|
346
|
+
if hasattr(result, "content"):
|
|
347
|
+
content = result.content
|
|
348
|
+
elif hasattr(result, "text"):
|
|
349
|
+
content = result.text
|
|
350
|
+
else:
|
|
351
|
+
content = str(result)
|
|
352
|
+
|
|
353
|
+
except (ExceptionWithMessageError, ValueError, TypeError, NotImplementedError, AttributeError) as e:
|
|
354
|
+
await logger.aerror(f"Error with structured chat agent: {e}")
|
|
355
|
+
# Fallback to regular agent
|
|
356
|
+
content_str = "No content returned from agent"
|
|
357
|
+
return Data(data={"content": content_str, "error": str(e)})
|
|
358
|
+
|
|
359
|
+
# Process with structured output validation
|
|
360
|
+
try:
|
|
361
|
+
structured_output = await self.build_structured_output_base(content)
|
|
362
|
+
|
|
363
|
+
# Handle different output formats
|
|
364
|
+
if isinstance(structured_output, list) and structured_output:
|
|
365
|
+
if len(structured_output) == 1:
|
|
366
|
+
return Data(data=structured_output[0])
|
|
367
|
+
return Data(data={"results": structured_output})
|
|
368
|
+
if isinstance(structured_output, dict):
|
|
369
|
+
return Data(data=structured_output)
|
|
370
|
+
return Data(data={"content": content})
|
|
371
|
+
|
|
372
|
+
except (ValueError, TypeError) as e:
|
|
373
|
+
await logger.aerror(f"Error in structured output processing: {e}")
|
|
374
|
+
return Data(data={"content": content, "error": str(e)})
|
|
181
375
|
|
|
182
376
|
async def get_memory_data(self):
|
|
183
377
|
# TODO: This is a temporary fix to avoid message duplication. We should develop a function for this.
|
|
@@ -190,7 +384,7 @@ class AgentComponent(ToolCallingAgentComponent):
|
|
|
190
384
|
message for message in messages if getattr(message, "id", None) != getattr(self.input_value, "id", None)
|
|
191
385
|
]
|
|
192
386
|
|
|
193
|
-
def get_llm(self):
|
|
387
|
+
async def get_llm(self):
|
|
194
388
|
if not isinstance(self.agent_llm, str):
|
|
195
389
|
return self.agent_llm, None
|
|
196
390
|
|
|
@@ -207,8 +401,8 @@ class AgentComponent(ToolCallingAgentComponent):
|
|
|
207
401
|
|
|
208
402
|
return self._build_llm_model(component_class, inputs, prefix), display_name
|
|
209
403
|
|
|
210
|
-
except
|
|
211
|
-
logger.
|
|
404
|
+
except (AttributeError, ValueError, TypeError, RuntimeError) as e:
|
|
405
|
+
await logger.aerror(f"Error building {self.agent_llm} language model: {e!s}")
|
|
212
406
|
msg = f"Failed to initialize language model: {e!s}"
|
|
213
407
|
raise ValueError(msg) from e
|
|
214
408
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from langflow.components._importing import import_mod
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from .cassandra import CassandraVectorStoreComponent
|
|
9
|
+
from .cassandra_chat import CassandraChatMemory
|
|
10
|
+
from .cassandra_graph import CassandraGraphVectorStoreComponent
|
|
11
|
+
|
|
12
|
+
_dynamic_imports = {
|
|
13
|
+
"CassandraVectorStoreComponent": "cassandra",
|
|
14
|
+
"CassandraGraphVectorStoreComponent": "cassandra_graph",
|
|
15
|
+
"CassandraChatMemory": "cassandra_chat",
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"CassandraChatMemory",
|
|
20
|
+
"CassandraGraphVectorStoreComponent",
|
|
21
|
+
"CassandraVectorStoreComponent",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def __getattr__(attr_name: str) -> Any:
|
|
26
|
+
"""Lazily import Cassandra components on attribute access."""
|
|
27
|
+
if attr_name not in _dynamic_imports:
|
|
28
|
+
msg = f"module '{__name__}' has no attribute '{attr_name}'"
|
|
29
|
+
raise AttributeError(msg)
|
|
30
|
+
try:
|
|
31
|
+
result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
|
|
32
|
+
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
|
33
|
+
msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
|
|
34
|
+
raise AttributeError(msg) from e
|
|
35
|
+
globals()[attr_name] = result
|
|
36
|
+
return result
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def __dir__() -> list[str]:
|
|
40
|
+
return list(__all__)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from langflow.components._importing import import_mod
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from .chroma import ChromaVectorStoreComponent
|
|
9
|
+
|
|
10
|
+
_dynamic_imports = {
|
|
11
|
+
"ChromaVectorStoreComponent": "chroma",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"ChromaVectorStoreComponent",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def __getattr__(attr_name: str) -> Any:
|
|
20
|
+
"""Lazily import Chroma components on attribute access."""
|
|
21
|
+
if attr_name not in _dynamic_imports:
|
|
22
|
+
msg = f"module '{__name__}' has no attribute '{attr_name}'"
|
|
23
|
+
raise AttributeError(msg)
|
|
24
|
+
try:
|
|
25
|
+
result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
|
|
26
|
+
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
|
27
|
+
msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
|
|
28
|
+
raise AttributeError(msg) from e
|
|
29
|
+
globals()[attr_name] = result
|
|
30
|
+
return result
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def __dir__() -> list[str]:
|
|
34
|
+
return list(__all__)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from langflow.components._importing import import_mod
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from .clickhouse import ClickhouseVectorStoreComponent
|
|
9
|
+
|
|
10
|
+
_dynamic_imports = {
|
|
11
|
+
"ClickhouseVectorStoreComponent": "clickhouse",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"ClickhouseVectorStoreComponent",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def __getattr__(attr_name: str) -> Any:
|
|
20
|
+
"""Lazily import ClickHouse components on attribute access."""
|
|
21
|
+
if attr_name not in _dynamic_imports:
|
|
22
|
+
msg = f"module '{__name__}' has no attribute '{attr_name}'"
|
|
23
|
+
raise AttributeError(msg)
|
|
24
|
+
try:
|
|
25
|
+
result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
|
|
26
|
+
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
|
27
|
+
msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
|
|
28
|
+
raise AttributeError(msg) from e
|
|
29
|
+
globals()[attr_name] = result
|
|
30
|
+
return result
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def __dir__() -> list[str]:
|
|
34
|
+
return list(__all__)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from langflow.components._importing import import_mod
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from .couchbase import CouchbaseVectorStoreComponent
|
|
9
|
+
|
|
10
|
+
_dynamic_imports = {
|
|
11
|
+
"CouchbaseVectorStoreComponent": "couchbase",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"CouchbaseVectorStoreComponent",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def __getattr__(attr_name: str) -> Any:
|
|
20
|
+
"""Lazily import Couchbase components on attribute access."""
|
|
21
|
+
if attr_name not in _dynamic_imports:
|
|
22
|
+
msg = f"module '{__name__}' has no attribute '{attr_name}'"
|
|
23
|
+
raise AttributeError(msg)
|
|
24
|
+
try:
|
|
25
|
+
result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
|
|
26
|
+
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
|
27
|
+
msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
|
|
28
|
+
raise AttributeError(msg) from e
|
|
29
|
+
globals()[attr_name] = result
|
|
30
|
+
return result
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def __dir__() -> list[str]:
|
|
34
|
+
return list(__all__)
|