feat:【AI 大模型】工作流增加 OLLAMA 的接入

This commit is contained in:
YunaiV 2025-05-03 19:50:29 +08:00
parent 04b8aa0422
commit 8b958cdc9b
5 changed files with 74 additions and 30 deletions

View File

@ -0,0 +1,12 @@
### 测试 AI 工作流
POST {{baseUrl}}/ai/workflow/test
Content-Type: application/json
Authorization: {{token}}
tenant-id: {{adminTenantId}}
{
"id": 4,
"params": {
"message": "1 + 1 = ?"
}
}

View File

@ -1,7 +1,8 @@
package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo;
import cn.hutool.core.util.StrUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.AssertTrue;
import lombok.Data;
import java.util.Map;
@ -10,11 +11,18 @@ import java.util.Map;
@Data
public class AiWorkflowTestReqVO {
@Schema(description = "工作流模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
@NotEmpty(message = "工作流模型不能为空")
@Schema(description = "工作流编号", example = "1024")
private Long id;
@Schema(description = "工作流模型", example = "{}")
private String graph;
@Schema(description = "参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
private Map<String, Object> params;
@AssertTrue(message = "工作流或模型,必须传递一个")
public boolean isGraphValid() {
return id != null || StrUtil.isNotEmpty(graph);
}
}

View File

@ -133,7 +133,7 @@ public interface AiModelService {
VectorStore getOrCreateVectorStore(Long id, Map<String, Class<?>> metadataFields);
/**
* 获取 Tinyflow 所需 LLm Provider
* 获取 TinyFlow 所需 LLm Provider
*
* @param tinyflow tinyflow
* @param modelId AI 模型 ID

View File

@ -12,6 +12,8 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelSaveReq
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
import cn.iocoder.yudao.module.ai.dal.mysql.model.AiChatMapper;
import com.agentsflex.llm.ollama.OllamaLlm;
import com.agentsflex.llm.ollama.OllamaLlmConfig;
import com.agentsflex.llm.qwen.QwenLlm;
import com.agentsflex.llm.qwen.QwenLlmConfig;
import dev.tinyflow.core.Tinyflow;
@ -171,6 +173,7 @@ public class AiModelServiceImpl implements AiModelService {
// return modelFactory.getOrCreateVectorStore(MilvusVectorStore.class, embeddingModel, metadataFields);
}
// TODO @lesan是不是返回 Llm 对象会好点哈
@Override
public void getLLmProvider4Tinyflow(Tinyflow tinyflow, Long modelId) {
AiModelDO model = validateModel(modelId);
@ -178,12 +181,20 @@ public class AiModelServiceImpl implements AiModelService {
AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform());
switch (platform) {
// TODO @lesan 考虑到未来不需要使用agents-flex 现在仅测试通义千问
// TODO @lesan重要是不是可以实现一个 SpringAiLlm这样的话内部全部用它就好了只实现 chat 部分这样就把 flex 作为一个 agent 框架内部调用还是 spring ai 相关的成本可能低一点
case TONG_YI:
QwenLlmConfig qwenLlmConfig = new QwenLlmConfig();
qwenLlmConfig.setApiKey(apiKey.getApiKey());
qwenLlmConfig.setModel(model.getModel());
// TODO @lesan这个有点奇怪如果一个链式里有多个模型咋整呀
tinyflow.setLlmProvider(id -> new QwenLlm(qwenLlmConfig));
break;
case OLLAMA:
OllamaLlmConfig ollamaLlmConfig = new OllamaLlmConfig();
ollamaLlmConfig.setEndpoint(apiKey.getUrl());
ollamaLlmConfig.setModel(model.getModel());
tinyflow.setLlmProvider(id -> new OllamaLlm(ollamaLlmConfig));
break;
}
}

View File

@ -40,7 +40,10 @@ public class AiWorkflowServiceImpl implements AiWorkflowService {
@Override
public Long createWorkflow(AiWorkflowSaveReqVO createReqVO) {
validateWorkflowForCreateOrUpdate(null, createReqVO.getCode());
// 1. 参数校验
validateCodeUnique(null, createReqVO.getCode());
// 2. 插入工作流配置
AiWorkflowDO workflow = BeanUtils.toBean(createReqVO, AiWorkflowDO.class);
workflowMapper.insert(workflow);
return workflow.getId();
@ -48,47 +51,33 @@ public class AiWorkflowServiceImpl implements AiWorkflowService {
@Override
public void updateWorkflow(AiWorkflowSaveReqVO updateReqVO) {
validateWorkflowForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getCode());
// 1. 参数校验
validateWorkflowExists(updateReqVO.getId());
validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
// 2. 更新工作流配置
AiWorkflowDO workflow = BeanUtils.toBean(updateReqVO, AiWorkflowDO.class);
workflowMapper.updateById(workflow);
}
@Override
public void deleteWorkflow(Long id) {
// 1. 校验存在
validateWorkflowExists(id);
// 2. 删除工作流配置
workflowMapper.deleteById(id);
}
@Override
public AiWorkflowDO getWorkflow(Long id) {
return workflowMapper.selectById(id);
}
@Override
public PageResult<AiWorkflowDO> getWorkflowPage(AiWorkflowPageReqVO pageReqVO) {
return workflowMapper.selectPage(pageReqVO);
}
@Override
public Object testWorkflow(AiWorkflowTestReqVO testReqVO) {
Map<String, Object> variables = testReqVO.getParams();
Tinyflow tinyflow = parseFlowParam(testReqVO.getGraph());
return tinyflow.toChain().executeForResult(variables);
}
private void validateWorkflowForCreateOrUpdate(Long id, String code) {
validateWorkflowExists(id);
validateCodeUnique(id, code);
}
private void validateWorkflowExists(Long id) {
private AiWorkflowDO validateWorkflowExists(Long id) {
if (ObjUtil.isNull(id)) {
return;
throw exception(WORKFLOW_NOT_EXISTS);
}
AiWorkflowDO workflow = workflowMapper.selectById(id);
if (ObjUtil.isNull(workflow)) {
throw exception(WORKFLOW_NOT_EXISTS);
}
return workflow;
}
private void validateCodeUnique(Long id, String code) {
@ -107,6 +96,30 @@ public class AiWorkflowServiceImpl implements AiWorkflowService {
}
}
@Override
public AiWorkflowDO getWorkflow(Long id) {
return workflowMapper.selectById(id);
}
@Override
public PageResult<AiWorkflowDO> getWorkflowPage(AiWorkflowPageReqVO pageReqVO) {
return workflowMapper.selectPage(pageReqVO);
}
@Override
public Object testWorkflow(AiWorkflowTestReqVO testReqVO) {
// 加载 graph
String graph = testReqVO.getGraph() != null ? testReqVO.getGraph()
: validateWorkflowExists(testReqVO.getId()).getGraph();
// 构建 TinyFlow 执行链
Tinyflow tinyflow = parseFlowParam(graph);
// 执行
Map<String, Object> variables = testReqVO.getParams();
return tinyflow.toChain().executeForResult(variables);
}
private Tinyflow parseFlowParam(String graph) {
// TODO @lesan可以使用 jackson
JSONObject json = JSONObject.parseObject(graph);