rustev_contract/
output.rs1use std::collections::BTreeMap;
5
6use serde::{Deserialize, Serialize};
7
8use crate::ids::ArtifactId;
9use crate::limits::BACKEND_OUTPUT_V1;
10use crate::schema;
11
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
13#[serde(deny_unknown_fields)]
14pub struct BackendOutputDoc {
15 pub schema: String,
16 pub step: String,
17 pub instance: Vec<String>,
18 pub artifact: ArtifactId,
20 pub output: RawOutput,
21}
22
23crate::document::document!(BackendOutputDoc, schema::BACKEND_OUTPUT, BACKEND_OUTPUT_V1);
24
25#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
27#[serde(rename_all = "snake_case", deny_unknown_fields)]
28pub enum RawOutput {
29 Label(String),
30 Distribution(BTreeMap<String, f64>),
31 Logits(BTreeMap<String, f64>),
32 Scores(BTreeMap<String, f64>),
33 Screen {
34 blocked: bool,
35 categories: Vec<String>,
36 units: ScreenUnits,
37 },
38 TextRecord(BTreeMap<String, TextValue>),
39 TypedRecord {
40 fields: BTreeMap<String, serde_json::Value>,
41 logprobs: Vec<FieldLogprobs>,
42 #[serde(deserialize_with = "provider_reported")]
43 provider_reported: BTreeMap<String, String>,
44 },
45}
46
47#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
49#[serde(rename_all = "snake_case", deny_unknown_fields)]
50pub enum ScreenUnits {
51 Reported { n: u64 },
52 NotReported,
53}
54
55#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
57#[serde(rename_all = "snake_case", deny_unknown_fields)]
58pub enum TextValue {
59 Text(String),
60 List(Vec<String>),
61}
62
63#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
65#[serde(deny_unknown_fields)]
66pub struct FieldLogprobs {
67 pub field: String,
68 pub item: LogprobItem,
69 #[serde(deserialize_with = "finite_logprobs")]
70 pub values: BTreeMap<String, f64>,
71}
72
73#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
74#[serde(rename_all = "snake_case")]
75pub enum LogprobItem {
76 None,
77 #[serde(untagged)]
79 Index(u64),
80}
81
82fn finite_logprobs<'de, D: serde::Deserializer<'de>>(
83 d: D,
84) -> Result<BTreeMap<String, f64>, D::Error> {
85 let v = BTreeMap::<String, f64>::deserialize(d)?;
86 if v.values().any(|n| !n.is_finite()) {
87 return Err(serde::de::Error::custom("non-finite extraction logprob"));
88 }
89 Ok(v)
90}
91
92fn provider_reported<'de, D: serde::Deserializer<'de>>(
93 d: D,
94) -> Result<BTreeMap<String, String>, D::Error> {
95 let v = BTreeMap::<String, String>::deserialize(d)?;
96 if v.values().any(|s| s.len() > 256) {
97 return Err(serde::de::Error::custom(
98 "provider_reported exceeds 256 bytes",
99 ));
100 }
101 Ok(v)
102}