跳到内容

步骤 03 - 流式响应

LLM 的响应可能很长。想象一下让模型生成一个故事。它可能产生数百行文本。

在当前应用程序中,整个响应会在发送到客户端之前被累积。在生成过程中,客户端正在等待响应,服务器正在等待模型完成响应的生成。当然,有一个“…”气泡表明正在进行一些操作,但这并不是最佳的用户体验。

流式传输允许我们在模型生成响应时,将响应分块发送。模型以块(token)的形式发送响应,服务器在接收到这些块时将它们发送给客户端。

此步骤的最终代码位于 step-03 目录中。但是,我们建议您按照以下说明进行操作,并继续扩展您当前的应用程序。

要求 LLM 返回块

第一步是要求 LLM 分块返回响应。最初,我们的 AI 服务是这样的

CustomerSupportAgent.java
package dev.langchain4j.quarkus.workshop;

import io.quarkiverse.langchain4j.RegisterAiService;
import jakarta.enterprise.context.SessionScoped;

@SessionScoped
@RegisterAiService
public interface CustomerSupportAgent {

    String chat(String userMessage);
}

请注意,chat 方法的返回类型是 String我们将将其更改为 Multi<String>,以表明响应将被流式传输而不是同步返回。

CustomerSupportAgent.java
package dev.langchain4j.quarkus.workshop;

import io.quarkiverse.langchain4j.RegisterAiService;
import io.smallrye.mutiny.Multi;
import jakarta.enterprise.context.SessionScoped;

@SessionScoped
@RegisterAiService
public interface CustomerSupportAgent {

    Multi<String> chat(String userMessage);
}

Multi<String> 是字符串流。Multi 是来自 Mutiny 库的类型,它代表一个项目流,可能是无限的。在这种情况下,它将是一个代表 LLM 响应的字符串流,并且它是有限的(幸运的是)。Multi 还有其他特性,例如处理背压的能力,我们将在本次研讨会中不涵盖。

从 WebSocket 提供流

好的,现在我们的 AI 服务返回了一个字符串流。但是,我们需要修改我们的 WebSocket 端点来处理这个流并将其发送给客户端。

目前,我们的 WebSocket 端点是这样的

CustomerSupportAgentWebSocket.java
package dev.langchain4j.quarkus.workshop;

import io.quarkus.websockets.next.OnOpen;
import io.quarkus.websockets.next.OnTextMessage;
import io.quarkus.websockets.next.WebSocket;

@WebSocket(path = "/customer-support-agent")
public class CustomerSupportAgentWebSocket {

    private final CustomerSupportAgent customerSupportAgent;

    public CustomerSupportAgentWebSocket(CustomerSupportAgent customerSupportAgent) {
        this.customerSupportAgent = customerSupportAgent;
    }

    @OnOpen
    public String onOpen() {
        return "Welcome to Miles of Smiles! How can I help you today?";
    }

    @OnTextMessage
    public String onTextMessage(String message) {
        return customerSupportAgent.chat(message);
    }
}

让我们修改 onTextMessage 方法,以便在响应到达时将其发送给客户端。

CustomerSupportAgentWebSocket.java
package dev.langchain4j.quarkus.workshop;

import io.quarkus.websockets.next.OnOpen;
import io.quarkus.websockets.next.OnTextMessage;
import io.quarkus.websockets.next.WebSocket;
import io.smallrye.mutiny.Multi;

@WebSocket(path = "/customer-support-agent")
public class CustomerSupportAgentWebSocket {

    private final CustomerSupportAgent customerSupportAgent;

    public CustomerSupportAgentWebSocket(CustomerSupportAgent customerSupportAgent) {
        this.customerSupportAgent = customerSupportAgent;
    }

    @OnOpen
    public String onOpen() {
        return "Welcome to Miles of Smiles! How can I help you today?";
    }

    @OnTextMessage
    public Multi<String> onTextMessage(String message) {
        return customerSupportAgent.chat(message);
    }
}

就是这样!现在响应将在到达时流式传输到客户端。这是因为 Quarkus 本地理解返回类型是 Multi,并且知道如何处理它。

测试流式传输

要测试流式传输,您可以使用与之前相同的聊天界面。应用程序应仍处于运行状态。返回浏览器,刷新页面,然后开始聊天。如果您问简单的问题,您可能不会注意到区别。

问一些诸如此类的问题

Tell me a story containing 500 words

您将看到响应在到达时被显示出来。

现在让我们切换到 下一步