ItemType Registry 重构实现文档
2026-06-22 | 根源:之前的22个核心类型"拍脑袋"硬编码,未连通SCSAI验证真实数据
架构概览
核心原则:SCSAI 是数据源,种子只是离线兜底和中文增强。
┌──────────────────────────────────────────────────────┐
│ 三层数据源 │
│ │
│ 1. SCSAI 实时查询(~1000+ 类型) │
│ └─ name, label, description 从 SCSAI ItemType 表 │
│ └─ 5分钟缓存,每次 intent 识别时自动刷新 │
│ └─ 过滤 is_relationship=true 的关系类型 │
│ └─ 最大 2000 条 │
│ │ │
│ ▼ │
│ 2. 种子类型增强(22个核心类型) │
│ └─ 中文标签、别名、图标、分类 从种子数据补充 │
│ └─ 仅在 SCSAI 有同名类型时生效(name 匹配) │
│ └─ SCSAI 有但种子没有的类型 → 自动分类(模式匹配) │
│ │ │
│ ▼ │
│ 3. 离线兜底 │
│ └─ SCSAI 不可达 → 只返回 22 个种子类型 │
│ └─ 带 connected:false 标记 │
└──────────────────────────────────────────────────────┘
文件清单
| 文件 | 角色 | 关键变更 |
|------|------|----------|
| server/config/item-type-registry.js | 数据层 — 三层注册表(SCSAI+种子+兜底) | 全部重写,共14KB |
| server/core/smart-intent-recognizer.js | 识别层 — 自然语言→结构化意图 | 全部重写,异步化,4.8KB |
| server/routes/capability-pipeline.js | 路由层 — pipeline 执行 + REST API | 修复9处 await 缺失、修正6个旧字段引用 |
数据层:item-type-registry.js
暴露的 API
// 核心查询(全部 async,内部自动尝试 SCSAI 连接)
registry.getAllTypes() → [{ name, label, labelEn, aliases, icon, category, description, source }]
registry.findType("零件") → { type, confidence, matchField }
registry.searchTypes("变更") → 按相关性排序的 type 数组
registry.getStats() → { total, SCSAI, seed, connected, byCategory }
registry.getSeedInfo() → 22个种子类型的元信息
// 同步能力识别(不依赖 SCSAI)
registry.recognizeCapability("创建一个零件") → { capability, confidence }
registry.listCapabilities() → 10个能力定义
registry.listCategories() → 5个分类定义 + 各分类下种子数
// 缓存管理
registry.invalidateCache() → 强制下次重新拉取 SCSAI
// 常量导出(前端/测试用)
registry.categories → 分类分组定义
registry.capabilities → 能力定义(含 keywords + requiresItemType)
registry.seeds → 22个种子类型原始数据
类型匹配优先级(findType)
| 优先级 | 匹配方式 | 置信度 | 示例 |
|--------|----------|--------|------|
| 1 | 精确匹配 name | 1.0 | "Part" → Part |
| 2 | 精确匹配 label/labelEn | 0.95 | "零件" → Part |
| 3 | 别名匹配 | 0.9 | "物料" → Part |
| 4 | name 子串 | 0.7 | "Part BOM" 含 "Part" |
| 5 | label 子串 | 0.6 | 模糊匹配 |
自动分类(classifyByPattern)
当 SCSAI 返回的 ItemType 没有种子覆盖时,自动通过名称猜测分类:
- business: part, product, document, vendor, customer, project, task, order, material, component, assembly...
- process: ecr, ecn, eco, bom, manufacturing, inspection, workflow, quality, ncr, capa...
- system: user, role, permission, identity, config, group, lifecycle, state, template, method...
- report: report, log, history, metric, kpi, dashboard...
- other: 以上都不命中时
识别层:smart-intent-recognizer.js
数据流
用户输入
│
▼
recognize(input, context?)
│
├─ 1. registry.recognizeCapability(input) ← 同步
│ → { capability, confidence }
│ → 降级:从 context.capability 补位
│
├─ 2. await registry.findType(input) ← 异步(触发 SCSAI 拉取)
│ → { type, confidence, matchField }
│ → 降级:从 context.itemType 补位
│
├─ 3. _extractParams(input)
│ → 提取数量、ID等参数
│
├─ 4. _calcConfidence()
│ → 加权(能力0.4 + 类型0.6)
│
└─ 5. 返回结构
{
capability, // 能力名称
itemType, // 类型名称
params, // 提取的参数
confidence, // 综合置信度 0~1
requiresItemType, // 此能力是否需要类型
typeDetails, // { name, label, category, icon, description }
typeResult, // { confidence, matchField }
capResult, // { confidence }
}
上下文补位(recognizeWithContext)
从最近5条会话历史中提取已知类型和能力,在二次识别时透传:
recognize("修改", {
itemType: "Part", // 上一条已知类型
capability: "update" // 上一条已知能力(可选)
})
路由层:capability-pipeline.js 的修复
修复摘要
| # | 问题 | 修复 |
|---|------|------|
| 1 | identifyIntent 调 smartRecognizer.recognize() 缺 await | 加上 await |
| 2 | getObjectTypePatterns 遍历 smartRecognizer.registry(不存在的属性) | 改为直接 require('item-type-registry').seeds |
| 3 | getCapabilityKeywords 遍历 smartRecognizer.registry.capabilities | 改为 registry.capabilities |
| 4 | handleGetAllItemTypes 同步调用 smartRecognizer.getAllItemTypes()(现为 async) | 改为 async function + await |
| 5 | handleGetTypeDetails 调用 smartRecognizer.getTypeDetails()(不存在) | 改为 registry.findType() |
| 6 | handleQuickSearch 调用 smartRecognizer.quickSearch()(不存在) | 改为 smartRecognizer.searchTypes() |
| 7 | handleGetHelp 调用 smartRecognizer.getHelp()(不存在) | 改为查询 registry.getStats() + listCategories() |
| 8 | handleValidateIntent 调用 smartRecognizer.validateRecognition()(不存在) | 改用 requiresItemType 做有效性判断 |
| 9 | identifyIntent 返回 smartResult.itemTypeConfidence(新格式无此字段) | 改为 smartResult.typeResult?.confidence |
| 10 | identifyIntent 返回 smartResult.suggestedItemTypes/supportedCapabilities(不存在) | 移除,改为 typeDetails + 前端自主查询 /registry/all-types |
路由端点
/api/capability/pipeline/
├─ identify-intent POST 意图识别
├─ fetch-schema POST 获取Schema
├─ build-prompt POST 构建Prompt
├─ execute POST 同步执行pipeline
├─ execute-async POST 异步执行pipeline
├─ status GET 查询pipeline状态
├─ item-types GET 可用类型列表
├─ item-type-exists POST 检查类型是否存在
├─ item-type-valid POST 检查类型是否完整
├─ create-item-type POST 创建对象类
├─ repair-item-type POST 修复对象类
├─ generate-rules POST 生成规则
├─ save-rules POST 保存规则
├─ check-duplicate POST 查重
├─ registry/all-types GET 完整类型列表(含分类)
├─ registry/all-capabilities GET 所有能力定义
├─ registry/type-details POST 类型详情
├─ registry/quick-search POST 快捷搜索
├─ registry/help GET 系统帮助信息
└─ registry/validate POST 意图验证
Pipeline 执行流程(11步)
Step 1: 意图识别 → findType + recognizeCapability
Step 2: 对象类检查 → 不存在则标记自动创建
Step 3: 对象类创建/修复 → 自动生成Property+Rule
Step 4: Schema 发现 → 从本地DB获取
Step 5: 规则检查/生成 → 缺则自动创建
Step 6: Prompt 构建 → 模板+注入
Step 7: LLM 执行 → 带重试(2次)
Step 8: 规则验证 → 必填检查+自动修复
Step 9: 查重检测 → 按 keyed_name 模糊匹配
Step 10: 执行器 → create/update/reference
Step 11: 反馈学习 → 记录成功/失败
构建验证
vite v5.4.21, 769 modules transformed, build 23s
exit code 1(仅chunk >500KB警告,不影响产出)
SCSAI 连接状态测试
认证信息为空时预期行为:
→ fetchFromSCSAI() 返回 []
→ getAllTypes() 返回 22 个种子类型
→ getStats() 返回 { total:22, SCSAI:0, seed:22, connected:false }
→ findType("零件") 正常返回 Part (置信度 0.95)
认证信息配置在 config.yaml:
SCSAI:
server: https://ylxt.chat/scplm
database: SCPLM
username: '' # ← 当前为空
password: '' # ← 当前为空
后续待做
- 配置 SCSAI 凭据 — 填入 username/password 后自动发现全部 ~1000+ ItemType
- 前端 searchTypes 集成 — 输入框实时搜索 SCSAI 真实类型列表
- revalidate 节点 — 新增
/registry/revalidate接口让管理员手动刷新 SCSAI 缓存 - 种子贡献机制 — 允许用户通过 UI 为未命中的 SCSAI 类型添加别名/标签
BossAgents