已解决php库Guzzle读取EventStream数据乱序问题

当使用 php 库 guzzle 在读取大模型的 stream 数据时,总是发生读取 n 个字节有可能同时读出 n 条 EventSource 消息的问题导致数据看起来是乱序的。

下面是核心方法,该方法是使用百度千帆 AppBuilder 的 OpenAPI 时遇到 stream 流式对话问题的一种解决方案

$answer = $buffer = '';
while (!$body->eof()) {
    // 读取 128byte 数据
    $buffer .= $body->read(128);
    
    // 这里使用 while 是因为读取 n 个字节有可能同时读出 n 条 EventSource 消息
    while (($pos = strpos($buffer, "\n\n")) !== false) {
        $eventMsg = substr($buffer, 0, $pos); // 一条 event 消息
        // echo Utils::formatMsg("event: {$eventMsg}");
        
        $buffer = substr($buffer, $pos + 2); // 剩余部分
        
        // 解析事件消息
        if (empty($eventMsg)) continue;
        $jsonString = str_replace('data: ', '', $eventMsg);
        $data = json_decode($jsonString, true);
        if (json_last_error() == JSON_ERROR_NONE) {
            if (empty($data['answer'])) continue;
            $content = $data['answer'];
            $answer .= $content;
            if (is_callable($callback)) $callback($content);
        } else {
            // 记录错误信息
            // echo Utils::formatMsg("error: {$eventMsg}");
            if (is_callable($callbackErr)) $callbackErr($eventMsg); // 带有 data: 开头的原始数据
        }
    }
}

return $answer;

以上大模型流式对话就算搞定了,参考文章:记一次chatgpt接入_guzzle接收stream event-CSDN博客

Author: thinkwei

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注