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    #[serde(alias = "task_app")]
98    Container,
99    Verifier,
100    Fused,
101    Environment,
102    Runner,
103    Evaluator,
104    Human,
105}
106
107impl Default for RewardSource {
108    fn default() -> Self {
109        Self::Container
110    }
111}
112
113/// Type of reward signal.
114#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
115#[serde(rename_all = "snake_case")]
116pub enum RewardType {
117    Shaped,
118    Sparse,
119    Penalty,
120    Evaluator,
121    Human,
122    Achievement,
123    AchievementDelta,
124    UniqueAchievementDelta,
125}
126
127impl Default for RewardType {
128    fn default() -> Self {
129        Self::Sparse
130    }
131}
132
133/// Scope of reward (event-level or outcome-level).
134#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
135#[serde(rename_all = "snake_case")]
136pub enum RewardScope {
137    Event,
138    Outcome,
139}
140
141impl Default for RewardScope {
142    fn default() -> Self {
143        Self::Outcome
144    }
145}
146
147/// Key identifying an objective metric.
148#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
149#[serde(rename_all = "snake_case")]
150pub enum ObjectiveKey {
151    Reward,
152    LatencyMs,
153    CostUsd,
154    TokensTotal,
155    TurnsCount,
156}
157
158impl Default for ObjectiveKey {
159    fn default() -> Self {
160        Self::Reward
161    }
162}
163
164/// Direction for objective optimization.
165#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
166#[serde(rename_all = "snake_case")]
167pub enum ObjectiveDirection {
168    Maximize,
169    Minimize,
170}
171
172impl Default for ObjectiveDirection {
173    fn default() -> Self {
174        Self::Maximize
175    }
176}
177
178/// Output mode for LLM responses.
179#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
180#[serde(rename_all = "snake_case")]
181pub enum OutputMode {
182    ToolCalls,
183    Text,
184    Structured,
185}
186
187impl Default for OutputMode {
188    fn default() -> Self {
189        Self::Text
190    }
191}
192
193/// Success/failure status for rollout execution.
194#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
195#[serde(rename_all = "snake_case")]
196pub enum SuccessStatus {
197    Success,
198    Timeout,
199    NetworkError,
200    ApplyFailed,
201    RuntimeError,
202    Failure,
203}
204
205impl SuccessStatus {
206    /// Returns true if the status indicates success.
207    pub fn is_success(&self) -> bool {
208        matches!(self, Self::Success)
209    }
210}
211
212impl Default for SuccessStatus {
213    fn default() -> Self {
214        Self::Success
215    }
216}
217
218/// Type of graph in graph optimization.
219#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
220#[serde(rename_all = "snake_case")]
221pub enum GraphType {
222    Sequential,
223    Parallel,
224    Conditional,
225    Loop,
226    Policy,
227    Verifier,
228    Rlm,
229}
230
231impl Default for GraphType {
232    fn default() -> Self {
233        Self::Sequential
234    }
235}
236
237/// Optimization mode for learning jobs.
238#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
239#[serde(rename_all = "snake_case")]
240pub enum OptimizationMode {
241    Online,
242    Offline,
243    Hybrid,
244    Auto,
245    GraphOnly,
246    PromptOnly,
247}
248
249impl Default for OptimizationMode {
250    fn default() -> Self {
251        Self::Online
252    }
253}
254
255/// Verifier evaluation mode.
256#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
257#[serde(rename_all = "snake_case")]
258pub enum VerifierMode {
259    Binary,
260    Rubric,
261    Criteria,
262    Custom,
263    Contrastive,
264    GoldExamples,
265}
266
267impl Default for VerifierMode {
268    fn default() -> Self {
269        Self::Binary
270    }
271}
272
273/// Training type for SFT/RL jobs.
274#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
275#[serde(rename_all = "snake_case")]
276pub enum TrainingType {
277    Sft,
278    Rl,
279    Dpo,
280    Ppo,
281    Grpo,
282    Gepa,
283    GraphEvolve,
284    Graphgen,
285    Gspo,
286}
287
288impl Default for TrainingType {
289    fn default() -> Self {
290        Self::Sft
291    }
292}
293
294/// Adaptive curriculum difficulty level.
295#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
296#[serde(rename_all = "snake_case")]
297pub enum AdaptiveCurriculumLevel {
298    Easy,
299    Medium,
300    Hard,
301    Expert,
302    #[serde(alias = "NONE")]
303    None,
304    #[serde(alias = "LOW")]
305    Low,
306    #[serde(alias = "MODERATE")]
307    Moderate,
308    #[serde(alias = "HIGH")]
309    High,
310}
311
312impl Default for AdaptiveCurriculumLevel {
313    fn default() -> Self {
314        Self::Medium
315    }
316}
317
318/// Adaptive batch sizing level.
319#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
320#[serde(rename_all = "snake_case")]
321pub enum AdaptiveBatchLevel {
322    Small,
323    Medium,
324    Large,
325    Auto,
326    #[serde(alias = "NONE")]
327    None,
328    #[serde(alias = "LOW")]
329    Low,
330    #[serde(alias = "MODERATE")]
331    Moderate,
332    #[serde(alias = "HIGH")]
333    High,
334}
335
336/// Synth-hosted model names.
337#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
338#[serde(rename_all = "snake_case")]
339pub enum SynthModelName {
340    SynthSmall,
341    SynthMedium,
342}
343
344impl Default for AdaptiveBatchLevel {
345    fn default() -> Self {
346        Self::Auto
347    }
348}
349
350#[cfg(test)]
351mod tests {
352    use super::*;
353
354    #[test]
355    fn test_job_status_terminal() {
356        assert!(!JobStatus::Pending.is_terminal());
357        assert!(!JobStatus::Running.is_terminal());
358        assert!(!JobStatus::Paused.is_terminal());
359        assert!(JobStatus::Succeeded.is_terminal());
360        assert!(JobStatus::Failed.is_terminal());
361        assert!(JobStatus::Cancelled.is_terminal());
362    }
363
364    #[test]
365    fn test_serde_roundtrip() {
366        let status = JobStatus::Running;
367        let json = serde_json::to_string(&status).unwrap();
368        assert_eq!(json, "\"running\"");
369
370        let parsed: JobStatus = serde_json::from_str(&json).unwrap();
371        assert_eq!(parsed, status);
372    }
373
374    #[test]
375    fn test_success_status() {
376        assert!(SuccessStatus::Success.is_success());
377        assert!(!SuccessStatus::Failure.is_success());
378        assert!(!SuccessStatus::Timeout.is_success());
379    }
380}