ChatClient, invites et sortie structurée
Appelez des modèles conversationnels via ChatClient avec des modèles d’invites et un mappage typé vers une sortie structurée.
ChatClient, invites et sortie structurée est une leçon Spring Boot 4 Complete Guide gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Spring Boot 4 Complete Guide, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Spring Boot 4 Complete Guide comprend 4 leçons au total.
Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.
Why ChatClient?
Spring AI gives you a fluent, high-level API for talking to LLMs: the ChatClient. Instead of hand-building HTTP requests to OpenAI, Anthropic, or Ollama, you describe what you want and let the framework handle transport, retries, and message assembly.
- ChatClient — fluent builder for one-shot or streaming calls.
- Prompt — a list of messages (system, user, assistant) plus options.
- Structured output — map the model's text reply directly into a typed Java object.
It is portable: swap the underlying ChatModel (OpenAI → Anthropic) and your ChatClient code stays the same.
Auto-configuration and dependencies
Add a Spring AI model starter and Spring Boot auto-configures a ChatModel bean plus a ChatClient.Builder you can inject.
- The starter (e.g.
spring-ai-starter-model-openai) reads your API key and model from properties. - You never construct
ChatClientdirectly — you inject the builder and call.build().
Typical configuration in application.yml:
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4o
temperature: 0.2Creating a ChatClient
Inject the auto-configured ChatClient.Builder and build a client once, usually in your service constructor. You can attach default system prompts or options here so every call inherits them.
Building per-service (not per-request) keeps configuration in one place and is cheap.
@Service
public class AssistantService {
private final ChatClient chatClient;
public AssistantService(ChatClient.Builder builder) {
this.chatClient = builder
.defaultSystem("You are a concise Spring expert. Answer in one sentence.")
.build();
}
}A first call: prompt().user().content()
The fluent chain reads like a sentence. Start with prompt(), add a user(...) message, then terminate with call() for a blocking response and content() to get the plain text.
call()— synchronous request/response.content()— extracts the assistant's text.chatResponse()— returns metadata (token usage, finish reason) instead.
public String ask(String question) {
return chatClient.prompt()
.user(question)
.call()
.content();
}System vs user messages
An LLM prompt is a sequence of messages with roles:
- System — instructions and persona; sets behavior.
- User — the actual request from the end user.
- Assistant — prior model replies (for multi-turn context).
You can override the default system message per call. Keep untrusted user input in user(...), never inside the system instruction, to reduce prompt-injection risk.
String answer = chatClient.prompt()
.system("You are a senior Java reviewer. Be blunt and specific.")
.user("Review this code: " + snippet)
.call()
.content();Prompt templates with variables
Hard-coding strings does not scale. Spring AI uses template placeholders (default {name} syntax via StringTemplate) that you fill with param(...). The framework substitutes values before the request is sent.
- Define the template text once with
{placeholders}. - Bind values with
.user(u -> u.text(...).param(...)).
This separates wording from data and keeps user values clearly bound.
String reply = chatClient.prompt()
.user(u -> u
.text("Summarize the topic {topic} for a {level} audience.")
.param("topic", "reactive streams")
.param("level", "beginner"))
.call()
.content();How template substitution works
Under the hood Spring AI builds a PromptTemplate and renders it. You can also use the template directly when you want to reuse it or load it from a resource file.
Here is the same idea as a plain Java program you can run to see substitution — no Spring needed, just string formatting that mirrors what the renderer does:
import java.util.Map;
public class TemplateDemo {
static String render(String tmpl, Map<String, String> vars) {
String out = tmpl;
for (var e : vars.entrySet()) {
out = out.replace("{" + e.getKey() + "}", e.getValue());
}
return out;
}
public static void main(String[] args) {
String t = "Summarize {topic} for a {level} audience.";
System.out.println(render(t, Map.of("topic", "reactive streams", "level", "beginner")));
}
}Structured output: entity()
Often you do not want prose — you want a typed object. Spring AI's structured output converters do three things: inject a format instruction into the prompt, receive the model's text, and deserialize it into your type.
Define a plain Java record, then call .entity(MyType.class) instead of .content().
public record MovieReview(String title, int year, double rating, String verdict) {}
public MovieReview review(String movie) {
return chatClient.prompt()
.user("Give a short structured review of the movie: " + movie)
.call()
.entity(MovieReview.class);
}Generic types with ParameterizedTypeReference
For collections or generic containers, Java erases the type parameter at runtime, so List.class is not enough. Pass a ParameterizedTypeReference so Spring AI knows the element type and generates the right JSON schema instruction.
import org.springframework.core.ParameterizedTypeReference;
import java.util.List;
public record Actor(String name, List<String> films) {}
public List<Actor> castOf(String movie) {
return chatClient.prompt()
.user("List the main cast of " + movie)
.call()
.entity(new ParameterizedTypeReference<List<Actor>>() {});
}What entity() does to the prompt
It is worth understanding the mechanism: entity() uses a BeanOutputConverter that generates a JSON Schema from your record and appends a format instruction telling the model to reply with matching JSON only.
- The model returns JSON text.
- The converter parses it (via Jackson) into your record.
- If the model adds stray prose, parsing can fail — lower
temperatureand keep records flat for reliability.
You can call the converter yourself to inspect the injected instruction:
import org.springframework.ai.converter.BeanOutputConverter;
record Weather(String city, double celsius) {}
var converter = new BeanOutputConverter<>(Weather.class);
String formatInstruction = converter.getFormat();
// This text is appended to your user prompt by entity()
System.out.println(formatInstruction);Streaming and response metadata
For long answers, stream tokens as they arrive using stream() instead of call(), which returns a reactive Flux<String>. For observability, grab the full ChatResponse to read token usage and the finish reason.
.stream().content()—Flux<String>of incremental chunks..call().chatResponse().getMetadata().getUsage()— prompt/completion tokens.
import reactor.core.publisher.Flux;
public Flux<String> streamAnswer(String question) {
return chatClient.prompt()
.user(question)
.stream()
.content();
}Quick Check
You need the model's reply mapped into a List<Actor>. Which terminal call is correct?
Recap
You learned to call LLMs the Spring way with ChatClient:
- Inject
ChatClient.Builder, setdefaultSystem, andbuild()once per service. - Use the fluent chain:
prompt().system(...).user(...).call().content(). - Keep system instructions and untrusted user input in separate messages.
- Use
{placeholder}templates with.param(...)to separate wording from data. - Map replies to typed records with
.entity(Type.class), and useParameterizedTypeReferencefor generics likeList<T>. - Stream with
.stream().content()and inspect token usage viachatResponse().getMetadata().
For reliable structured output, keep records flat and lower the temperature.
Apprends Java avec un tuteur IA — gratuit
Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.
- Cours
- 21
- Leçons
- 84
Questions Fréquemment Posées
La leçon « ChatClient, invites et sortie structurée » est-elle gratuite ?
Oui — le texte complet de « ChatClient, invites et sortie structurée » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Spring Boot 4 Complete Guide, passe à CoddyKit PRO. Le cours Spring Boot 4 Complete Guide comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « ChatClient, invites et sortie structurée » ?
Appelez des modèles conversationnels via ChatClient avec des modèles d’invites et un mappage typé vers une sortie structurée. Tu pratiques Spring Boot 4 Complete Guide avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Spring Boot 4 Complete Guide ?
Aucune expérience préalable n'est requise. Spring Boot 4 Complete Guide sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.
Combien de temps prend la leçon « ChatClient, invites et sortie structurée » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Spring Boot 4 Complete Guide ?
Oui. Chaque leçon Spring Boot 4 Complete Guide inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- ChatClient, invites et sortie structurée
- Plongements et recherche dans un magasin de vecteurs
- Pipelines de génération augmentée par recherche
- Appels d’outils et conseillers d’agents