Artificial Intelligence Blogs Posts
cancel
Showing results for 
Search instead for 
Did you mean: 

As we all know AI is spreading across industries like wildfire and a lot of companies want to bring their own custom models into their SAP setups. In this blog I will walk you through a hands-on example of deploying a custom AI model to SAP AI Core. And then making it a callable service in SAP AI Launchpad and connecting it directly to a CAP backend.

Rather than relying on pre-built generative AI services, we demonstrate how to bring your own model, package it in Docker, register it in AI Launchpad, and call it from your backend using a deployment ID. The goal is to cover the whole journey from serving the model to getting real-time results right in your UI.

Requirements

If you are not running everything locally, you'll need admin roles for SAP AI Launchpad and AI Core. For a local setup, there's a build step. For running the trained model in Docker a GPU is recommended but not strictly mandatory. (A CPU will work, just slower) Make sure your machine has enough CPU power, memory and disk space. If you want GPU acceleration, you’ll need a compatible NVIDIA GPU, the right drivers, and CUDA support.

Getting Data Set For Model Training

You can grab image datasets from Roboflow, Kaggle, Google Open Images, or other publicly available sources. But if you plan to use your model for more than just experimenting, you have to check the licenses and usage rights carefully. Or just make your own dataset by collecting and labeling images for your actual use case. That way you’ve got control over both quality and compliance.

Running the Application Locally

The application is first run locally to verify that it works as expected after pushing the model to Docker.

The Dockerfile used for local testing

 

 

 

 

 

 

 

 

 

 

In the CAP application, the requires section in package.json is updated as follows:

"cds": {
  "sql": {
  },
  "requires": {
    "[production]": {
    },
    "[hybrid]": {
    },
    "barcode-ai": {
      "kind": "rest",
      "credentials": {
        "url": "http://localhost:8080",
        "requestTimeout": 300000
      }
    }
  },
  "auth": "xsuaa",
  "html5-runtime": true,
  "portal": true
},

On the UI side, users will upload barcode images through a FileUploader component.

<u:FileUploader
                    id="imageUploader"
                    name="myFileUpload"
                    fileType="jpg,jpeg,png"
                    placeholder="{i18n>selectBarcodeImg}"
                    change="onImageSelected"
                    width="300px" />

                <Button
                    text="{i18n>barcodeImgTrigger}"
                    type="Emphasized"
                    press="onAnalyzeBarcode"
                    class="sapUiMediumMarginTop" />

The controller then adds the uploaded image to a FormData object and fires off a POST request.

onAnalyzeBarcode: async function () {
      if (!this._selectedFile) {
        MessageToast.show("Test: Please Select An Image");
        return;
      }

      try {
        this.getView().setBusy(true);
        const formData = new FormData();
        formData.append("image", this._selectedFile);

        const response = await fetch(
          "/catalog/RoleSearchService/analyze-barcode",
          {
            method: "POST",
            body: formData
          }
        );

        if (!response.ok) {
          throw new Error("Test: Cant Call Ai Srv");
        }

        const result = await response.json();
        this.byId("resultText").setText(
          JSON.stringify(result, null, 2)
        );
      } catch (err) {
        MessageBox.error("Test: Barcode Srv Failed");
        console.error(err);
      } finally {
        this.getView().setBusy(false);
      }
    }

For local testing the service call in service.js points to your locally running API. With this end-to-end local test you can check if the API can spot barcodes in uploaded images. And if so, pull out their locations, values, types and confidence scores.

The request-response structure of the local test service

 

AI Launchpad Connections

Once you've pushed your project that includes the Dockerfile, serve.py, requirements.txt, and serving_template.yaml to the GitHub, head over to SAP AI Launchpad.

Application settings in AI Launchpad for local testing

Under SAP AI Core Administration, go to Git Repositories and add your GitHub URL. Once the repository is synced, open All Applications and then create a new application. Pick your repository, set the path to (.), and revision to (main).

With the application synced, move to ML Operations and open Scenarios. You will see the serving_template.yaml is picked up automatically as an executable. The template defines the Docker image to run, the container port, resource requests, and the imagePullSecret pointing to our Docker Hub credentials, which are registered separately under Docker Registry Secrets.

blog-barcode_scenario.png

 

 

Next, make a Configuration under the scenario, linking the executable to a resource group.

One important detail here is that the serving_template.yaml must define the metadata annotations, labels, and spec fields as pipe-delimited strings rather than nested YAML objects. This is a requirement of the SAP AI Core ServingTemplate schema that differs from standard Kubernetes manifests.

apiVersion: ai.sap.com/v1alpha1
kind: ServingTemplate
metadata:
  name: barcode-reader-serving
  namespace: <your-namespace>
  labels:
    scenarios.ai.sap.com/id: "barcode-scenario"
    ai.sap.com/version: "1.0.0"
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/metric: rps
        autoscaling.knative.dev/target: "100"
    spec:
      containers:
        - name: kserve-container
          image: "<your-dockerhub-username>/barcode-reader:latest"
          ports:
            - containerPort: 8080
              protocol: TCP
          command: ["uvicorn", "serve:app", "--host", "0.0.0.0", "--port", "8080"]
          resources:
            requests:
              cpu: "0.5"
              memory: "512Mi"
            limits:
              cpu: "1"
              memory: "1Gi"

 

Once your configuration is set trigger a Deployment. Use the infer.m resource plan, as it gives enough compute. After a few minutes the deployment will reach Running status with a unique Deployment ID.

Deployment Details in SAP AI Launchpad

 


Model binding in the updated package.json

Take that Deployment ID and put it into the cds.requires section of package.json under the barcode-ai destination. Now you can pass base64-encoded images in the request and get back barcode predictions from your CAP service layer.

 

 

 

 

 

onAnalyzeBarcode: async function () {
      if (!this._selectedFile) {
        MessageToast.show("Please choose an image first!");
        return;
      }
      try {
        this.getView().setBusy(true);
        const arrayBuffer = await this._selectedFile.arrayBuffer();
        const base64 = btoa(
          new Uint8Array(arrayBuffer)
            .reduce((data, byte) => data + String.fromCharCode(byte), '')
        );
        const response = await fetch("/catalog/SIAService/analyzeBarcodeImage", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ image: base64 })
        });
        if (!response.ok) {
          throw new Error("Error in Ai srv call");
        }
        const raw = await response.json();
        const result = typeof raw.value === 'string' ? JSON.parse(raw.value) : raw.value;

        if (!result.barcodeValue) {
          this.byId("resultText").setText("No barcode detected in the image");
          return;
        }

        this.byId("resultText").setText(
          `Barcode: ${result.barcodeValue} | Type: ${result.confidence || "-"}`
        );

        MessageToast.show("Barcode Scanned Successfully!");

      } catch (err) {
        MessageBox.error("Barcode Analysis Failed: " + err.message);
        console.error(err);
      } finally {
        this.getView().setBusy(false);
      }
    }

 

this.on('analyzeBarcodeImage', async (req) => {
      try {
        const image = req.data.image;
        if (!image) {
          req.error(400, 'Image is required');
          return;
        }

        const barcodeAI = await cds.connect.to('<Your_Destination>');
        const deploymentId = '<deploymentId>';
        const response = await barcodeAI.send({
          method: 'POST',
          path: `/v2/inference/deployments/${deploymentId}/v2/models/barcode-model/infer`,
          headers: {
            'Content-Type': 'application/json',
            'AI-Resource-Group': 'default'
          },
          data: {
            image: image
          }
        });

        // response.predictions → [{data, type, rect}]
        const predictions = response?.predictions || [];

        if (predictions.length === 0) {
          return JSON.stringify({ barcodeValue: null, confidence: null, message: 'Barcode not found' });
        }

        return JSON.stringify({
          barcodeValue: predictions[0].data,
          confidence: predictions[0].type,
          allResults: predictions
        });

      } catch (err) {
        console.error('analyzeBarcodeImage error:', err);
        req.error(500, 'Barcode inference failed');
      }
    });

 

Once we have everything wired up and the CAP app is running, we head back to the frontend and run our test by uploading two images, one with a barcode and one without.

Barcode Detection In Action Test1

Barcode Detection In Action Test2

Future Improvements

The big takeaway integrating custom models with AI Launchpad is straightforward. And once you’ve plugged it in, you can use it across all kinds of projects with remarkable ease. That smooth integration makes a huge difference.

You can level this up in a bunch of ways. For example fine-tune a model like YOLOv8 for tricky conditions like dim lighting or angled shots or add QR code support with minimal changes or handle damaged barcodes by searching for similar visual embeddings in a database.

Summary

This blog walked through the full integration path of deploying a custom AI model to SAP AI Core and consuming it from a CAP backend. Instead of relying on a managed generative AI service, the model was packaged in Docker, registered in SAP AI Launchpad via a serving template, and called from the CAP backend using a deployment ID over the AI Launchpad Destination.

The result is a working barcode detection feature that runs entirely on SAP infrastructure, with the model hosted and scaled by AI Core and the business logic kept cleanly within the CAP service layer. And as we covered, this is just the start. The architecture is flexible. Fine-tune for complex real world scenarios, tack on QR codes, or deal with scenarios like damaged barcodes using similarity search.

Hopefully, this gives consultants a clear roadmap for moving past generic AI tools and plugging their own models into real world solutions. You're not limited to barcodes either. This blueprint works for custom vision models, language models, whatever you need.

If you have any questions or thoughts, feel free to leave a comment below.

Ege Aksöyek

Labels in this area