设计一套企业语义基座,最先要定下来的是这套东西凭什么算做成了,而技术选型要排在后面。多数团队把这句话写成让模型更懂企业的数据,写下去很顺,麻烦却在后面。验收标准绑在模型身上,模型一换代,去年那份验收报告也就没人认了。
换个写法,是把做成的标准定在判断能不能复算上。同一批证据递出去,不管接的是哪个模型,它看到的都是同一批;结论出来以后,指得回是哪几条事实支撑的,谁定的、依据什么、什么时候失效、被哪条顶掉,都查得到。这样的系统换模型只是换一个零件,而验收标准绑在模型上的系统,每换一次模型,企业的规矩就得重新讲一遍。
这其实是责任问题。模型给出的是归纳,归纳本身没有记忆,也没有义务;能追到依据的结论才有责任人。可复算要保的不是准确率,是结论背后那条可以复查的路径。
01基座承的是哪一层
企业里跑着几十套系统,每一套都自己把同一件事定义一遍。ERP 里的客户是一个结算主体,CRM 里的客户是一个联系人和一串跟进记录,报表里的客户是编号加名称。三处都叫客户,指的范围不一样,谁也不算错,因为各自只对自己那一段负责。
这种分散以前不算大问题,因为汇总是人做的。人会看见两份报表对不上,会去问哪边算错了,会自己判断这一次该信哪一份。麻烦在于这些定义散在几十套系统的配置里,改一个格子不需要谁批准,也没有一处记着是谁改的。
数据中台解决的是另一件事,把数据搬到一起。搬完之后客户还是三个客户,只是躺在同一张表里。搬不动的是认定:同一个词到底指哪个范围,这件事没有一个地方安放。
基座承的就是这一层。它横在系统中间,形态很朴素,一个进程、一个端口、一份库,不占任何一段业务流程,也不替哪套系统做主。它存三样东西:企业有哪些概念、概念之间怎么连;一条条具体的认定是什么、谁定的、什么时候管用;以及把认定按问题组装成一份可读材料的那套办法。
前两样是本体和记忆。本体是语言,说清有哪些词、词和词怎么连、哪些结论能从已有事实推出来;记忆是内容,一条条带时间、带来源、带属主的认定。只有本体没有记忆,是一本没人填过的词典;只有记忆没有本体,是一堆没名字的记录,谁都能照自己的叫法读。第三样是装配,可复算真正落在这里。
这套东西跟主数据不是一回事。主数据管的是应该是什么,维护一份黄金记录,各处照它对齐;基座管的是凭什么算这个,一条认定是谁提的、靠哪条事实、被谁替掉。前者要一个正确答案,后者要每条答案都有出处。企业里争得最厉害的那些事,谁都有答案,缺的是那个有资格定的人。
02为什么现在才要紧
答题的人换了。以前两份报表口径不一样,人对一眼能发现,会去查是哪边算错;现在把问题交给模型,它会把两边的材料合起来,给一个读起来完整、口气确定的答案。错的地方不会显示成空白或者冲突,而是被写得像结论。口径不统一的代价,从看得见的差异,变成看不见的错误。
03不可复算从哪来
它很少发生在查询这一侧。查询慢,人是有感觉的;更容易出问题的是把证据递到模型面前那一步,证据错了不会报错。
根子在版本没有收敛。同一个属性会留下很多条记录,改过的、作废的、被替代的,全都在库里,这本身是对的,历史不该丢。但装配时把这些记录平铺着递上去,模型看到的就是几十个并列的值,权重一样,编号连着,没有一条注明自己是当前值。它只能猜。这种并排在设计上有名字,叫竞争值。伤人的是同一件事的几个版本同时在场,跟上下文长短关系不大,读得多不等于选得对;几个互相矛盾的版本摆在一起,是逼它做一次没有依据的选择,而且它不会告诉你这次没有依据。
再往下是结构上的空缺。旧值标了作废,也记下了被谁替代,可取数那一侧不认这个标记,把有效和作废一起捞了回来;作废语句的更新条件只认主体和属性,没带隔离键,两家租户共用一个客户编号时,一家写新值,另一家的当前值跟着没了;判定只存结论,没存靠哪几条事实,那些事实作废以后推出来的东西还活着;注册入口不查调用者,父级留空就拿到全部权限。四处合起来,整套结构里没有一处要求判断必须追得到依据。
管理侧的情况也差不多。买软件的时候合同把功能和工期写得很清楚,就是不写它按谁的口径说话。认定权是跟着软件一起进门的。
04三条约束
这些落到设计上,是三条约束。
第一条,给认定留一个写入口。一条认定是谁提的、依据哪条事实、管多大范围、被哪条替掉,四件事记在一处。没有它,追溯就无从谈起,因为不知道要追的是谁。
第二条,历史只往后加,不覆盖。一条事实带两个时间,写进来的时间和业务上生效的时间。只有前者,能回答这条什么时候录的;只有后者,能回答这条什么时候管用;要回答当时认定的是什么,两个都得有。被替掉的记录不删,标上被谁替掉,否则无法还原那一刻的视图。
第三条最容易被跳过,它要求每一层都留一句能被证伪的话,说清这层坏了长什么样、用什么办法证明它没坏。写不出这句话,说明这一层还只是个框架,没落到可以验收的地方。
05基座内部要定的事
这几件事不是模块划分,是一条因果链:没有词表,类型无从附着;没有类型,规则无从判断;没有事实和状态,装配无从收敛;没有收敛,查出来的东西没法复核。顺序换一处,后面的全部落空。
最先是词表,登记不拒写,没登记的进待办日志。治理得先有对象:系统如果拒写,业务不会停下来,会在系统外面另找办法,记在表格里、备注里、聊天记录里,那些地方治理看不见也补不回来。
类型这一层要在分类器和规则化之间选。分类器能推出隐含的父类,代价是要一个独立进程,推理的时机不好控;而它推出的父类在类层次本来很浅的企业里几乎没有新信息,父类多是人写死的。背一个重依赖换回用不上的东西,所以走规则化,把推理变成能落到关系库上的规则前向链。规则集还要收得小,推错比推漏危险,错的结论看起来和真的一样。
事实这一层,两处非得这样:两个时间都得有;核心事实只允许属主直写,其余走提议,认定权要落到具体一方,否则谁都能改。形状约束只检查不拦写,不合规的记录得让人看得见,拦写会把脏数据推到看不见的地方,看得见的还能治。时间语义只做到一半,纯计数再带时间窗得退回事实表取近似。
装配是可复算真正落地的地方。全系统只留一个函数,段序不许改,每条证据挂引用编号,被排除的写明原因,整包按预算卡住,算哈希前先剔掉易变字段。定这么细只为一件事,两次装配出来的东西要逐字节相同;不相同,同一个问题问两遍答案不一样,复查就没有意义。
改动落在取数那一步。同一个属性按有效最新值折叠,作废的进排除清单,其余标成竞争值,一个属性在包里只剩一条当前值。包短下来是顺带的,要紧的是把选择权拿回来:不折叠,模型得自己从几十个版本里挑一个,这次挑选没有任何依据可以检查;折叠之后挑哪个由库里的规则决定,规则错了能改,模型猜错了只能重问。这里有两处代价都没解决:中文按字符折算跟真实分词有差距,预算只是名义上成立;外部记忆的命中如果只作提示、不进哈希,两次召回的排序会一致,代价是检索层等于白接。
查询这一层是把模型的输出空间收窄。中间表示是一份结构固定的表达式,只表达选择、过滤、分组和声明式连接。让它写自由 SQL,等于让它在无限大的空间里犯错,错法无穷,验法也无穷;收窄成有限几种形状,每种都能单独验完。口径的差异就藏在这样的地方,两条指标写法不同,人工看以为等价,真跑起来差在计数起点和类型过滤上;看起来一样并不等于等价,差别要靠跑才看得出来。
回答交出去之前,得有人看一眼。在这之前系统只管输入,回答回来没人管。校验纯只读,只留两类阻断,编造数字和引用不存在的编号,其余一律提醒,因为误伤比漏检贵,一条动不动就拦的校验会被人关掉,关掉之后什么都不查。这里和词表处境相反:词表宁可放宽,漏进来的还能治;校验宁可提醒,拦错的会让人放弃整道门。
06门与边界
门全绿却漏掉要紧的失效,问题出在门本身:清单跟着模块写,没跟着失效写。模块一个个都过了,跨模块的失效没有一条门在管。作废了不失效、跨租户误作废、注册不收权,三件事都落在接缝上,接缝不属于任何一个模块,所以没有人为它写门。失败的样子比成功的样子难想,跳过它的代价往往要等到出事才结算。
另外三件事不做:不做分类器,不做解码期约束,不做词表与能力面的自动上线。前两件越界,第三件把责任和归因一起交出去了。
这套东西收拢的是一处认定,不是把各家软件塞进同一个壳;它不接管任何一段业务流程,也不要求各家系统改成同一个样子。能改代码的直接连进来,改不了的老系统和外购软件走同步或者影子模式,在它那一侧补上认定,不要求它配合改造。
07生态:把认定从软件里拿出来
过去几十年,企业软件的卖法是把认定权和功能绑在一起。买一套系统,等于接受它那套口径:它叫客户的是什么,逾期从哪天算,库存在哪一刻。厂商越多,口径越多,对不上的数也越多。想把口径统一,常用的两条路,一条是上一套更大的系统把小的吞掉,一条是上中台把数据搬到一起。前者换代成本极高,等于把认定权交给一个更大的厂商;后者搬完,口径还留在原处。
基座是第三条路。认定从软件里抽出来,做成企业自己的一层;软件退回执行件的位置,可以换。换一套 CRM,客户还是同一个客户;换一套排产,逾期还是从同一天算起。软件的采购、替换、退出,不再等于企业重新定义一遍自己。
这条路光有技术不成立。技术只能把门造出来,走不走这道门靠三处制度配合。合同里写接入要求,验收要交一份一致性套件的运行报告,不通过就算没交付,靠的是甲方签字的那支笔,架构图上画多少箭头都代替不了。系统接进来能读本体和记忆,问一句这个客户还有哪些合同在跑,答得出来;不接的只能看见自己那一摊,业务部门自己会来催。判定和动作进一本可以封存的账,出合规证明时拿不出回放链的过不了这一关。
三样都属于制度安排,没有一样能靠技术组件实现。可复算之所以是制度属性,是因为它要的不是某个组件更强,而是每一方都愿意把自己的认定交出来受检查。
可复算管得住怎么改,管不住谁有权改。哈希链能给出程序,给不出权力来源。代码挡得住偷偷改,挡不住权力归属上的空缺。

