|
@@ -1,128 +0,0 @@
|
|
|
-# 归类独立成表(step_classification)· 3-I 设计
|
|
|
|
|
-
|
|
|
|
|
-> 来源:`归类口径修复与表结构优化方案.md` 第 6 节的 ④(归类级表)。
|
|
|
|
|
-> 范围:**只做 3-I**——新增一张 `step_classification` 表 + 回写改造 + 查询接口,**不动 `mode_process` 结构**(第 6.2 ①②③ 的 run/procedure/step 规范化 = 3-II,延后)。
|
|
|
|
|
-> 目标:让「维度联动取帖」与「工序解构表里显示的归类值」**同源**,从根上消除第 1 节的「树多归属 ≠ 表单归属」,且不再依赖 cat-api 树的 `knowledge_ids` / `top_k`。
|
|
|
|
|
-
|
|
|
|
|
----
|
|
|
|
|
-
|
|
|
|
|
-## 1. 现状回顾(本项目侧)
|
|
|
|
|
-
|
|
|
|
|
-- `stages/category_match.py`:对一帖五维度词(实质/形式/类型/作用/动作)调 cat-api `/api/v1/category-match`,`enrich_steps()` 只把**实质/形式**的「单一最优 name」回写进 `mode_process.steps[].substanceMatch / formMatch`(JSON blob 内)。
|
|
|
|
|
-- cat-api 侧 `record=True` 把命中节点记进分类库(= 树的 `knowledge_ids`)。`top_k` 已在批次 0 改为 `1`。
|
|
|
|
|
-- 前端(**aigc-web**,非本项目)维度联动:点分类树节点 → 用该节点 cat-api `knowledge_ids` 取帖 → 与帖里显示的 `substanceMatch` 口径不一致。
|
|
|
|
|
-
|
|
|
|
|
-痛点:归类结果埋在 `steps` JSON 里,DB 层**无法按归类值查询/索引**;前端只能依赖 cat-api 树,导致多归属不一致。
|
|
|
|
|
-
|
|
|
|
|
----
|
|
|
|
|
-
|
|
|
|
|
-## 2. 新增表 DDL(MySQL,加入 `db.py`)
|
|
|
|
|
-
|
|
|
|
|
-一行 = 某 case 某版本某工序某 step 某维度某子项的归类结果。
|
|
|
|
|
-
|
|
|
|
|
-```sql
|
|
|
|
|
-CREATE TABLE IF NOT EXISTS step_classification (
|
|
|
|
|
- id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
|
|
|
- case_id VARCHAR(128) NOT NULL,
|
|
|
|
|
- query_id VARCHAR(32) NULL COMMENT 'record 时的 post_id,便于溯源',
|
|
|
|
|
- version VARCHAR(32) NULL COMMENT '对齐 mode_process 最新真实版,重跑覆盖',
|
|
|
|
|
- procedure_id VARCHAR(16) NULL COMMENT 'p1,p2…',
|
|
|
|
|
- step_id VARCHAR(16) NULL COMMENT 's1,s2…',
|
|
|
|
|
- dimension VARCHAR(8) NOT NULL COMMENT '实质/形式/类型/作用/动作',
|
|
|
|
|
- sub_index SMALLINT NOT NULL COMMENT '原值「、」拆分后的子项下标(等长等序)',
|
|
|
|
|
- raw_term VARCHAR(255) NULL COMMENT '原始词',
|
|
|
|
|
- matched_name VARCHAR(255) NULL COMMENT '命中分类名(单一最优;无命中不入库)',
|
|
|
|
|
- matched_path VARCHAR(512) NULL COMMENT '命中分类全路径,如 /表象/视觉/空间/空间环境',
|
|
|
|
|
- matched_id INT NULL COMMENT 'cat-api stable_id',
|
|
|
|
|
- score FLOAT NULL,
|
|
|
|
|
- match_run_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
|
|
|
- UNIQUE KEY uk_step_dim_sub (case_id, version, procedure_id, step_id, dimension, sub_index),
|
|
|
|
|
- KEY idx_case (case_id),
|
|
|
|
|
- KEY idx_dim_name (dimension, matched_name),
|
|
|
|
|
- KEY idx_dim_path (dimension, matched_path) -- matched_path LIKE '前缀%' 走索引
|
|
|
|
|
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='step 维度归类结果(与 mode_process 解耦)';
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-设计要点:
|
|
|
|
|
-- **只入「有命中」的子项**(matched_name 非空)。无命中子项不入库——维度联动只关心命中的;`steps[].substanceMatch` 仍保留「无」占位供前端按下标对齐,二者职责分开。
|
|
|
|
|
-- 用**自然键** `(case_id, version, procedure_id, step_id, dimension, sub_index)` 唯一,不引 `process_step.id` 外键——这样 3-I 完全独立于 3-II;将来 3-II 落地再加 FK。
|
|
|
|
|
-- 写入用 **DELETE(by case_id,version)+INSERT** 原子覆盖(同 `replace_process`),重跑幂等、不留旧归属。
|
|
|
|
|
-
|
|
|
|
|
----
|
|
|
|
|
-
|
|
|
|
|
-## 3. 回写改造(`stages/category_match.py`)
|
|
|
|
|
-
|
|
|
|
|
-现 `_build_match_lookup` 只取 name。新增「全字段」lookup 与「记录构造」,**五维度全覆盖**(现仅实质/形式):
|
|
|
|
|
-
|
|
|
|
|
-```text
|
|
|
|
|
-_build_match_full(resp) -> {(term, source_type): {name, path, id, score}}
|
|
|
|
|
- 择优规则不变:精确同名(name==term)优先,再比 score。
|
|
|
|
|
-
|
|
|
|
|
-build_classification(procedures, resp, *, case_id, query_id, version) -> [record...]
|
|
|
|
|
- 遍历每 proc/step,对五维度逐子项(按「、」拆,_split_values)查 lookup:
|
|
|
|
|
- 实质 ← step.substance 形式 ← step.form
|
|
|
|
|
- 作用 ← step.effect 动作 ← step.action
|
|
|
|
|
- 类型 ← step.inputs[].type(多 input 顺序展开)
|
|
|
|
|
- 命中则产出一行 record(含 procedure_id=proc.id, step_id=step.id, dimension,
|
|
|
|
|
- sub_index, raw_term, matched_*),无命中跳过。
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-`process_one()` 流程在「`enrich_steps` 回写 steps」之后,**新增一步**:
|
|
|
|
|
-
|
|
|
|
|
-```text
|
|
|
|
|
-recs = build_classification(procedures, resp, case_id, query_id, version)
|
|
|
|
|
-db.replace_step_classification(case_id, version, recs) # DELETE+INSERT 原子覆盖
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-- `enrich_steps`(写 `substanceMatch/formMatch` 到 steps)**保留不动** → 前端工序表显示不受影响。
|
|
|
|
|
-- 即:一次归类,**双写**——steps 内显示值(name) + step_classification(name+path+score,五维)。
|
|
|
|
|
-
|
|
|
|
|
----
|
|
|
|
|
-
|
|
|
|
|
-## 4. 读侧接口
|
|
|
|
|
-
|
|
|
|
|
-`db.py` 新增:
|
|
|
|
|
-
|
|
|
|
|
-```text
|
|
|
|
|
-fetch_classified_cases(dimension, path=None, name=None, subtree=False) -> set[case_id]
|
|
|
|
|
- -- 默认(subtree=False):精确本节点 WHERE dimension=%s AND matched_path = %s
|
|
|
|
|
- -- → 帖数 = cat-api 树徽标(节点 knowledge_count)同口径,substanceMatch = 该节点名
|
|
|
|
|
- -- subtree=True:本节点及整棵子树 matched_path = %s OR matched_path LIKE CONCAT(%s,'/%')
|
|
|
|
|
- -- name:精确分类名 matched_name = %s
|
|
|
|
|
-```
|
|
|
|
|
-> 2026-06-28:`path` 默认由「子树」改为「精确本节点」——修维度联动取帖与树徽标/substanceMatch 不一致(后代节点帖混入)。子树改为 `subtree=1` 显式开启。
|
|
|
|
|
-
|
|
|
|
|
-`server.py` 新增路由:
|
|
|
|
|
-
|
|
|
|
|
-```text
|
|
|
|
|
-GET /api/classified_cases?dimension=实质&path=/表象/视觉/空间/空间环境
|
|
|
|
|
- -> {"dimension","path","cases":[...],"count":N}
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-aigc-web 维度联动据此把「取 case 的来源」从 cat-api `node.knowledge_ids` 切到本接口
|
|
|
|
|
-(→ 与 `substanceMatch` 同源,彻底解决树多归属)。**此前端改动属 aigc-web,3-I 不含,作为协同项单列。**
|
|
|
|
|
-
|
|
|
|
|
----
|
|
|
|
|
-
|
|
|
|
|
-## 5. 数据填充(与重跑合并,不单独迁移)
|
|
|
|
|
-
|
|
|
|
|
-- step_classification 的正确数据(含 path/score)只能来自**重跑** category-match(批次 4):旧 `steps` 里只有 name、无 path,回填无意义。
|
|
|
|
|
-- 故 3-I **不写迁移脚本**;建表后表为空,**批次 4 重跑即填充**(每帖 `replace_step_classification`)。这与「重跑放最后」一致。
|
|
|
|
|
-
|
|
|
|
|
----
|
|
|
|
|
-
|
|
|
|
|
-## 6. 落地清单(3-I)
|
|
|
|
|
-
|
|
|
|
|
-1. `db.py`:`DDL_STEP_CLASSIFICATION` + `init_tables()` 建表 + `replace_step_classification()` 写 + `fetch_classified_cases()` 读。
|
|
|
|
|
-2. `stages/category_match.py`:`_build_match_full()` + `build_classification()`,`process_one()` 调 `replace_step_classification`。
|
|
|
|
|
-3. `server.py`:`GET /api/classified_cases`。
|
|
|
|
|
-4. 跑 `python db.py init`(幂等建新表)。
|
|
|
|
|
-5. (协同/后续)aigc-web 维度联动切到 `/api/classified_cases`。
|
|
|
|
|
-6. (批次 4)重跑填充 step_classification。
|
|
|
|
|
-
|
|
|
|
|
----
|
|
|
|
|
-
|
|
|
|
|
-## 7. 风险与回退
|
|
|
|
|
-
|
|
|
|
|
-- 纯**新增**:新表 + 新函数 + 新路由 + category_match 多一步写;不改任何现有读写口径与表结构 → 旧链路完全不受影响,可回退(删表/去掉那一步写)。
|
|
|
|
|
-- 重跑前表为空,不影响现有功能。
|
|
|