Skip to content

Commit 10fd013

Browse files
roeybcsxlijin
andauthored
feat: added endpoint_url to amazon bedrock (#2555)
Added support to endpoint_url when calling amazon bedrock. This is needed to support private endpoints behind VPCs on aws. --------- Signed-off-by: Roey Ben Chaim <roey.benhaim@gmail.com> Co-authored-by: Sam Lijin <sam@boundaryml.com>
1 parent 40bc568 commit 10fd013

45 files changed

Lines changed: 1584 additions & 26 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎engine/baml-lib/llm-client/src/clients/aws_bedrock.rs‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub struct UnresolvedAwsBedrock<Meta> {
2222
secret_access_key: Option<StringOr>,
2323
session_token: Option<StringOr>,
2424
profile: Option<StringOr>,
25+
endpoint_url: Option<StringOr>,
2526
role_selection: UnresolvedRolesSelection,
2627
allowed_role_metadata: UnresolvedAllowedRoleMetadata,
2728
supported_request_modes: SupportedRequestModes,
@@ -78,6 +79,7 @@ pub struct ResolvedAwsBedrock {
7879
pub secret_access_key: Option<ApiKeyWithProvenance>,
7980
pub session_token: Option<String>,
8081
pub profile: Option<String>,
82+
pub endpoint_url: Option<String>,
8183
pub inference_config: Option<InferenceConfiguration>,
8284
role_selection: RolesSelection,
8385
pub allowed_role_metadata: AllowedRoleMetadata,
@@ -95,6 +97,7 @@ impl std::fmt::Debug for ResolvedAwsBedrock {
9597
.field("secret_access_key", &"<no-repr-available>")
9698
.field("session_token", &self.session_token)
9799
.field("profile", &self.profile)
100+
.field("endpoint_url", &self.endpoint_url)
98101
.field("inference_config", &"<no-repr-available>")
99102
.field("role_selection", &self.role_selection)
100103
.field("allowed_role_metadata", &self.allowed_role_metadata)
@@ -121,6 +124,12 @@ impl ResolvedAwsBedrock {
121124
serde_json::Value::String(region.clone()),
122125
);
123126
}
127+
if let Some(endpoint_url) = &self.endpoint_url {
128+
options.insert(
129+
"endpoint_url".to_string(),
130+
serde_json::Value::String(endpoint_url.clone()),
131+
);
132+
}
124133
options
125134
}
126135

@@ -162,6 +171,7 @@ impl<Meta: Clone> UnresolvedAwsBedrock<Meta> {
162171
secret_access_key: self.secret_access_key.clone(),
163172
session_token: self.session_token.clone(),
164173
profile: self.profile.clone(),
174+
endpoint_url: self.endpoint_url.clone(),
165175
role_selection: self.role_selection.clone(),
166176
allowed_role_metadata: self.allowed_role_metadata.clone(),
167177
supported_request_modes: self.supported_request_modes.clone(),
@@ -215,6 +225,11 @@ impl<Meta: Clone> UnresolvedAwsBedrock<Meta> {
215225
}
216226
}
217227

228+
match self.endpoint_url.as_ref() {
229+
Some(endpoint_url) => env_vars.extend(endpoint_url.required_env_vars()),
230+
None => {}
231+
}
232+
218233
env_vars.extend(self.role_selection.required_env_vars());
219234
env_vars.extend(self.allowed_role_metadata.required_env_vars());
220235
env_vars.extend(self.supported_request_modes.required_env_vars());
@@ -357,6 +372,18 @@ impl<Meta: Clone> UnresolvedAwsBedrock<Meta> {
357372
},
358373
};
359374

375+
let endpoint_url = match self.endpoint_url.as_ref() {
376+
Some(endpoint_url) => {
377+
let url = endpoint_url.resolve(ctx)?;
378+
if url.is_empty() {
379+
None
380+
} else {
381+
Some(url)
382+
}
383+
}
384+
None => None,
385+
};
386+
360387
#[cfg(target_arch = "wasm32")]
361388
{
362389
if region.is_none() {
@@ -377,6 +404,7 @@ impl<Meta: Clone> UnresolvedAwsBedrock<Meta> {
377404
secret_access_key,
378405
session_token,
379406
profile,
407+
endpoint_url,
380408
role_selection,
381409
allowed_role_metadata: self.allowed_role_metadata.resolve(ctx)?,
382410
supported_request_modes: self.supported_request_modes.clone(),
@@ -430,6 +458,9 @@ impl<Meta: Clone> UnresolvedAwsBedrock<Meta> {
430458
let profile = properties
431459
.ensure_string("profile", false)
432460
.map(|(_, v, _)| v.clone());
461+
let endpoint_url = properties
462+
.ensure_string("endpoint_url", false)
463+
.map(|(_, v, _)| v.clone());
433464

434465
let role_selection = properties.ensure_roles_selection();
435466
let allowed_metadata = properties.ensure_allowed_metadata();
@@ -511,6 +542,7 @@ impl<Meta: Clone> UnresolvedAwsBedrock<Meta> {
511542
secret_access_key,
512543
session_token,
513544
profile,
545+
endpoint_url,
514546
role_selection,
515547
allowed_role_metadata: allowed_metadata,
516548
supported_request_modes,

‎engine/baml-runtime/src/internal/llm_client/primitive/aws/aws_client.rs‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ impl AwsClient {
592592
let config = loader.load().await;
593593
let http_client = custom_http_client::client()?;
594594

595-
let bedrock_config = aws_sdk_bedrockruntime::config::Builder::from(&config)
595+
let mut bedrock_config = aws_sdk_bedrockruntime::config::Builder::from(&config)
596596
// To support HTTPS_PROXY https://github.com/awslabs/aws-sdk-rust/issues/169
597597
.http_client(http_client)
598598
// Adding a custom http client (above) breaks the stalled stream protection for some reason. If a bedrock request takes longer than 5s (the default grace period, it makes it error out), so we disable it.
@@ -601,9 +601,14 @@ impl AwsClient {
601601
call_stack,
602602
http_request_id.clone(),
603603
&self.properties,
604-
))
605-
.build();
606-
Ok(BedrockRuntimeClient::from_conf(bedrock_config))
604+
));
605+
606+
// Set endpoint_url if specified
607+
if let Some(endpoint_url) = self.properties.endpoint_url.as_ref() {
608+
bedrock_config = bedrock_config.endpoint_url(endpoint_url);
609+
}
610+
611+
Ok(BedrockRuntimeClient::from_conf(bedrock_config.build()))
607612
}
608613

609614
async fn chat_anyhow(&self, response: &ConverseOutput) -> Result<String> {

‎fern/03-reference/baml/clients/providers/aws-bedrock.mdx‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,10 @@ You can use this to modify the `region`, `access_key_id`, `secret_access_key`, a
479479
AWS profile name from credentials file. **Default: `AWS_PROFILE` environment variable**
480480
</ParamField>
481481

482+
<ParamField path="endpoint_url" type="string">
483+
AWS endpoint URL. Useful for using a VPC endpoint.
484+
</ParamField>
485+
482486
<Markdown src="/snippets/role-selection.mdx" />
483487
<Markdown src="/snippets/allowed-role-metadata-basic.mdx" />
484488
<Markdown src="/snippets/supports-streaming.mdx" />

‎integ-tests/baml_src/clients.baml‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,10 @@ client<llm> AwsBedrock {
227227
}
228228
// max_tokens 100000
229229
// max_completion_tokens 100000
230-
// model "anthropic.claude-3-5-sonnet-20240620-v1:0"
230+
model "anthropic.claude-3-5-sonnet-20240620-v1:0"
231231
// model_id "anthropic.claude-3-haiku-20240307-v1:0"
232-
model "arn:aws:bedrock:us-east-1:404337120808:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0"
232+
//model "arn:aws:bedrock:us-east-1:404337120808:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0"
233+
endpoint_url "https://bedrock-runtime.us-east-1.amazonaws.com/"
233234
// region "us-east-1"
234235
// access_key_id env.AWS_ACCESS_KEY_ID
235236
// secret_access_key env.AWS_SECRET_ACCESS_KEY
@@ -253,6 +254,14 @@ client<llm> AwsBedrockInvalidRegion {
253254
}
254255
}
255256

257+
client<llm> AwsBedrockInvalidEndpoint {
258+
provider aws-bedrock
259+
options {
260+
model "anthropic.claude-3-5-sonnet-20240620-v1:0"
261+
endpoint_url "https://bedrock-runtime.us-doenotexist-3.amazonaws.com"
262+
}
263+
}
264+
256265
client<llm> AwsBedrockInvalidAccessKey {
257266
provider aws-bedrock
258267
options {

‎integ-tests/baml_src/generators.baml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,5 @@ generator lang_go {
4949
output_dir "../go"
5050
version "0.211.0"
5151
client_package_name "example.com/integ-tests"
52-
on_generate "mise x -- gofmt -w . && mise x -- goimports -w . && mise x -- go mod tidy"
52+
on_generate "gofmt -w . && goimports -w . && go mod tidy"
5353
}

‎integ-tests/baml_src/test-files/providers/aws.baml‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ function TestAwsInvalidRegion(input: string) -> string {
3737
"#
3838
}
3939

40+
function TestAwsInvalidEndpoint(input: string) -> string {
41+
client AwsBedrockInvalidEndpoint
42+
prompt #"
43+
Write a nice short story about {{ input }}. Keep it to 15 words or less.
44+
"#
45+
}
46+
4047
function TestAwsInvalidAccessKey(input: string) -> string {
4148
client AwsBedrockInvalidAccessKey
4249
prompt #"

‎integ-tests/go/baml_client/baml_source_map.go‎

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎integ-tests/go/baml_client/functions.go‎

Lines changed: 66 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎integ-tests/go/baml_client/functions_parse.go‎

Lines changed: 47 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎integ-tests/go/baml_client/functions_parse_stream.go‎

Lines changed: 47 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)