首页
/ get-shit-done CJS↔SDK 硬接缝迁移:Shared-Module 单一事实源架构实践

get-shit-done CJS↔SDK 硬接缝迁移:Shared-Module 单一事实源架构实践

2026-09-08 21:42:04作者:蔡丛锟

导读

本文以 docs/prd/3524-cjs-sdk-hard-seam.md(CJS↔SDK hard seam PRD)为骨架,完整讲解 get-shit-done 项目中 CJS 工具层(get-shit-done/bin/lib/*.cjs)与 SDK 层(sdk/src/**/*.ts)之间结构性的配置漂移(drift)问题,以及通过"每个 Shared Module 只有一个手写事实源(source of truth)+ 生成物 + 新鲜度检查 + 门禁 lint"六阶段迁移方案根治该问题类的完整落地路径。读完本文,你将掌握:如何复用仓库中 gen-command-aliases 既有先例,把一对一手写同步(hand-synced)的 .cjs/.ts 文件替换为"TS 源 → 双端生成物 → Adapter"的硬接缝架构,以及配套的逐阶段验收标准、回滚策略、风险矩阵与性能约束。

背景:CJS↔SDK 边界为什么"结构上可渗透"

get-shit-done 存在两个运行时:CJS 工具层(shell 脚本回兼容所需的 gsd-tools)与 SDK(TypeScript 查询层,gsd-sdk query)。两者之间共享的多个 Shared Module——STATE.md Document Module、Workstream Inventory Module 等——历史上以"字符级一致的手写同步对"形式存在,即同一份逻辑在 get-shit-done/bin/lib/*.cjssdk/src/**/*.ts 各写一遍。常量(CONFIG_DEFAULTSVALID_CONFIG_KEYS)同样被定义两次。

此前的边界防线只有两道,均只能捕获部分漂移:

这两道防线漏掉了四类漂移,PRD 中逐一给出:

漂移类别 具体表现
默认值结构漂移 #3523:顶层 branching_strategy 在 CJS 侧返回 'none',SDK 侧返回 'phase'
告警/报错文案漂移 #3523:CJS 侧误报告警,SDK 侧静默移植(silently grafts)
变更路径漂移 两侧各自单测,缺少跨侧变更夹具(cross-side mutation fixture)
新增 Module 漂移 一侧新增常量另一侧不知情,完全不可见

该问题类反复出现,历史 bug 清单包括 #1535、#1542、#2047/#2052、#2638/#2655、#2653/#2670、#2687/#2706、#2798/#2816、#3055/#3116、#3523——每一例都是"修复只落在了一侧"。仓库内 docs/agents/cjs-sdk-seam.md 的 Phase 6 回顾部分记录了 15 个此类配置漂移 bug 的逐条档案(如 #2638:loadConfigsub_repos 写到顶层后被标记为未知键;#2047:intel.enabled 已文档化却不在 VALID_CONFIG_KEYS 导致 config-set 拒绝)。

既有先例:command-aliases 生成器模式

修复方案并非凭空设计,仓库中已经存在可工作的先例:命令别名(Command-Alias)模块。

sdk/scripts/gen-command-aliases.ts 是一个构建期生成器,它从 sdk/src/query/command-manifest.{state,verify,init,phase,phases,validate,roadmap,non-family}.ts 读取唯一的命令清单,一次生成两个产物:

  • sdk/src/query/command-aliases.generated.ts(SDK 侧的 TS 类型化别名表);
  • get-shit-done/bin/lib/command-aliases.generated.cjs(CJS 侧的纯 JS 别名表,通过 JSON.stringify 序列化并导出 module.exports)。

生成文件顶部自动插入 "GENERATED FILE — Source: …" 横幅,禁止手改。

配套的 sdk/scripts/check-command-aliases-fresh.mjs 是 CI 新鲜度门禁:它重新计算两侧期望值(TS 侧从编译产物 dist/query/*.js 导入 manifest,CJS 侧通过 require 加载已提交的生成文件),再与已提交产物逐项 JSON.stringify 比较,任何不一致都会抛出 "drift detected" 并令 CI 失败。PRD 明确将这一"一个 TS 源 → 双端生成物 → 两侧纯 Adapter 消费"模式推广到所有 Shared Module,并禁止继续手写同步对。

六步通用迁移配方

对每个待迁移的 Shared Module,PRD 规定如下机械式流程(以 TS 侧为事实源,因为其天然携带类型):

  1. 提升一侧为事实源:采用 TS 源(携带类型);
  2. 编写生成器 sdk/scripts/gen-<module>.ts,同时产出 .generated.ts.generated.cjs
  3. 编写新鲜度检查 sdk/scripts/check-<module>-fresh.mjs,仿照 check-command-aliases-fresh.mjs
  4. 把手写 CJS 文件替换为薄 re-export:仅从生成文件转发导出,保留原文件名以维持调用方(如 workstream-inventory.cjsstate-documentrequire)不变;
  5. 把新鲜度检查接入 CI
  6. 稳定一个发布周期后,清理不再被引用的手写内容(移除死 re-export)。

另有常驻 CI lint scripts/lint-shared-module-handsync.cjs(Phase 6 引入)扫描 get-shit-done/bin/lib/<name>.cjssdk/src/query/<name>.ts(或 sdk/src/<name>.ts)中"两侧都非 *.generated.* 且不在显式 allow-list 中"的对,直接阻断任何新手写同步对合并。

Phase 1 的真实实现印证

Phase 1(STATE.md Document Module)已经落地,其产物可以在仓库中直接核对:

  • 事实源 sdk/src/query/state-document.ts(纯变换模块,文件头注明 "does not read the filesystem and does not own persistence or locking");
  • 生成器 sdk/scripts/gen-state-document.ts:加载编译后的 sdk/dist/query/state-document.js,通过 Function.prototype.toString() 提取导出函数体、通过源码文本扫描(花括号配平)提取内部非导出 helper(escapeRegextoFiniteNumberexistingProgressExceedsDerived),拼接出 get-shit-done/bin/lib/state-document.generated.cjs
  • 新鲜度检查 sdk/scripts/check-state-document-fresh.mjs:在内存中重新生成期望内容并与已提交文件逐字节比对,退出码 0/1 表示新鲜/过期;
  • CJS Adapter get-shit-done/bin/lib/state-document.cjs:正文只有一行 module.exports = require('./state-document.generated.cjs');,使 state.cjsworkstream-inventory.cjsinit.cjs 及测试的既有 require('./state-document') 无需改动。

这印证了 PRD 的判断:"删除测试在接触时即通过(deletion test passes on contact)"——两侧本已字符级一致,一侧成为生成物后另一侧立即可替换为 re-export,且无任何外部消费者受损。

六阶段迁移计划

Phase 1 — STATE.md Document Module(最小可行证明)

为何最先做bin/lib/state-document.cjssdk/src/query/state-document.ts 已是字符级一致的手写同步对,且是纯变换模块(不读文件系统、不持有持久化或锁)。这是最安全的起步,也证明了生成器模式不仅适用于别名表,还适用于可执行逻辑。

范围:提升 TS 侧为事实源;编写 gen-state-document.tscheck-state-document-fresh.mjs;把 CJS 侧替换为薄 re-export(保留 state-document.cjs 文件名);把新鲜度检查接入 CI(与 check-command-aliases-fresh.mjs 并列)。

验收标准

  • bin/lib/state-document.cjs 只含对 state-document.generated.cjs 的 re-export;
  • check-state-document-fresh.mjs 在 CI 通过,且在故意失同步时失败;
  • 既有调用点(CJS:state.cjsworkstream-inventory.cjs;SDK:state-mutation.tsstate-project-load.ts 等)原样工作;
  • 两侧既有 STATE.md 单测全部通过;
  • CONTEXT.md "STATE.md Document Module" 条目补充一句事实源路径说明。

回滚:直接 revert 分支;从 git 历史重新导入被删除的 CJS 文件内容即恢复原手写同步形态,无外部消费者受损。

Phase 2 — Configuration Module(关闭 #3523 问题类)

为何第二:这是触发本次工作的问题模块,是杠杆率最高的漂移面,同时考验模式能否从"纯变换模块"扩展到"消费数据清单的模块"。

范围

  • 先在 CONTEXT.md 增加 Configuration Module 条目,定义:"Module owning config load, legacy-key normalization, defaults merge, and explicit on-disk migration for .planning/config.json",接口与不变量见 ADR §6;
  • CONFIG_DEFAULTSVALID_CONFIG_KEYSDYNAMIC_KEY_PATTERNSRUNTIME_STATE_KEYS 抽取为两份数据清单 sdk/shared/config-schema.manifest.jsonsdk/shared/config-defaults.manifest.json(先例:sdk/shared/model-catalog.json);
  • 编写模块源 sdk/src/configuration/index.ts(导入两份清单,导出 loadConfignormalizeLegacyKeysmergeDefaultsmigrateOnDisk);
  • 编写 gen-configuration.tscheck-configuration-fresh.mjs
  • bin/lib/core.cjs:loadConfig(约 220–243、434–449、485 行)与 bin/lib/config.cjs 校验面替换为薄 Adapter,删除内联 CONFIG_DEFAULTScore.cjs:444-449 的误报警告与重复的 _deepMergeConfig
  • sdk/src/config.ts:mergeDefaults(192–218 行)改为 re-export;
  • 为四种 legacy-key 归一化(顶层 branching_strategy、顶层 sub_reposmultiRepo: true、顶层 depth)扩展 read-only-parity.integration.test.ts 的夹具矩阵。

验收标准:CONTEXT.md 含接口契约;CJS 两侧不再有本地 CONFIG_DEFAULTS/VALID_CONFIG_KEYS 字面量;#3523 夹具矩阵在 CJS 与 SDK 双路径通过且误报警告消失;golden parity 矩阵四形状全绿;#3523 以指向本阶段的 back-reference 关闭。

回滚:revert 分支后内联实现自 git 历史恢复,manifest 文件保持未引用即可。

当前仓库中 sdk/scripts/check-configuration-fresh.mjs 已存在,其实现完全遵循先例:动态导入 ./gen-configuration.mjsbuildConfigurationCjs() 在内存中重算期望内容,与 get-shit-done/bin/lib/configuration.generated.cjs 比对,并提供 cd sdk && npm run gen:configuration 的再生成指引。

Phase 3 — Workstream Inventory Builder 与剩余手写同步对

为何第三:Phase 1 证明了纯变换,Phase 2 证明了数据清单支撑的逻辑,Phase 3 则推广到其余同步对,其中 Workstream Inventory Module 是重点,因为它要求 Builder/Reader 拆分——投影逻辑是纯且可共享的,而目录遍历在 CJS(同步 fs)与 SDK(异步 I/O)两侧是合理不同的。

范围

  • 编写 Builder 源 sdk/src/workstream-inventory/builder.ts:纯函数,接收目录条目列表 + 每个 workstream 的 STATE.md 文本 + plan-scan 结果,返回类型化的 WorkstreamPhaseInventory/WorkstreamInventory 投影,不做任何 fs 读取;
  • gen-workstream-inventory-builder.ts 产出 CJS 与 SDK 双侧生成物;check-workstream-inventory-builder-fresh.mjs 把关;
  • bin/lib/workstream-inventory.cjs 重构为同步 Reader Adapter(fs.readdirSync + readFileSync 读 STATE.md 后调用 Builder);sdk/src/query/workstream-inventory.ts 重构为异步 Reader Adapter(同形态、异步 I/O、调用 Builder);
  • 审计其余疑似对(frontmatter.cjsfrontmatter-mutation.tsplan-scan.cjs↔plan-scan SDK 等价物),可共享者套用 Builder 模式;结构性重复者(路由表、不同返回形态的 sync/async 等)在阶段 issue 中记录决策并推迟。

验收标准:两侧不再共享投影逻辑而都调用生成 Builder;CONTEXT.md 反映拆分;两侧 workstream golden 测试通过;范围内每个模块都有独立新鲜度检查;未迁移模块在阶段 issue 中留下段落级推迟说明。

Phase 4 — Project-Root Resolution Module

范围:CONTEXT.md 新增条目,接口为 findProjectRoot(startDir)findEffectiveRoot(startDir, options);事实源 sdk/src/project-root/index.ts(纯函数,注入 fs probe 或直接用 node:fs,两运行时均同步可用);生成器与新鲜度检查;bin/lib/core.cjs:74-140sdk/src/helpers.ts:497-630 替换为薄 Adapter;对独立项目、含 planning.sub_repos 的 monorepo、legacy multiRepo: true、深层嵌套四种配置扩展对等测试。

验收标准findProjectRoot 在源码形态上只定义一次;两侧都导入生成模块;四种配置的对等测试全部通过。

Phase 5 — CJS Command Router Adapter:委托给 SDK runtime bridge

为何第五:Phase 1–4 消灭了"共享逻辑"的漂移,Phase 5 则消灭"并行逻辑"的漂移——即 CJS 侧各命令族的 state/verify/init/phase/roadmap/validate handler 实现。落地后,经 gsd-tools 运行的每个 canonical 命令与 gsd-sdk query 执行同一个 SDK handler,进程内执行、无子进程跳转,接缝成为真正的墙。

范围

  • 修订 CONTEXT.md "CJS Command Router Adapter Module" 条目,记录 runtime-bridge 委托;
  • 为 CJS 调用方暴露同步友好的入口:QueryRuntimeBridge.execute() 本为异步,新增 executeForCjs(input) → { exitCode, stdoutChunks, stderrLines } 同步包装(在 deasync 或受控 runUntil 语义下运行 dispatch;若同步桥接不可行,退回 Worker 通道上的 Atomics.wait,绝不引入 gsd-sdk 子进程);
  • bin/lib/*-command-router.cjs 中各 canonical 族的 handlers map 替换为生成式委托发射器:每子命令调用 executeForCjs({ canonical, argv, env, cwd }) 并经由既有 CJS 输出 Adapter 写出;
  • 按顺序逐族迁移:state.*verify.*phase.*phases.*validate.*roadmap.*init.*frontmatter.*config.*,加上 sdk/src/query/command-manifest.non-family.ts 中列出的非族命令,一族一个子 PR,合入前运行 golden parity 矩阵;
  • CJS-only 模块(graphifygsd2-importschema-detectfallow-runnerinteldriftinstaller-migrations)保留进程内 CJS 实现,不进入 canonical 族注册表;
  • 扩展 sdk/src/golden/golden.integration.test.ts,对 manifest 中每个 canonical 命令验证 gsd-toolsgsd-sdk query 的退出码 + stdout 块 + stderr 行完全一致。

验收标准executeForCjs 落地;command-manifest.*.ts 中每个 canonical 族经 executeForCjs 路由,CJS-only 命令继续走既有 CJS handler;每个族的 CJS handler 文件不再含命令特定逻辑(仅剩委托接线或被删除);golden parity 矩阵对全部 canonical 命令验证两侧输出等价;gsd-tools 每次调用的子进程开销不增加(桥接在进程内)。

逐族回滚:每个族的 PR 可独立 revert;未迁移族的手写 handler 留在 git 历史中,委托回退时从历史恢复。

Phase 6 — 执行加固与回顾

范围

  • 编写 scripts/lint-shared-module-handsync.cjs:扫描 get-shit-done/bin/lib/<name>.cjssdk/src/query/<name>.ts(或 sdk/src/<name>.ts)中两侧均非 *.generated.* 且不在显式 allow-list 的配对,allow-list 记录"协作兄弟"例外(如实现结构性不同的路由文件);
  • 核对 Phase 1–4 每个 Shared Module 都有接入 CI 的新鲜度检查;
  • 核对 Phase 5 的 golden parity 矩阵覆盖每个 canonical 族;
  • sdk/src/<module>/**sdk/shared/*.manifest.jsonsdk/src/query-runtime-bridge.ts 增加 CODEOWNERS 规则(架构组评审);
  • 回顾式遍历反复 bug 清单(#1535 … #3523),在 docs/agents/cjs-sdk-seam.md 中记录每个 bug 会被哪层执行机制拦截(handsync lint、新鲜度检查、清单数据隔离、逐模块漂移 lint、runtime-bridge 委托);
  • docs/agents/cjs-sdk-seam.md 写成面向 CONTRIBUTING 的指南,说明如何新增 Shared Module 与新增 canonical 命令。

验收标准:handsync lint 进 CI 并演示能拦截故意的回归 PR;Phase 1–4 全部模块进入新鲜度检查工作流;Phase 5 矩阵在触碰 bin/lib/*sdk/src/query/* 的每个 PR 上运行;CODEOWNERS 就位;回顾文档提交;任何重新引入 #3523 反模式或绕过 runtime-bridge 委托的 PR 无法落地。

值得对照的是 docs/agents/cjs-sdk-seam.md 已记录六个阶段全部落地(#3531/#3540/#3548/#3554/#3558/#3574/#3577),并给出 Phase 6 的 15 个历史漂移 bug 回顾矩阵——例如 #1535(loadConfig 静默忽略未知顶层键)会被 handsync lint 拦截、#2638(sub_repos 写错位置)会被逐模块漂移 lint 拦截,每一条都映射到五层执行机制之一。

跨阶段关注点

向后兼容

CJS 公共 CLI 表面(gsd-tools <subcommand>)不变:标志位、退出码、stdout 形态全部保留。每一阶段都在既有 Module 接口之后替换内部实现,外部契约由既有 golden parity 套件加新增夹具矩阵固定。

性能

全程无子进程开销:生成的 .cjs 是可直接 require 的 CommonJS 模块,SDK 直接消费 TS 源;跨全部阶段合计每次 require 的模块加载成本 ≤ 10 ms。Phase 5 特别保持进程内模型——executeForCjs 与 CJS 分发器同 Node 进程运行 SDK handler,不调用 gsd-sdk 子进程,同步桥接相对此前的直接 CJS handler 调用每次仅增加至多几微秒,主导成本仍是既有 dispatch policy 开销。

构建/安装管线影响

  • 生成器只在开发机构建期(以及 CI 中的新鲜度检查)运行,无运行时生成
  • 已发布的 get-shit-done-cc 包同时包含 get-shit-done/bin/sdk/dist/;生成的 .cjs 文件(与今日的 command-aliases.generated.cjs 一样)提交进仓库,安装流程不变——不做安装期代码生成;
  • npm run build:sdk 维持原行为;生成器沿用 npm run gen:<module> 既有先例调用。

风险矩阵

风险 可能性 缓解
提交间生成物与源漂移 每模块 check-<module>-fresh.mjs 在 PR 期拦截;先例已在 command-aliases 使用
TS 源使用了 CJS 输出无法表达的特性 生成器只产出 CJS 兼容子集(源中禁 ESM-only 语法);既有 gen-command-aliases.ts 模板已覆盖
Phase 2 删除内联 _deepMergeConfig 改变微妙合并语义 golden parity 矩阵是测试:夹具不一致则矩阵失败,合入前修订新模块
migrateOnDisk 上线静默改变升级可见行为 migrateOnDisk 显式且 opt-in,安装器在下次升级调用一次并附 release-note;提供独立命令 gsd-tools migrate-config 手动调用
CODEOWNERS 拖慢架构组响应 仅对事实源目录与清单应用 CODEOWNERS;Adapter 与 .generated.* 保持开放;架构组承诺 ≤ 24 h SLA
Phase 3 审计暴露超出预期的配对,范围蔓延 非 Phase 1/2 模块在阶段 issue 中做范围核查,不契合者记录理由后推迟
Phase 5 同步桥接机制没有干净形态(deasync 绑定 C++、Atomics.wait 需要 Worker、全量改同步 SDK handler 巨大) Phase 5 spike 在任何族迁移前解决;若无干净机制,Phase 5 降级为只迁移 SDK handler 本就同步的族,其余转入后续增强
Phase 5 族迁移回退可见 CJS 输出(退出码、stdout/stderr 形态) 每族 golden parity 矩阵是门槛,矩阵在族内所有 canonical 命令全绿前不得合入
Phase 5 因 runtime bridge 提前加载更多 handler 改变启动时间 桥后惰性加载 handler(SDK 已有该模型);迁移前后测量 time gsd-tools state load,中位延迟回退 >20 ms 则打回该族 PR

待决开放问题(依赖它的阶段开始前解决)

  1. Phase 1 事实源位置sdk/src/state-document/index.ts(迁移)vs sdk/src/query/state-document.ts(原地)——在 Phase 1 PR 起草时定;
  2. Phase 2 清单格式:JSON vs JSONC vs TypeScript-as-source——Phase 2 决定,若无注释记录不变量需求则 JSON 胜出;
  3. Phase 3 兄弟模块审计:Builder 拆分 vs 推迟的精确配对清单——作为 Phase 3 spike 的交付物;
  4. Phase 5 同步桥接机制executeForCjs 实现策略(deasync 原生模块 / Worker 通道 Atomics.wait / 每个异步 handler 暴露同步入口)——在任何族迁移前的 spike issue 中定;
  5. Phase 5 族迁移顺序:推荐最小只读族先行(大概率 frontmatter.*config.* 读路径)作为模式证明,再按复杂度递增迁移 state/verify/phase/roadmap/validate/init;
  6. Phase 6 回顾格式:表格 vs 散文——起草回顾文档时定。

完成标准

#3524 的关闭条件是:六个阶段全部上线,每阶段有各自合并的 PR 关闭各自阶段 issue,且 Phase 6 回顾确认反复 bug 清单中的每个历史漂移 bug 都能被五层执行机制之一(handsync lint、新鲜度检查、清单数据隔离、逐模块漂移 lint、runtime-bridge 委托)拦截。

架构约束与设计要点总结

docs/adr/3524-cjs-sdk-hard-seam.md 及其 PRD 可以提炼出本方案区别于一般"去重重构"的四个关键约束:

  1. 以 Module 为单位,而非新增层标签:接缝词汇保持在既有 CONTEXT.md/LANGUAGE.md 框架内,不引入"shared core""shared data"等新层名,接缝所有权单位就是仓库处处在用的 Module。
  2. 不引入新构建工具:生成器就是既有 gen-command-aliases.ts 形态;不做双 CJS+ESM bundler、不改 package.json exports 子路径、不做 tsup/rollup 决策。
  3. 每侧 I/O Adapter 合理不同:状态 Adapter、verify Adapter 等不进 Shared Module 表——CJS 用同步 fs/exec,SDK 用异步 I/O 与观测装饰器;只有其背后的纯变换(解析、投影、归一化)被抽进 Shared Module,golden parity 测试钉住跨接缝可观测行为。
  4. 事实源即所有权:有行为的模块事实源在 sdk/src/<module-name>/(TypeScript),纯数据的在 sdk/shared/<module-name>.manifest.json;CJS 侧生成物 get-shit-done/bin/lib/<module-name>.generated.cjs 永不手编;defer 给既有 ADR(0001/0003/0004/0006/0009/0011)的模块不在本方案范围内重复定义。

这套"一个事实源 + 双端生成物 + 逐模块新鲜度门禁 + 手写同步对禁用 lint + golden parity 输出等价"的组合,将原本靠人工纪律维持的跨运行时一致性,变成了靠 CI 机械强制的不变量——这正是该 PRD 对反复出现九次的漂移 bug 类给出的根治性答案。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395