lfx-amazon 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lfx_amazon/__init__.py +19 -0
- lfx_amazon/components/__init__.py +0 -0
- lfx_amazon/components/amazon/__init__.py +51 -0
- lfx_amazon/components/amazon/amazon_bedrock_converse.py +194 -0
- lfx_amazon/components/amazon/amazon_bedrock_embedding.py +109 -0
- lfx_amazon/components/amazon/amazon_bedrock_model.py +130 -0
- lfx_amazon/components/amazon/s3_bucket_uploader.py +211 -0
- lfx_amazon/extension.json +16 -0
- lfx_amazon-0.1.0.dist-info/METADATA +45 -0
- lfx_amazon-0.1.0.dist-info/RECORD +12 -0
- lfx_amazon-0.1.0.dist-info/WHEEL +4 -0
- lfx_amazon-0.1.0.dist-info/entry_points.txt +2 -0
lfx_amazon/__init__.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""lfx-amazon: Amazon bundle.
|
|
2
|
+
|
|
3
|
+
Distribution unit ``lfx-amazon``. At runtime Langflow's loader
|
|
4
|
+
discovers ``extension.json`` shipped alongside this ``__init__.py`` and
|
|
5
|
+
registers the bundle's components under the namespaced IDs
|
|
6
|
+
``ext:amazon:<Class>@official``.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from lfx_amazon.components.amazon.amazon_bedrock_converse import AmazonBedrockConverseComponent
|
|
10
|
+
from lfx_amazon.components.amazon.amazon_bedrock_embedding import AmazonBedrockEmbeddingsComponent
|
|
11
|
+
from lfx_amazon.components.amazon.amazon_bedrock_model import AmazonBedrockComponent
|
|
12
|
+
from lfx_amazon.components.amazon.s3_bucket_uploader import S3BucketUploaderComponent
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"AmazonBedrockComponent",
|
|
16
|
+
"AmazonBedrockConverseComponent",
|
|
17
|
+
"AmazonBedrockEmbeddingsComponent",
|
|
18
|
+
"S3BucketUploaderComponent",
|
|
19
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Lazy component re-exports for the ``amazon`` bundle.
|
|
2
|
+
|
|
3
|
+
Mirrors the pre-extraction layout of ``lfx.components.amazon`` so saved
|
|
4
|
+
flows that referenced the module-level class
|
|
5
|
+
(e.g. ``lfx.components.amazon.<Class>``) keep resolving via the
|
|
6
|
+
migration table after rewrite to
|
|
7
|
+
``lfx_amazon.components.amazon.<Class>``.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from typing import TYPE_CHECKING, Any
|
|
13
|
+
|
|
14
|
+
from lfx.utils.lazy_import import import_mod
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from .amazon_bedrock_converse import AmazonBedrockConverseComponent
|
|
18
|
+
from .amazon_bedrock_embedding import AmazonBedrockEmbeddingsComponent
|
|
19
|
+
from .amazon_bedrock_model import AmazonBedrockComponent
|
|
20
|
+
from .s3_bucket_uploader import S3BucketUploaderComponent
|
|
21
|
+
|
|
22
|
+
_dynamic_imports = {
|
|
23
|
+
"AmazonBedrockComponent": "amazon_bedrock_model",
|
|
24
|
+
"AmazonBedrockConverseComponent": "amazon_bedrock_converse",
|
|
25
|
+
"AmazonBedrockEmbeddingsComponent": "amazon_bedrock_embedding",
|
|
26
|
+
"S3BucketUploaderComponent": "s3_bucket_uploader",
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"AmazonBedrockComponent",
|
|
31
|
+
"AmazonBedrockConverseComponent",
|
|
32
|
+
"AmazonBedrockEmbeddingsComponent",
|
|
33
|
+
"S3BucketUploaderComponent",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def __getattr__(attr_name: str) -> Any:
|
|
38
|
+
if attr_name not in _dynamic_imports:
|
|
39
|
+
msg = f"module {__name__!r} has no attribute {attr_name!r}"
|
|
40
|
+
raise AttributeError(msg)
|
|
41
|
+
try:
|
|
42
|
+
result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
|
|
43
|
+
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
|
44
|
+
msg = f"Could not import {attr_name!r} from {__name__!r}: {e}"
|
|
45
|
+
raise AttributeError(msg) from e
|
|
46
|
+
globals()[attr_name] = result
|
|
47
|
+
return result
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def __dir__() -> list[str]:
|
|
51
|
+
return list(__all__)
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
from lfx.base.models.aws_constants import AWS_REGIONS, AWS_MODEL_IDs
|
|
2
|
+
from lfx.base.models.model import LCModelComponent
|
|
3
|
+
from lfx.field_typing import LanguageModel
|
|
4
|
+
from lfx.inputs.inputs import BoolInput, FloatInput, IntInput, MessageTextInput, SecretStrInput
|
|
5
|
+
from lfx.io import DictInput, DropdownInput
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AmazonBedrockConverseComponent(LCModelComponent):
|
|
9
|
+
display_name: str = "Amazon Bedrock Converse"
|
|
10
|
+
description: str = (
|
|
11
|
+
"Generate text using Amazon Bedrock LLMs with the modern Converse API for improved conversation handling."
|
|
12
|
+
)
|
|
13
|
+
icon = "Amazon"
|
|
14
|
+
name = "AmazonBedrockConverseModel"
|
|
15
|
+
beta = True
|
|
16
|
+
|
|
17
|
+
inputs = [
|
|
18
|
+
*LCModelComponent.get_base_inputs(),
|
|
19
|
+
DropdownInput(
|
|
20
|
+
name="model_id",
|
|
21
|
+
display_name="Model ID",
|
|
22
|
+
options=AWS_MODEL_IDs,
|
|
23
|
+
value="anthropic.claude-3-5-sonnet-20241022-v2:0",
|
|
24
|
+
info="List of available model IDs to choose from.",
|
|
25
|
+
),
|
|
26
|
+
SecretStrInput(
|
|
27
|
+
name="aws_access_key_id",
|
|
28
|
+
display_name="AWS Access Key ID",
|
|
29
|
+
info="The access key for your AWS account. "
|
|
30
|
+
"Usually set in Python code as the environment variable 'AWS_ACCESS_KEY_ID'.",
|
|
31
|
+
value="AWS_ACCESS_KEY_ID",
|
|
32
|
+
required=True,
|
|
33
|
+
),
|
|
34
|
+
SecretStrInput(
|
|
35
|
+
name="aws_secret_access_key",
|
|
36
|
+
display_name="AWS Secret Access Key",
|
|
37
|
+
info="The secret key for your AWS account. "
|
|
38
|
+
"Usually set in Python code as the environment variable 'AWS_SECRET_ACCESS_KEY'.",
|
|
39
|
+
value="AWS_SECRET_ACCESS_KEY",
|
|
40
|
+
required=True,
|
|
41
|
+
),
|
|
42
|
+
SecretStrInput(
|
|
43
|
+
name="aws_session_token",
|
|
44
|
+
display_name="AWS Session Token",
|
|
45
|
+
advanced=True,
|
|
46
|
+
info="The session key for your AWS account. "
|
|
47
|
+
"Only needed for temporary credentials. "
|
|
48
|
+
"Usually set in Python code as the environment variable 'AWS_SESSION_TOKEN'.",
|
|
49
|
+
load_from_db=False,
|
|
50
|
+
),
|
|
51
|
+
SecretStrInput(
|
|
52
|
+
name="credentials_profile_name",
|
|
53
|
+
display_name="Credentials Profile Name",
|
|
54
|
+
advanced=True,
|
|
55
|
+
info="The name of the profile to use from your "
|
|
56
|
+
"~/.aws/credentials file. "
|
|
57
|
+
"If not provided, the default profile will be used.",
|
|
58
|
+
load_from_db=False,
|
|
59
|
+
),
|
|
60
|
+
DropdownInput(
|
|
61
|
+
name="region_name",
|
|
62
|
+
display_name="Region Name",
|
|
63
|
+
value="us-east-1",
|
|
64
|
+
options=AWS_REGIONS,
|
|
65
|
+
info="The AWS region where your Bedrock resources are located.",
|
|
66
|
+
),
|
|
67
|
+
MessageTextInput(
|
|
68
|
+
name="endpoint_url",
|
|
69
|
+
display_name="Endpoint URL",
|
|
70
|
+
advanced=True,
|
|
71
|
+
info="The URL of the Bedrock endpoint to use.",
|
|
72
|
+
),
|
|
73
|
+
# Model-specific parameters for fine control
|
|
74
|
+
FloatInput(
|
|
75
|
+
name="temperature",
|
|
76
|
+
display_name="Temperature",
|
|
77
|
+
value=0.7,
|
|
78
|
+
info="Controls randomness in output. Higher values make output more random.",
|
|
79
|
+
advanced=True,
|
|
80
|
+
),
|
|
81
|
+
IntInput(
|
|
82
|
+
name="max_tokens",
|
|
83
|
+
display_name="Max Tokens",
|
|
84
|
+
value=4096,
|
|
85
|
+
info="Maximum number of tokens to generate.",
|
|
86
|
+
advanced=True,
|
|
87
|
+
),
|
|
88
|
+
FloatInput(
|
|
89
|
+
name="top_p",
|
|
90
|
+
display_name="Top P",
|
|
91
|
+
value=0.9,
|
|
92
|
+
info="Nucleus sampling parameter. Controls diversity of output.",
|
|
93
|
+
advanced=True,
|
|
94
|
+
),
|
|
95
|
+
IntInput(
|
|
96
|
+
name="top_k",
|
|
97
|
+
display_name="Top K",
|
|
98
|
+
value=250,
|
|
99
|
+
info="Limits the number of highest probability vocabulary tokens to consider. "
|
|
100
|
+
"Note: Not all models support top_k. Use 'Additional Model Fields' for manual configuration if needed.",
|
|
101
|
+
advanced=True,
|
|
102
|
+
),
|
|
103
|
+
BoolInput(
|
|
104
|
+
name="disable_streaming",
|
|
105
|
+
display_name="Disable Streaming",
|
|
106
|
+
value=False,
|
|
107
|
+
info="If True, disables streaming responses. Useful for batch processing.",
|
|
108
|
+
advanced=True,
|
|
109
|
+
),
|
|
110
|
+
DictInput(
|
|
111
|
+
name="additional_model_fields",
|
|
112
|
+
display_name="Additional Model Fields",
|
|
113
|
+
advanced=True,
|
|
114
|
+
is_list=True,
|
|
115
|
+
info="Additional model-specific parameters for fine-tuning behavior.",
|
|
116
|
+
),
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
def build_model(self) -> LanguageModel: # type: ignore[type-var]
|
|
120
|
+
try:
|
|
121
|
+
from langchain_aws.chat_models.bedrock_converse import ChatBedrockConverse
|
|
122
|
+
except ImportError as e:
|
|
123
|
+
msg = "langchain_aws is not installed. Please install it with `pip install langchain_aws`."
|
|
124
|
+
raise ImportError(msg) from e
|
|
125
|
+
|
|
126
|
+
# Prepare initialization parameters
|
|
127
|
+
init_params = {
|
|
128
|
+
"model": self.model_id,
|
|
129
|
+
"region_name": self.region_name,
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# Add AWS credentials if provided
|
|
133
|
+
if self.aws_access_key_id:
|
|
134
|
+
init_params["aws_access_key_id"] = self.aws_access_key_id
|
|
135
|
+
if self.aws_secret_access_key:
|
|
136
|
+
init_params["aws_secret_access_key"] = self.aws_secret_access_key
|
|
137
|
+
if self.aws_session_token:
|
|
138
|
+
init_params["aws_session_token"] = self.aws_session_token
|
|
139
|
+
if self.credentials_profile_name:
|
|
140
|
+
init_params["credentials_profile_name"] = self.credentials_profile_name
|
|
141
|
+
if self.endpoint_url:
|
|
142
|
+
init_params["endpoint_url"] = self.endpoint_url
|
|
143
|
+
|
|
144
|
+
# Add model parameters directly as supported by ChatBedrockConverse
|
|
145
|
+
if hasattr(self, "temperature") and self.temperature is not None:
|
|
146
|
+
init_params["temperature"] = self.temperature
|
|
147
|
+
if hasattr(self, "max_tokens") and self.max_tokens is not None:
|
|
148
|
+
init_params["max_tokens"] = self.max_tokens
|
|
149
|
+
if hasattr(self, "top_p") and self.top_p is not None:
|
|
150
|
+
init_params["top_p"] = self.top_p
|
|
151
|
+
|
|
152
|
+
# Handle streaming - only disable if explicitly requested
|
|
153
|
+
if hasattr(self, "disable_streaming") and self.disable_streaming:
|
|
154
|
+
init_params["disable_streaming"] = True
|
|
155
|
+
|
|
156
|
+
# Handle additional model request fields carefully
|
|
157
|
+
# Based on the error, inferenceConfig should not be passed as additional fields for some models
|
|
158
|
+
additional_model_request_fields = {}
|
|
159
|
+
|
|
160
|
+
# Only add top_k if user explicitly provided additional fields or if needed for specific models
|
|
161
|
+
if hasattr(self, "additional_model_fields") and self.additional_model_fields:
|
|
162
|
+
for field in self.additional_model_fields:
|
|
163
|
+
if isinstance(field, dict):
|
|
164
|
+
additional_model_request_fields.update(field)
|
|
165
|
+
|
|
166
|
+
# For now, don't automatically add inferenceConfig for top_k to avoid validation errors
|
|
167
|
+
# Users can manually add it via additional_model_fields if their model supports it
|
|
168
|
+
|
|
169
|
+
# Only add if we have actual additional fields
|
|
170
|
+
if additional_model_request_fields:
|
|
171
|
+
init_params["additional_model_request_fields"] = additional_model_request_fields
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
output = ChatBedrockConverse(**init_params)
|
|
175
|
+
except Exception as e:
|
|
176
|
+
# Provide helpful error message with fallback suggestions
|
|
177
|
+
error_details = str(e)
|
|
178
|
+
if "validation error" in error_details.lower():
|
|
179
|
+
msg = (
|
|
180
|
+
f"ChatBedrockConverse validation error: {error_details}. "
|
|
181
|
+
f"This may be due to incompatible parameters for model '{self.model_id}'. "
|
|
182
|
+
f"Consider adjusting the model parameters or trying the legacy Amazon Bedrock component."
|
|
183
|
+
)
|
|
184
|
+
elif "converse api" in error_details.lower():
|
|
185
|
+
msg = (
|
|
186
|
+
f"Converse API error: {error_details}. "
|
|
187
|
+
f"The model '{self.model_id}' may not support the Converse API. "
|
|
188
|
+
f"Try using the legacy Amazon Bedrock component instead."
|
|
189
|
+
)
|
|
190
|
+
else:
|
|
191
|
+
msg = f"Could not initialize ChatBedrockConverse: {error_details}"
|
|
192
|
+
raise ValueError(msg) from e
|
|
193
|
+
|
|
194
|
+
return output
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from lfx.base.models.aws_constants import AWS_EMBEDDING_MODEL_IDS, AWS_REGIONS
|
|
2
|
+
from lfx.base.models.model import LCModelComponent
|
|
3
|
+
from lfx.field_typing import Embeddings
|
|
4
|
+
from lfx.inputs.inputs import SecretStrInput
|
|
5
|
+
from lfx.io import DropdownInput, MessageTextInput, Output
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AmazonBedrockEmbeddingsComponent(LCModelComponent):
|
|
9
|
+
display_name: str = "Amazon Bedrock Embeddings"
|
|
10
|
+
description: str = "Generate embeddings using Amazon Bedrock models."
|
|
11
|
+
icon = "Amazon"
|
|
12
|
+
name = "AmazonBedrockEmbeddings"
|
|
13
|
+
|
|
14
|
+
inputs = [
|
|
15
|
+
DropdownInput(
|
|
16
|
+
name="model_id",
|
|
17
|
+
display_name="Model Id",
|
|
18
|
+
options=AWS_EMBEDDING_MODEL_IDS,
|
|
19
|
+
value="amazon.titan-embed-text-v1",
|
|
20
|
+
),
|
|
21
|
+
SecretStrInput(
|
|
22
|
+
name="aws_access_key_id",
|
|
23
|
+
display_name="AWS Access Key ID",
|
|
24
|
+
info="The access key for your AWS account."
|
|
25
|
+
"Usually set in Python code as the environment variable 'AWS_ACCESS_KEY_ID'.",
|
|
26
|
+
value="AWS_ACCESS_KEY_ID",
|
|
27
|
+
required=True,
|
|
28
|
+
),
|
|
29
|
+
SecretStrInput(
|
|
30
|
+
name="aws_secret_access_key",
|
|
31
|
+
display_name="AWS Secret Access Key",
|
|
32
|
+
info="The secret key for your AWS account. "
|
|
33
|
+
"Usually set in Python code as the environment variable 'AWS_SECRET_ACCESS_KEY'.",
|
|
34
|
+
value="AWS_SECRET_ACCESS_KEY",
|
|
35
|
+
required=True,
|
|
36
|
+
),
|
|
37
|
+
SecretStrInput(
|
|
38
|
+
name="aws_session_token",
|
|
39
|
+
display_name="AWS Session Token",
|
|
40
|
+
advanced=False,
|
|
41
|
+
info="The session key for your AWS account. "
|
|
42
|
+
"Only needed for temporary credentials. "
|
|
43
|
+
"Usually set in Python code as the environment variable 'AWS_SESSION_TOKEN'.",
|
|
44
|
+
value="AWS_SESSION_TOKEN",
|
|
45
|
+
),
|
|
46
|
+
SecretStrInput(
|
|
47
|
+
name="credentials_profile_name",
|
|
48
|
+
display_name="Credentials Profile Name",
|
|
49
|
+
advanced=True,
|
|
50
|
+
info="The name of the profile to use from your "
|
|
51
|
+
"~/.aws/credentials file. "
|
|
52
|
+
"If not provided, the default profile will be used.",
|
|
53
|
+
value="AWS_CREDENTIALS_PROFILE_NAME",
|
|
54
|
+
),
|
|
55
|
+
DropdownInput(
|
|
56
|
+
name="region_name",
|
|
57
|
+
display_name="Region Name",
|
|
58
|
+
value="us-east-1",
|
|
59
|
+
options=AWS_REGIONS,
|
|
60
|
+
info="The AWS region where your Bedrock resources are located.",
|
|
61
|
+
),
|
|
62
|
+
MessageTextInput(
|
|
63
|
+
name="endpoint_url",
|
|
64
|
+
display_name="Endpoint URL",
|
|
65
|
+
advanced=True,
|
|
66
|
+
info="The URL of the AWS Bedrock endpoint to use.",
|
|
67
|
+
),
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
outputs = [
|
|
71
|
+
Output(display_name="Embeddings", name="embeddings", method="build_embeddings"),
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
def build_embeddings(self) -> Embeddings:
|
|
75
|
+
try:
|
|
76
|
+
from langchain_aws import BedrockEmbeddings
|
|
77
|
+
except ImportError as e:
|
|
78
|
+
msg = "langchain_aws is not installed. Please install it with `pip install langchain_aws`."
|
|
79
|
+
raise ImportError(msg) from e
|
|
80
|
+
try:
|
|
81
|
+
import boto3
|
|
82
|
+
except ImportError as e:
|
|
83
|
+
msg = "boto3 is not installed. Please install it with `pip install boto3`."
|
|
84
|
+
raise ImportError(msg) from e
|
|
85
|
+
if self.aws_access_key_id or self.aws_secret_access_key:
|
|
86
|
+
session = boto3.Session(
|
|
87
|
+
aws_access_key_id=self.aws_access_key_id,
|
|
88
|
+
aws_secret_access_key=self.aws_secret_access_key,
|
|
89
|
+
aws_session_token=self.aws_session_token,
|
|
90
|
+
)
|
|
91
|
+
elif self.credentials_profile_name:
|
|
92
|
+
session = boto3.Session(profile_name=self.credentials_profile_name)
|
|
93
|
+
else:
|
|
94
|
+
session = boto3.Session()
|
|
95
|
+
|
|
96
|
+
client_params = {}
|
|
97
|
+
if self.endpoint_url:
|
|
98
|
+
client_params["endpoint_url"] = self.endpoint_url
|
|
99
|
+
if self.region_name:
|
|
100
|
+
client_params["region_name"] = self.region_name
|
|
101
|
+
|
|
102
|
+
boto3_client = session.client("bedrock-runtime", **client_params)
|
|
103
|
+
return BedrockEmbeddings(
|
|
104
|
+
credentials_profile_name=self.credentials_profile_name,
|
|
105
|
+
client=boto3_client,
|
|
106
|
+
model_id=self.model_id,
|
|
107
|
+
endpoint_url=self.endpoint_url,
|
|
108
|
+
region_name=self.region_name,
|
|
109
|
+
)
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
from lfx.base.models.aws_constants import AWS_REGIONS, AWS_MODEL_IDs
|
|
2
|
+
from lfx.base.models.model import LCModelComponent
|
|
3
|
+
from lfx.field_typing import LanguageModel
|
|
4
|
+
from lfx.inputs.inputs import MessageTextInput, SecretStrInput
|
|
5
|
+
from lfx.io import DictInput, DropdownInput
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AmazonBedrockComponent(LCModelComponent):
|
|
9
|
+
display_name: str = "Amazon Bedrock"
|
|
10
|
+
description: str = (
|
|
11
|
+
"Generate text using Amazon Bedrock LLMs with the legacy ChatBedrock API. "
|
|
12
|
+
"This component is deprecated. Please use Amazon Bedrock Converse instead "
|
|
13
|
+
"for better compatibility, newer features, and improved conversation handling."
|
|
14
|
+
)
|
|
15
|
+
icon = "Amazon"
|
|
16
|
+
name = "AmazonBedrockModel"
|
|
17
|
+
legacy = True
|
|
18
|
+
replacement = "amazon.AmazonBedrockConverseModel"
|
|
19
|
+
|
|
20
|
+
inputs = [
|
|
21
|
+
*LCModelComponent.get_base_inputs(),
|
|
22
|
+
DropdownInput(
|
|
23
|
+
name="model_id",
|
|
24
|
+
display_name="Model ID",
|
|
25
|
+
options=AWS_MODEL_IDs,
|
|
26
|
+
value="anthropic.claude-3-haiku-20240307-v1:0",
|
|
27
|
+
info="List of available model IDs to choose from.",
|
|
28
|
+
),
|
|
29
|
+
SecretStrInput(
|
|
30
|
+
name="aws_access_key_id",
|
|
31
|
+
display_name="AWS Access Key ID",
|
|
32
|
+
info="The access key for your AWS account."
|
|
33
|
+
"Usually set in Python code as the environment variable 'AWS_ACCESS_KEY_ID'.",
|
|
34
|
+
value="AWS_ACCESS_KEY_ID",
|
|
35
|
+
required=True,
|
|
36
|
+
),
|
|
37
|
+
SecretStrInput(
|
|
38
|
+
name="aws_secret_access_key",
|
|
39
|
+
display_name="AWS Secret Access Key",
|
|
40
|
+
info="The secret key for your AWS account. "
|
|
41
|
+
"Usually set in Python code as the environment variable 'AWS_SECRET_ACCESS_KEY'.",
|
|
42
|
+
value="AWS_SECRET_ACCESS_KEY",
|
|
43
|
+
required=True,
|
|
44
|
+
),
|
|
45
|
+
SecretStrInput(
|
|
46
|
+
name="aws_session_token",
|
|
47
|
+
display_name="AWS Session Token",
|
|
48
|
+
advanced=False,
|
|
49
|
+
info="The session key for your AWS account. "
|
|
50
|
+
"Only needed for temporary credentials. "
|
|
51
|
+
"Usually set in Python code as the environment variable 'AWS_SESSION_TOKEN'.",
|
|
52
|
+
load_from_db=False,
|
|
53
|
+
),
|
|
54
|
+
SecretStrInput(
|
|
55
|
+
name="credentials_profile_name",
|
|
56
|
+
display_name="Credentials Profile Name",
|
|
57
|
+
advanced=True,
|
|
58
|
+
info="The name of the profile to use from your "
|
|
59
|
+
"~/.aws/credentials file. "
|
|
60
|
+
"If not provided, the default profile will be used.",
|
|
61
|
+
load_from_db=False,
|
|
62
|
+
),
|
|
63
|
+
DropdownInput(
|
|
64
|
+
name="region_name",
|
|
65
|
+
display_name="Region Name",
|
|
66
|
+
value="us-east-1",
|
|
67
|
+
options=AWS_REGIONS,
|
|
68
|
+
info="The AWS region where your Bedrock resources are located.",
|
|
69
|
+
),
|
|
70
|
+
DictInput(
|
|
71
|
+
name="model_kwargs",
|
|
72
|
+
display_name="Model Kwargs",
|
|
73
|
+
advanced=True,
|
|
74
|
+
is_list=True,
|
|
75
|
+
info="Additional keyword arguments to pass to the model.",
|
|
76
|
+
),
|
|
77
|
+
MessageTextInput(
|
|
78
|
+
name="endpoint_url",
|
|
79
|
+
display_name="Endpoint URL",
|
|
80
|
+
advanced=True,
|
|
81
|
+
info="The URL of the Bedrock endpoint to use.",
|
|
82
|
+
),
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
def build_model(self) -> LanguageModel: # type: ignore[type-var]
|
|
86
|
+
try:
|
|
87
|
+
from langchain_aws import ChatBedrock
|
|
88
|
+
except ImportError as e:
|
|
89
|
+
msg = "langchain_aws is not installed. Please install it with `pip install langchain_aws`."
|
|
90
|
+
raise ImportError(msg) from e
|
|
91
|
+
try:
|
|
92
|
+
import boto3
|
|
93
|
+
except ImportError as e:
|
|
94
|
+
msg = "boto3 is not installed. Please install it with `pip install boto3`."
|
|
95
|
+
raise ImportError(msg) from e
|
|
96
|
+
if self.aws_access_key_id or self.aws_secret_access_key:
|
|
97
|
+
try:
|
|
98
|
+
session = boto3.Session(
|
|
99
|
+
aws_access_key_id=self.aws_access_key_id,
|
|
100
|
+
aws_secret_access_key=self.aws_secret_access_key,
|
|
101
|
+
aws_session_token=self.aws_session_token,
|
|
102
|
+
)
|
|
103
|
+
except Exception as e:
|
|
104
|
+
msg = "Could not create a boto3 session."
|
|
105
|
+
raise ValueError(msg) from e
|
|
106
|
+
elif self.credentials_profile_name:
|
|
107
|
+
session = boto3.Session(profile_name=self.credentials_profile_name)
|
|
108
|
+
else:
|
|
109
|
+
session = boto3.Session()
|
|
110
|
+
|
|
111
|
+
client_params = {}
|
|
112
|
+
if self.endpoint_url:
|
|
113
|
+
client_params["endpoint_url"] = self.endpoint_url
|
|
114
|
+
if self.region_name:
|
|
115
|
+
client_params["region_name"] = self.region_name
|
|
116
|
+
|
|
117
|
+
boto3_client = session.client("bedrock-runtime", **client_params)
|
|
118
|
+
try:
|
|
119
|
+
output = ChatBedrock(
|
|
120
|
+
client=boto3_client,
|
|
121
|
+
model_id=self.model_id,
|
|
122
|
+
region_name=self.region_name,
|
|
123
|
+
model_kwargs=self.model_kwargs,
|
|
124
|
+
endpoint_url=self.endpoint_url,
|
|
125
|
+
streaming=self.stream,
|
|
126
|
+
)
|
|
127
|
+
except Exception as e:
|
|
128
|
+
msg = "Could not connect to AmazonBedrock API."
|
|
129
|
+
raise ValueError(msg) from e
|
|
130
|
+
return output
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from lfx.custom.custom_component.component import Component
|
|
5
|
+
from lfx.io import (
|
|
6
|
+
BoolInput,
|
|
7
|
+
DropdownInput,
|
|
8
|
+
HandleInput,
|
|
9
|
+
Output,
|
|
10
|
+
SecretStrInput,
|
|
11
|
+
StrInput,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class S3BucketUploaderComponent(Component):
|
|
16
|
+
"""S3BucketUploaderComponent is a component responsible for uploading files to an S3 bucket.
|
|
17
|
+
|
|
18
|
+
It provides two strategies for file upload: "By Data" and "By File Name". The component
|
|
19
|
+
requires AWS credentials and bucket details as inputs and processes files accordingly.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
display_name (str): The display name of the component.
|
|
23
|
+
description (str): A brief description of the components functionality.
|
|
24
|
+
icon (str): The icon representing the component.
|
|
25
|
+
name (str): The internal name of the component.
|
|
26
|
+
inputs (list): A list of input configurations required by the component.
|
|
27
|
+
outputs (list): A list of output configurations provided by the component.
|
|
28
|
+
|
|
29
|
+
Methods:
|
|
30
|
+
process_files() -> None:
|
|
31
|
+
Processes files based on the selected strategy. Calls the appropriate method
|
|
32
|
+
based on the strategy attribute.
|
|
33
|
+
process_files_by_data() -> None:
|
|
34
|
+
Processes and uploads files to an S3 bucket based on the data inputs. Iterates
|
|
35
|
+
over the data inputs, logs the file path and text content, and uploads each file
|
|
36
|
+
to the specified S3 bucket if both file path and text content are available.
|
|
37
|
+
process_files_by_name() -> None:
|
|
38
|
+
Processes and uploads files to an S3 bucket based on their names. Iterates through
|
|
39
|
+
the list of data inputs, retrieves the file path from each data item, and uploads
|
|
40
|
+
the file to the specified S3 bucket if the file path is available. Logs the file
|
|
41
|
+
path being uploaded.
|
|
42
|
+
_s3_client() -> Any:
|
|
43
|
+
Creates and returns an S3 client using the provided AWS access key ID and secret
|
|
44
|
+
access key.
|
|
45
|
+
|
|
46
|
+
Please note that this component requires the boto3 library to be installed. It is designed
|
|
47
|
+
to work with File and Director components as inputs
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
display_name = "S3 Bucket Uploader"
|
|
51
|
+
description = "Uploads files to S3 bucket."
|
|
52
|
+
icon = "Amazon"
|
|
53
|
+
name = "s3bucketuploader"
|
|
54
|
+
|
|
55
|
+
inputs = [
|
|
56
|
+
SecretStrInput(
|
|
57
|
+
name="aws_access_key_id",
|
|
58
|
+
display_name="AWS Access Key ID",
|
|
59
|
+
required=True,
|
|
60
|
+
password=True,
|
|
61
|
+
info="AWS Access key ID.",
|
|
62
|
+
),
|
|
63
|
+
SecretStrInput(
|
|
64
|
+
name="aws_secret_access_key",
|
|
65
|
+
display_name="AWS Secret Key",
|
|
66
|
+
required=True,
|
|
67
|
+
password=True,
|
|
68
|
+
info="AWS Secret Key.",
|
|
69
|
+
),
|
|
70
|
+
StrInput(
|
|
71
|
+
name="bucket_name",
|
|
72
|
+
display_name="Bucket Name",
|
|
73
|
+
info="Enter the name of the bucket.",
|
|
74
|
+
advanced=False,
|
|
75
|
+
),
|
|
76
|
+
DropdownInput(
|
|
77
|
+
name="strategy",
|
|
78
|
+
display_name="Strategy for file upload",
|
|
79
|
+
options=["Store Data", "Store Original File"],
|
|
80
|
+
value="By Data",
|
|
81
|
+
info=(
|
|
82
|
+
"Choose the strategy to upload the file. By Data means that the source file "
|
|
83
|
+
"is parsed and stored as LangFlow data. By File Name means that the source "
|
|
84
|
+
"file is uploaded as is."
|
|
85
|
+
),
|
|
86
|
+
),
|
|
87
|
+
HandleInput(
|
|
88
|
+
name="data_inputs",
|
|
89
|
+
display_name="Data Inputs",
|
|
90
|
+
info="The data to split.",
|
|
91
|
+
input_types=["Data", "JSON"],
|
|
92
|
+
is_list=True,
|
|
93
|
+
required=True,
|
|
94
|
+
),
|
|
95
|
+
StrInput(
|
|
96
|
+
name="s3_prefix",
|
|
97
|
+
display_name="S3 Prefix",
|
|
98
|
+
info="Prefix for all files.",
|
|
99
|
+
advanced=True,
|
|
100
|
+
),
|
|
101
|
+
BoolInput(
|
|
102
|
+
name="strip_path",
|
|
103
|
+
display_name="Strip Path",
|
|
104
|
+
info="Removes path from file path.",
|
|
105
|
+
required=True,
|
|
106
|
+
advanced=True,
|
|
107
|
+
),
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
outputs = [
|
|
111
|
+
Output(display_name="Writes to AWS Bucket", name="data", method="process_files"),
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
def process_files(self) -> None:
|
|
115
|
+
"""Process files based on the selected strategy.
|
|
116
|
+
|
|
117
|
+
This method uses a strategy pattern to process files. The strategy is determined
|
|
118
|
+
by the `self.strategy` attribute, which can be either "By Data" or "By File Name".
|
|
119
|
+
Depending on the strategy, the corresponding method (`process_files_by_data` or
|
|
120
|
+
`process_files_by_name`) is called. If an invalid strategy is provided, an error
|
|
121
|
+
is logged.
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
None
|
|
125
|
+
"""
|
|
126
|
+
strategy_methods = {
|
|
127
|
+
"Store Data": self.process_files_by_data,
|
|
128
|
+
"Store Original File": self.process_files_by_name,
|
|
129
|
+
}
|
|
130
|
+
strategy_methods.get(self.strategy, lambda: self.log("Invalid strategy"))()
|
|
131
|
+
|
|
132
|
+
def process_files_by_data(self) -> None:
|
|
133
|
+
"""Processes and uploads files to an S3 bucket based on the data inputs.
|
|
134
|
+
|
|
135
|
+
This method iterates over the data inputs, logs the file path and text content,
|
|
136
|
+
and uploads each file to the specified S3 bucket if both file path and text content
|
|
137
|
+
are available.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
None
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
None
|
|
144
|
+
"""
|
|
145
|
+
for data_item in self.data_inputs:
|
|
146
|
+
file_path = data_item.data.get("file_path")
|
|
147
|
+
text_content = data_item.data.get("text")
|
|
148
|
+
|
|
149
|
+
if file_path and text_content:
|
|
150
|
+
self._s3_client().put_object(
|
|
151
|
+
Bucket=self.bucket_name, Key=self._normalize_path(file_path), Body=text_content
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def process_files_by_name(self) -> None:
|
|
155
|
+
"""Processes and uploads files to an S3 bucket based on their names.
|
|
156
|
+
|
|
157
|
+
Iterates through the list of data inputs, retrieves the file path from each data item,
|
|
158
|
+
and uploads the file to the specified S3 bucket if the file path is available.
|
|
159
|
+
Logs the file path being uploaded.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
None
|
|
163
|
+
"""
|
|
164
|
+
for data_item in self.data_inputs:
|
|
165
|
+
file_path = data_item.data.get("file_path")
|
|
166
|
+
self.log(f"Uploading file: {file_path}")
|
|
167
|
+
if file_path:
|
|
168
|
+
self._s3_client().upload_file(file_path, Bucket=self.bucket_name, Key=self._normalize_path(file_path))
|
|
169
|
+
|
|
170
|
+
def _s3_client(self) -> Any:
|
|
171
|
+
"""Creates and returns an S3 client using the provided AWS access key ID and secret access key.
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
Any: A boto3 S3 client instance.
|
|
175
|
+
"""
|
|
176
|
+
try:
|
|
177
|
+
import boto3
|
|
178
|
+
except ImportError as e:
|
|
179
|
+
msg = "boto3 is not installed. Please install it using `uv pip install boto3`."
|
|
180
|
+
raise ImportError(msg) from e
|
|
181
|
+
|
|
182
|
+
return boto3.client(
|
|
183
|
+
"s3",
|
|
184
|
+
aws_access_key_id=self.aws_access_key_id,
|
|
185
|
+
aws_secret_access_key=self.aws_secret_access_key,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
def _normalize_path(self, file_path) -> str:
|
|
189
|
+
"""Process the file path based on the s3_prefix and path_as_prefix.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
file_path (str): The original file path.
|
|
193
|
+
s3_prefix (str): The S3 prefix to use.
|
|
194
|
+
path_as_prefix (bool): Whether to use the file path as the S3 prefix.
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
str: The processed file path.
|
|
198
|
+
"""
|
|
199
|
+
prefix = self.s3_prefix
|
|
200
|
+
strip_path = self.strip_path
|
|
201
|
+
processed_path: str = file_path
|
|
202
|
+
|
|
203
|
+
if strip_path:
|
|
204
|
+
# Filename only
|
|
205
|
+
processed_path = Path(file_path).name
|
|
206
|
+
|
|
207
|
+
# Concatenate the s3_prefix if it exists
|
|
208
|
+
if prefix:
|
|
209
|
+
processed_path = str(Path(prefix) / processed_path)
|
|
210
|
+
|
|
211
|
+
return processed_path
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://schemas.langflow.org/extension/v1.json",
|
|
3
|
+
"id": "lfx-amazon",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"name": "Amazon",
|
|
6
|
+
"description": "Amazon component(s) as a standalone Langflow Extension Bundle.",
|
|
7
|
+
"lfx": {
|
|
8
|
+
"compat": ["1"]
|
|
9
|
+
},
|
|
10
|
+
"bundles": [
|
|
11
|
+
{
|
|
12
|
+
"name": "amazon",
|
|
13
|
+
"path": "components/amazon"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lfx-amazon
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Amazon component(s) as a standalone Langflow Extension Bundle.
|
|
5
|
+
Project-URL: Homepage, https://github.com/langflow-ai/langflow
|
|
6
|
+
Project-URL: Documentation, https://docs.langflow.org/extensions
|
|
7
|
+
Project-URL: Repository, https://github.com/langflow-ai/langflow
|
|
8
|
+
Author-email: Langflow <contact@langflow.org>
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: amazon,bundle,extension,langflow,lfx
|
|
11
|
+
Requires-Python: <3.15,>=3.10
|
|
12
|
+
Requires-Dist: boto3<2.0.0,>=1.34.162
|
|
13
|
+
Requires-Dist: langchain-aws~=1.1.0
|
|
14
|
+
Requires-Dist: lfx<2.0.0,>=1.11.0.dev0
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# lfx-amazon
|
|
18
|
+
|
|
19
|
+
Amazon component(s) as a standalone Langflow Extension Bundle.
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install lfx-amazon
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The bundle is registered automatically via the `langflow.extensions`
|
|
28
|
+
entry-point. After install, restart your Langflow server; the bundle's
|
|
29
|
+
components will appear in the palette under the `amazon` group with
|
|
30
|
+
the namespaced IDs `ext:amazon:<Class>@official`.
|
|
31
|
+
|
|
32
|
+
## Develop
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
cd src/bundles/amazon
|
|
36
|
+
pip install -e .
|
|
37
|
+
lfx extension validate src/lfx_amazon
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Migration
|
|
41
|
+
|
|
42
|
+
Saved flows referencing the legacy class name(s) or the old import paths
|
|
43
|
+
under `lfx.components.amazon.*` are rewritten to the new namespaced
|
|
44
|
+
IDs by the migration table in
|
|
45
|
+
`src/lfx/src/lfx/extension/migration/migration_table.json`.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
lfx_amazon/__init__.py,sha256=xCWeEXTDF1DjAw-55rGmLj0MWT_9N4rhWoF_uXBU1QI,786
|
|
2
|
+
lfx_amazon/extension.json,sha256=Ejr9xXXpgIV_Ny6aBihhTgBQt8mW9rCYaq6zh1pie3A,339
|
|
3
|
+
lfx_amazon/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
lfx_amazon/components/amazon/__init__.py,sha256=VcvjM_esVzalJQaJMiZBPmjcajhmGUBJa5WnSr5X51c,1716
|
|
5
|
+
lfx_amazon/components/amazon/amazon_bedrock_converse.py,sha256=ZrlRn09iUwUiWNEzbcKLdje386r4YGj-bC0j7wyi5wM,8179
|
|
6
|
+
lfx_amazon/components/amazon/amazon_bedrock_embedding.py,sha256=cNA5_3nwkegWS3BY75IfjOwpo-g8dpg-EgtQJSgVXfg,4261
|
|
7
|
+
lfx_amazon/components/amazon/amazon_bedrock_model.py,sha256=kiCTqDG2Krbe0i5YBG9UODxwNTB9ePZwLfgNMR91UwQ,5113
|
|
8
|
+
lfx_amazon/components/amazon/s3_bucket_uploader.py,sha256=EZyJtr1AOad5dg5wr-K9TwXyCjCbb6U5NPV41nYJii4,7696
|
|
9
|
+
lfx_amazon-0.1.0.dist-info/METADATA,sha256=g1GcpT4-VoGMcDRDeWmkLKjQClbscD4YI0WoeFXVzsg,1342
|
|
10
|
+
lfx_amazon-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
11
|
+
lfx_amazon-0.1.0.dist-info/entry_points.txt,sha256=drlpBtwZARzsmLFCgTKDKFj98bTO_O4u2RpGDRrNiCc,46
|
|
12
|
+
lfx_amazon-0.1.0.dist-info/RECORD,,
|