1use burn::{config::Config, module::Module, tensor::backend::Backend};
2
3use crate::client::HeatClient;
4
5#[derive(Debug, Clone)]
6pub struct MultiDevice<B: Backend>(pub Vec<B::Device>);
7
8#[derive(Debug, Clone)]
9pub struct TrainCommandContext<B: Backend> {
10 client: HeatClient,
11 devices: Vec<B::Device>,
12 config: String,
13}
14
15impl<B: Backend> TrainCommandContext<B> {
16 pub fn new(client: HeatClient, devices: Vec<B::Device>, config: String) -> Self {
17 Self {
18 client,
19 devices,
20 config,
21 }
22 }
23
24 pub fn client(&mut self) -> &mut HeatClient {
25 &mut self.client
26 }
27
28 pub fn devices(&mut self) -> &mut Vec<B::Device> {
29 &mut self.devices
30 }
31
32 pub fn config(&self) -> &str {
33 &self.config
34 }
35}
36
37trait FromTrainCommandContext<B: Backend> {
38 fn from_context(context: &TrainCommandContext<B>) -> Self;
39}
40
41impl<B: Backend> FromTrainCommandContext<B> for HeatClient {
42 fn from_context(context: &TrainCommandContext<B>) -> Self {
43 context.client.clone()
44 }
45}
46
47impl<B: Backend> FromTrainCommandContext<B> for MultiDevice<B> {
48 fn from_context(context: &TrainCommandContext<B>) -> Self {
49 MultiDevice(context.devices.clone())
50 }
51}
52
53impl<B: Backend> IntoIterator for MultiDevice<B> {
54 type Item = B::Device;
55 type IntoIter = std::vec::IntoIter<Self::Item>;
56
57 fn into_iter(self) -> Self::IntoIter {
58 self.0.into_iter()
59 }
60}
61
62impl<B: Backend, T: Config> FromTrainCommandContext<B> for T {
63 fn from_context(context: &TrainCommandContext<B>) -> Self {
64 T::load_binary(context.config.as_bytes()).expect("Config should be loaded")
65 }
66}
67
68pub trait TrainCommandHandler<B: Backend, T, M: Module<B>, E: Into<Box<dyn std::error::Error>>> {
69 fn call(self, context: TrainCommandContext<B>) -> Result<M, E>;
70}
71
72impl<F, M, B, E: Into<Box<dyn std::error::Error>>> TrainCommandHandler<B, (), M, E> for F
73where
74 F: Fn() -> Result<M, E>,
75 M: Module<B>,
76 B: Backend,
77{
78 fn call(self, _context: TrainCommandContext<B>) -> Result<M, E> {
79 (self)()
80 }
81}
82
83impl<F, T, M, B, E: Into<Box<dyn std::error::Error>>> TrainCommandHandler<B, (T,), M, E> for F
84where
85 F: Fn(T) -> Result<M, E>,
86 T: FromTrainCommandContext<B>,
87 M: Module<B>,
88 B: Backend,
89{
90 fn call(self, context: TrainCommandContext<B>) -> Result<M, E> {
91 (self)(T::from_context(&context))
92 }
93}
94
95impl<F, T1, T2, M, B, E: Into<Box<dyn std::error::Error>>> TrainCommandHandler<B, (T1, T2), M, E>
96 for F
97where
98 F: Fn(T1, T2) -> Result<M, E>,
99 T1: FromTrainCommandContext<B>,
100 T2: FromTrainCommandContext<B>,
101 M: Module<B>,
102 B: Backend,
103{
104 fn call(self, context: TrainCommandContext<B>) -> Result<M, E> {
105 (self)(T1::from_context(&context), T2::from_context(&context))
106 }
107}
108
109impl<F, T1, T2, T3, M, B, E: Into<Box<dyn std::error::Error>>>
110 TrainCommandHandler<B, (T1, T2, T3), M, E> for F
111where
112 F: Fn(T1, T2, T3) -> Result<M, E>,
113 T1: FromTrainCommandContext<B>,
114 T2: FromTrainCommandContext<B>,
115 T3: FromTrainCommandContext<B>,
116 M: Module<B>,
117 B: Backend,
118{
119 fn call(self, context: TrainCommandContext<B>) -> Result<M, E> {
120 (self)(
121 T1::from_context(&context),
122 T2::from_context(&context),
123 T3::from_context(&context),
124 )
125 }
126}