feat: scaffold Rust ML service crate

Create Rust crate skeleton with Cargo.toml, main.rs, and config.rs.
Includes package metadata, dependencies (anyhow, axum, image, ndarray,
ort, serde, tokio, tower, tracing), and config module with LABELS
constants, SERVICE_NAME, SERVICE_VERSION, DEFAULT_INPUT_SIZE, and
resolve_model_path function. Config tests verify label order, relative
path resolution, and absolute path preservation.

Also includes approved spec and implementation plan documents.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Asep Haryana Saputra
2026-05-23 09:23:38 +00:00
co-authored by Claude Opus 4.7
parent b735897dc2
commit 10e890cc42
5 changed files with 2016 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
[package]
name = "zeavis-ml-service"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0"
axum = { version = "0.7", features = ["multipart"] }
image = "0.25"
ndarray = "0.15"
ort = "2.0.0-rc.10"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1.0", features = ["macros", "rt-multi-thread", "net"] }
tower = "0.5"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
[dev-dependencies]
temp-env = "0.3"
+47
View File
@@ -0,0 +1,47 @@
use std::path::{Path, PathBuf};
pub const LABELS: [&str; 4] = ["Bercak Daun", "Daun Sehat", "Karat Daun", "Hawar Daun"];
pub const SERVICE_NAME: &str = "zeavis-ml-service";
pub const SERVICE_VERSION: &str = env!("CARGO_PKG_VERSION");
pub const DEFAULT_INPUT_SIZE: u32 = 224;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Config {
pub host: String,
pub port: u16,
pub model_path: PathBuf,
pub input_size: u32,
}
pub fn resolve_model_path(base_dir: &Path, model_path: &str) -> PathBuf {
let path = PathBuf::from(model_path);
if path.is_absolute() {
path
} else {
base_dir.join(path)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn labels_match_training_class_order_with_display_names() {
assert_eq!(LABELS, ["Bercak Daun", "Daun Sehat", "Karat Daun", "Hawar Daun"]);
}
#[test]
fn relative_model_path_resolves_from_service_directory() {
let base = Path::new("/repo/apps/ml-service");
let resolved = resolve_model_path(base, "../../Machine_Learning/model/model.onnx");
assert_eq!(resolved, PathBuf::from("/repo/apps/ml-service/../../Machine_Learning/model/model.onnx"));
}
#[test]
fn absolute_model_path_is_preserved() {
let base = Path::new("/repo/apps/ml-service");
let resolved = resolve_model_path(base, "/models/model.onnx");
assert_eq!(resolved, PathBuf::from("/models/model.onnx"));
}
}
+5
View File
@@ -0,0 +1,5 @@
mod config;
fn main() {
println!("zeavis-ml-service");
}