Ontology

使用 Ollma 处理 Ontology 端到端生成

const p = `你是企业本体建模专家。你的任务是根据用户提供的公司业务材料,自动设计一个领域的本体(ontology)。
要求:
1. 输出一个严格的 JSON 对象,包含 concepts / relations / rules / scenarios / standards 五个数组。
2. 概念命名:localName 用 PascalCase(如 Employee、TravelRequest),labelZh 用中文,labelEn 用 PascalCase(不要带空格)。
3. 字段类型必须是:string / number / date / boolean / ref / array。枚举值(enum)必须取自材料里实际出现的值,不要套用示例里的值。
4. 复用已有核心概念(影响图谱连通性与跨领域去重):
   领域概念若与「平台已有核心概念」(见下方清单)中某个同义/等价(IS-A 关系),设 mapsToCore 指向该核心概念的 localName,
   系统会据此建等价关系(owl:equivalentClass),把领域概念链到核心概念——核心概念因此被引用、在图谱连通,跨领域也自动去重。
   原则:
   - 有同义核心概念就映射,不要新建同义概念又不映射。
   - 领域特有的概念(清单里没有对应的,如某领域特有的费用类型、业务动作)不设 mapsToCore,留空。
   - 宁可多映射(把能对上核心概念的领域概念都链上)也不要漏——漏了核心概念就成孤立节点。

【平台已有核心概念】(运行时从库中动态查出,复用这些而非新建同义概念):
- Person(人员:自然人,跨领域共享。员工、采购员、合同签署人、检查员都是它的具体化。)
- Organization(组织:组织单元,可以是部门、成本中心、子公司。)
- Money(金额:金额对象,含数值 + 币种。所有费用、预算、合同金额都引用此概念。)
- Document(文档:文档凭据,如发票、合同、采购单。)

5. 关系类型必须是:CONTAINS / BELONGS_TO / REFERENCES / SUBMIT / APPROVE 之一。

【关系完整性 —— 硬性约束,必须满足】
同一领域内的所有概念必须通过关系连通成一张图,不允许出现孤立概念(没有任何关系连到它的概念)。不相干的概念根本不应出现在同一个领域里——既然放进来,就必须有关系把它挂到领域图上。具体要求:
  - 每个概念至少出现在一条 relation 的 source 或 target 里(degree ≥ 1)。
  - 主/单据概念(如 TravelRequest、ExpenseReport、申请单)通过 SUBMIT 连到发起人(Employee),并 CONTAINS 其下所有明细概念。
  - 每个明细概念(如各项费用 AccommodationFee / MealFee / TransportationFee、明细行)必须被它的主单据 CONTAINS(即作为某条 CONTAINS relation 的 target),不能孤立。
  - ref 字段引用的概念(如 applicant→Employee)若该概念已在本领域,不必再为引用单独建关系;但被引用概念本身仍需通过其他关系连通。
  - 输出前自检:遍历 concepts,任一概念若不在任何 relation 中,补一条合理的关系(通常是 CONTAINS 挂到主单据,或 SUBMIT 连到 Employee),使其连通。
6. 规则 DSL 必须遵守以下语法(重要!):
   - when 子句支持:
     * isEmpty(path) / isNotEmpty(path) / exists(path)
     * path == "字符串" / path != "x" / path > 100 / path >= 100 / path < 100 / path <= 100
     * path in [a, b, c] / path not_in [a, b]
     * func(args)  # 受治理函数调用,如 amount > std_xxx(dim1, dim2)
     * all: [条件列表]  # 且
     * any: [条件列表]  # 或
     * not (条件)
   - 字符串字面量必须用双引号
   - message 用 {{path}} 插值
   - 多行 explanation 用 | 块标量
   - targetPath(重要!):当规则作用于"明细类概念"时,targetPath 必须写成"<对应数组字段名>[*]"使其逐条遍历。字段名 = 概念名转复数(AccommodationFee → accommodationFees)。示例:target: AccommodationFee, targetPath: accommodationFees[*]。不写 targetPath 的规则会在整单层求值一次。
   - 引用业务属性时直接用顶层概念字段(如 employee.level),不要走 ref 字段路径(如 travelRequest.applicant.level)——ref 字段(applicant/buyer 等)只携带 {id,name} 用于关联,不含 level/department 等业务属性,走 ref 路径会取不到值导致规则不触发。
6. 规则 severity 必须是 error / warning / info 之一(小写)。
7. 至少产出 3 个概念、2 条规则。关系数量无下限硬要求,但必须满足上面的「关系完整性」约束:所有概念连通,每个明细被 CONTAINS(通常 relations 数 ≥ concepts 数 - 1)。

【受治理标准(standards)—— 重点】
材料里常有"按城市×职级的住宿上限""按餐别×职级的餐标"这类数值标准表。这些数值是数据、不是代码,必须抽到 standards 数组里,供规则 DSL 通过受治理函数 call 取用,绝对不要把具体限额写进规则文本或硬编码。
每个 standard:
  - code:受治理函数名,与规则 call[0] 一致(如 std_hotel_max、std_meal_max)。命名用 std_ 前缀 + 语义。
  - matrix:嵌套查找表对象,下钻顺序 = 规则 call 的参数顺序。
    例:规则 when 里 amount > std_hotel_max(cityCategory, applicant.level),
    则 matrix = { "北上广深": { "其他员工": 400, "部门经理/部门副经理级": 600 }, "省会直辖市": { ... } }。
    叶子值必须是 number。
  - matrix 的键必须与材料里的枚举值/维度值完全一致(城市类别、职级、餐别等),不要编造或套用示例值。
规则 call 的参数个数必须与 matrix 的嵌套层数一致。一个 code 对应一个 standard(一个 matrix 覆盖所有维度组合)。
若材料没有对应标准表,就不要造该 standard,相关规则也不要 call 不存在的 std_xxx。

【scenarios(使用场景/Action)抽取规则 —— 重点】
一个业务领域通常有多个"使用场景",每个场景对应材料中描述的一个具体业务动作(Action)。
你必须通读材料,把材料里出现过的每一个独立业务动作都识别为一个 scenario,而不是只给一个笼统的"提交校验"。
常见动作来源包括但不限于:
- 制度流程中各办理环节(如"出差申请"、"费用报销"、"暂借款申请"等)
- 材料中明确列出的"动作一/动作二"或编号动作,每个动作应单独成一个 scenario
对每个 scenario:code 用 snake_case 英文,name 用中文动作名,description 说明该动作触发什么校验。通常一个领域应识别出 3 个以上 scenario。

输出 JSON Schema(字段值为结构演示,实际值取自材料):
{
  "concepts": [
    {
      "localName": "Employee",
      "labelZh": "员工",
      "labelEn": "Employee",
      "description": "业务材料中的员工",
      "mapsToCore": "Person",
      "fields": [
        { "name": "id", "type": "string", "required": true, "label": "工号" },
        { "name": "name", "type": "string", "required": true, "label": "姓名" },
        { "name": "level", "type": "string", "label": "职级", "enum": ["<取自材料>"] }
      ]
    }
  ],
  "relations": [
    { "name": "提交", "source": "Employee", "target": "TravelRequest", "relationType": "SUBMIT", "cardinality": "1:N", "description": "员工提交出差申请" }
  ],
  "rules": [
    {
      "code": "R-AC-001",
      "name": "住宿费超标",
      "severity": "warning",
      "target": "AccommodationFee",
      "targetPath": "accommodationFees[*]",
      "dsl": "- id: R-AC-001\\n  name: 住宿费超标\\n  severity: warning\\n  target: AccommodationFee\\n  targetPath: accommodationFees[*]\\n  when:\\n    amount > std_hotel_max(cityCategory, travelRequest.applicant.level)\\n  message: \\"住宿费{{amount}}元超过标准\\"\\n  explanation: |\\n    住宿费按城市类别与职级有上限\\n  tags: [住宿, 超标]",
      "message": "住宿费{{amount}}元超过标准",
      "explanation": "住宿费按城市类别与职级有上限",
      "tags": ["住宿","超标"]
    }
  ],
  "scenarios": [
    { "code": "submit_travel_request", "name": "提交出差申请", "description": "出差前提交审批单" }
  ],
  "standards": [
    {
      "code": "std_hotel_max",
      "matrix": { "北上广深": { "其他员工": 400, "部门经理/部门副经理级": 600 }, "省会直辖市": { "其他员工": 350, "部门经理/部门副经理级": 500 } },
      "description": "住宿费上限(元/间/天),按城市类别×职级"
    }
  ]
}
注意:DSL 字符串里的换行用 \n 转义,双引号用 " 转义。standards.matrix 里的数值与维度键必须取自材料,不要套用本示例的数字。
如下是用户上传的材料:
公司业务材料:

IT系统权限申请流程:
1. 员工发起权限申请,填写申请单号、目标系统名称、申请角色、生效日期
2. 申请包含“数据导出”权限需信息安全部审核
3. 申请包含“系统管理员”角色需技术总监审批
4. 申请单必须填写明确的业务使用场景说明
5. 权限生效日期不能早于今天
6. 同一申请单号不能重复提交
7. 申请包含多个操作节点,每个节点有安全等级(常规/敏感/极敏感)
8. 极敏感操作节点必须信息安全部专项复核
`



const url = "http://localhost:11434/api/generate"
const data = {
    "model": "qwen2:7b",
    "prompt": p,
    "stream": false
}
const response = await fetch(url, {
  method: "POST",
  body: JSON.stringify(data),
})
const json = await response.json();
console.log(json["response"])

posted @ 2026-08-30 14:58  tommao9925  阅读(2)  评论(0)    收藏  举报