LLM¶
The imbi.common.llm package holds the code that Imbi services use to
call language models and to manage the AI model catalog. For the
operator view of providers and models, see
AI models.
| Module | What it does |
|---|---|
imbi.common.llm |
AnthropicClient, a small wrapper for JSON completions |
drivers |
The static catalog of provider drivers |
discovery |
Reads the model list from a provider's list-models API |
typesafe |
Calls a TypeSafe System One decision model |
AnthropicClient and discovery need the llm extra, which installs
the anthropic package.
JSON completions¶
AnthropicClient.complete_json() sends one prompt and validates the
first JSON object in the response against a Pydantic model. It never
raises for a model failure. When the API key is not set, the SDK is not
installed, the call fails, or the response does not validate, it returns
your fallback with degraded=True. An endpoint can pass degraded to
the UI to say that AI is not available.
import pydantic
from imbi.common import llm
class Summary(pydantic.BaseModel):
title: str
body: str
client = llm.AnthropicClient()
result = await client.complete_json(
'Summarize these commits as JSON with title and body: ...',
schema=Summary,
fallback=Summary(title='', body=''),
)
if result.degraded:
...
Make one client at startup and use it for all requests. Call
aclose() at shutdown. Set cache_system_prompt=True with a system
prompt to send the system prompt with prompt caching.
| Variable | Default | Description |
|---|---|---|
ANTHROPIC_API_KEY |
none | The API key. Without it, every call returns the fallback |
IMBI_ANTHROPIC_DEFAULT_MODEL |
DEFAULT_MODEL |
The model to use when the call does not give one |
IMBI_ANTHROPIC_TIMEOUT |
30.0 |
Request timeout, in seconds |
IMBI_ANTHROPIC_MAX_RETRIES |
2 |
SDK retries |
Drivers¶
A driver is the code that talks to one kind of provider. Drivers are in
code, not in the graph. An AIProvider node exists only when an admin
configures a provider. DRIVERS is the catalog. Each DriverInfo says
if the driver has a default endpoint, needs a base_url, can use cloud
IAM credentials, supports model discovery, and serves generative or
decision models.
resolve_base_url(driver, base_url) returns the provider's own
base_url, or else the driver default.
Model discovery¶
discovery.list_models(driver, api_key, base_url) returns the models
that a provider reports. Only the anthropic, openai and
openai_compatible drivers support it. The admin UI uses it to make
AIModel nodes and to test a stored credential. Every failure raises
DiscoveryError. Its message contains no API key and no response body,
so the caller can show it to an admin.
Decision models¶
typesafe.decide() sends a state and a set of questions to a TypeSafe
System One model (the typesafe driver) and returns typed answers. Every
failure raises DecisionError, with a message that is safe to show.
API Reference¶
Anthropic client¶
AnthropicClient ¶
AnthropicClient(
settings: AnthropicSettings | None = None,
*,
client: AsyncAnthropic | None = None,
)
Thin wrapper around :class:anthropic.AsyncAnthropic.
A single instance is created at startup; callers reuse it across
requests. When :attr:available is False (no API key, or the
SDK is not installed), :meth:complete_json returns the caller's
fallback with degraded=True instead of raising.
Source code in libraries/common/src/imbi/common/llm/__init__.py
complete_json
async
¶
complete_json(
prompt: str,
*,
schema: type[T],
fallback: T,
max_tokens: int = 1024,
model: str | None = None,
system: str | None = None,
cache_system_prompt: bool = False,
) -> CompletionResult[T]
Issue a JSON-shaped completion.
schema is a Pydantic model the response is validated
against. fallback is returned (with degraded=True) on
any failure path. When cache_system_prompt is True and
system is provided, the system block is sent with prompt
caching enabled — useful for callers that re-use the same
instructions across many requests.
Source code in libraries/common/src/imbi/common/llm/__init__.py
CompletionResult ¶
Bases: BaseModel
Outcome of a :meth:AnthropicClient.complete_json call.
degraded=True signals that the underlying API call failed and
the caller-provided fallback was returned in its place. Endpoints
typically forward this flag to the UI so the user can be told
"AI unavailable".
AnthropicSettings ¶
Bases: BaseSettings
Anthropic client configuration.
Reads ANTHROPIC_API_KEY plus the IMBI_ANTHROPIC_* namespace
so the same env-var conventions used elsewhere in the codebase
apply (set IMBI_ANTHROPIC_DEFAULT_MODEL to override the model
org-wide, IMBI_ANTHROPIC_TIMEOUT for the request timeout).
Drivers¶
DriverInfo ¶
Bases: BaseModel
One entry in the static provider-driver catalog.
DRIVERS
module-attribute
¶
DRIVERS: tuple[DriverInfo, ...] = (
DriverInfo(
slug='anthropic',
name='Anthropic',
description='Claude models served by the Anthropic API.',
default_base_url='https://api.anthropic.com',
supports_discovery=True,
icon='Sparkles',
),
DriverInfo(
slug='openai',
name='OpenAI',
description='GPT models served by the OpenAI API.',
default_base_url='https://api.openai.com/v1',
supports_discovery=True,
icon='Bot',
),
DriverInfo(
slug='openai_compatible',
name='OpenAI-compatible',
description='Any endpoint that implements the OpenAI chat-completions API, such as vLLM, Ollama, or a gateway.',
requires_base_url=True,
supports_discovery=True,
icon='Server',
),
DriverInfo(
slug='bedrock',
name='AWS Bedrock',
description='Models served through AWS Bedrock, authenticated with an API key or the runtime IAM role.',
supports_iam=True,
icon='Cloud',
),
DriverInfo(
slug='vertex',
name='Google Vertex AI',
description='Models served through Google Cloud Vertex AI.',
supports_iam=True,
icon='Cloud',
),
DriverInfo(
slug='typesafe',
name='TypeSafe',
description='System One decision models, such as Jev, that return typed judgments and probabilities instead of text.',
default_base_url='https://api.typesafe.ai/v1',
model_types=('decision',),
icon='Scale',
),
)
get_driver ¶
resolve_base_url ¶
Return the endpoint a provider should call.
The provider's own base_url wins; otherwise the driver default,
which is None for drivers that have none.
Source code in libraries/common/src/imbi/common/llm/drivers.py
Discovery¶
list_models
async
¶
list_models(
driver: str,
api_key: str,
base_url: str | None,
*,
bearer: bool = False,
) -> list[DiscoveredModel]
Return the models driver reports for api_key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
driver
|
str
|
Provider driver slug. |
required |
api_key
|
str
|
Decrypted credential for the provider. |
required |
base_url
|
str | None
|
Endpoint to call, already resolved against the driver's default. |
required |
bearer
|
bool
|
|
False
|
Returns:
| Type | Description |
|---|---|
list[DiscoveredModel]
|
The provider's models, in the order the provider returned them. |
Raises:
| Type | Description |
|---|---|
DiscoveryError
|
The driver cannot be discovered, or the call failed. The message is safe to show an admin. |
Source code in libraries/common/src/imbi/common/llm/discovery.py
DiscoveredModel
dataclass
¶
DiscoveredModel(
model_id: str,
display_name: str,
created_at: datetime | None = None,
context_window: int | None = None,
max_output_tokens: int | None = None,
)
One model reported by a provider.
DiscoveryError ¶
Bases: Exception
A provider's model list could not be retrieved.
status is the HTTP status of the provider, when it answered.
Source code in libraries/common/src/imbi/common/llm/discovery.py
TypeSafe¶
decide
async
¶
decide(
api_key: str,
base_url: str,
model: str,
state: object,
questions: dict[str, Any],
transport: AsyncBaseTransport | None = None,
) -> DecisionResult
Ask model the questions about state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
api_key
|
str
|
Decrypted credential for the provider. |
required |
base_url
|
str
|
The provider endpoint, for example
|
required |
model
|
str
|
The model id, for example |
required |
state
|
object
|
A string, object, or array. |
required |
questions
|
dict[str, Any]
|
Question id to question, in the TypeSafe shape. |
required |
transport
|
AsyncBaseTransport | None
|
Test seam for :class: |
None
|
Raises:
| Type | Description |
|---|---|
DecisionError
|
The call failed; the message is safe to show. |
Source code in libraries/common/src/imbi/common/llm/typesafe.py
DecisionResult ¶
Bases: TypedDict
DecisionError ¶
Bases: Exception
The decision call failed.