Skip to content

Commit 96c1456

Browse files
Merge pull request #4 from glorious-beard/glorious-beard/367-fix-bedrockservicefactory
fix: fixes microsoft#10738 by adding function for scrubbing cross-regional pre…
2 parents 85020e9 + e668daf commit 96c1456

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

dotnet/src/Connectors/Connectors.Amazon.UnitTests/Extensions/BedrockKernelBuilderExtensionTests.cs

+29-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Copyright (c) Microsoft. All rights reserved.
22

3+
using System;
34
using Amazon.BedrockRuntime;
45
using Amazon.Runtime;
56
using Microsoft.SemanticKernel.ChatCompletion;
@@ -18,13 +19,15 @@ public class BedrockKernelBuilderExtensionTests
1819
/// <summary>
1920
/// Checks that AddBedrockTextGenerationService builds a proper kernel with a null bedrockRuntime.
2021
/// </summary>
21-
[Fact]
22-
public void AddBedrockTextGenerationCreatesServiceWithNonNullBedrockRuntime()
22+
[Theory]
23+
[InlineData("amazon.titan-text-premier-v1:0")]
24+
[InlineData("us.amazon.titan-text-premier-v1:0")]
25+
public void AddBedrockTextGenerationCreatesServiceWithNonNullBedrockRuntime(string modelId)
2326
{
2427
// Arrange
2528
var bedrockRuntime = new Mock<IAmazonBedrockRuntime>().Object;
2629
var builder = Kernel.CreateBuilder();
27-
builder.AddBedrockTextGenerationService("amazon.titan-text-premier-v1:0", bedrockRuntime);
30+
builder.AddBedrockTextGenerationService(modelId, bedrockRuntime);
2831

2932
// Act
3033
var kernel = builder.Build();
@@ -37,13 +40,15 @@ public void AddBedrockTextGenerationCreatesServiceWithNonNullBedrockRuntime()
3740
/// <summary>
3841
/// Checks that AddBedrockChatCompletionService builds a proper kernel with a non-null bedrockRuntime.
3942
/// </summary>
40-
[Fact]
41-
public void AddBedrockChatCompletionCreatesServiceWithNonNullBedrockRuntime()
43+
[Theory]
44+
[InlineData("amazon.titan-text-premier-v1:0")]
45+
[InlineData("us.amazon.titan-text-premier-v1:0")]
46+
public void AddBedrockChatCompletionCreatesServiceWithNonNullBedrockRuntime(string modelId)
4247
{
4348
// Arrange
4449
var bedrockRuntime = new Mock<IAmazonBedrockRuntime>().Object;
4550
var builder = Kernel.CreateBuilder();
46-
builder.AddBedrockChatCompletionService("amazon.titan-text-premier-v1:0", bedrockRuntime);
51+
builder.AddBedrockChatCompletionService(modelId, bedrockRuntime);
4752

4853
// Act
4954
var kernel = builder.Build();
@@ -65,4 +70,22 @@ public void AwsServiceClientBeforeServiceRequestDoesNothingForNonWebServiceReque
6570
// Assert
6671
// No exceptions should be thrown
6772
}
73+
74+
[Theory]
75+
[InlineData("unknown.titan-text-premier-v1:0")]
76+
[InlineData("us.unknown.titan-text-premier-v1:0")]
77+
public void AwsUnknownBedrockTextCompletionModelShouldThrowException(string modelId)
78+
{
79+
// Arrange
80+
var bedrockRuntime = new Mock<IAmazonBedrockRuntime>().Object;
81+
var builder = Kernel.CreateBuilder();
82+
builder.AddBedrockTextGenerationService(modelId, bedrockRuntime);
83+
84+
// Act & Assert
85+
Assert.Throws<KernelException>(() =>
86+
{
87+
var kernel = builder.Build();
88+
kernel.GetRequiredService<ITextGenerationService>();
89+
});
90+
}
6891
}

dotnet/src/Connectors/Connectors.Amazon/Bedrock/Core/BedrockServiceFactory.cs

+27-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft. All rights reserved.
22

33
using System;
4+
using System.Linq;
45

56
namespace Microsoft.SemanticKernel.Connectors.Amazon.Core;
67

@@ -9,6 +10,30 @@ namespace Microsoft.SemanticKernel.Connectors.Amazon.Core;
910
/// </summary>
1011
internal sealed class BedrockServiceFactory
1112
{
13+
/// <summary>
14+
/// Represents an array of region prefixes used to identify different cross-region configurations
15+
/// for service operations. The prefixes correspond to general geographic areas such as
16+
/// "us" (United States), "eu" (Europe), and "apac" (Asia-Pacific).
17+
/// (sourced from https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html)
18+
/// </summary>
19+
private static readonly string[] s_crossRegionPrefixes = ["us.", "eu.", "apac."];
20+
21+
/// <summary>
22+
/// Removes the cross-region prefix from the provided model identifier if it exists.
23+
/// </summary>
24+
/// <param name="modelId">The model identifier, which may contain a cross-region prefix.</param>
25+
/// <returns>The model identifier without the cross-region prefix.</returns>
26+
private static string ScrubCrossRegionPrefix(string modelId)
27+
{
28+
var prefix = s_crossRegionPrefixes.FirstOrDefault(prefix => modelId.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase));
29+
if (!string.IsNullOrWhiteSpace(prefix))
30+
{
31+
modelId = modelId.Substring(prefix.Length);
32+
}
33+
34+
return modelId;
35+
}
36+
1237
/// <summary>
1338
/// Gets the model service for body conversion.
1439
/// </summary>
@@ -17,7 +42,7 @@ internal sealed class BedrockServiceFactory
1742
/// <exception cref="NotSupportedException">Thrown if provider or model is not supported for text generation.</exception>
1843
internal IBedrockTextGenerationService CreateTextGenerationService(string modelId)
1944
{
20-
(string modelProvider, string modelName) = this.GetModelProviderAndName(modelId);
45+
(string modelProvider, string modelName) = this.GetModelProviderAndName(ScrubCrossRegionPrefix(modelId));
2146

2247
switch (modelProvider.ToUpperInvariant())
2348
{
@@ -79,7 +104,7 @@ internal IBedrockTextGenerationService CreateTextGenerationService(string modelI
79104
/// <exception cref="NotSupportedException">Thrown if provider or model is not supported for chat completion.</exception>
80105
internal IBedrockChatCompletionService CreateChatCompletionService(string modelId)
81106
{
82-
(string modelProvider, string modelName) = this.GetModelProviderAndName(modelId);
107+
(string modelProvider, string modelName) = this.GetModelProviderAndName(ScrubCrossRegionPrefix(modelId));
83108

84109
switch (modelProvider.ToUpperInvariant())
85110
{

0 commit comments

Comments
 (0)