Graphite:事件驱动的AI代理框架(graphite:事件驱动的ai代理框架在哪里)
ccwgpt 2025-05-11 14:33 24 浏览 0 评论
我们在之前的帖子中提到过这个产品,我们很自豪地宣布,我们现在已经在 GitHub 上开放了Graphite的源代码!如果喜欢的话,请在那里给它点个星!
你可能会想,“已经有了像ChatGPT、Claude以及各种代理平台和框架的AI解决方案,为什么还要再做一个?” 简短的回答是:我们发现了解决现实世界问题时存在空白。许多通用代理——比如典型的ReAct或CoT代理——在任务关键型任务中表现不佳,而这些任务中错误的成本可能很高。
Graphite 提供了一个简单且可控的工作流构建框架,不仅可以让大型语言模型(LLMs)推理和规划,还可以在定义明确、可审计且易于恢复的工作流中运行。它还内置了诸如可观察性、幂等性和可审计性等重要功能。
在这篇文章中,我们将简要介绍Graphite,从其架构到关键特性,并提供一个简单的示例:使用Graphite构建一个“了解你的客户”(KYC)AI助手。
1、架构:简单、强大且可组合
Graphite 被划分为三个概念层——助手、节点和工具:
- 助手负责协调工作流并管理对话状态。
- 节点封装离散逻辑,每个节点专门执行特定功能(例如调用LLM或执行函数)。
- 工具是纯函数,负责执行任务,例如调用API或运行Python函数。
此外,Graphite 使用事件溯源模式记录每次状态变化。每当助手、节点或工具被调用、响应或失败时,都会生成相应的事件并存储在事件存储中。
命令模式通过定义良好的命令对象和处理程序将请求发起者与执行者清晰分离。这些命令携带所有必要的上下文,使节点能够以自我包含和简单的方式调用工具。
节点通过轻量级的发布/订阅式工作流编排机制进行协调。
- 工作流使用发布/订阅模式并通过内存消息队列协调节点之间的交互。
这种架构解锁了即插即用的模块化——你可以像拼搭乐高积木一样构建工作流,添加或移除节点,并以外科手术般的精确度隔离故障。
2、特性:让Graphite脱颖而出
上述引入的核心设计原则展示了Graphite与其他代理框架的不同之处:
- 简单的三层执行模型
三个独立的层次——助手、节点和工具——管理执行,而专门的工作流层负责协调。 - 基于发布/订阅的事件驱动编排
通信依赖于发布和订阅事件,确保系统中数据流动的解耦和模块化。 - 事件作为单一事实来源
所有操作状态和转换都被记录为事件,提供了一种统一的方式来跟踪和重放系统行为,如有必要。
结合这些元素,Graphite 提供了一个生产级别的AI应用程序框架,能够在大规模下可靠运行,优雅地处理故障,并维护用户和利益相关者的信任。四个核心能力构成了这一方法的基础:
- 可观察性
复杂的AI解决方案涉及多个步骤、数据源和模型。Graphite 的事件驱动架构、日志记录和跟踪使得实时识别瓶颈或错误成为可能,确保每个组件的行为透明且可测量。 - 幂等性
异步工作流在部分失败发生或网络条件波动时通常需要重试。Graphite 的设计强调幂等操作,防止重复调用时出现数据重复或损坏。 - 可审计性
通过将事件视为单一事实来源,Graphite 自动记录每个状态变化和决策路径。这种详细的记录对于在受监管行业工作的用户或需要全面可追溯性以进行调试和合规性检查的用户来说是不可或缺的。 - 可恢复性
长时间运行的AI任务如果在执行过程中失败,可能会导致大量返工。在Graphite中,检查点和基于事件的回放使工作流能够从中断的确切位置恢复,最大限度地减少停机时间和资源效率。
这些能力——可观察性、幂等性、可审计性和可恢复性——共同使Graphite成为一个构建稳健且可信的AI应用的框架。以下是Graphite如何实现每项功能的详细分解。
3、展示代码:KYC助手
在设计基于AI的工作流时,请记住大型语言模型引入了不确定性。遵循奥卡姆剃刀原则是有帮助的,这意味着工作流越简单越好。
3.1 设计工作流
假设你想为健身注册流程创建一个“了解你的客户”(KYC)助手,并具有人类在环(HITL)功能。用户必须提供他们的全名和电子邮件地址才能完成注册工作流。如果缺少任何信息,工作流会暂停并要求客户提供更多信息。显然,现实世界的问题需要更多细节,但在这里我们简化它以进行演示。
3.2 构建助手
首先,从pip安装Graphite
pip install grafi
从上面的工作流图中,我们需要添加以下组件:
7个主题:
- 助手输入主题(框架提供)
from grafi.common.topics.topic import agent_input_topic
- 用户信息提取主题
user_info_extract_topic = Topic(name="user_info_extract_topic")
- 人类调用主题
hitl_call_topic = Topic(
name="hitl_call_topic",
condition=lambda msgs: msgs[-1].tool_calls[0].function.name
!= "register_client",
)
- 人类在环主题(框架提供)
from grafi.common.topics.human_request_topic import human_request_topic
- 注册用户主题
register_user_topic = Topic(
name="register_user_topic",
condition=lambda msgs: msgs[-1].tool_calls[0].function.name
== "register_client",
)
- 注册用户响应主题
register_user_respond_topic = Topic(name="register_user_respond")
- 助手输出主题(框架提供)
from grafi.common.topics.output_topic import agent_output_topic
5个节点:
- LLM节点 [用户信息提取节点] 用于从用户输入中提取姓名和电子邮件
user_info_extract_node = (
LLMNode.Builder()
.name("ThoughtNode")
.subscribe(
SubscriptionBuilder()
.subscribed_to(agent_input_topic)
.or_()
.subscribed_to(human_request_topic)
.build()
)
.command(
LLMResponseCommand.Builder()
.llm(
OpenAITool.Builder()
.name("ThoughtLLM")
.api_key(self.api_key)
.model(self.model)
.system_message(self.user_info_extract_system_message)
.build()
)
.build()
)
.publish_to(user_info_extract_topic)
.build()
)
- LLM节点 [动作节点] 根据提取的信息创建动作
action_node = (
LLMNode.Builder()
.name("ActionNode")
.subscribe(user_info_extract_topic)
.command(
LLMResponseCommand.Builder()
.llm(
OpenAITool.Builder()
.name("ActionLLM")
.api_key(self.api_key)
.model(self.model)
.system_message(self.action_llm_system_message)
.b构建()
)
.build()
)
.publish_to(hitl_call_topic)
.publish_to(register_user_topic)
.build()
)
- 功能工具节点 [human-in-the-loop] 用于请求用户补充信息(如有缺失)
human_request_function_call_node = (
LLMFunctionCallNode.Builder()
.name("HumanRequestNode")
.subscribe(hitl_call_topic)
.command(
FunctionCallingCommand.Builder()
.function_tool(self.hitl_request)
.build()
)
.publish_to(human_request_topic)
.build()
)
- 功能工具节点 [register user] 用于注册客户端
register_user_node = (
LLMFunctionCallNode.Builder()
.name("FunctionCallRegisterNode")
.subscribe(register_user_topic)
.command(
FunctionCallingCommand.Builder()
.function_tool(self.register_request)
.build()
)
.publish_to(register_user_respond_topic)
.build()
)
- LLM 节点 [response to user] 用于起草最终的用户回复
user_reply_node = (
LLMNode.Builder()
.name("LLMResponseToUserNode")
.subscribe(register_user_respond_topic)
.command(
LLMResponseCommand.Builder()
.llm(
OpenAITool.Builder()
.name("ResponseToUserLLM")
.api_key(self.api_key)
.model(self.model)
.system_message(self.summary_llm_system_message)
.build()
)
.build()
)
.publish_to(agent_output_topic)
.build()
)
以下是源代码链接——KYC助手
接下来让我们编写一个简单的代码来测试它:
import json
import uuid
from kyc_assistant import KycAssistant
from grafi.common.decorators.llm_function import llm_function
from grafi.common.models.execution_context import ExecutionContext
from grafi.common.models.message import Message
from grafi.tools.functions.function_tool import FunctionTool
class ClientInfo(FunctionTool):
@llm_function
def request_client_information(self, question_description: str):
"""
根据给定的问题描述,请求用户输入个人信息。
"""
return json.dumps({"question_description": question_description})
class RegisterClient(FunctionTool):
@llm_function
def register_client(self, name: str, email: str):
"""
根据姓名和电子邮件注册用户。
"""
return f"用户 {name},邮箱 {email} 已成功注册。"
user_info_extract_system_message = """
"您是一个严格的验证器,用于检查给定的输入是否包含用户的全名和电子邮件地址。您的任务是分析输入并确定是否同时存在全名(名字和姓氏)和有效的电子邮件地址。
### 验证标准:
- **全名**:输入应至少包含两个词,类似于名字和姓氏。忽略常见的占位符(例如“John Doe”)。
- **电子邮件地址**:输入应包括有效的电子邮件格式(例如 example@domain.com)。
- **不区分大小写**:电子邮件验证应不区分大小写。
- **准确性**:避免误报,确保随机文本、用户名或部分名称不会触发验证。
- **输出**:如果同时存在全名和电子邮件,则输出“Valid”,否则输出“Invalid”。可选地,提供输入无效的原因。
### 示例响应:
- **输入**:"John Smith, john.smith@email.com" → **输出**:"Valid"
- **输入**:"john.smith@email.com" → **输出**:"Invalid - 缺少全名"
- **输入**:"John" → **输出**:"Invalid - 缺少全名和电子邮件"
严格遵循这些验证规则,并不要假设缺少的细节。"
"""
def get_execution_context():
return ExecutionContext(
conversation_id="conversation_id",
execution_id=uuid.uuid4().hex,
assistant_request_id=uuid.uuid4().hex,
)
def test_kyc_assistant():
execution_context = get_execution_context()
assistant = (
KycAssistant.Builder()
.name("KycAssistant")
.api_key(
"YOUR_OPENAI_API_KEY"
)
.user_info_extract_system_message(user_info_extract_system_message)
.action_llm_system_message(
"根据请求选择最合适的工具。"
)
.summary_llm_system_message(
"以结果形式响应用户注册情况。如果成功,响应中必须包含'registered'。"
)
.hitl_request(ClientInfo(name="request_human_information"))
.register_request(RegisterClient(name="register_client"))
.build()
)
while True:
# 初始用户输入
user_input = input("用户: ")
input_data = [Message(role="user", content=user_input)]
output = assistant.execute(execution_context, input_data)
responses = []
for message in output:
try:
content_json = json.loads(message.content)
responses.append(content_json["question_description"])
except json.JSONDecodeError:
responses.append(message.content)
respond_to_user = " 和 ".join(responses)
print("助手:", respond_to_user)
if "registered" in output[0].content:
break
if __name__ == "__main__":
test_kyc_assistant()
3.3 测试、观察、调试和改进
Graphite 使用 OpenTelemetry 和 Arize 的 OpenInference 来跟踪和观察助手的行为。
要本地捕获跟踪,我们可以启动本地的 phoenix。
phoenix serve
以下是一个用户与助手之间的对话示例:
> 用户: 你好,我想在你们的健身房注册。你能帮我完成这个过程吗?
> 助手: 请提供您的全名和电子邮件地址以注册健身房。
> 用户: 我的名字是Craig Li,我的电子邮件是craig@example.com
> 助手: 恭喜你,Craig!你现在已成功注册我们的健身房。如果您有任何问题或需要帮助,请随时联系!
看起来不错。但是,如果你对测试进行扩展,很快就会遇到错误。例如:
> 用户: 你好,今天过得怎么样?
会发生错误,当我们使用 Phoenix 进行调试时,可以精确定位其位置:
问题源于 Action LLM。给定输入后,它应该选择适当的工具,但相反,它生成了一个普通的字符串响应。
为了解决这个问题,我们可以提供明确的指令:如果用户询问与健身房注册无关的问题,LLM 应该使用
request_client_information 工具礼貌地回应,并询问他们是否需要帮助进行健身房注册。
因此,让我们更新 action LLM 系统提示:
.action_llm_system_message(
"根据请求选择最合适的工具。如果用户询问与健身房注册无关的问题,LLM 应该使用 `request_client_information` 工具礼貌地回应,并询问他们是否需要帮助进行健身房注册。"
)
然后再次尝试:
> 用户: 你好,今天过得怎么样?
> 助手: 我在这里协助您完成健身房注册。请提供您的全名和电子邮件。
你现在已经建立了一个可以帮助完成健身房注册的助手!你可以在这里找到助手的代码 链接,示例代码可以在 这里 找到。
4、结束语
Graphite 是一个开源框架,通过可组合的事件驱动工作流构建领域特定的 AI 助手。
通过松散耦合的组件——助手、节点、工具和工作流,Graphite 实现了模块化设计,其中事件作为单一的真实来源。其架构支持复杂的逻辑,如 LLM 调用、函数执行和 RAG 检索,所有这些都通过专用的发布/订阅主题和命令协调。内置的支持可观测性、幂等性、可审计性和可恢复性使其生产就绪,允许工作流扩展、恢复并适应合规需求。
无论是构建会话代理还是自动化管道,Graphite 都提供了灵活且可扩展的基础,用于实际的 AI 系统。
相关推荐
- 一个基于.Net Core遵循Clean Architecture原则开源架构
-
今天给大家推荐一个遵循CleanArchitecture原则开源架构。项目简介这是基于Asp.netCore6开发的,遵循CleanArchitecture原则,可以高效、快速地构建基于Ra...
- AI写代码翻车无数次,我发现只要提前做好这3步,bug立减80%
-
写十万行全是bug之后终于找到方法了开发"提示词管理助手"新版本那会儿,我差点被bug整崩溃。刚开始两周,全靠AI改代码架构,结果十万行程序漏洞百出。本来以为AI说没问题就稳了,结果...
- OneCode低代码平台的事件驱动设计:架构解析与实践
-
引言:低代码平台的事件驱动范式在现代软件开发中,事件驱动架构(EDA)已成为构建灵活、松耦合系统的核心范式。OneCode低代码平台通过创新性的注解驱动设计,将事件驱动理念深度融入平台架构,实现了业务...
- 国内大厂AI插件评测:根据UI图生成Vue前端代码
-
在IDEA中安装大厂的AI插件,打开ruoyi增强项目:yudao-ui-admin-vue31.CodeBuddy插件登录腾讯的CodeBuddy后,大模型选择deepseek-v3,输入提示语:...
- AI+低代码技术揭秘(二):核心架构
-
本文档介绍了为VTJ低代码平台提供支持的基本架构组件,包括Engine编排层、Provider服务系统、数据模型和代码生成管道。有关UI组件库和widget系统的信息,请参阅UI...
- GitDiagram用AI把代码库变成可视化架构图
-
这是一个名为gitdiagram的开源工具,可将GitHub仓库实时转换为交互式架构图,帮助开发者快速理解代码结构。核心功能一键可视化:替换GitHubURL中的"hub...
- 30天自制操作系统:第六天:代码架构整理与中断处理
-
1.拆开bootpack.c文件。根据设计模式将对应的功能封装成独立的文件。2.初始化pic:pic(可编程中断控制器):在设计上,cpu单独只能处理一个中断。而pic是将8个中断信号集合成一个中断...
- AI写代码越帮越忙?2025年研究揭露惊人真相
-
近年来,AI工具如雨后春笋般涌现,许多人开始幻想程序员的未来就是“对着AI说几句话”,就能轻松写出完美的代码。然而,2025年的一项最新研究却颠覆了这一期待,揭示了一个令人意外的结果。研究邀请了16位...
- 一键理解开源项目:两个自动生成GitHub代码架构图与说明书工具
-
一、GitDiagram可以一键生成github代码仓库的架构图如果想要可视化github开源项目:https://github.com/luler/reflex_ai_fast,也可以直接把域名替换...
- 5分钟掌握 c# 网络通讯架构及代码示例
-
以下是C#网络通讯架构的核心要点及代码示例,按协议类型分类整理:一、TCP协议(可靠连接)1.同步通信//服务器端usingSystem.Net.Sockets;usingTcpListene...
- 从复杂到优雅:用建造者和责任链重塑代码架构
-
引用设计模式是软件开发中的重要工具,它为解决常见问题提供了标准化的解决方案,提高了代码的可维护性和可扩展性,提升了开发效率,促进了团队协作,提高了软件质量,并帮助开发者更好地适应需求变化。通过学习和应...
- 低代码开发当道,我还需要学习LangChain这些框架吗?| IT杂谈
-
专注LLM深度应用,关注我不迷路前两天有位兄弟问了个问题:当然我很能理解这位朋友的担忧:期望效率最大化,时间用在刀刃上,“不要重新发明轮子”嘛。铺天盖地的AI信息轰炸与概念炒作,很容易让人浮躁与迷茫。...
- 框架设计并不是简单粗暴地写代码,而是要先弄清逻辑
-
3.框架设计3.框架设计本节我们要开发一个UI框架,底层以白鹭引擎为例。框架设计的第一步并不是直接撸代码,而是先想清楚设计思想,抽象。一个一个的UI窗口是独立的吗?不是的,...
- 大佬用 Avalonia 框架开发的 C# 代码 IDE
-
AvalonStudioAvalonStudio是一个开源的跨平台的开发编辑器(IDE),AvalonStudio的目标是成为一个功能齐全,并且可以让开发者快速使用的IDE,提高开发的生产力。A...
- 轻量级框架Lagent 仅需20行代码即可构建自己的智能代理
-
站长之家(ChinaZ.com)8月30日消息:Lagent是一个专注于基于LLM模型的代理开发的轻量级框架。它的设计旨在简化和提高这种模型下代理的开发效率。LLM模型是一种强大的工具,可以...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- mfc框架 (52)
- abb框架断路器 (48)
- beego框架 (52)
- java框架spring (58)
- grpc框架 (65)
- tornado框架 (48)
- 前端框架bootstrap (54)
- orm框架有哪些 (51)
- 知识框架图 (52)
- ppt框架 (55)
- 框架图模板 (59)
- 内联框架 (52)
- cad怎么画框架 (58)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)