Skip to main content

rig_core/catalog/
details.rs

1//! What models.dev records about a model beyond the facts requests are
2//! checked against, under its own field names.
3
4use std::collections::BTreeMap;
5
6use serde::{Deserialize, Serialize};
7
8use super::spec::Modalities;
9
10/// What models.dev records about a model that rig does not act on: its
11/// description, lifecycle dates, extra prices, request overrides and
12/// service modes. Each field is `None` or empty when the row does not say.
13#[non_exhaustive]
14#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
15#[serde(default)]
16pub struct ModelDetails {
17    /// What the model is for, in a sentence.
18    pub description: Option<String>,
19    /// The family it belongs to, such as `gemini`.
20    pub family: Option<String>,
21    /// A specialized kind, models.dev's `type`, such as `image` or
22    /// `embedding`; `None` for a chat model.
23    #[serde(rename = "type")]
24    pub kind: Option<String>,
25    /// The `vendor/model` this row serves, when it is another vendor's.
26    pub canonical_model_id: Option<String>,
27    /// Whether it takes file attachments.
28    pub attachment: Option<bool>,
29    /// Whether, and under which field, it takes reasoning interleaved with
30    /// its messages.
31    pub interleaved: Option<Interleaved>,
32    /// What it writes, models.dev's `modalities.output`.
33    pub output: Option<Modalities>,
34    /// Its knowledge cutoff, `YYYY-MM` or `YYYY-MM-DD`.
35    pub knowledge: Option<String>,
36    /// When it was first released, `YYYY-MM` or `YYYY-MM-DD`.
37    pub release_date: Option<String>,
38    /// When it last changed, `YYYY-MM` or `YYYY-MM-DD`.
39    pub last_updated: Option<String>,
40    /// Whether its weights are public.
41    pub open_weights: Option<bool>,
42    /// Its lifecycle status as listed: `alpha`, `beta` or `deprecated`.
43    pub status: Option<String>,
44    /// Prices beyond [`Pricing`](super::Pricing), in USD per million tokens.
45    pub cost: CostDetails,
46    /// How a request reaches it, when that differs from its vendor's.
47    pub provider: Option<ProviderOverride>,
48    /// The service modes it is offered in, such as `fast` or `priority`, by
49    /// name: models.dev's `experimental.modes`.
50    pub modes: BTreeMap<String, Mode>,
51}
52
53/// Interleaved reasoning support: `true` in general, or the message field
54/// it is carried in, such as `reasoning_content`.
55#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
56#[serde(untagged)]
57pub enum Interleaved {
58    /// Supported, or not, with no field named.
59    Supported(bool),
60    /// Supported under this message field.
61    Field {
62        /// The field's name.
63        field: String,
64    },
65}
66
67/// Prices beyond the base [`Pricing`](super::Pricing).
68#[non_exhaustive]
69#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
70#[serde(default)]
71pub struct CostDetails {
72    /// Reasoning tokens, when billed apart from output.
73    pub reasoning: Option<f64>,
74    /// Audio input tokens, when billed apart.
75    pub input_audio: Option<f64>,
76    /// Audio output tokens, when billed apart.
77    pub output_audio: Option<f64>,
78    /// Prices that apply past a size of request.
79    pub tiers: Vec<CostTier>,
80    /// Prices for a request of more than 200k tokens.
81    pub context_over_200k: Option<Rates>,
82}
83
84/// One set of prices in USD per million tokens; each `None` when not
85/// listed.
86#[non_exhaustive]
87#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
88#[serde(default)]
89pub struct Rates {
90    /// Uncached input.
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub input: Option<f64>,
93    /// Output.
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub output: Option<f64>,
96    /// Input read from the cache.
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub cache_read: Option<f64>,
99    /// Input written to the cache.
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub cache_write: Option<f64>,
102    /// Reasoning tokens.
103    #[serde(skip_serializing_if = "Option::is_none")]
104    pub reasoning: Option<f64>,
105    /// Audio input tokens.
106    #[serde(skip_serializing_if = "Option::is_none")]
107    pub input_audio: Option<f64>,
108    /// Audio output tokens.
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pub output_audio: Option<f64>,
111}
112
113/// Prices that apply to a request past the size its [`Tier`] names.
114#[non_exhaustive]
115#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
116pub struct CostTier {
117    /// The prices.
118    #[serde(flatten)]
119    pub rates: Rates,
120    /// Where they start.
121    pub tier: Tier,
122}
123
124/// Where a [`CostTier`] starts: past `size` of what `kind` measures.
125#[non_exhaustive]
126#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
127pub struct Tier {
128    /// What is measured, such as `context`.
129    #[serde(rename = "type")]
130    pub kind: String,
131    /// The size, in tokens.
132    pub size: u64,
133}
134
135/// How a request reaches a model, or runs in a mode, where that differs
136/// from its vendor's: models.dev's per-model `provider`.
137#[non_exhaustive]
138#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
139#[serde(default)]
140pub struct ProviderOverride {
141    /// The AI SDK package that reaches it.
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub npm: Option<String>,
144    /// The API base URL, which may name environment variables as
145    /// `${NAME}`.
146    #[serde(skip_serializing_if = "Option::is_none")]
147    pub api: Option<String>,
148    /// The API shape, such as `responses`.
149    #[serde(skip_serializing_if = "Option::is_none")]
150    pub shape: Option<String>,
151    /// Fields added to the request body.
152    #[serde(skip_serializing_if = "Option::is_none")]
153    pub body: Option<serde_json::Value>,
154    /// Headers added to the request.
155    #[serde(skip_serializing_if = "BTreeMap::is_empty")]
156    pub headers: BTreeMap<String, String>,
157}
158
159/// A service mode a model is offered in.
160#[non_exhaustive]
161#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
162#[serde(default)]
163pub struct Mode {
164    /// Its prices, when they differ.
165    #[serde(skip_serializing_if = "Option::is_none")]
166    pub cost: Option<Rates>,
167    /// What a request in it changes.
168    #[serde(skip_serializing_if = "Option::is_none")]
169    pub provider: Option<ProviderOverride>,
170}