規(guī)則引擎Drools在貸后催收業(yè)務(wù)中的應(yīng)用
在日常業(yè)務(wù)開發(fā)工作中我們經(jīng)常會遇到一些根據(jù)業(yè)務(wù)規(guī)則做決策的場景。為了讓開發(fā)人員從大量的規(guī)則代碼的開發(fā)維護(hù)中釋放出來,把規(guī)則的維護(hù)和生成交由業(yè)務(wù)人員,為了達(dá)到這種目的通常我們會使用規(guī)則引擎來幫助我們實(shí)現(xiàn)。
本篇文章主要介紹了規(guī)則引擎的概念以及Kie和Drools的關(guān)系,重點(diǎn)講解了Drools中規(guī)則文件編寫以及匹配算法Rete原理。文章的最后為大家展示了規(guī)則引擎在催收系統(tǒng)中是如何使用的,主要解決的問題等。
一、業(yè)務(wù)背景
1.1 催收業(yè)務(wù)介紹
消費(fèi)貸作為vivo錢包中的重要業(yè)務(wù)板塊當(dāng)出現(xiàn)逾期的案件需要處理時,我們會將案件統(tǒng)計收集后導(dǎo)入到催收系統(tǒng)中,在催收系統(tǒng)中定義了一系列的規(guī)則來幫助業(yè)務(wù)方根據(jù)客戶的逾期程度、風(fēng)險合規(guī)評估、操作成本及收益回報最大原則制定催收策略。例如“分案規(guī)則” 會根據(jù)規(guī)則將不同類型的案件分配到不同的隊列,再通過隊列分配給各個催收崗位和催收員,最終由催收員去進(jìn)行催收。下面我會結(jié)合具體場景進(jìn)行詳細(xì)介紹。
1.2 規(guī)則引擎介紹
1.2.1 問題的引入
案例:根據(jù)上述分案規(guī)則我們列舉了如下的規(guī)則集:
代碼實(shí)現(xiàn):將以上規(guī)則集用代碼實(shí)現(xiàn)
業(yè)務(wù)變化:
- 條件字段和結(jié)果字段可能會增長而且變動頻繁。
- 上面列舉的規(guī)則集只是一類規(guī)則,實(shí)際上在我們系統(tǒng)中還有很多其他種類的規(guī)則集。
- 規(guī)則最好由業(yè)務(wù)人員維護(hù),可以隨時修改,不需要開發(fā)人員介入,更不希望重啟應(yīng)用。
問題產(chǎn)生:
可以看出如果規(guī)則很多或者比較復(fù)雜的場景需要在代碼中寫很多這樣if else的代碼,而且不容易維護(hù)一旦新增條件或者規(guī)則有變更則需要改動很多代碼。
此時我們需要引入規(guī)則引擎來幫助我們將規(guī)則從代碼中分離出去,讓開發(fā)人員從規(guī)則的代碼邏輯中解放出來,把規(guī)則的維護(hù)和設(shè)置交由業(yè)務(wù)人員去管理。
1.2.2 什么是規(guī)則引擎
規(guī)則引擎由推理引擎發(fā)展而來,是一種嵌入在應(yīng)用程序中的組件, 實(shí)現(xiàn)了將業(yè)務(wù)決策從應(yīng)用程序代碼中分離出來,并使用預(yù)定義的語義模塊編寫業(yè)務(wù)決策。
通過接收數(shù)據(jù)輸入解釋業(yè)務(wù)規(guī)則,最終根據(jù)業(yè)務(wù)規(guī)則做出業(yè)務(wù)決策。常用的規(guī)則引擎有:Drools,easyRules等等。本篇我們主要來介紹Drools。
二、Drools
2.1 整體介紹
2.1.1 KIE介紹
在介紹Drools之前我們不得不提到一個概念KIE,KIE(Knowledge Is Everything)是一個綜合性項目,將一些相關(guān)技術(shù)整合到一起,同時也是各個技術(shù)的核心,這里面就包含了今天要講到的Drools。
技術(shù)組成:
- Drools是一個業(yè)務(wù)規(guī)則管理系統(tǒng),具有基于前向鏈和后向鏈推理的規(guī)則引擎,允許快速可靠地評估業(yè)務(wù)規(guī)則和復(fù)雜的事件處理。
- jBPM是一個靈活的業(yè)務(wù)流程管理套件,允許通過描述實(shí)現(xiàn)這些目標(biāo)所需執(zhí)行的步驟來為您的業(yè)務(wù)目標(biāo)建模。
- OptaPlanner是一個約束求解器,可優(yōu)化員工排班、車輛路線、任務(wù)分配和云優(yōu)化等用例。
- UberFire是一個基于 Eclipse 的富客戶端平臺web框架。
2.1.2 Drools介紹
Drools 的基本功能是將傳入的數(shù)據(jù)或事實(shí)與規(guī)則的條件進(jìn)行匹配,并確定是否以及如何執(zhí)行規(guī)則。
Drools的優(yōu)勢:基于Java編寫易于學(xué)習(xí)和掌握,可以通過決策表動態(tài)生成規(guī)則腳本對業(yè)務(wù)人員十分友好。
Drools 使用以下基本組件:
- rule(規(guī)則):用戶定義的業(yè)務(wù)規(guī)則,所有規(guī)則必須至少包含觸發(fā)規(guī)則的條件和規(guī)則規(guī)定的操作。
- Facts(事實(shí)):輸入或更改到 Drools 引擎中的數(shù)據(jù),Drools 引擎匹配規(guī)則條件以執(zhí)行適用規(guī)則。
- production memory(生產(chǎn)內(nèi)存):用于存放規(guī)則的內(nèi)存。
- working memory(工作內(nèi)存):用于存放事實(shí)的內(nèi)存。
- Pattern matcher(匹配器):將規(guī)則庫中的所有規(guī)則與工作內(nèi)存中的fact對象進(jìn)行模式匹配,匹配成功后放入議程中
- Agenda(議程):存放匹配器匹配成功后激活的規(guī)則以準(zhǔn)備執(zhí)行。
當(dāng)用戶在 Drools 中添加或更新規(guī)則相關(guān)信息時,該信息會以一個或多個事實(shí)的形式插入 Drools 引擎的工作內(nèi)存中。Drools 引擎將這些事實(shí)與存儲在生產(chǎn)內(nèi)存中的規(guī)則條件進(jìn)行模式匹配。
當(dāng)滿足規(guī)則條件時,Drools 引擎會激活并在議程中注冊規(guī)則,然后Drools 引擎會按照優(yōu)先級進(jìn)行排序并準(zhǔn)備執(zhí)行。
2.2 規(guī)則(rule)
2.2.1 規(guī)則文件解析
DRL(Drools 規(guī)則語言)是在drl文本文件中定義的業(yè)務(wù)規(guī)則。主要包含:package,import,function,global,query,rule end等,同時Drools也支持Excel文件格式。
function
規(guī)則文件中的方法和我們平時代碼中定義的方法類似,提升規(guī)則邏輯的復(fù)用。
使用案例:
query
DRL 文件中的查詢是在 Drools 引擎的工作內(nèi)存中搜索與 DRL 文件中的規(guī)則相關(guān)的事實(shí)。在 DRL 文件中添加查詢定義,然后在應(yīng)用程序代碼中獲取匹配結(jié)果。查詢搜索一組定義的條件,不需要when或then規(guī)范。
查詢名稱對于 KIE 庫是全局的,因此在項目中的所有其他規(guī)則查詢中必須是唯一的。返回查詢結(jié)果ksession.getQueryResults("name"),其中"name"是查詢名稱。
使用案例:
規(guī)則:
全局變量global
通過 KIE 會話配置在 Drools 引擎的工作內(nèi)存中設(shè)置全局值,在 DRL 文件中的規(guī)則上方聲明全局變量,然后在規(guī)則的操作 ( then) 部分中使用它。
使用案例:
規(guī)則屬性
模式匹配
當(dāng)事實(shí)被插入到工作內(nèi)存中后,規(guī)則引擎會把事實(shí)和規(guī)則庫里的模式進(jìn)行匹配,對于匹配成功的規(guī)則再由 Agenda 執(zhí)行推理算法中規(guī)則的(then)部分。
- when
規(guī)則的“when”部分也稱為規(guī)則的左側(cè) (LHS)包含執(zhí)行操作必須滿足的條件。如果該when部分為空,則默認(rèn)為true。如果規(guī)則條件有多個可以使用(and,or),默認(rèn)連詞是and。如銀行要求貸款申請人年滿21歲,那么規(guī)則的when條件是Applicant(age < 21)
- then
規(guī)則的“then”部分也稱為規(guī)則的右側(cè)(RHS)包含在滿足規(guī)則的條件部分時要執(zhí)行的操作。如銀行要求貸款申請人年滿 21 歲(Applicant( age < 21 ))。不滿足則拒絕貸款setApproved(false)
內(nèi)置方法
Drools主要通過insert、update方法對工作內(nèi)存中的fact數(shù)據(jù)進(jìn)行操作,來達(dá)到控制規(guī)則引擎的目的。
操作完成之后規(guī)則引擎會重新匹配規(guī)則,原來沒有匹配成功的規(guī)則在我們修改完數(shù)據(jù)之后有可能就匹配成功了。
注意:這些方法會導(dǎo)致重新匹配,有可能會導(dǎo)致死循環(huán)問題,在編寫中最好設(shè)置屬性no-loop或者lock-on-active屬性來規(guī)避。
(1)insert:
作用:向工作內(nèi)存中插入fact數(shù)據(jù),并讓相關(guān)規(guī)則重新匹配
(2)update:
作用:修改工作內(nèi)存中fact數(shù)據(jù),并讓相關(guān)規(guī)則重新匹配
比較操作符
2.3 工程引入
2.3.1 配置文件的引入
需要有一個配置文件告訴代碼規(guī)則文件drl在哪里,在drools中這個文件就是kmodule.xml,放置到resources/META-INF目錄下。
說明:kmodule是6.0 之后引入的一種新的配置和約定方法來構(gòu)建 KIE 庫,而不是使用之前的程序化構(gòu)建器方法。
- Kmodule 中可以包含一個到多個 kbase,分別對應(yīng) drl 的規(guī)則文件。
- Kbase是所有應(yīng)用程序知識定義的存儲庫,包含了若干的規(guī)則、流程、方法等。需要一個唯一的name,可以取任意字符串。
KBase的default屬性表示當(dāng)前KBase是不是默認(rèn)的,如果是默認(rèn)的則不用名稱就可以查找到該 KBase,但每個 module 最多只能有一個默認(rèn) KBase。
KBase下面可以有一個或多個 ksession,ksession 的 name 屬性必須設(shè)置,且必須唯一。 - packages為drl文件所在resource目錄下的路徑,多個包用逗號分隔,通常drl規(guī)則文件會放在工程中的resource目錄下。
2.3.2 代碼中的使用
KieServices:可以訪問所有 Kie 構(gòu)建和運(yùn)行時的接口,通過它來獲取的各種對象(例如:KieContainer)來完成規(guī)則構(gòu)建、管理和執(zhí)行等操作。
KieContainer:KieContainer是一個KModule的容器,提供了獲取KBase的方法和創(chuàng)建KSession的方法。其中獲取KSession的方法內(nèi)部依舊通過KBase來創(chuàng)建KSession。
KieSession:KieSession是一個到規(guī)則引擎的對話連接,通過它就可以跟規(guī)則引擎通訊,并且發(fā)起執(zhí)行規(guī)則的操作。例如:通過kSession.insert方法來將事實(shí)(Fact)插入到引擎中,也就是Working Memory中,然后通過kSession.fireAllRules方法來通知規(guī)則引擎執(zhí)行規(guī)則。
說明:以上案例是使用的Kie的API(6.x之后的版本)
2.4 模式匹配算法-RETE
Rete算法由Charles Forgy博士發(fā)明,并在1978-79年的博士論文中記錄。Rete算法可以分為兩部分:規(guī)則編譯和運(yùn)行時執(zhí)行。
編譯算法描述了如何處理生產(chǎn)內(nèi)存中的規(guī)則以生成有效的決策網(wǎng)絡(luò)。在非技術(shù)術(shù)語中,決策網(wǎng)絡(luò)用于在數(shù)據(jù)通過網(wǎng)絡(luò)傳播時對其進(jìn)行過濾。
網(wǎng)絡(luò)頂部的節(jié)點(diǎn)會有很多匹配,隨著網(wǎng)絡(luò)向下延伸匹配會越來越少,在網(wǎng)絡(luò)的最底部是終端節(jié)點(diǎn)。
關(guān)于RETE算法官方給出的說明比較抽象,這里我們結(jié)合具體案例進(jìn)行說明。
2.4.1 案例說明
假設(shè)有以下事實(shí)對象:
A(a1=1,a2="A")
A(a1=2,a2="A2")
B(b1=1,b2="B")
B(b1=1,b2="B2")
B(b1=2,b2="B3")
C(c1=1,c2="B")
現(xiàn)有規(guī)則:
Bete網(wǎng)絡(luò):
2.4.2 節(jié)點(diǎn)說明
1.Root Node:根節(jié)點(diǎn)是所有對象進(jìn)入網(wǎng)絡(luò)的地方
2.one-input-node(單輸入節(jié)點(diǎn))
- 【ObjectTypeNode】:對象類型節(jié)點(diǎn)是根節(jié)點(diǎn)的后繼節(jié)點(diǎn),用來判斷類型是否一致
- 【AlphaNode】:用于判斷文本條件,例如(name == "cheddar",strength == "strong")
- 【LeftInputAdapterNode】:將對象作為輸入并傳播單個對象。
3.two-input-node(雙輸入節(jié)點(diǎn))
- 【BetaNode】:用于比較兩個對象,兩個對象可能是相同或不同的類型。上述案例中用到的join node就是betaNode的一種類型。join node 用于連接左右輸入,左部輸入的是事實(shí)對象列表,右部輸入一個事實(shí)對象,在Join節(jié)點(diǎn)按照對象類型或?qū)ο笞侄芜M(jìn)行比對。BetaNodes 也有內(nèi)存。左邊的輸入稱為 Beta Memory,它會記住所有傳入的對象列表。右邊的輸入稱為 Alpha Memory,它會記住所有傳入的事實(shí)對象。
4.TerminalNode:
表示一條規(guī)則已匹配其所有條件,帶有“或”條件的規(guī)則會為每個可能的邏輯分支生成子規(guī)則,因此一個規(guī)則可以有多個終端節(jié)點(diǎn)。
2.4.3 RETE網(wǎng)絡(luò)構(gòu)建流程
- 創(chuàng)建虛擬根節(jié)點(diǎn)
- 取出一個規(guī)則,例如 "Rete"
- 取出一個模式例如a1==1(模式:就是指when語句的條件,這里when條件可能是有幾個更小的條件組成的大條件。模式就是指的不能再繼續(xù)分割下去的最小的原子條件),檢查參數(shù)類型(ObjectTypeNode),
如果是新類型則加入一個類型節(jié)點(diǎn); - 檢查模式的條件約束:對于單類型約束a1==1,檢查對應(yīng)的alphaNode是否已存在,如果不存在將該約束作為一個alphaNode加入鏈的后繼節(jié)點(diǎn);
若為多類型約束a1==b1,則創(chuàng)建相應(yīng)的betaNode,其左輸入為LeftInputAdapterNode,右輸入為當(dāng)前鏈的alphaNode; - 重復(fù)4,直到該模式的所有約束處理完畢;
- 重復(fù)3-5,直到所有的模式處理完畢,創(chuàng)建TerminalNode,每個模式鏈的末尾連到TerminalNode;
- 將(Then)部分封裝成輸出節(jié)點(diǎn)。
2.4.4 運(yùn)行時執(zhí)行
- 從工作內(nèi)存中取一工作存儲區(qū)元素WME(Working Memory Element,簡稱WME)放入根節(jié)點(diǎn)進(jìn)行匹配。WME是為事實(shí)建立的元素,是用于和非根結(jié)點(diǎn)代表的模式進(jìn)行匹配的元素。
- 遍歷每個alphaNode和ObjectTypeNode,如果約束條件與該WME一致,則將該WME存在該alphaNode的匹配內(nèi)存中,并向其后繼節(jié)點(diǎn)傳播。
- 對每個betaNode進(jìn)行匹配,將左內(nèi)存中的對象列表與右內(nèi)存中的對象按照節(jié)點(diǎn)約束進(jìn)行匹配,符合條件則將該事實(shí)對象與左部對象列表合并,并傳遞到下一節(jié)點(diǎn)。
- 和3都完成之后事實(shí)對象列表進(jìn)入到TerminalNode。對應(yīng)的規(guī)則被觸活,將規(guī)則注冊進(jìn)議程(Agenda)。
- 對Agenda里的規(guī)則按照優(yōu)先級執(zhí)行。
2.4.5 共享模式
以下是模式共享的案例,兩個規(guī)則共享第一個模式Cheese( $cheddar : name == "cheddar" )
網(wǎng)絡(luò)圖:(左邊的類型為Cheese,右邊類型為Person)
2.4.6 小結(jié)
rete算法本質(zhì)上是通過共享規(guī)則節(jié)點(diǎn)和緩存匹配結(jié)果,獲得性能提升。
【狀態(tài)保存】:事實(shí)集合中的每次變化,其匹配后的狀態(tài)都被保存到alphaMemory和betaMemory中。在下一次事實(shí)集合發(fā)生變化時(絕大多數(shù)的結(jié)果都不需要變化)通過從內(nèi)存中取值,避免了大量的重復(fù)計算。
Rete算法主要是為那些事實(shí)集合變化不大的系統(tǒng)設(shè)計的,當(dāng)每次事實(shí)集合的變化非常劇烈時,rete的狀態(tài)保存算法效果并不理想。
【節(jié)點(diǎn)共享】:例如上面的案例不同規(guī)則之間含有相同的模式,可以共享同一個節(jié)點(diǎn)。
【hash索引】:每次將 AlphaNode 添加到 ObjectTypeNode 后繼節(jié)點(diǎn)時,它都會將文字值作為鍵添加到 HashMap,并將 AlphaNode 作為值。當(dāng)一個新實(shí)例進(jìn)入 ObjectType 節(jié)點(diǎn)時,它不會傳播到每個 AlphaNode,而是可以從HashMap 中檢索正確的 AlphaNode,從而避免不必要的文字檢查。
存在問題:
- 存在狀態(tài)重復(fù)保存的問題,匹配過多個模式的事實(shí)要同時保存在這些模式的節(jié)點(diǎn)緩存中,將占用較多空間并影響匹配效率。
- 不適合頻繁變化的數(shù)據(jù)與規(guī)則(數(shù)據(jù)變化引起節(jié)點(diǎn)保存的臨時事實(shí)頻繁變化,這將讓rete失去增量匹配的優(yōu)勢;數(shù)據(jù)的變化使得對規(guī)則網(wǎng)絡(luò)的種種優(yōu)化方法如索引、條件排序等失去效果)。
- rete算法使用了alphaMemory和betaMemory存儲已計算的中間結(jié)果, 以犧牲空間換取時間, 從而加快系統(tǒng)的速度。然而當(dāng)處理海量數(shù)據(jù)與規(guī)則時,beta內(nèi)存根據(jù)規(guī)則的條件與事實(shí)的數(shù)目而成指數(shù)級增長, 所以當(dāng)規(guī)則與事實(shí)很多時,會耗盡系統(tǒng)資源。
在Drools早期版本中使用的匹配算法是Rete,從6.x開始引入了phreak算法來解決Rete帶來的問題。
關(guān)于phreak算法可以看官方介紹:
??https://docs.drools.org/6.5.0.Final/drools-docs/html/ch05.html#PHREAK??
三、催收業(yè)務(wù)中的應(yīng)用
3.1 問題解決
文章開頭問題引出的例子中可以通過編寫drl規(guī)則腳本實(shí)現(xiàn),每次規(guī)則的變更只需要修改drl文件即可。
產(chǎn)生一個新的問題:
雖然通過編寫drl可以解決規(guī)則維護(hù)的問題,但是讓業(yè)務(wù)人員去編寫這樣一套規(guī)則腳本顯然是有難度的,那么在催收系統(tǒng)中是怎么做的呢,我們繼續(xù)往下看。
3.2 規(guī)則的設(shè)計
3.2.1 決策表設(shè)計
催收系統(tǒng)自研了一套決策表的解決方案,將drl中的條件和結(jié)果語句抽象成結(jié)構(gòu)化數(shù)據(jù)進(jìn)行存儲并在前端做了可視化頁面提供給業(yè)務(wù)人員進(jìn)行編輯不需要編寫規(guī)則腳本。例如新增規(guī)則:
將逾期天數(shù)大于a天小于b天且逾期總金額小于等于c的案件分配到A隊列中。
表中的每一行都對應(yīng)一個rule,業(yè)務(wù)人員可以根據(jù)規(guī)則情況進(jìn)行修改和添加,同時也可以根據(jù)條件定義對決策表進(jìn)行拓展。
決策表的主要構(gòu)成:
- 規(guī)則條件定義
定義了一些規(guī)則中用到的條件,例如:逾期天數(shù),逾期金額等。 - 規(guī)則結(jié)果定義
定義了一些規(guī)則中的結(jié)果,例如:分配到哪些隊列中,在隊列中停留時間等。 - 條件字段
在編輯一條規(guī)則時,需要用到的條件字段(從條件定義列表中選?。?/li> - 比較操作符與值
比較操作符包括:< 、<=、>、>=、==、!=,暫時不支持contain,member Of,match等
條件值目前包含數(shù)字和字符。條件字段+比較操作符+值,就構(gòu)成了一個條件語句。 - 結(jié)果
滿足條件后最終得到的結(jié)果也就是結(jié)果定義中的字段值。
3.2.2 規(guī)則生成
催收系統(tǒng)提供了可視化頁面配置來動態(tài)生成腳本的功能(業(yè)務(wù)人員根據(jù)條件定義和結(jié)果定義來編輯決策表進(jìn)而制定相應(yīng)規(guī)則)。
核心流程:
1.根據(jù)規(guī)則類型解析相應(yīng)的事實(shí)對象映射文件,并封裝成條件實(shí)體entitys與結(jié)果實(shí)體resultDefs,文件內(nèi)容如下圖:
事實(shí)對象映射xml
2.根據(jù)規(guī)則類型查詢規(guī)則集完整數(shù)據(jù)
3.將規(guī)則集數(shù)據(jù)與xml解析后的對象進(jìn)行整合,拼裝成一個drl腳本
4.將拼裝好的腳本保存到數(shù)據(jù)庫規(guī)則集表中
3.2.3 規(guī)則執(zhí)行
核心流程:
- 根據(jù)規(guī)則類型從規(guī)則集表中查詢drl腳本
- 將腳步添加至KnowledgeBuilder中構(gòu)建知識庫
- 獲取知識庫InternalKnowledgeBase(在新版本中對應(yīng) Kmodule中的Kbase)
- 通過InternalKnowledgeBase創(chuàng)建KieSession會話鏈接
- 創(chuàng)建AgendaFilter來制定執(zhí)行某一個或某一些規(guī)則
- 調(diào)用insert方法將事實(shí)對象fact插入工作內(nèi)存
- 調(diào)用fireAllRules方法執(zhí)行規(guī)則
- 最后調(diào)用dispose關(guān)閉連接
四、總結(jié)
本文主要由催收系統(tǒng)中的一個案例引出規(guī)則引擎Drools,然后詳細(xì)介紹了Drools的概念與用法以及模式匹配的原理Rete算法。最后結(jié)合催收系統(tǒng)給大家講解了Drools在催收系統(tǒng)中是如何使用的。
通過規(guī)則引擎的引入讓開發(fā)人員不再需要參與到規(guī)則的開發(fā)與維護(hù)中來,極大節(jié)約了開發(fā)成本。通過自研的催收系統(tǒng)可視化決策表,讓業(yè)務(wù)人員可以在系統(tǒng)中靈活配置維護(hù)規(guī)則而不需要每次編寫復(fù)雜的規(guī)則腳本,解決了業(yè)務(wù)人員的痛點(diǎn)。系統(tǒng)本質(zhì)上還是執(zhí)行的規(guī)則腳本,我們這里是把腳本的生成做了優(yōu)化處理,先通過可視化頁面錄入規(guī)則以結(jié)構(gòu)化的數(shù)據(jù)進(jìn)行存儲,再將其與規(guī)則定義進(jìn)行整合拼裝,最終由系統(tǒng)自動生成規(guī)則腳本。
當(dāng)前催收系統(tǒng)中的規(guī)則引擎仍然存在著一些問題,例如:
- 催收系統(tǒng)通過動態(tài)生成腳本的方式適合比較簡單的規(guī)則邏輯,如果想實(shí)現(xiàn)較為復(fù)雜的規(guī)則,需要寫很多復(fù)雜的代碼,維護(hù)成本比較高。
- 催收系統(tǒng)雖然使用的drools7.x版本,但是使用的方式依然使用的是5.x的程序化構(gòu)建器方法(Knowledge API)
- 催收系統(tǒng)目前規(guī)則固定頁面上只能編輯無法新增規(guī)則,只能通過初始化數(shù)據(jù)庫表的方式新增規(guī)則。
后續(xù)我們會隨著版本的迭代不斷升級優(yōu)化,感謝閱讀。
參考文檔: