Compare commits

...
Author SHA1 Message Date
QiuSW 60036587a6 feat: 初始化 Brain Python CUDA 项目骨架 (#10) 2026-08-27 18:15:09 +08:00
ila b37c350096 Merge pull request #109: 同步 DevHarness 最新工作流与文档基线
关联工单 #108;等待用户验收。
2026-08-27 17:21:33 +08:00
8 changed files with 301 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
# Safe local defaults. Do not add credentials, customer data, or production paths.
BRAIN_DEVICE=auto
BRAIN_LOG_LEVEL=INFO
+1
View File
@@ -0,0 +1 @@
3.11.15
+90
View File
@@ -0,0 +1,90 @@
# YoVision Brain
Brain 是无界面的独立推理交付单元。本骨架只提供可安装 Python 包、命令入口和运行时探测;尚不包含视频、模型、规则、事件或部署能力,也不依赖 Sense、Bell 在线。
## 冻结基线
| 项目 | 版本 / 选择 |
|---|---|
| Python | CPython `3.11.15`(`.python-version`;本机由 uv 隔离管理) |
| 环境与包管理 | Python `venv` + pip `26.2.1`;可用 uv `0.11.6` 取得固定 Python |
| 构建后端 | setuptools `80.9.0` |
| 测试 | pytest `8.4.2` |
| 数组运行时 | NumPy `2.3.3` |
| 推理运行时 | PyTorch `2.12.1` |
| CPU wheel | PyTorch 官方 `https://download.pytorch.org/whl/cpu` |
| NVIDIA wheel | PyTorch 官方 CUDA 12.6 `https://download.pytorch.org/whl/cu126` |
选择 Python 3.11 是因为 PyTorch 的 Windows 支持范围包含 Python 3.9–3.12,并且本机已有隔离的 CPython 3.11.15。选择 `torch 2.12.1 + cu126` 是因为 PyTorch 官方为 Linux/Windows 同时发布该固定组合;NVIDIA 的 CUDA 12.x 兼容表要求 Windows 驱动至少为 528.33,本机驱动 566.24 满足运行 CUDA 12.6 wheel 的驱动前提。
本机安装的 CUDA Toolkit 11.2 不参与 PyTorch wheel 构建,也不因本项目而修改。驱动满足最低版本只是兼容前提,不等于 GPU 已验证;必须以 `--smoke cuda` 的真实结果为准。
官方依据:
- [PyTorch - Start Locally](https://docs.pytorch.org/get-started/locally/)
- [PyTorch - Previous Versions](https://pytorch.org/get-started/previous-versions/)
- [NVIDIA CUDA 12.6 Release Notes](https://docs.nvidia.com/cuda/archive/12.6.0/cuda-toolkit-release-notes/index.html)
- [Python 3.11.15](https://www.python.org/downloads/release/python-31115/)
## 创建隔离环境
从仓库根目录执行。无需激活虚拟环境,也不需要更改 PowerShell 执行策略:
```powershell
uv python install 3.11.15
uv venv --python 3.11.15 Brain/.venv
Brain\.venv\Scripts\python.exe -m pip install pip==26.2.1 --index-url https://pypi.org/simple
Brain\.venv\Scripts\python.exe -m pip install -e "Brain[dev]" --index-url https://pypi.org/simple
```
若不使用 uv,也可以让已安装的 Python 3.11.15 创建环境:
```powershell
py -V:3.11 -m venv Brain/.venv
Brain\.venv\Scripts\python.exe -m pip install pip==26.2.1 --index-url https://pypi.org/simple
Brain\.venv\Scripts\python.exe -m pip install -e "Brain[dev]" --index-url https://pypi.org/simple
```
## 安装运行时
CPU 环境使用 PyTorch 官方 CPU 索引:
```powershell
Brain\.venv\Scripts\python.exe -m pip install numpy==2.3.3 --index-url https://pypi.org/simple
Brain\.venv\Scripts\python.exe -m pip install torch==2.12.1 --index-url https://download.pytorch.org/whl/cpu
```
目标 NVIDIA 环境使用官方 CUDA 12.6 wheel。该 wheel 自带所需 CUDA 用户态运行库,不要求把系统 Toolkit 改成 12.6:
```powershell
Brain\.venv\Scripts\python.exe -m pip install numpy==2.3.3 --index-url https://pypi.org/simple
Brain\.venv\Scripts\python.exe -m pip install torch==2.12.1 --index-url https://download.pytorch.org/whl/cu126
```
不要在同一环境混装 CPU 与 CUDA wheel;切换后端时重建 `.venv`。
## 运行和验证
入口的帮助与版本查询不导入 PyTorch,因此未安装运行时时也可用:
```powershell
Brain\.venv\Scripts\python.exe -m yovision_brain --help
Brain\.venv\Scripts\python.exe -m yovision_brain --version
```
安装相应运行时后执行:
```powershell
Brain\.venv\Scripts\python.exe -m pytest Brain/tests/test_package.py -q
Brain\.venv\Scripts\python.exe -m yovision_brain --runtime-info
Brain\.venv\Scripts\python.exe -m yovision_brain --smoke cpu
Brain\.venv\Scripts\python.exe -m yovision_brain --smoke cuda
```
`--runtime-info` 只输出 Python、PyTorch 和设备能力,不读取或显示环境变量值。`--smoke cuda` 在 CUDA wheel、驱动或设备不可用时以非零状态退出,不会回退 CPU 后伪称成功。
## 配置与安全边界
`.env.example` 只有无秘密默认值。Brain 不接收用户会话,不持有账户、RBAC、Alert 或通知状态。不得把 token、摄像头凭据、客户数据、内部文件路径或未经授权的人脸信息写入配置、日志或事件。
第三方许可证与来源见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。
+17
View File
@@ -0,0 +1,17 @@
# Third-party notices
本文件记录 Brain 骨架直接固定或明确依赖的第三方软件。具体安装包内许可证文本仍是最终依据。
| 组件 | 固定版本 | 许可证 | 来源 |
|---|---:|---|---|
| CPython | 3.11.15 | Python Software Foundation License | https://www.python.org/downloads/release/python-31115/ |
| pip | 26.2.1 | MIT | https://github.com/pypa/pip/tree/26.2.1 |
| uv(可选 Python 获取工具,不随 Brain 分发) | 0.11.6 | Apache-2.0 OR MIT | https://github.com/astral-sh/uv/tree/0.11.6 |
| python-build-standalone(uv 管理的 Python 分发来源,不随 Brain 分发) | 2026 系列 | MPL-2.0;分发包内另含 CPython 与组件许可证 | https://github.com/astral-sh/python-build-standalone |
| setuptools | 80.9.0 | MIT | https://github.com/pypa/setuptools/tree/v80.9.0 |
| pytest | 8.4.2 | MIT | https://github.com/pytest-dev/pytest/tree/8.4.2 |
| NumPy | 2.3.3 | BSD-3-Clause | https://github.com/numpy/numpy/tree/v2.3.3 |
| PyTorch | 2.12.1 | BSD-3-Clause | https://github.com/pytorch/pytorch/tree/v2.12.1 |
| NVIDIA CUDA runtime(随官方 PyTorch CUDA wheel 分发) | 12.6 系列 | NVIDIA CUDA Toolkit End User License Agreement | https://docs.nvidia.com/cuda/eula/index.html |
PyTorch 及后续模型可能带来额外第三方依赖与模型许可。本骨架未选择或分发任何模型;引入模型前必须另行核对商用、再分发、数据和输出限制,不能把框架许可证视为模型许可证。
+27
View File
@@ -0,0 +1,27 @@
[build-system]
requires = ["setuptools==80.9.0"]
build-backend = "setuptools.build_meta"
[project]
name = "yovision-brain"
version = "0.1.0"
description = "Headless inference delivery unit for YoVision"
readme = "README.md"
requires-python = "==3.11.*"
dependencies = []
[project.optional-dependencies]
# The wheel backend is selected by the official PyTorch index documented in
# README.md. Keeping one pinned requirement here prevents CPU/CUDA drift.
runtime = ["numpy==2.3.3", "torch==2.12.1"]
dev = ["pytest==8.4.2"]
[project.scripts]
yovision-brain = "yovision_brain.__main__:main"
[tool.setuptools.packages.find]
where = ["src"]
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--strict-markers"
+5
View File
@@ -0,0 +1,5 @@
"""YoVision Brain package."""
__version__ = "0.1.0"
__all__ = ["__version__"]
+112
View File
@@ -0,0 +1,112 @@
"""Command-line entry point for safe Brain runtime diagnostics."""
from __future__ import annotations
import argparse
import json
import platform
from collections.abc import Sequence
from typing import Any
from yovision_brain import __version__
def _load_torch() -> Any:
try:
import torch
except ImportError as exc:
raise RuntimeError(
"PyTorch runtime is not installed; install the pinned CPU or CUDA wheel "
"from Brain/README.md"
) from exc
return torch
def runtime_info() -> dict[str, object]:
"""Return non-sensitive interpreter and compute-runtime facts."""
info: dict[str, object] = {
"python": platform.python_version(),
"torch_installed": False,
"torch_version": None,
"cuda_build": None,
"cuda_available": False,
"cuda_device_count": 0,
}
try:
torch = _load_torch()
except RuntimeError:
return info
cuda_available = bool(torch.cuda.is_available())
info.update(
{
"torch_installed": True,
"torch_version": torch.__version__,
"cuda_build": torch.version.cuda,
"cuda_available": cuda_available,
"cuda_device_count": torch.cuda.device_count() if cuda_available else 0,
}
)
return info
def smoke(device: str) -> dict[str, object]:
"""Run a deterministic tensor operation on exactly the requested device."""
torch = _load_torch()
if device == "cuda" and not torch.cuda.is_available():
raise RuntimeError("CUDA was requested but PyTorch reports no available CUDA device")
tensor = torch.tensor([[1.0, 2.0], [3.0, 4.0]], device=device)
result = tensor @ tensor
expected = torch.tensor([[7.0, 10.0], [15.0, 22.0]], device=device)
if not torch.equal(result, expected):
raise RuntimeError("tensor smoke result did not match the expected value")
return {
"status": "ok",
"device": device,
"torch_version": torch.__version__,
"cuda_build": torch.version.cuda,
}
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="yovision-brain",
description="YoVision Brain runtime diagnostics",
)
parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
action = parser.add_mutually_exclusive_group()
action.add_argument(
"--runtime-info",
action="store_true",
help="print non-sensitive Python/PyTorch/CUDA capability information",
)
action.add_argument(
"--smoke",
choices=("cpu", "cuda"),
help="run a tensor smoke test on exactly the selected device",
)
return parser
def main(argv: Sequence[str] | None = None) -> int:
args = build_parser().parse_args(argv)
try:
if args.runtime_info:
payload = runtime_info()
elif args.smoke:
payload = smoke(args.smoke)
else:
build_parser().print_help()
return 0
except RuntimeError as exc:
print(json.dumps({"status": "error", "message": str(exc)}, ensure_ascii=False))
return 2
print(json.dumps(payload, ensure_ascii=False, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
+46
View File
@@ -0,0 +1,46 @@
from __future__ import annotations
import json
import subprocess
import sys
import pytest
from yovision_brain import __version__
from yovision_brain.__main__ import main, runtime_info, smoke
def test_package_version() -> None:
assert __version__ == "0.1.0"
def test_module_help_runs_without_other_products() -> None:
result = subprocess.run(
[sys.executable, "-m", "yovision_brain", "--help"],
check=False,
capture_output=True,
text=True,
)
assert result.returncode == 0
assert "YoVision Brain runtime diagnostics" in result.stdout
def test_runtime_info_is_non_sensitive(capsys: pytest.CaptureFixture[str]) -> None:
assert main(["--runtime-info"]) == 0
payload = json.loads(capsys.readouterr().out)
assert set(payload) == {
"cuda_available",
"cuda_build",
"cuda_device_count",
"python",
"torch_installed",
"torch_version",
}
assert payload == runtime_info()
def test_cpu_tensor_smoke() -> None:
pytest.importorskip("torch")
result = smoke("cpu")
assert result["status"] == "ok"
assert result["device"] == "cpu"