Skip to content

Consolidate Python dependency versions into a single constraints file (unblock numpy 2.x + py3.13 in backend) #10524

Description

@mrveiss

Goal

Establish a single source of truth for shared/transitive Python dependency versions so every component installs the same, latest version of common libraries (numpy first), and bumping a version is a one-line change. Today numpy is pinned in 6 files with 3 different floors, and the backend is silently held a major version behind.

Why this matters now — portable roles

AutoBot roles (backend, tts-worker, npu-worker, ai-stack, code_analysis) are relocatable across hosts and can be co-located on one host by Ansible. When two roles with conflicting pins land in the same Python environment, pip cannot satisfy both. Version skew also breaks the array/serialization ABI when a .npy/pickled embedding written by a numpy-2.x role is read by a numpy-1.x role. Single version is a co-location correctness requirement, not just hygiene.

Current state (evidence)

numpy declared in 6 files, 3 different floors:

File Pin
autobot-backend/code_analysis/requirements.txt:7 numpy>=2.4.6,<3.0.0
autobot-tts-worker/requirements.txt:6 numpy>=2.5.0,<3.0.0
autobot-npu-worker/requirements.txt:6 numpy>=2.5.0,<3.0.0
autobot-npu-worker/resources/windows-npu-worker/requirements.txt:60 numpy>=2.4.3,<3.0.0
autobot-infrastructure/shared/docker/ai-stack/requirements-ai.txt:25 numpy>=2.5.0,<3.0.0
autobot-infrastructure/autobot-npu-worker/docker/requirements-npu.txt:19 numpy>=2.5.0,<3.0.0

The main backend does NOT pin numpy directly; it is forced to numpy<2 transitively, via a constraint hidden on the opencv line (autobot-backend/requirements.txt:42). No constraints file exists anywhere in the repo.

Root cause / blocker

graspologic>=3.4.4 (autobot-backend/requirements.txt:51) is a double blocker — latest stable 3.4.4 declares:

numpy<2.0.0,>=1.26.4
requires_python: <3.13,>=3.9

So it caps the backend at numpy<2 and cannot install on Python 3.13+ (collides with the py3.14 migration). There is no numpy-2 graspologic release (even in dev). It is used in exactly one place — two leiden(G, trials=N) calls in autobot-backend/services/mesh_brain/community_clusterer.py:52,93, over a networkx graph, returning {node: community_id}.

Tasks

  • Task 1: Replace graspologic Leiden → PR refactor(mesh-brain): replace graspologic Leiden with NetworkX Louvain — unblock numpy 2.x + py3.13 (#10524) #10530
    • Subtask 1.1: Swap the two leiden() calls in services/mesh_brain/community_clusterer.py for a numpy-2 + py3.13-compatible equivalent — leidenalg+python-igraph (true Leiden) OR networkx.community.louvain_communities (already a dep, no new package). Recommend leidenalg for algorithmic fidelity; confirm choice with board.
    • Subtask 1.2: Preserve the {node: community_id} return contract + existing fallback/exception behavior; keep cluster_graph / _split_community behavior identical.
    • Subtask 1.3: Tests for community clustering on a known graph (stability of centroids).
    • Subtask 1.4: Remove graspologic>=3.4.4 from autobot-backend/requirements.txt; drop the opencv-python-headless<4.11 cap (allow latest opencv / numpy>=2).
  • Task 2: Single constraints file (source of truth) → PR build(deps): single-source shared dep versions via constraints/shared.txt + drift guard (#10524) #10556
    • Subtask 2.1: Add constraints/shared.txt at repo root with one pin per shared lib (numpy==<latest>, scipy, opencv, etc.).
    • Subtask 2.2: Reference it from every component requirements file (-c <relpath>/constraints/shared.txt) and remove the per-file numpy version, leaving bare numpy.
    • Subtask 2.3: Verify each component (backend, tts-worker, npu-worker, windows-npu-worker, ai-stack, code_analysis) resolves and builds against the shared constraint.
  • Task 3: Co-location guard → PR build(deps): single-source shared dep versions via constraints/shared.txt + drift guard (#10524) #10556
    • Subtask 3.1: CI check (or pre-commit) that fails if any requirements file declares a version for a lib listed in constraints/shared.txt (prevents re-drift).
    • Subtask 3.2: Document in dependency docs that portable/co-locatable roles must share the constraints file.

Verification

  • All component images build on the unified numpy (CPU default stays CPU-only; GPU extra unchanged).
  • community_clusterer tests pass with the new partitioner.
  • Backend imports on Python 3.13+ (graspologic removed).
  • Grep shows numpy version declared in exactly one place.

Activity

  1. mrveiss commented on Jun 27, 2026

    @mrveiss
    OwnerAuthor

    Task 1 complete → PR #10530. graspologic removed; community detection now uses NetworkX Louvain (zero new deps). Backend numpy<2 cap lifted (opencv <4.11 cap dropped) and the py3.13+ install blocker is gone. 31/31 mesh-brain tests pass. Tasks 2 (constraints/shared.txt single source of truth) and 3 (CI re-drift guard for portable/co-located roles) remain.

  2. mrveiss commented on Jun 27, 2026

    @mrveiss
    OwnerAuthor

    Tasks 2+3 complete → PR #10556. constraints/shared.txt is now the single source of truth for numpy (declared in exactly one place; 7 requirements files reference it via -c). Added scripts/check_constraint_drift.py + constraint-drift workflow that fails any PR re-pinning a constrained package. With Task 1 (#10530) merged, all three tasks are done; umbrella ready for human close once #10556 lands.

  3. github-actions commented on Jun 27, 2026

    @github-actions
    Contributor

    PR #10556 (merged to Dev_new_gui) references this issue with a close keyword.

    build(deps): single-source shared dep versions via constraints/shared.txt + drift guard (#10524)

    If this issue is fully resolved, close it manually. If work remains, no action is needed.

  4. github-actions commented on Jun 27, 2026

    @github-actions
    Contributor

    PR #10562 (merged to Dev_new_gui) references this issue with a close keyword.

    fix(deps): wire requirements-ci/ai-ml.txt to constraints + close guard glob gap (#10524)

    If this issue is fully resolved, close it manually. If work remains, no action is needed.

  5. mrveiss commented on Jun 27, 2026

    @mrveiss
    OwnerAuthor

    Complete — all tasks merged

    numpy is now declared in exactly one place repo-wide (constraints/shared.txt); every requirements file references it via -c.

    Task PR Status
    1 — Replace graspologic Leiden (unblock numpy 2.x + py3.13) #10530 merged
    2 — constraints/shared.txt single source of truth #10556 merged
    3 — constraint-drift CI guard #10556 merged
    Follow-up — wire requirements-ci/ai-ml.txt + close guard glob gap #10562 merged

    Outcome: graspologic removed (was the sole numpy<2 / py3.13 backend blocker); backend, 6 worker/infra files, and the CI requirements all share one numpy pin (>=2.5.0,<3.0.0); scripts/check_constraint_drift.py + the constraint-drift workflow fail any PR that re-pins a constrained package — preventing the per-file drift that breaks pip when Ansible co-locates roles on one host.

    Closing as done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions