1use crate::ids::{ArtifactId, DescriptorId, PlanId};
3use crate::judgment::{Derivation, Lineage, Unresolved};
4use crate::ranking::{Bias, RankMode, TieBreak};
5use serde::{Deserialize, Deserializer, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
8#[serde(deny_unknown_fields)]
9pub struct RankBinding {
10 pub backend_id: String,
11 pub artifact: ArtifactId,
12 pub descriptor: DescriptorId,
13 pub mode: RankMode,
14 pub bias: Bias,
15 pub generator: PermutationGenerator,
16 pub tie_break: TieBreak,
17 #[serde(deserialize_with = "crate::ranking::bound::<_, 0, 1024>")]
18 #[schemars(range(min = 0, max = 1024))]
19 pub pool_bound: u64,
20 pub max_requests: u64,
21}
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
23pub enum PermutationGenerator {
24 #[serde(rename = "rustev.permute/1")]
25 V1,
26}
27
28#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
30#[serde(deny_unknown_fields)]
31pub struct RankingScore {
32 pub candidate: String,
33 pub plan: PlanId,
34 pub step: String,
35 pub instance: Vec<String>,
36 #[serde(deserialize_with = "finite")]
37 pub value: f64,
38}
39#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
40#[serde(deny_unknown_fields)]
41pub struct ModelRanking {
42 pub mode: RankMode,
43 #[serde(deserialize_with = "list::<_, _, 1024>")]
44 #[schemars(length(max = 1024))]
45 pub pool: Vec<String>,
46 #[serde(deserialize_with = "list::<_, _, 1024>")]
47 #[schemars(length(max = 1024))]
48 pub entries: Vec<ModelRankEntry>,
49 #[serde(deserialize_with = "list::<_, _, 1024>")]
50 #[schemars(length(max = 1024))]
51 pub unranked: Vec<String>,
52 #[serde(deserialize_with = "list::<_, _, 8192>")]
56 #[schemars(length(max = 8192))]
57 pub dropped: Vec<DroppedId>,
58 pub partial: bool,
59 pub score_disagreements: u64,
60 pub pairwise: Option<PairwiseCounts>,
61}
62#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
63#[serde(deny_unknown_fields)]
64pub struct ModelRankEntry {
65 pub candidate: String,
66 #[serde(deserialize_with = "crate::ranking::bound::<_, 1, 1024>")]
67 #[schemars(range(min = 1, max = 1024))]
68 pub position: u64,
69 pub score: Option<RankingScore>,
70 pub wins: Option<u64>,
71 pub points: Option<u64>,
72}
73#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
74#[serde(deny_unknown_fields)]
75pub struct DroppedId {
76 pub id: String,
77 pub reason: DropReason,
78}
79#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
80#[serde(rename_all = "snake_case", deny_unknown_fields)]
81pub enum DropReason {
82 UnknownId,
83 OutsidePool,
84 Duplicate,
85 Failed { reason: Unresolved },
86}
87#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
88#[serde(deny_unknown_fields)]
89pub struct PairwiseCounts {
90 #[serde(deserialize_with = "crate::ranking::bound::<_, 0, 4096>")]
91 #[schemars(range(min = 0, max = 4096))]
92 pub issued: u64,
93 #[serde(deserialize_with = "crate::ranking::bound::<_, 1, 4096>")]
94 #[schemars(range(min = 1, max = 4096))]
95 pub max_comparisons: u64,
96 pub cyclic_triples: CycleCount,
97 pub inconsistent_pairs: u64,
98}
99#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
100#[serde(rename_all = "snake_case", deny_unknown_fields)]
101pub enum CycleCount {
102 NotObservable,
103 #[serde(untagged)]
108 Count(u64),
109}
110#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
111#[serde(deny_unknown_fields)]
112pub struct Selection {
113 #[serde(deserialize_with = "crate::ranking::bound::<_, 1, 1024>")]
114 #[schemars(range(min = 1, max = 1024))]
115 pub k: u64,
116 #[serde(deserialize_with = "list::<_, _, 1024>")]
117 #[schemars(length(max = 1024))]
118 pub entries: Vec<SelectionEntry>,
119 pub shortfall: u64,
120 pub model: SelectionModel,
121 pub backfill: SelectionBackfill,
122}
123#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
124#[serde(deny_unknown_fields)]
125pub struct SelectionEntry {
126 #[serde(deserialize_with = "crate::ranking::bound::<_, 1, 1024>")]
127 #[schemars(range(min = 1, max = 1024))]
128 pub position: u64,
129 pub id: String,
130 pub origin: SelectionOrigin,
131 #[serde(deserialize_with = "crate::ranking::bound::<_, 1, {u64::MAX}>")]
132 #[schemars(range(min = 1))]
133 pub source_position: u64,
134 pub derivation: Derivation,
135 pub lineage: Lineage,
137}
138#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
139#[serde(rename_all = "snake_case")]
140pub enum SelectionOrigin {
141 Model,
142 Backfill,
143}
144#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
145#[serde(rename_all = "snake_case", deny_unknown_fields)]
146pub enum SelectionModel {
147 Ranked { entries: u64, partial: bool },
148 Failed { reason: Unresolved },
149}
150#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
151#[serde(rename_all = "snake_case", deny_unknown_fields)]
152pub enum SelectionBackfill {
153 None,
154 NotNeeded,
155 Used {
156 taken: u64,
157 skipped_selected: u64,
158 skipped_outside_pool: u64,
159 },
160 Unresolved {
161 reason: Unresolved,
162 },
163}
164
165#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
166#[serde(deny_unknown_fields)]
167pub struct RankingEvidence {
168 pub ranking: Option<ModelRanking>,
170 #[serde(deserialize_with = "list::<_, _, 4096>")]
172 #[schemars(length(max = 4096))]
173 pub requests: Vec<RankingRequestEvidence>,
174 #[serde(deserialize_with = "list::<_, _, 4096>")]
176 #[schemars(length(max = 4096))]
177 pub comparisons: Vec<ComparisonAnswer>,
178}
179#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
180#[serde(deny_unknown_fields)]
181pub struct RankingRequestEvidence {
182 #[serde(deserialize_with = "list::<_, _, 1024>")]
183 #[schemars(length(max = 1024))]
184 pub presented: Vec<String>,
185 #[serde(deserialize_with = "list::<_, _, 1024>")]
186 #[schemars(length(max = 1024))]
187 pub scores: Vec<RankingScore>,
188}
189#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
190#[serde(rename_all = "snake_case", deny_unknown_fields)]
191pub enum ComparisonAnswer {
192 First,
193 Second,
194 Failed { reason: Unresolved },
195}
196
197pub(crate) fn list<'de, D: Deserializer<'de>, T: Deserialize<'de>, const MAX: usize>(
198 d: D,
199) -> Result<Vec<T>, D::Error> {
200 let v = Vec::<T>::deserialize(d)?;
201 if v.len() > MAX {
202 return Err(serde::de::Error::custom("ranking evidence bound exceeded"));
203 }
204 Ok(v)
205}
206pub(crate) fn finite<'de, D: Deserializer<'de>>(d: D) -> Result<f64, D::Error> {
207 let v = f64::deserialize(d)?;
208 if !v.is_finite() {
209 return Err(serde::de::Error::custom("ranking score must be finite"));
210 }
211 Ok(v)
212}