websocket请求通过IteratorAggregate实现流式输出

对接国内讯飞星火模型,官方文档接口采用的是websocket跟国外chatgpt有些差异。

虽然官网给出一个简单demo通过while(true),websocket的receive()可以实现逐条接受并输出给前端,但是通用和灵活度不高。不能兼容现有项目框架的流式输出。故模仿openai,采用IteratorAggregate接口实现迭代器可遍历获取响应结果。

IteratorAggregate只有一个需要实现的方法getIterator()实现起来简单方便,基本代码如下

php 复制代码
<?php
declare(strict_types=1);

namespace App\Extends;

use WebSocket\Client;
use IteratorAggregate;
use Generator;

class XingHuoClient
{
    protected $client;

    public function client(){
        $apikey = '';//自己填写真实内容
        $apiSecret = '';//自己填写真实内容
        $addr = '';//自己填写真实内容
        $authUrl = $this->assembleAuthUrl("GET",$addr,$apikey,$apiSecret);
        //创建ws连接对象
        $this->client = new Client($authUrl);
        return $this;
    }

    public function send($uid, array $message)
    {
        if($this->client){
            $data = $this->getBody($uid, $message);
            $this->client->send($data);
            $response = new XingResponseIterator($this->client);
            return $response;
        }else{
            throw new \Exception('星火客户端异常');
        }
    }

    //构造参数体
    protected function getBody($uid, $message){
        //...省略内容
        return $json_string;
    }

    //鉴权方法
    public function assembleAuthUrl($method, $addr, $apiKey, $apiSecret) {
        //...省略内容
        return $authAddr;
    }
}

class XingResponseIterator implements IteratorAggregate {

    protected $client;

    public function __construct($client) {
        $this->client = $client;
    }

    public function getIterator(): Generator {
        if($this->client){
            while(true){
                $response = $this->client->receive();
                $resp = json_decode($response,true);
                $code = $resp["header"]["code"];
                if(0 == $code){
                    $status = $resp["header"]["status"];
                    if($status != 2){
                        yield $resp['payload'];
                    }else{
                        yield $resp['payload'];
                        break;
                    }
                }else{
                    //TODO:记录错误日志或报警

                    break;
                }
            }
        }else{
            return [];
        }
    }
}

前提引入composer require textalk/websocket包用于socket请求星火接口,大部分内容还是官网提供的demo,主要是增加了XingResponseIterator 。

php 复制代码
$stream = xinghuo()->client()->send($uid, $messages);//xinghuo()是封装的XingHuoClient对象
foreach($stream as $response){
    //处理数据,格式化数据,统计,记录等操作,输出内容到响应流,此处不做细讲
}

输出形式可以分流式输出,以openai为例参考:

https://github.com/orhanerday/open-ai

https://packagist.org/packages/hhxsv5/php-sse

前端浏览器使用的是EventSource对象。

可以使用chunk形式,存在客户端不支持eventSource对象的情况可以选择使用,参考我的另一篇文章

https://blog.csdn.net/jinborui2/article/details/132325824

以及一些nginx配置和php配置也在这篇文章里有所讲解,保证服务端及时输出内容到客户端。

相关推荐
七夜zippoe13 天前
DolphinDB WebSocket接入:实时数据流
网络·websocket·网络协议·dolphindb·实时数据流
于先生吖13 天前
从零搭建Java萌宠社交系统:WebSocket实时聊天+动态发布模块实现
java·开发语言·websocket
Zhan86112414 天前
WebSocket心跳与断线重连实战:芬兰赫尔辛基指数行情数据接口接入记录
网络·websocket·网络协议
colofullove14 天前
实时游玩页与 WebSocket 状态管理实现
websocket·网络协议·状态模式
小短腿的代码世界14 天前
WebSocket协议在Qt中的工业级实现:5层架构设计与万级并发压测验证
qt·websocket·网络协议
葡萄皮sandy15 天前
SSE和WebSocket
网络·websocket·网络协议
hrw_embedded15 天前
国外新能源充电平台调试OCPP调试平台SteVe和Monta其实是互补的-websoket连接部分。
websocket·ocpp·新能源充电平台·steve·monta
JouYY15 天前
如何实现基于 WebSocket Agent 的断线重连与状态恢复
websocket·llm·agent
BlockWay16 天前
WEEX WebSocket 与 API 生态,正在解决什么问题?
网络·websocket·网络协议
俊俊谢16 天前
【python】FastAPI 实时推送:从 SSE 到 WebSocket
python·websocket·fastapi