tensor-spec 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. tensor_spec-0.1.0/.cache/.gitignore +1 -0
  2. tensor_spec-0.1.0/.cache/11480870307212335292 +208 -0
  3. tensor_spec-0.1.0/.cache/12807722618152218300 +4 -0
  4. tensor_spec-0.1.0/.cache/135790637525585456 +378 -0
  5. tensor_spec-0.1.0/.cache/14076623044218626799 +2236 -0
  6. tensor_spec-0.1.0/.cache/14146587318570206937 +4 -0
  7. tensor_spec-0.1.0/.cache/14903340242216501074 +253 -0
  8. tensor_spec-0.1.0/.cache/15183100223470348559 +332 -0
  9. tensor_spec-0.1.0/.cache/15213489598760314030 +73 -0
  10. tensor_spec-0.1.0/.cache/15596545198510088444 +4 -0
  11. tensor_spec-0.1.0/.cache/16264416866309051418 +439 -0
  12. tensor_spec-0.1.0/.cache/16767517100348141200 +134 -0
  13. tensor_spec-0.1.0/.cache/16849179548933260854 +4 -0
  14. tensor_spec-0.1.0/.cache/2099532674560583867 +209 -0
  15. tensor_spec-0.1.0/.cache/2988071765696220937 +269 -0
  16. tensor_spec-0.1.0/.cache/3029880074666011341 +451 -0
  17. tensor_spec-0.1.0/.cache/3476900567878811119 +4 -0
  18. tensor_spec-0.1.0/.cache/3732650278285798869 +4 -0
  19. tensor_spec-0.1.0/.cache/3821033688170008457 +4 -0
  20. tensor_spec-0.1.0/.cache/3865067390632366777 +4 -0
  21. tensor_spec-0.1.0/.cache/3931284605638262936 +4 -0
  22. tensor_spec-0.1.0/.cache/4886784083628767490 +331 -0
  23. tensor_spec-0.1.0/.cache/5350013240325030281 +4 -0
  24. tensor_spec-0.1.0/.cache/6131877972298479153 +4 -0
  25. tensor_spec-0.1.0/.cache/6607811052874903465 +4 -0
  26. tensor_spec-0.1.0/.cache/7493900657779480117 +422 -0
  27. tensor_spec-0.1.0/.cache/7670318653569743873 +4 -0
  28. tensor_spec-0.1.0/.cache/8512581374698401569 +4 -0
  29. tensor_spec-0.1.0/.cache/8514746950225771701 +208 -0
  30. tensor_spec-0.1.0/.cache/9353989903595800104 +4 -0
  31. tensor_spec-0.1.0/.cache/9980786406041809768 +239 -0
  32. tensor_spec-0.1.0/.claude/settings.local.json +56 -0
  33. tensor_spec-0.1.0/.github/codecov.yml +22 -0
  34. tensor_spec-0.1.0/.github/renovate.json +6 -0
  35. tensor_spec-0.1.0/.github/workflows/cd-docs.yml +33 -0
  36. tensor_spec-0.1.0/.github/workflows/cd-release.yml +29 -0
  37. tensor_spec-0.1.0/.github/workflows/ci-check-pr-title.yml +93 -0
  38. tensor_spec-0.1.0/.github/workflows/ci-static-checks.yml +13 -0
  39. tensor_spec-0.1.0/.github/workflows/ci-tests.yml +37 -0
  40. tensor_spec-0.1.0/.gitignore +29 -0
  41. tensor_spec-0.1.0/CONTRIBUTING.md +52 -0
  42. tensor_spec-0.1.0/PKG-INFO +118 -0
  43. tensor_spec-0.1.0/README.md +106 -0
  44. tensor_spec-0.1.0/_typos.toml +9 -0
  45. tensor_spec-0.1.0/cases/zero-size-bugs/cpu_cdist.txt +8 -0
  46. tensor_spec-0.1.0/cases/zero-size-bugs/cpu_ctc_loss.txt +11 -0
  47. tensor_spec-0.1.0/cases/zero-size-bugs/cpu_generate_proposals.txt +54 -0
  48. tensor_spec-0.1.0/cases/zero-size-bugs/cpu_getitem.txt +14 -0
  49. tensor_spec-0.1.0/cases/zero-size-bugs/cpu_put_along_axis.txt +8 -0
  50. tensor_spec-0.1.0/cases/zero-size-bugs/cpu_set_.txt +8 -0
  51. tensor_spec-0.1.0/cases/zero-size-bugs/gpu_flashmask_attention.txt +23 -0
  52. tensor_spec-0.1.0/cases/zero-size-bugs/gpu_generate_proposals.txt +26 -0
  53. tensor_spec-0.1.0/cases/zero-size-bugs/gpu_variable_length_memory_efficient_attention.txt +19 -0
  54. tensor_spec-0.1.0/cases/zero-size-bugs/gpu_weight_only_linear.txt +35 -0
  55. tensor_spec-0.1.0/docs/api/index.md +5 -0
  56. tensor_spec-0.1.0/docs/design/architecture.md +657 -0
  57. tensor_spec-0.1.0/docs/design/case-representation.md +534 -0
  58. tensor_spec-0.1.0/docs/design/decisions.md +498 -0
  59. tensor_spec-0.1.0/docs/design/implementation-prompt.md +98 -0
  60. tensor_spec-0.1.0/docs/design/legacy-analysis.md +571 -0
  61. tensor_spec-0.1.0/docs/design/modernization.md +379 -0
  62. tensor_spec-0.1.0/docs/index.md +31 -0
  63. tensor_spec-0.1.0/docs/plans/2026-03-03-phase0-implementation.md +2312 -0
  64. tensor_spec-0.1.0/docs/plans/2026-03-05-phase1-cross-framework-accuracy.md +2110 -0
  65. tensor_spec-0.1.0/docs/plans/2026-03-05-phase2-process-isolation-ipc.md +2330 -0
  66. tensor_spec-0.1.0/docs/plans/2026-03-11-docs-ci-test-design.md +284 -0
  67. tensor_spec-0.1.0/docs/plans/2026-03-11-docs-ci-test-implementation.md +701 -0
  68. tensor_spec-0.1.0/docs/plans/2026-03-20-zendev-design.md +113 -0
  69. tensor_spec-0.1.0/docs/rationale.md +169 -0
  70. tensor_spec-0.1.0/justfile +78 -0
  71. tensor_spec-0.1.0/loom.toml +15 -0
  72. tensor_spec-0.1.0/prek.toml +30 -0
  73. tensor_spec-0.1.0/pyproject.toml +133 -0
  74. tensor_spec-0.1.0/scripts/setup-venvs.sh +128 -0
  75. tensor_spec-0.1.0/src/tensor_spec/__init__.py +1 -0
  76. tensor_spec-0.1.0/src/tensor_spec/backend/__init__.py +1 -0
  77. tensor_spec-0.1.0/src/tensor_spec/backend/base.py +55 -0
  78. tensor_spec-0.1.0/src/tensor_spec/backend/paddle_backend.py +67 -0
  79. tensor_spec-0.1.0/src/tensor_spec/backend/torch_backend.py +64 -0
  80. tensor_spec-0.1.0/src/tensor_spec/cli.py +364 -0
  81. tensor_spec-0.1.0/src/tensor_spec/compare/__init__.py +0 -0
  82. tensor_spec-0.1.0/src/tensor_spec/compare/comparator.py +79 -0
  83. tensor_spec-0.1.0/src/tensor_spec/compare/tolerance.py +49 -0
  84. tensor_spec-0.1.0/src/tensor_spec/config/__init__.py +1 -0
  85. tensor_spec-0.1.0/src/tensor_spec/config/case.py +28 -0
  86. tensor_spec-0.1.0/src/tensor_spec/config/parser.py +385 -0
  87. tensor_spec-0.1.0/src/tensor_spec/config/project.py +131 -0
  88. tensor_spec-0.1.0/src/tensor_spec/datagen/__init__.py +1 -0
  89. tensor_spec-0.1.0/src/tensor_spec/datagen/constraints.py +38 -0
  90. tensor_spec-0.1.0/src/tensor_spec/datagen/generator.py +91 -0
  91. tensor_spec-0.1.0/src/tensor_spec/ipc/__init__.py +1 -0
  92. tensor_spec-0.1.0/src/tensor_spec/ipc/cuda_handle.py +93 -0
  93. tensor_spec-0.1.0/src/tensor_spec/ipc/gpu_array_view.py +47 -0
  94. tensor_spec-0.1.0/src/tensor_spec/ipc/shared_memory.py +94 -0
  95. tensor_spec-0.1.0/src/tensor_spec/log/__init__.py +0 -0
  96. tensor_spec-0.1.0/src/tensor_spec/log/setup.py +23 -0
  97. tensor_spec-0.1.0/src/tensor_spec/log/writer.py +48 -0
  98. tensor_spec-0.1.0/src/tensor_spec/mapping/__init__.py +0 -0
  99. tensor_spec-0.1.0/src/tensor_spec/mapping/mappings/apis.toml +62 -0
  100. tensor_spec-0.1.0/src/tensor_spec/mapping/mappings/paddle.rules.toml +14 -0
  101. tensor_spec-0.1.0/src/tensor_spec/mapping/mappings/torch.rules.toml +75 -0
  102. tensor_spec-0.1.0/src/tensor_spec/mapping/registry.py +161 -0
  103. tensor_spec-0.1.0/src/tensor_spec/py.typed +0 -0
  104. tensor_spec-0.1.0/src/tensor_spec/setup_cmd.py +123 -0
  105. tensor_spec-0.1.0/src/tensor_spec/spec/__init__.py +1 -0
  106. tensor_spec-0.1.0/src/tensor_spec/spec/device.py +76 -0
  107. tensor_spec-0.1.0/src/tensor_spec/spec/state.py +14 -0
  108. tensor_spec-0.1.0/src/tensor_spec/spec/stats.py +70 -0
  109. tensor_spec-0.1.0/src/tensor_spec/spec/tensor.py +155 -0
  110. tensor_spec-0.1.0/src/tensor_spec/tester/__init__.py +0 -0
  111. tensor_spec-0.1.0/src/tensor_spec/tester/accuracy.py +133 -0
  112. tensor_spec-0.1.0/src/tensor_spec/tester/base.py +101 -0
  113. tensor_spec-0.1.0/src/tensor_spec/tester/check.py +153 -0
  114. tensor_spec-0.1.0/src/tensor_spec/tester/isolated_accuracy.py +190 -0
  115. tensor_spec-0.1.0/src/tensor_spec/ui/__init__.py +1 -0
  116. tensor_spec-0.1.0/src/tensor_spec/ui/console.py +59 -0
  117. tensor_spec-0.1.0/src/tensor_spec/worker/__init__.py +1 -0
  118. tensor_spec-0.1.0/src/tensor_spec/worker/__main__.py +5 -0
  119. tensor_spec-0.1.0/src/tensor_spec/worker/coordinator.py +203 -0
  120. tensor_spec-0.1.0/src/tensor_spec/worker/process.py +236 -0
  121. tensor_spec-0.1.0/src/tensor_spec/worker/protocol.py +93 -0
  122. tensor_spec-0.1.0/task.md +270 -0
  123. tensor_spec-0.1.0/tensor-spec.toml +37 -0
  124. tensor_spec-0.1.0/tests/__init__.py +0 -0
  125. tensor_spec-0.1.0/tests/conftest.py +1 -0
  126. tensor_spec-0.1.0/tests/e2e/__init__.py +0 -0
  127. tensor_spec-0.1.0/tests/e2e/test_accuracy_pipeline.py +269 -0
  128. tensor_spec-0.1.0/tests/e2e/test_cli.py +177 -0
  129. tensor_spec-0.1.0/tests/unit/__init__.py +0 -0
  130. tensor_spec-0.1.0/tests/unit/test_backend/__init__.py +0 -0
  131. tensor_spec-0.1.0/tests/unit/test_backend/test_base.py +16 -0
  132. tensor_spec-0.1.0/tests/unit/test_backend/test_paddle_backend.py +104 -0
  133. tensor_spec-0.1.0/tests/unit/test_backend/test_torch_backend.py +100 -0
  134. tensor_spec-0.1.0/tests/unit/test_compare/__init__.py +0 -0
  135. tensor_spec-0.1.0/tests/unit/test_compare/test_comparator.py +159 -0
  136. tensor_spec-0.1.0/tests/unit/test_compare/test_tolerance.py +187 -0
  137. tensor_spec-0.1.0/tests/unit/test_config/__init__.py +0 -0
  138. tensor_spec-0.1.0/tests/unit/test_config/test_case.py +50 -0
  139. tensor_spec-0.1.0/tests/unit/test_config/test_parser.py +119 -0
  140. tensor_spec-0.1.0/tests/unit/test_config/test_project.py +125 -0
  141. tensor_spec-0.1.0/tests/unit/test_datagen/__init__.py +0 -0
  142. tensor_spec-0.1.0/tests/unit/test_datagen/test_constraints.py +32 -0
  143. tensor_spec-0.1.0/tests/unit/test_datagen/test_generator.py +83 -0
  144. tensor_spec-0.1.0/tests/unit/test_ipc/__init__.py +0 -0
  145. tensor_spec-0.1.0/tests/unit/test_ipc/test_cuda_handle.py +103 -0
  146. tensor_spec-0.1.0/tests/unit/test_ipc/test_gpu_array_view.py +69 -0
  147. tensor_spec-0.1.0/tests/unit/test_ipc/test_shared_memory.py +76 -0
  148. tensor_spec-0.1.0/tests/unit/test_log/__init__.py +0 -0
  149. tensor_spec-0.1.0/tests/unit/test_log/test_writer.py +98 -0
  150. tensor_spec-0.1.0/tests/unit/test_mapping/__init__.py +0 -0
  151. tensor_spec-0.1.0/tests/unit/test_mapping/test_mapping_coverage.py +146 -0
  152. tensor_spec-0.1.0/tests/unit/test_mapping/test_registry.py +166 -0
  153. tensor_spec-0.1.0/tests/unit/test_spec/__init__.py +0 -0
  154. tensor_spec-0.1.0/tests/unit/test_spec/test_device.py +63 -0
  155. tensor_spec-0.1.0/tests/unit/test_spec/test_state.py +21 -0
  156. tensor_spec-0.1.0/tests/unit/test_spec/test_stats.py +62 -0
  157. tensor_spec-0.1.0/tests/unit/test_spec/test_tensor.py +84 -0
  158. tensor_spec-0.1.0/tests/unit/test_tester/__init__.py +0 -0
  159. tensor_spec-0.1.0/tests/unit/test_tester/test_accuracy.py +132 -0
  160. tensor_spec-0.1.0/tests/unit/test_tester/test_base.py +97 -0
  161. tensor_spec-0.1.0/tests/unit/test_tester/test_isolated_accuracy.py +91 -0
  162. tensor_spec-0.1.0/tests/unit/test_worker/__init__.py +0 -0
  163. tensor_spec-0.1.0/tests/unit/test_worker/test_coordinator.py +82 -0
  164. tensor_spec-0.1.0/tests/unit/test_worker/test_gpu_commands.py +69 -0
  165. tensor_spec-0.1.0/tests/unit/test_worker/test_process.py +177 -0
  166. tensor_spec-0.1.0/tests/unit/test_worker/test_protocol.py +116 -0
  167. tensor_spec-0.1.0/tests/validate_mapping_rules.py +121 -0
  168. tensor_spec-0.1.0/uv.lock +887 -0
  169. tensor_spec-0.1.0/zensical.toml +80 -0
@@ -0,0 +1 @@
1
+ *
@@ -0,0 +1,208 @@
1
+ {
2
+ "data": {
3
+ "meta": {},
4
+ "content": "<h1 id=\"tensor-spec\">tensor-spec 设计决策速查<a class=\"headerlink\" href=\"#tensor-spec\" title=\"Permanent link\">&para;</a></h1>\n<p>每个点说明:做了什么选择、为什么、为什么不选其他方案。</p>\n<hr />\n<h2 id=\"1-dataclass-pydantic\">1. dataclass,不用 pydantic<a class=\"headerlink\" href=\"#1-dataclass-pydantic\" title=\"Permanent link\">&para;</a></h2>\n<p><strong>选择:</strong> <code>@dataclass(frozen=True, slots=True)</code></p>\n<p><strong>为什么:</strong>\n- spec 层要求零外部依赖,dataclass 是 stdlib\n- 我们不需要 JSON schema 生成或自动验证——序列化目标是 MessagePack 二进制协议\n- 验证逻辑明确且有限(float stats 不该出现在 bool tensor 上),<code>__post_init__</code> 足够</p>\n<p><strong>为什么不用 pydantic:</strong> pydantic 的核心优势(声明式验证、JSON 序列化)我们用不上。引入它只增加依赖,不增加价值。如果后续需要复杂嵌套验证,dataclass → pydantic 迁移成本很低(字段定义兼容)。</p>\n<hr />\n<h2 id=\"2-tensordtype-tensorshape-dtype\">2. Tensor.dtype() 工厂模式,不用 Tensor(shape, dtype)<a class=\"headerlink\" href=\"#2-tensordtype-tensorshape-dtype\" title=\"Permanent link\">&para;</a></h2>\n<p><strong>选择:</strong> <code>Tensor.float32((2, 3))</code> 返回 <code>FloatTensorSpec</code></p>\n<p><strong>为什么:</strong>\n- dtype 决定了 <code>.stats()</code> 的合法参数(float 有 min/max,bool 有 true_ratio)。工厂方法返回特定类型,类型安全在定义层面就确定了\n- 只有一个标识符 <code>Tensor</code>,不会与任何框架类名冲突\n- 新增 dtype 只需加一个 <code>@classmethod</code>,不需要新的顶级类</p>\n<p><strong>为什么不用 <code>Tensor(shape, \"float32\")</code>:</strong> <code>.stats()</code> 方法必须根据 dtype 接受不同参数,这在同一个类上做隐式多态——给 bool tensor 传 <code>min=-5.9</code> 只能运行时报错,无法从定义层面约束。</p>\n<p><strong>为什么不用 <code>Float32Tensor(shape)</code>:</strong> 标识符爆炸——15+ 个类(float16/32/64/bfloat16/int8/16/32/64/uint8/bool/complex64/128...),每加一个 dtype 就多一个顶级类。</p>\n<hr />\n<h2 id=\"3-device-dlpack\">3. Device 对标 DLPack,不自造体系<a class=\"headerlink\" href=\"#3-device-dlpack\" title=\"Permanent link\">&para;</a></h2>\n<p><strong>选择:</strong> <code>DeviceType</code> IntEnum 的整数值直接映射 DLPack 的 <code>DLDeviceType</code>(CPU=1, CUDA=2, ROCM=10, ONEAPI=14...);字段名 <code>device_type</code> + <code>device_id</code> 对标 DLPack 的 <code>DLDevice</code> 结构体。</p>\n<p><strong>为什么:</strong>\n- DLPack 是跨框架张量共享的事实标准(PyTorch/JAX/Paddle/CuPy/NumPy 都实现了 <code>__dlpack__</code>)\n- 对齐命名后,DeviceSpec 可直接产出 <code>__dlpack_device__()</code> 返回值,零转换\n- 避免自造一套设备名称体系后再写映射表</p>\n<p><strong>为什么不用纯字符串 type:</strong> 字符串无约束,拼写错误无法在定义时发现。IntEnum 提供编译期检查和自动补全。</p>\n<hr />\n<h2 id=\"4-parser-eval\">4. 白名单递归下降 parser,不用 eval()<a class=\"headerlink\" href=\"#4-parser-eval\" title=\"Permanent link\">&para;</a></h2>\n<p><strong>选择:</strong> 手写 tokenizer + 递归下降 parser,只允许 <code>Tensor</code>、<code>Device</code>、<code>tuple</code>、<code>list</code>、<code>slice</code>、字面量。</p>\n<p><strong>为什么:</strong>\n- <code>eval()</code> 是代码执行,不是解析。Config 字符串来自外部,eval 等于允许任意代码注入\n- 手写 parser 的错误信息精确到字符位置,eval 的报错是 Python traceback,对用户没有帮助\n- 调试时可以单步跟踪解析过程,eval 是黑盒</p>\n<p><strong>为什么不用 AST(<code>ast.literal_eval</code> / <code>ast.parse</code>):</strong> <code>ast.literal_eval</code> 不支持函数调用(<code>Tensor.float32(...)</code>)。<code>ast.parse</code> 可以,但需要遍历 AST 做白名单检查,复杂度不低于直接手写 parser,且多了 Python AST 这一层抽象。</p>\n<hr />\n<h2 id=\"5-api-hardcode\">5. 约束驱动数据生成,不按 API 名称 hardcode<a class=\"headerlink\" href=\"#5-api-hardcode\" title=\"Permanent link\">&para;</a></h2>\n<p><strong>选择:</strong> TensorSpec 的 <code>.stats()</code> 声明约束(nonzero/positive_definite/...),数据生成器只读 stats,不需要知道 API 名称。</p>\n<p><strong>为什么:</strong>\n- PaddleAPITest 的 <code>get_numpy_tensor()</code> 膨胀到 2500 行,本质是因为约束信息藏在代码里而非配置里\n- 新增约束 = 新增一个 <code>Constraint</code> 类 + 在 stats 上加一个字段,不修改主逻辑\n- Config 文件自包含——只看 config 就知道数据长什么样,不需要翻代码</p>\n<p><strong>为什么不沿用旧方案(API→代码分支):</strong> 不可维护。每新增一个有特殊数据需求的 API,就要加一个 <code>elif api_name ==</code> 分支。</p>\n<hr />\n<h2 id=\"6-frozen-dataclass-with_xxx-stats\">6. frozen dataclass + with_xxx() 替代链式可变 .stats()<a class=\"headerlink\" href=\"#6-frozen-dataclass-with_xxx-stats\" title=\"Permanent link\">&para;</a></h2>\n<p><strong>选择:</strong> 所有 TensorSpec 是 <code>frozen=True</code>,<code>.with_stats()</code> / <code>.with_state()</code> 返回新实例(via <code>dataclasses.replace()</code>)。</p>\n<p><strong>为什么:</strong>\n- 不可变数据结构在多进程传递时天然安全,不需要防御性拷贝\n- Parser 中间状态不会意外污染最终结果\n- 便于缓存和序列化——同一 spec 始终 equal</p>\n<p><strong>为什么不用可变链式调用(<code>.stats().state()</code> 修改 self):</strong> 与 <code>frozen=True</code> 矛盾。要么放弃 frozen(失去不可变保证),要么在 <code>.stats()</code> 里用 <code>object.__setattr__</code> hack——丑陋且容易出错。</p>\n<hr />\n<h2 id=\"7-venv-import\">7. 多 venv 进程隔离,不在同一进程 import 多框架<a class=\"headerlink\" href=\"#7-venv-import\" title=\"Permanent link\">&para;</a></h2>\n<p><strong>选择:</strong> 每个框架独立 venv + 独立子进程,用 SharedMemory/CUDA IPC 传数据。</p>\n<p><strong>为什么:</strong>\n- Paddle 和 PyTorch 有底层依赖冲突(CUDA/cuDNN 版本、C++ 库),同 env 安装不稳定\n- 隐式 import 顺序约束(\"paddle must import before torch\")在加第三个框架时彻底崩溃\n- 进程隔离后,每个 worker 的崩溃不影响其他 worker</p>\n<p><strong>为什么不用同进程 + import_order 配置:</strong> 脆弱的隐式约束。PaddleAPITest 全项目严格遵守这个顺序,但新贡献者一不注意就会引入 bug,且加 JAX 后三框架的 import 顺序无解。</p>\n<hr />\n<h2 id=\"8-gpu-cuda-ipc-cpu\">8. GPU 比较走 CUDA IPC 零拷贝,不拉回 CPU<a class=\"headerlink\" href=\"#8-gpu-cuda-ipc-cpu\" title=\"Permanent link\">&para;</a></h2>\n<p><strong>选择:</strong> GPU 测试结果留在 GPU,通过 CUDA IPC handle(64 字节)跨进程传引用,选一个 Comparator Worker 在 GPU 上做 <code>assert_close</code>。</p>\n<p><strong>为什么:</strong>\n- 16GB tensor 拉回 CPU 做 <code>np.allclose()</code> 需要 ~97 秒,GPU 上做 <code>torch.isclose()</code> 只需 ~50 毫秒,差 1000x\n- GPU tensor 本来就在显存里,拉回 CPU 是多余的</p>\n<p><strong>为什么不用 DLPack 跨进程:</strong> DLPack 的 <code>DLManagedTensor</code> 包含原始指针(<code>void* data</code>、<code>void (*deleter)</code>),是进程局部虚拟地址,不能跨进程。跨进程 GPU 共享只能用 CUDA IPC。</p>\n<p><strong>Phase 0 暂用 CPU 路径,Phase 1 实现 CUDA IPC。</strong></p>\n<hr />\n<h2 id=\"9-messagepack-zstd-case\">9. MessagePack + zstd 存储 case,不用纯文本<a class=\"headerlink\" href=\"#9-messagepack-zstd-case\" title=\"Permanent link\">&para;</a></h2>\n<p><strong>选择:</strong> <code>.tscase</code> 格式 = zstd 压缩的 MessagePack。</p>\n<p><strong>为什么:</strong>\n- 950 万条 case 纯文本 1.4GB,压缩后 33MB。MessagePack + 分组 + zstd 可到 ~10MB\n- MessagePack 有流式解析(<code>Unpacker</code>),不需要全量加载到内存\n- 跨语言生态好——Python/Rust/Go/JS 都有 msgpack 库,未来用 Rust 写高性能解析器无缝对接</p>\n<p><strong>为什么不用 Protobuf:</strong> 需要 <code>.proto</code> 文件和代码生成步骤,对我们的场景(动态 schema,不同 API 参数不同)过重。</p>\n<p><strong>为什么不用自定义二进制协议:</strong> 需要几百行 varint/struct 编解码代码,且只有 Python 能读。MessagePack 的性能差距只有 ~20%,实现成本低一个量级。</p>\n<hr />\n<h2 id=\"10-json-lines\">10. JSON Lines 运行日志,不用纯文本或数据库<a class=\"headerlink\" href=\"#10-json-lines\" title=\"Permanent link\">&para;</a></h2>\n<p><strong>选择:</strong> structlog → JSON Lines(<code>.jsonl</code>),一行一个 JSON 对象。</p>\n<p><strong>为什么:</strong>\n- 人可读(<code>cat</code> / <code>tail -f</code>) + 结构化(<code>jq</code> / <code>pandas</code> / DuckDB 直接分析)\n- append-only 流式写入,多进程安全(每行原子写入)\n- 不需要自定义解析脚本</p>\n<p><strong>为什么不用 SQLite:</strong> 多进程写入需要锁,高并发日志场景下成为瓶颈。</p>\n<p><strong>为什么不沿用纯文本日志:</strong> PaddleAPITest 的 12 种纯文本文件格式需要各自的解析脚本,无法用通用工具分析。</p>\n<hr />\n<h2 id=\"11-uv-pip-requirementstxt\">11. uv 包管理,不用 pip + requirements.txt<a class=\"headerlink\" href=\"#11-uv-pip-requirementstxt\" title=\"Permanent link\">&para;</a></h2>\n<p><strong>选择:</strong> uv + pyproject.toml,标准 PEP 621 项目结构。</p>\n<p><strong>为什么:</strong>\n- uv 的依赖解析和安装速度比 pip 快 10-100x\n- 内建 venv 管理——多 venv 隔离方案需要频繁创建/切换 venv,uv 做这件事极快\n- <code>uv.lock</code> 提供可重现的依赖锁定</p>\n<p><strong>为什么不用 pip:</strong> pip 没有 lockfile,没有内建 venv 管理,安装速度慢。在需要管理多个框架 venv 的场景下,pip 的慢速是实际的生产力问题。</p>\n<hr />\n<h2 id=\"12-typer-cli-click-argparse\">12. typer CLI,不用 click 或 argparse<a class=\"headerlink\" href=\"#12-typer-cli-click-argparse\" title=\"Permanent link\">&para;</a></h2>\n<p><strong>选择:</strong> typer(Phase 0 用 click,Phase 1 迁移到 typer)。</p>\n<p><strong>为什么:</strong>\n- 类型提示驱动的命令定义(<code>Annotated[str, typer.Option(...)]</code>),比 click 的装饰器更 Pythonic\n- 底层基于 click,继承 <code>CliRunner</code> 测试工具和子命令组织能力\n- 自动生成帮助文档,参数验证由类型系统保证\n- <code>str | None</code> 直接表达可选参数,无需 <code>Optional</code> 或 <code>default=None</code> 样板代码</p>\n<p><strong>为什么不用 click:</strong> click 的 <code>@click.option</code> 装饰器堆叠冗长,参数类型和默认值分散在装饰器和函数签名两处。typer 统一在函数签名中,一目了然。</p>\n<p><strong>为什么不用 argparse:</strong> 子命令支持需要手写 subparsers 样板代码;没有内建测试工具;参数验证需要手写 <code>type=</code> 函数。</p>",
5
+ "search": [
6
+ {
7
+ "location": null,
8
+ "level": 1,
9
+ "title": "tensor-spec 设计决策速查",
10
+ "text": "<p>每个点说明:做了什么选择、为什么、为什么不选其他方案。</p>",
11
+ "path": [],
12
+ "tags": []
13
+ },
14
+ {
15
+ "location": "1-dataclass-pydantic",
16
+ "level": 2,
17
+ "title": "1. dataclass,不用 pydantic",
18
+ "text": "<p>选择: <code>@dataclass(frozen=True, slots=True)</code></p> <p>为什么: - spec 层要求零外部依赖,dataclass 是 stdlib - 我们不需要 JSON schema 生成或自动验证——序列化目标是 MessagePack 二进制协议 - 验证逻辑明确且有限(float stats 不该出现在 bool tensor 上),<code>__post_init__</code> 足够</p> <p>为什么不用 pydantic: pydantic 的核心优势(声明式验证、JSON 序列化)我们用不上。引入它只增加依赖,不增加价值。如果后续需要复杂嵌套验证,dataclass → pydantic 迁移成本很低(字段定义兼容)。</p>",
19
+ "path": [],
20
+ "tags": []
21
+ },
22
+ {
23
+ "location": "2-tensordtype-tensorshape-dtype",
24
+ "level": 2,
25
+ "title": "2. Tensor.dtype() 工厂模式,不用 Tensor(shape, dtype)",
26
+ "text": "<p>选择: <code>Tensor.float32((2, 3))</code> 返回 <code>FloatTensorSpec</code></p> <p>为什么: - dtype 决定了 <code>.stats()</code> 的合法参数(float 有 min/max,bool 有 true_ratio)。工厂方法返回特定类型,类型安全在定义层面就确定了 - 只有一个标识符 <code>Tensor</code>,不会与任何框架类名冲突 - 新增 dtype 只需加一个 <code>@classmethod</code>,不需要新的顶级类</p> <p>为什么不用 <code>Tensor(shape, \"float32\")</code>: <code>.stats()</code> 方法必须根据 dtype 接受不同参数,这在同一个类上做隐式多态——给 bool tensor 传 <code>min=-5.9</code> 只能运行时报错,无法从定义层面约束。</p> <p>为什么不用 <code>Float32Tensor(shape)</code>: 标识符爆炸——15+ 个类(float16/32/64/bfloat16/int8/16/32/64/uint8/bool/complex64/128...),每加一个 dtype 就多一个顶级类。</p>",
27
+ "path": [],
28
+ "tags": []
29
+ },
30
+ {
31
+ "location": "3-device-dlpack",
32
+ "level": 2,
33
+ "title": "3. Device 对标 DLPack,不自造体系",
34
+ "text": "<p>选择: <code>DeviceType</code> IntEnum 的整数值直接映射 DLPack 的 <code>DLDeviceType</code>(CPU=1, CUDA=2, ROCM=10, ONEAPI=14...);字段名 <code>device_type</code> + <code>device_id</code> 对标 DLPack 的 <code>DLDevice</code> 结构体。</p> <p>为什么: - DLPack 是跨框架张量共享的事实标准(PyTorch/JAX/Paddle/CuPy/NumPy 都实现了 <code>__dlpack__</code>) - 对齐命名后,DeviceSpec 可直接产出 <code>__dlpack_device__()</code> 返回值,零转换 - 避免自造一套设备名称体系后再写映射表</p> <p>为什么不用纯字符串 type: 字符串无约束,拼写错误无法在定义时发现。IntEnum 提供编译期检查和自动补全。</p>",
35
+ "path": [],
36
+ "tags": []
37
+ },
38
+ {
39
+ "location": "4-parser-eval",
40
+ "level": 2,
41
+ "title": "4. 白名单递归下降 parser,不用 eval()",
42
+ "text": "<p>选择: 手写 tokenizer + 递归下降 parser,只允许 <code>Tensor</code>、<code>Device</code>、<code>tuple</code>、<code>list</code>、<code>slice</code>、字面量。</p> <p>为什么: - <code>eval()</code> 是代码执行,不是解析。Config 字符串来自外部,eval 等于允许任意代码注入 - 手写 parser 的错误信息精确到字符位置,eval 的报错是 Python traceback,对用户没有帮助 - 调试时可以单步跟踪解析过程,eval 是黑盒</p> <p>为什么不用 AST(<code>ast.literal_eval</code> / <code>ast.parse</code>): <code>ast.literal_eval</code> 不支持函数调用(<code>Tensor.float32(...)</code>)。<code>ast.parse</code> 可以,但需要遍历 AST 做白名单检查,复杂度不低于直接手写 parser,且多了 Python AST 这一层抽象。</p>",
43
+ "path": [],
44
+ "tags": []
45
+ },
46
+ {
47
+ "location": "5-api-hardcode",
48
+ "level": 2,
49
+ "title": "5. 约束驱动数据生成,不按 API 名称 hardcode",
50
+ "text": "<p>选择: TensorSpec 的 <code>.stats()</code> 声明约束(nonzero/positive_definite/...),数据生成器只读 stats,不需要知道 API 名称。</p> <p>为什么: - PaddleAPITest 的 <code>get_numpy_tensor()</code> 膨胀到 2500 行,本质是因为约束信息藏在代码里而非配置里 - 新增约束 = 新增一个 <code>Constraint</code> 类 + 在 stats 上加一个字段,不修改主逻辑 - Config 文件自包含——只看 config 就知道数据长什么样,不需要翻代码</p> <p>为什么不沿用旧方案(API→代码分支): 不可维护。每新增一个有特殊数据需求的 API,就要加一个 <code>elif api_name ==</code> 分支。</p>",
51
+ "path": [],
52
+ "tags": []
53
+ },
54
+ {
55
+ "location": "6-frozen-dataclass-with_xxx-stats",
56
+ "level": 2,
57
+ "title": "6. frozen dataclass + with_xxx() 替代链式可变 .stats()",
58
+ "text": "<p>选择: 所有 TensorSpec 是 <code>frozen=True</code>,<code>.with_stats()</code> / <code>.with_state()</code> 返回新实例(via <code>dataclasses.replace()</code>)。</p> <p>为什么: - 不可变数据结构在多进程传递时天然安全,不需要防御性拷贝 - Parser 中间状态不会意外污染最终结果 - 便于缓存和序列化——同一 spec 始终 equal</p> <p>为什么不用可变链式调用(<code>.stats().state()</code> 修改 self): 与 <code>frozen=True</code> 矛盾。要么放弃 frozen(失去不可变保证),要么在 <code>.stats()</code> 里用 <code>object.__setattr__</code> hack——丑陋且容易出错。</p>",
59
+ "path": [],
60
+ "tags": []
61
+ },
62
+ {
63
+ "location": "7-venv-import",
64
+ "level": 2,
65
+ "title": "7. 多 venv 进程隔离,不在同一进程 import 多框架",
66
+ "text": "<p>选择: 每个框架独立 venv + 独立子进程,用 SharedMemory/CUDA IPC 传数据。</p> <p>为什么: - Paddle 和 PyTorch 有底层依赖冲突(CUDA/cuDNN 版本、C++ 库),同 env 安装不稳定 - 隐式 import 顺序约束(\"paddle must import before torch\")在加第三个框架时彻底崩溃 - 进程隔离后,每个 worker 的崩溃不影响其他 worker</p> <p>为什么不用同进程 + import_order 配置: 脆弱的隐式约束。PaddleAPITest 全项目严格遵守这个顺序,但新贡献者一不注意就会引入 bug,且加 JAX 后三框架的 import 顺序无解。</p>",
67
+ "path": [],
68
+ "tags": []
69
+ },
70
+ {
71
+ "location": "8-gpu-cuda-ipc-cpu",
72
+ "level": 2,
73
+ "title": "8. GPU 比较走 CUDA IPC 零拷贝,不拉回 CPU",
74
+ "text": "<p>选择: GPU 测试结果留在 GPU,通过 CUDA IPC handle(64 字节)跨进程传引用,选一个 Comparator Worker 在 GPU 上做 <code>assert_close</code>。</p> <p>为什么: - 16GB tensor 拉回 CPU 做 <code>np.allclose()</code> 需要 ~97 秒,GPU 上做 <code>torch.isclose()</code> 只需 ~50 毫秒,差 1000x - GPU tensor 本来就在显存里,拉回 CPU 是多余的</p> <p>为什么不用 DLPack 跨进程: DLPack 的 <code>DLManagedTensor</code> 包含原始指针(<code>void* data</code>、<code>void (*deleter)</code>),是进程局部虚拟地址,不能跨进程。跨进程 GPU 共享只能用 CUDA IPC。</p> <p>Phase 0 暂用 CPU 路径,Phase 1 实现 CUDA IPC。</p>",
75
+ "path": [],
76
+ "tags": []
77
+ },
78
+ {
79
+ "location": "9-messagepack-zstd-case",
80
+ "level": 2,
81
+ "title": "9. MessagePack + zstd 存储 case,不用纯文本",
82
+ "text": "<p>选择: <code>.tscase</code> 格式 = zstd 压缩的 MessagePack。</p> <p>为什么: - 950 万条 case 纯文本 1.4GB,压缩后 33MB。MessagePack + 分组 + zstd 可到 ~10MB - MessagePack 有流式解析(<code>Unpacker</code>),不需要全量加载到内存 - 跨语言生态好——Python/Rust/Go/JS 都有 msgpack 库,未来用 Rust 写高性能解析器无缝对接</p> <p>为什么不用 Protobuf: 需要 <code>.proto</code> 文件和代码生成步骤,对我们的场景(动态 schema,不同 API 参数不同)过重。</p> <p>为什么不用自定义二进制协议: 需要几百行 varint/struct 编解码代码,且只有 Python 能读。MessagePack 的性能差距只有 ~20%,实现成本低一个量级。</p>",
83
+ "path": [],
84
+ "tags": []
85
+ },
86
+ {
87
+ "location": "10-json-lines",
88
+ "level": 2,
89
+ "title": "10. JSON Lines 运行日志,不用纯文本或数据库",
90
+ "text": "<p>选择: structlog → JSON Lines(<code>.jsonl</code>),一行一个 JSON 对象。</p> <p>为什么: - 人可读(<code>cat</code> / <code>tail -f</code>) + 结构化(<code>jq</code> / <code>pandas</code> / DuckDB 直接分析) - append-only 流式写入,多进程安全(每行原子写入) - 不需要自定义解析脚本</p> <p>为什么不用 SQLite: 多进程写入需要锁,高并发日志场景下成为瓶颈。</p> <p>为什么不沿用纯文本日志: PaddleAPITest 的 12 种纯文本文件格式需要各自的解析脚本,无法用通用工具分析。</p>",
91
+ "path": [],
92
+ "tags": []
93
+ },
94
+ {
95
+ "location": "11-uv-pip-requirementstxt",
96
+ "level": 2,
97
+ "title": "11. uv 包管理,不用 pip + requirements.txt",
98
+ "text": "<p>选择: uv + pyproject.toml,标准 PEP 621 项目结构。</p> <p>为什么: - uv 的依赖解析和安装速度比 pip 快 10-100x - 内建 venv 管理——多 venv 隔离方案需要频繁创建/切换 venv,uv 做这件事极快 - <code>uv.lock</code> 提供可重现的依赖锁定</p> <p>为什么不用 pip: pip 没有 lockfile,没有内建 venv 管理,安装速度慢。在需要管理多个框架 venv 的场景下,pip 的慢速是实际的生产力问题。</p>",
99
+ "path": [],
100
+ "tags": []
101
+ },
102
+ {
103
+ "location": "12-typer-cli-click-argparse",
104
+ "level": 2,
105
+ "title": "12. typer CLI,不用 click 或 argparse",
106
+ "text": "<p>选择: typer(Phase 0 用 click,Phase 1 迁移到 typer)。</p> <p>为什么: - 类型提示驱动的命令定义(<code>Annotated[str, typer.Option(...)]</code>),比 click 的装饰器更 Pythonic - 底层基于 click,继承 <code>CliRunner</code> 测试工具和子命令组织能力 - 自动生成帮助文档,参数验证由类型系统保证 - <code>str | None</code> 直接表达可选参数,无需 <code>Optional</code> 或 <code>default=None</code> 样板代码</p> <p>为什么不用 click: click 的 <code>@click.option</code> 装饰器堆叠冗长,参数类型和默认值分散在装饰器和函数签名两处。typer 统一在函数签名中,一目了然。</p> <p>为什么不用 argparse: 子命令支持需要手写 subparsers 样板代码;没有内建测试工具;参数验证需要手写 <code>type=</code> 函数。</p>",
107
+ "path": [],
108
+ "tags": []
109
+ }
110
+ ],
111
+ "title": "tensor-spec 设计决策速查",
112
+ "toc": [
113
+ {
114
+ "title": "tensor-spec 设计决策速查",
115
+ "id": "tensor-spec",
116
+ "url": "#tensor-spec",
117
+ "children": [
118
+ {
119
+ "title": "1. dataclass,不用 pydantic",
120
+ "id": "1-dataclass-pydantic",
121
+ "url": "#1-dataclass-pydantic",
122
+ "children": [],
123
+ "level": 2
124
+ },
125
+ {
126
+ "title": "2. Tensor.dtype() 工厂模式,不用 Tensor(shape, dtype)",
127
+ "id": "2-tensordtype-tensorshape-dtype",
128
+ "url": "#2-tensordtype-tensorshape-dtype",
129
+ "children": [],
130
+ "level": 2
131
+ },
132
+ {
133
+ "title": "3. Device 对标 DLPack,不自造体系",
134
+ "id": "3-device-dlpack",
135
+ "url": "#3-device-dlpack",
136
+ "children": [],
137
+ "level": 2
138
+ },
139
+ {
140
+ "title": "4. 白名单递归下降 parser,不用 eval()",
141
+ "id": "4-parser-eval",
142
+ "url": "#4-parser-eval",
143
+ "children": [],
144
+ "level": 2
145
+ },
146
+ {
147
+ "title": "5. 约束驱动数据生成,不按 API 名称 hardcode",
148
+ "id": "5-api-hardcode",
149
+ "url": "#5-api-hardcode",
150
+ "children": [],
151
+ "level": 2
152
+ },
153
+ {
154
+ "title": "6. frozen dataclass + with_xxx() 替代链式可变 .stats()",
155
+ "id": "6-frozen-dataclass-with_xxx-stats",
156
+ "url": "#6-frozen-dataclass-with_xxx-stats",
157
+ "children": [],
158
+ "level": 2
159
+ },
160
+ {
161
+ "title": "7. 多 venv 进程隔离,不在同一进程 import 多框架",
162
+ "id": "7-venv-import",
163
+ "url": "#7-venv-import",
164
+ "children": [],
165
+ "level": 2
166
+ },
167
+ {
168
+ "title": "8. GPU 比较走 CUDA IPC 零拷贝,不拉回 CPU",
169
+ "id": "8-gpu-cuda-ipc-cpu",
170
+ "url": "#8-gpu-cuda-ipc-cpu",
171
+ "children": [],
172
+ "level": 2
173
+ },
174
+ {
175
+ "title": "9. MessagePack + zstd 存储 case,不用纯文本",
176
+ "id": "9-messagepack-zstd-case",
177
+ "url": "#9-messagepack-zstd-case",
178
+ "children": [],
179
+ "level": 2
180
+ },
181
+ {
182
+ "title": "10. JSON Lines 运行日志,不用纯文本或数据库",
183
+ "id": "10-json-lines",
184
+ "url": "#10-json-lines",
185
+ "children": [],
186
+ "level": 2
187
+ },
188
+ {
189
+ "title": "11. uv 包管理,不用 pip + requirements.txt",
190
+ "id": "11-uv-pip-requirementstxt",
191
+ "url": "#11-uv-pip-requirementstxt",
192
+ "children": [],
193
+ "level": 2
194
+ },
195
+ {
196
+ "title": "12. typer CLI,不用 click 或 argparse",
197
+ "id": "12-typer-cli-click-argparse",
198
+ "url": "#12-typer-cli-click-argparse",
199
+ "children": [],
200
+ "level": 2
201
+ }
202
+ ],
203
+ "level": 1
204
+ }
205
+ ]
206
+ },
207
+ "hash": 12694106999519513322
208
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "data": "\n<!doctype html>\n<html lang=\"en\" class=\"no-js\">\n <head>\n \n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n \n <meta name=\"description\" content=\"Framework-agnostic deep learning API quality verification tool\">\n \n \n \n <link rel=\"canonical\" href=\"/design/implementation-prompt/\">\n \n \n \n \n \n \n \n <link rel=\"icon\" href=\"../../assets/images/favicon.png\">\n <meta name=\"generator\" content=\"zensical-0.0.26\">\n \n \n \n <title>tensor-spec 实施提示词 - tensor-spec</title>\n \n \n \n \n \n \n <link rel=\"stylesheet\" href=\"../../assets/stylesheets/modern/main.50057488.min.css\">\n \n \n \n \n <link rel=\"stylesheet\" href=\"../../assets/stylesheets/modern/palette.dfe2e883.min.css\">\n \n \n\n\n \n \n \n \n \n \n \n \n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,500,500i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback\">\n <style>:root{--md-text-font:\"Inter\";--md-code-font:\"JetBrains Mono\"}</style>\n \n \n \n <script>__md_scope=new URL(\"../..\",location),__md_hash=e=>[...e].reduce(((e,t)=>(e<<5)-e+t.charCodeAt(0)),0),__md_get=(e,t=localStorage,a=__md_scope)=>JSON.parse(t.getItem(a.pathname+\".\"+e)),__md_set=(e,t,a=localStorage,_=__md_scope)=>{try{a.setItem(_.pathname+\".\"+e,JSON.stringify(t))}catch(e){}},document.documentElement.setAttribute(\"data-platform\",navigator.platform)</script>\n \n \n\n \n \n </head>\n \n \n \n \n \n \n \n \n \n <body dir=\"ltr\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\">\n \n \n <input class=\"md-toggle\" data-md-toggle=\"drawer\" type=\"checkbox\" id=\"__drawer\" autocomplete=\"off\">\n <input class=\"md-toggle\" data-md-toggle=\"search\" type=\"checkbox\" id=\"__search\" autocomplete=\"off\">\n <label class=\"md-overlay\" for=\"__drawer\" aria-label=\"Navigation\"></label>\n <div data-md-component=\"skip\">\n \n \n <a href=\"#tensor-spec\" class=\"md-skip\">\n Skip to content\n </a>\n \n </div>\n <div data-md-component=\"announce\">\n \n </div>\n \n \n \n\n<header class=\"md-header\" data-md-component=\"header\">\n <nav class=\"md-header__inner md-grid\" aria-label=\"Header\">\n <a href=\"../..\" title=\"tensor-spec\" class=\"md-header__button md-logo\" aria-label=\"tensor-spec\" data-md-component=\"logo\">\n \n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-book-open\" viewBox=\"0 0 24 24\"><path d=\"M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\"/></svg>\n\n </a>\n <label class=\"md-header__button md-icon\" for=\"__drawer\" aria-label=\"Navigation\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-menu\" viewBox=\"0 0 24 24\"><path d=\"M4 5h16M4 12h16M4 19h16\"/></svg>\n </label>\n <div class=\"md-header__title\" data-md-component=\"header-title\">\n <div class=\"md-header__ellipsis\">\n <div class=\"md-header__topic\">\n <span class=\"md-ellipsis\">\n tensor-spec\n </span>\n </div>\n <div class=\"md-header__topic\" data-md-component=\"header-topic\">\n <span class=\"md-ellipsis\">\n \n tensor-spec 实施提示词\n \n </span>\n </div>\n </div>\n </div>\n \n \n <form class=\"md-header__option\" data-md-component=\"palette\">\n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme: light)\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to dark mode\" type=\"radio\" name=\"__palette\" id=\"__palette_0\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to dark mode\" for=\"__palette_1\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z\"/></svg>\n </label>\n \n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme: dark)\" data-md-color-scheme=\"slate\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to light mode\" type=\"radio\" name=\"__palette\" id=\"__palette_1\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to light mode\" for=\"__palette_0\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z\"/></svg>\n </label>\n \n \n</form>\n \n \n \n <script>var palette=__md_get(\"__palette\");if(palette&&palette.color){if(\"(prefers-color-scheme)\"===palette.color.media){var media=matchMedia(\"(prefers-color-scheme: light)\"),input=document.querySelector(media.matches?\"[data-md-color-media='(prefers-color-scheme: light)']\":\"[data-md-color-media='(prefers-color-scheme: dark)']\");palette.color.media=input.getAttribute(\"data-md-color-media\"),palette.color.scheme=input.getAttribute(\"data-md-color-scheme\"),palette.color.primary=input.getAttribute(\"data-md-color-primary\"),palette.color.accent=input.getAttribute(\"data-md-color-accent\")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute(\"data-md-color-\"+key,value)}</script>\n \n \n \n \n \n <label class=\"md-header__button md-icon\" for=\"__search\" aria-label=\"Search\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-search\" viewBox=\"0 0 24 24\"><path d=\"m21 21-4.34-4.34\"/><circle cx=\"11\" cy=\"11\" r=\"8\"/></svg>\n </label>\n <div class=\"md-search\" data-md-component=\"search\" role=\"dialog\" aria-label=\"Search\">\n <button type=\"button\" class=\"md-search__button\">\n Search\n </button>\n</div>\n \n \n <div class=\"md-header__source\">\n \n </div>\n </nav>\n \n</header>\n \n <div class=\"md-container\" data-md-component=\"container\">\n \n \n \n \n \n<nav class=\"md-tabs\" aria-label=\"Tabs\" data-md-component=\"tabs\">\n <div class=\"md-grid\">\n <ul class=\"md-tabs__list\">\n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../..\" class=\"md-tabs__link\">\n \n \n Home\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../rationale/\" class=\"md-tabs__link\">\n \n \n Design Rationale\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../architecture/\" class=\"md-tabs__link\">\n \n \n Design\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../plans/2026-03-03-phase0-implementation/\" class=\"md-tabs__link\">\n \n \n Plans\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../poc/2026-03-05-cuda-ipc-verification/\" class=\"md-tabs__link\">\n \n \n PoC\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../api/\" class=\"md-tabs__link\">\n \n \n API Reference\n\n </a>\n </li>\n \n\n \n </ul>\n </div>\n</nav>\n \n \n \n <main class=\"md-main\" data-md-component=\"main\">\n <div class=\"md-main__inner md-grid\">\n \n \n \n <div class=\"md-sidebar md-sidebar--primary\" data-md-component=\"sidebar\" data-md-type=\"navigation\" >\n <div class=\"md-sidebar__scrollwrap\">\n <div class=\"md-sidebar__inner\">\n \n\n\n \n\n\n<nav class=\"md-nav md-nav--primary md-nav--lifted\" aria-label=\"Navigation\" data-md-level=\"0\">\n <label class=\"md-nav__title\" for=\"__drawer\">\n <a href=\"../..\" title=\"tensor-spec\" class=\"md-nav__button md-logo\" aria-label=\"tensor-spec\" data-md-component=\"logo\">\n \n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-book-open\" viewBox=\"0 0 24 24\"><path d=\"M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\"/></svg>\n\n </a>\n tensor-spec\n </label>\n \n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../..\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Home\n \n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../rationale/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Design Rationale\n \n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n \n \n <input class=\"md-nav__toggle md-toggle md-toggle--indeterminate\" type=\"checkbox\" id=\"__nav_3\" >\n \n \n <label class=\"md-nav__link\" for=\"__nav_3\" id=\"__nav_3_label\" tabindex=\"0\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Design\n \n\n \n </span>\n \n \n\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_3_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_3\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n Design\n \n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../architecture/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Architecture\n \n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../decisions/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Decisions\n \n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../case-representation/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Case Representation\n \n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../modernization/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Modernization\n \n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../legacy-analysis/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Legacy Analysis\n \n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n \n \n <input class=\"md-nav__toggle md-toggle md-toggle--indeterminate\" type=\"checkbox\" id=\"__nav_4\" >\n \n \n <label class=\"md-nav__link\" for=\"__nav_4\" id=\"__nav_4_label\" tabindex=\"0\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Plans\n \n\n \n </span>\n \n \n\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_4_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_4\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n Plans\n \n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../plans/2026-03-03-phase0-implementation/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Phase 0: Foundation\n \n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../plans/2026-03-05-phase1-cross-framework-accuracy/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Phase 1: Accuracy\n \n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../plans/2026-03-05-phase2-process-isolation-ipc/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Phase 2: Isolation\n \n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../plans/2026-03-11-docs-ci-test-design/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Docs + CI + Tests\n \n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n \n \n <input class=\"md-nav__toggle md-toggle md-toggle--indeterminate\" type=\"checkbox\" id=\"__nav_5\" >\n \n \n <label class=\"md-nav__link\" for=\"__nav_5\" id=\"__nav_5_label\" tabindex=\"0\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n PoC\n \n\n \n </span>\n \n \n\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_5_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_5\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n PoC\n \n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../poc/2026-03-05-cuda-ipc-verification/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n CUDA IPC Verification\n \n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../api/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n API Reference\n \n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n </ul>\n</nav>\n </div>\n </div>\n </div>\n \n \n \n <div class=\"md-sidebar md-sidebar--secondary\" data-md-component=\"sidebar\" data-md-type=\"toc\" >\n <div class=\"md-sidebar__scrollwrap\">\n <div class=\"md-sidebar__inner\">\n \n\n\n<nav class=\"md-nav md-nav--secondary\" aria-label=\"On this page\">\n \n \n \n \n \n \n <label class=\"md-nav__title\" for=\"__toc\">\n <span class=\"md-nav__icon md-icon\"></span>\n On this page\n </label>\n <ul class=\"md-nav__list\" data-md-component=\"toc\" data-md-scrollfix>\n \n <li class=\"md-nav__item\">\n <a href=\"#_1\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n \n 提示词开始\n \n </span>\n </a>\n \n <nav class=\"md-nav\" aria-label=\"提示词开始\">\n <ul class=\"md-nav__list\">\n \n <li class=\"md-nav__item\">\n <a href=\"#_2\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n \n 核心设计决策速查\n \n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#phase-0\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n \n Phase 0 实施目标(从这里开始)\n \n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#_3\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n \n 关键约束\n \n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#apipaddleapitest\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n \n 参考:旧系统的关键 API(PaddleAPITest)\n \n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#_4\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n \n 开始\n \n </span>\n </a>\n \n</li>\n \n </ul>\n </nav>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#_5\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n \n 提示词结束\n \n </span>\n </a>\n \n</li>\n \n </ul>\n \n</nav>\n </div>\n </div>\n </div>\n \n \n \n <div class=\"md-content\" data-md-component=\"content\">\n \n <article class=\"md-content__inner md-typeset\">\n \n \n\n<h1 id=\"tensor-spec\">tensor-spec 实施提示词<a class=\"headerlink\" href=\"#tensor-spec\" title=\"Permanent link\">&para;</a></h1>\n<blockquote>\n<p>复制下方分隔线之间的内容,在 tensor-spec repo 目录中作为提示词发给 AI Agent 开始实施。</p>\n</blockquote>\n<hr />\n<h2 id=\"_1\">提示词开始<a class=\"headerlink\" href=\"#_1\" title=\"Permanent link\">&para;</a></h2>\n<p>你将实施 <strong>tensor-spec</strong> — 一个框架无关的深度学习 API 质量验证工具,替代 PaddleAPITest(https://github.com/PFCCLab/PaddleAPITest)。</p>\n<p>当前目录下有 5 份设计文档,是前期方案设计的成果。请先完整阅读以下文件,理解全部设计决策后再动手:</p>\n<ol>\n<li><code>architecture_design.md</code> — 10 层架构设计、模块职责、代码骨架</li>\n<li><code>design_decisions.md</code> — 技术选型(dataclass、MessagePack、TOML、多 venv + CUDA IPC)</li>\n<li><code>design_four_questions.md</code> — 现代工具链、进程隔离、渐进路线、Case 管理</li>\n<li><code>case_representation_design.md</code> — Case 表示格式(Approach 4: Tensor 工厂模式)</li>\n<li><code>PaddleAPITest_analysis.md</code> — 旧系统分析(作为参考,了解哪些问题要解决)</li>\n</ol>\n<h3 id=\"_2\">核心设计决策速查<a class=\"headerlink\" href=\"#_2\" title=\"Permanent link\">&para;</a></h3>\n<p><strong>项目定位:</strong> 框架无关的 DL API 质量验证工具。支持 Paddle / PyTorch / JAX / 任意框架。</p>\n<p><strong>技术栈:</strong>\n- 包管理:uv + pyproject.toml\n- 数据类:dataclass(frozen=True, slots=True),不用 pydantic\n- Lint/Format:ruff\n- 类型检查:ty\n- 测试:pytest\n- CLI:click 或 typer\n- 日志:structlog → JSON Lines\n- Case 存储:MessagePack + zstd(<code>.tscase</code> 格式)\n- 配置:TOML\n- 语言:Python 为主,性能热点用 Rust (PyO3)</p>\n<p><strong>Case 表示格式(Approach 4):</strong>\n<div class=\"highlight\"><pre><span></span><code><a id=\"__codelineno-0-1\" name=\"__codelineno-0-1\" href=\"#__codelineno-0-1\"></a>abs(x=Tensor.float64((1, 100)))\n<a id=\"__codelineno-0-2\" name=\"__codelineno-0-2\" href=\"#__codelineno-0-2\"></a>linalg.cholesky(x=Tensor.float64((4, 4)).stats(positive_definite=True))\n<a id=\"__codelineno-0-3\" name=\"__codelineno-0-3\" href=\"#__codelineno-0-3\"></a>nn.conv2d(x=Tensor.float32((1, 3, 224, 224)).state(need_grad=True), weight=Tensor.float32((64, 3, 7, 7)), stride=2, padding=3)\n</code></pre></div></p>\n<p><strong>进程隔离:</strong> 多 venv(uv 管理),每个框架独立 Python 解释器子进程。</p>\n<p><strong>数据传输双路径:</strong>\n- GPU 测试 → CUDA IPC + <code>__cuda_array_interface__</code> + Comparator Worker GPU 比较(结果不离开 GPU)\n- 纯 CPU 测试 → SharedMemory + numpy 比较(降级路径)</p>\n<p><strong>GPU Comparator 选择:</strong> 优先级列表 <code>[\"torch\", \"jax\", \"paddle\"]</code>,运行时从参与测试的 backend 中选最高优先级的做 comparator。Backend 声明 <code>supports_gpu_compare</code> 能力。</p>\n<p><strong>10 层架构:</strong> spec → config → datagen → backend → mapping → compare → tester → engine → log → cli</p>\n<h3 id=\"phase-0\">Phase 0 实施目标(从这里开始)<a class=\"headerlink\" href=\"#phase-0\" title=\"Permanent link\">&para;</a></h3>\n<div class=\"highlight\"><pre><span></span><code><a id=\"__codelineno-1-1\" name=\"__codelineno-1-1\" href=\"#__codelineno-1-1\"></a>目标:能解析 case、生成数据、跑单框架单 case\n<a id=\"__codelineno-1-2\" name=\"__codelineno-1-2\" href=\"#__codelineno-1-2\"></a>验收标准:能跑通 abs, add, matmul 三个 API 的单框架测试\n</code></pre></div>\n<p>需要实现的模块:</p>\n<ol>\n<li><strong>项目骨架</strong> — <code>pyproject.toml</code>(uv 项目),src layout,ruff/ty 配置</li>\n<li><strong>spec/</strong> — Tensor 工厂类 + TensorSpec dataclass 家族(FloatTensorSpec, IntTensorSpec, BoolTensorSpec, ComplexTensorSpec)+ Stats + State + Device</li>\n<li><strong>config/parser.py</strong> — 白名单递归下降 parser,解析 case 字符串 → CaseConfig(不用 eval)</li>\n<li><strong>config/case.py</strong> — CaseConfig dataclass(api_name + args/kwargs)</li>\n<li><strong>datagen/generator.py</strong> — TensorSpec → numpy array(约束驱动 pipeline)</li>\n<li><strong>datagen/constraints.py</strong> — 基础约束:NonZero, PositiveDefinite</li>\n<li><strong>backend/base.py</strong> — BackendBase 抽象类</li>\n<li><strong>backend/paddle_backend.py</strong> — PaddleBackend 实现</li>\n<li><strong>cli.py</strong> — <code>tensor-spec run --backend paddle --case \"abs(x=Tensor.float32((100,)))\"</code></li>\n<li><strong>tests/</strong> — 所有模块的单元测试(pytest)</li>\n</ol>\n<h3 id=\"_3\">关键约束<a class=\"headerlink\" href=\"#_3\" title=\"Permanent link\">&para;</a></h3>\n<ul>\n<li>spec 层<strong>零框架依赖</strong>,只用 Python stdlib(dataclass)</li>\n<li>config parser <strong>不用 eval()</strong>,白名单递归下降</li>\n<li>所有 dataclass 用 <code>frozen=True, slots=True</code></li>\n<li>全量 type hints,通过 ty 检查</li>\n<li>每个模块都要有对应的 pytest 单测</li>\n<li>遵循如无必要勿增实体原则,不过度设计</li>\n<li>Phase 0 暂不需要:torch backend、mapping 层、compare 层、engine 层、日志层、CUDA IPC</li>\n</ul>\n<h3 id=\"apipaddleapitest\">参考:旧系统的关键 API(PaddleAPITest)<a class=\"headerlink\" href=\"#apipaddleapitest\" title=\"Permanent link\">&para;</a></h3>\n<p>以下是 tensor-spec 要替代的旧系统中的关键实现,可参考但不要照搬:</p>\n<ul>\n<li><code>tester/api_config/config_analyzer.py</code> — 3132 行,TensorConfig + APIConfig + <code>get_numpy_tensor()</code>(2500 行 API 感知 hardcode)</li>\n<li><code>tester/base.py</code> — 1149 行,paddle 必须在 torch 前 import,DLPack 比较</li>\n<li><code>tester/accuracy.py</code> — 638 行,torch 先执行后释放 GPU,再执行 paddle</li>\n<li><code>tester/paddle_to_torch/rules.py</code> — 6545 行,API 转换规则</li>\n<li><code>engineV2.py</code> — 1049 行,Pebble ProcessPool + spawn + GPU 分配</li>\n</ul>\n<p>旧系统在 <code>/workspace/PaddleAPITest/</code> 目录,如需查看细节可自行阅读。</p>\n<h3 id=\"_4\">开始<a class=\"headerlink\" href=\"#_4\" title=\"Permanent link\">&para;</a></h3>\n<p>请先阅读上述 5 份设计文档,然后制定 Phase 0 的详细实施计划并开始实施。从项目骨架开始,逐步构建各模块,每完成一个模块就写对应的测试。</p>\n<h2 id=\"_5\">提示词结束<a class=\"headerlink\" href=\"#_5\" title=\"Permanent link\">&para;</a></h2>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n </article>\n </div>\n \n \n<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith(\"__tabbed_\"))</script>\n </div>\n \n <button type=\"button\" class=\"md-top md-icon\" data-md-component=\"top\" hidden>\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-circle-arrow-up\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m16 12-4-4-4 4M12 16V8\"/></svg>\n Back to top\n</button>\n \n </main>\n \n <footer class=\"md-footer\">\n \n <div class=\"md-footer-meta md-typeset\">\n <div class=\"md-footer-meta__inner md-grid\">\n <div class=\"md-copyright\">\n \n \n Made with\n <a href=\"https://zensical.org/\" target=\"_blank\" rel=\"noopener\">\n Zensical\n </a>\n \n</div>\n \n </div>\n </div>\n</footer>\n \n </div>\n <div class=\"md-dialog\" data-md-component=\"dialog\">\n <div class=\"md-dialog__inner md-typeset\"></div>\n </div>\n \n \n \n \n \n \n <script id=\"__config\" type=\"application/json\">{\"annotate\":null,\"base\":\"../..\",\"features\":[\"content.code.annotate\",\"content.code.copy\",\"navigation.expand\",\"navigation.instant\",\"navigation.sections\",\"navigation.tabs\",\"navigation.top\",\"search.highlight\",\"search.suggest\",\"toc.follow\"],\"search\":\"../../assets/javascripts/workers/search.e2d2d235.min.js\",\"tags\":null,\"translations\":{\"clipboard.copied\":\"Copied to clipboard\",\"clipboard.copy\":\"Copy to clipboard\",\"search.result.more.one\":\"1 more on this page\",\"search.result.more.other\":\"# more on this page\",\"search.result.none\":\"No matching documents\",\"search.result.one\":\"1 matching document\",\"search.result.other\":\"# matching documents\",\"search.result.placeholder\":\"Type to start searching\",\"search.result.term.missing\":\"Missing\",\"select.version\":\"Select version\"},\"version\":null}</script>\n \n \n <script src=\"../../assets/javascripts/bundle.5fd3284f.min.js\"></script>\n \n \n </body>\n</html>",
3
+ "hash": 5078177612633991174
4
+ }