已开启
[RFC] knowledge-query-asc-enhance:为 Ascend C API 补齐版本/架构适用面与声明级证据 #67
flyingXLB创建于  6 天前
flyingXLB
flyingXLB
6 天前 创建

[RFC] knowledge-query-asc-enhance:为 Ascend C API 补齐版本/架构适用面与声明级证据

当前问题与修改必要性

  • 受影响组件与场景:knowledge-query 的知识检索(含 ascendc-api-knowledge-query 专用消费流程)。当问题把 CANN 版本或 NPU 架构钉死时(例如"CANN 9.2.0、3510 架构下这个 API 怎么用"),现有检索只能给到知识卡,而卡片不携带可核对的版本适用面:本仓 knowledge/ops/ascendc/apis/** 的卡片中,cann_versions 声明率为 0 / 16(实测,见下)。同时,知识库只镜像 asc-devkit 的 文档,不含 include/ 声明与 examples/ 样例,因此"这个 API 的签名、参数地址空间、dtype、配套样例是什么"也无法从知识库回答。
  • 当前行为与证据:governance/specs/skills.md 已明载「Query 当前不按 CANN 版本执行结构化过滤」;checks/sources.py 侧只保留 source_headers 指针(卡片 419 行的 asc_mmad 卡仅给出 2 个头文件路径,没有结构化声明)。asc-devkit 仓内已有现成的 asc-search 引擎,能把「文档 slim 头 + include Doxygen + examples marker」三类头派生为按版本/架构筛选的索引,但知识库侧没有消费它的入口。
  • 为什么现有能力不能满足:① knowledge-query 无版本维度过滤,无法回答"这个 API 在 9.2.0/3510 是否适用";② ascendc-api-knowledge-query 复用同一索引,同样只有卡片;③ 卡片正文即使提到版本,也只是散文,无法按 --version/--product/--dtype/--param/--enum 过滤或反查;④ 首次 POC 已证伪"镜像存在覆盖缺口"的假设——镜像完整(A Hit@5 = 1.000),所以这不是一个"补召回"的需求,而是"补适用面与证据"的需求。
  • 频率/影响:凡是需要按版本或架构判定 API 适用性的任务(跨代迁移、RegBase/SIMT 选型、dtype 支持面核对)都要回到上游文档人工比对,属于高频重复劳动。

目标与方案

  • 期望改变的行为:在 knowledge-query 之外提供一条只读补充通道 knowledge-query-asc-enhance:按需准备 asc-devkit 精简单检出(.agent/docs/include/examples),用其 asc-search 建立按 surface × 架构 × CANN 版本 分实例的索引,返回带版本区间、逐产品支持、include 声明、样例关联的候选。不替代 Query 的知识卡检索,也不产生任何卡片。
  • 本次范围:Skill 本体(SKILL.md + 3 篇 references + 2 个脚本)、安装/文档/治理接入、evals/ 用例与离线回归。不包含:知识卡内容变更、asc-devkit 侧标注工作、除 c_api 之外 surface 的落地。
  • 设计与实现:输入 = 问题(自然语言或维度参数)、架构、CANN 版本;输出 = 候选列表(kind(doc/include/example) / path / api / title / version / product_support / headers / examples / why)+ 机器可读 JSON。写入边界:只在缓存目录($CANNBOT_ASC_DEVKIT_SLIM 或 $HOME/.cache/cannbot/asc-devkit-slim)写克隆与索引,不写知识仓、不改 asc-devkit 正文、不产卡、不写 Query receipt。
    • 缓存原子性:探测远端 ref → 与缓存 manifest 的 commit 比对 → 落后则建 <cache>.new 后原子替换并删除旧版本;--offline 只用缓存;--from-local 支持用本地仓(便于验证未合并的标注分支)。实测:联网稀疏克隆 3.8s、幂等重入 0.19s。
    • 索引实例:<index-root>/<surface>/<arch>/<cann-version>/,与 asc-search 的 index/<surface> 单实例布局解耦;廉价新鲜度判据 = 索引 meta.source_commit == 缓存 commit 且 surface/arch/cann-version 一致(O(1)),需要字节级复验时用 --verify(约 3.5s)。
    • 契约断言:build_index.py 必需 --scope/--arch/--cann-version/--out/--check,query.py 必需 --index-dir/--json;surface 从 --help 解析而不硬编码;任一不满足 → exit 2 并给出可操作原因。
  • 扩展接入:完全复用 asc-devkit 既有 asc-search,不复制其推导逻辑;本仓只新增一个消费型 Skill、一个 evals 用例集与离线回归。surface 可拓展性:当前仅 c_api(上游 SCOPES 只有这一项);新增 surface 时上游加一条 SCOPES 并补齐该层级标注即可,本 Skill 无需改代码(--surface 透传、索引按 surface 分目录、精简单检出一次到位覆盖四目录)。
  • 替代方案:① 不新增 Skill,直接在 knowledge-query 里加版本过滤——被否:Query 的索引建立在知识卡上,卡片本身没有版本结构化字段,等于要改卡片 Schema(更大且与镜像同步器冲突);② 扩展现有 ascendc-api-knowledge-query——被否:该 Skill 的契约是"复用 Query 索引",塞入跨仓外部索引会破坏其单一索引与审计契约;③ 等 asc-devkit 把标注合入后再做——被否:标注进度不在本仓控制内,且本能力已可用 fork 上公开 ref 复现验证。
  • 既有行为变更:无。knowledge-query、ascendc-api-knowledge-query、镜像同步、check.sh 既有门禁均不变;本 Skill 为新增可选能力,安装模式新增随 consumer/contributor 一起安装。
  • 兼容性、资源成本、权限:只读知识仓;需要一次网络准备(约 190MB 工作树,可用 --offline/--from-local 规避);查询 p95 0.32s;不新增任何写入权限。

A/B 实验计划与结果

  • 假设与验收标准(跑前固定):B(+asc-enhance)相对 A(仅 Query)应满足——① cann_versions 可核对率 ≥ 90%(A 基线 0%);② 命中候选带 include 声明证据 = 100%;③ 期望样例的用例中样例可得率 ≥ 50%;④ Hit@5 不劣化(B ≥ A,门槛 0;原计划的 +0.15 门槛已由 POC 证伪并修订,见下);⑤ p95 ≤ 3s(不含首次建索引)。

  • A 与 B:A = knowledge-query search(--match literal,platform 950);B = A 的同一问题 + query_asc.py。数据集:evals/asc_enhance_cases.yaml(16 条,来自 asc-search 索引的客观期望值:期望文档、版本区间、头文件、样例),驱动 evals/run_asc_enhance_ab.py;数据源为公开可复现的 flyingXLB/asc-devkit@okf-knowledge-user(b0f4a7e91)。

  • POC 阶段的关键修订(先失败后修订,记录在案):初版预注册门槛是"Hit@5 绝对提升 ≥ +0.15"。POC 实测 A 0.875 → B 1.000(+0.125)未达标,进一步核查发现:知识库对 asc-devkit 文档的镜像没有内容缺口(16/16 期望卡的镜像卡都存在),且初版 A 的命中判定口径有误(漏去 Concept ID 的 .md 后缀)。修正口径后 A = B = 1.000——说明召回不是本能力的价值点,价值在适用面与证据。据此把指标修订为上面 5 条并重新预注册。

  • 实测结果(16 条用例,b0f4a7e91):

    指标 A B 门槛 判定
    Hit@5 1.000 1.000 不劣化 ✅
    cann_versions 可核对率 0.000 1.000 ≥ 0.90 ✅
    命中候选带 include 声明 0(仅 source_headers 指针) 1.000 = 1.00 ✅
    样例关联可得率(期望样例用例) 0 0.778(7/9) ≥ 0.50 ✅
    p95 查询耗时 0.99s(p50) 0.32s ≤ 3s ✅
    首条候选同时带 version 与 headers — 0.875 观察项 —
  • 控制变量:同一问题文本、同一目标平台、同一机器;A/B 都按 API 名精确检索(A 用 --match literal,B 用 --kw,避免用家族展开语义造成假阴性);B 的索引固定为 3510 × 9.2.0 单实例。

  • 完整结果与复现:artifacts/asc_enhance_ab.json(忽略产物)+ 用例文件在 evals/;一条命令可复跑:python3 evals/run_asc_enhance_ab.py --from-local <asc-devkit 仓> --ref okf-knowledge-user。

  • 结论:5 项门槛全部达成;召回归因不成立、适用面与证据归因成立。风险与退化见下节。

  • 回归约束:不触碰 knowledge/ 与索引产物,knowledge_lint、sync-indexes --check、evals/run_retrieval.py --quality-gate 与既有单测保持原状;新增离线回归 evals/test_asc_enhance.py(10 项,fixture 驱动,无需网络)。

风险与边界

  • 上游依赖:cann/asc-devkit@master 目前只有 1 篇带 slim 头的文档,默认形态下索引为空——这是跨仓依赖,不是本 Skill 缺陷;Skill 会明确报告 doc_count 与"上游未标注"的事实,并可用 --source/--ref/--from-local 指向已标注来源。
  • 上游契约漂移:asc-search CLI 变更会由契约断言拦截并 exit 2,不会静默给出错误结果。
  • 量化收益的边界:收益随标注覆盖率线性变化;当前证据基于 c_api(613 篇索引文档)。
likedislike
flyingXLBflyingXLB
6 天前 关联了pull request:feat(knowledge): 新增 knowledge-query-asc-enhance(asc-devkit 声明与样例增强消费)
Junyi
1 天前 评论:

已核对关联 !166 当前 3088404,固定提交、缓存/索引锁及A/B执行失败关闭已有实现。PR现有31项离线回归在补齐本地PyYAML依赖后全部通过;这些是本地fixture测试,不是重跑RFC的真实A/B结果。

仍有一处与本RFC默认来源边界直接相关的输出缺口:query_asc.py L338-L355 只返回候选数,未传出当前索引的文档覆盖量;空索引也只显示 count=0 / no matches,没有覆盖不足提示。RFC承诺的“报告doc_count与上游未标注事实”尚未体现在这条输出中。

我用隔离本地Git仓、asc-search替身和PR原版ensure/query入口做了两组对照:① 当前实例 meta.doc_count=0;② 索引有1篇文档,但关键词未命中。两者均退出0、count=0、stderr为空,输出均没有覆盖量或告警字段。这里验证的是消费协议,未执行真实上游asc-search,也不据此测量召回率或速度。

建议把当前surface/arch/version实例的覆盖量及覆盖不足提示带到JSON和文本输出,并与“非空索引中的普通零命中”分别回归。零覆盖的原因应依据索引范围/构建记录说明,不直接推断为API不支持;真实零命中的既有退出码语义可保留。这样默认未标注源、过滤后无覆盖和已有覆盖却没搜到,不会在消费端变成同一种否定结论。

likedislike