Class LLMSupport
LLMProvider adapters.
Plumbing, not surface: it is public only because those three live in sibling packages, and
nothing outside this module should call it. The API is
LLMProvider and LLMProviderFactory.
It does two things none of the three should be duplicating. LangChain4j's chat models are
synchronous while LLMProvider is not, so the call runs on a virtual thread (ADR-001).
Each provider previously called CompletableFuture.supplyAsync(Supplier) with no
executor, which is the common ForkJoinPool — sized cores - 1, and shared with
everything else in the application — for an HTTP request that lasts seconds. The embedding
side of this module and the Redis adapters already ran on virtual threads; the LLM side was
the exception.
It also classifies a provider failure into the LLMException.ErrorType a caller can branch on
(wrap(java.lang.String, java.lang.String, java.lang.Throwable)), the same job EmbeddingSupport does for embeddings — before this, a
chat failure either travelled bare inside a CompletionException (OpenAI, Anthropic) or
arrived as an LLMException always of type UNKNOWN (Ollama).
- Since:
- 0.35.0
-
Method Summary
Modifier and TypeMethodDescriptionstatic voidapplyCommonParameters(dev.langchain4j.model.chat.request.ChatRequest.Builder builder, LLMRequest request) Applies everyLLMRequestsampling field thatChatRequest.Builderexposes directly, skipping whatever the request left unset.static StringorGeneratedId(String id) Returnsidif present, or a freshly generated one.static StringresolveModel(LLMRequest request, String builtWith) Resolves the model for one request, per ADR-017:request.model()when it names one, otherwise the model the provider was built with.static <T> CompletableFuture<T> supplyAsync(Supplier<T> work) Runs a blocking provider call on a virtual thread.static LLMExceptionWrapscauseas anLLMException, classified as far as it can be.
-
Method Details
-
supplyAsync
Runs a blocking provider call on a virtual thread.- Type Parameters:
T- the result type- Parameters:
work- the blocking call- Returns:
- a future completed with the result, or failed with whatever
workthrew
-
resolveModel
Resolves the model for one request, per ADR-017:request.model()when it names one, otherwise the model the provider was built with.The result belongs on the request handed to the client, not only on the label of the response. Every adapter used to put it on the label alone, or not read it at all, so a request could name one model and be answered by another with nothing reporting it.
- Parameters:
request- the request, which may or may not name a modelbuiltWith- the provider's own model, used when the request names none- Returns:
- the model to ask, and to label the answer with
-
applyCommonParameters
public static void applyCommonParameters(dev.langchain4j.model.chat.request.ChatRequest.Builder builder, LLMRequest request) Applies everyLLMRequestsampling field thatChatRequest.Builderexposes directly, skipping whatever the request left unset. Shared by all three adapters, which previously read none of these — a request could ask fortopPor a stop sequence and every adapter would silently ignore it.Deliberately not applied here:
LLMRequest.n(), which no bundled adapter's client library can honour — LangChain4j has no multiple-completions parameter to set it on — andLLMRequest.additionalParameters(), which has no generic equivalent belowChatRequest.Builder; each adapter maps it through its own provider-specific escape hatch where one exists (OpenAI'scustomParameters) rather than pretending one generic mapping covers all three.- Parameters:
builder- the request being built for the clientrequest- the request as the caller specified it
-
wrap
Wrapscauseas anLLMException, classified as far as it can be.- Parameters:
provider- provider name, attached to the exception and used in its messagemodel- the model the failed request named, ornullif it was never resolved (a failure before the request reached the client)cause- whatever the LangChain4j client threw- Returns:
- the classified exception; never wraps an
LLMExceptiona second time
-
orGeneratedId
Returnsidif present, or a freshly generated one.LLMResponse.builder(java.lang.String, java.lang.String)requires a non-null id, and OpenAI and Anthropic passChatResponse.id()straight through — a completed chat response that carries no id metadata therefore failed with a bareNullPointerExceptionfrom inside the builder, on success, not on a provider failure. Ollama already synthesizes aUUIDfor this reason; this gives the other two the same fallback instead of the same defect twice, so the field means the same thing regardless of provider.- Parameters:
id- the id the client reported, ornull- Returns:
id, or a new random one if it wasnull
-