引入依赖

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.42</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.6.0</version>
        </dependency>

代码

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

/**
 * deepseek工具类
 */
@Component
public class DeepSeekUtil {

    private final Logger log = LoggerFactory.getLogger(DeepSeekUtil.class);

    private static OkHttpClient client;

    private final static String CHAT_URL = "/v1/chat/completions";

    private static String deepseekHost;
    @Value("${deepseekHost}")
    public void setDeepseekHost(String deepseekHost) {
        DeepSeekUtil.deepseekHost = deepseekHost;
    }

    private static String deepseekChatUrl;
    @Value("${deepseekChatUrl}")
    public void setDeepseekChatUrl(String deepseekChatUrl) {
        DeepSeekUtil.deepseekChatUrl = deepseekChatUrl;
    }

    private static String deepseekApiKey;
    @Value("${deepseekApiKey}")
    public void setDeepseekApiKey(String deepseekApiKey) {
        DeepSeekUtil.deepseekApiKey = deepseekApiKey;
    }

    private static String deepseekModel;
    @Value("${deepseekModel}")
    public void setDeepseekModel(String deepseekModel) {
        DeepSeekUtil.deepseekModel = deepseekModel;
    }


    DeepSeekUtil(){
        client = new OkHttpClient.Builder()
            .connectTimeout(60, TimeUnit.SECONDS) // 连接超时 60s
            .readTimeout(120, TimeUnit.SECONDS)   // 读取超时 120s
            .writeTimeout(60, TimeUnit.SECONDS)   // 写入超时 60s
            .build();
    }

    /**
     * deepseek会话回复接口
     */
    @FunctionalInterface
    public interface ReplyFunction {
        void apply(String reasoningContent, String content);
    }

    /**
     * deepseek会话
     * @param question 问题
     * @param maxTokens 最大回复量
     * @param preMessage 之前的消息,用于多轮会话
     * @return
     * @throws IOException
     */
    public void chat(ReplyFunction replyFunction, String question, int maxTokens, JSONArray preMessage) throws IOException {

        JSONArray messages = new JSONArray();

        if (preMessage != null) {
            messages.addAll(preMessage);
        }

        JSONObject message = new JSONObject();
        message.put("role", "user");
        message.put("content", question);
        messages.add(message);

        JSONObject json = new JSONObject();
        json.put("model", deepseekModel);
        json.put("messages", messages);
        json.put("max_tokens", maxTokens);
        json.put("stream", true);

        RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json.toString());
        Request request = new Request.Builder()
                .url(deepseekHost + CHAT_URL)
                .addHeader("Authorization", "Bearer " + deepseekApiKey)
                .post(body).build();

        Response response = client.newCall(request).execute();

        if (response.code() == 401 || response.code() == 403) {
            throw new BadRequestAlertException("Unauthorized", "认证失败", "");
        }

        // 获取响应流
        InputStream inputStream = response.body().byteStream();

        // 包装为BufferedReader,指定编码方式
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));

        String line;

        try {
            // 逐行读取数据
            while ((line = reader.readLine()) != null) {
                String str = line.replace("data:", "");
                if (!StringUtils.hasText(str) || "[DONE]".equals(str.trim())) continue;

                try {
                    JSONObject responseJson = JSONObject.parseObject(str);
                    if (responseJson.containsKey("choices") && !responseJson.getJSONArray("choices").isEmpty()) {
                        JSONObject delta = responseJson.getJSONArray("choices")
                            .getJSONObject(0)
                            .getJSONObject("delta");
                        // 有些模型思考内容会在reasoning_content中单独返回
                        String reasoningContent = delta.getString("reasoning_content");
                        String content = delta.getString("content");

                        boolean isFinish = "stop".equals(responseJson.getJSONArray("choices").getJSONObject(0).get("finish_reason"));

                        replyFunction.apply(reasoningContent, content);
                    }
                } catch (Exception e) {
                    log.error(line);
                }
            }
        } catch (IOException e) {
            log.error("unreadable response", e);
        } finally {
            // 确保关闭所有流和资源
            try {
                reader.close();
            } catch (IOException e) {
                log.error("close BufferedReader error", e);
            }
        }
    }
}
最后修改:2025 年 03 月 11 日
如果觉得我的文章对你有用,请随意赞赏