lfx-nightly 0.1.13.dev2__py3-none-any.whl → 0.1.13.dev4__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/_assets/component_index.json +1 -1
- lfx/base/agents/agent.py +17 -1
- lfx/base/agents/utils.py +15 -2
- lfx/base/composio/composio_base.py +24 -9
- lfx/base/datastax/__init__.py +5 -0
- lfx/{components/vectorstores/astradb.py → base/datastax/astradb_base.py} +84 -473
- lfx/base/io/chat.py +5 -4
- lfx/base/mcp/util.py +101 -15
- lfx/cli/commands.py +1 -1
- lfx/components/agents/agent.py +1 -1
- lfx/components/agents/cuga_agent.py +1 -1
- lfx/components/agents/mcp_component.py +16 -0
- lfx/components/amazon/amazon_bedrock_converse.py +1 -1
- lfx/components/apify/apify_actor.py +3 -3
- lfx/components/datastax/__init__.py +12 -6
- lfx/components/datastax/{astra_assistant_manager.py → astradb_assistant_manager.py} +1 -0
- lfx/components/datastax/astradb_chatmemory.py +40 -0
- lfx/components/datastax/astradb_cql.py +5 -31
- lfx/components/datastax/astradb_graph.py +9 -123
- lfx/components/datastax/astradb_tool.py +12 -52
- lfx/components/datastax/astradb_vectorstore.py +133 -976
- lfx/components/datastax/create_assistant.py +1 -0
- lfx/components/datastax/create_thread.py +1 -0
- lfx/components/datastax/dotenv.py +1 -0
- lfx/components/datastax/get_assistant.py +1 -0
- lfx/components/datastax/getenvvar.py +1 -0
- lfx/components/datastax/graph_rag.py +1 -1
- lfx/components/datastax/list_assistants.py +1 -0
- lfx/components/datastax/run.py +1 -0
- lfx/components/knowledge_bases/ingestion.py +17 -9
- lfx/components/knowledge_bases/retrieval.py +16 -8
- lfx/components/mistral/mistral_embeddings.py +1 -1
- lfx/components/openrouter/openrouter.py +49 -147
- lfx/components/vectorstores/__init__.py +0 -6
- lfx/custom/custom_component/component.py +3 -2
- lfx/graph/edge/base.py +2 -2
- lfx/graph/graph/base.py +1 -1
- lfx/graph/graph/schema.py +3 -2
- lfx/graph/vertex/vertex_types.py +1 -1
- {lfx_nightly-0.1.13.dev2.dist-info → lfx_nightly-0.1.13.dev4.dist-info}/METADATA +1 -1
- {lfx_nightly-0.1.13.dev2.dist-info → lfx_nightly-0.1.13.dev4.dist-info}/RECORD +44 -65
- lfx/components/datastax/astra_db.py +0 -77
- lfx/components/datastax/cassandra.py +0 -92
- lfx/components/vectorstores/astradb_graph.py +0 -326
- lfx/components/vectorstores/cassandra.py +0 -264
- lfx/components/vectorstores/cassandra_graph.py +0 -238
- lfx/components/vectorstores/chroma.py +0 -167
- lfx/components/vectorstores/clickhouse.py +0 -135
- lfx/components/vectorstores/couchbase.py +0 -102
- lfx/components/vectorstores/elasticsearch.py +0 -267
- lfx/components/vectorstores/faiss.py +0 -111
- lfx/components/vectorstores/graph_rag.py +0 -141
- lfx/components/vectorstores/hcd.py +0 -314
- lfx/components/vectorstores/milvus.py +0 -115
- lfx/components/vectorstores/mongodb_atlas.py +0 -213
- lfx/components/vectorstores/opensearch.py +0 -243
- lfx/components/vectorstores/pgvector.py +0 -72
- lfx/components/vectorstores/pinecone.py +0 -134
- lfx/components/vectorstores/qdrant.py +0 -109
- lfx/components/vectorstores/supabase.py +0 -76
- lfx/components/vectorstores/upstash.py +0 -124
- lfx/components/vectorstores/vectara.py +0 -97
- lfx/components/vectorstores/vectara_rag.py +0 -164
- lfx/components/vectorstores/weaviate.py +0 -89
- /lfx/components/datastax/{astra_vectorize.py → astradb_vectorize.py} +0 -0
- {lfx_nightly-0.1.13.dev2.dist-info → lfx_nightly-0.1.13.dev4.dist-info}/WHEEL +0 -0
- {lfx_nightly-0.1.13.dev2.dist-info → lfx_nightly-0.1.13.dev4.dist-info}/entry_points.txt +0 -0
lfx/base/io/chat.py
CHANGED
|
@@ -6,8 +6,9 @@ class ChatComponent(Component):
|
|
|
6
6
|
description = "Use as base for chat components."
|
|
7
7
|
|
|
8
8
|
def get_properties_from_source_component(self):
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
vertex = self.get_vertex()
|
|
10
|
+
if vertex and hasattr(vertex, "incoming_edges") and vertex.incoming_edges:
|
|
11
|
+
source_id = vertex.incoming_edges[0].source_id
|
|
11
12
|
source_vertex = self.graph.get_vertex(source_id)
|
|
12
13
|
component = source_vertex.custom_component
|
|
13
14
|
source = component.display_name
|
|
@@ -15,6 +16,6 @@ class ChatComponent(Component):
|
|
|
15
16
|
possible_attributes = ["model_name", "model_id", "model"]
|
|
16
17
|
for attribute in possible_attributes:
|
|
17
18
|
if hasattr(component, attribute) and getattr(component, attribute):
|
|
18
|
-
return getattr(component, attribute), icon, source, component.
|
|
19
|
-
return source, icon, component.display_name, component.
|
|
19
|
+
return getattr(component, attribute), icon, source, component.get_id()
|
|
20
|
+
return source, icon, component.display_name, component.get_id()
|
|
20
21
|
return None, None, None, None
|
lfx/base/mcp/util.py
CHANGED
|
@@ -35,13 +35,33 @@ HTTP_INTERNAL_SERVER_ERROR = 500
|
|
|
35
35
|
HTTP_UNAUTHORIZED = 401
|
|
36
36
|
HTTP_FORBIDDEN = 403
|
|
37
37
|
|
|
38
|
-
# MCP Session Manager constants
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
# MCP Session Manager constants - lazy loaded
|
|
39
|
+
_mcp_settings_cache: dict[str, Any] = {}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _get_mcp_setting(key: str, default: Any = None) -> Any:
|
|
43
|
+
"""Lazy load MCP settings from settings service."""
|
|
44
|
+
if key not in _mcp_settings_cache:
|
|
45
|
+
settings = get_settings_service().settings
|
|
46
|
+
_mcp_settings_cache[key] = getattr(settings, key, default)
|
|
47
|
+
return _mcp_settings_cache[key]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_max_sessions_per_server() -> int:
|
|
51
|
+
"""Get maximum number of sessions per server to prevent resource exhaustion."""
|
|
52
|
+
return _get_mcp_setting("mcp_max_sessions_per_server")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def get_session_idle_timeout() -> int:
|
|
56
|
+
"""Get 5 minutes idle timeout for sessions."""
|
|
57
|
+
return _get_mcp_setting("mcp_session_idle_timeout")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_session_cleanup_interval() -> int:
|
|
61
|
+
"""Get cleanup interval in seconds."""
|
|
62
|
+
return _get_mcp_setting("mcp_session_cleanup_interval")
|
|
63
|
+
|
|
64
|
+
|
|
45
65
|
# RFC 7230 compliant header name pattern: token = 1*tchar
|
|
46
66
|
# tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
|
|
47
67
|
# "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
|
|
@@ -65,6 +85,46 @@ ALLOWED_HEADERS = {
|
|
|
65
85
|
}
|
|
66
86
|
|
|
67
87
|
|
|
88
|
+
def create_mcp_http_client_with_ssl_option(
|
|
89
|
+
headers: dict[str, str] | None = None,
|
|
90
|
+
timeout: httpx.Timeout | None = None,
|
|
91
|
+
auth: httpx.Auth | None = None,
|
|
92
|
+
*,
|
|
93
|
+
verify_ssl: bool = True,
|
|
94
|
+
) -> httpx.AsyncClient:
|
|
95
|
+
"""Create an httpx AsyncClient with configurable SSL verification.
|
|
96
|
+
|
|
97
|
+
This is a custom factory that extends the standard MCP client factory
|
|
98
|
+
to support disabling SSL verification for self-signed certificates.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
headers: Optional headers to include with all requests.
|
|
102
|
+
timeout: Request timeout as httpx.Timeout object.
|
|
103
|
+
auth: Optional authentication handler.
|
|
104
|
+
verify_ssl: Whether to verify SSL certificates (default: True).
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
Configured httpx.AsyncClient instance.
|
|
108
|
+
"""
|
|
109
|
+
kwargs: dict[str, Any] = {
|
|
110
|
+
"follow_redirects": True,
|
|
111
|
+
"verify": verify_ssl,
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if timeout is None:
|
|
115
|
+
kwargs["timeout"] = httpx.Timeout(30.0)
|
|
116
|
+
else:
|
|
117
|
+
kwargs["timeout"] = timeout
|
|
118
|
+
|
|
119
|
+
if headers is not None:
|
|
120
|
+
kwargs["headers"] = headers
|
|
121
|
+
|
|
122
|
+
if auth is not None:
|
|
123
|
+
kwargs["auth"] = auth
|
|
124
|
+
|
|
125
|
+
return httpx.AsyncClient(**kwargs)
|
|
126
|
+
|
|
127
|
+
|
|
68
128
|
def validate_headers(headers: dict[str, str]) -> dict[str, str]:
|
|
69
129
|
"""Validate and sanitize HTTP headers according to RFC 7230.
|
|
70
130
|
|
|
@@ -432,7 +492,7 @@ class MCPSessionManager:
|
|
|
432
492
|
"""Periodically clean up idle sessions."""
|
|
433
493
|
while True:
|
|
434
494
|
try:
|
|
435
|
-
await asyncio.sleep(
|
|
495
|
+
await asyncio.sleep(get_session_cleanup_interval())
|
|
436
496
|
await self._cleanup_idle_sessions()
|
|
437
497
|
except asyncio.CancelledError:
|
|
438
498
|
break
|
|
@@ -450,7 +510,7 @@ class MCPSessionManager:
|
|
|
450
510
|
sessions_to_remove = []
|
|
451
511
|
|
|
452
512
|
for session_id, session_info in list(sessions.items()):
|
|
453
|
-
if current_time - session_info["last_used"] >
|
|
513
|
+
if current_time - session_info["last_used"] > get_session_idle_timeout():
|
|
454
514
|
sessions_to_remove.append(session_id)
|
|
455
515
|
|
|
456
516
|
# Clean up idle sessions
|
|
@@ -573,7 +633,7 @@ class MCPSessionManager:
|
|
|
573
633
|
await self._cleanup_session_by_id(server_key, session_id)
|
|
574
634
|
|
|
575
635
|
# Check if we've reached the maximum number of sessions for this server
|
|
576
|
-
if len(sessions) >=
|
|
636
|
+
if len(sessions) >= get_max_sessions_per_server():
|
|
577
637
|
# Remove the oldest session
|
|
578
638
|
oldest_session_id = min(sessions.keys(), key=lambda x: sessions[x]["last_used"])
|
|
579
639
|
await logger.ainfo(
|
|
@@ -675,7 +735,7 @@ class MCPSessionManager:
|
|
|
675
735
|
|
|
676
736
|
Args:
|
|
677
737
|
session_id: Unique identifier for this session
|
|
678
|
-
connection_params: Connection parameters including URL, headers, timeouts
|
|
738
|
+
connection_params: Connection parameters including URL, headers, timeouts, verify_ssl
|
|
679
739
|
preferred_transport: If set to "sse", skip Streamable HTTP and go directly to SSE
|
|
680
740
|
|
|
681
741
|
Returns:
|
|
@@ -691,6 +751,19 @@ class MCPSessionManager:
|
|
|
691
751
|
# Track which transport succeeded
|
|
692
752
|
used_transport: list[str] = []
|
|
693
753
|
|
|
754
|
+
# Get verify_ssl option from connection params, default to True
|
|
755
|
+
verify_ssl = connection_params.get("verify_ssl", True)
|
|
756
|
+
|
|
757
|
+
# Create custom httpx client factory with SSL verification option
|
|
758
|
+
def custom_httpx_factory(
|
|
759
|
+
headers: dict[str, str] | None = None,
|
|
760
|
+
timeout: httpx.Timeout | None = None,
|
|
761
|
+
auth: httpx.Auth | None = None,
|
|
762
|
+
) -> httpx.AsyncClient:
|
|
763
|
+
return create_mcp_http_client_with_ssl_option(
|
|
764
|
+
headers=headers, timeout=timeout, auth=auth, verify_ssl=verify_ssl
|
|
765
|
+
)
|
|
766
|
+
|
|
694
767
|
async def session_task():
|
|
695
768
|
"""Background task that keeps the session alive."""
|
|
696
769
|
streamable_error = None
|
|
@@ -705,6 +778,7 @@ class MCPSessionManager:
|
|
|
705
778
|
url=connection_params["url"],
|
|
706
779
|
headers=connection_params["headers"],
|
|
707
780
|
timeout=connection_params["timeout_seconds"],
|
|
781
|
+
httpx_client_factory=custom_httpx_factory,
|
|
708
782
|
) as (read, write, _):
|
|
709
783
|
session = ClientSession(read, write)
|
|
710
784
|
async with session:
|
|
@@ -745,6 +819,7 @@ class MCPSessionManager:
|
|
|
745
819
|
connection_params["headers"],
|
|
746
820
|
connection_params["timeout_seconds"],
|
|
747
821
|
sse_read_timeout,
|
|
822
|
+
httpx_client_factory=custom_httpx_factory,
|
|
748
823
|
) as (read, write):
|
|
749
824
|
session = ClientSession(read, write)
|
|
750
825
|
async with session:
|
|
@@ -1196,6 +1271,8 @@ class MCPStreamableHttpClient:
|
|
|
1196
1271
|
headers: dict[str, str] | None = None,
|
|
1197
1272
|
timeout_seconds: int = 30,
|
|
1198
1273
|
sse_read_timeout_seconds: int = 30,
|
|
1274
|
+
*,
|
|
1275
|
+
verify_ssl: bool = True,
|
|
1199
1276
|
) -> list[StructuredTool]:
|
|
1200
1277
|
"""Connect to MCP server using Streamable HTTP transport with SSE fallback (SDK style)."""
|
|
1201
1278
|
# Validate and sanitize headers early
|
|
@@ -1213,12 +1290,13 @@ class MCPStreamableHttpClient:
|
|
|
1213
1290
|
msg = f"Invalid Streamable HTTP or SSE URL ({url}): {error_msg}"
|
|
1214
1291
|
raise ValueError(msg)
|
|
1215
1292
|
# Store connection parameters for later use in run_tool
|
|
1216
|
-
# Include SSE read timeout for fallback
|
|
1293
|
+
# Include SSE read timeout for fallback and SSL verification option
|
|
1217
1294
|
self._connection_params = {
|
|
1218
1295
|
"url": url,
|
|
1219
1296
|
"headers": validated_headers,
|
|
1220
1297
|
"timeout_seconds": timeout_seconds,
|
|
1221
1298
|
"sse_read_timeout_seconds": sse_read_timeout_seconds,
|
|
1299
|
+
"verify_ssl": verify_ssl,
|
|
1222
1300
|
}
|
|
1223
1301
|
elif headers:
|
|
1224
1302
|
self._connection_params["headers"] = validated_headers
|
|
@@ -1238,11 +1316,18 @@ class MCPStreamableHttpClient:
|
|
|
1238
1316
|
return response.tools
|
|
1239
1317
|
|
|
1240
1318
|
async def connect_to_server(
|
|
1241
|
-
self,
|
|
1319
|
+
self,
|
|
1320
|
+
url: str,
|
|
1321
|
+
headers: dict[str, str] | None = None,
|
|
1322
|
+
sse_read_timeout_seconds: int = 30,
|
|
1323
|
+
*,
|
|
1324
|
+
verify_ssl: bool = True,
|
|
1242
1325
|
) -> list[StructuredTool]:
|
|
1243
1326
|
"""Connect to MCP server using Streamable HTTP with SSE fallback transport (SDK style)."""
|
|
1244
1327
|
return await asyncio.wait_for(
|
|
1245
|
-
self._connect_to_server(
|
|
1328
|
+
self._connect_to_server(
|
|
1329
|
+
url, headers, sse_read_timeout_seconds=sse_read_timeout_seconds, verify_ssl=verify_ssl
|
|
1330
|
+
),
|
|
1246
1331
|
timeout=get_settings_service().settings.mcp_server_timeout,
|
|
1247
1332
|
)
|
|
1248
1333
|
|
|
@@ -1473,7 +1558,8 @@ async def update_tools(
|
|
|
1473
1558
|
client = mcp_stdio_client
|
|
1474
1559
|
elif mode in ["Streamable_HTTP", "SSE"]:
|
|
1475
1560
|
# Streamable HTTP connection with SSE fallback
|
|
1476
|
-
|
|
1561
|
+
verify_ssl = server_config.get("verify_ssl", True)
|
|
1562
|
+
tools = await mcp_streamable_http_client.connect_to_server(url, headers=headers, verify_ssl=verify_ssl)
|
|
1477
1563
|
client = mcp_streamable_http_client
|
|
1478
1564
|
else:
|
|
1479
1565
|
logger.error(f"Invalid MCP server mode for '{server_name}': {mode}")
|
lfx/cli/commands.py
CHANGED
|
@@ -43,7 +43,7 @@ def serve_command(
|
|
|
43
43
|
host: str = typer.Option("127.0.0.1", "--host", "-h", help="Host to bind the server to"),
|
|
44
44
|
port: int = typer.Option(8000, "--port", "-p", help="Port to bind the server to"),
|
|
45
45
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show diagnostic output and execution details"), # noqa: FBT001, FBT003
|
|
46
|
-
env_file: Path | None = typer.Option(
|
|
46
|
+
env_file: Path | None = typer.Option(
|
|
47
47
|
None,
|
|
48
48
|
"--env-file",
|
|
49
49
|
help="Path to the .env file containing environment variables",
|
lfx/components/agents/agent.py
CHANGED
|
@@ -61,6 +61,7 @@ class MCPToolsComponent(ComponentWithCache):
|
|
|
61
61
|
"mcp_server",
|
|
62
62
|
"tool",
|
|
63
63
|
"use_cache",
|
|
64
|
+
"verify_ssl",
|
|
64
65
|
]
|
|
65
66
|
|
|
66
67
|
display_name = "MCP Tools"
|
|
@@ -86,6 +87,16 @@ class MCPToolsComponent(ComponentWithCache):
|
|
|
86
87
|
value=False,
|
|
87
88
|
advanced=True,
|
|
88
89
|
),
|
|
90
|
+
BoolInput(
|
|
91
|
+
name="verify_ssl",
|
|
92
|
+
display_name="Verify SSL Certificate",
|
|
93
|
+
info=(
|
|
94
|
+
"Enable SSL certificate verification for HTTPS connections. "
|
|
95
|
+
"Disable only for development/testing with self-signed certificates."
|
|
96
|
+
),
|
|
97
|
+
value=True,
|
|
98
|
+
advanced=True,
|
|
99
|
+
),
|
|
89
100
|
DropdownInput(
|
|
90
101
|
name="tool",
|
|
91
102
|
display_name="Tool",
|
|
@@ -210,6 +221,11 @@ class MCPToolsComponent(ComponentWithCache):
|
|
|
210
221
|
self.tools = []
|
|
211
222
|
return [], {"name": server_name, "config": server_config}
|
|
212
223
|
|
|
224
|
+
# Add verify_ssl option to server config if not present
|
|
225
|
+
if "verify_ssl" not in server_config:
|
|
226
|
+
verify_ssl = getattr(self, "verify_ssl", True)
|
|
227
|
+
server_config["verify_ssl"] = verify_ssl
|
|
228
|
+
|
|
213
229
|
_, tool_list, tool_cache = await update_tools(
|
|
214
230
|
server_name=server_name,
|
|
215
231
|
server_config=server_config,
|
|
@@ -92,7 +92,7 @@ class ApifyActorsComponent(Component):
|
|
|
92
92
|
"""Run the Actor and return node output."""
|
|
93
93
|
input_ = json.loads(self.run_input)
|
|
94
94
|
fields = ApifyActorsComponent.parse_dataset_fields(self.dataset_fields) if self.dataset_fields else None
|
|
95
|
-
res = self.
|
|
95
|
+
res = self.run_actor(self.actor_id, input_, fields=fields)
|
|
96
96
|
if self.flatten_dataset:
|
|
97
97
|
res = [ApifyActorsComponent.flatten(item) for item in res]
|
|
98
98
|
data = [Data(data=item) for item in res]
|
|
@@ -159,7 +159,7 @@ class ApifyActorsComponent(Component):
|
|
|
159
159
|
# retrieve if nested, just in case
|
|
160
160
|
input_dict = input_dict.get("run_input", input_dict)
|
|
161
161
|
|
|
162
|
-
res = parent.
|
|
162
|
+
res = parent.run_actor(actor_id, input_dict)
|
|
163
163
|
return "\n\n".join([ApifyActorsComponent.dict_to_json_str(item) for item in res])
|
|
164
164
|
|
|
165
165
|
return ApifyActorRun
|
|
@@ -256,7 +256,7 @@ class ApifyActorsComponent(Component):
|
|
|
256
256
|
valid_chars = string.ascii_letters + string.digits + "_-"
|
|
257
257
|
return "".join(char if char in valid_chars else "_" for char in actor_id)
|
|
258
258
|
|
|
259
|
-
def
|
|
259
|
+
def run_actor(self, actor_id: str, run_input: dict, fields: list[str] | None = None) -> list[dict]:
|
|
260
260
|
"""Run an Apify Actor and return the output dataset.
|
|
261
261
|
|
|
262
262
|
Args:
|
|
@@ -5,17 +5,19 @@ from typing import TYPE_CHECKING, Any
|
|
|
5
5
|
from lfx.components._importing import import_mod
|
|
6
6
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
|
-
from .
|
|
9
|
-
from .
|
|
10
|
-
from .astra_vectorize import AstraVectorizeComponent
|
|
8
|
+
from .astradb_assistant_manager import AstraAssistantManager
|
|
9
|
+
from .astradb_chatmemory import AstraDBChatMemory
|
|
11
10
|
from .astradb_cql import AstraDBCQLToolComponent
|
|
11
|
+
from .astradb_graph import AstraDBGraphVectorStoreComponent
|
|
12
12
|
from .astradb_tool import AstraDBToolComponent
|
|
13
|
+
from .astradb_vectorize import AstraVectorizeComponent
|
|
13
14
|
from .astradb_vectorstore import AstraDBVectorStoreComponent
|
|
14
15
|
from .create_assistant import AssistantsCreateAssistant
|
|
15
16
|
from .create_thread import AssistantsCreateThread
|
|
16
17
|
from .dotenv import Dotenv
|
|
17
18
|
from .get_assistant import AssistantsGetAssistantName
|
|
18
19
|
from .getenvvar import GetEnvVar
|
|
20
|
+
from .graph_rag import GraphRAGComponent
|
|
19
21
|
from .list_assistants import AssistantsListAssistants
|
|
20
22
|
from .run import AssistantsRun
|
|
21
23
|
|
|
@@ -25,14 +27,16 @@ _dynamic_imports = {
|
|
|
25
27
|
"AssistantsGetAssistantName": "get_assistant",
|
|
26
28
|
"AssistantsListAssistants": "list_assistants",
|
|
27
29
|
"AssistantsRun": "run",
|
|
28
|
-
"AstraAssistantManager": "
|
|
30
|
+
"AstraAssistantManager": "astradb_assistant_manager",
|
|
29
31
|
"AstraDBCQLToolComponent": "astradb_cql",
|
|
30
|
-
"AstraDBChatMemory": "
|
|
32
|
+
"AstraDBChatMemory": "astradb_chatmemory",
|
|
33
|
+
"AstraDBGraphVectorStoreComponent": "astradb_graph",
|
|
31
34
|
"AstraDBToolComponent": "astradb_tool",
|
|
32
35
|
"AstraDBVectorStoreComponent": "astradb_vectorstore",
|
|
33
|
-
"AstraVectorizeComponent": "
|
|
36
|
+
"AstraVectorizeComponent": "astradb_vectorize",
|
|
34
37
|
"Dotenv": "dotenv",
|
|
35
38
|
"GetEnvVar": "getenvvar",
|
|
39
|
+
"GraphRAGComponent": "graph_rag",
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
__all__ = [
|
|
@@ -44,11 +48,13 @@ __all__ = [
|
|
|
44
48
|
"AstraAssistantManager",
|
|
45
49
|
"AstraDBCQLToolComponent",
|
|
46
50
|
"AstraDBChatMemory",
|
|
51
|
+
"AstraDBGraphVectorStoreComponent",
|
|
47
52
|
"AstraDBToolComponent",
|
|
48
53
|
"AstraDBVectorStoreComponent",
|
|
49
54
|
"AstraVectorizeComponent",
|
|
50
55
|
"Dotenv",
|
|
51
56
|
"GetEnvVar",
|
|
57
|
+
"GraphRAGComponent",
|
|
52
58
|
]
|
|
53
59
|
|
|
54
60
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from lfx.base.datastax.astradb_base import AstraDBBaseComponent
|
|
2
|
+
from lfx.base.memory.model import LCChatMemoryComponent
|
|
3
|
+
from lfx.field_typing.constants import Memory
|
|
4
|
+
from lfx.inputs.inputs import MessageTextInput
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AstraDBChatMemory(AstraDBBaseComponent, LCChatMemoryComponent):
|
|
8
|
+
display_name = "Astra DB Chat Memory"
|
|
9
|
+
description = "Retrieves and stores chat messages from Astra DB."
|
|
10
|
+
name = "AstraDBChatMemory"
|
|
11
|
+
icon: str = "AstraDB"
|
|
12
|
+
|
|
13
|
+
inputs = [
|
|
14
|
+
*AstraDBBaseComponent.inputs,
|
|
15
|
+
MessageTextInput(
|
|
16
|
+
name="session_id",
|
|
17
|
+
display_name="Session ID",
|
|
18
|
+
info="The session ID of the chat. If empty, the current session ID parameter will be used.",
|
|
19
|
+
advanced=True,
|
|
20
|
+
),
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
def build_message_history(self) -> Memory:
|
|
24
|
+
try:
|
|
25
|
+
from langchain_astradb.chat_message_histories import AstraDBChatMessageHistory
|
|
26
|
+
except ImportError as e:
|
|
27
|
+
msg = (
|
|
28
|
+
"Could not import langchain Astra DB integration package. "
|
|
29
|
+
"Please install it with `uv pip install langchain-astradb`."
|
|
30
|
+
)
|
|
31
|
+
raise ImportError(msg) from e
|
|
32
|
+
|
|
33
|
+
return AstraDBChatMessageHistory(
|
|
34
|
+
session_id=self.session_id,
|
|
35
|
+
collection_name=self.collection_name,
|
|
36
|
+
token=self.token,
|
|
37
|
+
api_endpoint=self.get_api_endpoint(),
|
|
38
|
+
namespace=self.get_keyspace(),
|
|
39
|
+
environment=self.environment,
|
|
40
|
+
)
|
|
@@ -8,20 +8,22 @@ import requests
|
|
|
8
8
|
from langchain_core.tools import StructuredTool, Tool
|
|
9
9
|
from pydantic import BaseModel, Field, create_model
|
|
10
10
|
|
|
11
|
+
from lfx.base.datastax.astradb_base import AstraDBBaseComponent
|
|
11
12
|
from lfx.base.langchain_utilities.model import LCToolComponent
|
|
12
|
-
from lfx.io import DictInput, IntInput,
|
|
13
|
+
from lfx.io import DictInput, IntInput, StrInput, TableInput
|
|
13
14
|
from lfx.log.logger import logger
|
|
14
15
|
from lfx.schema.data import Data
|
|
15
16
|
from lfx.schema.table import EditMode
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
class AstraDBCQLToolComponent(LCToolComponent):
|
|
19
|
+
class AstraDBCQLToolComponent(AstraDBBaseComponent, LCToolComponent):
|
|
19
20
|
display_name: str = "Astra DB CQL"
|
|
20
21
|
description: str = "Create a tool to get transactional data from DataStax Astra DB CQL Table"
|
|
21
22
|
documentation: str = "https://docs.langflow.org/bundles-datastax#astra-db-cql"
|
|
22
23
|
icon: str = "AstraDB"
|
|
23
24
|
|
|
24
25
|
inputs = [
|
|
26
|
+
*AstraDBBaseComponent.inputs,
|
|
25
27
|
StrInput(name="tool_name", display_name="Tool Name", info="The name of the tool.", required=True),
|
|
26
28
|
StrInput(
|
|
27
29
|
name="tool_description",
|
|
@@ -29,34 +31,6 @@ class AstraDBCQLToolComponent(LCToolComponent):
|
|
|
29
31
|
info="The tool description to be passed to the model.",
|
|
30
32
|
required=True,
|
|
31
33
|
),
|
|
32
|
-
StrInput(
|
|
33
|
-
name="keyspace",
|
|
34
|
-
display_name="Keyspace",
|
|
35
|
-
value="default_keyspace",
|
|
36
|
-
info="The keyspace name within Astra DB where the data is stored.",
|
|
37
|
-
required=True,
|
|
38
|
-
advanced=True,
|
|
39
|
-
),
|
|
40
|
-
StrInput(
|
|
41
|
-
name="table_name",
|
|
42
|
-
display_name="Table Name",
|
|
43
|
-
info="The name of the table within Astra DB where the data is stored.",
|
|
44
|
-
required=True,
|
|
45
|
-
),
|
|
46
|
-
SecretStrInput(
|
|
47
|
-
name="token",
|
|
48
|
-
display_name="Astra DB Application Token",
|
|
49
|
-
info="Authentication token for accessing Astra DB.",
|
|
50
|
-
value="ASTRA_DB_APPLICATION_TOKEN",
|
|
51
|
-
required=True,
|
|
52
|
-
),
|
|
53
|
-
StrInput(
|
|
54
|
-
name="api_endpoint",
|
|
55
|
-
display_name="API Endpoint",
|
|
56
|
-
info="API endpoint URL for the Astra DB service.",
|
|
57
|
-
value="ASTRA_DB_API_ENDPOINT",
|
|
58
|
-
required=True,
|
|
59
|
-
),
|
|
60
34
|
StrInput(
|
|
61
35
|
name="projection_fields",
|
|
62
36
|
display_name="Projection fields",
|
|
@@ -204,7 +178,7 @@ class AstraDBCQLToolComponent(LCToolComponent):
|
|
|
204
178
|
|
|
205
179
|
def astra_rest(self, args):
|
|
206
180
|
headers = {"Accept": "application/json", "X-Cassandra-Token": f"{self.token}"}
|
|
207
|
-
astra_url = f"{self.
|
|
181
|
+
astra_url = f"{self.get_api_endpoint()}/api/rest/v2/keyspaces/{self.get_keyspace()}/{self.collection_name}/"
|
|
208
182
|
where = {}
|
|
209
183
|
|
|
210
184
|
for param in self.tools_params:
|