sink) {
+ try {
+ workflowClient.runWorkflowStream(request, new WorkflowStreamCallback() {
+ @Override
+ public void onWorkflowStarted(WorkflowStartedEvent event) {
+ sink.next("工作流开始: " + write2Json(event.getData()));
+ }
+
+ @Override
+ public void onNodeStarted(NodeStartedEvent event) {
+ sink.next("节点开始: " + write2Json(event.getData()));
+ }
+
+ @Override
+ public void onNodeFinished(NodeFinishedEvent event) {
+ sink.next("节点完成: " + write2Json(event.getData().getOutputs()));
+ }
+
+ @Override
+ public void onWorkflowFinished(WorkflowFinishedEvent event) {
+ sink.next("工作流完成: " + write2Json(event.getData().getOutputs()));
+ sink.complete();
+ }
+
+ @Override
+ public void onError(ErrorEvent event) {
+ sink.error(new RuntimeException(event.getMessage()));
+ }
+
+ @Override
+ public void onException(Throwable throwable) {
+ sink.error(throwable);
+ }
+ });
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
}
\ No newline at end of file
diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot-ai/src/main/java/com/xxl/job/executor/jobhandler/AIXxlJob.java b/xxl-job-executor-samples/xxl-job-executor-sample-springboot-ai/src/main/java/com/xxl/job/executor/jobhandler/AIXxlJob.java
index 01a21957..115b2266 100644
--- a/xxl-job-executor-samples/xxl-job-executor-sample-springboot-ai/src/main/java/com/xxl/job/executor/jobhandler/AIXxlJob.java
+++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot-ai/src/main/java/com/xxl/job/executor/jobhandler/AIXxlJob.java
@@ -3,10 +3,17 @@ package com.xxl.job.executor.jobhandler;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.util.GsonTool;
+import io.github.imfangs.dify.client.DifyClientFactory;
+import io.github.imfangs.dify.client.DifyWorkflowClient;
+import io.github.imfangs.dify.client.enums.ResponseMode;
+import io.github.imfangs.dify.client.model.workflow.WorkflowRunRequest;
+import io.github.imfangs.dify.client.model.workflow.WorkflowRunResponse;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
+import java.util.HashMap;
import java.util.Map;
/**
@@ -23,7 +30,7 @@ public class AIXxlJob {
/**
* 1、ollama Chat任务
*
- * 参数示例:
+ * 参数示例:格式见 OllamaParam
*
* {
* "input": "{输入信息,必填信息}",
@@ -43,16 +50,14 @@ public class AIXxlJob {
return;
}
- // param parse
- String prompt = "你是一个研发工程师,擅长解决技术类问题。";
- String input;
+ // ollama param
+ OllamaParam ollamaParam = null;
try {
- Map paramMap =GsonTool.fromJson(param, Map.class);
- if (paramMap.containsKey("prompt")) {
- prompt = paramMap.get("prompt");
+ ollamaParam = GsonTool.fromJson(param, OllamaParam.class);
+ if (ollamaParam.getPrompt() == null) {
+ ollamaParam.setPrompt("你是一个研发工程师,擅长解决技术类问题。");
}
- input = paramMap.get("input");
- if (input == null || input.trim().isEmpty()) {
+ if (ollamaParam.getInput() == null || ollamaParam.getInput().trim().isEmpty()) {
XxlJobHelper.log("input is empty.");
XxlJobHelper.handleFail();
@@ -65,15 +70,133 @@ public class AIXxlJob {
}
// input
- XxlJobHelper.log("
【Input】: " + input + "
");
+ XxlJobHelper.log("
【Input】: " + ollamaParam.getInput()+ "
");
// invoke
String result = chatClient
- .prompt(prompt)
- .user(input)
+ .prompt(ollamaParam.getPrompt())
+ .user(ollamaParam.getInput())
.call()
.content();
XxlJobHelper.log("
【Output】: " + result+ "
");
}
+ private static class OllamaParam{
+ private String input;
+ private String prompt;
+
+ public String getInput() {
+ return input;
+ }
+
+ public void setInput(String input) {
+ this.input = input;
+ }
+
+ public String getPrompt() {
+ return prompt;
+ }
+
+ public void setPrompt(String prompt) {
+ this.prompt = prompt;
+ }
+ }
+
+
+
+ @Value("${dify.api-key}")
+ private String apiKey;
+ @Value("${dify.base-url}")
+ private String baseUrl;
+
+ /**
+ * 2、dify Workflow任务
+ *
+ * 参数示例:格式见 DifyParam
+ *
+ * {
+ * "inputs":{ // inputs 为dify工作流任务参数;参数不固定,结合各自 workflow 自行定义。
+ * "input":"{用户输入信息}" // 该参数为示例变量,需要 workflow 的“开始”节点 自定义参数 “input”,可自行调整或删除。
+ * },
+ * "user": "{用户标识,选填}"
+ * }
+ *
+ */
+ @XxlJob("difyWorkflowJobHandler")
+ public void difyWorkflowJobHandler() throws Exception {
+
+ // param
+ String param = XxlJobHelper.getJobParam();
+ if (param==null || param.trim().isEmpty()) {
+ XxlJobHelper.log("param is empty.");
+ XxlJobHelper.handleFail();
+ return;
+ }
+
+ // param parse
+ DifyParam difyParam;
+ try {
+ difyParam =GsonTool.fromJson(param, DifyParam.class);
+ if (difyParam.getInputs() == null) {
+ difyParam.setInputs(new HashMap<>());
+ }
+ if (difyParam.getUser() == null) {
+ difyParam.setUser("xxl-job");
+ }
+ } catch (Exception e) {
+ XxlJobHelper.log(e);
+ XxlJobHelper.handleFail();
+ return;
+ }
+
+
+ // dify param
+ XxlJobHelper.log("
【inputs】: " + difyParam.getInputs() + "
");
+
+ // dify request
+ WorkflowRunRequest request = WorkflowRunRequest.builder()
+ .inputs(difyParam.getInputs())
+ .responseMode(ResponseMode.BLOCKING)
+ .user(difyParam.getUser())
+ .build();
+
+ // dify invoke
+ DifyWorkflowClient workflowClient = DifyClientFactory.createWorkflowClient(baseUrl, apiKey);
+ WorkflowRunResponse response = workflowClient.runWorkflow(request);
+
+ // response
+ XxlJobHelper.log("
【Output】: " + response.getData().getOutputs()+ "
");
+ }
+
+ private static class DifyParam{
+
+ /**
+ * 输入参数,允许传入 App 定义的各变量值
+ */
+ private Map inputs;
+
+ /**
+ * 用户标识
+ */
+ private String user;
+
+ public Map getInputs() {
+ return inputs;
+ }
+
+ public void setInputs(Map inputs) {
+ this.inputs = inputs;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public void setUser(String user) {
+ this.user = user;
+ }
+
+ }
+
+
}
diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot-ai/src/main/resources/application.properties b/xxl-job-executor-samples/xxl-job-executor-sample-springboot-ai/src/main/resources/application.properties
index a4b8e118..33b2cf38 100644
--- a/xxl-job-executor-samples/xxl-job-executor-sample-springboot-ai/src/main/resources/application.properties
+++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot-ai/src/main/resources/application.properties
@@ -3,6 +3,9 @@ server.port=8082
# no web
#spring.main.web-environment=false
+server.servlet.encoding.force=true
+server.servlet.encoding.charset=UTF-8
+
# log config
logging.config=classpath:logback.xml
@@ -34,3 +37,9 @@ spring.ai.ollama.chat.enabled=true
### chat model,must install it locally through ollama
spring.ai.ollama.chat.options.model=qwen2.5:1.5b
spring.ai.ollama.chat.options.temperature=0.8
+
+### dify url
+dify.base-url=http://localhost/v1
+### dify api-key
+dify.api-key=app-OUVgNUOQRIMokfmuJvBJoUTN
+