Skip to main content

verify-conversion

E2E gate — verifies that applied patches produce a working, numerically sane end-to-end inference through the OpenVINO plugin. Handles HuggingFace/optimum-intel, native OV conversion (ovc/convert_model), and ONNX. Used by orchestrators as the mandatory gate before any PR is published.

소스 정보

저장소
openvinotoolkit/openvino
최근 소스 활동
2026년 5월 27일 04:32
감지된 SKILL.md 언어
영어
스타
11,007
포크
3,458

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
verify-conversion
description
E2E gate — verifies that applied patches produce a working, numerically sane end-to-end inference through the OpenVINO plugin. Handles HuggingFace/optimum-intel, native OV conversion (ovc/convert_model), and ONNX. Used by orchestrators as the mandatory gate before any PR is published.
# Skill: Verify Conversion (E2E Gate) > **This skill is a hard gate before PR publication.** > A PR must **not** be opened until both steps below pass: > 1. The model converts without error. > 2. A real end-to-end inference through the OV plugin layer produces numerically > sane output (no NaN/Inf, non-empty, correct shape). > > Conversion success alone is not sufficient — plugin-level issues (wrong kernel > output, silent data corruption, incorrect type/shape inference at runtime) are > only caught by an actual inference run. This is **not** a full strategy matrix run — use `try-conversion.md` skill for that. Goal: one conversion, one inference run, numerical sanity check, structured result. --- ## Step 1 — Determine conversion path Read `agent-results/pipeline_state.json` (or context file) to identify: | Signal | Conversion path | |---|---| | `model_id` starts with `org/name` (HuggingFace ID) AND `optimum_supported=true` | **Path A** — `optimum-cli` | | `model_id` is a local path with `.onnx` file | **Path B** — OV native (`ovc` / `convert_model`) | | `model_id` is a local PyTorch model or `.pt` / `.pth` file | **Path B** — OV native (`convert_model`) | | `model_id` is a local TF SavedModel or `.pb` file | **Path B** — OV native (`ovc`) | | Unclear | Try Path A first, fall back to Path B on failure | --- ## Path A — HuggingFace model via optimum-intel ### Auto-detect task ```python from transformers import AutoConfig PIPELINE_TAG_MAP = { "text-generation": "text-generation-with-past", "text2text-generation": "text2text-generation-with-past", "image-text-to-text": "image-text-to-text", "text-classification": "text-classification", "token-classification": "token-classification", "question-answering": "question-answering", "feature-extraction": "feature-extraction", "fill-mask": "fill-mask", "text-to-image": "text-to-image", "image-to-text": "image-to-text", "automatic-speech-recognition": "automatic-speech-recognition", "audio-classification": "audio-classification", } try: cfg = AutoConfig.from_pretrained(MODEL_ID, trust_remote_code=True) pipeline_tag = getattr(cfg, "pipeline_tag", None) model_type = getattr(cfg, "model_type", "") if pipeline_tag: task = PIPELINE_TAG_MAP.get(pipeline_tag, pipeline_tag) elif model_type in ("t5", "mt5", "bart", "mbart"): task = "text2text-generation-with-past" else: task = "text-generation-with-past" except Exception: task = "text-generation-with-past" print(f"[verify] Resolved task: {task}") ``` ### Export ```bash optimum-cli export openvino \ --model "$MODEL_ID" \ --task "$TASK" \ --weight-format fp16 \ ov_verify_check/ ``` If export fails with a timeout or OOM, retry with `--weight-format int4`. ### Quick inference check ```python from optimum.intel import OVModelForCausalLM from transformers import AutoTokenizer tok = AutoTokenizer.from_pretrained("ov_verify_check/", trust_remote_code=True) model = OVModelForCausalLM.from_pretrained("ov_verify_check/", trust_remote_code=True) inputs = tok("Hello", return_tensors="pt") out = model.generate(**inputs, max_new_tokens=5) print("[verify] Inference OK:", tok.decode(out[0])) ``` For non-causal models (classification, ASR, etc.), adapt the class and inputs accordingly. --- ## Path B — Native OV conversion (`ovc` / `convert_model`) ### ONNX model ```python import openvino as ov import numpy as np core = ov.Core() model = core.read_model("path/to/model.onnx") compiled = core.compile_model(model, "CPU") # Run one inference pass infer = compiled.create_infer_request() for inp in compiled.inputs: shape = [d if d > 0 else 1 for d in inp.partial_shape.get_min_shape()] infer.set_tensor(inp, ov.Tensor(np.zeros(shape, dtype=inp.element_type.to_dtype()))) infer.infer() print("[verify] ONNX compile + inference OK") ``` ### PyTorch model ```python import torch, openvino as ov # Load your torch model # torch_model = ... example_input = torch.zeros(1, 3, 224, 224) # adjust shape ov_model = ov.convert_model(torch_model, example_input=example_input) compiled = ov.Core().compile_model(ov_model, "CPU") result = list(compiled({0: example_input.numpy()}).values())[0] print("[verify] PyTorch convert + inference OK, output shape:", result.shape) ``` ### TF / generic via ovc ```bash ovc path/to/saved_model --output_model ov_verify_check/model.xml python3 -c " import openvino as ov, numpy as np core = ov.Core() m = core.read_model('ov_verify_check/model.xml') cmp = core.compile_model(m, 'CPU') infer = cmp.create_infer_request() for inp in cmp.inputs: shape = [d if d > 0 else 1 for d in inp.partial_shape.get_min_shape()] infer.set_tensor(inp, ov.Tensor(np.zeros(shape, dtype=inp.element_type.to_dtype()))) infer.infer() print('[verify] ovc + compile + inference OK') " ``` --- ## Step 3 — E2E Numerical Sanity Check After inference completes, validate output quality through the plugin layer: ```python import numpy as np def check_output_sanity(outputs: dict, label: str) -> tuple[bool, str]: """Returns (passed, reason). Checks all output tensors.""" for name, arr in outputs.items(): arr = np.asarray(arr) if arr.size == 0: return False, f"{label}: output '{name}' is empty (size=0)" if np.isnan(arr).any(): return False, f"{label}: output '{name}' contains NaN" if np.isinf(arr).any(): return False, f"{label}: output '{name}' contains Inf" return True, "OK" # For HF/optimum path — check that generated tokens are non-empty def check_lm_output(out_ids, tokenizer, label: str) -> tuple[bool, str]: if out_ids is None or out_ids.shape[-1] == 0: return False, f"{label}: generated token sequence is empty" decoded = tokenizer.decode(out_ids[0], skip_special_tokens=True) if not decoded.strip(): return False, f"{label}: decoded output is blank" return True, f"generated: '{decoded[:80]}'" ``` Apply the appropriate check based on conversion path: - **Path A (HF/optimum)**: use `check_lm_output` on the generated token ids - **Path B (native OV)**: use `check_output_sanity` on the infer request output tensors If the sanity check fails, set `e2e_passed = false` with the reason — do **not** silently swallow the failure. --- ## Result reporting Write the outcome to `agent-results/<agent>/verify_result.json`: ```json { "verify_passed": true, "e2e_passed": true, "conversion_path": "optimum-cli | ovc | convert_model", "task": "<task or null>", "e2e_detail": "<short description of what was run and what output was checked>", "error": null } ``` `verify_passed` is `true` only when **both** conversion and E2E inference pass. On failure, set `"verify_passed": false`, `"e2e_passed": false` (if inference failed), and populate `"error"` with the specific failure reason. Do **not** abort the pipeline — the orchestrator decides whether to retry or escalate.
GitHub에서 보기