Spring Boot සහ TensorFlow Java | ML API Integration Sinhala Guide

Spring Boot සහ TensorFlow Java | ML API Integration Sinhala Guide

ඉතින් කොහොමද යාලුවනේ! අද අපි කතා කරන්න යන්නේ මේ වෙනකොට හැම තැනම වගේ තියෙන Artificial Intelligence (AI) සහ Machine Learning (ML) කියන දේවල් අපේ Software Applications වලට ගලපගන්නේ කොහොමද කියලා.

අපි ගොඩක් දෙනෙක් Java, විශේෂයෙන්ම Spring Boot එක්ක වැඩ කරනවා නේ. එතකොට අපිට හිතෙන්න පුළුවන්, Python වල හදපු Machine Learning Model එකක් Java Application එකක් ඇතුළට ගෙනැත්, API එකක් හරහා ඒකෙන් predictions ලබා දෙන්නේ කොහොමද කියලා. ඔව්, මේක කරන්න පුළුවන්! අද අපි ඒ ගැන පියවරෙන් පියවර බලමු.

මේ tutorial එක අවසානය වන විට, ඔබට Spring Boot Application එකක් තුළ TensorFlow Java භාවිතයෙන් Machine Learning Model එකක් load කර, REST API එකක් හරහා predictions ලබා දීමට හැකියාව ලැබේවි. මේ දැනුම ඔයාගේ ඊළඟ AI-powered project එකට ගොඩක් වැදගත් වෙයි!

AI/ML සහ Spring Boot: ඇයි මේක වැදගත්?

අද කාලේ applications වලට AI/ML functionality එකතු කිරීම ගොඩක් වැදගත් වෙලා තියෙනවා. Recommendation systems, fraud detection, natural language processing (NLP) වගේ ගොඩක් දේවල් වලට Machine Learning models යොදා ගන්නවා.

Python කියන්නේ Machine Learning model training වලට ගොඩක් ජනප්‍රිය භාෂාවක්. ඒත්, production-ready enterprise applications හදන්න Java සහ Spring Boot ගොඩක් ප්‍රබලයි. ඒකෙන් අපිට scalability, robustness, security වගේ ගොඩක් දේවල් ලැබෙනවා.

TensorFlow Java කියන්නේ Google එකෙන් දෙන API එකක්. මේකෙන් පුළුවන් Python වලින් TensorFlow එකේ train කරපු models, Java applications ඇතුළේ load කරලා, run කරන්න. මේකෙන් අපිට Java ecosystem එකේම ඉඳගෙන, ML models අපේ applications වලට එකතු කරන්න පුළුවන්කම ලැබෙනවා. මේක Microservices architecture එකකදී නම් තවත් ලොකු වාසියක්.

අවශ්‍ය දේවල් සූදානම් කරගනිමු (Setting Up the Environment)

මේ tutorial එකට අපිට අවශ්‍ය මූලික දේවල් ටිකක් තියෙනවා:

  • Java Development Kit (JDK) 17 හෝ ඊට වැඩි version එකක්.
  • Maven හෝ Gradle (අපි Maven භාවිතා කරමු).
  • IDE එකක් (IntelliJ IDEA, VS Code, Eclipse වගේ එකක්).
  • Internet connection එකක් (dependencies download කරගන්න).

Spring Boot Project එකක් හදා ගනිමු

මුලින්ම අපි Spring Initializr (https://start.spring.io/) එකට ගිහින් අලුත් Spring Boot project එකක් හදා ගමු. මේ විදියට settings දාගන්න:

  • Project: Maven Project
  • Language: Java
  • Spring Boot: 3.x (latest stable version)
  • Group: com.example
  • Artifact: ml-prediction-service
  • Java: 17
  • Dependencies: Spring Web

දැන් Generate බොත්තම ඔබලා project එක download කරගෙන, ඔයාගේ IDE එකේ extract කරලා open කරගන්න.

TensorFlow Java Dependency එක එකතු කරමු

ඊළඟට, අපිට TensorFlow Java අවශ්‍ය වෙනවා. ඒක project එකට එකතු කරන්න, ඔයාගේ pom.xml file එකට පහත dependency එක <dependencies> tag එක ඇතුළට එකතු කරන්න:

<dependency>
    <groupId>org.tensorflow</groupId>
    <artifactId>tensorflow-core-platform</artifactId>
    <version>0.5.0</version> <!-- නවතම stable version එක භාවිතා කරන්න -->
</dependency>

Version එක (0.5.0) වෙනස් වෙන්න පුළුවන්, ඒ නිසා Maven Repository එකෙන් නවතම stable version එක බලාගන්න. Maven dependencies update කරන්න අමතක කරන්න එපා.

ML Model එකක් Load කරලා Predict කරමු (Loading and Predicting with a ML Model)

අපි මේ tutorial එකට pre-trained SavedModel format එකේ තියෙන TensorFlow model එකක් භාවිතා කරනවා. මේ model එක Python වලින් train කරපු එකක් වෙන්න පුළුවන්. example එකක් විදියට, input number එකක් double කරන ඉතාම සරල model එකක් ගැන අපි හිතමු.

ඔයාට මේ වගේ model එකක් download කරගන්න පුළුවන්, නැත්නම් Python එකෙන් හදාගන්න පුළුවන්. ඒ model එක project එකේ src/main/resources/ml_models/simple_model වගේ path එකක තියන්න.

Prediction Service එකක් හදමු

දැන් අපි model එක load කරලා, ඒකෙන් predictions ලබා දෙන Java service එකක් හදා ගමු. com.example.mlpredictionservice package එක ඇතුළේ PredictionService.java කියලා class එකක් හදන්න.

package com.example.mlpredictionservice;

import org.springframework.stereotype.Service;
import org.tensorflow.SavedModelBundle;
import org.tensorflow.Tensor;
import org.tensorflow.Session;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.stream.Stream;

@Service
public class PredictionService {

    private SavedModelBundle model; // TensorFlow model එක load කරන්න

    // model path එක resources folder එකේ
    private final String MODEL_PATH = "ml_models/simple_model"; 

    @PostConstruct
    public void loadModel() {
        try {
            // ClassLoader එකෙන් resource path එක ගන්න
            Path modelDirectory = Paths.get(Objects.requireNonNull(
                getClass().getClassLoader().getResource(MODEL_PATH)).toURI());
            
            System.out.println("Loading TensorFlow model from: " + modelDirectory);
            // SavedModelBundle එක load කරන්න
            model = SavedModelBundle.load(modelDirectory.toString(), "serve");
            System.out.println("TensorFlow model loaded successfully!");
        } catch (Exception e) {
            System.err.println("Error loading TensorFlow model: " + e.getMessage());
            e.printStackTrace();
            // Critical error: application එක shutdown කරන්න පුළුවන්
            // SpringApplication.exit(context, () -> 1);
        }
    }

    public float predict(float input) {
        if (model == null) {
            throw new IllegalStateException("Model is not loaded.");
        }

        // Input data එක Tensor එකක් විදියට හදන්න
        try (Tensor<Float> inputTensor = Tensor.create(input, Float.class)) {
            // Session එකෙන් model එක run කරන්න
            Session.Runner runner = model.session().runner();
            
            // Model එකේ input node එකේ නම 'x' කියලත්, output node එකේ නම 'y' කියලත් අපි හිතමු
            // මේ නම් model එක හදනකොට දීපු නම්
            runner.feed("serving_default_x", inputTensor); // Input tensor එක feed කරන්න
            runner.fetch("serving_default_y"); // Output tensor එක fetch කරන්න

            // Model එක run කරලා results ගන්න
            try (Stream<Tensor<?>> outputTensors = runner.run().stream()) {
                Tensor<?> outputTensor = outputTensors.findFirst()
                                                        .orElseThrow(() -> new RuntimeException("No output tensor found."));
                
                // Output tensor එක float එකක් විදියට ගන්න
                float[] result = new float[1];
                outputTensor.copyTo(result);
                return result[0]; // First element එක return කරන්න
            }
        }
    }

    @PreDestroy
    public void closeModel() {
        if (model != null) {
            model.close(); // Model එකේ resources නිදහස් කරන්න
            System.out.println("TensorFlow model closed.");
        }
    }
}

ඉහත කේතය සඳහා වැදගත් සටහන්:

  • MODEL_PATH: මේක ඔයාගේ model file එක resources folder එකේ තියෙන path එක. SavedModel එකක් කියන්නේ folder එකක්. ඒක ml_models/simple_model වගේ තියෙන්න ඕනේ.
  • @PostConstruct: Spring Boot application එක start වෙනකොටම model එක load කරන්න මේක භාවිතා කරනවා.
  • @PreDestroy: application එක shutdown වෙනකොට model එකේ resources නිදහස් කරන්න මේක භාවිතා කරනවා.
  • feed("serving_default_x", inputTensor) සහ fetch("serving_default_y"): මේවා TensorFlow model එකේ input සහ output nodes වල නම්. මේවා ඔයාගේ model එක හදනකොට දීපු නම් වලට අනුව වෙනස් වෙන්න පුළුවන්. Python වලදී model.signatures['serving_default'].inputs සහ model.signatures['serving_default'].outputs බලලා මේ නම් හොයාගන්න පුළුවන්.

REST API එකක් හරහා Prediction Serve කරමු (Serving Predictions via a REST API)

දැන් අපි PredictionService එකෙන් predictions ලබා ගන්න පුළුවන් REST API endpoint එකක් හදමු. මේකට අපි Spring MVC RestController එකක් භාවිතා කරනවා.

com.example.mlpredictionservice package එක ඇතුළේ PredictionController.java කියලා class එකක් හදන්න.

package com.example.mlpredictionservice;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
@RequestMapping("/api/predict")
public class PredictionController {

    private final PredictionService predictionService;

    @Autowired
    public PredictionController(PredictionService predictionService) {
        this.predictionService = predictionService;
    }

    @PostMapping
    public ResponseEntity<Map<String, Float>> getPrediction(@RequestBody Map<String, Float> requestBody) {
        // Request body එකෙන් 'input' කියන key එකේ value එක ගන්න
        Float input = requestBody.get("input"); 

        if (input == null) {
            return ResponseEntity.badRequest().body(Map.of("error", 0.0f)); // Invalid input
        }

        try {
            float prediction = predictionService.predict(input);
            return ResponseEntity.ok(Map.of("prediction", prediction));
        } catch (IllegalStateException e) {
            return ResponseEntity.status(503).body(Map.of("error", -1.0f, "message", (float) e.getMessage().hashCode())); // Model not loaded
        } catch (Exception e) {
            return ResponseEntity.internalServerError().body(Map.of("error", -2.0f, "message", (float) e.getMessage().hashCode())); // Other errors
        }
    }
}

මේ controller එකේ, /api/predict POST request එකකට, අපි request body එකෙන් input කියන float value එක අරන්, predictionService එකට දෙනවා. ඒකෙන් එන prediction එක JSON response එකක් විදියට ආපහු දෙනවා.

මෙය Test කරමු

දැන් ඔයාගේ Spring Boot Application එක run කරන්න. console එකේ model loading messages ටික බලාගන්න පුළුවන්.

දැන් අපිට API එක test කරන්න Postman, Insomnia වගේ tool එකක්, නැත්නම් curl command එකක් භාවිතා කරන්න පුළුවන්.

curl -X POST \
  http://localhost:8080/api/predict \
  -H 'Content-Type: application/json' \
  -d '{ "input": 10.5 }'

මේ request එකෙන් ඔයාට මේ වගේ response එකක් බලාගන්න පුළුවන් (අපේ model එක input එක double කරනවා නම්):

{
    "prediction": 21.0
}

වැඩිදුරටත්: Performance, Error Handling, සහ Best Practices

මේක මූලික setup එකක්. real-world production environment එකකට මේක යොදා ගන්න කලින් තවත් ගොඩක් දේවල් ගැන හිතන්න ඕනේ.

Performance Optimization

  • Model Loading Time: models ගොඩක් ලොකු නම් load වෙන්න වෙලාව යනවා. Lazy loading, multiple instances වලට model එක pre-load කරන එක වගේ දේවල් ගැන හිතන්න පුළුවන්.
  • Batch Predictions: එක input එකක් වෙනුවට inputs batch එකක් අරන් predict කරන එක ගොඩක් කාර්යක්ෂමයි. TensorFlow Java API එක batch predictions වලට support කරනවා.
  • Hardware Acceleration: GPU acceleration (CUDA) හෝ CPU-specific optimizations (MKL) TensorFlow Java එක්ක භාවිතා කරන්න පුළුවන්. ඒකට අවශ්‍ය native libraries setup කරන්න ඕනේ.

Error Handling

  • Model Not Found: model එක load වෙන්නේ නැත්නම් application එක නිවැරදිව handle කරන්න ඕනේ. @PostConstruct එකේ exception handling හොඳට කරන්න.
  • Invalid Input: API එකට එන input data model එකට අනුකූලද කියලා validate කරන්න ඕනේ.
  • TensorFlow Exceptions: prediction කරනකොට TensorFlow runtime exceptions ඇතිවෙන්න පුළුවන්. ඒවා නිවැරදිව catch කරලා user-friendly error messages දෙන්න.

Resource Management

  • Tensor Objects: TensorFlow Java වලදී Tensor.create() වලින් Tensor එකක් හදුවාම, ඒක try-with-resources block එකක් ඇතුළේ භාවිතා කරලා automatically close කරන්න (මම උඩ code එකේ පෙන්නුවා වගේ) නැත්නම් අතින් tensor.close() කරන්න අමතක කරන්න එපා. නැත්නම් memory leaks වෙන්න පුළුවන්.
  • SavedModelBundle: model එක application එකෙන් නිදහස් වෙනකොට model.close() කරන්න ඕනේ. @PreDestroy මේකට හොඳම තැනක්.

Scalability සහ Deployment

  • Microservices: ML prediction service එක වෙනම microservice එකක් විදියට deploy කරන එක ගොඩක් හොඳයි. ඒකෙන් isolation සහ independent scaling පහසු වෙනවා.
  • Cloud Deployment: AWS Lambda (GraalVM native images එක්ක), Google Cloud Run, Kubernetes වගේ platforms වලට deploy කරන්න පුළුවන්.

අවසානයට

ඉතින් යාලුවනේ, ඔයාලට දැන් තේරෙනවා ඇති Spring Boot සහ TensorFlow Java එකතු කරලා Machine Learning Model එකක් REST API එකක් හරහා serve කරන්නේ කොහොමද කියලා.

මේ tutorial එක ඔයාලට AI/ML capabilities ඔයාලගේ Java applications වලට ගලපගන්න හොඳ පදනමක් ලබා දෙන්න ඇති කියලා මම හිතනවා. මේක ඉතාම බලවත් සංයෝගයක්, විශේෂයෙන්ම enterprise-grade production systems වලට.

මේක ඔයාගේ ඊළඟ project එකට implement කරලා බලන්න. ඔයාගේ අත්දැකීම්, ගැටලු, නැත්නම් මේ ගැන අලුත් අදහස් පහළ comment section එකේ අපිට කියන්න. අපි කතා කරමු!

තවත් මේ වගේ tutorials වලින් හමුවෙමු! සුභ දවසක්!