OpenAI-compatible models
The model-provider seam. create_language_model_client returns a client
satisfying the LanguageModelClient protocol, routing to Azure OpenAI or to any
OpenAI-compatible host (Ollama, vLLM) without the caller knowing which.
OpenAISDKClient is the shared base both concrete clients inherit from — it
holds the chat/embedding calls, retry logic and token-metric logging, so a
provider class only supplies its own SDK construction.
Provider-agnostic language-model client seam.
Workbench issues all chat/embedding traffic through a small, provider-neutral
surface — call_chat(messages) -> str and call_embedding(batch) -> list[list[float]].
This module defines that surface as the LanguageModelClient
Protocol and a factory
that constructs the right concrete client for a chosen provider, so call sites can be
routed to Azure OpenAI or any OpenAI-compatible host (OpenAI directly, Ollama, vLLM,
hosted open models) without changing the callers.
LanguageModelClient
Bases: Protocol
Structural interface every language-model client conforms to.
Callers depend only on this surface — never on provider-specific SDK objects.
Both AzureOpenAIClient and OpenAICompatibleClient satisfy it (as does the
test double MockAzureOpenAIClient).
call_chat
call_chat(messages, max_retries=5, max_completion_tokens=None)
Return the chat completion text for messages.
call_embedding
call_embedding(batch, max_retries=5)
Return one embedding vector per string in batch.
close
close()
Release any underlying connections.
ModelProvider
Bases: StrEnum
Supported language-model hosting providers.
create_language_model_client
create_language_model_client(provider=None, **config)
Construct a language-model client for the given provider.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
provider
|
ModelProvider | str | None
|
|
None
|
**config
|
Any
|
Connection/config kwargs. Keys not relevant to the selected provider
are ignored, so a single loosely-populated config dict can drive any provider.
Azure keys: |
{}
|
Returns:
| Type | Description |
|---|---|
LanguageModelClient
|
A concrete client satisfying |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
OpenAISDKClient
Shared implementation for clients backed by an OpenAI-style SDK.
Both the Azure OpenAI SDK (openai.AzureOpenAI) and the plain OpenAI SDK
(openai.OpenAI, which also fronts OpenAI-compatible hosts such as Ollama or
vLLM via a custom base_url) expose identical chat.completions.create and
embeddings.create interfaces and return identically-shaped response objects.
This base therefore holds the retry/backoff, token-metric logging and response
parsing once; concrete subclasses only differ in how they construct self.client
and resolve self.model.
Subclasses must call super().__init__(...) with an already-constructed SDK
client and the resolved per-instance model, response_format and temperature.
Attributes:
| Name | Type | Description |
|---|---|---|
client |
AzureOpenAI | OpenAI
|
The underlying |
model |
str | None
|
Model / deployment name used for chat and embedding calls. |
response_format |
dict[Any, Any] | None
|
Optional response format, e.g. |
temperature |
float | None
|
Sampling temperature; |
__del__
__del__()
Destructor to ensure cleanup if close() wasn't called.
__enter__
__enter__()
Context manager entry point.
__exit__
__exit__(exc_type, exc_val, exc_tb)
Context manager exit point - ensures connections are cleaned up.
call_chat
call_chat(messages, max_retries=5, max_completion_tokens=None)
Call the chat completions API.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
messages
|
list[dict[str, Any]]
|
List of dictionary objects specifying the messages to send. Messages must adhere to the prompting standard. |
required |
max_retries
|
int
|
Number of times to call the API before raising an error |
5
|
max_completion_tokens
|
int | None
|
Maximum number of tokens to generate in the response. If None, uses API default. |
None
|
Returns:
| Type | Description |
|---|---|
str
|
Response from the chat API. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If attempts exceeds |
call_embedding
call_embedding(batch, max_retries=5)
Call the embeddings API.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch
|
list[str]
|
List of strings to embed |
required |
max_retries
|
int
|
Number of times to call the API before raising an error |
5
|
Returns:
| Type | Description |
|---|---|
list[list[float]]
|
List of embeddings |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If attempts exceeds |
close
close()
Explicitly close the underlying SDK client and release all connections.
Call this method when you're done using the client to ensure connections are properly cleaned up, especially in high-concurrency scenarios.
OpenAICompatibleClient
Bases: OpenAISDKClient
A client for any OpenAI-compatible chat/embeddings endpoint.
Uses the plain openai.OpenAI SDK pointed at a custom base_url, which covers
OpenAI directly, local runtimes such as Ollama (http://localhost:11434/v1) and
vLLM, and most hosted open-model providers. Chat/embedding calls, retry logic and
token-metric logging are inherited from the shared
OpenAISDKClient base, so token
counts land under the same counts.chat.* / counts.embeddings.* metric paths as
the Azure client.
Attributes:
| Name | Type | Description |
|---|---|---|
api_key |
str
|
API key for the endpoint. Defaults to environment variable |
base_url |
str
|
The endpoint base URL, e.g. |
model |
str | None
|
Model name to request. Defaults to environment variable |
response_format |
dict[Any, Any] | None
|
The type of response to request. For example for JSON: { "type": "json_object" }. |
client |
AzureOpenAI | OpenAI
|
The |
__init__
__init__(api_key=None, base_url=None, model=None, response_format=None, temperature=0.1, timeout=600.0)
Initialize the OpenAI-compatible client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
api_key
|
str | None
|
API key for the endpoint. If not provided, defaults to |
None
|
base_url
|
str | None
|
The endpoint base URL, e.g. |
None
|
model
|
str | None
|
Model name to request. If not provided, defaults to |
None
|
response_format
|
dict[Any, Any] | None
|
The type of response to request, e.g. |
None
|
temperature
|
float | None
|
Sampling temperature. Pass |
0.1
|
timeout
|
float
|
Read/write timeout in seconds (default: 600.0 / 10 minutes). |
600.0
|