exist前面的讨论中,我们通过AI助手快速浏览并分析了LlamaIndexThe core source code and its visualization part of the。In the last,We have largely completed the process of usingJavaThe visualization part of the version implementation,Although in the workflow(workflow)Only a preliminary exploration of the analysis of the。at the present,We will delve into a key question:connectLlamaIndexexistPythonBusiness processes and core code in,Successfully migrated and converted toJavareleases。
Next, we will get straight to the point. First, we review the overall architecture and core functionality of LlamaIndex, and then proceed to the development of the Java version of the implementation.
Workflow
It is possible that we have somewhat forgotten the previous details, so describing and recording them through words alone may not help us recall the key contents as quickly and effectively as visual diagrams. In order to sort out the ideas more clearly and help you understand and recall them more visually, I draw a brief summary framework diagram.
Brief summary framework diagram
First, we will review a few key core classes and analyze their respective properties and methods in detail from a concise perspective. As shown in the figure:
The remaining part is the crucial business process classworkflow
up. To make sure we have a clear idea of the overall business process, we can start with a brief overview of the business process. There is no need to focus too much on the details here, which can be explored further by looking at the source code.
Okay, next we will go through the AI assistants one by one to help us with the code transformation work. Although we are well aware that the output of AI may not be 100% perfect, but even so, with the aid of AI, we can at least improve the efficiency dramatically, and expect to be able to save about 50% of the coding time. Let's get started now.
devise
Event
Again, just ask the assistant directly.
Next, I will make further optimization and adjustments according to the initial solution provided by the AI assistant. Get the final result code as below:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@JsonInclude(.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) {
(params);
}
public Object get(String key) {
key = ().getSimpleName() + "." + key;
if ((key)) {
return (key);
} else {
throw new IllegalArgumentException("No such key: " + key);
}
}
public void set(String key, Object value) {
key = ().getSimpleName() + "." + key;
(key, value);
}
public boolean containsKey(String key) {
key = ().getSimpleName() + "." + key;
return (key);
}
public Set<String> keySet() {
return ();
}
public Collection<Object> values() {
return ();
}
public Set<<String, Object>> entrySet() {
return ();
}
public int size() {
return ();
}
public boolean isEmpty() {
return ();
}
public void clear() {
();
}
public Map<String, Object> toMap() {
return ;
}
/**
* eventName默认为类名
*/
public String getEventName() {
if ( == null) {
= ().getSimpleName();
}
return ;
}
}
可以看到,在此代码中我实现的是一个最基础的版本。我们并不打算在初期阶段实现所有功能,而是先着手于构建一个简化版的工作流系统。The purpose of this is to implement a basic runnable version first,Then optimize and improve on it,in order to end up with a more efficient and responsive solution.。
Next, the generation of start and end nodes in the workflow is implemented, again a relatively simple process. The following is the corresponding code implementation:
@Data
@NoArgsConstructor
@Accessors(chain = true)
@JsonInclude(.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(.NON_NULL)
public class StopEvent extends ToolEvent {
private String eventName = "end";
/**
* The results are returned
*/
private String result;
public StopEvent(String params) {
result = params;
}
}
LlamaIndex's events encapsulate a lot of other functionality and details that, while useful, we won't delve into at this stage.
Step annotations
Then we look at the notes, this part can also be asked to the AI assistant, as shown in the picture:
Python's decorators aren't the same as Java annotations, though, so let's go ahead and implement them ourselves.
@Retention()
@Target()
public @interface Step {
// String eventName();
Class<? extends ToolEvent>[] acceptedEvents();
int numWorkers() default 10;
// Class<?>[] returnTypes();
// RetryPolicy retryPolicy() default ;
}
workflow
Next, we will proceed to the implementation of the main processes of the workflow. This part is relatively complex, mainly because the business processes involved are very large and complex, and therefore require some time and effort to deal with. In order to simplify our work, we can first refer to the implementation of the AI assistant, by analyzing its design ideas and working principles, to help us better understand how to carry out the specific implementation.
On this basis, we then tailor and optimize the process as necessary according to actual needs. This is shown in the figure below:
Finally, this part of the code is a bit much, so I'll simply write down the main process. The code is as follows:
@Data
@Slf4j
public abstract class Workflow {
/**
* Workflow timeout
*/
private int timeout = 10;
/**
* Whether to output detailed logs
*/
private boolean verbose = false;
/**
* Verification switch
*/
private boolean validation = false;
/**
* Validation switch
*/ private boolean showUI = false; /***
private boolean showUI = false;
/**
* 1: Scan all methods of the current class with @Step annotation.
* 2: Execute each step in turn according to the step ordering
*/
public String run(String jsonString) throws IOException{}
/**
* Initialize the workflow.
*/
private WorkflowContext initialContext() {}
WorkflowContext
The most critical factor lies in the design of the workflow context, because in this architecture all nodes are able to share global variables. This feature ensures data transfer and coordination between different nodes in the workflow, thus improving the flexibility and convenience of the whole system. Without such a sharing mechanism, the efficiency and maneuverability of the workflow will be greatly reduced and lose its original advantages.
Let's go ahead and ask how the AI assistant is implemented. As shown in the picture:
Since LlamaIndex provides a lot of functionality, its implementation seems relatively complex. In order to simplify the development process, we decided to eliminate some unnecessary features, such as class serialization, a feature that is mainly used for restoring and loading workflows. However, our goal was to implement a minimal and workable workflow. The final code is as follows:
@Slf4j
@Data
public class WorkflowContext {
/**
* Is it a single-step mode
*/
private boolean stepwise;
/**
* Is it running
*/
private boolean isRunning;
/**
* Currently running events
*/
private ToolEvent stepEventHolding;
/**
* event queue:k:method name,v:formation
*/
private Map<String, ArrayBlockingQueue<ToolEvent>> eventQueue;
private List<Thread> tasks = new ArrayList<>();
private Map<String,Object> globalContext;
private String result;
//picture (e.g. of life in the city)
private Graph graph = new MultiGraph("workflow");
public WorkflowContext(boolean stepwise){
("", "swing");
= stepwise;
= false;
= new ConcurrentHashMap<>();
= null;
= new ConcurrentHashMap<>();
= null;
//Add start and end nodes
Node nodeA = ("start");
Node nodeB = ("end");
}
public void addThread(Thread thread) {
(thread);
}
public void sendEvent(ToolEvent value) {}
We removed a few things and added a visualization of the streams we discussed in the last section. And the publish event feature needs to be implemented.
WorkflowHandler
Finally add a processing class, again ask the AI assistant directly to help us go through the basic business logic as shown in the figure:
Then I got rid of all the useless logic and ended up with this code, which is shown below:
@Slf4j
@Data
@AllArgsConstructor
public class WorkflowHandler {
private WorkflowContext context;
public void handleTask(int timeout){}
Next, we need to populate the basic business logic section. This phase of the work mainly involves implementing specific functionality and processing flows to ensure that the workflow works as expected. Since this part of the code involves specific business requirements and internal implementation details, it will not be disclosed for the time being. The workflow startup log is as follows:
The final result is shown in the picture:
summarize
Through the above analysis and practice, we successfully reviewed the core functionality of LlamaIndex and gradually migrated the business process and core code of its Python version to the Java implementation. Although we encountered some challenges in the process, such as the complexity of workflows, differences in events and annotations, etc., we were able to efficiently complete the code conversion and initial implementation with the assistance of the AI assistant.
The next steps will be to further improve each module based on the current implementation, optimize the execution efficiency of the workflow, and improve the reliability and scalability of the system.
I'm Rain, a Java server-side coder, studying the mysteries of AI technology. I love technical communication and sharing, and I am passionate about open source community. I am also a Tencent Cloud Creative Star, Ali Cloud Expert Blogger, Huawei Cloud Enjoyment Expert, and Nuggets Excellent Author.
💡 I won't be shy about sharing my personal explorations and experiences on the technology path in the hope that I can bring some inspiration and help to your learning and growth.
🌟 Welcome to the effortless drizzle! 🌟