V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
nonfu
V2EX  ›  程序员

基于 PHP +EventSource 实现了 ChatGPT 的 Stream 响应,源码分享给大家

  •  
  •   nonfu · 2023-03-17 12:21:55 +08:00 · 2880 次点击
    这是一个创建于 618 天前的主题,其中的信息可能已经有所发展或是发生改变。

    虽迟但到,这周给我的小玩具 GeekChat 新增了对 stream 响应的支持,实现边回复边输出,感兴趣可以体验下:GeekChat —— 支持语音的免费体验版 ChatGPT。前端交互还有待优化,放到下个迭代吧。

    由于 GeekChat 是用 Laravel + Vue3 实现的,所以也必须依赖这套技术栈实现 stream 流式响应,对应的实现源码已经提交到 Github:https://github.com/geekr-dev/geekchat,如果觉得对你有帮助,顺手点个 star 。

    用到的东西:

    注意点:

    由于用到了 headerob_flushflush 这些函数,所以不支持基于 Swoole 、RoadRunner 之类常驻内存机制驱动的 PHP HTTP 服务器,在部署到生产环境的时候需要注意这一点。

    15 条回复    2024-04-13 15:21:16 +08:00
    PickleFish
        1
    PickleFish  
       2023-03-17 12:33:07 +08:00
    不懂 但已 star
    sunny1688
        2
    sunny1688  
       2023-03-17 13:39:08 +08:00
    那你这个 server 还能并发?
    brader
        3
    brader  
       2023-03-17 15:43:25 +08:00
    我建议你关闭缓冲区或者调整缓冲区的大小,它会让你 UI 表现看起来是逐字出现而不是一段一段的出现,表现更加丝滑,体验会更加友好。
    缓冲区可能存在于列举任何一个地方:代码、中间代理服务、nginx 等等
    nonfu
        4
    nonfu  
    OP
       2023-03-17 16:35:49 +08:00
    @sunny1688 并发肯定能做的啊 调用的 API 肯定支持并发 不要超过它的频率限制就好了
    nonfu
        5
    nonfu  
    OP
       2023-03-17 16:36:09 +08:00
    @brader 好的 感谢反馈
    shellus
        6
    shellus  
       2023-03-17 17:41:32 +08:00
    @brader 这个逐字出现的效果在前端实现比较好吧,为了这个效果去调整传输层的缓冲区,好没有必要的感觉
    shellus
        7
    shellus  
       2023-03-17 17:43:35 +08:00
    请教一下,这个 EventSource 和 websocket 相比好像没什么优势吧,后端的支持的话,也是 swoole 的 websocket 更好简单实用,技术栈比较主流吧?
    brader
        8
    brader  
       2023-03-17 18:06:03 +08:00
    @shellus 客户端是无法实现的我说的效果的,因为流形式 gpt 回答问题是持续性逐字回答。
    因为开启了缓冲区,假设一段话被分为了 A 、B 、C 三块进行输出,那么客户端接收数据流程如下:

    客户端等待 -> 客户端接收 A 块消息(这里按你说的,客户端自实现逐字输出) -> 等待 -> 接收 B 块消息 -> 等待 -> 接收 c 块消息

    你会发现上面的流程,虽然你接收到一整块的大量文字的时候,自己做了逐字输出,但因为服务端必须等待接收满一个缓冲区的数据,才会向客户端发送数据,所以客户端在每一块数据之间,又进入了等待期,失去了连续性。
    shellus
        9
    shellus  
       2023-03-17 18:46:47 +08:00
    @brader 有道理
    Acckr
        10
    Acckr  
       2023-03-20 10:38:32 +08:00
    速度好慢,另外总是出现 接收回复出错,请重试
    nonfu
        11
    nonfu  
    OP
       2023-03-21 02:07:03 +08:00
    @Acckr 访问频率太高+key 消耗完了
    ieliwb
        12
    ieliwb  
       2023-03-23 11:24:46 +08:00
    大佬好,php-fpm 有连接限制的,你这开启流模式,会导致一直占有 fpm 进程,后面的用户因为连接数限制完全挤不进来啊,服务器不挂了
    nonfu
        13
    nonfu  
    OP
       2023-03-23 21:01:08 +08:00
    @ieliwb 一条消息处理完就关闭了 这不比 websocket 那种一直监听
    voidmnwzp
        14
    voidmnwzp  
       2023-03-28 18:14:33 +08:00 via iPhone
    我用 evensource 会丢掉数据中的空格符 不知道啥原因
    alanhe421
        15
    alanhe421  
       225 天前
    @shellus websocket 是全双工,EventSource 是单工,开销自然是 EventSource 小一些。具体肯定是看场景。

    AI 聊天是发送消息,之后服务端持续输出,WebSocket 多少是浪费点。

    不过 ChatGPT 目前用的是 fetch ,而非 eventsource ,毕竟 eventsource 没办法发请求体,只靠 URL 或者再加个请求做,多少不方便点。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1647 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 16:37 · PVG 00:37 · LAX 08:37 · JFK 11:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.