DLAI-知识图谱智能体笔记-全-
DLAI 知识图谱智能体笔记(全)
001:课程介绍 🧠

在本节课中,我们将要学习如何利用知识图谱来解决AI智能体在复杂业务流程中面临的API发现与调用顺序难题。课程由SAP Business AI的两位专家——业务知识图谱负责人Perfka GK和高级知识工程师La Healing——共同讲授。
概述
大型企业可能拥有成千上万个由不同团队开发的API,这些API旨在支持企业内部的各种任务,例如购买或退货、申请差旅批准、申请数据访问的IT批准等。虽然为AI智能体构建大量API是件好事,但这实际上使得智能体难以确定在执行业务流程时应该使用哪些API以及以何种顺序调用它们。
知识图谱的核心作用
为了解决这个问题,我们将使用知识图谱。其核心思路是:将原始的API规范导入知识图谱,从而获得所有API的结构化视图。更重要的是,我们会在图谱中添加信息,以指明调用API的正确顺序。
一个具体例子
假设一个智能体的任务是“购买一件商品”。它可能会搜索并找到“采购订单API”作为最相关的API,并试图直接调用该API来下单。然而,在一个大公司里,智能体可能不知道,它首先需要调用另一个API来创建“采购申请”,该申请需要经过IT部门批准后,才能最终调用“采购订单API”来下单。
这个“先创建采购申请,再获取IT批准,最后下订单”的流程信息,可能并不包含在单个API的定义中。如果没有这类信息,你的知识图谱和智能体理解并执行重要业务流程的能力将是不完整的。

扩展知识图谱:从列表到网络




正如Andrew所说,为了捕捉这种流程信息,你需要用过程数据来扩展知识图谱。这将使你的图谱从一个简单的API列表,转变为一个描述它们在真实流程中如何连接的网络。这样,智能体就能意识到,在调用创建订单的API之前,需要先调用采购申请API。
实现步骤:从语义检索到流程整合
为了给智能体提供执行给定任务所需的正确API,我们将遵循以下步骤:
上一节我们介绍了知识图谱如何结构化API信息,本节中我们来看看如何为智能体找到并组织这些API。
以下是实现智能体API发现的两个关键步骤:

- 语义检索:首先,我们将对所有API及其规范进行嵌入,并使用相似性搜索来找到最佳匹配。例如,如果智能体想创建采购订单,它会检索到语义上相关的API,如“采购订单API”。
- 图谱扩展搜索:然而,直接调用检索到的API可能并不正确,因为业务流程可能要求先调用“采购申请API”以获得经理批准。为了解决这个问题,我们将在知识图谱上进行扩展搜索,以查找并包含业务流程所需的相关API。这将为智能体提供所有必要的API以及它们应该被调用的顺序。
课程目标与展望
在最后一课中,我们将把所有内容整合起来,构建一个能够执行真实任务并遵循正确流程顺序的AI智能体。
本课程的创建离不开许多人的努力。特别感谢SAP团队的Tristph Meyer、Felix Sasaki和Johannes Hoofffat,以及来自Deep Blalinda AI的Eshma Gvari。

总结
本节课中我们一起学习了企业拥有复杂且重要的业务流程,而构建能够执行这些流程的生成式AI劳动力是AI社区未来工作的一个重要部分。正确地实现这一点是一个至关重要的问题。

下一课将是知识图谱的入门介绍,我们将了解什么是知识图谱,以及如何使用它们来帮助智能体理解并遵循复杂的多步骤流程。让我们进入下一个视频,开始学习吧。
002:知识图谱基础 🧠

在本节课中,我们将要学习什么是知识图谱,了解构建它们的多种方法,并探讨它们如何在企业应用场景中,帮助AI智能体更好地发现和执行API。

概述
知识图谱是一种以图结构表示结构化信息的方法。它通过节点代表实体,边代表实体间的关系,将信息组织成一个互联的网络。这种结构不仅有助于人类理解复杂关系,更能为AI系统提供丰富的上下文和语义信息,从而提升其执行任务的准确性和效率。
知识图谱的实践应用
为了了解知识图谱在实践中的应用,我们可以进行一次快速的网络搜索。例如,搜索“SAP”。

在搜索结果中,除了匹配的网站列表,你还会看到一个关于实体“SAP”的全面概览,这便来源于知识图谱。这里展示了诸如描述、关联网站等属性,以及与其他实体的关系,例如其总部位于“沃尔多夫”。点击“沃尔多夫”,会跳转到该城市对应的知识图谱条目,再次看到其描述和与其他实体(如所属地区)的关系。
技术基础
现在我们已经看到了知识图谱的实际应用,让我们深入一点来理解其技术基础。
一个知识图谱以图的形式表示结构化信息,其中节点代表实体,边代表这些实体之间的关系。
知识图谱主要由两个部分组成:
- 模式或本体:定义了知识图谱中出现的实体类型、它们的属性以及实体之间的关系。
- 实例数据:构成图谱的具体实例,遵循模式的定义。
通常,表示知识图谱有两种主要方法:标签属性图和资源描述框架。虽然两者都建模实体和关系,但它们在结构、表达能力和适用场景上有所不同。在本课程中,我们将使用RDF作为基于图的数据模型来表示知识图谱。
资源描述框架是一种基于图的数据模型,由万维网联盟标准化。RDF不强制要求模式,这使其非常灵活,易于集成来自异构数据源的数据。SPARQL是RDF的标准查询语言,具有明确定义的语义,类似于关系数据模型中的SQL。
RDF的基本构建块是三元组。一个三元组由主体、谓词和客体组成。每个三元组都可以表示为RDF图中的一条带标签的有向边。
例如,边 (SAP, 位于, 沃尔多夫) 就表示“SAP位于沃尔多夫”这一事实。
知识图谱示例
理解了RDF图的基本元素后,让我们来看一个与我们之前网络搜索实验类似的知识图谱示例。
我们首先从一个代表SAP的节点开始。在RDF中,统一资源标识符 用于唯一标识图中的资源。我们可以为SAP实例添加属性,例如其成立年份、名称,并声明它是一个公司。RDF中属性的值被称为字面量。
我们可以进一步扩展图谱,将SAP链接到图中的其他节点,例如其CEO“克里斯蒂安·克莱因”和总部所在地城市“沃尔多夫”。
知识图谱的一个优势是能够推断出数据中未明确陈述、但可以从本体定义中推导出的事实。例如,通过定义“位于”是一种可传递的关系,我们就可以推断出“SAP位于德国”。
RDF图通常以机器可读的格式序列化,例如 .nt 或 .ttl 文件。如下所示,文件中的一个示例三元组表明SAP的CEO是克里斯蒂安·克莱因。
<SAP> <CEO> "Christian Klein" .
构建知识图谱的方法
有多种方法可以构建知识图谱。
以下是几种主要的数据源类型及其处理方法:
- 结构化源:拥有固定的模式,同一类型或类别的实体使用相同的属性进行描述,例如关系数据库。这里会使用R2RML等映射规则来构建知识图谱。
- 半结构化源:拥有灵活的模式,同一类型或类别的实体可能以不同方式描述,例如XML文档。这里同样使用映射规则来构建知识图谱。
- 非结构化源:完全没有固定模式,例如自然语言文本或图像。可以使用自然语言处理等技术从这类数据源构建知识图谱。
在本课程中,你将使用结构化源来构建一个示例知识图谱。
知识图谱构建流程概览
以下是构建知识图谱的高级流程概述:
- 步骤0:定义用例:定义用例、范围以及需要通过图谱回答的业务问题。这决定了需要提取哪些元数据、建模什么内容等。
- 步骤1:数据采集:从整个企业生态系统中收集数据,这构成了知识图谱的基础。这是连接各种系统并提取其有价值的业务数据的奠基阶段。每个源系统都有自己的“语言”并以不同方式组织数据,例如CSV、XML、JSON等。
- 步骤2:数据分析与标准化:分析和标准化数据,确保其“知识图谱就绪”。可以将其视为将不同的方言翻译成一种通用语言,包括去重、解决不一致性和验证数据质量,以确保知识图谱建立在可信信息的坚实基础上。
- 步骤3:数据建模:这是魔法发生的地方。在这里,你将干净的数据转换为标准化的RDF三元组。每一条业务信息都被表示为主体-谓词-客体的陈述,直接反映了相关底层系统中的关系。
- 步骤4:价值实现:在这里,你利用知识图谱的互联特性来交付价值。这些对源系统及其新连接的统一表示,使得分析和洞察能够从作为互联整体的源元数据中衍生出来。
知识图谱赋能AI智能体
现在你知道了什么是知识图谱以及构建它的各种方法,让我们看一个在企业环境中如何将知识图谱与AI智能体结合使用的例子。
假设有一个用户请求:“为采购组002和采购组织3000创建一份购买5支铅笔的采购订单”。你希望一个AI智能体来完成这个请求。如果没有上下文,这对智能体来说并非易事,因为企业系统环境可能非常复杂,有数千个可能相关的不同API。
因此,我们在系统环境中构建一个API知识图谱,并用业务流程信息对其进行丰富,从而为智能体提供正确的上下文,以完成用户请求。
在拥有复杂且不断演进的API的大型企业环境中,AI智能体面临几个挑战。知识图谱可以有效应对这些挑战:
以下是知识图谱如何帮助AI智能体应对企业环境挑战:
- 挑战一:API发现效率低:大语言模型通常需要花费大量时间在试错过程中寻找正确的API,这会显著降低效率。
- 知识图谱的解决方案:知识图谱围绕业务流程和对象组织API,缩小了搜索空间,使规划更高效,减少了不必要的重新规划,从而整体上加速了执行。
- 挑战二:缺乏深度上下文:虽然大语言模型和RAG等检索系统擅长提取相关内容,但它们常常忽略更深层次的结构和上下文,特别是在涉及领域特定逻辑或API元数据时。
- 知识图谱的解决方案:知识图谱提供了缺失的上下文。因为它们是结构化的且语义丰富,反映了API、业务流程和数据模型之间的关系。这对于确保回答的准确性和避免幻觉特别有帮助,尤其是在动态或定制的业务环境中。
- 挑战三:处理复杂任务能力有限:对于简单的读取操作,大语言模型通常能应对。但当任务变得更复杂时,例如按正确顺序执行一系列API调用或理解允许的固定值,它们就开始力不从心。
- 知识图谱的解决方案:知识图谱提供了内置的结构,可以映射这些依赖关系和序列,逐步指导智能体,减少出错机会。
- 挑战四:推理过程不透明:AI智能体通常基于学习到的模式或检索到的片段生成答案,但很少提供它们如何得出答案的可见性。这使得解释结果或追溯到源逻辑变得困难,尤其是当同一查询返回不同结果时。
- 知识图谱的解决方案:知识图谱通过使推理过程透明化来改变这一点。你可以精确追踪使用了哪些API、使用了什么过滤器、系统返回了什么、源系统是什么等等。这些能力在企业环境中至关重要,因为信任、可审计性和可重现性是不可妥协的。


总结


本节课中,我们一起学习了知识图谱的基础概念。我们了解到知识图谱是一种用图结构(节点和边)表示实体及其关系的技术。它可以通过结构化、半结构化和非结构化数据源构建。在企业应用中,知识图谱通过为AI智能体提供丰富的、结构化的上下文信息,显著提升了其在复杂系统环境中进行API发现、任务规划和执行的效率与准确性,同时增强了整个过程的透明度和可追溯性。
003:API知识图谱构建 🧱

在本节课中,我们将学习如何从一个关于API服务及其端点的示例数据集构建知识图谱。具体来说,你将了解一种声明式的知识图谱构建方法。


概述
我们将从查看输入数据开始,然后学习如何为知识图谱建模数据,即引入知识图谱模式。最后,你将学习一种声明式的方法,按照模式将输入数据映射到知识图谱。虽然本课程使用OData API及其EDMX规范,但该方法并不局限于OData,也可应用于其他API规范。
现在,让我们进入实践环节,构建第一个知识图谱。
导入必要包
我们首先导入所有必要的包。使用 pandas 读取CSV文件,RDFLib 构建知识图谱,networkx 和 matplotlib 用于可视化知识图谱,以及一些辅助函数将RDF图转换为networkx图。
import pandas as pd
from rdflib import Graph, URIRef, Literal, Namespace
import networkx as nx
import matplotlib.pyplot as plt
# 假设有一些辅助函数,例如 `rdf_to_networkx`
加载输入数据
让我们从CSV文件读取输入数据,了解每个API概念的信息。
1. 读取服务数据
首先,我们从CSV文件读取服务信息。我们定义其为逗号分隔文件,可以指定版本列的数据类型为字符串,并定义如何处理数据中的空值。
services_df = pd.read_csv('services.csv', sep=',', dtype={'version': str}, na_values=[''])
print(services_df.head(1))
我们查看CSV文件的第一行。可以看到API服务的名称、版本和描述。例如,有一个版本为4.0的采购订单API,描述为“用于采购订单的OData服务”。
2. 读取实体类型数据
接下来,查看实体类型。同样从CSV文件读取,处理空值。对于实体类型,有名称和该实体类型所属的服务。
entity_types_df = pd.read_csv('entity_types.csv', sep=',', na_values=[''])
print(entity_types_df.head(1))
例如,有一个“采购申请项目类型”,属于采购申请API。
3. 读取属性数据
现在,查看为这些实体类型提供更多信息的属性。再次读取CSV文件,处理空值。对于属性,有属性所属的服务、属性所属的实体类型、属性名称、更描述性的标签、属性类型、最大长度、是否是实体类型的关键属性以及是否可被UI应用程序选择。
properties_df = pd.read_csv('properties.csv', sep=',', na_values=[''])
print(properties_df.head(1))
例如,属性“现金折扣”,标签为“现金折扣百分比”,类型为十进制。
4. 读取导航属性数据
接下来,加载导航属性。我们读取CSV文件,并查看前两行以理解导航的类型。
navigations_df = pd.read_csv('navigations.csv', sep=',', na_values=[''])
print(navigations_df.head(2))
导航属性为服务定义,有名称、导航起始的实体类型、导航目标的实体类型以及多重性。例如,从采购订单项目导航到采购订单的多重性为“1”,表示一个采购订单项目恰好属于一个采购订单。而从采购订单导航到采购订单项目的多重性为“*”,表示一对多关系。
5. 读取实体集数据
最后,查看实体集。加载CSV文件,查看第一行。实体集是特定实体类型实体的逻辑容器。每个实体类型恰好属于一个实体集。
entity_sets_df = pd.read_csv('entity_sets.csv', sep=',', na_values=[''])
print(entity_sets_df.head(1))
这里有实体集的名称、所属的服务以及所属的实体类型。
数据统计
现在,简要查看刚刚导入的数据的统计信息。我们建立一个简单的字典,将加载的类型映射到每个对应数据框的行数。
data_stats = {
'Services': len(services_df),
'Entity Sets': len(entity_sets_df),
'Entity Types': len(entity_types_df),
'Navigations': len(navigations_df),
'Properties': len(properties_df)
}
print(data_stats)
可以看到有39个服务,总共101个实体集和对应的实体类型,1206个导航属性,以及为这101个实体类型定义的超过2000个属性类型。
定义知识图谱模式
在理解了输入数据之后,下一步是为我们的知识图谱定义模式或本体。知识图谱模式定义了图内的结构和关系。它指定了可以存在于图中的实体类型(节点)和关系类型(边)。模式充当蓝图,提供了被建模领域知识的正式表示,并支持对知识图谱进行高效查询、推理和推断。
所有数据API都使用实体数据模型进行描述,我们从该模型派生出知识图谱模式。让我们看看这个模式。
- 服务:主要入口点。服务以机器可读的形式宣传其具体数据模型,允许通用客户端以定义良好的方式与服务交互。
- 实体类型:用于描述API服务端点提供的数据结构的基本构建块。
- 属性:定义实体类型实例将包含的数据的形状和特征。属性具有数据类型、最大长度等,并指示它们是否是实体类型的关键属性。
- 导航属性:实体类型上的可选属性,允许从关联的一端导航到另一端。
- 实体集:实体类型实例的逻辑容器。每个实体类型链接到恰好一个实体集。
使用SPARQL进行映射
接下来,你需要定义映射,以使用此模式将输入数据转换为知识图谱。在本课程中,你将使用SPARQL(RDF的标准查询语言)来定义这些映射。
如果你不熟悉SPARQL,这里有一个快速介绍。SPARQL是RDF的标准查询语言,你可以将其视为RDF的SQL,可能会注意到一些语法上的相似之处。
让我们看一个示例SPARQL查询。查询的主要部分是 WHERE 子句,它定义了应在RDF图中匹配的图模式。此类图模式的核心组件是三元组模式。三元组模式类似于RDF三元组,但也允许使用应在图中匹配的变量,变量以问号开头。
此外,SPARQL支持各种查询形式。本示例使用 SELECT 查询形式来检索解决方案映射,类似于SQL。SELECT 查询的结果可以表示为一个表,其中列对应于查询中的变量,行对应于解决方案。
在本课中,你将使用 CONSTRUCT 查询形式来构建图。在 CONSTRUCT SPARQL查询中,你可以在 CONSTRUCT 子句中使用三元组模式来定义要构建的图的形状。你还可以在查询的 WHERE 子句中使用 BIND 语句来创建要添加到图中的实体的唯一标识符。
在我们的映射函数中,图模式中的变量被CSV文件列的值替换。也就是说,CSV文件的每一行都会得到一个实例化,该实例化被添加到我们的知识图谱中。
在笔记本中实践
现在,让我们回到笔记本,在实践中完成这个步骤。
1. 构建服务的三元组
我们可以设置第一个 CONSTRUCT 查询,为服务数据生成RDF三元组。这对应于你刚才看到的查询。
CONSTRUCT {
?service a :Service ;
:description ?description ;
:version ?version ;
:name ?name .
}
WHERE {
BIND(URI(CONCAT("http://example.org/service/", ?name)) AS ?service)
}
现在,让我们看一下转换函数,它接收输入数据框和查询作为输入,并为这些输入生成RDF三元组。
def transform(df, construct_query, first_row_only=False):
result_graph = Graph()
query_graph = Graph()
query_graph.parse(data=construct_query, format='sparql')
headers = df.columns.tolist()
data_iter = df.head(1).iterrows() if first_row_only else df.iterrows()
for index, row in data_iter:
init_bindings = {var: Literal(row[col]) for var, col in zip(['?'+h for h in headers], headers)}
for triple in query_graph.query(construct_query, initBindings=init_bindings):
result_graph.add(triple)
return result_graph
让我们仅为服务数据框的第一行执行该函数并打印结果。
sample_service_triples = transform(services_df.head(1), service_construct_query)
print(sample_service_triples.serialize(format='turtle'))
你看到使用Turtle序列化创建的结果三元组。我们为采购订单创建了一个服务,并添加了描述、名称和版本的三元组。
接下来,我们处理整个数据框,并将构建的三元组添加到我们之前定义的知识图谱 kg 中。
kg = Graph()
service_triples = transform(services_df, service_construct_query)
kg += service_triples
print(f"知识图谱大小(添加服务后): {len(kg)}")
通过处理服务的整个数据框,我们创建了一个包含156个三元组的知识图谱。
2. 处理剩余数据框
让我们继续处理剩余的数据框。
以下是实体集的 CONSTRUCT 查询。我们再次调用转换函数,并在将实体集添加到知识图谱后打印知识图谱的大小。
entity_set_construct_query = """
CONSTRUCT {
?entity_set a :EntitySet ;
:belongsTo ?service ;
:containsEntityType ?entity_type ;
:name ?name .
}
WHERE {
BIND(URI(CONCAT("http://example.org/entityset/", ?name)) AS ?entity_set)
BIND(URI(CONCAT("http://example.org/service/", ?service_name)) AS ?service)
BIND(URI(CONCAT("http://example.org/entitytype/", ?entity_type_name)) AS ?entity_type)
}
"""
entity_set_triples = transform(entity_sets_df, entity_set_construct_query)
kg += entity_set_triples
print(f"知识图谱大小(添-加实体集后): {len(kg)}")
如你所见,知识图谱的大小增加了。我们现在有超过400个三元组。
类似地,我们将处理实体类型、属性和导航属性,每次处理后都打印知识图谱的大小。最终,我们得到了一个更大的知识图谱,拥有超过14000个三元组,这是因为有超过2000个属性,它们为图添加了相当数量的三元组。
可视化知识图谱
现在,你已成功构建了业务API的知识图谱。我们的AI智能体已经可以利用它与单个API进行交互。然而,它仍然缺乏这些API如何在业务流程中使用的上下文。
考虑采购申请和采购订单的实体集,它们在直接材料采购过程中存在依赖关系。让我们通过绘制由这两个实体集诱导的子图来可视化这种不连通性。
首先,我们使用SPARQL查询从图中检索采购订单和采购申请的实体集节点。
def get_entity_set_node(graph, entity_set_name):
query = """
SELECT ?entity_set WHERE {
?entity_set a :EntitySet ;
:name ?name .
FILTER(?name = "%s")
}
""" % entity_set_name
result = list(graph.query(query))
return result[0][0] if result else None
po_node = get_entity_set_node(kg, "PurchaseOrder")
pr_node = get_entity_set_node(kg, "PurchaseRequisition")
接下来,我们构建由这两个节点从知识图谱中诱导出的子图。
def get_subgraph(graph, central_node, depth=2):
# 这是一个简化示例,实际中可能需要更复杂的遍历
# 这里假设有一个辅助函数 `expand_graph` 来获取特定深度内的邻居
subgraph_nodes = expand_graph(graph, central_node, depth)
subgraph = graph.subgraph(subgraph_nodes)
return subgraph
po_subgraph = get_subgraph(kg, po_node)
pr_subgraph = get_subgraph(kg, pr_node)
combined_subgraph = nx.compose(po_subgraph, pr_subgraph)
为了可视化该图,我们使用networkx库。
def visualize_graph(graph):
pos = nx.spring_layout(graph, seed=42)
node_colors = []
node_shapes = []
for node in graph.nodes():
if 'PurchaseOrder' in str(node):
node_colors.append('lightgray')
elif 'PurchaseRequisition' in str(node):
node_colors.append('lightblue')
else:
node_colors.append('white')
# 根据节点类型分配形状(示例)
if 'Service' in str(node):
node_shapes.append('o') # 圆形
elif 'EntityType' in str(node):
node_shapes.append('s') # 方形
elif 'Property' in str(node):
node_shapes.append('^') # 上三角
elif 'Navigation' in str(node):
node_shapes.append('v') # 下三角
else:
node_shapes.append('o')
nx.draw(graph, pos, with_labels=False, node_color=node_colors, node_shape=node_shapes[0], node_size=300)
plt.show()
visualize_graph(combined_subgraph)
在此可视化中,蓝色节点对应于采购申请API,灰色节点对应于采购订单API。你还可以看到不同形状的节点。例如,中心的圆形节点对应于实际的API服务,它连接到表示为方形节点的不同实体类型。对于每个实体类型,你可以看到许多用上三角形表示的属性。此外,你看到连接不同实体类型的较大的下三角形,这对应于不同实体类型之间的导航。
如你所见,采购申请API在知识图谱中并未连接到采购订单API。我鼓励你尝试在知识图谱中搜索其他实体集并绘制它们,以查看它们在知识图谱中的结构表示。
序列化知识图谱
目前,知识图谱是一个保存在内存中的RDFLib图。为了共享和重用知识图谱,你可以使用任何RDF序列化将其具体化到磁盘上。在这里,我们使用你在上一课中已经见过的Turtle格式序列化知识图谱。
kg.serialize(destination='api_knowledge_graph.ttl', format='turtle')
print("知识图谱已保存到 'api_knowledge_graph.ttl'")
生成的知识图谱将存储到磁盘,我们可以在下一课中使用它。
总结

在本节课中,我们为API数据构建了一个知识图谱。你看到了它是如何不连通的,API之间没有连接。在下一课中,你将学习如何集成业务流程数据,以便根据API服务在业务流程中的使用情况来连接这些API服务。
004:与业务流程集成


在本节课中,我们将学习如何将业务流程数据扩展到知识图谱中,以更好地连接API服务,并提供关于流程中依赖关系的上下文信息。
概述
上一节我们介绍了如何构建包含API元数据的基础知识图谱。本节中,我们将探讨如何集成业务流程数据,从而在API之间建立有意义的连接,使AI智能体能够理解服务在特定业务上下文中的依赖关系。
业务流程的核心概念
为了将流程数据集成到图谱中,我们首先需要理解两个核心概念:流程和活动。

- 流程:定义了一组按特定顺序执行以完成某个业务目标的活动集合。一个流程包含名称、描述和版本信息,并链接到该流程的起始活动。
- 活动:代表流程中的一个具体步骤。每个活动有名称和描述,并链接到流程中的下一个活动。

为了将流程图谱数据与API数据连接起来,我们可以在适用的情况下将活动链接到对应的实体集。例如,“创建采购申请”这个活动可以链接到“采购申请”实体集。为简化起见,本课程我们省略了分支、循环等复杂流程,仅关注顺序执行的简单流程。
业务流程示例
现在,让我们来看一个具体的例子。考虑一个用于直接物料采购的简单流程,该流程通常由采购员执行。
- 首先,创建一个采购申请。
- 在该申请获得批准后,基于此申请创建一个新的采购订单。
- 最后,经过一些潜在的中间步骤后,采购订单被关闭。
在这个流程中,“创建采购申请”和“创建采购订单”这两个步骤可以链接到知识图谱中相应的实体集。通过这种连接,AI智能体可以推导出:在此特定流程的上下文中,采购订单实体集依赖于采购申请实体集。
接下来,让我们进入实践环节,看看如何将流程数据与上一课创建的API数据和知识图谱进行集成。
实践:集成流程与API数据
我们将通过代码演示如何将业务流程数据整合到已有的API知识图谱中。
1. 导入必要的包
首先,我们导入所需的软件包,这些包与上一课使用的相同。
# 导入必要的库,例如用于处理RDF图的rdflib
import rdflib
from rdflib.namespace import RDF, RDFS
2. 加载上一课的知识图谱
为了将流程数据链接到已有的业务API知识图谱,我们首先从上一课导入这个图谱。
# 创建一个空的API知识图谱
api_kg = rdflib.Graph()
# 读取并解析上一课保存的文件
api_kg.parse("api_knowledge_graph.ttl", format="turtle")
# 打印图谱中的三元组数量
print(f"API知识图谱包含 {len(api_kg)} 个三元组。")
运行结果应显示超过14000个三元组,这与上一课图谱的大小相符。
3. 加载业务流程图谱
对于本课,我们已经从BPMN图中提取了一些流程并将其转换为RDF格式。BPMN(业务流程模型与标记法)是定义业务流程的标准。
# 创建一个空的流程知识图谱
process_kg = rdflib.Graph()
# 从Turtle文件解析业务流程数据
process_kg.parse("business_processes.ttl", format="turtle")
# 打印业务流程图谱的大小
print(f"业务流程图谱包含 {len(process_kg)} 个三元组。")
我们的业务流程图谱大约有150个三元组。让我们查看一下其中包含哪些流程。
4. 查询业务流程
我们使用SPARQL查询来检索业务流程图谱中的流程。
# 定义SPARQL查询,选择所有流程及其名称
query = """
PREFIX kg: <http://example.org/kg#>
SELECT ?process ?processName
WHERE {
?process a kg:Process .
?process kg:name ?processName .
}
"""
# 在流程知识图谱上运行查询
results = process_kg.query(query)
# 打印所有流程的名称
print("知识图谱中的流程包括:")
for row in results:
print(f"- {row.processName}")
以下是查询结果示例。这些流程包括直接物料采购、库存领用、外部运输计划等,这些是大多数公司中常见的流程。
5. 合并知识图谱
现在我们已经看到了一些流程,我们可以简单地将业务流程图谱添加到上一课的业务API图谱中,从而得到一个组合知识图谱。
# 创建一个新的空图谱作为合并后的图谱
combined_kg = rdflib.Graph()
# 将API图谱和流程图谱合并到新图谱中
combined_kg += api_kg
combined_kg += process_kg
# 打印合并后图谱的大小
print(f"合并后的知识图谱包含 {len(combined_kg)} 个三元组。")
如你所见,合并后的知识图谱大小正好等于两个独立图谱(API知识图谱和流程知识图谱)大小之和。与上一课类似,你可以将知识图谱序列化为Turtle语法并写入磁盘。
6. 探索流程与API的连接
合并图谱后,我们可以查询知识图谱,并发现流程与API之间的连接。在流程图谱中,活动可以链接到相应的API实体集(如果适用)。
以下是一个SPARQL查询,用于检索“直接物料采购”流程的活动,以及链接到实体集的活动。
# 查询特定流程的活动及其链接的实体集和服务
connection_query = """
PREFIX kg: <http://example.org/kg#>
SELECT ?activityName ?entitySetName ?serviceName
WHERE {
# 找到“直接物料采购”流程
?process a kg:Process ;
kg:name "Procurement of Direct Materials" ;
kg:hasStartActivity ?startActivity .
# 使用属性路径查询获取该流程的所有后续活动
?activity kg:next* ?startActivity .
?activity kg:name ?activityName .
# 检查活动是否链接到实体集
OPTIONAL {
?activity kg:linksToEntitySet ?entitySet .
?entitySet kg:name ?entitySetName ;
kg:belongsTo ?service .
?service kg:name ?serviceName .
}
}
"""
# 在合并图谱上运行查询
connection_results = combined_kg.query(connection_query)
# 打印结果
print("流程活动及其连接的实体集和服务:")
for row in connection_results:
if row.entitySetName:
print(f"活动 '{row.activityName}' 链接到服务 '{row.serviceName}' 中的实体集 '{row.entitySetName}'")
else:
print(f"活动 '{row.activityName}' 未链接到实体集")
我们能看到类似以下的结果:活动“创建采购申请”链接到“采购申请API”服务中的“采购申请”实体集;活动“创建采购订单”链接到“采购订单API”服务中的“采购订单”实体集。
7. 可视化连接关系
让我们回顾一下上一课中看到的断开连接的图谱。如你所见,API之间没有连接,“采购申请API”信息和“采购订单API”信息是孤立的。
现在你将看到这些服务如何通过流程连接起来。与上一课类似,你首先从知识图谱中获取节点。但现在,你只需要“采购订单”节点或“采购申请”节点中的一个作为起始实体集,因为实体集现在可以通过流程信息相互访问。
# 查询“采购订单”实体集作为起始点
start_query = """
PREFIX kg: <http://example.org/kg#>
SELECT ?entitySet
WHERE {
?entitySet a kg:EntitySet ;
kg:name "Purchase Order" .
}
"""
start_result = list(combined_kg.query(start_query))
purchase_order_uri = start_result[0][0] if start_result else None
print(f"起始实体集URI: {purchase_order_uri}")
现在,你可以通过以“采购订单”实体集URI为种子节点来绘制连接图。我们再次将RDF图转换为networkX图以便可视化,并构建由该节点诱导出的子图。
import networkx as nx
import matplotlib.pyplot as plt
# 将RDF子图转换为networkX图(此处为示意,实际转换需要更多代码)
# nx_graph = convert_rdf_to_networkx(combined_kg, seed_node=purchase_order_uri, depth=3)
# 绘制图形
# ... 可视化代码 ...
最终生成的图谱将是连通的。图中,蓝色部分代表“采购申请API”的信息,灰色部分代表“采购订单API”的信息,而红色的节点则是来自业务流程的活动,正是这些活动使我们能够连接“采购订单”和“采购申请”的实体集。
8. 查看完整知识图谱
在创建了结合API信息和业务流程信息的知识图谱,并看到它们如何通过流程活动连接之后,让我们看一下整个知识图谱的全貌。
虽然模型或模式相当简单,只包含少数几个概念,但包含实际API定义和流程的实例数据的知识图谱则要大得多且复杂得多。因此,我们只可视化包含100条随机边的图谱子集。
# SPARQL查询,随机选择100条边
sample_query = """
SELECT ?s ?p ?o
WHERE {
?s ?p ?o .
}
ORDER BY RAND()
LIMIT 100
"""
# 获取边列表并绘制(此处为示意)
# sampled_edges = list(combined_kg.query(sample_query))
# ... 使用networkX绘制采样后的图 ...
该图展示了知识图谱的规模和复杂性,并且它甚至只显示了100条边,这仅占整个图谱的约0.7%。由此可见,整个知识图谱过于庞大和复杂,无法将其全部内容作为上下文提供给AI智能体。
总结


本节课中,我们一起学习了如何将业务流程数据集成到API知识图谱中。我们介绍了流程和活动的核心概念,并通过实践演示了如何加载、合并流程与API图谱,以及如何通过流程活动在原本孤立的API服务之间建立有意义的连接。最后,我们看到完整的知识图谱规模庞大,直接将其全部提供给AI智能体是不现实的。在下一课中,我们将学习如何利用语义嵌入技术,从知识图谱中智能地发现仅与当前任务相关的API。
005:使用知识图谱进行API发现 🔍

在本节课中,我们将学习如何利用知识图谱来帮助AI智能体发现API。我们将回顾之前构建的知识图谱,并学习如何通过两个关键步骤——设计时准备和运行时查询处理——来增强API发现过程,从而更智能、更准确地为智能体提供相关的API信息。

设计时:初始检索准备
在上一节中,我们构建了一个整合了API及其相关业务流程信息的图谱。本节中,我们来看看如何为API发现做准备。以下是设计时需要完成的步骤:
- 从知识图谱中检索实体集及其属性:首先,我们需要从图谱中获取所有实体集(如“采购订单”)及其标签和属性。
- 将检索到的文本转换为嵌入向量:接着,使用嵌入模型将这些文本信息转化为向量表示,以便后续进行语义相似度搜索。
运行时:接收并处理用户查询
在运行时,当接收到用户查询时,我们将执行以下步骤来发现最相关的API:
- 基于嵌入向量的初步检索:首先,根据用户查询的嵌入向量,在索引中进行初步检索,得到一个相关的实体集列表。
- 添加通过业务流程边连接的API:然后,利用知识图谱中的业务流程依赖关系,将与初步检索结果相关的其他API(例如,创建“采购订单”前所需的“采购申请”)也加入候选列表。
- 基于业务流程信息丰富检索结果:最后,将相关的业务流程信息附加到检索到的实体集上,为AI智能体提供更完整的上下文。
开始实践:导入必要包
与之前的课程一样,我们首先导入所有必要的Python包。本节引入了一些新工具:
# 导入用于语义相似度搜索的FAISS索引类
from faiss import IndexFlatL2
# 导入用于显示循环进度的工具
from tqdm import tqdm
# 导入OpenAI的文本嵌入模型
from langchain.embeddings import OpenAIEmbeddings
# 导入参数化SPARQL查询的辅助函数
from helper_functions import parameterize_sparql_query
设置好数据框的显示格式后,我们初始化嵌入模型。
初始化嵌入模型
我们使用OpenAI的text-embedding-3-large模型来初始化一个嵌入模型:
embedding_model = OpenAIEmbeddings(model="text-embedding-3-large")
接着,加载我们在之前课程中构建的知识图谱。在实际业务场景中,我们可能面对成千上万个API,直接将所有选项提供给大型语言模型通常因令牌限制和延迟问题而效率低下。因此,我们需要将API选择空间缩小到一个与用户查询相关的小型子集。
为何需要增强检索?
简单的平面检索能在一定程度上减少API数量,但存在两个问题:
- 假阴性问题:有些相关的API可能因为与用户查询的语义相似度不够高,在检索步骤中被遗漏。通过利用知识图谱中的业务流程边进行第二步增强检索,这些API仍然可以被找到。
- 假阳性问题:在检索到的API端点列表之上添加业务流程信息,有助于智能体排除不相关的假阳性结果。
为实体集构建嵌入文本
在构建实体集的嵌入文本之前,我们首先需要从知识图谱中检索每个实体集的所有属性。
以下是一个SPARQL查询示例,用于检索与“采购订单”实体集相关的所有属性:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX aud: <http://example.org/auditor/>
SELECT DISTINCT ?entitySet ?propertyLabel
WHERE {
# 绑定到特定的实体集(例如采购订单)
BIND(aud:PurchaseOrder AS ?entitySet).
# 确保绑定的URI被声明为一个实体集
?entitySet rdf:type aud:EntitySet.
# 获取实体集的名称
?entitySet aud:name ?entitySetName.
# 获取该实体集对应的实体类型
?entitySet aud:hasEntityType ?entityType.
# 获取该实体类型的所有属性及其标签
?entityType aud:hasProperty ?property.
?property aud:label ?propertyLabel.
}
执行此查询后,我们将获得一个字典,其中包含实体集名称及其对应的属性标签列表。
生成嵌入向量并建立索引
接下来,我们将每个实体集及其属性名称连接成一个文本字符串,然后使用嵌入模型将其转换为向量:
# 假设 `entity_texts` 是包含所有实体集文本的列表
embeddings = []
for text in tqdm(entity_texts):
vector = embedding_model.embed_query(text)
embeddings.append(vector)
获得所有嵌入向量后,我们使用FAISS库来建立索引,以便进行高效的相似度搜索:
import faiss
import numpy as np
# 将嵌入向量列表转换为numpy数组
embedding_array = np.array(embeddings).astype('float32')
# 创建FAISS索引(使用L2距离)
index = faiss.IndexFlatL2(embedding_array.shape[1])
index.add(embedding_array)
最后,我们将索引和对应的实体集URI保存到磁盘,供后续使用。
执行查询与初步检索
现在我们已经创建了索引,可以定义一个函数来查找给定查询的最相似实体集:
def find_similar_entities(query, top_k=5):
# 将用户查询转换为嵌入向量
query_embedding = embedding_model.embed_query(query)
query_embedding = np.array([query_embedding]).astype('float32')
# 在索引中搜索最相似的top_k个实体
distances, indices = index.search(query_embedding, top_k)
# 返回对应的实体集URI
return [entity_uris[i] for i in indices[0]]
让我们用一个示例查询来测试:“为采购组002和采购组织3000创建一份购买五支铅笔的采购订单”。
执行此函数后,我们可能会得到一系列与“采购订单”相关的实体集。但需要注意的是,初步检索可能会遗漏“采购申请抬头”这个重要的前置实体集。
利用业务流程边增强检索
为了解决假阴性问题,我们需要从知识图谱中获取与已检索实体集相连的业务流程边。
以下SPARQL查询用于查找与给定实体集有流程依赖关系的其他实体集:
PREFIX pr: <http://example.org/process/>
SELECT DISTINCT ?sourceEntity ?targetEntity ?sourceName ?targetName
WHERE {
{
# 查找以给定实体集为起点的流程边
?sourceEntity pr:hasNext ?targetEntity.
?sourceEntity aud:name ?sourceName.
?targetEntity aud:name ?targetName.
FILTER(?sourceEntity IN (<...URI列表...>))
} UNION {
# 查找以给定实体集为终点的流程边(反向依赖)
?targetEntity pr:hasNext ?sourceEntity.
?sourceEntity aud:name ?sourceName.
?targetEntity aud:name ?targetName.
FILTER(?targetEntity IN (<...URI列表...>))
}
}
执行此查询后,我们可以获得一个扩展的实体集列表,其中包含了通过业务流程连接的相关API。在我们的例子中,“采购申请抬头”就被成功添加进来。
整合:知识图谱增强的API发现流程
现在,我们将平面检索和业务流程依赖检索结合起来,形成一个完整的API发现函数:
def enhanced_api_discovery(user_query, top_k_initial=5):
# 1. 基于嵌入的初步检索
initial_entities = find_similar_entities(user_query, top_k=top_k_initial)
# 2. 获取业务流程依赖
process_entities = get_process_dependencies(initial_entities)
# 3. 合并结果并去重
all_relevant_entities = list(set(initial_entities + process_entities))
# 4. (可选)从图谱中获取这些实体的业务流程信息
business_process_info = get_business_process_info(all_relevant_entities)
return all_relevant_entities, business_process_info
使用相同的示例查询调用此函数,我们现在不仅能得到与“采购订单”相关的实体集,还能获得“采购申请抬头”以及“采购订单依赖于采购申请”这样的业务流程信息。
总结
本节课中我们一起学习了如何利用知识图谱进行API发现:
- 在设计时,我们通过查询知识图谱,将实体集的属性转化为文本表示,并计算其嵌入向量以建立索引。
- 在运行时,发现过程从基于嵌入向量的初步检索开始,得到一个实体集列表。
- 为了弥补初步检索可能遗漏相关API的不足,我们添加了通过业务流程边连接的API(例如,成功添加了“采购申请”)。
- 最后,我们利用知识图谱中的业务流程信息丰富了检索到的实体集,为AI智能体提供了更全面的上下文。


在下一节课中,我们将应用本节构建的发现机制,让AI智能体实际执行API的发现与调用。🚀
006:构建业务流程智能体
概述

在本节课中,我们将学习如何利用上一节课构建的知识图谱,创建一个能够自动发现并执行API以完成用户查询的AI智能体。我们将定义三个核心工具,并演示智能体如何遵循业务流程规则来执行“获取采购订单”和“创建采购订单”等任务。

准备工作
上一节我们介绍了如何基于语义嵌入和业务流程关系从知识图谱中发现相关API。本节中,我们来看看如何利用这些发现来驱动一个智能体。
首先,导入所有必要的包。
# 导入自定义辅助函数,用于参数化SPARQL查询和获取OpenAI API密钥
from helpers import parameterize_sparql_query, fetch_openai_key
接下来,设置我们将要使用的大语言模型和嵌入模型。
# 设置LLM和嵌入模型
llm = ChatOpenAI(model="gpt-4", temperature=0)
embedding_model = OpenAIEmbeddings()
然后,加载我们在前几节课中创建的知识图谱。

# 加载知识图谱
knowledge_graph = load_knowledge_graph("path_to_graph")
定义发现工具
为了定义发现工具,我们需要获取实体集的属性(properties)和导航链接(navigation links)。以下辅助函数负责获取并合并这两类信息。
def fetch_entity_specification(entity_set_name):
"""
获取指定实体集的属性和导航链接。
"""
properties = get_properties(entity_set_name)
navigations = get_navigations(entity_set_name)
return combine_specs(properties, navigations)
让我们用一个示例查询来尝试这个函数。这里我们获取“采购订单”实体集的规范。
# 示例:获取采购订单实体集的规范
po_spec = fetch_entity_specification("PurchaseOrder")
print(po_spec)
在结果中,你会看到:
- 一个服务于“采购订单”的服务。
- 实体集的名称及其属性,例如
PurchasingProcessingStatus(采购处理状态)、PurchasingGroup(采购组)等。 PurchaseOrderNumber是这个实体集的键(key)。- 我们还检索到了该实体集的导航链接,例如与
PurchaseOrderItem的一对多关系,这意味着一个采购订单可以包含多个采购订单项。
现在,我们拥有了定义发现工具所需的所有必要元素。为此,我们首先加载上一课创建的实体集嵌入索引。
# 加载实体集嵌入索引
entity_set_index = load_entity_set_index()
同时,导入之前定义的用于发现API和流程的辅助函数。
from helpers import discover_apis_and_process
回想一下,discover_apis_and_process 函数返回一个匹配的实体集列表及其业务流程信息。
让我们用一个示例查询来测试它。
# 示例:为查询“显示活跃的采购订单”发现API和流程信息
matches = discover_apis_and_process("show me active purchase orders", entity_set_index, knowledge_graph)
print(matches)
在列表中,你可以看到匹配的实体集,包括 PurchaseOrder、PurchaseOrderItem、PurchaseRequisition 和 PurchaseRequisitionItem。此外,我们还检索到流程信息:PurchaseOrder 依赖于 PurchaseRequisition。
效果很好。你现在拥有了工具发现所需的所有关键元素。现在,我们准备将其定义为一个工具,供后续的智能体使用。
from langchain.tools import tool
@tool
def discover_apis_tool(user_query: str) -> str:
"""
发现工具:接收用户的自然语言输入,识别相关实体集,并返回其API规范(包括业务流程信息)。
"""
relevant_entities = discover_apis_and_process(user_query, entity_set_index, knowledge_graph)
return format_api_specs(relevant_entities)
准备API执行(模拟服务)
现在我们有了发现工具,接下来为API执行做准备,这里使用模拟服务。
我们导入用于获取、提交和显示模拟数据服务的辅助函数。
from mock_services import get_mock_data, post_mock_data, display_mock_db
首先,查看模拟数据库的内容。先看采购申请。
# 显示采购申请模拟数据
display_mock_db("PurchaseRequisition")
你会看到有两个采购申请,编号分别以1和2结尾。第一个采购申请有一个“尺子”的物料项,第二个采购申请有两个物料项(编号10和20),分别是“铅笔”和“钢笔”。
现在,看看采购订单数据集是什么样的。
# 显示采购订单模拟数据
display_mock_db("PurchaseOrder")
这里我们有三个采购订单,编号以1、2、3结尾,每个订单对应特定数量的“尺子”、“铅笔”和“钢笔”。需要注意的是,采购订单中的每个物料项都引用了采购申请中对应的物料项。例如,PurchaseOrder1 的物料项10引用了上面看到的 PurchaseRequisition1 的物料项10。同样,PurchaseOrder2 的物料项10引用了 PurchaseRequisition2 的物料项10(对应铅笔)。
让我们看看用于提交数据的模拟服务。
# 模拟提交采购订单
new_po = post_mock_data(service="PurchaseOrder", payload={"items": [{"material": "mouse"}, {"material": "keyboard"}]})
print(new_po)
对于与采购订单实体集相关的服务,这个特定函数会向采购订单API发起一次调用,包含物料项级别的请求,执行此调用,并返回新创建的采购订单(在这个例子中,是编号以4结尾的采购订单)。与之前的结果相比,我们现在有了一个新的采购订单,以及调用中请求的两个新物料项“鼠标”和“键盘”。
接下来,调用获取数据的模拟函数来检索符合特定条件的第一个采购订单。
# 模拟获取采购订单数据
filter_criteria = "PurchasingGroup eq '005' and PurchasingOrganization eq '3000'"
result = get_mock_data(service="PurchaseOrder", filter_string=filter_criteria)
print(result)
这个函数显示了对服务的OData调用,匹配感兴趣的过滤条件,并返回匹配的采购订单(在本例中,是第一个采购订单,其采购组和采购组织符合请求)。
现在你知道了这两个模拟函数的作用,让我们为智能体定义工具。
@tool
def get_data_tool(service_name: str, filter_string: str) -> str:
"""获取数据工具:用于执行GET请求,例如处理与获取采购订单相关的查询。"""
return get_mock_data(service_name, filter_string)
@tool
def post_data_tool(service_name: str, payload: dict) -> str:
"""提交数据工具:用于执行POST请求,例如基于知识图谱中的业务流程信息创建采购申请和采购订单。"""
return post_mock_data(service_name, payload)
创建并运行智能体
我们现在拥有了所有必要的构建模块。接下来开始创建智能体。
我们将使用LangChain预定义的智能体循环(Agent Loop)。

from langchain.agents import create_react_agent, AgentExecutor
现在,你需要做的就是提供之前定义的工具以及提示词(prompt)。
在提示词中,我们告诉智能体:基于用户查询发现API和业务流程信息,然后根据业务流程调用API。我们还必须告诉智能体如何使用导航链接在单次调用中创建抬头(header)和行项目(item)级别的对象。

# 定义智能体提示词
agent_prompt = """
你是一个能够发现并执行API的助手。
首先,使用发现工具来查找与用户查询相关的API及其业务流程信息。
然后,根据发现的业务流程规则,调用相应的GET或POST数据工具来执行操作。
特别注意:当创建涉及抬头和行项目的对象(如采购订单)时,请利用API规范中的导航属性,在单个API调用中构建完整的嵌套结构。
始终遵循业务流程中定义的依赖关系(例如,创建采购订单前需先创建采购申请)。
用户查询:{input}
"""
现在,让我们把所有东西整合在一起。我们提供之前定义的工具以及刚刚准备的提示词。
# 创建智能体
tools = [discover_apis_tool, get_data_tool, post_data_tool]
agent = create_react_agent(llm=llm, tools=tools, prompt=agent_prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
让我们用一些示例查询来尝试运行这个智能体。
第一个查询与获取活跃采购订单有关。
# 示例查询1:获取活跃采购订单
result1 = agent_executor.invoke({"input": "Show me active purchase orders for purchasing group 005 and organization 3000"})
print(result1['output'])
如你所见,智能体首先使用查询调用 discover_apis_tool,获取匹配的API实体集列表及其属性、导航链接,并最终确定流程信息。然后,它调用 get_data_tool,传入与采购订单相关的服务名称,并直接传递用户查询中的过滤字符串(在本例中,它寻找处理状态为“active”的采购订单)。随后它报告说,在该特定采购组和采购组织中,没有活跃的采购订单。
这里,模型使用了字面值“active”,而不是对应的技术状态码(如“02”),因此它无法获取到活跃的采购订单。
我们可以灵活地添加所谓的“固定值帮助映射”,将状态描述映射到状态码。现在让我们把这个添加到知识图谱中。
# 向知识图谱添加状态码映射
status_mappings = [
{"description": "In Process", "code": "01"},
{"description": "Active", "code": "02"},
{"description": "Completed", "code": "03"}
]
add_fixed_values_to_graph(knowledge_graph, "PurchaseOrder", "PurchasingProcessingStatus", status_mappings)
这里我们添加了一组相关的状态码,例如“01”代表处理中,“02”代表活跃等,并将其关联到采购订单实体集,最终添加到图谱中。
现在,让我们尝试用智能体再次运行相同的查询。
# 再次运行相同的查询
result1_updated = agent_executor.invoke({"input": "Show me active purchase orders for purchasing group 005 and organization 3000"})
print(result1_updated['output'])
这次,智能体成功地将采购处理状态映射到了“02”,而不是之前的“active”,现在能够正确找到两个处于活跃状态的采购订单。这展示了知识图谱提供的灵活性:它可以动态地使用相应的业务条目扩展图谱,并将它们映射到智能体的用例中。
现在,让我们看另一个更复杂一点的例子,这次是关于创建采购订单。

# 示例查询2:创建采购订单
result2 = agent_executor.invoke({"input": "Create a purchase order for 5 laptops, referring to a new requisition"})
print(result2['output'])


在这里,智能体必须确定需要先创建一个采购申请,然后创建一个引用该采购申请的采购订单。

如你所见,智能体首先进行发现,获取正确的API及其属性、导航和业务流程信息规范。这次,它识别出应该使用业务流程信息,即创建采购订单前应先创建采购申请。因此,它首先调用 post_data_tool,服务名称为“PurchaseRequisition”,在单个有效负载中创建了采购申请。然后,以此作为参考,再次调用 post_data_tool,使用采购订单API,创建了一个新的编号以5结尾的采购订单,引用了新创建的采购申请(Ref3)。
让我们查看一下模拟数据库,看看最后一次调用后发生了什么变化。
# 查看更新后的采购申请数据
display_mock_db("PurchaseRequisition")
你可以看到一个新的编号以3结尾的采购申请及其物料项10。
# 查看更新后的采购订单数据
display_mock_db("PurchaseOrder")
这里有一个新的编号以5结尾的采购订单。重要的是,它引用了刚刚创建的编号以3结尾的采购申请。这基本上证明了智能体遵守了业务流程规则:创建采购订单前必须先创建采购申请。
总结智能体工作流
让我们用最后一个关于创建采购订单的例子来总结智能体的工作流。
- 用户输入:用户输入被传递给智能体。
- 发现API:智能体决定调用发现工具,以查找与给定用户输入相关的API和流程信息。
- 查询知识库:发现工具调用向量数据库(本例中只是一个本地内存索引)来检索相关的实体集。
- 获取元数据:该工具查询知识图谱以获取业务流程信息、其他相关实体集及其元数据。
- 信息返回:所有这些信息都返回给智能体。
- 决策与执行:智能体拥有所有相关信息后,决定首先需要调用POST API来创建采购申请。它调用相应的
post_data_tool,执行API,并将新创建的采购申请返回给智能体。 - 最终执行:最后,智能体再次执行POST API,创建一个引用新采购申请的采购订单,并将结果返回。
本节课总结

在本节课中,我们一起学习了如何构建一个业务流程驱动的AI智能体。我们定义了三个核心工具:发现工具、获取数据工具和提交数据工具。智能体能够理解用户的自然语言查询,利用知识图谱自动发现相关的API和业务流程规则,并正确地按顺序执行这些API来完成任务,例如先创建采购申请再创建采购订单。我们还看到了知识图谱的灵活性,例如通过添加固定值映射来帮助智能体更准确地理解业务术语。通过这种方式,我们实现了从知识发现到自动化执行的完整闭环。
007:课程总结 🎓
在本节课中,我们将对《用于AI智能体API发现的知识图谱》这门课程进行总结,回顾所学到的核心知识与技能。
恭喜你完成本课程。你学习了知识图谱如何为企业数据带来结构和意义。
上一节我们介绍了知识图谱的实际应用,本节中我们来看看其核心价值。知识图谱连接了API与业务流程,为AI智能体提供了相关的业务上下文。
你学习了如何利用知识图谱,帮助智能体更智能地发现API并与之协作,从而执行具体操作。
现在,你已经掌握了坚实的基础,可以构建能够在真实企业环境中工作的AI智能体。


从这里出发,尝试将所学知识应用于你自己的数据。进行测试并探索知识图谱如何助力你的AI应用。
再次感谢你的参与。我们期待看到你未来的构建成果。😊
本节课中我们一起学习了知识图谱在构建智能AI智能体中的关键作用,包括如何为数据赋予结构、连接不同业务组件,以及为智能体提供行动所需的上下文。你已准备好将这些概念付诸实践。

浙公网安备 33010602011771号