diff --git a/.github/workflows/desktop.yaml b/.github/workflows/desktop.yaml index 0892f0bf1..51d1f98e8 100644 --- a/.github/workflows/desktop.yaml +++ b/.github/workflows/desktop.yaml @@ -59,6 +59,10 @@ jobs: if (-not $wheel) { throw "Hivemind wheel build produced no artifact" } python -m pip install $wheel.FullName - name: Install qualified Windows CUDA runtime + # Hosted CI runners have no Intel GPU, so CI always bundles the CUDA + # build. Local XPU bundles install torch==2.6.0+xpu instead (see + # scripts/install.ps1 and scripts/install.sh with DRIFT_DEVICE=xpu); + # the verify steps below accept either qualified build. if: runner.os == 'Windows' run: >- python -m pip install @@ -68,16 +72,16 @@ jobs: run: | python -m pip install -e "..[api]" python -m pip install -e ".[dev]" - - name: Verify qualified Windows CUDA runtime + - name: Verify qualified Windows GPU runtime if: runner.os == 'Windows' - run: python -c "import torch; assert torch.__version__ == '2.6.0+cu124'" + run: python -c "import torch; assert torch.__version__ in ('2.6.0+cu124', '2.6.0+xpu'), torch.__version__" - name: Run protocol and runtime-boundary tests working-directory: . run: | python -m unittest discover -s desktop/tests -v communityai-desktop --self-test - - name: Reverify qualified CUDA runtime before bundling - run: python -c "import torch; assert torch.__version__ == '2.6.0+cu124'" + - name: Reverify qualified GPU runtime before bundling + run: python -c "import torch; assert torch.__version__ in ('2.6.0+cu124', '2.6.0+xpu'), torch.__version__" - name: Build and smoke unsigned public-alpha bundle run: >- python build_desktop.py diff --git a/.github/workflows/qualify-model-matrix.yaml b/.github/workflows/qualify-model-matrix.yaml index 6951b4162..332ab8e3b 100644 --- a/.github/workflows/qualify-model-matrix.yaml +++ b/.github/workflows/qualify-model-matrix.yaml @@ -38,6 +38,11 @@ jobs: id: scope shell: bash run: | + # NOTE: "windows-xpu" and "linux-xpu" are registered in + # scripts/run_external_model_qualification.py but intentionally not + # scheduled here yet: no self-hosted XPU runner is provisioned, and + # scheduling a profile with no matching runner would queue forever. + # Add them to the public-alpha list once an XPU runner exists. if [[ "${{ inputs.qualification_scope }}" == "public-alpha" ]]; then echo 'profiles=["windows-cpu","windows-cuda","linux-cpu","linux-cuda"]' >> "$GITHUB_OUTPUT" else diff --git a/README.md b/README.md index 69ac6b2dd..f32e6024a 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ alpha; the lowest supported hardware configuration has not been certified. | --- | --- | | **CPU** | 64-bit Intel or AMD (x86-64). Four cores recommended. | | **RAM** | 8 GB as a starting point; 16 GB recommended. Sharing needs extra memory for the model parts you contribute. | -| **GPU** | Optional. NVIDIA CUDA is supported for acceleration and sharing; an RTX 2070 SUPER with 8 GB VRAM has been tested. AMD and Intel GPU acceleration is not included. | +| **GPU** | Optional. NVIDIA CUDA and Intel XPU are supported for acceleration and sharing; an RTX 2070 SUPER with 8 GB VRAM has been tested. AMD GPU acceleration is not included. | | **Disk space** | Start with 20 GB free, preferably on an SSD. The app uses about 4.3 GB on Windows or 5.2 GB on Linux; the small local model adds about 1.8 GB. Sharing requires additional space. | | **Operating system** | 64-bit Windows 10 (1809+)/11, Ubuntu 22.04+ or Debian 12+ with a desktop environment. | | **Internet** | Required for community inference and initial downloads. The small local model works offline after downloading. | @@ -72,7 +72,9 @@ updates in the sidebar, then choose **Restart to update** when the download fini The online installer downloads and verifies the full package during setup. For NVIDIA use, install a CUDA 12.4-compatible driver (551.61+ on Windows, -550.54.14+ on Linux). Python, PyTorch and the CUDA runtime are included. +550.54.14+ on Linux). For Intel use, install a recent Intel GPU driver with +XPU/oneAPI support and select the XPU runtime (`DRIFT_DEVICE=xpu`, see the +installation guide). Python, PyTorch and the matching GPU runtime are included. See the [installation guide](https://github.com/flujo-app/CommunityAI/blob/codex/gate14-20260902-b/docs/ALPHA_INSTALL.md) for setup, updates and the current alpha limitations. diff --git a/desktop/build_desktop.py b/desktop/build_desktop.py index 2dac1013d..6200f6efc 100644 --- a/desktop/build_desktop.py +++ b/desktop/build_desktop.py @@ -34,6 +34,11 @@ "Linux": ("communityai-desktop-linux.tar.gz", "tar.gz"), "Windows": ("communityai-desktop-windows.zip", "zip"), } +QUALIFIED_TORCH_BUILDS = ( + # Qualified node runtimes: NVIDIA CUDA 12.4 and Intel XPU. + "2.6.0+cu124", + "2.6.0+xpu", +) UNSIGNED_ALPHA_WARNING = ( "Unsigned public-alpha engineering bundle: verify SHA256SUMS before use. " "No publisher signature or authenticated automatic update is provided." @@ -1059,8 +1064,11 @@ def _verify_desktop_metrics( for field in ("drift", "torch", "transformers", "hivemind", "fastapi", "uvicorn", "keyring"): if not _is_printable_string(node_runtime.get(field)): raise RuntimeError(f"node runtime metric {field} is missing or unsafe") - if node_runtime["torch"] != "2.6.0+cu124": - raise RuntimeError("node runtime is not the qualified CUDA PyTorch build") + if node_runtime["torch"] not in QUALIFIED_TORCH_BUILDS: + raise RuntimeError( + "node runtime is not a qualified PyTorch build " + f"(expected one of {', '.join(QUALIFIED_TORCH_BUILDS)})" + ) expected_worker_runtime = { "schema_version": 1, diff --git a/scripts/run_external_model_qualification.py b/scripts/run_external_model_qualification.py index 4507915e8..9cf13e2d2 100644 --- a/scripts/run_external_model_qualification.py +++ b/scripts/run_external_model_qualification.py @@ -56,8 +56,10 @@ class HostProfile: HOST_PROFILES: Mapping[str, HostProfile] = { "windows-cpu": HostProfile(system="windows", device="cpu"), "windows-cuda": HostProfile(system="windows", device="cuda"), + "windows-xpu": HostProfile(system="windows", device="xpu"), "linux-cpu": HostProfile(system="linux", device="cpu"), "linux-cuda": HostProfile(system="linux", device="cuda"), + "linux-xpu": HostProfile(system="linux", device="xpu"), "macos-cpu": HostProfile(system="macos", device="cpu"), "macos-mps": HostProfile(system="macos", device="mps"), } @@ -142,6 +144,10 @@ def require_device(profile: HostProfile) -> None: if profile.device == "cuda" and not torch.cuda.is_available(): raise ExternalQualificationError("the CUDA-labelled runner has no available CUDA device") + if profile.device == "xpu": + xpu = getattr(torch, "xpu", None) + if xpu is None or not xpu.is_available(): + raise ExternalQualificationError("the XPU-labelled runner has no available Intel XPU device") if profile.device == "mps": mps = getattr(torch.backends, "mps", None) if mps is None or not mps.is_available():