Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
In questa esercitazione si creerà un'applicazione di intelligenza artificiale intelligente integrando Azure OpenAI con un'applicazione Java Spring Boot e distribuendola nel servizio app di Azure. Si creerà un controller Spring Boot che invia una query ad Azure OpenAI e invierà la risposta al browser.
Suggerimento
Anche se questa esercitazione usa Spring Boot, i concetti di base della creazione di un'applicazione di chat con Azure OpenAI si applicano a qualsiasi applicazione Web Java. Se si usa un'opzione di hosting diversa nel servizio app, ad esempio Tomcat o JBoss EAP, è possibile adattare i modelli di autenticazione e l'utilizzo di Azure SDK illustrati di seguito al framework preferito.
In questa esercitazione si apprenderà come:
- Creare una risorsa OpenAI di Azure e distribuire un modello linguistico.
- Creare un'applicazione Spring Boot che si connette ad Azure OpenAI.
- Usare l'iniezione delle dipendenze per configurare il client OpenAI di Azure.
- Distribuire l'applicazione nel servizio app di Azure.
- Implementare l'autenticazione sicura senza password sia nell'ambiente di sviluppo che in Azure.
Prerequisiti
- Un account Azure con una sottoscrizione attiva
- Un account GitHub per l'uso di GitHub Codespaces
1. Creare una risorsa OpenAI di Azure
In questa sezione si useranno GitHub Codespaces per creare una risorsa Azure OpenAI con Azure CLI.
Passare a GitHub Codespaces e accedere con l'account GitHub.
Trovare il modello Vuoto di GitHub e selezionare Usa questo modello per creare un nuovo spazio di codice vuoto.
Nel terminale Codespace installare l'interfaccia della riga di comando di Azure:
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
Accedere all'account Azure:
az login
Seguire le istruzioni nel terminale per l'autenticazione.
Impostare le variabili di ambiente per il nome del gruppo di risorse, il nome del servizio OpenAI di Azure e la posizione:
export RESOURCE_GROUP="<group-name>" export OPENAI_SERVICE_NAME="<azure-openai-name>" export APPSERVICE_NAME="<app-name>" export LOCATION="eastus2"
Importante
L'area è fondamentale perché è associata alla disponibilità a livello di area del modello scelto. La disponibilità del modello e il tipo di distribuzione variano da un'area all'altra. Questa esercitazione usa
gpt-4o-mini
, disponibile nel tipo di distribuzione Standardeastus2
. Se si esegue la distribuzione in un'area diversa, questo modello potrebbe non essere disponibile o potrebbe richiedere un livello diverso. Prima di modificare le aree, consultare la tabella di riepilogo del modello e la disponibilità dell'area per verificare il supporto del modello nell'area preferita.Creare un gruppo di risorse e una risorsa OpenAI di Azure con un dominio personalizzato, quindi aggiungere un modello gpt-4o-mini:
# Resource group az group create --name $RESOURCE_GROUP --location $LOCATION # Azure OpenAI resource az cognitiveservices account create \ --name $OPENAI_SERVICE_NAME \ --resource-group $RESOURCE_GROUP \ --location $LOCATION \ --custom-domain $OPENAI_SERVICE_NAME \ --kind OpenAI \ --sku s0 # gpt-4o-mini model az cognitiveservices account deployment create \ --name $OPENAI_SERVICE_NAME \ --resource-group $RESOURCE_GROUP \ --deployment-name gpt-4o-mini \ --model-name gpt-4o-mini \ --model-version 2024-07-18 \ --model-format OpenAI \ --sku-name Standard \ --sku-capacity 1 # Cognitive Services OpenAI User role that lets the signed in Azure user to read models from Azure OpenAI az role assignment create \ --assignee $(az ad signed-in-user show --query id -o tsv) \ --role "Cognitive Services OpenAI User" \ --scope /subscriptions/$(az account show --query id -o tsv)/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.CognitiveServices/accounts/$OPENAI_SERVICE_NAME
Dopo aver creato una risorsa OpenAI di Azure, si creerà un'applicazione Web per interagire con essa.
2. Creare e configurare un'app Web Spring Boot
Nel terminale Codespace clonare l'esempio REST Spring Boot nell'area di lavoro e provare a eseguirlo per la prima volta.
git clone https://github.com/rd-1-2022/rest-service . mvn spring-boot:run
Verrà visualizzata una notifica in GitHub Codespaces che indica che l'app è disponibile in una porta specifica. Selezionare Apri nel browser per avviare l'app in una nuova scheda del browser. Quando viene visualizzata la pagina di errore dell'etichetta bianca, l'app Spring Boot funziona.
Tornare al terminale Codespace, arrestare l'app con CTRL+C.
Aprire pom.xml e aggiungere le dipendenze seguenti:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>com.azure</groupId> <artifactId>azure-ai-openai</artifactId> <version>1.0.0-beta.16</version> </dependency> <dependency> <groupId>com.azure</groupId> <artifactId>azure-core</artifactId> <version>1.55.3</version> </dependency> <dependency> <groupId>com.azure</groupId> <artifactId>azure-identity</artifactId> <version>1.16.0</version> <scope>compile</scope> </dependency>
Nella stessa directory di Application.java (src/main/java/com/example/restservice) aggiungere un file Java denominato ChatController.java e copiarne il contenuto seguente:
package com.example.restservice; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import com.azure.ai.openai.OpenAIAsyncClient; import com.azure.ai.openai.models.ChatChoice; import com.azure.ai.openai.models.ChatCompletionsOptions; import com.azure.ai.openai.models.ChatRequestMessage; import com.azure.ai.openai.models.ChatRequestUserMessage; import com.azure.ai.openai.models.ChatResponseMessage; import com.azure.core.credential.TokenCredential; import com.azure.identity.DefaultAzureCredentialBuilder; @Configuration class AzureConfig { // Reads the endpoint from environment variable AZURE_OPENAI_ENDPOINT @Value("${azure.openai.endpoint}") private String openAiEndpoint; // Provides a credential for local dev and production @Bean public TokenCredential tokenCredential() { return new DefaultAzureCredentialBuilder().build(); } // Configures the OpenAIAsyncClient bean @Bean public OpenAIAsyncClient openAIClient(TokenCredential tokenCredential) { return new com.azure.ai.openai.OpenAIClientBuilder() .endpoint(openAiEndpoint) .credential(tokenCredential) .buildAsyncClient(); } } @Controller public class ChatController { private final OpenAIAsyncClient openAIClient; // Inject the OpenAIAsyncClient bean public ChatController(OpenAIAsyncClient openAIClient) { this.openAIClient = openAIClient; } @RequestMapping(value = "/", method = RequestMethod.GET) public String chatFormOrWithMessage(Model model, @RequestParam(value = "userMessage", required = false) String userMessage) { String aiResponse = null; if (userMessage != null && !userMessage.isBlank()) { // Create a list of chat messages List<ChatRequestMessage> chatMessages = new ArrayList<>(); chatMessages.add(new ChatRequestUserMessage(userMessage)); // Send the chat completion request String deploymentName = "gpt-4o-mini"; StringBuilder serverResponse = new StringBuilder(); var chatCompletions = openAIClient.getChatCompletions( deploymentName, new ChatCompletionsOptions(chatMessages) ).block(); if (chatCompletions != null) { for (ChatChoice choice : chatCompletions.getChoices()) { ChatResponseMessage message = choice.getMessage(); serverResponse.append(message.getContent()); } } aiResponse = serverResponse.toString(); } model.addAttribute("aiResponse", aiResponse); return "chat"; } }
Suggerimento
Per ridurre al minimo i file in questa esercitazione, il codice combina le classi Spring
@Configuration
e@Controller
in un unico file. Nell'ambiente di produzione, in genere si separano la configurazione e la logica di business per garantire la gestibilità.In src/main/resources creare una directory templates e aggiungere un chat.html con il contenuto seguente per l'interfaccia di chat:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Azure OpenAI Chat</title> <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container py-4"> <h2 class="mb-4">Azure OpenAI Chat</h2> <form action="/" method="get" class="d-flex mb-3"> <input name="userMessage" class="form-control me-2" type="text" placeholder="Type your message..." autocomplete="off" required /> <button class="btn btn-primary" type="submit">Send</button> </form> <div class="mb-3"> <div th:if="${aiResponse}" class="alert alert-info">AI: <span th:text="${aiResponse}"></span></div> </div> </div> </body> </html>
Nel terminale recuperare l'endpoint OpenAI:
az cognitiveservices account show \ --name $OPENAI_SERVICE_NAME \ --resource-group $RESOURCE_GROUP \ --query properties.endpoint \ --output tsv
Esegui di nuovo l'app aggiungendo
AZURE_OPENAI_ENDPOINT
con il suo valore dall'output della CLI:AZURE_OPENAI_ENDPOINT=<output-from-previous-cli-command> mvn spring-boot:run
Selezionare Apri nel browser per avviare l'app in una nuova scheda del browser.
Digitare un messaggio nella casella di testo e selezionare "Invia e assegnare all'app alcuni secondi la risposta con il messaggio da Azure OpenAI.
L'applicazione usa DefaultAzureCredential, che usa automaticamente l'utente connesso all'interfaccia della riga di comando di Azure per l'autenticazione del token. Più avanti in questa esercitazione si distribuirà l'app Web nel servizio app di Azure e la si configurerà per connettersi in modo sicuro alla risorsa OpenAI di Azure usando l'identità gestita. Lo stesso DefaultAzureCredential
nel codice può rilevare l'identità gestita e usarla per l'autenticazione. Non è necessario alcun codice aggiuntivo.
3. Distribuire nel servizio app di Azure e configurare la connessione OpenAI
Ora che l'app funziona in locale, è possibile distribuirla nel servizio app di Azure e configurare una connessione del servizio ad Azure OpenAI usando l'identità gestita.
Creare un pacchetto di distribuzione con Maven.
mvn clean package
Innanzitutto, distribuisci l'app su Azure App Service usando il comando Azure CLI
az webapp up
. Questo comando crea una nuova app Web e distribuisce il codice:az webapp up \ --resource-group $RESOURCE_GROUP \ --location $LOCATION \ --name $APPSERVICE_NAME \ --plan $APPSERVICE_NAME \ --sku B1 \ --runtime "JAVA:21" \ --os-type Linux \ --track-status false
Il completamento di questo comando potrebbe richiedere alcuni minuti. Crea una nuova app Web nello stesso gruppo di risorse della risorsa OpenAI.
Dopo aver distribuito l'app, creare una connessione al servizio tra l'app Web e la risorsa OpenAI di Azure usando l'identità gestita:
az webapp connection create cognitiveservices \ --resource-group $RESOURCE_GROUP \ --name $APPSERVICE_NAME \ --target-resource-group $RESOURCE_GROUP \ --account $OPENAI_SERVICE_NAME \ --system-identity
Questo comando crea una connessione tra l'app Web e la risorsa OpenAI di Azure tramite:
- Generazione dell'identità gestita assegnata dal sistema per l'app Web.
- Aggiunta del ruolo Collaboratore di Servizi cognitivi OpenAI all'identità gestita per la risorsa Azure OpenAI.
- Aggiunta dell'impostazione dell'app
AZURE_OPENAI_ENDPOINT
per l'app Web.
Aprire l'app Web distribuita nel browser.
az webapp browse
Digitare un messaggio nella casella di testo e selezionare "Invia e assegnare all'app alcuni secondi la risposta con il messaggio da Azure OpenAI.
L'app viene ora distribuita e connessa ad Azure OpenAI con identità gestita. Si noti che accede all'impostazione dell'app AZURE_OPENAI_ENDPOINT
tramite l'iniezione di @Configuration.
Domande frequenti
-
Perché l'esempio usa
@Configuration
e Spring beans per il client OpenAI? - Cosa accade se si vuole connettersi a OpenAI anziché ad Azure OpenAI?
- È invece possibile connettersi ad Azure OpenAI con una chiave API?
- Come funziona DefaultAzureCredential in questa esercitazione?
Perché l'esempio usa @Configuration
e Spring beans per il client OpenAI?
L'uso di un bean Spring per il OpenAIAsyncClient
assicura che:
- Tutte le proprietà di configurazione (ad esempio l'endpoint) vengono caricate e inserite da Spring.
- Le credenziali e il client vengono creati dopo l'inizializzazione completa del contesto dell'applicazione.
- Si utilizza l'iniezione delle dipendenze, che è il modello standard più affidabile nelle applicazioni Spring.
Il client asincrono è più affidabile, soprattutto quando si usa DefaultAzureCredential
con l'autenticazione dell'interfaccia della riga di comando di Azure. Il componente sincrono OpenAIClient
può incontrare problemi con l'acquisizione di token in alcuni scenari di sviluppo locali. L'uso del client asincrono evita questi problemi ed è l'approccio consigliato.
Cosa accade se si vuole connettersi a OpenAI anziché ad Azure OpenAI?
Per connettersi invece a OpenAI, usare il codice seguente:
OpenAIClient client = new OpenAIClientBuilder()
.credential(new KeyCredential(<openai-api-key>))
.buildClient();
Per altre informazioni, vedere Autenticazione api OpenAI.
Quando si usano segreti di connessione nel servizio app, è consigliabile usare i riferimenti a Key Vault anziché archiviare i segreti direttamente nella codebase. Ciò garantisce che le informazioni riservate rimangano sicure e gestite centralmente.
È invece possibile connettersi ad Azure OpenAI con una chiave API?
Sì, è possibile connettersi ad Azure OpenAI usando una chiave API anziché un'identità gestita. Questo approccio è supportato dagli SDK OpenAI di Azure e dal kernel semantico.
- Per informazioni dettagliate sull'uso delle chiavi API con Semantic Kernel: Guida rapida di Semantic Kernel C#.
- Per informazioni dettagliate sull'uso delle chiavi API con la libreria client OpenAI di Azure: Avvio rapido: Introduzione all'uso dei completamenti della chat con il servizio Azure OpenAI.
Quando si usano segreti di connessione nel servizio app, è consigliabile usare i riferimenti a Key Vault anziché archiviare i segreti direttamente nella codebase. Ciò garantisce che le informazioni riservate rimangano sicure e gestite centralmente.
Come funziona DefaultAzureCredential in questa esercitazione?
Semplifica DefaultAzureCredential
l'autenticazione selezionando automaticamente il metodo di autenticazione migliore disponibile:
-
Durante lo sviluppo locale: dopo aver eseguito
az login
, usa le credenziali della CLI di Azure locale. - Quando viene distribuito nel servizio app di Azure: usa l'identità gestita dell'app per l'autenticazione sicura e senza password.
Questo approccio consente di eseguire il codice in modo sicuro e senza problemi in ambienti locali e cloud senza modifiche.
Passaggi successivi
- Esercitazione: Creare una generazione aumentata di recupero con Azure OpenAI e Ricerca di intelligenza artificiale di Azure (Spring Boot)
- Esercitazione: Eseguire il chatbot in App Service con un'estensione sidecar Phi-4 (Spring Boot)
- Creare e distribuire una risorsa del Servizio OpenAI di Azure
- Configurare il servizio app di Azure
- Abilitare l'identità gestita per l'app
- Configurare Java nel servizio app di Azure