Spring AI + MCP + DeepSeek-R1-7B + SSE 全流程實(shí)戰(zhàn)指南
作者:編程疏影 
  通過以上步驟,我們成功實(shí)現(xiàn)了:Ollama 部署并運(yùn)行 DeepSeek-R1-7B 本地大模型;Spring Boot 封裝 OpenAI 接口 ??stream: true??;實(shí)現(xiàn)后端 SSE 推流 + 前端實(shí)時(shí) Token 渲染;支持國產(chǎn)開源模型的類 ChatGPT 對話功能?。
 本教程將帶你從 0 到 1 實(shí)現(xiàn)一個(gè)完整的 AI 流式問答應(yīng)用,整合以下組件:
- Spring Boot + Spring AI 構(gòu)建服務(wù)框架
 - MCP(Model Connector Plugin) 用于統(tǒng)一管理本地/云端大模型
 - DeepSeek-R1-7B 國產(chǎn)高性能大模型(OpenAI API 兼容)
 - SSE(Server-Sent Events) 實(shí)現(xiàn)前后端實(shí)時(shí)流式響應(yīng)
 - Ollama(可選) 更便捷地部署 DeepSeek-R1-7B 模型并提供 OpenAI 接口支持
 
模型部署方式推薦:Ollama 運(yùn)行 DeepSeek-R1-7B
安裝 Ollama
訪問:https://ollama.com
# macOS / Linux 安裝
curl-fsSL https://ollama.com/install.sh |sh
# Windows:安裝官方 MSI 安裝包拉取模型(以 DeepSeek 為例)
ollama pull deepseek:chat也可以加載其它模型,如
llama3,qwen:chat,yi:34b,phi3,mistral等。
啟動 Ollama
ollama run deepseek:chatOllama 會自動監(jiān)聽 OpenAI 風(fēng)格接口(http://localhost:11434/v1/chat/completions),兼容 stream: true。
Spring Boot 接入 SSE 流式輸出服務(wù)
添加依賴(pom.xml)
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
</dependencies>WebClient 配置類
@Configuration
public class WebClientConfig {
    @Bean
    public WebClient webClient() {
        return WebClient.builder()
                .baseUrl("http://localhost:11434/v1") // Ollama API 地址
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .build();
    }
}請求體結(jié)構(gòu)封裝
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChatCompletionRequest {
    private String model;
    private List<Map<String, String>> messages;
    private boolean stream = true;
    private double temperature = 0.7;
}DeepSeek-R1-7B 接口封裝(支持 stream: true)
@Service
public class DeepSeekStreamingService {
    @Autowired
    private WebClient webClient;
    public void streamChat(String userPrompt, SseEmitter emitter) {
        ChatCompletionRequest request = new ChatCompletionRequest();
        request.setModel("deepseek:chat");
        request.setStream(true);
        request.setMessages(List.of(
                Map.of("role", "user", "content", userPrompt)
        ));
        webClient.post()
                .uri("/chat/completions")
                .body(BodyInserters.fromValue(request))
                .accept(MediaType.TEXT_EVENT_STREAM)
                .retrieve()
                .bodyToFlux(String.class)
                .doOnNext(chunk -> {
                    try {
                        if (chunk.contains("[DONE]")) {
                            emitter.send(SseEmitter.event().data("[DONE]"));
                            emitter.complete();
                        } else if (chunk.startsWith("data:")) {
                            String json = chunk.replaceFirst("data: *", "");
                            String token = parseTokenFromJson(json);
                            emitter.send(SseEmitter.event().data(token));
                        }
                    } catch (Exception e) {
                        emitter.completeWithError(e);
                    }
                })
                .doOnError(emitter::completeWithError)
                .subscribe();
    }
    private String parseTokenFromJson(String json) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode node = mapper.readTree(json);
            return node.path("choices").get(0).path("delta").path("content").asText("");
        } catch (Exception e) {
            return "";
        }
    }
}控制器對外暴露 SSE 接口
@RestController
@RequestMapping("/api/ai")
public class ChatSseController {
    @Autowired
    private DeepSeekStreamingService streamingService;
    @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter stream(@RequestParam("prompt") String prompt) {
        SseEmitter emitter = new SseEmitter(0L); // 永不超時(shí)
        streamingService.streamChat(prompt, emitter);
        return emitter;
    }
}前端 JS 接入 SSE 實(shí)現(xiàn)流式展示
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>AI 流式問答</title>
</head>
<body>
  <input id="prompt" placeholder="請輸入你的問題...">
  <button onclick="startStream()">提問</button>
  <div id="result"></div>
  <script>
    function startStream() {
      const prompt = document.getElementById('prompt').value;
      const eventSource = new EventSource(`/api/ai/stream?prompt=${encodeURIComponent(prompt)}`);
      document.getElementById('result').innerHTML = '';
      eventSource.onmessage = function (event) {
        if (event.data === '[DONE]') {
          eventSource.close();
        } else {
          document.getElementById('result').innerHTML += event.data;
        }
      };
    }
  </script>
</body>
</html>總結(jié)
通過以上步驟,我們成功實(shí)現(xiàn)了:
- Ollama 部署并運(yùn)行 DeepSeek-R1-7B 本地大模型
 - Spring Boot 封裝 OpenAI 接口 
stream: true - 實(shí)現(xiàn)后端 SSE 推流 + 前端實(shí)時(shí) Token 渲染
 - 支持國產(chǎn)開源模型的類 ChatGPT 對話功能
 
責(zé)任編輯:武曉燕 
                    來源:
                    路條編程
 














 
 
 



















 
 
 
 