You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于CLIPS的可行烹饪食谱专家系统开发技术问询

CLIPS烹饪食谱专家系统开发问题解决指南

核心需求与现存问题

  • 开发目标:基于CLIPS构建烹饪食谱专家系统,从库存食材及可制作食谱推理可行菜品,执行食谱时自动更新食材库存
  • 现存技术问题:
    1. 无法根据是否执行制作动作(如make_dough)为新生成食材设置available或feasible状态
    2. 无法对已存在的食材(如面团)进行数量累加,只能重复断言新实例
  • 附加需求:能否输出制作N公斤某食材的完整步骤、现有可用食材及需采购食材,怀疑此类反向推理需求更适合Prolog

代码问题修复方案

针对上述两个核心问题,修正后的代码如下,关键改动已标注:

(defrule at-start
=>
    (set-dynamic-constraint-checking TRUE)
)

(deftemplate Ingredient
    (slot name)
    (slot quantityKg (type FLOAT) (default 0.0) (range 0.0 ?VARIABLE))
    (slot status) ; 可选值:available/feasible
)

(deftemplate DoAction
    (slot name) ; 记录需要执行的动作,如make_dough
)

(defrule feasible_recipe_dough
    ?f0 <- (Ingredient (name flour) (quantityKg ?q0))
    (test (>= ?q0 0.5))
    ?f1 <- (Ingredient (name butter | oil) (quantityKg ?q1))
    (test (>= ?q1 0.15))    
=>
    ; 消耗原材料
    (modify ?f0 (quantityKg (- ?q0 0.5)))
    (modify ?f1 (quantityKg (- ?q1 0.15)))
    
    ; 修复问题1:根据是否存在DoAction事实设置status
    (bind ?s "feasible")
    (if (find-fact ((?a DoAction)) (eq ?a:name "make_dough"))
        then (bind ?s "available")
    )
    
    ; 修复问题2:累加已有食材数量或断言新实例
    (bind ?existing_dough (find-fact ((?d Ingredient)) (eq ?d:name "dough")))
    (if ?existing_dough
        then (modify ?existing_dough (quantityKg (+ ?existing_dough:quantityKg 0.5)) (status ?s))
        else (assert (Ingredient (name dough) (quantityKg 0.5) (status ?s)))
    )
)

(defrule feasible_recipe_tomato_sauce
    ?f0 <- (Ingredient (name tomato) (quantityKg ?q0))
    (test (>= ?q0 0.5))
=>
    (modify ?f0 (quantityKg (- ?q0 0.5)))
    ; 同样应用累加逻辑和status设置
    (bind ?s "feasible")
    (if (find-fact ((?a DoAction)) (eq ?a:name "make_tomato_sauce"))
        then (bind ?s "available")
    )
    (bind ?existing_sauce (find-fact ((?sauce Ingredient)) (eq ?sauce:name "tomatoSauce")))
    (if ?existing_sauce
        then (modify ?existing_sauce (quantityKg (+ ?existing_sauce:quantityKg 0.5)) (status ?s))
        else (assert (Ingredient (name tomatoSauce) (quantityKg 0.5) (status ?s)))
    )
)

(defrule feasible_recipe_pizza_margarita
    ?f0 <- (Ingredient (name dough) (quantityKg ?q0))
    (test (>= ?q0 0.5))
    ?f1 <- (Ingredient (name tomatoSauce) (quantityKg ?q1))
    (test (>= ?q1 0.15))   
    ?f2 <- (Ingredient (name mozzarela) (quantityKg ?q2))
    (test (>= ?q2 0.3))       
=>
    (modify ?f0 (quantityKg (- ?q0 0.5)))
    (modify ?f1 (quantityKg (- ?q1 0.15)))
    (modify ?f2 (quantityKg (- ?q2 0.3)))    
    ; 披萨的累加逻辑
    (bind ?s "feasible")
    (if (find-fact ((?a DoAction)) (eq ?a:name "make_pizza_margarita"))
        then (bind ?s "available")
    )
    (bind ?existing_pizza (find-fact ((?p Ingredient)) (eq ?p:name "pizzaMargarita")))
    (if ?existing_pizza
        then (modify ?existing_pizza (quantityKg (+ ?existing_pizza:quantityKg 0.75)) (status ?s))
        else (assert (Ingredient (name pizzaMargarita) (quantityKg 0.75) (status ?s)))
    )
)

关键修复说明

  1. 状态设置逻辑:使用find-fact函数查询工作内存中是否存在指定的DoAction事实,以此动态绑定status值。避免了原代码中直接在RHS使用模式匹配的语法错误。
  2. 食材数量累加:通过find-fact检查目标食材是否已存在,存在则用modify更新数量,不存在则断言新实例,解决了重复生成实例的问题。

附加问题解答

制作N公斤食材的反向推理需求,Prolog确实因其逻辑编程范式更适合这类目标驱动的推理场景,但CLIPS也可以通过以下方式实现:

  • 定义目标事实(如(target (name pizzaMargarita) (quantityKg 2.0)))
  • 编写反向链规则:从目标食材倒推所需原料,计算现有库存与需求的缺口,递归处理需要制作的中间食材
  • 记录推理路径,最终输出完整步骤、现有可用食材及需采购清单

不过相比之下,Prolog的回溯机制和逻辑查询语法会让这类实现更简洁直观。

内容的提问来源于stack exchange,提问作者B.Bocquet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 15:15:02