订单配置系统的数据结构设计与规则编写
1. 系统知识与推荐策略
在构建系统时,有两类知识可以融入其中:技术知识和营销知识。技术知识能让系统告知客户如何将各个组件组装成一个可运行的系统;营销知识则用于说服客户购买更多商品。
对于当前系统,技术推荐将基于产品类别的概念。每个产品都属于一个类别,使用该产品可能需要或希望搭配其他类别的产品。例如,Univac 2000 属于计算机类别,使用它可能需要一个视频监视器(属于监视器类别),因为监视器不包含在计算机中。因此,监视器是计算机客户的需求。如果系统用户购买了 Univac 2000,系统应该推荐她也购买一个监视器。其他配件,如扬声器和软件,也可能是不错的选择,系统也会将它们作为需求进行推荐。
营销方面,有四个销售录像带和 DVD 的机会:
- 如果客户正在购买 VCR 或 DVD 播放器,推荐相应的媒体。
- 如果客户在之前的访问中购买过 VCR 或 DVD 播放器,推荐更多适合该设备的媒体。
- 如果客户正在购买录像带或 DVD,推荐另一盘。
- 如果客户过去购买过录像带或 DVD,推荐另一盘。
在所有情况下,都应跟踪客户的先前购买记录,避免推荐客户已经购买过的录像带或 DVD。
2. 数据结构设计
与专家交流后,发现系统中的重要实体包括:
- 产品(Products):待售的物品。
- 客户(Customers):系统的当前和过去用户。
- 订单(Orders):客户当前和过去的购买记录。
- 订单项(Line items):构成订单的物品集合。
- 推荐(Recommendations):系统输出的推荐内容。
可以为每个实体定义模板:
(deftemplate product
(slot name)
(slot category)
(slot part-number)
(slot price)
(multislot requires))
例如,名为 TekMart 19 TV 的产品可能属于 tv 类别,requires 插槽可能包含电池(用于遥控器)。
(deftemplate customer
(multislot name)
(multislot address)
(slot customer-id))
(deftemplate order
(slot customer-id)
(slot order-number))
(deftemplate line-item
(slot order-number)
(slot part-number)
(slot customer-id)
(slot quantity (default 1)))
(deftemplate recommend
(slot order-number)
(multislot because)
(slot type)
(slot part-number))
有了这些基本的数据结构,就可以开始为订单配置系统编写规则了。
3. 规则编写
3.1 规则编写注意事项
编写的规则将检查事实并断言推荐,但不会显示任何内容或与用户进行交互。用户界面将在后续使用 HTML 和 JSP 编写。目前,要查看规则的效果,需要使用调试命令,如 (watch) 和 (facts)。
在编写规则时,要记住 Jess 会同时处理多个客户的多个订单中的多个订单项。因此,确保所有规则明确识别正在处理的特定客户和订单非常重要,避免将一个客户可能喜欢的产品推荐给另一个无关的客户。
3.2 规则测试
规则最终将嵌入到 Web 应用程序中,届时调试会很困难,因此在编写规则时进行测试很重要。可以将一些产品、订单和订单项的事实放在一个单独的文件中,使用 load-facts 加载它们作为测试用例。设计测试事实来探测每个单独的规则,并在运行测试之前思考正确的结果应该是什么。
例如,有这样一个规则:
(defrule recommend-rubber-duck
(customer (customer-id ?id))
(not (and (order (order-number ?order) (customer-id ?id))
(line-item (order-number ?order) (part-number ?part))
(product (part-number ?part) (name "Rubber duck"))))
=>
(assert (recommend (order-number ?order) (part-number ?part))))
这个规则表示:“如果有一个客户,并且他们从未从我们这里购买过橡皮鸭,那么推荐他们购买。”为了测试这个规则,需要几组事实:一组是有客户购买过橡皮鸭的,另一组是没有购买过的。还可以测试购买了多只橡皮鸭的客户,以及过去下过多个订单的客户和新访问网站的客户(包括购买过橡皮鸭和没有购买过的)。
3.3 推荐需求规则(recommend-requirements)
这可能是推荐代理中最重要的规则,用于为其他产品明确需要的产品创建推荐。为了最大化收入,会推荐目录中最昂贵的产品。规则如下:
(defrule recommend-requirements
(order (customer-id ?id) (order-number ?currentOrder))
(not (order (customer-id ?id)
(order-number ?order2&:(> ?order2 ?currentOrder))))
(line-item (order-number ?currentOrder) (part-number ?part))
(product (part-number ?part) (name ?product)
(requires $? ?category $?))
(product (category ?category) (price ?price)
(part-number ?second-part))
(not (product (category ?category) (price ?p&:(> ?p ?price))))
=>
(assert (recommend (order-number ?currentOrder)
(type requirement)
(part-number ?second-part)
(because ?product))))
这个规则的工作流程如下:
graph TD;
A[匹配当前订单] --> B[匹配订单项];
B --> C[匹配需要其他类别产品的产品];
C --> D[匹配所需类别的产品];
D --> E[找出最昂贵的产品];
E --> F[断言推荐事实];
3.4 推荐视频和 DVD 的规则
3.4.1 为播放器推荐媒体规则(recommend-media-for-player)
(defrule recommend-media-for-player
"If customer has bought a VCR or DVD player in the
past, recommend some media for it."
(product (part-number ?media) (category ?c&dvd-disk|videotape))
(product (name ?name) (part-number ?player)
(category =(if (eq ?c dvd-disk) then dvd else vcr)))
(line-item (customer-id ?id) (order-number ?order1)
(part-number ?player))
(order (customer-id ?id)
(order-number ?currentOrder&:(> ?currentOrder ?order1)))
(not (order (customer-id ?id)
(order-number ?order3&:(> ?order3 ?currentOrder))))
(not (line-item (customer-id ?id) (part-number ?media)))
(not (recommend (order-number ?currentOrder)
(type =(sym-cat discretionary- ?c))))
=>
(assert (recommend (order-number ?currentOrder)
(because ?name)
(part-number ?media)
(type =(sym-cat discretionary- ?c)))))
这个规则的前两个模式匹配目录中的 DVD 或录像带以及能播放它们的播放器。将这两个模式放在规则开头,因为它们只匹配目录中的内容,在程序运行时不会改变。一般来说,将匹配固定不变事实的模式放在规则顶部是个好做法,这样可以避免多次评估。
3.4.2 推荐更多媒体规则(recommend-more-media)
(defrule recommend-more-media
"If customer buys a disk or tape, recommend a random
other item of the same category."
?p1 <- (product (part-number ?part1)
(category ?c&dvd-disk|videotape) (name ?name))
?p2 <- (product (part-number ?part2) (category ?c))
(test (neq ?p1 ?p2))
(line-item (order-number ?order) (part-number ?part1))
(not (recommend (order-number ?order)
(type =(sym-cat discretionary- ?c))))
=>
(assert (recommend (order-number ?order)
(because ?name)
(part-number ?part2)
(type =(sym-cat discretionary- ?c)))))
这个规则在客户购买录像带或 DVD 时,推荐同一类别的另一个随机物品。
3.4.3 推荐同类型媒体规则(recommend-same-type-of-media)
(defrule recommend-same-type-of-media
"If customer has bought a disk or tape in the past,
recommend a random other item of the same category."
?p1 <- (product (part-number ?part1)
(category ?c&dvd-disk|videotape) (name ?name))
?p2 <- (product (part-number ?part2) (category ?c))
(test (neq ?p1 ?p2))
(line-item (customer-id ?id)
(order-number ?order1) (part-number ?part1))
(order (customer-id ?id)
(order-number ?currentOrder&:(> ?currentOrder ?order1)))
(not (order (customer-id ?id)
(order-number ?order3&:(> ?order3 ?currentOrder))))
(not (line-item (customer-id ?id) (part-number ?part2)))
(not (recommend (order-number ?currentOrder)
(type =(sym-cat discretionary- ?c))))
=>
(assert (recommend (order-number ?currentOrder)
(because ?name)
(part-number ?part2)
(type =(sym-cat discretionary- ?c)))))
这个规则尝试让过去购买过媒体的客户在每次回访时购买更多同类型的媒体。
4. 推荐优化规则
4.1 合并推荐规则(coalesce-recommendations)
(defrule coalesce-recommendations
"If there are multiple recommendations for the same product,
coalesce them."
?r1 <- (recommend (order-number ?order) (type ?type)
(because ?product) (part-number ?part))
?r2 <- (recommend (order-number ?order) (part-number ?part)
(because $?products&
:(not (member$
?product
$?products))))
=>
(retract ?r1 ?r2)
(assert (recommend (order-number ?order) (type ?type)
(because (create$ ?product $?products))
(part-number ?part))))
这个规则将对同一产品的多个推荐合并为一个。
4.2 移除已满足的推荐规则(remove-satisfied-recommendations)
(defrule remove-satisfied-recommendations
"If there are two products in the same category, and
one is part of an order, and there is a recommendation
of type 'requirement' for the other part, then remove
the recommendation, as the customer is
already buying something in that category."
(product (part-number ?part1) (category ?category))
(product (part-number ?part2) (category ?category))
(line-item (order-number ?order) (part-number ?part2))
?r <- (recommend (order-number ?order)
(part-number ?part1) (type requirement))
=>
(retract ?r))
这个规则移除那些客户已经在购买同一类别其他产品时所产生的无效需求推荐。
5. 有用的查询
查询可以让你有效地访问 Jess 工作内存中的指定元素,将 Jess 变成一个关系数据库(虽然不使用 SQL)。在构建 Web 应用程序时,将使用 Jess 来存储所有应用程序数据。
defquery
类似于没有右侧操作的规则,它包含一组模式,用于匹配事实,与规则的模式匹配方式相同。不同之处在于,规则会自动匹配,而查询需要调用
run-query
函数来触发。该函数返回一个
java.util.Iterator
,表示查询模式的匹配列表。
例如,
all-products
查询匹配目录中的每个产品:
(defquery all-products
(product))
Web 应用程序可以通过调用 Jess 函数
(run-query all-products)
来获取目录中所有产品的列表,这对于构建订单表单很有用。
综上所述,通过合理设计数据结构和编写规则,结合有效的查询机制,可以构建一个功能强大的订单配置和推荐系统,为客户提供更好的购物体验,同时提高销售效率。
6. 规则总结与应用场景
6.1 规则总结
以下是对前面编写的规则进行的总结:
| 规则名称 | 规则作用 |
| — | — |
|
recommend-requirements
| 为其他产品明确需要的产品创建推荐,推荐目录中最昂贵的产品 |
|
recommend-media-for-player
| 当客户过去购买过 VCR 或 DVD 播放器时,推荐适合的媒体 |
|
recommend-more-media
| 当客户购买录像带或 DVD 时,推荐同一类别的另一个随机物品 |
|
recommend-same-type-of-media
| 让过去购买过媒体的客户在每次回访时购买更多同类型的媒体 |
|
coalesce-recommendations
| 将对同一产品的多个推荐合并为一个 |
|
remove-satisfied-recommendations
| 移除那些客户已经在购买同一类别其他产品时所产生的无效需求推荐 |
6.2 应用场景
这些规则可以应用于多种电子商务场景,例如:
-
新客户购买
:当新客户购买产品时,
recommend-requirements
规则可以推荐所需的配件,提高客户购买的完整性。
-
老客户回访
:对于老客户,
recommend-media-for-player
和
recommend-same-type-of-media
规则可以推荐相关的媒体产品,增加客户的购买量。
-
购物车优化
:在客户的购物车中,
recommend-more-media
规则可以推荐更多的同类型产品,促进客户的额外购买。
7. 规则性能优化思考
7.1 模式排序
在编写规则时,模式的排序是一个需要平衡的问题,主要有以下三个重要且相互影响的因素:
-
清晰度
:按照规则逻辑清晰的顺序编写模式,使规则易于理解。
-
性能
:将匹配固定、不变事实的模式放在规则顶部,避免多次评估,提高性能。
-
内存使用
:将匹配较少事实的模式放在规则开头,减少部分匹配的数量,限制内存消耗。
例如,在
recommend-media-for-player
规则中,将匹配目录内容的模式放在开头,就是为了提高性能。
7.2 规则优化示例
如果发现某些规则的性能不佳,可以考虑对规则进行优化。例如,对于
recommend-requirements
规则,可以添加一些缓存机制,避免重复查找最昂贵的产品。
;; 假设添加一个缓存事实来存储每个类别的最昂贵产品
(deftemplate category-expensive-product
(slot category)
(slot part-number)
(slot price))
;; 修改 recommend-requirements 规则
(defrule recommend-requirements
(order (customer-id ?id) (order-number ?currentOrder))
(not (order (customer-id ?id)
(order-number ?order2&:(> ?order2 ?currentOrder))))
(line-item (order-number ?currentOrder) (part-number ?part))
(product (part-number ?part) (name ?product)
(requires $? ?category $?))
(category-expensive-product (category ?category) (part-number ?second-part) (price ?price))
=>
(assert (recommend (order-number ?currentOrder)
(type requirement)
(part-number ?second-part)
(because ?product))))
;; 添加一个规则来更新缓存
(defrule update-category-expensive-product
(product (category ?category) (price ?price) (part-number ?part))
(not (category-expensive-product (category ?category) (price ?p&:(> ?p ?price))))
=>
(retract (category-expensive-product (category ?category)))
(assert (category-expensive-product (category ?category) (part-number ?part) (price ?price))))
8. 系统集成与未来扩展
8.1 系统集成
这些规则将集成到 Web 应用程序中,Web 应用程序可以通过查询机制获取当前订单的物品列表、推荐列表和产品目录。例如,使用
all-products
查询获取产品目录,用于构建订单表单。
8.2 未来扩展
- 个性化推荐 :可以结合客户的购买历史、浏览记录等信息,实现更个性化的推荐。例如,根据客户过去购买的产品类别和品牌,推荐更符合客户喜好的产品。
- 促销活动 :可以添加规则来处理促销活动,如满减、折扣等。例如,当客户购买的产品总价达到一定金额时,推荐相关的促销产品。
- 多语言支持 :在 Web 应用程序中添加多语言支持,让不同语言的客户都能使用系统。
9. 总结
通过设计合理的数据结构和编写有效的规则,结合查询机制,我们构建了一个订单配置和推荐系统。这个系统可以为客户提供更好的购物体验,同时提高销售效率。在实际应用中,还可以根据具体需求对规则进行优化和扩展,以适应不同的业务场景。
整个系统的工作流程可以用以下 mermaid 流程图表示:
graph LR;
A[客户下单] --> B[规则匹配];
B --> C{是否有推荐};
C -- 是 --> D[生成推荐列表];
C -- 否 --> E[无推荐];
D --> F[合并推荐];
F --> G[移除无效推荐];
G --> H[展示推荐给客户];
E --> H;
这个流程图展示了从客户下单到最终展示推荐给客户的整个过程,体现了规则在系统中的作用。通过不断优化规则和系统架构,可以进一步提升系统的性能和用户体验。
超级会员免费看
2744

被折叠的 条评论
为什么被折叠?



