浏览博客
工程 / Agent 系统设计 更新于 2026年10月29日 约 42 分钟阅读

本体如何参与 Agent 的决策

从一顿晚餐,看懂本体、事实、行动规则与模型怎样共同决定下一步。

BigDog

文章目录 · 7 章 · 约 42 分钟

“朋友今晚来吃饭,只用植物食材,帮我安排菜单,再看看还要买什么。”

AI 很容易列出几道菜。但一道“蘑菇汤”可能用了牛奶,合适的菜也未必有足够食材。程序要查清菜谱、食材和库存之间的关系,才能给出可用的购物清单。

四格漫画:确认只用植物食材,查看菜谱组成,核对番茄和豆腐的库存,生成缺少豆腐的购物清单。
图 1:本例的蘑菇汤配方含牛奶,因此被排除;番茄豆腐的完整配方符合要求,库存核对后只缺豆腐。画面省略了已核实且备齐的其他配料。机器人代表会查询资料、调用软件的 Agent,最后只生成清单,没有下单。

这篇文章讲的是:把对象及其关系明确写出来之后,Agent 怎样利用它们决定下一步。 这套关于对象、类别和关系的定义,称为“本体”。它会参与资料查询和动作筛选,而模型仍负责理解请求、处理疑问、选择下一步操作。

一、先把关系说清楚

三元组是表达格式,本体提供语义定义,实例是被描述的具体对象,知识图谱把定义和事实组织起来。 下面用晚餐系统中的同一套对象,逐步写出这些定义和事实。

1.1 先确定:我们管理什么对象

晚餐系统管理的是食材目录中的条目。牛奶条目和豆腐条目各有固定标识,菜谱和库存都引用这些标识。“牛奶条目”表示目录里的一个食材种类;库存记录保存它当前有多少。

这套模型有三种基本类别:菜谱、食材种类、库存记录。对应的实例分别是配方A、牛奶条目、库存K。

为了按来源筛选目录条目,我们再定义植物来源食材种类、动物来源食材种类;后者包含乳制品种类。这些名称都指一组食材目录条目。下文的“乳制品种类”始终是类,“牛奶条目”始终是实例。

1.2 都是三元组,含义有什么不同

采用 RDF 时,可以把知识写成“主语—谓词—宾语”。下面使用简化的中文标识,保留标准谓词名称;每一行都是一条三元组。

先写本体定义:有哪些类,它们怎样包含彼此。

食材种类          rdf:type         owl:Class
动物来源食材种类  rdfs:subClassOf  食材种类
乳制品种类        rdfs:subClassOf  动物来源食材种类
植物来源食材种类  rdfs:subClassOf  食材种类

owl:Class表示类;rdfs:subClassOf表示子类关系。“乳制品种类是动物来源食材种类的子类”,意思是:归入前者的每个目录条目,也归入后者。

再写实例事实:具体有哪些条目,哪份菜谱引用了它们。

牛奶条目  rdf:type      乳制品种类
豆腐条目  rdf:type      植物来源食材种类
配方A     rdf:type      菜谱
配方A     所需食材种类  牛奶条目
库存K     rdf:type      库存记录
库存K     对应食材种类  豆腐条目
库存K     可用数量      0
库存K     计量单位      "盒"

牛奶条目 rdf:type 乳制品种类把一个实例归入一个类;它与上一组的“类包含于类”不同。结合两组数据,程序可以推导:

牛奶条目  rdf:type  动物来源食材种类

这里的推导来自明确的类别关系。rdf:type也用于前面的类声明,所以不能仅凭出现了这个谓词,就把整条语句判为业务数据;要看它是在声明类,还是给业务对象归类。RDF Schema 对类型和子类的定义说明了这两种关系的语义。

本体还要定义所需食材种类这个关系的含义:从一份菜谱指向它使用的食材目录条目。配方A 所需食材种类 牛奶条目则是对这份配方的具体陈述。两者分别负责定义关系和使用关系记录事实。

关系定义也可以写成三元组

下面继续使用相同的对象粒度,省略前缀声明。domain说明关系主语的类别,range说明宾语的类别。

菜谱          rdf:type  owl:Class
库存记录      rdf:type  owl:Class
所需食材种类  rdf:type  owl:ObjectProperty
所需食材种类  rdfs:domain  菜谱
所需食材种类  rdfs:range   食材种类
对应食材种类  rdf:type  owl:ObjectProperty
对应食材种类  rdfs:domain  库存记录
对应食材种类  rdfs:range   食材种类

RDFS 的 domain 和 range 用于推导类型。输入是否缺字段、数量是否有效,由数据校验程序检查并决定接受或拒绝。

1.3 本体和实例,怎样组成知识图谱

把这些三元组连接起来,就能从配方A找到牛奶条目,再找到它所属的类及上级类;也能从豆腐条目找到对应的库存记录。这种按对象及其关系组织知识的方式,就是这里所说的知识图谱。

知识图谱可以同时包含本体定义和实例事实,本体文件中也可以写实例声明。 阅读三元组时,要看它在定义类别与关系,还是记录具体对象的事实。工程上常把定义与业务数据分开维护,便于分别更新和核验。OWL 2 入门文档也说明本体可以包含具体对象的知识。

在本例中,开发者和领域人员核对类别及关系定义;菜谱资料提供配方事实;库存查询提供数量、时间和版本。模型可以帮助提取信息,来源与归类仍需核实。

两层之间,最常见的连接是实例归类,但也可以有其他业务关联。 为了保存用户要求,我们增加饮食要求这个类,并创建本次饮食要求这个实例:

本次饮食要求  rdf:type  饮食要求
本次饮食要求  禁止类别  动物来源食材种类

第一条回答“这个对象是什么”;第二条回答“这个要求针对哪一类食材”。禁止类别是本文自定义的业务关系,宾语引用一个类别标识。程序据此找到要检查的类别范围。

规则程序读取这项配置,查找菜谱所需条目是否归入被禁止的类,包括经子类关系推导出的归类。牛奶条目属于乳制品种类,而后者是动物来源食材种类的子类,因此配方 A 会被排除。这里的两个步骤是记录禁止哪类,再按配置执行检查。

因此,读跨层关系时要看箭头上的谓词:rdf:type给实例归类;禁止类别指定检查范围。业务对象还可以引用类别来表达适用范围或检查目标,并由对应的查询和规则处理。

实现时,怎样处理“实例引用类别”?

上面的第二条是应用层建模示意。普通实现可以把目标类的标识保存在配置里,由查询程序读取并查找该类的实例。筛选时需要包括子类推导,不能只做字符串相等比较。

若采用 OWL 2 DL,对象属性连接的是个体。可以用 punning,让同一个标识分别作为类和个体使用;但这两个视角在直接语义下分别解释。禁止类别指向其个体视角,不会自动把类的全部成员变成被禁止的对象。仍需应用查询或明确的规则把配置与类别成员联系起来,见 OWL 2 的元建模说明。

1.4 加上任务规则,才能决定选不选

三元组告诉我们配方 A 需要牛奶条目,并能推导它属于动物来源食材种类。是否排除这份配方,还取决于用户这次的要求。

针对“只用植物食材”,我们写出三个分支:

  • 已核实某个所需条目不符合植物食材要求,就排除配方。
  • 配料表不完整,或某个条目的来源分类未核实,就继续查询,暂不通过。
  • 配料表完整,且所有所需条目都已核实符合要求,才加入候选菜单。

因此,排除蘑菇汤的过程是:查到配方 A 需要牛奶条目 → 根据类关系推导它是动物来源 → 按本次任务规则排除。 若用户接受蛋奶,筛选条件可以改变,牛奶条目的来源分类无需改变。

这三条是任务规则,可以由普通代码执行。前面的子类推导属于语义推理;保存清单、下单等动作还需要各自的执行条件。

1.5 实操方法:什么时候建成类

“一个概念会被多个对象当作标签使用”,可以帮助发现候选类。下一步要检查:这个标签是否有明确的归类含义,以及系统是否需要利用这种归类。 单个类只是本体的一部分;本体还包括关系定义和逻辑约定。

可以按下面四步决定。本例的取舍参考了 Ontology Development 101先确定用途与问题、再组织类和实例的做法。

  1. 先写要回答的问题。 例如“配方 A 用了哪些食材种类”“哪些不符合本次要求”“每种还缺多少”。这些问题决定需要什么信息。
  2. 确定独立标识代表什么。 本例一个食材标识代表一个目录条目。若以后管理每盒食材的保质期,需要另建实物对象,为每盒实物分配独立标识,再关联到原来的目录条目。
  3. 检查归类和继承是否成立。 乳制品种类可以容纳牛奶、奶酪等条目,并定义为动物来源食材种类的子类。检验子类时,问“前者的每个实例,是否必然也是后者的实例”。
  4. 放入真实样例,核对查询结果。 加入牛奶、豆腐及来源未知的条目,检查系统能否分别排除、通过来源检查和要求补查。不能因为没有动物来源记录,就自动判为植物来源。

例如,“本周推荐”也会贴在很多菜谱上,但本例只需要显示它,可以保存为标签;可用数量是属性,0是属性值;牛奶条目需要独立标识并被菜谱引用,是实例。如果推荐资格后来有明确条件且参与推理,也可以重新考虑建模。

类可以暂时没有实例,或只有一个实例;实例数量不是硬性门槛。分类含义、对象身份和查询需求,才是本文采用的判断依据。

如果把“牛奶”建成类,可以吗?

可以。若系统追踪每盒实物,可以定义牛奶实物类,让某盒牛奶成为它的实例。那是另一种对象粒度。本文选择食材目录方案:牛奶条目是食材种类的实例,库存记录统计它的可用数量。两种方案的名字、标识和关系需要分别定义。

小型实现可以用配置文件维护概念定义,用数据库或 JSON 保存目录和库存,再用代码完成查询和筛选;采用 RDF 的系统则可将定义与事实分别放在文件或命名图中。

1.6 把定义、事实和规则放在一起

这张图按知识关系布局,上部是本体中的类,下部是具体实例。沿箭头可以读出“主语—关系—宾语”。蓝色实线是子类关系,绿色虚线是实例归类,绿色实线连接具体事实;橙色线单独表示对类别的业务引用。

两层知识图谱:本次饮食要求通过实例归类连接饮食要求类,同时通过禁止类别业务引用连接动物来源食材种类;牛奶条目归入乳制品种类,后者是动物来源食材种类的子类;配方 A 需要牛奶条目,配方 B 需要豆腐条目。
图 2:两层知识,一张图谱。下方绿色区域中的实例通过虚线归入上方蓝色区域中的类;橙色“禁止类别”引用的是类别标识,表达本次要求的禁止范围,交由程序解释和检查。图中曲线交叉处不表示新增节点;为突出跨层关系,省略库存、其他配料及来源记录。点击图片可查看原尺寸。

规则如何使用这张网:

  • 排除:某个所需条目已核实归入禁止类别,就排除对应配方;图中的牛奶条目会使配方 A 被排除。
  • 补查:配料表不完整或来源分类未知,继续查询。没有命中禁止类别,只能说明当前没有查到禁止项。
  • 通过:完整配料表中的每个条目都已核实符合本次植物食材要求,才加入候选菜单。配方 B 的豆腐条目已符合要求,其余配料也要逐项核实。

二、本体怎样参与一次决策

现在让 Agent 处理开头的请求。这里的 Agent 是能够选择下一步、调用查询或写入功能,并根据结果继续操作的程序。

2.1 把人的话对应到明确的要求

用户说“只用植物食材”,系统将它记录为这次菜单的要求:每道菜所需的食材都必须符合这个范围。若用户只说“素一点”,含义就不够清楚,需要先询问是否接受蛋奶。

模型负责从语言中提出对应的概念,本体提供可使用的类别与关系。模型识别出的结果先作为待确认信息;有歧义时向用户询问,确认后写入任务要求。

2.2 沿着关系查完整资料

Agent 找到蘑菇汤配方,沿“所需食材种类”查询目录条目,再根据条目的类型及子类关系检查来源。配方 A 引用了牛奶条目,该条目可推导为动物来源食材种类的实例,因此不符合本次要求。

这里增加本体的意义,是让“查菜谱”“核对食材类别”“解释排除原因”使用同一组明确关系。即使资料里有“鲜奶”和“牛乳”等不同称呼,也可以先通过核实过的名称映射,找到同一个食材目录条目。

如果菜谱只列出主料,Agent 就继续查询调味料。配料齐全并逐项核实后,才能判断这道菜是否符合要求。

2.3 根据规则形成候选菜单

本例采用一条明确的任务规则:只有配料完整、各食材条目的来源分类已核实且均符合要求的菜谱,才进入候选菜单。

本体定义食材种类及来源分类的含义,实例数据记录菜谱引用了哪个条目、条目归入哪个类,任务规则检查它们是否满足当前要求。

筛选后仍可能有多个合适菜谱。模型可以结合人数、口味和准备时间提出方案。涉及数量的计算交给程序处理;用户未提供的偏好保留为未知,必要时询问。

2.4 查库存,生成购物清单

选定番茄豆腐配方 B 后,Agent 沿“所需食材种类”查到豆腐等条目,再读取各配料的两人份用量,并按条目标识查库存。关系本身只说明需要哪种食材,用量另存在这份配方的配料明细中。单位换算和缺口计算由程序完成。本例中,其他配料已备齐,只有豆腐不足,于是清单中列出豆腐及缺少的数量。

“配方 B 所需食材种类 豆腐条目”是实例之间的事实;“将豆腐加入清单”是动作。关系说明对象怎样关联,动作改变任务状态。

清单保存后,本次任务完成。若要继续购买,系统需要另行取得用户授权。

三、把各部分接成架构

本体在这次任务中参与了四项工作:理解用户用语、寻找关联资料、检查参数类别,以及为模型挑选当前需要的事实。

具体实现时,可以让模型通过类型明确的查询工具访问这些信息。规则程序先筛出适用的动作,再交给模型选择。下面按晚餐案例区分各部分的工作。

表 1:晚餐 Agent 中各部分的职责。 同一份菜谱会经过多个部分处理;每一行承担的判断不同。

部分在这个例子中负责什么
本体定义菜谱、食材种类、库存记录这些类及关系含义
实例事实与任务状态保存条目类型、配方配料、库存、来源及当前方案
行动模型与规则规定资料齐全后才能生成清单,下单还需另外授权
规划器选择先补查哪项资料、何时请求用户确认
执行器检查参数和权限,调用查询或清单写入功能
结果检查器核对清单数量、要求及实际保存结果

这些部分组成一个循环:读取状态 → 查询关系和事实 → 筛选候选动作 → 选择并执行 → 核对结果 → 更新状态。

以菜谱配料不全为例,当前状态记着“调味料未核实”。规则程序允许查询完整配方或请求补充,暂不允许提交菜单。规划器选择查询配方;工具返回结果后,程序记录来源与版本,再重新筛选动作。

两格漫画:蘑菇汤配料表不完整时继续查询,补查发现牛奶后,依据植物食材要求排除该配方。
图 3:资料缺失和不符合要求,是两种不同结果。左格没有完整配料表,因此继续查询;右格查到配方引用牛奶条目,结合条目的乳制品类型与本体中的子类定义,推导其动物来源分类,任务规则据此排除配方。图中的机器人代表规划器及其调用的查询程序。

如果多个查询都能补齐资料,模型可以选择更有希望解决当前疑问的那个。步骤固定时也可以用普通工作流;目标、动作和成本都明确时,可以用传统规划算法。这些决策方式都可以查询本体及实例数据。

3.1 状态里要保留什么

本体的类别和关系定义相对稳定;库存、菜谱版本和任务进度会变化,需要单独保存。

状态至少应能回答:用户确认了什么要求,哪些资料已核实,哪些还未知,当前选择哪个方案,执行过什么操作。查询记录附带来源、时间和版本,使用时根据任务要求检查是否需要更新。

“尚未查库存”“确认库存为零”“查询失败”是三种不同情况。它们分别对应查询、计算购买量、等待或处理错误。如果都写成“没有”,Agent 就无法选对下一步。

每次发给模型的上下文,从状态中按当前问题选取。当前要确认豆腐用量,就提供对应菜谱、份数、库存及未决问题;原始资料保留引用,按需读取。

四、从关系到动作,还要定义什么

本体定义“对应食材种类”连接库存记录与食材目录条目。执行动作还需要更具体的约定:收什么参数,满足什么条件才允许执行,执行后应该发生什么。

例如,save_shopping_list 接收菜单方案、份数和库存版本。执行前,程序检查配方是否完整、数量单位是否一致、饮食要求是否已核实,以及调用者是否有权保存这份清单。执行后,读取已保存的清单,核对它与计算结果一致。

这类行动模型可以借鉴 PDDL 对参数、前置条件和效果的描述。实际工具接口还要实现身份认证、失败返回和并发控制。

行动模型的配置示意

下面用一份自定义配置表示这些约定:

action: save_shopping_list
parameters:
  menu_plan: MenuPlanId
  servings: PositiveInteger
  inventory_version: Version
preconditions:
  - ingredients_complete
  - dietary_requirement_verified
  - quantities_and_units_valid
  - caller_can_save_list
expected_effect:
  - shopping_list_saved
verification:
  - read_back_saved_items
on_unknown_result:
  - query_original_request

参数类型引用本体中的对象类型;执行器检查调用权限和数据版本,并通过数据库事务完成写入。

4.1 执行结果如何返回状态

保存清单时,应先持久化请求编号及参数,再发送请求。如果回复丢失,先查询原请求是否成功,而不是直接创建另一份清单。重试去重需要接收请求的系统支持,并约定编号的有效期与使用范围。

库存也可能在计算期间发生变化。需要按最新库存生成清单时,保存操作要校验对应版本;版本冲突则重新查询和计算。仅在发送请求前读一次版本,仍可能遗漏读取和写入之间的修改。

四格漫画:菜单需要两盒豆腐,查询时库存为零;主人补入一盒后库存版本更新,旧清单保存被拒绝,重新查询后只需购买一盒。
图 4:从查询到保存,库存可能变化。按左上、右上、左下、右下阅读:版本 7 时库存为零;主人放入一盒,库存更新为版本 8;执行器拒绝按旧版本保存;程序重新计算为购买一盒,并核对保存结果。“所需食材种类”的关系定义保持不变,配方仍引用同一个豆腐条目;变化的是库存记录中的数量与版本、计算结果和任务状态。

工具返回的资料可能含有“直接购买”等文字,它们只作为资料处理。权限和动作范围由程序检查。用户取消、调用预算用完或多次查询仍无结果时,停止新增操作,并保留未确认请求供核对或人工接手。

一个包含本体查询的执行循环

这里的函数名表示职责。权限、事务和调度机制需要在各模块内实现。

def advance(task_id):
    state = store.load(task_id)

    if state.pending_request:
        return reconcile_or_handoff(state)  # 有次数与时间限制

    if state.cancelled or budget.exhausted(state):
        return handoff_or_stop(state)

    facts = observe_and_record(state)
    context = semantic_layer.query(
        ontology=ontology,
        facts=facts,
        goal=state.goal,
    )
    candidates = action_model.allowed(context, state.principal)
    action = planner.select(state.goal, context, candidates)

    if action is None:
        return ask_wait_or_stop(state)

    result = executor.validate_and_run(action, state)
    state = store.record_result(state, result)
    return completed(state) if verifier.goal_reached(state) else schedule(state)

semantic_layer.query 返回相关对象、关系、来源和未知项;allowed 依据明确规则筛选动作;validate_and_run 使用执行时的权威记录再次检查。新结果先作为观察记录,核实后再用于事实更新,避免把模型猜测直接写成已知事实。

实际运行还需防止同一任务被多个进程同时推进,并保证保存状态后仍能触发后续执行。

五、本体能带来什么,什么时候值得用

本体定义可供不同任务复用;核实后的名称映射也是可复用的数据。例如将“鲜奶”“牛乳”映射到同一个牛奶条目后,菜谱和库存便能通过条目标识关联。以后增加早餐计划或多人聚餐,不必为每个入口重新解释一遍食材和库存的关系。

本体也使错误更容易定位。菜单不合适时,可以分别检查:用户要求是否识别错误,菜谱资料是否缺失,类别定义或条目归类是否错误,还是筛选规则漏掉了条件。

但关系定义和事实来源都需要维护。如果菜谱只有几条、字段固定,一份类型定义加规则代码可能已经足够。跨资料源名称不一致、对象关系多、同一知识需要服务多个任务时,显式本体才更值得考虑。

5.1 本体语言、数据校验和业务规则

OWL 2可以描述类别、属性、个体与逻辑关系。在本文模型中,牛奶条目是乳制品种类的实例;借助子类关系,可推导它也是动物来源食材种类的实例。它采用开放世界语义:没有记录某个断言,不等于这个断言为假。因此不能因为图中没写某条目的动物来源类型,就确认它属于植物来源食材种类。

本例要求“完整配料已核实”,是额外的任务规则。使用 RDF 图保存数据时,SHACL可检查声明的数据约束;JSON Schema、关系数据库约束或普通规则代码也能承担各自适合的检查。通过格式与结构检查,仍需要可靠来源支持事实本身。

工程上应分别决定:哪些关系需要本体表达,哪些事实由数据源提供,哪些条件由规则检查,哪些动作由执行器授权。

六、如何判断本体有没有帮助

先验证一次完整任务。给出含牛奶的候选配方,系统应指出具体配料并排除;缺少配料表,应继续查询而不是通过;库存单位不一致,应先换算或要求补充;没有购买授权,生成清单后就结束。

再加入名称不同但指向同一食材条目、错误归类、过时库存、重复请求、进程中断等案例。分别记录模型的错误建议、数据映射错误、规则判断错误和实际执行错误,才能知道问题出在哪里。

要评估本体本身的作用,可以比较两个版本:两者都有相同的状态存储、工具和执行检查,其中一个使用显式本体,另一个使用原有字段与规则。保持模型、任务、事实、权限及上下文预算尽量一致;需要调整检索和提示时,将调整记录下来。

除任务完成率外,还要比较资料缺失时是否正确暂停、解释能否追溯到来源、延迟、人工介入和维护成本。例如接入一份新的库存表,是否减少了重复映射工作。

从这个例子开始实现,先定义少量对象与关系,接入可核实的数据,再写筛选规则和工具条件。让一份菜单从需求走到购物清单,并能解释每一次选择,然后再增加更多任务。

本体与状态空间有什么区别?

本体描述对象及其含义,状态空间描述任务可能处于的情况,以及动作怎样使情况变化。

在完全可观测、动作结果确定的简化模型中,可写成:

P=(S,A,T,s0,G,C),st+1=T(st,at)\mathcal P=(S,A,T,s_0,G,C),\qquad s_{t+1}=T(s_t,a_t)

SS 是状态集合,AA 是动作集合,TT 描述变化,s0s_0 是初始状态,GG 判断任务完成,CC 表示约束。菜谱已核实、库存已查询、清单已保存,是不同的任务状态。

现实中只能掌握部分信息,规划器使用带来源和时间的运行记录。严格 POMDP 中的信念状态是对隐藏状态的概率分布,要采用这种模型,需要另外定义隐藏状态及其概率更新方式,背景见 Kaelbling 等人的论文。

本体可以帮助组织状态中的对象、关系和查询;行动模型规定前置条件与效果;规划器在候选动作中选择。三者共同参与运行,但各自解决不同问题。

七、参考资料

晚餐流程与模块组合为本文的教学设计。漫画与知识图谱插图由 AI 生成。

输入关键词,查找全部技术文章。

    搜索范围:正文、标题、分类和标签