|

Understanding Prompts in Spring AI: A Comprehensive Guide

In the rapidly evolving world of AI development, mastering the art of prompt engineering is crucial for effective interaction with AI models. Spring AI, a framework that simplifies AI integration in Spring applications, offers robust tools for handling prompts. Let’s dive into the world of prompts in Spring AI and explore how you can leverage them to create powerful AI-driven applications.

What are Prompts?

Prompts are the inputs that guide an AI model to generate specific outputs. The design and phrasing of these prompts significantly influence the model’s responses. In Spring AI, prompts are much like the “View” in Spring MVC – they’re extensive texts with placeholders for dynamic content, which are then populated based on user requests or application logic. This approach is also reminiscent of parameterized SQL statements.

The Evolution of Prompt Structures

The structure of prompts has undergone significant evolution in the AI field:

  1. Initially, prompts were simple strings.
  2. They later incorporated placeholders for specific inputs (e.g., “USER:”).
  3. OpenAI introduced further structure by categorizing message strings into distinct roles.

API Overview

Prompt Class

The Prompt class serves as a container for an organized series of Message objects and a request ChatOptions. It enables intricate interactions with AI models by constructing prompts from multiple messages, each with a specific role in the dialogue.

public class Prompt implements ModelRequest<List<Message>> {
    private final List<Message> messages;
    private ChatOptions chatOptions;
}Code language: Java (java)

Message Interface

The Message interface encapsulates a prompt’s textual content, metadata attributes, and a MessageType categorization.

public interface Content {
    String getContent();
    Map<String, Object> getMetadata();
}

public interface Message extends Content {
    MessageType getMessageType();
}Code language: Java (java)

Multimodal message types also implement the MediaContent interface, which provides media content objects. Different Message implementations correspond to categories of messages that an AI can process. These are mapped by MessageType.

Roles in Messages

Each message is assigned a specific role, categorizing the messages and clarifying the context and purpose of each segment of the prompt. The primary roles are:

  • System Role: Guides the AI’s behavior and response style.
  • User Role: Represents the user’s input.
  • Assistant Role: The AI’s response to the user’s input.
  • Tool/Function Role: Focuses on returning additional information in response to Tool Call Assistant Messages.

PromptTemplate

The PromptTemplate class is a key component for prompt templating in Spring AI. It uses the StringTemplate engine for constructing and managing prompts, offering methods to create both string-based prompts and Message objects.

Example Usage

PromptTemplate promptTemplate = new PromptTemplate("Tell me a {adjective} joke about {topic}");

Prompt prompt = promptTemplate.create(Map.of("adjective", adjective, "topic", topic));

return chatModel.call(prompt).getResult();Code language: Java (java)

PromptTemplate usually used for User messages.

If you want to use System prompt you can use SystemPromptTemplate class

 SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate("system prompt text");

Example Usage

Now let’s look at the some examples of prompt usage using ChatClient API.

In below example we are only using User prompt.

@RestController
@RequestMapping("/chatai")
public class ChatAIController {

    public static final String SYSTEM_PROMPT = "You are a movie recommender, helping users discover new films " +
            "based on their preferences, moods, and interests. Offer personalized " +
            "recommendations, provide insights into the movies' plots, themes, and key " +
            "features, and suggest similar films that users may enjoy. Help users find their " +
            "next favorite movie experience.";
    private final ChatClient chatClient;
    private final ChatModel chatModel;

    @Value("classpath:/prompts/system-message.st")
    private Resource systemPrompt;


    public ChatAIController(ChatClient.Builder chatClientBuilder,ChatModel chatModel) {
        this.chatClient = chatClientBuilder.build();
        this.chatModel = chatModel;
    }

    @GetMapping("/movieRecommendation")
    public String getMovieRecommendation(@RequestParam(value = "genre") String genre) {
        String userPrompt = "Recommend me a movie in %s genre".formatted(genre);
        ChatResponse response =
                chatClient.prompt().user(userPrompt).call().chatResponse();
        return response.getResult().getOutput().getContent();
    }

}Code language: Java (java)

Below example shows both User and System prompt

@GetMapping("/movieRecommendation2")
    public String getMovieRecommendation2(@RequestParam(value = "genre") String genre) {
        String userPrompt = "Recommend me a movie in %s genre".formatted(genre);
        ChatResponse response =
                chatClient.prompt().user(userPrompt).system(SYSTEM_PROMPT).call().chatResponse();
        return response.getResult().getOutput().getContent();
    }Code language: Java (java)

Belo examples shows the different ways User and System prompt can be passed to AI system.

@GetMapping("/movieRecommendation3")<br>public String getMovieRecommendation3(@RequestParam(value = "genre") String genre) {<br>    String userPrompt = "Recommend me a movie in %s genre".formatted(genre);<br>    ChatResponse response =<br>            chatClient.prompt().messages(new UserMessage(userPrompt),<br>                    new SystemMessage(<em>SYSTEM_PROMPT</em>), new AssistantMessage("")).call().chatResponse();<br>    return response.getResult().getOutput().getContent();<br>}<br><br>@GetMapping("/getMovieRecommendation4")<br>public String getMovieRecommendation4(@RequestParam(value = "genre") String genre) {<br>    String userPrompt = "Recommend me a movie in %s genre".formatted(genre);<br>    ChatResponse response =<br>            chatClient.prompt().messages(List.<em>of</em>(new UserMessage(userPrompt),<br>                    new SystemMessage(<em>SYSTEM_PROMPT</em>))).call().chatResponse();<br>    return response.getResult().getOutput().getContent();<br>}Code language: Java (java)

Now let’s look at the some examples of prompt usage using ChatModel API.

@GetMapping("/movieRecommendation21")
    public String getMovieRecommendations21(@RequestParam(value = "genre") String genre) {
        PromptTemplate promptTemplate = new PromptTemplate("Recommend me a movie in " +
                "{category} genre");

        Prompt prompt = promptTemplate.create(Map.of("category", genre ));

        return chatModel.call(prompt).getResult().toString();
    }



    @GetMapping("/movieRecommendation22")
    public String getMovieRecommendations22(@RequestParam(value = "genre") String genre) {
        PromptTemplate promptTemplate = new PromptTemplate("Recommend me a movie in " +
                "{category} genre");
        Prompt userPrompt = promptTemplate.create(Map.of("category", genre ));
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);

      List<Message> promptMessages = new ArrayList<>();
      promptMessages.add(systemPromptTemplate.createMessage());
      promptMessages.addAll(userPrompt.getInstructions());
      return chatModel.call( promptMessages.toArray(new Message[0]) );
    }Code language: Java (java)

Using resources instead of raw Strings

Spring AI supports the org.springframework.core.io.Resource abstraction, so you can put prompt data in a file that can directly be used in a PromptTemplate. For example, you can define a field in your Spring managed component to retrieve the Resource

First create system-prompt.st file under resources/prompt folder.

Place your prompt text in the file

You are a movie recommender, helping users discover new films based on their preferences, moods, and interests. Offer personalized
 recommendations, provide insights into the movies' plots, themes, and key features, and suggest similar films that users may enjoy.
 Help users find their next favorite movie experience.Code language: Java (java)

Now define the resource variable

@Value("classpath:/prompts/system-prompt.st")
private Resource systemResource;Code language: Java (java)

and then pass that resource to the SystemPromptTemplate directly.

SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource);Code language: Java (java)

Creating Effective Prompts

When developing prompts, consider integrating these key components:

  1. Instructions: Offer clear and direct instructions to the AI.
  2. External Context: Include relevant background information when necessary.
  3. User Input: The user’s direct request or question.
  4. Output Indicator: Specify the desired format for the AI’s response.

Conclusion

Mastering prompt engineering in Spring AI opens up a world of possibilities for creating sophisticated AI-driven applications. By understanding the components of prompts, roles, and effective techniques, you can significantly enhance your AI model interactions and outputs. Remember, the art of crafting prompts is an ongoing learning process – keep experimenting and refining your approach for the best results!

Similar Posts