chatgpt-web-dev / chatgpt-web

A third-party ChatGPT Web UI page built with Express and Vue3, through the official OpenAI completion API. / 用 Express 和 Vue3 搭建的第三方 ChatGPT 前端页面, 基于 OpenAI 官方 completion API.
https://chatgpt-web.dev
MIT License
1.61k stars 441 forks source link

使用 `gpt-4o` 和 `gpt-4o-mini` 字符出现乱码 #563

Open Sun-ZhenXing opened 1 month ago

Sun-ZhenXing commented 1 month ago

特别是 gpt-4o-mini 出现乱码概率极高,每次对话都有很多乱码,官方验证没有问题,应该是流式传输将字符打断了。

注意到本项目使用了 @chatgptweb/chatgpt-api,这个项目目前不受支持,我们是否有办法切换到 openai 官方库,看了一下代码,依赖并非很复杂。如果后期有时间可参与重构。

Sun-ZhenXing commented 1 month ago

更新:这里有一个好消息,我已经使用官方库 openai 替换了 @chatgptweb/chatgpt-api 的实现,并且测试成功没有乱码。但我没有考虑 Socks 代理等细节,等代码完全更改完成后我会拉取请求。

可参考我的 Fork,目前可以直接替换使用。

xdl5566 commented 1 month ago

特别是gpt-4o-mini出现乱码的概率极高,每次对话都有很多乱码,官方验证没有问题,应该是流式传输将字符打断了。

注意到本项目使用了@chatgptweb/chatgpt-api,该项目目前不受支持,我们是否有办法切换到openai官方库,看一下代码依赖,并不是很复杂。如果后期有时间可参与重构。

有出现乱码吗?好像@chatgptweb/chatgpt-api库有更新,只是本项目开源大佬,没再维护此项目,可能另有原因吧~

Sun-ZhenXing commented 1 month ago

作者已经宣布 chatgpt@chatgptweb/chatgpt-api 都不再或不积极维护了,参见 #644。推荐是使用 openai 库直接替代,但实测 Claude 3.5 和国内一些模型不完全兼容 ChatGPT 接口,需要一些魔法操作。

BobDu commented 1 month ago

最初的 https://www.npmjs.com/package/chatgpt 很早之前原始作者就不维护了。 当时为了支持 vision 模型 然后我们就自己fork发布了 https://github.com/chatgpt-web-dev/chatgpt-api https://www.npmjs.com/package/@chatgptweb/chatgpt-api

之前是有考虑过换成 openai-sdk 但是确实就是上面说的。如果想支持claude3这些就反而不太方便了。

Sun-ZhenXing commented 1 month ago

原来是这样。现在的 openai 库还存在一些缺陷,但是基本上都是验证问题,通过一些 workaround 基本上可以弥补。如果更稳定一点还是修复一下 4o 的问题,不过还可以考虑维护两个分支,但感觉作者很难有精力了,这个项目维护也不如 Fork 的那个快。我觉得后面可以考虑维护一部分,或者 Fork 版本试试,用新技术给自己挖坑。

BobDu commented 1 month ago

如果能定位到 https://github.com/chatgpt-web-dev/chatgpt-api 中具体导致 4o 出现乱码bug的原因fix一下应该是最快修复这个问题的方案。

Sun-ZhenXing commented 1 month ago

我找到原因了,openai 没有假定流一定是可解码的的 openai/openai-node #L230,而是使用 Buffer 存储流直到找到 SSE chunk 结束符,而 @chatgptweb/chatgpt-api 使用了 eventsource-parser,而 feed() 方法似乎总是认为流的 chunk 是可解码的 rexxars/eventsource-parser #L45,所以 4o 实际上读取的流不是固定的以文本分段的方式发送的,如果尝试解码就会乱码。

实际上可以通过模仿 openai 的 SSE 解码方法自行构造一些工具函数,不能仅依赖于可解码的流解码方式 chatgpt-web-dev/chatgpt-api #L84,包括 stream-async-iterable.ts 的实现也没有考虑流中字符中断的情况。

image

gpt-4o-mini 的测试效果,实际返回内容:

{
    "role": "assistant",
    "content": "当然可以!这里有一个笑话:\n\n有一天,一只鸡走进了图书馆。它走到图书管理员那里,咯咯叫了几声,图书管理员给了它三本书。鸡拿着书走了出去。\n\n第二天,鸡又来了,还是咯咯叫,图书管理员又给了它三本书。鸡再次走了出去。\n\n第三天,鸡又来了,这次图书管理员好奇了,决定跟在鸡后面看看它到底要做什么。鸡走到池塘边,把书一本本地递给一只青蛙。青蛙看了每本书,只是说:“读过,读过,读过!”\n\n哈哈,希望这个笑话能让你笑一笑!",
    "usage": {
        "total_tokens": 312,
        "prompt_tokens": 77,
        "completion_tokens": 235
    }
}

image

BobDu commented 3 weeks ago

怎么去快速复现一下这个问题呢? 我日常使用中从从来没有遇到过乱码的问题 ...

Sun-ZhenXing commented 3 weeks ago

@BobDu 可能你的服务供应商已经规范过结果了,按照 SSE 严格分块发送,不是直接发不完整的 chunk。有一个方法就是代理转发流消息,设置一下 buffer 大小,4o-mini 这样的模型因为速度快就会出现多个流不是正常分段的。

前面说的官方库 openai 模型不兼容性我已经解决了,在我的魔改 Fork 里面,去除了原版 api 依赖库。这个 Fork 目前是自用的,后面再考虑原版 api 库的问题。

BobDu commented 3 weeks ago

明白了。那可能是因为我是直接接的openai的接口。没有用第三方代理商的转发。所以没遇到这个问题。