Reference
llmbroker
llmbroker — a standalone, host-agnostic LLM-provider broker.
AsyncBroker
Façade over the LLM pool: route completions, inspect state, edit the catalog.
Source code in src/llmbroker/broker/broker.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | |
disable_llm(name)
async
Set the manual latch: withdraws the slot, survives preset rolls, covers
every operation including future ones. Only enable_llm clears it.
Source code in src/llmbroker/broker/broker.py
239 240 241 242 243 244 245 | |
enable_llm(name)
async
Clear the manual latch — a re-enabled model rehabilitates through new ratings, no quality reset exists.
Source code in src/llmbroker/broker/broker.py
247 248 249 250 251 252 253 | |
ensure_pool()
async
Lazy idempotent initializer — provisions the pool exactly once.
Raises if the registry is empty — call sync(preset) first.
Source code in src/llmbroker/broker/broker.py
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | |
sync(preset)
async
Mirror preset into the registry: add new entries, update existing
ones, delete entries absent from the preset. Explicit and idempotent —
call it once to initialize a fresh DB, or again whenever the preset changes.
If the pool is already provisioned, the change takes effect immediately.
Source code in src/llmbroker/broker/broker.py
150 151 152 153 154 155 156 157 158 159 160 161 162 163 | |
AsyncLLM
Handle returned by AsyncBroker.get(name) — live view into broker internals.
Source code in src/llmbroker/broker/result.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
AsyncResult
Returned by AsyncBroker.ask()/chat().
Source code in src/llmbroker/broker/result.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | |
Broker
Synchronous client over an AsyncBroker on a background loop thread.
Source code in src/llmbroker/sync.py
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | |
DictSecrets
Read-only secrets resolver backed by an in-memory mapping (tests / preloaded keys).
Source code in src/llmbroker/standalone/secrets.py
25 26 27 28 29 30 31 32 33 34 | |
FileStore
Day-split JSONL call journal plus a YAML disabled-verdict map, under one directory.
Source code in src/llmbroker/standalone/store.py
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | |
calls(*, limit, scope=None)
async
Newest-first tail of the journal, both kinds interleaved — unfiltered by scope
(learning is global); scope is accepted for the host-facing filter only.
Source code in src/llmbroker/standalone/store.py
179 180 181 182 | |
InMemoryStore
Explicit in-memory opt-out — no persistence, session-scoped learning; disabled verdicts live only in process memory.
Source code in src/llmbroker/standalone/store.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
LLM
Synchronous analogue of AsyncLLM.
Source code in src/llmbroker/sync.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
LLMRequestError
Bases: Exception
Base: this request could not be completed.
Source code in src/llmbroker/exceptions.py
6 7 | |
LifecyclePhase
Bases: Enum
The FSM label for one LLM's lifecycle, always derived from cooldown_until vs now.
Source code in src/llmbroker/models.py
14 15 16 17 18 | |
NoLLMAvailableError
Bases: LLMRequestError
No LLM slot was available for this request.
reason is one of:
"empty_pool"— the pool has zero slots."no_keys"— slots exist but none has a resolved key."all_disabled"— keyed slots exist but every one is admin-disabled."excluded"— every candidate was excluded for this request (internal)."timeout"— the deadline expired (or nothing is free right now);retry_atcarries the earliest known return time, when known.
Source code in src/llmbroker/exceptions.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
Optimizer
dataclass
Consecutive-failure counter for backoff, plus per-(model, operation) sliding windows of raw quality ratings backing the demoted-last selection order.
Source code in src/llmbroker/optimizer.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | |
is_demoted(llm_name, operation)
True iff the window holds at least quality_min_count ratings and their
Wilson-score upper bound sits below quality_floor.
Source code in src/llmbroker/optimizer.py
72 73 74 75 76 77 78 79 | |
load_scores(scores)
Replace every window wholesale — used by the journal rebuild.
Source code in src/llmbroker/optimizer.py
98 99 100 101 102 103 104 105 106 107 | |
on_rate_limited(llm_name)
Increment the consecutive-failure count the router reads for its backoff exponent.
Source code in src/llmbroker/optimizer.py
54 55 56 | |
record_quality(llm_name, operation, score)
Fold one rating into the (model, operation) window, oldest evicted first.
Source code in src/llmbroker/optimizer.py
88 89 90 91 92 93 94 95 96 | |
wilson_bound(llm_name, operation)
The Wilson-score upper bound backing is_demoted, for diagnostics.
Source code in src/llmbroker/optimizer.py
65 66 67 68 69 70 | |
Registry
File-backed read-only registry — .toml / .json by extension.
Source code in src/llmbroker/standalone/registry.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
key_info()
async
Per-provider onboarding metadata from the [keys] table, keyed by api_key_ref.
Source code in src/llmbroker/standalone/registry.py
77 78 79 80 81 82 | |
Result
Synchronous analogue of AsyncResult.
Source code in src/llmbroker/sync.py
43 44 45 46 47 48 49 50 51 52 53 54 | |
Secrets
Read-only env-backed secrets resolver (the default battery).
Source code in src/llmbroker/standalone/secrets.py
15 16 17 18 19 20 21 22 | |
arun_tool_loop(llms, messages, *, tools=None, dispatch=None, max_steps=8, **chat_kwargs)
async
Drive broker.chat until a tool-call-free reply; execute tools via dispatch.
Source code in src/llmbroker/chat.py
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | |
run_tool_loop(llms, messages, *, tools=None, dispatch=None, max_steps=8, **chat_kwargs)
Synchronous tool loop over a sync Broker.
Mirrors arun_tool_loop but calls the blocking Broker.chat; it does
not use the async engine directly so it is safe to call from any thread.
Source code in src/llmbroker/chat.py
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | |
__main__
python -m llmbroker entry point.
aws
AWS Secrets Manager backend for llmbroker.
Needs the aioboto3 driver (llmbroker[aws]); importing this package is
how a host declares that dependency, so a bare import llmbroker stays
driver-free.
Secrets
AWS Secrets Manager-backed mutable secrets store.
A secretsmanager client is opened as an async context manager per call;
there is no shared client state, so aclose is a no-op. endpoint_url
targets a non-default endpoint (e.g. LocalStack or a VPC endpoint).
Source code in src/llmbroker/aws/secrets.py
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
secrets
AWS Secrets Manager-backed mutable secrets store.
Secrets
AWS Secrets Manager-backed mutable secrets store.
A secretsmanager client is opened as an async context manager per call;
there is no shared client state, so aclose is a no-op. endpoint_url
targets a non-default endpoint (e.g. LocalStack or a VPC endpoint).
Source code in src/llmbroker/aws/secrets.py
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
backends
Zero-dependency storage core: declarative table spec, the Driver protocol,
generic ports written once against any Driver, and an in-memory reference driver.
Importable by a bare import llmbroker — no driver package required. Each DB
backend package (sqlite, postgres, mongodb) supplies one Driver
implementation and wraps the generic ports in its facade classes.
driver
The per-DB storage contract: record-shaped, not domain-shaped.
A driver method body is the one statement that is genuinely DB-specific; the
generic layer (backends.ports) owns lazy ensure_schema gating, JSON⇄dataclass
translation, and KeyError semantics.
Driver
Bases: Protocol
Source code in src/llmbroker/backends/driver.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
fetch(table)
async
All rows, ordered by key columns (registry load order feeds selection priority).
Source code in src/llmbroker/backends/driver.py
23 24 25 | |
purge(table, before)
async
Delete rows older than before; returns the count removed.
Source code in src/llmbroker/backends/driver.py
44 45 46 | |
recent(table, limit, match=None)
async
Newest-first tail; match is an optional equality filter.
Source code in src/llmbroker/backends/driver.py
40 41 42 | |
inmemory
Trivial dict-based Driver — a test double, and a dependency-free storage
option for hosts that want the full port surface without a database.
InMemoryDriver
In-process Driver implementation. Not persisted, not process-shared.
Source code in src/llmbroker/backends/inmemory.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | |
ports
Generic ports: the domain protocols implemented once over any Driver.
Registry and secrets are global — no user scope exists anywhere in this layer
(the broker turns an opaque scope string into a secret-ref prefix and a
journal attribution field instead).
DriverRegistry
Registry over any Driver — a pure preset mirror, globally scoped.
Source code in src/llmbroker/backends/ports.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | |
mirror(configs)
async
Total mirror: add new, update existing, delete stored entries absent
from configs — the only registry write path.
Source code in src/llmbroker/backends/ports.py
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | |
DriverSecrets
Flat ref -> value secrets store over any Driver. Exact-match lookups
only — the own→shared prefix fallback lives in the broker.
Source code in src/llmbroker/backends/ports.py
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | |
DriverStore
Journal (append/recent/purge) + admin disabled-map, over any Driver.
Self-purges call rows older than retention, checked at most once per
hour on write activity.
Source code in src/llmbroker/backends/ports.py
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | |
calls(*, limit, scope=None)
async
Newest-first tail of the journal, both kinds interleaved — unfiltered by scope
(learning is global); scope is accepted for the host-facing filter only.
Source code in src/llmbroker/backends/ports.py
171 172 173 174 175 176 | |
record_quality(llm_name, operation, score, *, call_id=None)
async
Append a self-contained quality record — never updates the call row.
Source code in src/llmbroker/backends/ports.py
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | |
seed_disabled(names)
async
Insert-if-absent every name with disabled=False — never touches existing values.
Source code in src/llmbroker/backends/ports.py
200 201 202 203 204 205 | |
spec
One declarative description of the stores, consumed by every driver's
ensure_schema. Column types are portable strings — each driver maps them to
its own native DDL/wire representation.
TableSpec
dataclass
One store's shape: name, identity columns, and portable column types.
Every key column is a single non-null text column: registry (name,),
disabled (name,), secrets (ref,) — the user scope rides inside the
ref string, so no scope columns exist anywhere. The calls journal has no
keyed access (append-only); its id column is listed for completeness
and uniqueness only.
Source code in src/llmbroker/backends/spec.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
broker
The async broker engine: the AsyncBroker façade plus its live-pool collaborators.
Implementation lives in focused sibling modules — broker / catalog / router /
pool_view / pool / result / state. Request exceptions live in llmbroker.exceptions
and the optimizer knob in llmbroker.optimizer.
broker
The AsyncBroker façade over the LLM pool and its collaborators.
AsyncBroker owns the external ports (registry, secrets, store),
lazily provisions the live LLMPool once, and delegates each operation to
the collaborator that owns it:
Catalog— pool membership in sync with the registry;sync(preset)mirrors a preset into it (the only registry write path)Router— routing a completion over the pool with failoverPoolView— read-only views of current pool state_LearningHook— quality windows, dead-key drops, and the debounced journal rebuild feeding shared cooldowns, snapshot metrics, and the admin disabled-verdict map (only wired whenoptimizeis truthy)
The call journal (calls) is a thin pass-through to a queryable store
backend; each backend self-purges records past its retention horizon. There is
no alerts API: the few human-actionable events (dead key, demotion flip,
under-provisioned pool) are log lines; hosts poll snapshot() for current
raw state or hook the llmbroker logger.
AsyncBroker
Façade over the LLM pool: route completions, inspect state, edit the catalog.
Source code in src/llmbroker/broker/broker.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | |
disable_llm(name)
async
Set the manual latch: withdraws the slot, survives preset rolls, covers
every operation including future ones. Only enable_llm clears it.
Source code in src/llmbroker/broker/broker.py
239 240 241 242 243 244 245 | |
enable_llm(name)
async
Clear the manual latch — a re-enabled model rehabilitates through new ratings, no quality reset exists.
Source code in src/llmbroker/broker/broker.py
247 248 249 250 251 252 253 | |
ensure_pool()
async
Lazy idempotent initializer — provisions the pool exactly once.
Raises if the registry is empty — call sync(preset) first.
Source code in src/llmbroker/broker/broker.py
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | |
sync(preset)
async
Mirror preset into the registry: add new entries, update existing
ones, delete entries absent from the preset. Explicit and idempotent —
call it once to initialize a fresh DB, or again whenever the preset changes.
If the pool is already provisioned, the change takes effect immediately.
Source code in src/llmbroker/broker/broker.py
150 151 152 153 154 155 156 157 158 159 160 161 162 163 | |
catalog
Catalog: keep the live pool's membership in sync with the registry.
Loads configs from the registry, resolves their API keys via the secrets
backend, and reflects every change into the LLMPool. The registry is a
pure mirror of a preset (see sync) — nothing else writes it.
Catalog
Reconciles the persistent registry into the live pool, and mirrors presets into it.
Source code in src/llmbroker/broker/catalog.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
provision()
async
Reconcile the pool with the registry. The caller serializes this one-time init; it is not re-entrant. Raises if the registry is empty.
Source code in src/llmbroker/broker/catalog.py
35 36 37 38 39 40 41 42 43 44 | |
resync()
async
Re-read the registry and reconcile pool membership — no emptiness check.
Called by the debounced journal rebuild so registry edits and key changes from other processes/nodes take effect on a running broker.
Source code in src/llmbroker/broker/catalog.py
46 47 48 49 50 51 52 53 | |
sync(preset)
async
Mirror preset into the registry: add new entries, update existing
ones, delete entries absent from the preset — the total mirror, nothing to
preserve. Refuses (raises) a model identity change under an existing
name, since that binds learned stats to the model name; a model bump must
land under a new entry name instead.
Source code in src/llmbroker/broker/catalog.py
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
learning
_LearningHook: the wrapper around a store backend.
Drives Optimizer bookkeeping (backoff counters, quality windows) from the
live event stream, and periodically rebuilds derived state — quality-window
verdicts, shared cooldowns, snapshot metrics, registry membership, and the
admin disabled-verdict map — from one cached read of the journal tail. No
second storage subsystem: everything llmbroker learns beyond config is
re-derived from the append-only journal plus the tiny disabled map.
metrics_from_calls(rows)
rows newest-first: the first call row per model is its most recent.
Source code in src/llmbroker/broker/learning.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | |
resolve_metrics_map(store)
async
Derive a per-LLM metrics map from whatever the store can offer:
a _LearningHook's cache, a queryable store's tail, or nothing.
Source code in src/llmbroker/broker/learning.py
55 56 57 58 59 60 61 62 63 | |
pool
LLMPool: live per-LLM slot state (config, key, cooldown, quality) backing routing.
LLMPool
The pool of LLM slots and their live cooldown / quality state.
Source code in src/llmbroker/broker/pool.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | |
add(cfg, key, order=None)
async
Register/refresh a config. A None key leaves any prior key intact.
Upserts in place so an existing slot's live state (cooldown, fail count,
in-flight, disabled) survives a config refresh. order defaults to
insertion order when the caller has no curated position to assert.
Source code in src/llmbroker/broker/pool.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | |
apply_peer_cooldowns(cooldowns, fail_counts=None)
async
Raise each named slot's cooldown_until to at least the given value.
Called from the debounced journal rebuild — never lowers an already-later
local cooldown, and never touches in_flight (nothing was acquired in
this code path). The peer fail-streak folds in as max(local, peer).
Source code in src/llmbroker/broker/pool.py
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | |
cool_down(config, delay)
async
Withdraw the slot for delay seconds.
Source code in src/llmbroker/broker/pool.py
232 233 234 235 236 237 238 239 240 241 242 | |
drop(name)
async
Remove a slot entirely, so a later re-add under the same name starts clean.
Source code in src/llmbroker/broker/pool.py
89 90 91 92 93 | |
release(config)
async
A missing name is legal (removed mid-flight) — no-op.
Source code in src/llmbroker/broker/pool.py
215 216 217 218 219 220 221 | |
set_disabled(name)
Withdraw the slot. An in-flight call finishes normally; the flag excludes the slot from every acquisition afterward.
Source code in src/llmbroker/broker/pool.py
99 100 101 102 103 104 | |
pool_view
PoolView: read-only views of the broker's current pool state.
PoolView
Live views over the pool: a single LLM handle, the count, a full snapshot.
Source code in src/llmbroker/broker/pool_view.py
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
result
Per-call result handle and the live per-LLM view returned by the broker.
AsyncLLM
Handle returned by AsyncBroker.get(name) — live view into broker internals.
Source code in src/llmbroker/broker/result.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
AsyncResult
Returned by AsyncBroker.ask()/chat().
Source code in src/llmbroker/broker/result.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | |
router
Router: route one completion over the pool with per-LLM failover.
Acquires a free slot, calls the provider, and on a 429/503/401/403/5xx cools that LLM down (or drops it) and tries the next free one; a client-side 4xx (any other status in [400, 500)) fails over without cooling and, if every candidate is exhausted this way, surfaces the provider error to the caller. Every attempt is recorded to the journal.
Router
Routes a completion request over the pool, failing over between LLMs.
Source code in src/llmbroker/broker/router.py
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | |
source
Dispatch a plain string/Path source to a registry/secrets/store triple.
Dispatch is dumb and explicit: .toml/.json -> file registry + env
secrets (AsyncBroker falls back to the store/ sibling default); sqlite://
/ .db / .sqlite -> sqlite, one file backing all three ports;
postgresql:// / mongodb:// -> by scheme, one driver shared by all three
ports. Anything else raises a clear error naming the accepted forms.
Each backend package is imported lazily here (never at module load) so a bare
import llmbroker never pulls in a driver package.
resolve_source(source)
Returns (registry, secrets, store); a None store means
"use the caller's own default" (the file-registry store/ sibling).
Source code in src/llmbroker/broker/source.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
chat
OpenAI-compatible chat primitives and the host-agnostic tool-loop helpers.
Request building, response parsing and retry parsing live here once, adapted to
the new LLMConfig (the resolved key is passed in, never read off the config).
arun_tool_loop drives broker.chat() back-and-forth until a tool-call-free
reply; run_tool_loop is its sync wrapper.
arun_tool_loop(llms, messages, *, tools=None, dispatch=None, max_steps=8, **chat_kwargs)
async
Drive broker.chat until a tool-call-free reply; execute tools via dispatch.
Source code in src/llmbroker/chat.py
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | |
build_chat_request(config, api_key, messages, tools=None)
Return (url, headers, json_body) for an OpenAI-compatible chat completion.
Source code in src/llmbroker/chat.py
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
call_provider(config, api_key, messages, tools, *, client=None)
async
POST an OpenAI-compatible completion and return (content, tool_calls, usage).
With client passed, it is reused as-is (never closed here — the caller
owns its lifetime); with None, an ephemeral client is opened and closed
for this single call.
Source code in src/llmbroker/chat.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
execute_tool_calls(tool_calls, dispatch)
Run each tool call via dispatch; return the tool-result messages to append.
Source code in src/llmbroker/chat.py
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |
message_from_response(data)
Extract the assistant message object from a chat-completion response body.
Source code in src/llmbroker/chat.py
64 65 66 | |
parse_tool_calls(message)
Extract the raw tool_calls list from an assistant message, verbatim.
Source code in src/llmbroker/chat.py
128 129 130 131 132 133 | |
parse_usage(data)
Extract token counts from a chat-completion response body, if present.
Source code in src/llmbroker/chat.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | |
retry_after_seconds(headers, default_sec)
Parse Retry-After as either delay-seconds or an HTTP-date, per RFC 9110.
Source code in src/llmbroker/chat.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | |
run_tool_loop(llms, messages, *, tools=None, dispatch=None, max_steps=8, **chat_kwargs)
Synchronous tool loop over a sync Broker.
Mirrors arun_tool_loop but calls the blocking Broker.chat; it does
not use the async engine directly so it is safe to call from any thread.
Source code in src/llmbroker/chat.py
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | |
cli
python -m llmbroker
Subcommands: env (emit .env skeleton), preset (download curated preset TOML), sync (mirror a preset TOML into a DB registry — DB-init workflow).
exceptions
All exceptions a caller of llmbroker may catch, in one place.
LLMRequestError
Bases: Exception
Base: this request could not be completed.
Source code in src/llmbroker/exceptions.py
6 7 | |
NoLLMAvailableError
Bases: LLMRequestError
No LLM slot was available for this request.
reason is one of:
"empty_pool"— the pool has zero slots."no_keys"— slots exist but none has a resolved key."all_disabled"— keyed slots exist but every one is admin-disabled."excluded"— every candidate was excluded for this request (internal)."timeout"— the deadline expired (or nothing is free right now);retry_atcarries the earliest known return time, when known.
Source code in src/llmbroker/exceptions.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
integrations
Host-side hooks for coexisting with third-party tools (e.g. Alembic).
These modules carry no backend logic and import no drivers; they are thin shims a host wires into another tool's configuration.
alembic
Alembic coexistence hook — autogenerate ignores every llmbroker_* object.
Wire into alembic/env.py::
import llmbroker.integrations.alembic
context.configure(
...,
include_object=llmbroker.integrations.alembic.include_object,
)
Imports nothing from Alembic — it only inspects the object name.
models
DTOs, enums, and the shared resource-lifecycle protocol for llmbroker.
Pure data and the one cross-cutting capability protocol. No I/O, no driver imports — safe to import from anywhere in the package.
AsyncResourceProtocol
Bases: Protocol
Lifecycle capability for any backend that holds an open resource.
Orthogonal to a backend's data contract. aclose() is idempotent.
Source code in src/llmbroker/models.py
173 174 175 176 177 178 179 180 | |
Call
dataclass
One append-only journal record: a call attempt (kind="call") or a
self-contained quality rating (kind="quality"), interleaved in one stream.
A quality record fills only llm_name, operation, quality_score,
ts, and optionally call_id (an opaque host-UI passthrough — never
joined against the call row it rates); status is None exactly on
quality records.
Source code in src/llmbroker/models.py
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | |
KeyInfo
dataclass
Per-provider onboarding metadata for one api_key_ref: a help blurb plus
a free-form passthrough of whatever else the TOML [keys.REF] section holds —
llmbroker has no taxonomy opinion on it.
Source code in src/llmbroker/models.py
30 31 32 33 34 35 36 37 38 | |
LLMConfig
dataclass
Pure stored config for one LLM — no secret, safe to expose.
The registry is a pure mirror of the preset (see sync): nothing else
writes it, so there is no provenance/curation marker to carry here.
Source code in src/llmbroker/models.py
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
from_metadata(*, name, base_url, model, api_key_ref, metadata)
classmethod
Reconstruct from the core columns plus the JSON metadata blob.
Source code in src/llmbroker/models.py
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
to_metadata()
Structured optional config, serialized for the registry's JSON column.
LLMConfig(name="g", base_url="https://x/v1", model="m", api_key_ref="K").to_metadata() {}
Source code in src/llmbroker/models.py
55 56 57 58 59 60 61 62 63 64 | |
LLMMetrics
dataclass
Per-LLM admin read-model derived from Call rows.
Source code in src/llmbroker/models.py
147 148 149 150 151 152 153 | |
LLMSnapshot
dataclass
Frozen point-in-time materialization of one LLM: raw facts, no status enum or precedence rule — the host derives whatever presentation it wants.
demoted_operations may contain None: the bucket for calls made without
an operation= label.
Source code in src/llmbroker/models.py
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | |
LLMState
dataclass
Snapshot of one LLM's live runtime state, built fresh on each read.
Source code in src/llmbroker/models.py
21 22 23 24 25 26 27 | |
LifecyclePhase
Bases: Enum
The FSM label for one LLM's lifecycle, always derived from cooldown_until vs now.
Source code in src/llmbroker/models.py
14 15 16 17 18 | |
Usage
dataclass
Resource use the provider reported for one call.
Source code in src/llmbroker/models.py
96 97 98 99 100 101 102 103 | |
key_hash(secret)
Short digest of a resolved key value — the quota-scope identity for shared cooldowns and dead-key drops (never the key itself).
key_hash("sk-abc") == key_hash("sk-abc") True len(key_hash("sk-abc")) 12
Source code in src/llmbroker/models.py
135 136 137 138 139 140 141 142 143 144 | |
mongodb
MongoDB backend: registry, store, and secrets.
Needs the motor driver (llmbroker[mongodb]); importing this package is
how a host declares that dependency, so a bare import llmbroker stays
driver-free. All collections are llmbroker_-prefixed and owned by ensure_schema.
Registry
Bases: DriverRegistry
MongoDB-backed mutable registry over llmbroker_registry — a pure preset mirror.
Source code in src/llmbroker/mongodb/registry.py
9 10 11 12 13 | |
Secrets
Bases: DriverSecrets
MongoDB-backed mutable secrets store over llmbroker_secrets.
Source code in src/llmbroker/mongodb/secrets.py
9 10 11 12 13 | |
Store
Bases: DriverStore
MongoDB-backed queryable store over llmbroker_calls + the
llmbroker_disabled admin verdict map.
Source code in src/llmbroker/mongodb/store.py
14 15 16 17 18 19 20 21 22 23 24 | |
driver
MongoDB Driver: renders indexes from backends.spec.TABLES.
One known installation, upgraded manually — on a version-marker mismatch
ensure_schema fails fast instead of attempting an in-place migration.
MongoDriver
One Mongo database backing every llmbroker_* collection.
Source code in src/llmbroker/mongodb/driver.py
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | |
__init__(db, *, client=None)
Pass client= only when the driver should own (and close) it — the
explicit-db facade use case does not own the caller's client.
Source code in src/llmbroker/mongodb/driver.py
41 42 43 44 45 46 47 48 49 50 51 52 | |
ensure_schema()
async
A plain per-instance flag: one driver per stack is app-lifetime, so this
gives one check per process under intended usage. Not id(db)-keyed —
after GC an id can be reused by a different database and falsely skip creation.
Source code in src/llmbroker/mongodb/driver.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | |
registry
MongoDB-backed mutable registry over llmbroker_registry — a pure preset mirror.
Registry
Bases: DriverRegistry
MongoDB-backed mutable registry over llmbroker_registry — a pure preset mirror.
Source code in src/llmbroker/mongodb/registry.py
9 10 11 12 13 | |
secrets
MongoDB-backed mutable secrets store over llmbroker_secrets.
Secrets
Bases: DriverSecrets
MongoDB-backed mutable secrets store over llmbroker_secrets.
Source code in src/llmbroker/mongodb/secrets.py
9 10 11 12 13 | |
store
MongoDB-backed queryable store over llmbroker_calls + the
llmbroker_disabled admin verdict map.
Store
Bases: DriverStore
MongoDB-backed queryable store over llmbroker_calls + the
llmbroker_disabled admin verdict map.
Source code in src/llmbroker/mongodb/store.py
14 15 16 17 18 19 20 21 22 23 24 | |
optimizer
The Optimizer knob — per-LLM failure bookkeeping, and per-(model, operation)
quality-window demotion verdicts feeding the pool's demoted-last selection order.
Optimizer
dataclass
Consecutive-failure counter for backoff, plus per-(model, operation) sliding windows of raw quality ratings backing the demoted-last selection order.
Source code in src/llmbroker/optimizer.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | |
is_demoted(llm_name, operation)
True iff the window holds at least quality_min_count ratings and their
Wilson-score upper bound sits below quality_floor.
Source code in src/llmbroker/optimizer.py
72 73 74 75 76 77 78 79 | |
load_scores(scores)
Replace every window wholesale — used by the journal rebuild.
Source code in src/llmbroker/optimizer.py
98 99 100 101 102 103 104 105 106 107 | |
on_rate_limited(llm_name)
Increment the consecutive-failure count the router reads for its backoff exponent.
Source code in src/llmbroker/optimizer.py
54 55 56 | |
record_quality(llm_name, operation, score)
Fold one rating into the (model, operation) window, oldest evicted first.
Source code in src/llmbroker/optimizer.py
88 89 90 91 92 93 94 95 96 | |
wilson_bound(llm_name, operation)
The Wilson-score upper bound backing is_demoted, for diagnostics.
Source code in src/llmbroker/optimizer.py
65 66 67 68 69 70 | |
wilson_upper(scores, z)
Wilson-score upper bound of the mean of scores at confidence z.
round(wilson_upper([1.0] * 25 + [0.0] * 5, 1.96), 4) 0.9266
Source code in src/llmbroker/optimizer.py
17 18 19 20 21 22 23 24 25 26 27 28 29 | |
postgres
Postgres backend: registry, store, and secrets.
Needs the asyncpg driver (llmbroker[postgres]); importing this package is
how a host declares that dependency, so a bare import llmbroker stays
driver-free. All tables are llmbroker_-prefixed and owned by ensure_schema.
Registry
Bases: DriverRegistry
Postgres-backed mutable registry over llmbroker_registry — a pure preset mirror.
Source code in src/llmbroker/postgres/registry.py
9 10 11 12 13 | |
Secrets
Bases: DriverSecrets
Postgres-backed mutable secrets store over llmbroker_secrets.
Source code in src/llmbroker/postgres/secrets.py
9 10 11 12 13 | |
Store
Bases: DriverStore
Postgres-backed queryable store over llmbroker_calls + the
llmbroker_disabled admin verdict map.
Source code in src/llmbroker/postgres/store.py
14 15 16 17 18 19 | |
driver
Postgres Driver: renders DDL and DML from backends.spec.TABLES.
The caller owns the pool (pool = await asyncpg.create_pool(dsn)); aclose()
is a no-op. One known installation, upgraded manually — on a fresh database the
schema is created and stamped; on a version-marker mismatch ensure_schema
fails fast instead of attempting an in-place migration.
PostgresDriver
One asyncpg pool backing every llmbroker_* table.
Pass a pre-built pool when the caller owns it (aclose() stays a
no-op, unchanged contract). Pass dsn= instead to let the driver create
and own its own pool lazily on first use (needed because pool creation is
async but this constructor is not) — aclose() then closes it.
Source code in src/llmbroker/postgres/driver.py
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | |
ensure_schema()
async
A plain per-instance flag: one driver per stack is app-lifetime, so this
gives one check per process under intended usage. Not id(pool)-keyed —
after GC an id can be reused by a different pool and falsely skip creation.
Source code in src/llmbroker/postgres/driver.py
117 118 119 120 121 122 123 124 125 126 127 128 129 130 | |
upsert(table, key, row)
async
key is part of the Driver contract but unused here: the row already
carries its own key-column values, which ON CONFLICT matches against.
Source code in src/llmbroker/postgres/driver.py
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | |
registry
Postgres-backed mutable registry over llmbroker_registry — a pure preset mirror.
Registry
Bases: DriverRegistry
Postgres-backed mutable registry over llmbroker_registry — a pure preset mirror.
Source code in src/llmbroker/postgres/registry.py
9 10 11 12 13 | |
secrets
Postgres-backed mutable secrets store over llmbroker_secrets.
Secrets
Bases: DriverSecrets
Postgres-backed mutable secrets store over llmbroker_secrets.
Source code in src/llmbroker/postgres/secrets.py
9 10 11 12 13 | |
store
Postgres-backed queryable store over llmbroker_calls + the
llmbroker_disabled admin verdict map.
Store
Bases: DriverStore
Postgres-backed queryable store over llmbroker_calls + the
llmbroker_disabled admin verdict map.
Source code in src/llmbroker/postgres/store.py
14 15 16 17 18 19 | |
protocols
Backend contracts: what a registry / secrets / store must do.
Implement these to add a custom backend. The zero-dependency implementations
ship in llmbroker.standalone; dependency-carrying ones in per-driver
packages (llmbroker.sqlite, …).
registry
Registry contract: load LLM configs; mutable backends also mirror a preset into them.
KeyInfoProtocol
Bases: Protocol
Optional capability: per-key onboarding metadata (help text plus a
free-form extra passthrough).
Maps each api_key_ref to a KeyInfo. Keyed by the env-var name because
one key is usually shared by several LLMs. A source without such metadata
simply does not implement this protocol; callers probe with
isinstance(reg, KeyInfoProtocol). It is independent of the broker — hosts
query whichever registry they built.
Source code in src/llmbroker/protocols/registry.py
20 21 22 23 24 25 26 27 28 29 30 31 32 | |
MutableRegistryProtocol
Bases: RegistryProtocol, Protocol
Source code in src/llmbroker/protocols/registry.py
12 13 14 15 16 17 | |
mirror(configs)
async
Total mirror: add entries absent from the store, update existing ones,
delete stored entries absent from configs. The only registry write path.
Source code in src/llmbroker/protocols/registry.py
14 15 16 17 | |
secrets
Secrets contract: resolve api_key_ref to a key; mutable backends also set.
store
Store contract: record calls; queryable backends also read the journal.
DisabledMapProtocol is the optional admin-verdict half: a tiny mutable
name -> disabled document a backend may additionally implement.
DisabledMapProtocol
Bases: Protocol
Optional capability: the admin disabled-verdict map (name -> bool).
Source code in src/llmbroker/protocols/store.py
29 30 31 32 33 34 35 36 | |
sqlite
SQLite backend: registry, store, and secrets over one DB file.
Needs the aiosqlite driver (llmbroker[sqlite]); importing this package is
how a host declares that dependency, so a bare import llmbroker stays
driver-free. All tables are llmbroker_-prefixed and owned by ensure_schema.
Registry
Bases: DriverRegistry
SQLite-backed mutable registry over llmbroker_registry — a pure preset mirror.
Source code in src/llmbroker/sqlite/registry.py
9 10 11 12 13 | |
Secrets
Bases: DriverSecrets
SQLite-backed mutable secrets store over llmbroker_secrets.
Source code in src/llmbroker/sqlite/secrets.py
9 10 11 12 13 | |
Store
Bases: DriverStore
SQLite-backed queryable store over llmbroker_calls + the
llmbroker_disabled admin verdict map.
Source code in src/llmbroker/sqlite/store.py
13 14 15 16 17 18 | |
driver
SQLite Driver: renders DDL and DML from backends.spec.TABLES.
One known installation, upgraded manually by its operator — on a fresh
database the schema is created and stamped; on a version-marker mismatch
ensure_schema fails fast instead of attempting an in-place migration.
SqliteDriver
One SQLite file (or one process-local :memory: database) backing
every llmbroker_* table.
Source code in src/llmbroker/sqlite/driver.py
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | |
ensure_schema()
async
A real file path migrates under its own isolation_level=None connection
and a BEGIN IMMEDIATE transaction, so concurrent OS processes serialize on
sqlite's file lock instead of racing. :memory: has no cross-process concern.
Source code in src/llmbroker/sqlite/driver.py
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | |
upsert(table, key, row)
async
key is part of the Driver contract but unused here: the row already
carries its own key-column values, which ON CONFLICT matches against.
Source code in src/llmbroker/sqlite/driver.py
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | |
registry
SQLite-backed mutable registry over llmbroker_registry — a pure preset mirror.
Registry
Bases: DriverRegistry
SQLite-backed mutable registry over llmbroker_registry — a pure preset mirror.
Source code in src/llmbroker/sqlite/registry.py
9 10 11 12 13 | |
secrets
SQLite-backed mutable secrets store over llmbroker_secrets.
Secrets
Bases: DriverSecrets
SQLite-backed mutable secrets store over llmbroker_secrets.
Source code in src/llmbroker/sqlite/secrets.py
9 10 11 12 13 | |
store
SQLite-backed queryable store over llmbroker_calls + the
llmbroker_disabled admin verdict map.
Store
Bases: DriverStore
SQLite-backed queryable store over llmbroker_calls + the
llmbroker_disabled admin verdict map.
Source code in src/llmbroker/sqlite/store.py
13 14 15 16 17 18 | |
standalone
Zero-dependency implementations that work without any external backend.
The simplest way to use llmbroker (the path the README advertises): a config
file, env-var secrets, a file-backed store — no database, no
integration code. Available with a bare import llmbroker (re-exported as
llmbroker.Registry etc.). Dependency-carrying backends live in per-driver
packages instead.
registry
File-backed registry: .toml / .json of [[llms]] rows, no secrets.
Registry
File-backed read-only registry — .toml / .json by extension.
Source code in src/llmbroker/standalone/registry.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
key_info()
async
Per-provider onboarding metadata from the [keys] table, keyed by api_key_ref.
Source code in src/llmbroker/standalone/registry.py
77 78 79 80 81 82 | |
key_info_from_entry(ref, raw)
Parse one [keys.REF] entry; a bare string is the help-only form.
Source code in src/llmbroker/standalone/registry.py
28 29 30 31 32 33 34 35 36 37 38 39 40 | |
secrets
Env-var and in-memory secrets resolvers — read-only, no external backend.
Secrets() resolves api_key_ref from os.environ; DictSecrets
from a mapping. Both are read-only. A plain callable is accepted and adapted.
DictSecrets
Read-only secrets resolver backed by an in-memory mapping (tests / preloaded keys).
Source code in src/llmbroker/standalone/secrets.py
25 26 27 28 29 30 31 32 33 34 | |
Secrets
Read-only env-backed secrets resolver (the default battery).
Source code in src/llmbroker/standalone/secrets.py
15 16 17 18 19 20 21 22 | |
as_secrets(secrets)
Return a SecretsProtocol, wrapping a bare callable if needed.
Source code in src/llmbroker/standalone/secrets.py
50 51 52 53 54 55 56 57 58 | |
store
File-backed and in-memory stores — no external backend.
InMemoryStore() implements only the minimal contract and keeps its
disabled-verdict map in process memory (session-scoped learning). It is
llmbroker's internal subsystem, not application logging — a host that wants
logs uses logging itself.
FileStore(directory) is the default persistent store: a day-split
JSON-lines call journal (<directory>/calls/YYYY-MM-DD.jsonl, chosen by
each record's UTC date — pure storage layout, not aggregation, since rebuild
needs raw per-record scores and a quality record can rate a call from an
earlier day) plus a YAML admin disabled-verdict map
(<directory>/disabled.yml, meant for hand-editing). It self-purges call
records older than retention by unlinking whole expired day files — no
rewrite, no race with concurrent appends — checked at most once per hour on
write activity. The disabled map is never purged.
FileStore
Day-split JSONL call journal plus a YAML disabled-verdict map, under one directory.
Source code in src/llmbroker/standalone/store.py
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | |
calls(*, limit, scope=None)
async
Newest-first tail of the journal, both kinds interleaved — unfiltered by scope
(learning is global); scope is accepted for the host-facing filter only.
Source code in src/llmbroker/standalone/store.py
179 180 181 182 | |
InMemoryStore
Explicit in-memory opt-out — no persistence, session-scoped learning; disabled verdicts live only in process memory.
Source code in src/llmbroker/standalone/store.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
sync
Synchronous Broker / LLM / Result — blocking proxies over AsyncBroker.
Broker runs an AsyncBroker on a dedicated background event-loop thread;
its blocking methods submit coroutines to that loop and wait. The pool's
concurrency persists across calls.
Broker
Synchronous client over an AsyncBroker on a background loop thread.
Source code in src/llmbroker/sync.py
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | |
LLM
Synchronous analogue of AsyncLLM.
Source code in src/llmbroker/sync.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
Result
Synchronous analogue of AsyncResult.
Source code in src/llmbroker/sync.py
43 44 45 46 47 48 49 50 51 52 53 54 | |
vault
HashiCorp Vault backend for llmbroker.
Needs the hvac client (llmbroker[vault]); importing this package is
how a host declares that dependency, so a bare import llmbroker stays
driver-free. Uses KV v2.
Secrets
HashiCorp Vault KV v2-backed mutable secrets store.
hvac is sync-only; all calls run inside asyncio.to_thread.
aclose is a no-op.
Source code in src/llmbroker/vault/secrets.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | |
secrets
HashiCorp Vault KV v2-backed mutable secrets store.
Secrets
HashiCorp Vault KV v2-backed mutable secrets store.
hvac is sync-only; all calls run inside asyncio.to_thread.
aclose is a no-op.
Source code in src/llmbroker/vault/secrets.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | |