本工程仿造OpneAI Chat Completion API(即GPT3.5 API)的实现,为ChatGLM-6B提供流式HTTP API。
本仓库提供了Flask和FastAPI下的示例服务和开箱即用的静态Web UI,无需Node.js、npm或webpack。
实际版本以ChatGLM-6B官方为准。但是这里需要提醒一下:
- 官方更新
stream_chat
方法后,已不能使用4.25.1的transformers包,故transformers==4.26.1。 - cpm_kernel需要本机安装CUDA(若torch中的CUDA使用集成方式,如各种一键安装包时,需要注意这点。)
- 为了获得更好的性能,建议使用CUDA11.6或11.7配合PyTorch 1.13和torchvision 0.14.1。
以下为本人开发环境的配置:
protobuf>=3.18,<3.20.1
transformers==4.26.1
torch==1.12.1+cu113
torchvision==0.13.1
icetk
cpm_kernels
非流式接口
-
接口URL:
http://{host_name}/chat
-
请求方式:POST(JSON body)
-
请求参数:
字段名 类型 说明 query string 用户问题 history array[string] 会话历史 -
返回结果:
字段名 类型 说明 query string 用户问题 response string 完整的回复 history array[string] 会话历史
流式接口,使用server-sent events技术。
-
接口URL:
http://{host_name}/stream
-
请求方式:POST(JSON body)
-
返回方式:
- 使用Event Stream格式,返回服务端事件流,
- 事件名称:
delta
- 数据类型:JSON
-
返回结果:
字段名 类型 说明 delta string 产生的字符 query string 用户问题,为省流,finished为 true
时返回response string 目前为止的回复,finished为 true
时,为完整的回复history array[string] 会话历史,为省流,finished为 true
时返回finished boolean true
表示结束,false
表示仍然有数据流。
清理显存接口
- 接口URL:
http://{host_name}/clear
- 请求方式:GET
Flask下实现server-sent events,本可以使用Flask-SSE
,但是由于该包依赖Redis,而这一场景下并无必要,因此参考了这篇文档,仅用最简单的方式实现了server-sent events。
Flask
Flask-Cors
gevent
python3 -u chatglm_service_flask.py --host 127.0.0.1 --port 8800 --quantize 8 --device 0
参数中,--device 为 -1 表示 cpu,其他数字i
表示第i
张卡。
FastAPI可以使用sse-starlette
创建和发送server-sent events。
注意,sse-starlette 输出的事件流可能带有多余的符号,前端处理时需要注意。
fastApi
sse-starlette
unicorn
python3 -u chatglm_service_fastapi.py --host 127.0.0.1 --port 8800 --quantize 8 --device 0
本仓库提供了该流式API的调用演示页面,内网环境即开即用,无需Nodejs、npm或webpack。
基于本人有限的开发环境制约和贫乏的技术储备,HTML Demo使用bootstrap.js 3.x + Vue.js 2.x开发,使用marked.js+highlight.js渲染,具体版本可参看HTML中的CDN链接。
由于浏览器本身的EventSource实现不支持POST方法,设定请求头等能力,需要使用第三方实现替代。
若正经开发中使用NPM,可以用@microsoft/fetch-event-source实现;
但是本人条件所限,懒得编译TypeScript,于是采用了@rangermauve/fetch-event-source。不过该工程只有EventSource的最基本功能,所以又在此基础上做了魔改。
不过,使用该方式后,在Chrome的DevTools中,不能正确展现EventStream。
在static/js/chatglm.js
中修改第1行对应的端口:
var baseUrl = "http://localhost:8800/"
-
流式问答生成过程中可能会出现乱码
这主要是部分token并不是完整的字符造成的,因此接口最后返回了完整的生成结果。如果是非0平面的Unicode字符,可以通过编码判断处理;但还存在个别其它乱码现象,本人会进一步排查。
除上述引用的仓库外,还需要感谢以下项目:
ikechan8370/SimpleChatGLM6BAPI 参考了其中的参数逻辑