Commit a9695ca8 by zhangxingmin

push

parent f9b8b265
......@@ -2,11 +2,8 @@ package com.yd.ai.api.controller;
import com.yd.ai.api.service.ApiAiStreamService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api/ai")
......@@ -16,14 +13,11 @@ public class ApiAiStreamController {
private ApiAiStreamService apiAiStreamService;
/**
* 调用大模型接口获取AI输出的流信息
* @param question
* @return
* 调用大模型接口获取AI回答(非流式)
*/
@CrossOrigin(origins = "*") // 开发时允许跨域
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> streamChat(@RequestParam String question) {
@CrossOrigin(origins = "*")
@GetMapping(value = "/stream")
public Mono<String> streamChat(@RequestParam String question) {
return apiAiStreamService.streamChat(question);
}
}
\ No newline at end of file
package com.yd.ai.api.service;
import org.springframework.http.codec.ServerSentEvent;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface ApiAiStreamService {
Flux<ServerSentEvent<String>> streamChat(String question);
}
Mono<String> streamChat(String question);
}
\ No newline at end of file
......@@ -17,9 +17,7 @@ import com.yd.notice.feign.client.ApiNotificationTaskFeignClient;
import com.yd.notice.feign.request.ApiSendRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
......@@ -36,21 +34,18 @@ public class ApiAiStreamServiceImpl implements ApiAiStreamService {
private ApiNotificationTaskFeignClient apiNotificationTaskFeignClient;
/**
* 调用大模型接口获取AI输出的流信息(非流式,一次性返回完整内容)
* @param question
* @return
* 调用大模型接口获取AI回答(非流式,返回完整字符串)
*/
@Override
public Flux<ServerSentEvent<String>> streamChat(String question) {
// 敏感词校验(保持不变)
public Mono<String> streamChat(String question) {
// 敏感词校验
try {
apiSensitiveWordDetailService.checkWord(question);
} catch (BusinessException e) {
int code = e.getCode();
if (code == ResultCode.SENSITIVE_WORDS_EXIST.getCode()) {
log.info("检测到禁用敏感词,返回提示语");
String tipMsg = "抱歉,您输入的内容包含敏感词汇,无法为您提供服务。请调整后重新提问。";
return Flux.just(ServerSentEvent.builder(tipMsg).build());
return Mono.just("抱歉,您输入的内容包含敏感词汇,无法为您提供服务。请调整后重新提问。");
} else if (code == ResultCode.SENSITIVE_TZ_WORDS_EXIST.getCode()) {
log.info("检测到通知类型敏感词,发送企业微信通知");
AuthUserDto authUserDto = SecurityUtil.getCurrentLoginUser();
......@@ -63,17 +58,14 @@ public class ApiAiStreamServiceImpl implements ApiAiStreamService {
request.setParams(params);
apiNotificationTaskFeignClient.send(request);
return Flux.just(
ServerSentEvent.<String>builder()
.event("sensitive_notification")
.data("show_products")
.build()
);
// 注意:此处前端需要特殊处理,可通过自定义响应头或约定特定字符串
// 简便做法:返回一个特殊标记字符串,前端检测到后展示产品列表
return Mono.just("__SENSITIVE_NOTIFICATION__");
}
throw e;
}
// ========== 核心修改:改用非流式调用,一次性获取完整回答 ==========
// 正常调用大模型非流式接口
Generation gen = new Generation();
Message systemMsg = Message.builder()
.role(Role.SYSTEM.getValue())
......@@ -89,14 +81,12 @@ public class ApiAiStreamServiceImpl implements ApiAiStreamService {
.model("qwen3-max")
.messages(Arrays.asList(systemMsg, userMsg))
.resultFormat(GenerationParam.ResultFormat.MESSAGE)
.incrementalOutput(false) // 关闭增量输出,一次性返回完整答案
.incrementalOutput(false) // 关闭增量输出
.build();
// 使用 Mono.fromCallable 包装同步调用,并指定在弹性线程池执行
return Mono.fromCallable(() -> {
try {
GenerationResult result = gen.call(param);
// 提取完整回答文本
return result.getOutput().getChoices().get(0).getMessage().getContent();
} catch (NoApiKeyException e) {
log.error("NoApiKeyException: {}", e.getMessage());
......@@ -106,11 +96,10 @@ public class ApiAiStreamServiceImpl implements ApiAiStreamService {
return "系统错误:输入参数异常";
}
})
.subscribeOn(Schedulers.boundedElastic()) // 避免阻塞主线程
.flatMapMany(fullAnswer -> Flux.just(ServerSentEvent.builder(fullAnswer).build()))
.subscribeOn(Schedulers.boundedElastic())
.onErrorResume(e -> {
log.error("非流式响应处理出错: {}", e.getMessage());
return Flux.just(ServerSentEvent.builder("系统繁忙,请稍后重试").build());
return Mono.just("系统繁忙,请稍后重试");
});
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment