CtrlK
CommunityDocumentationLog inGet started
Tessl Logo

tessl/maven-org-springframework-ai--spring-ai-azure-openai

Spring AI integration for Azure OpenAI services providing chat completion, text embeddings, image generation, and audio transcription with GPT, DALL-E, and Whisper models

Overview
Eval results
Files

integration-patterns.mddocs/guides/

Integration Patterns

Common integration patterns for combining multiple Azure OpenAI capabilities.

RAG (Retrieval-Augmented Generation) Pipeline

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));

Multi-Modal Content Pipeline

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));

Semantic Search with Embeddings

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());

Conversational AI with Memory

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));

Structured Data Extraction

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();

Batch Processing

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());

Tool/Function Calling

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 response

Streaming with Real-Time Updates

Stream 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())
);

Content Moderation Pipeline

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();
    }
}

Next Steps

  • Real-World Scenarios - See these patterns in action
  • Performance Guide - Optimize your integrations
  • Error Handling - Handle failures gracefully
tessl i tessl/maven-org-springframework-ai--spring-ai-azure-openai@1.1.1

docs

index.md

tile.json