From 37a3da79e4968518089398a22ec8b5d7a58c5e93 Mon Sep 17 00:00:00 2001
From: jubgjf
Date: Thu, 12 Sep 2024 13:32:43 +0800
Subject: [PATCH] Update README.md: Release huozi 3.5
---
README-v3.md | 603 ++++++++++++++++++++++++++++++++++
README.md | 218 ++++--------
data.md | 11 +
image/evaluation-v3.5.png | Bin 0 -> 263836 bytes
image/examples/v3.5-case1.png | Bin 0 -> 183143 bytes
image/examples/v3.5-case2.png | Bin 0 -> 263493 bytes
image/examples/v3.5-case3.png | Bin 0 -> 217478 bytes
image/examples/v3.5-case4.png | Bin 0 -> 563442 bytes
image/examples/v3.5-case5.png | Bin 0 -> 391297 bytes
image/examples/v3.5-case6.png | Bin 0 -> 297660 bytes
image/metric-v3.5-h.png | Bin 0 -> 755239 bytes
image/metric-v3.5-v.png | Bin 0 -> 581323 bytes
image/models-v3.5.png | Bin 0 -> 489060 bytes
image/smoe-v3.5.png | Bin 0 -> 215005 bytes
image/train-process-v3.5.png | Bin 0 -> 339572 bytes
15 files changed, 675 insertions(+), 157 deletions(-)
create mode 100644 README-v3.md
create mode 100644 data.md
create mode 100644 image/evaluation-v3.5.png
create mode 100644 image/examples/v3.5-case1.png
create mode 100644 image/examples/v3.5-case2.png
create mode 100644 image/examples/v3.5-case3.png
create mode 100644 image/examples/v3.5-case4.png
create mode 100644 image/examples/v3.5-case5.png
create mode 100644 image/examples/v3.5-case6.png
create mode 100644 image/metric-v3.5-h.png
create mode 100644 image/metric-v3.5-v.png
create mode 100644 image/models-v3.5.png
create mode 100644 image/smoe-v3.5.png
create mode 100644 image/train-process-v3.5.png
diff --git a/README-v3.md b/README-v3.md
new file mode 100644
index 0000000..39883a2
--- /dev/null
+++ b/README-v3.md
@@ -0,0 +1,603 @@
+
+
+
+
+
+ 活字通用大模型
+
+
+
+
+
+
+## 🎉 更新
+
+- [2024-02-09] 发布活字3.0版本和中文MT-Bench数据集
+- [2023-08-06] 发布活字1.0和活字2.0版本
+- [2023-05-04] 发布《ChatGPT调研报告》;内测活字大模型
+
+## 🔖 目录
+
+|章节|说明|
+|---|---|
+|[💁🏻♂ 开源清单](#-开源清单)|本仓库开源项目清单|
+|[💡 模型介绍](#-模型介绍)|简要介绍活字模型结构和训练过程|
+|[📥 模型下载](#-模型下载)|活字模型下载链接|
+|[💻 模型推理](#-模型推理)|活字模型推理样例,包括vLLM推理加速、llama.cpp量化推理等框架的使用流程|
+|[📈 模型性能](#-模型性能)|活字模型在主流评测任务上的性能|
+|[🗂 生成样例](#-生成样例)|活字模型实际生成效果样例|
+
+## 💁🏻♂ 开源清单
+![](image/models-v3.png)
+- **活字 3.0**: [[模型权重](#-模型下载)] [[在线Demo](https://huozi.8wss.com)]
+ - 活字3.0为一个稀疏混合专家模型,支持32K上下文,具有丰富的中、英文知识和强大的数学推理、代码生成能力。活字3.0较旧版活字具有更强的指令遵循能力和安全性。
+- **中文MT-Bench**: [[数据集](data/mt-bench-zh/)]
+ - 本数据集是英文MT-Bench对话能力评测数据集的中文版。它包含了一系列多轮对话问题,每一组问题都经过了精心的人工校对,并为适应中文语境进行了必要的调整。
+- **《ChatGPT 调研报告》**: [[PDF](https://github.com/HIT-SCIR/huozi/blob/main/pdf/chatgpt_book.pdf)]
+ - 哈工大自然语言处理研究所组织多位老师和同学撰写了本调研报告,从技术原理、应用场景、未来发展等方面对ChatGPT进行了尽量详尽的介绍及总结。
+- **活字 2.0**: [[模型权重](https://huggingface.co/HIT-SCIR/huozi-7b-rlhf)] [[RLHF数据](data/huozi-rlhf/huozi_rlhf_data.csv)]
+ - 在活字1.0基础上,通过人类反馈的强化学习(RLHF)进一步优化了模型回复质量,使其更加符合人类偏好。相较于上一个版本平均长度明显提高,遵从指令的能力更强,逻辑更加清晰。
+ - 16.9k 人工标注的偏好数据,回复来自活字模型,可以用于训练奖励模型。
+- **活字 1.0**: [[模型权重](https://huggingface.co/HIT-SCIR/huozi-7b-sft)]
+ - 在Bloom模型的基础上,在大约 150 亿 tokens 上进行指令微调训练得到的模型,具有更强的指令遵循能力、更好的安全性。
+
+## 💡 模型介绍
+
+大规模语言模型(LLM)在自然语言处理领域取得了显著的进展,并在广泛的应用场景中展现了其强大的潜力。这一技术不仅吸引了学术界的广泛关注,也成为了工业界的热点。在此背景下,哈尔滨工业大学社会计算与信息检索研究中心(HIT-SCIR)近期推出了最新成果——**活字3.0**,致力于为自然语言处理的研究和实际应用提供更多可能性和选择。
+
+活字3.0是基于[Chinese-Mixtral-8x7B](https://github.com/HIT-SCIR/Chinese-Mixtral-8x7B),在大约30万行指令数据上微调得到的模型。该模型支持**32K上下文**,能够有效处理长文本。活字3.0继承了基座模型丰富的**中英文知识**,并在**数学推理**、**代码生成**等任务上具有强大性能。经过指令微调,活字3.0还在**指令遵循能力**和**安全性**方面实现了显著提升。
+
+此外,我们开源了**中文MT-Bench数据集**。这是一个中文开放问题集,包括80组对话任务,用于评估模型的多轮对话和指令遵循能力。该数据集是根据原始MT-Bench翻译得来的,每组问题均经过人工校对和中文语境下的适当调整。我们还对原始MT-Bench中的部分错误答案进行了修正。
+
+> [!IMPORTANT]
+> 活字系列模型仍然可能生成包含事实性错误的误导性回复或包含偏见/歧视的有害内容,请谨慎鉴别和使用生成的内容,请勿将生成的有害内容传播至互联网。
+
+> 活字1.0和活字2.0的文档请见[此处](README-v1v2.md)。
+
+### 模型结构
+
+活字3.0是一个稀疏混合专家模型(SMoE),使用了Mixtral-8x7B的模型结构。它区别于LLaMA、BLOOM等常见模型,该模型的每个前馈神经网络(FFN)层被替换为了“专家层”,该层包含8个FFN和一个“路由器”。这种设计使得模型在推理过程中,可以独立地将每个Token路由到最适合处理它的两个专家中。该模型共拥有46.7B个参数,但得益于其稀疏激活的特性,实际推理时仅需激活13B参数,有效提升了计算效率和处理速度。
+
+![](image/smoe.png)
+
+### 训练过程
+
+由于Mixtral-8x7B词表不支持中文,因此对中文的编解码效率较低,限制了中文场景下的实用性。我们首先基于Mixtral-8x7B进行了中文扩词表增量预训练,显著提高了模型对中文的编解码效率,并使模型具备了强大的中文生成和理解能力。这项成果名为[Chinese-Mixtral-8x7B](https://github.com/HIT-SCIR/Chinese-Mixtral-8x7B),我们已于2024年1月18日开源了其模型权重和训练代码。基于此,我们进一步对模型进行指令微调,最终推出了活字3.0。这一版本的中文编码、指令遵循、安全回复等能力都有显著提升。
+
+## 📥 模型下载
+
+|模型名称|文件大小|下载地址|备注|
+|:---:|:---:|:---:|:---:|
+|huozi3|88GB|[🤗HuggingFace](https://huggingface.co/HIT-SCIR/huozi3)
[ModelScope](https://modelscope.cn/models/HIT-SCIR/huozi3/summary)|活字3.0 完整模型|
+|huozi3-gguf|25GB|[🤗HuggingFace](https://huggingface.co/HIT-SCIR/huozi3-gguf)
[ModelScope](https://modelscope.cn/models/HIT-SCIR/huozi3-gguf/summary)|活字3.0 GGUF版本,适用于llama.cpp等推理框架|
+|huozi3-awq|24GB|[🤗HuggingFace](https://huggingface.co/HIT-SCIR/huozi3-awq)
[ModelScope](https://modelscope.cn/models/HIT-SCIR/huozi3-awq/summary)|活字3.0 AWQ版本,适用于AutoAWQ等推理框架|
+
+如果您希望微调活字3.0或Chinese-Mixtral-8x7B,请参考[此处训练代码](https://github.com/HIT-SCIR/Chinese-Mixtral-8x7B?tab=readme-ov-file#%E5%BE%AE%E8%B0%83)。
+
+## 💻 模型推理
+
+### Quick Start
+
+活字3.0采用ChatML格式的prompt模板,格式为:
+```
+<|beginofutterance|>系统
+{system prompt}<|endofutterance|>
+<|beginofutterance|>用户
+{input}<|endofutterance|>
+<|beginofutterance|>助手
+{output}<|endofutterance|>
+```
+
+使用活字3.0进行推理的示例代码如下:
+```python
+# quickstart.py
+
+import torch
+from transformers import AutoModelForCausalLM, AutoTokenizer
+
+model_id = "HIT-SCIR/huozi3"
+
+tokenizer = AutoTokenizer.from_pretrained(model_id)
+model = AutoModelForCausalLM.from_pretrained(
+ model_id,
+ attn_implementation="flash_attention_2",
+ torch_dtype=torch.bfloat16,
+ device_map="auto",
+)
+
+text = """<|beginofutterance|>系统
+你是一个智能助手<|endofutterance|>
+<|beginofutterance|>用户
+请你用python写一段快速排序的代码<|endofutterance|>
+<|beginofutterance|>助手
+"""
+
+inputs = tokenizer(text, return_tensors="pt").to(0)
+
+outputs = model.generate(
+ **inputs,
+ eos_token_id=57001,
+ temperature=0.8,
+ top_p=0.9,
+ max_new_tokens=2048,
+)
+print(tokenizer.decode(outputs[0], skip_special_tokens=False))
+```
+
+活字3.0支持全部Mixtral模型生态,包括Transformers、vLLM、llama.cpp、AutoAWQ、Text generation web UI等框架。
+
+如果您在下载模型时遇到网络问题,可以使用我们在[ModelScope](#modelscope-模型推理)上提供的检查点。
+
+
+
+
+#### Transformers 模型推理 + 流式生成
+
+
+
+transformers支持为tokenizer添加聊天模板,并支持流式生成。示例代码如下:
+```python
+# example/transformers-stream/stream.py
+
+import torch
+from transformers import AutoModelForCausalLM, AutoTokenizer, TextStreamer
+
+model_id = "HIT-SCIR/huozi3"
+
+model = AutoModelForCausalLM.from_pretrained(
+ model_id,
+ attn_implementation="flash_attention_2",
+ torch_dtype=torch.bfloat16,
+ device_map="auto",
+)
+
+tokenizer = AutoTokenizer.from_pretrained(model_id)
+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 %}
+{% if add_generation_prompt and messages[-1]['role'] != '助手' %}{{ '<|beginofutterance|>助手\n' }}{% endif %}"""
+
+chat = [
+ {"role": "系统", "content": "你是一个智能助手"},
+ {"role": "用户", "content": "请你用python写一段快速排序的代码"},
+]
+
+inputs = tokenizer.apply_chat_template(
+ chat,
+ tokenize=True,
+ add_generation_prompt=True,
+ return_tensors="pt",
+).to(0)
+
+stream_output = model.generate(
+ inputs,
+ streamer=TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True),
+ eos_token_id=57001,
+ temperature=0.8,
+ top_p=0.9,
+ max_new_tokens=2048,
+)
+```
+
+
+
+
+
+
+#### ModelScope 模型推理
+
+
+
+ModelScope的接口与Transformers非常相似,只需将transformers替换为modelscope即可:
+```diff
+# example/modelscope-generate/generate.py
+
+import torch
+- from transformers import AutoModelForCausalLM, AutoTokenizer
++ from modelscope import AutoTokenizer, AutoModelForCausalLM
+
+model_id = "HIT-SCIR/huozi3"
+
+tokenizer = AutoTokenizer.from_pretrained(model_id)
+model = AutoModelForCausalLM.from_pretrained(
+ model_id,
+ attn_implementation="flash_attention_2",
+ torch_dtype=torch.bfloat16,
+ device_map="auto",
+)
+
+text = """<|beginofutterance|>系统
+你是一个智能助手<|endofutterance|>
+<|beginofutterance|>用户
+请你用python写一段快速排序的代码<|endofutterance|>
+<|beginofutterance|>助手
+"""
+
+inputs = tokenizer(text, return_tensors="pt").to(0)
+
+outputs = model.generate(
+ **inputs,
+ eos_token_id=57001,
+ temperature=0.8,
+ top_p=0.9,
+ max_new_tokens=2048,
+)
+print(tokenizer.decode(outputs[0], skip_special_tokens=False))
+```
+
+
+
+
+
+
+#### vLLM 推理加速
+
+
+
+活字3.0支持通过vLLM实现推理加速,示例代码如下:
+```python
+# example/vllm-generate/generate.py
+
+from vllm import LLM, SamplingParams
+
+prompts = [
+ """<|beginofutterance|>系统
+你是一个智能助手<|endofutterance|>
+<|beginofutterance|>用户
+请你用python写一段快速排序的代码<|endofutterance|>
+<|beginofutterance|>助手
+""",
+]
+
+sampling_params = SamplingParams(
+ temperature=0.8, top_p=0.95, stop_token_ids=[57001], max_tokens=2048
+)
+llm = LLM(
+ model="HIT-SCIR/huozi3",
+ tensor_parallel_size=4,
+)
+outputs = llm.generate(prompts, sampling_params)
+
+for output in outputs:
+ prompt = output.prompt
+ generated_text = output.outputs[0].text
+ print(generated_text)
+```
+
+
+
+
+
+
+#### 部署 OpenAI API Server
+
+
+
+活字3.0可以部署为支持OpenAI API协议的服务,这使得活字3.0可以直接通过OpenAI API进行调用。
+
+环境准备:
+```shell
+$ pip install vllm openai
+```
+
+启动服务:
+```shell
+$ 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
+```
+
+使用OpenAI API发送请求:
+```python
+# example/openai-api/openai-client.py
+
+from openai import OpenAI
+
+openai_api_key = "EMPTY"
+openai_api_base = "http://localhost:8000/v1"
+
+client = OpenAI(
+ api_key=openai_api_key,
+ base_url=openai_api_base,
+)
+
+chat_response = client.chat.completions.create(
+ model="huozi",
+ messages=[
+ {"role": "系统", "content": "你是一个智能助手"},
+ {"role": "用户", "content": "请你用python写一段快速排序的代码"},
+ ],
+ extra_body={"stop_token_ids": [57001]},
+)
+print("Chat response:", chat_response.choices[0].message.content)
+```
+
+下面是一个使用OpenAI API + Gradio + 流式生成的示例代码:
+```python
+# example/openai-api/openai-client-gradio.py
+
+from openai import OpenAI
+import gradio as gr
+
+openai_api_key = "EMPTY"
+openai_api_base = "http://localhost:8000/v1"
+
+client = OpenAI(
+ api_key=openai_api_key,
+ base_url=openai_api_base,
+)
+
+
+def predict(message, history):
+ history_openai_format = [
+ {"role": "系统", "content": "你是一个智能助手"},
+ ]
+ for human, assistant in history:
+ history_openai_format.append({"role": "用户", "content": human})
+ history_openai_format.append({"role": "助手", "content": assistant})
+ history_openai_format.append({"role": "用户", "content": message})
+ models = client.models.list()
+
+ stream = client.chat.completions.create(
+ model=models.data[0].id,
+ messages=history_openai_format,
+ temperature=0.8,
+ stream=True,
+ extra_body={"repetition_penalty": 1, "stop_token_ids": [57001]},
+ )
+
+ partial_message = ""
+ for chunk in stream:
+ partial_message += chunk.choices[0].delta.content or ""
+ yield partial_message
+
+
+gr.ChatInterface(predict).queue().launch()
+```
+
+
+
+### 量化推理
+
+活字3.0支持量化推理,下表为活字3.0在各个量化框架下显存占用量:
+
+|量化方法|显存占用|
+|:---:|:---:|
+|无|95GB|
+|AWQ|32GB|
+|GGUF(q4_0)|28GB|
+|GGUF(q2_k)|18GB|
+|GGUF(q2_k, offload 16层)|9.6GB|
+
+
+
+
+#### GGUF 格式
+
+
+
+GGUF格式旨在快速加载和保存模型,由llama.cpp团队推出。我们已经提供了[GGUF格式的活字3.0](https://huggingface.co/HIT-SCIR/huozi3-gguf)。
+
+您也可以手动将HuggingFace格式的活字3.0转换到GGUF格式,以使用其他的量化方法。
+
+##### Step 1 环境准备
+
+首先需要下载llama.cpp的源码。我们在仓库中提供了llama.cpp的submodule,这个版本的llama.cpp已经过测试,可以成功进行推理:
+```shell
+$ git clone --recurse-submodules https://github.com/HIT-SCIR/huozi
+$ cd examples/llama.cpp
+```
+
+您也可以下载最新版本的llama.cpp源码:
+```shell
+$ git clone https://github.com/ggerganov/llama.cpp.git
+$ cd llama.cpp
+```
+
+然后需要进行编译。根据您的硬件平台,编译命令有细微差异:
+```shell
+$ make # 用于纯CPU推理
+$ make LLAMA_CUBLAS=1 # 用于GPU推理
+$ LLAMA_METAL=1 make # 用于Apple Silicon,暂未经过测试
+```
+
+##### Step 2 格式转换(可选)
+
+以下命令需要在`llama.cpp/`目录下:
+```shell
+# 转换为GGUF格式
+$ python convert.py --outfile /path/to/huozi-gguf/huozi3.gguf /path/to/huozi3
+# 进行GGUF格式的q4_0量化
+$ quantize /path/to/huozi-gguf/huozi3.gguf /path/to/huozi-gguf/huozi3-q4_0.gguf q4_0
+```
+
+##### Step 3 开始推理
+
+以下命令需要在`llama.cpp/`目录下:
+```shell
+$ 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|>"
+```
+
+`-ngl`参数表示向GPU中offload的层数,降低这个值可以缓解GPU显存压力。经过我们的实际测试,q2_k量化的模型offload 16层,显存占用可降低至9.6GB,可在消费级GPU上运行模型:
+```shell
+$ 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|>"
+```
+
+关于`main`的更多参数,可以参考llama.cpp的[官方文档](https://github.com/ggerganov/llama.cpp/tree/master/examples/main)。
+
+
+
+
+
+
+#### AWQ 格式
+
+
+
+AWQ是一种量化模型的存储格式。我们已经提供了[AWQ格式的活字3.0](https://huggingface.co/HIT-SCIR/huozi3-awq),您也可以手动将HuggingFace格式的活字3.0转换到AWQ格式。
+
+##### Step 1 格式转换(可选)
+
+```python
+# example/autoawq-generate/quant.py
+
+from awq import AutoAWQForCausalLM
+from transformers import AutoTokenizer
+
+model_path = "/path/to/huozi3"
+quant_path = "/path/to/save/huozi3-awq"
+modules_to_not_convert = ["gate"]
+quant_config = {
+ "zero_point": True,
+ "q_group_size": 128,
+ "w_bit": 4,
+ "version": "GEMM",
+ "modules_to_not_convert": modules_to_not_convert,
+}
+
+model = AutoAWQForCausalLM.from_pretrained(
+ model_path,
+ safetensors=True,
+ **{"low_cpu_mem_usage": True},
+)
+tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
+
+model.quantize(
+ tokenizer,
+ quant_config=quant_config,
+ modules_to_not_convert=modules_to_not_convert,
+)
+
+model.save_quantized(quant_path)
+tokenizer.save_pretrained(quant_path)
+
+print(f'Model is quantized and saved at "{quant_path}"')
+```
+
+##### Step 2 开始推理
+
+在获取到AWQ格式的模型权重后,可以使用AutoAWQForCausalLM代替AutoModelForCausalLM加载模型。示例代码如下:
+```diff
+# example/autoawq-generate/generate.py
+
+import torch
++ from awq import AutoAWQForCausalLM
+from transformers import AutoTokenizer, TextStreamer
+
+
+- model_id = "HIT-SCIR/huozi3"
++ model_id = "HIT-SCIR/huozi3-awq" # or model_id = "/path/to/saved/huozi3-awq"
+
++ model = AutoAWQForCausalLM.from_quantized(model_id, fuse_layers=True)
+- model = AutoModelForCausalLM.from_pretrained(
+- model_id,
+- attn_implementation="flash_attention_2",
+- torch_dtype=torch.bfloat16,
+- device_map="auto",
+- )
+
+tokenizer = AutoTokenizer.from_pretrained(model_id)
+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 %}
+{% if add_generation_prompt and messages[-1]['role'] != '助手' %}{{ '<|beginofutterance|>助手\n' }}{% endif %}"""
+
+chat = [
+ {"role": "系统", "content": "你是一个智能助手"},
+ {"role": "用户", "content": "请你用python写一段快速排序的代码"},
+]
+
+inputs = tokenizer.apply_chat_template(
+ chat,
+ tokenize=True,
+ add_generation_prompt=True,
+ return_tensors="pt",
+).to(0)
+
+stream_output = model.generate(
+ inputs,
+ streamer=TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True),
+ eos_token_id=57001,
+ temperature=0.8,
+ top_p=0.9,
+ max_new_tokens=2048,
+)
+```
+
+
+
+## 📈 模型性能
+
+![](image/metric-v3-h.png)
+
+针对大模型综合能力评价,我们分别使用以下评测数据集对活字3.0进行评测:
+- C-Eval:一个全面的中文基础模型评估套件。它包含了13948个多项选择题,涵盖了52个不同的学科和四个难度级别。
+- CMMLU:一个综合性的中文评估基准,专门用于评估语言模型在中文语境下的知识和推理能力,涵盖了从基础学科到高级专业水平的67个主题。
+- GAOKAO:一个以中国高考题目为数据集,旨在提供和人类对齐的,直观,高效地测评大模型语言理解能力、逻辑推理能力的测评框架。
+- MMLU:一个包含57个多选任务的英文评测数据集,涵盖了初等数学、美国历史、计算机科学、法律等,难度覆盖高中水平到专家水平,是目前主流的LLM评测数据集之一。
+- HellaSwag:一个极具挑战的英文NLI评测数据集,每一个问题都需要对上下文进行深入理解,而不能基于常识进行回答。
+- GSM8K:一个高质量的小学数学应用题的数据集,这些问题需要 2 到 8 个步骤来解决,解决方案主要涉及使用基本算术运算,可用于评价多步数学推理能力。
+- HumanEval:一个由 164 个原创编程问题组成的数据集,通过衡量从文档字符串生成程序的功能正确性,来够评估语言理解、算法和简单的数学能力。
+- MT-Bench:一个开放的英文问题集,包括80个多轮对话任务,用于评估聊天机器人的多轮对话和指令遵循能力,并通过大模型裁判(GPT-4)对模型回答进行打分。
+- MT-Bench-zh:我们根据MT-Bench翻译得来的中文问题集,每组问题均经过人工校对和中文语境下的适当调整。我们已在[此处](data/mt-bench-zh/)开源MT-Bench-zh数据集。
+- MT-Bench-safety:我们手工构造的安全数据集,包括暴力、色情、敏感等风险内容。该数据集为封闭数据集。
+
+活字3.0在推理时仅激活13B参数。下表为活字3.0与其他13B规模的中文模型以及旧版活字在各个评测数据集上的结果:
+
+
+![](image/evaluation-v3.png)
+
+> 我们在C-Eval、CMMLU、MMLU采用5-shot,GSM8K采用4-shot,HellaSwag、HumanEval采用0-shot,HumanEval采用pass@1指标。所有测试均采用greedy策略。
+>
+> 我们使用OpenCompass作为评测框架,commit hash为[4c87e77](https://github.com/open-compass/opencompass/tree/4c87e777d855636b9eda7ec87bcbbf12b62caed3)。评测代码位于[此处](./evaluate/)。
+
+根据上表中的测试结果,活字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模型。
+
+## 🗂 生成样例
+
+下面是活字3.0在MT-Bench-zh评测集上的生成效果展示,并与活字2.0(RLHF版本)进行对比:
+
+![](image/examples/v3-case1.png)
+![](image/examples/v3-case2.png)
+![](image/examples/v3-case3.png)
+![](image/examples/v3-case4.png)
+![](image/examples/v3-case5.png)
+
+## 开源协议
+对本仓库源码的使用遵循开源许可协议 [Apache 2.0](https://github.com/HIT-SCIR/huozi/blob/main/LICENSE)。
+
+活字支持商用。如果将活字模型或其衍生品用作商业用途,请您按照如下方式联系许可方,以进行登记并向许可方申请书面授权:联系邮箱:。
+
+## Citation
+
+### 活字大模型
+
+```latex
+@misc{huozi,
+ author = {Huozi-Team}.
+ title = {Huozi: Leveraging Large Language Models for Enhanced Open-Domain Chatting}
+ year = {2024},
+ publisher = {GitHub},
+ journal = {GitHub repository}
+ howpublished = {\url{https://github.com/HIT-SCIR/huozi}}
+}
+```
+
+## Star History
+
+[![Star History Chart](https://api.star-history.com/svg?repos=HIT-SCIR/huozi&type=Date)](https://star-history.com/#HIT-SCIR/huozi&Date)
diff --git a/README.md b/README.md
index 39883a2..a6291c0 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,8 @@
## 🎉 更新
-- [2024-02-09] 发布活字3.0版本和中文MT-Bench数据集
+- [2024-09-12] 发布活字3.5版本
+- [2024-02-09] 发布活字3.5版本和中文MT-Bench数据集
- [2023-08-06] 发布活字1.0和活字2.0版本
- [2023-05-04] 发布《ChatGPT调研报告》;内测活字大模型
@@ -36,12 +37,15 @@
|[💁🏻♂ 开源清单](#-开源清单)|本仓库开源项目清单|
|[💡 模型介绍](#-模型介绍)|简要介绍活字模型结构和训练过程|
|[📥 模型下载](#-模型下载)|活字模型下载链接|
-|[💻 模型推理](#-模型推理)|活字模型推理样例,包括vLLM推理加速、llama.cpp量化推理等框架的使用流程|
+|[💻 模型推理](#-模型推理)|活字模型推理样例,包括vLLM、llama.cpp、Ollama等推理框架的使用流程|
|[📈 模型性能](#-模型性能)|活字模型在主流评测任务上的性能|
|[🗂 生成样例](#-生成样例)|活字模型实际生成效果样例|
## 💁🏻♂ 开源清单
-![](image/models-v3.png)
+![](image/models-v3.5.png)
+
+- **活字 3.5**: [[模型权重](#-模型下载)]
+ - 活字3.5为基于活字3.0和Chinese-Mixtral-8x7B进行进一步性能优化的新模型。
- **活字 3.0**: [[模型权重](#-模型下载)] [[在线Demo](https://huozi.8wss.com)]
- 活字3.0为一个稀疏混合专家模型,支持32K上下文,具有丰富的中、英文知识和强大的数学推理、代码生成能力。活字3.0较旧版活字具有更强的指令遵循能力和安全性。
- **中文MT-Bench**: [[数据集](data/mt-bench-zh/)]
@@ -56,42 +60,55 @@
## 💡 模型介绍
-大规模语言模型(LLM)在自然语言处理领域取得了显著的进展,并在广泛的应用场景中展现了其强大的潜力。这一技术不仅吸引了学术界的广泛关注,也成为了工业界的热点。在此背景下,哈尔滨工业大学社会计算与信息检索研究中心(HIT-SCIR)近期推出了最新成果——**活字3.0**,致力于为自然语言处理的研究和实际应用提供更多可能性和选择。
+大规模语言模型(LLM)在自然语言处理领域取得了显著的进展,并在广泛的应用场景中展现了其强大的潜力。这一技术不仅吸引了学术界的广泛关注,也成为了工业界的热点。在此背景下,哈尔滨工业大学社会计算与信息检索研究中心(HIT-SCIR)近期推出了最新成果——**活字3.5**,致力于为自然语言处理的研究和实际应用提供更多可能性和选择。
-活字3.0是基于[Chinese-Mixtral-8x7B](https://github.com/HIT-SCIR/Chinese-Mixtral-8x7B),在大约30万行指令数据上微调得到的模型。该模型支持**32K上下文**,能够有效处理长文本。活字3.0继承了基座模型丰富的**中英文知识**,并在**数学推理**、**代码生成**等任务上具有强大性能。经过指令微调,活字3.0还在**指令遵循能力**和**安全性**方面实现了显著提升。
-
-此外,我们开源了**中文MT-Bench数据集**。这是一个中文开放问题集,包括80组对话任务,用于评估模型的多轮对话和指令遵循能力。该数据集是根据原始MT-Bench翻译得来的,每组问题均经过人工校对和中文语境下的适当调整。我们还对原始MT-Bench中的部分错误答案进行了修正。
+活字3.5是在[活字3.0](https://github.com/HIT-SCIR/huozi/README-v3.md)和[Chinese-Mixtral-8x7B](https://github.com/HIT-SCIR/Chinese-Mixtral-8x7B)基础上,进行进一步性能增强得到的模型。活字3.5支持**32K长上下文**,继承了活字3.0强大的综合能力,并在**中英文知识**、**数学推理**、**代码生成**、**指令遵循能力**、**内容安全性**等诸多方面实现了性能提升。
> [!IMPORTANT]
> 活字系列模型仍然可能生成包含事实性错误的误导性回复或包含偏见/歧视的有害内容,请谨慎鉴别和使用生成的内容,请勿将生成的有害内容传播至互联网。
> 活字1.0和活字2.0的文档请见[此处](README-v1v2.md)。
+> 活字3.0和中文MT-Bench的文档请见[此处](README-v3.md)。
### 模型结构
-活字3.0是一个稀疏混合专家模型(SMoE),使用了Mixtral-8x7B的模型结构。它区别于LLaMA、BLOOM等常见模型,该模型的每个前馈神经网络(FFN)层被替换为了“专家层”,该层包含8个FFN和一个“路由器”。这种设计使得模型在推理过程中,可以独立地将每个Token路由到最适合处理它的两个专家中。该模型共拥有46.7B个参数,但得益于其稀疏激活的特性,实际推理时仅需激活13B参数,有效提升了计算效率和处理速度。
+活字3.5是一个稀疏混合专家模型(SMoE),每个专家层包含8个FFN,每次前向计算采用top-2稀疏激活。活字3.5共拥有46.7B参数,得益于其稀疏激活的特性,实际推理时仅需激活13B参数,有效提升了计算效率和处理速度。
-![](image/smoe.png)
+
+
+
+
### 训练过程
-由于Mixtral-8x7B词表不支持中文,因此对中文的编解码效率较低,限制了中文场景下的实用性。我们首先基于Mixtral-8x7B进行了中文扩词表增量预训练,显著提高了模型对中文的编解码效率,并使模型具备了强大的中文生成和理解能力。这项成果名为[Chinese-Mixtral-8x7B](https://github.com/HIT-SCIR/Chinese-Mixtral-8x7B),我们已于2024年1月18日开源了其模型权重和训练代码。基于此,我们进一步对模型进行指令微调,最终推出了活字3.0。这一版本的中文编码、指令遵循、安全回复等能力都有显著提升。
+活字3.5经过了多步训练,如下图所示:
+
+![](image/train-process-v3.5.png)
+
+其训练过程为:
+1. 【中文扩词表增量预训练】: 由于Mixtral-8x7B词表不支持中文,因此对中文的编解码效率较低,限制了中文场景下的实用性。我们首先基于Mixtral-8x7B进行了中文扩词表增量预训练,显著提高了模型对中文的编解码效率,并使模型具备了强大的中文生成和理解能力。我们已于[Chinese-Mixtral-8x7B代码仓库](https://github.com/HIT-SCIR/Chinese-Mixtral-8x7B)开源了模型权重和训练代码。
+2. 【活字3.0训练】:我们基于Chinese-Mixtral-8x7B在大约30万行指令数据上进行微调,得到了活字3.0模型,使用的数据集见[此处说明](https://github.com/HIT-SCIR/huozi/issues/11#issuecomment-1973113428)。活字3.0继承了基座模型丰富的中英文知识,并在数学推理、代码生成等任务上具有强大性能。经过指令微调,活字3.0还在指令遵循能力和安全性方面实现了显著提升。
+3. 【活字1.0数据集微调】:我们尝试使用活字1.0数据集对Chinese-Mixtral-8x7B进行指令微调,得到的*中间检查点 1*在中英文知识(如 C-Eval、CMMLU、MMLU 等任务)方面表现优异,甚至超过了活字3.0。然而,该模型在指令遵循能力和安全性上落后活字3.0较多。
+4. 【指令遵循能力强化】:针对*中间检查点 1*在指令遵循能力上的不足,我们引入了额外的数据集进行强化。此外,根据[Longxu Dou等人的经验](https://arxiv.org/pdf/2404.03608),我们在训练过程中使用了[BPE Dropout](https://aclanthology.org/2020.acl-main.170/)技术,以进一步增加模型对指令的鲁棒性。该过程训练得到了*中间检查点 2*。
+5. 【模型融合】:我们参考[Yiming Cui等人的方法](https://github.com/ymcui/Chinese-LLaMA-Alpaca-3),对*中间检查点 1*、*中间检查点 2*以及活字3.0模型进行融合,生成了*中间检查点 3*。
+6. 【模型融合后训练】:在融合后的模型基础上,我们进一步进行了指令微调,最终推出了活字3.5。该版本在中英文知识、指令遵循能力和安全性回复等方面均有提升。
## 📥 模型下载
|模型名称|文件大小|下载地址|备注|
|:---:|:---:|:---:|:---:|
-|huozi3|88GB|[🤗HuggingFace](https://huggingface.co/HIT-SCIR/huozi3)
[ModelScope](https://modelscope.cn/models/HIT-SCIR/huozi3/summary)|活字3.0 完整模型|
-|huozi3-gguf|25GB|[🤗HuggingFace](https://huggingface.co/HIT-SCIR/huozi3-gguf)
[ModelScope](https://modelscope.cn/models/HIT-SCIR/huozi3-gguf/summary)|活字3.0 GGUF版本,适用于llama.cpp等推理框架|
-|huozi3-awq|24GB|[🤗HuggingFace](https://huggingface.co/HIT-SCIR/huozi3-awq)
[ModelScope](https://modelscope.cn/models/HIT-SCIR/huozi3-awq/summary)|活字3.0 AWQ版本,适用于AutoAWQ等推理框架|
+|huozi3.5|88GB|[🤗HuggingFace](https://huggingface.co/HIT-SCIR/huozi3.5)
[ModelScope](https://modelscope.cn/models/HIT-SCIR/huozi3.5/summary)|活字3.5 完整模型|
+|huozi3.5-ckpt-1|88GB|[🤗HuggingFace](https://huggingface.co/HIT-SCIR/huozi3.5-ckpt-1)
[ModelScope](https://modelscope.cn/models/HIT-SCIR/huozi3.5-ckpt-1/summary)|活字3.5 中间检查点 1|
+|huozi3.5-ckpt-2|88GB|[🤗HuggingFace](https://huggingface.co/HIT-SCIR/huozi3.5-ckpt-2)
[ModelScope](https://modelscope.cn/models/HIT-SCIR/huozi3.5-ckpt-2/summary)|活字3.5 中间检查点 2|
+|huozi3.5-ckpt-3|88GB|[🤗HuggingFace](https://huggingface.co/HIT-SCIR/huozi3.5-ckpt-3)
[ModelScope](https://modelscope.cn/models/HIT-SCIR/huozi3.5-ckpt-3/summary)|活字3.5 中间检查点 3|
-如果您希望微调活字3.0或Chinese-Mixtral-8x7B,请参考[此处训练代码](https://github.com/HIT-SCIR/Chinese-Mixtral-8x7B?tab=readme-ov-file#%E5%BE%AE%E8%B0%83)。
+如果您希望微调活字3.5或Chinese-Mixtral-8x7B,请参考[此处训练代码](https://github.com/HIT-SCIR/Chinese-Mixtral-8x7B?tab=readme-ov-file#%E5%BE%AE%E8%B0%83)。
## 💻 模型推理
### Quick Start
-活字3.0采用ChatML格式的prompt模板,格式为:
+活字3.5采用ChatML格式的prompt模板,格式为:
```
<|beginofutterance|>系统
{system prompt}<|endofutterance|>
@@ -101,14 +118,14 @@
{output}<|endofutterance|>
```
-使用活字3.0进行推理的示例代码如下:
+使用活字3.5进行推理的示例代码如下:
```python
# quickstart.py
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
-model_id = "HIT-SCIR/huozi3"
+model_id = "HIT-SCIR/huozi3.5"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
@@ -137,7 +154,7 @@ outputs = model.generate(
print(tokenizer.decode(outputs[0], skip_special_tokens=False))
```
-活字3.0支持全部Mixtral模型生态,包括Transformers、vLLM、llama.cpp、AutoAWQ、Text generation web UI等框架。
+活字3.5支持全部Mixtral模型生态,包括Transformers、vLLM、llama.cpp、Ollama、Text generation web UI等框架。
如果您在下载模型时遇到网络问题,可以使用我们在[ModelScope](#modelscope-模型推理)上提供的检查点。
@@ -155,7 +172,7 @@ transformers支持为tokenizer添加聊天模板,并支持流式生成。示
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, TextStreamer
-model_id = "HIT-SCIR/huozi3"
+model_id = "HIT-SCIR/huozi3.5"
model = AutoModelForCausalLM.from_pretrained(
model_id,
@@ -207,7 +224,7 @@ import torch
- from transformers import AutoModelForCausalLM, AutoTokenizer
+ from modelscope import AutoTokenizer, AutoModelForCausalLM
-model_id = "HIT-SCIR/huozi3"
+model_id = "HIT-SCIR/huozi3.5"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
@@ -245,7 +262,7 @@ print(tokenizer.decode(outputs[0], skip_special_tokens=False))
-活字3.0支持通过vLLM实现推理加速,示例代码如下:
+活字3.5支持通过vLLM实现推理加速,示例代码如下:
```python
# example/vllm-generate/generate.py
@@ -264,7 +281,7 @@ sampling_params = SamplingParams(
temperature=0.8, top_p=0.95, stop_token_ids=[57001], max_tokens=2048
)
llm = LLM(
- model="HIT-SCIR/huozi3",
+ model="HIT-SCIR/huozi3.5",
tensor_parallel_size=4,
)
outputs = llm.generate(prompts, sampling_params)
@@ -284,7 +301,7 @@ for output in outputs:
-活字3.0可以部署为支持OpenAI API协议的服务,这使得活字3.0可以直接通过OpenAI API进行调用。
+活字3.5可以部署为支持OpenAI API协议的服务,这使得活字3.5可以直接通过OpenAI API进行调用。
环境准备:
```shell
@@ -293,7 +310,7 @@ $ pip install vllm openai
启动服务:
```shell
-$ 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
+$ python -m vllm.entrypoints.openai.api_server --model /path/to/huozi3.5/checkpoint --served-model-name huozi --chat-template template.jinja --tensor-parallel-size 8 --response-role 助手 --max-model-len 2048
```
使用OpenAI API发送请求:
@@ -368,16 +385,6 @@ gr.ChatInterface(predict).queue().launch()
### 量化推理
-活字3.0支持量化推理,下表为活字3.0在各个量化框架下显存占用量:
-
-|量化方法|显存占用|
-|:---:|:---:|
-|无|95GB|
-|AWQ|32GB|
-|GGUF(q4_0)|28GB|
-|GGUF(q2_k)|18GB|
-|GGUF(q2_k, offload 16层)|9.6GB|
-
@@ -385,9 +392,7 @@ gr.ChatInterface(predict).queue().launch()
-GGUF格式旨在快速加载和保存模型,由llama.cpp团队推出。我们已经提供了[GGUF格式的活字3.0](https://huggingface.co/HIT-SCIR/huozi3-gguf)。
-
-您也可以手动将HuggingFace格式的活字3.0转换到GGUF格式,以使用其他的量化方法。
+GGUF格式旨在快速加载和保存模型,由llama.cpp团队推出,适用于llama.cpp、Ollama等框架。您可以手动将HuggingFace格式的活字3.5转换到GGUF格式。
##### Step 1 环境准备
@@ -415,129 +420,34 @@ $ LLAMA_METAL=1 make # 用于Apple Silicon,暂未经过测试
以下命令需要在`llama.cpp/`目录下:
```shell
# 转换为GGUF格式
-$ python convert.py --outfile /path/to/huozi-gguf/huozi3.gguf /path/to/huozi3
+$ python convert.py --outfile /path/to/huozi-gguf/huozi3.5.gguf /path/to/huozi3.5
# 进行GGUF格式的q4_0量化
-$ quantize /path/to/huozi-gguf/huozi3.gguf /path/to/huozi-gguf/huozi3-q4_0.gguf q4_0
+$ quantize /path/to/huozi-gguf/huozi3.5.gguf /path/to/huozi-gguf/huozi3.5-q4_0.gguf q4_0
```
##### Step 3 开始推理
以下命令需要在`llama.cpp/`目录下:
```shell
-$ 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|>"
+$ main -m /path/to/huozi-gguf/huozi3.5-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|>"
```
`-ngl`参数表示向GPU中offload的层数,降低这个值可以缓解GPU显存压力。经过我们的实际测试,q2_k量化的模型offload 16层,显存占用可降低至9.6GB,可在消费级GPU上运行模型:
```shell
-$ 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|>"
+$ main -m /path/to/huozi-gguf/huozi3.5-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|>"
```
关于`main`的更多参数,可以参考llama.cpp的[官方文档](https://github.com/ggerganov/llama.cpp/tree/master/examples/main)。
-
-
-
-
-
-#### AWQ 格式
-
-
-
-AWQ是一种量化模型的存储格式。我们已经提供了[AWQ格式的活字3.0](https://huggingface.co/HIT-SCIR/huozi3-awq),您也可以手动将HuggingFace格式的活字3.0转换到AWQ格式。
-
-##### Step 1 格式转换(可选)
-
-```python
-# example/autoawq-generate/quant.py
-
-from awq import AutoAWQForCausalLM
-from transformers import AutoTokenizer
-
-model_path = "/path/to/huozi3"
-quant_path = "/path/to/save/huozi3-awq"
-modules_to_not_convert = ["gate"]
-quant_config = {
- "zero_point": True,
- "q_group_size": 128,
- "w_bit": 4,
- "version": "GEMM",
- "modules_to_not_convert": modules_to_not_convert,
-}
-
-model = AutoAWQForCausalLM.from_pretrained(
- model_path,
- safetensors=True,
- **{"low_cpu_mem_usage": True},
-)
-tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
-
-model.quantize(
- tokenizer,
- quant_config=quant_config,
- modules_to_not_convert=modules_to_not_convert,
-)
-
-model.save_quantized(quant_path)
-tokenizer.save_pretrained(quant_path)
-
-print(f'Model is quantized and saved at "{quant_path}"')
-```
-
-##### Step 2 开始推理
-
-在获取到AWQ格式的模型权重后,可以使用AutoAWQForCausalLM代替AutoModelForCausalLM加载模型。示例代码如下:
-```diff
-# example/autoawq-generate/generate.py
-
-import torch
-+ from awq import AutoAWQForCausalLM
-from transformers import AutoTokenizer, TextStreamer
-
-
-- model_id = "HIT-SCIR/huozi3"
-+ model_id = "HIT-SCIR/huozi3-awq" # or model_id = "/path/to/saved/huozi3-awq"
-
-+ model = AutoAWQForCausalLM.from_quantized(model_id, fuse_layers=True)
-- model = AutoModelForCausalLM.from_pretrained(
-- model_id,
-- attn_implementation="flash_attention_2",
-- torch_dtype=torch.bfloat16,
-- device_map="auto",
-- )
-
-tokenizer = AutoTokenizer.from_pretrained(model_id)
-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 %}
-{% if add_generation_prompt and messages[-1]['role'] != '助手' %}{{ '<|beginofutterance|>助手\n' }}{% endif %}"""
-
-chat = [
- {"role": "系统", "content": "你是一个智能助手"},
- {"role": "用户", "content": "请你用python写一段快速排序的代码"},
-]
-
-inputs = tokenizer.apply_chat_template(
- chat,
- tokenize=True,
- add_generation_prompt=True,
- return_tensors="pt",
-).to(0)
-
-stream_output = model.generate(
- inputs,
- streamer=TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True),
- eos_token_id=57001,
- temperature=0.8,
- top_p=0.9,
- max_new_tokens=2048,
-)
-```
+使用Ollama框架进行推理,可以参考Ollama的[README说明](https://github.com/ollama/ollama#import-from-gguf)。
## 📈 模型性能
-![](image/metric-v3-h.png)
+![](image/metric-v3.5-h.png)
-针对大模型综合能力评价,我们分别使用以下评测数据集对活字3.0进行评测:
+针对大模型综合能力评价,我们分别使用以下评测数据集对活字3.5进行评测:
- C-Eval:一个全面的中文基础模型评估套件。它包含了13948个多项选择题,涵盖了52个不同的学科和四个难度级别。
- CMMLU:一个综合性的中文评估基准,专门用于评估语言模型在中文语境下的知识和推理能力,涵盖了从基础学科到高级专业水平的67个主题。
- GAOKAO:一个以中国高考题目为数据集,旨在提供和人类对齐的,直观,高效地测评大模型语言理解能力、逻辑推理能力的测评框架。
@@ -549,34 +459,28 @@ stream_output = model.generate(
- MT-Bench-zh:我们根据MT-Bench翻译得来的中文问题集,每组问题均经过人工校对和中文语境下的适当调整。我们已在[此处](data/mt-bench-zh/)开源MT-Bench-zh数据集。
- MT-Bench-safety:我们手工构造的安全数据集,包括暴力、色情、敏感等风险内容。该数据集为封闭数据集。
-活字3.0在推理时仅激活13B参数。下表为活字3.0与其他13B规模的中文模型以及旧版活字在各个评测数据集上的结果:
+活字3.5在推理时仅激活13B参数。下表为活字3.5与其他13B规模的中文模型以及旧版活字在各个评测数据集上的结果:
-
-![](image/evaluation-v3.png)
+![](image/evaluation-v3.5.png)
> 我们在C-Eval、CMMLU、MMLU采用5-shot,GSM8K采用4-shot,HellaSwag、HumanEval采用0-shot,HumanEval采用pass@1指标。所有测试均采用greedy策略。
>
> 我们使用OpenCompass作为评测框架,commit hash为[4c87e77](https://github.com/open-compass/opencompass/tree/4c87e777d855636b9eda7ec87bcbbf12b62caed3)。评测代码位于[此处](./evaluate/)。
+>
+> 在活字3.0的性能评测中,我们在HumanEval错误使用了base模型的评测方法,正确的评测结果已在上表内更新。
-根据上表中的测试结果,活字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模型。
+根据上表中的测试结果,活字3.5较活字3.0取得了较稳定的性能提升,活字3.5的**中英文知识**、**数学推理**、**代码生成**、**中文指令遵循能力**、**中文内容安全性**等多方面能力均得到了加强。
## 🗂 生成样例
-下面是活字3.0在MT-Bench-zh评测集上的生成效果展示,并与活字2.0(RLHF版本)进行对比:
+下面是活字3.5在MT-Bench-zh评测集上的生成效果展示:
-![](image/examples/v3-case1.png)
-![](image/examples/v3-case2.png)
-![](image/examples/v3-case3.png)
-![](image/examples/v3-case4.png)
-![](image/examples/v3-case5.png)
+![](image/examples/v3.5-case1.png)
+![](image/examples/v3.5-case2.png)
+![](image/examples/v3.5-case3.png)
+![](image/examples/v3.5-case4.png)
+![](image/examples/v3.5-case5.png)
+![](image/examples/v3.5-case6.png)
## 开源协议
对本仓库源码的使用遵循开源许可协议 [Apache 2.0](https://github.com/HIT-SCIR/huozi/blob/main/LICENSE)。
diff --git a/data.md b/data.md
new file mode 100644
index 0000000..d4ecaac
--- /dev/null
+++ b/data.md
@@ -0,0 +1,11 @@
+132800:基于ckpt-35000训练,BPE Dropout 0.1
+表格名称:huozi3.5-bpedropout
+TRAIN_DATASETS=(
+ 1.00:post-gpt4-code
+ 1.00:post-huozi-identity
+ 1.00:post-llama-factory-identity
+ 1.00:post-scir-safe
+ 1.00:post-sharegpt
+ 1.00:skypile
+ 1.00:slimpajama
+)
\ No newline at end of file
diff --git a/image/evaluation-v3.5.png b/image/evaluation-v3.5.png
new file mode 100644
index 0000000000000000000000000000000000000000..2c22224c8d84dd3359242b5b0326eb71d7ddbc91
GIT binary patch
literal 263836
zcmeFZWmJ@3+cyj<1`-CHiU`t3HwGyTDKSG!w=_tp2#5$scbC8nIdmx!(jC$vIRa9`
z0K+_c{KtL0&-?AY{qnALvDR>&oOAZx$FYxJY(msj22=?&kye;Ewrgc_AtY?-Kay2Kc9>Vk(yaToW&SJYqzyW>w-Kh<^B
zg(!=eI@)uam^nT(=k~OJjyn&Ygr^u-wKsP)x#ekZ=inmdDarJE4>7Qg+swms>-R3M
zwvtS`5Vc#69i7c@332ms^D;>h-nw;5!r9D1OhZQQ@58}gl1x^vuFu7Icsx8jxIOr}
z9i1(C?u&|w^6>KU@bPhhJ-A%F99&I2xg1>X{B@Fl&Ld;)V(M)D+|}CA;TG<^CeIw*
zTqT*9a2NXb=db%T_q6_>D>=CQ{aD}ud2rwG+~?-y`S;x5Pzl^tF*R#Xb33SvwLN%e
z;2Ki*d3i-7ejo7v`s#l!`5%Ys{?DQOA_BbsdFX$9^?x6#tG~rrMRWe(T+;T{#qIHMeBp
z*V$rAO!VGz%F45yzlDc?`2pU!YcKIG{E5|9uxnJ82`C%ioJ7CgS-3uP=|`09UoYyVg7ApG?8&z|tYe-mo%J-j*R
zZmth+{^*10j+-t}pJSar_xaK?kyvGG8=1)CGCLer5i;uO~2
zdQ){;g_KrR3T?Ku5X|U6=Q{8(tjx3{37zs{qrjA)CWIyF<4!xR
zqd*Qa?|Jj_XbFw*^z+9{j{YZlkDr9{H12DhCdX{$9KG1<6;9q6UC7%NZzIzbNb_6_
z5#i~o@9Tcfn)3XSX-~p^r>7bT6roEI(o)(r+;`3#mZ&UKoM2h*8w`Bv58FCH+j@if>^lExDqBxdm`zlYvz=ZGN3@xRRkCV-a
z_*RYS5@_M~{yOw~(cDqJ0@9WL&3h)e9FvL18LD{4xmV`v_Z$Aa4=#SdH^ZX_
zi&w9rUO9Ep3)`@l-aURehwk&x*c(JzCI2j;g~$$yC~H!4?VObOV^AYU8w0^Fu$aS}
z)>1z|otIBp$$M=-f-FpVTW<{!hJijRN9Qm6BQM3d%c^?DJv3=ddC66fOHf{kt1>1r
zuA8S>BJx+>YtMajzyIw19OT92=riJn=+hWT^|H%uCu_v4_jcnOqI9Qr>cH=Zpr1in
zcaBjd@{ncpqaEFHsTtSdyNhFC_Eq0l__u6J8ilTJHDfW3BS@kY>b@uE4~M#M*%=2A
z-8%mjkMHIGcJW^MVve`ChHyBORnyzz8PIw+^wdyd=gvL)rw(`}b=`A0R)=O-nID2$
zkJoorT&kbLIG`rQ(1*>~87ubjO24{;F+JL%lBO5g1s}(2K%b$71P+ZkzVk0@qp+0#
z0gUiYRUr}m{-K>h&+fWjTI>N7+Go$+>rP04l{!0G>KOAeFYqiZ$g>fMHK3(5^fXy=
zNk7rIBN%!2J<&4FT7Y~NCcO>~H~UX*
zmtXez_06(+2DS3&KtuCNbLQ^K^uf5%+|i0~^E&rU`8hr$HhW`1a9qD)XRChuxLP#$
z|2s4s5I$$FizkO)<5&`L>G9v~GT?X)d(0W79!9p&w
zekoj>LL+L%IzN@BgVDdi+b7#vt0wc<_Kmkf<)Zg`ZafV{=@Y`%9yWj!o30~KO&a?`
z3qeiWS8q2S&bA9T?S!=lGx|-qr(eb8VJ2S8{;;snq*b;Ml|S}mj&@w%1u`Yc{r@1b
zUfEpk5m|a4w(YYjZXYQP#)U9caeeXTY^lNfF(1+?Z)WLhm#?T*J!V?g_g_~sdbe7z
zl3*GhMCE_F)3KwA6zXgQ?|@cS^5Cf`DHFxN`TyO6NYM-?zhJ@}iN6V+R~lD%xz*TJ
zm;(OlC{I-~ROVja!_zsd^ZK{zd{Lgq4G^5jfkz0=C)Njxp*-Owq*6!o?I5SjcrJwr
z(`cNX&Igb_BN!&v(JxyzVugAB1Ua_#u<7ieq=WEdUjS#q2DQe!R4_Ks8l5gu(pL2F
zDVe^$!eZ4UJm*8q_C2WBj$po|Lfm*#2AyK{)oqn3*
zX0ZRgW+~kEN5fv9MXBVki91y>c4t)6G2|w04F|$si1-Cq63wF8*^A&q76s!3=mk>$
z36X;l%^7o@4j!L{t7Vnu1XA-a&(nZx;ixB}!P~S^STwoiq|SxkW$Cf(GV8T!e|k{j
zZ|^NSSz~;LUgd!^*MGA}u7skree-2?&1=C3*}m?)gQjJ#@jlxj^*?$H|FJ!HGFIIr
zxE~sXIdwL4JcmnKc20)&aG~r0IkIvVEJ*N0JN^D={8bwWh$!f}@7r<1(q4~3r(a&8
z#l}W0sl?9*4PFX5uTH2G-d&70d||Ce=+KP$)xO)!Gv^)=dUpL@{j^yp8dMCko}iGa
z?}Jb39*A@0L!POKEL=e4w`b%in#(4?C38B?12=3x`Pxd8;UGV>=Duk=(!M;W^mh(T
z^WI{+LF{L%Fc0b%A5+kG9ennZ=j=E^dk}N|NCzYT62u&tfUR9k3&rl+pQ4PgbvxC~
z7(|TzTC(dH)DqHqmzs1c@J;?XVT&}cmG&-<5;|8HGJHNjX7*j1xZmTpWK=B#J@pf%c5PFky
z7EZ+7D>P*nhN~P5#d8nHkB4EOz@=_;y&Lnjo#pF4)S!0BL&y-#hupmrFtN?}V80Sl
ze)p!=&F;z14LL)YSWu6kAh>!&rk8p5()quN5nN3|B|?1!+J1VB)P@9Ey*r@)Y3`Ta
zH_EG=r4LY0Kcm9hTikos9PF7Smi+)74<*=b4wM^rDgxn(i(RP23H0G;|UjT3UleM%P6
zwp~?|9L;X;BpAz(y)yqeIbGo5G|zVZ%iV8p>)6t@XGW2J)ZN>!E-_GTR*oC0yWD)O
zzYBlfr1|ZhW_$9JS-<^3F#Kaij*M3zgxBzS-;hXNQ#ZU~autzizCFg1*Hf0lN5xbiw&W_HB#D=mZn
zawY0^cVQPKE~N-dnV0?b0QA0;53C+{io)n(1PXYJ-UOc(Zj#J^T&^pUmN#Tc1(~*F
zOJX?H(Xj|E9~Dk&sz`d*7~+xamR)d-0?~B55orEZ)yU<1xWZg-oUICTbyFaQSGNB^
zaxUd*_`WZ+Rgh9$4r0DGjXvp+K8t+YqzT291lgcd^IumH?vpzCq2JHI5+pmfnQ>C0
zlza!uGgTn*6zx|&k-NMM2L6a7+6CF(UOaY)UMzY`cDh&A>B^g4;w!;v->iB)68U2P
zj)o#t#tLQhh7fm`d+qLkwUjdP+ZCreU!yl1hrXY0rpn{
zh|yxb3Y9M+va(myrb1P(toVg&H;!uSA)ZTUPkU{VC!S|t6z;F6-x;2El_DH}z>Ie`
zM;s<@=+s88uBo19DN)~f)8wN|VGMpzv9o!Q(<{4g-OpC3g5=x9DiXz@mio6CSvzd6
zg*PS*!?XSlfS~PK>m26eUPr%ZZw4*f#N>B%iN0xmy@^3yv`AYexr=3U(pJ-`6hkGJ
z7O97mg0`3BXD>cEbk89nFs4wp6iRR_eyK3^mE$^9%QaAY%heOT2|&52;W@yrz5^9t
z*+=V49vUz}W`7|Oha;K~r{>P8M%|^4<^$}T1re6*CP~^s*(JW4w(2e&`xA~eN43_q
zaB_JUN<@{2->-`FNQluSu@gymZfImGtmeTJ8>5%6ml$EtyVSQg5SM^Vs
z9f83#%)HF{Rl|Yau#Fe8PYfjkx!OD!COk`Jof%8PC5+&bfhf(CJ!^DS1K*jn`H%s|cY9
z7TbEtQQT;3uzBQ8kf1sU1KaS%B>_v)q1kem5Dcv<eaq5^aRv!*zXiiQBC|>*HyTGYC`+4!j0s&_rPw4+u+6h)-#7R&LV(XNCVl{0;`4Epdw
zRIp*Mwe~3KM
zyZi3kzMt$X=??LhRQzVAdasBPo6U>Z2cC?V8YkYAL!pBw1xm^re5jZ~k7=ilR!6OwqtB#%AC%7a*zs&X
z3HH8A-lC*!rfNeBZh)IVU3y1*GF}X!YB+q7t+4o4e(5FVk3JQ
z+WjK&;PL2kUUW(XHGf{wZeEysxqda_r*{?H*3TZA_;<@CF2mEEAottI%CfAry*f{l
zg`RD&@GN-995sN>8{Iy8y_AT$jl!LFIJa_a2eoC&{TB;?
zlrVqr(ik_zP-P!pMVV!2)<2CeyI;a))=-Szs(k3N_G{9Xr%P6GIjc*EOLbbimQF_Y
zCDW5e+0zvh-PZnh9K}@7y)hGNrTVdyy0K+4FBZRURCPqC%=(Cpo?PyCVjhspS?Eq_~DPd}z5A^c&ERJids$vr>?sMnms5
zqF(0Kji{a#tLnMV-frl#(>ACgzDd^k1WrM1SJ5kEukB?PDNL7uU03y=JYK``YEyO1
ztEnD_C}GyCSNuA=6YA^1==1aQAg;prCe_u9-AoD&
zX_6MN1@M@4=pw(@;vU9zBYHzm!>x@iKjj8Jh`>Q&;puCQyImZKor5a^0Fye{z}_ia
zV1EWn3#8|E?lWme1czl}N#wtH8BBf#Sws2-pnWv4$|m-+J%lcROv#Ij<(oycshAo9
zD#+v1x6m1JtVDa7D_Xe@HLrW`O7e^@+f9A?cj;ggtJHjYP{;^Lm6QG!Z`rlmKOM0u5IsQ9slo3*(V(oCb
zhpS?9L>aqt?Y~b)h-$`{Jd}d*@x8^IJ@mWerc{6TCY=6Z1@j$~-rC1B8k3QJ~
z@FwinoIh4!0mnw_mLaU9S}biMk)hdo1jhMK^F8ad@Z!i#*wC;o9L3vca!i7V+mm
zaQBX>2biY&>?$&`Z{j(kd7Mk$o-1{C<@wSHL&6`EE3R7oQbOD5;B8g;1SJz#Wj4c^
z6{-O4O68Lg_n>P!_w%snuyK0fQAFW()9EsgyhaXZcdGBNZ!wUjY^6wiXnyr1cW2>u
zJAkbfBv$q2j}sU&6Ew*O*{*gExa?75_1*tye{5@PcM4K+IMBfV@^`g4^{i6eV}WJ
zcdp1(+-m1+)6qZq-VKn)9BxA^7wJ1CLsLg}#?Hk8@WXlk;u;_G-Q&m{Q>riFW3o=!
zf^+6wrCQtuP?rwF!)(NJT}OvQ`Myxdx&((*;d2j-Zs!d
z&%X8Moz_ELZ@CDi=W@x`r}>gN@fmANpZVK#keGbOH|t%mQjr75x`
zw$fEAO&ysH%2I|QUzw~q)Go)RIdSo0TV*AMZcvwQ6qefYavOIiwDlFPQlpS)^G>d%
zb8U&{J3q!9aox1;cQ+l2uAcMrJ~~|Bm{%~z6iBK}yq*^GipYvLf!=5iA>Ge}zX|1q=vR^V
zsJfWUp<94rQMRui2SnG}7gFi>To*8ax(M3>5X1tHTAp>NDXDt_e|QXOW8(E>!AR|oe
zvL1y~x1Pk*xlm{Eil0@#7?2HLGs>>rm=VKSsZ!h0>a~
z@puDwsK8F^P0P4?kiDl`
zYT5l-(mF%3B`lkXdcI@J;~kE+~`L`Wryq2I{ur4yB(j26m-}IwnN?lcmd*aW(MBv-rx=P%$oPkfr^!Q#Z~l;nz^o
zeuu6n0m9?v*stG_px09?Tz3T9)X-zC^HL8kD-+8DiF!~=`vp`Ow#--5oDe5u%XO9T
z)24GhaR0m+Rq~Mpl0a@a<0;^Kg}(IgejzF_8JfKgP}3!ei=n|lQ^jACBajYf~Lu;9>=4YrNXiYb7VCjUyedC98smsQe@%D-rf
zr)O@;9#B5@j)vUaD+KcymkeCXlxcLgNage29)9(f`AbImm`(Iv=JRv#=C8bvo-wk3
z&PEQ|k#FIIsHZ{aegZ;}7K|ay-O5=Mc2-Wm^c)*US5)7^YNQdG
z+r?^WTYDQ0h5|xgq-uyRD4Ngo2>$c9>150HD$Ct1cxMu?#CX`-T~R&)W8aJ?*0)?W
zct1q_0F>tSGcvvHG}j?T@vcKqiHuMPDb=z;;^edN?1+h;+@I6oRq-yaXWXLj{8857
z-cxN-Sq8>76gU5nucaI)pl&NfCuEJ{5+lV6-{<$0WlT5y+t@
zgP_Wz!ul@J&MC}X`$UMX?f2y#Y>s1U-qxY@C{Tsp=a!W3N4ZZw=^qY~gMH5j^`uRU3f@Y~P!3@8UYyb%BFPf>GyJ>@Ts32<9!;(!=O
z=@~b%d=*razfD;;Y+`g(qRjLrq(G=(AM?g}ezh~zV=AqXXEUu5L!35NdR3`g|yfTu*`fwU7@m{G5(o%k)C9Ml*(EY
zP*tibr~Hm70ZTIA?IXFG;=4ck4jwd@uocE71c~>B|$sEs*yFpc)a(CeM=Ssy^%P-Qv
zsNL*x=-?qi&r3%!et^xb=HiVZ&%>UsN^h->?L;YYhg>=s5`iAd7vh})ok@NH@6A?i
z$cMc?ah@t}cwm%K?trA3J)Ff4?S!kpwRu)<(@+R
zkDE-TzXnvm82OG>2TfLARItiiwbzh4_$uh(k}a1=_s!YEJIhktK#4K6&`)KlIGpqM
z=cubmH-UtoSeNw$M`p(Mn>6WkxDPB!g7kpQ=ykS5RK`Km=r3_~X&JRls;JKj?-y+($s;6qK5$~DqfkY0nz{JkSP)GvPNyY!NGV!?QtPGNA`+uV9XDPhN)
zt;I&UzZ`F!!4*7QRr|t_NQ{?sZF(YW@=7v!jcx31e6zr?mYg?E
zY|fVw-V6o>QTwUlW^o%=Lw*^20H+Jowgfpj&G^z^sh_Q=n9LOm4;#G?c|U$&Xeh5l
zZxY)LKYKt+p0S@@3(ruzQuPe{f^b%Om~^m2?Q%UG4w-WND}H`$?%
z?Z<1Gjq?_gt7CeOkT>dvExhJVgiE6=yEHtdV`OY5lM)(Tp9n2|{TV&yUxgrp`seG;
z+~8U|2lb6r--F6j+Qqc`p9pOTjahec9MbI249MIWZ%}VbvG|60`4cmWNb}h!$iHD#
zF{TdaP9vqGajLjVd>1e{KOPHsVc)3$0>*ac<=B$t{gI@zfzFSbR4lf1&^?!pC76mW
zB$nH#Dlg&LyNMc=Nt#j6b(jp}Y4SeTaaX9O#CGtloOOK&F@!U6Mq3X$K19*SyO9#i
zTLc$yCbXVc`bUW{-v9auUeRa6?OC%Nr}ylxwh={3YIANw7J;+Z+5Yu;aW;k%r<2vD
ztTHL~eLA+xAQkPPG@sqhBc4;p)t!-tSey;uSdmdMvn7mdce(#^5Qs`ZO%JA>ys{>rW^EL-y`dkYe217STxfI0zXATVK0axl>t5%A7p&?XV1VmcFY?4X?_~f6BgEFq%_V0Ua+(XxnlG
zM!2`|z-Jm+PbG~dQJKLEHr`_oFVUMFSF||u_}9|g!*k#aVx4x8GdY#$hht_w|T{s3`xsN
z_dBi$8<11U)Rg?ddIsWOf{13lUY}NO`3mE4*#^1fr*hXs!9+yrTP|6WWxeLW{!Ld&
zIFb0W_k>>wKxy|Gf@GaEV#-sBc$i*e|lA-q|
z`L;@0m2u{BnO7DhSXP>p*PocW!i6n>qI5yiC>({FOnTE
z*PR@bx*wQX0y3D6w#YPzs-!4ine?%N>F@A_r6JJzVPA65l1+!E`5~BaOT*edO4J?pdxK1}NgNnGXuK{&3#%a`JGFdnD8seq!P~JKKu9
zl7Sq`ueBrG^HvC}&B*0yM<_*ikpDY6-OD!^sZm5q8NR)`tNHpbM90><*;dm>LmN|Y
zLdbk`Hz=HOj)1Il1MS3qNf?(R;`ke7+a0Ng&V3`2E>z)h@1M?W$G=J#z|pxY-fr)6
zUowhO=Qualn@)<9zjw5Tc(AfkYt@c4c#f?gxfyy*I;~!MH@R`vtER-suit;;>l&|u
zov_|2AxixC0%QD5In?JWY`dn%+uBz4)MH|u?&_yr(oH@iLZ{C+aflPA8h&ghvbwLI
z6rBs(+*+E=j&XnN0r);Sud|ltQ0)f-A27?Ht8acQ|43O!ZIO@}E3|2|UXL?n9ZUgs
znNbe{q~U@|ve(Q0f#lj&=&P|_;%s=Kp+hge-VSb!lNJI{Lt8)m+q6qRJqBoxzoN%>
zPJ?J2)?VOON_`c;FC=})#RLV~(jDIm3Q%6x@;LTTW(}FBp-S^cnKDh}{yHL1~iqJQ+TB)s6x|3xiXSQxjjoE0XX3m+fVx=+f4m^(6
z^XrXw)VnZS!dzytbD&Tbt!niK%72G>Ni@9ZOkv6%LMjTzH&c!u_M{GmRv+YU#sjB|
z^O2?x;xj4g+d{=I>_x@mqT!jd#1A+yurxD&$6*qF^HLSgE~-{dYT{I~2D1fWj*>#l
zNBLm_r@WIX#y=*?GOP8+alDJ3KKHB`@nWq&*qCWaSJ>UvsQ%J9&d(djYl?&tnZrR3
zjgDFK_p5m=!^H{n@@9*(-Bkb)i_haKCl%94dxiy`V2=5OK;2Fe`0Du
zD(7ES{o7Td7nSll66SQJ%1hzZI+Vmg8
z*d8AO>j}lA8ZU>RAF8SEjlsbWxO+jksi~W?rtsVm?1)Y*Y>F(_&GwF6?*c{GCG2Q?
znFE#HG9RKjf!rUwKfWpF+@h~^YKG0`zx?Uy0nTFOjN7T)>K;Pu#UFYCa~1326dE`CHz_79@%`FjNM7iM?
zyK2~%c>Mkn2JrQTCm1buJiVo_8e~;t>^YSxeEKfm%;R%0DK#aI4ApTGF~RJ|t=bIT
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