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

2023-09-18 14:33:56

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

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

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

<?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 。

$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配置也在这篇文章里有所讲解,保证服务端及时输出内容到客户端。

更多推荐

利用Pycharm将python程序打包为exe文件(亲测可用)

最近做了一个关于py的小项目,对利用Pycharm将python文件打包为exe文件不是很熟悉,故学习记录之。目录一、下载pyinstaller库二、打开Pycharm进行打包(不更改图标)三、打开Pycharm进行打包(更改图标)一、下载pyinstaller库1.点击win+r,输入cmd打开控制管理器2.输入pi

[maven] scopes & 管理 & profile & 测试覆盖率

[maven]scopes&管理&profile&测试覆盖率这里将一些其他的特性和测试覆盖率(主要是jacoco)scopesmaven的scope主要就是用来限制和管理依赖的传递性,简单的说就是,每一个scope都有其对应的特性,并且会决定依赖包在打包和运行时是否会被使用这里主要谈论的差别是compileclassp

Secrets of RLHF in Large Language Models Part I: PPO

本文是LLM系列文章,针对《SecretsofRLHFinLargeLanguageModelsPartI:PPO》的翻译。大型语言模型中RLHF的秘密(上):PPO摘要1引言2相关工作3人类反馈的强化学习4有益和无害的奖励模型5PPO的探索6评估和讨论局限性摘要大型语言模型(LLM)为通用人工智能的发展制定了蓝图。它

DC/DC开关电源学习笔记(七)低压大电流DC/DC变换技术

低压大电流DC/DC变换技术1.无暂态要求的低压大电流DC/DC变换技术2.负载极其快速变化的低压大电流DC/DC变换技术2.1非隔离型VRM2.2隔离型VRM低压大电流高功率DC/DC变换技术,已从前些年的3.3V降至现在的1.0V左右,电流目前已可达到几十安至几百安。同时,电源的输出指标,如纹波、精度、效率、过冲、

sql 脚本 WITH 作用

WITH是SQL中的一个关键字,用于创建临时表达式,也称为公共表表达式(CommonTableExpression,CTE)。它可以在查询中定义一个临时的命名结果集,并可以在后续的查询中引用该结果集。WITH的主要作用有两个:提高可读性:通过使用WITH关键字,可以将复杂的查询逻辑分解为多个简单的部分,并使用有意义的名

Sqilte3初步教程

文章目录安装创建数据库创建和删除表插入行数据安装Windows下安装,首先到下载页面,下载Windows安装软件,一般是sqlite-dll-win32-*.zipsqlite-tools-win32-*.zip下载之后将其内容解压到同一个文件夹下,我把它们都放在了D:\CS\sqlite目录下,然后将这个目录添加到环

【Springboot】Springboot如何优雅停机?K8S中Pod如何优雅停机?

什么是优雅停机:就是对应用进程发送停止指令之后,执行的一系列保证应用正常关闭的操作。这些操作往往包括等待已有请求执行完成、关闭线程、关闭连接和释放资源等就是对应用进程发送停止指令之后,能保证正在执行的业务操作不受影响,可以继续完成已有请求的处理,但是停止接受新请求本质上是JVM即将关闭前执行的一些额外的处理代码可以避免

安卓核心板开发板的操作系统版本有哪些?

安卓核心板也就是安卓主板平台,一般是指芯片主板硬件平台以及系统开发平台的总称。采用ARM应用处理器平台运行google的android智能化操作系统,是将核心功能封装的一块电子主板,集成芯片、存储器和功放器件等,并提供标准接口的芯片。新移科技专注于安卓核心板定制开发,联发科紫光展锐高通安卓核心板四核/八核方案定制。4G

ubuntu:在ubuntu系统上使用apache2服务器部署多个vue项目

在Ubuntu系统上使用Apache2服务器部署多个Vue.js项目,你可以按照以下步骤进行操作:1.安装Apache2如果你的系统上还没有安装Apache2,可以使用以下命令安装:sudoaptupdatesudoaptinstallapache22.配置虚拟主机要部署多个Vue.js项目,最好为每个项目配置一个单独

算法通关村-----回溯模板如何解决排列组合问题

组合总和问题描述给你一个无重复元素的整数数组candidates和一个目标整数target,找出candidates中可以使数字和为目标数target的所有不同组合,并以列表形式返回。你可以按任意顺序返回这些组合。candidates中的同一个数字可以无限制重复被选取。如果至少一个数字的被选数量不同,则两种组合是不同的

论文阅读:AugGAN: Cross Domain Adaptation with GAN-based Data Augmentation

Abstract基于GAN的图像转换方法存在两个缺陷:保留图像目标和保持图像转换前后的一致性,这导致不能用它生成大量不同域的训练数据。论文提出了一种结构感知(Structure-aware)的图像转换网络(image-to-imagetranslationnetwork)。ProposedFramework为了将图像正

热文推荐