Skip to content

fix: decouple oa-vm from the ML training stack via lazy package imports#263

Merged
abrichr merged 1 commit into
mainfrom
fix/oa-vm-decouple-ml-imports
Jul 10, 2026
Merged

fix: decouple oa-vm from the ML training stack via lazy package imports#263
abrichr merged 1 commit into
mainfrom
fix/oa-vm-decouple-ml-imports

Conversation

@abrichr

@abrichr abrichr commented Jul 10, 2026

Copy link
Copy Markdown
Member

Problem

oa-vm (VM lifecycle CLI) crashed on startup:

A module that was compiled using NumPy 1.x cannot be run in NumPy 2.0.2 ...
  from openadapt_evals.benchmarks.vm_cli import main
  ...eventually...
  from transformers import TrainerCallback

Root cause is an import-chain problem, not NumPy: oa-vm's entry point
imports openadapt_evals.benchmarks.vm_cli, which triggers the package
__init__ modules. Those eagerly did from openadapt_evals.agents import ...,
cascading into transformers/peft — the entire ML training stack — just to
start and stop VMs. Under a NumPy 2 / stale-transformers environment that
cascade hard-crashes, taking oa-vm down with it. Downgrading NumPy would be a
workaround; a VM CLI should not import the training stack at all.

Fix

Resolve the re-exported public API of openadapt_evals and
openadapt_evals.benchmarks lazily (PEP 562 module __getattr__), caching
each name as a module global on first access. The repo already used this pattern
for PolicyAgent/Azure; this extends it to the heavy re-exports.

  • Importing either package is now light and pulls in no ML/vision
    dependency. agents/transformers load only when an agent-dependent name is
    actually accessed.
  • Public API and object identity are unchanged: from openadapt_evals import BenchmarkAgent and oe.WAAAdapter is <direct import> both hold.

Verification

  • oa-vm --help and oa-vm pool-status run cleanly (both in the broken
    anaconda env that reproduced the crash and in the uv env).
  • Full public API resolves with identity preserved.
  • New subprocess regression guard TestVmCliStaysLight asserts the oa-vm
    import path pulls in none of transformers/peft/torch/agents, and that
    lazy re-exports still resolve to the real objects.
  • Test suite: 302 passed, 1 pre-existing unrelated failure
    (test_demo_persistence.py::...test_demo_format_and_persistence imports the
    optional openadapt_ml directly without an importorskip guard — fails on
    main too; flagged, not in scope here).

🤖 Generated with Claude Code

The oa-vm console script imports openadapt_evals.benchmarks.vm_cli, which
triggered the package __init__ modules' eager `from openadapt_evals.agents
import ...`. That cascaded into transformers/peft — dead weight for VM
lifecycle management, and a hard crash under a NumPy 2 / stale-transformers
environment (a module compiled against NumPy 1.x cannot run on NumPy 2.x),
which broke `oa-vm` entirely.

Resolve the re-exported public API of openadapt_evals and
openadapt_evals.benchmarks lazily (PEP 562 module __getattr__), caching each
name as a module global on first access. Importing either package is now
light and touches no ML/vision dependency; agents/transformers load only when
an agent-dependent name is actually used. Public API and object identity are
unchanged.

Adds a subprocess regression guard (TestVmCliStaysLight) asserting the oa-vm
import path pulls in none of transformers/peft/torch/agents, plus a check that
the lazy re-exports still resolve to the real objects.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CKrVJJy5jWVCkXAqgUqtqZ
@abrichr abrichr merged commit dca4ff7 into main Jul 10, 2026
1 check passed
Sign up for free to 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