diff --git a/metis-starter/pom.xml b/metis-starter/pom.xml
index 6f9d18a..14a8e03 100644
--- a/metis-starter/pom.xml
+++ b/metis-starter/pom.xml
@@ -31,14 +31,6 @@
org.springframework.boot
spring-boot-starter-validation
-
- dev.langchain4j
- langchain4j-open-ai
-
-
- dev.langchain4j
- langchain4j-mcp
-
com.alibaba.fastjson2
fastjson2
@@ -77,6 +69,24 @@
io.swagger.core.v3
swagger-annotations-jakarta
+
+
+ org.apache.velocity
+ velocity
+
+
+
+ dev.langchain4j
+ langchain4j-open-ai
+
+
+ dev.langchain4j
+ langchain4j-ollama
+
+
+ dev.langchain4j
+ langchain4j-mcp
+
diff --git a/metis-starter/src/main/java/com/metis/constant/BaseConstant.java b/metis-starter/src/main/java/com/metis/constant/BaseConstant.java
index 9eb934b..a6781f3 100644
--- a/metis-starter/src/main/java/com/metis/constant/BaseConstant.java
+++ b/metis-starter/src/main/java/com/metis/constant/BaseConstant.java
@@ -3,4 +3,6 @@ package com.metis.constant;
public interface BaseConstant {
Integer DEFAULT_VERSION = 1;
+
+ String TEXT = "text";
}
diff --git a/metis-starter/src/main/java/com/metis/convert/ModelPlatformConvert.java b/metis-starter/src/main/java/com/metis/convert/ModelPlatformConvert.java
index e2f1480..43c2393 100644
--- a/metis-starter/src/main/java/com/metis/convert/ModelPlatformConvert.java
+++ b/metis-starter/src/main/java/com/metis/convert/ModelPlatformConvert.java
@@ -2,6 +2,7 @@ package com.metis.convert;
import com.metis.domain.entity.ModelPlatform;
import com.metis.domain.entity.ModelPlatformInfo;
+import com.metis.domain.entity.base.Model;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@@ -13,4 +14,6 @@ public interface ModelPlatformConvert {
ModelPlatformInfo toInfo(ModelPlatform modelPlatform);
+ Model toModel(ModelPlatform modelPlatform);
+
}
diff --git a/metis-starter/src/main/java/com/metis/domain/context/RunningContext.java b/metis-starter/src/main/java/com/metis/domain/context/RunningContext.java
index 2b61a3a..09ecef0 100644
--- a/metis-starter/src/main/java/com/metis/domain/context/RunningContext.java
+++ b/metis-starter/src/main/java/com/metis/domain/context/RunningContext.java
@@ -1,16 +1,22 @@
package com.metis.domain.context;
+import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.metis.runner.FlowRunningContext;
import lombok.Builder;
import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
+@Slf4j
@Getter
@Builder
public class RunningContext {
@@ -59,6 +65,39 @@ public class RunningContext {
}
+ /**
+ * 获得值
+ *
+ * @param key 关键
+ * @return {@link Object }
+ */
+ public Object getValue(String key) {
+ Assert.isTrue(StrUtil.isNotBlank(key), "key is blank");
+ if (key.startsWith(SYS_PREFIX)) {
+ ExpressionParser parser = new SpelExpressionParser();
+ StandardEvaluationContext context = new StandardEvaluationContext(this);
+ return parser.parseExpression(key).getValue(context);
+ }
+
+ try {
+ // 解析 key 中的数字部分并转换为 Long 类型
+ String[] parts = key.split("\\.");
+ if (parts.length == 2 && StrUtil.isNumeric(parts[0])) {
+ Long nodeId = Long.valueOf(parts[0]);
+ JSONObject runningContext = getRunningContext(nodeId);
+ if (runningContext != null) {
+ return runningContext.get(parts[1]);
+ }
+ }
+ } catch (Exception e) {
+ log.error("数字类型获取动态参数失败: {}", key);
+ }
+ ExpressionParser parser = new SpelExpressionParser();
+ StandardEvaluationContext context = new StandardEvaluationContext(this);
+ return parser.parseExpression(key).getValue(context);
+ }
+
+
/**
* 获得价值 不满足条件, 则返回null, 需要业务自行判断
*
diff --git a/metis-starter/src/main/java/com/metis/domain/entity/ModelPlatform.java b/metis-starter/src/main/java/com/metis/domain/entity/ModelPlatform.java
index 9a86841..f5288ef 100644
--- a/metis-starter/src/main/java/com/metis/domain/entity/ModelPlatform.java
+++ b/metis-starter/src/main/java/com/metis/domain/entity/ModelPlatform.java
@@ -51,6 +51,11 @@ public class ModelPlatform extends SimpleBaseEntity {
*/
private String apiKey;
+ /**
+ * 配置
+ */
+ private String configJson;
+
/**
* 状态
*/
diff --git a/metis-starter/src/main/java/com/metis/domain/entity/base/Model.java b/metis-starter/src/main/java/com/metis/domain/entity/base/Model.java
index ee0f8cd..7ecfd74 100644
--- a/metis-starter/src/main/java/com/metis/domain/entity/base/Model.java
+++ b/metis-starter/src/main/java/com/metis/domain/entity/base/Model.java
@@ -1,12 +1,84 @@
package com.metis.domain.entity.base;
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson2.JSONObject;
+import com.metis.enums.ModelTypeEnum;
+import com.metis.enums.YesOrNoEnum;
import lombok.Data;
@Data
public class Model {
+ /**
+ * 主键
+ */
+ private Long id;
+ /**
+ * 名字
+ */
private String name;
+ /**
+ * 类型
+ */
+ private ModelTypeEnum type;
+
+ /**
+ * 自定义类型
+ */
+ private String customType;
+
+ /**
+ * 请求地址
+ */
+ private String url;
+
+ /**
+ * api密匙
+ */
+ private String apiKey;
+
+ /**
+ * 配置
+ */
+ private JSONObject config;
+
+ /**
+ * 状态
+ */
+ private YesOrNoEnum state;
+
+ /**
+ * 描述
+ */
+ private String description;
+
+ private transient Class> configClass;
+
+ /**
+ * 获取配置
+ *
+ * @return {@link T }
+ */
+ public T getConfig() {
+ if (ObjectUtil.isNull(config)) {
+ return null;
+ }
+ return (T) config.to(configClass);
+ }
+
+ /**
+ * 设置配置类
+ *
+ * @param configClass 配置类
+ */
+ public void setConfigClass(Class configClass) {
+ if (ObjectUtil.isNotNull(this.configClass)) {
+ return;
+ }
+ this.configClass = configClass;
+ }
+
}
diff --git a/metis-starter/src/main/java/com/metis/domain/entity/base/Node.java b/metis-starter/src/main/java/com/metis/domain/entity/base/Node.java
index c5d976b..3148a0f 100644
--- a/metis-starter/src/main/java/com/metis/domain/entity/base/Node.java
+++ b/metis-starter/src/main/java/com/metis/domain/entity/base/Node.java
@@ -40,13 +40,11 @@ public class Node {
/**
* 宽度
*/
-// @NotNull(message = "节点宽度不能为空")
private Integer width;
/**
* 高度
*/
-// @NotNull(message = "节点高度不能为空")
private Integer height;
/**
diff --git a/metis-starter/src/main/java/com/metis/domain/entity/config/node/LLMNodeConfig.java b/metis-starter/src/main/java/com/metis/domain/entity/config/node/LLMNodeConfig.java
deleted file mode 100644
index 6a2df06..0000000
--- a/metis-starter/src/main/java/com/metis/domain/entity/config/node/LLMNodeConfig.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.metis.domain.entity.config.node;
-
-import com.metis.domain.entity.base.NodeConfig;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class LLMNodeConfig extends NodeConfig {
-}
diff --git a/metis-starter/src/main/java/com/metis/domain/entity/config/node/common/RetryConfig.java b/metis-starter/src/main/java/com/metis/domain/entity/config/node/common/RetryConfig.java
new file mode 100644
index 0000000..510289f
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/domain/entity/config/node/common/RetryConfig.java
@@ -0,0 +1,30 @@
+package com.metis.domain.entity.config.node.common;
+
+import lombok.Data;
+
+/**
+ * 重试配置
+ *
+ * @author clay
+ * @date 2025/05/04
+ */
+@Data
+public class RetryConfig {
+
+ /**
+ * 启用
+ */
+ private Boolean enable;
+
+ /**
+ * 最大重试次数
+ */
+ private Integer maxRetries;
+
+ /**
+ * 重试时间间隔
+ */
+ private Integer retryInterval;
+
+
+}
diff --git a/metis-starter/src/main/java/com/metis/domain/entity/config/node/llm/LLMNodeConfig.java b/metis-starter/src/main/java/com/metis/domain/entity/config/node/llm/LLMNodeConfig.java
new file mode 100644
index 0000000..bf9e87b
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/domain/entity/config/node/llm/LLMNodeConfig.java
@@ -0,0 +1,31 @@
+package com.metis.domain.entity.config.node.llm;
+
+import com.metis.domain.entity.base.NodeConfig;
+import com.metis.domain.entity.config.node.common.RetryConfig;
+import com.metis.llm.domain.LLMChatModeConfig;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class LLMNodeConfig extends NodeConfig {
+
+ private String context;
+
+ /**
+ * 重试配置
+ */
+ private RetryConfig retryConfig;
+
+ /**
+ * 提示模板
+ */
+ private List promptTemplate;
+
+ /**
+ * 模型
+ */
+ private LLMChatModeConfig model;
+}
diff --git a/metis-starter/src/main/java/com/metis/domain/entity/config/node/llm/PromptTemplate.java b/metis-starter/src/main/java/com/metis/domain/entity/config/node/llm/PromptTemplate.java
new file mode 100644
index 0000000..b3cc0cf
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/domain/entity/config/node/llm/PromptTemplate.java
@@ -0,0 +1,15 @@
+package com.metis.domain.entity.config.node.llm;
+
+import com.metis.enums.ChatRoleType;
+import lombok.Data;
+
+@Data
+public class PromptTemplate {
+
+ private ChatRoleType role;
+
+ private String text;
+
+ private String id;
+
+}
diff --git a/metis-starter/src/main/java/com/metis/enums/ChatRoleType.java b/metis-starter/src/main/java/com/metis/enums/ChatRoleType.java
new file mode 100644
index 0000000..d78382c
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/enums/ChatRoleType.java
@@ -0,0 +1,13 @@
+package com.metis.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum ChatRoleType {
+ SYSTEM,
+ USER,
+ AI,
+ TOOL_EXECUTION_RESULT;
+
+
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/CustomModelEngine.java b/metis-starter/src/main/java/com/metis/llm/CustomModelEngine.java
new file mode 100644
index 0000000..173bcd4
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/CustomModelEngine.java
@@ -0,0 +1,16 @@
+package com.metis.llm;
+
+import com.metis.enums.ModelTypeEnum;
+import com.metis.llm.domain.config.BaseModelConfig;
+
+public interface CustomModelEngine extends ModelEngine {
+
+
+ String getCustomType();
+
+
+ default ModelTypeEnum getType() {
+ return ModelTypeEnum.CUSTOM;
+ }
+
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/ModelEngine.java b/metis-starter/src/main/java/com/metis/llm/ModelEngine.java
new file mode 100644
index 0000000..6fafd26
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/ModelEngine.java
@@ -0,0 +1,41 @@
+package com.metis.llm;
+
+
+import com.metis.domain.entity.base.Model;
+import com.metis.enums.ModelTypeEnum;
+import com.metis.llm.domain.LLMChatModeConfig;
+import com.metis.llm.domain.LLMEmbeddingModelConfig;
+import com.metis.llm.domain.config.BaseModelConfig;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.embedding.EmbeddingModel;
+
+public interface ModelEngine {
+
+
+ /**
+ * 获取模型类型
+ *
+ * @return {@link ModelTypeEnum }
+ */
+ ModelTypeEnum getType();
+
+ /**
+ * 获取聊天语言模型
+ *
+ * @param model 模型
+ * @param modelConfig
+ * @return {@link ChatModel }
+ */
+ ChatModel getChatLanguageModel(Model model, LLMChatModeConfig modelConfig);
+
+ /**
+ * 获取嵌入模型
+ *
+ * @param model 模型
+ * @param modeConfig
+ * @return {@link EmbeddingModel }
+ */
+ EmbeddingModel getEmbeddingModel(Model model, LLMEmbeddingModelConfig modeConfig);
+
+
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/ModelEngineService.java b/metis-starter/src/main/java/com/metis/llm/ModelEngineService.java
new file mode 100644
index 0000000..2463934
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/ModelEngineService.java
@@ -0,0 +1,27 @@
+package com.metis.llm;
+
+import com.metis.llm.domain.LLMChatModeConfig;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.embedding.EmbeddingModel;
+
+public interface ModelEngineService {
+
+
+ /**
+ * 获取聊天语言模型
+ *
+ * @param modeConfig 模型id
+ * @return {@link ChatModel }
+ */
+ ChatModel getChatLanguageModel(LLMChatModeConfig modeConfig);
+
+
+ /**
+ * 获取嵌入模型
+ *
+ * @param modeConfig@return {@link EmbeddingModel }
+ */
+ EmbeddingModel getEmbeddingModel(LLMChatModeConfig modeConfig);
+
+
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/ModelService.java b/metis-starter/src/main/java/com/metis/llm/ModelService.java
index 879d943..0afb5c6 100644
--- a/metis-starter/src/main/java/com/metis/llm/ModelService.java
+++ b/metis-starter/src/main/java/com/metis/llm/ModelService.java
@@ -13,7 +13,7 @@ public interface ModelService {
* @param modelId llm id
* @return {@link List }<{@link Model }>
*/
- List listModel(Long modelId);
+ Model getByModelId(Long modelId);
}
diff --git a/metis-starter/src/main/java/com/metis/llm/PlatformModeList.java b/metis-starter/src/main/java/com/metis/llm/PlatformModeList.java
deleted file mode 100644
index e7dbf54..0000000
--- a/metis-starter/src/main/java/com/metis/llm/PlatformModeList.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.metis.llm;
-
-import com.metis.domain.entity.ModelPlatform;
-import com.metis.domain.entity.base.Model;
-import com.metis.enums.ModelTypeEnum;
-
-import java.util.List;
-
-public interface PlatformModeList {
-
-
- List modelList(ModelPlatform modelPlatform);
-
-
- /**
- * 得到类型
- *
- * @return {@link ModelTypeEnum }
- */
- ModelTypeEnum getType();
-
-
-}
diff --git a/metis-starter/src/main/java/com/metis/llm/domain/CompletionParams.java b/metis-starter/src/main/java/com/metis/llm/domain/CompletionParams.java
new file mode 100644
index 0000000..6b27282
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/domain/CompletionParams.java
@@ -0,0 +1,42 @@
+package com.metis.llm.domain;
+
+import lombok.Data;
+
+@Data
+public class CompletionParams {
+
+ /**
+ * 温度
+ */
+ private Double temperature;
+
+ /**
+ * 最大token数
+ */
+ private Integer maxTokens;
+
+ /**
+ * Top P
+ */
+ private Double topP;
+
+ /**
+ * Top K
+ */
+ private Double topK;
+
+ /**
+ * 随机种子
+ */
+ private Integer seed;
+
+ /**
+ * 重复处罚
+ */
+ private Double presencePenalty;
+
+ /**
+ * 响应格式
+ */
+ private String responseFormat;
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/domain/LLMChatModeConfig.java b/metis-starter/src/main/java/com/metis/llm/domain/LLMChatModeConfig.java
new file mode 100644
index 0000000..a758e07
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/domain/LLMChatModeConfig.java
@@ -0,0 +1,24 @@
+package com.metis.llm.domain;
+
+import lombok.Data;
+
+@Data
+public class LLMChatModeConfig {
+
+ /**
+ * 模型id
+ */
+ private Long modelId;
+
+ /**
+ * 模型名称
+ */
+ private String modelName;
+
+ /**
+ * 完成参数
+ */
+ private CompletionParams completionParams;
+
+
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/domain/LLMEmbeddingModelConfig.java b/metis-starter/src/main/java/com/metis/llm/domain/LLMEmbeddingModelConfig.java
new file mode 100644
index 0000000..d03b558
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/domain/LLMEmbeddingModelConfig.java
@@ -0,0 +1,17 @@
+package com.metis.llm.domain;
+
+import lombok.Data;
+
+@Data
+public class LLMEmbeddingModelConfig {
+
+ /**
+ * 模型id
+ */
+ private Long modelId;
+
+ /**
+ * 模型名称
+ */
+ private String modelName;
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/domain/config/BaseModelConfig.java b/metis-starter/src/main/java/com/metis/llm/domain/config/BaseModelConfig.java
new file mode 100644
index 0000000..9c41cb1
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/domain/config/BaseModelConfig.java
@@ -0,0 +1,4 @@
+package com.metis.llm.domain.config;
+
+public abstract class BaseModelConfig {
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/domain/config/OllamaModelConfig.java b/metis-starter/src/main/java/com/metis/llm/domain/config/OllamaModelConfig.java
new file mode 100644
index 0000000..46f6d93
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/domain/config/OllamaModelConfig.java
@@ -0,0 +1,17 @@
+package com.metis.llm.domain.config;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * Ollama模型配置
+ *
+ * @author clay
+ * @date 2025/05/04
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class OllamaModelConfig extends BaseModelConfig{
+
+
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/domain/config/OpenApiConfig.java b/metis-starter/src/main/java/com/metis/llm/domain/config/OpenApiConfig.java
new file mode 100644
index 0000000..28b82ab
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/domain/config/OpenApiConfig.java
@@ -0,0 +1,9 @@
+package com.metis.llm.domain.config;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class OpenApiConfig extends BaseModelConfig {
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/engine/OllamaModelEngine.java b/metis-starter/src/main/java/com/metis/llm/engine/OllamaModelEngine.java
new file mode 100644
index 0000000..fe2c36e
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/engine/OllamaModelEngine.java
@@ -0,0 +1,9 @@
+package com.metis.llm.engine;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class OllamaModelEngine {
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/engine/OpenApiModelEngine.java b/metis-starter/src/main/java/com/metis/llm/engine/OpenApiModelEngine.java
new file mode 100644
index 0000000..ad2b494
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/engine/OpenApiModelEngine.java
@@ -0,0 +1,51 @@
+package com.metis.llm.engine;
+
+import com.metis.domain.entity.base.Model;
+import com.metis.enums.ModelTypeEnum;
+import com.metis.llm.ModelEngine;
+import com.metis.llm.domain.CompletionParams;
+import com.metis.llm.domain.LLMChatModeConfig;
+import com.metis.llm.domain.LLMEmbeddingModelConfig;
+import com.metis.llm.domain.config.OpenApiConfig;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.embedding.EmbeddingModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class OpenApiModelEngine implements ModelEngine {
+
+ @Override
+ public ModelTypeEnum getType() {
+ return ModelTypeEnum.OPEN_AI;
+ }
+
+ @Override
+ public ChatModel getChatLanguageModel(Model model, LLMChatModeConfig modelConfig) {
+ CompletionParams completionParams = modelConfig.getCompletionParams();
+ return OpenAiChatModel.builder()
+ .apiKey(model.getApiKey())
+ .baseUrl(model.getUrl())
+ .modelName(modelConfig.getModelName())
+ .temperature(completionParams.getTemperature())
+ .maxTokens(completionParams.getMaxTokens())
+ .topP(completionParams.getTopP())
+ .seed(completionParams.getSeed())
+ .presencePenalty(completionParams.getPresencePenalty())
+ .responseFormat(completionParams.getResponseFormat())
+ .build();
+ }
+
+ @Override
+ public EmbeddingModel getEmbeddingModel(Model model, LLMEmbeddingModelConfig modelConfig) {
+ return OpenAiEmbeddingModel.builder()
+ .apiKey(model.getApiKey())
+ .baseUrl(modelConfig.getModelName())
+ .modelName(modelConfig.getModelName())
+ .build();
+ }
+
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/factory/ModelEngineFactory.java b/metis-starter/src/main/java/com/metis/llm/factory/ModelEngineFactory.java
new file mode 100644
index 0000000..e97dc26
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/factory/ModelEngineFactory.java
@@ -0,0 +1,105 @@
+package com.metis.llm.factory;
+
+import cn.hutool.core.lang.Assert;
+import com.metis.enums.ModelTypeEnum;
+import com.metis.llm.CustomModelEngine;
+import com.metis.llm.ModelEngine;
+import com.metis.llm.domain.config.BaseModelConfig;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class ModelEngineFactory {
+
+
+ /**
+ * 模型图
+ */
+ private static final Map> MODEL_MAP = new ConcurrentHashMap<>();
+
+ /**
+ * 自定义模型图
+ */
+ private static final Map> CUSTOM_MODEL_MAP = new ConcurrentHashMap<>();
+
+ /**
+ * 型号表
+ *
+ * @return {@link Set }<{@link ModelTypeEnum }>
+ */
+ public static Set modelTypeList() {
+ return MODEL_MAP.keySet();
+ }
+
+ /**
+ * 自定义模型类型列表
+ *
+ * @return {@link Set }<{@link String }>
+ */
+ public static Set customModelTypeList() {
+ return CUSTOM_MODEL_MAP.keySet();
+ }
+
+ /**
+ * 发动机型号清单
+ *
+ * @return {@link List }<{@link ModelEngine }<{@link ? } {@link extends } {@link BaseModelConfig }>>
+ */
+ public static List> modelEngineList() {
+ return new ArrayList<>(MODEL_MAP.values());
+ }
+
+ /**
+ * 自定义型号引擎列表
+ *
+ * @return {@link List }<{@link ModelEngine }<{@link ? } {@link extends } {@link BaseModelConfig }>>
+ */
+ public static List> customModelEngineList() {
+ return new ArrayList<>(CUSTOM_MODEL_MAP.values());
+ }
+
+ /**
+ * 注册
+ *
+ * @param modelEngine 模型引擎
+ */
+ static void register(ModelEngine extends BaseModelConfig> modelEngine) {
+ MODEL_MAP.put(modelEngine.getType(), modelEngine);
+ }
+
+
+ /**
+ * 得到
+ *
+ * @param type 类型
+ * @return {@link ModelEngine }<{@link ? } {@link extends } {@link BaseModelConfig }>
+ */
+ public static ModelEngine extends BaseModelConfig> get(ModelTypeEnum type) {
+ return MODEL_MAP.get(type);
+ }
+
+ /**
+ * 注册自定义
+ *
+ * @param modelEngine 模型引擎
+ */
+ static void registerCustom(CustomModelEngine extends BaseModelConfig> modelEngine) {
+ Assert.isTrue(!CUSTOM_MODEL_MAP.containsKey(modelEngine.getCustomType()), "已存在类型:{}, class:{}的模型", modelEngine.getCustomType(), modelEngine.getClass());
+ CUSTOM_MODEL_MAP.put(modelEngine.getCustomType(), modelEngine);
+ }
+
+ /**
+ * 得到自定义
+ *
+ * @param type 类型
+ * @return {@link ModelEngine }<{@link ? } {@link extends } {@link BaseModelConfig }>
+ */
+ public static ModelEngine extends BaseModelConfig> getCustom(String type) {
+ return CUSTOM_MODEL_MAP.get(type);
+ }
+
+
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/factory/ModelEngineInitiate.java b/metis-starter/src/main/java/com/metis/llm/factory/ModelEngineInitiate.java
new file mode 100644
index 0000000..47b44ba
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/factory/ModelEngineInitiate.java
@@ -0,0 +1,32 @@
+package com.metis.llm.factory;
+
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.ObjectUtil;
+import com.metis.enums.ModelTypeEnum;
+import com.metis.llm.CustomModelEngine;
+import com.metis.llm.ModelEngine;
+import com.metis.llm.domain.config.BaseModelConfig;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+@Service
+public class ModelEngineInitiate implements ApplicationContextAware {
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ Map modelMap = applicationContext.getBeansOfType(ModelEngine.class);
+ modelMap.forEach((modelBeanName, model) -> {
+ if (ObjectUtil.isNull(model.getType())) {
+ return;
+ }
+ if (ModelTypeEnum.CUSTOM.equals(model.getType())) {
+ Assert.isTrue(model instanceof CustomModelEngine extends BaseModelConfig>, "自定义模型必须实现CustomModelEngine接口");
+ ModelEngineFactory.registerCustom((CustomModelEngine extends BaseModelConfig>) model);
+ }
+ ModelEngineFactory.register((ModelEngine extends BaseModelConfig>) model);
+ });
+ }
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/impl/ModelEngineServiceImpl.java b/metis-starter/src/main/java/com/metis/llm/impl/ModelEngineServiceImpl.java
new file mode 100644
index 0000000..7bf0815
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/llm/impl/ModelEngineServiceImpl.java
@@ -0,0 +1,81 @@
+package com.metis.llm.impl;
+
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.ObjectUtil;
+import com.metis.domain.entity.base.Model;
+import com.metis.enums.ModelTypeEnum;
+import com.metis.llm.ModelEngine;
+import com.metis.llm.ModelEngineService;
+import com.metis.llm.ModelService;
+import com.metis.llm.domain.LLMChatModeConfig;
+import com.metis.llm.domain.LLMEmbeddingModelConfig;
+import com.metis.llm.factory.ModelEngineFactory;
+import com.metis.utils.GenericInterfacesUtils;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.embedding.EmbeddingModel;
+import lombok.Builder;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class ModelEngineServiceImpl implements ModelEngineService {
+
+ private final ModelService modelService;
+
+ @Override
+ public ChatModel getChatLanguageModel(LLMChatModeConfig modeConfig) {
+ ModelWrapper modelWrapper = getModelWrapper(modeConfig);
+ return modelWrapper.getChatLanguageModel();
+ }
+
+
+ @Override
+ public EmbeddingModel getEmbeddingModel(LLMChatModeConfig modeConfig) {
+ ModelWrapper modelWrapper = getModelWrapper(modeConfig);
+ return modelWrapper.getEmbeddingModel();
+ }
+
+ private ModelWrapper getModelWrapper(LLMChatModeConfig modeConfig) {
+ Model model = getModel(modeConfig.getModelId());
+ ModelEngine modelEngine = null;
+ if (model.getType().equals(ModelTypeEnum.CUSTOM)) {
+ modelEngine = ModelEngineFactory.getCustom(model.getCustomType());
+ } else {
+ modelEngine = ModelEngineFactory.get(model.getType());
+ }
+ model.setConfigClass(GenericInterfacesUtils.getClass(modelEngine));
+ return ModelWrapper.builder()
+ .modelEngine(modelEngine)
+ .modeConfig(modeConfig)
+ .model(model)
+ .build();
+ }
+
+
+ private Model getModel(Long modelId) {
+ Assert.isTrue(ObjectUtil.isNotNull(modelId), "模型ID不能为空");
+ Model model = modelService.getByModelId(modelId);
+ Assert.isTrue(ObjectUtil.isNotNull(model), "模型不存在");
+ return model;
+ }
+
+
+ @Builder
+ private record ModelWrapper(Model model,
+ ModelEngine modelEngine,
+ LLMChatModeConfig modeConfig,
+ LLMEmbeddingModelConfig embeddingModelConfig) {
+ public ChatModel getChatLanguageModel() {
+ return modelEngine.getChatLanguageModel(model, modeConfig);
+ }
+
+ public EmbeddingModel getEmbeddingModel() {
+ return modelEngine.getEmbeddingModel(model, embeddingModelConfig);
+ }
+ }
+
+
+}
diff --git a/metis-starter/src/main/java/com/metis/llm/impl/ModelServiceImpl.java b/metis-starter/src/main/java/com/metis/llm/impl/ModelServiceImpl.java
index 9224ace..56f0591 100644
--- a/metis-starter/src/main/java/com/metis/llm/impl/ModelServiceImpl.java
+++ b/metis-starter/src/main/java/com/metis/llm/impl/ModelServiceImpl.java
@@ -2,6 +2,7 @@ package com.metis.llm.impl;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
+import com.metis.convert.ModelPlatformConvert;
import com.metis.domain.entity.ModelPlatform;
import com.metis.domain.entity.base.Model;
import com.metis.llm.ModelService;
@@ -10,8 +11,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
-import java.util.List;
-
@Slf4j
@Service
@RequiredArgsConstructor
@@ -21,11 +20,10 @@ public class ModelServiceImpl implements ModelService {
@Override
- public List listModel(Long modelId) {
+ public Model getByModelId(Long modelId) {
Assert.isTrue(ObjectUtil.isNotNull(modelId), "模型平台ID不能为空");
ModelPlatform modelPlatform = modelPlatformService.getById(modelId);
Assert.isTrue(ObjectUtil.isNotNull(modelPlatform), "模型平台不存在");
-
- return List.of();
+ return ModelPlatformConvert.INSTANCE.toModel(modelPlatform);
}
}
diff --git a/metis-starter/src/main/java/com/metis/runner/factory/NodeRunnerFactory.java b/metis-starter/src/main/java/com/metis/runner/factory/NodeRunnerFactory.java
index a2204fa..41e927a 100644
--- a/metis-starter/src/main/java/com/metis/runner/factory/NodeRunnerFactory.java
+++ b/metis-starter/src/main/java/com/metis/runner/factory/NodeRunnerFactory.java
@@ -1,6 +1,7 @@
package com.metis.runner.factory;
import cn.hutool.core.lang.Assert;
+import com.metis.domain.entity.base.NodeConfig;
import com.metis.enums.NodeType;
import com.metis.runner.CustomNodeRunner;
import com.metis.runner.NodeRunner;
@@ -13,18 +14,18 @@ public final class NodeRunnerFactory {
/**
* 内置节点运行器
*/
- private static final Map NODE_MAP = new ConcurrentHashMap<>(8);
+ private static final Map> NODE_MAP = new ConcurrentHashMap<>(8);
/**
* 自定义节点映射
*/
- private static final Map CUSTOM_NODE_MAP = new ConcurrentHashMap<>(8);
+ private static final Map> CUSTOM_NODE_MAP = new ConcurrentHashMap<>(8);
/**
* 注册
*
* @param runner 跑步者
*/
- static void register(NodeRunner runner) {
+ static void register(NodeRunner extends NodeConfig> runner) {
NODE_MAP.put(runner.getType(), runner);
}
@@ -35,7 +36,7 @@ public final class NodeRunnerFactory {
* @param type 类型
* @return {@link NodeRunner }
*/
- public static NodeRunner get(NodeType type) {
+ public static NodeRunner extends NodeConfig> get(NodeType type) {
return NODE_MAP.get(type);
}
@@ -45,7 +46,7 @@ public final class NodeRunnerFactory {
*
* @param runner 跑步者
*/
- static void registerCustom(CustomNodeRunner runner) {
+ static void registerCustom(CustomNodeRunner extends NodeConfig> runner) {
Assert.isTrue(!CUSTOM_NODE_MAP.containsKey(runner.getCustomNodeType()), "已存在类型:{}, class:{}的运行器", runner.getCustomNodeType(), runner.getClass());
CUSTOM_NODE_MAP.put(runner.getCustomNodeType(), runner);
}
@@ -56,7 +57,7 @@ public final class NodeRunnerFactory {
* @param type 类型
* @return {@link NodeRunner }
*/
- public static NodeRunner getCustom(String type) {
+ public static NodeRunner extends NodeConfig> getCustom(String type) {
return CUSTOM_NODE_MAP.get(type);
}
diff --git a/metis-starter/src/main/java/com/metis/runner/factory/RunnerInitialize.java b/metis-starter/src/main/java/com/metis/runner/factory/RunnerInitialize.java
index b02873a..e0848a3 100644
--- a/metis-starter/src/main/java/com/metis/runner/factory/RunnerInitialize.java
+++ b/metis-starter/src/main/java/com/metis/runner/factory/RunnerInitialize.java
@@ -1,6 +1,8 @@
package com.metis.runner.factory;
import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.ObjectUtil;
+import com.metis.domain.entity.base.NodeConfig;
import com.metis.enums.NodeType;
import com.metis.runner.CustomNodeRunner;
import com.metis.runner.NodeRunner;
@@ -26,11 +28,14 @@ public class RunnerInitialize implements ApplicationContextAware {
Map runnerMap = applicationContext.getBeansOfType(NodeRunner.class);
runnerMap.forEach((runnerBeanName, runner) -> {
+ if (ObjectUtil.isNull(runner.getType())) {
+ return;
+ }
if (NodeType.CUSTOM.equals(runner.getType())) {
Assert.isTrue(runner instanceof CustomNodeRunner, "自定义节点必须实现CustomNodeRunner接口");
- NodeRunnerFactory.registerCustom((CustomNodeRunner) runner);
+ NodeRunnerFactory.registerCustom((CustomNodeRunner extends NodeConfig>) runner);
} else {
- NodeRunnerFactory.register(runner);
+ NodeRunnerFactory.register((NodeRunner extends NodeConfig>) runner);
}
});
}
diff --git a/metis-starter/src/main/java/com/metis/runner/impl/LLMNodeRunner.java b/metis-starter/src/main/java/com/metis/runner/impl/LLMNodeRunner.java
index 1779a34..f91bd65 100644
--- a/metis-starter/src/main/java/com/metis/runner/impl/LLMNodeRunner.java
+++ b/metis-starter/src/main/java/com/metis/runner/impl/LLMNodeRunner.java
@@ -1,27 +1,96 @@
package com.metis.runner.impl;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson2.JSONObject;
+import com.metis.constant.BaseConstant;
import com.metis.domain.context.RunningContext;
import com.metis.domain.context.RunningResult;
import com.metis.domain.entity.base.Edge;
import com.metis.domain.entity.base.Node;
-import com.metis.domain.entity.config.node.LLMNodeConfig;
+import com.metis.domain.entity.config.node.llm.LLMNodeConfig;
+import com.metis.domain.entity.config.node.llm.PromptTemplate;
import com.metis.enums.NodeType;
+import com.metis.llm.ModelEngineService;
+import com.metis.llm.domain.LLMChatModeConfig;
import com.metis.runner.NodeRunner;
+import com.metis.template.domain.RenderContext;
+import com.metis.template.utils.VelocityUtil;
+import dev.langchain4j.data.message.AiMessage;
+import dev.langchain4j.data.message.ChatMessage;
+import dev.langchain4j.data.message.SystemMessage;
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.chat.response.ChatResponse;
+import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
@Slf4j
@Service
+@RequiredArgsConstructor
public class LLMNodeRunner implements NodeRunner {
+
+ private final ModelEngineService modelEngineService;
+
+
@Override
public RunningResult run(RunningContext context, Node node, List edges) {
- return RunningResult.buildResult();
+ LLMNodeConfig config = node.getConfig();
+ LLMChatModeConfig model = config.getModel();
+
+ ChatModel chatModel = modelEngineService.getChatLanguageModel(model);
+ List chatMessageList = buildChatMessage(context, config);
+ ChatResponse chat = chatModel.chat(chatMessageList);
+ String string = chat.toString();
+
+ log.info("LLM 输出结果: {}", string);
+ JSONObject result = new JSONObject();
+ result.put(BaseConstant.TEXT, string);
+ return RunningResult.buildResult(result);
}
@Override
public NodeType getType() {
return NodeType.LLM;
}
+
+
+ private List buildChatMessage(RunningContext context,
+ LLMNodeConfig config) {
+ // 获取模板
+ List promptTemplate = config.getPromptTemplate();
+ // 如果没有模板, 则直接返回
+ if (CollUtil.isEmpty(promptTemplate)) {
+ return List.of();
+ }
+ // 获取模板参数
+ Map templateMap = promptTemplate.stream().collect(Collectors.toMap(PromptTemplate::getId, PromptTemplate::getText));
+
+ // 上下文参数
+ String contextValue = (String) context.getValue(config.getContext());
+ RenderContext renderContext = RenderContext.builder()
+ .context(contextValue)
+ .sys(context.getSys())
+ .templateMap(templateMap)
+ .nodeRunningContext(context.getNodeRunningContext())
+ .build();
+ // 渲染结果
+ Map rendered = VelocityUtil.renderBatch(renderContext);
+ // 构建消息返回
+ return promptTemplate.stream()
+ .map(template -> switch (template.getRole()) {
+ case SYSTEM -> SystemMessage.from(rendered.get(template.getId()));
+ case USER -> UserMessage.from(rendered.get(template.getId()));
+ case AI -> AiMessage.from(rendered.get(template.getId()));
+ default -> null;
+ }).filter(ObjectUtil::isNotNull)
+ .toList();
+ }
+
+
}
diff --git a/metis-starter/src/main/java/com/metis/template/domain/RenderContext.java b/metis-starter/src/main/java/com/metis/template/domain/RenderContext.java
new file mode 100644
index 0000000..0ef2378
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/template/domain/RenderContext.java
@@ -0,0 +1,52 @@
+package com.metis.template.domain;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.metis.domain.context.SysContext;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Data
+@Builder
+public class RenderContext {
+
+ /**
+ * 模板
+ */
+ private String template;
+
+ /**
+ * 模板映射
+ */
+ private Map templateMap;
+
+ /**
+ * 上下文
+ */
+ private String context;
+
+ /**
+ * 系统数据
+ */
+ private SysContext sys;
+
+ /**
+ * 节点运行上下文, 需要数据进行传递
+ */
+ private Map nodeRunningContext;
+
+
+ public Map getContext() {
+ Map context = new HashMap<>();
+ context.put("context", this.context);
+ context.put("sys", this.sys);
+ for (Map.Entry entry : nodeRunningContext.entrySet()) {
+ context.put(String.valueOf(entry.getKey()), entry.getValue());
+ }
+ return context;
+ }
+
+
+}
diff --git a/metis-starter/src/main/java/com/metis/template/package-info.java b/metis-starter/src/main/java/com/metis/template/package-info.java
new file mode 100644
index 0000000..6b4fb33
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/template/package-info.java
@@ -0,0 +1 @@
+package com.metis.template;
\ No newline at end of file
diff --git a/metis-starter/src/main/java/com/metis/template/utils/VelocityUtil.java b/metis-starter/src/main/java/com/metis/template/utils/VelocityUtil.java
new file mode 100644
index 0000000..358c374
--- /dev/null
+++ b/metis-starter/src/main/java/com/metis/template/utils/VelocityUtil.java
@@ -0,0 +1,66 @@
+package com.metis.template.utils;
+
+import com.metis.template.domain.RenderContext;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.runtime.resource.loader.StringResourceLoader;
+
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+public class VelocityUtil {
+ // 初始化Velocity引擎
+ private static final VelocityEngine engine = new VelocityEngine();
+
+ static {
+ engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "string");
+ engine.setProperty("string.resource.loader.class",
+ StringResourceLoader.class.getName());
+ engine.init();
+ }
+
+
+ public static String parseContent(String templateContent, Map context) {
+ VelocityContext velocityContext = new VelocityContext(context);
+ // 执行模板渲染
+ StringWriter writer = new StringWriter();
+ engine.evaluate(velocityContext, writer, "StringTemplate", templateContent);
+ return writer.toString();
+ }
+
+
+ /**
+ * 渲染
+ *
+ * @param renderContext 渲染上下文
+ * @return {@link String }
+ */
+ public static String render(RenderContext renderContext) {
+ // 获取上下文
+ Map context = renderContext.getContext();
+ // 渲染
+ return VelocityUtil.parseContent(renderContext.getTemplate(), context);
+ }
+
+
+ /**
+ * 渲染
+ *
+ * @param renderContext 渲染上下文
+ * @return {@link Map }<{@link String:标识 }, {@link String:渲染结果 }>
+ */
+ public static Map renderBatch(RenderContext renderContext) {
+ Map result = new HashMap<>();
+ for (Map.Entry entry : renderContext.getTemplateMap().entrySet()) {
+ String key = entry.getKey();
+ String template = entry.getValue();
+ String render = VelocityUtil.parseContent(template, renderContext.getContext());
+ result.put(key, render);
+ }
+ return result;
+ }
+
+
+}
diff --git a/metis-starter/src/main/java/com/metis/validator/impl/node/LLMNodeValidator.java b/metis-starter/src/main/java/com/metis/validator/impl/node/LLMNodeValidator.java
index 2dd04a6..3b4002b 100644
--- a/metis-starter/src/main/java/com/metis/validator/impl/node/LLMNodeValidator.java
+++ b/metis-starter/src/main/java/com/metis/validator/impl/node/LLMNodeValidator.java
@@ -2,7 +2,7 @@ package com.metis.validator.impl.node;
import com.metis.domain.entity.base.Edge;
import com.metis.domain.entity.base.Node;
-import com.metis.domain.entity.config.node.LLMNodeConfig;
+import com.metis.domain.entity.config.node.llm.LLMNodeConfig;
import com.metis.enums.NodeType;
import com.metis.validator.NodeValidator;
import com.metis.validator.ValidatorResult;
diff --git a/metis-starter/src/test/resources/flow.json b/metis-starter/src/test/resources/flow.json
new file mode 100644
index 0000000..526b43a
--- /dev/null
+++ b/metis-starter/src/test/resources/flow.json
@@ -0,0 +1,189 @@
+
+{
+ "appId": 1919041086810968064,
+ "name": "llm运行测试",
+ "description": "llm运行测试",
+ "graph": {
+ "nodes": [
+ {
+ "id": "5",
+ "type": "start",
+ "initialized": false,
+ "position": {
+ "x": -221.9030111576117,
+ "y": 59.99186709389075
+ },
+ "data": {
+ "label": "开始",
+ "icon": "SuitcaseLine",
+ "toolbarPosition": "right",
+ "config": {
+ "variables": [
+ {
+ "variable": "query",
+ "label": "查询条件",
+ "type": "text-input",
+ "maxLength": 60,
+ "required": true
+ },
+ {
+ "variable": "background",
+ "label": "背景",
+ "type": "text-input",
+ "maxLength": 60,
+ "required": true
+ }
+ ]
+ },
+ "handles": [
+ {
+ "id": "51",
+ "type": "source",
+ "position": "right",
+ "connectable": true
+ }
+ ]
+ },
+ "customType": null,
+ "width": 200,
+ "height": 40
+ },
+ {
+ "id": "700",
+ "type": "llm",
+ "initialized": false,
+ "position": {
+ "x": 6.81248018754539,
+ "y": 68.80431452712736
+ },
+ "data": {
+ "label": "llm",
+ "icon": "",
+ "toolbarPosition": "right",
+ "config": {
+ "context": "5.background",
+ "retryConfig": {
+ "enable": true,
+ "maxRetries": 3,
+ "retryInterval": 1000
+ },
+ "promptTemplate": [
+ {
+ "role": "system",
+ "text": "你的背景是${context}",
+ "id": "1"
+ },
+ {
+ "role": "user",
+ "text": "请你解释一下上述问题${5.query}",
+ "id": "2"
+ }
+ ],
+ "model": {
+ "modelId": 1,
+ "modelName": "Qwen/Qwen2.5-Coder-32B-Instruct",
+ "completionParams": {
+ "temperature": 0.7,
+ "topP": 0.9,
+ "maxTokens": 1024,
+ "seed": 1234,
+ "presencePenalty": 0,
+ "responseFormat": "text"
+ }
+ }
+ },
+ "handles": [
+ {
+ "id": "57",
+ "type": "source",
+ "position": "left",
+ "connectable": true
+ },
+ {
+ "id": "35",
+ "type": "source",
+ "position": "right",
+ "connectable": true
+ }
+ ]
+ },
+ "customType": null,
+ "width": 200,
+ "height": 40
+ },
+ {
+ "id": "802",
+ "type": "end",
+ "initialized": false,
+ "position": {
+ "x": 221.7192701843481,
+ "y": 67.57111673995398
+ },
+ "data": {
+ "label": "结束",
+ "icon": "",
+ "toolbarPosition": "right",
+ "config": {},
+ "handles": [
+ {
+ "id": "13",
+ "type": "target",
+ "position": "left",
+ "connectable": true
+ }
+ ]
+ },
+ "customType": null,
+ "width": 200,
+ "height": 40
+ }
+ ],
+ "edges": [
+ {
+ "id": "vueflow__edge-551-70057",
+ "type": "default",
+ "source": "5",
+ "target": "700",
+ "sourceHandle": "51",
+ "targetHandle": "57",
+ "data": {},
+ "label": "",
+ "animated": true,
+ "markerStart": "none",
+ "markerEnd": "none",
+ "sourceX": -15.903013850339164,
+ "sourceY": 79.9918688890424,
+ "targetX": 4.312479626560497,
+ "targetY": 88.80432081015815
+ },
+ {
+ "id": "802",
+ "type": "default",
+ "source": "700",
+ "target": "802",
+ "sourceHandle": "35",
+ "targetHandle": "13",
+ "data": {},
+ "label": "",
+ "animated": true,
+ "markerStart": "none",
+ "markerEnd": "none",
+ "sourceX": 212.81248478762151,
+ "sourceY": 88.80432081015815,
+ "targetX": 219.2192701843481,
+ "targetY": 87.5711275108639
+ }
+ ],
+ "position": [
+ 987.9498689166815,
+ 102.12938290987324
+ ],
+ "zoom": 3.5988075528449266,
+ "viewport": {
+ "x": 987.9498689166815,
+ "y": 102.12938290987324,
+ "zoom": 3.5988075528449266
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 12a1df8..0f6c817 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,5 +1,6 @@
-
+
4.0.0
com.metis
@@ -19,7 +20,11 @@
1.18.34
1.6.2
1.2.3
+ 1.7
1.0.0-beta2
+ 1.0.0-rc1
+ 1.0.0-beta4
+ 1.0.0-beta4
3.5.8
2.18.0
3.8.1
@@ -45,16 +50,6 @@
pom
import
-
- dev.langchain4j
- langchain4j-open-ai
- ${langchain4j.version}
-
-
- dev.langchain4j
- langchain4j-mcp
- 1.0.0-beta2
-
com.alibaba.fastjson2
fastjson2
@@ -78,7 +73,7 @@
cn.hutool
hutool-all
- 5.8.24
+ 5.8.37
@@ -101,6 +96,27 @@
swagger-annotations-jakarta
2.2.15
+
+
+ org.apache.velocity
+ velocity
+ ${velocity.version}
+
+
+ dev.langchain4j
+ langchain4j-open-ai
+ ${open.api.version}
+
+
+ dev.langchain4j
+ langchain4j-ollama
+ ${ollama.version}
+
+
+ dev.langchain4j
+ langchain4j-mcp
+ ${mcp.version}
+