大模型對話同步 - 流式返回(spring - ollama - java8)

快一年沒寫 spring 了,手癢了,今天寫了兩個接口, 舒服了

  1. 大模型對話同步返回接口

  2. 大模型對話流式返回接口

...

第一步找一個 springboot 模版:https://start.aliyun.com/

這裏我選的 java8 支持的,代碼結構非常清爽。

  1. starter(依賴 service 和 controller)

  2. service

  3. controller(依賴 service)

第二步編寫 controller 接口:引入 web 依賴,引入 service 依賴

@RestController
@ResponseBody
public class OllamaController {

    @Autowired
    private OllamaService ollamaService;

    @GetMapping("/hello")
    public String sayHello() {
        return"Hello, World!";
    }

    @GetMapping("/chat")
    public String getChatMessage(@RequestParam String question){
        String chatMessage = ollamaService.getChatMessage(question);
        return chatMessage;
    }

    @GetMapping(value = "/steamChat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> steamChat(@RequestParam String msg) {
        return ollamaService.steamChat(msg);
    }
}

這裏流式接口使用 Flux 響應編程,底層基於 sse 響應編程

ps:我記得 2 年前實習的時候,我是基於 websocket 實現的流失輸出

第三步是 service 接口:引入 ai4j 和 webflux 依賴,增加配置文件,實現接口

引入依賴如下:

<dependency>
  <groupId>io.github.lnyo-cly</groupId>
  <artifactId>ai4j-spring-boot-stater</artifactId>
  <version>0.6.2</version>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

增加配置文件如下:

spring:
  application:
    name:spring-ai-05-ollama
ai:
  ollama:
    api-host: http://localhost:11434
    model: qwen2:0.5b

實現接口如下:

@Service
public class OllamaServiceImpl implements OllamaService{

    // 注入Ai服務
    @Autowired
    private AiService aiService;
    @Override
    public String getChatMessage(String question) {
        // 獲取OLLAMA的聊天服務
        IChatService chatService = aiService.getChatService(PlatformType.OLLAMA);

        // 創建請求參數
        ChatCompletion chatCompletion = ChatCompletion.builder()
                .model("qwen2:0.5b")
                .message(ChatMessage.withUser(question))
                .build();

        System.out.println(chatCompletion);

        // 發送chat請求
        ChatCompletionResponse chatCompletionResponse = null;
        try {
            chatCompletionResponse = chatService.chatCompletion(chatCompletion);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        // 獲取聊天內容和token消耗
        String content = chatCompletionResponse.getChoices().get(0).getMessage().getContent();
        long totalTokens = chatCompletionResponse.getUsage().getTotalTokens();
        System.out.println("總token消耗: " + totalTokens);

        return content;
    }

    @Override
    public Flux<String> steamChat(String msg) {
        return Flux.create(sink -> {
            // 獲取chat服務實例
            IChatService chatService = aiService.getChatService(PlatformType.OLLAMA);

            // 構造請求參數
            ChatCompletion chatCompletion = ChatCompletion.builder()
                    .model("qwen2:0.5b")
                    .message(ChatMessage.withUser(msg))
                    .build();

            // 自定義監聽器,用於將數據推送到 Flux Sink 中
            SseListener sseListener = new SseListener() {
                @Override
                protected void send() {
                    String currentData = this.getCurrStr();
                    sink.next(currentData);  // 發射當前片段
                }
            };
            sseListener.setShowToolArgs(true);

            // 發送SSE請求
            try {
                chatService.chatCompletionStream(chatCompletion, sseListener);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            System.out.println(sseListener.getOutput());
        });
    }
}

...

最後來看看效果吧

  1. 大模型對話同步返回接口

  1. 大模型對話流式返回接口

如果有興趣,可以看看具體代碼 https://github.com/meehom/springAI-demo

好好工作,升級加薪!

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/WlFVN5ZOh1RqVVQZ50UE9g