DeepSeek调用API

目录

1.首次调用API

2.通过代码调用API,并解析数据

(1)非流式输出,一次性返回响应信息(以下是通过对象解析方式处理)

(2)非流式输出,一次性返回响应信息(以下是通过JsonNode节点解析方式处理)

(3)流式输出,逐行逐字返回响应信息

3.通过SSE单向推送数据,流式输出数据到前端进行渲染

(1)技术方案选择

(2)后端实现(Spring Boot + SSE)

(3)前端实现(VUE + JavaScript)

(4)展示效果和待优化内容

 

一、首次调用API

调用API首先要创建一个API key,通过地址https://platform.deepseek.com/api_keys 进行创建,创建完成后在列表内会展示刚创建的API key。API key 仅在创建时可见可复制,请妥善保存(后续都会以脱敏方式显示)。不要与他人共享你的 API key,或将其暴露在浏览器或其他客户端代码中。

在创建 API key 之后,你可以使用以下样例脚本的来访问 DeepSeek API。样例为非流式输出,您可以将 stream 设置为 true 来使用流式输出。

curl https://api.deepseek.com/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer Your API key" \ -d '{ "model": "deepseek-chat", "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "你好!"} ], "stream": false }'

二、通过代码调用API,并解析数据

依赖maven

<!-- JSON处理 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.15.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.15.0</version>
</dependency>

关键参数说明

 

1、非流式输出,一次性返回响应信息(以下是通过对象解析方式处理)

常量信息

/**
 * API_KEY
 */
public static final String API_KEY = "sk-XXXXXXXXXXXXXXXXXXXXXXXXX";

/**
 * API_URL
 */
public static final String API_URL = "https://api.deepseek.com/v1/chat/completions";

创建请求对象ChatRequest类

import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.List;

public class ChatRequest {

    /** 必填参数 模型名称,如 "deepseek-chat"*/
    private String model;

    /** 对话消息列表*/
    private List<Message> messages;

    /** 生成文本的随机性(0~2)*/
    private Double temperature;

    /**  生成的最大 token 数 */
    @JsonProperty("max_tokens")
    private Integer maxTokens;

    /** 核采样概率(0~1) */
    @JsonProperty("top_p")
    private Double topP;

    /** 是否流式输出 */
    private Boolean stream;

    // 无参构造函数和 getter/setter 方法
    public ChatRequest() {}

    public ChatRequest(String model, List<Message> messages, Double temperature, Integer maxTokens, Double topP, Boolean stream) {
        this.model = model;
        this.messages = messages;
        this.temperature = temperature;
        this.maxTokens = maxTokens;
        this.topP = topP;
        this.stream = stream;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public List<Message> getMessages() {
        return messages;
    }

    public void setMessages(List<Message> messages) {
        this.messages = messages;
    }

    public Double getTemperature() {
        return temperature;
    }

    public void setTemperature(Double temperature) {
        this.temperature = temperature;
    }

    public Integer getMaxTokens() {
        return maxTokens;
    }

    public void setMaxTokens(Integer maxTokens) {
        this.maxTokens = maxTokens;
    }

    public Double getTopP() {
        return topP;
    }

    public void setTopP(Double topP) {
        this.topP = topP;
    }

    public Boolean getStream() {
        return stream;
    }

    public void setStream(Boolean stream) {
        this.stream = stream;
    }
}

创建返回对象ChatResponse类

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;

@JsonIgnoreProperties(ignoreUnknown = true)
public class ChatResponse {

    private List<Choice> choices;

    // 必须有无参构造函数
    public ChatResponse() {}

    // 带 @JsonProperty 注解的构造函数(可选,但推荐)
    public ChatResponse(@JsonProperty("choices") List<Choice> choices) {
        this.choices = choices;
    }

    // Getter 和 Setter
    public List<Choice> getChoices() {
        return choices;
    }

    public void setChoices(List<Choice> choices) {
        this.choices = choices;
    }
}

创建Choice类

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonIgnoreProperties(ignoreUnknown = true)
public class Choice {

    private Message message;

    public Choice() {}

    public Choice(@JsonProperty("message") Message message) {
        this.message = message;
    }

    public Message getMessage() {
        return message;
    }

    public void setMessage(Message message) {
        this.message = message;
    }
}

创建Message类

@JsonIgnoreProperties(ignoreUnknown = true)
public class Message {

    private String role;
    private String content;

    public Message() {}

    public Message(@JsonProperty("role") String role, @JsonProperty("content") String content) {
        this.role = role;
        this.content = content;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

创建模拟调用的客户端DeepSeekChat

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.learn.common.utils.StringUtils;
import com.learn.common.constant.Constants;
import com.learn.deepseek.pojo.*;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * 非流式输出方式
 */
public class DeepSeekChat {

    // 序列化为 JSON(使用配置好的 ObjectMapper)
    private static ObjectMapper mapper = new ObjectMapper();
    // 创建客户端并发送消息
    private static HttpClient client = HttpClient.newHttpClient();

    /**
     * 创建ChatRequest对象
     *
     * @param message 消息
     * @return ChatRequest对象
     */
    private static ChatRequest createChatRequest(String message) {
        ChatRequest request = new ChatRequest();
        request.setModel("deepseek-chat");
        request.setTemperature(0.7);
        request.setMaxTokens(8192);
        // 设置对话消息
        List<Message> messages = new ArrayList<>();
        messages.add(new Message("user", message));
        request.setMessages(messages);
        return request;
    }

    /**
     * 发送消息
     *
     * @param chatRequest 请求对象
     * @return 响应JSON对象
     */
    private static String sendMessage(ChatRequest chatRequest) {
        String result = null;
        try {
            // 未知参数处理
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            // 请求对象转JSON
            String jsonBody = mapper.writeValueAsString(chatRequest);
            HttpRequest httpRequest = HttpRequest.newBuilder()
                .uri(URI.create(Constants.API_URL))
                .header("Content-Type", "application/json")
                .header("Authorization", "Bearer " + Constants.API_KEY)
                .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                .build();
            // 发送消息
            HttpResponse<String> response = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
            System.out.println("Status Code: " + response.statusCode());
            System.out.println("Response Body: " + response.body());
            if (response.statusCode() != 200) {
                String errorMsg = String.format("请求失败!状态码:%d\n响应内容:%s", response.statusCode(), response.body());
                throw new RuntimeException(errorMsg);
            }
            result = response.body();
        } catch (Exception e) {
            System.err.println("发生异常:" + e.getMessage());
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 解析响应JSON对象
     *
     * @param responseBody 响应JSON对象
     */
    private static void parseResponseBody(String responseBody) {
        if(!StringUtils.isEmpty(responseBody)) {
            try {
                // JSON解析成对象
                ChatResponse chatResponse = mapper.readValue(responseBody, ChatResponse.class);
                if (chatResponse.getChoices().size() > 0) {
                    String content = chatResponse.getChoices().get(0).getMessage().getContent();
                    System.out.println("=== 生成结果 ===\n" + content);
                } else {
                    System.err.println("警告:未收到有效响应内容");
                }
            } catch (JsonProcessingException e) {
                System.err.println("发生异常:" + e.getMessage());
                e.printStackTrace();
            }
        } else {
            System.err.println("警告:未收到有效响应内容");
        }
    }

    public static void main(String[] args) {
        // 1.创建ChatRequest对象,设置对话消息
        ChatRequest chatRequest = createChatRequest("你是谁?");
        // 2.发送消息
        String responseBody = sendMessage(chatRequest);
        // 3.解析对象
        parseResponseBody(responseBody);
    }
}

打印结果:

2.非流式输出,一次性返回响应信息(以下是通过JsonNode节点解析方式处理)

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.learn.common.utils.StringUtils;
import com.learn.common.constant.Constants;
import com.learn.deepseek.pojo.*;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * 非流式输出方式
 */
public class DeepSeekChat {

    // 序列化为 JSON(使用配置好的 ObjectMapper)
    private static ObjectMapper mapper = new ObjectMapper();
    // 创建客户端并发送消息
    private static HttpClient client = HttpClient.newHttpClient();

    /**
     * 创建ChatRequest对象
     *
     * @param message 消息
     * @return ChatRequest对象
     */
    private static ChatRequest createChatRequest(String message) {
        ChatRequest request = new ChatRequest();
        request.setModel("deepseek-chat");
        request.setTemperature(0.7);
        request.setMaxTokens(8192);
        // 设置对话消息
        List<Message> messages = new ArrayList<>();
        messages.add(new Message("user", message));
        request.setMessages(messages);
        return request;
    }

    /**
     * 发送消息
     *
     * @param chatRequest 请求对象
     * @return 响应JSON对象
     */
    private static String sendMessage(ChatRequest chatRequest) {
        String result = null;
        try {
            // 未知参数处理
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            // 请求对象转JSON
            String jsonBody = mapper.writeValueAsString(chatRequest);
            HttpRequest httpRequest = HttpRequest.newBuilder()
                .uri(URI.create(Constants.API_URL))
                .header("Content-Type", "application/json")
                .header("Authorization", "Bearer " + Constants.API_KEY)
                .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                .build();
            // 发送消息
            HttpResponse<String> response = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
            System.out.println("Status Code: " + response.statusCode());
            System.out.println("Response Body: " + response.body());
            if (response.statusCode() != 200) {
                String errorMsg = String.format("请求失败!状态码:%d\n响应内容:%s", response.statusCode(), response.body());
                throw new RuntimeException(errorMsg);
            }
            result = response.body();
        } catch (Exception e) {
            System.err.println("发生异常:" + e.getMessage());
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 解析响应JSON对象
     *
     * @param responseBody 响应JSON对象
     */
    private static void parseResponseBody(String responseBody) {
        if(!StringUtils.isEmpty(responseBody)) {
            try {
                // JSON解析成对象
                ChatResponse chatResponse = mapper.readValue(responseBody, ChatResponse.class);
                if (chatResponse.getChoices().size() > 0) {
                    String content = chatResponse.getChoices().get(0).getMessage().getContent();
                    System.out.println("=== 生成结果 ===\n" + content);
                } else {
                    System.err.println("警告:未收到有效响应内容");
                }
            } catch (JsonProcessingException e) {
                System.err.println("发生异常:" + e.getMessage());
                e.printStackTrace();
            }
        } else {
            System.err.println("警告:未收到有效响应内容");
        }
    }

    public static void main(String[] args) {
        // 1.创建ChatRequest对象,设置对话消息
        ChatRequest chatRequest = createChatRequest("你是谁?");
        // 2.发送消息
        String responseBody = sendMessage(chatRequest);
        // 3.解析对象
        parseResponseBody(responseBody);
    }
}

打印结果

3、流式输出,逐行逐字返回响应信息

依赖maven

 

<!-- 客户端 -->
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.12.0</version>
</dependency>
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.learn.common.constant.Constants;
import com.learn.deepseek.pojo.ChatRequest;
import com.learn.deepseek.pojo.Message;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 流式输出方式
 */
public class DeepSeekChatStream {

    // 序列化为JSON
    private static ObjectMapper mapper = new ObjectMapper();
    // 创建客户端并发送消息
    private static OkHttpClient client = new OkHttpClient();

    /**
     * 创建ChatRequest对象
     *
     * @param message 消息
     * @return ChatRequest对象
     */
    private static ChatRequest createChatRequest(String message) {
        ChatRequest chatRequest = new ChatRequest();
        chatRequest.setModel("deepseek-chat");
        chatRequest.setTemperature(0.7);
        chatRequest.setMaxTokens(8192);
        // 流式输出
        chatRequest.setStream(true);
        // 设置对话消息
        List<Message> messages = new ArrayList<>();
        messages.add(new Message("user", message));
        chatRequest.setMessages(messages);
        return chatRequest;
    }

    /**
     * 异步发送消息,处理流式响应
     *
     * @param chatRequest 请求对象
     * @return 响应JSON对象
     */
    private static void sendMessage(ChatRequest chatRequest) {
        try {
            // 请求对象转JSON
            String jsonBody = mapper.writeValueAsString(chatRequest);
            // 创建客户端并发送消息
            Request request = new Request.Builder()
                .url(Constants.API_URL)
                .header("Authorization", "Bearer " + Constants.API_KEY)
                .post(RequestBody.create(jsonBody, MediaType.get("application/json")))
                .build();
            // 异步发送请求并处理流式响应
            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {
                    System.err.println("请求异常: " + e.getMessage());
                }

                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                    if (!response.isSuccessful()) {
                        System.err.println("请求失败: " + response.code());
                        return;
                    }
                    // 逐块读取响应流
                    try (ResponseBody responseBody = response.body()) {
                        if (responseBody != null) {
                            // 使用字符流逐行读取
                            responseBody.source().request(Long.MAX_VALUE);
                            while (true) {
                                // 逐行读取响应流
                                String line = responseBody.source().readUtf8Line();
                                // 流结束
                                if (line == null) break;
                                // 解析并打印内容(例如:data: {"content": "Hi..."})
                                processLine(line);
                            }
                        }
                    }
                }
            });
        } catch (Exception e) {
            System.err.println("发生异常:" + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 解析单行数据并打印内容
     *
     * @param line 逐行读取
     */
    private static void processLine(String line) {
        if (line.startsWith("data: ")) {
            String json = line.substring(6).trim();
            if (json.equals("[DONE]")) {
                System.out.println("\n流式传输结束");
                return;
            }
            try {
                JsonNode node = mapper.readTree(json);
                String content = node.path("choices").get(0).path("delta").path("content").asText();
                if (!content.isEmpty()) {
                    // 逐字符打印,模拟聊天效果
                    for (char c : content.toCharArray()) {
                        System.out.print(c);
                        // 控制输出速度
                        Thread.sleep(50);
                    }
                }
            } catch (Exception e) {
                System.err.println("解析错误: " + e.getMessage());
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        // 1.创建ChatRequest对象,设置对话消息
        ChatRequest chatRequest = createChatRequest("你是谁?");
        // 2.异步发送消息,处理流式响应
        sendMessage(chatRequest);
    }
}

输出结果

三、通过SSE单向推送数据,流式输出数据到前端进行渲染

要在 Web 页面实现流式输出的逐字响应效果(类似 DeepSeek 的逐字生成),需要 前后端配合,核心思路是:后端通过流式接口获取数据后,将数据分块(chunk)推送到前端,前端逐步渲染。

完整流程图

客户端发起 SSE 请求 → 服务器保持连接 → 分块发送数据 → 客户端实时渲染 → 流结束或断开

1、技术方案选择

2、后端实现(Spring Boot + SSE)

添加依赖

        <!-- SpringBoot Web容器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- JSON处理 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.15.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.15.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.15.0</version>
        </dependency>

        <!-- okhttp3 -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.14.9</version>
        </dependency>

创建处理流式调用Controller

package com.learn.web.controller.deepseek;

import com.learn.common.core.controller.BaseController;
import com.learn.deepseek.service.IStreamService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
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;

/**
 * 处理流式调用Controller
 *
 * @author chengx
 * @date 2025-03-24
 */
@RestController
@RequestMapping("/stream")
public class StreamController extends BaseController
{

    @Autowired
    private IStreamService streamService;

    /**
     * 创建 SSE 连接端点
     */
    @GetMapping(value = "/streamData", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter streamData(String message) {
        // 超时时间 300 秒
        SseEmitter emitter = new SseEmitter(300_000L);
        new Thread(() -> streamService.callStreamApi(message, emitter)).start();
        return emitter;
    }
}


处理流式调用Service

package com.learn.deepseek.service;

import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

/**
 * 处理流式调用Service
 *
 * @author chengx
 * @date 2025-03-24
 */
public interface IStreamService {

    /**
     * 调用流式API
     *
     * @param message 请求消息
     * @param emitter sse发射器
     */
    public void callStreamApi(String message, SseEmitter emitter);
}
处理流式调用Service业务层处理
package com.learn.deepseek.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.learn.common.constant.DeepSeekConstants;
import com.learn.deepseek.pojo.ChatRequest;
import com.learn.deepseek.pojo.Message;
import com.learn.deepseek.service.IStreamService;
import okhttp3.*;
import okio.BufferedSource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 处理流式调用Service业务层处理
 *
 * @author chengx
 * @date 2025-03-24
 */
@Service
public class StreamServiceImpl implements IStreamService {

    /**
     * 序列化为JSON
     */
    private ObjectMapper mapper = new ObjectMapper();

    /**
     * 创建客户端并发送消息
     */
    private OkHttpClient client = new OkHttpClient();

    /**
     * 创建ChatRequest对象
     *
     * @param message 消息
     * @return ChatRequest对象
     */
    private ChatRequest createChatRequest(String message) {
        ChatRequest chatRequest = new ChatRequest();
        chatRequest.setModel("deepseek-chat");
        chatRequest.setTemperature(0.7);
        chatRequest.setMaxTokens(8192);
        // 流式输出
        chatRequest.setStream(true);
        // 设置对话消息
        List<Message> messages = new ArrayList<>();
        messages.add(new Message("user", message));
        chatRequest.setMessages(messages);
        return chatRequest;
    }

    /**
     * 解析单行数据并打印内容
     *
     * @param chunk 逐块读取
     * @param emitter sse发射器
     */
    private void processChunk(String chunk, SseEmitter emitter) {
        if (chunk.startsWith("data: ")) {
            String json = chunk.substring(6).trim();
            if (json.equals("[DONE]")) {
                System.out.println("\n流式传输结束");
                return;
            }
            try {
                JsonNode node = mapper.readTree(json);
                String content = node.path("choices").get(0).path("delta").path("content").asText();
                if (StringUtils.isNotEmpty(content)) {
                    try {
                        // 推送数据到前端
                        emitter.send(content);
                        System.out.print(content);
                        // 模拟延迟,控制输出速度
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        System.err.println("请求异常: " + e.getMessage());
                        e.printStackTrace();
                    }
                }
            } catch (Exception e) {
                System.err.println("解析错误: " + e.getMessage());
                e.printStackTrace();
            }
        }
    }

    /**
     * 调用流式API
     *
     * @param message 请求消息
     * @param emitter sse发射器
     */
    @Override
    public void callStreamApi(String message, SseEmitter emitter) {
        try {
            // 1.创建ChatRequest对象,设置对话消息
            ChatRequest chatRequest = createChatRequest(message);
            // 2.请求对象转JSON
            String jsonBody = mapper.writeValueAsString(chatRequest);
            RequestBody requestBody = RequestBody.create(MediaType.get("application/json"), jsonBody);
            // 3.创建客户端并发送消息
            Request request = new Request.Builder()
                .url(DeepSeekConstants.API_URL)
                .header("Authorization", "Bearer " + DeepSeekConstants.API_KEY)
                .post(requestBody)
                .build();
            // 4.异步发送请求并处理流式响应
            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {
                    emitter.completeWithError(e);
                    System.err.println("请求异常: " + e.getMessage());
                }

                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) {
                    try (ResponseBody responseBody = response.body()) {
                        if (!response.isSuccessful()) {
                            emitter.completeWithError(new RuntimeException("API 请求失败"));
                            return;
                        }
                        // 5.逐块读取流式响应
                        BufferedSource source = responseBody.source();
                        while (!source.exhausted()) {
                            String chunk = source.readUtf8Line();
                            if(StringUtils.isNotBlank(chunk)) {
                                // 6.解析单行数据并打印内容
                                processChunk(chunk, emitter);
                            }
                        }
                        // 标记完成
                        emitter.complete();
                    } catch (IOException e) {
                        emitter.completeWithError(e);
                        System.err.println("请求异常: " + e.getMessage());
                    }
                }
            });
        } catch (Exception e) {
            emitter.completeWithError(e);
            System.err.println("发生异常:" + e.getMessage());
        }
    }
}

3、前端实现(VUE + JavaScript)

创建stream.vue处理流式输出内容渲染

<template>
  <div class="app-container">
    <div class="output">{{ outputText }}</div>
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
      <el-form-item prop="inputMessage">
        <el-input
          v-model="queryParams.inputMessage"
          placeholder="给 DeepSeek 发送消息"
          clearable
          style="width: 240px"
          @keyup.enter="startStream"
        />
      </el-form-item>
      <el-form-item>
        <el-button
          type="primary"
          size="small"
          @click="startStream"
          :icon="icon"
        >发送</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        // 查询参数
        queryParams: {
          inputMessage: "",
        },
        // 输出文本
        outputText: "",
        // 保存 SSE 连接对象
        eventSource: null,
        // 搜索图标
        icon: 'el-icon-search'
      };
    },
    methods: {
      // 发送
      startStream() {
        // 关闭旧连接(如果存在)
        if (this.eventSource) {
          this.eventSource.close();
        }
        this.icon = 'el-icon-loading'
        // 清空输出
        this.outputText = "";
        const message = this.queryParams.inputMessage
        const url = "http://localhost:18080/stream/streamData?message=" + message

        // 创建 EventSource 实例
        this.eventSource = new EventSource(url);

        // 连接打开时触发
        this.eventSource.onopen = () => {
          console.log(this.eventSource.readyState)
          console.log(this.eventSource.withCredentials)
        };

        // 监听消息事件
        this.eventSource.onmessage = (event) => {
          console.log("收到数据:", event.data)
          // 逐字显示
          this.appendText(event.data);
        };

        // 监听错误(连接发生错误或中断)
        this.eventSource.onerror = (error) => {
          console.error("SSE 错误:", error);
          this.eventSource.close();
          // 流数出结束更换按钮图标
          this.icon = 'el-icon-search'
        };
      },
      // 逐字追加文本(模拟打字机效果)
      appendText(text) {
        let index = 0;
        const addChar = () => {
          if (index < text.length) {
            this.outputText += text.charAt(index);
            index++;
            addChar();
          }
        };
        addChar();
      },
    },
    // 组件销毁时关闭连接
    beforeUnmount() {
      if (this.eventSource) {
        this.eventSource.close();
      }
    },
  };
</script>

<style scoped>
  .output {
    white-space: pre-wrap;
    margin-top: 20px;
    border: 1px solid #ccc;
    padding: 10px;
    margin-bottom: 10px;
  }
</style>

4、展示效果和待优化内容

输出结果

 

待优化内容:

1、输出格式还需要优化,目前版本不能换行

2、输出速度没有控制的话,会出现文字前后交叉错乱情况

posted on 2025-04-02 11:13  天涯明月夜  阅读(1073)  评论(0)    收藏  举报