前言

在前面的开发过程中,完成了基于MCP的AI模型的功能添加和输入输出护轨的实现,此次主要的任务是完成SSE流式输出和前端的搭建

SSE

概念

SSE(Server-Sent Events) 是一种用于在客户端和服务器之间进行单向实时通信的技术。它允许服务器主动向客户端推送数据,而不需要客户端不断地发起请求。这种方式特别适合于需要实时更新的应用场景,比如聊天应用、实时通知等

在AI 应用中,使用 SSE 可以实现流式输出,也就是类似打字机的效果。进而提升用户体验,避免用户一直要等待至结果全部加载。通过将 AI 的响应逐步推送到客户端,用户可以实时看到对话进展,增强交互感

实现

这里我们使用Flux实现流式输出,Flux是提供的响应式流类型,广泛用于 Spring WebFlux、响应式微服务等场景。 langchain4j 为了支持响应式流(Reactor/Flux)而做的适配扩展,通过引入以下配置

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-reactor</artifactId>
    <version>1.1.0-beta7</version>
</dependency>

给 AI Service 增加流式对话方法,定义chatStream 方法返回一个 Flux<String>,表示一个响应式流,允许逐步接收 AI 的输出。

@InputGuardrails({SafeInputGuardrail.class})
@OutputGuardrails({SafeOutputGuardrail.class})
public interface Ai408HelperService {

    //······
    //流式对话
    Flux<String> chatStream(@MemoryId int memoryId, @UserMessage String userMessage);
}

增加流式模型配置API后,指定流式对话模型并注入

@Resource
private StreamingChatModel qwenStreamingChatModel;

Ai408HelperService ai408HelperService = AiServices.builder(Ai408HelperService.class)
        .chatModel(myQwenChatModel)
        .streamingChatModel(qwenStreamingChatModel)
        .chatMemory(chatMemory)
        .chatMemoryProvider(memoryId ->
                MessageWindowChatMemory.withMaxMessages(10)) // 每个会话独立存储
        .contentRetriever(contentRetriever) // RAG 检索增强生成
        .tools(new InterviewQuestionTool()) // 工具调用
        .toolProvider(mcpToolProvider) // MCP 工具调用
        .build();

编写 Controller 接口

@RestController
@RequestMapping("/ai")
publicclass AiController {

    @Resource
    private Ai408HelperService ai408HelperService;

    @GetMapping("/chat")
    public Flux<ServerSentEvent<String>> chat(int memoryId, String message) {
        return ai408HelperService.chatStream(memoryId, message)
                .map(chunk -> ServerSentEvent.<String>builder()
                        .data(chunk)
                        .build());
    }
}

前端

前端采用Vue框架进行开发

配置跨域

前后端分离开发时,前端和后端通常不在同一个端口或域名,必须配置 CORS(Cross-Origin Resource Sharing,即“跨域资源共享”),否则前端请求会被浏览器拦截

@Configuration
publicclass CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
       
        registry.addMapping("/**")
                .allowCredentials(true)
                .allowedOriginPatterns("*")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
}

前端我主要通过AI辅助设计,通过输入设计文档等方法帮助开发,快速生成了前端代码

最终效果如下:

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐