From 6e9730ebbbff634d27c2c49ec328156c8905b508 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Thu, 30 Oct 2025 13:52:14 +0800
Subject: [PATCH] feat(ai): 简化AI对话项创建逻辑并新增连续对话类型 - 移除复杂的对话项更新逻辑,统一通过add方法创建新项 - 新增AiTalkOutputEnum枚举值CONTEXT_TALK用于AI陪练连续对话 - 更新ApiMemberTalkAnswerSavaDto注释以包含新的对话类型 - 修复对话项创建时类型参数未正确传递的问题 - 优化代码结构,减少冗余的条件判断和数据转换操作
---
src/main/java/cc/mrbird/febs/ai/service/impl/AiServiceImpl.java | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 208 insertions(+), 0 deletions(-)
diff --git a/src/main/java/cc/mrbird/febs/ai/service/impl/AiServiceImpl.java b/src/main/java/cc/mrbird/febs/ai/service/impl/AiServiceImpl.java
index 953dcfe..5e5d556 100644
--- a/src/main/java/cc/mrbird/febs/ai/service/impl/AiServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/ai/service/impl/AiServiceImpl.java
@@ -1,15 +1,24 @@
package cc.mrbird.febs.ai.service.impl;
+import cc.mrbird.febs.ai.entity.AiTalkItem;
import cc.mrbird.febs.ai.enumerates.AiTypeEnum;
import cc.mrbird.febs.ai.entity.AiProductRole;
import cc.mrbird.febs.ai.req.ai.AiMessage;
import cc.mrbird.febs.ai.req.ai.AiRequest;
+import cc.mrbird.febs.ai.req.talk.AiTalkAnswerStream;
import cc.mrbird.febs.ai.res.ai.AiResponse;
import cc.mrbird.febs.ai.res.ai.RadarDataItem;
import cc.mrbird.febs.ai.res.ai.Report;
+import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkStreamVoOld;
import cc.mrbird.febs.ai.service.AiProductRoleService;
import cc.mrbird.febs.ai.service.AiService;
+import cc.mrbird.febs.ai.service.AiTalkItemService;
+import cc.mrbird.febs.ai.strategy.enumerates.LlmStrategyContextEnum;
+import cc.mrbird.febs.common.entity.FebsResponse;
+import cc.mrbird.febs.mall.entity.DataDictionaryCustom;
+import cc.mrbird.febs.mall.mapper.DataDictionaryCustomMapper;
import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
@@ -23,10 +32,12 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
+import reactor.core.publisher.Flux;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@@ -65,6 +76,8 @@
private final AiProductRoleService aiProductRoleService;
private final ObjectMapper objectMapper;
+ private final AiTalkItemService aiTalkItemService;
+ private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
@Value("${ai.service.ak}")
private String ak;
@@ -100,6 +113,32 @@
if (service != null) {
service.shutdownExecutor();
}
+ }
+
+ @Override
+ public Integer getSystemSetAiType() {
+ Integer type = 2;
+ DataDictionaryCustom dataDictionaryCustom = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
+ LlmStrategyContextEnum.LLM_STRATEGY.getCode(),
+ LlmStrategyContextEnum.LLM_STRATEGY.getCode()
+ );
+ if (dataDictionaryCustom != null) {
+ type = Integer.parseInt(dataDictionaryCustom.getValue());
+ }
+ return type;
+ }
+
+ @Override
+ public String getSystemSetLTAiPrompt() {
+ String prompt = "请将问题转换为中文,并给出一个最详细的答案。";
+ DataDictionaryCustom dataDictionaryCustom = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
+ LlmStrategyContextEnum.LLM_LING_TONG_PROMPT.getCode(),
+ LlmStrategyContextEnum.LLM_LING_TONG_PROMPT.getCode()
+ );
+ if (dataDictionaryCustom != null) {
+ prompt = dataDictionaryCustom.getValue();
+ }
+ return prompt;
}
@Override
@@ -354,6 +393,175 @@
}
}
+ // 修改服务实现
+ @Override
+ public Flux<FebsResponse> answerStream(String question) {
+ log.info("----- standard request -----");
+
+ final ChatMessage systemMessage = ChatMessage.builder()
+ .role(ChatMessageRole.SYSTEM)
+ .content("你是豆包,是由字节跳动开发的 AI 人工智能助手")
+ .build();
+
+ final ChatMessage userMessage = ChatMessage.builder()
+ .role(ChatMessageRole.USER)
+ .content(question)
+ .build();
+
+ List<ChatMessage> messages = Arrays.asList(systemMessage, userMessage);
+
+ ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
+ .model("ep-20250805124033-lhxbf")
+ .messages(messages)
+ .stream(true)
+ .thinking(new ChatCompletionRequest.ChatCompletionRequestThinking("enabled"))
+ .temperature(0.7)
+ .topP(0.9)
+ .maxTokens(2048)
+ .frequencyPenalty(0.0)
+ .build();
+
+ return Flux.from(service.streamChatCompletion(chatCompletionRequest))
+ .map(response -> {
+ if (response == null || response.getChoices() == null || response.getChoices().isEmpty()) {
+ return new FebsResponse().success().data("END");
+ }
+
+ ChatCompletionChoice choice = response.getChoices().get(0);
+ if (choice == null || choice.getMessage() == null) {
+ return new FebsResponse().success().data("END");
+ }
+
+
+ ApiMemberTalkStreamVoOld apiMemberTalkStreamVoOld = new ApiMemberTalkStreamVoOld();
+ // 判断是否触发深度思考,触发则打印模型输出的思维链内容
+ ChatMessage message = choice.getMessage();
+ if (message.getReasoningContent()!= null &&!message.getReasoningContent().isEmpty()) {
+ apiMemberTalkStreamVoOld.setReasoningContent(message.getReasoningContent());
+// System.out.print(message.getReasoningContent());
+ }
+
+ String content = message.getContent() == null ? "" : message.getContent().toString();
+ apiMemberTalkStreamVoOld.setContent(content);
+ System.out.print(content);
+ return new FebsResponse().success().data(apiMemberTalkStreamVoOld);
+ })
+ .onErrorResume(throwable -> {
+ log.error("流式调用AI服务失败,问题输入: {}", question, throwable);
+ FebsResponse errorResponse = new FebsResponse().fail().message("AI服务调用失败");
+ return Flux.just(errorResponse);
+ });
+ }
+
+ @Override
+ public Flux<FebsResponse> answerStreamV2(AiTalkAnswerStream dto) {
+ String question = dto.getQuestion();
+ log.info("----- standard request -----");
+
+ // 参数校验
+ if (StrUtil.isBlank(question)) {
+ return Flux.just(new FebsResponse().fail().message("问题不能为空"));
+ }
+
+ List<ChatMessage> messages = new ArrayList<>();
+
+ final ChatMessage systemMessage = ChatMessage.builder()
+ .role(ChatMessageRole.SYSTEM)
+ .content("你是豆包,是由字节跳动开发的 AI 人工智能助手,请使用中文回复")
+ .build();
+ messages.add(systemMessage);
+
+ // 获取历史消息记录
+ if (StrUtil.isNotEmpty(dto.getTalkId())) {
+ List<AiTalkItem> aiTalkItems = aiTalkItemService.getListByTalkId(dto.getTalkId());
+ if (CollUtil.isNotEmpty(aiTalkItems)) {
+ for (AiTalkItem aiTalkItem : aiTalkItems) {
+ ChatMessage chatMessage = buildChatMessageFromItem(aiTalkItem);
+ if (chatMessage != null) {
+ messages.add(chatMessage);
+ }
+ }
+ }
+ }
+
+ final ChatMessage userMessage = ChatMessage.builder()
+ .role(ChatMessageRole.USER)
+ .content(question)
+ .build();
+ messages.add(userMessage);
+
+ ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
+ .model("ep-20250805124033-lhxbf")
+ .messages(messages)
+ .stream(true)
+ .thinking(new ChatCompletionRequest.ChatCompletionRequestThinking("enabled"))
+ .temperature(0.7)
+ .topP(0.9)
+ .maxTokens(2048)
+ .frequencyPenalty(0.0)
+ .build();
+
+ return Flux.from(service.streamChatCompletion(chatCompletionRequest))
+ .map(response -> {
+ if (response == null || response.getChoices() == null || response.getChoices().isEmpty()) {
+ return new FebsResponse().success().data("END");
+ }
+
+ ChatCompletionChoice choice = response.getChoices().get(0);
+ if (choice == null || choice.getMessage() == null) {
+ return new FebsResponse().success().data("END");
+ }
+
+ ChatMessage message = choice.getMessage();
+ ApiMemberTalkStreamVoOld apiMemberTalkStreamVoOld = new ApiMemberTalkStreamVoOld();
+
+ // 处理 reasoning content
+ String reasoningContent = message.getReasoningContent();
+ if (StrUtil.isNotEmpty(reasoningContent)) {
+ apiMemberTalkStreamVoOld.setReasoningContent(reasoningContent);
+ log.debug("Reasoning Content: {}", reasoningContent);
+ }
+
+ // 安全处理 content
+ String content = "";
+ if (message.getContent() != null) {
+ content = message.getContent().toString();
+ }
+ apiMemberTalkStreamVoOld.setContent(content);
+ System.out.print(content);
+ log.debug("Content: {}", content);
+
+ return new FebsResponse().success().data(apiMemberTalkStreamVoOld);
+ })
+ .onErrorResume(throwable -> {
+ log.error("流式调用AI服务失败,问题输入: {}", question, throwable);
+ FebsResponse errorResponse = new FebsResponse().fail().message("AI服务调用失败");
+ return Flux.just(errorResponse);
+ });
+ }
+
+ // 提取为私有方法,提高可读性和复用性
+ private ChatMessage buildChatMessageFromItem(AiTalkItem item) {
+ if (item == null) return null;
+
+ switch (item.getType()) {
+ case 1:
+ return ChatMessage.builder()
+ .role(ChatMessageRole.USER)
+ .content(item.getContext())
+ .build();
+ case 2:
+ return ChatMessage.builder()
+ .role(ChatMessageRole.ASSISTANT)
+ .content(item.getContext())
+ .build();
+ default:
+ return null;
+ }
+ }
+
+
+
private Report tryRepairTruncatedJson(String truncatedJson) {
String[] repairAttempts = {
truncatedJson + "\"}}}",
--
Gitblit v1.9.1