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