| """Provider-prefixed model reference helpers.""" |
|
|
| from dataclasses import dataclass |
| from typing import Protocol |
|
|
|
|
| @dataclass(frozen=True, slots=True) |
| class ConfiguredChatModelRef: |
| """A unique configured chat model reference.""" |
|
|
| model_ref: str |
| provider_id: str |
| model_id: str |
|
|
|
|
| class ChatModelConfig(Protocol): |
| model: str |
| model_fable: str | None |
| model_opus: str | None |
| model_sonnet: str | None |
| model_haiku: str | None |
|
|
|
|
| def parse_provider_type(model_ref: str) -> str: |
| """Extract provider type from any 'provider/model' string.""" |
|
|
| return model_ref.split("/", 1)[0] |
|
|
|
|
| def parse_model_name(model_ref: str) -> str: |
| """Extract model name from any 'provider/model' string. |
| |
| Bare ids (no provider prefix) are returned whole; the prefix is optional |
| and such ids resolve to the OpenAI-compatible endpoint that advertises them. |
| """ |
|
|
| return model_ref.split("/", 1)[1] if "/" in model_ref else model_ref |
|
|
|
|
| def configured_chat_model_refs( |
| settings: ChatModelConfig, |
| ) -> tuple[ConfiguredChatModelRef, ...]: |
| """Return unique configured chat provider/model refs.""" |
|
|
| model_refs = dict.fromkeys( |
| model_ref |
| for model_ref in ( |
| settings.model, |
| settings.model_fable, |
| settings.model_opus, |
| settings.model_sonnet, |
| settings.model_haiku, |
| ) |
| if model_ref is not None |
| ) |
|
|
| return tuple( |
| ConfiguredChatModelRef( |
| model_ref=model_ref, |
| provider_id=parse_provider_type(model_ref), |
| model_id=parse_model_name(model_ref), |
| ) |
| for model_ref in model_refs |
| ) |
|
|