✍️【技术宅拯救世界】SpringBoot×LangChain:本地化DeepSeek流式对话全栈实战指南

119 阅读2分钟

大家好,我是你们的技术火锅博主,今天我们要涮的不是羊肉,而是让本地部署的DeepSeek大模型在你的SpringBoot应用中"咕嘟咕嘟"沸腾起来!全程高能预警,附带前后端完整代码,保证你吃完这顿还能打包源码回家二次烹饪~


一、食材准备(环境依赖)

先来看看我们的技术火锅底料配方:

xml
<!-- 先来口汤底:SpringBoot父级配方 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.5</version>
    <relativePath/>
</parent>

<dependencies>
    <!-- 主菜:Web魔法锅 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- 响应式火焰喷射器 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

    <!-- 智能锅铲(HTTP客户端) -->
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>4.12.0</version>
    </dependency>

    <!-- 灵魂调味料(Lombok) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <!-- JSON解剖刀 -->
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20231013</version>
    </dependency>
</dependencies>

🚀 火力升级指南

二、熬制汤底(SpringBoot后端篇)

2.1 灵魂蘸料 - DeepSeek客户端

java
@Component
@Slf4j
public class DeepSeekChef {
    
    private static final String LOCAL_API = "http://192.168.1.88:8080/deepseek/v1/chat/completions";

    public Flux<String> cookStreamResponse(String prompt) {
        return WebClient.create()
            .post()
            .uri(LOCAL_API)
            .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .bodyValue(createRequest(prompt))
            .retrieve()
            .bodyToFlux(String.class)
            .map(this::extractContent)
            .onErrorResume(e -> {
                log.error("厨房失火啦!", e);
                return Flux.just("🔥 厨师把锅烧穿了:" + e.getMessage());
            });
    }

    private String extractContent(String json) {
        // JSON解析逻辑(记得处理流式响应中的delta内容)
        return new JSONObject(json).optString("content", "");
    }
}

2.2 传菜窗口 - SSE控制器

java
@RestController
@RequestMapping("/ai-diner")
public class AIController {
    
    @Autowired
    private DeepSeekChef chef;

    @GetMapping(path = "/stream-chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<String>> streamChat(@RequestParam String message) {
        return chef.cookStreamResponse(message)
            .map(content -> ServerSentEvent.<String>builder()
                .data(content)
                .build())
            .doOnComplete(() -> log.info("👨🍳 用户已光盘!"));
    }
}

三、摆盘艺术(Vue前端篇)

3.1 智能涮锅界面

vue
<template>
  <div class="ai-wok">
    <div class="bubble-area">
      <div v-for="(msg, index) in messages" :key="index" 
           class="bubble" :class="{ 'ai-bubble': msg.role === 'AI' }">
        <span class="streaming" v-if="msg.streaming">{{ msg.content }}█</span>
        <template v-else>{{ msg.content }}</template>
      </div>
    </div>
    
    <div class="control-panel">
      <input v-model="inputMsg" @keyup.enter="sendMsg" />
      <button @click="sendMsg" :disabled="isCooking">
        {{ isCooking ? '烹饪中...' : '上菜!' }}
      </button>
    </div>
  </div>
</template>

3.2 核心火候控制

javascript
<script>
export default {
  data() {
    return {
      inputMsg: '',
      messages: [],
      isCooking: false,
      eventSource: null
    }
  },
  methods: {
    sendMsg() {
      if (!this.inputMsg.trim()) return;
      
      this.messages.push({
        role: 'AI',
        content: '',
        streaming: true
      });
      
      const index = this.messages.length - 1;
      this.isCooking = true;
      
      this.eventSource = new EventSource(`/ai-diner/stream-chat?message=${encodeURIComponent(this.inputMsg)}`);
      
      this.eventSource.onmessage = (e) => {
        this.messages[index].content += e.data;
        this.$nextTick(() => window.scrollTo(0, document.body.scrollHeight));
      };
      
      this.eventSource.onerror = () => {
        this.isCooking = false;
        this.eventSource.close();
      };
      
      this.inputMsg = '';
    }
  }
}
</script>

四、摆盘效果展示

(想象一下这里有个实时生成文字的打字机效果动图)


五、涮锅秘诀(关键技术点)

  1. 流式管道搭建:采用Spring WebFlux的Flux响应式流,像传送带一样持续输送"美味数据"
  2. SSE协议加持:比WebSocket更轻量的实时通讯方案,完美契合流式场景
  3. 防粘锅处理:前端消息队列的动态索引管理,防止多并发请求导致的数据混乱
  4. 异常熔断机制:通过onErrorResume保证即使厨房着火也不影响餐厅营业

六、涮后总结

现在你的本地DeepSeek已经像海底捞的服务员一样随时待命啦!通过这套方案,我们实现了:
✅ 本地模型的安全调用
✅ 丝滑的流式交互体验
✅ 完整的推理过程可视化
✅ 火锅级...哦不,企业级的稳定服务

最后友情提示:吃火锅别忘加麻酱,调代码记得加日志!遇到任何"糊锅"问题,欢迎在评论区涮(酸)我~