自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

JDK1.8也可以對(duì)接DeepSeek-R1,你知道嗎?

人工智能
AI4J 是一款 Java SDK,用于快速接入 AI 大模型應(yīng)用。它能整合多平臺(tái)大模型,如 OpenAI、Ollama、智譜 Zhipu(ChatGLM)、深度求索 DeepSeek、月之暗面 Moonshot(Kimi)、騰訊混元 Hunyuan、零一萬(wàn)物(01)等,為用戶(hù)提供快速整合 AI 的能力。

什么是ai4j

首先,我們先了解一下什么是ai4j。

AI4J 是一款 Java SDK,用于快速接入 AI 大模型應(yīng)用。它能整合多平臺(tái)大模型,如 OpenAI、Ollama、智譜 Zhipu(ChatGLM)、深度求索 DeepSeek、月之暗面 Moonshot(Kimi)、騰訊混元 Hunyuan、零一萬(wàn)物(01)等,為用戶(hù)提供快速整合 AI 的能力。

其特點(diǎn)包括提供統(tǒng)一的輸入輸出(對(duì)齊 OpenAI)以消除差異化,優(yōu)化函數(shù)調(diào)用(Tool Call)和 RAG 調(diào)用,支持向量數(shù)據(jù)庫(kù)(如 Pinecone),并且支持 JDK1.8,能滿(mǎn)足很多仍在使用 JDK8 版本的應(yīng)用需求。

敲重點(diǎn):JDK1.8

看過(guò)上一篇使用SpringAI的都知道,SpringAI對(duì)JDK的要求非常高,那次了不起使用了JDK 17,但是Java發(fā)展了這么多年,很多項(xiàng)目都是基于JDK1.8來(lái)構(gòu)建的,你讓他們現(xiàn)在去升級(jí)JDK,可能AI還沒(méi)接入,項(xiàng)目就先起不來(lái)了。

也因此誕生了ai4j,他支持 JDK1.8,能滿(mǎn)足很多仍在使用 JDK8 版本的應(yīng)用需求,并且向量數(shù)據(jù)庫(kù)還能幫助很多項(xiàng)目做知識(shí)庫(kù)搜索。

進(jìn)入正題

我們使用目前最新版本的ai4j。

<dependency>
      <groupId>io.github.lnyo-cly</groupId>
      <artifactId>ai4j</artifactId>
      <version>0.8.1</version>
  </dependency>

現(xiàn)在網(wǎng)上很多版本的ai4j都不支持ollama調(diào)用,所以直接使用最新版本的話,就沒(méi)有問(wèn)題了。

我們依舊是寫(xiě)兩個(gè)接口,一個(gè)直接返回,一個(gè)流式返回。

IChatService chatService = aiService.getChatService(PlatformType.OLLAMA);

通過(guò)getChatService的方式,選擇是用本地ollama還是其他平臺(tái)。

它一共支持以下平臺(tái)。

@AllArgsConstructor
@Getter
public enum PlatformType {
    OPENAI("openai"),
    ZHIPU("zhipu"),
    DEEPSEEK("deepseek"),
    MOONSHOT("moonshot"),
    HUNYUAN("hunyuan"),
    LINGYI("lingyi"),
    OLLAMA("ollama"),
    MINIMAX("minimax"),
    BAICHUAN("baichuan"),
    ;
   ....
}

由于我修改過(guò)ollama的端口,所以我沒(méi)辦法使用默認(rèn)的端口,需要單獨(dú)設(shè)置調(diào)用的url。

spring.application.name=demo
server.port=8080
ai.ollama.api-host=http://localhost:8000

創(chuàng)建請(qǐng)求體:

// 創(chuàng)建請(qǐng)求參數(shù)
  ChatCompletion chatCompletion = ChatCompletion.builder()
         .model("deepseek-r1:7b")
         .message(ChatMessage.withUser(question))
         .build();

直接返回就調(diào)用chatCompletion方法:

// 發(fā)送chat請(qǐng)求
ChatCompletionResponse chatCompletionResponse = chatService.chatCompletion(chatCompletion);

流式放回就調(diào)用chatCompletionStream方法:

// 發(fā)送chat請(qǐng)求
chatService.chatCompletionStream(chatCompletion, sseListener);

流式的話他是以SSE端點(diǎn)的形式去獲取數(shù)據(jù),所以需要你實(shí)現(xiàn)一個(gè)SSE監(jiān)聽(tīng)器去打印和發(fā)送數(shù)據(jù)給前端。

以下是完整的后端接口:

@RestController
@CrossOrigin
public class OllamChatController {
    // 注入Ai服務(wù)
    @Autowired
    private AiService aiService;

    @GetMapping("/chat")
    public String getChatMessage(@RequestParam String question) throws Exception {
        // 獲取OLLAMA的聊天服務(wù)
        IChatService chatService = aiService.getChatService(PlatformType.OLLAMA);
        // 創(chuàng)建請(qǐng)求參數(shù)
        ChatCompletion chatCompletion = ChatCompletion.builder()
               .model("deepseek-r1:7b")
               .message(ChatMessage.withUser(question))
               .build();
        System.out.println(chatCompletion);
        // 發(fā)送chat請(qǐng)求
        ChatCompletionResponse chatCompletionResponse = chatService.chatCompletion(chatCompletion);
        // 獲取聊天內(nèi)容和token消耗
        String content = chatCompletionResponse.getChoices().get(0).getMessage().getContent();
        long totalTokens = chatCompletionResponse.getUsage().getTotalTokens();
        System.out.println("總token消耗: " + totalTokens);
        return content;
    }

    @GetMapping(path = "/chat-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<String>> chatStream(@RequestParam String question) {
        Logger logger = LoggerFactory.getLogger(getClass());
        return Flux.create(emitter -> {
            try {
                logger.info("開(kāi)始進(jìn)行Chat對(duì)話: {}", question);
                // 獲取chat服務(wù)實(shí)例
                IChatService chatService = aiService.getChatService(PlatformType.OLLAMA);
                logger.info("成功創(chuàng)建服務(wù)實(shí)例");
                // 構(gòu)造請(qǐng)求參數(shù)
                ChatCompletion chatCompletion = ChatCompletion.builder()
                        .model("deepseek-r1:7b")
                        .messages(Arrays.asList(ChatMessage.withUser(question)))
                        .functions()
                        .build();
                logger.info("成功構(gòu)建流式請(qǐng)求體");
                // 構(gòu)造監(jiān)聽(tīng)器
                SseListener sseListener = new SseListener() {
                    @Override
                    protected void send() {
                        try {
                            // 將消息發(fā)送到前端
                            String data = this.getCurrStr();
                            if (data != null && !data.isEmpty()) {
                                emitter.next(ServerSentEvent.<String>builder()
                                        .data(data)
                                        .build());
                            }
                        } catch (Exception e) {
                            logger.error("SSE端點(diǎn)報(bào)錯(cuò)", e);
                            emitter.error(e);
                        }
                    }
                };
                // 顯示函數(shù)參數(shù),默認(rèn)不顯示
                sseListener.setShowToolArgs(true);
                // 發(fā)送SSE請(qǐng)求
                chatService.chatCompletionStream(chatCompletion, sseListener);
                logger.info("成功請(qǐng)求SSE端點(diǎn)");
            } catch (Exception e) {
                logger.error("流式輸出報(bào)錯(cuò)", e);
                emitter.error(e);
            }
        });
    }


}

流式的話,我們?cè)賹?xiě)個(gè)前端來(lái)看看測(cè)試效果。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chat Stream Frontend</title>
</head>

<body>
<input type="text" id="questionInput" placeholder="請(qǐng)輸入問(wèn)題">
<button id="sendButton">發(fā)送</button>
<div id="responseContainer"></div>

<script>
    const questionInput = document.getElementById('questionInput');
    const sendButton = document.getElementById('sendButton');
    const responseContainer = document.getElementById('responseContainer');

    sendButton.addEventListener('click', () => {
        const question = questionInput.value;
        if (question.trim() === '') {
            alert('請(qǐng)輸入問(wèn)題');
            return;
        }

        // 創(chuàng)建 EventSource 實(shí)例,連接到后端的 SSE 接口
        const eventSource = new EventSource(`http://localhost:8080/chat-stream?question=${encodeURIComponent(question)}`);

        // 監(jiān)聽(tīng) message 事件,當(dāng)接收到服務(wù)器發(fā)送的消息時(shí)觸發(fā)
        eventSource.onmessage = (event) => {
            const data = event.data;
            // 將接收到的數(shù)據(jù)追加到響應(yīng)容器中
            responseContainer.textContent += data;
        };

        // 監(jiān)聽(tīng) error 事件,當(dāng)連接出現(xiàn)錯(cuò)誤時(shí)觸發(fā)
        eventSource.onerror = (error) => {
            console.error('EventSource failed:', error);
            // 關(guān)閉連接
            eventSource.close();
        };
    });
</script>
</body>

</html>

運(yùn)行服務(wù),打開(kāi)html,在輸入框輸入一個(gè)問(wèn)題,點(diǎn)擊按鈕發(fā)送,在F12的接口請(qǐng)求里,你會(huì)在Response里看到服務(wù)不斷的推送文字給你。

圖片圖片

責(zé)任編輯:武曉燕 來(lái)源: Java面試教程
相關(guān)推薦

2025-02-19 08:00:00

2022-05-09 07:49:47

PulsarJava問(wèn)題排查

2024-01-09 07:29:05

Argo代碼庫(kù)應(yīng)用程序

2024-06-14 08:36:57

2025-02-19 08:33:18

2022-12-12 08:17:29

2023-09-04 07:54:06

2024-04-07 00:00:00

ESlint命令變量

2024-05-28 09:12:10

2025-03-05 10:21:04

DeepSeekLVLM

2023-12-12 08:41:01

2023-12-20 08:23:53

NIO組件非阻塞

2024-04-30 09:02:48

2023-04-26 10:21:04

2022-09-26 07:32:24

開(kāi)發(fā)接口編程

2021-04-20 23:16:06

SparkSQL語(yǔ)法

2021-10-14 06:52:47

算法校驗(yàn)碼結(jié)構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)