entrenar/ecosystem/ruchy/
session.rs1use super::metrics::SessionMetrics;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct EntrenarSession {
10 pub id: String,
12 pub name: String,
14 pub user: Option<String>,
16 pub created_at: chrono::DateTime<chrono::Utc>,
18 pub ended_at: Option<chrono::DateTime<chrono::Utc>>,
20 pub model_architecture: Option<String>,
22 pub dataset_id: Option<String>,
24 pub config: HashMap<String, String>,
26 pub metrics: SessionMetrics,
28 pub code_history: Vec<CodeCell>,
30 pub tags: Vec<String>,
32 pub notes: Option<String>,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct CodeCell {
39 pub execution_order: u32,
41 pub source: String,
43 pub output: Option<String>,
45 pub timestamp: chrono::DateTime<chrono::Utc>,
47 pub duration_ms: Option<u64>,
49}
50
51impl EntrenarSession {
52 pub fn new(id: impl Into<String>, name: impl Into<String>) -> Self {
54 Self {
55 id: id.into(),
56 name: name.into(),
57 user: None,
58 created_at: chrono::Utc::now(),
59 ended_at: None,
60 model_architecture: None,
61 dataset_id: None,
62 config: HashMap::new(),
63 metrics: SessionMetrics::new(),
64 code_history: Vec::new(),
65 tags: Vec::new(),
66 notes: None,
67 }
68 }
69
70 pub fn with_user(mut self, user: impl Into<String>) -> Self {
72 self.user = Some(user.into());
73 self
74 }
75
76 pub fn with_architecture(mut self, arch: impl Into<String>) -> Self {
78 self.model_architecture = Some(arch.into());
79 self
80 }
81
82 pub fn with_dataset(mut self, dataset: impl Into<String>) -> Self {
84 self.dataset_id = Some(dataset.into());
85 self
86 }
87
88 pub fn with_config(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
90 self.config.insert(key.into(), value.into());
91 self
92 }
93
94 pub fn with_tag(mut self, tag: impl Into<String>) -> Self {
96 self.tags.push(tag.into());
97 self
98 }
99
100 pub fn with_notes(mut self, notes: impl Into<String>) -> Self {
102 self.notes = Some(notes.into());
103 self
104 }
105
106 pub fn add_code_cell(&mut self, cell: CodeCell) {
108 self.code_history.push(cell);
109 }
110
111 pub fn end(&mut self) {
113 self.ended_at = Some(chrono::Utc::now());
114 }
115
116 pub fn duration(&self) -> Option<chrono::Duration> {
118 self.ended_at.map(|end| end - self.created_at)
119 }
120
121 pub fn has_training_data(&self) -> bool {
123 !self.metrics.is_empty()
124 }
125
126 pub fn export_json(&self) -> Result<serde_json::Value, serde_json::Error> {
132 let export = SessionExport {
133 session_id: self.id.clone(),
134 name: self.name.clone(),
135 user: self.user.clone(),
136 created_at: self.created_at.to_rfc3339(),
137 ended_at: self.ended_at.map(|t| t.to_rfc3339()),
138 duration_seconds: self.duration().map(|d| d.num_seconds()),
139 model_architecture: self.model_architecture.clone(),
140 dataset_id: self.dataset_id.clone(),
141 config: self.config.clone(),
142 metrics: MetricsExportSummary {
143 total_steps: self.metrics.total_steps(),
144 final_loss: self.metrics.final_loss(),
145 best_loss: self.metrics.best_loss(),
146 final_accuracy: self.metrics.final_accuracy(),
147 best_accuracy: self.metrics.best_accuracy(),
148 loss_history: self.metrics.loss_history.clone(),
149 accuracy_history: self.metrics.accuracy_history.clone(),
150 custom_metrics: self.metrics.custom.clone(),
151 },
152 code_cells_count: self.code_history.len(),
153 tags: self.tags.clone(),
154 notes: self.notes.clone(),
155 };
156 serde_json::to_value(export)
157 }
158
159 pub fn export_json_string(&self) -> Result<String, serde_json::Error> {
164 let value = self.export_json()?;
165 serde_json::to_string_pretty(&value)
166 }
167}
168
169#[derive(Debug, Clone, Serialize, Deserialize)]
171pub struct SessionExport {
172 pub session_id: String,
174 pub name: String,
176 pub user: Option<String>,
178 pub created_at: String,
180 pub ended_at: Option<String>,
182 pub duration_seconds: Option<i64>,
184 pub model_architecture: Option<String>,
186 pub dataset_id: Option<String>,
188 pub config: HashMap<String, String>,
190 pub metrics: MetricsExportSummary,
192 pub code_cells_count: usize,
194 pub tags: Vec<String>,
196 pub notes: Option<String>,
198}
199
200#[derive(Debug, Clone, Serialize, Deserialize)]
202pub struct MetricsExportSummary {
203 pub total_steps: usize,
205 pub final_loss: Option<f64>,
207 pub best_loss: Option<f64>,
209 pub final_accuracy: Option<f64>,
211 pub best_accuracy: Option<f64>,
213 pub loss_history: Vec<f64>,
215 pub accuracy_history: Vec<f64>,
217 pub custom_metrics: HashMap<String, Vec<f64>>,
219}