Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
DOTYCZY: Wszystkich poziomów zarządzania API
W tym artykule zaimportujesz interfejs API modelu języka Amazon Bedrock do wystąpienia usługi API Management jako interfejs API przekazywania. Jest to przykład modelu hostowanego u dostawcy wnioskowania innego niż usługi Azure AI. Użyj zasad bramy sztucznej inteligencji i innych funkcji w usłudze API Management, aby uprościć integrację, zwiększyć czytelność i zwiększyć kontrolę nad punktami końcowymi modelu.
Dowiedz się więcej o zarządzaniu interfejsami API sztucznej inteligencji w usłudze API Management:
Dowiedz się więcej o amazon Bedrock:
Wymagania wstępne
- Istniejąca instancja usługi API Management. Utwórz go, jeśli jeszcze tego nie zrobiono.
- Konto usługi Amazon Web Services (AWS) z dostępem do aplikacji Amazon Bedrock i dostęp do co najmniej jednego modelu fundacji Amazon Bedrock. Dowiedz się więcej
Tworzenie kluczy dostępu użytkowników IAM
Aby uwierzytelnić wystąpienie usługi API Management w usłudze Amazon API Gateway, musisz mieć klucze dostępu dla użytkownika usługi AWS IAM.
Aby wygenerować wymagany identyfikator klucza dostępu i klucz tajny przy użyciu konsoli zarządzania platformy AWS, zobacz Tworzenie klucza dostępu dla siebie w dokumentacji platformy AWS.
Zapisz klucze dostępu w bezpiecznej lokalizacji. Zapiszesz je jako nazwane wartości w następnym kroku.
Ostrzeżenie
Klucze dostępu są poświadczeniami długoterminowymi i należy zarządzać nimi tak bezpiecznie, jak w przypadku hasła. Dowiedz się więcej o zabezpieczaniu kluczy dostępu
Przechowywanie kluczy dostępu użytkowników IAM jako nazwanych wartości
Bezpiecznie przechowuj dwa klucze dostępu użytkowników IAM jako sekretne nazwane wartości w instancji usługi Azure API Management przy użyciu konfiguracji zalecanej w poniższej tabeli.
| Wpis tajny platformy AWS | Nazwa | Tajna wartość |
|---|---|---|
| Klucz dostępu | accesskey | Identyfikator klucza dostępu pobrany z platformy AWS |
| Tajny klucz dostępu | secretkey | Klucz dostępu tajnego pobrany z platformy AWS |
Importowanie interfejsu API Bedrock przy użyciu portalu
Aby zaimportować interfejs API Amazon Bedrock do usługi API Management:
Na portalu Azure przejdź do instancji zarządzania API.
W menu po lewej stronie, w obszarze APIs, wybierz APIs>+ Dodaj API.
W obszarze Definiowanie nowego interfejsu API wybierz pozycję Interfejs API modelu językowego.
Na karcie Konfiguracja API :
Wprowadź nazwę wyświetlaną i opcjonalny opis dla API.
Wprowadź następujący adres URL domyślnego punktu końcowego Amazon Bedrock:
https://bedrock-runtime.<aws-region>.amazonaws.com.Przykład:
https://bedrock-runtime.us-east-1.amazonaws.comOpcjonalnie wybierz co najmniej jeden produkt do skojarzenia z interfejsem API.
W polu Ścieżka dołącz ścieżkę używaną przez wystąpienie usługi API Management do uzyskiwania dostępu do punktów końcowych interfejsu API LLM.
Wybierz opcję Typ, a następnie wybierz Utwórz API passthrough.
Pozostaw puste wartości w polu Klucz dostępu .
Na pozostałych kartach opcjonalnie skonfiguruj zasady do zarządzania użyciem tokenów, buforowaniem semantycznym i bezpieczeństwem zawartości sztucznej inteligencji. Aby uzyskać szczegółowe informacje, zobacz Importowanie interfejsu API modelu językowego.
Wybierz opcję Przejrzyj.
Po zweryfikowaniu ustawień wybierz pozycję Utwórz.
Usługa API Management tworzy interfejs API i (opcjonalnie) zasady ułatwiające monitorowanie interfejsu API i zarządzanie nim.
Konfigurowanie zasad w celu uwierzytelniania żądań w interfejsie API Amazon Bedrock
Skonfiguruj polityki zarządzania API, aby podpisywać zapytania do interfejsu API Amazon Bedrock. Dowiedz się więcej o podpisywaniu żądań interfejsu API platformy AWS
W poniższym przykładzie użyto wcześniej utworzonych nazwanych wartości accesskey i secretkey dla klucza dostępu i tajnego klucza platformy AWS. Ustaw zmienną region na odpowiednią wartość dla interfejsu API Amazon Bedrock. W przykładzie użyto us-east-1 dla regionu.
Na portalu Azure przejdź do instancji zarządzania API.
W menu po lewej stronie w obszarze Interfejsy API wybierz pozycję Interfejsy API.
Wybierz API, które utworzyłeś w poprzedniej sekcji.
W menu po lewej stronie w obszarze Projekt wybierz pozycję Wszystkie operacje.
Wybierz kartę Przetwarzanie przychodzące .
W edytorze zasad przetwarzania przychodzącego wybierz /<>, aby otworzyć edytor zasad.
Skonfiguruj następujące zasady:
<policies> <inbound> <base /> <set-variable name="now" value="@(DateTime.UtcNow)" /> <set-header name="X-Amz-Date" exists-action="override"> <value>@(((DateTime)context.Variables["now"]).ToString("yyyyMMddTHHmmssZ"))</value> </set-header> <set-header name="X-Amz-Content-Sha256" exists-action="override"> <value>@{ var body = context.Request.Body.As<string>(preserveContent: true); using (var sha256 = System.Security.Cryptography.SHA256.Create()) { var hash = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(body)); return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); } }</value> </set-header> <set-header name="Authorization" exists-action="override"> <value>@{ var accessKey = "{{accesskey}}"; var secretKey = "{{secretkey}}"; var region = "us-east-1"; var service = "bedrock"; var method = context.Request.Method; var uri = context.Request.Url; var host = uri.Host; // Create canonical path var path = uri.Path; var modelSplit = path.Split(new[] { "model/" }, 2, StringSplitOptions.None); var afterModel = modelSplit.Length > 1 ? modelSplit[1] : ""; var parts = afterModel.Split(new[] { '/' }, 2); var model = System.Uri.EscapeDataString(parts[0]); var remainder = parts.Length > 1 ? parts[1] : ""; var canonicalPath = $"/model/{model}/{remainder}"; var amzDate = ((DateTime)context.Variables["now"]).ToString("yyyyMMddTHHmmssZ"); var dateStamp = ((DateTime)context.Variables["now"]).ToString("yyyyMMdd"); // Hash the payload var body = context.Request.Body.As<string>(preserveContent: true); string hashedPayload; using (var sha256 = System.Security.Cryptography.SHA256.Create()) { var hash = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(body)); hashedPayload = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); } // Create canonical query string var queryDict = context.Request.Url.Query; var canonicalQueryString = ""; if (queryDict != null && queryDict.Count > 0) { var encodedParams = new List<string>(); foreach (var kvp in queryDict) { var encodedKey = System.Uri.EscapeDataString(kvp.Key); var encodedValue = System.Uri.EscapeDataString(kvp.Value.First() ?? ""); encodedParams.Add($"{encodedKey}={encodedValue}"); } canonicalQueryString = string.Join("&", encodedParams.OrderBy(p => p)); } // Create signed headers and canonical headers var headers = context.Request.Headers; var canonicalHeaderList = new List<string[]>(); // Add content-type if present var contentType = headers.GetValueOrDefault("Content-Type", "").ToLowerInvariant(); if (!string.IsNullOrEmpty(contentType)) { canonicalHeaderList.Add(new[] { "content-type", contentType }); } // Always add host canonicalHeaderList.Add(new[] { "host", host }); // Add x-amz-* headers (excluding x-amz-date, x-amz-content-sha256) foreach (var header in headers) { var name = header.Key.ToLowerInvariant(); if (string.Equals(name, "x-amz-content-sha256", StringComparison.OrdinalIgnoreCase) || string.Equals(name, "x-amz-date", StringComparison.OrdinalIgnoreCase)) { continue; } if (name.StartsWith("x-amz-")) { var value = header.Value.First()?.Trim(); canonicalHeaderList.Add(new[] { name, value }); } } canonicalHeaderList.Add(new[] { "x-amz-content-sha256", hashedPayload }); canonicalHeaderList.Add(new[] { "x-amz-date", amzDate }); var canonicalHeadersOrdered = canonicalHeaderList.OrderBy(h => h[0]); var canonicalHeaders = string.Join("\n", canonicalHeadersOrdered.Select(h => $"{h[0]}:{h[1].Trim()}")) + "\n"; var signedHeaders = string.Join(";", canonicalHeadersOrdered.Select(h => h[0])); // Create and hash the canonical request var canonicalRequest = $"{method}\n{canonicalPath}\n{canonicalQueryString}\n{canonicalHeaders}\n{signedHeaders}\n{hashedPayload}"; string hashedCanonicalRequest = ""; using (var sha256 = System.Security.Cryptography.SHA256.Create()) { var hash = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(canonicalRequest)); hashedCanonicalRequest = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); } // Build string to sign var credentialScope = $"{dateStamp}/{region}/{service}/aws4_request"; var stringToSign = $"AWS4-HMAC-SHA256\n{amzDate}\n{credentialScope}\n{hashedCanonicalRequest}"; // Sign it using secret key byte[] kSecret = System.Text.Encoding.UTF8.GetBytes("AWS4" + secretKey); byte[] kDate, kRegion, kService, kSigning; using (var h1 = new System.Security.Cryptography.HMACSHA256(kSecret)) { kDate = h1.ComputeHash(System.Text.Encoding.UTF8.GetBytes(dateStamp)); } using (var h2 = new System.Security.Cryptography.HMACSHA256(kDate)) { kRegion = h2.ComputeHash(System.Text.Encoding.UTF8.GetBytes(region)); } using (var h3 = new System.Security.Cryptography.HMACSHA256(kRegion)) { kService = h3.ComputeHash(System.Text.Encoding.UTF8.GetBytes(service)); } using (var h4 = new System.Security.Cryptography.HMACSHA256(kService)) { kSigning = h4.ComputeHash(System.Text.Encoding.UTF8.GetBytes("aws4_request")); } // Auth header string signature; using (var hmac = new System.Security.Cryptography.HMACSHA256(kSigning)) { var sigBytes = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringToSign)); signature = BitConverter.ToString(sigBytes).Replace("-", "").ToLowerInvariant(); } return $"AWS4-HMAC-SHA256 Credential={accessKey}/{credentialScope}, SignedHeaders={signedHeaders}, Signature={signature}"; }</value> </set-header> <set-header name="Host" exists-action="override"> <value>@(context.Request.Url.Host)</value> </set-header> </inbound> <backend> <base /> </backend> <outbound> <base /> </outbound> <on-error> <base /> </on-error> </policies>
Wywołaj interfejs API Bedrock
Aby wywołać interfejs API Bedrock za pomocą usługi API Management, możesz użyć zestawu AWS Bedrock SDK. W tym przykładzie użyto zestawu .NET SDK, ale możesz użyć dowolnego języka obsługującego interfejs API AWS Bedrock.
W poniższym przykładzie użyto niestandardowego klienta HTTP, który tworzy wystąpienia klas zdefiniowanych w towarzyszącym pliku BedrockHttpClientFactory.cs. Niestandardowy klient HTTP kieruje żądania do punktu końcowego usługi API Management i zawiera klucz subskrypcji usługi API Management (w razie potrzeby) w nagłówkach żądania.
using Amazon;
using Amazon.BedrockRuntime;
using Amazon.BedrockRuntime.Model;
using Amazon.Runtime;
using BedrockClient;
// Leave accessKey and secretKey values as empty strings. Authentication to AWS API is handled through policies in API Management.
var accessKey = "";
var secretKey = "";
var credentials = new BasicAWSCredentials(accessKey, secretKey);
// Create custom configuration to route requests through API Management
// apimUrl is the API Management endpoint, such as https://apim-hello-word.azure-api.net/bedrock
var apimUrl = "<api-management-endpoint">;
// Provide name and value for the API Management subscription key header.
var apimSubscriptionHeaderName = "api-key";
var apimSubscriptionKey = "<your-apim-subscription-key>";
var config = new AmazonBedrockRuntimeConfig()
{
HttpClientFactory = new BedrockHttpClientFactory(apimUrl, apimSubscriptionHeaderName, apimSubscriptionKey),
// Set the AWS region where your Bedrock model is hosted.
RegionEndpoint = RegionEndpoint.USEast1
};
var client = new AmazonBedrockRuntimeClient(credentials, config);
// Set the model ID, e.g., Claude 3 Haiku. Find the supported models in Amazon Bedrock documentation: https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html.
var modelId = "us.anthropic.claude-3-5-haiku-20241022-v1:0";
// Define the user message.
var userMessage = "Describe the purpose of a 'hello world' program in one line.";
// Create a request with the model ID, the user message, and an inference configuration.
var request = new ConverseRequest
{
ModelId = modelId,
Messages = new List<Message>
{
new Message
{
Role = ConversationRole.User,
Content = new List<ContentBlock> { new ContentBlock { Text = userMessage } }
}
},
InferenceConfig = new InferenceConfiguration()
{
MaxTokens = 512,
Temperature = 0.5F,
TopP = 0.9F
}
};
try
{
// Send the request to the Bedrock runtime and wait for the result.
var response = await client.ConverseAsync(request);
// Extract and print the response text.
string responseText = response?.Output?.Message?.Content?[0]?.Text ?? "";
Console.WriteLine(responseText);
}
catch (AmazonBedrockRuntimeException e)
{
Console.WriteLine($"ERROR: Can't invoke '{modelId}'. Reason: {e.Message}");
throw;
}
BedrockHttpClientFactory.cs
Poniższy kod implementuje klasy w celu utworzenia niestandardowego klienta HTTP, który kieruje żądania do interfejsu API Bedrock przez zarządzanie interfejsem API, umieszczając klucz subskrypcji zarządzania interfejsem API w nagłówkach.
using Amazon.Runtime;
namespace BedrockClient
{
public class BedrockHttpClientFactory : HttpClientFactory
{
readonly string subscriptionKey;
readonly string subscriptionHeaderName;
readonly string rerouteUrl;
public BedrockHttpClientFactory(string rerouteUrl, string subscriptionHeaderName, string subscriptionKey)
{
this.rerouteUrl = rerouteUrl;
this.subscriptionHeaderName = subscriptionHeaderName;
this.subscriptionKey = subscriptionKey;
}
public override HttpClient CreateHttpClient(IClientConfig clientConfig)
{
var handler = new RerouteHandler(rerouteUrl)
{
InnerHandler = new HttpClientHandler()
};
var httpClient = new HttpClient(handler);
httpClient.DefaultRequestHeaders.Add(this.subscriptionHeaderName, this.subscriptionKey);
return httpClient;
}
}
public class RerouteHandler : DelegatingHandler
{
readonly string rerouteUrl;
readonly string host;
public RerouteHandler(string rerouteUrl)
{
this.rerouteUrl = rerouteUrl;
this.host = rerouteUrl.Split("/")[2].Split(":")[0];
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var originalUri = request.RequestUri;
request.RequestUri = new Uri($"{this.rerouteUrl}{originalUri.PathAndQuery}");
request.Headers.Host = this.host;
return base.SendAsync(request, cancellationToken);
}
}
}