Skip to main content

entrenar/config/train/batches/
json.rs

1//! JSON batch loading
2
3use crate::error::{Error, Result};
4use crate::train::Batch;
5use crate::Tensor;
6use std::path::Path;
7
8/// Load batches from JSON file
9pub fn load_json_batches(path: &Path, batch_size: usize) -> Result<Vec<Batch>> {
10    println!("  Loading JSON: {}", path.display());
11
12    // Try to load as JSON array of {input, target} objects
13    let content = std::fs::read_to_string(path).map_err(|e| {
14        Error::ConfigError(format!("Failed to read JSON {}: {}", path.display(), e))
15    })?;
16
17    #[derive(serde::Deserialize)]
18    struct Example {
19        input: Vec<f32>,
20        target: Vec<f32>,
21    }
22
23    #[derive(serde::Deserialize)]
24    struct DataFile {
25        examples: Vec<Example>,
26    }
27
28    // Try structured format first
29    if let Ok(data) = serde_json::from_str::<DataFile>(&content) {
30        println!("  Loaded {} examples from JSON", data.examples.len());
31        let batches: Vec<Batch> = data
32            .examples
33            .chunks(batch_size.max(1))
34            .map(|chunk| {
35                let input_data: Vec<f32> = chunk.iter().flat_map(|ex| ex.input.clone()).collect();
36                let target_data: Vec<f32> = chunk.iter().flat_map(|ex| ex.target.clone()).collect();
37                Batch::new(
38                    Tensor::from_vec(input_data, false),
39                    Tensor::from_vec(target_data, false),
40                )
41            })
42            .collect();
43        return Ok(batches);
44    }
45
46    // Try array of examples
47    if let Ok(examples) = serde_json::from_str::<Vec<Example>>(&content) {
48        println!("  Loaded {} examples from JSON array", examples.len());
49        let batches: Vec<Batch> = examples
50            .chunks(batch_size.max(1))
51            .map(|chunk| {
52                let input_data: Vec<f32> = chunk.iter().flat_map(|ex| ex.input.clone()).collect();
53                let target_data: Vec<f32> = chunk.iter().flat_map(|ex| ex.target.clone()).collect();
54                Batch::new(
55                    Tensor::from_vec(input_data, false),
56                    Tensor::from_vec(target_data, false),
57                )
58            })
59            .collect();
60        return Ok(batches);
61    }
62
63    // NEVER substitute synthetic data for a dataset we failed to parse — a run
64    // that trains on fabricated examples and exits 0 is worse than one that
65    // refuses to start.
66    Err(Error::ConfigError(format!(
67        "Could not parse training data '{}': {}",
68        path.display(),
69        super::loader::JSON_SCHEMA_HINT
70    )))
71}