You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
4.3 KiB
125 lines
4.3 KiB
package com.wok.supportbot.controller;
|
|
|
|
import cn.hutool.json.JSONUtil;
|
|
import com.wok.supportbot.app.AssistantApp;
|
|
import com.wok.supportbot.app.ProductInfoApp;
|
|
import com.wok.supportbot.entity.ProductInfo;
|
|
import jakarta.annotation.Resource;
|
|
import org.springframework.ai.chat.model.ChatModel;
|
|
import org.springframework.ai.tool.ToolCallback;
|
|
import org.springframework.http.MediaType;
|
|
import org.springframework.http.codec.ServerSentEvent;
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
|
import reactor.core.publisher.Flux;
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
@RestController
|
|
@RequestMapping("/ai")
|
|
public class AiController {
|
|
|
|
@Resource
|
|
private AssistantApp assistantApp;
|
|
@Resource
|
|
private ProductInfoApp productInfoApp;
|
|
|
|
|
|
/**
|
|
* 同步调用 AI 提取结构化商品信息
|
|
*
|
|
* @param message
|
|
* @return
|
|
*/
|
|
@GetMapping("/product_info_app/chat/sync")
|
|
public String doChatWithProductInfoAppSync(String message) {
|
|
ProductInfo productInfo = productInfoApp.extractProductInfo(message);
|
|
return JSONUtil.toJsonStr(productInfo);
|
|
}
|
|
|
|
/**
|
|
* 同步调用 AI 智能客服应用
|
|
*
|
|
* @param message
|
|
* @param chatId
|
|
* @return
|
|
*/
|
|
@GetMapping("/assistant_app/chat/sync")
|
|
public String doChatWithAssistantAppSync(String message, String chatId) {
|
|
return assistantApp.doChat(message, chatId);
|
|
}
|
|
|
|
/**
|
|
* SSE 流式调用 AI 智能客服应用
|
|
* 返回Flux 响应式对象,并且添加 SSE 对应的 MediaType
|
|
*
|
|
* @param message
|
|
* @param chatId
|
|
* @return
|
|
*/
|
|
@GetMapping(value = "/assistant_app/chat/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
|
public Flux<String> doChatWithLoveAppSSE(String message, String chatId) {
|
|
return assistantApp.doChatByStream(message, chatId);
|
|
}
|
|
|
|
/**
|
|
* SSE 流式调用 AI 智能客服应用
|
|
* 返回 Flux 对象,并且设置泛型为 ServerSentEvent。使用这种方式可以省略 MediaType
|
|
*
|
|
* @param message
|
|
* @param chatId
|
|
* @return
|
|
*/
|
|
@GetMapping(value = "/assistant_app/chat/server_sent_event")
|
|
public Flux<ServerSentEvent<String>> doChatWithAssistantAppServerSentEvent(String message, String chatId) {
|
|
return assistantApp.doChatByStream(message, chatId)
|
|
.map(chunk -> ServerSentEvent.<String>builder()
|
|
.data(chunk)
|
|
.build());
|
|
}
|
|
|
|
/**
|
|
* SSE 流式调用 AI 智能客服应用
|
|
* 使用 SSEEmiter,通过 send 方法持续向 SseEmitter 发送消息
|
|
*
|
|
* @param message
|
|
* @param chatId
|
|
* @return
|
|
*/
|
|
@GetMapping(value = "/assistant_app/chat/sse_emitter")
|
|
public SseEmitter doChatWithAssistantAppServerSseEmitter(String message, String chatId) {
|
|
// 创建一个超时时间较长的 SseEmitter
|
|
SseEmitter sseEmitter = new SseEmitter(180000L); // 3 分钟超时
|
|
// 获取 Flux 响应式数据流并且直接通过订阅推送给 SseEmitter
|
|
assistantApp.doChatByStream(message, chatId)
|
|
.subscribe(chunk -> {
|
|
try {
|
|
sseEmitter.send(chunk);
|
|
} catch (IOException e) {
|
|
sseEmitter.completeWithError(e);
|
|
}
|
|
}, sseEmitter::completeWithError, sseEmitter::complete);
|
|
// 返回
|
|
return sseEmitter;
|
|
}
|
|
|
|
/**
|
|
* RAG 知识库同步对话(支持查询重写策略)
|
|
*
|
|
* @param message 用户消息
|
|
* @param chatId 会话ID
|
|
* @param rewriteStrategy 查询重写策略(可选):NONE/REWRITE/TRANSLATION/COMPRESSION/MULTI_QUERY,默认为 REWRITE
|
|
* @return AI 回答
|
|
*/
|
|
@GetMapping("/assistant_app/chat/rag/sync")
|
|
public String doChatWithRagSync(String message, String chatId, String rewriteStrategy) {
|
|
// 如果未指定策略,默认使用 REWRITE
|
|
String strategy = (rewriteStrategy != null && !rewriteStrategy.isEmpty())
|
|
? rewriteStrategy
|
|
: "REWRITE";
|
|
return assistantApp.doChatWithRagStrategy(message, chatId, strategy);
|
|
}
|
|
}
|