响应流式传输
LLM 是逐个 token 生成文本的,因此许多 LLM 提供商提供了 流式传输响应 的方式,即逐个 token 地返回结果,而不是等待整个文本生成完成。
这样可以显著改善用户体验,因为用户不需要等待一个未知时长,几乎可以立即开始阅读响应。
对于 ChatModel
和 LanguageModel
接口,分别有对应的StreamingChatModel
和 StreamingLanguageModel
接口。
它们提供了类似的 API,但可以流式传输响应。
这些接口接收一个 StreamingChatResponseHandler
接口的实现作为参数。
public interface StreamingChatResponseHandler {
void onPartialResponse(String partialResponse);
default void onPartialThinking(PartialThinking partialThinking) {}
default void onPartialToolCall(PartialToolCall partialToolCall) {}
default void onCompleteToolCall(CompleteToolCall completeToolCall) {}
void onCompleteResponse(ChatResponse completeResponse);
void onError(Throwable error);
}
通过实现 StreamingChatResponseHandler
,你可以为以下事件定义处理逻辑:
- 当生成下一个部分文本响应时:调用
onPartialResponse(String)
。
根据 LLM 提供商的不同,部分响应可能包含一个或多个 token。
例如,你可以在 token 可用时立即将其发送到 UI。 - 当生成下一个部分思考/推理文本时:调用
onPartialThinking(PartialThinking)
。
根据 LLM 提供商的不同,部分思考文本可能包含一个或多个 token。 - 当生成下一个 部分工具调用 时:调用
onPartialToolCall(PartialToolCall)
。 - 当 LLM 完成一个工具调用的流式传输时:调用
onCompleteToolCall(CompleteToolCall)
。 - 当 LLM 完成整个响应生成时:调用
onCompleteResponse(ChatResponse)
。ChatResponse
对象包含完整响应(AiMessage
)以及ChatResponseMetadata
。 - 当发生错误时:调用
onError(Throwable error)
。
下面是一个使用 StreamingChatModel
实现流式传输的示例:
StreamingChatModel model = OpenAiStreamingChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(GPT_4_O_MINI)
.build();
String userMessage = "Tell me a joke";
model.chat(userMessage, new StreamingChatResponseHandler() {
@Override
public void onPartialResponse(String partialResponse) {
System.out.println("onPartialResponse: " + partialResponse);
}
@Override
public void onPartialThinking(PartialThinking partialThinking) {
System.out.println("onPartialThinking: " + partialThinking);
}
@Override
public void onPartialToolCall(PartialToolCall partialToolCall) {
System.out.println("onPartialToolCall: " + partialToolCall);
}
@Override
public void onCompleteToolCall(CompleteToolCall completeToolCall) {
System.out.println("onCompleteToolCall: " + completeToolCall);
}
@Override
public void onCompleteResponse(ChatResponse completeResponse) {
System.out.println("onCompleteResponse: " + completeResponse);
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
}
});
一种更简洁的流式传输方式是使用 LambdaStreamingResponseHandler
类。
该工具类提供了静态方法,可以通过 lambda 表达式 来创建 StreamingChatResponseHandler
。
使用 lambda 来流式处理响应非常简单,只需要调用 onPartialResponse()
静态方法,
并传入定义如何处理部分响应的 lambda 表达式:
import static dev.langchain4j.model.LambdaStreamingResponseHandler.onPartialResponse;
model.chat("Tell me a joke", onPartialResponse(System.out::print));
onPartialResponseAndError()
方法允许你同时定义onPartialResponse()
和 onError()
的处理逻辑:
import static dev.langchain4j.model.LambdaStreamingResponseHandler.onPartialResponseAndError;
model.chat("Tell me a joke", onPartialResponseAndError(System.out::print, Throwable::printStackTrace));