feat(ai-web): 增加feedback

This commit is contained in:
2025-06-15 23:42:26 +08:00
parent e2d69bc6e8
commit 138ee140e1
9 changed files with 301 additions and 24 deletions

View File

@@ -0,0 +1,42 @@
package com.lanyuanxiaoyao.service.ai.web.controller.feedback;
import cn.hutool.core.util.ObjectUtil;
import com.lanyuanxiaoyao.service.ai.core.entity.amis.AmisResponse;
import com.lanyuanxiaoyao.service.ai.web.service.feedback.FeedbackService;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.ImmutableList;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("feedback")
public class FeedbackController {
private final FeedbackService feedbackService;
public FeedbackController(FeedbackService feedbackService) {
this.feedbackService = feedbackService;
}
@PostMapping("add")
public void add(
@RequestParam("source") String source,
@RequestParam(value = "pictures", required = false) ImmutableList<Long> pictures
) {
feedbackService.add(source, ObjectUtil.defaultIfNull(pictures, Lists.immutable.empty()));
}
@GetMapping("list")
public AmisResponse<?> list() {
return AmisResponse.responseCrudData(feedbackService.list());
}
@GetMapping("delete")
public void delete(@RequestParam("id") Long id) {
feedbackService.remove(id);
}
}

View File

@@ -0,0 +1,22 @@
package com.lanyuanxiaoyao.service.ai.web.entity;
import lombok.Data;
import org.eclipse.collections.api.list.ImmutableList;
@Data
public class Feedback {
private Long id;
private String source;
private String analysisShort;
private String analysis;
private ImmutableList<String> pictureIds;
private Status status;
private Long createdTime;
private Long modifiedTime;
public enum Status {
ANALYSIS_PROCESSING,
ANALYSIS_SUCCESS,
FINISHED,
}
}

View File

@@ -0,0 +1,81 @@
package com.lanyuanxiaoyao.service.ai.web.service.feedback;
import club.kingon.sql.builder.SqlBuilder;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.lanyuanxiaoyao.service.ai.core.configuration.SnowflakeId;
import com.lanyuanxiaoyao.service.ai.web.entity.Feedback;
import com.lanyuanxiaoyao.service.common.Constants;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.ImmutableList;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
public class FeedbackService {
public static final String FEEDBACK_TABLE_NAME = Constants.DATABASE_NAME + ".service_ai_feedback";
private static final RowMapper<Feedback> feedbackMapper = (rs, row) -> {
Feedback feedback = new Feedback();
feedback.setId(rs.getLong(1));
feedback.setSource(rs.getString(2));
feedback.setAnalysisShort(rs.getString(3));
feedback.setAnalysis(rs.getString(4));
feedback.setPictureIds(
StrUtil.isBlank(rs.getString(5))
? Lists.immutable.empty()
: Lists.immutable.ofAll(StrUtil.split(rs.getString(5), ","))
);
feedback.setStatus(EnumUtil.fromString(Feedback.Status.class, rs.getString(6)));
feedback.setCreatedTime(rs.getTimestamp(7).getTime());
feedback.setModifiedTime(rs.getTimestamp(8).getTime());
return feedback;
};
private final JdbcTemplate template;
public FeedbackService(JdbcTemplate template) {
this.template = template;
}
@Transactional(rollbackFor = Exception.class)
public void add(String source, ImmutableList<Long> pictureIds) {
template.update(
SqlBuilder.insertInto(FEEDBACK_TABLE_NAME, "id", "source", "pictures")
.values()
.addValue("?", "?", "?")
.precompileSql(),
SnowflakeId.next(),
source,
ObjectUtil.isEmpty(pictureIds)
? null
: pictureIds.makeString(",")
);
}
public ImmutableList<Feedback> list() {
return template.query(
SqlBuilder.select("id", "source", "analysis_short", "analysis", "pictures", "status", "created_time", "modified_time")
.from(FEEDBACK_TABLE_NAME)
.orderByDesc("created_time")
.build(),
feedbackMapper
)
.stream()
.collect(Collectors.toCollection(Lists.mutable::empty))
.toImmutable();
}
@Transactional(rollbackFor = Exception.class)
public void remove(Long id) {
template.update(
SqlBuilder.delete(FEEDBACK_TABLE_NAME)
.whereEq("id", id)
.build()
);
}
}

View File

@@ -18,6 +18,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
@@ -38,10 +39,9 @@ import org.springframework.core.io.PathResource;
* @author lanyuanxiaoyao
* @version 20250523
*/
@Slf4j
@LiteflowComponent
public class EmbeddingNodes {
private static final Logger logger = LoggerFactory.getLogger(EmbeddingNodes.class);
private final ChatClient chatClient;
private final QdrantClient qdrantClient;
private final EmbeddingModel embeddingModel;
@@ -196,7 +196,6 @@ public class EmbeddingNodes {
.call()
.content();
Assert.notBlank(response, "LLM response is empty");
logger.info("LLM response: \n{}", response);
// noinspection DataFlowIssue
return Arrays.stream(StrUtil.trim(response).split("---"))
.map(text -> text.replaceAll("(?!^.+) +$", ""))

View File

@@ -0,0 +1,14 @@
package com.lanyuanxiaoyao.service.ai.web.service.node;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Qualifier;
@LiteflowComponent
public class FeedbackNodes {
private final ChatClient.Builder chatClientBuilder;
public FeedbackNodes(@Qualifier("chat") ChatClient.Builder chatClientBuilder) {
this.chatClientBuilder = chatClientBuilder;
}
}