fix: 调试

This commit is contained in:
stream 2026-01-04 16:56:21 +08:00
parent 9d92b48ef3
commit a33c009178
16 changed files with 413 additions and 23 deletions

View File

@ -0,0 +1,29 @@
package com.cmvr.web.controller.test;
import com.cmvr.common.core.controller.BaseController;
import com.cmvr.common.core.domain.AjaxResult;
import com.cmvr.test.model.domain.TeAiEvaluation;
import com.cmvr.test.service.ITeAiEvaluationService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "测试--AI评估")
@RestController
@RequestMapping("/test/evaluation")
@RequiredArgsConstructor
public class TeAiEvaluationController extends BaseController {
private final ITeAiEvaluationService teAiEvaluationService;
@ApiOperation("回调AI评估")
@PostMapping("/callback")
public AjaxResult list(@RequestBody TeAiEvaluation teAiEvaluation) {
return AjaxResult.ok(teAiEvaluationService.edit(teAiEvaluation));
}
}

View File

@ -55,9 +55,9 @@ spring:
servlet:
multipart:
# 单个文件大小
max-file-size: 10MB
max-file-size: 100MB
# 设置总上传的文件大小
max-request-size: 20MB
max-request-size: 200MB
# token配置
token:

View File

@ -114,7 +114,7 @@ public class SecurityConfig
requests.antMatchers("/login", "/register", "/captchaImage").permitAll()
// 静态资源可匿名访问
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
.antMatchers("/flow/**","/flowise/**","/kws/**","/ws/**","/api/grpc/**","/show/**","/node-red/**","/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
.antMatchers("/test/evaluation/callback","/flow/**","/flowise/**","/kws/**","/ws/**","/api/grpc/**","/show/**","/node-red/**","/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated();
})

View File

@ -23,6 +23,10 @@ public enum ActionEnum {
BRANCH("NONE", "BRANCH", "分支"),
SUB_END("NONE", "SUB_END", "子流程结束"),
SLEEP("NONE", "SLEEP", "延迟节点"),
// AI评估
AI_EVALUATION_PRE("AE", "AI_EVALUATION_PRE", "AI评估预处理"),
// AI评估
AI_EVALUATION_EXECUTE("AE", "AI_EVALUATION_END", "AI评估执行"),
// 系统行为
NONE("NONE", "NONE", "无操作"),
@ -62,7 +66,6 @@ public enum ActionEnum {
INTENT_RECOGNITION("LLM", "INTENT_RECOGNITION", "意图识别"),
GENERATE_ADVANCED_AUDIO("LLM", "GENERATE_ADVANCED_AUDIO", "tts语音合成"),
;

View File

@ -21,7 +21,8 @@ public enum FlowiseActionEnum {
MUSIC_ON("music_on", "打开音乐"),
MUSIC_OFF("music_off", "关闭音乐"),
DRIVE_MODE_ECONOMY("drive_mode_economy", "设置驾驶模式为节能模式"),
DRIVE_MODE_COMFORT("drive_mode_comfort", "设置驾驶模式为舒适模式");
DRIVE_MODE_COMFORT("drive_mode_comfort", "设置驾驶模式为舒适模式"),
HELLO("hello", "打招呼");
private final String action;
private final String description;

View File

@ -12,7 +12,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.function.Function;
@Slf4j

View File

@ -0,0 +1,28 @@
package com.cmvr.test.flow.runtime.operator.ae;
import com.cmvr.common.exception.GlobalException;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult;
import com.cmvr.test.flow.runtime.operator.AbstractNodeOperateHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
@Slf4j
@Component("AE")
@RequiredArgsConstructor
public class AENodeOperateHandler extends AbstractNodeOperateHandler {
private final List<AEOperateService> aeOperateServices;
@Override
protected TaskNodeExecuteResult doExecute(TaskNodeExecuteMessage message) {
return aeOperateServices.stream()
.filter(s -> s.supports(message.getAction()))
.findFirst()
.map(s -> s.execute(message))
.orElseThrow(() -> new GlobalException("不支持的评估操作: " + message.getAction()));
}
}

View File

@ -0,0 +1,12 @@
package com.cmvr.test.flow.runtime.operator.ae;
import com.cmvr.test.enums.ActionEnum;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult;
public interface AEOperateService {
boolean supports(ActionEnum action);
TaskNodeExecuteResult execute(TaskNodeExecuteMessage message);
}

View File

@ -0,0 +1,147 @@
package com.cmvr.test.flow.runtime.operator.ae;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.cmvr.common.exception.GlobalException;
import com.cmvr.common.utils.http.CallAPIUtil;
import com.cmvr.common.utils.uuid.IdUtils;
import com.cmvr.test.enums.ActionEnum;
import com.cmvr.test.flow.builder.FlowNodeWrapper;
import com.cmvr.test.flow.context.TaskInstHolder;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult;
import com.cmvr.test.model.domain.TeAiEvaluation;
import com.cmvr.test.service.ITeAiEvaluationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.StringJoiner;
@Slf4j
@Service
@RequiredArgsConstructor
public class AIEvaluationOperateService implements AEOperateService {
private final TaskInstHolder taskInstHolder;
private final ITeAiEvaluationService teAiEvaluationService;
@Resource(name = "threadPoolTaskExecutor")
private final ThreadPoolTaskExecutor executor;
// private
@Override
public boolean supports(ActionEnum action) {
return action.name().startsWith("AI_EVALUATION_");
}
@Override
public TaskNodeExecuteResult execute(TaskNodeExecuteMessage message) {
ActionEnum action = message.getAction();
String instId = message.getInstId();
JSONObject inputParams = message.getInputParams();
List<Integer> iterations = message.getIterations();
switch (action) {
case AI_EVALUATION_PRE:
String taeType = inputParams.getString("taskType");
Integer sceneType = inputParams.getInteger("sceneType");
// 构建评估对象公共部分
TeAiEvaluation teAiEvaluation = new TeAiEvaluation();
teAiEvaluation.setTaeId(IdUtils.fastSimpleUUID());
teAiEvaluation.setInstId(instId);
teAiEvaluation.setTaeType(taeType);
teAiEvaluation.setTaeSubType(sceneType);
// 唤醒语料
JSONObject wakeCorpus = inputParams.getJSONObject("wakeCorpus");
String wakeContent = wakeCorpus.getString("textContent");
// 测试语料
JSONArray testCorpusArray = inputParams.getJSONArray("testCorpus");
// 统一内容构建
String content;
String corpusId;
switch (sceneType) {
case 1:
// 仅唤醒
content = wakeContent;
corpusId = wakeCorpus.getString("parentId");
break;
case 2:
// 单次对话一层循环
int index = iterations.get(0) - 1;
JSONObject singleCorpus = testCorpusArray.getJSONObject(index);
String singleContent = singleCorpus.getString("textContent");
content = StrUtil.join(", ", wakeContent, singleContent);
corpusId = singleCorpus.getString("parentId");
break;
case 3:
// 连续对话多轮
int outerIdx = iterations.get(0) - 1;
JSONArray continuousCorpus = testCorpusArray.getJSONArray(outerIdx);
StringJoiner joiner = new StringJoiner(",");
joiner.add(wakeContent);
for (int j = 0; j < continuousCorpus.size(); j++) {
JSONObject obj = continuousCorpus.getJSONObject(j);
joiner.add(obj.getString("textContent"));
}
content = joiner.toString();
JSONObject obj = continuousCorpus.getJSONObject(0);
corpusId = obj.getString("parentId");
break;
default:
throw new IllegalArgumentException("不支持的 sceneType: " + sceneType);
}
// 设置内容并统一返回
teAiEvaluation.setContent(content);
teAiEvaluation.setCorpusId(corpusId);
return TaskNodeExecuteResult.success(
JSONObject.of("teAiEvaluation", teAiEvaluation)
);
case AI_EVALUATION_EXECUTE:
FlowNodeWrapper pre = message.getGraph()
.getNodeMap()
.values()
.stream()
.filter(node -> ActionEnum.AI_EVALUATION_PRE.equals(node.getAction()))
.findFirst()
.orElseThrow(() -> new IllegalStateException("未找到AI评估预处理节点"));
JSONObject preParams = taskInstHolder.getNodeOutParams(instId, pre.getNodeId(), iterations);
JSONObject aiEvaluation = preParams.getJSONObject("teAiEvaluation");
TeAiEvaluation teaExecute = aiEvaluation.to(TeAiEvaluation.class);
// 获取视频地址
JSONArray videoUrls = inputParams.getJSONArray("videoUrl");
String videoUrl = CollUtil.getLast(videoUrls).toString();
teaExecute.setVideoPath(videoUrl);
teaExecute.setStatus(0);
teaExecute.setStartTime(System.currentTimeMillis());
teAiEvaluationService.insert(teaExecute);
// 执行ai评估
executor.submit(() -> {
CallAPIUtil.doPostJson(
"http://192.168.0.140:8000/analyze",
null,
teaExecute);
});
return TaskNodeExecuteResult.success();
default:
throw new GlobalException("不支持的action:" + action.name());
}
}
}

View File

@ -1,18 +1,23 @@
package com.cmvr.test.flow.runtime.operator.edge;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.cmvr.common.enums.FileType;
import com.cmvr.common.exception.GlobalException;
import com.cmvr.edge.client.model.EdgeCommonVO;
import com.cmvr.edge.client.service.EdgeCameraService;
import com.cmvr.test.enums.ActionEnum;
import com.cmvr.test.flow.builder.FlowNodeWrapper;
import com.cmvr.test.flow.context.TaskInstHolder;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
public class EdgeCameraOperateService implements EdgeOperateService {
@ -89,8 +94,18 @@ public class EdgeCameraOperateService implements EdgeOperateService {
}
case CAMERA_RECORDING_START: {
String videoUrl = edgeCameraService.startRecording(edgeCommonVO);
videoUrl = StrUtil.format("{}/{}", "http://10.148.108.162/system/video", StrUtil.subAfter(videoUrl, "/", true));
// String videoUrl = edgeCameraService.startRecording(edgeCommonVO);
// videoUrl = StrUtil.format("{}/{}", "http://10.148.108.162/system/video", StrUtil.subAfter(videoUrl, "/", true));
List<String> videoList = CollUtil.newArrayList(
"http://192.168.0.100:9000/cmvr-iot/VIDEO/20251223/1766477538765.mp4",
"http://192.168.0.100:9000/cmvr-iot/VIDEO/20251223/1766477608318.mp4",
"http://192.168.0.100:9000/cmvr-iot/VIDEO/20251223/1766477631974.mp4",
"http://192.168.0.100:9000/cmvr-iot/VIDEO/20251223/1766478299920.mp4",
"http://192.168.0.100:9000/cmvr-iot/VIDEO/20251223/1766477777557.mp4"
);
Integer index = CollUtil.getLast(message.getIterations());
String videoUrl = videoList.get(index -1);
// String videoUrl = "http://10.148.108.162/system/video/cam4_1752225205349.mp4";
// JSONArray videoUrls = new JSONArray();
// if (ObjUtil.isNotEmpty(upstreamOutput)) {
@ -111,21 +126,21 @@ public class EdgeCameraOperateService implements EdgeOperateService {
case CAMERA_RECORDING_STOP: {
edgeCameraService.stopRecording(edgeCommonVO);
// todo 结束录像获取视频路径输出
// // 获取视频录制开始节点的id
// FlowNodeWrapper startRecordNode = message.getGraph()
// .getNodeMap()
// .values()
// .stream()
// .filter(node -> ActionEnum.CAMERA_RECORDING_START.equals(node.getAction()))
// .findFirst()
// .orElseThrow(() -> new IllegalStateException("未找到视频录制开始节点"));
//
// // 从上下文获取上游节点存储的参数 获取视频地址
// JSONObject pre = taskInstHolder.getNodeOutParams(instId, startRecordNode.getNodeId());
// JSONArray videoUrl = pre.getJSONArray("videoUrl");
// output.put("videoUrl", videoUrl);
// output.put("isPlay", true);
// output.put("type", FileType.VIDEO.code());
// 获取视频录制开始节点的id
FlowNodeWrapper startRecordNode = message.getGraph()
.getNodeMap()
.values()
.stream()
.filter(node -> ActionEnum.CAMERA_RECORDING_START.equals(node.getAction()))
.findFirst()
.orElseThrow(() -> new IllegalStateException("未找到视频录制开始节点"));
// 从上下文获取上游节点存储的参数 获取视频地址
JSONObject pre = taskInstHolder.getNodeOutParams(instId, startRecordNode.getNodeId(),message.getIterations());
JSONArray videoUrl = pre.getJSONArray("videoUrl");
output.put("videoUrl", videoUrl);
output.put("isPlay", true);
output.put("type", FileType.VIDEO.code());
break;
}
default:

View File

@ -54,6 +54,7 @@ public class ViSchemeOperateService implements EdgeOperateService {
JSONObject output = new JSONObject();
output.put("wakeCorpus", wakeCorpus);
output.put("sceneType", sceneType);
switch (sceneType) {
case 1:
break;

View File

@ -0,0 +1,12 @@
package com.cmvr.test.mapper;
import com.cmvr.test.model.domain.TeAiEvaluation;
import com.github.yulichang.base.MPJBaseMapper;
/**
* AI评估Mapper接口
*
* @author cmvr-iot
*/
public interface TeAiEvaluationMapper extends MPJBaseMapper<TeAiEvaluation> {
}

View File

@ -0,0 +1,59 @@
package com.cmvr.test.model.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* AI评估实体类
*/
@Data
@ApiModel("AI评估")
public class TeAiEvaluation implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("taeId")
@TableId(value = "tae_id", type = IdType.INPUT)
private String taeId;
@ApiModelProperty("评估类型VOICE:语音TOUCH:触控)")
private String taeType;
@ApiModelProperty("评估子类型1:唤醒测试2:单次对话测试3:连续对话测试)")
private Integer taeSubType;
@ApiModelProperty("流程实例ID")
private String instId;
@ApiModelProperty("节点ID列表")
private String nodeIds;
@ApiModelProperty("语料ID")
private String corpusId;
@ApiModelProperty("评估内容")
private String content;
@ApiModelProperty("视频地址")
private String videoPath;
@ApiModelProperty("评估状态0:待评估1:评估中3:评估完成4:评估失败")
private Integer status;
@ApiModelProperty("评估预期结果JSON")
private String expectResult;
@ApiModelProperty("评估最终结果JSON")
private String result;
@ApiModelProperty("开始时间戳ms")
private Long startTime;
@ApiModelProperty("结束时间戳ms")
private Long endTime;
}

View File

@ -197,6 +197,11 @@ public class FlowiseActionService {
log.info("驾驶模式已切换为舒适模式");
return "驾驶模式已切换为舒适模式";
case HELLO:
HttpUtil.post("http://192.168.0.128:8000/action/hello", "");
log.info("打招呼");
return "打招呼";
default:
throw new UnsupportedOperationException("未实现的 Flowise Action: " + action);
}

View File

@ -0,0 +1,25 @@
package com.cmvr.test.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.cmvr.test.model.domain.TeAiEvaluation;
/**
* AI评估Service接口
*
* @author cmvr-iot
*/
public interface ITeAiEvaluationService extends IService<TeAiEvaluation> {
/**
* 新增AI评估
*/
public boolean insert(TeAiEvaluation teAiEvaluation);
/**
* 修改AI评估
*/
public boolean edit(TeAiEvaluation teAiEvaluation);
}

View File

@ -0,0 +1,54 @@
package com.cmvr.test.service.impl;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmvr.common.exception.GlobalException;
import com.cmvr.test.mapper.TeAiEvaluationMapper;
import com.cmvr.test.model.domain.TeAiEvaluation;
import com.cmvr.test.service.ITeAiEvaluationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
@RequiredArgsConstructor
public class ITeAiEvaluationServiceImpl extends ServiceImpl<TeAiEvaluationMapper, TeAiEvaluation> implements ITeAiEvaluationService {
@Override
public boolean insert(TeAiEvaluation teAiEvaluation) {
return this.save(teAiEvaluation);
}
@Override
public boolean edit(TeAiEvaluation teAiEvaluation) {
if (StrUtil.isEmpty(teAiEvaluation.getTaeId())) {
throw new GlobalException("AI评估ID不能为空!");
}
String result = teAiEvaluation.getResult();
if (StrUtil.isEmpty(result)) {
throw new GlobalException("AI评估结果不能为空!");
}
JSONObject jsonObject = JSON.parseObject(result);
String overallResult = jsonObject.getString("overall_result");
int status ;
if (StrUtil.isNotEmpty(overallResult) && overallResult.equals("成功")) {
status = 3;
}else {
status = 4;
}
LambdaUpdateWrapper<TeAiEvaluation> wrapper = Wrappers.lambdaUpdate();
wrapper.eq(TeAiEvaluation::getTaeId, teAiEvaluation.getTaeId())
.set(TeAiEvaluation::getResult, result)
.set(TeAiEvaluation::getStatus, status) // 评估完成/失败
.set(TeAiEvaluation::getEndTime,System.currentTimeMillis());
return this.update(wrapper);
}
}