CtrlK
CommunityDocumentationLog inGet started
Tessl Logo

tessl/maven-org-springframework-ai--spring-ai-starter-model-openai

Spring Boot Starter for OpenAI integration providing auto-configuration for chat completion, embeddings, image generation, audio speech synthesis, audio transcription, and content moderation models. Includes high-level ChatClient API and conversation memory support.

Overview
Eval results
Files

real-world-scenarios.mddocs/examples/

Real-World Scenarios

Practical examples showing how to use Spring AI OpenAI Starter in production applications.

Scenario 1: Customer Support Chatbot

Build an intelligent customer support chatbot with conversation memory:

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.memory.ChatMemory;
import org.springframework.stereotype.Service;

@Service
public class CustomerSupportBot {

    private final ChatClient chatClient;

    public CustomerSupportBot(ChatClient.Builder builder, ChatMemory chatMemory) {
        this.chatClient = builder
            .defaultSystem("""
                You are a helpful customer support agent.
                Be polite, concise, and helpful.
                If you don't know the answer, admit it and offer to escalate.
                """)
            .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory))
            .build();
    }

    public String handleCustomerQuery(String customerId, String query) {
        return chatClient.prompt()
            .user(query)
            .advisors(advisor -> advisor.param("conversationId", customerId))
            .call()
            .content();
    }
}

Scenario 2: Document Analysis with RAG

Implement Retrieval-Augmented Generation for document Q&A:

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiEmbeddingModel;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.ai.document.Document;
import org.springframework.stereotype.Service;

@Service
public class DocumentAnalyzer {

    private final ChatClient chatClient;
    private final OpenAiEmbeddingModel embeddingModel;
    private final VectorStore vectorStore;

    public DocumentAnalyzer(
            ChatClient.Builder builder,
            OpenAiEmbeddingModel embeddingModel,
            VectorStore vectorStore) {
        this.chatClient = builder.build();
        this.embeddingModel = embeddingModel;
        this.vectorStore = vectorStore;
    }

    public void indexDocument(String content, Map<String, Object> metadata) {
        Document document = new Document(content, metadata);
        float[] embedding = embeddingModel.embed(document);
        document.setEmbedding(embedding);
        vectorStore.add(List.of(document));
    }

    public String queryDocuments(String question) {
        // Find relevant documents
        List<Document> similarDocs = vectorStore.similaritySearch(
            SearchRequest.query(question).withTopK(3)
        );

        // Build context from similar documents
        String context = similarDocs.stream()
            .map(Document::getContent)
            .collect(Collectors.joining("\n\n"));

        // Query with context
        return chatClient.prompt()
            .system("Answer based on this context: " + context)
            .user(question)
            .call()
            .content();
    }
}

Scenario 3: Content Moderation Pipeline

Build a content moderation system for user-generated content:

import org.springframework.ai.openai.moderation.OpenAiModerationModel;
import org.springframework.ai.model.moderation.*;
import org.springframework.stereotype.Service;

@Service
public class ContentModerationService {

    private final OpenAiModerationModel moderationModel;

    public ContentModerationService(OpenAiModerationModel moderationModel) {
        this.moderationModel = moderationModel;
    }

    public ModerationDecision moderateContent(String content) {
        ModerationPrompt prompt = new ModerationPrompt(content);
        ModerationResponse response = moderationModel.call(prompt);
        Moderation moderation = response.getResult().getOutput();

        for (ModerationResult result : moderation.getResults()) {
            if (result.isFlagged()) {
                return new ModerationDecision(
                    false,
                    "Content violates policy",
                    getFlaggedCategories(result.getCategories())
                );
            }
        }

        return new ModerationDecision(true, "Content approved", List.of());
    }

    private List<String> getFlaggedCategories(Categories categories) {
        List<String> flagged = new ArrayList<>();
        if (categories.isHate()) flagged.add("hate");
        if (categories.isHarassment()) flagged.add("harassment");
        if (categories.isSelfHarm()) flagged.add("self-harm");
        if (categories.isSexual()) flagged.add("sexual");
        if (categories.isViolence()) flagged.add("violence");
        return flagged;
    }

    record ModerationDecision(boolean approved, String reason, List<String> categories) {}
}

Scenario 4: Image Generation Service

Create a service for generating marketing images:

import org.springframework.ai.openai.OpenAiImageModel;
import org.springframework.ai.image.*;
import org.springframework.stereotype.Service;
import java.util.Base64;

@Service
public class MarketingImageService {

    private final OpenAiImageModel imageModel;

    public MarketingImageService(OpenAiImageModel imageModel) {
        this.imageModel = imageModel;
    }

    public byte[] generateProductImage(String description, ImageStyle style) {
        OpenAiImageOptions options = OpenAiImageOptions.builder()
            .model("dall-e-3")
            .quality("hd")
            .size("1024x1024")
            .style(style == ImageStyle.REALISTIC ? "natural" : "vivid")
            .responseFormat("b64_json")
            .build();

        ImagePrompt prompt = new ImagePrompt(
            "Product image: " + description,
            options
        );

        ImageResponse response = imageModel.call(prompt);
        String base64Image = response.getResult().getOutput().getB64Json();
        return Base64.getDecoder().decode(base64Image);
    }

    enum ImageStyle { REALISTIC, VIVID }
}

Scenario 5: Multilingual Translation Service

Build a translation service with context awareness:

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.stereotype.Service;

@Service
public class TranslationService {

    private final ChatClient chatClient;

    public TranslationService(ChatClient.Builder builder) {
        this.chatClient = builder
            .defaultOptions(OpenAiChatOptions.builder()
                .temperature(0.3) // Lower temperature for consistency
                .build())
            .build();
    }

    public String translate(String text, String targetLanguage, String context) {
        return chatClient.prompt()
            .system("""
                You are a professional translator.
                Translate accurately while preserving meaning and tone.
                Context: {context}
                """)
            .user("Translate to {language}: {text}")
            .advisors(advisor -> advisor
                .param("language", targetLanguage)
                .param("text", text)
                .param("context", context))
            .call()
            .content();
    }
}

Scenario 6: Podcast Transcription and Summarization

Transcribe audio and generate summaries:

import org.springframework.ai.openai.audio.transcription.OpenAiAudioTranscriptionModel;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;

@Service
public class PodcastProcessor {

    private final OpenAiAudioTranscriptionModel transcriptionModel;
    private final ChatClient chatClient;

    public PodcastProcessor(
            OpenAiAudioTranscriptionModel transcriptionModel,
            ChatClient.Builder builder) {
        this.transcriptionModel = transcriptionModel;
        this.chatClient = builder.build();
    }

    public PodcastSummary processEpisode(Resource audioFile) {
        // Transcribe audio
        TranscriptionResponse transcription = transcriptionModel.call(audioFile);
        String transcript = transcription.getResult().getOutput();

        // Generate summary
        String summary = chatClient.prompt()
            .system("Summarize this podcast transcript in 2-3 paragraphs")
            .user(transcript)
            .call()
            .content();

        // Extract key points
        String keyPoints = chatClient.prompt()
            .system("Extract 5 key points as a bullet list")
            .user(transcript)
            .call()
            .content();

        return new PodcastSummary(transcript, summary, keyPoints);
    }

    record PodcastSummary(String transcript, String summary, String keyPoints) {}
}

Scenario 7: Code Review Assistant

AI-powered code review with specific guidelines:

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.stereotype.Service;

@Service
public class CodeReviewAssistant {

    private final ChatClient chatClient;

    public CodeReviewAssistant(ChatClient.Builder builder) {
        this.chatClient = builder
            .defaultSystem("""
                You are an expert code reviewer.
                Focus on:
                - Security vulnerabilities
                - Performance issues
                - Code maintainability
                - Best practices
                Provide specific, actionable feedback.
                """)
            .defaultOptions(OpenAiChatOptions.builder()
                .model("gpt-4o")
                .temperature(0.3)
                .build())
            .build();
    }

    public CodeReview reviewCode(String code, String language) {
        String review = chatClient.prompt()
            .user("Review this {language} code:\n\n{code}")
            .advisors(advisor -> advisor
                .param("language", language)
                .param("code", code))
            .call()
            .content();

        return new CodeReview(review);
    }

    record CodeReview(String feedback) {}
}

Scenario 8: Streaming Chat for Real-Time UI

Implement streaming responses for better UX:

import org.springframework.ai.chat.client.ChatClient;
import reactor.core.publisher.Flux;
import org.springframework.stereotype.Service;

@Service
public class StreamingChatService {

    private final ChatClient chatClient;

    public StreamingChatService(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }

    public Flux<String> streamResponse(String userMessage) {
        return chatClient.prompt()
            .user(userMessage)
            .stream()
            .content();
    }

    // For Server-Sent Events endpoint
    public Flux<String> streamChatSSE(String message) {
        return streamResponse(message)
            .map(chunk -> "data: " + chunk + "\n\n")
            .concatWith(Flux.just("data: [DONE]\n\n"));
    }
}

Scenario 9: Tool/Function Calling for External APIs

Integrate external APIs using function calling:

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.model.function.FunctionCallback;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ToolConfiguration {

    @Bean
    public FunctionCallback weatherTool(RestTemplate restTemplate) {
        return FunctionCallback.builder()
            .function("getCurrentWeather", (WeatherRequest request) -> {
                // Call actual weather API
                return restTemplate.getForObject(
                    "https://api.weather.com?location=" + request.location(),
                    WeatherResponse.class
                );
            })
            .description("Get current weather for a location")
            .inputType(WeatherRequest.class)
            .build();
    }

    record WeatherRequest(String location) {}
    record WeatherResponse(String temperature, String conditions) {}
}

@Service
public class WeatherChatService {

    private final ChatClient chatClient;

    public WeatherChatService(ChatClient.Builder builder, FunctionCallback weatherTool) {
        this.chatClient = builder
            .defaultTools(weatherTool)
            .build();
    }

    public String chatWithWeather(String userMessage) {
        return chatClient.prompt()
            .user(userMessage)
            .call()
            .content();
    }
}

Scenario 10: Structured Data Extraction

Extract structured data from unstructured text:

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;

@Service
public class DataExtractionService {

    private final ChatClient chatClient;

    public DataExtractionService(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }

    public Person extractPersonInfo(String text) {
        return chatClient.prompt()
            .user("Extract person information from: " + text)
            .call()
            .entity(Person.class);
    }

    public List<Product> extractProducts(String invoice) {
        return chatClient.prompt()
            .user("Extract all products from this invoice: " + invoice)
            .call()
            .entity(new ParameterizedTypeReference<List<Product>>() {});
    }

    record Person(String name, Integer age, String occupation, String location) {}
    record Product(String name, double price, int quantity) {}
}

Best Practices

  1. Use appropriate models: gpt-4o for complex tasks, gpt-4o-mini for simple ones
  2. Set temperature wisely: Lower (0.0-0.3) for consistency, higher (0.7-1.0) for creativity
  3. Implement error handling: Catch OpenAiApiException for API errors
  4. Monitor costs: Track token usage via ChatResponseMetadata
  5. Cache responses: Store results for repeated queries
  6. Use streaming: Better UX for long responses
  7. Implement retry logic: Handle rate limits gracefully (auto-configured)
  8. Moderate content: Use ModerationModel for user inputs
  9. Set token limits: Use maxTokens to control costs
  10. Enable observability: Monitor performance in production

Next Steps

  • Configuration Reference - Customize all settings
  • API Documentation - Detailed API specifications
  • Quick Start - Get started quickly
  • Return to Overview
tessl i tessl/maven-org-springframework-ai--spring-ai-starter-model-openai@1.1.1

docs

examples

real-world-scenarios.md

index.md

tile.json