Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Van toepassing op: Alle API Management-lagen
In dit artikel importeert u een Amazon Bedrock language model-API in uw API Management-exemplaar als een passthrough-API. Dit is een voorbeeld van een model dat wordt gehost op een andere deductieprovider dan Azure AI-services. Gebruik AI-gatewaybeleid en andere mogelijkheden in API Management om integratie te vereenvoudigen, waarneembaarheid te verbeteren en de controle over de modeleindpunten te verbeteren.
Meer informatie over het beheren van AI-API's in API Management:
Meer informatie over Amazon Bedrock:
Vereiste voorwaarden
- Een bestaand API Management-exemplaar. Maak er een als u dat nog niet hebt gedaan.
- Een Amazon Web Services-account (AWS) met toegang tot Amazon Bedrock en toegang tot een of meer Amazon Bedrock foundation-modellen. Meer informatie
Toegangssleutels voor IAM-gebruikers maken
Als u uw API Management-exemplaar wilt verifiëren bij Amazon API Gateway, hebt u toegangssleutels nodig voor een AWS IAM-gebruiker.
Zie Een toegangssleutel voor uzelf maken in de AWS-documentatie om de vereiste toegangssleutel en geheime sleutel te genereren met behulp van de AWS-beheerconsole.
Sla uw toegangssleutels op een veilige locatie op. U slaat ze op als benoemde waarden in de volgende stap.
Waarschuwing
Toegangssleutels zijn referenties voor de lange termijn en u moet deze net zo veilig beheren als een wachtwoord. Meer informatie over het beveiligen van toegangssleutels
Toegangssleutels voor IAM-gebruikers opslaan als benoemde waarden
Sla de twee IAM-gebruikerstoegangssleutels veilig op als geheim benoemde waarden in uw Azure API Management-exemplaar met behulp van de configuratie die wordt aanbevolen in de volgende tabel.
| AWS-geheim | Naam | Geheime waarde |
|---|---|---|
| Toegangssleutel | toegangssleutel | Toegangssleutel-id opgehaald uit AWS |
| Geheime toegangssleutel | secretkey | Geheime toegangssleutel opgehaald uit AWS |
Een Bedrock-API importeren met behulp van de portal
Een Amazon Bedrock-API importeren in API Management:
Blader in Azure Portal naar uw API Management-exemplaar.
Selecteer in het linkermenu onder API'sAPI's, >.
Selecteer onder Een nieuwe API definiërende taalmodel-API.
Op het tabblad API configureren :
Voer een weergavenaam en een optionele beschrijving voor de API in.
Voer de volgende URL in naar het standaard Amazon Bedrock-eindpunt:
https://bedrock-runtime.<aws-region>.amazonaws.com.Voorbeeld:
https://bedrock-runtime.us-east-1.amazonaws.comSelecteer eventueel een of meer producten die u aan de API wilt koppelen.
Voeg in Pad een pad toe dat uw API Management-exemplaar gebruikt voor toegang tot de LLM API-eindpunten.
Selecteer in Typeeen passthrough-API maken.
Laat waarden in de Access-sleutel leeg.
Configureer op de resterende tabbladen eventueel beleidsregels voor het beheren van tokenverbruik, semantische caching en beveiliging van AI-inhoud. Zie Een taalmodel-API importeren voor meer informatie.
Selecteer Beoordelen.
Nadat de instellingen zijn gevalideerd, selecteert u Maken.
API Management maakt het API- en (optioneel) beleid om u te helpen de API te bewaken en te beheren.
Beleid configureren voor het verifiëren van aanvragen voor de Amazon Bedrock-API
Configureer API Management-beleid om aanvragen te ondertekenen bij de Amazon Bedrock-API. Meer informatie over het ondertekenen van AWS API-aanvragen
In het volgende voorbeeld worden de waarden voor de toegangssleutel en geheime sleutel gebruikt die u eerder hebt gemaakt voor de AWS-toegangssleutel en geheime sleutel. Stel de region variabele in op de juiste waarde voor uw Amazon Bedrock-API. In het voorbeeld wordt gebruikgemaakt van de regio us-east-1.
Blader in Azure Portal naar uw API Management-exemplaar.
Selecteer API's in het linkermenu onder API's.
Selecteer de API die u in de vorige sectie hebt gemaakt.
Selecteer Alle bewerkingen in het linkermenu onder Ontwerpen.
Selecteer het tabblad Binnenkomende verwerking .
In de editor voor inkomend verwerkingsbeleid selecteer </> om de beleidseditor te openen.
Configureer het volgende beleid:
<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>
De Bedrock-API aanroepen
Als u de Bedrock-API wilt aanroepen via API Management, kunt u de AWS Bedrock SDK gebruiken. In dit voorbeeld wordt de .NET SDK gebruikt, maar u kunt elke taal gebruiken die ondersteuning biedt voor de AWS Bedrock-API.
In het volgende voorbeeld wordt een aangepaste HTTP-client gebruikt waarmee klassen worden geïnstitueerde die zijn gedefinieerd in het bijbehorende bestand BedrockHttpClientFactory.cs. De aangepaste HTTP-client routeert aanvragen naar het API Management-eindpunt en bevat de API Management-abonnementssleutel (indien nodig) in de aanvraagheaders.
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
Met de volgende code worden klassen geïmplementeerd om een aangepaste HTTP-client te maken waarmee aanvragen naar de Bedrock-API worden gerouteerd via API Management, inclusief een API Management-abonnementssleutel in de headers.
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);
}
}
}