batch_mode_batch_triple/
ensure_input_matches_output.rs

1// ---------------- [ File: batch-mode-batch-triple/src/ensure_input_matches_output.rs ]
2crate::ix!();
3
4impl BatchFileTriple {
5
6    pub async fn ensure_input_matches_output(&self) 
7        -> Result<(), BatchValidationError> 
8    {
9        // Load input and output files
10        let input_data  = load_input_file(self.input().as_ref().unwrap()).await?;
11
12        let output_data = load_output_file(self.output().as_ref().unwrap()).await?;
13
14        // Compare request IDs
15        let input_ids:  HashSet<_> = input_data.request_ids().into_iter().collect();
16        let output_ids: HashSet<_> = output_data.request_ids().into_iter().collect();
17
18        if input_ids != output_ids {
19            return Err(BatchValidationError::RequestIdsMismatch {
20                index:      self.index().clone(),
21                input_ids:  Some(input_ids),
22                output_ids: Some(output_ids),
23                error_ids:  None,
24            });
25        }
26
27        info!("for our batch triple {:#?}, we have now ensured the input request ids match the request ids from the output file",self);
28
29        Ok(())
30    }
31}
32
33#[cfg(test)]
34mod batch_file_triple_ensure_input_matches_output_exhaustive_tests {
35    use super::*;
36    use tempfile::NamedTempFile;
37    use std::io::Write;
38    use tokio::runtime::Runtime;
39    use tracing::*;
40
41    #[traced_test]
42    fn ensure_input_matches_output_succeeds_with_identical_ids() {
43        info!("Starting test: ensure_input_matches_output_succeeds_with_identical_ids");
44
45        // Create the input file with 2 requests
46        let mut input_file = NamedTempFile::new().expect("Failed to create a temp file for input");
47        {
48            // Each entire JSON object must be on exactly one line
49            let req1 = LanguageModelBatchAPIRequest::mock("id-1");
50            let req2 = LanguageModelBatchAPIRequest::mock("id-2");
51
52            writeln!(input_file, "{}", serde_json::to_string(&req1).unwrap())
53                .expect("Failed to write req1 to input file");
54            writeln!(input_file, "{}", serde_json::to_string(&req2).unwrap())
55                .expect("Failed to write req2 to input file");
56        }
57
58        // Create the output file with 2 response records, each on exactly ONE line.
59        // Because the parser reads line by line, multi-line JSON objects will be broken.
60        let mut output_file = NamedTempFile::new().expect("Failed to create a temp file for output");
61        {
62            let line_1 = r#"{"id":"batch_req_id-1","custom_id":"id-1","response":{"status_code":200,"request_id":"resp_req_id-1","body":{"id":"success-id","object":"chat.completion","created":0,"model":"test-model","choices":[],"usage":{"prompt_tokens":0,"completion_tokens":0,"total_tokens":0,"prompt_tokens_details":null,"completion_tokens_details":null},"system_fingerprint":null}},"error":null}"#;
63            let line_2 = r#"{"id":"batch_req_id-2","custom_id":"id-2","response":{"status_code":200,"request_id":"resp_req_id-2","body":{"id":"success-id","object":"chat.completion","created":0,"model":"test-model","choices":[],"usage":{"prompt_tokens":0,"completion_tokens":0,"total_tokens":0,"prompt_tokens_details":null,"completion_tokens_details":null},"system_fingerprint":null}},"error":null}"#;
64
65            writeln!(output_file, "{}", line_1)
66                .expect("Failed to write line_1 to output file");
67            writeln!(output_file, "{}", line_2)
68                .expect("Failed to write line_2 to output file");
69        }
70
71        // Construct a triple referencing these new files
72        let triple = BatchFileTriple::new_direct(
73            &BatchIndex::Usize(2),
74            Some(input_file.path().to_path_buf()),
75            Some(output_file.path().to_path_buf()),
76            None, // no error file for this test
77            None,
78            Arc::new(MockBatchWorkspace::default()),
79        );
80
81        let rt = Runtime::new().expect("Failed to create tokio Runtime");
82        let result = rt.block_on(async { triple.ensure_input_matches_output().await });
83
84        debug!("Result of ensure_input_matches_output: {:?}", result);
85        assert!(
86            result.is_ok(),
87            "Should succeed when input and output share the same IDs"
88        );
89
90        info!("Finished test: ensure_input_matches_output_succeeds_with_identical_ids");
91    }
92}