Skip to main content

synth_ai_core/data/
enums.rs

1//! Core enumeration types for the Synth SDK.
2//!
3//! These enums match the Python SDK's `synth_ai/data/enums.py`.
4
5use serde::{Deserialize, Serialize};
6
7/// Type of optimization/training job.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9#[serde(rename_all = "snake_case")]
10pub enum JobType {
11    PromptLearning,
12    Sft,
13    Rl,
14    Gspo,
15    Eval,
16    ResearchAgent,
17    Inference,
18}
19
20impl Default for JobType {
21    fn default() -> Self {
22        Self::PromptLearning
23    }
24}
25
26/// Status of a job.
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
28#[serde(rename_all = "snake_case")]
29pub enum JobStatus {
30    Pending,
31    Queued,
32    Running,
33    Paused,
34    Succeeded,
35    Failed,
36    Cancelled,
37}
38
39impl JobStatus {
40    /// Returns true if the job is in a terminal state.
41    pub fn is_terminal(&self) -> bool {
42        matches!(self, Self::Succeeded | Self::Failed | Self::Cancelled)
43    }
44
45    /// Returns true if the job completed successfully.
46    pub fn is_success(&self) -> bool {
47        matches!(self, Self::Succeeded)
48    }
49}
50
51impl Default for JobStatus {
52    fn default() -> Self {
53        Self::Pending
54    }
55}
56
57/// LLM provider name.
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
59#[serde(rename_all = "snake_case")]
60pub enum ProviderName {
61    Openai,
62    Groq,
63    Google,
64    Anthropic,
65    Together,
66    Fireworks,
67    Bedrock,
68    Azure,
69}
70
71impl Default for ProviderName {
72    fn default() -> Self {
73        Self::Openai
74    }
75}
76
77/// Inference mode for model calls.
78#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
79#[serde(rename_all = "snake_case")]
80pub enum InferenceMode {
81    Standard,
82    Batched,
83    Streaming,
84    SynthHosted,
85}
86
87impl Default for InferenceMode {
88    fn default() -> Self {
89        Self::Standard
90    }
91}
92
93/// Source of reward signal.
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
95#[serde(rename_all = "snake_case")]
96pub enum RewardSource {
97    TaskApp,
98    Verifier,
99    Fused,
100    Environment,
101    Runner,
102    Evaluator,
103    Human,
104}
105
106impl Default for RewardSource {
107    fn default() -> Self {
108        Self::TaskApp
109    }
110}
111
112/// Type of reward signal.
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
114#[serde(rename_all = "snake_case")]
115pub enum RewardType {
116    Shaped,
117    Sparse,
118    Penalty,
119    Evaluator,
120    Human,
121    Achievement,
122    AchievementDelta,
123    UniqueAchievementDelta,
124}
125
126impl Default for RewardType {
127    fn default() -> Self {
128        Self::Sparse
129    }
130}
131
132/// Scope of reward (event-level or outcome-level).
133#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
134#[serde(rename_all = "snake_case")]
135pub enum RewardScope {
136    Event,
137    Outcome,
138}
139
140impl Default for RewardScope {
141    fn default() -> Self {
142        Self::Outcome
143    }
144}
145
146/// Key identifying an objective metric.
147#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
148#[serde(rename_all = "snake_case")]
149pub enum ObjectiveKey {
150    Reward,
151    LatencyMs,
152    CostUsd,
153    TokensTotal,
154    TurnsCount,
155}
156
157impl Default for ObjectiveKey {
158    fn default() -> Self {
159        Self::Reward
160    }
161}
162
163/// Direction for objective optimization.
164#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
165#[serde(rename_all = "snake_case")]
166pub enum ObjectiveDirection {
167    Maximize,
168    Minimize,
169}
170
171impl Default for ObjectiveDirection {
172    fn default() -> Self {
173        Self::Maximize
174    }
175}
176
177/// Output mode for LLM responses.
178#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
179#[serde(rename_all = "snake_case")]
180pub enum OutputMode {
181    ToolCalls,
182    Text,
183    Structured,
184}
185
186impl Default for OutputMode {
187    fn default() -> Self {
188        Self::Text
189    }
190}
191
192/// Success/failure status for rollout execution.
193#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
194#[serde(rename_all = "snake_case")]
195pub enum SuccessStatus {
196    Success,
197    Timeout,
198    NetworkError,
199    ApplyFailed,
200    RuntimeError,
201    Failure,
202}
203
204impl SuccessStatus {
205    /// Returns true if the status indicates success.
206    pub fn is_success(&self) -> bool {
207        matches!(self, Self::Success)
208    }
209}
210
211impl Default for SuccessStatus {
212    fn default() -> Self {
213        Self::Success
214    }
215}
216
217/// Type of graph in graph optimization.
218#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
219#[serde(rename_all = "snake_case")]
220pub enum GraphType {
221    Sequential,
222    Parallel,
223    Conditional,
224    Loop,
225    Policy,
226    Verifier,
227    Rlm,
228}
229
230impl Default for GraphType {
231    fn default() -> Self {
232        Self::Sequential
233    }
234}
235
236/// Optimization mode for learning jobs.
237#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
238#[serde(rename_all = "snake_case")]
239pub enum OptimizationMode {
240    Online,
241    Offline,
242    Hybrid,
243    Auto,
244    GraphOnly,
245    PromptOnly,
246}
247
248impl Default for OptimizationMode {
249    fn default() -> Self {
250        Self::Online
251    }
252}
253
254/// Verifier evaluation mode.
255#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
256#[serde(rename_all = "snake_case")]
257pub enum VerifierMode {
258    Binary,
259    Rubric,
260    Criteria,
261    Custom,
262    Contrastive,
263    GoldExamples,
264}
265
266impl Default for VerifierMode {
267    fn default() -> Self {
268        Self::Binary
269    }
270}
271
272/// Training type for SFT/RL jobs.
273#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
274#[serde(rename_all = "snake_case")]
275pub enum TrainingType {
276    Sft,
277    Rl,
278    Dpo,
279    Ppo,
280    Grpo,
281    Gepa,
282    GraphEvolve,
283    Graphgen,
284    Gspo,
285}
286
287impl Default for TrainingType {
288    fn default() -> Self {
289        Self::Sft
290    }
291}
292
293/// Adaptive curriculum difficulty level.
294#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
295#[serde(rename_all = "snake_case")]
296pub enum AdaptiveCurriculumLevel {
297    Easy,
298    Medium,
299    Hard,
300    Expert,
301    #[serde(alias = "NONE")]
302    None,
303    #[serde(alias = "LOW")]
304    Low,
305    #[serde(alias = "MODERATE")]
306    Moderate,
307    #[serde(alias = "HIGH")]
308    High,
309}
310
311impl Default for AdaptiveCurriculumLevel {
312    fn default() -> Self {
313        Self::Medium
314    }
315}
316
317/// Adaptive batch sizing level.
318#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
319#[serde(rename_all = "snake_case")]
320pub enum AdaptiveBatchLevel {
321    Small,
322    Medium,
323    Large,
324    Auto,
325    #[serde(alias = "NONE")]
326    None,
327    #[serde(alias = "LOW")]
328    Low,
329    #[serde(alias = "MODERATE")]
330    Moderate,
331    #[serde(alias = "HIGH")]
332    High,
333}
334
335/// Synth-hosted model names.
336#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
337#[serde(rename_all = "snake_case")]
338pub enum SynthModelName {
339    SynthSmall,
340    SynthMedium,
341}
342
343impl Default for AdaptiveBatchLevel {
344    fn default() -> Self {
345        Self::Auto
346    }
347}
348
349#[cfg(test)]
350mod tests {
351    use super::*;
352
353    #[test]
354    fn test_job_status_terminal() {
355        assert!(!JobStatus::Pending.is_terminal());
356        assert!(!JobStatus::Running.is_terminal());
357        assert!(!JobStatus::Paused.is_terminal());
358        assert!(JobStatus::Succeeded.is_terminal());
359        assert!(JobStatus::Failed.is_terminal());
360        assert!(JobStatus::Cancelled.is_terminal());
361    }
362
363    #[test]
364    fn test_serde_roundtrip() {
365        let status = JobStatus::Running;
366        let json = serde_json::to_string(&status).unwrap();
367        assert_eq!(json, "\"running\"");
368
369        let parsed: JobStatus = serde_json::from_str(&json).unwrap();
370        assert_eq!(parsed, status);
371    }
372
373    #[test]
374    fn test_success_status() {
375        assert!(SuccessStatus::Success.is_success());
376        assert!(!SuccessStatus::Failure.is_success());
377        assert!(!SuccessStatus::Timeout.is_success());
378    }
379}