Inferencer Node
Overview
The Inferencer node provides AI-powered computer vision inference by running machine learning models in Docker containers. It acts as a bridge between Node-RED flows and Python-based ML models, supporting detection, classification, segmentation, anomaly detection, and OCR tasks.
The node uses a modular 7-stage inference pipeline and communicates with the inference server via gRPC.
Key Features
- Multiple ML frameworks: YOLO, PaddlePaddle, RF-DETR, TensorRT, Anomalib
- Task support: Object detection, image classification, instance/semantic segmentation, anomaly detection, OCR, recognition
- Docker-based execution: Isolated Python containers with automatic lifecycle management
- Dynamic worker scaling: Scale inference workers without restarting containers
- Dynamic models: Load models at runtime or configure statically
- Always-on warmup: Server-side synthetic image generation for zero cold-start latency
- Firebase integration: Automatic model download from Firebase storage with unified model dropdown
- Promise mode: Asynchronous processing for high-throughput batch workflows
- Config prefabs: 13 pre-built model type configurations for quick setup
- Output customization: Configure detection boxes, masks, and result formats
- Class mapping: Rename or filter model output classes
- Debug visualization: Display processed images on Node-RED canvas
- Performance tracking: Built-in metrics at
msg.performance.inference.{node_name}
Architecture
Inference Pipeline
The node processes each request through a 7-stage modular pipeline:
validate-request → resolve-model → ensure-model → process-images → execute-inference → convert-results → assemble-response- validate-request: Validates input message structure and image format
- resolve-model: Determines target model (static config or dynamic from message)
- ensure-model: Downloads model from Firebase if needed, verifies model availability
- process-images: Reads and preprocesses images (format conversion, color space)
- execute-inference: Sends gRPC request to inference server, handles concurrency
- convert-results: Transforms raw protobuf results into output format
- assemble-response: Builds final message with results and performance metrics
Components
- Node-RED Node: Configuration, message routing, and pipeline orchestration
- Docker Containers: Python inference servers (1-10 worker instances)
- gRPC Protocol: Communication between Node-RED and containers
- Model Storage:
/opt/storage/models/directory - Firebase: Optional model download source
Data Flow
Input Images → Pipeline → gRPC → Docker Container → ML Model → Predictions → Output
↓
Dynamic Worker ScalingSupported Model Types
| Framework | Task | Config Prefab |
|---|---|---|
| YOLO | Detection | yolo_detection |
| YOLO | Classification | yolo_classification |
| YOLO | Segmentation | yolo_segmentation |
| PaddlePaddle | Detection | paddle_detection |
| PaddlePaddle | OCR | paddle_ocr |
| PaddlePaddle | Recognition | paddle_recognition |
| PaddlePaddle | Document Rotation | paddle_document_rotation |
| Pipeline | OCR | pipeline_ocr |
| RF-DETR | Detection | rfdetr_detection |
| TensorRT | Classification | tensorrt_classification |
| TensorRT | Detection | tensorrt_detection |
| TensorRT | Segmentation | tensorrt_segmentation |
| Anomalib | Anomaly | anomaly_anomaly |
Configuration
Settings Tab
Name
- Type: String
- Optional: Yes
- Description: Display name for the node
Input Field
- Type: Message property path
- Default:
payload - Description: Message field containing input images (single image or array)
Output Field
- Type: Message property path
- Default:
payload - Description: Where inference results will be stored
- Note: Performance stats saved to
msg.performance.inference.{node_name}
Model Source
- Type: Select
- Options:
- Select here: Choose from available models in
/opt/storage/modelsor from Firebase (unified dropdown) - Dynamic: Provide model name at runtime via message/flow/global property
- Select here: Choose from available models in
Model Name (Static Mode)
- Type: Dropdown (unified Firebase + local models)
- Description: Select from available models — shows model name, task type, framework, and source (local/Firebase)
Model Field (Dynamic Mode)
- Type: TypedInput (msg, flow, global)
- Example:
msg.modelName,flow.currentModel,global.activeModel - Description: Property path containing model name at runtime
- Note: Enables automatic model download if Firebase is configured
Promise Mode
- Type: Checkbox
- Default: Disabled
- Description: Return promises instead of waiting for results
- Use Case: High-throughput batch processing — resolve promises in a downstream function node using
Promise.all()
Promises Field
- Type: Message property path
- Default:
promises - Visible: When Promise Mode enabled
- Description: Array field to store pending promises
Number of Workers
- Type: Number
- Range: 1-10
- Default: 1
- Description: Inference worker instances for load balancing
- Note: Workers scale dynamically without container restart (since v1.2.1)
Maximum Concurrent Predictions
- Type: Number
- Range: 1-20
- Default: 5
- Description: Parallel requests per server
- Behavior: Excess requests queue until slot available
Show Debug Image
- Type: Checkbox
- Default: Disabled
- Description: Display processed images on Node-RED canvas
Debug Interval
- Type: Number
- Default: 1
- Visible: When debug enabled
- Description: Show every Nth image (1 = all images)
Debug Image Width
- Type: Number (pixels)
- Default: 200
- Visible: When debug enabled
- Description: Display width for debug images
JSON Config Tab
Advanced model configuration in JSON format. Structure varies by model type. Each model type has a corresponding config prefab that provides sensible defaults.
Common Fields (All Models)
{
"common": {
"model_name": "my-model",
"config_type": "predict",
"task": "Detection",
"device": "auto",
"image_shape": {
"width": 640,
"height": 640
},
"verbose": false,
"max_batch": 100
}
}Fields:
model_name: Model identifierconfig_type: Always "predict"task: Detection, Classification, Segmentation, Anomaly, OCR, Recognitiondevice: "auto", "cpu", "cuda", "mps"image_shape: Target dimensions for resizingverbose: Enable detailed loggingmax_batch: Maximum batch size
Detection Models (YOLO, RF-DETR, PaddlePaddle, TensorRT)
{
"common": { },
"task_specific": {
"conf_threshold": 0.5,
"nms_iou_threshold": 0.7,
"max_det": 300
}
}Classification Models
{
"common": { },
"task_specific": {
"top_k": 5
}
}Segmentation Models (YOLO, TensorRT)
{
"common": { },
"task_specific": {
"conf_threshold": 0.5,
"retina_masks": true
}
}Anomaly Detection
{
"common": { },
"task_specific": {
"threshold": 0.5,
"normalize": true
},
"model_specific": {
"optional": {
"image_threshold": 0.5,
"pixel_threshold": 0.5
}
}
}TensorRT Batch Configuration
TensorRT models support batch size tuning via model_specific:
{
"model_specific": {
"optional": {
"half": true,
"min_batch": 1,
"opt_batch": 4,
"max_batch": 16
}
}
}Constraint: min_batch <= opt_batch <= max_batch
Output Formats Tab
Configure detection and segmentation output formats.
Detection Output Formats
- boxes_xyxy: Bounding boxes [x1, y1, x2, y2] (top-left, bottom-right)
- boxes_xywh: Bounding boxes [x_center, y_center, width, height]
- boxes_tlwh: Bounding boxes [x_top_left, y_top_left, width, height]
- boxes_corners: Four corners [[x1,y1], [x2,y2], [x3,y3], [x4,y4]]
Segmentation Output Formats
- masks_rle: Run-length encoding (compact format)
- masks_polygon: Polygon contours
- masks_bitmap: Binary pixel masks
Classes Tab
Map or filter model output classes.
Features:
- Rename classes to custom labels
- Filter results by remapping to empty string
- Per-model configuration storage
Example:
Original: "person" → Custom: "human"
Original: "car" → Custom: "vehicle"
Original: "background" → Custom: "" (filtered out)Image Format
The node accepts multiple image formats:
1. Rosepetal Bitmap Format
{
width: 1920,
height: 1080,
data: Buffer, // Raw pixel data
colorSpace: "RGB", // "GRAY", "RGB", "RGBA", "BGR", "BGRA"
channels: 3, // Auto-inferred if omitted
dtype: "uint8" // Currently only uint8 supported
}Color space mapping:
GRAY: 1 channelRGB/BGR: 3 channelsRGBA/BGRA: 4 channels
2. JPEG/PNG Buffers
msg.payload = fs.readFileSync('image.jpg');The node automatically decodes standard image formats.
3. Array of Images
msg.payload = [image1, image2, image3];Processes multiple images in batch for improved performance.
Input
Basic Input
msg.payload = imageBuffer;
return msg;Dynamic Model Selection
// Configure node with Model Source: Dynamic, Model Field: msg.modelName
msg.modelName = "yolo-detection-v8";
msg.payload = imageBuffer;
return msg;Warmup Request
msg.warmup = true;
return msg;Triggers model warmup. The server generates a synthetic image internally — no need to provide one.
Inferencer Request (Control Messages)
// Load a specific model
msg.inferencerRequest = { type: "loadModel", modelName: "my-model" };
// Unload the current model
msg.inferencerRequest = { type: "unloadModel" };
// Trigger warmup
msg.inferencerRequest = { type: "warmup" };Output
Detection Results
{
payload: [
{
box: {
xyxy: [100, 150, 300, 400],
xywh: [200, 275, 200, 250],
confidence: 0.95
},
class: "person",
class_id: 0
}
],
performance: {
inference: {
"my-inferencer": {
inferenceTime: 45.2,
preprocessTime: 5.1,
postprocessTime: 3.8,
totalTime: 54.1
}
}
}
}Classification Results
{
payload: [
{ class: "cat", class_id: 281, confidence: 0.98 },
{ class: "dog", class_id: 179, confidence: 0.01 }
]
}Segmentation Results
{
payload: [
{
box: { xyxy: [100, 150, 300, 400] },
class: "person",
mask: {
rle: "...",
polygon: [[x1, y1], [x2, y2], ...],
bitmap: Buffer
}
}
]
}Promise Mode Output
{
promises: [
Promise { <pending> },
Promise { <pending> }
]
}Resolve in a function node:
msg.results = await Promise.all(msg.promises);
return msg;Usage Examples
Example 1: Simple Object Detection
// Function node: Load image
msg.payload = {
width: 640, height: 480,
data: imageBuffer,
colorSpace: "RGB"
};
return msg;Inferencer configuration:
- Model: yolo-v8-detection
- Input: payload
- Output: detections
// Function node: Filter high confidence
msg.payload = msg.detections.filter(det => det.box.confidence > 0.8);
return msg;Example 2: Batch Processing
// Function node: Prepare batch
msg.payload = [
{ width: 640, height: 480, data: buffer1, colorSpace: "RGB" },
{ width: 640, height: 480, data: buffer2, colorSpace: "RGB" },
{ width: 640, height: 480, data: buffer3, colorSpace: "RGB" }
];
return msg;Output:
msg.payload = [
[detection1a, detection1b], // Results from image 1
[detection2a], // Results from image 2
[] // No detections in image 3
];Example 3: Dynamic Model Selection
// Function node: Choose model based on input
if (msg.topic === "quality-check") {
msg.modelName = "defect-detection-model";
} else if (msg.topic === "classification") {
msg.modelName = "product-classifier";
}
msg.payload = imageData;
return msg;Example 4: Multi-Model Pipeline
[Camera] → [Inferencer: Detection] → [Function: Crop] → [Inferencer: Classification] → [Output]Detection step:
msg.detections = msg.payload;
msg.payload = cropDetections(msg.payload); // Extract regions
return msg;Classification step:
msg.classifications = msg.payload;
return msg;Performance Optimization
Concurrency Settings
Low throughput (sporadic requests):
- Workers: 1
- Max concurrent: 5
High throughput (production):
- Workers: 3-10
- Max concurrent: 10-20
Batch Processing
Optimal batch size:
- Small models (YOLO-nano): 10-20 images
- Medium models (YOLO-v8): 5-10 images
- Large models (Segmentation): 2-5 images
Model Warmup
Warmup is always enabled (since v1.2.1). The server generates a synthetic image internally on startup, eliminating cold-start latency on the first real request.
Docker Container Management
Container Lifecycle
- Startup: Node creates Docker container with inference server
- Health Check: Waits for gRPC handshake
- Warmup: Server-side synthetic image warmup
- Running: Process inference requests
- Shutdown: Clean container removal on deploy/close
Container Image
europe-southwest1-docker.pkg.dev/rosepetal-artifact/node-red-vp/rosepetal-detection:<tag>Container Logs
# View container logs
docker logs <container-id>
# Find inferencer containers
docker ps | grep rosepetal-servingMemory Usage
Per container (approximate):
- YOLO-nano: 500MB-1GB
- YOLO-v8: 2GB-4GB
- Segmentation: 4GB-8GB
- PaddlePaddle OCR: 2GB-3GB
Worker scaling multiplies memory usage proportionally.
Model Management
Model Directory Structure
/opt/storage/models/
├── yolo-v8-detection/
│ ├── model.pt
│ └── config.json
├── product-classifier/
│ ├── model.onnx
│ └── config.json
└── segmentation-model/
├── model.pt
└── config.jsonAdding Models Manually
- Create directory:
/opt/storage/models/<model-name>/ - Copy model file:
model.pt,model.onnx, etc. - Create
config.json(optional, for auto-detection) - Refresh Node-RED editor
Firebase Model Download
Requirements:
- Firebase config node connected
- Model exists in Firebase storage
- Dynamic mode enabled or Firebase model selected in unified dropdown
Behavior:
- Checks local storage first
- Downloads if missing
- Caches for future use
- Shows download progress in status
Error Handling
Common Errors
"Docker image not available"
- Cause: Inference Docker image not pulled
- Solution:
docker pull <image-name>
"Model not found"
- Cause: Model doesn't exist in
/opt/storage/models - Solution: Verify model name, check directory, download if needed
"Container failed to start"
- Cause: Port conflict, insufficient memory, corrupted model
- Solution: Check Docker logs, verify system resources
"gRPC connection failed"
- Cause: Container not ready, network issue
- Solution: Wait for container startup, check Docker status
"Invalid image format"
- Cause: Missing required fields, wrong data type
- Solution: Validate image object structure
"CUDA out of memory"
- Cause: Batch too large, concurrent requests exceeded capacity
- Solution: Reduce batch size, lower concurrency, use CPU
"TensorRT batch config invalid"
- Cause: min_batch, opt_batch, max_batch constraint violated
- Solution: Ensure min_batch <= opt_batch <= max_batch
Debugging
Enable verbose logging:
{
"common": {
"verbose": true
}
}Check container logs:
docker logs <container-id>Enable debug visualization:
- Check "Show debug image"
- Set debug interval: 1
- Verify images display correctly
Best Practices
Model Selection
- Match task to model: Detection vs Classification vs Segmentation
- Consider speed/accuracy tradeoff: nano (fast) vs large (accurate)
- Use TensorRT for production: Optimized inference on NVIDIA GPUs
- Test on representative data: Validate before production
- Version models: Track changes, enable rollback
Configuration
- Use config prefabs: Start from built-in configurations for each model type
- Document class mappings: Clear naming conventions
- Set appropriate thresholds: Balance false positives/negatives
Maintenance
- Clean up unused containers:
docker system prune - Monitor disk space: Models can be large
- Update Docker images: Stay current with improvements
- Log performance metrics: Track degradation over time
Troubleshooting
Slow Inference
Possible causes:
- Model too large for hardware
- CPU inference on GPU model
- High concurrent load
Solutions:
- Use smaller model variant or TensorRT optimization
- Enable GPU if available
- Reduce concurrency
- Cache models locally
High Memory Usage
Possible causes:
- Too many workers
- Large batch sizes
- Memory leak in model
Solutions:
- Reduce number of workers
- Process smaller batches
- Restart containers periodically
- Update to latest image
Inconsistent Results
Possible causes:
- Wrong color space
- Incorrect image dimensions
- Threshold too sensitive
Solutions:
- Validate input format
- Check preprocessing
- Adjust confidence thresholds
- Enable debug visualization
See Also
- Triton Inferencer Node - TensorRT-optimized inference via NVIDIA Triton
- OCR Inferencer Node - Specialized OCR inference
- Dataset Upload Node - Upload training data
- Firebase Config Node - Configure Firebase access
- Vision Platform Overview - Complete platform documentation