文章目录文件下载效果展示IdeaPythonPostman使用说明核心代码controllerService文件下载百度网盘 提取码: jsfc蓝奏云 密码:5kxz效果展示IdeaPythonPostman注postman中只有websocket才有流式效果使用说明修改配置文件请求路径为/chat在请求体中传入对话列表可以携带对话的历史记录[ { content: 你是一个乐于助人的助手。, role: system }, { content: 记住a1,b2, role: user }, { content: 好的我已经记住了**a 1****b 2**。如果有其他问题或需要进一步帮助请告诉我 ??, role: assistant }, { content: a b等于什么, role: user } ] 响应结果如下 根据我记住的 **a 1** 和 **b 2****a b 1 2 3**。 结果是 **3**还有其他问题吗 ??核心代码controllerimport com.deepseek.deepseekdemo.service.AiChatService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; import reactor.core.scheduler.Schedulers; import java.util.List; import java.util.Map; RestController public class AiChatController { Autowired private AiChatService aiChatService; GetMapping(value /chat, produces application/streamjson) public FluxString chat(RequestBody ListMapString, String messages) { FluxString responseFlux aiChatService.chat(messages); return Flux.create(sink - { responseFlux.subscribeOn(Schedulers.boundedElastic()) .subscribe( sink::next, // 返回流式字符串 sink::error, // 返回错误请在调用端完成错误处理 sink::complete // 返回完成事件 ); }); } }Serviceimport com.deepseek.deepseekdemo.config.DeepSeekConfig; import com.deepseek.deepseekdemo.dto.AiMessageDto; import com.deepseek.deepseekdemo.dto.DefaultAiMessageDto; import com.deepseek.deepseekdemo.dto.StreamingAiMessageDto; import com.deepseek.deepseekdemo.service.AiChatService; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import okhttp3.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; Slf4j Service public class AiChatServiceA implements AiChatService { MapString, Object body new HashMap(); Headers headers; AiMessageDto aiMessageDto; Autowired private DeepSeekConfig deepSeekConfig; Autowired private OkHttpClient httpClient; // 初始化 PostConstruct public void init() { body.put(model, deepSeekConfig.getModel()); body.put(frequency_penalty, deepSeekConfig.getFrequencyPenalty()); body.put(max_tokens, deepSeekConfig.getMaxTokens()); body.put(presence_penalty, deepSeekConfig.getPresencePenalty()); body.put(response_format, deepSeekConfig.getResponseFormat()); body.put(stop, deepSeekConfig.getStop()); body.put(stream, deepSeekConfig.getStream()); if (deepSeekConfig.getStream()) { body.put(stream_options, deepSeekConfig.getStreamOptions()); } body.put(temperature, deepSeekConfig.getTemperature()); body.put(top_p, deepSeekConfig.getTopP()); body.put(tools, deepSeekConfig.getTools()); body.put(tool_choice, deepSeekConfig.getToolChoice()); if (deepSeekConfig.getLogprobs()) { body.put(logprobs, deepSeekConfig.getLogprobs()); body.put(top_logprobs, deepSeekConfig.getTopLogprobs()); } // 构建请求头 headers new Headers.Builder().add(Authorization, Bearer deepSeekConfig.getApiKey()).add(Content-Type, application/json).build(); if (deepSeekConfig.getStream()) { aiMessageDto new StreamingAiMessageDto(); } else { aiMessageDto new DefaultAiMessageDto(); } } Override public FluxString chat(ListMapString, String question) { body.put(messages, question); // 将请求体转换为 JSON 字符串 ObjectMapper objectMapper new ObjectMapper(); String payload; try { payload objectMapper.writeValueAsString(body); } catch (JsonProcessingException e) { throw new RuntimeException(无法将负载转换为JSON, e); } // 构建请求 Request request new Request.Builder().url(deepSeekConfig.getUrl()).post(RequestBody.create(payload, MediaType.parse(application/json))).headers(headers).build(); // 返回 FluxString 以流式返回数据 return Flux.create(emitter - { try (Response response httpClient.newCall(request).execute()) { if (!response.isSuccessful()) { emitter.error(new IOException(请求失败响应码: response.code())); return; } // 处理流式响应 ResponseBody responseBody response.body(); if (responseBody ! null) { while (!responseBody.source().exhausted()) { String line responseBody.source().readUtf8Line(); if (line ! null !line.isEmpty()) { try { emitter.next(aiMessageDto.getMessage(line)); // 逐步发送数据 } catch (Exception e) { log.error(处理数据时发生错误: , e); } } } emitter.complete(); // 完成流 } } catch (IOException e) { emitter.error(e); } }); } }