Merge branch 'main' into main
This commit is contained in:
commit
f1f7e4bbf8
15
FAQ.md
Normal file
15
FAQ.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
## Q1
|
||||||
|
|
||||||
|
**Mac直接加载量化后的模型出现提示 `clang: error: unsupported option '-fopenmp'**
|
||||||
|
|
||||||
|
这是由于Mac由于本身缺乏omp导致的,此时可运行但是单核。需要单独安装 openmp 依赖,即可在Mac下使用OMP:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 参考`https://mac.r-project.org/openmp/`
|
||||||
|
## 假设: gcc(clang)是14.x版本,其他版本见R-Project提供的表格
|
||||||
|
curl -O https://mac.r-project.org/openmp/openmp-14.0.6-darwin20-Release.tar.gz
|
||||||
|
sudo tar fvxz openmp-14.0.6-darwin20-Release.tar.gz -C /
|
||||||
|
```
|
||||||
|
此时会安装下面几个文件:`/usr/local/lib/libomp.dylib`, `/usr/local/include/ompt.h`, `/usr/local/include/omp.h`, `/usr/local/include/omp-tools.h`。
|
||||||
|
|
||||||
|
> 注意:如果你之前运行`ChatGLM`项目失败过,最好清一下Huggingface的缓存,i.e. 默认下是 `rm -rf ${HOME}/.cache/huggingface/modules/transformers_modules/chatglm-6b-int4`。由于使用了`rm`命令,请明确知道自己在删除什么。
|
42
README.md
42
README.md
@ -123,17 +123,14 @@ Multi-Query Attention 同时也降低了生成过程中 KV Cache 的显存占用
|
|||||||
|
|
||||||
## 使用方式
|
## 使用方式
|
||||||
### 环境安装
|
### 环境安装
|
||||||
|
首先需要下载本仓库:
|
||||||
使用 pip 安装依赖:`pip install -r requirements.txt`,其中 `transformers` 库版本推荐为 `4.27.1`,`torch` 推荐使用 2.0 以上的版本,以获得最佳的推理性能。
|
|
||||||
|
|
||||||
|
|
||||||
我们提供了一个网页版 Demo 和一个命令行 Demo。使用时首先需要下载本仓库:
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git clone https://github.com/THUDM/ChatGLM2-6B
|
git clone https://github.com/THUDM/ChatGLM2-6B
|
||||||
cd ChatGLM2-6B
|
cd ChatGLM2-6B
|
||||||
```
|
```
|
||||||
|
|
||||||
|
然后使用 pip 安装依赖:`pip install -r requirements.txt`,其中 `transformers` 库版本推荐为 `4.30.2`,`torch` 推荐使用 2.0 以上的版本,以获得最佳的推理性能。
|
||||||
|
|
||||||
### 代码调用
|
### 代码调用
|
||||||
|
|
||||||
可以通过如下代码调用 ChatGLM2-6B 模型来生成对话:
|
可以通过如下代码调用 ChatGLM2-6B 模型来生成对话:
|
||||||
@ -183,7 +180,18 @@ python web_demo.py
|
|||||||
```
|
```
|
||||||
|
|
||||||
程序会运行一个 Web Server,并输出地址。在浏览器中打开输出的地址即可使用。
|
程序会运行一个 Web Server,并输出地址。在浏览器中打开输出的地址即可使用。
|
||||||
> 由于国内 Gradio 的网络访问较为缓慢,启用 `demo.queue().launch(share=True, inbrowser=True)` 时所有网络会经过 Gradio 服务器转发,导致打字机体验大幅下降,现在默认启动方式已经改为 `share=False`,如有需要公网访问的需求,可以重新修改为 `share=True` 启动。
|
> 默认使用了 `share=False` 启动,不会生成公网链接。如有需要公网访问的需求,可以修改为 `share=True` 启动。
|
||||||
|
>
|
||||||
|
|
||||||
|
感谢 [@AdamBear](https://github.com/AdamBear) 实现了基于 Streamlit 的网页版 Demo `web_demo2.py`。使用时首先需要额外安装以下依赖:
|
||||||
|
```shell
|
||||||
|
pip install streamlit streamlit-chat
|
||||||
|
```
|
||||||
|
然后通过以下命令运行:
|
||||||
|
```shell
|
||||||
|
streamlit run web_demo2.py
|
||||||
|
```
|
||||||
|
经测试,如果输入的 prompt 较长的话,使用基于 Streamlit 的网页版 Demo 会更流畅。
|
||||||
|
|
||||||
### 命令行 Demo
|
### 命令行 Demo
|
||||||
|
|
||||||
@ -232,7 +240,6 @@ model = AutoModel.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True).q
|
|||||||
|
|
||||||
如果你的内存不足,可以直接加载量化后的模型:
|
如果你的内存不足,可以直接加载量化后的模型:
|
||||||
```python
|
```python
|
||||||
# INT8 量化的模型将"THUDM/chatglm-6b-int4"改为"THUDM/chatglm-6b-int8"
|
|
||||||
model = AutoModel.from_pretrained("THUDM/chatglm2-6b-int4",trust_remote_code=True).cuda()
|
model = AutoModel.from_pretrained("THUDM/chatglm2-6b-int4",trust_remote_code=True).cuda()
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -244,14 +251,15 @@ model = AutoModel.from_pretrained("THUDM/chatglm2-6b-int4",trust_remote_code=Tru
|
|||||||
```python
|
```python
|
||||||
model = AutoModel.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True).float()
|
model = AutoModel.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True).float()
|
||||||
```
|
```
|
||||||
|
如果你的内存不足的话,也可以使用量化后的模型
|
||||||
<!--
|
```python
|
||||||
|
model = AutoModel.from_pretrained("THUDM/chatglm2-6b-int4",trust_remote_code=True).float()
|
||||||
如果遇到了报错 `Could not find module 'nvcuda.dll'` 或者 `RuntimeError: Unknown platform: darwin` (MacOS) ,请[从本地加载模型](README.md#从本地加载模型) -->
|
```
|
||||||
|
在 cpu 上运行量化后的模型需要安装 `gcc` 与 `openmp`。多数 Linux 发行版默认已安装。对于 Windows ,可在安装 [TDM-GCC](https://jmeubank.github.io/tdm-gcc/) 时勾选 `openmp`。 Windows 测试环境 `gcc` 版本为 `TDM-GCC 10.3.0`, Linux 为 `gcc 11.3.0`。在 MacOS 上请参考 [Q1](FAQ.md#q1)。
|
||||||
|
|
||||||
### Mac 部署
|
### Mac 部署
|
||||||
|
|
||||||
对于搭载了 Apple Silicon 或者 AMD GPU 的 Mac,可以使用 MPS 后端来在 GPU 上运行 ChatGLM2-6B。需要参考 Apple 的 [官方说明](https://developer.apple.com/metal/pytorch) 安装 PyTorch-Nightly(正确的版本号应该是2.1.0.dev2023xxxx,而不是 2.0.0)。
|
对于搭载了 Apple Silicon 或者 AMD GPU 的 Mac,可以使用 MPS 后端来在 GPU 上运行 ChatGLM2-6B。需要参考 Apple 的 [官方说明](https://developer.apple.com/metal/pytorch) 安装 PyTorch-Nightly(正确的版本号应该是2.x.x.dev2023xxxx,而不是 2.x.x)。
|
||||||
|
|
||||||
目前在 MacOS 上只支持[从本地加载模型](README.md#从本地加载模型)。将代码中的模型加载改为从本地加载,并使用 mps 后端:
|
目前在 MacOS 上只支持[从本地加载模型](README.md#从本地加载模型)。将代码中的模型加载改为从本地加载,并使用 mps 后端:
|
||||||
```python
|
```python
|
||||||
@ -259,12 +267,8 @@ model = AutoModel.from_pretrained("your local path", trust_remote_code=True).to(
|
|||||||
```
|
```
|
||||||
|
|
||||||
加载半精度的 ChatGLM2-6B 模型需要大概 13GB 内存。内存较小的机器(比如 16GB 内存的 MacBook Pro),在空余内存不足的情况下会使用硬盘上的虚拟内存,导致推理速度严重变慢。
|
加载半精度的 ChatGLM2-6B 模型需要大概 13GB 内存。内存较小的机器(比如 16GB 内存的 MacBook Pro),在空余内存不足的情况下会使用硬盘上的虚拟内存,导致推理速度严重变慢。
|
||||||
<!-- 此时可以使用量化后的模型如 chatglm-6b-int4。因为 GPU 上量化的 kernel 是使用 CUDA 编写的,因此无法在 MacOS 上使用,只能使用 CPU 进行推理。
|
此时可以使用量化后的模型 chatglm2-6b-int4。因为 GPU 上量化的 kernel 是使用 CUDA 编写的,因此无法在 MacOS 上使用,只能使用 CPU 进行推理。
|
||||||
```python
|
为了充分使用 CPU 并行,还需要[单独安装 OpenMP](FAQ.md#q1)。
|
||||||
# INT8 量化的模型将"THUDM/chatglm-6b-int4"改为"THUDM/chatglm-6b-int8"
|
|
||||||
model = AutoModel.from_pretrained("THUDM/chatglm-6b-int4",trust_remote_code=True).float()
|
|
||||||
```
|
|
||||||
为了充分使用 CPU 并行,还需要[单独安装 OpenMP](FAQ.md#q1)。 -->
|
|
||||||
|
|
||||||
## 协议
|
## 协议
|
||||||
|
|
||||||
|
2
api.py
2
api.py
@ -51,6 +51,6 @@ async def create_item(request: Request):
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True)
|
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True)
|
||||||
model = AutoModel.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True, device='cuda')
|
model = AutoModel.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True).cuda()
|
||||||
model.eval()
|
model.eval()
|
||||||
uvicorn.run(app, host='0.0.0.0', port=8000, workers=1)
|
uvicorn.run(app, host='0.0.0.0', port=8000, workers=1)
|
||||||
|
@ -6,7 +6,7 @@ import readline
|
|||||||
from utils import load_model_on_gpus
|
from utils import load_model_on_gpus
|
||||||
|
|
||||||
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True)
|
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True)
|
||||||
model = AutoModel.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True, device='cuda')
|
model = AutoModel.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True).cuda()
|
||||||
# 多显卡支持,使用下面三行代替上面两行,将num_gpus改为你实际的显卡数量
|
# 多显卡支持,使用下面三行代替上面两行,将num_gpus改为你实际的显卡数量
|
||||||
# model_path = "THUDM/chatglm2-6b"
|
# model_path = "THUDM/chatglm2-6b"
|
||||||
# tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
|
# tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
protobuf
|
protobuf
|
||||||
transformers==4.27.1
|
transformers==4.30.2
|
||||||
cpm_kernels
|
cpm_kernels
|
||||||
torch>=2.0
|
torch>=2.0
|
||||||
gradio
|
gradio
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
from transformers import AutoModel, AutoTokenizer
|
from transformers import AutoModel, AutoTokenizer
|
||||||
import gradio as gr
|
import gradio as gr
|
||||||
import mdtex2html
|
import mdtex2html
|
||||||
|
from utils import load_model_on_gpus
|
||||||
|
|
||||||
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True)
|
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True)
|
||||||
model = AutoModel.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True, device='cuda')
|
model = AutoModel.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True).cuda()
|
||||||
# 多显卡支持,使用下面三行代替上面两行,将num_gpus改为你实际的显卡数量
|
# 多显卡支持,使用下面三行代替上面两行,将num_gpus改为你实际的显卡数量
|
||||||
# model_path = "THUDM/chatglm2-6b"
|
# model_path = "THUDM/chatglm2-6b"
|
||||||
# tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
|
# tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
|
||||||
|
72
web_demo2.py
Normal file
72
web_demo2.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
from transformers import AutoModel, AutoTokenizer
|
||||||
|
import streamlit as st
|
||||||
|
from streamlit_chat import message
|
||||||
|
|
||||||
|
|
||||||
|
st.set_page_config(
|
||||||
|
page_title="ChatGLM2-6b 演示",
|
||||||
|
page_icon=":robot:",
|
||||||
|
layout='wide'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@st.cache_resource
|
||||||
|
def get_model():
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True)
|
||||||
|
model = AutoModel.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True).cuda()
|
||||||
|
model = model.eval()
|
||||||
|
return tokenizer, model
|
||||||
|
|
||||||
|
|
||||||
|
MAX_TURNS = 20
|
||||||
|
MAX_BOXES = MAX_TURNS * 2
|
||||||
|
|
||||||
|
|
||||||
|
def predict(input, max_length, top_p, temperature, history=None):
|
||||||
|
tokenizer, model = get_model()
|
||||||
|
if history is None:
|
||||||
|
history = []
|
||||||
|
|
||||||
|
with container:
|
||||||
|
if len(history) > 0:
|
||||||
|
if len(history)>MAX_BOXES:
|
||||||
|
history = history[-MAX_TURNS:]
|
||||||
|
for i, (query, response) in enumerate(history):
|
||||||
|
message(query, avatar_style="big-smile", key=str(i) + "_user")
|
||||||
|
message(response, avatar_style="bottts", key=str(i))
|
||||||
|
|
||||||
|
message(input, avatar_style="big-smile", key=str(len(history)) + "_user")
|
||||||
|
st.write("AI正在回复:")
|
||||||
|
with st.empty():
|
||||||
|
for response, history in model.stream_chat(tokenizer, input, history, max_length=max_length, top_p=top_p,
|
||||||
|
temperature=temperature):
|
||||||
|
query, response = history[-1]
|
||||||
|
st.write(response)
|
||||||
|
|
||||||
|
return history
|
||||||
|
|
||||||
|
|
||||||
|
container = st.container()
|
||||||
|
|
||||||
|
# create a prompt text for the text generation
|
||||||
|
prompt_text = st.text_area(label="用户命令输入",
|
||||||
|
height = 100,
|
||||||
|
placeholder="请在这儿输入您的命令")
|
||||||
|
|
||||||
|
max_length = st.sidebar.slider(
|
||||||
|
'max_length', 0, 32768, 8192, step=1
|
||||||
|
)
|
||||||
|
top_p = st.sidebar.slider(
|
||||||
|
'top_p', 0.0, 1.0, 0.8, step=0.01
|
||||||
|
)
|
||||||
|
temperature = st.sidebar.slider(
|
||||||
|
'temperature', 0.0, 1.0, 0.95, step=0.01
|
||||||
|
)
|
||||||
|
|
||||||
|
if 'state' not in st.session_state:
|
||||||
|
st.session_state['state'] = []
|
||||||
|
|
||||||
|
if st.button("发送", key="predict"):
|
||||||
|
with st.spinner("AI正在思考,请稍等........"):
|
||||||
|
# text generation
|
||||||
|
st.session_state["state"] = predict(prompt_text, max_length, top_p, temperature, st.session_state["state"])
|
Loading…
Reference in New Issue
Block a user