一家做工业品的公司,销售在客户系统里查一家老客户,屏幕上跳出三条记录。一条躺在十年前的进销存里,一条在五年前上的客户关系系统里,一条在去年做的报价小程序后台。三条记录写的是同一家企业,公司名却各写各的:一条是全称,一条少了“股份”两个字,一条只剩个简称。销售看一眼,手就停在键盘上。再往下翻,三套折扣政策,三个年度采购额。老板问一句这家客户去年到底做了多少,要三个人各查一遍,查完坐下来对。对不拢的那部分,谁也说不清该信谁。老板要的只是一个数。一个数要三个人坐下来对,同一个客户怎么会有三个去年,这笔账该记在谁头上,得换个地方问起。 PART 01这笔账不在许可证上 遇到这种场面,账很容易算到软件头上。买多了,买重了,下回多问几家供应商,压一压价,就算有了交代。企业软件这几十年的采购单,就是这么一张张签下来的。这样算账有个来历。软件一直被当成一件件买回来的东西,是东西就能比价、能替换、能折旧;买重了算采购的眼光,不算结构的毛病。真正的浪费不在许可证上。同一家企业、同一个产品、同一个口径,被各自维护了三遍。换系统的时候这笔账最疼。上一套拆掉,历史数据要迁,字段对不上,迁完还得人工核三个月,核完抬头一看,新系统自己又带了一份地基。把应用推倒重来,多半会失败。旧的三张客户表拆干净了,新系统照样自带一套根,两年之后,桌上又是三张表。变的只是机房,和供应商的名字。问题从来不在买了几套软件,在同一件事被定义了几遍。往下要说的,是怎么让它只定义一遍。 PART 02让同一件事只定义一遍 把三套系统用接口连起来,能让它们互相取数,取出来的还是各自那一份客户。连得通,不等于只定义一遍。买回来的软件从验收那天起就在折旧,根不会。企业软件卖了几十年的成品,成品越换越新,地基却每换一次重新浇一遍。要让同一件事只定义一遍,就得把全公司共用的那部分沉到底下自己留着,不随任何一套应用走。顺序因此跟直觉反着来:先补根,再让应用往上接,应用可以换,根和历史不动。对甲方来说,最直接的好处是换应用不换根,选型时不必再被一家供应商锁死,换谁上都还能接回来。这里说的层,是软件资产的层,不是公司的事业部,也不是谁向谁汇报。这种结构性重复,用一棵树来说最省事:根、干、枝,越往下越沉,越往上越轻。判断一个东西该放哪一层,只看一条:换一家公司就得改的放在枝上,换一家只改配置的放在干上,谁都不用改的放在根上。 PART 03根、干、枝上,各放什么 根是这家企业认得的全部对象,客户、产品、供应商、项目、人。对象之间的关系也在根上,谁供谁、谁签谁、谁控股谁。对象身上被反复引用的数字也在根上,采购额、回款周期、毛利率。进了根的东西只有一份。应用点开客户,看见的都是同一个客户。一个对象要进根,先得有身份证。名字对得上的直接挂上本体,碰上同名多候选,机器不敢认,留给人来点头。根上还有一层记忆。它不存聊天记录,只存结论:这家客户为什么会丢,这个报价为什么被压。结论是会变的。去年判断这家客户只看价格,今年发现真正卡住的是交付周期。旧结论不能删,要留一个失效时刻,查询默认给当下有效的那一条,翻历史才看得到变更发生在哪天。少了这个时刻,记忆就是一堆自相矛盾的话,越用越不敢信,最后没人查它。记忆还有预算,一次召回只带固定额度的条目,用不上的要能淡出。不然上下文越滚越长,模型反而看漏最要紧的那条。 同一个数,凭什么有三个答案?口径也在根上,这一块最得罪人。采购额按合同额算、按开票额算、按回款算,三套算法能差出一倍。底座的做法是把口径先定义再取数,没定义的查询直接拒绝。口径从来不是算术问题,是定义权归谁。财务和销售各自都觉得自己那套是对的。财务把三张报表打出来摊在桌上,和销售对了一下午,最后发现差的是一张过期合同没关账。被拒绝过几次之后,两边才开始用同一个数说话。根厚不厚,不看文件多、代码多,看同一件事是不是只在一个地方定义,别处只能引用。干是规矩:谁能看、谁能改、谁能批,改动留不留痕,时间按哪个时区算,一条能力归谁管。一条能力上线前要先声明它落在哪个业务包、读哪些表、写哪些表;往后有人把它删掉,系统启动就报错,因为还有调用方在等它。删除不报错,是最难查的一类故障。接口在,返回空,页面不报错,人以为本来就没数据,查三天才发现是上游删了东西。时间也是干上的事。国内客户的账按北京时间算,听着是常识,做起来是全仓改动:取时间的代码都得换,存量时间戳也得跟着平移。同一套底座要服务多家客户,数据不许串,每个查询强制带上租户条件,写漏一处就是事故。枝是应用,获客、舆情、人力、培训,各有各的业务。枝上只写这家公司特有的东西:线索怎么判重,商机怎么分阶段,跟进纪律是三天还是七天。 PART 04AI原生,不只是一个对话框 这套底座还挂着“AI原生”四个字。这个词被用得很松,界面上加一个对话框就叫原生。什么样的才叫原生?能写成规则的不交给模型。判得了的,规则当场就定;规则说不清的,才轮到模型。一条命令是装依赖还是删数据,一句话是查询还是要对外发布,分界就画在这里。这样分工的原因很实际:规则给的是确定答案,模型给的是概率,还得等它算完。把确定性的事交给概率模型,等于给自己加一层不确定。每一次自动判定都要记账,判了什么、依据哪条、走的是规则还是模型、模型给的概率是多少,事后能一条条翻。没这本账,出了事只能猜,事后复盘全靠各说各话。模型得有自己的记忆,而且记忆会过期。否则同一家客户问十遍,十遍答得不一样,人就不敢用第二次。能力要能被机器发现。系统里得有一张能力清单,每条能力都有名字、有参数、有归属,模型查得到这张表才可能调对。查不到只能猜,猜错了还没人知道,这是AI功能在真实业务里悄悄失效的共同原因。模型读到的上下文全在根上。根要是裂的,模型只能各读各的,同一个问题答出两个版本,还都说得通。界面是最便宜的那一层,也是最容易装出来给人看的那一层。PART 05获客:把跑着的系统接回根上 获客飞轮照这个办法接:不是另起一套,是把一套已经在跑的系统接到现成的根和干上,边接边改,不停机。接客户与产品这件事排在最前。线索进来先问本体认不认得这家企业,名字完全一致的直接挂上,拿不准的进待确认队列,等人点头。以前每个系统各写一套模糊匹配,规则散在代码里,谁也不知道另一套是怎么判的。现在匹配只有一份,挂错了改一处,所有应用同时改。运营在后台点一次确认,三个应用同时看到结果。跟进纪律同样接在根上。哪条线索认领后三天没触达,哪个商机两周没推进,依据来自同一份事实表,不来自各系统的私有状态。人换了、系统换了,纪律还是那条纪律,这一条比任何界面都值钱。指标也从口径层取。周报里那个本月新增商机金额,取的是口径层定义好的算式,不是页面里临时拼出来的。口径要改就升版本,旧报表还能对上旧版本,不然历史数据永远说不清,年底审计时又得吵一遍。接的时候新增的,只有业务表和规则:线索、商机、跟进、报价,加上什么阶段该做什么、什么情况该告警。这些是这家公司特有的,换一家就得改,所以它们归枝管。报价单模板也在枝上,客户授信额度在根上。那是这家企业对所有客户统一的一套规矩。怎么算接完,看能力对齐。原系统有多少个入口、多少个功能组,接过来一条条对上,少了哪条写清为什么不做了。对齐用的是台账,不是口头承诺。每次改完代码还会自动跑一批检查,红了不许提交:行数超出预算、表名撞了数据库保留字、时间写成了别的时区,都在里面拦。人被拦住会烦,但被拦住一次,比上线后查三天便宜得多。 PART 06舆情,材料从外面来 获客那边,线索从自家系统进来,名字跟本体对得上就能挂。舆情的材料从外面来。那家做工业品的公司,在公开源里的名字有七八种写法:简称、全称、英文名、旧商标。一条消息抓回来,先过本体这一关。认出说的是不是它,才谈得上判重,才算进这家企业的声量。这一步不靠模型。认主体靠的是根里那一份客户,跟销售在客户系统里点开的是同一个。声量怎么算,情感怎么判,事件窗口从哪天到哪天,不在舆情里另定一套,都归口径层管。获客周报里的金额,也是从那里取的。获客面对的是自家录进去的数据,舆情面对的是别人写出来的话,脏得多。要新写的是采集回来之后那一层判断:这条是真是假,是新的还是旧的,是不是同一件事被十家媒体转了一遍。 PART 07还没补完的地方 根上的缺口摆出来,比藏着有用。本体的覆盖还没到全部业务对象,新系统接进来,对象还没进本体;口径定义只覆盖报表里用到的那些,业务系统内部临时算的还管不住;能力对齐靠人一条条核,还没有自动比对;改一个类会牵连多少事实、多少映射,能算,但还没接到开工流程里。知道缺口在哪,比宣称已经做完有用。宣称做完最省事,也最贵,代价都在第二年。一棵树能不能立住,不看枝条多茂盛,看根记不记账。记不住对象、记不住关系、记不住口径,枝叶再密,风一来就散。开头那位销售要查的,从来不是三套系统,是同一家客户的一个数。这个数对不对得上,不取决于买了几套软件,取决于同一件事在这家企业里被定义了几遍。应用共用一份会记账的根,同一个数才不会有三个答案。