cadrumo.core.model_catalogue module¶
The typed local-model catalogue: what may be selected, and under whose licence.
One home for a fact that was previously invisible. Before this module the model
identifiers lived as bare string defaults on
Settings with their trade-offs described in field
docstrings, and the licence axis was described nowhere at all – so the shipped
vision default was a research-licensed model that bars commercial use, inside a
commercial tax product, with nothing in the tree that could have said so.
Three declarations per candidate carry the weight:
memory_requirement_bytesThe publisher’s stated weight size, the figure
assess_model_load_contention()compares against measured free headroom. It is the requirement BEFORE the configured safety margin, never after – the margin is deployment policy and lives onSettings.max_context_tokensThe capability floor, and the reason selection is bounded from BELOW. The document read sends the registry allow-list prompt plus an encoded page, so a model whose window cannot hold
cadrumo_llm_ollama_num_ctxis not a cheaper option – it is an unusable one, and it must be excluded on capability rather than ranked below on quality.ModelLicenceAn SPDX identifier plus an EXPLICIT
commercial_use_permittedflag, each verified against the publisher’s own text at authoring and carrying the quote and URL that were read. An unverified licence is a refusal input, not a permissive default:ModelLicencerefuses to be constructed as commercially usable without a verification source, so the failure direction of a future hand-edit is a build error rather than a silent legal claim.
This is deployment configuration, not registry data – it encodes no tax
semantics – so it lives in core/ beside the
Settings fields it supplies defaults to, and the
selection logic that consumes it lives in the application layer at
select_model_for_role().
See also
AcceleratorKindThe measured-hardware axis selection filters candidates against.
HardwareProfileThe measured profile whose free figures decide whether a candidate fits.
- class ModelRole(*values)[source]¶
Bases:
StrEnumThe distinct jobs a local model is selected for.
Kept as roles rather than as one “the local model” axis because the capability bars differ, and they differ in BOTH directions: only vision transcription needs image input, and the two text roles must be satisfiable on a machine that cannot host a vision model at all. Each role resolves independently through
select_model_for_role().The two text roles are not one role. Column-role mapping is strictly easier than text extraction – a selection over a short closed vocabulary given a handful of short header strings, against reading a whole document’s text layer – so it is kept separate precisely so it can be sized DOWN independently rather than inheriting the harder role’s model.
VISION_TRANSCRIPTIONreads a scanned or photographed page;TEXT_EXTRACTIONclassifies an already-extracted text layer;COLUMN_ROLE_MAPPINGnames the columns of a delimited table from their header strings; andSUPPLY_NATURE_PROPOSALproposes whether invoice lines supply goods or services for an operator to confirm.- VISION_TRANSCRIPTION¶
- TEXT_EXTRACTION¶
- COLUMN_ROLE_MAPPING¶
- SUPPLY_NATURE_PROPOSAL¶
- class ModelRuntime(*values)[source]¶
Bases:
StrEnumWhere a candidate’s weights actually run, which changes what may be judged.
The axis exists because two of the catalogue’s bars are meaningless off-host. A hosted model has no local memory requirement to compare against measured free headroom, and no weights to pull; what it has instead is a service contract. Collapsing the two runtimes into one list would force every consumer to special-case that, and would let a cloud model be ranked by a memory figure it does not have.
The capability and licence bars still apply to both: the prompt is the same size wherever it runs, and “may we use this commercially” is the same question whether the answer comes from a weights licence or a terms of service.
Members:
LOCAL_OLLAMA: Weights pulled and run on the operator’s own machine. CLOUD_ANTHROPIC: A hosted Anthropic API model; nothing runs on-host.
- LOCAL_OLLAMA¶
- CLOUD_ANTHROPIC¶
- class LicenceVerification(*values)[source]¶
Bases:
StrEnumHow a catalogue entry’s licence claim was checked, and against what.
Recorded because the claim’s provenance is the part that can rot. An SPDX identifier written from recall reads identically to one read off the publisher’s licence file, and only one of the two survives a lawyer. The member names the artefact that was actually read.
PUBLISHER_LICENCE_FILEmeans the publisher’s LICENSE text was read;PUBLISHER_MODEL_CARDmeans its model-card licence field was read;PUBLISHER_SERVICE_TERMSmeans its service terms were read; andUNVERIFIEDmeans no publisher text was read and therefore bars a commercial-use claim (seeModelLicence).- PUBLISHER_LICENCE_FILE¶
- PUBLISHER_MODEL_CARD¶
- PUBLISHER_SERVICE_TERMS¶
- UNVERIFIED¶
- class DeploymentLicencePosture(*values)[source]¶
Bases:
StrEnumWhether this deployment needs a licence that permits commercial use.
COMMERCIALis the product’s posture: Cadrumo is a commercial tax product and a gestor filing for clients is unambiguously commercial use.NON_COMMERCIALexists so an individual filing their own return, or a research evaluation, is not refused a candidate whose licence genuinely covers them – the posture is a fact about the deployment, and encoding it as one is what keeps the commercial default honest rather than merely strict.Members:
COMMERCIAL: Only candidates whose licence permits commercial use. NON_COMMERCIAL: Research-licensed candidates are additionally eligible.
- COMMERCIAL¶
- NON_COMMERCIAL¶
- class ModelSelectionAdvisory(*values)[source]¶
Bases:
StrEnumWhy a resolved selection is worth telling the operator about.
Selection never fails silently and an override is never honoured silently. Each member keys one operator-visible statement, so a caller renders the reason rather than re-deriving it from the selection’s shape.
Members:
- LICENCE_COMMERCIAL_USE_BARRED: The selected model’s licence bars
commercial use under the active posture. Only reachable through an explicit override; automatic selection excludes such candidates.
- LICENCE_UNVERIFIED: No publisher licence text backs the selected model,
so no licence claim can be made about it at all.
- OVERRIDE_NOT_IN_CATALOGUE: The operator named a model the catalogue does
not describe, so neither its licence nor its fit could be judged.
- OVERRIDE_BELOW_CONTEXT_FLOOR: The selected model’s context window is
smaller than the configured request window.
- FIT_EXCEEDS_MEASURED_HEADROOM: The selected model’s requirement plus the
safety margin exceeds measured free memory.
- FIT_UNVERIFIED: Free memory could not be measured, so fit was not
checked here. The load itself still fails closed at
assess_model_load_contention().
- LICENCE_COMMERCIAL_USE_BARRED¶
- LICENCE_UNVERIFIED¶
- OVERRIDE_NOT_IN_CATALOGUE¶
- OVERRIDE_BELOW_CONTEXT_FLOOR¶
- FIT_EXCEEDS_MEASURED_HEADROOM¶
- FIT_UNVERIFIED¶
- class ModelLicence(**data)[source]¶
Bases:
BaseModelOne model’s licence, its commercial-use consequence, and the text that proves it.
commercial_use_permittedis declared explicitly rather than derived fromspdx_idbecause the derivation is exactly the step that goes wrong: a reader who knows Apache-2.0 permits commercial use will assume a publisher-specificLicenseRef-*does too, and one of this catalogue’s entries is a licence whose text says “FOR NON-COMMERCIAL PURPOSES ONLY”.verified_quoteandsource_urlare required whenever a verification source is claimed, so the claim can be re-checked by opening one URL. The validator enforces the asymmetry that matters: anUNVERIFIEDlicence may not assert commercial use. Unverified is a refusal input, never a permissive default.- Parameters:
- spdx_id: str¶
- name: str¶
- commercial_use_permitted: bool¶
- verification: LicenceVerification¶
- source_url: OptionalSourceUrl¶
- verified_quote: str¶
- class ModelCandidate(**data)[source]¶
Bases:
BaseModelOne selectable local model: what it costs, what it can hold, and its licence.
rolesis a set because a vision-capable model serves both the transcription and the tabular-mapping roles from one pulled copy, and duplicating the row per role would let the two descriptions of the same weights drift.measured_baseline_refnames the corpus measurement that justifies this candidate’s place in the ordering, or is empty where none has been run yet. Empty is the honest state for most of this catalogue today and must stay distinguishable from a measured zero – a candidate carrying no baseline is selected on its declared capability bars alone.- Parameters:
runtime_id (str)
runtime (ModelRuntime)
memory_requirement_bytes (int | None)
input_price_per_mtok_usd (Decimal | None)
max_context_tokens (int)
licence (ModelLicence)
measured_baseline_ref (str)
notes (str)
- runtime_id: str¶
- runtime: ModelRuntime¶
- roles: frozenset[ModelRole]¶
- memory_requirement_bytes: int | None¶
- input_price_per_mtok_usd: Decimal | None¶
- max_context_tokens: int¶
- licence: ModelLicence¶
- measured_baseline_ref: str¶
- notes: str¶
- property selection_rank: Decimal¶
Return the ascending ‘weakest first’ key for this candidate’s runtime.
Memory bytes on-host, published input price off-host. Comparable only within one runtime, which is why
candidates_for_role()is scoped to one.
- permitted_under(posture)[source]¶
Return whether this candidate’s licence permits
posture.A non-commercial posture accepts every catalogued licence; a commercial posture accepts only those whose publisher text was read AND permits commercial use.
- Return type:
- Parameters:
posture (DeploymentLicencePosture)
- APACHE_2_0: Final¶
Apache-2.0 as declared on the publishers’ own model cards.
Read from the
license:frontmatter field of each covered model’s card at authoring;source_urlnames one of them and the remainder are recorded on each candidate’snotes. Apache-2.0 is an SPDX-listed permissive licence whose grant is explicitly commercial-capable.
- QWEN_RESEARCH: Final¶
The Qwen Research licence, whose text bars commercial use outright.
Not an SPDX-listed licence, so it carries an SPDX
LicenseRef-identifier rather than a fabricated listed one. The publisher’s licence file adds “If you are commercially using the Materials, you shall request a license from us”, which is what makes a barred candidate reachable only through an explicit, advised operator override rather than through automatic selection.
- ANTHROPIC_COMMERCIAL_TERMS: Final¶
The service contract a hosted Anthropic model is used under.
Not a weights licence – there are no weights to license – so it carries an SPDX
LicenseRef-identifier and is verified against the publisher’s terms of service rather than a LICENSE file. The same terms assign output ownership to the customer, which is what makes a hosted read usable in a filing-grade product at all.Reading it as a licence keeps ONE gate over both runtimes: “may we use this commercially” has to be answered for a hosted model exactly as for a local one, and a second, parallel notion of permission is how one of the two answers goes unchecked.
- DEFAULT_MODEL_BY_RUNTIME_AND_ROLE: Final[Mapping[ModelRuntime, Mapping[ModelRole, str]]]¶
Every shipped default, keyed by runtime then role – the source of the settings defaults.
Keyed by runtime as well as role because the two runtimes are configured separately and a role’s answer differs between them. Declared here rather than as literals on
Settingsso the licence gate has ONE place to read every shipped default from, across both runtimes, and so a default cannot name a model the catalogue does not describe.That completeness is the point. A per-role gate that only knew about local defaults would have passed while every cloud route fell through to a frontier-tier model, which is exactly the state this mapping was added to correct.
- candidates_for_role(role, runtime=ModelRuntime.LOCAL_OLLAMA)[source]¶
Return every candidate serving
roleonruntime, weakest first.Scoped to one runtime because the ordering is only meaningful within one: ascending declared memory requirement ranks local candidates, and a hosted candidate has no such figure to be ranked by. Mixing them would sort a cloud model against a number it does not have.
Within a runtime the order IS the selection order: the design point is the weakest model that clears the capability bars, never the strongest the hardware or the budget could reach. A caller that wants a larger model names it as an override.
- Return type:
- Parameters:
role (ModelRole)
runtime (ModelRuntime)
- model_candidate(runtime_id)[source]¶
Return the catalogued candidate with
runtime_id, orNone.Nonemeans “this catalogue makes no claim about that model”, which is distinct from a claim that it is unlicensed – an operator naming an uncatalogued model is advised, not refused.- Return type:
- Parameters:
runtime_id (str)
- default_model_runtime_id(role, runtime=ModelRuntime.LOCAL_OLLAMA)[source]¶
Return the shipped default runtime id for
roleonruntime.Supplies the
Settingsfield defaults for both runtimes, so the settings surface and the licence gate read one value.- Return type:
- Parameters:
role (ModelRole)
runtime (ModelRuntime)