
后端前端人工智能RAG知识图谱知识管理搜索引擎【免费下载链接】utopiaWorlds first open-source enterprise world model.项目地址https://gitcode.com/gh_mirrors/ont/utopia点击查看免费下载本篇文章以 Utopia 的决策记录 0021-a-rule-reads-attributes-and-concludes-a-type.md 为核心骨架结合 规则求值器源码、迁移脚本、存储层、API 路由 与 数据库集成测试完整讲解 Utopia 中业务规则attribute rules这一能力规则如何读取一个实体自己的属性事实字面值经阈值比较、集合判定等条件后派生出它是某类或它的某属性为某值的结论。读完你会掌握derived_facts为什么被拓宽、派生归类为何落在内建is_a谓词上、规则表与条件表的结构化存储形态、求值器第二趟的语义以及从建表到验收的完整落地路径。从录井报告说起一个读得懂数据的规则无处安放决策 0021 由 issue #277 提出场景是油气行业的泥浆录井mud-logging一口井的全烃total hydrocarbon读数超过阈值并且解释类别是气测异常用户就希望这口井被标记为含气井GasBearingWell。两个数值都已作为带日期的属性事实dated attribute facts入库且附着来源段落。问题不在数据而在规则本身没有容身之处推理引擎决策 0002只编译本体公理transitive、symmetric、inverseOf、subPropertyOf派生只跑在实体—实体的边上字面值与阈值的比较无法表达成公理这口井是含气井无法作为带前提的派生事实落库。于是需要一种新机制人写的规则读一个实体自己的属性事实得出一个派生结论。这条记录定义了它的全部边界。既有资产与两处缺口哪些能复用哪些拦路三件可直接复用的机器fact_derivations证明链0002 已经建立了派生事实 → 前提事实的有序链条。规则结论要的正是这个井是含气井因为这两条读数。物化节奏materialisation cadencematerialize_inferences开关、inference_interval_minutes默认 60 分钟、前提撤回即失效的无效化invalidate通道——都是规则无关的业务规则复用同一套开关。断言优先于派生的优先级派生行永不覆盖断言行只想读事实真值的查询过滤derived_by_rule IS NULL或跳过derived_facts的并集。两处拦路的缺口derived_facts比facts窄。facts的宾语可以是实体对象也可以是字面值CHECK (object_id IS NOT NULL OR object_value IS NOT NULL)而derived_facts.object_id和predicate_id当时都是NOT NULL。这意味着派生永远是实体—实体边。#277 的两种结论都不是边派生归类Well→GasBearingWell是一个类派生属性gas_potential good是一个字面值。rules表只装公理不装条件。它的形状是(predicate_id, kind ∈ {transitive, symmetric})一个谓词、一种封闭的公理种类没有放比较表达式的地方。四项设计决策决策 1拓宽derived_facts以匹配facts而不是另建平行表把object_id改为可空新增object_value JSONB并复制facts的检查约束object_id IS NOT NULL OR object_value IS NOT NULL。这样派生属性gas_potential good就是一条字面值派生态下游一切路径——证明链、无效化、物化对账、图上画成派生、derived_by_rule优先级——都无需改动因为它们认的是这一行在derived_facts里而不是它的宾语是实体。备选方案是建derived_typings表再加属性拓宽这会给派生阅读方增加两种新形状而地基里已有一个通用形状facts规则结论只是它的特例。0021 明确选择了让机制移动而不是在机制旁边再开一条半成品平行路径。迁移脚本 0028_a_rule_reads_attributes.sql 完整呈现了这次拓宽其中有一个极易遗漏的细节——同一性索引的重建-- 旧索引按 (kb, 主, 谓, 宾, 起, 止) 认还是那一条 -- 而字面值结论的 object_id 是 NULL。 -- Postgres 默认把 NULL 视作互不相同于是同一条结论每跑一轮都能再插一行。 DROP INDEX derived_facts_identity_idx; CREATE UNIQUE INDEX derived_facts_identity_idx ON derived_facts (kb_id, subject_id, predicate_id, object_id, object_value, valid_from, valid_to) NULLS NOT DISTINCT WHERE invalidated_at IS NULL;不重建这个索引物化对账步骤每轮都会把同一条字面值结论误判为新插入重复行随轮次线性增长。决策 2派生归类是内建is_a谓词上的派生属性事实Well→GasBearingWell存储为一条派生事实谓词是内建is_aobject_value指名结论类按 IRI 存储因此类标签被编辑后依然有效参见 0009-no-type-is-a-type。它不写entities.type_id该列保存断言类型规则结论是派生的位于它之下0015-recording-a-sentence-is-not-asserting-a-fact。实体保留断言的Well图和面板把GasBearingWell显示为派生叠加层规则停止触发时叠加层消失。这是决策 1 值得付出的代价的原因有了字面值派生事实派生归类不再需要第二个概念只需要一个保留谓词。存储层中 business_rules.rs 的ensure_is_a展示了这个保留谓词的按需创建策略第一个写归类规则的知识库才建is_a从不写规则的知识库不会多出一个看不懂的谓词与 #231 给metric/dimension的选择一致。决策 3规则存于新的attribute_rules表由人编写模型永不提议与公理同一条治理线0002推理判据是写下来的不是猜出来的。规则行命名主体类subject class规则只作用于该类及其子类的实体结论归类一个类 IRI或派生属性属性谓词 值条件合取每个条件是(attribute_predicate, op, operand)其中op属于 in presentoperand 是一个数字、一个数字区间或一组类别字符串。条件以结构化形式存储不是自由文本——写下来的判据要能被读、被校验、被界面原样画出来。规则在本体工作台ontology workbench上编写或从文件导入。明确排除跨实体的算术、聚合、跨实体属性的析取。一条规则 一个实体、它自己的属性、一个结论。通用规则语言继续被排除理由与 0002 相同。迁移脚本中的attribute_rules与attribute_rule_conditions两表给出了确切的 DDL 形状CREATE TABLE attribute_rules ( id UUID PRIMARY KEY, kb_id UUID NOT NULL REFERENCES knowledge_bases(id) ON DELETE CASCADE, name TEXT NOT NULL, description TEXT NOT NULL DEFAULT , subject_type_id UUID NOT NULL REFERENCES entity_types(id) ON DELETE CASCADE, conclusion TEXT NOT NULL CHECK (conclusion IN (typing, attribute)), conclude_type_id UUID REFERENCES entity_types(id) ON DELETE CASCADE, conclude_predicate_id UUID REFERENCES relation_types(id) ON DELETE CASCADE, conclude_value JSONB, enabled BOOLEAN NOT NULL DEFAULT TRUE, ... CONSTRAINT attribute_rule_conclusion_shape CHECK ( (conclusion typing AND conclude_type_id IS NOT NULL AND conclude_predicate_id IS NULL AND conclude_value IS NULL) OR (conclusion attribute AND conclude_type_id IS NULL AND conclude_predicate_id IS NOT NULL AND conclude_value IS NOT NULL) ), UNIQUE (kb_id, name) );值得注意的工程细节结论三格互相定义CHECK约束挡住填串了的半截状态更新结论时三格整组替换见 business_rules.rs 的updateCOALESCE无法做到显式清空故用CASE WHEN分支enabled开关关掉不等于删除。关闭的规则下一轮不产出已产出的结论按前提消失的老路径失效attribute_rule_conditions的CHECKpresent不带操作数其余操作符必须带操作数规则与派生行通过derived_facts.attribute_rule_id关联derived_facts.rule_id公理派生与attribute_rule_id业务规则派生恰有一个非空derived_one_rule约束。决策 4有效性是前提区间的交集一口井有 2023 年的一条读数触发规则和 2025 年的一条读数不触发那么它在 2023 区间上是含气井、在 2025 区间上不是——这是跨两次求值的两段区间而不是一行翻来覆去的状态。结论的valid_from取前提中最晚的valid_fromvalid_to取前提中最早的valid_to交集为空则什么都不推。精度跟随较粗的前提沿用facts表的(date, precision)不变量。这是整个机制里唯一的新时间逻辑其余全部复用既有派生事实生命周期。求值器源码中的单测two_readings_give_two_intervals和premises_that_never_overlapped_fire_nothing正是这一语义的验证同属性的两次读数各自成立 → 两段区间两条前提从未在时间上重叠 → 零命中。求值器第二趟而非derive()的扩展derive()位于utopia-reason走TimedEdge——实体—实体三元组——在公理集下做闭包。属性事实带字面值永远不会进入它也不应该进入对阈值的比较是不同于沿传递边走的另一种操作。业务规则这一趟是同 crate 中的独立函数crates/utopia-reason/src/rules.rs对范围内每个实体加载其属性事实逐条求值规则的合取产出携带满足前提和交集区间的Derived。它在同一个物化任务中、在derive()之后运行因此规则可以得出结论类型而后续公理趟从不消费它公理在边上类型是属性——该顺序按构造免于循环。这一限制——结论是类型或属性绝不是边——是决策 3 的 op 集合在做双重职责。Op 与操作数rules.rs中的精确形状求值器把条件编译为强类型枚举避免在求值热路径上反复解析 JSONrules.rsop含义operand 形状gt/gte大于 / 大于等于数字lt/lte小于 / 小于等于数字between闭区间[lo, hi]两个数字in属于集合逐字匹配字符串数组not_in不属于集合字符串数组present该属性有记录无注not_in与或分组是后续 0029-a-rule-may-say-or-once 加入的演进between也在此后补齐。当前仓库的Op枚举即上表全量。比较语义中几个值得写进运维手册的行为字符串里的数字也认抽取把12.3存成字符串是常有的事num()会把数字字符串与布尔转成数值参与比较——否则阈值规则会因引号而静默失效这是最难发现的那类失效类型不对就是不满足不是报错一个本该是数字的属性被抽成了十二点三规则在该实体上不成立而不是让整轮物化失败present判的是一条存在的事实not_in同样只在有一条读数时才算成立——压根没有这个属性是另一回事开放世界假设下缺失 ≠ 不是空条件集永不命中空合取逻辑上恒真会把整个类都归进去那是最坏的规则还没写完的失败方式入口校验直接拒绝空条件见 business_rules.rs 的create。组合展开与上限MAX_COMBOS 64合取语义是每个条件各挑出满足它的事实再在所有组合上求区间交集一口井的同一项读数报过三次、三个条件就是 27 种组合。组合数是各条件命中集大小的乘积MAX_COMBOS 64封顶。展开不完必须报出来RuleReport.capped因为少推了几条与这个实体不满足在结果里长得一模一样。a_capped_expansion_is_remembered测试进一步验证capped_at_last_run会落在规则行上读数减回来时归零绝不单调累积成吓人的假话。修订注记顺序安全 → 有限性论证0021 原始论证是规则趟安全因为它只在derive()之后跑一次且不结论任何公理可消费的东西。这条论证后来一半退役0030 已让规则趟成为最多MAX_DEPTH轮的定点fixed point安全的来源是可派生空间有限而非顺序无环0047-a-rule-may-conclude-a-relation 进一步提议让规则结论边并重新进入下一轮derive()。始终保持不变的是这句话阈值比较与传递闭包是两种不同的推理器0047 用它们共享的池耦合二者而不是合并成一个。存储、API 与审计规则如何进出系统存储层utopia-store/src/business_rules.rscreate/update/delete/list/matches五个入口list附带此刻凭它成立的结论条数derived_count与上次运行的capped_at_last_runmatches回答这条规则此刻标了哪些实体——卡片上的数字点开就是这份列表且前提一并返回凭哪几条读数与结论本身同样是答案的一半见 business_rules.rs 的matches条件更新是整组替换而非逐条增删——条件是一个合取整体替换比对着 seq 打补丁好读也没有改到一半的中间状态删除规则时其派生行随ON DELETE CASCADE一起走规则没了凭它得出的结论就没有依据了留着无从解释。API 层utopia-server/src/api/rule_routes.rslist/create/update/delete为 REST 接口写规则要求 Editor 角色rule_routes.rs 注释直言它是本体的一部分——一条规则改一次全库结论跟着变与改一条公理同一量级每个写操作都写审计行rule.created/rule.updated/rule.deleted特别地run_now端点让作者不等下一个物化周期默认 60 分钟立即看结果走的是同一个materialize——预览与正式是同一条路不另写一份会漂移的逻辑。MCP只读暴露写不暴露决策 0021 明确读取已落地——list_rules和rule_matches通过 MCP 暴露entity_facts返回标注了由哪条规则得出的结论Agent 因此可以按准则解释一次分类而不是用自己猜的阈值从读数重新推导。写作刻意不暴露0002 画下的线是反对模型发明判据而人向自己的 Agent 口述规则并非这条线禁止的事——但一次工具调用无法区分两者审计无论哪种情况都记在人的 token 名下。此外规则比事实重得多一条错误的规则会在每次物化时悄悄重判整个知识库。若日后开放写它需要一个形如pending_facts的待决队列让人点头后规则才生效。MCP 的只读工具清单见 mcp.rs 的EXPOSED数组。数据库级验证a_rule_concludes_a_type.rs钉住的四件事纯逻辑求值层的单测在utopia-reason::rules内、不依赖数据库a_rule_concludes_a_type.rs 则钉住求值层看不见的落库行为命中真的落进derived_facts的字面值通道且挂着attribute_rule_idobject_id为 NULL、object_value是{class: gas_well}无 IRI 时退回 key记的是类而不是标签前提链进fact_derivations两条前提按seq记录回答这口井凭哪两条读数重跑不产生第二行同一性索引把 NULL 宾语认成同一条NULLS NOT DISTINCTreport.inserted 0且report.invalidated 0阈值抬高后重跑旧结论作废而不是删除invalidated_at被标记记录轴上留着我们曾据此推出。同文件还验证了规则结论不写entities.type_id断言类型始终是WellGasBearingWell只作为派生存在且落在内建is_a上把结论从推一个类改成推一个属性值时旧结论作废而非与新结论并存禁用规则等同于前提消失——下一轮结论退场而规则行还在。实施阶段PhasingSchema拓宽derived_facts决策 1、内建is_a谓词决策 2、attribute_rules及其条件行决策 3。按领域文件规则一个迁移主分支后按迁移策略折叠。声明Declarationattribute_rules的存储/读取以及本体工作台编写规则的界面主体类、条件、结论。文件导入随后。求值Evaluationutopia-reason的第二趟接入物化任务区间交集前提撤回即失效直接复用。解释Explanation实体面板显示规则与每条前提事实回指其来源段落图把派生归类画成派生。验收Acceptance#277 样例端到端定义两个属性与规则 → 上传报告 → 井以GasBearingWell出现两条读数作为其解释把阈值抬到读数之上 → 下一轮清除区间与报告日期一致。run_now端点与图上派生叠加层即验收路径的产物——作者写规则后立即触发物化在实体面板上核对结论与前提。死路Dead ends两条明确不走的路线从规则写entities.type_id这会把派生结论放进断言类型居住的地方前提撤回时就不得不从派生重构地面真值被 0015 的界线禁止。叠加层overlay避免了它。通用规则 DSL0002 对公理已经走过这条路并折返#277 明确范围是一个实体自己的属性。DSL 会为没人要的通用性而造并重新打开模型写判据的门。未决问题Open questions派生归类要不要喂给抽取 prompt 或映射探针它们读本体的类一口派生为GasBearingWell的井并未被断言为含气井。倾向不——派生是读取时的叠加层不是本体教回抽取的事实——但规则结论的类随后被语料强化是一个值得盯住的循环。类别条件与语言interpretation_category ∈ {气测异常, 气测异常后效}是逐字匹配。同一类别若从另一来源以英文到达集合会漏掉。此问题超出 0021 范围类别词表归属映射层0011。每条规则一个结论还是多个#277 说一个。同一份报告若同时要定一个类型和一个gas_potential等级今天得写两条共享前提的规则这是否构成麻烦由样例回答。Agent 是否该能写规则读取已落地写被刻意排除若要开放需要pending_facts形状的待决队列。规则分类实体的画布标记结论是对单个实体的判断而非连接所以不画边今天只在面板可见断言属性也没有标记只为派生加一个会颠倒地基。真正的缺口——哪些实体被这条规则标记——已由rule_matches回答。规则的导出形态若部署的规则是其本体的一部分RDF 导出#308必须说明规则如何表达——规则不是 OWL 公理。推迟到导出落地时。后续演进脉络0021 是 Utopia 规则体系的第一块基石后续决策沿同一条治理线演进值得顺藤摸瓜0029-a-rule-may-say-or-once条件分或组group_seq迁移 0039组内与、组间或一层不嵌套——因为一次命中要带回使它成立的读数而析取没有自己的前提0030-a-rule-may-read-what-a-rule-concluded规则可读规则结论一趟内存定点证明树化0032-a-rule-computes-what-it-concludes结论与门槛可以是属性上的四则表达式树add/sub/mul/div深度上限MAX_EXPR_DEPTH 4迁移 0041选出来的不是敲出来的聚合仍被拒绝0047-a-rule-may-conclude-a-relation让规则结论边的提议。attribute_rules作为唯一一类人写、机器算、可解释的推理判据与公理编译器共同构成 Utopia 的两个推理器、一个物化任务格局——完整现状可对照 docs/design/rules.md 的规则领域设计页阅读。赞分享后端前端人工智能RAG知识图谱知识管理搜索引擎【免费下载链接】utopiaWorlds first open-source enterprise world model.项目地址https://gitcode.com/gh_mirrors/ont/utopia点击查看免费下载相关推荐Utopia 规则引擎之计算型结论用表达式树让规则真正算出它断言的值Utopia 规则引擎之计算型结论用表达式树让规则真正算出它断言的值 导读 本文围绕 Utopia 项目开源企业级世界模型中的技术决策记录 0032后端前端人工智能RAG知识图谱知识管理搜索引擎PredictionIO 分类引擎自定义属性读取实战从默认四属性迁移到 featureA~featureD 与自定义实体类型PredictionIO 分类引擎自定义属性读取实战从默认四属性迁移到 featureA~featureD 与自定义实体类型 PredictionIO 的 S机器学习后端推荐系统Ruff 类型检查中的 invalid-attribute-access 规则类/实例属性赋值与泛型实例属性的访问校验Ruff 类型检查中的 invalid attribute access 规则类/实例属性赋值与泛型实例属性的访问校验 invalid attribute a开发工具Lint格式化静态分析CLI上一篇Agentic Machine Learning Systems以“托管轨迹”为单位的智能体系统架构CS249r 第三卷全解析下一篇PaddleFormers/PaddleHub 数据集 API 全解析从 CV、NLP 到 Audio 的八大数据集使用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考