1#![allow(
6 missing_docs,
7 reason = "fields mirror pi's TypeScript types; contracts are noted where they differ from the name"
8)]
9
10use indexmap::IndexMap;
11use serde::{Deserialize, Serialize};
12use serde_json::{Map, Value};
13
14use crate::message::{ImageContent, TextContent, Usage};
15
16#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
18pub struct BoolCriteria {
19 #[serde(rename = "true")]
20 pub yes: String,
21 #[serde(rename = "false")]
22 pub no: String,
23}
24
25#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
27#[serde(tag = "type", rename_all = "lowercase")]
28pub enum ClassifierQuestion {
29 Choice {
31 instructions: String,
32 criteria: IndexMap<String, String>,
33 },
34 Score {
36 instructions: String,
37 criteria: Vec<String>,
38 },
39 Bool {
41 instructions: String,
42 criteria: BoolCriteria,
43 },
44}
45
46impl ClassifierQuestion {
47 pub fn instructions(&self) -> &str {
49 match self {
50 ClassifierQuestion::Choice { instructions, .. }
51 | ClassifierQuestion::Score { instructions, .. }
52 | ClassifierQuestion::Bool { instructions, .. } => instructions,
53 }
54 }
55}
56
57#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
59pub struct ClassifierContext {
60 pub state: Map<String, Value>,
61 pub questions: IndexMap<String, ClassifierQuestion>,
62}
63
64#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
66#[serde(tag = "type", rename_all = "lowercase")]
67pub enum ClassifierAnswer {
68 Choice {
69 choice: String,
70 probabilities: IndexMap<String, f64>,
71 confidence: f64,
72 },
73 Score {
74 score: f64,
75 confidence: f64,
76 },
77 Bool {
78 probability: f64,
79 },
80}
81
82#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
84#[serde(rename_all = "lowercase")]
85pub enum OutcomeReason {
86 Stop,
87 Error,
88 Aborted,
89}
90
91#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
93#[serde(rename_all = "camelCase")]
94pub struct ClassifierResult {
95 pub api: String,
96 pub provider: String,
97 pub model: String,
98 pub answers: IndexMap<String, ClassifierAnswer>,
99 #[serde(default, skip_serializing_if = "Option::is_none")]
101 pub usage: Option<Usage>,
102 pub stop_reason: OutcomeReason,
103 #[serde(default, skip_serializing_if = "Option::is_none")]
104 pub error_message: Option<String>,
105 pub timestamp: u64,
106}
107
108#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
110#[serde(tag = "type", rename_all = "lowercase")]
111pub enum ImagesContent {
112 Text(TextContent),
113 Image(ImageContent),
114}
115
116#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
118pub struct ImagesContext {
119 pub input: Vec<ImagesContent>,
120}
121
122#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
124#[serde(rename_all = "camelCase")]
125pub struct AssistantImages {
126 pub api: String,
127 pub provider: String,
128 pub model: String,
129 pub output: Vec<ImagesContent>,
130 #[serde(default, skip_serializing_if = "Option::is_none")]
131 pub response_id: Option<String>,
132 #[serde(default, skip_serializing_if = "Option::is_none")]
133 pub usage: Option<Usage>,
134 pub stop_reason: OutcomeReason,
135 #[serde(default, skip_serializing_if = "Option::is_none")]
136 pub error_message: Option<String>,
137 pub timestamp: u64,
138}