Skip to content

feat(vectordb)Migrate vectordb engine to abi3 packaging#897

Merged
qin-ctx merged 1 commit intomainfrom
feature/abi3-engine
Mar 23, 2026
Merged

feat(vectordb)Migrate vectordb engine to abi3 packaging#897
qin-ctx merged 1 commit intomainfrom
feature/abi3-engine

Conversation

@zhoujh01
Copy link
Copy Markdown
Collaborator

PR 标题

Migrate vectordb engine to abi3 packaging

变更摘要

这个 PR 将 vectordb 原生引擎从 pybind11 绑定迁移到基于 CPython Stable ABI 的 abi3 打包模式,并通过一层轻量的 Python 适配层保持 Python 侧 API 的可用性和整体使用方式稳定。

这次改动的核心目标有三个:

  1. 将原来按 CPython 小版本分别构建 wheel 的模式,收敛为基于 Python 3.10 的一条 abi3 wheel 产线,供 3.10+ 复用。
  2. 从引擎构建、打包和 CI 流程中移除 pybind11 依赖。
  3. 保留现有的 x86 / 非 x86 运行时后端选择逻辑,同时继续暴露相同层级的 Python 入口。

背景与动机

此前的 vectordb engine 打包方式依赖 pybind11,并且生成的是与具体 CPython 版本绑定的扩展二进制。这会带来几个问题:

  1. wheel 矩阵偏大,每个 Python 小版本都需要重新构建和发布原生扩展。
  2. 引擎绑定层依赖 pybind11,扩大了构建依赖和 CI 维护面。
  3. 运行时 loader 与 CPython 特定扩展文件命名耦合较深,不利于复用稳定 ABI 的分发方式。

迁移到 abi3 后,可以在保留 C++ 引擎实现的前提下,把 wheel 分发从“跟着 Python 小版本走”变成“跟着 Stable ABI 走”。

变更范围

本 PR 包含:

  1. abi3 C API 后端替换原有 vectordb 的 pybind11 Python 绑定实现。
  2. 新增纯 Python 适配层,在新的 backend 导出之上重建 engine 对外 Python API。
  3. 调整 CMake 和 setuptools 打包逻辑,使 engine 产物以 *.abi3.so / *.pyd 形式输出和打包。
  4. 将 release 默认构建策略收敛到 cp310 这一条 stable-ABI 基线。
  5. 删除遗留的 pybind11 源码、依赖和工作流引用。

本 PR 不包含:

  1. vectordb 检索或索引算法层面的功能变更。
  2. runtime backend 选择策略的重设计。
  3. 超出兼容现有 engine 入口所需范围之外的大规模 API 扩展。

设计方案

1. 整体运行时架构

迁移后的运行时可以拆成四层:

  1. src/abi3_engine_backend.cpp
    使用 CPython limited API 暴露原生引擎能力,并通过 _ENGINE_BACKEND_API = "abi3-v1" 标记 backend 协议版本。
  2. openviking/storage/vectordb/engine/_python_api.py
    在 Python 层重建 IndexEnginePersistStoreVolatileStore、请求对象、结果对象和 BytesRow 包装。
  3. openviking/storage/vectordb/engine/__init__.py
    延续现有 variant 选择逻辑,负责加载正确的 backend 二进制,并在 legacy 导出模式和 abi3-v1 导出模式之间切换。
  4. src/abi3_x86_caps.cpp
    独立承担 x86 CPU 能力探测,供 loader 在运行时自动选择 sse3avx2avx512 后端。

这样拆分后,C++ backend 只负责提供稳定、收敛的底层能力,Python API 兼容问题交给 Python 层适配。

2. Python API 兼容策略

本次迁移的关键设计是:不再让 C++ 直接导出复杂 Python 对象,而是改为暴露一套更窄、更稳定的 backend 协议,再由 Python 层重建对外 API。

具体做法:

  1. C++ backend 只导出低层原语,例如 _new_index_engine_index_engine_search_store_exec_op_new_schema_new_bytes_row 等函数。
  2. openviking/storage/vectordb/engine/_python_api.py 负责把这些原语重新封装成外部已有的 Python 类和结果对象。
  3. openviking/storage/vectordb/engine/__init__.py 在发现 backend 暴露 _ENGINE_BACKEND_API == "abi3-v1" 时,调用 build_abi3_exports(),并把重建后的符号注入模块命名空间。

这样做的收益是:

  1. C++ 绑定层更简单,不再深度依赖 pybind11 风格的对象导出。
  2. Python 对外入口仍然保持在 openviking.storage.vectordb.engine
  3. 后续如果 backend 协议演进,可以围绕 abi3-v1 这种显式版本做增量兼容。

3. 原生 backend 设计

新的 C++ backend 直接基于 CPython limited API 实现,核心点如下:

  1. src/abi3_engine_backend.cppsrc/abi3_x86_caps.cpp 都显式定义了 Py_LIMITED_API=0x030A0000
  2. 通过 OV_PY_MODULE_NAME 生成不同的 PyInit_<module> 入口,使同一套实现可以产出 _native_x86_sse3_x86_avx2_x86_avx512 等模块。
  3. 对可能较重的原生调用,用 PyEval_SaveThread / PyEval_RestoreThread 包裹,释放 GIL。
  4. 原生资源通过 capsule / handle 模式在 Python 与 C++ 间传递,而不是继续走 pybind11 的对象绑定模式。

这使 backend 更贴近 stable ABI 分发模型,也让模块初始化和导出边界更清晰。

4. backend 选择与加载行为

这次迁移刻意保持了原有 loader 的行为模型,降低运行时回归风险:

  1. x86 平台下,仍然基于“已打包 variant + 当前 CPU 能力”做自动选择,优先级仍是 avx512 -> avx2 -> sse3
  2. 非 x86 平台仍然加载 _native
  3. OV_ENGINE_VARIANT 仍然支持显式覆盖,但现在会同时校验“wheel 中是否打包了该 variant”以及“当前 CPU 是否支持该 variant”。
  4. loader 会显式扫描 importlib.machinery.EXTENSION_SUFFIXES 中带 abi3 的后缀,再回退到常规 import。

因此,运行时策略基本不变,变化主要在 backend 的装载方式和产物命名方式上。

5. 构建与打包设计

构建和打包链路的关键调整如下:

  1. setup.py 中的 engine extension 被标记为 py_limited_api=True
  2. bdist_wheel 在 finalize 阶段设置 py_limited_api = "cp310",把 cp310 作为 stable ABI wheel 的基线标签。
  3. setup.pypyproject.toml 的 package data 从 storage/vectordb/engine/*.so 调整为 storage/vectordb/engine/*.abi3.so
  4. wheel 输出目录在构建前会主动清理旧的非 abi3 engine 二进制,避免陈旧产物混入 wheel。
  5. setuptools 会把 OV_PY_EXT_SUFFIXOV_PY_OUTPUT_DIR 传给 CMake,确保 CMake 生成的模块文件名和 wheel 预期严格对齐。

这部分设计的目标是确保“构建系统、wheel 文件名、运行时加载逻辑”三者一致,不再混用旧的 .so 语义。

6. CI 与发布策略调整

CI / release 侧的策略也一起收敛:

  1. .github/workflows/_build.yml.github/workflows/release.yml 的默认 python_json 都改成 ["3.10"]
  2. workflow 中安装构建依赖时不再安装 pybind11
  3. 旧矩阵假设下额外存在的 wheel verify job 被删除。
  4. 仓库文档和说明更新为 “vectordb engine 是 Python abi3 扩展”。

这个调整的核心思路是:既然 engine wheel 进入 stable ABI 分发模式,那么 release 默认矩阵就不应该继续按每个 CPython 小版本平铺。

关键代码整理

新增文件

  1. src/abi3_engine_backend.cpp
    新的 stable-ABI backend,覆盖 engine、store、schema、bytes-row 等原生能力导出。
  2. openviking/storage/vectordb/engine/_python_api.py
    新的 Python 兼容层,用于在 backend 原语之上重建对外 API。
  3. src/abi3_x86_caps.cpp
    从旧的 CPU capability probe 演进而来,并改造成 limited API 扩展。
  4. tests/misc/test_abi3_packaging_config.py
    覆盖 abi3 打包配置、workflow 默认值、pybind11 移除、limited API 预期等回归点。

删除文件

  1. src/pybind11_interface.cpp
  2. src/py_accessors.h
  3. src/cpu_feature_probe.cpp

重点更新文件

  1. openviking/storage/vectordb/engine/__init__.py
    增强 loader,使其既能识别 abi3 backend,又能将 abi3 backend 桥接回 Python 命名空间。
  2. setup.py
    切换到 limited-ABI wheel 配置,并处理旧产物清理。
  3. src/CMakeLists.txt
    调整 variant backend 目标生成逻辑,统一产出 limited-API 模块。
  4. .github/workflows/_build.yml.github/workflows/release.yml
    默认 Python 矩阵收敛,构建依赖移除 pybind11

兼容性说明

  1. 对外 import 路径仍然是 openviking.storage.vectordb.engine
  2. runtime variant 选择仍然保留环境变量驱动和 CPU 感知能力。
  3. wheel 标签基线变为 Python 3.10 的 stable ABI。
  4. 一些 pybind11 时代遗留但不再需要的导出被移除,例如 FetchDataResult

风险与关注点

  1. abi3-v1 现在成为 C++ 与 Python 之间的关键协议边界,后续 backend 变更必须同步维护 _python_api.py
  2. wheel 兼容性现在更多依赖 limited API 使用是否规范,而不是由 pybind11 屏蔽细节,因此需要更明确的回归测试保护。
  3. release 默认矩阵已经缩小,如果仍有隐含的解释器版本耦合问题,后续可能只会在下游安装验证中暴露。

后续建议

  1. 增加跨 Python 版本的安装 smoke test,验证同一个 cp310-abi3 wheel 在多个受支持 CPython 版本下都能安装和加载。
  2. abi3-v1 backend 协议单独文档化,降低后续维护成本。
  3. 如果 Windows 是主要发布风险点,可以补一个针对 .pyd 产物命名与加载的独立检查。

验证结果

已执行:

pytest tests/misc/test_abi3_packaging_config.py tests/misc/test_vectordb_engine_loader.py -q

结果:

  1. 10 passed
  2. 运行环境:Python 3.11.4 / darwin
  3. 存在少量已有的 Pydantic deprecation warnings,但与本 PR 变更无直接关系

Reviewer 建议阅读顺序

  1. src/abi3_engine_backend.cpp
  2. openviking/storage/vectordb/engine/_python_api.py
  3. openviking/storage/vectordb/engine/__init__.py
  4. setup.py
  5. src/CMakeLists.txt
  6. tests/misc/test_abi3_packaging_config.py
  7. tests/misc/test_vectordb_engine_loader.py

chore: remove pybind11 remnants after abi3 migration

fix: scope linux abi3 wheel smoke test to engine loader
@github-actions
Copy link
Copy Markdown

Failed to generate code suggestions for PR

@qin-ctx qin-ctx merged commit 033826f into main Mar 23, 2026
40 of 41 checks passed
@qin-ctx qin-ctx deleted the feature/abi3-engine branch March 23, 2026 11:11
@github-project-automation github-project-automation bot moved this from Backlog to Done in OpenViking project Mar 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants