Upload README.md
Browse files
README.md
CHANGED
|
@@ -1,3 +1,595 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- markdownlint-disable first-line-h1 -->
|
| 2 |
+
<!-- markdownlint-disable html -->
|
| 3 |
+
|
| 4 |
+
<div align="center">
|
| 5 |
+
<h1>
|
| 6 |
+
<img src="image/huozi-logo.jpg" width="30" /> 活字通用大模型
|
| 7 |
+
</h1>
|
| 8 |
+
</div>
|
| 9 |
+
</p>
|
| 10 |
+
|
| 11 |
+
<div align="center">
|
| 12 |
+
<a href="https://github.com/HIT-SCIR/huozi/pulls">
|
| 13 |
+
<image src="https://img.shields.io/badge/PRs-welcome-brightgreen">
|
| 14 |
+
</a>
|
| 15 |
+
<a href="https://github.com/HIT-SCIR/huozi/pulls">
|
| 16 |
+
<image src="https://img.shields.io/badge/License-Apache_2.0-green.svg">
|
| 17 |
+
</a>
|
| 18 |
+
<!-- <h4 align="center">
|
| 19 |
+
<p>
|
| 20 |
+
<b>中文</b> |
|
| 21 |
+
<a href="https://github.com/HIT-SCIR/huozi/blob/main/README_EN.md">English</a>
|
| 22 |
+
<p>
|
| 23 |
+
</h4> -->
|
| 24 |
+
</div>
|
| 25 |
+
|
| 26 |
+
## 🔖 目录
|
| 27 |
+
|
| 28 |
+
|章节|说明|
|
| 29 |
+
|---|---|
|
| 30 |
+
|[💁🏻♂ 开源清单](#-开源清单)|本仓库开源项目清单|
|
| 31 |
+
|[💡 模型介绍](#-模型介绍)|简要介绍活字模型结构和训练过程|
|
| 32 |
+
|[📥 模型下载](#-模型下载)|活字模型下载链接|
|
| 33 |
+
|[💻 模型推理](#-模型推理)|活字模型推理样例,包括vLLM推理加速、llama.cpp量化推理等框架的使用流程|
|
| 34 |
+
|[📈 模型性能](#-模型性能)|活字模型在主流评测任务上的性能|
|
| 35 |
+
|[🗂 生成样例](#-生成样例)|活字模型实际生成效果样例|
|
| 36 |
+
|
| 37 |
+
## 💁🏻♂ 开源清单
|
| 38 |
+

|
| 39 |
+
- **活字 3.0**: [[模型权重](#-模型下载)]
|
| 40 |
+
- 活字3.0为一个稀疏混合专家模型,支持32K上下文,具有丰富的中、英文知识和强大的数学推理、代码生成能力。活字3.0较旧版活字具有更强的指令遵循能力和安全性。
|
| 41 |
+
- **中文MT-Bench**: [[数据集](data/mt-bench-zh/)]
|
| 42 |
+
- 本数据集是英文MT-Bench对话能力评测数据集的中文版。它包含了一系列多轮对话问题,每一组问题都经过了精心的人工校对,并为适应中文语境进行了必要的调整。
|
| 43 |
+
- **《ChatGPT 调研报告》**: [[PDF](https://github.com/HIT-SCIR/huozi/blob/main/pdf/chatgpt_book.pdf)]
|
| 44 |
+
- 哈工大自然语言处理研究所组织多位老师和同学撰写了本调研报告,从技术原理、应用场景、未来发展等方面对ChatGPT进行了尽量详尽的介绍及总结。
|
| 45 |
+
- **活字 2.0**: [[模型权重](https://huggingface.co/HIT-SCIR/huozi-7b-rlhf)] [[RLHF数据](data/huozi-rlhf/huozi_rlhf_data.csv)]
|
| 46 |
+
- 在活字1.0基础上,通过人类反馈的强化学习(RLHF)进一步优化了模型回复质量,使其更加符合人类偏好。相较于上一个版本平均长度明显提高,遵从指令的能力更强,逻辑更加清晰。
|
| 47 |
+
- 16.9k 人工标注的偏好数据,回复来自活字模型,可以用于训练奖励模型。
|
| 48 |
+
- **活字 1.0**: [[模型权重](https://huggingface.co/HIT-SCIR/huozi-7b-sft)]
|
| 49 |
+
- 在Bloom模型的基础上,在大约 150 亿 tokens 上进行指令微调训练得到的模型,具有更强的指令遵循能力、更好的安全性。
|
| 50 |
+
|
| 51 |
+
## 💡 模型介绍
|
| 52 |
+
|
| 53 |
+
大规模语言模型(LLM)在自然语言处理领域取得了显著的进展,并在广泛的应用场景中展现了其强大的潜力。这一技术不仅吸引了学术界的广泛关注,也成为了工业界的热点。在此背景下,哈尔滨工业大学社会计算与信息检索研究中心(HIT-SCIR)近期推出了最新成果——**活字3.0**,致力于为自然语言处理的研究和实际应用提供更多可能性和选择。
|
| 54 |
+
|
| 55 |
+
活字3.0是基于Chinese-Mixtral-8x7B,在大约30万行指令数据上微调得到的模型。该模型支持**32K上下文**,能够有效处理长文本。活字3.0继承了基座模型丰富的**中英文知识**,并在**数学推理**、**代码生成**等任务上具有强大性能。经过指令微调,活字3.0还在**指令遵循能力**和**安全性**方面实现了显著提升。
|
| 56 |
+
|
| 57 |
+
此外,我们开源了**中文MT-Bench数据集**。这是一个中文开放问题集,包括80组对话任务,用于评估模型的多轮对话和指令遵循能力。该数据集是根据原始MT-Bench翻译得来的,每组问题均经过人工校对和中文语境下的适当调整。我们还对原始MT-Bench中的部分错误答案进行了修正。
|
| 58 |
+
|
| 59 |
+
> [!IMPORTANT]
|
| 60 |
+
> 活字系列模型仍然可能生成包含事实性错误的误导性回复或包含偏见/歧视的有害内容,请谨慎鉴别和使用生成的内容,请勿将生成的有害内容传播至互联网。
|
| 61 |
+
|
| 62 |
+
### 模型结构
|
| 63 |
+
|
| 64 |
+
活字3.0是一个稀疏混合专家模型(SMoE),使用了Mixtral-8x7B的模型结构。它区别于LLaMA、BLOOM等常见模型,活字3.0的每个前馈神经网络(FFN)层被替换为了“专家层”,该层包含8个FFN和一个“路由器”。这种设计使得模型在推理过程中,可以独立地将每个Token路由到最适合处理它的两个专家中。活字3.0共拥有46.7B个参数,但得益于其稀疏激活的特性,实际推理时仅需激活13B参数,有效提升了计算效率和处理速度。
|
| 65 |
+
|
| 66 |
+

|
| 67 |
+
|
| 68 |
+
### 训练过程
|
| 69 |
+
|
| 70 |
+
由于Mixtral-8x7B词表不支持中文,因此对中文的编解码效率较低,限制了中文场景下的实用性。我们首先基于Mixtral-8x7B进行了中文扩词表增量预训练,显著提高了模型对中文的编解码效率,并使模型具备了强大的中文生成和理解能力。这项成果名为[Chinese-Mixtral-8x7B](https://github.com/HIT-SCIR/Chinese-Mixtral-8x7B),我们已于2024年1月18日开源了其模型权重和训练代码。基于此,我们进一步对模型进行指令微调,最终推出了活字3.0。这一版本的中文编码、指令遵循、安全回复等能力都有显著提升。
|
| 71 |
+
|
| 72 |
+
## 📥 模型下载
|
| 73 |
+
|
| 74 |
+
|模型名称|文件大小|下载地址|备注|
|
| 75 |
+
|:---:|:---:|:---:|:---:|
|
| 76 |
+
|huozi3|88GB|[🤗HuggingFace](https://huggingface.co/HIT-SCIR/huozi3)<br>[ModelScope](https://modelscope.cn/models/HIT-SCIR/huozi3/summary)|活字3.0 完整模型|
|
| 77 |
+
|huozi3-gguf|25GB|[🤗HuggingFace](https://huggingface.co/HIT-SCIR/huozi3-gguf)<br>[ModelScope](https://modelscope.cn/models/HIT-SCIR/huozi3-gguf/summary)|活字3.0 GGUF版本,适用于llama.cpp等推理框架|
|
| 78 |
+
|huozi3-awq|24GB|[🤗HuggingFace](https://huggingface.co/HIT-SCIR/huozi3-awq)<br>[ModelScope](https://modelscope.cn/models/HIT-SCIR/huozi3-awq/summary)|活字3.0 AWQ版本,适用于AutoAWQ等推理框架|
|
| 79 |
+
|
| 80 |
+
如果您希望微调活字3.0或Chinese-Mixtral-8x7B,请参考[此处训练代码](https://github.com/HIT-SCIR/Chinese-Mixtral-8x7B?tab=readme-ov-file#%E5%BE%AE%E8%B0%83)。
|
| 81 |
+
|
| 82 |
+
## 💻 模型推理
|
| 83 |
+
|
| 84 |
+
### Quick Start
|
| 85 |
+
|
| 86 |
+
活字3.0采用ChatML格式的prompt模板,格式为:
|
| 87 |
+
```
|
| 88 |
+
<|beginofutterance|>系统
|
| 89 |
+
{system prompt}<|endofutterance|>
|
| 90 |
+
<|beginofutterance|>用户
|
| 91 |
+
{input}<|endofutterance|>
|
| 92 |
+
<|beginofutterance|>助手
|
| 93 |
+
{output}<|endofutterance|>
|
| 94 |
+
```
|
| 95 |
+
|
| 96 |
+
使用活字3.0进行推理的示例代码如下:
|
| 97 |
+
```python
|
| 98 |
+
# quickstart.py
|
| 99 |
+
|
| 100 |
+
import torch
|
| 101 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 102 |
+
|
| 103 |
+
model_id = "HIT-SCIR/huozi3"
|
| 104 |
+
|
| 105 |
+
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 106 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 107 |
+
model_id,
|
| 108 |
+
attn_implementation="flash_attention_2",
|
| 109 |
+
torch_dtype=torch.bfloat16,
|
| 110 |
+
device_map="auto",
|
| 111 |
+
)
|
| 112 |
+
|
| 113 |
+
text = """<|beginofutterance|>系统
|
| 114 |
+
你是一个智能助手<|endofutterance|>
|
| 115 |
+
<|beginofutterance|>用户
|
| 116 |
+
请你用python写一段快速排序的代码<|endofutterance|>
|
| 117 |
+
<|beginofutterance|>助手
|
| 118 |
+
"""
|
| 119 |
+
|
| 120 |
+
inputs = tokenizer(text, return_tensors="pt").to(0)
|
| 121 |
+
|
| 122 |
+
outputs = model.generate(
|
| 123 |
+
**inputs,
|
| 124 |
+
eos_token_id=57001,
|
| 125 |
+
temperature=0.8,
|
| 126 |
+
top_p=0.9,
|
| 127 |
+
max_new_tokens=2048,
|
| 128 |
+
)
|
| 129 |
+
print(tokenizer.decode(outputs[0], skip_special_tokens=False))
|
| 130 |
+
```
|
| 131 |
+
|
| 132 |
+
活字3.0支持全部Mixtral模型生态,包括Transformers、vLLM、llama.cpp、AutoAWQ、Text generation web UI等框架。
|
| 133 |
+
|
| 134 |
+
如果您在下载模型时遇到网络问题,可以使用我们在[ModelScope](#modelscope-模型推理)上提供的检查点。
|
| 135 |
+
|
| 136 |
+
<details>
|
| 137 |
+
<summary>
|
| 138 |
+
|
| 139 |
+
#### Transformers 模型推理 + 流式生成
|
| 140 |
+
|
| 141 |
+
</summary>
|
| 142 |
+
|
| 143 |
+
transformers支持为tokenizer添加聊天模板,并支持流式生成。示例代码如下:
|
| 144 |
+
```python
|
| 145 |
+
# example/transformers-stream/stream.py
|
| 146 |
+
|
| 147 |
+
import torch
|
| 148 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer, TextStreamer
|
| 149 |
+
|
| 150 |
+
model_id = "HIT-SCIR/huozi3"
|
| 151 |
+
|
| 152 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 153 |
+
model_id,
|
| 154 |
+
attn_implementation="flash_attention_2",
|
| 155 |
+
torch_dtype=torch.bfloat16,
|
| 156 |
+
device_map="auto",
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 160 |
+
tokenizer.chat_template = """{% for message in messages %}{{'<|beginofutterance|>' + message['role'] + '\n' + message['content']}}{% if (loop.last and add_generation_prompt) or not loop.last %}{{ '<|endofutterance|>' + '\n'}}{% endif %}{% endfor %}
|
| 161 |
+
{% if add_generation_prompt and messages[-1]['role'] != '助手' %}{{ '<|beginofutterance|>助手\n' }}{% endif %}"""
|
| 162 |
+
|
| 163 |
+
chat = [
|
| 164 |
+
{"role": "系统", "content": "你是一个智能助手"},
|
| 165 |
+
{"role": "用户", "content": "请你用python写一段快速排序的代码"},
|
| 166 |
+
]
|
| 167 |
+
|
| 168 |
+
inputs = tokenizer.apply_chat_template(
|
| 169 |
+
chat,
|
| 170 |
+
tokenize=True,
|
| 171 |
+
add_generation_prompt=True,
|
| 172 |
+
return_tensors="pt",
|
| 173 |
+
).to(0)
|
| 174 |
+
|
| 175 |
+
stream_output = model.generate(
|
| 176 |
+
inputs,
|
| 177 |
+
streamer=TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True),
|
| 178 |
+
eos_token_id=57001,
|
| 179 |
+
temperature=0.8,
|
| 180 |
+
top_p=0.9,
|
| 181 |
+
max_new_tokens=2048,
|
| 182 |
+
)
|
| 183 |
+
```
|
| 184 |
+
|
| 185 |
+
</details>
|
| 186 |
+
|
| 187 |
+
<details>
|
| 188 |
+
<summary>
|
| 189 |
+
|
| 190 |
+
#### ModelScope 模型推理
|
| 191 |
+
|
| 192 |
+
</summary>
|
| 193 |
+
|
| 194 |
+
ModelScope的接口与Transformers非常相似,只需将transformers替换为modelscope即可:
|
| 195 |
+
```diff
|
| 196 |
+
# example/modelscope-generate/generate.py
|
| 197 |
+
|
| 198 |
+
import torch
|
| 199 |
+
- from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 200 |
+
+ from modelscope import AutoTokenizer, AutoModelForCausalLM
|
| 201 |
+
|
| 202 |
+
model_id = "HIT-SCIR/huozi3"
|
| 203 |
+
|
| 204 |
+
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 205 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 206 |
+
model_id,
|
| 207 |
+
attn_implementation="flash_attention_2",
|
| 208 |
+
torch_dtype=torch.bfloat16,
|
| 209 |
+
device_map="auto",
|
| 210 |
+
)
|
| 211 |
+
|
| 212 |
+
text = """<|beginofutterance|>系统
|
| 213 |
+
你是一个智能助手<|endofutterance|>
|
| 214 |
+
<|beginofutterance|>用户
|
| 215 |
+
请你用python写一段快速排序的代码<|endofutterance|>
|
| 216 |
+
<|beginofutterance|>助手
|
| 217 |
+
"""
|
| 218 |
+
|
| 219 |
+
inputs = tokenizer(text, return_tensors="pt").to(0)
|
| 220 |
+
|
| 221 |
+
outputs = model.generate(
|
| 222 |
+
**inputs,
|
| 223 |
+
eos_token_id=57001,
|
| 224 |
+
temperature=0.8,
|
| 225 |
+
top_p=0.9,
|
| 226 |
+
max_new_tokens=2048,
|
| 227 |
+
)
|
| 228 |
+
print(tokenizer.decode(outputs[0], skip_special_tokens=False))
|
| 229 |
+
```
|
| 230 |
+
|
| 231 |
+
</details>
|
| 232 |
+
|
| 233 |
+
<details>
|
| 234 |
+
<summary>
|
| 235 |
+
|
| 236 |
+
#### vLLM 推理加速
|
| 237 |
+
|
| 238 |
+
</summary>
|
| 239 |
+
|
| 240 |
+
活字3.0支持通过vLLM实现推理加速,示例代码如下:
|
| 241 |
+
```python
|
| 242 |
+
# example/vllm-generate/generate.py
|
| 243 |
+
|
| 244 |
+
from vllm import LLM, SamplingParams
|
| 245 |
+
|
| 246 |
+
prompts = [
|
| 247 |
+
"""<|beginofutterance|>系统
|
| 248 |
+
你是一个智能助手<|endofutterance|>
|
| 249 |
+
<|beginofutterance|>用户
|
| 250 |
+
请你用python写一段快速排序的代码<|endofutterance|>
|
| 251 |
+
<|beginofutterance|>助手
|
| 252 |
+
""",
|
| 253 |
+
]
|
| 254 |
+
|
| 255 |
+
sampling_params = SamplingParams(
|
| 256 |
+
temperature=0.8, top_p=0.95, stop_token_ids=[57001], max_tokens=2048
|
| 257 |
+
)
|
| 258 |
+
llm = LLM(
|
| 259 |
+
model="HIT-SCIR/huozi3",
|
| 260 |
+
tensor_parallel_size=4,
|
| 261 |
+
)
|
| 262 |
+
outputs = llm.generate(prompts, sampling_params)
|
| 263 |
+
|
| 264 |
+
for output in outputs:
|
| 265 |
+
prompt = output.prompt
|
| 266 |
+
generated_text = output.outputs[0].text
|
| 267 |
+
print(generated_text)
|
| 268 |
+
```
|
| 269 |
+
|
| 270 |
+
</details>
|
| 271 |
+
|
| 272 |
+
<details>
|
| 273 |
+
<summary>
|
| 274 |
+
|
| 275 |
+
#### 部署 OpenAI API Server
|
| 276 |
+
|
| 277 |
+
</summary>
|
| 278 |
+
|
| 279 |
+
活字3.0可以部署为支持OpenAI API协议的服务,这使得活字3.0可以直接通过OpenAI API进行调用。
|
| 280 |
+
|
| 281 |
+
环境准备:
|
| 282 |
+
```shell
|
| 283 |
+
$ pip install vllm openai
|
| 284 |
+
```
|
| 285 |
+
|
| 286 |
+
启动服务:
|
| 287 |
+
```shell
|
| 288 |
+
$ python -m vllm.entrypoints.openai.api_server --model /path/to/huozi3/checkpoint --served-model-name huozi --chat-template template.jinja --tensor-parallel-size 8 --response-role 助手 --max-model-len 2048
|
| 289 |
+
```
|
| 290 |
+
|
| 291 |
+
使用OpenAI API发送请求:
|
| 292 |
+
```python
|
| 293 |
+
# example/openai-api/openai-client.py
|
| 294 |
+
|
| 295 |
+
from openai import OpenAI
|
| 296 |
+
|
| 297 |
+
openai_api_key = "EMPTY"
|
| 298 |
+
openai_api_base = "http://localhost:8000/v1"
|
| 299 |
+
|
| 300 |
+
client = OpenAI(
|
| 301 |
+
api_key=openai_api_key,
|
| 302 |
+
base_url=openai_api_base,
|
| 303 |
+
)
|
| 304 |
+
|
| 305 |
+
chat_response = client.chat.completions.create(
|
| 306 |
+
model="huozi",
|
| 307 |
+
messages=[
|
| 308 |
+
{"role": "系统", "content": "你是一个智能助手"},
|
| 309 |
+
{"role": "用户", "content": "请你用python写一段快速排序的代码"},
|
| 310 |
+
],
|
| 311 |
+
extra_body={"stop_token_ids": [57001]},
|
| 312 |
+
)
|
| 313 |
+
print("Chat response:", chat_response.choices[0].message.content)
|
| 314 |
+
```
|
| 315 |
+
|
| 316 |
+
下面是一个使用OpenAI API + Gradio + 流式生成的示例代码:
|
| 317 |
+
```python
|
| 318 |
+
# example/openai-api/openai-client-gradio.py
|
| 319 |
+
|
| 320 |
+
from openai import OpenAI
|
| 321 |
+
import gradio as gr
|
| 322 |
+
|
| 323 |
+
openai_api_key = "EMPTY"
|
| 324 |
+
openai_api_base = "http://localhost:8000/v1"
|
| 325 |
+
|
| 326 |
+
client = OpenAI(
|
| 327 |
+
api_key=openai_api_key,
|
| 328 |
+
base_url=openai_api_base,
|
| 329 |
+
)
|
| 330 |
+
|
| 331 |
+
|
| 332 |
+
def predict(message, history):
|
| 333 |
+
history_openai_format = [
|
| 334 |
+
{"role": "系统", "content": "你是一个智能助手"},
|
| 335 |
+
]
|
| 336 |
+
for human, assistant in history:
|
| 337 |
+
history_openai_format.append({"role": "用户", "content": human})
|
| 338 |
+
history_openai_format.append({"role": "助手", "content": assistant})
|
| 339 |
+
history_openai_format.append({"role": "用户", "content": message})
|
| 340 |
+
models = client.models.list()
|
| 341 |
+
|
| 342 |
+
stream = client.chat.completions.create(
|
| 343 |
+
model=models.data[0].id,
|
| 344 |
+
messages=history_openai_format,
|
| 345 |
+
temperature=0.8,
|
| 346 |
+
stream=True,
|
| 347 |
+
extra_body={"repetition_penalty": 1, "stop_token_ids": [57001]},
|
| 348 |
+
)
|
| 349 |
+
|
| 350 |
+
partial_message = ""
|
| 351 |
+
for chunk in stream:
|
| 352 |
+
partial_message += chunk.choices[0].delta.content or ""
|
| 353 |
+
yield partial_message
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
gr.ChatInterface(predict).queue().launch()
|
| 357 |
+
```
|
| 358 |
+
|
| 359 |
+
</details>
|
| 360 |
+
|
| 361 |
+
### 量化推理
|
| 362 |
+
|
| 363 |
+
活字3.0支持量化推理,下表为活字3.0在各个量化框架下显存占用量:
|
| 364 |
+
|
| 365 |
+
|量化方法|显存占用|
|
| 366 |
+
|:---:|:---:|
|
| 367 |
+
|无|95GB|
|
| 368 |
+
|AWQ|32GB|
|
| 369 |
+
|GGUF(q4_0)|28GB|
|
| 370 |
+
|GGUF(q2_k)|18GB|
|
| 371 |
+
|GGUF(q2_k, offload 16层)|9.6GB|
|
| 372 |
+
|
| 373 |
+
<details>
|
| 374 |
+
<summary>
|
| 375 |
+
|
| 376 |
+
#### GGUF 格式
|
| 377 |
+
|
| 378 |
+
</summary>
|
| 379 |
+
|
| 380 |
+
GGUF格式旨在快速加载和保存模型,由llama.cpp团队推出。我们已经提供了[GGUF格式的活字3.0](https://huggingface.co/HIT-SCIR/huozi3-gguf)。
|
| 381 |
+
|
| 382 |
+
您也可以手动将HuggingFace格式的活字3.0转换到GGUF格式,以使用其他的量化方法。
|
| 383 |
+
|
| 384 |
+
##### Step 1 环境准备
|
| 385 |
+
|
| 386 |
+
首先需要下载llama.cpp的源码。我们在仓库中提供了llama.cpp的submodule,这个版本的llama.cpp已经过测试,可以成功进行推理:
|
| 387 |
+
```shell
|
| 388 |
+
$ git clone --recurse-submodules https://github.com/HIT-SCIR/huozi
|
| 389 |
+
$ cd examples/llama.cpp
|
| 390 |
+
```
|
| 391 |
+
|
| 392 |
+
您也可以下载最新版本的llama.cpp源码:
|
| 393 |
+
```shell
|
| 394 |
+
$ git clone https://github.com/ggerganov/llama.cpp.git
|
| 395 |
+
$ cd llama.cpp
|
| 396 |
+
```
|
| 397 |
+
|
| 398 |
+
然后需要进行编译。根据您的硬件平台,编译命令有细微差异:
|
| 399 |
+
```shell
|
| 400 |
+
$ make # 用于纯CPU推理
|
| 401 |
+
$ make LLAMA_CUBLAS=1 # 用于GPU推理
|
| 402 |
+
$ LLAMA_METAL=1 make # 用于Apple Silicon,暂未经过测试
|
| 403 |
+
```
|
| 404 |
+
|
| 405 |
+
##### Step 2 格式转换(可选)
|
| 406 |
+
|
| 407 |
+
以下命令需要在`llama.cpp/`目录下:
|
| 408 |
+
```shell
|
| 409 |
+
# 转换为GGUF格式
|
| 410 |
+
$ python convert.py --outfile /path/to/huozi-gguf/huozi3.gguf /path/to/huozi3
|
| 411 |
+
# 进行GGUF格式的q4_0量化
|
| 412 |
+
$ quantize /path/to/huozi-gguf/huozi3.gguf /path/to/huozi-gguf/huozi3-q4_0.gguf q4_0
|
| 413 |
+
```
|
| 414 |
+
|
| 415 |
+
##### Step 3 开始推理
|
| 416 |
+
|
| 417 |
+
以下命令需要在`llama.cpp/`目录下:
|
| 418 |
+
```shell
|
| 419 |
+
$ main -m /path/to/huozi-gguf/huozi3-q4_0.gguf --color --interactive-first -c 2048 -t 6 --temp 0.2 --repeat_penalty 1.1 -ngl 999 --in-prefix "<|beginofutterance|>用户\n" --in-suffix "<|endofutterance|>\n<|beginofutterance|>助手" -r "<|endofutterance|>"
|
| 420 |
+
```
|
| 421 |
+
|
| 422 |
+
`-ngl`参数表示向GPU中offload的层数,降低这个值可以缓解GPU显存压力。经过我们的实际测试,q2_k量化的模型offload 16层,显存占用可降低至9.6GB,可在消费级GPU上运行模型:
|
| 423 |
+
```shell
|
| 424 |
+
$ main -m /path/to/huozi-gguf/huozi3-q2_k.gguf --color --interactive-first -c 2048 -t 6 --temp 0.2 --repeat_penalty 1.1 -ngl 16 --in-prefix "<|beginofutterance|>用户\n" --in-suffix "<|endofutterance|>\n<|beginofutterance|>助手" -r "<|endofutterance|>"
|
| 425 |
+
```
|
| 426 |
+
|
| 427 |
+
关于`main`的更多参数,可以参考llama.cpp的[官方文档](https://github.com/ggerganov/llama.cpp/tree/master/examples/main)。
|
| 428 |
+
|
| 429 |
+
</details>
|
| 430 |
+
|
| 431 |
+
<details>
|
| 432 |
+
<summary>
|
| 433 |
+
|
| 434 |
+
#### AWQ 格式
|
| 435 |
+
|
| 436 |
+
</summary>
|
| 437 |
+
|
| 438 |
+
AWQ是一种量化模型的存储格式。我们已经提供了[AWQ格式的活字3.0](https://huggingface.co/HIT-SCIR/huozi3-awq),您也可以手动将HuggingFace格式的活字3.0转换到AWQ格式。
|
| 439 |
+
|
| 440 |
+
##### Step 1 格式转换(可选)
|
| 441 |
+
|
| 442 |
+
```python
|
| 443 |
+
# example/autoawq-generate/quant.py
|
| 444 |
+
|
| 445 |
+
from awq import AutoAWQForCausalLM
|
| 446 |
+
from transformers import AutoTokenizer
|
| 447 |
+
|
| 448 |
+
model_path = "/path/to/huozi3"
|
| 449 |
+
quant_path = "/path/to/save/huozi3-awq"
|
| 450 |
+
modules_to_not_convert = ["gate"]
|
| 451 |
+
quant_config = {
|
| 452 |
+
"zero_point": True,
|
| 453 |
+
"q_group_size": 128,
|
| 454 |
+
"w_bit": 4,
|
| 455 |
+
"version": "GEMM",
|
| 456 |
+
"modules_to_not_convert": modules_to_not_convert,
|
| 457 |
+
}
|
| 458 |
+
|
| 459 |
+
model = AutoAWQForCausalLM.from_pretrained(
|
| 460 |
+
model_path,
|
| 461 |
+
safetensors=True,
|
| 462 |
+
**{"low_cpu_mem_usage": True},
|
| 463 |
+
)
|
| 464 |
+
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
|
| 465 |
+
|
| 466 |
+
model.quantize(
|
| 467 |
+
tokenizer,
|
| 468 |
+
quant_config=quant_config,
|
| 469 |
+
modules_to_not_convert=modules_to_not_convert,
|
| 470 |
+
)
|
| 471 |
+
|
| 472 |
+
model.save_quantized(quant_path)
|
| 473 |
+
tokenizer.save_pretrained(quant_path)
|
| 474 |
+
|
| 475 |
+
print(f'Model is quantized and saved at "{quant_path}"')
|
| 476 |
+
```
|
| 477 |
+
|
| 478 |
+
##### Step 2 开始推理
|
| 479 |
+
|
| 480 |
+
在获取到AWQ格式的模型权重后,可以使用AutoAWQForCausalLM代替AutoModelForCausalLM加载模型。示例代码如下:
|
| 481 |
+
```diff
|
| 482 |
+
# example/autoawq-generate/generate.py
|
| 483 |
+
|
| 484 |
+
import torch
|
| 485 |
+
+ from awq import AutoAWQForCausalLM
|
| 486 |
+
from transformers import AutoTokenizer, TextStreamer
|
| 487 |
+
|
| 488 |
+
|
| 489 |
+
- model_id = "HIT-SCIR/huozi3"
|
| 490 |
+
+ model_id = "HIT-SCIR/huozi3-awq" # or model_id = "/path/to/saved/huozi3-awq"
|
| 491 |
+
|
| 492 |
+
+ model = AutoAWQForCausalLM.from_quantized(model_id, fuse_layers=True)
|
| 493 |
+
- model = AutoModelForCausalLM.from_pretrained(
|
| 494 |
+
- model_id,
|
| 495 |
+
- attn_implementation="flash_attention_2",
|
| 496 |
+
- torch_dtype=torch.bfloat16,
|
| 497 |
+
- device_map="auto",
|
| 498 |
+
- )
|
| 499 |
+
|
| 500 |
+
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 501 |
+
tokenizer.chat_template = """{% for message in messages %}{{'<|beginofutterance|>' + message['role'] + '\n' + message['content']}}{% if (loop.last and add_generation_prompt) or not loop.last %}{{ '<|endofutterance|>' + '\n'}}{% endif %}{% endfor %}
|
| 502 |
+
{% if add_generation_prompt and messages[-1]['role'] != '助手' %}{{ '<|beginofutterance|>助手\n' }}{% endif %}"""
|
| 503 |
+
|
| 504 |
+
chat = [
|
| 505 |
+
{"role": "系统", "content": "你是一个智能助手"},
|
| 506 |
+
{"role": "用户", "content": "请你用python写一段快速排序的代码"},
|
| 507 |
+
]
|
| 508 |
+
|
| 509 |
+
inputs = tokenizer.apply_chat_template(
|
| 510 |
+
chat,
|
| 511 |
+
tokenize=True,
|
| 512 |
+
add_generation_prompt=True,
|
| 513 |
+
return_tensors="pt",
|
| 514 |
+
).to(0)
|
| 515 |
+
|
| 516 |
+
stream_output = model.generate(
|
| 517 |
+
inputs,
|
| 518 |
+
streamer=TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True),
|
| 519 |
+
eos_token_id=57001,
|
| 520 |
+
temperature=0.8,
|
| 521 |
+
top_p=0.9,
|
| 522 |
+
max_new_tokens=2048,
|
| 523 |
+
)
|
| 524 |
+
```
|
| 525 |
+
|
| 526 |
+
</details>
|
| 527 |
+
|
| 528 |
+
## 📈 模型性能
|
| 529 |
+
|
| 530 |
+

|
| 531 |
+
|
| 532 |
+
针对大模型综合能力评价,我们分别使用以下评测数据集对活字3.0进行评测:
|
| 533 |
+
- C-Eval:一个全面的中文基础模型评估套件。它包含了13948个多项选择题,涵盖了52个不同的学科和四个难度级别。
|
| 534 |
+
- CMMLU:一个综合性的中文评估基准,专门用于评估语言模型在中文语境下的知识和推理能力,涵盖了从基础学科到高级专业水平的67个主题。
|
| 535 |
+
- GAOKAO:一个以中国高考题目为数据集,旨在提供和人类对齐的,直观,高效地测评大模型语言理解能力、逻辑推理能力的测评框架。
|
| 536 |
+
- MMLU:一个包含57个多选任务的英文评测数据集,涵盖了初等数学、美国历史、计算机科学、法律等,难度覆盖高中水平到专家水平,是目前主流的LLM评测数据集之一。
|
| 537 |
+
- HellaSwag:一个极具挑战的英文NLI评测数据集,每一个问题都需要对上下文进行深入理解,而不能基于常识进行回答。
|
| 538 |
+
- GSM8K:一个高质量的小学数学应用题的数据集,这些问题需要 2 到 8 个步骤来解决,解决方案主���涉及使用基本算术运算,可用于评价多步数学推理能力。
|
| 539 |
+
- HumanEval:一个由 164 个原创编程问题组成的数据集,通过衡量从文档字符串生成程序的功能正确性,来够评估语言理解、算法和简单的数学能力。
|
| 540 |
+
- MT-Bench:一个开放的英文问题集,包括80个多轮对话任务,用于评估聊天机器人的多轮对话和指令遵循能力,并通过大模型裁判(GPT-4)对模型回答进行打分。
|
| 541 |
+
- MT-Bench-zh:我们根据MT-Bench翻译得来的中文问题集,每组问题均经过人工校对和中文语境下的适当调整。我们已在[此处](data/mt-bench-zh/)开源MT-Bench-zh数据集。
|
| 542 |
+
- MT-Bench-safety:我们手工构造的安全数据集,包括暴力、色情、敏感等风险内容。该数据集为封闭数据集。
|
| 543 |
+
|
| 544 |
+
活字3.0在推理时仅激活13B参数。下表为活字3.0与其他13B规模的中文模型以及旧版活字在各个评测数据集上的结果:
|
| 545 |
+
|
| 546 |
+
<!-- | 模型名称 | 模型结构 | C-Eval<br>(中文) | CMMLU<br>(中文) | GAOKAO<br>(中文) | MT-Bench-zh<br>(中文对话) | MT-Bench-safety<br>(中文安全) | MMLU<br>(英文) | HellaSwag<br>(英文) | MT-Bench<br>(英文对话) | GSM8K<br>(数学) | HumanEval<br>(代码) |
|
| 547 |
+
|---------------------------------------------|---------|--------------|-------------|---------------|--------------------------|-----------------------------|------------|------------------|-----------------------|-------------|-----------------|
|
| 548 |
+
| baichuan-inc/Baichuan2-13B-Chat v2 | Baichuan| 56.13 | 58.50 | 48.99 | 6.74 | 8.30 | 54.50 | 51.19 | 6.59 | 25.17 | 20.12 |
|
| 549 |
+
| wangrongsheng/Aurora-Plus | Mixtral | 47.67 | 48.75 | 35.05 | 5.47 | 6.70 | 67.80 | 78.27 | 7.13 | 66.26 | 27.44 |
|
| 550 |
+
| TigerResearch/tigerbot-13b-chat-v5 | LLaMA | 49.78 | 51.28 | 41.31 | 5.98 | 7.63 | 56.34 | 35.17 | 4.88 | 66.19 | 14.63 |
|
| 551 |
+
| hfl/chinese-alpaca-2-13b | LLaMA | 43.47 | 44.53 | 25.94 | 5.77 | 8.13 | 53.05 | 56.85 | 6.24 | 32.75 | 14.02 |
|
| 552 |
+
| 活字1.0 | BLOOM | 37.27 | 36.24 | 19.72 | 4.48 | 7.18 | 39.68 | 33.21 | 4.34 | 21.99 | 13.41 |
|
| 553 |
+
| 活字2.0 | BLOOM | 32.05 | 34.68 | 22.97 | 5.08 | 6.68 | 38.04 | 33.34 | 4.79 | 19.86 | 6.71 |
|
| 554 |
+
| **活字3.0(最新版本)** | Mixtral | 51.82 | 51.06 | 41.21 | 6.29 | 7.58 | 69.48 | 65.18 | 7.62 | 65.81 | 40.85 | -->
|
| 555 |
+

|
| 556 |
+
|
| 557 |
+
> 我们在C-Eval、CMMLU、MMLU采用5-shot,GSM8K采用4-shot,HellaSwag、HumanEval采用0-shot,HumanEval采用pass@1指标。所有测试均采用greedy策略。
|
| 558 |
+
>
|
| 559 |
+
> 我们使用OpenCompass作为评测框架,commit hash为[4c87e77](https://github.com/open-compass/opencompass/tree/4c87e777d855636b9eda7ec87bcbbf12b62caed3)。评测代码位于[此处](./evaluate/)。
|
| 560 |
+
|
| 561 |
+
根据上表中的测试结果,活字3.0较旧版活字取得了巨大的性能提升。在中文知识方面,活字3.0达到了与Tigerbot-13B-chat-v5相当的性能,并是在中文对话和指令遵循方面表现得更加优秀。在英文知识方面,得益于原版Mixtral-8x7B的强大性能,活字3.0超过了Baichuan2-13B-Chat v2和LLaMA系列的扩词表模型,并在英文对话和指令遵循能力上达到了较高水平。在数学推理和代码生成任务上,活字3.0均展现出强大的性能,这说明活字3.0对复杂问题的深层次理解、多步推理、以及结构化信息处理等方面具有较强水平。由于我们采用了较高质量的代码数据集,活字3.0的代码生成能力也超越了同为Mixtral结构的Aurora-Plus模型。
|
| 562 |
+
|
| 563 |
+
## 🗂 生成样例
|
| 564 |
+
|
| 565 |
+
下面是活字3.0在MT-Bench-zh评测集上的生成效果展示,并与活字2.0(RLHF版本)进行对比:
|
| 566 |
+
|
| 567 |
+

|
| 568 |
+

|
| 569 |
+

|
| 570 |
+

|
| 571 |
+

|
| 572 |
+
|
| 573 |
+
## <img src="https://cdn.jsdelivr.net/gh/LightChen233/blog-img/folders.png" width="25" /> 开源协议
|
| 574 |
+
对本仓库源码的使用遵循开源许可协议 [Apache 2.0](https://github.com/HIT-SCIR/huozi/blob/main/LICENSE)。
|
| 575 |
+
|
| 576 |
+
活字支持商用。如果将活字模型或其衍生品用作商业用途,请您按照如下方式联系许可方,以进行登记并向许可方申请书面授权:联系邮箱:<[email protected]>。
|
| 577 |
+
|
| 578 |
+
## <img src="https://cdn.jsdelivr.net/gh/LightChen233/blog-img/notes.png" width="25" /> Citation
|
| 579 |
+
|
| 580 |
+
### 活字大模型
|
| 581 |
+
|
| 582 |
+
```latex
|
| 583 |
+
@misc{huozi,
|
| 584 |
+
author = {Huozi-Team}.
|
| 585 |
+
title = {Huozi: Leveraging Large Language Models for Enhanced Open-Domain Chatting}
|
| 586 |
+
year = {2024},
|
| 587 |
+
publisher = {GitHub},
|
| 588 |
+
journal = {GitHub repository}
|
| 589 |
+
howpublished = {\url{https://github.com/HIT-SCIR/huozi}}
|
| 590 |
+
}
|
| 591 |
+
```
|
| 592 |
+
|
| 593 |
+
## <img src="https://cdn.jsdelivr.net/gh/LightChen233/blog-img/star.png" width="25" /> Star History
|
| 594 |
+
|
| 595 |
+
[](https://star-history.com/#HIT-SCIR/huozi&Date)
|