Quellcode durchsuchen

chore(mode_workflow): 停止跟踪 docs 目录并加入 .gitignore

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
刘文武 vor 3 Wochen
Ursprung
Commit
fc331a5ac0

+ 2 - 1
examples/mode_workflow/.gitignore

@@ -12,4 +12,5 @@ import_process_knowledge.处理方式.md
 归类口径修复与表结构优化方案.md
 工序接口文档.md
 流程执行手册.md
-拆表_3-II_设计.md
+拆表_3-II_设计.md
+docs/

+ 0 - 78
examples/mode_workflow/docs/knowledge_ingest_api.md

@@ -1,78 +0,0 @@
-# 知识导入接口(knowledge ingest)
-
-> 来源:`stages/import_process_knowledge.py`(`build_payload` + `ingest_one`)
-> 用途:把 DB 中「已采纳」的工序解构(mode_process)逐条写入知识库。
-
-## 基本信息
-
-| 项 | 值 |
-|----|----|
-| Method | `POST` |
-| URL | `{api_url}/api/v1/knowledge/ingest` |
-| 默认 `api_url` | `http://47.236.83.130:8001` |
-| 完整默认地址 | `http://47.236.83.130:8001/api/v1/knowledge/ingest` |
-| Content-Type | `application/json` |
-| 超时 | 30s |
-| 成功状态码 | `201 Created` |
-
-**一条 procedure(工序)= 一次请求 = 一条知识。** 同一个 case 下有 N 个工序就调用 N 次。
-
-## 请求头
-
-```
-Content-Type: application/json
-```
-
-## 请求体字段
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| `source` | object | 是 | 来源帖子信息 |
-| `source.id` | string | 是 | 来源主键,直接取 DB 的 `case_id` |
-| `source.source_type` | string | 是 | 固定 `"post"` |
-| `source.title` | string \| null | 是 | 来源标题,空则 `null` |
-| `source.author` | string \| null | 是 | 来源作者,空则 `null` |
-| `source.source_metadata` | object | 是 | 来源附加元信息(见下) |
-| `source.source_metadata.platform` | string | 是 | 平台,空则 `""` |
-| `source.source_metadata.date` | string | 是 | 发布日期,空则 `""` |
-| `source.source_metadata.url` | string \| null | 是 | 原文链接,空则 `null` |
-| `source.source_metadata.excerpt` | string | 是 | 摘要,截断到 500 字符 |
-| `source.source_metadata.procedure_id` | string | 是 | 工序 id,空则 `""` |
-| `source.source_metadata.procedure_name` | string | 是 | 工序名,空则 `""` |
-| `title` | string | 是 | 知识标题,截断到 512 字符。取工序名;为空回退 `"来源标题 — 工序N"`,再空则 `"工序N"` |
-| `content` | string | 是 | 整个 procedure 对象序列化后的 JSON 字符串(`ensure_ascii=False`) |
-| `dim_attributes` | string[] | 是 | 固定 `["how工序"]` |
-| `dim_creations` | string[] | 是 | 固定 `["制作"]` |
-| `scopes` | object[] | 否 | 作用域;为空时**不带该字段** |
-| `scopes[].scope_type` | string | - | `"substance"` 或 `"form"` |
-| `scopes[].value` | string | - | 由各步骤 `substance`/`form` 按顿号拆分去重 |
-| `custom_ext` | object[] | 否 | 自定义扩展;为空时**不带该字段** |
-| `custom_ext[].key` | string | - | `"作用"`(effect)/ `"动作"`(action)/ `"工具"`(via,`human` 除外) |
-| `custom_ext[].type` | string | - | 固定 `"str"` |
-| `custom_ext[].value` | string | - | 对应步骤字段按顿号拆分去重 |
-
-> 注:`scopes` 与 `custom_ext` 仅在非空时才会出现在请求体里(脚本里条件添加)。
-
-## 成功响应(201)
-
-```json
-{
-  "knowledge_id": "<生成的知识ID>"
-}
-```
-
-## 失败响应
-
-| 情况 | 处理 |
-|------|------|
-| 非 201 | 读取响应 JSON 的 `detail` 字段(无则取 `text[:300]`)作为错误信息 |
-| 超时(30s) | 记为失败,信息 `"超时(30s)"` |
-| 网络异常 | 记为失败,信息为异常字符串 |
-
-## curl 示例
-
-```bash
-curl -X POST http://47.236.83.130:8001/api/v1/knowledge/ingest \
-  -H "Content-Type: application/json" \
-  -d @knowledge_ingest_payload.json
-```

+ 0 - 34
examples/mode_workflow/docs/knowledge_ingest_payload.json

@@ -1,34 +0,0 @@
-{
-  "source": {
-    "id": "xhs_a1b2c3",
-    "source_type": "post",
-    "title": "用 AI 生成二次元风格头像的完整流程",
-    "author": "设计师小王",
-    "source_metadata": {
-      "platform": "xiaohongshu",
-      "date": "2026-03-15",
-      "url": "https://www.xiaohongshu.com/explore/xhs_a1b2c3",
-      "excerpt": "本文介绍如何用 AI 工具把真人照片转成二次元风格头像,包含线稿、上色、细节调整三步……",
-      "procedure_id": "proc_001",
-      "procedure_name": "二次元头像生成"
-    }
-  },
-  "title": "二次元头像生成",
-  "content": "{\"id\": \"proc_001\", \"name\": \"二次元头像生成\", \"steps\": [{\"substance\": \"真人照片\", \"form\": \"二次元线稿\", \"effect\": \"风格转换\", \"action\": \"上传并生成\", \"via\": \"Midjourney\"}, {\"substance\": \"二次元线稿\", \"form\": \"上色稿\", \"effect\": \"着色\", \"action\": \"自动上色\", \"via\": \"Photoshop\"}]}",
-  "dim_attributes": ["how工序"],
-  "dim_creations": ["制作"],
-  "scopes": [
-    { "scope_type": "substance", "value": "真人照片" },
-    { "scope_type": "substance", "value": "二次元线稿" },
-    { "scope_type": "form", "value": "二次元线稿" },
-    { "scope_type": "form", "value": "上色稿" }
-  ],
-  "custom_ext": [
-    { "key": "作用", "type": "str", "value": "风格转换" },
-    { "key": "作用", "type": "str", "value": "着色" },
-    { "key": "动作", "type": "str", "value": "上传并生成" },
-    { "key": "动作", "type": "str", "value": "自动上色" },
-    { "key": "工具", "type": "str", "value": "Midjourney" },
-    { "key": "工具", "type": "str", "value": "Photoshop" }
-  ]
-}

+ 0 - 128
examples/mode_workflow/docs/step_classification_3-I_设计.md

@@ -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 多一步写;不改任何现有读写口径与表结构 → 旧链路完全不受影响,可回退(删表/去掉那一步写)。
-- 重跑前表为空,不影响现有功能。