feat:【AI 大模型】工作流增加 OLLAMA 的接入
This commit is contained in:
parent
04b8aa0422
commit
8b958cdc9b
|
@ -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 = ?"
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue