借助AI助手快速解析LlamaIndex的Workflow设计与Java迁移
在前面的讨论中,我们通过AI助手快速浏览并分析了LlamaIndex的核心源码及其可视化部分。在上次的工作中,我们已基本完成了使用Java版本实现的可视化部分,尽管在工作流(workflow)的分析上只是进行了初步探讨。今天,我们将深入探讨一个关键问题:能否将LlamaIndex在Python中的业务流程和核心代码,成功迁移并转化为Java版本。
接下来,我们将直接进入正题。首先,我们回顾一下LlamaIndex的整体架构和核心功能,然后着手进行Java版本的开发实现。
Workflow
可能大家已经有些遗忘了之前的细节,因此仅通过文字描述并记录下来,可能无法像可视化图示那样快速有效地帮助我们回忆起关键内容。为了更清晰地梳理思路,并帮助大家更直观地理解和回顾,我绘制一张简要的总结框架图。
简要总结框架图
首先,我们将从一个简洁的角度,回顾几个关键的核心类,并详细分析它们各自的属性和方法。如图所示:

剩下的部分就是至关重要的业务流程类 workflow 了。为了确保我们对整体业务流程有一个清晰的认知,我们可以先对业务流程进行一个简要的梳理。这里不需要过多关注细节,细节部分可以通过查看源码来进一步探讨。

好的,接下来我们将逐一通过AI助手来帮助我们完成代码转化的工作。虽然我们清楚地知道,AI的输出可能无法达到100%的完美效果,但即便如此,借助AI的辅助,至少可以大幅度提高效率,预计能够节省大约50%的编码时间。我们现在就开始吧。
设计
Event
同样直接询问助手即可。

接下来,我将根据AI助手提供的初步方案进行进一步的优化和调整。得到最终结果代码如下:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public abstract class ToolEvent {
/**
* 事件id
*/
private String eventId;
/**
* 事件name
*/
private String eventName;
/**
* 存储各节点数据,并暴露出方法供其他人调用
*/
private Map<String,Object> eventData = new HashMap<>();
public ToolEvent(Map<String, Object> params) {
this.eventData.putAll(params);
}
public Object get(String key) {
key = this.getClass().getSimpleName() + "." + key;
if (this.eventData.containsKey(key)) {
return this.eventData.get(key);
} else {
throw new IllegalArgumentException("No such key: " + key);
}
}
public void set(String key, Object value) {
key = this.getClass().getSimpleName() + "." + key;
this.eventData.put(key, value);
}
public boolean containsKey(String key) {
key = this.getClass().getSimpleName() + "." + key;
return this.eventData.containsKey(key);
}
public Set<String> keySet() {
return this.eventData.keySet();
}
public Collection<Object> values() {
return this.eventData.values();
}
public Set<Map.Entry<String, Object>> entrySet() {
return this.eventData.entrySet();
}
public int size() {
return this.eventData.size();
}
public boolean isEmpty() {
return this.eventData.isEmpty();
}
public void clear() {
this.eventData.clear();
}
public Map<String, Object> toMap() {
return this.eventData;
}
/**
* eventName默认为类名
*/
public String getEventName() {
if (this.eventName == null) {
this.eventName = this.getClass().getSimpleName();
}
return this.eventName;
}
}
可以看到,在此代码中我实现的是一个最基础的版本。我们并不打算在初期阶段实现所有功能,而是先着手于构建一个简化版的工作流系统。这样做的目的是先实现一个基础的可运行版本,再在此基础上进行优化和改进,以便最终得到一个更加高效且符合需求的解决方案。
接下来,实现工作流中的开始节点和结束节点的生成,这一过程同样相对简单。以下是相应的代码实现:
@Data
@NoArgsConstructor
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class StartEvent extends ToolEvent {
private String eventName = "start";
public StartEvent(Map<String, Object> params) {
super(params);
}
}
@Data
@NoArgsConstructor
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class StopEvent extends ToolEvent {
private String eventName = "end";
/**
* 结果返回
*/
private String result;
public StopEvent(String params) {
result = params;
}
}
LlamaIndex的事件封装了很多其他功能和细节,这些内容虽然很有用,但在当前阶段我们先不深入探讨。
Step注解
然后我们看下注解,这部分也可以询问下AI助手,如图所示:

不过Python的装饰器并不和Java注解一样,所以我们先来自己实现一下。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Step {
// String eventName();
Class<? extends ToolEvent>[] acceptedEvents();
int numWorkers() default 10;
// Class<?>[] returnTypes();
// RetryPolicy retryPolicy() default RetryPolicy.DEFAULT;
}
workflow
接下来,我们将着手实现工作流的主要流程。这一部分相对较为复杂,主要因为涉及的业务流程非常庞大且复杂,因此需要一定的时间和精力进行处理。为了简化我们的工作,首先我们可以参考AI助手的实现方式,通过分析其设计思路和工作原理,帮助我们更好地理解如何进行具体的实现。
在此基础上,我们再根据实际需求对流程进行必要的裁剪和优化。如下图所示:

最后,这部分代码有些多,我就简单的将主要流程写下来。代码如下:
@Data
@Slf4j
public abstract class Workflow {
/**
* 工作流超时时间
*/
private int timeout = 10;
/**
* 是否输出详细日志
*/
private boolean verbose = false;
/**
* 校验开关
*/
private boolean validation = false;
/**
* 校验开关
*/
private boolean showUI = false;
/**
* 1:扫描当前类的所有带有 @Step 注解的方法
* 2:根据步骤顺序,依次执行各个步骤
*/
public String run(String jsonString) throws IOException{}
/**
*初始化工作流
*/
private WorkflowContext initialContext() {}
WorkflowContext
最关键的因素在于工作流上下文的设计,因为在这种架构下,所有节点都能够共享全局变量。这一特性保证了工作流中不同节点之间的数据传递和协调,从而提高了整个系统的灵活性和便利性。如果没有这样的共享机制,工作流的效率和可操作性将大大降低,失去其原本的优势。
我们先去询问下AI助手如何实现。如图所示:

由于LlamaIndex提供了许多功能,因此其实现显得相对复杂。为了简化开发过程,我们决定剔除一些不必要的功能,比如类的序列化,这一功能主要用于恢复和加载工作流。然而,我们的目标是实现一个最基本且可行的工作流。最终代码如下:
@Slf4j
@Data
public class WorkflowContext {
/**
* 是否是单步模式
*/
private boolean stepwise;
/**
* 是否正在运行
*/
private boolean isRunning;
/**
* 当前运行的事件
*/
private ToolEvent stepEventHolding;
/**
* 事件队列:k:方法名,v:队列
*/
private Map<String, ArrayBlockingQueue<ToolEvent>> eventQueue;
private List<Thread> tasks = new ArrayList<>();
private Map<String,Object> globalContext;
private String result;
//画图
private Graph graph = new MultiGraph("workflow");
public WorkflowContext(boolean stepwise){
System.setProperty("org.graphstream.ui", "swing");
this.stepwise = stepwise;
this.isRunning = false;
this.eventQueue = new ConcurrentHashMap<>();
this.stepEventHolding = null;
this.globalContext = new ConcurrentHashMap<>();
this.result = null;
//添加开始和结束节点
Node nodeA = graph.addNode("start");
Node nodeB = graph.addNode("end");
}
public void addThread(Thread thread) {
tasks.add(thread);
}
public void sendEvent(ToolEvent value) {}
我们去除了一些东西,加了一个上一章节我们讨论的流的可视化。并且需要实现发布事件功能。
WorkflowHandler
最后加一个处理类,同样直接问一下AI助手,帮助我们去实现一下基本业务逻辑,如图所示:

然后我把所有没有用的逻辑全都去除掉,最后剩下这些代码,如下所示:
@Slf4j
@Data
@AllArgsConstructor
public class WorkflowHandler {
private WorkflowContext context;
public void handleTask(int timeout){}
接下来,我们需要填充基本的业务逻辑部分,这一阶段的工作主要涉及实现具体的功能和处理流程,确保工作流能够按照预期正常运行。由于这部分代码涉及到特定的业务需求和内部实现细节,因此暂时不公开。工作流启动日志如下:

最终的效果如图所示:

总结
通过以上的分析和实践,我们成功地对LlamaIndex的核心功能进行了回顾,并逐步将其Python版的业务流程和核心代码迁移到Java实现。尽管在过程中遇到了一些挑战,如工作流的复杂性、事件和注解的差异等,但借助AI助手的辅助,我们能够高效地完成了代码转换和初步实现。
接下来的步骤,将是基于当前实现,进一步完善各个模块,优化工作流的执行效率,提升系统的可靠性和扩展性。
我是努力的小雨,一名 Java 服务端码农,潜心研究着 AI 技术的奥秘。我热爱技术交流与分享,对开源社区充满热情。同时也是一位腾讯云创作之星、阿里云专家博主、华为云云享专家、掘金优秀作者。
我将不吝分享我在技术道路上的个人探索与经验,希望能为你的学习与成长带来一些启发与帮助。
欢迎关注努力的小雨!
借助AI助手快速解析LlamaIndex的Workflow设计与Java迁移的更多相关文章
- 最佳案例 | 游戏知几 AI 助手的云原生容器化之路
作者 张路,运营开发专家工程师,现负责游戏知几 AI 助手后台架构设计和优化工作. 游戏知几 随着业务不断的拓展,游戏知几AI智能问答机器人业务已经覆盖了自研游戏.二方.海外的多款游戏.游戏知几研发团 ...
- 微软推出中文学习AI助手Microsoft Learn Chinese
编者按:美国总统特朗普访华期间,他6岁的外孙女阿拉贝拉用中文普通话演唱和背诵传统诗歌的视频在中国社交媒体上引起广泛关注,可以感受得到,越来越多的人对中文学习充满了兴趣.智能私教微软小英帮助很多中国 ...
- 利用android studio gsonformat插件快速解析复杂json
在android开发过程中,难免会遇到json解析,在这篇文章中为你快速解析复杂的json. 首先,在android studio中安装gsonformat插件. 点击File->Setting ...
- [Swift通天遁地]七、数据与安全-(2)对XML和HTML文档的快速解析
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- 1.svn 彻底clear时,注意代码备份 2.借助vc助手加头文件
1.svn 彻底clear时,注意代码备份 2.不小心彻底clear可以在回收站找到 3.借助vc助手加头文件
- Ubuntu下借助URLOS实现快速安装DzzOffice企业办公套件
如今,越来越多的个人.团队甚至企业都在使用GSuite或者Office365等网络办公套件,为什么人们越来越喜爱使用网络办公套件?一方面是考虑数字资产的安全性以及管理效率,另一方面则是日益增大的协同办 ...
- Ficow 的 AI 平台快速上手指南(ChatGPT, NewBing, ChatGLM-6B, cursor.so)
本文首发于 Ficow Shen's Blog,原文地址: Ficow 的 AI 平台快速上手指南(ChatGPT, NewBing, ChatGLM-6B, cursor.so). 内容概览 前言 ...
- Spring源码解析-ioc容器的设计
Spring源码解析-ioc容器的设计 1 IoC容器系列的设计:BeanFactory和ApplicatioContext 在Spring容器中,主要分为两个主要的容器系列,一个是实现BeanFac ...
- 开源一个CSV解析器(附设计过程 )
在ExcelReport支持csv的开发过程中,需要一个NETStandard的csv解析器.在nuget上找了几个试用,但都不太适合. 于是,便有了:AxinLib.IO.CSV. 先看看怎么用: ...
- Atitit。Tree文件解析器的原理流程与设计实现 java c# php js
Atitit.Tree文件解析器的原理流程与设计实现 java c# php js 1. 解析原理与流程1 1.1. 判断目录 ,表示服 dirFlagChar = "└├─&quo ...
随机推荐
- ASP.NET Core C# 反射 & 表达式树 (第四篇)
前言 上一篇说完了动态创建表达式树, 这篇来说一说解析表达式树. 我之所以会用到是因为最近开始大量使用 trigger 来维护冗余. 但 trigger 本身并不好维护 (EF Core 也不支持), ...
- SQL Server – Trigger 触发器
参考: SQLServer触发器详解(概述.工作原理.应用) CREATE TRIGGER (Transact-SQL) SQL Server Triggers and Transactions 以前 ...
- Flutter Forward 活动正式发布
2023 年 1 月 25 日,Flutter 团队将在肯尼亚首都内罗毕举办 Flutter Forward 大会,并同时开启线上直播,敬请期待! 活动将于北京时间 1 月 25 日 22:30 开始 ...
- iframe嵌套登录页-页面无法加载
背景 活动页面和登录页跨域,过去都是跳转到登录页登录之后再跳转回来,体验不好. 现在需要将登录模块嵌入到活动页,因为懒,不想开发重复的模块,首先我想到的是iframe 刚开始还能正常使用,一段时间后安 ...
- 暑假集训SCP提高模拟10
我(看着百度百科):我已经知道这场谁组的题了 CTH: 谁 我:你想想,能在模拟赛里塞四道数学题还玩邦的,还能有谁 CTH: 我不知道 我:我不知道 CTH: 我知道了 我:我知道了 我:我是 Bob ...
- 全网最适合入门的面向对象编程教程:55 Python字符串与序列化-字节序列类型和可变字节字符串
全网最适合入门的面向对象编程教程:55 Python 字符串与序列化-字节序列类型和可变字节字符串 摘要: 在 Python 中,字符编码是将字符映射为字节的过程,而字节序列(bytes)则是存储这些 ...
- Salesforce AI Specialist篇之 Prompt Builder
本篇参考: https://salesforce.vidyard.com/watch/UUAxcUfHYGAxH3D9wV1RxJ https://help.salesforce.com/s/arti ...
- linux内核 快速分片,技术|Linux slabtop命令——显示内核片缓存信息
Linux内核需要为临时对象如任务或者设备结构和节点分配内存,缓存分配器管理着这些类型对象的缓存.现代Linux内核部署了该缓存分配器以持有缓存,称之为片.不同类型的片缓存由片分配器维护.本文集中讨论 ...
- iOS本地化NSLocalizedString的使用小结
在iOS设备,包括iPhone和iPad是全球可用.显然,iOS用户都来自不同国家,说着不同的语言.为了提供出色的用户体验,你可能希望以多种语言提供您的应用程序.适应应用程序以支持特定语言的过程通常被 ...
- IPV6改造 华为云如此简单
现在很多企业都在搞这个IPV6改造,说实话这个IPV6改造我这边也不是特别精通,也是通过查阅各种资料来了解IPV6这个东西,下面是我查的一些资料大家可以借鉴一下. IPv6改造三步曲--Vecloud ...