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


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

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

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

    1. declare(strict_types=1);
    2. namespace App\Extends;
    3. use WebSocket\Client;
    4. use IteratorAggregate;
    5. use Generator;
    6. class XingHuoClient
    7. {
    8. protected $client;
    9. public function client(){
    10. $apikey = '';//自己填写真实内容
    11. $apiSecret = '';//自己填写真实内容
    12. $addr = '';//自己填写真实内容
    13. $authUrl = $this->assembleAuthUrl("GET",$addr,$apikey,$apiSecret);
    14. //创建ws连接对象
    15. $this->client = new Client($authUrl);
    16. return $this;
    17. }
    18. public function send($uid, array $message)
    19. {
    20. if($this->client){
    21. $data = $this->getBody($uid, $message);
    22. $this->client->send($data);
    23. $response = new XingResponseIterator($this->client);
    24. return $response;
    25. }else{
    26. throw new \Exception('星火客户端异常');
    27. }
    28. }
    29. //构造参数体
    30. protected function getBody($uid, $message){
    31. //...省略内容
    32. return $json_string;
    33. }
    34. //鉴权方法
    35. public function assembleAuthUrl($method, $addr, $apiKey, $apiSecret) {
    36. //...省略内容
    37. return $authAddr;
    38. }
    39. }
    40. class XingResponseIterator implements IteratorAggregate {
    41. protected $client;
    42. public function __construct($client) {
    43. $this->client = $client;
    44. }
    45. public function getIterator(): Generator {
    46. if($this->client){
    47. while(true){
    48. $response = $this->client->receive();
    49. $resp = json_decode($response,true);
    50. $code = $resp["header"]["code"];
    51. if(0 == $code){
    52. $status = $resp["header"]["status"];
    53. if($status != 2){
    54. yield $resp['payload'];
    55. }else{
    56. yield $resp['payload'];
    57. break;
    58. }
    59. }else{
    60. //TODO:记录错误日志或报警
    61. break;
    62. }
    63. }
    64. }else{
    65. return [];
    66. }
    67. }
    68. }

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

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

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

  • 相关阅读:
    SpringCloud LoadBalancer 新一代负载均衡器
    盘点3种Python网络爬虫过程中的中文乱码的处理方法
    Android 小组件 AppWidgetProvider
    基于java班费收支管理系统计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署
    【2】c++11新特性(稳定性和兼容性)—>超长整型 long long
    R语言编程之分别为正负条形图着色
    Github 常用资源搜索技巧 & Git - Pycharm 项目推拉 - 基本使用
    基于人脸识别的课堂考勤系统 tkinter+openpyxl+face_recognition
    【ISO14229_UDS刷写】-1-$34诊断服务RequestDownload理论部分
    脚手架构建VUE项目
  • 原文地址:https://blog.csdn.net/jinborui2/article/details/132970863