Skip to main content

trustformers_wasm/plugins/
example_plugin.rs

1// Example plugin implementation for TrustformeRS WASM
2// Demonstrates how to create community plugins
3
4#![allow(clippy::missing_enforced_import_renames)]
5
6use crate::plugin_framework::{
7    ExecutionMetrics, Plugin, PluginConfig, PluginContext, PluginError, PluginErrorCode,
8    PluginMetadata, PluginPermission, PluginResult, PluginType,
9};
10use std::collections::HashMap;
11
12/// Example text processor plugin
13pub struct TextProcessorPlugin {
14    enabled: bool,
15    settings: HashMap<String, String>,
16}
17
18impl Default for TextProcessorPlugin {
19    fn default() -> Self {
20        Self::new()
21    }
22}
23
24impl TextProcessorPlugin {
25    pub fn new() -> Self {
26        Self {
27            enabled: false,
28            settings: HashMap::new(),
29        }
30    }
31}
32
33impl Plugin for TextProcessorPlugin {
34    fn metadata(&self) -> PluginMetadata {
35        PluginMetadata {
36            name: "Text Processor".to_string(),
37            version: "1.0.0".to_string(),
38            author: "TrustformeRS Community".to_string(),
39            description: "Example plugin for text preprocessing".to_string(),
40            plugin_type: PluginType::Preprocessor,
41            dependencies: vec![],
42            permissions: vec![
43                PluginPermission::ReadModelData,
44                PluginPermission::DebugAccess,
45            ],
46        }
47    }
48
49    fn initialize(&mut self, config: PluginConfig) -> Result<(), PluginError> {
50        self.settings = config.settings;
51        self.enabled = true;
52
53        // Validate required settings
54        if !self.settings.contains_key("processing_mode") {
55            return Err(PluginError {
56                code: PluginErrorCode::InvalidConfiguration,
57                message: "Missing 'processing_mode' setting".to_string(),
58                details: Some("Valid modes: 'lowercase', 'uppercase', 'trim'".to_string()),
59            });
60        }
61
62        Ok(())
63    }
64
65    fn execute(&self, context: &PluginContext) -> Result<PluginResult, PluginError> {
66        if !self.enabled {
67            return Err(PluginError {
68                code: PluginErrorCode::ExecutionFailed,
69                message: "Plugin not initialized".to_string(),
70                details: None,
71            });
72        }
73
74        let start_time = std::time::Instant::now();
75        let mut result_data = HashMap::new();
76
77        // Get input text from context
78        let input_text = context.request_data.get("input_text").cloned().unwrap_or_default();
79
80        // Process text based on settings
81        let default_mode = "trim".to_string();
82        let processing_mode = self.settings.get("processing_mode").unwrap_or(&default_mode);
83
84        let processed_text = match processing_mode.as_str() {
85            "lowercase" => input_text.to_lowercase(),
86            "uppercase" => input_text.to_uppercase(),
87            "trim" => input_text.trim().to_string(),
88            _ => input_text.clone(), // No processing
89        };
90
91        result_data.insert("processed_text".to_string(), processed_text.clone());
92        result_data.insert("original_length".to_string(), input_text.len().to_string());
93        result_data.insert(
94            "processed_length".to_string(),
95            processed_text.len().to_string(),
96        );
97        result_data.insert("processing_mode".to_string(), processing_mode.clone());
98
99        let execution_time = start_time.elapsed().as_millis() as f64;
100
101        Ok(PluginResult {
102            success: true,
103            data: result_data,
104            metrics: ExecutionMetrics {
105                execution_time_ms: execution_time,
106                memory_used_mb: 0.1, // Minimal memory usage
107                cpu_usage_percent: 5.0,
108                gpu_memory_used_mb: None,
109            },
110            messages: vec![format!(
111                "Processed {} characters using {} mode",
112                processed_text.len(),
113                processing_mode
114            )],
115        })
116    }
117
118    fn cleanup(&mut self) {
119        self.enabled = false;
120        self.settings.clear();
121    }
122}
123
124/// Example model optimizer plugin
125pub struct ModelOptimizerPlugin {
126    enabled: bool,
127    optimization_level: u8,
128}
129
130impl Default for ModelOptimizerPlugin {
131    fn default() -> Self {
132        Self::new()
133    }
134}
135
136impl ModelOptimizerPlugin {
137    pub fn new() -> Self {
138        Self {
139            enabled: false,
140            optimization_level: 1,
141        }
142    }
143}
144
145impl Plugin for ModelOptimizerPlugin {
146    fn metadata(&self) -> PluginMetadata {
147        PluginMetadata {
148            name: "Model Optimizer".to_string(),
149            version: "1.2.0".to_string(),
150            author: "TrustformeRS Team".to_string(),
151            description: "Example plugin for model optimization".to_string(),
152            plugin_type: PluginType::Optimizer,
153            dependencies: vec![],
154            permissions: vec![
155                PluginPermission::ReadModelData,
156                PluginPermission::WriteModelData,
157                PluginPermission::GpuAccess,
158                PluginPermission::ProfilingAccess,
159            ],
160        }
161    }
162
163    fn initialize(&mut self, config: PluginConfig) -> Result<(), PluginError> {
164        // Parse optimization level from config
165        if let Some(level_str) = config.settings.get("optimization_level") {
166            match level_str.parse::<u8>() {
167                Ok(level) if level <= 3 => self.optimization_level = level,
168                _ => {
169                    return Err(PluginError {
170                        code: PluginErrorCode::InvalidConfiguration,
171                        message: "Invalid optimization level (must be 0-3)".to_string(),
172                        details: None,
173                    })
174                },
175            }
176        }
177
178        self.enabled = true;
179        Ok(())
180    }
181
182    fn execute(&self, context: &PluginContext) -> Result<PluginResult, PluginError> {
183        if !self.enabled {
184            return Err(PluginError {
185                code: PluginErrorCode::ExecutionFailed,
186                message: "Plugin not initialized".to_string(),
187                details: None,
188            });
189        }
190
191        let start_time = std::time::Instant::now();
192        let mut result_data = HashMap::new();
193
194        // Simulate model optimization based on level
195        let optimization_applied = match self.optimization_level {
196            0 => "None",
197            1 => "Basic quantization",
198            2 => "Advanced quantization + pruning",
199            3 => "Full optimization suite",
200            _ => "Unknown",
201        };
202
203        // Simulate optimization metrics
204        let size_reduction = match self.optimization_level {
205            0 => 0.0,
206            1 => 15.0,
207            2 => 35.0,
208            3 => 55.0,
209            _ => 0.0,
210        };
211
212        let speed_improvement = match self.optimization_level {
213            0 => 0.0,
214            1 => 10.0,
215            2 => 25.0,
216            3 => 40.0,
217            _ => 0.0,
218        };
219
220        result_data.insert(
221            "optimization_applied".to_string(),
222            optimization_applied.to_string(),
223        );
224        result_data.insert(
225            "size_reduction_percent".to_string(),
226            size_reduction.to_string(),
227        );
228        result_data.insert(
229            "speed_improvement_percent".to_string(),
230            speed_improvement.to_string(),
231        );
232        result_data.insert(
233            "optimization_level".to_string(),
234            self.optimization_level.to_string(),
235        );
236
237        // Add model metadata if available
238        if let Some(ref metadata) = context.model_metadata {
239            result_data.insert(
240                "original_model_size_mb".to_string(),
241                metadata.size_mb.to_string(),
242            );
243            result_data.insert("model_type".to_string(), metadata.model_type.clone());
244        }
245
246        let execution_time = start_time.elapsed().as_millis() as f64;
247
248        Ok(PluginResult {
249            success: true,
250            data: result_data,
251            metrics: ExecutionMetrics {
252                execution_time_ms: execution_time,
253                memory_used_mb: 5.0,
254                cpu_usage_percent: 15.0,
255                gpu_memory_used_mb: Some(2.0),
256            },
257            messages: vec![
258                format!("Applied {optimization_applied} optimization"),
259                format!(
260                    "Achieved {:.1}% size reduction and {:.1}% speed improvement",
261                    size_reduction, speed_improvement
262                ),
263            ],
264        })
265    }
266
267    fn cleanup(&mut self) {
268        self.enabled = false;
269        self.optimization_level = 1;
270    }
271}
272
273/// Example visualization plugin
274pub struct VisualizationPlugin {
275    enabled: bool,
276    chart_type: String,
277}
278
279impl Default for VisualizationPlugin {
280    fn default() -> Self {
281        Self::new()
282    }
283}
284
285impl VisualizationPlugin {
286    pub fn new() -> Self {
287        Self {
288            enabled: false,
289            chart_type: "bar".to_string(),
290        }
291    }
292}
293
294impl Plugin for VisualizationPlugin {
295    fn metadata(&self) -> PluginMetadata {
296        PluginMetadata {
297            name: "Data Visualizer".to_string(),
298            version: "0.9.0".to_string(),
299            author: "Community Developer".to_string(),
300            description: "Create charts and graphs from model data".to_string(),
301            plugin_type: PluginType::Visualizer,
302            dependencies: vec![],
303            permissions: vec![PluginPermission::ReadModelData, PluginPermission::UiAccess],
304        }
305    }
306
307    fn initialize(&mut self, config: PluginConfig) -> Result<(), PluginError> {
308        if let Some(chart_type) = config.settings.get("chart_type") {
309            let valid_types = ["bar", "line", "pie", "scatter"];
310            if valid_types.contains(&chart_type.as_str()) {
311                self.chart_type = chart_type.clone();
312            } else {
313                return Err(PluginError {
314                    code: PluginErrorCode::InvalidConfiguration,
315                    message: format!("Invalid chart type: {chart_type}"),
316                    details: Some("Valid types: bar, line, pie, scatter".to_string()),
317                });
318            }
319        }
320
321        self.enabled = true;
322        Ok(())
323    }
324
325    fn execute(&self, _context: &PluginContext) -> Result<PluginResult, PluginError> {
326        if !self.enabled {
327            return Err(PluginError {
328                code: PluginErrorCode::ExecutionFailed,
329                message: "Plugin not initialized".to_string(),
330                details: None,
331            });
332        }
333
334        let start_time = std::time::Instant::now();
335        let mut result_data = HashMap::new();
336
337        // Generate mock chart data based on chart type
338        let chart_data = match self.chart_type.as_str() {
339            "bar" => {
340                r#"{"type":"bar","data":{"labels":["Q1","Q2","Q3","Q4"],"values":[10,20,15,25]}}"#
341            },
342            "line" => r#"{"type":"line","data":{"x":[1,2,3,4,5],"y":[2,4,3,5,4]}}"#,
343            "pie" => r#"{"type":"pie","data":{"labels":["A","B","C"],"values":[30,40,30]}}"#,
344            "scatter" => r#"{"type":"scatter","data":{"points":[[1,2],[2,4],[3,3],[4,5]]}}"#,
345            _ => r#"{"type":"unknown","data":{}}"#,
346        };
347
348        result_data.insert("chart_type".to_string(), self.chart_type.clone());
349        result_data.insert("chart_data".to_string(), chart_data.to_string());
350        result_data.insert("width".to_string(), "800".to_string());
351        result_data.insert("height".to_string(), "600".to_string());
352
353        let execution_time = start_time.elapsed().as_millis() as f64;
354
355        Ok(PluginResult {
356            success: true,
357            data: result_data,
358            metrics: ExecutionMetrics {
359                execution_time_ms: execution_time,
360                memory_used_mb: 1.0,
361                cpu_usage_percent: 8.0,
362                gpu_memory_used_mb: None,
363            },
364            messages: vec![
365                format!("Generated {chart_type} chart", chart_type = self.chart_type),
366                "Chart data ready for rendering".to_string(),
367            ],
368        })
369    }
370
371    fn cleanup(&mut self) {
372        self.enabled = false;
373        self.chart_type = "bar".to_string();
374    }
375}