对接国内讯飞星火模型,官方文档接口采用的是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配置也在这篇文章里有所讲解,保证服务端及时输出内容到客户端。