Merge pull request #414 from 0-yy-0/master

Qwen3 Docker 镜像
This commit is contained in:
不要葱姜蒜
2025-05-03 17:20:41 +08:00
committed by GitHub
4 changed files with 147 additions and 91 deletions
+100 -31
View File
@@ -10,9 +10,7 @@
- **分布式推理**:框架支持在多 `GPU` 环境中进行分布式推理,通过模型并行策略和高效的数据通信,提升了处理大型模型的能力。
- **开源共享**`vLLM` 由于其开源的属性,拥有活跃的社区支持,这也便于开发者贡献和改进,共同推动技术发展。
## 环境准备
## 环境准备
本文基础环境如下:
@@ -37,8 +35,8 @@ pip install modelscope
pip install vllm
```
> 考虑到部分同学配置环境可能会遇到一些问题,我们在 AutoDL 平台准备了 Qwen3-8B 的环境镜像,点击下方链接并直接创建 Autodl 示例即可。
> ***https://www.codewithgpu.com/i/datawhalechina/self-llm/Qwen3-8B-self-llm***
> 考虑到部分同学配置环境可能会遇到一些问题,我们在 AutoDL 平台准备了 Qwen3 的环境镜像,点击下方链接并直接创建 Autodl 示例即可。
> ***https://www.codewithgpu.com/i/datawhalechina/self-llm/Qwen3***
## 模型下载
@@ -56,10 +54,9 @@ model_dir = snapshot_download('Qwen/Qwen3-8B', cache_dir='/root/autodl-tmp', rev
> 注意:记得修改 `cache_dir` 为你的模型下载路径哦~
## **代码准备**
### **Python脚本**
### **Python 脚本**
新建 `vllm_model.py` 文件并在其中输入以下内容,粘贴代码后请及时保存文件。下面的代码有很详细的注释,如有不理解的地方,欢迎大家提 `issue`
@@ -69,7 +66,7 @@ model_dir = snapshot_download('Qwen/Qwen3-8B', cache_dir='/root/autodl-tmp', rev
然后,通过使用分词器的 apply_chat_template 函数,将我们的 prompt(提示词)格式化为模型所需的输入格式。
默认情况下,Qwen3启用了思考能力,类似于QwQ-32B。这意味着该模型将利用其推理能力来提升生成回答的质量。例如,当在tokenizer.apply_chat_template中显式设置enable_thinking=True或保留其默认值时,模型将进入思考模式。
默认情况下,Qwen3 启用了思考能力,类似于 QwQ-32B。这意味着该模型将利用其推理能力来提升生成回答的质量。例如,当在 tokenizer.apply_chat_template 中显式设置 enable_thinking=True 或保留其默认值时,模型将进入思考模式。
我们可以通过这个代码示例熟悉下 ` vLLM` 引擎的使用方式。被注释的部分内容可以丰富模型的能力,但不是必要的,大家可以按需选择,自己多多动手尝试 ~
@@ -92,7 +89,7 @@ def get_completion(prompts, model, tokenizer=None, temperature=0.6, top_p=0.95,
return outputs
if __name__ == "__main__":
if __name__ == "__main__":
# 初始化 vLLM 推理引擎
model='/root/autodl-tmp/Qwen/Qwen3-8B' # 指定模型路径
tokenizer = AutoTokenizer.from_pretrained(model, use_fast=False) # 加载分词器
@@ -114,9 +111,10 @@ if __name__ == "__main__":
# 打印输出。
for output in outputs:
prompt = output.prompt
generated_text = output.outputs[0].text
generated_text = output.outputs[0].text
print(f"Prompt: {prompt!r}, \nResponse: {generated_text!r}")
```
运行代码
```bash
@@ -126,7 +124,7 @@ python vllm_model.py
结果如下:
```bash
Prompt: '<|im_start|>user\n给我一个关于大模型的简短介绍。<|im_end|>\n<|im_start|>assistant\n',
Prompt: '<|im_start|>user\n给我一个关于大模型的简短介绍。<|im_end|>\n<|im_start|>assistant\n',
Response: '<think>\n好的,用户让我给他一个关于大模型的简短介绍。首先,我需要确定“大模型”指的是什么。通常来说,大模型指的是大规模预训练模型,比如像GPT、BERT这样的深度学习模型。用户可能对AI领域不太熟悉,所以需要解释清楚基本概念。\n\n接下来,我要考虑用户的需求。他们可能是在寻找一个简短的概述,不需要太技术性的术语,但又要涵盖关键点。可能需要包括定义、特点、应用领域以及优势。不过用户要求的是简短,所以不能太冗长。\n\n然后,我需要检查是否有遗漏的重要信息。比如,大模型的规模通常以参数量衡量,比如百亿或千亿参数。此外,它们通常使用Transformer架构,这可能需要提到。另外,应用场景如自然语言处理、图像识别、语音处理等也是重点。\n\n还要注意用户可能的背景。如果是普通用户,可能需要更通俗的解释,避免使用太多专业术语。但如果是技术人员,可能需要更详细的技术细节。不过用户没有说明,所以保持中立,简明扼要。\n\n另外,用户可能想知道大模型的优势,比如强大的泛化能力、多任务处理能力,以及在不同领域的应用实例。同时,可能存在的挑战,比如计算资源需求高、训练成本大,这些是否需要提及?但用户要的是简短介绍,可能不需要深入讨论缺点。\n\n最后,确保语言简洁,结构清晰,分点或分段说明。可能需要用一两句话概括定义,接着说明特点,然后应用领域,最后总结优势。这样用户能快速抓住重点。\n</think>\n\n大模型(Large Language Models, LLMs)是基于深度学习的先进人工智能技术,通过海量文本数据训练,具备强大的语言理解和生成能力。它们通常拥有数十亿至数千亿参数,能够完成文本生成、问答、翻译、编程等复杂任务,广泛应用于智能助手、内容创作、数据分析等领域,显著提升了人机交互的效率与智能化水平。'
```
@@ -153,7 +151,7 @@ def get_completion(prompts, model, tokenizer=None, temperature=0.6, top_p=0.95,
return outputs
if __name__ == "__main__":
if __name__ == "__main__":
# 初始化 vLLM 推理引擎
model='/root/autodl-tmp/Qwen/Qwen3-8B' # 指定模型路径
tokenizer = AutoTokenizer.from_pretrained(model, use_fast=False) # 加载分词器
@@ -175,18 +173,17 @@ if __name__ == "__main__":
# 打印输出。
for output in outputs:
prompt = output.prompt
generated_text = output.outputs[0].text
generated_text = output.outputs[0].text
print(f"Prompt: {prompt!r},Response: {generated_text!r}")
```
结果如下:
```bash
Prompt: '<|im_start|>user\n你是谁?<|im_end|>\n<|im_start|>assistant\n<think>\n\n</think>\n\n',
Prompt: '<|im_start|>user\n你是谁?<|im_end|>\n<|im_start|>assistant\n<think>\n\n</think>\n\n',
Response: '我是通义千问,由通义实验室研发的超大规模语言模型。我能够回答各种问题、创作文字,比如写故事、写邮件、写剧本,还能进行逻辑推理、多语言理解、代码编写等。我旨在成为你最得力的助手,帮助你解决各种问题。有什么我可以帮你的吗?'
```
### 创建兼容 OpenAI API 接口的服务器
`Qwen3-8B` 兼容 `OpenAI API` 协议,所以我们可以直接使用 `vLLM` 创建 `OpenAI API` 服务器。`vLLM` 部署实现 `OpenAI API` 协议的服务器非常方便。默认会在 http://localhost:8000 启动服务器。服务器当前一次托管一个模型,并实现列表模型、`completions``chat completions` 端口。
@@ -202,9 +199,9 @@ Response: '我是通义千问,由通义实验室研发的超大规模语言模
- `--served-model-name` 指定服务模型的名称。
- `--max-model-len` 指定模型的最大长度。
- `--enable-reasoning` 开启思考模式
- `--reasoning-parser` 指定如何解析模型生成的推理内容。设置 --enable-reasoning 参数时,--reasoning-parser 是必需的。推理模型会在输出中包含一个额外的 reasoning_content 字段,该字段包含导致最终结论的推理步骤。通过指定合适的解析器,可以正确提取和格式化这些推理内容。例如deepseek_r1解析器适用于 DeepSeek R1 系列模型,能够解析 <think> ... </think> 格式的内容
- `--reasoning-parser` 指定如何解析模型生成的推理内容。设置 --enable-reasoning 参数时,--reasoning-parser 是必需的。推理模型会在输出中包含一个额外的 reasoning_content 字段,该字段包含导致最终结论的推理步骤。通过指定合适的解析器,可以正确提取和格式化这些推理内容。例如 deepseek_r1 解析器适用于 DeepSeek R1 系列模型,能够解析 <think> ... </think> 格式的内容
我们复制以下命令到终端上,就可以成功启动 Qwen3-8 B模型的 API 接口
我们复制以下命令到终端上,就可以成功启动 Qwen3-8 B 模型的 API 接口
```bash
VLLM_USE_MODELSCOPE=true vllm serve /root/autodl-tmp/Qwen/Qwen3-8B --served-model-name Qwen3-8B --max_model_len 8192 --enable-reasoning --reasoning-parser deepseek_r1
@@ -220,14 +217,42 @@ VLLM_USE_MODELSCOPE=true vllm serve /root/autodl-tmp/Qwen/Qwen3-8B --served-mode
curl http://localhost:8000/v1/models
```
得到的返回值如下所示
得到的返回值如下所示
```json
{"object":"list","data":[{"id":"Qwen3-8B","object":"model","created":1745950421,"owned_by":"vllm","root":"/root/autodl-tmp/Qwen/Qwen3-8B","parent":null,"max_model_len":8192,"permission":[{"id":"modelperm-3f20f566536d445cbfbf5a9ddb115204","object":"model_permission","created":1745950421,"allow_create_engine":false,"allow_sampling":true,"allow_logprobs":true,"allow_search_indices":false,"allow_view":true,"allow_fine_tuning":false,"organization":"*","group":null,"is_blocking":false}]}]}
{
"object": "list",
"data": [
{
"id": "Qwen3-8B",
"object": "model",
"created": 1745950421,
"owned_by": "vllm",
"root": "/root/autodl-tmp/Qwen/Qwen3-8B",
"parent": null,
"max_model_len": 8192,
"permission": [
{
"id": "modelperm-3f20f566536d445cbfbf5a9ddb115204",
"object": "model_permission",
"created": 1745950421,
"allow_create_engine": false,
"allow_sampling": true,
"allow_logprobs": true,
"allow_search_indices": false,
"allow_view": true,
"allow_fine_tuning": false,
"organization": "*",
"group": null,
"is_blocking": false
}
]
}
]
}
```
- 使用 `curl` 命令测试 `OpenAI Completions API`
- 使用 `curl` 命令测试 `OpenAI Completions API`
```bash
curl http://localhost:8000/v1/completions \
@@ -240,14 +265,34 @@ curl http://localhost:8000/v1/completions \
}'
```
得到的返回值如下所示
得到的返回值如下所示
```json
{"id":"cmpl-fb7fa8e981164942b1e126afe43b2acf","object":"text_completion","created":1745950506,"model":"Qwen3-8B","choices":[{"index":0,"text":"嗯,好的,我现在要算5的阶乘是多少。首先,我得回忆一下阶乘的定义。阶乘就是从1乘到那个数本身,对吧?比如n的阶乘就是n×(n-1)×(n-2)×…×1。那这样的话,5的阶乘应该是5×4×3×2×1。不过,我是不是应该再仔细确认一下这个定义有没有错误?\n\n让我再想想,比如3的阶乘是3×2×1=6,对吧?那4的阶乘就是4×3×2×1=24,对吗?那5的阶乘应该就是5×4×3×2×1。那这样的话,先算5×4=20,然后20×3=60,接着60×2=120,最后120×1=120。所以结果应该是120?\n\n不过,有没有可能我哪里算错了?比如,是不是有时候阶乘的定义是从0开始?比如0的阶乘是1?不过题目是问5的阶乘,所以应该没问题。那再检查一下每一步的乘法是否正确。\n\n首先,5×4=20,没错。然后20×3=60,对的。接下来60×2=120,没错。最后乘以1的话,结果还是120。所以应该是对的。\n\n或者有没有可能我漏掉了某个步骤?比如,是不是应该包括更多的数?比如,5的阶乘是不是应该包括5×4×3×2×1,而没有其他数?是的,没错。所以结果应该是120。\n\n不过,为了确保万无一失,我可以换一种方式计算。比如,先算4的阶乘是24,然后5的阶乘就是5×24=120。这样是不是更快捷?是的,这样算的话,结果也是一样的。所以两种方法都得到120,应该没错。\n\n或者,我可以使用计算器来验证一下,不过现在假设没有计算器的话,手动计算应该没问题。再试一次:5×4=20,20×3=6060×2=120120×1=120。没错,结果一致。\n\n所以,我觉得5的阶乘应该是120。不过,有没有可能我记错了阶乘的定义?比如,是不是有时候阶乘是从0开始的?比如,0! =1,1! =12! =23! =64! =245! =120。是的,这样看来是对的。所以答案应该是120。\n\n或者,有没有可能题目中的阶乘有其他定义?比如,某些特殊情况下有不同的定义?不过一般来说,阶乘的标准定义就是n! =n×(n-1)×…×1,所以应该没问题。\n\n总之,经过多次验证,我觉得5的阶乘是120。\n</think>\n\n5的阶乘(记作5!)是通过将从1到5的所有正整数相乘得到的。具体计算过程如下:\n\n$$\n5! = 5 \\times 4 \\times 3 \\times 2 \\times 1\n$$\n\n分步计算:\n1. $5 \\times 4 = 20$\n2. $20 \\times 3 = 60$\n3. $60 \\times 2 = 120$\n4. $120 \\times 1 = 120$\n\n因此,**5的阶乘是120**。\n\n**答案:120**","logprobs":null,"finish_reason":"stop","stop_reason":null,"prompt_logprobs":null}],"usage":{"prompt_tokens":12,"total_tokens":797,"completion_tokens":785,"prompt_tokens_details":null}}
{
"id": "cmpl-fb7fa8e981164942b1e126afe43b2acf",
"object": "text_completion",
"created": 1745950506,
"model": "Qwen3-8B",
"choices": [
{
"index": 0,
"text": "嗯,好的,我现在要算5的阶乘是多少。首先,我得回忆一下阶乘的定义。阶乘就是从1乘到那个数本身,对吧?比如n的阶乘就是n×(n-1)×(n-2)×…×1。那这样的话,5的阶乘应该是5×4×3×2×1。不过,我是不是应该再仔细确认一下这个定义有没有错误?\n\n让我再想想,比如3的阶乘是3×2×1=6,对吧?那4的阶乘就是4×3×2×1=24,对吗?那5的阶乘应该就是5×4×3×2×1。那这样的话,先算5×4=20,然后20×3=60,接着60×2=120,最后120×1=120。所以结果应该是120?\n\n不过,有没有可能我哪里算错了?比如,是不是有时候阶乘的定义是从0开始?比如0的阶乘是1?不过题目是问5的阶乘,所以应该没问题。那再检查一下每一步的乘法是否正确。\n\n首先,5×4=20,没错。然后20×3=60,对的。接下来60×2=120,没错。最后乘以1的话,结果还是120。所以应该是对的。\n\n或者有没有可能我漏掉了某个步骤?比如,是不是应该包括更多的数?比如,5的阶乘是不是应该包括5×4×3×2×1,而没有其他数?是的,没错。所以结果应该是120。\n\n不过,为了确保万无一失,我可以换一种方式计算。比如,先算4的阶乘是24,然后5的阶乘就是5×24=120。这样是不是更快捷?是的,这样算的话,结果也是一样的。所以两种方法都得到120,应该没错。\n\n或者,我可以使用计算器来验证一下,不过现在假设没有计算器的话,手动计算应该没问题。再试一次:5×4=20,20×3=6060×2=120120×1=120。没错,结果一致。\n\n所以,我觉得5的阶乘应该是120。不过,有没有可能我记错了阶乘的定义?比如,是不是有时候阶乘是从0开始的?比如,0! =1,1! =12! =23! =64! =245! =120。是的,这样看来是对的。所以答案应该是120。\n\n或者,有没有可能题目中的阶乘有其他定义?比如,某些特殊情况下有不同的定义?不过一般来说,阶乘的标准定义就是n! =n×(n-1)×…×1,所以应该没问题。\n\n总之,经过多次验证,我觉得5的阶乘是120。\n</think>\n\n5的阶乘(记作5!)是通过将从1到5的所有正整数相乘得到的。具体计算过程如下:\n\n$$\n5! = 5 \\times 4 \\times 3 \\times 2 \\times 1\n$$\n\n分步计算:\n1. $5 \\times 4 = 20$\n2. $20 \\times 3 = 60$\n3. $60 \\times 2 = 120$\n4. $120 \\times 1 = 120$\n\n因此,**5的阶乘是120**。\n\n**答案:120**",
"logprobs": null,
"finish_reason": "stop",
"stop_reason": null,
"prompt_logprobs": null
}
],
"usage": {
"prompt_tokens": 12,
"total_tokens": 797,
"completion_tokens": 785,
"prompt_tokens_details": null
}
}
```
-`Python` 脚本请求 `OpenAI Completions API`
-`Python` 脚本请求 `OpenAI Completions API`
```python
# vllm_openai_completions.py
@@ -271,14 +316,13 @@ print(completion.choices[0].message)
python vllm_openai_completions.py
```
得到的返回值如下所示
得到的返回值如下所示
```
ChatCompletionMessage(content='\n\n5的阶乘(记作5!)是将1到5的所有正整数相乘的结果。计算过程如下:\n\n$$\n5! = 5 \\times 4 \\times 3 \\times 2 \\times 1 = 120\n$$\n\n**答案:** 5的阶乘是 **120**。', refusal=None, role='assistant', annotations=None, audio=None, function_call=None, tool_calls=[], reasoning_content='\n嗯,用户问的是5的阶乘是多少。首先,我得确认阶乘的定义。阶乘就是从1乘到那个数,对吧?比如n的阶乘是n×(n-1)×...×1。那5的阶乘就是5×4×3×2×1。\n\n不过,我得仔细检查一下,别搞错了。有时候可能会有计算错误,比如把某个数漏掉或者乘错。比如,5×4是20,然后20×3是60,接着60×2是120,最后120×1还是120。所以结果应该是120。\n\n但用户可能是个刚开始学数学的学生,或者对阶乘不太熟悉,所以需要确认是否理解正确。或者他们可能在做作业,需要快速得到答案。也有可能他们想确认自己计算的正确性,所以给出详细的步骤会更好。\n\n另外,有没有可能用户问的是其他类型的阶乘?比如递归定义或者其他变种?不过一般来说,阶乘都是指标准的n!,所以应该没问题。再想想,有没有可能用户输入有误?比如是不是5的阶乘还是别的数?不过问题明确说是5,所以应该没问题。\n\n再检查一遍计算过程:5×4=2020×3=6060×2=120120×1=120。没错,结果确实是120。所以答案应该是120。不过为了确保万无一失,可以再用另一种方式计算,比如分步计算或者用计算器验证。但作为思考过程,这里已经足够详细了。\n')
```
-`curl` 命令测试 `OpenAI Chat Completions API`
-`curl` 命令测试 `OpenAI Chat Completions API`
```bash
curl http://localhost:8000/v1/chat/completions \
@@ -294,11 +338,36 @@ curl http://localhost:8000/v1/chat/completions \
得到的返回值如下所示
```json
{"id":"chatcmpl-ebe5eb4e638449dc83d628175e540365","object":"chat.completion","created":1745950682,"model":"Qwen3-8B","choices":[{"index":0,"message":{"role":"assistant","reasoning_content":"\n嗯,用户问的是5的阶乘是多少。首先,我得确认阶乘的定义。阶乘就是从1乘到那个数,对吧?比如n的阶乘是n×(n-1)×...×1。所以5的阶乘应该是5×4×3×2×1。让我算一下,5乘4是20,然后20乘3是60,接着60乘2是120,最后120乘1还是120。所以答案应该是120。不过,我得再检查一遍,确保没有算错。或者有没有可能用户问的是别的什么?比如有时候可能会有其他数学概念混淆,但阶乘通常就是这个意思。再想想,有没有可能用户输入的时候有错别字?比如“阶乘”是不是别的词?不过看起来没问题。再确认一下计算步骤,5×4=20,没错;20×3=60,对的;60×2=120,没错;120×1=120。没错,应该是对的。或者有没有可能用户需要更详细的解释?比如阶乘的定义或者应用场景?不过问题直接问的是数值,所以直接回答结果应该就可以了。不过有时候用户可能不太清楚阶乘的概念,可能需要简单说明一下。不过根据问题,用户可能已经知道阶乘是什么,只是需要数值。所以直接给出答案120应该没问题。再想想有没有其他可能的错误,比如计算顺序或者乘法错误?比如有没有可能把5×4×3×2×1算成别的?比如5×4=2020×3=6060×2=120120×1=120,没错。或者有没有可能用户问的是5的幂次?比如5的5次方是3125,但那是不同的概念。不过用户明确说是阶乘,所以应该没问题。总之,答案应该是120。\n","content":"\n\n5的阶乘(记作5!)是5×4×3×2×1,计算结果为:\n\n**5! = 5 × 4 × 3 × 2 × 1 = 120**\n\n所以,5的阶乘是 **120**。","tool_calls":[]},"logprobs":null,"finish_reason":"stop","stop_reason":null}],"usage":{"prompt_tokens":20,"total_tokens":511,"completion_tokens":491,"prompt_tokens_details":null},"prompt_logprobs":null}
{
"id": "chatcmpl-ebe5eb4e638449dc83d628175e540365",
"object": "chat.completion",
"created": 1745950682,
"model": "Qwen3-8B",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"reasoning_content": "\n嗯,用户问的是5的阶乘是多少。首先,我得确认阶乘的定义。阶乘就是从1乘到那个数,对吧?比如n的阶乘是n×(n-1)×...×1。所以5的阶乘应该是5×4×3×2×1。让我算一下,5乘4是20,然后20乘3是60,接着60乘2是120,最后120乘1还是120。所以答案应该是120。不过,我得再检查一遍,确保没有算错。或者有没有可能用户问的是别的什么?比如有时候可能会有其他数学概念混淆,但阶乘通常就是这个意思。再想想,有没有可能用户输入的时候有错别字?比如“阶乘”是不是别的词?不过看起来没问题。再确认一下计算步骤,5×4=20,没错;20×3=60,对的;60×2=120,没错;120×1=120。没错,应该是对的。或者有没有可能用户需要更详细的解释?比如阶乘的定义或者应用场景?不过问题直接问的是数值,所以直接回答结果应该就可以了。不过有时候用户可能不太清楚阶乘的概念,可能需要简单说明一下。不过根据问题,用户可能已经知道阶乘是什么,只是需要数值。所以直接给出答案120应该没问题。再想想有没有其他可能的错误,比如计算顺序或者乘法错误?比如有没有可能把5×4×3×2×1算成别的?比如5×4=2020×3=6060×2=120120×1=120,没错。或者有没有可能用户问的是5的幂次?比如5的5次方是3125,但那是不同的概念。不过用户明确说是阶乘,所以应该没问题。总之,答案应该是120。\n",
"content": "\n\n5的阶乘(记作5!)是5×4×3×2×1,计算结果为:\n\n**5! = 5 × 4 × 3 × 2 × 1 = 120**\n\n所以,5的阶乘是 **120**。",
"tool_calls": []
},
"logprobs": null,
"finish_reason": "stop",
"stop_reason": null
}
],
"usage": {
"prompt_tokens": 20,
"total_tokens": 511,
"completion_tokens": 491,
"prompt_tokens_details": null
},
"prompt_logprobs": null
}
```
-`Python` 脚本请求 `OpenAI Chat Completions API`
-`Python` 脚本请求 `OpenAI Chat Completions API`
```python
# vllm_openai_chat_completions.py
@@ -1,20 +1,23 @@
# 04-Qwen3-8B EvalScope智商情商评测
# 04-Qwen3-8B EvalScope 智商情商评测
## 大模型评测是什么
大语言模型评测是指对大语言模型(LLM)在多种任务和场景下的性能进行全面评估的过程。评测的目的是衡量模型的通用能力、特定领域表现、效率、鲁棒性、安全性等多方面性能,以便优化模型设计、指导技术选型和推动模型在实际应用中的部署。
评测的主要内容包括以下几个方面:
- 通用能力:评估模型在语言理解、生成、推理等方面的基础能力。
- 特定领域表现:针对特定任务(如数学推理、代码生成、情感分析等)的性能评估。
- 效率与资源消耗:包括模型的训练和推理时间、计算资源需求等。
- 鲁棒性与可靠性:评估模型在面对噪声、对抗攻击或输入扰动时的稳定性。
- 伦理与安全性:检测模型是否会产生有害内容、是否存在偏见或歧视。
EvalScope是魔搭社区官方推出的模型评测与性能基准测试框架,内置多个常用测试基准和评测指标,如MMLU、CMMLU、C-Eval、GSM8K、ARC、HellaSwag、TruthfulQA、MATHHumanEval等;支持多种类型的模型评测,包括LLM、多模态LLM、embedding模型和reranker模型。EvalScope还适用于多种评测场景,如端到端RAG评测、竞技场模式和模型推理性能压测等。此外,通过ms-swift训练框架的无缝集成,可一键发起评测,实现了模型训练到评测的全链路支持。
EvalScope 是魔搭社区官方推出的模型评测与性能基准测试框架,内置多个常用测试基准和评测指标,如 MMLU、CMMLU、C-Eval、GSM8K、ARC、HellaSwag、TruthfulQA、MATHHumanEval 等;支持多种类型的模型评测,包括 LLM、多模态 LLM、embedding 模型和 reranker 模型。EvalScope 还适用于多种评测场景,如端到端 RAG 评测、竞技场模式和模型推理性能压测等。此外,通过 ms-swift 训练框架的无缝集成,可一键发起评测,实现了模型训练到评测的全链路支持。
官网地址:https://evalscope.readthedocs.io/zh-cn/latest/get_started
# EvalScope评测使用方法
# EvalScope 评测使用方法
## 环境准备
## 环境准备
本文基础环境如下:
@@ -26,7 +29,9 @@ Cuda 12.4
PyTorch 2.5.1
----------------
```
**pip 安装 EvalScope**
```
pip install evalscope # 安装 Native backend (默认)
# 额外选项
@@ -37,9 +42,8 @@ pip install evalscope[perf] # 安装 模型压测模块 依赖
pip install evalscope[all] # 安装所有 backends (Native, OpenCompass, VLMEvalKit, RAGEval)
```
> 考虑到部分同学配置环境可能会遇到一些问题,我们在 AutoDL 平台准备了 gemma-3-4b-it 的环境镜像,点击下方链接并直接创建 Autodl 示例即可。
> ***https://www.codewithgpu.com/i/datawhalechina/self-llm/self-llm-gemma3***
> 考虑到部分同学配置环境可能会遇到一些问题,我们在 AutoDL 平台准备了 Qwen3 的环境镜像,点击下方链接并直接创建 Autodl 示例即可。
> ***https://www.codewithgpu.com/i/datawhalechina/self-llm/Qwen3***
## 模型评测方法
@@ -47,25 +51,26 @@ pip install evalscope[all] # 安装所有 backends (Native, OpenCompas
下面我们以**智商情商评测**为例,对 Qwen3-8 模型进行评测。
我们将使用 EvalScope 模型评测框架,在 IQuiz 数据集上进行评测,这个数据集中收集了40道 IQ 测试和80道 EQ 测试选择题,其中包括一些经典问题:
我们将使用 EvalScope 模型评测框架,在 IQuiz 数据集上进行评测,这个数据集中收集了 40 道 IQ 测试和 80 道 EQ 测试选择题,其中包括一些经典问题:
- 数字9.89.11哪个大?
- 数字 9.89.11 哪个大?
- 单词 strawberry 和 blueberry 中一共有多少个 r
- 刘雨正在休假,突然被要求开车送领导去机场,他正为休假计划的泡汤而懊恼,因此在送领导时,刹车踩得比较用力。在车上,领导突然说:“小刘啊,这不愧是有着悠久历史的西安,我这坐车有一种回到古代坐马车的感觉。” 领导是什么意思?
可以点击[这里](https://modelscope.cn/datasets/AI-ModelScope/IQuiz/dataPeview)看看你能答对多少,再期待一下AI模型的表现吧。
可以点击[这里](https://modelscope.cn/datasets/AI-ModelScope/IQuiz/dataPeview)看看你能答对多少,再期待一下 AI 模型的表现吧。
### 步骤一: **创建vLLM服务器**
这里我们参照[第2节教程内容(02-Qwen3-8B-vLLM部署调用)](./02-Qwen3-8B-vLLM%20部署调用.md),使用vLLM创建兼容 OpenAI API 接口的服务器,然后使用 EvalScope进行评测。当然接入其他的 api 也是可以的。
### 步骤一: **创建 vLLM 服务器**
这里我们参照[第 2 节教程内容(02-Qwen3-8B-vLLM 部署调用)](./02-Qwen3-8B-vLLM%20部署调用.md),使用 vLLM 创建兼容 OpenAI API 接口的服务器,然后使用 EvalScope 进行评测。当然接入其他的 api 也是可以的。
在终端输入以下命令,即可用 vLLM 部署 Qwen3-8B 模型到一个兼容 OpenAI API 接口的服务器上。
```bash
VLLM_USE_MODELSCOPE=true vllm serve /root/autodl-tmp/Qwen/Qwen3-8B --served-model-name Qwen3-8B --max_model_len 8192 --enable-reasoning --reasoning-parser deepseek_r1
```
### 步骤二: **执行评测**
我们可以使用 EvalScope 命令进行评测,直接在终端输入以下命令:
@@ -83,7 +88,8 @@ evalscope eval \
也可以使用 Python 命令进行评测:
新建eval_api.py文件,并输入以下代码:
新建 eval_api.py 文件,并输入以下代码:
```
# 导入执行任务的函数和任务配置类
from evalscope.run import run_task
@@ -116,20 +122,21 @@ task_cfg = TaskConfig(
run_task(task_cfg=task_cfg)
```
新建一个bash窗口,也就是终端中执行。
新建一个 bash 窗口,也就是终端中执行。
控制台运行`python eval_api.py`命令即可。
等待3分钟左右评测就完成啦,控制台输出的结果如下图所示:
等待 3 分钟左右评测就完成啦,控制台输出的结果如下图所示:
![](./images/04-01.png)
实验结果可能有误差,因为在评测任务配置中我们把 temperature 调到了1.0,如果调小一些,可能会得到更精确的结果。
实验结果可能有误差,因为在评测任务配置中我们把 temperature 调到了 1.0,如果调小一些,可能会得到更精确的结果。
可以看到模型的得分还是不错的,模型评测的文件保存在`/root/autodl-tmp/outputs/Qwen3-8B/20250502_002809/reviews/Qwen3-8B`目录下。
![](./images/04-02.png)
## EvalScope 简介:
- EvalScope 支持多种模型评测backend,包括OpenAI API、OpenCompass、VLMEvalKit、RAGEval等。
- EvalScope 支持多种模型评测 backend,包括 OpenAI API、OpenCompass、VLMEvalKit、RAGEval 等。
![](./images/04-03.png)
@@ -1,6 +1,4 @@
# Qwen3-8B-LoRASwanLab可视化记录
# Qwen3-8B-LoRASwanLab 可视化记录
## 环境配置
@@ -17,12 +15,13 @@ pip install swanlab==0.5.7
```
> 考虑到部分同学配置环境可能会遇到一些问题,我们在 AutoDL 平台准备了 Qwen3 的环境镜像,点击下方链接并直接创建 Autodl 示例即可。
> ***https://www.codewithgpu.com/i/datawhalechina/self-llm/Qwen3***
## 模型下载
```python
# model_download.py
# model_download.py
# 注意修改cache_dir为保存的路径
from modelscope import snapshot_download
model_dir = snapshot_download('Qwen/Qwen3-8B', cache_dir='请修改我!!!', revision='master')
@@ -30,8 +29,6 @@ model_dir = snapshot_download('Qwen/Qwen3-8B', cache_dir='请修改我!!!'
print(f"模型下载完成,保存路径为:{model_dir}")
```
## 数据集构建
对大语言模型进行 `supervised-finetuning``sft`,有监督微调)的数据格式如下:
@@ -46,7 +43,7 @@ print(f"模型下载完成,保存路径为:{model_dir}")
其中,`instruction` 是用户指令,告知模型其需要完成的任务;`input` 是用户输入,是完成用户指令所必须的输入内容;`output` 是模型应该给出的输出。
有监督微调的目标是让模型具备理解并遵循用户指令的能力。因此,在构建数据集时,我们应针对我们的目标任务,针对性构建数据。比如,如果我们的目标是通过大量人物的对话数据微调得到一个能够role-play甄嬛对话风格的模型,因此在该场景下的数据示例如下:
有监督微调的目标是让模型具备理解并遵循用户指令的能力。因此,在构建数据集时,我们应针对我们的目标任务,针对性构建数据。比如,如果我们的目标是通过大量人物的对话数据微调得到一个能够 role-play 甄嬛对话风格的模型,因此在该场景下的数据示例如下:
```json
{
@@ -58,8 +55,6 @@ print(f"模型下载完成,保存路径为:{model_dir}")
所有的示例微调数据集位于 [/dataset](../dataset/huanhuan.json)
## 数据准备
`LoRA``Low-Rank Adaptation`)训练的数据是需要经过格式化、编码之后再输入给模型进行训练的,我们需要先将输入文本编码为 `input_ids`,将输出文本编码为 `labels`,编码之后的结果是向量。我们首先定义一个预处理函数,这个函数用于对每一个样本,同时编码其输入、输出文本并返回一个编码后的字典:
@@ -70,10 +65,10 @@ def process_func(example):
input_ids, attention_mask, labels = [], [], [] # 初始化返回值
# 适配chat_template
instruction = tokenizer(
f"<s><|im_start|>system\n现在你要扮演皇帝身边的女人--甄嬛<|im_end|>\n"
f"<|im_start|>user\n{example['instruction'] + example['input']}<|im_end|>\n"
f"<|im_start|>assistant\n<think>\n\n</think>\n\n",
add_special_tokens=False
f"<s><|im_start|>system\n现在你要扮演皇帝身边的女人--甄嬛<|im_end|>\n"
f"<|im_start|>user\n{example['instruction'] + example['input']}<|im_end|>\n"
f"<|im_start|>assistant\n<think>\n\n</think>\n\n",
add_special_tokens=False
)
response = tokenizer(f"{example['output']}", add_special_tokens=False)
# 将instructio部分和response部分的input_ids拼接,并在末尾添加eos token作为标记结束的token
@@ -81,7 +76,7 @@ def process_func(example):
# 注意力掩码,表示模型需要关注的位置
attention_mask = instruction["attention_mask"] + response["attention_mask"] + [1]
# 对于instruction,使用-100表示这些位置不计算loss(即模型不需要预测这部分)
labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [tokenizer.pad_token_id]
labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [tokenizer.pad_token_id]
if len(input_ids) > MAX_LENGTH: # 超出最大序列长度截断
input_ids = input_ids[:MAX_LENGTH]
attention_mask = attention_mask[:MAX_LENGTH]
@@ -131,7 +126,9 @@ print(text)
</think>
```
开启 `thinking mode`
```python
messages = [
{"role": "system", "content": "===system_message_test==="},
@@ -162,9 +159,7 @@ print(text)
<|im_start|>assistant
```
## 加载模型和tokenizer
## 加载模型和 tokenizer
```python
tokenizer = AutoTokenizer.from_pretrained('请修改我!!!/Qwen/Qwen3-8B')
@@ -172,8 +167,6 @@ tokenizer = AutoTokenizer.from_pretrained('请修改我!!!/Qwen/Qwen3-8B')
model = AutoModelForCausalLM.from_pretrained('请修改我!!!/Qwen/Qwen3-8B', device_map="auto", torch_dtype=torch.bfloat16)
```
## Lora Config
`LoraConfig`这个类中可以设置很多参数,比较重要的如下
@@ -195,13 +188,11 @@ config = LoraConfig(
)
```
## Training Arguments
- `output_dir`:模型的输出路径
- `per_device_train_batch_size`:每张卡上的 `batch_size`
- `gradient_accumulation_steps`: 梯度累计
- `gradient_accumulation_steps`: 梯度累计
- `num_train_epochs`:顾名思义 `epoch`
```python
@@ -211,7 +202,7 @@ args = TrainingArguments(
gradient_accumulation_steps=4,
logging_steps=10,
num_train_epochs=3,
save_steps=100,
save_steps=100,
learning_rate=1e-4,
save_on_each_node=True,
gradient_checkpointing=True,
@@ -219,23 +210,19 @@ args = TrainingArguments(
)
```
## SwanLab简介
## SwanLab 简介
![](./images/05-2.png)
[SwanLab](https://github.com/swanhubx/swanlab) 是一个开源的模型训练记录工具,面向AI研究者,提供了训练可视化、自动日志记录、超参数记录、实验对比、多人协同等功能。在 `SwanLab` 上,研究者能基于直观的可视化图表发现训练问题,对比多个实验找到研究灵感,并通过在线链接的分享与基于组织的多人协同训练,打破团队沟通的壁垒。
[SwanLab](https://github.com/swanhubx/swanlab) 是一个开源的模型训练记录工具,面向 AI 研究者,提供了训练可视化、自动日志记录、超参数记录、实验对比、多人协同等功能。在 `SwanLab` 上,研究者能基于直观的可视化图表发现训练问题,对比多个实验找到研究灵感,并通过在线链接的分享与基于组织的多人协同训练,打破团队沟通的壁垒。
**为什么要记录训练**
相较于软件开发,模型训练更像一个实验科学。一个品质优秀的模型背后,往往是成千上万次实验。研究者需要不断尝试、记录、对比,积累经验,才能找到最佳的模型结构、超参数与数据配比。在这之中,如何高效进行记录与对比,对于研究效率的提升至关重要。
## 实例化 SwanLabCallback
## 实例化SwanLabCallback
建议先在 [SwanLab官网](https://swanlab.cn/) 注册账号,然后在训练初始化阶段选择
建议先在 [SwanLab 官网](https://swanlab.cn/) 注册账号,然后在训练初始化阶段选择
`(2) Use an existing SwanLab account` 并使用 private API Key 登录
@@ -250,8 +237,6 @@ swanlab_callback = SwanLabCallback(
)
```
## 使用 Trainer 训练
```python
@@ -269,7 +254,7 @@ trainer.train()
TrainOutput(global_step=699, training_loss=2.6425710331557988, metrics={'train_runtime': 879.9696, 'train_samples_per_second': 12.713, 'train_steps_per_second': 0.794, 'total_flos': 5.190619083415757e+16, 'train_loss': 2.6425710331557988, 'epoch': 2.990353697749196})
```
训练完成后,打开 `SwanLab` ,可以查看训练过程中记录的参数和可视化的训练loss曲线:
训练完成后,打开 `SwanLab` ,可以查看训练过程中记录的参数和可视化的训练 loss 曲线:
![](./images/05-1.png)
@@ -277,10 +262,6 @@ TrainOutput(global_step=699, training_loss=2.6425710331557988, metrics={'train_r
[图表 Qwen3-Lora/Qwen3-8B-LoRA-shufan.jiang](https://swanlab.cn/@datawhale-kmno4/Qwen3-Lora/runs/nwvcclgt7s1r57euwr0pm/chart)
## 加载 lora 权重推理
得到任意 `checkpoints` 之后加载 `lora` 权重进行推理:
@@ -289,7 +270,7 @@ TrainOutput(global_step=699, training_loss=2.6425710331557988, metrics={'train_r
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
from peft import PeftModel
mode_path = '请修改我!!!/Qwen/Qwen3-8B' # 注意修改
lora_path = './output/Qwen3_8B_lora/checkpoint-699' # 注意修改
@@ -323,4 +304,3 @@ with torch.no_grad():
```
我是甄嬛,家父是大理寺少卿甄远道。
```
@@ -68,7 +68,7 @@ pip install swanlab==0.5.7 # 用于监控训练过程与评估模型效果
```
> 考虑到部分同学配置环境可能会遇到一些问题,我们在 AutoDL 平台准备了 Qwen3 的环境镜像,点击下方链接并直接创建 Autodl 示例即可。
> ***https://www.codewithgpu.com/i/datawhalechina/self-llm/self-llm-qwen3***
> ***https://www.codewithgpu.com/i/datawhalechina/self-llm/Qwen3***
## 2. 模型下载