LangChain4j Chat Models
Configure chat models in LangChain4j: OpenAI, Anthropic Claude, Google Gemini, Mistral and Ollama — with streaming, timeouts, retries and how to swap providers without touching your code.
On this page
The ChatModel is the seam that makes provider choice a one-line decision. This tutorial shows how
to configure each major provider, add streaming and resilience, and swap between them without
touching a line of your application code.
Key Takeaways
- Every provider is a
ChatModelimplementation — swap the constructor, keep everything else. - Always set a timeout and retries; a model call with neither is a latent outage.
StreamingChatModelfor interactive UIs,ChatModelfor everything else.- Configure once in a
@Bean; inject the interface everywhere.
The providers
ChatModel openai = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-4o-mini")
.temperature(0.2)
.timeout(Duration.ofSeconds(60))
.maxRetries(3)
.build();ChatModel claude = AnthropicChatModel.builder()
.apiKey(System.getenv("ANTHROPIC_API_KEY"))
.modelName("claude-sonnet-4-latest")
.temperature(0.2)
.timeout(Duration.ofSeconds(60))
.build();ChatModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(System.getenv("GOOGLE_AI_API_KEY"))
.modelName("gemini-2.0-flash")
.build();ChatModel local = OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("llama3.2")
.timeout(Duration.ofSeconds(120)) // local models can be slower
.build();Each needs its own Maven module (langchain4j-open-ai, langchain4j-anthropic, and so on). The
interface they all satisfy is the same.
Swapping providers is a construction change
// Your service depends on ChatModel, not on any provider.
public class Assistant {
private final ChatModel model;
public Assistant(ChatModel model) { this.model = model; }
// ... uses model
}
// Wire whichever provider you want. Switching is a one-line edit here.
Assistant assistant = new Assistant(openai); // or claude, or localStreaming
For interactive UIs, use StreamingChatModel and handle tokens as they arrive:
StreamingChatModel streaming = OpenAiStreamingChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-4o-mini")
.build();
streaming.chat("Explain virtual threads", new StreamingChatResponseHandler() {
@Override
public void onPartialResponse(String token) {
// Forward each token to the client (e.g. over SSE) as it arrives.
emitter.send(token);
}
@Override
public void onCompleteResponse(ChatResponse response) {
emitter.complete();
}
@Override
public void onError(Throwable error) {
emitter.completeWithError(error);
}
});The declarative AiServices style can also return a TokenStream from an interface method, which is
usually cleaner — covered in the architecture tutorial.
Resilience: timeouts and retries
ChatModel resilient = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-4o-mini")
// A hung provider must not hold a thread forever.
.timeout(Duration.ofSeconds(60))
// Retries transient 429/5xx with backoff; not 4xx client errors.
.maxRetries(3)
.build();Model options that matter
OpenAiChatModel.builder()
.modelName("gpt-4o-mini")
.temperature(0.0) // deterministic for extraction/classification
.maxTokens(1000) // caps response length and cost
.topP(1.0)
.build();Temperature is the option you will tune most. Near zero for structured, deterministic tasks; higher only where variety is the goal.
Logging requests during development
OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-4o-mini")
.logRequests(true) // dev only — requests may contain personal data
.logResponses(true)
.build();Turn these off in production; request logs carry prompt content, which is often personal data. See security in AI-powered Spring applications.
Choosing a model
- Development / high volume / simple tasks — a small hosted model or local Ollama.
- General production — a mid-tier model like
gpt-4o-mini. - Hard reasoning / code analysis — a frontier model, and measure whether the quality gain justifies the cost on your inputs.
Route between them per task rather than picking one for everything — see agent frameworks compared and small language models.
Next
Frequently Asked Questions
How do I switch chat model providers in LangChain4j?
What is the difference between ChatModel and StreamingChatModel?
How do I set a timeout and retries in LangChain4j?
Can I use Azure OpenAI or Amazon Bedrock with LangChain4j?
Related tutorials
- LangChain4j Introduction & ArchitectureA complete LangChain4j introduction for Java developers: core abstractions, the AiServices declarative style, memory, tools and retrieval — plus an honest comparison with Spring AI.
- LangChain4j Chains & CompositionCompose multi-step LLM workflows in LangChain4j: sequential chains, routing by classification, and building custom chains from AI Services — when to chain and when a single call suffices.
- LangChain4j Document LoadersLoad documents into LangChain4j from files, URLs, S3, GitHub and more, and parse PDF, DOCX and HTML with Apache Tika — the ingestion front-end for any RAG pipeline in Java.
- LangChain4j Text SplittersChunk documents effectively in LangChain4j: the recursive splitter, chunk size and overlap tuning, splitting code and markdown, and why chunking is the highest-impact decision in RAG.