GenieX Python 绑定构建与分发指南:三 sdist 架构、SDK 按需拉取与本地打包全流程
GenieX Python 绑定构建与分发指南三 sdist 架构、SDK 按需拉取与本地打包全流程【免费下载链接】GenieXRun frontier LLMs and VLMs locally on Qualcomm devices across NPU, GPU, and CPU with a few lines of code项目地址: https://gitcode.com/GitHub_Trending/ne/GenieX本指南围绕 GenieX 仓库中 bindings/python/BUILD.md 展开系统讲解 GenieX Python 绑定的构建与开发全流程同一个发布标签下如何产出geniex、geniex-llama-cpp、geniex-qairt三个纯 Python 源码分发包sdist安装时如何通过 HTTP Range 请求按需拉取平台匹配的 SDK 原生库以及如何在本地从源码构建 SDK、打包 sdist 并做端到端验证。读完本文你将掌握 GenieX Python 绑定的产物布局、安装源选择、构建期/运行期环境变量、Dev 模式与 Bazel 构建并能独立完成从源码到可安装 sdist的完整构建链路。面向的读者需要在 Qualcomm 平台Linux ARM64 / Windows ARM64 等上部署 GenieX Python 绑定、参与其 Python 包开发或希望理解其纯 Python 安装时拉取原生库分发策略的开发者。一、产物布局一个发布标签三个同源 sdistGenieX 的 Python 绑定采用三合一的分发策略同一个发布标签下从仓库同时产出三个纯 Python 源码分发包sdist它们的差异仅在于打包时编排stage了哪些后端插件sdist源码树编排的插件geniexbindings/python/llama.cpp和QAIRTgeniex-llama-cppbindings/python-llama-cpp/仅 llama.cppgeniex-qairtbindings/python-qairt/仅 QAIRT从源码结构看三个 sdist 共享同一套 Python 逻辑geniex/包、安装期 SDK 拉取器_sdk_fetch.py、共享构建驱动_shared_setup.py、PEP 517 包装器_geniex_backend.py、README.md与LICENSE都只维护在bindings/python/下其余两个目录bindings/python-llama-cpp/、bindings/python-qairt/在仓库中仅各自 git 跟踪一个 4 行的setup.py。共享源码的镜像动作由 bindings/sync_siblings.py 在每次构建前完成见 bindings/sync_siblings.py它把_sdk_fetch.py、_shared_setup.py、_geniex_backend.py、README.md、LICENSE、MANIFEST.in六个文件与整个geniex/目录复制进两个兄弟树并从规范版pyproject.toml通过正则只替换name和description两个字段见 bindings/sync_siblings.py生成各兄弟树自己的pyproject.toml。被镜像的副本在 git 中被忽略git-ignored不会污染仓库。每个 sdist 的pyproject.toml/setup.py/MANIFEST.in各司其职例如 bindings/python/MANIFEST.in 明确收编了setup.py、_sdk_fetch.py、_shared_setup.py、_geniex_backend.py、README.md、LICENSE、pyproject.toml并递归包含geniex/*.py、排除geniex/lib——因为 sdist 阶段绝不携带预编译库原生库留给安装阶段拉取。二、pip 安装时发生了什么纯 Python sdist 按需 SDK 拉取三个 sdist 都是纯 Python这是理解整个分发策略的关键。当pip install从任意一个 sdist 组装 wheel 时自定义的build_py命令会执行_sdk_fetch.fetch(..., backends...)从与平台匹配的 SDK zip 中只拉取当前 sdist 所需的那一片geniexbackends(llama-cpp, qairt)见 bindings/python/setup.pygeniex-llama-cppbackends(llama-cpp,)geniex-qairtbackends(qairt,)。共享驱动在 bindings/python/_shared_setup.py 中run_setup定义一个继承build_py的_BuildPyWithSdk类在run()里先调用_sdk_fetch.fetch(here / geniex, release_tag, backendsbackends)再交给父类执行见 bindings/python/_shared_setup.py。release_tag从 bindings/python/geniex/_version.py 读取用于拼装 SDK 下载地址。SDK 拉取的核心逻辑在 bindings/python/_sdk_fetch.py优先走 HTTP Range 请求见 bindings/python/_sdk_fetch.py先请求 zip 尾部探测 End-of-Central-Directory 记录解析中央目录筛选出当前 sdist 需要的条目核心库geniex.dll/libgeniex.so/libgeniex.dylib与对应插件子目录再按最小字节区间分段拉取就地解压并做 CRC32 校验——相比整体下载显著节省带宽镜像不支持 Range 时回退为全量下载同时下载.sha256sidecar 文件做完整性校验对公开默认源缺少 sidecar 会直接判定失败避免无人值守安装静默跳过校验见 bindings/python/_sdk_fetch.py遇到 ZIP64 归档会明确放弃 Range 路径并回退全量下载bindings/python/_sdk_fetch.py拉取完成后原生库被安放到site-packages/geniex/lib/下由 bindings/python/geniex/_ffi/_lib.py 在运行时发现并加载。三、安装源PyPI、TestPyPI 与 GitHub Release原文档给出了三种权威安装方式均可直接复制使用# 从 PyPI 安装稳定版 pip install geniex pip install geniex-llama-cpp pip install geniex-qairt # 从 TestPyPI 安装预发布标签预发布标签会自动发布到 TestPyPI pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple geniex pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple geniex-llama-cpp pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple geniex-qairt # 从 GitHub Release 直接安装canonical 来源——按需选择分发版本 pip install https://github.com/qualcomm/GenieX/releases/download/v0.0.3-alpha.1/geniex-pysdist-v0.0.3-alpha.1.tar.gz pip install https://github.com/qualcomm/GenieX/releases/download/v0.0.3-alpha.1/geniex-pysdist-llama_cpp-v0.0.3-alpha.1.tar.gz pip install https://github.com/qualcomm/GenieX/releases/download/v0.0.3-alpha.1/geniex-pysdist-qairt-v0.0.3-alpha.1.tar.gz需要注意几点TestPyPI 命令中--extra-index-url https://pypi.org/simple是为了让依赖如tqdm4.65声明于 bindings/python/pyproject.toml能从未发布到 TestPyPI 的 PyPI 官方索引补齐上例中v0.0.3-alpha.1是原文档写作时的示例标签实际安装时请替换为仓库当前发布的标签当前仓库 bindings/python/geniex/_version.py 中__version__ 0.1.0由于geniex、geniex-llama-cpp、geniex-qairt三个包都提供geniex模块安装多个会产生覆盖冲突通常按目标设备能力只装一个即可。安装后命令行入口为geniex-py在 bindings/python/pyproject.toml 中定义这是刻意与 Go 版geniex二进制错开的命名。支持的平台自动 SDK 下载SDK 下载的目标平台由sys.platform与platform.machine()联合判定映射关系如下sys.platformmachine()Release 资产win32arm64geniex-sdk-windows-arm64-tag.ziplinuxaarch64/arm64geniex-sdk-linux-arm64-tag.zip该映射表在 bindings/python/_sdk_fetch.py 中有源码级定义。任何其他平台组合都会让pip install以明确的错误信息中止详见下文不支持的平台。此外从源码实现可以观察到两个平台相关的补充细节CPU-only 变体针对无法运行默认 linux-arm64 SDK 的 armv8.0 基线板如 unoqCI 会额外发布-cpu后缀的 CPU-only SDK通过环境变量GENIEX_SDK_VARIANTcpu显式选择见 bindings/python/_sdk_fetch.py。CPU-only SDK 不含 QAIRT 后端那些板卡没有 NPU此时安装器会主动从后端集合中剔除qairt并提示改装geniex-llama-cppbindings/python/_sdk_fetch.py默认拉取顺序为公共 S3 镜像qaihub-public-assets.s3.us-west-2.amazonaws.com/qai-hub-geniex/geniex-sdk-platform-tag.zip扁平布局文件名中的tag用于区分版本→ 匹配的 GitHub Release 资产任何网络、HTTP 或 SHA-256 错误都会触发回退bindings/python/_sdk_fetch.py。四、构建期与运行期环境变量速查原文档将环境变量分为构建期与运行期两类这里连同源码中确认的补充变量一并整理构建期影响pip install/python -m build变量用途GENIEX_SDK_DOWNLOAD_URL覆盖 SDK zip 的基础 URL内部镜像或file:///...用于离线测试。实际资产名geniex-sdk-platform-tag.zip会被自动追加。设置为单个来源后会禁用 S3/GitHub 回退覆盖模式下允许缺少.sha256sidecar 并以无校验方式继续见 bindings/python/_sdk_fetch.pyGENIEX_SKIP_SDK_DOWNLOAD设为1跳过 SDK 下载——适用于不支持的平台或运行时通过GENIEX_LIB_PATH自行提供库文件的场景GENIEX_SDK_VARIANT取值为default或cpu源码级确认见 bindings/python/_sdk_fetch.py仅对 linux-arm64 生效用于选择 CPU-only SDK运行期影响 Python 进程加载原生库变量用途GENIEX_LIB_PATH指向已构建好的libgeniex.so/geniex.dll所在目录或文件本身。覆盖全部自动发现逻辑优先于 wheel 布局、仓库内 Dev 构建和 OS 链接器搜索运行时加载顺序在 bindings/python/geniex/_ffi/_lib.py 中有清晰实现GENIEX_LIB_PATH→ wheel 布局site-packages/geniex/lib/→ 仓库内 Dev 构建repo/sdk/pkg-geniex/lib/→ctypes.util.find_library(geniex)。值得注意的实现细节是若 wheel 与 Dev 构建同时存在会按 mtime 选择较新的那份避免陈旧副本遮蔽新构建。加载前还会以RTLD_LOCAL预加载同目录下的全部共享库并设置LD_LIBRARY_PATH/PATH、GENIEX_PLUGIN_PATH以保证插件 dlopen 时依赖可解析。五、不支持的平台错误处理与两条出路如果sys.platform/machine()不在上表内pip install会中止并输出明确错误源码中的错误文本见 bindings/python/_sdk_fetch.py。原文档给出两条官方 workaround方案一本地构建 SDK 跳过下载GENIEX_SKIP_SDK_DOWNLOAD1 pip install sdist-url export GENIEX_LIB_PATH/path/to/sdk/pkg-geniex/lib/方案二仓库检出内预置库文件# 把 SDK 安装产物复制到包内 lib 目录再直接从仓库目录安装 # 将 sdk/pkg-geniex/lib 复制到 bindings/python/geniex/lib/ pip install bindings/python/两条路线的共同前提是先把 SDK 原生库构建出来见下文从源码构建 SDK。六、Dev 模式从仓库检出直接跑在仓库内开发时无需任何环境变量——只要把 SDK 构建到树内默认位置bindings/python/geniex/_ffi/_lib.py 的 Dev 分支会自动从sdk/pkg-geniex/lib/发现原生库bindings/python/geniex/_ffi/_lib.pycd sdk cmake --preset default # 本机原生构建Linux x86_64 cmake --build --preset default cmake --install build-default --prefix pkg-geniex python -m geniex.cli chat /path/to/model.gguf其他平台的 preset 名包括arm64-linux-snapdragon-release、arm64-windows-snapdragon-release、arm64-android-snapdragon-release等完整清单定义在 sdk/CMakePresets.json 中含 debug/release、snapdragon/cpu-only 各变体。无论哪个平台构建后都必须执行cmake --install因为pkg-geniex/lib/正是运行时自动发现与GENIEX_LIB_PATH共同约定的安装位置。如需强制指定库目录设置GENIEX_LIB_PATH/path/to/lib/dir/即可覆盖自动发现。七、从源码构建 SDK官方先决条件Python 3.10、CMake 3.20、C 编译器GCC / Clang / MSVC。SDK 本体位于 sdk/ 目录C 接口 sdk/src/插件 sdk/plugins/完整平台专项构建说明Linux、Windows ARM64 Hexagon、Android 交叉编译以 CMake preset 形式集中在 sdk/CMakePresets.json。cmake --install之后库文件落在sdk/pkg-geniex/lib/Dev 模式与GENIEX_LIB_PATH均能直接拾取。八、本地构建三个 sdist 并做端到端测试先镜像共享源码再逐个构建python -m pip install build python bindings/sync_siblings.py python -m build --sdist bindings/python --outdir dist/ # geniex python -m build --sdist bindings/python-llama-cpp --outdir dist/ # geniex-llama-cpp python -m build --sdist bindings/python-qairt --outdir dist/ # geniex-qairt ls dist/ # geniex-version.tar.gz # geniex_llama_cpp-version.tar.gz # geniex_qairt-version.tar.gz三个 sdist 均为纯 Python对应的 SDK 库切片在安装阶段才被拉取。端到端本地测试文件镜像file://原文档给出了一个完全离线的验证流程适合 CI 或断网环境# 1. 产出本地 SDK zip示例arm64 Linux cd sdk cmake --preset arm64-linux-snapdragon-release \ cmake --build --preset arm64-linux-snapdragon-release \ cmake --install build-arm64-linux-snapdragon-release --prefix pkg-geniex mkdir -p /tmp/geniex-mirror (cd sdk zip -r /tmp/geniex-mirror/geniex-sdk-linux-arm64-v0.0.3-alpha.1.zip pkg-geniex) sha256sum /tmp/geniex-mirror/geniex-sdk-linux-arm64-v0.0.3-alpha.1.zip \ /tmp/geniex-mirror/geniex-sdk-linux-arm64-v0.0.3-alpha.1.zip.sha256 # 2. 指向镜像安装 sdist GENIEX_SDK_DOWNLOAD_URLfile:///tmp/geniex-mirror \ pip install dist/geniex-0.0.3a1.tar.gz # 3. 冒烟测试 python -c import geniex; geniex.init(); print(geniex.version())注意几点镜像目录中资产文件名必须严格匹配geniex-sdk-platform-tag.zip约定tag与_version.py中的__release_tag__一致file://路径下_sdk_fetch.py会走本地文件读取分支bindings/python/_sdk_fetch.py同样支持Range 切片语义。九、Bazel 构建 sdist仓库以 Bazel 管理构建sdist 目标同样可用bazelisk build //bindings/python:geniex_sdist # dev0.0.0.dev0 bazelisk build //bindings/python:geniex_sdist --defineVERSIONv0.0.3-alpha.1 # release输出为bazel-bin/bindings/python/geniex_sdist.tar.gz与python -m build --sdist产物形状一致、安装行为一致。底层实现见 bindings/python/BUILD.bazelgen_versiongenrule 根据--defineVERSION生成 bindings/python/geniex/_version.py把 SemVer 标签转换为 PEP 440 版本号v0.1.0-alpha.1 → 0.1.0a1、-beta.→b、-rc.→rc同时写出__release_tag__供setup.py拼装 SDK 下载 URLbindings/python/BUILD.bazelgeniex_sdistgenrule 把源码树暂存到临时目录后委托python3 -m build --sdist完成打包bindings/python/BUILD.bazel因此 Bazel 目标本身不产生与直接调用python -m build不同的产物。十、两个值得了解的底层设计PEP 517 包装器为缺失 tomllib 的 Python 兜底bindings/python/pyproject.toml 声明了树内构建后端build-backend _geniex_backend、backend-path [.]。bindings/python/_geniex_backend.py 在导入setuptools.build_meta之前先检查sys.modules是否已有tomllib若 stdlib 缺失则把tomli注册为tomllib别名见 bindings/python/_geniex_backend.py随后原样转发全部 PEP 517 / PEP 660 钩子。这是为了在 Qualcomm Linux 精简版 Python 3.12其 stdlib 不含tomllib而上游setuptools.compat.py310在 3.11 分支无条件导入tomllib上让pip install得以成功在具备 stdlibtomllib的主机上别名路径被完全跳过行为等同原生 setuptools。tomli2.0被显式放入requires确保隔离构建环境可注入该垫片。wheel 内不装原生库package-data只服务于显式打包值得注意的是bindings/python/pyproject.toml 中geniex [lib/**/*]的package-data仅在你显式执行pip wheel并把sdk/pkg-geniex/lib/复制进geniex/lib/时才会把原生库打进 wheel而 MANIFEST.in 又用prune geniex/lib保证 sdist 永远纯 Python。这一默认安装时拉取、显式场景才随包携带的双轨设计正是理解 GenieX Python 分发策略的核心。十一、发布验证与冒烟测试发布流程最后一步是端到端验证。实践中可通过从 TestPyPI 安装预发布 sdist → 指向file://本地镜像 →python -c import geniex; geniex.init(); print(geniex.version())这条链路完成冒烟测试构建期GENIEX_SDK_DOWNLOAD_URL指向镜像即可让安装全程离线可复现。若需同时验证多个后端切片分别安装三个 sdist 并确认geniex/lib/下出现的插件目录llama_cpp/、qairt/与所选分发一致即可。小结GenieX Python 绑定采用纯 Python sdist 安装时按需拉取 SDK 切片的分发模型三个 sdist 共享同一份规范源码通过 bindings/sync_siblings.py 在构建前镜像同步安装时自定义build_py触发_sdk_fetch优先走 HTTP Range 局部拉取并回退到带 SHA-256 校验的全量下载运行期由GENIEX_LIB_PATH或自动发现机制加载原生库。无论是普通用户安装、开发者 Dev 模式、还是参与打包发布的工程人员都可以在上文的环境变量与命令清单中直接找到可复用的操作路径。【免费下载链接】GenieXRun frontier LLMs and VLMs locally on Qualcomm devices across NPU, GPU, and CPU with a few lines of code项目地址: https://gitcode.com/GitHub_Trending/ne/GenieX创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考