org.llm4s.llmconnect.spi
Members list
Type members
Classlikes
A unit of provider registration: everything one module contributes.
A unit of provider registration: everything one module contributes.
The discovered unit is a module rather than a single ProviderDescriptor so that one artifact can supply several related providers — llm4s-openai contributes OpenAI, Azure, OpenRouter and Requesty from a single entry.
Implementations must be a plain class with a public no-arg constructor, '''not''' a Scala object: java.util.ServiceLoader instantiates the named class, and an object exposes its instance as a MODULE$ field instead. Delegate to an object from the class if you want one:
class MyProviderModule extends Llm4sProviderModule:
def chatProviders: Seq[ProviderDescriptor] = Seq(MyProvider)
Classpath discovery via META-INF/services arrives with PR 3 of #1131; until then a module is registered explicitly through ProviderRegistry.of or ProviderRegistry.withModule.
Attributes
- Supertypes
-
class Objecttrait Matchableclass Any
- Known subtypes
-
object BuiltinProviders
The shape of a provider's llm4s.providers.<name> section: which fields it requires, and what to tell the user when one is missing.
The shape of a provider's llm4s.providers.<name> section: which fields it requires, and what to tell the user when one is missing.
This replaces the per-provider NamedProviderValidator implementations that llm4s-core used to hold, one object per provider in a shared file. A provider now declares its own requirements, and a single generic validator turns that declaration into the same error messages as before.
== Why defaults live here rather than in HOCON == Chat-provider config is keyed by the user's ''instance'' name (llm4s.providers.my-openai.baseUrl), so a reference.conf fragment shipped by a provider module cannot express "the default baseUrl for anything whose provider = "openai"" — it does not know the instance name. defaultBaseUrl is therefore code, and is the single source for a provider's default endpoint.
Value parameters
- baseUrlExample
-
example shown when a required
baseUrlis missing. - defaultBaseUrl
-
base URL used when the section omits one.
- endpointDescription
-
what this provider means by
endpoint, shown when a required one is missing. Providers repurpose the field (Azure: deployment name; Vertex AI: GCP project id). - requiresApiKey
-
the section must carry a non-empty
apiKey. - requiresBaseUrl
-
the section must carry a non-empty
baseUrl; set this only when there is nodefaultBaseUrl. - requiresEndpoint
-
the section must carry a non-empty
endpoint.
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Attributes
- Companion
- class
- Supertypes
-
trait Producttrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
ProviderConfigSpec.type
Everything llm4s needs to know about one LLM provider, supplied by the provider itself.
Everything llm4s needs to know about one LLM provider, supplied by the provider itself.
A descriptor is the whole extension point: implement it, register it (by listing it in an Llm4sProviderModule, or by handing it to ProviderRegistry.of), and the provider becomes reachable from configuration, validation, client construction and model discovery without editing anything in llm4s-core. Before this existed, adding a provider meant edits to roughly eight shared files — see #1131.
Attributes
- Example
-
object BedrockProvider extends ProviderDescriptor: val id = ProviderId("bedrock") val configSpec = ProviderConfigSpec(requiresApiKey = true, requiresEndpoint = true) def buildConfig(providerName: String, section: NamedProviderConfig)(using ContextWindowResolver ): Result[ProviderConfig] = ... def buildClient(config: ProviderConfig, options: LlmClientOptions)(using ModelRegistryService ): Result[LLMClient] = ProviderDescriptor.expectConfig[BedrockConfig](id, config).flatMap(BedrockClient(_, options.metrics)) - Companion
- object
- Supertypes
-
class Objecttrait Matchableclass Any
- Known subtypes
-
object AnthropicProviderobject AzureProviderobject CohereProviderobject DeepSeekProviderobject GeminiProviderobject MistralProviderobject OllamaProviderobject OpenAIProviderobject OpenRouterProviderobject RequestyProviderobject VertexAIProviderobject ZaiProviderShow all
Attributes
- Companion
- trait
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
ProviderDescriptor.type
What a provider implementation can actually do, declared by the provider itself.
What a provider implementation can actually do, declared by the provider itself.
This is a '''static''' declaration made by a ProviderDescriptor, not a runtime discovery: it describes the client this build ships, so a caller can ask "will streaming work here?" without making a call and reading the error. Contrast org.llm4s.llmconnect.utils.ProviderCapabilities, which is a health-check snapshot attached to a live connection.
The flags default to true because a provider that omits them is claiming the full interface; a provider that cannot honour part of it must say so, and saying so is then visible to users rather than buried in a Left at call time. Cohere and Mistral currently declare streaming = false — see #925.
Value parameters
- streaming
-
whether
LLMClient.streamCompleteis implemented. - toolCalling
-
whether the provider accepts tool/function definitions.
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all
Attributes
- Companion
- class
- Supertypes
-
trait Producttrait Mirrorclass Objecttrait Matchableclass Any
- Self type
-
ProviderFeatures.type
The set of providers this build can resolve.
The set of providers this build can resolve.
A registry is an immutable value, not a mutable global: withProvider and withModule return a new registry, and an application that wants a different set constructs one with ProviderRegistry.of and passes it in. Core code resolves a registry through a using clause, so the default is ProviderRegistry.default unless the caller supplies another.
Lookup is by ProviderId and never throws: an id nothing handles produces a Left naming the ids that are registered, which is the difference between a usable error and "provider openai not registered".
Attributes
- Companion
- object
- Supertypes
-
class Objecttrait Matchableclass Any
Attributes
- Companion
- class
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
ProviderRegistry.type