Spring AI integration for Azure OpenAI services providing chat completion, text embeddings, image generation, and audio transcription with GPT, DALL-E, and Whisper models
Common integration patterns for combining multiple Azure OpenAI capabilities.
Combine embeddings and chat for context-aware responses.
// 1. Create embedding model for document indexing
AzureOpenAiEmbeddingModel embeddingModel = new AzureOpenAiEmbeddingModel(
openAIClient,
MetadataMode.EMBED,
AzureOpenAiEmbeddingOptions.builder()
.deploymentName("text-embedding-ada-002")
.build()
);
// 2. Embed documents
List<String> documents = loadDocuments();
EmbeddingResponse embedResponse = embeddingModel.call(
new EmbeddingRequest(documents, null)
);
storeInVectorDatabase(embedResponse.getResults());
// 3. Create chat model for generation
AzureOpenAiChatModel chatModel = AzureOpenAiChatModel.builder()
.openAIClientBuilder(clientBuilder)
.defaultOptions(AzureOpenAiChatOptions.builder()
.deploymentName("gpt-4o")
.temperature(0.7)
.build())
.build();
// 4. Query: embed query, retrieve docs, generate answer
String userQuery = "What is Spring AI?";
EmbeddingResponse queryEmbedding = embeddingModel.call(
new EmbeddingRequest(List.of(userQuery), null)
);
List<String> relevantDocs = retrieveSimilarDocuments(
queryEmbedding.getResults().get(0).getOutput()
);
// 5. Generate answer with context
String context = String.join("\n", relevantDocs);
String promptText = "Context:\n" + context + "\n\nQuestion: " + userQuery;
ChatResponse answer = chatModel.call(new Prompt(promptText));Process audio, generate summaries, and create images.
// 1. Transcribe audio
AzureOpenAiAudioTranscriptionModel transcriptionModel =
new AzureOpenAiAudioTranscriptionModel(
openAIClient,
AzureOpenAiAudioTranscriptionOptions.builder()
.deploymentName("whisper")
.build()
);
Resource audioFile = new FileSystemResource("podcast.mp3");
String transcript = transcriptionModel.call(audioFile);
// 2. Summarize transcript
AzureOpenAiChatModel chatModel = AzureOpenAiChatModel.builder()
.openAIClientBuilder(clientBuilder)
.defaultOptions(AzureOpenAiChatOptions.builder()
.deploymentName("gpt-4o")
.build())
.build();
String summaryPrompt = "Summarize this podcast transcript:\n\n" + transcript;
ChatResponse summary = chatModel.call(new Prompt(summaryPrompt));
// 3. Generate cover image based on summary
AzureOpenAiImageModel imageModel = new AzureOpenAiImageModel(
openAIClient,
AzureOpenAiImageOptions.builder()
.deploymentName("dall-e-3")
.width(1792)
.height(1024)
.build()
);
String imagePrompt = "Create podcast cover art for: " +
summary.getResult().getOutput().getText();
ImageResponse coverArt = imageModel.call(new ImagePrompt(imagePrompt));Build a semantic search engine.
// Index documents
List<String> documents = List.of(
"Spring AI provides AI integration for Spring applications",
"Azure OpenAI offers enterprise-grade AI models",
"DALL-E generates images from text descriptions"
);
EmbeddingResponse docEmbeddings = embeddingModel.call(
new EmbeddingRequest(documents, null)
);
// Store embeddings with documents
Map<String, float[]> documentIndex = new HashMap<>();
for (int i = 0; i < documents.size(); i++) {
documentIndex.put(
documents.get(i),
docEmbeddings.getResults().get(i).getOutput()
);
}
// Search with query
String query = "How to use AI in Spring?";
EmbeddingResponse queryEmbedding = embeddingModel.call(
new EmbeddingRequest(List.of(query), null)
);
float[] queryVector = queryEmbedding.getResults().get(0).getOutput();
// Find most similar documents
List<Map.Entry<String, Double>> results = documentIndex.entrySet().stream()
.map(entry -> Map.entry(
entry.getKey(),
cosineSimilarity(queryVector, entry.getValue())
))
.sorted(Map.Entry.<String, Double>comparingByValue().reversed())
.limit(3)
.collect(Collectors.toList());Maintain conversation context across multiple turns.
List<Message> conversationHistory = new ArrayList<>();
// User asks first question
conversationHistory.add(new UserMessage("What is machine learning?"));
ChatResponse response1 = chatModel.call(new Prompt(conversationHistory));
conversationHistory.add(new AssistantMessage(
response1.getResult().getOutput().getText()
));
// User asks follow-up (context maintained)
conversationHistory.add(new UserMessage("Can you give an example?"));
ChatResponse response2 = chatModel.call(new Prompt(conversationHistory));
conversationHistory.add(new AssistantMessage(
response2.getResult().getOutput().getText()
));
// Continue conversation with full context
conversationHistory.add(new UserMessage("How is it used in practice?"));
ChatResponse response3 = chatModel.call(new Prompt(conversationHistory));Extract structured data from unstructured text.
// Define JSON schema for extraction
Map<String, Object> schema = Map.of(
"type", "object",
"properties", Map.of(
"name", Map.of("type", "string"),
"email", Map.of("type", "string"),
"phone", Map.of("type", "string"),
"company", Map.of("type", "string")
),
"required", List.of("name", "email")
);
AzureOpenAiResponseFormat format = AzureOpenAiResponseFormat.builder()
.type(AzureOpenAiResponseFormat.Type.JSON_SCHEMA)
.jsonSchema(AzureOpenAiResponseFormat.JsonSchema.builder()
.name("ContactInfo")
.schema(schema)
.strict(true)
.build())
.build();
AzureOpenAiChatOptions options = AzureOpenAiChatOptions.builder()
.responseFormat(format)
.build();
String text = "Contact John Doe at john@example.com or call 555-0123. He works at Acme Corp.";
Prompt prompt = new Prompt("Extract contact information: " + text, options);
ChatResponse response = chatModel.call(prompt);
// Response is guaranteed valid JSON matching schema
String jsonData = response.getResult().getOutput().getText();Process multiple requests efficiently.
// Batch embedding generation
List<String> texts = List.of(
"First document",
"Second document",
"Third document"
// ... up to 2048 texts
);
EmbeddingResponse batchResponse = embeddingModel.call(
new EmbeddingRequest(texts, null)
);
// Parallel chat processing
ExecutorService executor = Executors.newFixedThreadPool(10);
List<String> prompts = loadPrompts();
List<CompletableFuture<ChatResponse>> futures = new ArrayList<>();
for (String promptText : prompts) {
CompletableFuture<ChatResponse> future = CompletableFuture.supplyAsync(
() -> chatModel.call(new Prompt(promptText)),
executor
);
futures.add(future);
}
List<ChatResponse> responses = futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());Enable models to call external functions.
// Define tool callback
ToolCallback weatherTool = new ToolCallback(
"get_weather",
"Get current weather for a location",
(args) -> {
String location = (String) args.get("location");
return fetchWeatherData(location);
}
);
AzureOpenAiChatOptions options = AzureOpenAiChatOptions.builder()
.toolCallbacks(weatherTool)
.toolNames("get_weather")
.internalToolExecutionEnabled(true)
.build();
Prompt prompt = new Prompt("What's the weather in Seattle?", options);
ChatResponse response = chatModel.call(prompt);
// Model automatically calls weather tool and includes result in responseStream responses for better UX.
Prompt prompt = new Prompt("Write a long article about AI");
Flux<ChatResponse> stream = chatModel.stream(prompt);
StringBuilder fullResponse = new StringBuilder();
stream.subscribe(
chunk -> {
String token = chunk.getResult().getOutput().getText();
if (token != null) {
fullResponse.append(token);
updateUI(token); // Update UI in real-time
}
},
error -> handleError(error),
() -> saveResponse(fullResponse.toString())
);Combine chat and embeddings for content safety.
// 1. Check against known unsafe patterns
String userInput = getUserInput();
EmbeddingResponse inputEmbedding = embeddingModel.call(
new EmbeddingRequest(List.of(userInput), null)
);
// 2. Compare with unsafe content embeddings
boolean isSafe = checkSafety(inputEmbedding.getResults().get(0).getOutput());
if (isSafe) {
// 3. Process with chat model
ChatResponse response = chatModel.call(new Prompt(userInput));
// 4. Check response safety
EmbeddingResponse responseEmbedding = embeddingModel.call(
new EmbeddingRequest(
List.of(response.getResult().getOutput().getText()),
null
)
);
if (checkSafety(responseEmbedding.getResults().get(0).getOutput())) {
return response.getResult().getOutput().getText();
}
}tessl i tessl/maven-org-springframework-ai--spring-ai-azure-openai@1.1.1