Skip to content

Harden ML inference load and decode paths - #73

Merged
chiruu12 merged 4 commits into
devfrom
fix/ml-inference-hardening
Jul 20, 2026
Merged

Harden ML inference load and decode paths#73
chiruu12 merged 4 commits into
devfrom
fix/ml-inference-hardening

Conversation

@chiruu12

@chiruu12chiruu12 commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Fix BIOES empty-label crash, validate *-INJ label maps at load (ModelError), validate forced torch devices (ConfigError), and make ModelProvider/SpanInferenceModel load thread-safe
  • Route torch/transformers imports through unplug.optional.ml helpers; add ML module logging for device selection and tokenizer fallbacks
  • Add offline synthetic BIOES checkpoint fixture + unit tests so inference runs in CI without real weights

Test plan

  • cd sdk && make check (1027 passed)
  • cd sdk && make test-cov (80% gate green; span_model.py ~82%, injection_ml.py ~72%)
  • New tests: test_bioes, test_device, test_providers, test_span_model, test_injection_ml_scanner (marked requires_ml)

Note

Medium Risk
Changes sit on the injection-detection ML path (load, decode, device), but behavior for valid checkpoints should match prior logic while invalid config and mislabeled weights fail earlier with explicit errors.

Overview
Hardens the ML injection span pipeline so bad checkpoints and device config fail clearly instead of crashing at decode time, and concurrent loads do not double-initialize models.

SpanInferenceModel now rejects checkpoints whose label map lacks any *-INJ tags at load with ModelError, and decode_bioes_spansreturns no spans when those columns are missing (defense in depth). resolve_torch_device validates forced devices (ConfigError with available backends), keeps cpu without importing torch, and auto-selection still prefers cuda → mps → cpu via unplug.optional.ml.

Thread-safe loading uses double-checked locking on ModelProvider and SpanInferenceModel (predict stays lock-free after load). Torch/transformers imports go through get_torch / get_transformers; providers and span model log load, device, and tokenizer fallback warnings.

CI/offline testing: session-scoped synthetic BIOES checkpoints plus unit tests for BIOES decode, device resolution, concurrent provider load, span model load/predict/overflow, and InjectionSpanScanner integration (requires_ml).

Reviewed by Cursor Bugbot for commit b6e33f5. Bugbot is set up for automated code reviews on this repo. Configure here.

@greptile-apps

greptile-appsBot commented Jul 20, 2026

Copy link
Copy Markdown

Greptile Summary

This PR hardens the ML inference load and decode path. The main changes are:

  • Adds load-time validation for injection label maps.
  • Handles BIOES decoding when no injection labels are present.
  • Validates forced torch device settings before model load.
  • Makes model provider and span model loading thread-safe.
  • Routes torch and transformers access through optional ML helpers.
  • Adds synthetic offline ML fixtures and unit coverage.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.
  • The forced-device validation now uses torch parsing and backend checks, so the previously reported valid-device rejection path is addressed.

Important Files Changed

FilenameOverview
sdk/src/unplug/ml/device.pyForced torch device settings are now parsed and validated before use.
sdk/src/unplug/ml/span_model.pySpan model loading now uses optional ML helpers, validates injection labels, and protects load state with a lock.
sdk/src/unplug/ml/bioes.pyBIOES decoding now returns no spans when no injection labels are present.

Reviews (4): Last reviewed commit: "Accept indexed and probeable torch devic..." | Re-trigger Greptile

Comment threadsdk/src/unplug/ml/device.py Outdated
@github-actions

github-actionsBot commented Jul 20, 2026

Copy link
Copy Markdown

coverage

SDK Coverage •
FileStmtsMissCoverMissing
src/unplug/ml
bioes.py40587%41–42, 47, 52, 56
device.py501178%54, 57–59, 62–66, 72, 75
models.py79198%45
providers.py361266%23–24, 40, 44–45, 49–54, 58
span_model.py2013682%71, 75, 82, 91–92, 109, 111, 142, 144, 224–225, 228, 233–238, 240–243, 250, 255, 258, 327–328, 330–331, 357–358, 374–375, 379–380, 391
TOTAL7162101785%

TestsSkippedFailuresErrorsTime
114725 💤0 ❌0 🔥40.458s ⏱️

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 702e8d4. Configure here.

Comment threadsdk/src/unplug/ml/device.py Outdated
Comment threadsdk/src/unplug/ml/device.py
Comment threadsdk/src/unplug/ml/device.py Outdated
Comment threadsdk/src/unplug/ml/device.py Outdated
@chiruu12
chiruu12 merged commit 316e2e1 into devJul 20, 2026
6 checks passed
This was referenced Jul 20, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@chiruu12