이 문서에서는 Azure IoT Operations 데이터 흐름 그래프의 일부로 대역 내 유추를 수행하기 위해 WebAssembly 모듈 내에 작은 ONNX(Open Neural Network Exchange) 모델을 포함하고 실행하는 방법을 보여 줍니다. 외부 예측 서비스를 호출하지 않고 스트리밍 데이터에서 직접 낮은 지연 시간의 데이터 보강 및 분류에 이 방법을 사용합니다.
중요합니다
데이터 흐름 그래프는 현재 MQTT(메시지 큐 원격 분석 전송), Kafka 및 OpenTelemetry 엔드포인트만 지원합니다. Data Lake, Microsoft Fabric OneLake, Azure Data Explorer 및 로컬 스토리지와 같은 다른 엔드포인트 형식은 지원되지 않습니다. 자세한 내용은 알려진 문제참조하세요.
대역 내 ONNX 간섭을 사용하는 이유
Azure IoT Operations 데이터 흐름 그래프를 사용하면 외부 예측 서비스를 호출하는 대신 파이프라인에 직접 작은 ONNX 모델 유추를 포함할 수 있습니다. 이 방법은 다음과 같은 몇 가지 실질적인 이점을 제공합니다.
- 짧은 대기 시간: 데이터가 도착하는 동일한 연산자 경로에서 실시간 보강 또는 분류를 수행합니다. 각 메시지는 로컬 CPU 유추만 발생하므로 네트워크 왕복을 방지합니다.
- 컴팩트 디자인: MobileNet 클래스 모델과 같은 소형 모델을 대상으로 합니다. 이 기능은 대형 변압기 모델, GPU/TPU 가속 또는 빈번한 A/B 모델 롤아웃용이 아닙니다.
-
특정 사용 사례에 최적화됨:
- 기능이 그래프에 이미 반영되어 있는 다중 소스 스트림 처리가 포함된 인라인
- 이벤트 시간 의미 체계에 맞게, 추론에서 다른 연산자와 동일한 타임스탬프를 사용합니다.
- 실제 WASM 크기 및 메모리 제약 조건을 초과하지 않고 모듈에 포함할 수 있을 만큼 작게 유지
- 간단한 업데이트: WASM 및 포함된 모델을 사용하여 새 모듈을 배송한 다음 그래프 정의 참조를 업데이트합니다. 별도의 모델 레지스트리 또는 외부 엔드포인트를 변경할 필요가 없습니다.
-
하드웨어 제약 조건: ONNX 백 엔드는 WASI(WebAssembly 시스템 인터페이스)
wasi-nn를 통해 CPU에서 실행됩니다. GPU/TPU 대상이 없습니다. 지원되는 ONNX 연산자만 실행됩니다. - 수평 크기 조정: 추론은 데이터 흐름 그래프가 확장됨에 따라 확장됩니다. 런타임에서 처리량에 더 많은 작업자를 추가하면 각 작업자가 포함된 모델을 로드하고 부하 분산에 참여합니다.
대역 내 ONNX 유추를 사용하는 경우
다음과 같은 요구 사항이 있는 경우 대역 내 유추를 사용합니다.
- 낮은 대기 시간이 필요해 수집 시간에 메시지를 인라인으로 보강하거나 분류해야 합니다.
- MobileNet 클래스 비전 또는 유사한 컴팩트 모델과 같은 작고 효율적인 모델
- 이벤트 시간 처리 및 다른 연산자와 동일한 타임스탬프에 맞춰야 하는 유추
- 업데이트된 모델을 사용하여 새 모듈 버전을 배송하여 간단한 업데이트
다음과 같은 요구 사항이 있는 경우 대역 내 유추를 피합니다.
- 대형 트랜스포머 모델, GPU/TPU 가속 또는 정교한 A/B 출시
- 다중 텐서 입력, 키-값 캐싱 또는 지원되지 않는 ONNX 연산자가 필요한 모델
비고
모듈 및 포함된 모델을 작게 유지하려고 합니다. 대형 모델 및 메모리가 많은 워크로드는 지원되지 않습니다. 이미지 분류에는 컴팩트 아키텍처와 224×224와 같은 작은 입력 크기를 사용합니다.
필수 조건
시작하기 전에 다음이 있는지 확인합니다.
- 데이터 흐름 그래프 기능이 있는 Azure IoT Operations 배포
- Azure Container Registry와 같은 컨테이너 레지스트리에 액세스합니다.
- WebAssembly 모듈 개발을 위한 개발 환경 설정
자세한 설정 지침은 WebAssembly 모듈 개발을 참조하세요.
아키텍처 패턴
데이터 흐름 그래프에서 ONNX 유추에 대한 일반적인 패턴은 다음과 같습니다.
-
전처리 데이터: 원시 입력 데이터를 모델의 예상 형식과 일치하도록 변환합니다. 이미지 모델의 경우 이 프로세스에는 일반적으로 다음이 포함됩니다.
- 이미지 바이트 디코딩
- 대상 차원으로 크기 조정(예: 224×224).
- 색 공간 변환(예: RGB에서 BGR로).
- 픽셀 값을 예상 범위(0~1 또는 -1~1)로 정규화합니다.
- 올바른 텐서 레이아웃으로 데이터 정렬: NCHW(일괄 처리, 채널, 높이, 너비) 또는 NHWC(일괄 처리, 높이, 너비, 채널).
-
유추 실행: 인터페이스를 사용하여 전처리된 데이터를 텐서로 변환하고, CPU 백 엔드를 사용하여
wasi-nn포함된 ONNX 모델을 로드하고, 실행 컨텍스트에서 입력 텐서를 설정하고, 모델의 전달 패스를 호출하고, 원시 예측을 포함하는 출력 텐서를 검색합니다. -
후처리 출력: 원시 모델 출력을 의미 있는 결과로 변환합니다. 일반적인 작업:
- softmax를 적용하여 분류 확률을 생성합니다.
- 상위 K 예측을 선택합니다.
- 신뢰도 임계값을 적용하여 저신뢰성 결과를 필터링합니다.
- 예측 인덱스를 사람이 읽을 수 있는 레이블에 매핑합니다.
- 다운스트림 사용량에 대한 결과 서식을 지정합니다.
Rust WASM 연산자의 IoT 샘플에서 다음 패턴을 따르는 두 가지 샘플을 찾을 수 있습니다.
- 데이터 변환 "형식" 샘플: 이미지를 RGB24 224×224로 디코딩하고 크기 조정합니다.
- 이미지/비디오 처리 "스냅샷" 샘플: MobileNet v2 ONNX 모델을 포함하고, CPU 유추를 실행하고, softmax를 계산합니다.
그래프 정의 구성
데이터 흐름 그래프에서 ONNX 유추를 사용하도록 설정하려면 그래프 구조와 모듈 매개 변수를 모두 구성해야 합니다. 그래프 정의는 파이프라인 흐름을 지정하는 반면 모듈 구성은 전처리 및 유추 동작의 런타임 사용자 지정을 허용합니다.
WASI-NN 지원 활성화하기
WebAssembly 신경망 인터페이스 지원을 활성화하려면 그래프 정의에 wasi-nn 기능을 추가하십시오.
moduleRequirements:
apiVersion: "1.1.0"
runtimeVersion: "1.1.0"
features:
- name: "wasi-nn"
작업 및 데이터 흐름 정의
추론 파이프라인을 구성하는 작업을 설정합니다. 이 예제에서는 일반적인 이미지 분류 워크플로를 보여줍니다.
operations:
- operationType: "source"
name: "camera-input"
- operationType: "map"
name: "module-format/map"
module: "format:1.0.0"
- operationType: "map"
name: "module-snapshot/map"
module: "snapshot:1.0.0"
- operationType: "sink"
name: "results-output"
connections:
- from: { name: "camera-input" }
to: { name: "module-format/map" }
- from: { name: "module-format/map" }
to: { name: "module-snapshot/map" }
- from: { name: "module-snapshot/map" }
to: { name: "results-output" }
이 구성은 다음과 같은 파이프라인을 만듭니다.
-
camera-input원본에서 원시 이미지 데이터를 수신합니다. -
module-format/map이미지 전처리(디코딩, 크기 조정, 형식 변환) -
module-snapshot/mapONNX 유추 및 후처리를 실행합니다. -
results-output싱크에 분류 결과를 전달합니다
모듈 매개 변수 구성
다시 빌드하지 않고 모듈 동작을 사용자 지정하는 런타임 매개 변수를 정의합니다. 이러한 매개 변수는 초기화 시 WASM 모듈에 전달됩니다.
moduleConfigurations:
- name: module-format/map
parameters:
width:
name: width
description: "Target width for image resize (default: 224)"
required: false
height:
name: height
description: "Target height for image resize (default: 224)"
required: false
pixelFormat:
name: pixel_format
description: "Output pixel format (rgb24, bgr24, grayscale)"
required: false
- name: module-snapshot/map
parameters:
executionTarget:
name: execution_target
description: "Inference execution target (cpu, auto)"
required: false
labelMap:
name: label_map
description: "Label mapping strategy (embedded, imagenet, custom)"
required: false
scoreThreshold:
name: score_threshold
description: "Minimum confidence score to include in results (0.0-1.0)"
required: false
topK:
name: top_k
description: "Maximum number of predictions to return (default: 5)"
required: false
운영자 init 는 모듈 구성 인터페이스를 통해 이러한 값을 읽을 수 있습니다. 자세한 내용은 모듈 구성 매개 변수를 참조하세요.
모델을 패키지화하십시오
ONNX 모델을 WASM 구성 요소에 직접 포함하면 원자성 배포 및 버전 일관성이 보장됩니다. 이 방법은 배포를 간소화하고 외부 모델 파일 또는 레지스트리에 대한 런타임 종속성을 제거합니다.
팁 (조언)
포함은 모델 및 연산자 논리의 버전을 함께 유지합니다. 모델을 업데이트하려면 새 모듈 버전을 게시하고 이를 참조하도록 그래프 정의를 업데이트합니다. 이 방법은 모델 드리프트를 제거하고 재현 가능한 배포를 보장합니다.
모델 준비 지침
모델을 포함하기 전에 WASM 배포에 대한 요구 사항을 충족하는지 확인합니다.
- 실제 WASM 로드 시간 및 메모리 제약 조건을 위해 모델을 50MB 미만으로 유지합니다.
- 모델이 공통 형식(float32 또는 uint8)으로 단일 텐서 입력을 허용하는지 확인합니다.
- WASM ONNX 런타임 백 엔드가 모델에서 사용하는 모든 연산자를 지원하는지 확인합니다.
- ONNX 최적화 도구를 사용하여 모델 크기를 줄이고 유추 속도를 개선합니다.
임베딩 워크플로
모델 및 관련 리소스를 포함하려면 다음 단계를 수행합니다.
-
모델 자산 구성: 원본 트리에
.onnx모델 파일 및 선택 사항을labels.txt배치합니다. 명확한 구성을 위해src/fixture/models/src/fixture/labels/와 같은 전용 디렉터리 구조를 사용합니다. -
컴파일 시간에 포함: 언어별 메커니즘을 사용하여 이진 파일에 모델 바이트를 포함합니다. Rust에서 이진 데이터에는
include_bytes!를, 텍스트 파일에는include_str!를 사용합니다. -
WASI-NN 그래프 초기화: 연산자의
init함수에서 포함된 바이트에서 그래프를 만들고wasi-nnONNX 인코딩 및 CPU 실행 대상을 지정합니다. - 유추 루프 구현: 들어오는 각 메시지에 대해 모델 요구 사항에 맞게 입력을 전처리하고, 입력 텐서를 설정하고, 유추를 실행하고, 출력을 검색하고, 후처리를 적용합니다.
- 정상적으로 오류 처리: 모델 로드 오류, 지원되지 않는 연산자 및 런타임 유추 오류에 대한 적절한 오류 처리를 구현합니다.
전체 구현 패턴은 "스냅샷" 샘플을 참조하세요.
권장되는 프로젝트 구조
문제가 명확하게 분리된 WASM 모듈 프로젝트를 구성합니다.
src/
├── lib.rs # Main module implementation
├── model/
│ ├── mod.rs # Model management module
│ └── inference.rs # Inference logic
└── fixture/
├── models/
│ ├── mobilenet.onnx # Primary model
│ └── mobilenet_opt.onnx # Optimized variant
└── labels/
├── imagenet.txt # ImageNet class labels
└── custom.txt # Custom label mappings
예제 파일 참조
"스냅샷" 샘플에서 다음 파일 레이아웃을 참조로 사용합니다.
최소 임베딩 예제
다음 예제에서는 최소 Rust 포함을 보여줍니다. 경로는 매크로가 포함된 원본 파일을 기준으로 합니다.
// src/lib.rs (example)
// Embed ONNX model and label map into the component
static MODEL: &[u8] = include_bytes!("fixture/models/mobilenet.onnx");
static LABEL_MAP: &[u8] = include_bytes!("fixture/labels/synset.txt");
fn init_model() -> Result<(), anyhow::Error> {
// Create wasi-nn graph from embedded ONNX bytes using the CPU backend
// Pseudocode – refer to the snapshot sample for the full implementation
// use wasi_nn::{graph::{load, GraphEncoding, ExecutionTarget}, Graph};
// let graph = load(&[MODEL.to_vec()], GraphEncoding::Onnx, ExecutionTarget::Cpu)?;
// let exec_ctx = Graph::init_execution_context(&graph)?;
Ok(())
}
성능 최적화
모든 메시지에 대해 ONNX 그래프 및 실행 컨텍스트를 다시 만들지 않도록 하려면 한 번 초기화하고 다시 사용하십시오.
공용 샘플은 정적 LazyLock:
use crate::wasi::nn::{
graph::{load, ExecutionTarget, Graph, GraphEncoding, GraphExecutionContext},
tensor::{Tensor, TensorData, TensorDimensions, TensorType},
};
static mut CONTEXT: LazyLock<GraphExecutionContext> = LazyLock::new(|| {
let graph = load(&[MODEL.to_vec()], GraphEncoding::Onnx, ExecutionTarget::Cpu).unwrap();
Graph::init_execution_context(&graph).unwrap()
});
fn run_inference(/* input tensors, etc. */) {
unsafe {
// (*CONTEXT).compute()?;
}
}
모듈 배포
간소화된 샘플 작성기를 다시 사용하거나 로컬로 빌드합니다.
- 간소화된 Docker 작성기를 사용하려면 Rust Docker 작성기 샘플을 참조하세요.
- 일반적인 WebAssembly 배포 및 레지스트리 단계는 데이터 흐름 그래프와 함께 WebAssembly 사용을 참조하세요.
다음 배포 프로세스를 따릅니다.
- 릴리스 모드에서 WASM 모듈을 빌드하고 파일을 생성합니다
<module-name>-<version>.wasm. - OCI 레지스트리를 스토리지(ORAS)로 사용하여 모듈 및 선택적으로 그래프 정의를 레지스트리에 푸시합니다.
- Azure IoT Operations에서 레지스트리 엔드포인트를 만들거나 다시 사용합니다.
- 그래프 정의 아티팩트를 참조하는 데이터 흐름 그래프 리소스를 만듭니다.
예: MobileNet 이미지 분류
IoT 공용 샘플은 이미지 분류를 위해 그래프에 유선으로 연결되는 두 개의 샘플을 제공합니다. "형식" 샘플 은 이미지 디코딩 및 크기 조정 기능을 제공하며, "스냅샷" 샘플 은 ONNX 유추 및 소프트맥스 처리를 제공합니다.
이 예제를 배포하려면 공용 레지스트리에서 아티팩트를 끌어오고, 레지스트리에 푸시하고, 예제 2: 복잡한 그래프 배포와 같이 데이터 흐름 그래프를 배포합니다. 복잡한 그래프는 이러한 모듈을 사용하여 이미지 스냅샷을 처리하고 분류 결과를 내보낸다.
제한점
WASM 데이터 흐름 그래프의 유추에는 다음과 같은 제한 사항이 있습니다.
- ONNX만 해당합니다. 데이터 흐름 그래프는 TFLite와 같은 다른 형식을 지원하지 않습니다.
- CPU만 해당합니다. GPU/TPU 가속이 없습니다.
- 작은 모델을 권장합니다. 대용량 모델 및 메모리 집약적 유추는 지원되지 않습니다.
- 단일 텐서 입력 모델이 지원됩니다. 다중 입력 모델, 키-값 캐싱 및 고급 시퀀스 또는 생성 시나리오는 지원되지 않습니다.
- WASM 런타임의 ONNX 백 엔드가 모델의 연산자를 지원하는지 확인합니다. 연산자가 지원되지 않으면 로드 또는 실행 시 유추가 실패합니다.