背景
最近再折腾GPT的时候, 遇到流式的响应,总是感觉有点怪怪的,但是又很好,解析了一下,发现竟然是标准化更广的一种协议。
Server-Sent Events
data: {"id":"id-1720428652482","object":"chat.completion.chunk","created":1720428652,"model":"gemma-7b-it","choices":[{"delta":{"content":"。"}}]}
data: [DONE]
openai 返回的流式数据特征非常清晰。
每一行都是 data:
开头,后面是 json 数据,最后一行是 data: [DONE]
表示结束。content type 是 text/event-stream
。
这个标准就很HTTP,简单高效,实际上,每行的文本也能自定义。如下代码。
spring webflux
@GetMapping(path = "/stream-flux", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamFlux() {
return Flux.interval(Duration.ofSeconds(1))
.map(sequence -> "Flux - " + LocalTime.now().toString());
}
NDJSON
但是实际上我最早期接触的是 NDJSON, 也就是 Newline Delimited JSON, 也就是每一行都是一个 json 对象,如下代码。
NDJSON 更在乎的是结构化的 json 本体,所以其他内容都不会有。但是该规范要晚一点,2013年才有了1.0版。
虽然暂时还是没有看到大型项目中使用过,但是未来可期。两种规范我都是比较支持的。未来的科技领域上 stream 响应一定会越来越多。
spring webflux
@GetMapping(value = "interval", produces = MediaType.APPLICATION_NDJSON_VALUE)
public Flux<TimeModel> interval() {
DateFormatter dateFormatter = new DateFormatter();
return Flux.interval(Duration.ofSeconds(1))
.map(i -> Instant.now())
.map(ins -> new TimeModel(ins.toEpochMilli(), dateFormatter.print(Date.from(ins), Locale.CHINA)))
.log();
}