Student0809 commited on
Commit
511365c
·
verified ·
1 Parent(s): 6586463

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. ms-swift/.dev_scripts/build_docs.sh +8 -0
  2. ms-swift/.github/ISSUE_TEMPLATE/bug_report.md +19 -0
  3. ms-swift/.github/workflows/lint.yaml +22 -0
  4. ms-swift/dataset_OSST.json +0 -0
  5. ms-swift/dataset_Overlap.json +0 -0
  6. ms-swift/dataset_new_3.json +0 -0
  7. ms-swift/docs/source/BestPractices/Embedding训练.md +97 -0
  8. ms-swift/docs/source/BestPractices/GRPO完整流程.md +179 -0
  9. ms-swift/docs/source/BestPractices/NPU支持.md +225 -0
  10. ms-swift/docs/source/Customization/自定义数据集.md +241 -0
  11. ms-swift/docs/source/GetStarted/SWIFT安装.md +87 -0
  12. ms-swift/docs/source/GetStarted/快速开始.md +103 -0
  13. ms-swift/docs/source/Instruction/命令行参数.md +660 -0
  14. ms-swift/docs/source/Instruction/导出与推送.md +55 -0
  15. ms-swift/docs/source/_templates/autosummary/class.rst +10 -0
  16. ms-swift/docs/source_en/BestPractices/Embedding.md +97 -0
  17. ms-swift/docs/source_en/BestPractices/GRPO-Code-Training.md +136 -0
  18. ms-swift/docs/source_en/BestPractices/GRPO-Multi-Modal-Training.md +349 -0
  19. ms-swift/docs/source_en/BestPractices/GRPO.md +298 -0
  20. ms-swift/docs/source_en/BestPractices/Rapidly-Training-VL-model.md +228 -0
  21. ms-swift/docs/source_en/Customization/Custom-dataset.md +255 -0
  22. ms-swift/docs/source_en/GetStarted/Quick-start.md +105 -0
  23. ms-swift/docs/source_en/Instruction/Export-and-push.md +57 -0
  24. ms-swift/docs/source_en/Instruction/ReleaseNote3.0.md +93 -0
  25. ms-swift/docs/source_en/_templates/classtemplate.rst +12 -0
  26. ms-swift/docs/source_en/index.rst +61 -0
  27. ms-swift/examples/app/mllm.sh +13 -0
  28. ms-swift/examples/deploy/bert/server.sh +10 -0
  29. ms-swift/examples/deploy/client/llm/base/openai_client.py +41 -0
  30. ms-swift/examples/deploy/client/llm/chat/swift_client.py +60 -0
  31. ms-swift/examples/deploy/client/mllm/openai_client.py +97 -0
  32. ms-swift/examples/deploy/client/mllm/swift_client.py +127 -0
  33. ms-swift/examples/deploy/lora/client.py +27 -0
  34. ms-swift/examples/deploy/server/README.md +9 -0
  35. ms-swift/examples/eval/llm/eval.sh +7 -0
  36. ms-swift/examples/export/merge_lora.sh +5 -0
  37. ms-swift/examples/export/quantize/mllm/gptq.sh +18 -0
  38. ms-swift/examples/export/quantize/moe/gptq.sh +13 -0
  39. ms-swift/examples/export/quantize/omni/gptq.sh +18 -0
  40. ms-swift/examples/export/quantize/reward_model/bnb.sh +12 -0
  41. ms-swift/examples/export/quantize/reward_model/gptq.sh +13 -0
  42. ms-swift/examples/infer/cli_demo.sh +6 -0
  43. ms-swift/examples/infer/demo.py +73 -0
  44. ms-swift/examples/infer/demo_agent.py +118 -0
  45. ms-swift/examples/infer/demo_bert.py +53 -0
  46. ms-swift/examples/infer/demo_hf.py +61 -0
  47. ms-swift/examples/infer/demo_lora.py +68 -0
  48. ms-swift/examples/infer/demo_mllm.py +145 -0
  49. ms-swift/examples/infer/pt/batch_ddp.sh +9 -0
  50. ms-swift/examples/infer/pt/bert.sh +8 -0
ms-swift/.dev_scripts/build_docs.sh ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ pip install -r requirements/docs.txt
2
+ cd docs
3
+ rm -rf build
4
+
5
+ # update api rst
6
+ #rm -rf source/api/
7
+ #sphinx-apidoc --module-first -o source/api/ ../modelscope/
8
+ make html
ms-swift/.github/ISSUE_TEMPLATE/bug_report.md ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Describe the bug**
11
+ What the bug is, and how to reproduce, better with screenshots(描述bug以及复现过程,最好有截图)
12
+
13
+
14
+ **Your hardware and system info**
15
+ Write your system info like CUDA version/system/GPU/torch version here(在这里给出硬件信息和系统信息,如CUDA版本,系统,GPU型号和torch版本等)
16
+
17
+
18
+ **Additional context**
19
+ Add any other context about the problem here(在这里补充其他信息)
ms-swift/.github/workflows/lint.yaml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Lint test
2
+
3
+ on: [push, pull_request]
4
+
5
+ concurrency:
6
+ group: ${{ github.workflow }}-${{ github.ref }}
7
+ cancel-in-progress: true
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+ - name: Set up Python 3.10
15
+ uses: actions/setup-python@v2
16
+ with:
17
+ python-version: '3.10'
18
+ - name: Install pre-commit hook
19
+ run: |
20
+ pip install pre-commit
21
+ - name: Linting
22
+ run: pre-commit run --all-files
ms-swift/dataset_OSST.json ADDED
The diff for this file is too large to render. See raw diff
 
ms-swift/dataset_Overlap.json ADDED
The diff for this file is too large to render. See raw diff
 
ms-swift/dataset_new_3.json ADDED
The diff for this file is too large to render. See raw diff
 
ms-swift/docs/source/BestPractices/Embedding训练.md ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Embedding训练
2
+
3
+ SWIFT已经支持Embedding模型的训练,包括纯文本和多模态两个类型。目前已经支持的模型有:
4
+
5
+ 1. modernbert embedding模型
6
+ - [ModelScope](https://modelscope.cn/models/iic/gte-modernbert-base) [Hugging Face](https://huggingface.co/Alibaba-NLP/gte-modernbert-base)
7
+ 2. gte embedding模型
8
+ - 1.5B: [ModelScope](https://www.modelscope.cn/models/iic/gte_Qwen2-1.5B-instruct) [Hugging Face](https://huggingface.co/Alibaba-NLP/gte-Qwen2-1.5B-instruct)
9
+ - 7B: [ModelScope](https://www.modelscope.cn/models/iic/gte_Qwen2-7B-instruct) [Hugging Face](https://huggingface.co/Alibaba-NLP/gte-Qwen2-7B-instruct)
10
+ 3. gme embedding模型
11
+ - 2B: [ModelScope](https://www.modelscope.cn/models/iic/gme-Qwen2-VL-2B-Instruct) [Hugging Face](https://huggingface.co/Alibaba-NLP/gme-Qwen2-VL-2B-Instruct)
12
+ - 7B: [ModelScope](https://www.modelscope.cn/models/iic/gme-Qwen2-VL-7B-Instruct) [Hugging Face](https://huggingface.co/Alibaba-NLP/gme-Qwen2-VL-7B-Instruct)
13
+
14
+ 开发者可以自行集成自己的模型,模型forward输出值需要满足:
15
+
16
+ ```json
17
+ {"last_hidden_state": some-embedding-tensor}
18
+ ```
19
+
20
+ 返回值是一个json,具有`last_hidden_state` key,value是embedding tensor即可,输入部分可以使用我们已经支持的template。
21
+
22
+ 需要注意的是,SWIFT目前支持的embedding模型均为符合纯文本或多模态LLM,目前并不支持CLIP类型的模型训练。
23
+
24
+ 此外,SWIFT支持的所有embedding模型在模型forward最后都增加了normalize,如自行增加新模型请注意增加normalize层。
25
+
26
+ ## loss
27
+
28
+ 目前SWIFT支持的Embedding模型可以使用的loss有:
29
+
30
+ - cosine_similarity: cosine相似度loss,计算两个embedding的相似度,并根据label的值拟合,实际为MSE loss
31
+ - contrastive: 可调margin的对比学习loss,label仅支持0和1两个值
32
+ - online_contrastive: 考虑hard negative和hard positive部分的contrastive loss,label仅支持0和1两个值
33
+ - infonce: 在同一个batch中不同row两两计算cosine相似度,并使row内部相似度最大,不同row相似度最小,不需要label
34
+
35
+ loss的源代码可以在[这里](https://github.com/modelscope/ms-swift/blob/main/swift/plugin/loss.py)找到。
36
+
37
+ ## 数据集格式
38
+
39
+ > 注:
40
+ > 1. 下面的多模态部分<image>标签可以出现在query/response/rejected_response的任意位置,只需要标签数量和images的值数量相等即可
41
+ > 2. 标签和images的对应顺序为先对应query中的<image>标签,然后是response中的,之后按顺序解析rejected_response中的
42
+ > 3. query代表anchor sample,response代表positive sample或对比sample,rejected_response是hard negative samples
43
+ > 4. 也支持<video>, <audio>标签,即天然支持video和audio的embedding
44
+
45
+ ### cosine_similarity loss对应的格式
46
+
47
+ ```json lines
48
+ # LLM
49
+ {"query": "sentence1", "response": "sentence2", "label": 0.8}
50
+ # MLLM
51
+ {"query": "<image>", "response": "<image>sentence", "images": ["/some/images1.jpg", "/some/images2.jpg"], "label": 0.7}
52
+ {"query": "sentence1", "response": "<image>sentence2", "images": ["/some/images1.jpg"], "label": 0.7}
53
+ ```
54
+
55
+
56
+ ### contrastive/online_contrastive loss对应的格式
57
+
58
+ ```json lines
59
+ # LLM
60
+ {"query": "sentence1", "response": "sentence2", "label": 1}
61
+ # MLLM
62
+ {"query": "<image>", "response": "sentence", "images": "/some/images.jpg", "label": 1}
63
+ {"query": "<image>sentence1", "response": "sentence2", "images": "/some/images.jpg", "label": 0}
64
+ ```
65
+
66
+ 评测的指标分别是两个embedding的欧式距离、点积等的pearson系数以及spearman系数,共八个指标。
67
+
68
+ ### infonce 格式
69
+
70
+ ```json lines
71
+ # LLM
72
+ {"query": "sentence1", "response": "sentence2"}
73
+ # MLLM
74
+ {"query": "<image>", "response": "sentence", "images": "/some/images.jpg"}
75
+ {"query": "<image>sentence1", "response": "<image>sentence2", "rejected_response": ["<image>sentence1", "<image>sentence2"], "images": ["/some/images.jpg", "/some/images.jpg", "/some/images.jpg", "/some/images.jpg"]}
76
+ ```
77
+
78
+ infonce loss支持几个环境变量:
79
+ 1. INFONCE_TEMPERATURE temperature参数,不设置的话默认值是0.01
80
+ 2. INFONCE_USE_BATCH 使用sample内部的rejected_response(hard negative样例)还是使用一个batch的所有responses,默认为True代表使用batch内部的responses
81
+ 3. INFONCE_HARD_NEGATIVES hard negatives的数量,如果不设置会使用rejected_response的所有samples,由于长度未必一致,因此会采用for循环计算loss(计算会慢),如果设置为某个数值,则如果不够会对缺失数量进行随机采样,超长会选用前`INFONCE_HARD_NEGATIVES`个
82
+ 4. INFONCE_MASK_FAKE_NEGATIVE mask掉假negative。默认为False,开启时会判断positive sample的similarity+0.1,比该值大的sample的similarity会被设置为-inf,防止positive sample泄露问题
83
+
84
+ > 也可以在数据集中将hard negatives数量设置为数量相等,这样即使不设置也不会使用for循环方式,加快计算速度
85
+ > rejected_response也可以没有,这种情况下INFONCE_USE_BATCH保持为True,会使用一个batch内部的其他samples作为rejected responses
86
+
87
+ infonce loss的评测会有下面几个指标:
88
+ - mean_neg 所有hard_negative的平均值
89
+ - mean_pos 所有positive的平均值
90
+ - margin positive-max_hard_negative的平均值
91
+
92
+ ## 脚手架
93
+
94
+ SWIFT提供了两个脚手架训练脚本:
95
+
96
+ - [gte模型](https://github.com/tastelikefeet/swift/blob/main/examples/train/embedding/train_gte.sh)
97
+ - [gme模型](https://github.com/tastelikefeet/swift/blob/main/examples/train/embedding/train_gme.sh)
ms-swift/docs/source/BestPractices/GRPO完整流程.md ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # GRPO完整实验流程
2
+
3
+ 本文从较为简单的数学任务 Coundown Game 出发,从数据集定义、奖励函数定义和GRPO训练几个步骤介绍完整的GRPO训练流程。任务定义和训练参数等参考了 [mini-deepseek-r1](https://github.com/philschmid/deep-learning-pytorch-huggingface/blob/main/training/mini-deepseek-r1-aha-grpo.ipynb)。
4
+
5
+ ## 任务与数据集定义
6
+
7
+ Coundown Game 的任务目标是根据给定的几个数字和加减乘除四种运算,得到目标数字,因此,我们定义数据集如下:
8
+ ```python
9
+ class CoundownTaskPreprocessor(ResponsePreprocessor):
10
+
11
+ def preprocess(self, row: Dict[str, Any]) -> Dict[str, Any]:
12
+ numbers = row['nums']
13
+ target = row.pop('response', None)
14
+ query = f"""
15
+ Using the numbers {numbers}, create an equation that equals {target}.
16
+ You can use basic arithmetic operations (+, -, *, /) and each number can only be used once.
17
+ Show your work in <think> </think> tags. And return the final equation and answer in <answer> </answer> tags,
18
+ for example <answer> (1 + 2) / 3 * 4 = 4 </answer>.
19
+ """
20
+ row.update({'target': target, 'query': query})
21
+ return super().preprocess(row)
22
+
23
+ register_dataset(
24
+ DatasetMeta(
25
+ ms_dataset_id='zouxuhong/Countdown-Tasks-3to4',
26
+ subsets=['default'],
27
+ preprocess_func=CoundownTaskPreprocessor(),
28
+ tags=['math']))
29
+ ```
30
+ 通过 template, 使用 numbers 和 target 完成任务定义,并给到 query 字段供模型采样使用。同时,我们需要保留 nums 和 target 两个字段,用于后续的奖励函数计算。
31
+
32
+ ## 奖励函数定义:
33
+ 本任务使用的奖励函数有两个,一个是 Deepseek-R1 中提到的格式奖励函数,另一是 Coundown Game 的准确性奖励函数。前者已经在swift中内置,通过 `--reward_funcs format` 可以直接使用,而后者需要我们自己定义,在这里我们使用 external_plugin 的方式定义准确性奖励函数,将代码放在`swift/examples/train/grpo/plugin/plugin.py`中。
34
+
35
+ 在这里,奖励函数的输入包括 completions、target 和 nums 三个字段,分别表示模型生成的文本、目标答案和可用的数字。每个都是list,支持多个 completion 同时计算。注意,在这里,除了 completions 之外的参数都是数据集中定义的字段透传而来,如果有任务上的变动,可以分别对数据集和奖励函数做对应的改变即可。
36
+ ```python
37
+ class CountdownORM(ORM):
38
+ def __call__(self, completions, target, nums, **kwargs) -> List[float]:
39
+ """
40
+ Evaluates completions based on Mathematical correctness of the answer
41
+ Args:
42
+ completions (list[str]): Generated outputs
43
+ target (list[str]): Expected answers
44
+ nums (list[str]): Available numbers
45
+ Returns:
46
+ list[float]: Reward scores
47
+ """
48
+ rewards = []
49
+ for completion, gt, numbers in zip(completions, target, nums):
50
+ try:
51
+ # Check if the format is correct
52
+ match = re.search(r"<answer>(.*?)<\/answer>", completion)
53
+ if match is None:
54
+ rewards.append(0.0)
55
+ continue
56
+ # Extract the "answer" part from the completion
57
+ equation = match.group(1).strip()
58
+ if '=' in equation:
59
+ equation = equation.split('=')[0]
60
+ # Extract all numbers from the equation
61
+ used_numbers = [int(n) for n in re.findall(r'\d+', equation)]
62
+ # Check if all numbers are used exactly once
63
+ if sorted(used_numbers) != sorted(numbers):
64
+ rewards.append(0.0)
65
+ continue
66
+ # Define a regex pattern that only allows numbers, operators, parentheses, and whitespace
67
+ allowed_pattern = r'^[\d+\-*/().\s]+$'
68
+ if not re.match(allowed_pattern, equation):
69
+ rewards.append(0.0)
70
+ continue
71
+ # Evaluate the equation with restricted globals and locals
72
+ result = eval(equation, {"__builti'ns__": None}, {})
73
+ # Check if the equation is correct and matches the ground truth
74
+ if abs(float(result) - float(gt)) < 1e-5:
75
+ rewards.append(1.0)
76
+ else:
77
+ rewards.append(0.0)
78
+ except Exception as e:
79
+ # If evaluation fails, reward is 0
80
+ rewards.append(0.0)
81
+ return rewards
82
+ orms['external_countdown'] = CountdownORM
83
+ ```
84
+
85
+ ## GRPO训练实验记录
86
+ 首先贴上GRPO的公式:
87
+
88
+ $$
89
+ \begin{aligned}
90
+ \mathcal{J}_{G R P O}(\theta) & =\mathbb{E}\left[q \sim P(Q),\left\{o_i\right\}_{i=1}^G \sim \pi_{\theta_{o l d}}(O \mid q)\right] \\
91
+ & \frac{1}{G} \sum_{i=1}^G \frac{1}{\left|o_i\right|} \sum_{t=1}^{\left|o_i\right|}\left\{\min \left[\frac{\pi_\theta\left(o_{i, t} \mid q, o_{i,<t}\right)}{\pi_{\theta_{o l d}}\left(o_{i, t} \mid q, o_{i,<t}\right)} \hat{A}_{i, t}, \operatorname{clip}\left(\frac{\pi_\theta\left(o_{i, t} \mid q, o_{i,<t}\right)}{\pi_{\theta_{o l d}}\left(o_{i, t} \mid q, o_{i,<t}\right)}, 1-\varepsilon, 1+\varepsilon\right) \hat{A}_{i, t}\right]-\beta \mathbb{D}_{K L}\left[\pi_\theta| | \pi_{r e f}\right]\right\}
92
+ \end{aligned}
93
+ $$
94
+ ### 训练参数:
95
+ 我们选取 Qwen2.5-3B-Instruct 作为基础模型进行训练,选取 Instruct 而不是基模的主要原因是可以更快地获取 format reward。我们在三卡 GPU 上进行实验,因此vllm的推理部署在最后一张卡上,而进程数设置为2,在剩下两张卡上进行梯度更新。
96
+
97
+ 由于任务较为简单,我们设置 max_completion_length 和 vllm_max_model_len 为1024,如果有更复杂的任务,可以适当加大模型输出长度,但请注意,**这两个参数越大,模型训练需要的显存越多,训练速度越慢,单个step的训练时间与max_completion_length呈现线性关系**。
98
+
99
+ 在我们的实验中,总batch_size为 $num\_processes \times per\_device\_train\_batch\_size \times gradient\_accumulation\_steps = 2 \times 8 \times 8 = 128$ 而参数设置有一个限制,即:$num\_processes \times per\_device\_train\_batch\_size$ 必须整除 $num\_generations$,其中,$num\_generations$就是GRPO公式中的 $G$,故我们设置为8。 注意,这里单卡batch_size设置也与显存息息相关,请根据显存上限设置一个合适的值。 同时,还有一个公式,即总的steps数量 :$num\_steps = epochs \times len(datasets) \times num\_generations \div batch\_size $,需要根据这个来合理规划训练的学习率和warmup设置。
100
+
101
+ 最后比较重要的设置是学习率和 beta,学习率比较好理解,而beta则是是以上公式的 $\beta$,即KL散度的梯度的权重。这两个参数设置的越大,模型收敛原则上更快,但训练往往会不稳定。经过实验,我们分别设置为 `5e-7` 和 `0.001`。在实际训练中,请根据是否出现不稳定的震荡情况适当调整这两个参数。
102
+
103
+ 对于KL散度,社区有很多的讨论,可以参考[为什么GRPO坚持用KL散度](https://zhuanlan.zhihu.com/p/25862547100)。
104
+
105
+ 其他参数的设置,没有做太多探讨,所以这里不进行详细说明。
106
+ ```bash
107
+ CUDA_VISIBLE_DEVICES=0,1,2 \
108
+ WANDB_API_KEY=your_wandb_key \
109
+ NPROC_PER_NODE=2 \
110
+ swift rlhf \
111
+ --rlhf_type grpo \
112
+ --model Qwen/Qwen2.5-3B-Instruct \
113
+ --external_plugins examples/train/grpo/plugin/plugin.py \
114
+ --reward_funcs external_countdown format \
115
+ --use_vllm true \
116
+ --vllm_device auto \
117
+ --vllm_gpu_memory_utilization 0.6 \
118
+ --train_type full \
119
+ --torch_dtype bfloat16 \
120
+ --dataset 'zouxuhong/Countdown-Tasks-3to4#50000' \
121
+ --max_length 2048 \
122
+ --max_completion_length 1024 \
123
+ --num_train_epochs 1 \
124
+ --per_device_train_batch_size 8 \
125
+ --per_device_eval_batch_size 8 \
126
+ --learning_rate 5e-7 \
127
+ --gradient_accumulation_steps 8 \
128
+ --eval_steps 500 \
129
+ --save_steps 100 \
130
+ --save_total_limit 20 \
131
+ --logging_steps 1 \
132
+ --output_dir output/GRPO_COUNTDOWN \
133
+ --warmup_ratio 0.01 \
134
+ --dataloader_num_workers 4 \
135
+ --num_generations 8 \
136
+ --temperature 1.0 \
137
+ --system 'You are a helpful assistant. You first thinks about the reasoning process in the mind and then provides the user with the answer.' \
138
+ --deepspeed zero3 \
139
+ --log_completions true \
140
+ --vllm_max_model_len 1024 \
141
+ --report_to wandb \
142
+ --beta 0.001 \
143
+ --num_iterations 1
144
+ ```
145
+ ### 实验现象
146
+ ![image.png](../../resources/grpo_countdown.png)
147
+ 从训练了2000 step的实验结果来看,有几点观察:
148
+ 1. 自定义的CoundownORM在不断增加,证明模型学习到了如何完成这一任务,最终任务成功率在0.5左右。
149
+ 2. Format Reward整体处在较高的水平,在0.9-1左右震荡。
150
+ 3. reward_std 最终在0.2-0.3左右,仍未完全收敛,模型仍然有继续提升reward的空间。
151
+ 4. 观察模型输出可以发现,相当一部分失败案例是由于模型简单加减乘除做不对,因此模型最终的收敛方向也变成了逐步运算上,如果换成更大的模型,可能有不同的收敛方向。
152
+ 5. completion length呈现先下降再增加,在200 step左右最低,然后逐渐上升到350左右。证明模型经历了思考方式的转变。
153
+ 6. 模型的思考方式在不断变化,最终模型发现做排列组合并逐步运算能更好地完成这一任务,最终的采样输出也大多是这一格式,以下是不同step的completion变化:
154
+
155
+ step 1:
156
+ ```
157
+ "<think>\nWe need to create an equation using the given numbers [70, 5, 42, 30] exactly once and make it equal to 77. \n\nFirst, let's consider the possibility of multiplication or division to get closer to 77. Notice that 77 is close to 70 and 42. If we can use these numbers together, it might work.\n\nMultiplying 70 by 1.1 would give us approximately 77, which is very close. So, let's try to make 1.1 using the remaining numbers 5 and 30. \nIf we take 30/5 = 6, and then 5/6 = 0.8333..., this isn't useful here, so let's look at other possibilities.\n\nNext, let's consider if there's another way to achieve 77 using addition, subtraction, or another combination of our numbers. Given the numbers provided, it seems that multiplication or division will be key. \n\nWe can try subtracting 5 from 30 to get 25. Then, if we divide 42 by 25, we don't get a whole number, but we can round it to the nearest whole number, 1. Now, we need to make the equation fit 77. Let's multiply 25 by 3 and add 7 (since 77 = 25*3 + 7). However, we only have one 7 available and we need to find a way to use the remaining numbers to get 7.\n\nLet's try: \n70 - 42 = 28 \nThen, 28 + 5 = 33 \nNext, 33 + 30 = 63 \nFinally, 77 - 63 = 14, which doesn't help.\n\nConsidering different combinations, one viable way is:\n(70 - 42) * (30 / 5) = 28 * 6 = 168 / 2 = 84 / 2 = 42 / 2 = 21 / 3 = 7\n\nSo, (70 - 42) * (30 / 5) = 77.\n</think>\n<answer>(70 - 42) * (30 / 5) = 77</answer>"
158
+ ```
159
+ step 200:
160
+ ```
161
+ "<think>\nWe need to use all the given numbers in a way that the resultant value of the calculation is 99. Given these restrictions, it's clear we should look into how the numbers relate and the mathematical operations that will bring them together to meet our condition.\n\nFirstly, let's evaluate the sums, differences, and multiplication/division among the numbers and their relations to see how this could lead us towards an outcome of 99.\n- Summing the three numbers: 96 + 70 + 73 = 239, which is far from 99. This shows addition isn't practical.\n- Subtracting numbers: For instance, subtracting the lowest two (i.e., 73 - 70 = 3) and combining with the highest one (96) does not work. Also, there is no other combination of subtraction that would result in the number needing to add up to 99.\n- Multiplying or dividing the numbers alone wouldn’t reach to any near solution since none of the products or division results of the numbers themselves is very close to 99. We might think more carefully about the arrangement of them using a combination of the operations provided.\nTherefore, considering the possible arrangement, a combination like taking (73 - 70 + 96) may produce an effective solution as this will sum the values in such a manner that it aligns with the goal of 99.\n\nSo we conclude that the operation: 73 - 70 + 96 gives the right sequence to equal 99.\n</think>\n\n<answer>73 - 70 + 96 = 99</answer>"
162
+ ```
163
+ step 500:
164
+ ```
165
+ "<think>\nLet's begin by exploring various possible combinations of the given numbers using the arithmetic operators we have access to.\n\n- If I add the numbers, I get: 56 + 73 + 51 = 180 which is not equal to our target number (68)\n- If I subtract one number from another I will still exceed our target value as well since the maximum difference is: |(difference between max-min):| | (73 - 51) or | (73 - 56), etc.|\n- Let's multiply the numbers individually and see if the division operation can bring us closer to the goal:\n - (73 * 51) - 56 = 3723 - 56 = 3667 which isn't the goal either.\n - The only operator left is addition and subtraction; I'll try the combination: \n ((73 - 56) + 51) gives me (17 + 51) = 68.\n \nThus, our solution fits the provided problem constraints and meets the required outcome.\n</think>\n<answer>(73 - 56) + 51 = 68</answer>"
166
+ ```
167
+
168
+ step 1000:
169
+ ```
170
+ "<think>\nWe need to form an expression using the given numbers (50, 86, and 49) such that it equals 85. Let's try different combinations:\n\n(86 - 50) + 49 = 76 + 49 = 125 (too big)\n(86 - 49) + 50 = 37 + 50 = 87 (too big)\n(86 - 50) + 49 = 37 + 49 = 86 (too big)\n(86 + 50) - 49 = 136 - 49 = 87 (too big)\n(86 - 50) + (49 - x)? Not working!\n(50 + 86) - 49: this is 136 which isn't our aim.\n50 + (86 - 49) = 50 + 37 = 87 which wasn't correct.\n50 - 86 + 49 = -16 + 49: This doesn't match up as well.\n86 - (50 + 49) = 86 - 99 which doesn't work too.\n\nWe try one more:\n(86 + 49) - 50 = 135 - 50 = 85!\n\nThat's it!\n</think>\n\n<answer>(86 + 49) - 50 = 85</answer>"
171
+ ```
172
+
173
+ step 2000:
174
+ ```
175
+ "<think>\nWe need to form an expression using the numbers 58, 9, 78, and 44 which evaluates to 73. Let's try different combinations:\n(78 - 58) + (9 + 44) = 10 + 53 = 63 (too low)\n(78 - 58) + (9 - 44) = 20 - 35 = -15 (too low)\n(78 - 58) + (44 - 9) = 20 + 35 = 55 (too low)\n(78 + 58) - (9 + 44) = 136 - 53 = 83 (too high)\n(78 + 58) - (9 - 44) = 136 + 35 = 171 (too high)\n(78 + 58) - (44 + 9) = 136 + 53 = 189 (too high)\n(78 + 9) - (58 + 44) = 87 - 102 = -15 (too low)\n(78 + 9) - (58 - 44) = 87 - 14 = 73\n\nSo our solution is: (78 + 9) - (58 - 44) = 73</think>\n\n<answer>(78 + 9) - (58 - 44) = 73</answer>"
176
+ ```
177
+
178
+ 附learning_rate和beta分别取值1e-6和0.04的不稳定实验记录,模型在step 200左右出现了震荡,format和CountdownORM瞬间走低:
179
+ ![](../../resources/grpo_countdown_1.png)
ms-swift/docs/source/BestPractices/NPU支持.md ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NPU支持
2
+ 作者: [chuanzhubin](https://github.com/chuanzhubin)
3
+
4
+ ## 环境准备
5
+
6
+ 实验环境:8 * 昇腾910B3 64G (设备由[@chuanzhubin](https://github.com/chuanzhubin)提供, 感谢对modelscope和swift的支持~)
7
+
8
+ ```shell
9
+ # 创建新的conda虚拟环境(可选)
10
+ conda create -n swift-npu python=3.10 -y
11
+ conda activate swift-npu
12
+
13
+ # 设置pip全局镜像 (可选,加速下载)
14
+ pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
15
+ pip install ms-swift -U
16
+
17
+ # 安装torch-npu
18
+ pip install torch-npu decorator
19
+ # 如果你想要使用deepspeed (控制显存占用,训练速度会有一定下降)
20
+ pip install deepspeed
21
+ ```
22
+
23
+ 测试环境是否安装正确,NPU能否被正常加载:
24
+ ```python
25
+ from transformers.utils import is_torch_npu_available
26
+ import torch
27
+
28
+ print(is_torch_npu_available()) # True
29
+ print(torch.npu.device_count()) # 8
30
+ print(torch.randn(10, device='npu:0'))
31
+ ```
32
+
33
+ 查看NPU的P2P连接,这里看到每个NPU都通过7条HCCS与其他NPU互联
34
+ ```shell
35
+ (valle) root@valle:~/src# npu-smi info -t topo
36
+ NPU0 NPU1 NPU2 NPU3 NPU4 NPU5 NPU6 NPU7 CPU Affinity
37
+ NPU0 X HCCS HCCS HCCS HCCS HCCS HCCS HCCS 144-167
38
+ NPU1 HCCS X HCCS HCCS HCCS HCCS HCCS HCCS 144-167
39
+ NPU2 HCCS HCCS X HCCS HCCS HCCS HCCS HCCS 96-119
40
+ NPU3 HCCS HCCS HCCS X HCCS HCCS HCCS HCCS 96-119
41
+ NPU4 HCCS HCCS HCCS HCCS X HCCS HCCS HCCS 0-23
42
+ NPU5 HCCS HCCS HCCS HCCS HCCS X HCCS HCCS 0-23
43
+ NPU6 HCCS HCCS HCCS HCCS HCCS HCCS X HCCS 48-71
44
+ NPU7 HCCS HCCS HCCS HCCS HCCS HCCS HCCS X 48-71
45
+
46
+ Legend:
47
+
48
+ X = Self
49
+ SYS = Path traversing PCIe and NUMA nodes. Nodes are connected through SMP, such as QPI, UPI.
50
+ PHB = Path traversing PCIe and the PCIe host bridge of a CPU.
51
+ PIX = Path traversing a single PCIe switch
52
+ PXB = Path traversing multiple PCIe switches
53
+ HCCS = Connection traversing HCCS.
54
+ NA = Unknown relationship.
55
+ ```
56
+
57
+ 查看NPU状态, npu-smi命令详解可以查看[官方文档](https://support.huawei.com/enterprise/zh/doc/EDOC1100079287/10dcd668)
58
+ ```shell
59
+ (valle) root@valle:~/src# npu-smi info
60
+ +------------------------------------------------------------------------------------------------+
61
+ | npu-smi 24.1.rc1.b030 Version: 24.1.rc1.b030 |
62
+ +---------------------------+---------------+----------------------------------------------------+
63
+ | NPU Name | Health | Power(W) Temp(C) Hugepages-Usage(page)|
64
+ | Chip | Bus-Id | AICore(%) Memory-Usage(MB) HBM-Usage(MB) |
65
+ +===========================+===============+====================================================+
66
+ | 0 910B3 | OK | 101.8 43 0 / 0 |
67
+ | 0 | 0000:C1:00.0 | 0 0 / 0 3318 / 65536 |
68
+ +===========================+===============+====================================================+
69
+ | 1 910B3 | OK | 92.0 39 0 / 0 |
70
+ | 0 | 0000:C2:00.0 | 0 0 / 0 3314 / 65536 |
71
+ +===========================+===============+====================================================+
72
+ | 2 910B3 | OK | 102.0 40 0 / 0 |
73
+ | 0 | 0000:81:00.0 | 0 0 / 0 3314 / 65536 |
74
+ +===========================+===============+====================================================+
75
+ | 3 910B3 | OK | 99.8 40 0 / 0 |
76
+ | 0 | 0000:82:00.0 | 0 0 / 0 3314 / 65536 |
77
+ +===========================+===============+====================================================+
78
+ | 4 910B3 | OK | 98.6 45 0 / 0 |
79
+ | 0 | 0000:01:00.0 | 0 0 / 0 3314 / 65536 |
80
+ +===========================+===============+====================================================+
81
+ | 5 910B3 | OK | 99.7 44 0 / 0 |
82
+ | 0 | 0000:02:00.0 | 0 0 / 0 3314 / 65536 |
83
+ +===========================+===============+====================================================+
84
+ | 6 910B3 | OK | 103.8 45 0 / 0 |
85
+ | 0 | 0000:41:00.0 | 0 0 / 0 3314 / 65536 |
86
+ +===========================+===============+====================================================+
87
+ | 7 910B3 | OK | 98.2 44 0 / 0 |
88
+ | 0 | 0000:42:00.0 | 0 0 / 0 3315 / 65536 |
89
+ +===========================+===============+====================================================+
90
+ ```
91
+
92
+ ## 微调
93
+ 以下介绍LoRA的微调, 全参数微调设置参数`--train_type full`即可.
94
+
95
+ | 模型大小 | NPU数量 | deepspeed类型 | 最大显存占用量 |
96
+ |------|-------|-------------|-----------|
97
+ | 7B | 1 | None | 1 * 28 GB |
98
+ | 7B | 4 | None | 4 * 22 GB |
99
+ | 7B | 4 | zero2 | 4 * 28 GB |
100
+ | 7B | 4 | zero3 | 4 * 22 GB |
101
+ | 7B | 8 | None | 8 * 22 GB |
102
+ | 14B | 1 | None | 1 * 45 GB |
103
+ | 14B | 8 | None | 8 * 51 GB |
104
+ | 14B | 8 | zero2 | 8 * 49 GB |
105
+ | 14B | 8 | zero3 | 8 * 31 GB |
106
+
107
+ ### 单卡训练
108
+
109
+ 通过如下命令启动单卡微调: (注意: 如果微调期间出现nan的情况, 请设置`--torch_dtype float32`.)
110
+
111
+ ```shell
112
+ # 实验环境: 昇腾910B3
113
+ # 显存需求: 28 GB
114
+ # 运行时长: 8小时
115
+ ASCEND_RT_VISIBLE_DEVICES=0 \
116
+ swift sft \
117
+ --model Qwen/Qwen2-7B-Instruct \
118
+ --dataset AI-ModelScope/blossom-math-v2 \
119
+ --num_train_epochs 5 \
120
+ --train_type lora \
121
+ --output_dir output \
122
+ --learning_rate 1e-4 \
123
+ --gradient_accumulation_steps 16 \
124
+ --save_steps 100 \
125
+ --eval_steps 100
126
+
127
+ ```
128
+
129
+
130
+ ### 数据并行训练
131
+ 我们使用其中的4卡进行ddp训练
132
+
133
+ ```shell
134
+ # 实验环境: 4 * 昇腾910B3
135
+ # 显存需求: 4 * 22 GB
136
+ # 运行时长: 2小时
137
+ NPROC_PER_NODE=4 \
138
+ ASCEND_RT_VISIBLE_DEVICES=0,1,2,3 \
139
+ swift sft \
140
+ --model Qwen/Qwen2-7B-Instruct \
141
+ --dataset AI-ModelScope/blossom-math-v2 \
142
+ --num_train_epochs 5 \
143
+ --train_type lora \
144
+ --output_dir output \
145
+ ...
146
+ ```
147
+
148
+
149
+ ### Deepspeed训练
150
+
151
+ ZeRO2:
152
+ ```shell
153
+ # 实验环境: 4 * 昇腾910B3
154
+ # 显存需求: 4 * 28GB
155
+ # 运行时长: 3.5小时
156
+ NPROC_PER_NODE=4 \
157
+ ASCEND_RT_VISIBLE_DEVICES=0,1,2,3 \
158
+ swift sft \
159
+ --model Qwen/Qwen2-7B-Instruct \
160
+ --dataset AI-ModelScope/blossom-math-v2 \
161
+ --num_train_epochs 5 \
162
+ --train_type lora \
163
+ --output_dir output \
164
+ --deepspeed zero2 \
165
+ ...
166
+ ```
167
+
168
+ ZeRO3:
169
+ ```shell
170
+ # 实验环境: 4 * 昇腾910B3
171
+ # 显存需求: 4 * 22 GB
172
+ # 运行时长: 8.5小时
173
+ NPROC_PER_NODE=4 \
174
+ ASCEND_RT_VISIBLE_DEVICES=0,1,2,3 \
175
+ swift sft \
176
+ --model Qwen/Qwen2-7B-Instruct \
177
+ --dataset AI-ModelScope/blossom-math-v2 \
178
+ --num_train_epochs 5 \
179
+ --train_type lora \
180
+ --output_dir output \
181
+ --deepspeed zero3 \
182
+ ...
183
+ ```
184
+
185
+
186
+ ## 推理
187
+
188
+ 原始模型:
189
+ ```shell
190
+ ASCEND_RT_VISIBLE_DEVICES=0 swift infer \
191
+ --model Qwen/Qwen2-7B-Instruct \
192
+ --stream true --max_new_tokens 2048
193
+ ```
194
+
195
+ LoRA微调后:
196
+ ```shell
197
+ ASCEND_RT_VISIBLE_DEVICES=0 swift infer \
198
+ --adapters xxx/checkpoint-xxx --load_data_args true \
199
+ --stream true --max_new_tokens 2048
200
+
201
+ # merge-lora并推理
202
+ ASCEND_RT_VISIBLE_DEVICES=0 swift export --adapters xx/checkpoint-xxx --merge_lora true
203
+
204
+ ASCEND_RT_VISIBLE_DEVICES=0 swift infer \
205
+ --model xxx/checkpoint-xxx-merged --load_data_args true \
206
+ --stream true --max_new_tokens 2048
207
+ ```
208
+
209
+
210
+ ## 部署
211
+ NPU不支持使用vllm进行推理/部署加速, 但是可以使用原生pytorch进行部署.
212
+
213
+ 原始模型:
214
+ ```shell
215
+ ASCEND_RT_VISIBLE_DEVICES=0 swift deploy --model Qwen/Qwen2-7B-Instruct --max_new_tokens 2048
216
+ ```
217
+
218
+ LoRA微调后:
219
+ ```shell
220
+ ASCEND_RT_VISIBLE_DEVICES=0 swift deploy --adapters xxx/checkpoint-xxx --max_new_tokens 2048
221
+
222
+ # merge-lora并推理
223
+ ASCEND_RT_VISIBLE_DEVICES=0 swift export --adapters xx/checkpoint-xxx --merge_lora true
224
+ ASCEND_RT_VISIBLE_DEVICES=0 swift deploy --model xxx/checkpoint-xxx-merged --max_new_tokens 2048
225
+ ```
ms-swift/docs/source/Customization/自定义数据集.md ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 自定义数据集
2
+
3
+ 自定义数据集的接入方法有三种,对预处理函数的控制能力逐渐加强,但接入难度逐步增加。例如,方案一最为方便,但对预处理函数的控制能力最弱,需要预先对数据集进行转换,传入特定格式的数据集:
4
+ 1. 【推荐】直接使用命令行传参的方式接入,即`--dataset <dataset_path1> <dataset_path2>`。这将使用AutoPreprocessor将数据集转换为标准格式(支持4种数据集格式,具体查看下面对AutoPreprocessor的介绍)。你可以使用`--columns`进行列名转换。支持传入csv、json、jsonl、txt、文件夹(例如git clone开源数据集)。该方案不需要修改dataset_info.json,适合刚接触ms-swift的用户,下面两种方案适合对ms-swift进行拓展的开发者。
5
+ 2. 添加数据集到`dataset_info.json`中,可以参考ms-swift内置的[dataset_info.json](https://github.com/modelscope/ms-swift/blob/main/swift/llm/dataset/data/dataset_info.json)。该方案也将使用AutoPreprocessor将数据集转换为标准格式。dataset_info.json为数据集元信息的list,每一项元信息必填ms_dataset_id/hf_dataset_id/dataset_path中的一项,通过`columns`字段进行列名转换。添加到`dataset_info.json`或者注册的数据集在运行[run_dataset_info.py](https://github.com/modelscope/ms-swift/blob/main/scripts/utils/run_dataset_info.py)时将自动产生[支持的数据集文档](https://swift.readthedocs.io/zh-cn/latest/Instruction/%E6%94%AF%E6%8C%81%E7%9A%84%E6%A8%A1%E5%9E%8B%E5%92%8C%E6%95%B0%E6%8D%AE%E9%9B%86.html)。此外,你可以采用外接`dataset_info.json`的方式,使用`--custom_dataset_info xxx.json`解析json文件(方便pip install而非git clone的用户),然后指定`--dataset <dataset_id/dataset_dir/dataset_path>`。
6
+ 3. 手动注册数据集,具有最灵活的预处理函数定制能力,支持使用函数对数据集进行预处理,但难度较高。可以参考[内置数据集](https://github.com/modelscope/ms-swift/blob/main/swift/llm/dataset/dataset/llm.py)或者[examples](https://github.com/modelscope/swift/blob/main/examples/custom)中的样例。你可以通过指定`--custom_register_path xxx.py`解析外置注册内容(方便pip install而非git clone的用户)。
7
+ - 方案一和二在实现中借助了方案三,只是注册的过程为自动发生。
8
+
9
+ 以下将对`AutoPreprocessor`可以处理的数据集格式进行介绍:
10
+
11
+ ms-swift的标准数据集格式可接受的keys包括: 'messages'、'rejected_response'、'label'、'images'、'videos'、'audios'、'tools'和'objects'。其中'messages'是必需的key,'rejected_response'用于DPO等RLHF训练,'label'用于KTO训练和分类模型训练,'images'、'videos'、'audios'用于存储多模态数据的路径或者url,'tools'用于Agent任务,'objects'用于grounding任务。
12
+
13
+ ms-swift中存在三种核心预处理器:`MessagesPreprocessor`、`AlpacaPreprocessor`、`ResponsePreprocessor`。MessagesPreprocessor用于将类messages和sharegpt格式的数据集转换为标准格式,AlpacaPreprocessor则转换alpaca格式的数据集,ResponsePreprocessor则转换类query/response格式的数据集。`AutoPreprocessor`则自动选择合适的预处理进行处理。
14
+
15
+ 以下四种格式在`AutoPreprocessor`处理下都会转换成ms-swift标准格式中的messages字段,即都可以直接使用`--dataset <dataset-path>`接入:
16
+
17
+ messages格式(标准格式):
18
+ ```jsonl
19
+ {"messages": [{"role": "system", "content": "<system>"}, {"role": "user", "content": "<query1>"}, {"role": "assistant", "content": "<response1>"}, {"role": "user", "content": "<query2>"}, {"role": "assistant", "content": "<response2>"}]}
20
+ ```
21
+ - 注意:system部分是可选的。数据集中的system优先级高于命令行传入的`--system`,最后是定义在template中的`default_system`。
22
+
23
+ sharegpt格式:
24
+ ```jsonl
25
+ {"system": "<system>", "conversation": [{"human": "<query1>", "assistant": "<resonse1>"}, {"human": "<query2>", "assistant": "<resonse2>"}]}
26
+ ```
27
+
28
+ alpaca格式:
29
+ ```jsonl
30
+ {"system": "<system>", "instruction": "<query-inst>", "input": "<query-input>", "output": "<response>"}
31
+ ```
32
+
33
+ query-response格式:
34
+ ```jsonl
35
+ {"system": "<system>", "query": "<query2>", "response": "<response2>", "history": [["<query1>", "<response1>"]]}
36
+ ```
37
+
38
+ ## 标准数据集格式
39
+
40
+ 以下给出ms-swift的标准数据集格式,其中system字段是可选的,默认使用template中定义的`default_system`。之前介绍的4种数据集格式也可以被AutoPreprocessor处理成标准数据集格式。
41
+
42
+ ### 预训练
43
+
44
+ ```jsonl
45
+ {"messages": [{"role": "assistant", "content": "I love music"}]}
46
+ {"messages": [{"role": "assistant", "content": "教练我要打篮球"}]}
47
+ {"messages": [{"role": "assistant", "content": "西红柿鸡蛋盖饭和地三鲜盖饭哪个更权威"}]}
48
+ ```
49
+
50
+ ### 监督微调
51
+
52
+ ```jsonl
53
+ {"messages": [{"role": "system", "content": "你是个有用无害的助手"}, {"role": "user", "content": "告诉我明天��天气"}, {"role": "assistant", "content": "明天天气晴朗"}]}
54
+ {"messages": [{"role": "system", "content": "你是个有用无害的数学计算器"}, {"role": "user", "content": "1+1等于几"}, {"role": "assistant", "content": "等于2"}, {"role": "user", "content": "再加1呢"}, {"role": "assistant", "content": "等于3"}]}
55
+ ```
56
+
57
+ ### RLHF
58
+
59
+ #### DPO/ORPO/CPO/SimPO/RM
60
+
61
+ ```jsonl
62
+ {"messages": [{"role": "system", "content": "你是个有用无害的助手"}, {"role": "user", "content": "告诉我明天的天气"}, {"role": "assistant", "content": "明天天气晴朗"}], "rejected_response": "我不知道"}
63
+ {"messages": [{"role": "system", "content": "你是个有用无害的数学计算器"}, {"role": "user", "content": "1+1等于几"}, {"role": "assistant", "content": "等于2"}, {"role": "user", "content": "再加1呢"}, {"role": "assistant", "content": "等于3"}], "rejected_response": "我不知道"}
64
+ ```
65
+
66
+ #### KTO
67
+
68
+ ```jsonl
69
+ {"messages": [{"role": "system", "content": "你是个有用无害的助手"}, {"role": "user", "content": "告诉我明天的天气"}, {"role": "assistant", "content": "我不知道"}], "label": false}
70
+ {"messages": [{"role": "system", "content": "你是个有用无害的数学计算器"}, {"role": "user", "content": "1+1等于几"}, {"role": "assistant", "content": "等于2"}, {"role": "user", "content": "再加1呢"}, {"role": "assistant", "content": "等于3"}], "label": true}
71
+ ```
72
+
73
+ #### PPO/GRPO
74
+
75
+ ```jsonl
76
+ {"messages": [{"role": "system", "content": "你是个有用无害的助手"}, {"role": "user", "content": "告诉我明天的天气"}]}
77
+ {"messages": [{"role": "system", "content": "你是个有用无害的数学计算器"}, {"role": "user", "content": "1+1等于几"}, {"role": "assistant", "content": "等于2"}, {"role": "user", "content": "再加1呢"}]}
78
+ {"messages": [{"role": "user", "content": "你的名字是什么"}]}
79
+ ```
80
+ - 注意:GRPO会透传所有额外的字段内容给ORM,而不像其他训练方法,默认将额外的字段删除。例如: 你可以额外传入'solution'。自定义的ORM需要包含一个位置参数completions,其他为关键词参数,由数据集额外字段透传。
81
+
82
+
83
+ ### 序列分类
84
+
85
+ **单标签任务**:
86
+ ```jsonl
87
+ {"messages": [{"role": "user", "content": "今天天气真好呀"}], "label": 1}
88
+ {"messages": [{"role": "user", "content": "今天真倒霉"}], "label": 0}
89
+ {"messages": [{"role": "user", "content": "好开心"}], "label": 1}
90
+ ```
91
+ **多标签任务**:
92
+ ```jsonl
93
+ {"messages": [{"role": "user", "content": "<sentence>"}], "label": [1, 3, 5]}
94
+ ```
95
+
96
+ **单回归任务**:
97
+ ```jsonl
98
+ {"messages": [{"role": "user", "content": "求两句话的相似度,范围为0-1。\nsentence1: <sentence1>\nsentence2: <sentence2>"}], "label": 0.8}
99
+ ```
100
+ **多回归任务**:
101
+
102
+ ```jsonl
103
+ {"messages": [{"role": "user", "content": "<sentence>"}], "label": [1.2, -0.6, 0.8]}
104
+ ```
105
+
106
+ ### Embedding
107
+
108
+ 请参考[embedding训练文档](../BestPractices/Embedding训练.md#数据集格式)
109
+
110
+ ### 多模态
111
+
112
+ 对于多模态数据集,和上述任务的格式相同。区别在于增加了`images`, `videos`, `audios`几个key,分别代表多模态资源的url或者path(推荐使用绝对路径),`<image>` `<video>` `<audio>`标签代表了插入图片/视频/音频的位置,ms-swift支持多图片/视频/音频的情况。这些特殊tokens将在预处理的时候进行替换,参考[这里](https://github.com/modelscope/ms-swift/blob/main/swift/llm/template/template/qwen.py#L198)。下面给出的四条示例分别展示了纯文本,以及包含图像、视频和音频数据的数据格式。
113
+
114
+ 预训练:
115
+ ```
116
+ {"messages": [{"role": "assistant", "content": "预训练的文本在这里"}]}
117
+ {"messages": [{"role": "assistant", "content": "<image>是一只小狗,<image>是一只小猫"}], "images": ["/xxx/x.jpg", "/xxx/x.png"]}
118
+ {"messages": [{"role": "assistant", "content": "<audio>描述了今天天气真不错"}], "audios": ["/xxx/x.wav"]}
119
+ {"messages": [{"role": "assistant", "content": "<image>是一个大象,<video>是一只狮子在跑步"}], "images": ["/xxx/x.jpg"], "videos": ["/xxx/x.mp4"]}
120
+ ```
121
+
122
+ 微调:
123
+ ```jsonl
124
+ {"messages": [{"role": "user", "content": "浙江的省会在哪?"}, {"role": "assistant", "content": "浙江的省会在杭州。"}]}
125
+ {"messages": [{"role": "user", "content": "<image><image>两张图片有什么区别"}, {"role": "assistant", "content": "前一张是小猫,后一张是小狗"}], "images": ["/xxx/x.jpg", "/xxx/x.png"]}
126
+ {"messages": [{"role": "user", "content": "<audio>语音说了什么"}, {"role": "assistant", "content": "今天天气真好呀"}], "audios": ["/xxx/x.mp3"]}
127
+ {"messages": [{"role": "system", "content": "你是个有用无害的助手"}, {"role": "user", "content": "<image>图片中是什么,<video>视频中是什么"}, {"role": "assistant", "content": "图片中是一个大象,视频中是一只小狗在草地上奔跑"}], "images": ["/xxx/x.jpg"], "videos": ["/xxx/x.mp4"]}
128
+ ```
129
+
130
+ 多模态模型的RLHF和序列分类的数据格式可以参考���文本大模型的格式,并在此基础上增加`images`等字段。
131
+
132
+ #### grounding
133
+
134
+ 如果是grounding(物体检测)任务,SWIFT支持两种方式:
135
+ 1. 直接使用对应模型grounding任务的数据集格式,例如qwen2-vl的格式如下:
136
+
137
+ ```jsonl
138
+ {"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "<image>描述图像"}, {"role": "assistant", "content": "<|object_ref_start|>一只狗<|object_ref_end|><|box_start|>(221,423),(569,886)<|box_end|>和<|object_ref_start|>一个女人<|object_ref_end|><|box_start|>(451,381),(733,793)<|box_end|>正在沙滩上玩耍"}], "images": ["/xxx/x.jpg"]}
139
+ {"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "<image>找到图像中的<|object_ref_start|>羊<|object_ref_end|>"}, {"role": "assistant", "content": "<|box_start|>(101,201),(150,266)<|box_end|><|box_start|>(401,601),(550,666)<|box_end|>"}], "images": ["/xxx/x.jpg"]}
140
+ {"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "<image>帮我打开谷歌浏览器"}, {"role": "assistant", "content": "Action: click(start_box='<|box_start|>(246,113)<|box_end|>')"}], "images": ["/xxx/x.jpg"]}
141
+ ```
142
+ 使用这种类型的数据需要注意:
143
+ - 不同模型grounding任务的特殊字符和数据集格式不同。
144
+ - 不同模型对bbox是否归一化的处理不同。例如:qwen2.5-vl使用绝对坐标,而qwen2-vl、internvl2.5需要对bbox的坐标进行千分位坐标归一化。
145
+
146
+ 2. 使用SWIFT的grounding数据格式:
147
+
148
+ ```jsonl
149
+ {"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "<image>描述图像"}, {"role": "assistant", "content": "<ref-object><bbox>和<ref-object><bbox>正在沙滩上玩耍"}], "images": ["/xxx/x.jpg"], "objects": {"ref": ["一只狗", "一个女人"], "bbox": [[331.5, 761.4, 853.5, 1594.8], [676.5, 685.8, 1099.5, 1427.4]]}}
150
+ {"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "<image>找到图像中的<ref-object>"}, {"role": "assistant", "content": "<bbox><bbox>"}], "images": ["/xxx/x.jpg"], "objects": {"ref": ["羊"], "bbox": [[90.9, 160.8, 135, 212.8], [360.9, 480.8, 495, 532.8]]}}
151
+ {"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "<image>帮我打开谷歌浏览器"}, {"role": "assistant", "content": "Action: click(start_box='<bbox>')"}], "images": ["/xxx/x.jpg"], "objects": {"ref": [], "bbox": [[615, 226]]}}
152
+ ```
153
+ 该格式将自动转换数据集格式为对应模型的grounding任务格式,且选择对应模型的bbox归一化方式。该格式比通用格式多了objects字段,该字段包含的字段有:
154
+ - ref: 用于替换`<ref-object>`。
155
+ - bbox: 用于替换`<bbox>`。若bbox中每个box长度为2,则代表x和y坐标,若box长度为4,则代表2个点的x和y坐标。
156
+ - bbox_type: 可选项为'real','norm1'。默认为'real',即bbox为真实bbox值。若是'norm1',则bbox已经归一化为0~1。
157
+ - image_id: 该参数只有当bbox_type为'real'时生效。代表bbox对应的图片是第几张,用于缩放bbox。索引从0开始,默认全为第0张。
158
+
159
+ ### 文生图格式
160
+
161
+ ```jsonl
162
+ {"messages": [{"role": "system", "content": "你是个有用无害的助手"}, {"role": "user", "content": "给我画出一个苹果"}, {"role": "assistant", "content": "<image>"}], "images": ["/xxx/x.jpg"]}
163
+ ```
164
+
165
+ ### Agent格式
166
+ 这里分别提供了纯文本Agent和多模态Agent的示例数据样本:
167
+ ```jsonl
168
+ {"tools": ["{\"type\": \"function\", \"function\": {\"name\": \"realtime_aqi\", \"description\": \"天气预报。获取实时空气质量。当前空气质量,PM2.5,PM10信息\", \"parameters\": {\"type\": \"object\", \"properties\": {\"city\": {\"type\": \"string\", \"description\": \"城市名,例如:上海\"}}, \"required\": [\"city\"]}}}"], "messages": [{"role": "user", "content": "北京和上海今天的天气情况"}, {"role": "tool_call", "content": "{\"name\": \"realtime_aqi\", \"arguments\": {\"city\": \"北京\"}}"}, {"role": "tool_call", "content": "{\"name\": \"realtime_aqi\", \"arguments\": {\"city\": \"上海\"}}"}, {"role": "tool_response", "content": "{\"city\": \"北京\", \"aqi\": \"10\", \"unit\": \"celsius\"}"}, {"role": "tool_response", "content": "{\"city\": \"上海\", \"aqi\": \"72\", \"unit\": \"fahrenheit\"}"}, {"role": "assistant", "content": "根据天气预报工具,北京今天的空气质量指数为10,属于良好水平;上海今天的空气质量指数为72,属于轻度污染水平。"}]}
169
+ {"tools": ["{\"type\": \"function\", \"function\": {\"name\": \"click\", \"description\": \"点击屏幕中的某个位置\", \"parameters\": {\"type\": \"object\", \"properties\": {\"x\": {\"type\": \"integer\", \"description\": \"横坐标,表示屏幕上的水平位置\"}, \"y\": {\"type\": \"integer\", \"description\": \"纵坐标,表示屏幕上的垂直位置\"}}, \"required\": [\"x\", \"y\"]}}}"], "messages": [{"role": "user", "content": "<image>现在几点了?"}, {"role": "assistant", "content": "<think>\n我可以通过打开日历App来获取当前时间。\n</think>\n"}, {"role": "tool_call", "content": "{\"name\": \"click\", \"arguments\": {\"x\": 105, \"y\": 132}}"}, {"role": "tool_response", "content": "{\"images\": \"<image>\", \"status\": \"success\"}"}, {"role": "assistant", "content": "成功打开日历App,现在的时间为中午11点"}], "images": ["desktop.png", "calendar.png"]}
170
+ ```
171
+ - agent_template为"react_en", "hermes"等情况下,该格式适配所有模型Agent训练,可以轻松在不同模型间切换。
172
+ - 其中tools是一个`List[str]`,其中每一个tool需要是json字符串,messages中role为'tool_call'和'tool_response/tool'的content部分都需要是json字符串。
173
+ - tools字段将在训练/推理时和`{"role": "system", ...}"`部分组合,根据agent_template组成完整的system部分。
174
+ - `{"role": "tool_call", ...}`部分将根据agent_template自动转成对应格式的`{"role": "assistant", ...}`,多条连续的`{"role": "assistant", ...}`将拼接在一起组成完整的assistant_content。
175
+ - `{"role": "tool_response", ...}`也可以写成`{"role": "tool", ...}`,这两种写法是等价的。该部分也将根据`agent_template`自动转换格式。该部分在训练时将不进行损失的计算,角色类似于`{"role": "user", ...}`。
176
+ - 该格式支持并行调用工具,例子参考第一条数据样本。多模态Agent数据样本中`<image>`标签数量应与"images"长度相同,其标签位置代表图像特征的插入位置。当然也支持其他模态,例如audios, videos。
177
+ - 更多请参考[Agent文档](../Instruction/Agent支持.md)。
178
+
179
+ ## dataset_info.json
180
+
181
+ 可以参考ms-swift内置的[dataset_info.json](https://github.com/modelscope/ms-swift/blob/main/swift/llm/dataset/data/dataset_info.json)。该方案使用AutoPreprocessor预处理函数将数据集转换为标准格式。dataset_info.json文件中包含了数据集元信息的list,以下为一些例子:
182
+
183
+ ```json
184
+ [
185
+ {
186
+ "ms_dataset_id": "xxx/xxx"
187
+ },
188
+ {
189
+ "dataset_path": "<dataset_dir/dataset_path>"
190
+ },
191
+ {
192
+ "ms_dataset_id": "<dataset_id>",
193
+ "subsets": ["v1"],
194
+ "split": ["train", "validation"],
195
+ "columns": {
196
+ "input": "query",
197
+ "output": "response"
198
+ }
199
+ },
200
+ {
201
+ "ms_dataset_id": "<dataset_id>",
202
+ "hf_dataset_id": "<hf_dataset_id>",
203
+ "subsets": [{
204
+ "subset": "subset1",
205
+ "columns": {
206
+ "problem": "query",
207
+ "content": "response"
208
+ }
209
+ },
210
+ {
211
+ "subset": "subset2",
212
+ "columns": {
213
+ "messages": "_",
214
+ "new_messages": "messages"
215
+ }
216
+ }]
217
+ }
218
+ ]
219
+ ```
220
+
221
+ 支持以下参数:
222
+ - ms_dataset_id: 参考DatasetMeta参数。
223
+ - hf_dataset_id: 参考DatasetMeta参数。
224
+ - dataset_path: 参考DatasetMeta参数。
225
+ - dataset_name: 参考DatasetMeta参数。
226
+ - subsets: 参考DatasetMeta参数。
227
+ - split: 参考DatasetMeta参数。
228
+ - columns: 在数据集进行预处理前,对数据集进行列名转换。
229
+
230
+
231
+ ## 数据集注册
232
+
233
+ register_dataset会在`DATASET_MAPPING`中注册数据集,调用函数`register_dataset(dataset_meta)`即可完成数据集注册,其中dataset_meta将存储模型的元信息。DatasetMeta的参数列表如下:
234
+ - ms_dataset_id: ModelScope的dataset_id,默认为None。
235
+ - hf_dataset_id: HuggingFace的dataset_id,默认为None。
236
+ - dataset_path: dataset的本地路径(推荐使用绝对路径)。默认为None。
237
+ - dataset_name: 数据集别名,可以通过`--dataset <dataset_name>`指定数据集,这在dataset_path很长时很方便。默认为None。
238
+ - subsets: 子数据集的名字列表或者`SubsetDataset`对象的列表,默认为`['default']`。(只有dataset_id或者dataset_dir(git clone开源数据集)有子数据集和split的概念)。
239
+ - split: 默认为`['train']`。
240
+ - preprocess_func: 预处理函数或可调用对象,默认为`AutoPreprocessor()`。该预处理函数接口为传入`HfDataset`,并返回满足标准格式的`HfDataset`。
241
+ - load_function: 默认为`DatasetLoader.load`。若需要自定义载入函数,则该载入函数需返回满足标准格式的`HfDataset`,这将抛弃ms-swift的数据集载入机制,提供给用户最大的自由度。通常该参数不需要进行修改。
ms-swift/docs/source/GetStarted/SWIFT安装.md ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SWIFT安装
2
+
3
+ ## Wheel包安装
4
+
5
+ 可以使用pip进行安装:
6
+
7
+ ```shell
8
+ pip install 'ms-swift'
9
+ # 使用评测
10
+ pip install 'ms-swift[eval]' -U
11
+ # 全能力
12
+ pip install 'ms-swift[all]' -U
13
+ ```
14
+
15
+ ## 源代码安装
16
+
17
+ ```shell
18
+ # pip install git+https://github.com/modelscope/ms-swift.git
19
+
20
+ # 全能力
21
+ # pip install "git+https://github.com/modelscope/ms-swift.git#egg=ms-swift[all]"
22
+
23
+ git clone https://github.com/modelscope/ms-swift.git
24
+ cd ms-swift
25
+ pip install -e .
26
+
27
+ # 全能力
28
+ # pip install -e '.[all]'
29
+ ```
30
+
31
+ ## 旧版本
32
+
33
+ SWIFT在3.0版本开始进行了不兼容式重构,如果需要使用2.x旧版本,请执行如下命令进行安装:
34
+ ```shell
35
+ pip install ms-swift==2.*
36
+ ```
37
+
38
+ ## 镜像
39
+
40
+ ```
41
+ # vllm0.8.3 (该版本vllm可能导致部分GRPO训练卡住,GRPO建议优先使用vllm0.7.3)
42
+ modelscope-registry.cn-hangzhou.cr.aliyuncs.com/modelscope-repo/modelscope:ubuntu22.04-cuda12.4.0-py311-torch2.6.0-vllm0.8.3-modelscope1.25.0-swift3.3.0.post1
43
+ modelscope-registry.us-west-1.cr.aliyuncs.com/modelscope-repo/modelscope:ubuntu22.04-cuda12.4.0-py311-torch2.6.0-vllm0.8.3-modelscope1.25.0-swift3.3.0.post1
44
+
45
+ # vllm0.7.3
46
+ modelscope-registry.us-west-1.cr.aliyuncs.com/modelscope-repo/modelscope:ubuntu22.04-cuda12.4.0-py311-torch2.5.1-modelscope1.25.0-swift3.2.2
47
+ ```
48
+
49
+ 更多镜像可以查看[这里](https://modelscope.cn/docs/intro/environment-setup#%E6%9C%80%E6%96%B0%E9%95%9C%E5%83%8F)
50
+
51
+ ## 支持的硬件
52
+
53
+ | 硬件环境 | 备注 |
54
+ | --------------- | --------------------------- |
55
+ | A10/A100/H100 | |
56
+ | RTX20/30/40系列 | |
57
+ | T4/V100 | 部分模型出现NAN |
58
+ | Ascend NPU | 部分模型出现NAN或算子不支持 |
59
+ | MPS | |
60
+ | CPU | |
61
+
62
+
63
+ ## 运行环境
64
+
65
+ | | 范围 | 推荐 | 备注 |
66
+ | ------ |--------------| ---- | --|
67
+ | python | >=3.9 | 3.10 ||
68
+ | cuda | | cuda12 |使用cpu、npu、mps则无需安装|
69
+ | torch | >=2.0 | ||
70
+ | transformers | >=4.33 | 4.51 ||
71
+ | modelscope | >=1.23 | ||
72
+ | peft | >=0.11,<0.16 | ||
73
+ | trl | >=0.13,<0.18 | 0.17 |RLHF|
74
+ | deepspeed | >=0.14 | 0.14.5 |训练|
75
+ | vllm | >=0.5.1 | 0.7.3/0.8 |推理/部署/评测|
76
+ | lmdeploy | >=0.5 | 0.8 |推理/部署/评测|
77
+ | evalscope | >=0.11 | |评测|
78
+
79
+ 更多可选依赖可以参考[这里](https://github.com/modelscope/ms-swift/blob/main/requirements/install_all.sh)。
80
+
81
+ ## Notebook环境
82
+
83
+ Swift支持训练的绝大多数模型都可以在`A10`显卡上使用,用户可以使用ModelScope官方提供的免费显卡资源:
84
+
85
+ 1. 进入[ModelScope](https://www.modelscope.cn)官方网站并登录
86
+ 2. 点击左侧的`我的Notebook`并开启一个免费GPU实例
87
+ 3. 愉快地薅A10显卡羊毛
ms-swift/docs/source/GetStarted/快速开始.md ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 快速开始
2
+
3
+ ms-swift是魔搭社区提供的大模型与多模态大模型训练部署框架,现已支持500+大模型与200+多模态大模型的训练(预训练、微调、人类对齐)、推理、评测、量化与部署。模型开发者可以在ms-swift框架中一站式完成围绕大模型的各类需求。目前ms-swift的主要能力包含:
4
+
5
+ - 🍎 模型类型:支持500+纯文本大模型、200+多模态大模型以及All-to-All全模态模型、序列分类模型、Embedding模型训练到部署全流程。
6
+ - 数据集类型:内置150+预训练、微调、人类对齐、多模态等各种类型的数据集,并支持自定义数据集。
7
+ - 硬件支持:CPU、RTX系列、T4/V100、A10/A100/H100、Ascend NPU、MPS等。
8
+ - 🍊 轻量训练:支持了LoRA、QLoRA、DoRA、LoRA+、ReFT、RS-LoRA、LLaMAPro、Adapter、GaLore、Q-Galore、LISA、UnSloth、Liger-Kernel等轻量微调方式。
9
+ - 分布式训练:支持分布式数据并行(DDP)、device_map简易模型并行、DeepSpeed ZeRO2 ZeRO3、FSDP等分布式训练技术。
10
+ - 量化训练:支持对BNB、AWQ、GPTQ、AQLM、HQQ、EETQ量化模型进行训练。
11
+ - RLHF训练:支持纯文本大模型和多模态大模型的DPO、GRPO、RM、PPO、KTO、CPO、SimPO、ORPO等人类对齐训练方法。
12
+ - 🍓 多模态训练:支持对图像、视频和语音不同模态模型进行训练,支持VQA、Caption、OCR、Grounding任务的训练。
13
+ - 界面训练:以界面的方式提供训练、推理、评测、量化的能力,完成大模型的全链路。
14
+ - 插件化与拓展:支持自定义模型和数据集拓展,支持对loss、metric、trainer、loss-scale、callback、optimizer等组件进行自定义。
15
+ - 🍉 工具箱能力:除了对大模型和多模态大模型的训练支持外,还支持其推理、评测、量化和部署全流程。
16
+ - 推理加速:支持PyTorch、vLLM、LmDeploy推理加速引擎,并提供OpenAI接口,为推理、部署和评测模块提供加速。
17
+ - 模型评测:以EvalScope作为评测后端,支持100+评测数据集对纯文本和多模态模型进行评测。
18
+ - 模型量化:支持AWQ、GPTQ和BNB的量化导出,导出的模型支持使用vLLM/LmDeploy推理加速,并支持继续训练。
19
+
20
+
21
+ ## 安装
22
+
23
+ ms-swift的安装请参考[安装文档](./SWIFT安装.md)。
24
+
25
+ ## 使用样例
26
+
27
+ 10分钟在单卡3090上对Qwen2.5-7B-Instruct进行自我认知微调:
28
+ ```shell
29
+ # 22GB
30
+ CUDA_VISIBLE_DEVICES=0 \
31
+ swift sft \
32
+ --model Qwen/Qwen2.5-7B-Instruct \
33
+ --train_type lora \
34
+ --dataset 'AI-ModelScope/alpaca-gpt4-data-zh#500' \
35
+ 'AI-ModelScope/alpaca-gpt4-data-en#500' \
36
+ 'swift/self-cognition#500' \
37
+ --torch_dtype bfloat16 \
38
+ --num_train_epochs 1 \
39
+ --per_device_train_batch_size 1 \
40
+ --per_device_eval_batch_size 1 \
41
+ --learning_rate 1e-4 \
42
+ --lora_rank 8 \
43
+ --lora_alpha 32 \
44
+ --target_modules all-linear \
45
+ --gradient_accumulation_steps 16 \
46
+ --eval_steps 50 \
47
+ --save_steps 50 \
48
+ --save_total_limit 2 \
49
+ --logging_steps 5 \
50
+ --max_length 2048 \
51
+ --output_dir output \
52
+ --system 'You are a helpful assistant.' \
53
+ --warmup_ratio 0.05 \
54
+ --dataloader_num_workers 4 \
55
+ --model_author swift \
56
+ --model_name swift-robot
57
+ ```
58
+
59
+ 小贴士:
60
+ - 如果要使用自定义数据集进行训练,你可以参考[这里](../Customization/自定义数据集.md)组织数据集格式,并指定`--dataset <dataset_path>`。
61
+ - `--model_author`和`--model_name`参数只有当数据集中包含`swift/self-cognition`时才生效。
62
+ - 如果要使用其他模型进行训练,你只需要修改`--model <model_id/model_path>`即可。
63
+ - 默认使用ModelScope进行模型和数据集的下载。如果要使用HuggingFace,指定`--use_hf true`即可。
64
+
65
+ 训练完成后,使用以下命令对训练后的权重进行推理:
66
+ - 这里的`--adapters`需要替换成训练生成的last checkpoint文件夹。由于adapters文件夹中包含了训练的参数文件`args.json`,因此不需要额外指定`--model`,`--system`,swift会自动读取这些参数。如果要关闭此行为,可以设置`--load_args false`。
67
+
68
+ ```shell
69
+ # 使用交互式命令行进行推理
70
+ CUDA_VISIBLE_DEVICES=0 \
71
+ swift infer \
72
+ --adapters output/vx-xxx/checkpoint-xxx \
73
+ --stream true \
74
+ --temperature 0 \
75
+ --max_new_tokens 2048
76
+
77
+ # merge-lora并使用vLLM进行推理加速
78
+ CUDA_VISIBLE_DEVICES=0 \
79
+ swift infer \
80
+ --adapters output/vx-xxx/checkpoint-xxx \
81
+ --stream true \
82
+ --merge_lora true \
83
+ --infer_backend vllm \
84
+ --max_model_len 8192 \
85
+ --temperature 0 \
86
+ --max_new_tokens 2048
87
+ ```
88
+
89
+ 最后,使用以下命令将模型推送到ModelScope:
90
+ ```shell
91
+ CUDA_VISIBLE_DEVICES=0 \
92
+ swift export \
93
+ --adapters output/vx-xxx/checkpoint-xxx \
94
+ --push_to_hub true \
95
+ --hub_model_id '<your-model-id>' \
96
+ --hub_token '<your-sdk-token>' \
97
+ --use_hf false
98
+ ```
99
+
100
+ ## 了解更多
101
+
102
+ - 更多Shell脚本:[https://github.com/modelscope/ms-swift/tree/main/examples](https://github.com/modelscope/ms-swift/tree/main/examples)
103
+ - 使用Python:[https://github.com/modelscope/ms-swift/blob/main/examples/notebook/qwen2_5-self-cognition/self-cognition-sft.ipynb](https://github.com/modelscope/ms-swift/blob/main/examples/notebook/qwen2_5-self-cognition/self-cognition-sft.ipynb)
ms-swift/docs/source/Instruction/命令行参数.md ADDED
@@ -0,0 +1,660 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 命令行参数
2
+
3
+ 命令行参数的介绍会分为基本参数,原子参数、集成参数和特定模型参数。命令行最终使用的参数列表为集成参数。集成参数继承自基本参数和一些原子参数。特定模型参数是针对于具体模型的参数,可以通过`--model_kwargs'`或者环境变量进行设置。Megatron-SWIFT命令行参数介绍可以在[Megatron-SWIFT训练文档](./Megatron-SWIFT训练.md)中找到。
4
+
5
+ 提示:
6
+ - 命令行传入list使用空格隔开即可。例如:`--dataset <dataset_path1> <dataset_path2>`。
7
+ - 命令行传入dict使用json。例如:`--model_kwargs '{"fps_max_frames": 12}'`。
8
+ - 带🔥的参数为重要参数,刚熟悉ms-swift的用户可以先关注这些命令行参数。
9
+
10
+ ## 基本参数
11
+
12
+ - 🔥tuner_backend: 可选为'peft','unsloth'。默认为'peft'。
13
+ - 🔥train_type: 可选为: 'lora'、'full'、'longlora'、'adalora'、'llamapro'、'adapter'、'vera'、'boft'、'fourierft'、'reft'。默认为'lora'。
14
+ - 🔥adapters: 用于指定adapter的id/path的list,默认为`[]`。
15
+ - external_plugins: 外部plugin py文件列表,这些文件会被注册进plugin模块中,例子请参见[这里](https://github.com/modelscope/ms-swift/tree/main/examples/train/grpo/plugin/run_external_rm.sh)。
16
+ - seed: 默认为42。
17
+ - model_kwargs: 特定模型可传入的额外参数,该参数列表会在训练推理时打印日志进行提示。例如`--model_kwargs '{"fps_max_frames": 12}'`。
18
+ - load_args: 当指定`--resume_from_checkpoint`、`--model`、`--adapters`会读取保存文件中的`args.json`,将默认为None的`基本参数`(除去数据参数和生成参数)进行赋值(可通过手动传入进行覆盖)。推理和导出时默认为True,训练时默认为False。
19
+ - load_data_args: 如果将该参数设置为True,则会额外读取`args.json`中的数据参数。默认为False。
20
+ - use_hf: 控制模型下载、数据集下载、模型推送使用ModelScope还是HuggingFace。默认为False,使用ModelScope。
21
+ - hub_token: hub token. modelscope的hub token可以查看[这里](https://modelscope.cn/my/myaccesstoken)。
22
+ - custom_register_path: 自定义模型、对话模板和数据集注册的`.py`文件路径的list。默认为`[]`。
23
+
24
+ ### 模型参数
25
+ - 🔥model: 模型id或模型本地路径。如果是自定义模型请配合`model_type`和`template`使用,具体可以参考[自定义模型](../Customization/自定义模型.md)。
26
+ - model_type: 模型类型。相同的模型架构、template、模型加载过程被定义为一个model_type。默认为None,根据`--model`的后缀和config.json中的architectures属性进行自动选择。
27
+ - model_revision: 模型版本,默认为None。
28
+ - task_type: 默认为'causal_lm'。可选为'causal_lm'、'seq_cls'、'embedding'。seq_cls的例子可以查看[这里](https://github.com/modelscope/ms-swift/tree/main/examples/train/seq_cls),embedding的例子查看[这里](https://github.com/modelscope/ms-swift/tree/main/examples/train/embedding)。
29
+ - 🔥torch_dtype: 模型权重的数据类型,支持`float16`,`bfloat16`,`float32`。默认为None,从config.json文件中读取。
30
+ - attn_impl: attention类型,可选项为`flash_attn`, `sdpa`, `eager`。默认使用sdpa,若不支持则使用eager。
31
+ - 注意:这三种实现并不一定都支持,这取决于对应模型的支持情况。
32
+ - num_labels: 分类模型(即`--task_type seq_cls`)需要指定该参数。代表标签数量,默认为None。
33
+ - problem_type: 分类模型(即`--task_type seq_cls`)需要指定该参数。可选为'regression', 'single_label_classification', 'multi_label_classification'。默认为None,根据num_labels和数据集类型进行自动设置。
34
+ - rope_scaling: rope类型,支持`linear`和`dynamic`,请配合`max_length`共同使用。默认为None。
35
+ - device_map: 模型使用的device_map配置,例如:'auto'、'cpu'、json字符串、json文件路径。默认为None,根据设备和分布式训练情况自动设置。
36
+ - max_memory: device_map设置为'auto'或者'sequential'时,会根据max_memory进行模型权重的device分配,例如:`--max_memory '{0: "20GB", 1: "20GB"}'`。默认为None。
37
+ - local_repo_path: 部分模型在加载时依赖于github repo。为了避免`git clone`时遇到网络问题,可以直接使用本地repo。该参数需要传入本地repo的路径, 默认为`None`。
38
+ - init_strategy: 加载模型时,初始化模型中所有未初始化的参数。可选为'zero', 'uniform', 'normal', 'xavier_uniform', 'xavier_normal', 'kaiming_uniform', 'kaiming_normal', 'orthogonal'。默认为None。
39
+
40
+
41
+ ### 数据参数
42
+ - 🔥dataset: 数据集id或路径的list。默认为`[]`。每个数据集的传入格式为:`数据集id or 数据集路径:子数据集#采样数量`,其中子数据集和取样数据可选。本地数据集支持jsonl、csv、json、文件夹等。开源数据集可以通过git clone到本地并将文件夹传入而离线使用。自定义数据集格式可以参考[自定义数据集](../Customization/自定义数据集.md)。你可以传入`--dataset <dataset1> <dataset2>`来使用多个数据集。
43
+ - 子数据集: 该参数只有当dataset为ID或者文件夹时生效。若注册时指定了subsets,且只有一个子数据集,则默认选择注册时指定的子数据集,否则默认为'default'。你可以使用`/`来选择多个子数据集,例如:`<dataset_id>:subset1/subset2`。你也可以使用'all'来选择所有的子数据集,例如:`<dataset_id>:all`。
44
+ - 采样数量: 默认使用完整的数据集。若采样数少于数据样本总数,则进行随机选择(不重复采样)。若采样数高于数据样本总数,则只额外随机采样`采样数%数据样本总数`的样本,数据样本重复采样`采样数//数据样本总数`次。注意:流式数据集只进行顺序采样。若设置`--dataset_shuffle false`,则非流式数据集也进行顺序采样。
45
+ - 🔥val_dataset: 验证集id或路径的list。默认为`[]`。
46
+ - 🔥split_dataset_ratio: 不指定val_dataset时如何拆分训练集和验证集,默认为0.01。若不需要切分验证集,设置为0即可。
47
+ - data_seed: 数据集随机种子,默认为42。
48
+ - 🔥dataset_num_proc: 数据集预处理的进程数,默认为1。
49
+ - 🔥load_from_cache_file: 是否从缓存中加载数据集,默认为False。
50
+ - dataset_shuffle: 是否对dataset进行随机操作。默认为True。
51
+ - 注意:CPT/SFT的随机包括两个部分:数据集的随机,由`dataset_shuffle`控制;train_dataloader中的随机,由`train_dataloader_shuffle`控制。
52
+ - val_dataset_shuffle: 是否对val_dataset进行随机操作。默认为False。
53
+ - 🔥streaming: 流式读取并处理数据集,默认False。通常在处理大型数据集时,设置为True。
54
+ - 注意:需要额外设置`--max_steps`,因为流式数据集无法获得其长度。你可以通过设置`--save_strategy epoch`并设置较大的max_steps来实现与`--num_train_epochs`等效的训练。或者,你也可以设置`max_epochs`确保训练到对应epochs时退出训练,并对权重进行验证和保存。
55
+ - interleave_prob: 默认值为 None。在组合多个数据集时,默认使用 `concatenate_datasets` 函数;如果设置了该参数,则会使用 `interleave_datasets` 函数。该参数通常用于流式数据集的组合,并会作为参数传入 `interleave_datasets` 函数中。
56
+ - stopping_strategy: 可选为"first_exhausted", "all_exhausted",默认为"first_exhausted"。传入interleave_datasets函数中。
57
+ - shuffle_buffer_size: 该参数用于指定流式数据集的随机buffer大小,默认为1000。
58
+ - download_mode: 数据集下载模式,包含`reuse_dataset_if_exists`和`force_redownload`,默认为reuse_dataset_if_exists。
59
+ - columns: 用于对数据集进行列映射,使数据集满足AutoPreprocessor可以处理的样式,具体查看[这里](../Customization/自定义数据集.md)。你可以传入json字符串,例如:`'{"text1": "query", "text2": "response"}'`,默认为None。
60
+ - strict: 如果为True,则数据集只要某行有问题直接抛错,否则会丢弃出错数据样本。默认False。
61
+ - remove_unused_columns: 是否删除数据集中不被使用的列,默认为True。
62
+ - 🔥model_name: 仅用于自我认知任务,只对`swift/self-cognition`数据集生效,替换掉数据集中的`{{NAME}}`通配符。传入模型中文名和英文名,以空格分隔,例如:`--model_name 小黄 'Xiao Huang'`。默认为None。
63
+ - 🔥model_author: 仅用于自我认知任务,只对`swift/self-cognition`数据集生效,替换掉数据集中的`{{AUTHOR}}`通配符。传入模型作者的中文名和英文名,以空格分隔,例如:`--model_author '魔搭' 'ModelScope'`。默认为None。
64
+ - custom_dataset_info: 自定义数据集注册的json文件路径,参考[自定义数据集](../Customization/自定义数据集.md)。默认为`[]`。
65
+
66
+ ### 模板参数
67
+ - 🔥template: 对话模板类型。默认为None,自动选择对应model的template类型。
68
+ - 🔥system: 自定义system字段,可以传入字符串或者txt文件路径。默认为None,使用template的默认system。
69
+ - 注意:数据集中的system优先级最高,然后是`--system`,最后是定义在template中的`default_system`。
70
+ - 🔥max_length: 单样本的tokens最大长度。默认为None,设置为模型支持的tokens最大长度(max_model_len)。
71
+ - 注意:PPO、GRPO和推理情况下,max_length代表max_prompt_length。
72
+ - truncation_strategy: 如果单样本的tokens超过`max_length`如何处理,支持`delete`, `left`和`right`,代表删除、左侧裁剪和右侧裁剪,默认为'delete'。
73
+ - 🔥max_pixels: 多模态模型输入图片的最大像素数(H\*W),将超过该限制的图像进行缩放。默认为None,不限制最大像素数。
74
+ - 🔥agent_template: Agent模板,确定如何将工具列表转换成system,如何从模型回复中提取toolcall,以及确定`{"role": "tool_call", "content": "xxx"}`, `{"role": "tool_response", "content": "xxx"}`的模板格式。可选为"react_en", "hermes", "glm4", "qwen_en", "toolbench"等,更多请查看[这里](https://github.com/modelscope/ms-swift/blob/main/swift/plugin/agent_template/__init__.py)。默认为None,根据模型类型进行选择。
75
+ - response_prefix: response的前缀字符,例如QwQ-32B将response_prefix设置为`'<think>\n'`。默认为None,根据模型自动设置。
76
+ - 注意:若对deepseek-r1/qwq模型使用不包含`<think>...</think>`的数据集进行训练,请加在推理训练后模型时额外传入`--response_prefix ''`。
77
+ - padding_side: 当训练`batch_size>=2`时的padding_side,可选值为'left'、'right',默认为'right'。(推理时的batch_size>=2时,只进行左padding)。
78
+ - loss_scale: 训练tokens的loss权重设置。默认为`'default'`,代表所有response(含history)以1计算交叉熵损失,忽略对应agent_template的`tool_response`的损失。可选值为'default'、'last_round'、'all'、'ignore_empty_think',以及agent需要的loss_scale: 'react'、'hermes'、'qwen'、'agentflan'、'alpha_umi'。agent部分可以查看[插件化](../Customization/插件化.md)和[Agent文档](./Agent支持.md)。
79
+ - 'last_round': 只计算最后一轮response的损失。
80
+ - 'all': 计算所有tokens的损失。
81
+ - 'ignore_empty_think': 在`'default'`的基础上,忽略空的`'<think>\n\n</think>\n\n'`损失计算,具体请参考[此issue](https://github.com/modelscope/ms-swift/issues/4030)。
82
+ - 'react', 'hermes', 'qwen': 在`'default'`的基础上,将`tool_call`部分的loss权重调整为2。
83
+ - sequence_parallel_size: 序列并行大小,默认是1。当前支持pt/sft/dpo。训练脚本参考[这里](https://github.com/modelscope/ms-swift/tree/main/examples/train/long_text/sequence_parallel.sh)。
84
+ - use_chat_template: 使用chat模板或generation模板,默认为`True`。`swift pt`会自动设置为generation模板。
85
+ - template_backend: 选择template后端,可选为'swift'、'jinja',默认为'swift'。如果使用jinja,则使用transformers的`apply_chat_template`。
86
+ - 注意:jinja的template后端只支持推理,不支持训练。
87
+
88
+ ### 生成参数
89
+ 参考[generation_config](https://huggingface.co/docs/transformers/main_classes/text_generation#transformers.GenerationConfig)文档。
90
+
91
+ - 🔥max_new_tokens: 推理最大生成新tokens的数量。默认为None,无限制。
92
+ - temperature: 温度参数。默认为None,读取generation_config.json。
93
+ - 注意:do_sample参数在本版本中移除了,请将temperature配置为0来达到相同效果。
94
+ - top_k: top_k参数,默认为None。读取generation_config.json。
95
+ - top_p: top_p参数,默认为None。读取generation_config.json。
96
+ - repetition_penalty: 重复惩罚项。默认为None,读取generation_config.json。
97
+ - num_beams: beam search的并行保留数量,默认为1。
98
+ - 🔥stream: 流式输出,默认为`False`。
99
+ - stop_words: 除了eos_token外额外的停止词,默认为`[]`。
100
+ - 注意:eos_token会在输出respsone中被删除,额外停止词会在输出中保留。
101
+ - logprobs: 是否输出logprobs,默认为False。
102
+ - top_logprobs: 输出top_logprobs的数量,默认为None。
103
+
104
+ ### 量化参数
105
+ 以下为加载模型时量化的参数,具体含义可以查看[量化](https://huggingface.co/docs/transformers/main/en/main_classes/quantization)文档。这里不包含`swift export`中涉及的`gptq`、`awq`量化参数。
106
+
107
+ - 🔥quant_method: 加载模型时采用的量化方法,可选项为`bnb`、`hqq`、`eetq`。
108
+ - 🔥quant_bits: 量化bits数,默认为None。
109
+ - hqq_axis: hqq量化axis,默认为None。
110
+ - bnb_4bit_compute_dtype: bnb量化计算类型,可选为`float16`、`bfloat16`、`float32`。默认为None,设置为`torch_dtype`。
111
+ - bnb_4bit_quant_type: bnb量化类型,支持`fp4`和`nf4`,默认为`nf4`。
112
+ - bnb_4bit_use_double_quant: 是否使用双重量化,默认为`True`。
113
+ - bnb_4bit_quant_storage: bnb量化存储类型,默认为None。
114
+
115
+
116
+ ## 原子参数
117
+
118
+ ### Seq2SeqTrainer参数
119
+
120
+ 该参数列表继承自transformers `Seq2SeqTrainingArguments`,ms-swift对其默认值进行了覆盖。未列出的请参考[HF官方文档](https://huggingface.co/docs/transformers/main/en/main_classes/trainer#transformers.Seq2SeqTrainingArguments)。
121
+
122
+ - 🔥output_dir: 默认为None,设置为`output/<model_name>`。
123
+ - 🔥gradient_checkpointing: 是否使用gradient_checkpointing,默认为True。
124
+ - 🔥deepspeed: 默认为None。可以设置为'zero0', 'zero1', 'zero2', 'zero3', 'zero2_offload', 'zero3_offload'来使用ms-swift内置的deepspeed配置文件。
125
+ - zero_hpz_partition_size: 默认为None,这个参数是ZeRO++的特性,即node内模型分片,node间数据分片,如果遇到grad_norm NaN,请尝试使用`--torch_dtype float16`。
126
+ - 🔥per_device_train_batch_size: 默认值1。
127
+ - 🔥per_device_eval_batch_size: 默认值1。
128
+ - 🔥gradient_accumulation_steps: 梯度累加,默认为None,即设置gradient_accumulation_steps使得total_batch_size>=16。total_batch_size等于`per_device_train_batch_size * gradient_accumulation_steps * world_size`。
129
+ - weight_decay: weight衰减系数,默认值0.1。
130
+ - adam_beta2: 默认为0.95。
131
+ - 🔥learning_rate: 学习率,全参数默认为1e-5,LoRA等tuners为1e-4。
132
+ - lr_scheduler_type: lr_scheduler类型,默认为'cosine'。
133
+ - lr_scheduler_kwargs: lr_scheduler其他参数。默认为None。
134
+ - 🔥gradient_checkpointing_kwargs: 传入`torch.utils.checkpoint`中的参数。例如设置为`--gradient_checkpointing_kwargs '{"use_reentrant": false}'`。默认为None。
135
+ - full_determinism: 确保训练中获得可重现的结果,注意:这会对性能产生负面影响。默认为False。
136
+ - 🔥report_to: 默认值为`tensorboard`。你也可以指定`--report_to tensorboard wandb swanlab`、`--report_to all`。
137
+ - logging_first_step: 是否记录第一个step的日志,默认为True。
138
+ - logging_steps: 日志打印间隔,默认为5。
139
+ - predict_with_generate: 验证时使用生成式的方式,默认为False。
140
+ - metric_for_best_model: 默认为None,即当`predict_with_generate`设置为False时,设置为'loss',否则设置为'rouge-l'(在PPO训练时,不进行默认值设置;GRPO训练设置为'reward')。
141
+ - greater_is_better: 默认为None,即当`metric_for_best_model`含'loss'时,设置为False,否则设置为True。
142
+ - max_epochs: 训练到`max_epochs`时强制退出训练,并对权重进行验证和保存。该参数在使用流式数据集时很有用。默认为None。
143
+
144
+ 其他重要参数:
145
+ - 🔥num_train_epochs: 训练的epoch数,默认为3。
146
+ - 🔥save_strategy: 保存模型的策略,可选为'no'、'steps'、'epoch',默认为'steps'。
147
+ - 🔥save_steps: 默认为500。
148
+ - 🔥eval_strategy: 评估策略。默认为None,跟随`save_strategy`的策略。
149
+ - 🔥eval_steps: 默认为None,如果存在评估数据集,则跟随`save_steps`的策略。
150
+ - 🔥save_total_limit: 最多保存的checkpoint数,会将过期的checkpoint进行删除。默认为None,保存所有的checkpoint。
151
+ - max_steps: 最大训练的steps数。在数据集为流式时需要被设置。默认为-1。
152
+ - 🔥warmup_ratio: 默认为0.。
153
+ - save_on_each_node: 默认为False。在多机训练时需要被考虑。
154
+ - save_only_model: 是否只保存模型权重而不包含优化器状态,随机种子状态等内容。默认为False。
155
+ - 🔥resume_from_checkpoint: 断点续训参数,传入checkpoint路径。默认为None。
156
+ - 注意: resume_from_checkpoint会读取模型权重,优化器权重,随机种子,并从上次训练的steps继续开始训练。你可以指定`--resume_only_model`只读取模型权重。
157
+ - 🔥ddp_backend: 可选为"nccl"、"gloo"、"mpi"、"ccl"、"hccl" 、"cncl"、"mccl"。默认为None,进行自动选择。
158
+ - 🔥ddp_find_unused_parameters: 默认为None。
159
+ - ddp_timeout: 默认为1800,单位为秒。
160
+ - 🔥dataloader_num_workers: 默认为None,若是windows平台,则设置为0,否则设置为1。
161
+ - dataloader_pin_memory: 默认为True。
162
+ - dataloader_persistent_workers: 默认为False。
163
+ - dataloader_prefetch_factor: 默认为None,若`dataloader_num_workers > 0`,设置为10。
164
+ - train_dataloader_shuffle: CPT/SFT训练的dataloader是否随机,默认为True。该参数对IterableDataset无效。IterableDataset采用顺序的方式读取。
165
+ - 🔥neftune_noise_alpha: neftune添加的噪声系数, 默认为0,通常可以设置为5、10、15。
166
+ - 🔥use_liger_kernel: 是否启用[Liger](https://github.com/linkedin/Liger-Kernel)内核加速训练并减少显存消耗。默认为False。示例shell参考[这里](https://github.com/modelscope/ms-swift/blob/main/examples/train/liger)。
167
+ - average_tokens_across_devices: 是否在设备之间进行token数平均。如果设置为True,将使用all_reduce同步`num_tokens_in_batch`以进行精确的损失计算。默认为False。
168
+ - max_grad_norm: 梯度裁剪。默认为1.。
169
+ - push_to_hub: 推送checkpoint到hub。默认为False。
170
+ - hub_model_id: 默认为None。
171
+ - hub_private_repo: 默认为False。
172
+
173
+ ### Tuner参数
174
+ - 🔥freeze_llm: 该参数只对多模态模型生效,可用于全参和LoRA,但含义不同。若是全参数训练,将freeze_llm设置为True将会将llm部分权重进行冻结,若是LoRA训练且`target_modules`设置为'all-linear',将freeze_llm设置为True将会取消在llm部分添加LoRA模块。该参数默认为False。
175
+ - 🔥freeze_vit: 该参数只对多模态模型生效,可用于全参和LoRA,含义参考`freeze_llm`。默认为True。
176
+ - 🔥freeze_aligner: 该参数只对多模态模型生效,可用于全参和LoRA,含义参考`freeze_llm`。默认为True。
177
+ - 🔥target_modules: 指定lora模块, 默认为`all-linear`. 在LLM和多模态LLM中,其行为有所不同. 若是LLM则自动寻找除lm_head外的linear并附加tuner,若是多模态LLM,则默认只在LLM上附加tuner,该行为可以被`freeze_llm`、`freeze_vit`、`freeze_aligner`控制。该参数���限于LoRA,可用于其他tuners。
178
+ - 🔥target_regex: 指定lora模块的regex表达式,默认为`None`。如果该值传入,则target_modules参数失效。该参数不限于LoRA,可用于其他tuners。
179
+ - init_weights: 初始化weights的方法,LoRA可以指定为`true`、`false`、`gaussian`、`pissa`、`pissa_niter_[number of iters]`,Bone可以指定为`true`、`false`、`bat`。默认值`true`。
180
+ - 🔥modules_to_save: 在已附加tuner后,额外指定一部分原模型模块参与训练和存储。默认为`[]`. 该参数不限于LoRA,可用于其他tuners。
181
+
182
+ #### 全参
183
+ - freeze_parameters: 需要被冻结参数的前缀,默认为`[]`。
184
+ - freeze_parameters_regex: 需要被冻结参数的正则表达式,默认为None。
185
+ - freeze_parameters_ratio: 从下往上冻结的参数比例,默认为0。可设置为1将所有参数冻结,结合`trainable_parameters`设置可训练参数。
186
+ - trainable_parameters: 额外可训练参数的前缀,默认为`[]`。
187
+ - trainable_parameters_regex: 匹配额外可训练参数的正则表达式,默认为None。
188
+   - 备注:`trainable_parameters`、`trainable_parameters_regex`的优先级高于`freeze_parameters`、`freeze_parameters_regex`和`freeze_parameters_ratio`。当指定全参数训练时,会将所有模块设置为可训练的状态,随后根据`freeze_parameters`、`freeze_parameters_regex`、`freeze_parameters_ratio`将部分参数冻结,最后根据`trainable_parameters`、`trainable_parameters_regex`重新打开部分参数参与训练。
189
+
190
+ #### LoRA
191
+ - 🔥lora_rank: 默认为`8`。
192
+ - 🔥lora_alpha: 默认为`32`。
193
+ - lora_dropout: 默认为`0.05`。
194
+ - lora_bias: 默认为`'none'`,可以选择的值: 'none'、'all'。如果你要将bias全都设置为可训练,你可以设置为`'all'`。
195
+ - lora_dtype: 指定lora模块的dtype类型。支持'float16'、'bfloat16'、'float32'。默认为None,跟随原模型类型。
196
+ - 🔥use_dora: 默认为`False`,是否使用`DoRA`。
197
+ - use_rslora: 默认为`False`,是否使用`RS-LoRA`。
198
+ - 🔥lorap_lr_ratio: LoRA+参数,默认值`None`,建议值`10~16`。使用lora时指定该参数可使用lora+。
199
+
200
+ ##### LoRA-GA
201
+ - lora_ga_batch_size: 默认值为 `2`。在 LoRA-GA 中估计梯度以进行初始化时使用的批处理大小。
202
+ - lora_ga_iters: 默认值为 `2`。在 LoRA-GA 中估计梯度以进行初始化时的迭代次数。
203
+ - lora_ga_max_length: 默认值为 `1024`。在 LoRA-GA 中估计梯度以进行初始化时的最大输入长度。
204
+ - lora_ga_direction: 默认值为 `ArB2r`。在 LoRA-GA 中使用估计梯度进行初始化时的初始方向。允许的值有:`ArBr`、`A2rBr`、`ArB2r` 和 `random`。
205
+ - lora_ga_scale: 默认值为 `stable`。LoRA-GA 的初始化缩放方式。允许的值有:`gd`、`unit`、`stable` 和 `weightS`。
206
+ - lora_ga_stable_gamma: 默认值为 `16`。当初始化时选择 `stable` 缩放时的 gamma 值。
207
+
208
+ #### FourierFt
209
+
210
+ FourierFt使用`target_modules`, `target_regex`, `modules_to_save`三个参数.
211
+
212
+ - fourier_n_frequency: 傅里叶变换的频率数量, `int`类型, 类似于LoRA中的`r`. 默认值`2000`.
213
+ - fourier_scaling: W矩阵的缩放值, `float`类型, 类似LoRA中的`lora_alpha`. 默认值`300.0`.
214
+
215
+ #### BOFT
216
+
217
+ BOFT使用`target_modules`, `target_regex`, `modules_to_save`三个参数.
218
+
219
+ - boft_block_size: BOFT块尺寸, 默认值4.
220
+ - boft_block_num: BOFT块数量, 不能和`boft_block_size`同时使用.
221
+ - boft_dropout: boft的dropout值, 默认0.0.
222
+
223
+ #### Vera
224
+
225
+ Vera使用`target_modules`, `target_regex`, `modules_to_save`三个参数.
226
+
227
+ - vera_rank: Vera Attention的尺寸, 默认值256.
228
+ - vera_projection_prng_key: 是否存储Vera映射矩阵, 默认为True.
229
+ - vera_dropout: Vera的dropout值, 默认`0.0`.
230
+ - vera_d_initial: Vera的d矩阵的初始值, 默认`0.1`.
231
+
232
+ #### GaLore
233
+
234
+ - 🔥use_galore: 默认值False, 是否使用GaLore.
235
+ - galore_target_modules: 默认值None, 不传的情况下对attention和mlp应用GaLore.
236
+ - galore_rank: 默认值128, GaLore的rank值.
237
+ - galore_update_proj_gap: 默认值50, 分解矩阵的更新间隔.
238
+ - galore_scale: 默认值1.0, 矩阵权重系数.
239
+ - galore_proj_type: 默认值`std`, GaLore矩阵分解类型.
240
+ - galore_optim_per_parameter: 默认值False, 是否给每个Galore目标Parameter设定一个单独的optimizer.
241
+ - galore_with_embedding: 默认值False, 是否对embedding应用GaLore.
242
+ - galore_quantization: 是否使用q-galore. 默认值`False`.
243
+ - galore_proj_quant: 是否对SVD分解矩阵做量化, 默认`False`.
244
+ - galore_proj_bits: SVD量化bit数.
245
+ - galore_proj_group_size: SVD量化分组数.
246
+ - galore_cos_threshold: 投影矩阵更新的cos相似度阈值. 默认值0.4.
247
+ - galore_gamma_proj: 在投影矩阵逐渐相似后会拉长更新间隔, 本参数为每次拉长间隔的系数, 默认值2.
248
+ - galore_queue_size: 计算投影矩阵相似度的队列长度, 默认值5.
249
+
250
+ #### LISA
251
+
252
+ 注意:LISA仅支持全参数,即`--train_type full`.
253
+
254
+ - 🔥lisa_activated_layers: 默认值`0`, 代表不使用LISA,改为非0代表需要激活的layers个数,建议设置为2或8.
255
+ - lisa_step_interval: 默认值`20`, 多少iter切换可反向传播的layers.
256
+
257
+ #### UNSLOTH
258
+
259
+ 🔥unsloth无新增参数,对已有参数进行调节即可支持:
260
+
261
+ ```
262
+ --tuner_backend unsloth
263
+ --train_type full/lora
264
+ --quant_bits 4
265
+ ```
266
+
267
+ #### LLAMAPRO
268
+
269
+ - 🔥llamapro_num_new_blocks: 默认值`4`, 插入的新layers总数.
270
+ - llamapro_num_groups: 默认值`None`, 分为多少组插入new_blocks, 如果为`None`则等于`llamapro_num_new_blocks`, 即每个新的layer单独插入原模型.
271
+
272
+ #### AdaLoRA
273
+
274
+ 以下参数`train_type`设置为`adalora`时生效. adalora的`target_modules`等参数继承于lora的对应参数, 但`lora_dtype`参数不生效.
275
+
276
+ - adalora_target_r: 默认值`8`, adalora的平均rank.
277
+ - adalora_init_r: 默认值`12`, adalora的初始rank.
278
+ - adalora_tinit: 默认值`0`, adalora的初始warmup.
279
+ - adalora_tfinal: 默认值`0`, adalora的final warmup.
280
+ - adalora_deltaT: 默认值`1`, adalora的step间隔.
281
+ - adalora_beta1: 默认值`0.85`, adalora的EMA参数.
282
+ - adalora_beta2: 默认值`0.85`, adalora的EMA参数.
283
+ - adalora_orth_reg_weight: 默认值`0.5`, adalora的正则化参数.
284
+
285
+ #### ReFT
286
+
287
+ 以下参数`train_type`设置为`reft`时生效.
288
+
289
+ > 1. ReFT无法合并tuner
290
+ > 2. ReFT和gradient_checkpointing不兼容
291
+ > 3. 如果使用DeepSpeed遇到问题请暂时卸载DeepSpeed
292
+
293
+ - 🔥reft_layers: ReFT应用于哪些层上, 默认为`None`, 代表所有层, 可以输入层号的list, 例如reft_layers 1 2 3 4`
294
+ - 🔥reft_rank: ReFT矩阵的rank, 默认为`4`.
295
+ - reft_intervention_type: ReFT的类型, 支持'NoreftIntervention', 'LoreftIntervention', 'ConsreftIntervention', 'LobireftIntervention', 'DireftIntervention', 'NodireftIntervention', 默认为`LoreftIntervention`.
296
+ - reft_args: ReFT Intervention中的其他支持参数, 以json-string格式输入.
297
+
298
+ ### LMDeploy参数
299
+ 参数含义可以查看[lmdeploy文档](https://lmdeploy.readthedocs.io/en/latest/api/pipeline.html#turbomindengineconfig)。
300
+
301
+ - 🔥tp: tensor并行度。默认为`1`。
302
+ - session_len: 默认为`None`。
303
+ - cache_max_entry_count: 默认为`0.8`。
304
+ - quant_policy: 默认为`0`。
305
+ - vision_batch_size: 默认为`1`。
306
+
307
+ ### vLLM参数
308
+ 参数含义可以查看[vllm文档](https://docs.vllm.ai/en/latest/serving/engine_args.html)。
309
+
310
+ - 🔥gpu_memory_utilization: 默认值`0.9`。
311
+ - 🔥tensor_parallel_size: 默认为`1`。
312
+ - pipeline_parallel_size: 默认为`1`。
313
+ - max_num_seqs: 默认为`256`。
314
+ - 🔥max_model_len: 默认为`None`。
315
+ - disable_custom_all_reduce: 默认为`False`。
316
+ - enforce_eager: vllm使用pytorch eager模式还是建立cuda graph,默认为`False`。设置为True可以节约显存,但会影响效率。
317
+ - 🔥limit_mm_per_prompt: 控制vllm使用多图,默认为`None`。例如传入`--limit_mm_per_prompt '{"image": 5, "video": 2}'`。
318
+ - vllm_max_lora_rank: 默认为`16`。vllm对于lora支持的参数。
319
+ - vllm_quantization: vllm可以在内部量化模型,参数支持的值详见[这里](https://docs.vllm.ai/en/latest/serving/engine_args.html)。
320
+ - enable_prefix_caching: 开启vllm的自动前缀缓存,节约重复查询前缀的处理时间。默认为`False`。
321
+
322
+
323
+ ### 合并参数
324
+
325
+ - 🔥merge_lora: 是否合并lora,本参数支持lora、llamapro、longlora,默认为False。例子参数[这里](https://github.com/modelscope/ms-swift/blob/main/examples/export/merge_lora.sh)。
326
+ - safe_serialization: 是否存储safetensors,默认为True。
327
+ - max_shard_size: 单存储文件最大大小,默认'5GB'。
328
+
329
+
330
+ ## 集成参数
331
+
332
+ ### 训练参数
333
+ 训练参数除包含[基本参数](#基本参数)、[Seq2SeqTrainer参数](#Seq2SeqTrainer参数)、[tuner参数](#tuner参数)外,还包含下面的部分:
334
+
335
+ - add_version: 在output_dir上额外增加目录`'<版本号>-<时间戳>'`防止权重覆盖,默认为True。
336
+ - resume_only_model: 默认为False。如果在指定resume_from_checkpoint的基础上,将该参数设置为True,则仅resume模型权重。
337
+ - check_model: 检查本地模型文件有损坏或修改并给出提示,默认为True。如果是断网环境,请设置为False。
338
+ - 🔥create_checkpoint_symlink: 额外创建checkpoint软链接,方便书写自动化训练脚本。best_model和last_model的软链接路径分别为f'{output_dir}/best'和f'{output_dir}/last'。
339
+ - loss_type: loss类型。默认为None,使用模型自带损失函数。
340
+ - 🔥packing: 是否使用序列packing提升计算效率,默认为False。
341
+ - 注意:使用packing请结合`--attn_impl flash_attn`使用且"transformers>=4.44",具体查看[该PR](https://github.com/huggingface/transformers/pull/31629)。
342
+ - 🔥lazy_tokenize: 是否使用lazy_tokenize。若该参数设置为False,则在训练之前对所有的数据集样本进行tokenize(多模态模型则包括从磁盘中读取图片)。该参数在LLM训练中默认设置为False,而MLLM训练默认为True,节约内存。
343
+ - acc_strategy: 训练和验证时计算acc的策略。可选为`seq`和`token`级别的acc,默���为`token`。
344
+ - max_new_tokens: 覆盖生成参数。predict_with_generate=True时的最大生成token数量,默认64。
345
+ - temperature: 覆盖生成参数。predict_with_generate=True时的temperature,默认0。
346
+ - optimizer: plugin的自定义optimizer名称,默认为None。
347
+ - metric: plugin的自定义metric名称。默认为None,即在predict_with_generate=False的情况下设置为'acc',在predict_with_generate=True的情况下设置为'nlg'。
348
+ - eval_use_evalscope: 是否使用evalscope进行训练时评测,需要设置该参数来开启评测,具体使用参考[示例](../Instruction/评测.md#训练中评测)。
349
+ - eval_datasets: 评测数据集,可设置多个数据集,用空格分割。
350
+ - eval_datasets_args: 评测数据集参数,json格式,可设置多个数据集的参数。
351
+ - eval_limit: 评测数据集采样数。
352
+ - eval_generation_config: 评测时模型推理配置,json格式,默认为`{'max_tokens': 512}`。
353
+
354
+ ### RLHF参数
355
+ RLHF参数继承于[训练参数](#训练参数)。
356
+
357
+ - 🔥rlhf_type: 人类对齐算法类型,支持`dpo`、`orpo`、`simpo`、`kto`、`cpo`、`rm`、`ppo`和`grpo`。默认为'dpo'。
358
+ - ref_model: 采用dpo、kto、ppo、grpo算法且使用全参数训练时需要传入。默认为None。
359
+ - ref_model_type: 同model_type。默认为None。
360
+ - ref_model_revision: 同model_revision。默认为None。
361
+ - 🔥beta: KL正则项系数,默认为`None`,即`simpo`算法默认为`2.`,GRPO默认为`0.04`,其他算法默认为`0.1`。具体参考[文档](./人类对齐.md)。
362
+ - label_smoothing: 是否使用DPO smoothing,默认值为`0`。
363
+ - 🔥rpo_alpha: 控制DPO中加入sft_loss的权重,默认为`1`。最后的loss为`KL_loss + rpo_alpha * sft_loss`。
364
+ - cpo_alpha: CPO/SimPO loss 中 nll loss的系数, 默认为`1.`。
365
+ - simpo_gamma: SimPO算法中的reward margin项,论文建议设置为0.5-1.5,默认为`1.`。
366
+ - desirable_weight: KTO算法中对desirable response的loss权重 $\lambda_D$,默认为`1.`。
367
+ - undesirable_weight: KTO算法中对undesirable response的loss权重 $\lambda_U$,默认为`1.`。
368
+ - loss_scale: 覆盖模板参数,默认为'last_round'。
369
+ - temperature: 默认为0.9,该参数将在PPO、GRPO中使用。
370
+
371
+ #### Reward模型参数
372
+ reward模型参数将在PPO、GRPO中使用。
373
+
374
+ - reward_model: 默认为None。
375
+ - reward_adapters: 默认为`[]`。
376
+ - reward_model_type: 默认为None。
377
+ - reward_model_revision: 默认为None。
378
+
379
+ #### PPO参数
380
+
381
+ 以下参数含义可以参考[这里](https://huggingface.co/docs/trl/main/ppo_trainer)。
382
+ - num_ppo_epochs: 默认为4。
383
+ - whiten_rewards: 默认为False。
384
+ - kl_coef: 默认为0.05。
385
+ - cliprange: 默认为0.2。
386
+ - vf_coef: 默认为0.1。
387
+ - cliprange_value: 默认为0.2。
388
+ - gamma: 默认为1.0。
389
+ - lam: 默认为0.95。
390
+ - num_mini_batches: 默认为1。
391
+ - local_rollout_forward_batch_size: 默认为64。
392
+ - num_sample_generations: 默认为10。
393
+ - response_length: 默认为512。
394
+ - missing_eos_penalty: 默认为None。
395
+
396
+
397
+ #### GRPO参数
398
+ - per_device_train_batch_size: 每个设备训练批量大小,在GRPO中,指 completion 的批次大小。
399
+ - per_device_eval_batch_size: 每个设备评估批量大小,在GRPO中,指 completion 的批次大小。
400
+ - num_generations: 每个prompt采样的数量,论文中的G值,需要被 per_device_batch_size * gradient_accumulation_steps * nproc_per_node 整除,默认为8。
401
+ - max_completion_length: GRPO算法中的最大生成长度,默认为512。
402
+ - ds3_gather_for_generation: 该参数适用于DeepSpeed ZeRO-3。如果启用,策略模型权重将被收集用于生成,从而提高生成速度。然而,禁用此选项允许训练超出单个GPU VRAM的模型,尽管生成速度会变慢。禁用此选项与vLLM生成不兼容。默认为True。
403
+ - reward_funcs: GRPO算法奖励函数,可选项为`accuracy`、`format`、`cosine` 和 `repetition`,见swift/plugin/orm.py。你也可以在plugin中自定义自己的奖励函数。默认为`[]`。
404
+ - reward_weights: 每个奖励函数的权重。必须与奖励函数和奖励模型的总数量匹配。如果为 None,则所有奖励的权重都相等,为`1.0`。
405
+ - 提示:如果GRPO训练中包含`--reward_model`,则其加在奖励函数的最后位置。
406
+ - reward_model_plugin: 奖励模型逻辑,默认为orm逻辑, 详细见[自定义奖励模型](./GRPO.md#自定义奖励模型)。
407
+ - dataset_shuffle: 是否对dataset进行随机操作,默认为True。
408
+ - loss_type: loss 归一化的类型,可选项为['grpo', 'bnpo', 'dr_grpo'], 默认为'grpo', 具体查看该[pr](https://github.com/huggingface/trl/pull/3256#discussion_r2033213348)。
409
+ - log_completions: 是否记录训练中的模型生成内容,搭配 `--report_to wandb` 使用。默认为False。
410
+ - 提示:若没有设置`--report_to wandb`,则会在checkpoint中创建`completions.jsonl`来存储生成内容。
411
+ - use_vllm: 是否使用vLLM作为GRPO生成的infer_backend,默认为False。
412
+ - num_infer_workers: 每个node上推理worker数量,仅对vllm或者lmdeploy时有效。
413
+ - vllm_device: 设置vLLM部署的设备,可以设置为`auto`,代表按照num_infer_workers数量使用最后的几张卡,否则请传入和num_infer_workers相等数量的设备,例如`--vllm_device cuda:1 cuda:2`。
414
+ - vllm_gpu_memory_utilization: vllm透传参数,默认为0.9。
415
+ - vllm_max_model_len: vllm透传参数,默认为None。
416
+ - vllm_max_num_seqs: vllm透传参数,默认为256。
417
+ - vllm_enforce_eager: vllm透传参数,默认为False。
418
+ - vllm_limit_mm_per_prompt: vllm透传参数,默认为None。
419
+ - vllm_enable_prefix_caching: vllm透传参数,默认为True。
420
+ - vllm_server_host:vLLM server host地址,默认为None,使用外部vLLM server时使用。
421
+ - vllm_server_port vLLM server 服务端口,默认为8000。
422
+ - vllm_server_timeout 连接vLLM server的超时时间,默认为120s。
423
+ - top_k: 默认为50。
424
+ - top_p: 默认为0.9。
425
+ - repetition_penalty: 重复惩罚项。默认为1.。
426
+ - num_iterations: 每个批次代更新次数,默认为1。
427
+ - epsilon: clip 系数,默认为0.2。
428
+ - epsilon_high: upper clip 系数,默认为None,设置后与epsilon共同构成[epsilon, epsilon_high]裁剪范围。
429
+ - async_generate: 异步rollout以提高训练速度,默认`false`。
430
+ - sleep_level: vllm特有参数,在训练和rollout复用卡的时候,可以选择vllm进行offload。
431
+ - move_model_batches: 在模型向vLLM/LMDeploy等快速推理框架移动参数时,将layers分为多少个batch. 默认为None, 代表整个模型不进行拆分,否则拆分为move_model_batches+1(非layer参数)+1(多模态部分参数)个。
432
+ - offload_optimizer: 是否在vLLM/LMDeploy推理时offload optimizer参数,默认为False。
433
+ - offload_model: 是否在vLLM/LMDeploy推理时offload 模型本身,默认为False。
434
+ - 注意:若该参数设置为True,训练时grad_norm一直为0,请安装`vllm==0.7.3`。
435
+ - gc_collect_after_offload: 是否在offload结束时进行gc(python gc和GPU gc),默认为False。
436
+ - multi_turn_func: 多轮GRPO参数, 传入对应的plugin名称, 同时在plugin/multi_turn.py中添加好对应的实现。
437
+ - dynamic_sample:筛除group内奖励标准差为0的数据,额外采样新数据,默认为False。
438
+ - max_resample_times:dynamic_sample设置下限制重采样次数,默认3次。
439
+ - overlong_filter:跳过超长截断的样本,不参与loss计算,默认为False。
440
+
441
+ cosine 奖励参数
442
+ - cosine_min_len_value_wrong:cosine 奖励函数参数,生成错误答案时,最小长度对应的奖励值。默认值为0.0。
443
+ - cosine_max_len_value_wrong:生成错误答案时,最大长度对应的奖励值。默认值为-0.5。
444
+ - cosine_min_len_value_correct:生成正确答案时,最小长度对应的奖励值。默认值为1.0。
445
+ - cosine_max_len_value_correct:生成正确答案时,最大长度对应的奖励值。默认值为0.5。
446
+ - cosine_max_len:生成文本的最大长度限制。默认等于 max_completion_length。
447
+
448
+ repetition 奖励参数
449
+ - repetition_n_grams:用于检测重复的 n-gram 大小。默认值为3。
450
+ - repetition_max_penalty:最大惩罚值,用于控制惩罚的强度。默认值为-1.0。
451
+
452
+ soft overlong 奖励参数
453
+ - soft_max_length: 论文中的L_max,模型的最大生成长度,默认等于max_completion_length。
454
+ - soft_cache_length: 论文中的L_cache,控制长度惩罚区间,区间为[soft_max_length-soft_cache_length, soft_max_length]。
455
+
456
+ #### SWANLAB
457
+
458
+ - swanlab_token: SwanLab的api-key。
459
+ - swanlab_project: swanlab的project,需要在页面中预先创建好:[https://swanlab.cn/space/~](https://swanlab.cn/space/~)。
460
+ - swanlab_workspace: 默认为None,会使用api-key对应的username。
461
+ - swanlab_exp_name: 实验名,可以为空,为空时默认传入--output_dir的值。
462
+ - swanlab_mode: 可选cloud和local,云模式或者本地模式。
463
+
464
+ ### 推理参数
465
+
466
+ 推理参数除包含[基本参数](#基本参数)、[合并参数](#合并参数)、[vLLM参数](#vllm参数)、[LMDeploy参数](#LMDeploy参数)外,还包含下面的部分:
467
+
468
+ - 🔥infer_backend: 推理加速后端,支持'pt'、'vllm'、'lmdeploy'三种推理引擎。默认为'pt'。
469
+ - 🔥max_batch_size: 指定infer_backend为pt时生效,用于批量推理,默认为1。
470
+ - ddp_backend: 指定infer_backend为pt时生效,用于指定多卡推理时的分布式后端,默认为None,进行自动选择。多卡推理例子可以查看[这里](https://github.com/modelscope/ms-swift/tree/main/examples/infer/pt)。
471
+ - 🔥result_path: 推理结果存储路径(jsonl),默认为None,保存在checkpoint目录(含args.json文件)或者'./result'目录,最终存储路径会在命令行中打印。
472
+ - metric: 对推理的结果进行评估,目前支持'acc'和'rouge'。默认为None,即不进行评估。
473
+ - val_dataset_sample: 推理数据集采样数,默认为None。
474
+
475
+
476
+ ### 部署参数
477
+
478
+ 部署参数继承于[推理参数](#推理参数)。
479
+
480
+ - host: 服务host,默认为'0.0.0.0'。
481
+ - port: 端口号,默认为8000。
482
+ - api_key: 访问需要使用的api_key,默认为None。
483
+ - owned_by: 默认为`swift`。
484
+ - 🔥served_model_name: 提供服务的模型名称,默认使用model的后缀。
485
+ - verbose: 打印详细日志,默认为True。
486
+ - 注意:在`swift app`或者`swift eval`时,默认为False。
487
+ - log_interval: tokens/s统计值打印间隔,默认20秒。设置为-1则不打印。
488
+ - max_logprobs: 最多返回客户端的logprobs数量,默认为20。
489
+ - use_async_engine: vLLM backend下是否使用async engine,默认为True。
490
+
491
+ ### Web-UI参数
492
+ - server_name: web-ui的host,默认为'0.0.0.0'。
493
+ - server_port: web-ui的port,默认为7860。
494
+ - share: 默认为False。
495
+ - lang: web-ui的语言,可选为'zh', 'en'。默认为'zh'。
496
+
497
+
498
+ ### App参数
499
+
500
+ App参数继承于[部署参数](#部署参数), [Web-UI参数](#Web-UI参数)。
501
+ - base_url: 模型部署的base_url,例如`http://localhost:8000/v1`。默认为`None`,使用本地部署。
502
+ - studio_title: studio的标题。默认为None,设置为模型名。
503
+ - is_multimodal: 是否启动多模态版本的app。默认为None,自动根据model判断,若无法判断,设置为False。
504
+ - lang: 覆盖Web-UI参数,默认为'en'。
505
+
506
+ ### 评测参数
507
+
508
+ 评测参数继承于[部署参数](#部署参数)。
509
+
510
+ - 🔥eval_backend: 评测后端,默认为'Native',也可以指定为'OpenCompass'或'VLMEvalKit'。
511
+ - 🔥eval_dataset: 评测数据集,请查看[评测文档](./评测.md)。
512
+ - eval_limit: 每个评测集的采样数,默认为None。
513
+ - eval_output_dir: 评测存储结果的文件夹,默认为'eval_output'。
514
+ - temperature: 覆盖生成参数,默认为0。
515
+ - eval_num_proc: 评测时客户端最大并发数,默认为16。
516
+ - eval_url: 评测url,例如`http://localhost:8000/v1`。例子可以查看[这里](https://github.com/modelscope/ms-swift/tree/main/examples/eval/eval_url)。默认为None,采用本地部署评估。
517
+ - eval_generation_config: 评测时模型推理配置,需传入json字符串格式,例如:`'{"max_new_tokens": 512}'`;默认为None。
518
+ - extra_eval_args: 额外评测参数,需传入json字符串格式,默认为空。仅对Native评测有效,更多参数说明请查看[这里](https://evalscope.readthedocs.io/zh-cn/latest/get_started/parameters.html)
519
+ - local_dataset: 部分评测集,如`CMB`无法直接运行,需要下载额外数据包才可以使用。设置本参数为`true`可以自动下载全量数据包,并在当前目录下创建`data`文件夹并开始评测。数据包仅会下载一次,后续会使用缓存。该参数默认为`false`。
520
+ - 注意:默认评测会使用`~/.cache/opencompass`下的数据集,在指定本参数后会直接使用当前目录下的data文件夹。
521
+
522
+ ### 导出参数
523
+
524
+ 导出参数除包含[基本参数](#基本参数)和[合并参数](#合并参数)外,还包含下面的部分:
525
+
526
+ - 🔥output_dir: 导出结果存储路径。默认为None,会自动设置合适后缀的路径。
527
+ - exist_ok: 如果output_dir存在,不抛出异常,进行覆盖。默认为False。
528
+ - 🔥quant_method: 可选为'gptq'、'awq'、'bnb',默认为None。例子参考[这里](https://github.com/modelscope/ms-swift/tree/main/examples/export/quantize)。
529
+ - quant_n_samples: gptq/awq的校验集采样数,默认为256。
530
+ - max_length: 校准集的max_length, 默认值2048。
531
+ - quant_batch_size: 量化batch_size,默认为1。
532
+ - group_size: 量化group大小,默认为128。
533
+ - to_ollama: 产生ollama所需的Modelfile文件。默认为False。
534
+ - 🔥to_mcore: HF格式权重转成Megatron格式。默认为False。
535
+ - to_hf: Megatron格式权重转成HF格式。默认为False。
536
+ - mcore_model: mcore格式模型路径。默认为None。
537
+ - thread_count: `--to_mcore true`时的模型切片数。默认为None,根据模型大小自动设置,使得最大分片小于10GB。
538
+ - 🔥test_convert_precision: 测试HF和Megatron格式权重转换的精度误差。默认为False。
539
+ - 🔥push_to_hub: 是否推送hub,默认为False。例子参考[这里](https://github.com/modelscope/ms-swift/blob/main/examples/export/push_to_hub.sh)。
540
+ - hub_model_id: 推送的model_id,默认为None。
541
+ - hub_private_repo: 是否是private repo,默认为False。
542
+ - commit_message: 提交信息,默认为'update files'。
543
+
544
+ ### 采样参数
545
+
546
+ - prm_model: 过程奖励模型的类型,可以是模型id(以pt方式拉起),或者plugin中定义的prm key(自定义推理过程)。
547
+ - orm_model: 结果奖励模型的类型,通常是通配符或测试用例等,一般定义在plugin中。
548
+ - sampler_type:采样类型,目前支持 sample, mcts,未来会支持 dvts。
549
+ - sampler_engine:支持`pt`, `lmdeploy`, `vllm`, `client`, `no`,默认为`pt`,采样模型的推理引擎。
550
+ - sampler_type:采样类型,目前支持sample(do_sample方式),未来会支持mcts和dvts。
551
+ - sampler_engine:支持`pt`, `lmdeploy`, `vllm`, `no`,默认为`pt`,采样模型的推理引擎。
552
+ - output_dir:输出目录,默认为`sample_output`。
553
+ - output_file:输出文件名称,默认为`None`使用时间戳作为文件名。传入时不需要传入目录,仅支持jsonl格式。
554
+ - override_exist_file:如`output_file`存在,是否覆盖。
555
+ - num_sampling_per_gpu_batch_size:每次采样的batch_size。
556
+ - num_sampling_per_gpu_batches:共采样多少batch。
557
+ - n_best_to_keep:返回多少最佳sequences。
558
+ - data_range:本采样处理数据集的分片。传入格式为`2 3`,代表数据集分为3份处理(这意味着通常有三个`swift sample`在并行处理),本实例正在处理第3个分片。
559
+ - temperature:在这里默认为1.0。
560
+ - prm_threshold:PRM阈值,低于该阈值的结果会被过滤掉,默认值为`0`。
561
+ - easy_query_threshold:单个query的所有采样中,ORM评估如果正确,大于该比例的query会被丢弃,防止过于简单的query出现在结果中,默认为`None`,代表不过滤。
562
+ - engine_kwargs:传入sampler_engine的额外参数,以json string传入,例如`{"cache_max_entry_count":0.7}`。
563
+ - num_return_sequences:采样返回的原始sequence数量。默认为64,本参数对`sample`采样有效。
564
+ - cache_files:为避免同时加载prm和generator造成显存OOM,可以分两步进行采样,第一步将prm和orm置为`None`,则所有结果都会输出到文件中,第二次运行采样将sampler_engine置为`no`并传入`--cache_files`为上次采样的输出文件,则会使用上次输出的结果进行prm和orm评估并输出最终结果。
565
+ - 注意:使用cache_files时,`--dataset`仍然需要传入,这是因为cache_files的id是由原始数据计算的md5,需要把两部分信息结合使用。
566
+
567
+ #### MCTS
568
+ - rollout_depth:rollout 时的最大深度,默认为 `5`。
569
+ - rollout_start_depth:开始 rollout 时的深度,低于此深度的节点只会进行 expand 操作,默认为 `3`。
570
+ - max_iterations:mcts 的最大迭代次数,默认为 `100`。
571
+ - process_reward_rate:select 中计算 value 时 process reward 占的比例,默认为 `0.0`,即不使用 PRM。
572
+ - exploration_rate:UCT 算法中的探索参数,值越大越照顾探索次数较小的节点,默认为 `0.5`。
573
+ - api_key:使用 client 作为推理引擎时需要,默认为 `EMPTY`。
574
+ - base_url:使用 client 作为推理引擎时需要,默认为 'https://dashscope.aliyuncs.com/compatible-mode/v1'
575
+
576
+
577
+ ## 特定模型参数
578
+ 特定模型参数可以通过`--model_kwargs`或者环境变量进行设置,例如: `--model_kwargs '{"fps_max_frames": 12}'`或者`FPS_MAX_FRAMES=12`。
579
+
580
+ ### qwen2_vl, qvq, qwen2_5_vl
581
+ 参数含义同`qwen_vl_utils`或者`qwen_omni_utils`库,可以查看[这里](https://github.com/QwenLM/Qwen2.5-VL/blob/main/qwen-vl-utils/src/qwen_vl_utils/vision_process.py#L24)。
582
+
583
+ - IMAGE_FACTOR: 默认为28。
584
+ - MIN_PIXELS: 默认为`4 * 28 * 28`。
585
+ - 🔥MAX_PIXELS: 默认为`16384 * 28 * 28`,参考[这里](https://github.com/modelscope/ms-swift/blob/main/examples/train/multimodal/ocr.sh#L3)。
586
+ - MAX_RATIO: 默认为200。
587
+ - VIDEO_MIN_PIXELS: 默认为`128 * 28 * 28`。
588
+ - 🔥VIDEO_MAX_PIXELS: 默认为`768 * 28 * 28`,参考[这里](https://github.com/modelscope/ms-swift/blob/main/examples/train/multimodal/video.sh#L7)。
589
+ - VIDEO_TOTAL_PIXELS: 默认为`24576 * 28 * 28`。
590
+ - FRAME_FACTOR: 默认为2。
591
+ - FPS: 默认为2.0。
592
+ - FPS_MIN_FRAMES: 默认为4。
593
+ - 🔥FPS_MAX_FRAMES: 默认为768,参考[这里](https://github.com/modelscope/ms-swift/blob/main/examples/train/multimodal/video.sh#L8)。
594
+
595
+ ### qwen2_audio
596
+ - SAMPLING_RATE: 默认为16000。
597
+
598
+ ### qwen2_5_omni
599
+ qwen2_5_omni除了包含qwen2_5_vl和qwen2_audio的模型特定参数外,还包含以下参数:
600
+ - USE_AUDIO_IN_VIDEO: 默认为False。
601
+ - 🔥ENABLE_AUDIO_OUTPUT: 默认为True。若使用zero3进行训练,请设置为False。
602
+
603
+ ### internvl, internvl_phi3
604
+ 参数含义可以查看[这里](https://modelscope.cn/models/OpenGVLab/Mini-InternVL-Chat-2B-V1-5)。
605
+ - MAX_NUM: 默认为12。
606
+ - INPUT_SIZE: 默认为448。
607
+
608
+ ### internvl2, internvl2_phi3, internvl2_5, internvl3
609
+ 参数含义可以查看[这里](https://modelscope.cn/models/OpenGVLab/InternVL2_5-2B)。
610
+ - MAX_NUM: 默认为12。
611
+ - INPUT_SIZE: 默认为448。
612
+ - VIDEO_MAX_NUM: 默认为1。视频的MAX_NUM。
613
+ - VIDEO_SEGMENTS: 默认为8。
614
+
615
+
616
+ ### minicpmv2_6, minicpmo2_6
617
+ - MAX_SLICE_NUMS: 默认为9,参考[这里](https://modelscope.cn/models/OpenBMB/MiniCPM-V-2_6/file/view/master?fileName=config.json&status=1)。
618
+ - VIDEO_MAX_SLICE_NUMS: 默认为1,视频的MAX_SLICE_NUMS,参考[这里](https://modelscope.cn/models/OpenBMB/MiniCPM-V-2_6)。
619
+ - MAX_NUM_FRAMES: 默认为64,参考[这里](https://modelscope.cn/models/OpenBMB/MiniCPM-V-2_6)。
620
+
621
+ ### minicpmo2_6
622
+ - INIT_TTS: 默认为False。
623
+ - INIT_AUDIO: 默认为False。
624
+
625
+ ### ovis1_6, ovis2
626
+ - MAX_PARTITION: 默认为9,参考[这里](https://github.com/AIDC-AI/Ovis/blob/d248e34d755a95d24315c40e2489750a869c5dbc/ovis/model/modeling_ovis.py#L312)。
627
+
628
+ ### mplug_owl3, mplug_owl3_241101
629
+ - MAX_NUM_FRAMES: 默认为16,��考[这里](https://modelscope.cn/models/iic/mPLUG-Owl3-7B-240728)。
630
+
631
+ ### xcomposer2_4khd
632
+ - HD_NUM: 默认为55,参考[这里](https://modelscope.cn/models/Shanghai_AI_Laboratory/internlm-xcomposer2-4khd-7b)。
633
+
634
+ ### xcomposer2_5
635
+ - HD_NUM: 图片数量为1时,默认值为24。大于1,默认为6。参考[这里](https://modelscope.cn/models/AI-ModelScope/internlm-xcomposer2d5-7b/file/view/master?fileName=modeling_internlm_xcomposer2.py&status=1#L254)。
636
+
637
+ ### video_cogvlm2
638
+ - NUM_FRAMES: 默认为24,参考[这里](https://github.com/THUDM/CogVLM2/blob/main/video_demo/inference.py#L22)。
639
+
640
+ ### phi3_vision
641
+ - NUM_CROPS: 默认为4,参考[这里](https://modelscope.cn/models/LLM-Research/Phi-3.5-vision-instruct)。
642
+
643
+ ### llama3_1_omni
644
+ - N_MELS: 默认为128,参考[这里](https://github.com/ictnlp/LLaMA-Omni/blob/544d0ff3de8817fdcbc5192941a11cf4a72cbf2b/omni_speech/infer/infer.py#L57)。
645
+
646
+ ### video_llava
647
+ - NUM_FRAMES: 默认为16。
648
+
649
+
650
+ ## 其他环境变量
651
+ - CUDA_VISIBLE_DEVICES: 控制使用哪些GPU卡。默认使用所有卡。
652
+ - ASCEND_RT_VISIBLE_DEVICES: 控制使用哪些NPU卡(ASCEND卡生效)。默认使用所有卡。
653
+ - MODELSCOPE_CACHE: 控制缓存路径。
654
+ - NPROC_PER_NODE: torchrun中`--nproc_per_node`的参数透传。默认为1。若设置了`NPROC_PER_NODE`或者`NNODES`环境变量,则使用torchrun启动训练或推理。
655
+ - MASTER_PORT: torchrun中`--master_port`的参数透传。默认为29500。
656
+ - MASTER_ADDR: torchrun中`--master_addr`的参数透传。
657
+ - NNODES: torchrun中`--nnodes`的参数透传。
658
+ - NODE_RANK: torchrun中`--node_rank`的参数透传。
659
+ - LOG_LEVEL: 日志的level,默认为'INFO',你可以设置为'WARNING', 'ERROR'等。
660
+ - SWIFT_DEBUG: 在`engine.infer(...)`时,若设置为'1',则会打印input_ids和generate_ids的内容。
ms-swift/docs/source/Instruction/导出与推送.md ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 导出与推送
2
+
3
+
4
+ ## Merge LoRA
5
+
6
+ - 查看[这里](https://github.com/modelscope/ms-swift/blob/main/examples/export/merge_lora.sh)。
7
+
8
+ ## 量化
9
+
10
+ SWFIT支持AWQ、GPTQ、BNB模型的量化导出。其中使用AWQ、GPTQ需使用校准数据集,量化性能较好但量化耗时较长;而BNB无需校准数据集,量化耗时较短。
11
+
12
+ | 量化技术 | 多模态 | 推理加速 | 继续训练 |
13
+ | -------- | ------ | -------- | -------- |
14
+ | GPTQ | ✅ | ✅ | ✅ |
15
+ | AWQ | ✅ | ✅ | ✅ |
16
+ | BNB | ❌ | ✅ | ✅ |
17
+
18
+
19
+ 除SWIFT安装外,需要安装以下额外依赖:
20
+ ```shell
21
+ # 使用awq量化:
22
+ # autoawq和cuda版本有对应关系,请按照`https://github.com/casper-hansen/AutoAWQ`选择版本
23
+ # 如果出现torch依赖冲突,请额外增加指令`--no-deps`
24
+ pip install autoawq -U
25
+
26
+ # 使用gptq量化:
27
+ # auto_gptq和cuda版本有对应关系,请按照`https://github.com/PanQiWei/AutoGPTQ#quick-installation`选择版本
28
+ pip install auto_gptq optimum -U
29
+
30
+ # 使用bnb量化:
31
+ pip install bitsandbytes -U
32
+ ```
33
+
34
+ 我们提供了一系列脚本展现SWIFT的量化导出能力:
35
+ - 支持[AWQ](https://github.com/modelscope/ms-swift/blob/main/examples/export/quantize/awq.sh)/[GPTQ](https://github.com/modelscope/ms-swift/blob/main/examples/export/quantize/gptq.sh)/[BNB](https://github.com/modelscope/ms-swift/blob/main/examples/export/quantize/bnb.sh)量化导出。
36
+ - 多模态量化: 支持使用GPTQ和AWQ对多模态模型进行量化,其中AWQ支持的多模态模型有限。参考[这里](https://github.com/modelscope/ms-swift/tree/main/examples/export/quantize/mllm)。
37
+ - 更多系列模型的支持: 支持[Bert](https://github.com/modelscope/ms-swift/tree/main/examples/export/quantize/bert),[Reward Model](https://github.com/modelscope/ms-swift/tree/main/examples/export/quantize/reward_model)的量化导出。
38
+ - 使用SWIFT量化导出的模型支持使用vllm/lmdeploy进行推理加速;也支持使用QLoRA继续进行SFT/RLHF。
39
+
40
+
41
+ ## 推送模型
42
+
43
+ SWIFT支持将训练/量化的模型重新推送到ModelScope/HuggingFace。默认推送到ModelScope,你可以指定`--use_hf true`推送到HuggingFace。
44
+ ```shell
45
+ swift export \
46
+ --model output/vx-xxx/checkpoint-xxx \
47
+ --push_to_hub true \
48
+ --hub_model_id '<model-id>' \
49
+ --hub_token '<sdk-token>' \
50
+ --use_hf false
51
+ ```
52
+
53
+ 小贴士:
54
+ - 你可以使用`--model <checkpoint-dir>`或者`--adapters <checkpoint-dir>`指定需要推送的checkpoint目录,这两种写法在推送模型场景没有差异。
55
+ - 推送到ModelScope时,你需要确保你已经注册了魔搭账号,你的SDK token可以在[该页面](https://www.modelscope.cn/my/myaccesstoken)中获取。推送模型需确保sdk token的账号具有model_id对应组织的编辑权限。推送模型将自动创建对应model_id的模型仓库(如果该模型仓库不存在),你可以使用`--hub_private_repo true`来自动创建私有的模型仓库。
ms-swift/docs/source/_templates/autosummary/class.rst ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ .. currentmodule:: {{ module }}
2
+
3
+
4
+ {{ name | underline}}
5
+
6
+ .. autoclass:: {{ name }}
7
+ :inherited-members:
8
+ :members:
9
+
10
+ .. autogenerated from source/_templates/autosummary/class.rst
ms-swift/docs/source_en/BestPractices/Embedding.md ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Embedding Training
2
+
3
+ SWIFT has already supported the training of Embedding models, including both pure text and multimodal types. The currently supported models are:
4
+
5
+ 1. **ModernBERT Embedding Model**
6
+ - [ModelScope](https://modelscope.cn/models/iic/gte-modernbert-base) | [Hugging Face](https://huggingface.co/Alibaba-NLP/gte-modernbert-base)
7
+ 2. **GTE Embedding Models**
8
+ - **1.5B**: [ModelScope](https://www.modelscope.cn/models/iic/gte_Qwen2-1.5B-instruct) | [Hugging Face](https://huggingface.co/Alibaba-NLP/gte-Qwen2-1.5B-instruct)
9
+ - **7B**: [ModelScope](https://www.modelscope.cn/models/iic/gte_Qwen2-7B-instruct) | [Hugging Face](https://huggingface.co/Alibaba-NLP/gte-Qwen2-7B-instruct)
10
+ 3. **GME Embedding Models**
11
+ - **2B**: [ModelScope](https://www.modelscope.cn/models/iic/gme-Qwen2-VL-2B-Instruct) | [Hugging Face](https://huggingface.co/Alibaba-NLP/gme-Qwen2-VL-2B-Instruct)
12
+ - **7B**: [ModelScope](https://www.modelscope.cn/models/iic/gme-Qwen2-VL-7B-Instruct) | [Hugging Face](https://huggingface.co/Alibaba-NLP/gme-Qwen2-VL-7B-Instruct)
13
+
14
+ Developers can integrate their own models independently. The `forward` output of the model needs to satisfy:
15
+
16
+ ```json
17
+ {"last_hidden_state": some-embedding-tensor}
18
+ ```
19
+
20
+ The return value should be a JSON with the key `last_hidden_state`, and the value should be the embedding tensor. For the input part, you can use the templates we have already supported.
21
+
22
+ **Note:** Currently, SWIFT supports embedding models that conform to pure text or multimodal LLMs. It does not support the training of CLIP-type models at this time.
23
+
24
+ Besides, All Embedding models supported by SWIFT have a normalize layer at last, consider add one when you are adding new models.
25
+
26
+ ## Loss
27
+
28
+ The Embedding models supported by SWIFT currently can use the following loss functions:
29
+
30
+ - **cosine_similarity**: Cosine similarity loss, which calculates the similarity between two embeddings and fits based on the label value. It is effectively an MSE loss.
31
+ - **contrastive**: Contrastive learning loss with adjustable margin. Labels are only supported as 0 and 1.
32
+ - **online_contrastive**: Contrastive loss considering hard negatives and hard positives. Labels are only supported as 0 and 1.
33
+ - **infonce**: Computes pairwise cosine similarities between different rows within the same batch, maximizing similarity within rows and minimizing similarity between different rows. No labels are required.
34
+
35
+ The source code for the loss functions can be found [here](https://github.com/modelscope/ms-swift/blob/main/swift/plugin/loss.py).
36
+
37
+ ## Dataset Format
38
+
39
+ > **Note:**
40
+ > 1. The `<image>` tag in the multimodal section below can appear in any position within `query`, `response`, or `rejected_response`. It is only required that the number of tags matches the number of values in `images`.
41
+ > 2. The correspondence between tags and `images` follows the order: first matching the `<image>` tags in `query`, then those in `response`, and finally parsing the `<image>` tags in `rejected_response` sequentially.
42
+ > 3. `query` represents the anchor sample, `response` represents the positive or contrastive sample, and `rejected_response` corresponds to hard negative samples.
43
+ > 4. The `<video>` and `<audio>` tags are also supported, enabling native support for video and audio embeddings.
44
+
45
+ ### Format for Cosine Similarity Loss
46
+
47
+ ```json lines
48
+ # LLM
49
+ {"query": "sentence1", "response": "sentence2", "label": 0.8}
50
+ # MLLM
51
+ {"query": "<image>", "response": "<image>sentence", "images": ["/some/images1.jpg", "/some/images2.jpg"], "label": 0.7}
52
+ {"query": "sentence1", "response": "<image>sentence2", "images": ["/some/images1.jpg"], "label": 0.7}
53
+ ```
54
+
55
+ The eval metrics are the Pearson and Spearman's Rank Correlation Coefficient of the embeddings' euclidean distance/dot production and so on, totally 8 values.
56
+
57
+ ### Format for Contrastive/Online Contrastive Loss
58
+
59
+ ```json lines
60
+ # LLM
61
+ {"query": "sentence1", "response": "sentence2", "label": 1}
62
+ # MLLM
63
+ {"query": "<image>", "response": "sentence", "images": "/some/images.jpg", "label": 1}
64
+ {"query": "<image>sentence1", "response": "sentence2", "images": "/some/images.jpg", "label": 0}
65
+ ```
66
+
67
+ ### Format for InfoNCE
68
+
69
+ ```json lines
70
+ # LLM
71
+ {"query": "sentence1", "response": "sentence2"}
72
+ # MLLM
73
+ {"query": "<image>", "response": "sentence", "images": "/some/images.jpg"}
74
+ {"query": "<image>sentence1", "response": "<image>sentence2", "rejected_response": ["<image>sentence1", "<image>sentence2"], "images": ["/some/images.jpg", "/some/images.jpg", "/some/images.jpg", "/some/images.jpg"]}
75
+ ```
76
+
77
+ InfoNCE loss supports the following environment variables:
78
+ 1. `INFONCE_TEMPERATURE`: The temperature parameter. If not set, the default value is 0.01.
79
+ 2. `INFONCE_USE_BATCH`: Determines whether to use `rejected_response` within the sample (hard negative samples) or to use all `responses` within a batch. The default is `True`, which means using responses within the batch.
80
+ 3. `INFONCE_HARD_NEGATIVES`: The number of hard negatives. If not set, all samples in `rejected_response` will be used. Since the lengths may not be consistent, a for loop will be used to compute the loss (which is slower). If set to a specific number, and there are not enough samples, the missing number will be randomly sampled. If there are excess samples, the first `INFONCE_HARD_NEGATIVES` will be selected.
81
+ 4. `INFONCE_MASK_FAKE_NEGATIVE`: Masks out fake negatives. The default is set to False. When enabled, it checks if a sample's similarity is greater than the positive sample's similarity plus 0.1. If so, the sample's similarity is set to -inf to prevent the leakage of the positive sample.
82
+
83
+ > It is also possible to set the number of hard negatives to be equal in the dataset, so that even if not set, the for loop method will not be used, thereby speeding up computation.
84
+ >
85
+ > `rejected_response` can also be omitted. In this case, `INFONCE_USE_BATCH` remains `True` and will use other samples within the batch as rejected responses.
86
+
87
+ The evaluation of InfoNCE loss includes the following metrics:
88
+ - mean_neg: The average of all hard negatives
89
+ - mean_pos: The average of all positives
90
+ - margin: The average of (positive - max hard negative)
91
+
92
+ ## Scaffolding
93
+
94
+ SWIFT provides two scaffold training scripts:
95
+
96
+ - [GTE Model](https://github.com/tastelikefeet/swift/blob/main/examples/train/embedding/train_gte.sh)
97
+ - [GME Model](https://github.com/tastelikefeet/swift/blob/main/examples/train/embedding/train_gme.sh)
ms-swift/docs/source_en/BestPractices/GRPO-Code-Training.md ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Code Training with GRPO
2
+ This document explains how to use GRPO to train models for code tasks.
3
+
4
+
5
+ Model: [Qwen/Qwen2.5-7B-Instruct](https://www.modelscope.cn/models/Qwen/Qwen2.5-VL-7B-Instruct)
6
+
7
+ Dataset: [open-r1/verifiable-coding-problems-python-10k](https://www.modelscope.cn/datasets/open-r1/verifiable-coding-problems-python-10k/dataPeview)
8
+
9
+ dataset example
10
+ ```json
11
+ {
12
+ "problem": "Solve the following coding problem using the programming language python: Polycarp has $n$ different binary words. A word called binary if it contains only characters '0' and '1'. For example, these words are binary: \"0001\", \"11\", \"0\" and \"0011100\". Polycarp wants to offer his set of $n$ binary words to play a game \"words\". In this game, players name words and each next word (starting from the second) must start with the last character of the previous word. The first word can be any. For example, these sequence of words can be named during the game: \"0101\", \"1\", \"10\", \"00\", \"00001\". Word reversal is the operation of reversing the order of the characters. For example, the word \"0111\" after the reversal becomes \"1110\", the word \"11010\" after the reversal becomes \"01011\". Probably, Polycarp has such a set of words that there is no way to put them in the order correspondent to the game rules. In this situation, he wants to reverse some words from his set so that: the final set of $n$ words still contains different words (i.e. all words are unique); there is a way to put all words of the final set of words in the order so that the final sequence of $n$ words is consistent with the game rules. Polycarp wants to reverse minimal number of words. Please, help him. -----Input----- The first line of the input contains one integer $t$ ($1 \\le t \\le 10^4$) — the number of test cases in the input. Then $t$ test cases follow. The first line of a test case contains one integer $n$ ($1 \\le n \\le 2\\cdot10^5$) — the number of words in the Polycarp's set. Next $n$ lines contain these words. All of $n$ words aren't empty and contains only characters '0' and '1'. The sum of word lengths doesn't exceed $4\\cdot10^6$. All words are different. Guaranteed, that the sum of $n$ for all test cases in the input doesn't exceed $2\\cdot10^5$. Also, guaranteed that the sum of word lengths for all test cases in the input doesn't exceed $4\\cdot10^6$. -----Output----- Print answer for all of $t$ test cases in the order they appear. If there is no answer for the test case, print -1. Otherwise, the first line of the output should contain $k$ ($0 \\le k \\le n$) — the minimal number of words in the set which should be reversed. The second line of the output should contain $k$ distinct integers — the indexes of the words in the set which should be reversed. Words are numerated from $1$ to $n$ in the order they appear. If $k=0$ you can skip this line (or you can print an empty line). If there are many answers you can print any of them. -----Example----- Input 4 4 0001 1000 0011 0111 3 010 101 0 2 00000 00001 4 01 001 0001 00001 Output 1 3 -1 0 2 1 2 The input will be stdin and you should print your solution to stdout Now solve the problem and return the code.",
13
+ "verification_info": {
14
+ "language": "python",
15
+ "test_cases": [
16
+ {
17
+ "input": "4\n4\n0001\n1000\n0011\n0111\n3\n010\n101\n0\n2\n00000\n00001\n4\n01\n001\n0001\n00001\n",
18
+ "output": "1\n3 \n-1\n0\n\n2\n1 2 \n",
19
+ "type": "stdin_stdout"
20
+ }
21
+ ]
22
+ }
23
+ }
24
+ ```
25
+
26
+ `verification_info` provides the programming language as well as test cases, which include input and expected output.
27
+
28
+
29
+ ## Reward Functions
30
+
31
+ The training process utilizes two reward functions: `code_reward` and `code_format`. For implementation details, refer to the [code]((../../../examples/train/grpo/plugin/plugin.py)).
32
+
33
+
34
+ - `code_reward` Executes the generated code using [e2b](https://e2b.dev/) or [judge0](https://judge0.com/). Validates the code against the test cases in the dataset and assigns a reward value based on correctness.
35
+ - `code_format` Requires the model to produce formatted responses that include code blocks.
36
+
37
+ Note: Currently, executing code through E2B only supports the Python language. If you need to execute code in other languages, you can use Judge0([judge0 supported languages](https://github.com/judge0/judge0?tab=readme-ov-file#supported-languages)).
38
+
39
+ ## Training Script
40
+
41
+ - Register on [e2b](https://e2b.dev/dashboard) to obtain your E2B_API_KEY and set it as an environment variable.
42
+ - Add `external_code_reward` as a reward function with `--reward_funcs`.
43
+ - Set `--external_plugins` to the path of plugin.py.
44
+
45
+ ```bash
46
+ E2B_API_KEY=xxx \
47
+ WANDB_API_KEY=xxx \
48
+ CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
49
+ NPROC_PER_NODE=7 \
50
+ swift rlhf \
51
+ --rlhf_type grpo \
52
+ --model Qwen/Qwen2.5-7B-Instruct \
53
+ --external_plugins examples/train/grpo/plugin/plugin.py \
54
+ --reward_funcs external_code_reward external_code_format \
55
+ --reward_weights 1.0 0.1 \
56
+ --use_vllm true \
57
+ --vllm_device auto \
58
+ --vllm_gpu_memory_utilization 0.7 \
59
+ --vllm_max_model_len 8192 \
60
+ --train_type lora \
61
+ --torch_dtype bfloat16 \
62
+ --dataset 'open-r1/verifiable-coding-problems-python-10k' \
63
+ --max_completion_length 2048 \
64
+ --num_train_epochs 1 \
65
+ --per_device_train_batch_size 2 \
66
+ --per_device_eval_batch_size 2 \
67
+ --learning_rate 1e-6 \
68
+ --gradient_accumulation_steps 1 \
69
+ --eval_steps 200 \
70
+ --save_steps 200 \
71
+ --save_total_limit 2 \
72
+ --logging_steps 5 \
73
+ --max_length 4096 \
74
+ --output_dir output \
75
+ --warmup_ratio 0.05 \
76
+ --dataloader_num_workers 4 \
77
+ --dataset_num_proc 4 \
78
+ --num_generations 14 \
79
+ --temperature 0.9 \
80
+ --num_infer_workers 1 \
81
+ --system 'examples/train/grpo/prompt.txt' \
82
+ --deepspeed zero2 \
83
+ --log_completions true \
84
+ --report_to wandb
85
+ ```
86
+ ### judge0
87
+ - Set environment variables:
88
+ - (Required) JUDGE0_ENDPOINT: The endpoint address for accessing Judge0.
89
+ - (Optional) JUDGE0_X_AUTH_TOKEN: The access token for Judge0.
90
+ - Add `external_code_reward_by_judge0` as a reward function with `--reward_funcs`.
91
+ - Set `--external_plugins` to the path of `plugin.py`.
92
+
93
+ ```bash
94
+ JUDGE0_ENDPOINT=xxx \
95
+ JUDGE0_X_AUTH_TOKEN=xxx \
96
+ WANDB_API_KEY=xxx \
97
+ CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
98
+ NPROC_PER_NODE=7 \
99
+ swift rlhf \
100
+ --rlhf_type grpo \
101
+ --model Qwen/Qwen2.5-7B-Instruct \
102
+ --external_plugins examples/train/grpo/plugin/plugin.py \
103
+ --reward_funcs external_code_reward_by_judge0 external_code_format \
104
+ --reward_weights 1.0 0.1 \
105
+ --use_vllm true \
106
+ --vllm_device auto \
107
+ --vllm_gpu_memory_utilization 0.7 \
108
+ --vllm_max_model_len 8192 \
109
+ --train_type lora \
110
+ --torch_dtype bfloat16 \
111
+ --dataset 'open-r1/verifiable-coding-problems-python-10k' \
112
+ --max_completion_length 2048 \
113
+ --num_train_epochs 1 \
114
+ --per_device_train_batch_size 2 \
115
+ --per_device_eval_batch_size 2 \
116
+ --learning_rate 1e-6 \
117
+ --gradient_accumulation_steps 1 \
118
+ --eval_steps 200 \
119
+ --save_steps 200 \
120
+ --save_total_limit 2 \
121
+ --logging_steps 5 \
122
+ --max_length 4096 \
123
+ --output_dir output \
124
+ --warmup_ratio 0.05 \
125
+ --dataloader_num_workers 4 \
126
+ --dataset_num_proc 4 \
127
+ --num_generations 14 \
128
+ --temperature 0.9 \
129
+ --num_infer_workers 1 \
130
+ --system 'examples/train/grpo/prompt.txt' \
131
+ --deepspeed zero2 \
132
+ --log_completions true \
133
+ --report_to wandb
134
+ ```
135
+ Training Reward Curve
136
+ ![Training Reward Curve](../../resources/grpo_code.png)
ms-swift/docs/source_en/BestPractices/GRPO-Multi-Modal-Training.md ADDED
@@ -0,0 +1,349 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Complete Multimodal GRPO Experiment Workflow
2
+
3
+ This document explains how to use SWIFT GRPO for training multimodal models and tasks. The goal is to train on multiple multimodal tasks to improve task accuracy. Task definitions, training parameters, etc., refer to [R1-V](https://github.com/Deep-Agent/R1-V.git) and [open-r1-multimodal](https://github.com/EvolvingLMMs-Lab/open-r1-multimodal.git).
4
+
5
+ ---
6
+
7
+ ## **ClevrCount Task**
8
+
9
+ ### **Task and Dataset Definition**
10
+
11
+ This task is based on the `clevr_cogen_a_train` dataset. The model's goal is to output the number of objects in the image. Therefore, we define the dataset as follows:
12
+
13
+ ```python
14
+ class ClevrPreprocessor(ResponsePreprocessor):
15
+
16
+ def preprocess(self, row: Dict[str, Any]) -> Dict[str, Any]:
17
+ query = row.get('query', '')
18
+ query = f"""{query} Output the thinking process in <think> </think> and
19
+ final answer (number) in <answer> </answer> tags."""
20
+ row.update({'query': query})
21
+ return super().preprocess(row)
22
+
23
+
24
+ register_dataset(
25
+ DatasetMeta(
26
+ ms_dataset_id='okwinds/clevr_cogen_a_train',
27
+ subsets=[
28
+ SubsetDataset(
29
+ name='default',
30
+ subset='default',
31
+ split=['train'],
32
+ ),
33
+ ],
34
+ preprocess_func=ClevrPreprocessor(),
35
+ tags=['qa', 'math']))
36
+ ```
37
+
38
+ The purpose of redefining the dataset preprocessor here is to modify the query. A sample dataset entry is as follows, including `messages`, `images`, and `solution` fields. The `solution` is used in the reward function, while `messages` and `images` serve as model input.
39
+ - Note: `{'role': 'assistant', 'content': '<answer> 3 </answer>'}` will be removed in GRPOTrainer and can be ignored. The 'solution' field will be passed directly into the ORM. When creating a custom dataset, the 'images' field should be organized as `["image_path1", "image_path2"]`.
40
+
41
+ ```json
42
+ {
43
+ "images": ["image_path1", "image_path2"],
44
+ "messages": [
45
+ {
46
+ "role": "user",
47
+ "content": "How many items are there in the image? Output the thinking process in <think> </think> and\n final answer (number) in <answer> </answer> tags."
48
+ }
49
+ ],
50
+ "solution": "<answer> 3 </answer>"
51
+ }
52
+
53
+ ```
54
+
55
+ ---
56
+
57
+ ## **Reward Function Definition**
58
+
59
+ This task uses two reward functions: one is the format reward function mentioned in `Deepseek-R1`, and the other is the accuracy reward function for ClevrCount. The former is built into SWIFT and can be used directly with `--reward_funcs format`. The latter needs to be custom-defined. Here, we use the `external_plugin` method to define the accuracy reward function by placing the code in `swift/examples/train/grpo/plugin/plugin.py`.
60
+
61
+ The reward function's input includes `completions` and `solution` fields, representing the model-generated text and ground truth, respectively. Each is a list, allowing the computation of multiple completions simultaneously. Note that the `solution` field is passed through directly from the dataset definition. If there are task changes, corresponding modifications can be made to the dataset and reward function.
62
+
63
+ ```python
64
+ class MultiModalAccuracyORM(ORM):
65
+
66
+ def __call__(self, completions, solution, **kwargs) -> List[float]:
67
+ """
68
+ Reward function that checks if the completion is correct.
69
+ Args:
70
+ completions (list[str]): Generated outputs
71
+ solution (list[str]): Ground Truths.
72
+
73
+ Returns:
74
+ list[float]: Reward scores
75
+ """
76
+ rewards = []
77
+ from math_verify import parse, verify
78
+ for content, sol in zip(completions, solution):
79
+ reward = 0.0
80
+ # Try symbolic verification first
81
+ try:
82
+ answer = parse(content)
83
+ if float(verify(answer, parse(sol))) > 0:
84
+ reward = 1.0
85
+ except Exception:
86
+ pass # Continue to next verification method if this fails
87
+
88
+ # If symbolic verification failed, try string matching
89
+ if reward == 0.0:
90
+ try:
91
+ # Extract answer from solution if it has think/answer tags
92
+ sol_match = re.search(r'<answer>(.*?)</answer>', sol)
93
+ ground_truth = sol_match.group(1).strip() if sol_match else sol.strip()
94
+
95
+ # Extract answer from content if it has think/answer tags
96
+ content_match = re.search(r'<answer>(.*?)</answer>', content)
97
+ student_answer = content_match.group(1).strip() if content_match else content.strip()
98
+
99
+ # Compare the extracted answers
100
+ if student_answer == ground_truth:
101
+ reward = 1.0
102
+ except Exception:
103
+ pass # Keep reward as 0.0 if both methods fail
104
+ rewards.append(reward)
105
+ return rewards
106
+ orms['external_r1v_acc'] = MultiModalAccuracyORM
107
+ ```
108
+
109
+ ---
110
+
111
+ ### **GRPO Training Experiment Log**
112
+
113
+ #### **Training Parameters**
114
+
115
+ We selected `Qwen2.5-VL-3B-Instruct` as the base model for training. The main reason for choosing the `Instruct` model over the base model is to rapidly achieve format rewards. Experiments were conducted on 8 GPUs. SWIFT GRPO training supports multi-GPU deployment to accelerate rollouts, so we set `num_infer_workers` to 2 and processes to 6 (2 GPUs for deployment, 6 GPUs for training). If you encounter deployment errors for `qwen2.5-vl` on `vllm`, refer to [this issue](https://github.com/vllm-project/vllm/issues/13285).
116
+
117
+ Since the task is simple, we set `max_completion_length` to 1024 and selected `external_r1v_acc` and `format` as reward functions. The learning rate and beta are set to `1e-6` and `0.001`, respectively. Other configurations are as follows. The settings for `batch_size` and `num_generations` can be referenced from [GRPO Full Workflow](./GRPO完整流程.md).
118
+
119
+ ```shell
120
+ WANDB_API_KEY=your_wandb_api_key \
121
+ NPROC_PER_NODE=6 \
122
+ swift rlhf \
123
+ --rlhf_type grpo \
124
+ --model Qwen/Qwen2.5-VL-3B-Instruct \
125
+ --external_plugins examples/train/grpo/plugin/plugin.py \
126
+ --reward_funcs external_r1v_acc format \
127
+ --use_vllm true \
128
+ --vllm_device auto \
129
+ --vllm_gpu_memory_utilization 0.6 \
130
+ --train_type full \
131
+ --torch_dtype bfloat16 \
132
+ --dataset 'okwinds/clevr_cogen_a_train' \
133
+ --vllm_max_model_len 8192 \
134
+ --max_completion_length 1024 \
135
+ --num_train_epochs 1 \
136
+ --per_device_train_batch_size 8 \
137
+ --per_device_eval_batch_size 8 \
138
+ --learning_rate 1e-6 \
139
+ --gradient_accumulation_steps 2 \
140
+ --save_strategy 'steps' \
141
+ --eval_strategy 'steps' \
142
+ --eval_steps 1000 \
143
+ --save_steps 1000 \
144
+ --save_total_limit 10 \
145
+ --logging_steps 1 \
146
+ --output_dir output/GRPO_CLEVR_COUNTDOWN \
147
+ --warmup_ratio 0.01 \
148
+ --dataloader_num_workers 4 \
149
+ --num_generations 24 \
150
+ --temperature 1.0 \
151
+ --system 'examples/train/grpo/prompt.txt' \
152
+ --deepspeed zero3 \
153
+ --log_completions true \
154
+ --report_to wandb \
155
+ --num_iterations 1 \
156
+ --num_infer_workers 2 \
157
+ --async_generate false \
158
+ --beta 0.001 \
159
+ ```
160
+
161
+ #### **Experimental Observations**
162
+
163
+ [image.png](../../resources/grpo_clevr_count.png)
164
+
165
+ - Given the simplicity of the dataset and task, the model converged after 500 epochs. Key observations:
166
+ 1. The custom `ClevrORM` reward steadily increased, proving the model learned how to complete the task. The task success rate climbed from an initial 0.4 to nearly 1.
167
+ 2. The `Format Reward` remained stable at 1, likely due to the consistent query format across all dataset samples.
168
+ 3. The `reward_std` stabilized below 0.1.
169
+ 4. The `completion length` eventually stabilized between 60-80 tokens, with the model learning a fixed output pattern for item-by-item counting.
170
+
171
+ ---
172
+ For additional tasks like Geometric QA and Open R1 Multimodal datasets, refer to their respective sections in the full experiment documentation.
173
+
174
+ ## **Geometric QA Task**
175
+
176
+ ### **Task and Dataset Definition**
177
+
178
+ This task is a Geometric QA task, where the task description is: given a geometric figure, answer mathematical questions related to the figure. The original data comes from [this paper](https://arxiv.org/pdf/2312.11370), and [R1-V](https://github.com/Deep-Agent/R1-V.git) has preprocessed the data into a `problem-solution` format while retaining the images in the `image` field. Therefore, we do not need to redefine the dataset and can directly use `--dataset AI-ModelScope/GEOQA_R1V_Train_8K`.
179
+
180
+ ---
181
+
182
+ ### **Reward Function**
183
+
184
+ As this is also a mathematical problem, and the answers are already processed into final results, we directly use the previously defined `MultiModalAccuracyORM` reward function.
185
+
186
+ ---
187
+
188
+ ### **GRPO Training Experiment Log**
189
+
190
+ #### **Training Parameters**
191
+
192
+ The selected model and most hyperparameters are similar to the previous experiment, with two main differences:
193
+ 1. **SWIFT now supports the `--num_iteration` parameter**, allowing multiple updates during a single rollout. We set it to 2.
194
+ 2. During the experiment, we found that training might become unstable in mathematical problems, causing the model to collapse. This is characterized by a sharp drop in all rewards, a rapid increase in loss, `grad_norm`, and KL divergence, with no subsequent recovery. To prevent this, we set `--max_grad_norm 0.5` to ensure stable training. Note that this instability can have some randomness.
195
+
196
+ ```shell
197
+ WANDB_API_KEY=your_wandb_api_key \
198
+ MAX_PIXELS=401408 \
199
+ NPROC_PER_NODE=6 \
200
+ swift rlhf \
201
+ --rlhf_type grpo \
202
+ --model Qwen/Qwen2.5-VL-3B-Instruct \
203
+ --external_plugins examples/train/grpo/plugin/plugin.py \
204
+ --reward_funcs external_r1v_acc format \
205
+ --use_vllm true \
206
+ --vllm_device auto \
207
+ --vllm_gpu_memory_utilization 0.6 \
208
+ --train_type full \
209
+ --torch_dtype bfloat16 \
210
+ --dataset 'AI-ModelScope/GEOQA_R1V_Train_8K' \
211
+ --vllm_max_model_len 8192 \
212
+ --max_completion_length 1024 \
213
+ --num_train_epochs 1 \
214
+ --per_device_train_batch_size 8 \
215
+ --per_device_eval_batch_size 8 \
216
+ --learning_rate 1e-6 \
217
+ --gradient_accumulation_steps 2 \
218
+ --save_strategy 'steps' \
219
+ --eval_strategy 'steps' \
220
+ --eval_steps 400 \
221
+ --save_steps 400 \
222
+ --save_total_limit 10 \
223
+ --logging_steps 1 \
224
+ --output_dir output/GRPO_GEOQA \
225
+ --warmup_ratio 0.05 \
226
+ --dataloader_num_workers 4 \
227
+ --num_generations 8 \
228
+ --temperature 1.0 \
229
+ --repetition_penalty 1.1 \
230
+ --system 'examples/train/grpo/prompt.txt' \
231
+ --deepspeed zero3 \
232
+ --log_completions true \
233
+ --report_to wandb \
234
+ --num_iterations 2 \
235
+ --num_infer_workers 2 \
236
+ --async_generate false \
237
+ --beta 0.001 \
238
+ --max_grad_norm 0.5 \
239
+ ```
240
+
241
+ ---
242
+
243
+ #### **Experimental Observations**
244
+
245
+ [image.png](../../resources/grpo_geoqa.png)
246
+
247
+ The training curve is shown above.
248
+
249
+ 1. Compared to the **Count task**, the **Geometric QA task** is significantly more challenging. As a result, the **Accuracy Reward** converges much more slowly and has larger oscillations.
250
+ 2. The `completion_length` exhibits a clear trend, eventually stabilizing at around 250 tokens.
251
+ 3. The reward converges, with the standard deviation stabilizing at around 0.2 after a total of 1300 steps.
252
+
253
+ Below is an example of the model's completion after training:
254
+
255
+ ```plaintext
256
+ User:
257
+ "If AB is the tangent to circle O with the tangent point A, and BO intersects circle O at point C, and point D is located on circle O, what is the measure of angle ADC if the degree of angle ABO is 32.0?"
258
+ Assistant:
259
+ "<think>\nTo find the measure of angle ADC, we first need to understand the properties of the tangent and the circle. Since AB is a tangent to the circle at point A, the line segment OA (which is perpendicular to the tangent AB) is perpendicular to AB. This means that angle OAB is 90 degrees.\n\nGiven that angle ABO is 32 degrees, we can find angle BAO by subtracting angle ABO from 90 degrees:\n∠BAO = 90° - ∠ABO = 90° - 32° = 58°\n\nSince angle BAO is an angle in the minor arc AD, the angle ADC, which is an angle in the minor arc AD, is half the angle BAO. Therefore, angle ADC is:\n∠ADC = 1/2 × ∠BAO = 1/2 × 58° = 29°\n\nSo, the measure of angle ADC is 29 degrees.\n</think>\n<answer>\nThe measure of angle ADC is 29 degrees.\n</answer>"
260
+ ```
261
+
262
+ ---
263
+
264
+ ## **Multimodal Open R1 Dataset Experiment**
265
+
266
+ ### **Task and Dataset Definition**
267
+
268
+ This task is based on the experiments in [open-r1-multimodal](https://github.com/EvolvingLMMs-Lab/open-r1-multimodal.git), using the dataset: [lmms-lab/multimodal-open-r1-8k-verified](https://www.modelscope.cn/datasets/lmms-lab/multimodal-open-r1-8k-verified). This dataset focuses on multimodal mathematical reasoning tasks, with data generated by GPT4o based on the `Math360K` and `Geo170K` datasets. It includes reasoning paths and verifiable answers. The dataset already contains `image`, `problem`, and `solution` fields, so no additional prompt modifications are required, and there is no need to redefine the dataset.
269
+
270
+ ---
271
+
272
+ ### **Reward Function**
273
+
274
+ We directly use the previously defined `MultiModalAccuracyORM` reward function.
275
+
276
+ ---
277
+
278
+ ### **GRPO Training Experiment Log**
279
+
280
+ #### **Training Parameters**
281
+
282
+ The selected model and most hyperparameters are similar to the previous experiment. Due to an **OOM (Out of Memory) issue**, we set `MAX_PIXELS=262144` to reduce memory usage.
283
+
284
+ ```shell
285
+ WANDB_API_KEY=your_wandb_api_key \
286
+ MAX_PIXELS=262144 \
287
+ MASTER_PORT=29600 \
288
+ NPROC_PER_NODE=6 \
289
+ swift rlhf \
290
+ --rlhf_type grpo \
291
+ --model Qwen/Qwen2.5-VL-3B-Instruct \
292
+ --external_plugins examples/train/grpo/plugin/plugin.py \
293
+ --reward_funcs external_r1v_acc format \
294
+ --use_vllm true \
295
+ --vllm_device auto \
296
+ --vllm_gpu_memory_utilization 0.6 \
297
+ --train_type full \
298
+ --torch_dtype bfloat16 \
299
+ --dataset 'lmms-lab/multimodal-open-r1-8k-verified' \
300
+ --vllm_max_model_len 8192 \
301
+ --max_completion_length 1024 \
302
+ --num_train_epochs 1 \
303
+ --per_device_train_batch_size 8 \
304
+ --per_device_eval_batch_size 8 \
305
+ --learning_rate 1e-6 \
306
+ --gradient_accumulation_steps 2 \
307
+ --save_strategy 'steps' \
308
+ --eval_strategy 'steps' \
309
+ --eval_steps 400 \
310
+ --save_steps 400 \
311
+ --save_total_limit 10 \
312
+ --logging_steps 1 \
313
+ --output_dir output/GRPO_GEOQA \
314
+ --warmup_ratio 0.05 \
315
+ --dataloader_num_workers 4 \
316
+ --num_generations 8 \
317
+ --temperature 1.0 \
318
+ --repetition_penalty 1.1 \
319
+ --system 'examples/train/grpo/prompt.txt' \
320
+ --deepspeed zero3 \
321
+ --log_completions true \
322
+ --report_to wandb \
323
+ --num_iterations 2 \
324
+ --num_infer_workers 2 \
325
+ --async_generate false \
326
+ --beta 0.001 \
327
+ --max_grad_norm 0.5 \
328
+ ```
329
+
330
+ ---
331
+
332
+ #### **Experimental Observations**
333
+
334
+ [image.png](../../resources/grpo_openr1_multimodal.png)
335
+
336
+ The training curve is shown above.
337
+
338
+ - With a total of 8k data samples, the training reached **1268 steps**, with the **Accuracy Reward** converging around 0.5.
339
+ - The `completion_length` stabilized around 200 tokens.
340
+ - The `reward_std` eventually oscillated around 0.2.
341
+
342
+ Below is an example of the model's completion after training:
343
+
344
+ ```plaintext
345
+ User:
346
+ "Based on the map, which state falls into the lowest percentage range of lots, and what is that percentage range?"
347
+ Assistant:
348
+ "<think>\nThe image provided shows a color-coded map of the USA indicating different ranges of lot percentages across various states. According to the legend at the bottom, the lowest percentage range (6.0% - 6.5%) is represented by white. In the image, Alabama (AL) is shaded in white, which corresponds to the 6.0% - 6.5% category. Therefore, based on the map, the state that falls into the lowest percentage range of lots is Alabama, with the percentage range of 6.0% - 6.5%.\nTherefore, the answer is 6.0% - 6.5%.\n</think>\n<answer>Alabama</answer>"
349
+ ```
ms-swift/docs/source_en/BestPractices/GRPO.md ADDED
@@ -0,0 +1,298 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Complete GRPO Experiment Process
2
+
3
+ This article starts with the relatively simple mathematical task "Countdown Game" and introduces the complete GRPO training process through several steps: dataset definition, reward function definition, and GRPO training. The task definition and training parameters are based on [mini-deepseek-r1](https://github.com/philschmid/deep-learning-pytorch-huggingface/blob/main/training/mini-deepseek-r1-aha-grpo.ipynb).
4
+
5
+ ## Task and Dataset Definition
6
+
7
+ The goal of the Countdown Game task is to reach a target number using the given numbers and the four basic arithmetic operations. Therefore, we define the dataset as follows:
8
+
9
+ ```python
10
+ class CoundownTaskPreprocessor(ResponsePreprocessor):
11
+
12
+ def preprocess(self, row: Dict[str, Any]) -> Dict[str, Any]:
13
+ numbers = row['nums']
14
+ target = row.pop('response', None)
15
+ query = f"""
16
+ Using the numbers {numbers}, create an equation that equals {target}.
17
+ You can use basic arithmetic operations (+, -, *, /) and each number can only be used once.
18
+ Show your work in <think> </think> tags. And return the final equation and answer in <answer> </answer> tags,
19
+ for example <answer> (1 + 2) / 3 * 4 = 4 </answer>.
20
+ """
21
+ row.update({'target': target, 'query': query})
22
+ return super().preprocess(row)
23
+
24
+ register_dataset(
25
+ DatasetMeta(
26
+ ms_dataset_id='zouxuhong/Countdown-Tasks-3to4',
27
+ subsets=['default'],
28
+ preprocess_func=CoundownTaskPreprocessor(),
29
+ tags=['math']))
30
+ ```
31
+
32
+ Through a template, numbers and the target are used to define the task, and a `query` field is provided for model sampling. At the same time, we need to retain the `nums` and `target` fields for subsequent reward function calculation.
33
+
34
+ ## Reward Function Definition
35
+
36
+ Two reward functions are used for this task: one is the format reward function mentioned in Deepseek-R1, and the other is the accuracy reward function for the Countdown Game. The former is already built into Swift and can be used directly with `--reward_funcs format`, while the latter requires custom definition. Here, we use the `external_plugin` method to define the accuracy reward function, placing the code in `swift/examples/train/grpo/plugin/plugin.py`.
37
+
38
+ The input to the reward function includes three fields: `completions`, `target`, and `nums`, representing the model-generated text, the target answer, and the available numbers, respectively. Each is a list, supporting simultaneous computation of multiple completions. Note that, except for `completions`, the other parameters are transparently passed from the fields defined in the dataset. If there are changes to the task, adjustments can be made to both the dataset and the reward function as needed.
39
+
40
+ ```python
41
+ class CountdownORM(ORM):
42
+ def __call__(self, completions, target, nums, **kwargs) -> List[float]:
43
+ """
44
+ Evaluates completions based on Mathematical correctness of the answer
45
+ Args:
46
+ completions (list[str]): Generated outputs
47
+ target (list[str]): Expected answers
48
+ nums (list[str]): Available numbers
49
+ Returns:
50
+ list[float]: Reward scores
51
+ """
52
+ rewards = []
53
+ for completion, gt, numbers in zip(completions, target, nums):
54
+ try:
55
+ # Check if the format is correct
56
+ match = re.search(r"<answer>(.*?)<\/answer>", completion)
57
+ if match is None:
58
+ rewards.append(0.0)
59
+ continue
60
+ # Extract the "answer" part from the completion
61
+ equation = match.group(1).strip()
62
+ if '=' in equation:
63
+ equation = equation.split('=')[0]
64
+ # Extract all numbers from the equation
65
+ used_numbers = [int(n) for n in re.findall(r'\d+', equation)]
66
+ # Check if all numbers are used exactly once
67
+ if sorted(used_numbers) != sorted(numbers):
68
+ rewards.append(0.0)
69
+ continue
70
+ # Define a regex pattern that only allows numbers, operators, parentheses, and whitespace
71
+ allowed_pattern = r'^[\d+\-*/().\s]+$'
72
+ if not re.match(allowed_pattern, equation):
73
+ rewards.append(0.0)
74
+ continue
75
+ # Evaluate the equation with restricted globals and locals
76
+ result = eval(equation, {"__builti'ns__": None}, {})
77
+ # Check if the equation is correct and matches the ground truth
78
+ if abs(float(result) - float(gt)) < 1e-5:
79
+ rewards.append(1.0)
80
+ else:
81
+ rewards.append(0.0)
82
+ except Exception as e:
83
+ # If evaluation fails, reward is 0
84
+ rewards.append(0.0)
85
+ return rewards
86
+ orms['external_countdown'] = CountdownORM
87
+ ```
88
+
89
+ ## GRPO Training Experiment Record
90
+
91
+ We first present the GRPO formula:
92
+
93
+ $$
94
+ \begin{aligned}
95
+ \mathcal{J}_{G R P O}(\theta) & =\mathbb{E}\left[q \sim P(Q),\left\{o_i\right\}_{i=1}^G \sim \pi_{\theta_{o l d}}(O \mid q)\right] \\
96
+ & \frac{1}{G} \sum_{i=1}^G \frac{1}{\left|o_i\right|} \sum_{t=1}^{\left|o_i\right|}\left\{\min \left[\frac{\pi_\theta\left(o_{i, t} \mid q, o_{i,<t}\right)}{\pi_{\theta_{o l d}}\left(o_{i, t} \mid q, o_{i,<t}\right)} \hat{A}_{i, t}, \operatorname{clip}\left(\frac{\pi_\theta\left(o_{i, t} \mid q, o_{i,<t}\right)}{\pi_{\theta_{o l d}}\left(o_{i, t} \mid q, o_{i,<t}\right)}, 1-\varepsilon, 1+\varepsilon\right) \hat{A}_{i, t}\right]-\beta \mathbb{D}_{K L}\left[\pi_\theta| | \pi_{r e f}\right]\right\}
97
+ \end{aligned}
98
+ $$
99
+
100
+ ### Training Parameters
101
+
102
+ We selected Qwen2.5-3B-Instruct as the base model for training, as using an instruct-tuned model allows for faster acquisition of format rewards. The experiment was conducted on three GPUs, with vLLM inference deployed on the last GPU and two processes set on the remaining GPUs for gradient updates.
103
+
104
+ Since the task is relatively simple, we set both `max_completion_length` and `vllm_max_model_len` to 1024. For more complex tasks, the model output length can be increased appropriately, but note that **the larger these parameters, the more GPU memory is required, and the slower the training speed**. The training time per step is linearly related to `max_completion_length`.
105
+
106
+ In our experiment, the total batch size is:
107
+
108
+ $$
109
+ \text{total batch size} = \text{num\_processes} \times \text{per\_device\_train\_batch\_size} \times \text{gradient\_accumulation\_steps} = 2 \times 8 \times 8 = 128
110
+ $$
111
+
112
+ There is a constraint:
113
+
114
+ $$
115
+ \text{num\_processes} \times \text{per\_device\_train\_batch\_size} \text{ must divide evenly into } \text{num\_generations},
116
+ $$
117
+
118
+ where `num_generations` corresponds to $G$ in the GRPO formula. Therefore, we set it to 8. Note that the single-GPU batch size is also closely related to GPU memory capacity, so set an appropriate value based on memory limits. Additionally, the total number of steps can be calculated as:
119
+
120
+ $$
121
+ \text{num\_steps} = \text{epochs} \times \text{len(datasets)} \times \text{num\_generations} \div \text{batch\_size}
122
+ $$
123
+
124
+ This formula should guide the planning of learning rate and warmup settings.
125
+
126
+ Finally, two important parameters are learning rate and $\beta$. The learning rate is straightforward, while $\beta$ is the weight of the KL divergence gradient in the formula. Increasing these parameters accelerates convergence but may lead to instability. After experimentation, we set them to `5e-7` and `0.001`, respectively. During training, adjust these parameters appropriately if instability or oscillations occur.
127
+
128
+ For KL divergence, the community has extensive discussions, such as [Why GRPO Adheres to KL Divergence](https://zhuanlan.zhihu.com/p/25862547100).
129
+
130
+ Other parameter settings were not explored in detail and will not be discussed here.
131
+
132
+ ```bash
133
+ CUDA_VISIBLE_DEVICES=0,1,2 \
134
+ WANDB_API_KEY=your_wandb_key \
135
+ NPROC_PER_NODE=2 \
136
+ swift rlhf \
137
+ --rlhf_type grpo \
138
+ --model Qwen/Qwen2.5-3B-Instruct \
139
+ --external_plugins examples/train/grpo/plugin/plugin.py \
140
+ --reward_funcs external_countdown format \
141
+ --use_vllm true \
142
+ --vllm_device auto \
143
+ --vllm_gpu_memory_utilization 0.6 \
144
+ --train_type full \
145
+ --torch_dtype bfloat16 \
146
+ --dataset 'zouxuhong/Countdown-Tasks-3to4#50000' \
147
+ --max_length 2048 \
148
+ --max_completion_length 1024 \
149
+ --num_train_epochs 1 \
150
+ --per_device_train_batch_size 8 \
151
+ --per_device_eval_batch_size 8 \
152
+ --learning_rate 5e-7 \
153
+ --gradient_accumulation_steps 8 \
154
+ --eval_steps 500 \
155
+ --save_steps 100 \
156
+ --save_total_limit 20 \
157
+ --logging_steps 1 \
158
+ --output_dir output/GRPO_COUNTDOWN \
159
+ --warmup_ratio 0.01 \
160
+ --dataloader_num_workers 4 \
161
+ --num_generations 8 \
162
+ --temperature 1.0 \
163
+ --system 'You are a helpful assistant. You first thinks about the reasoning process in the mind and then provides the user with the answer.' \
164
+ --deepspeed zero3 \
165
+ --log_completions true \
166
+ --vllm_max_model_len 1024 \
167
+ --report_to wandb \
168
+ --beta 0.001 \
169
+ --num_iterations 1
170
+ ```
171
+
172
+ ### Experimental Observations
173
+
174
+ After training for 2000 steps, the following observations were made:
175
+
176
+ 1. **Custom CountdownORM Rewards**: The custom `CountdownORM` reward is steadily increasing, which proves that the model is learning to accomplish the task. The final task success rate is around 50%.
177
+ 2. **Format Reward**: The format reward remains at a relatively high level, fluctuating between 0.9 and 1.
178
+ 3. **Reward Standard Deviation**: The reward standard deviation stabilizes around 0.2-0.3 but has not fully converged, indicating that the model still has room to improve its reward.
179
+ 4. **Failure Cases**: By examining the model's output, many failure cases are due to the model making simple arithmetic errors. Therefore, the model's final convergence direction involves solving the problem step by step. Using a larger model may lead to different convergence directions.
180
+ 5. **Completion Length**: The completion length initially decreases and then increases, reaching its lowest point around 200 steps and later rising to approximately 350. This suggests the model underwent a change in reasoning approach.
181
+ 6. **Reasoning Patterns**: The model's reasoning pattern evolves over time. Eventually, the model realizes that performing permutations and step-by-step calculations is more effective for completing this task. The final sampled outputs mostly follow this format. Below are examples of how completions change across different steps:
182
+
183
+ #### Completion Examples at Different Steps
184
+
185
+ **Step 1:**
186
+
187
+ ```plaintext
188
+ <think>
189
+ We need to create an equation using the given numbers [70, 5, 42, 30] exactly once and make it equal to 77.
190
+
191
+ First, let's consider the possibility of multiplication or division to get closer to 77. Notice that 77 is close to 70 and 42. If we can use these numbers together, it might work.
192
+
193
+ Multiplying 70 by 1.1 would give us approximately 77, which is very close. So, let's try to make 1.1 using the remaining numbers 5 and 30.
194
+ If we take 30/5 = 6, and then 5/6 = 0.8333..., this isn't useful here, so let's look at other possibilities.
195
+
196
+ Next, let's consider if there's another way to achieve 77 using addition, subtraction, or another combination of our numbers. Given the numbers provided, it seems that multiplication or division will be key.
197
+
198
+ We can try subtracting 5 from 30 to get 25. Then, if we divide 42 by 25, we don't get a whole number, but we can round it to the nearest whole number, 1. Now, we need to make the equation fit 77. Let's multiply 25 by 3 and add 7 (since 77 = 25*3 + 7). However, we only have one 7 available and we need to find a way to use the remaining numbers to get 7.
199
+
200
+ Let's try:
201
+ 70 - 42 = 28
202
+ Then, 28 + 5 = 33
203
+ Next, 33 + 30 = 63
204
+ Finally, 77 - 63 = 14, which doesn't help.
205
+
206
+ Considering different combinations, one viable way is:
207
+ (70 - 42) * (30 / 5) = 28 * 6 = 168 / 2 = 84 / 2 = 42 / 2 = 21 / 3 = 7
208
+
209
+ So, (70 - 42) * (30 / 5) = 77.
210
+ </think>
211
+ <answer>(70 - 42) * (30 / 5) = 77</answer>
212
+ ```
213
+
214
+ **Step 200:**
215
+
216
+ ```plaintext
217
+ <think>
218
+ We need to use all the given numbers in a way that the resultant value of the calculation is 99. Given these restrictions, it's clear we should look into how the numbers relate and the mathematical operations that will bring them together to meet our condition.
219
+
220
+ Firstly, let's evaluate the sums, differences, and multiplication/division among the numbers and their relations to see how this could lead us towards an outcome of 99.
221
+ - Summing the three numbers: 96 + 70 + 73 = 239, which is far from 99. This shows addition isn't practical.
222
+ - Subtracting numbers: For instance, subtracting the lowest two (i.e., 73 - 70 = 3) and combining with the highest one (96) does not work. Also, there is no other combination of subtraction that would result in the number needing to add up to 99.
223
+ - Multiplying or dividing the numbers alone wouldn’t reach any near solution since none of the products or division results of the numbers themselves is very close to 99. We might think more carefully about the arrangement of them using a combination of the operations provided.
224
+ Therefore, considering the possible arrangement, a combination like taking (73 - 70 + 96) may produce an effective solution as this will sum the values in such a manner that it aligns with the goal of 99.
225
+
226
+ So we conclude that the operation: 73 - 70 + 96 gives the right sequence to equal 99.
227
+ </think>
228
+ <answer>73 - 70 + 96 = 99</answer>
229
+ ```
230
+
231
+ **Step 500:**
232
+
233
+ ```plaintext
234
+ <think>
235
+ Let's begin by exploring various possible combinations of the given numbers using the arithmetic operators we have access to.
236
+
237
+ - If I add the numbers, I get: 56 + 73 + 51 = 180 which is not equal to our target number (68)
238
+ - If I subtract one number from another I will still exceed our target value as well since the maximum difference is: |(difference between max-min):| | (73 - 51) or | (73 - 56), etc.|
239
+ - Let's multiply the numbers individually and see if the division operation can bring us closer to the goal:
240
+ - (73 * 51) - 56 = 3723 - 56 = 3667 which isn't the goal either.
241
+ - The only operator left is addition and subtraction; I'll try the combination:
242
+ ((73 - 56) + 51) gives me (17 + 51) = 68.
243
+
244
+ Thus, our solution fits the provided problem constraints and meets the required outcome.
245
+ </think>
246
+ <answer>(73 - 56) + 51 = 68</answer>
247
+ ```
248
+
249
+ **Step 1000:**
250
+
251
+ ```plaintext
252
+ <think>
253
+ We need to form an expression using the given numbers (50, 86, and 49) such that it equals 85. Let's try different combinations:
254
+
255
+ (86 - 50) + 49 = 76 + 49 = 125 (too big)
256
+ (86 - 49) + 50 = 37 + 50 = 87 (too big)
257
+ (86 - 50) + 49 = 37 + 49 = 86 (too big)
258
+ (86 + 50) - 49 = 136 - 49 = 87 (too big)
259
+ (86 - 50) + (49 - x)? Not working!
260
+ (50 + 86) - 49: this is 136 which isn't our aim.
261
+ 50 + (86 - 49) = 50 + 37 = 87 which wasn't correct.
262
+ 50 - 86 + 49 = -16 + 49: This doesn't match up as well.
263
+ 86 - (50 + 49) = 86 - 99 which doesn't work too.
264
+
265
+ We try one more:
266
+ (86 + 49) - 50 = 135 - 50 = 85!
267
+
268
+ That's it!
269
+ </think>
270
+ <answer>(86 + 49) - 50 = 85</answer>
271
+ ```
272
+
273
+ **Step 2000:**
274
+
275
+ ```plaintext
276
+ <think>
277
+ We need to form an expression using the numbers 58, 9, 78, and 44 which evaluates to 73. Let's try different combinations:
278
+ (78 - 58) + (9 + 44) = 10 + 53 = 63 (too low)
279
+ (78 - 58) + (9 - 44) = 20 - 35 = -15 (too low)
280
+ (78 - 58) + (44 - 9) = 20 + 35 = 55 (too low)
281
+ (78 + 58) - (9 + 44) = 136 - 53 = 83 (too high)
282
+ (78 + 58) - (9 - 44) = 136 + 35 = 171 (too high)
283
+ (78 + 58) - (44 + 9) = 136 + 53 = 189 (too high)
284
+ (78 + 9) - (58 + 44) = 87 - 102 = -15 (too low)
285
+ (78 + 9) - (58 - 44) = 87 - 14 = 73
286
+
287
+ So our solution is: (78 + 9) - (58 - 44) = 73
288
+ </think>
289
+ <answer>(78 + 9) - (58 - 44) = 73</answer>
290
+ ```
291
+
292
+ ---
293
+
294
+ ### Unstable Experiment Records
295
+
296
+ For learning rate set to `1e-6` and $\beta$ set to `0.04`, the model showed oscillations around step 200. Both the format reward and CountdownORM reward dropped significantly:
297
+
298
+ [Unstable Experiment Graph](../../resources/grpo_countdown_1.png)
ms-swift/docs/source_en/BestPractices/Rapidly-Training-VL-model.md ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Best Practices for Rapidly Training Vision-Language (VL) Models
2
+
3
+ This document provides best practices for quickly training vision-language (VL) models from scratch.
4
+
5
+ Model Links
6
+ - [Qwen2.5-VL-7B-Instruct](https://www.modelscope.cn/models/Qwen/Qwen2.5-VL-7B-Instruct)
7
+ - [Qwen3-8B](https://www.modelscope.cn/models/Qwen/Qwen3-8B)
8
+
9
+ Trained Model Link
10
+ - [Simple-VL-8B](https://www.modelscope.cn/models/swift/Simple-VL-8B/summary)
11
+
12
+
13
+ The training workflow builds upon the Qwen2.5-VL-7B-Instruct model architecture by replacing its internal large language model (LLM) component with the weights from Qwen3-8B , thereby enhancing the model's visual understanding capabilities. The process involves the following steps:
14
+
15
+ 1. Modify the original model’s configuration file config.json to align with Qwen3-8B.
16
+ 2. Initialize and load new model weights, saving them as a new model.
17
+ 3. Fine-tune the new model in two stages:
18
+ 1. Stage 1 : Train only the vision-to-language alignment module (aligner), freezing the ViT and LLM components.
19
+ 2. Stage 2 : Unfreeze all modules and perform joint fine-tuning to improve overall performance.
20
+
21
+
22
+ ## Model Modification
23
+
24
+ ### Config File (config.json) Update
25
+ Due to structural differences between Qwen2.5-7B-Instruct and Qwen3-8B (e.g., number of layers, hidden dimensions), create a new config.json based on the Qwen2.5-VL-7B-Instruct config and update the following parameters to match Qwen3-8B:
26
+
27
+
28
+ ```
29
+ Modified Parameters
30
+ 1. hidden_size 3584->4096
31
+ 2. intermediate_size: 18944->12288
32
+ 3. num_attention_heads: 28->32
33
+ 4. num_key_value_heads: 4->8
34
+ 5. num_hidden_layers: 28->32
35
+ 6. vocab_size:152064->151936
36
+ 7. max_window_layers:28->36
37
+
38
+ Newly Added Parameter
39
+ 1. head_dim: 128
40
+ ```
41
+
42
+ ### Model Weight Initialization and Replacement
43
+ Use the following Python script to initialize, replace, and save the model weights:
44
+ ```python
45
+ import torch
46
+ from modelscope import Qwen2_5_VLForConditionalGeneration, AutoModelForCausalLM, AutoConfig
47
+ from transformers.models.qwen2_5_vl.modeling_qwen2_5_vl import Qwen2_5_VLPatchMerger, Qwen2_5_VLModel
48
+ from accelerate import Accelerator
49
+
50
+ # Load original VL model and Qwen3-8B model
51
+ qwen2_5_vl_7b_model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
52
+ "Qwen/Qwen2.5-VL-7B-Instruct",
53
+ device_map="cuda",
54
+ torch_dtype=torch.bfloat16
55
+ )
56
+ device = qwen2_5_vl_7b_model.device
57
+
58
+ qwen3_8b_model = AutoModelForCausalLM.from_pretrained(
59
+ "Qwen/Qwen3-8B",
60
+ device_map=device,
61
+ torch_dtype=torch.bfloat16
62
+ )
63
+
64
+ # Load configurations
65
+ old_config = AutoConfig.from_pretrained("Qwen/Qwen2.5-VL-7B-Instruct")
66
+ new_config = AutoConfig.from_pretrained("/path/to/new_config_dir") # Path to new config directory
67
+
68
+ # Replace merger (aligner) layer
69
+ new_merger = Qwen2_5_VLPatchMerger(
70
+ dim=new_visual_config.out_hidden_size,
71
+ context_dim=new_visual_config.hidden_size,
72
+ spatial_merge_size=new_visual_config.spatial_merge_size,
73
+ ).to(device).to(torch.bfloat16)
74
+ qwen2_5_vl_7b_model.visual.merger = new_merger
75
+
76
+ # Replace LLM part of the VL model
77
+ new_llm_model = Qwen2_5_VLModel(new_config).to(device).to(torch.bfloat16)
78
+
79
+ for name, param in qwen3_8b_model.model.named_parameters():
80
+ if name in new_llm_model.state_dict():
81
+ new_llm_model.state_dict()[name].copy_(param)
82
+
83
+ qwen2_5_vl_7b_model.model = new_llm_model
84
+ qwen2_5_vl_7b_model.lm_head = qwen3_8b_model.lm_head
85
+
86
+ # Save modified model
87
+ accelerator = Accelerator()
88
+ accelerator.save_model(
89
+ model=qwen2_5_vl_7b_model,
90
+ save_directory="/path/to/save/Qwen3-VL-Model",
91
+ max_shard_size="4GB",
92
+ safe_serialization=True
93
+ )
94
+ ```
95
+
96
+
97
+ ## Training
98
+ To simplify the process, we skip pre-training and proceed directly to supervised fine-tuning (SFT). The training is divided into two stages:
99
+
100
+ ### Stage 1: Train Aligner Layer
101
+ Train only the vision-to-language alignment module while freezing the ViT and LLM parts:
102
+ ```bash
103
+ NNODES=$WORLD_SIZE \
104
+ NODE_RANK=$RANK \
105
+ NPROC_PER_NODE=8 \
106
+ MAX_PIXELS=1003520 \
107
+ CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
108
+ swift sft \
109
+ --model /path/to/new_vl_model \
110
+ --model_type qwen2_5_vl \
111
+ --train_type full \
112
+ --dataset xxx \
113
+ --torch_dtype bfloat16 \
114
+ --attn_impl flash_attn \
115
+ --freeze_vit true \
116
+ --freeze_llm true \
117
+ --freeze_aligner false \
118
+ --num_train_epochs 3 \
119
+ --per_device_train_batch_size 2 \
120
+ --learning_rate 5e-6 \
121
+ --gradient_accumulation_steps 8 \
122
+ --eval_steps -1 \
123
+ --save_steps 1000 \
124
+ --save_total_limit 10 \
125
+ --logging_steps 5 \
126
+ --max_length 8192 \
127
+ --output_dir output \
128
+ --warmup_ratio 0.05 \
129
+ --dataloader_num_workers 4 \
130
+ --dataset_num_proc 8 \
131
+ --deepspeed zero2
132
+ ```
133
+
134
+ ### Stage 2: Full Model Training
135
+
136
+ Unfreeze all modules and jointly train to enhance the model's visual understanding:
137
+
138
+ ```bash
139
+ NNODES=$WORLD_SIZE \
140
+ NODE_RANK=$RANK \
141
+ NPROC_PER_NODE=8 \
142
+ MAX_PIXELS=1003520 \
143
+ CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
144
+ swift sft \
145
+ --model /path/to/stage1_checkpoint \
146
+ --model_type qwen2_5_vl \
147
+ --train_type full \
148
+ --dataset xxx \
149
+ --torch_dtype bfloat16 \
150
+ --attn_impl flash_attn \
151
+ --freeze_vit false \
152
+ --freeze_llm false \
153
+ --freeze_aligner false \
154
+ --num_train_epochs 3 \
155
+ --per_device_train_batch_size 2 \
156
+ --learning_rate 5e-6 \
157
+ --gradient_accumulation_steps 8 \
158
+ --eval_steps -1 \
159
+ --save_steps 1000 \
160
+ --save_total_limit 10 \
161
+ --logging_steps 5 \
162
+ --max_length 8192 \
163
+ --output_dir output \
164
+ --warmup_ratio 0.05 \
165
+ --dataloader_num_workers 4 \
166
+ --dataset_num_proc 8 \
167
+ --deepspeed zero2
168
+ ```
169
+
170
+ ## Inference / Deployment / Evaluation
171
+
172
+ ### Inference
173
+ Perform inference using `swift infer`:
174
+ ```bash
175
+ swift infer \
176
+ --model /path/to/stage2_checkpoint
177
+ ```
178
+
179
+ ### Deoloyment
180
+ Accelerate model serving with vLLM:
181
+ ```bash
182
+ CUDA_VISIBLE_DEVICES=0 \
183
+ MAX_PIXELS=1003520 \
184
+ VIDEO_MAX_PIXELS=50176 \
185
+ FPS_MAX_FRAMES=12 \
186
+ swift deploy \
187
+ --model /path/to/stage2_checkpoint \
188
+ --infer_backend vllm \
189
+ --gpu_memory_utilization 0.9 \
190
+ --max_model_len 8192 \
191
+ --max_new_tokens 2048 \
192
+ --limit_mm_per_prompt '{"image": 5, "video": 2}' \
193
+ --served_model_name Qwen3-VL
194
+ ```
195
+
196
+ ### Evaluation
197
+ Evaluate the trained VL model using [EvalScope](https://github.com/modelscope/evalscope/).
198
+
199
+ Example Evaluation Using MMMU Benchmark
200
+ ```python
201
+ from evalscope import TaskConfig, run_task
202
+
203
+ task_cfg_dict = TaskConfig(
204
+ work_dir='outputs',
205
+ eval_backend='VLMEvalKit',
206
+ eval_config={
207
+ 'data': ['MMMU_DEV_VAL'],
208
+ 'mode': 'all',
209
+ 'model': [
210
+ {
211
+ 'api_base': 'http://localhost:8000/v1/chat/completions',
212
+ 'key': 'EMPTY',
213
+ 'name': 'CustomAPIModel',
214
+ 'temperature': 0.6,
215
+ 'type': 'Qwen3-VL',
216
+ 'img_size': -1,
217
+ 'video_llm': False,
218
+ 'max_tokens': 512,
219
+ }
220
+ ],
221
+ 'reuse': False,
222
+ 'nproc': 64,
223
+ 'judge': 'exact_matching'
224
+ },
225
+ )
226
+
227
+ run_task(task_cfg=task_cfg_dict)
228
+ ```
ms-swift/docs/source_en/Customization/Custom-dataset.md ADDED
@@ -0,0 +1,255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Custom Dataset
2
+
3
+ There are three methods for accessing custom datasets, each offering progressively greater control over preprocessing functions but also increasing in complexity. For example, Solution 1 is the most convenient but offers the least control over preprocessing functions, requiring prior conversion of the dataset into a specific format:
4
+
5
+ 1. **Recommended**: Directly use the command line parameter to access the dataset with `--dataset <dataset_path1> <dataset_path2>`. This will use `AutoPreprocessor` to convert your dataset into a standard format (supporting four dataset formats; see the introduction to AutoPreprocessor below). You can use `--columns` to transform column names. The supported input formats include csv, json, jsonl, txt, and folders (e.g. git clone open-source datasets). This solution does not require modifying `dataset_info.json` and is suitable for users new to ms-swift. The following two solutions are suitable for developers looking to extend ms-swift.
6
+ 2. Add the dataset to `dataset_info.json`, which you can refer to in the built-in [dataset_info.json](https://github.com/modelscope/ms-swift/blob/main/swift/llm/dataset/data/dataset_info.json) of ms-swift. This solution also uses AutoPreprocessor to convert the dataset to a standard format. `dataset_info.json` is a list of metadata for datasets, and one of the fields ms_dataset_id/hf_dataset_id/dataset_path must be filled. Column name transformation can be done through the `columns` field. Datasets added to `dataset_info.json` or registered ones will automatically generate [supported dataset documentation](https://swift.readthedocs.io/en/latest/Instruction/Supported-models-and-datasets.html) when running [run_dataset_info.py](https://github.com/modelscope/ms-swift/blob/main/scripts/utils/run_dataset_info.py). In addition, you can use the external `dataset_info.json` approach by parsing the JSON file with `--custom_dataset_info xxx.json` (to facilitate users who prefer `pip install` over `git clone`), and then specify `--dataset <dataset_id/dataset_dir/dataset_path>`.
7
+ 3. Manually register the dataset to have the most flexible customization capability for preprocessing functions, allowing the use of functions to preprocess datasets, but it is more difficult. You can refer to the [built-in datasets](https://github.com/modelscope/ms-swift/blob/main/swift/llm/dataset/dataset/llm.py) or [examples](https://github.com/modelscope/swift/blob/main/examples/custom). You can specify `--custom_register_path xxx.py` to parse external registration content (convenient for users who use pip install instead of git clone).
8
+ - Solutions one and two leverage solution three under the hood, where the registration process occurs automatically.
9
+
10
+ The following is an introduction to the dataset formats that `AutoPreprocessor` can handle:
11
+
12
+ The standard dataset format for ms-swift accepts keys such as: 'messages', 'rejected_response', 'label', 'images', 'videos', 'audios', 'tools', and 'objects'. Among these, 'messages' is a required key. 'rejected_response' is used for DPO and other RLHF training, 'label' is used for KTO training and classification model training. The keys 'images', 'videos', and 'audios' are used to store paths or URLs for multimodal data, 'tools' is used for Agent tasks, and 'objects' is used for grounding tasks.
13
+
14
+ There are three core preprocessors in ms-swift: `MessagesPreprocessor`, `AlpacaPreprocessor`, and `ResponsePreprocessor`. `MessagesPreprocessor` is used to convert datasets in the messages and sharegpt format into the standard format. `AlpacaPreprocessor` converts datasets in the alpaca format, while `ResponsePreprocessor` converts datasets in the query/response format. `AutoPreprocessor` automatically selects the appropriate preprocessor for the task.
15
+
16
+ The following four formats will all be converted into the `messages` field of the ms-swift standard format under the processing of `AutoPreprocessor`, meaning they can all be directly used with `--dataset <dataset-path>`:
17
+
18
+ Messages format (standard format):
19
+ ```jsonl
20
+ {"messages": [{"role": "system", "content": "<system>"}, {"role": "user", "content": "<query1>"}, {"role": "assistant", "content": "<response1>"}, {"role": "user", "content": "<query2>"}, {"role": "assistant", "content": "<response2>"}]}
21
+ ```
22
+ - Note: The system part is optional. The system in the dataset has a higher priority than the `--system` passed through the command line, followed by the `default_system` defined in the template.
23
+
24
+ ShareGPT format:
25
+ ```jsonl
26
+ {"system": "<system>", "conversation": [{"human": "<query1>", "assistant": "<response1>"}, {"human": "<query2>", "assistant": "<response2>"}]}
27
+ ```
28
+
29
+ Alpaca format:
30
+ ```jsonl
31
+ {"system": "<system>", "instruction": "<query-inst>", "input": "<query-input>", "output": "<response>"}
32
+ ```
33
+
34
+ Query-Response format:
35
+ ```jsonl
36
+ {"system": "<system>", "query": "<query2>", "response": "<response2>", "history": [["<query1>", "<response1>"]]}
37
+ ```
38
+
39
+ ## Standard Dataset Format
40
+
41
+ The following outlines the standard dataset format for ms-swift, where the "system" field is optional and uses the "default_system" defined in the template by default. The four dataset formats introduced earlier can also be processed by AutoPreprocessor into the standard dataset format.
42
+
43
+ ### Pre-training
44
+
45
+ ```jsonl
46
+ {"messages": [{"role": "assistant", "content": "I love music"}]}
47
+ {"messages": [{"role": "assistant", "content": "Coach, I want to play basketball"}]}
48
+ {"messages": [{"role": "assistant", "content": "Which is more authoritative, tomato and egg rice or the third fresh stir-fry?"}]}
49
+ ```
50
+
51
+ ### Supervised Fine-tuning
52
+
53
+ ```jsonl
54
+ {"messages": [{"role": "system", "content": "You are a useful and harmless assistant"}, {"role": "user", "content": "Tell me tomorrow's weather"}, {"role": "assistant", "content": "Tomorrow's weather will be sunny"}]}
55
+ {"messages": [{"role": "system", "content": "You are a useful and harmless math calculator"}, {"role": "user", "content": "What is 1 + 1?"}, {"role": "assistant", "content": "It equals 2"}, {"role": "user", "content": "What about adding 1?"}, {"role": "assistant", "content": "It equals 3"}]}
56
+ ```
57
+
58
+ ### RLHF
59
+
60
+ #### DPO/ORPO/CPO/SimPO/RM
61
+
62
+ ```jsonl
63
+ {"messages": [{"role": "system", "content": "You are a useful and harmless assistant"}, {"role": "user", "content": "Tell me tomorrow's weather"}, {"role": "assistant", "content": "Tomorrow's weather will be sunny"}], "rejected_response": "I don't know"}
64
+ {"messages": [{"role": "system", "content": "You are a useful and harmless math calculator"}, {"role": "user", "content": "What is 1 + 1?"}, {"role": "assistant", "content": "It equals 2"}, {"role": "user", "content": "What about adding 1?"}, {"role": "assistant", "content": "It equals 3"}], "rejected_response": "I don't know"}
65
+ ```
66
+
67
+ #### KTO
68
+
69
+ ```jsonl
70
+ {"messages": [{"role": "system", "content": "You are a useful and harmless assistant"}, {"role": "user", "content": "Tell me tomorrow's weather"}, {"role": "assistant", "content": "I don't know"}], "label": false}
71
+ {"messages": [{"role": "system", "content": "You are a useful and harmless math calculator"}, {"role": "user", "content": "What is 1 + 1?"}, {"role": "assistant", "content": "It equals 2"}, {"role": "user", "content": "What about adding 1?"}, {"role": "assistant", "content": "It equals 3"}], "label": true}
72
+ ```
73
+
74
+ #### PPO/GRPO
75
+
76
+ ```jsonl
77
+ {"messages": [{"role": "system", "content": "You are a useful and harmless assistant"}, {"role": "user", "content": "Tell me tomorrow's weather"}]}
78
+ {"messages": [{"role": "system", "content": "You are a useful and harmless math calculator"}, {"role": "user", "content": "What is 1 + 1?"}, {"role": "assistant", "content": "It equals 2"}, {"role": "user", "content": "What about adding 1?"}]}
79
+ {"messages": [{"role": "user", "content": "What is your name?"}]}
80
+ ```
81
+ - Note: GRPO will pass through all additional field content to the ORM, unlike other training methods that, by default, delete extra fields. For example, you can additionally pass in 'solution'. The custom ORM needs to include a positional argument called `completions`, with other arguments as keyword arguments passed through from the additional dataset fields.
82
+
83
+ ### Sequence Classification
84
+
85
+ **Single-label Task**:
86
+ ```jsonl
87
+ {"messages": [{"role": "user", "content": "The weather is really nice today"}], "label": 1}
88
+ {"messages": [{"role": "user", "content": "Today is really unlucky"}], "label": 0}
89
+ {"messages": [{"role": "user", "content": "So happy"}], "label": 1}
90
+ ```
91
+
92
+ **Multi-label Task**:
93
+
94
+ ```jsonl
95
+ {"messages": [{"role": "user", "content": "<sentence>"}], "label": [1, 3, 5]}
96
+ ```
97
+
98
+ **Single Regression Task**:
99
+
100
+ ```jsonl
101
+ {"messages": [{"role": "user", "content": "Calculate the similarity between two sentences, with a range of 0-1.\nsentence1: <sentence1>\nsentence2: <sentence2>"}], "label": 0.8}
102
+ ```
103
+
104
+ **Multi Regression Task**:
105
+
106
+ ```jsonl
107
+ {"messages": [{"role": "user", "content": "<sentence>"}], "label": [1.2, -0.6, 0.8]}
108
+ ```
109
+
110
+ ### Embedding
111
+
112
+ Please refer to [embedding训练文档](../BestPractices/Embedding.md#dataset-format).
113
+
114
+ ### Multimodal
115
+
116
+ For multimodal datasets, the format is the same as the aforementioned tasks. The difference lies in the addition of several keys: `images`, `videos`, and `audios`, which represent the URLs or paths (preferably absolute paths) of multimodal resources. The tags `<image>`, `<video>`, and `<audio>` indicate where to insert images, videos, or audio. MS-Swift supports multiple images, videos, and audio files. These special tokens will be replaced during preprocessing, as referenced [here](https://github.com/modelscope/ms-swift/blob/main/swift/llm/template/template/qwen.py#L198). The four examples below respectively demonstrate the data format for plain text, as well as formats containing image, video, and audio data.
117
+
118
+
119
+ Pre-training:
120
+ ```jsonl
121
+ {"messages": [{"role": "assistant", "content": "Pre-trained text goes here"}]}
122
+ {"messages": [{"role": "assistant", "content": "<image>is a puppy, <image>is a kitten"}], "images": ["/xxx/x.jpg", "/xxx/x.png"]}
123
+ {"messages": [{"role": "assistant", "content": "<audio>describes how nice the weather is today"}], "audios": ["/xxx/x.wav"]}
124
+ {"messages": [{"role": "assistant", "content": "<image>is an elephant, <video>is a lion running"}], "images": ["/xxx/x.jpg"], "videos": ["/xxx/x.mp4"]}
125
+ ```
126
+
127
+ Supervised Fine-tuning:
128
+
129
+ ```jsonl
130
+ {"messages": [{"role": "user", "content": "Where is the capital of Zhejiang?"}, {"role": "assistant", "content": "The capital of Zhejiang is Hangzhou."}]}
131
+ {"messages": [{"role": "user", "content": "<image><image>What is the difference between the two images?"}, {"role": "assistant", "content": "The first one is a kitten, and the second one is a puppy."}], "images": ["/xxx/x.jpg", "/xxx/x.png"]}
132
+ {"messages": [{"role": "user", "content": "<audio>What did the audio say?"}, {"role": "assistant", "content": "The weather is really nice today."}], "audios": ["/xxx/x.mp3"]}
133
+ {"messages": [{"role": "system", "content": "You are a helpful and harmless assistant."}, {"role": "user", "content": "<image>What is in the image, <video>What is in the video?"}, {"role": "assistant", "content": "The image shows an elephant, and the video shows a puppy running on the grass."}], "images": ["/xxx/x.jpg"], "videos": ["/xxx/x.mp4"]}
134
+ ```
135
+
136
+ The data format for RLHF and sequence classification of multimodal models can reference the format of pure text large models, with additional fields such as `images` added on top of that.
137
+
138
+ #### Grounding
139
+
140
+ For grounding (object detection) tasks, SWIFT supports two methods:
141
+
142
+ 1. Directly use the data format of the grounding task corresponding to the model. For example, the format for qwen2-vl is as follows:
143
+
144
+ ```
145
+ {"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "<image>Describe the image."}, {"role": "assistant", "content": "<|object_ref_start|>a dog<|object_ref_end|><|box_start|>(221,423),(569,886)<|box_end|> and <|object_ref_start|>a woman<|object_ref_end|><|box_start|>(451,381),(733,793)<|box_end|> are playing on the beach"}], "images": ["/xxx/x.jpg"]}
146
+ {"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "<image>Find the <|object_ref_start|>sheep<|object_ref_end|> in the image"}, {"role": "assistant", "content": "<|box_start|>(101,201),(150,266)<|box_end|><|box_start|>(401,601),(550,666)<|box_end|>"}], "images": ["/xxx/x.jpg"]}
147
+ {"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "<image>Help me open Google Chrome"}, {"role": "assistant", "content": "Action: click(start_box='<|box_start|>(246,113)<|box_end|>')"}], "images": ["/xxx/x.jpg"]}
148
+ ```
149
+
150
+ When using this type of data, please note:
151
+
152
+ - Different models have different special characters and data format for the grounding task.
153
+ - The handling of bounding box normalization varies across different models: for example, qwen2.5-vl uses absolute coordinates, while qwen2-vl and internvl2.5 require bounding box coordinates to be normalized to the thousandth scale.
154
+
155
+ 1. Use SWIFT's grounding data format:
156
+
157
+ ```
158
+ {"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "<image>Describe the image."}, {"role": "assistant", "content": "<ref-object><bbox> and <ref-object><bbox> are playing on the beach"}], "images": ["/xxx/x.jpg"], "objects": {"ref": ["a dog", "a woman"], "bbox": [[331.5, 761.4, 853.5, 1594.8], [676.5, 685.8, 1099.5, 1427.4]]}}
159
+ {"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "<image>Find the <ref-object> in the image"}, {"role": "assistant", "content": "<bbox><bbox>"}], "images": ["/xxx/x.jpg"], "objects": {"ref": ["sheep"], "bbox": [[90.9, 160.8, 135, 212.8], [360.9, 480.8, 495, 532.8]]}}
160
+ {"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "<image>Help me open Google Chrome"}, {"role": "assistant", "content": "Action: click(start_box='<bbox>')"}], "images": ["/xxx/x.jpg"], "objects": {"ref": [], "bbox": [[615, 226]]}}
161
+ ```
162
+
163
+ The format will automatically convert the dataset format to the corresponding model's grounding task format and select the appropriate model's bbox normalization method. Compared to the general format, this format includes an additional "objects" field, which contains the following subfields:
164
+
165
+ - ref: Used to replace `<ref-object>`.
166
+ - bbox: Used to replace `<bbox>`. If the length of each box in the bbox is 2, it represents the x and y coordinates. If the box length is 4, it represents the x and y coordinates of two points.
167
+ - bbox_type: Optional values are 'real' and 'norm1'. The default is 'real', meaning the bbox represents the actual bounding box value. If set to 'norm1', the bbox is normalized to the range 0~1.
168
+ - image_id: This parameter is only effective when bbox_type is 'real'. It indicates the index of the image corresponding to the bbox, used for scaling the bbox. The index starts from 0, and the default is 0 for all.
169
+
170
+ ### Text-to-Image Format
171
+
172
+ ```jsonl
173
+ {"messages": [{"role": "system", "content": "You are a useful and harmless assistant"}, {"role": "user", "content": "Draw me an apple"}, {"role": "assistant", "content": "<image>"}], "images": ["/xxx/x.jpg"]}
174
+ ```
175
+
176
+ ### Agent Format
177
+ Here are example data samples for a text-only Agent and a multimodal Agent:
178
+ ```jsonl
179
+ {"tools": ["{\"type\": \"function\", \"function\": {\"name\": \"realtime_aqi\", \"description\": \"Weather forecast. Get real-time air quality, including current air quality, PM2.5, and PM10 information.\", \"parameters\": {\"type\": \"object\", \"properties\": {\"city\": {\"type\": \"string\", \"description\": \"City name, e.g., Shanghai\"}}, \"required\": [\"city\"]}}}"], "messages": [{"role": "user", "content": "What is the weather like in Beijing and Shanghai today?"}, {"role": "tool_call", "content": "{\"name\": \"realtime_aqi\", \"arguments\": {\"city\": \"Beijing\"}}"}, {"role": "tool_call", "content": "{\"name\": \"realtime_aqi\", \"arguments\": {\"city\": \"Shanghai\"}}"}, {"role": "tool_response", "content": "{\"city\": \"Beijing\", \"aqi\": \"10\", \"unit\": \"celsius\"}"}, {"role": "tool_response", "content": "{\"city\": \"Shanghai\", \"aqi\": \"72\", \"unit\": \"fahrenheit\"}"}, {"role": "assistant", "content": "According to the weather forecast tool, the air quality index (AQI) in Beijing is 10, which indicates good air quality; whereas in Shanghai, the AQI is 72, indicating mild pollution."}]}
180
+ {"tools": ["{\"type\": \"function\", \"function\": {\"name\": \"click\", \"description\": \"Click on a position on the screen\", \"parameters\": {\"type\": \"object\", \"properties\": {\"x\": {\"type\": \"integer\", \"description\": \"X-coordinate representing the horizontal position on the screen\"}, \"y\": {\"type\": \"integer\", \"description\": \"Y-coordinate representing the vertical position on the screen\"}}, \"required\": [\"x\", \"y\"]}}}"], "messages": [{"role": "user", "content": "<image>What time is it now?"}, {"role": "assistant", "content": "<think>\nI can check the current time by opening the calendar app.\n</think>\n"}, {"role": "tool_call", "content": "{\"name\": \"click\", \"arguments\": {\"x\": 105, \"y\": 132}}"}, {"role": "tool_response", "content": "{\"images\": \"<image>\", \"status\": \"success\"}"}, {"role": "assistant", "content": "Successfully opened the calendar app. The current time is 11 o'clock in the morning."}], "images": ["desktop.png", "calendar.png"]}
181
+ ```
182
+ - When the `agent_template` is set to "react_en", "hermes", etc., this format is compatible with training for all model Agents and allows easy switching between different models.
183
+ - Here, `tools` is a `List[str]`, where each tool needs to be a JSON string. Additionally, the `content` part of the messages where the role is `'tool_call'` or `'tool_response/tool'` must also be in JSON string format.
184
+ - The `tools` field will be combined with the `{"role": "system", ...}` section during training/inference according to the `agent_template`, forming a complete system section.
185
+ - The `{"role": "tool_call", ...}` part will automatically be converted into corresponding formats of `{"role": "assistant", ...}` based on the `agent_template`. Multiple consecutive `{"role": "assistant", ...}` entries will be concatenated to form a complete assistant_content.
186
+ - The `{"role": "tool_response", ...}` can also be written as `{"role": "tool", ...}`, these two forms are equivalent. This part will also be automatically converted according to the `agent_template`. During training, this part does not participate in loss calculations, similar to `{"role": "user", ...}`.
187
+ - This format supports parallel tool calls; refer to the first data sample for an example. In multimodal Agent data samples, the number of `<image>` tags should match the length of "images", and their positions indicate where the image features are inserted. It also supports other modalities, such as audios and videos.
188
+ - For more details, please refer to [Agent Documentation](../Instruction/Agent-support.md).
189
+
190
+
191
+ ## dataset_info.json
192
+
193
+ You can refer to the ms-swift built-in [dataset_info.json](https://github.com/modelscope/ms-swift/blob/main/swift/llm/dataset/data/dataset_info.json). This approach uses the AutoPreprocessor function to convert the dataset into a standard format. The dataset_info.json file contains a list of metadata about the dataset. Here are some examples:
194
+
195
+
196
+ ```json
197
+ [
198
+ {
199
+ "ms_dataset_id": "xxx/xxx"
200
+ },
201
+ {
202
+ "dataset_path": "<dataset_dir/dataset_path>"
203
+ },
204
+ {
205
+ "ms_dataset_id": "<dataset_id>",
206
+ "subsets": ["v1"],
207
+ "split": ["train", "validation"],
208
+ "columns": {
209
+ "input": "query",
210
+ "output": "response"
211
+ }
212
+ },
213
+ {
214
+ "ms_dataset_id": "<dataset_id>",
215
+ "hf_dataset_id": "<hf_dataset_id>",
216
+ "subsets": [{
217
+ "subset": "subset1",
218
+ "columns": {
219
+ "problem": "query",
220
+ "content": "response"
221
+ }
222
+ },
223
+ {
224
+ "subset": "subset2",
225
+ "columns": {
226
+ "messages": "_",
227
+ "new_messages": "messages"
228
+ }
229
+ }]
230
+ }
231
+ ]
232
+ ```
233
+
234
+ The following parameters are supported:
235
+
236
+ - ms_dataset_id: Refers to the DatasetMeta parameter.
237
+ - hf_dataset_id: Refers to the DatasetMeta parameter.
238
+ - dataset_path: Refers to the DatasetMeta parameter.
239
+ - dataset_name: Refers to the DatasetMeta parameter.
240
+ - subsets: Refers to the DatasetMeta parameter.
241
+ - split: Refers to the DatasetMeta parameter.
242
+ - columns: Transforms column names before preprocessing the dataset.
243
+
244
+ ## Dataset Registration
245
+
246
+ `register_dataset` will register the dataset in `DATASET_MAPPING`. You can call the function `register_dataset(dataset_meta)` to complete the dataset registration, where `dataset_meta` will store the metadata of the model. The parameter list for DatasetMeta is as follows:
247
+
248
+ - ms_dataset_id: The dataset_id for ModelScope, default is None.
249
+ - hf_dataset_id: The dataset_id for HuggingFace, default is None.
250
+ - dataset_path: The local path to the dataset (an absolute path is recommended), default is None.
251
+ - dataset_name: The alias of the dataset, which can be specified via `--dataset <dataset_name>`. This is very convenient when the dataset_path is long. The default value is None.
252
+ - subsets: A list of subdataset names or a list of `SubsetDataset` objects, default is `['default']`. (The concepts of subdatasets and splits only exist for dataset_id or dataset_dir (open source datasets cloned via git)).
253
+ - split: Defaults to `['train']`.
254
+ - preprocess_func: A preprocessing function or callable object, default is `AutoPreprocessor()`. This preprocessing function takes an `HfDataset` as input and returns an `HfDataset` in the standard format.
255
+ - load_function: Defaults to `DatasetLoader.load`. If a custom loading function is needed, it should return an `HfDataset` in the standard format, allowing users maximum flexibility while bypassing the ms-swift dataset loading mechanism. This parameter usually does not need to be modified.
ms-swift/docs/source_en/GetStarted/Quick-start.md ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Quick Start
2
+
3
+ ms-swift is a comprehensive training and deployment framework for large language models and multimodal large models, provided by the ModelScope Community. It currently supports the training (CPT, SFT, RLHF), inference, evaluation, quantization, and deployment of 500+ LLM and 200+ MLLM. Model developers can fulfill all kinds of needs related to large models in a single platform within the ms-swift framework. The main capabilities of ms-swift include:
4
+
5
+ - 🍎 Model Types: Supports 500+ pure text large models, 200+ multi-modal large models, as well as All-to-All multi-modal models, sequence classification models, and embedding models, covering the entire process from training to deployment.
6
+ - Dataset Types: Comes with more than 150 pre-built datasets for pre-training, fine-tuning, human alignment, multimodal, and supports custom datasets.
7
+ - Hardware Support: Compatible with CPU, RTX series, T4/V100, A10/A100/H100, Ascend NPU, MPS and others.
8
+ - 🍊 Lightweight Training: Supports lightweight fine-tuning methods like LoRA, QLoRA, DoRA, LoRA+, ReFT, RS-LoRA, LLaMAPro, Adapter, GaLore, Q-Galore, LISA, UnSloth, Liger-Kernel, and more.
9
+ - Distributed Training: Supports distributed data parallel (DDP), simple model parallelism via device_map, DeepSpeed ZeRO2 ZeRO3, FSDP, and other distributed training technologies.
10
+ - Quantization Training: Provides training for quantized models like BNB, AWQ, GPTQ, AQLM, HQQ, EETQ.
11
+ - RLHF Training: Supports human alignment training methods like DPO, GRPO, RM, PPO, KTO, CPO, SimPO, ORPO for both text-based and multimodal large models.
12
+ - 🍓 Multimodal Training: Capable of training models for different modalities such as images, videos, and audios; supports tasks like VQA (Visual Question Answering), Captioning, OCR (Optical Character Recognition), and Grounding.
13
+ - Interface-driven Training: Offers training, inference, evaluation, and quantization capabilities through an interface, enabling a complete workflow for large models.
14
+ - Plugins and Extensions: Allows customization and extension of models and datasets, and supports customizations for components like loss, metric, trainer, loss-scale, callback, optimizer, etc.
15
+ - 🍉 Toolbox Capabilities: Offers not only training support for large models and multi-modal large models but also covers the entire process of inference, evaluation, quantization, and deployment.
16
+ - Inference Acceleration: Supports inference acceleration engines like PyTorch, vLLM, LmDeploy, and provides OpenAI interface, accelerating inference, deployment, and evaluation modules.
17
+ - Model Evaluation: Uses EvalScope as the evaluation backend and supports evaluation of text-based and multimodal models with over 100 evaluation datasets.
18
+ - Model Quantization: Supports the export of quantized models in AWQ, GPTQ, and BNB formats, which can be accelerated using vLLM/LmDeploy for inference and support continued training.
19
+
20
+ ## Installation
21
+
22
+ For the installation of ms-swift, please refer to the [installation documentation](./SWIFT-installation.md).
23
+
24
+ ## Usage Example
25
+
26
+ 10 minutes of self-cognition fine-tuning of Qwen2.5-7B-Instruct on a single 3090 GPU:
27
+
28
+ ```shell
29
+ # 22GB
30
+ CUDA_VISIBLE_DEVICES=0 \
31
+ swift sft \
32
+ --model Qwen/Qwen2.5-7B-Instruct \
33
+ --train_type lora \
34
+ --dataset 'AI-ModelScope/alpaca-gpt4-data-zh#500' \
35
+ 'AI-ModelScope/alpaca-gpt4-data-en#500' \
36
+ 'swift/self-cognition#500' \
37
+ --torch_dtype bfloat16 \
38
+ --num_train_epochs 1 \
39
+ --per_device_train_batch_size 1 \
40
+ --per_device_eval_batch_size 1 \
41
+ --learning_rate 1e-4 \
42
+ --lora_rank 8 \
43
+ --lora_alpha 32 \
44
+ --target_modules all-linear \
45
+ --gradient_accumulation_steps 16 \
46
+ --eval_steps 50 \
47
+ --save_steps 50 \
48
+ --save_total_limit 2 \
49
+ --logging_steps 5 \
50
+ --max_length 2048 \
51
+ --output_dir output \
52
+ --system 'You are a helpful assistant.' \
53
+ --warmup_ratio 0.05 \
54
+ --dataloader_num_workers 4 \
55
+ --model_author swift \
56
+ --model_name swift-robot
57
+ ```
58
+
59
+ Tips:
60
+
61
+ - If you want to train with a custom dataset, you can refer to [this guide](../Customization/Custom-dataset.md) to organize your dataset format and specify `--dataset <dataset_path>`.
62
+ - The `--model_author` and `--model_name` parameters are only effective when the dataset includes `swift/self-cognition`.
63
+ - To train with a different model, simply modify `--model <model_id/model_path>`.
64
+ - By default, ModelScope is used for downloading models and datasets. If you want to use HuggingFace, simply specify `--use_hf true`.
65
+
66
+ After training is complete, use the following command to infer with the trained weights:
67
+
68
+ - Here, `--adapters` should be replaced with the last checkpoint folder generated during training. Since the adapters folder contains the training parameter file `args.json`, there is no need to specify `--model`, `--system` separately; Swift will automatically read these parameters. To disable this behavior, you can set `--load_args false`.
69
+
70
+ ```shell
71
+ # Using an interactive command line for inference.
72
+ CUDA_VISIBLE_DEVICES=0 \
73
+ swift infer \
74
+ --adapters output/vx-xxx/checkpoint-xxx \
75
+ --stream true \
76
+ --temperature 0 \
77
+ --max_new_tokens 2048
78
+
79
+ # merge-lora and use vLLM for inference acceleration
80
+ CUDA_VISIBLE_DEVICES=0 \
81
+ swift infer \
82
+ --adapters output/vx-xxx/checkpoint-xxx \
83
+ --stream true \
84
+ --merge_lora true \
85
+ --infer_backend vllm \
86
+ --max_model_len 8192 \
87
+ --temperature 0 \
88
+ --max_new_tokens 2048
89
+ ```
90
+
91
+ Finally, use the following command to push the model to ModelScope:
92
+
93
+ ```shell
94
+ CUDA_VISIBLE_DEVICES=0 \
95
+ swift export \
96
+ --adapters output/vx-xxx/checkpoint-xxx \
97
+ --push_to_hub true \
98
+ --hub_model_id '<your-model-id>' \
99
+ --hub_token '<your-sdk-token>' \
100
+ --use_hf false
101
+ ```
102
+
103
+ ## Learn More
104
+ - More Shell scripts: [https://github.com/modelscope/ms-swift/tree/main/examples](https://github.com/modelscope/ms-swift/tree/main/examples)
105
+ - Using Python: [https://github.com/modelscope/ms-swift/blob/main/examples/notebook/qwen2_5-self-cognition/self-cognition-sft.ipynb](https://github.com/modelscope/ms-swift/blob/main/examples/notebook/qwen2_5-self-cognition/self-cognition-sft.ipynb)
ms-swift/docs/source_en/Instruction/Export-and-push.md ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Export and Push
2
+
3
+ ## Merge LoRA
4
+
5
+ - See [here](https://github.com/modelscope/ms-swift/blob/main/examples/export/merge_lora.sh).
6
+
7
+ ## Quantization
8
+
9
+ SWIFT supports quantization exports for AWQ, GPTQ, and BNB models. AWQ and GPTQ require a calibration dataset, which yields better quantization performance but takes longer to quantize. On the other hand, BNB does not require a calibration dataset and is quicker to quantize.
10
+
11
+ | Quantization Technique | Multimodal | Inference Acceleration | Continued Training |
12
+ | ---------------------- | ---------- | ---------------------- | ------------------ |
13
+ | GPTQ | ✅ | ✅ | ✅ |
14
+ | AWQ | ✅ | ✅ | ✅ |
15
+ | BNB | ❌ | ✅ | ✅ |
16
+
17
+ In addition to the SWIFT installation, the following additional dependencies need to be installed:
18
+
19
+ ```shell
20
+ # For AWQ quantization:
21
+ # The versions of autoawq and CUDA are correlated; please choose the version according to `https://github.com/casper-hansen/AutoAWQ`.
22
+ # If there are dependency conflicts with torch, please add the `--no-deps` option.
23
+ pip install autoawq -U
24
+
25
+ # For GPTQ quantization:
26
+ # The versions of auto_gptq and CUDA are correlated; please choose the version according to `https://github.com/PanQiWei/AutoGPTQ#quick-installation`.
27
+ pip install auto_gptq optimum -U
28
+
29
+ # For BNB quantization:
30
+ pip install bitsandbytes -U
31
+ ```
32
+
33
+ We provide a series of scripts to demonstrate SWIFT's quantization export capabilities:
34
+
35
+ - Supports [AWQ](https://github.com/modelscope/ms-swift/blob/main/examples/export/quantize/awq.sh)/[GPTQ](https://github.com/modelscope/ms-swift/blob/main/examples/export/quantize/gptq.sh)/[BNB](https://github.com/modelscope/ms-swift/blob/main/examples/export/quantize/bnb.sh) quantization exports.
36
+ - Multimodal quantization: Supports quantizing multimodal models using GPTQ and AWQ, with limited multimodal models supported by AWQ. Refer to [here](https://github.com/modelscope/ms-swift/tree/main/examples/export/quantize/mllm).
37
+ - Support for more model series: Supports quantization exports for [BERT](https://github.com/modelscope/ms-swift/tree/main/examples/export/quantize/bert) and [Reward Model](https://github.com/modelscope/ms-swift/tree/main/examples/export/quantize/reward_model).
38
+ - Models exported with SWIFT's quantization support inference acceleration using vllm/lmdeploy; they also support further SFT/RLHF using QLoRA.
39
+
40
+
41
+ ## Push Model
42
+
43
+ SWIFT supports re-pushing trained/quantized models to ModelScope/Hugging Face. By default, it pushes to ModelScope, but you can specify `--use_hf true` to push to Hugging Face.
44
+
45
+ ```shell
46
+ swift export \
47
+ --model output/vx-xxx/checkpoint-xxx \
48
+ --push_to_hub true \
49
+ --hub_model_id '<model-id>' \
50
+ --hub_token '<sdk-token>' \
51
+ --use_hf false
52
+ ```
53
+
54
+ Tips:
55
+
56
+ - You can use `--model <checkpoint-dir>` or `--adapters <checkpoint-dir>` to specify the checkpoint directory to be pushed. There is no difference between these two methods in the model pushing scenario.
57
+ - When pushing to ModelScope, you need to make sure you have registered for a ModelScope account. Your SDK token can be obtained from [this page](https://www.modelscope.cn/my/myaccesstoken). Ensure that the account associated with the SDK token has edit permissions for the organization corresponding to the model_id. The model pushing process will automatically create a model repository corresponding to the model_id (if it does not already exist), and you can use `--hub_private_repo true` to automatically create a private model repository.
ms-swift/docs/source_en/Instruction/ReleaseNote3.0.md ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ReleaseNote 3.0
2
+
3
+ > If you encounter any issues while using version 3.x, please submit an issue to us. If something works in version 2.x but not in 3.x, please use version 2.x temporarily while we complete the fixes.
4
+
5
+ ## New Features
6
+
7
+ 1. Dataset module refactoring. The dataset loading speed has improved by 2-20 times, and encoding speed has improved by 2-4 times, with support for streaming mode.
8
+ - Removed the dataset_name mechanism; now use dataset_id, dataset_dir, or dataset_path to specify the dataset.
9
+ - Use `--dataset_num_proc` to support multi-process acceleration.
10
+ - Use `--streaming` to support streaming loading of hub and local datasets.
11
+ - Support `--packing` command for more stable training efficiency.
12
+ - Use `--dataset <dataset_dir>` to support local loading of open-source datasets.
13
+
14
+ 2. Model refactoring:
15
+ - Removed model_type mechanism; use `--model <model_id>/<model_path>` for training and inference.
16
+ - For new models, directly use `--model <model_id>/<model_path> --template xxx --model_type xxx` without needing to write a Python script for model registration.
17
+
18
+ 3. Template module refactoring:
19
+ - Use `--template_backend jinja` for Jinja mode inference.
20
+ - Utilize messages format as the input parameter interface.
21
+
22
+ 4. Supported plugin mechanism for customizing the training process. Current plugins include:
23
+ - callback to customize training callbacks,
24
+ - loss to customize the loss method,
25
+ - loss_scale to customize the weight of each token,
26
+ - metric to customize cross-validation metrics,
27
+ - optimizer to customize the optimizer and lr_scheduler used in training,
28
+ - tools to customize agent training system format,
29
+ - tuner to customize new tuners.
30
+
31
+ 5. Training module refactoring:
32
+ - Supports a single command to launch multi-machine training. See details [here](https://github.com/modelscope/ms-swift/tree/main/examples/train/multi-node/deepspeed/README.md).
33
+ - Supports PreTraining for all multi-modal LLMs.
34
+ - In training, predict_with_generate now uses the infer module, supporting multi-modal LLM and multi-card setups.
35
+ - Human alignment KTO algorithm supports multi-modal LLMs.
36
+
37
+ 6. Inference and deployment module refactoring:
38
+ - Supports batch inference under pt backend and multi-card inference.
39
+ - Inference and deployment modules are unified using the OpenAI format interface.
40
+ - Supports asynchronous inference interface.
41
+
42
+ 7. Merged app-ui into web-ui, with app-ui supporting multi-modal inference.
43
+
44
+ 8. Supports All-to-All models, such as Emu3-Gen and Janus for text-to-image or all-modal model training and deployment.
45
+
46
+ 9. Enhanced the functionality of the examples, so that they can now fully reflect the capabilities of SWIFT and have stronger usability.
47
+
48
+ 10. Use `--use_hf true/false` to switch between downloading/uploading datasets and models from HuggingFace and ModelScope communities.
49
+
50
+ 11. Improved support for training and inference through code. The code structure is clearer, and extensive code comments have been added.
51
+
52
+ ## BreakChanges
53
+
54
+ This document lists the BreakChanges between version 3.x and 2.x. Developers should note these differences when using them.
55
+
56
+ ### Parameter Differences
57
+
58
+ - Version 3.0 only requires specifying --model. The model_type only needs to be specified additionally when the model is not supported by SWIFT.
59
+ - sft_type is renamed to train_type.
60
+ - model_id_or_path is renamed to model.
61
+ - template_type is renamed to template.
62
+ - quantization_bit is renamed to quant_bits.
63
+ - check_model_is_latest is renamed to check_model.
64
+ - batch_size is renamed to per_device_train_batch_size, following the transformers naming convention.
65
+ - eval_batch_size is renamed to per_device_eval_batch_size, following the transformers naming convention.
66
+ - tuner_backend has removed the swift option.
67
+ - use_flash_attn is renamed to attn_impl.
68
+ - bnb_4bit_comp_dtype is renamed to bnb_4bit_compute_dtype.
69
+ - Removed train_dataset_sample and val_dataset_sample.
70
+ - The term 'dtype' has been renamed to 'torch_dtype', and the option names have been changed from 'bf16' to the standard 'bfloat16', 'fp16' to 'float16', and 'fp32' to 'float32'.
71
+ - Removed eval_human option.
72
+ - The dataset option has removed the HF:: usage; use the new --use_hf to control downloading and uploading.
73
+ - Removed the do_sample option, and now use temperature for control.
74
+ - add_output_dir_suffix is renamed to add_version.
75
+ - Removed eval_token; API key is now supported.
76
+ - target_modules (lora_target_modules) ALL is changed to all-linear, retaining the same meaning.
77
+ - The parameters --ckpt_dir have been removed from infer/deploy/export, and control is now done using --model and --adapters.
78
+
79
+ The parameters marked as compatible in version 2.0 have been entirely removed.
80
+
81
+ ### Functionality
82
+
83
+ 1. For pre-training, please use the swift pt command. This command will default to using the generation template, while the swift sft command will default to the template preset by model_type.
84
+
85
+ 2. Completely removed the examples directory from version 2.x, and added new examples categorized by functionality.
86
+
87
+ 3. The dataset format is now fully compatible with messages format; query/response/history formats are no longer supported.
88
+
89
+ 4. The storage directory for merge_lora can be specified using `--output_dir`, and merge_lora and quantization cannot be executed in the same command; at least two commands are required.
90
+
91
+ 5. Use `swift app --model xxx` to launch the app-ui interface, which supports multimodal interface inference.
92
+
93
+ 6. Removed dependencies for AIGC along with corresponding examples and training code.
ms-swift/docs/source_en/_templates/classtemplate.rst ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .. currentmodule:: {{ module }}
2
+
3
+
4
+ {{ name | underline}}
5
+
6
+ .. autoclass:: {{ name }}
7
+ :members:
8
+ :special-members: __init__, __call__
9
+
10
+ ..
11
+ autogenerated from source/_templates/classtemplate.rst
12
+ note it does not have :inherited-members:
ms-swift/docs/source_en/index.rst ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .. swift documentation file,
2
+ You can adapt this file completely to your liking, but it should at least
3
+ contain the root `toctree` directive.
4
+
5
+ Swift DOCUMENTATION
6
+ ========================
7
+
8
+ .. toctree::
9
+ :maxdepth: 2
10
+ :caption: Get Started
11
+
12
+ GetStarted/SWIFT-installation.md
13
+ GetStarted/Quick-start.md
14
+ GetStarted/Web-UI.md
15
+
16
+ .. toctree::
17
+ :maxdepth: 2
18
+ :caption: Instruction
19
+
20
+ Instruction/Command-line-parameters.md
21
+ Instruction/Pre-training-and-Fine-tuning.md
22
+ Instruction/RLHF.md
23
+ Instruction/Inference-and-deployment.md
24
+ Instruction/Megatron-SWIFT-Training.md
25
+ Instruction/Sample.md
26
+ Instruction/Evaluation.md
27
+ Instruction/Export-and-push.md
28
+ Instruction/Reinforced-Fine-tuning.md
29
+ Instruction/GRPO.md
30
+ Instruction/Agent-support.md
31
+ Instruction/Supported-models-and-datasets.md
32
+ Instruction/Use-tuners.md
33
+ Instruction/Frequently-asked-questions.md
34
+
35
+
36
+ .. toctree::
37
+ :maxdepth: 2
38
+ :caption: Customization
39
+
40
+ Customization/Custom-model.md
41
+ Customization/Custom-dataset.md
42
+ Customization/Pluginization.md
43
+
44
+
45
+ .. toctree::
46
+ :maxdepth: 2
47
+ :caption: Best Practices
48
+
49
+ BestPractices/GRPO.md
50
+ BestPractices/GRPO-Multi-Modal-Training.md
51
+ BestPractices/GRPO-Code-Training.md
52
+ BestPractices/Embedding.md
53
+ BestPractices/Rapidly-Training-VL-model.md
54
+ BestPractices/NPU-support.md
55
+ BestPractices/More-Best-Practices.md
56
+
57
+ Indices and tables
58
+ ==================
59
+ * :ref:`genindex`
60
+ * :ref:`modindex`
61
+ * :ref:`search`
ms-swift/examples/app/mllm.sh ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CUDA_VISIBLE_DEVICES=0 \
2
+ MAX_PIXELS=1003520 \
3
+ VIDEO_MAX_PIXELS=50176 \
4
+ FPS_MAX_FRAMES=12 \
5
+ swift app \
6
+ --model Qwen/Qwen2.5-VL-7B-Instruct \
7
+ --stream true \
8
+ --infer_backend vllm \
9
+ --gpu_memory_utilization 0.9 \
10
+ --max_model_len 8192 \
11
+ --max_new_tokens 2048 \
12
+ --limit_mm_per_prompt '{"image": 5, "video": 2}' \
13
+ --lang zh
ms-swift/examples/deploy/bert/server.sh ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ # Since `swift/test_lora` is trained by swift and contains an `args.json` file,
2
+ # there is no need to explicitly set `--model`, `--system`, etc., as they will be automatically read.
3
+ CUDA_VISIBLE_DEVICES=0 swift deploy \
4
+ --host 0.0.0.0 \
5
+ --port 8000 \
6
+ --adapters swift/test_bert \
7
+ --served_model_name bert-base-chinese \
8
+ --infer_backend pt \
9
+ --truncation_strategy right \
10
+ --max_length 512
ms-swift/examples/deploy/client/llm/base/openai_client.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Alibaba, Inc. and its affiliates.
2
+ import os
3
+
4
+ from openai import OpenAI
5
+
6
+ os.environ['CUDA_VISIBLE_DEVICES'] = '0'
7
+
8
+
9
+ def infer(client, model: str, messages):
10
+ query = messages[0]['content']
11
+ print(f'query: {query}')
12
+ resp = client.completions.create(model=model, prompt=query, max_tokens=64, temperature=0)
13
+ response = resp.choices[0].text
14
+ print(f'response: {response}')
15
+ # or (The two calling methods are equivalent.)
16
+ resp = client.chat.completions.create(model=model, messages=messages, max_tokens=64, temperature=0)
17
+ response = resp.choices[0].message.content
18
+ print(f'response: {response}')
19
+ return response
20
+
21
+
22
+ def run_client(host: str = '127.0.0.1', port: int = 8000):
23
+ client = OpenAI(
24
+ api_key='EMPTY',
25
+ base_url=f'http://{host}:{port}/v1',
26
+ )
27
+ model = client.models.list().data[0].id
28
+ print(f'model: {model}')
29
+
30
+ messages = [{'role': 'user', 'content': '浙江 -> 杭州\n安徽 -> 合肥\n四川 ->'}]
31
+ infer(client, model, messages)
32
+
33
+
34
+ if __name__ == '__main__':
35
+ from swift.llm import run_deploy, DeployArguments
36
+ # NOTE: In a real deployment scenario, please comment out the context of run_deploy.
37
+ with run_deploy(
38
+ DeployArguments(
39
+ model='Qwen/Qwen2.5-1.5B', verbose=False, log_interval=-1, infer_backend='pt',
40
+ use_chat_template=False)) as port:
41
+ run_client(port=port)
ms-swift/examples/deploy/client/llm/chat/swift_client.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Alibaba, Inc. and its affiliates.
2
+ import os
3
+ from typing import List
4
+
5
+ os.environ['CUDA_VISIBLE_DEVICES'] = '0'
6
+
7
+
8
+ def infer_batch(engine: 'InferEngine', infer_requests: List['InferRequest']):
9
+ request_config = RequestConfig(max_tokens=512, temperature=0)
10
+ metric = InferStats()
11
+
12
+ resp_list = engine.infer(infer_requests, request_config, metrics=[metric])
13
+ # # The asynchronous interface below is equivalent to the synchronous interface above.
14
+ # async def _run():
15
+ # tasks = [engine.infer_async(infer_request, request_config) for infer_request in infer_requests]
16
+ # return await asyncio.gather(*tasks)
17
+ # resp_list = asyncio.run(_run())
18
+
19
+ query0 = infer_requests[0].messages[0]['content']
20
+ print(f'query0: {query0}')
21
+ print(f'response0: {resp_list[0].choices[0].message.content}')
22
+ print(f'metric: {metric.compute()}')
23
+
24
+
25
+ def infer_stream(engine: 'InferEngine', infer_request: 'InferRequest'):
26
+ request_config = RequestConfig(max_tokens=512, temperature=0, stream=True)
27
+ metric = InferStats()
28
+ gen_list = engine.infer([infer_request], request_config, metrics=[metric])
29
+ query = infer_request.messages[0]['content']
30
+ print(f'query: {query}\nresponse: ', end='')
31
+ for resp in gen_list[0]:
32
+ if resp is None:
33
+ continue
34
+ print(resp.choices[0].delta.content, end='', flush=True)
35
+ print()
36
+ print(f'metric: {metric.compute()}')
37
+
38
+
39
+ def run_client(host: str = '127.0.0.1', port: int = 8000):
40
+ engine = InferClient(host=host, port=port)
41
+ print(f'models: {engine.models}')
42
+ # Here, `load_dataset` is used for convenience; `infer_batch` does not require creating a dataset.
43
+ dataset = load_dataset(['AI-ModelScope/alpaca-gpt4-data-zh#1000'], seed=42)[0]
44
+ print(f'dataset: {dataset}')
45
+ infer_requests = [InferRequest(**data) for data in dataset]
46
+ infer_batch(engine, infer_requests)
47
+
48
+ messages = [{'role': 'user', 'content': 'who are you?'}]
49
+ infer_stream(engine, InferRequest(messages=messages))
50
+
51
+
52
+ if __name__ == '__main__':
53
+ from swift.llm import (InferEngine, InferRequest, InferClient, RequestConfig, load_dataset, run_deploy,
54
+ DeployArguments)
55
+ from swift.plugin import InferStats
56
+ # NOTE: In a real deployment scenario, please comment out the context of run_deploy.
57
+ with run_deploy(
58
+ DeployArguments(model='Qwen/Qwen2.5-1.5B-Instruct', verbose=False, log_interval=-1,
59
+ infer_backend='vllm')) as port:
60
+ run_client(port=port)
ms-swift/examples/deploy/client/mllm/openai_client.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Alibaba, Inc. and its affiliates.
2
+ import os
3
+ from typing import Literal
4
+
5
+ from openai import OpenAI
6
+
7
+ os.environ['CUDA_VISIBLE_DEVICES'] = '0'
8
+
9
+
10
+ def infer(client, model: str, messages):
11
+ resp = client.chat.completions.create(model=model, messages=messages, max_tokens=512, temperature=0)
12
+ query = messages[0]['content']
13
+ response = resp.choices[0].message.content
14
+ print(f'query: {query}')
15
+ print(f'response: {response}')
16
+ return response
17
+
18
+
19
+ # streaming
20
+ def infer_stream(client, model: str, messages):
21
+ gen = client.chat.completions.create(model=model, messages=messages, stream=True, temperature=0)
22
+ print(f'messages: {messages}\nresponse: ', end='')
23
+ for chunk in gen:
24
+ print(chunk.choices[0].delta.content, end='', flush=True)
25
+ print()
26
+
27
+
28
+ def get_message(mm_type: Literal['text', 'image', 'video', 'audio']):
29
+ if mm_type == 'text':
30
+ message = {'role': 'user', 'content': 'who are you?'}
31
+ elif mm_type == 'image':
32
+ message = {
33
+ 'role':
34
+ 'user',
35
+ 'content': [{
36
+ 'type': 'image',
37
+ 'image': 'http://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/animal.png'
38
+ }, {
39
+ 'type': 'text',
40
+ 'text': 'How many sheep are there in the picture?'
41
+ }]
42
+ }
43
+
44
+ elif mm_type == 'video':
45
+ # # use base64
46
+ # import base64
47
+ # with open('baby.mp4', 'rb') as f:
48
+ # vid_base64 = base64.b64encode(f.read()).decode('utf-8')
49
+ # video = f'data:video/mp4;base64,{vid_base64}'
50
+
51
+ # use url
52
+ video = 'https://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/baby.mp4'
53
+ message = {
54
+ 'role': 'user',
55
+ 'content': [{
56
+ 'type': 'video',
57
+ 'video': video
58
+ }, {
59
+ 'type': 'text',
60
+ 'text': 'Describe this video.'
61
+ }]
62
+ }
63
+ elif mm_type == 'audio':
64
+ message = {
65
+ 'role':
66
+ 'user',
67
+ 'content': [{
68
+ 'type': 'audio',
69
+ 'audio': 'http://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/weather.wav'
70
+ }, {
71
+ 'type': 'text',
72
+ 'text': 'What does this audio say?'
73
+ }]
74
+ }
75
+ return message
76
+
77
+
78
+ def run_client(host: str = '127.0.0.1', port: int = 8000):
79
+ client = OpenAI(
80
+ api_key='EMPTY',
81
+ base_url=f'http://{host}:{port}/v1',
82
+ )
83
+ model = client.models.list().data[0].id
84
+ print(f'model: {model}')
85
+
86
+ query = 'who are you?'
87
+ messages = [{'role': 'user', 'content': query}]
88
+ response = infer(client, model, messages)
89
+ messages.append({'role': 'assistant', 'content': response})
90
+ messages.append(get_message(mm_type='video'))
91
+ infer_stream(client, model, messages)
92
+
93
+
94
+ if __name__ == '__main__':
95
+ from swift.llm import run_deploy, DeployArguments
96
+ with run_deploy(DeployArguments(model='Qwen/Qwen2.5-VL-3B-Instruct', verbose=False, log_interval=-1)) as port:
97
+ run_client(port=port)
ms-swift/examples/deploy/client/mllm/swift_client.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Alibaba, Inc. and its affiliates.
2
+ import os
3
+ from typing import List, Literal
4
+
5
+ os.environ['CUDA_VISIBLE_DEVICES'] = '0'
6
+
7
+
8
+ def infer_batch(engine: 'InferEngine', infer_requests: List['InferRequest']):
9
+ request_config = RequestConfig(max_tokens=512, temperature=0)
10
+ metric = InferStats()
11
+ resp_list = engine.infer(infer_requests, request_config, metrics=[metric])
12
+ query0 = infer_requests[0].messages[0]['content']
13
+ print(f'query0: {query0}')
14
+ print(f'response0: {resp_list[0].choices[0].message.content}')
15
+ print(f'metric: {metric.compute()}')
16
+
17
+
18
+ def infer_stream(engine: 'InferEngine', infer_request: 'InferRequest'):
19
+ request_config = RequestConfig(max_tokens=512, temperature=0, stream=True)
20
+ metric = InferStats()
21
+ gen_list = engine.infer([infer_request], request_config, metrics=[metric])
22
+ query = infer_request.messages[0]['content']
23
+ print(f'query: {query}\nresponse: ', end='')
24
+ for resp in gen_list[0]:
25
+ if resp is None:
26
+ continue
27
+ print(resp.choices[0].delta.content, end='', flush=True)
28
+ print()
29
+ print(f'metric: {metric.compute()}')
30
+
31
+
32
+ def get_message(mm_type: Literal['text', 'image', 'video', 'audio']):
33
+ if mm_type == 'text':
34
+ message = {'role': 'user', 'content': 'who are you?'}
35
+ elif mm_type == 'image':
36
+ message = {
37
+ 'role':
38
+ 'user',
39
+ 'content': [
40
+ {
41
+ 'type': 'image',
42
+ # url or local_path or PIL.Image or base64
43
+ 'image': 'http://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/animal.png'
44
+ },
45
+ {
46
+ 'type': 'text',
47
+ 'text': 'How many sheep are there in the picture?'
48
+ }
49
+ ]
50
+ }
51
+
52
+ elif mm_type == 'video':
53
+ # # use base64
54
+ # import base64
55
+ # with open('baby.mp4', 'rb') as f:
56
+ # vid_base64 = base64.b64encode(f.read()).decode('utf-8')
57
+ # video = f'data:video/mp4;base64,{vid_base64}'
58
+
59
+ # use url
60
+ video = 'https://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/baby.mp4'
61
+ message = {
62
+ 'role': 'user',
63
+ 'content': [{
64
+ 'type': 'video',
65
+ 'video': video
66
+ }, {
67
+ 'type': 'text',
68
+ 'text': 'Describe this video.'
69
+ }]
70
+ }
71
+ elif mm_type == 'audio':
72
+ message = {
73
+ 'role':
74
+ 'user',
75
+ 'content': [{
76
+ 'type': 'audio',
77
+ 'audio': 'http://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/weather.wav'
78
+ }, {
79
+ 'type': 'text',
80
+ 'text': 'What does this audio say?'
81
+ }]
82
+ }
83
+ return message
84
+
85
+
86
+ def get_data(mm_type: Literal['text', 'image', 'video', 'audio']):
87
+ data = {}
88
+ if mm_type == 'text':
89
+ messages = [{'role': 'user', 'content': 'who are you?'}]
90
+ elif mm_type == 'image':
91
+ # The number of <image> tags must be the same as len(images).
92
+ messages = [{'role': 'user', 'content': '<image>How many sheep are there in the picture?'}]
93
+ # Support URL/Path/base64/PIL.Image
94
+ data['images'] = ['http://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/animal.png']
95
+ elif mm_type == 'video':
96
+ messages = [{'role': 'user', 'content': '<video>Describe this video.'}]
97
+ data['videos'] = ['https://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/baby.mp4']
98
+ elif mm_type == 'audio':
99
+ messages = [{'role': 'user', 'content': '<audio>What does this audio say?'}]
100
+ data['audios'] = ['http://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/weather.wav']
101
+ data['messages'] = messages
102
+ return data
103
+
104
+
105
+ def run_client(host: str = '127.0.0.1', port: int = 8000):
106
+ engine = InferClient(host=host, port=port)
107
+ print(f'models: {engine.models}')
108
+ # Here, `load_dataset` is used for convenience; `infer_batch` does not require creating a dataset.
109
+ dataset = load_dataset(['AI-ModelScope/LaTeX_OCR:small#1000'], seed=42)[0]
110
+ print(f'dataset: {dataset}')
111
+ infer_requests = [InferRequest(**data) for data in dataset]
112
+ infer_batch(engine, infer_requests)
113
+
114
+ infer_stream(engine, InferRequest(messages=[get_message(mm_type='video')]))
115
+ # This writing is equivalent to the above writing.
116
+ infer_stream(engine, InferRequest(**get_data(mm_type='video')))
117
+
118
+
119
+ if __name__ == '__main__':
120
+ from swift.llm import (InferEngine, InferRequest, InferClient, RequestConfig, load_dataset, run_deploy,
121
+ DeployArguments)
122
+ from swift.plugin import InferStats
123
+ # NOTE: In a real deployment scenario, please comment out the context of run_deploy.
124
+ with run_deploy(
125
+ DeployArguments(model='Qwen/Qwen2.5-VL-3B-Instruct', verbose=False, log_interval=-1,
126
+ infer_backend='vllm')) as port:
127
+ run_client(port=port)
ms-swift/examples/deploy/lora/client.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from swift.llm import InferClient, InferRequest, RequestConfig
2
+
3
+
4
+ def infer_multilora(engine: InferClient, infer_request: InferRequest):
5
+ # Dynamic LoRA
6
+ models = engine.models
7
+ print(f'models: {models}')
8
+ request_config = RequestConfig(max_tokens=512, temperature=0)
9
+
10
+ # use lora1
11
+ resp_list = engine.infer([infer_request], request_config, model=models[1])
12
+ response = resp_list[0].choices[0].message.content
13
+ print(f'lora1-response: {response}')
14
+ # origin model
15
+ resp_list = engine.infer([infer_request], request_config, model=models[0])
16
+ response = resp_list[0].choices[0].message.content
17
+ print(f'response: {response}')
18
+ # use lora2
19
+ resp_list = engine.infer([infer_request], request_config, model=models[2])
20
+ response = resp_list[0].choices[0].message.content
21
+ print(f'lora2-response: {response}')
22
+
23
+
24
+ if __name__ == '__main__':
25
+ engine = InferClient(host='127.0.0.1', port=8000)
26
+ infer_request = InferRequest(messages=[{'role': 'user', 'content': 'who are you?'}])
27
+ infer_multilora(engine, infer_request)
ms-swift/examples/deploy/server/README.md ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ Please refer to the examples in [examples/infer](../../infer/) and change `swift infer` to `swift deploy` to start the service. (You need to additionally remove `--val_dataset`)
2
+
3
+ e.g.
4
+ ```shell
5
+ CUDA_VISIBLE_DEVICES=0 \
6
+ swift deploy \
7
+ --model Qwen/Qwen2.5-7B-Instruct \
8
+ --infer_backend vllm
9
+ ```
ms-swift/examples/eval/llm/eval.sh ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ CUDA_VISIBLE_DEVICES=0 \
2
+ swift eval \
3
+ --model Qwen/Qwen2.5-1.5B-Instruct \
4
+ --eval_backend OpenCompass \
5
+ --infer_backend vllm \
6
+ --eval_limit 100 \
7
+ --eval_dataset gsm8k
ms-swift/examples/export/merge_lora.sh ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # Since `output/vx-xxx/checkpoint-xxx` is trained by swift and contains an `args.json` file,
2
+ # there is no need to explicitly set `--model`, `--system`, etc., as they will be automatically read.
3
+ swift export \
4
+ --adapters output/vx-xxx/checkpoint-xxx \
5
+ --merge_lora true
ms-swift/examples/export/quantize/mllm/gptq.sh ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # OMP_NUM_THREADS=14 please Check issue: https://github.com/AutoGPTQ/AutoGPTQ/issues/439
2
+ OMP_NUM_THREADS=14 \
3
+ CUDA_VISIBLE_DEVICES=0 \
4
+ MAX_PIXELS=1003520 \
5
+ VIDEO_MAX_PIXELS=50176 \
6
+ FPS_MAX_FRAMES=12 \
7
+ swift export \
8
+ --model Qwen/Qwen2.5-VL-3B-Instruct \
9
+ --dataset 'AI-ModelScope/alpaca-gpt4-data-zh#500' \
10
+ 'AI-ModelScope/alpaca-gpt4-data-en#500' \
11
+ 'modelscope/coco_2014_caption:validation#500' \
12
+ 'swift/VideoChatGPT:Generic#500' \
13
+ --quant_n_samples 256 \
14
+ --quant_batch_size 1 \
15
+ --max_length 2048 \
16
+ --quant_method gptq \
17
+ --quant_bits 4 \
18
+ --output_dir Qwen2.5-VL-3B-Instruct-GPTQ-Int4
ms-swift/examples/export/quantize/moe/gptq.sh ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 2 * 80GB
2
+ OMP_NUM_THREADS=14 \
3
+ CUDA_VISIBLE_DEVICES=0,1 \
4
+ swift export \
5
+ --model Qwen/Qwen2-57B-A14B-Instruct \
6
+ --dataset 'AI-ModelScope/alpaca-gpt4-data-zh#1000' \
7
+ 'AI-ModelScope/alpaca-gpt4-data-en#1000' \
8
+ --quant_n_samples 512 \
9
+ --quant_batch_size 1 \
10
+ --max_length 4096 \
11
+ --quant_method gptq \
12
+ --quant_bits 4 \
13
+ --output_dir Qwen2-57B-A14B-Instruct-GPTQ-Int4
ms-swift/examples/export/quantize/omni/gptq.sh ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # OMP_NUM_THREADS=14 please Check issue: https://github.com/AutoGPTQ/AutoGPTQ/issues/439
2
+ OMP_NUM_THREADS=14 \
3
+ CUDA_VISIBLE_DEVICES=0 \
4
+ MAX_PIXELS=1003520 \
5
+ VIDEO_MAX_PIXELS=50176 \
6
+ FPS_MAX_FRAMES=12 \
7
+ swift export \
8
+ --model Qwen/Qwen2.5-Omni-7B \
9
+ --dataset 'AI-ModelScope/alpaca-gpt4-data-zh#500' \
10
+ 'AI-ModelScope/alpaca-gpt4-data-en#500' \
11
+ 'modelscope/coco_2014_caption:validation#500' \
12
+ 'swift/VideoChatGPT:Generic#500' \
13
+ --quant_n_samples 256 \
14
+ --quant_batch_size 1 \
15
+ --max_length 2048 \
16
+ --quant_method gptq \
17
+ --quant_bits 4 \
18
+ --output_dir Qwen2.5-Omni-7B-GPTQ-Int4
ms-swift/examples/export/quantize/reward_model/bnb.sh ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # bnb quantize
2
+ CUDA_VISIBLE_DEVICES=0 swift export \
3
+ --model Shanghai_AI_Laboratory/internlm2-1_8b-reward \
4
+ --output_dir output/internlm2-1_8b-reward-bnb-int4 \
5
+ --quant_bits 4 \
6
+ --quant_method bnb
7
+
8
+ # infer
9
+ CUDA_VISIBLE_DEVICES=0 swift infer \
10
+ --model output/internlm2-1_8b-reward-bnb-int4 \
11
+ --val_dataset 'AI-ModelScope/alpaca-gpt4-data-zh#1000' \
12
+ --max_batch_size 16
ms-swift/examples/export/quantize/reward_model/gptq.sh ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # gptq quantize
2
+ CUDA_VISIBLE_DEVICES=0 swift export \
3
+ --model Shanghai_AI_Laboratory/internlm2-1_8b-reward \
4
+ --output_dir output/internlm2-1_8b-reward-gptq-int4 \
5
+ --quant_bits 4 \
6
+ --quant_method gptq \
7
+ --dataset 'AI-ModelScope/alpaca-gpt4-data-zh#1000' 'AI-ModelScope/alpaca-gpt4-data-en#1000'
8
+
9
+ # infer
10
+ CUDA_VISIBLE_DEVICES=0 swift infer \
11
+ --model output/internlm2-1_8b-reward-gptq-int4 \
12
+ --val_dataset 'AI-ModelScope/alpaca-gpt4-data-zh#1000' \
13
+ --max_batch_size 16
ms-swift/examples/infer/cli_demo.sh ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ CUDA_VISIBLE_DEVICES=0 \
2
+ swift infer \
3
+ --model Qwen/Qwen2.5-1.5B-Instruct \
4
+ --infer_backend pt \
5
+ --stream true \
6
+ --max_new_tokens 2048
ms-swift/examples/infer/demo.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Alibaba, Inc. and its affiliates.
2
+ import asyncio
3
+ import os
4
+ from typing import List
5
+
6
+ os.environ['CUDA_VISIBLE_DEVICES'] = '0'
7
+
8
+
9
+ def infer_batch(engine: 'InferEngine', infer_requests: List['InferRequest']):
10
+ request_config = RequestConfig(max_tokens=512, temperature=0)
11
+ metric = InferStats()
12
+ resp_list = engine.infer(infer_requests, request_config, metrics=[metric])
13
+ query0 = infer_requests[0].messages[0]['content']
14
+ print(f'query0: {query0}')
15
+ print(f'response0: {resp_list[0].choices[0].message.content}')
16
+ print(f'metric: {metric.compute()}')
17
+ # metric.reset() # reuse
18
+
19
+
20
+ def infer_async_batch(engine: 'InferEngine', infer_requests: List['InferRequest']):
21
+ # The asynchronous interface below is equivalent to the synchronous interface above.
22
+ request_config = RequestConfig(max_tokens=512, temperature=0)
23
+
24
+ async def _run():
25
+ tasks = [engine.infer_async(infer_request, request_config) for infer_request in infer_requests]
26
+ return await asyncio.gather(*tasks)
27
+
28
+ resp_list = asyncio.run(_run())
29
+
30
+ query0 = infer_requests[0].messages[0]['content']
31
+ print(f'query0: {query0}')
32
+ print(f'response0: {resp_list[0].choices[0].message.content}')
33
+
34
+
35
+ def infer_stream(engine: 'InferEngine', infer_request: 'InferRequest'):
36
+ request_config = RequestConfig(max_tokens=512, temperature=0, stream=True)
37
+ metric = InferStats()
38
+ gen_list = engine.infer([infer_request], request_config, metrics=[metric])
39
+ query = infer_request.messages[0]['content']
40
+ print(f'query: {query}\nresponse: ', end='')
41
+ for resp in gen_list[0]:
42
+ if resp is None:
43
+ continue
44
+ print(resp.choices[0].delta.content, end='', flush=True)
45
+ print()
46
+ print(f'metric: {metric.compute()}')
47
+
48
+
49
+ if __name__ == '__main__':
50
+ from swift.llm import InferEngine, InferRequest, PtEngine, RequestConfig, load_dataset
51
+ from swift.plugin import InferStats
52
+ model = 'Qwen/Qwen2.5-1.5B-Instruct'
53
+ infer_backend = 'pt'
54
+
55
+ if infer_backend == 'pt':
56
+ engine = PtEngine(model, max_batch_size=64)
57
+ elif infer_backend == 'vllm':
58
+ from swift.llm import VllmEngine
59
+ engine = VllmEngine(model, max_model_len=8192)
60
+ elif infer_backend == 'lmdeploy':
61
+ from swift.llm import LmdeployEngine
62
+ engine = LmdeployEngine(model)
63
+
64
+ # Here, `load_dataset` is used for convenience; `infer_batch` does not require creating a dataset.
65
+ dataset = load_dataset(['AI-ModelScope/alpaca-gpt4-data-zh#1000'], seed=42)[0]
66
+ print(f'dataset: {dataset}')
67
+ infer_requests = [InferRequest(**data) for data in dataset]
68
+ # if infer_backend in {'vllm', 'lmdeploy'}:
69
+ # infer_async_batch(engine, infer_requests)
70
+ infer_batch(engine, infer_requests)
71
+
72
+ messages = [{'role': 'user', 'content': 'who are you?'}]
73
+ infer_stream(engine, InferRequest(messages=messages))
ms-swift/examples/infer/demo_agent.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Alibaba, Inc. and its affiliates.
2
+ import os
3
+
4
+ os.environ['CUDA_VISIBLE_DEVICES'] = '0'
5
+ # os.environ['SWIFT_DEBUG'] = '1'
6
+
7
+
8
+ def infer(engine: 'InferEngine', infer_request: 'InferRequest'):
9
+ stop = [engine.default_template.agent_template.keyword.observation] # compat react_en
10
+ request_config = RequestConfig(max_tokens=512, temperature=0, stop=stop)
11
+ resp_list = engine.infer([infer_request], request_config)
12
+ query = infer_request.messages[0]['content']
13
+ response = resp_list[0].choices[0].message.content
14
+ print(f'query: {query}')
15
+ print(f'response: {response}')
16
+ print(f'tool_calls: {resp_list[0].choices[0].message.tool_calls}')
17
+
18
+ tool = '{"temperature": 32, "condition": "Sunny", "humidity": 50}'
19
+ print(f'tool_response: {tool}')
20
+ infer_request.messages += [{'role': 'assistant', 'content': response}, {'role': 'tool', 'content': tool}]
21
+ resp_list = engine.infer([infer_request], request_config)
22
+ response2 = resp_list[0].choices[0].message.content
23
+ print(f'response2: {response2}')
24
+
25
+
26
+ def infer_stream(engine: 'InferEngine', infer_request: 'InferRequest'):
27
+ stop = [engine.default_template.agent_template.keyword.observation]
28
+ request_config = RequestConfig(max_tokens=512, temperature=0, stream=True, stop=stop)
29
+ gen_list = engine.infer([infer_request], request_config)
30
+ query = infer_request.messages[0]['content']
31
+ response = ''
32
+ print(f'query: {query}\nresponse: ', end='')
33
+ for resp in gen_list[0]:
34
+ if resp is None:
35
+ continue
36
+ delta = resp.choices[0].delta.content
37
+ response += delta
38
+ print(delta, end='', flush=True)
39
+ print()
40
+ print(f'tool_calls: {resp.choices[0].delta.tool_calls}')
41
+
42
+ tool = '{"temperature": 32, "condition": "Sunny", "humidity": 50}'
43
+ print(f'tool_response: {tool}\nresponse2: ', end='')
44
+ infer_request.messages += [{'role': 'assistant', 'content': response}, {'role': 'tool', 'content': tool}]
45
+ gen_list = engine.infer([infer_request], request_config)
46
+ for resp in gen_list[0]:
47
+ if resp is None:
48
+ continue
49
+ print(resp.choices[0].delta.content, end='', flush=True)
50
+ print()
51
+
52
+
53
+ def get_infer_request():
54
+ return InferRequest(
55
+ messages=[{
56
+ 'role': 'user',
57
+ 'content': "How's the weather in Beijing today?"
58
+ }],
59
+ tools=[{
60
+ 'name': 'get_current_weather',
61
+ 'description': 'Get the current weather in a given location',
62
+ 'parameters': {
63
+ 'type': 'object',
64
+ 'properties': {
65
+ 'location': {
66
+ 'type': 'string',
67
+ 'description': 'The city and state, e.g. San Francisco, CA'
68
+ },
69
+ 'unit': {
70
+ 'type': 'string',
71
+ 'enum': ['celsius', 'fahrenheit']
72
+ }
73
+ },
74
+ 'required': ['location']
75
+ }
76
+ }])
77
+
78
+
79
+ def infer_continue_generate(engine):
80
+ # Continue generating after the assistant message.
81
+ infer_request = InferRequest(messages=[{
82
+ 'role': 'user',
83
+ 'content': 'How is the weather today?'
84
+ }, {
85
+ 'role': 'assistant',
86
+ 'content': 'It is sunny today, '
87
+ }, {
88
+ 'role': 'assistant',
89
+ 'content': None
90
+ }])
91
+ request_config = RequestConfig(max_tokens=512, temperature=0)
92
+ resp_list = engine.infer([infer_request], request_config)
93
+ response = resp_list[0].choices[0].message.content
94
+ print(f'response: {response}')
95
+
96
+
97
+ if __name__ == '__main__':
98
+ from swift.llm import InferEngine, InferRequest, PtEngine, RequestConfig
99
+ from swift.plugin import agent_templates
100
+ model = 'Qwen/Qwen2.5-1.5B-Instruct'
101
+ infer_backend = 'pt'
102
+
103
+ if infer_backend == 'pt':
104
+ engine = PtEngine(model, max_batch_size=64)
105
+ elif infer_backend == 'vllm':
106
+ from swift.llm import VllmEngine
107
+ engine = VllmEngine(model, max_model_len=8192)
108
+ elif infer_backend == 'lmdeploy':
109
+ from swift.llm import LmdeployEngine
110
+ engine = LmdeployEngine(model)
111
+
112
+ # agent_template = agent_templates['hermes']() # react_en/qwen_en/qwen_en_parallel
113
+ # engine.default_template.agent_template = agent_template
114
+
115
+ infer(engine, get_infer_request())
116
+ infer_stream(engine, get_infer_request())
117
+
118
+ # infer_continue_generate(engine)
ms-swift/examples/infer/demo_bert.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Alibaba, Inc. and its affiliates.
2
+ import os
3
+ from typing import List
4
+
5
+ os.environ['CUDA_VISIBLE_DEVICES'] = '0'
6
+
7
+
8
+ def infer_batch(engine: 'InferEngine', infer_requests: List['InferRequest']):
9
+ resp_list = engine.infer(infer_requests)
10
+ query0 = infer_requests[0].messages[0]['content']
11
+ query1 = infer_requests[1].messages[0]['content']
12
+ print(f'query0: {query0}')
13
+ print(f'response0: {resp_list[0].choices[0].message.content}')
14
+ print(f'query1: {query1}')
15
+ print(f'response1: {resp_list[1].choices[0].message.content}')
16
+
17
+
18
+ if __name__ == '__main__':
19
+ # This is an example of BERT with LoRA.
20
+ from swift.llm import InferEngine, InferRequest, PtEngine, load_dataset, safe_snapshot_download, BaseArguments
21
+ from swift.tuners import Swift
22
+ adapter_path = safe_snapshot_download('swift/test_bert')
23
+ args = BaseArguments.from_pretrained(adapter_path)
24
+ args.max_length = 512
25
+ args.truncation_strategy = 'right'
26
+ # method1
27
+ model, processor = args.get_model_processor()
28
+ model = Swift.from_pretrained(model, adapter_path)
29
+ template = args.get_template(processor)
30
+ engine = PtEngine.from_model_template(model, template, max_batch_size=64)
31
+
32
+ # method2
33
+ # engine = PtEngine(args.model, adapters=[adapter_path], max_batch_size=64,
34
+ # task_type=args.task_type, num_labels=args.num_labels)
35
+ # template = args.get_template(engine.processor)
36
+ # engine.default_template = template
37
+
38
+ # Here, `load_dataset` is used for convenience; `infer_batch` does not require creating a dataset.
39
+ dataset = load_dataset(['DAMO_NLP/jd:cls#1000'], seed=42)[0]
40
+ print(f'dataset: {dataset}')
41
+ infer_requests = [InferRequest(messages=data['messages']) for data in dataset]
42
+ infer_batch(engine, infer_requests)
43
+
44
+ infer_batch(engine, [
45
+ InferRequest(messages=[{
46
+ 'role': 'user',
47
+ 'content': '今天天气真好呀'
48
+ }]),
49
+ InferRequest(messages=[{
50
+ 'role': 'user',
51
+ 'content': '真倒霉'
52
+ }])
53
+ ])
ms-swift/examples/infer/demo_hf.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def infer_hf():
2
+ from transformers import AutoModelForCausalLM, AutoTokenizer
3
+ from peft import PeftModel
4
+ from modelscope import snapshot_download
5
+ model_dir = snapshot_download('Qwen/Qwen2.5-7B-Instruct')
6
+ adapter_dir = snapshot_download('swift/test_lora')
7
+ model = AutoModelForCausalLM.from_pretrained(
8
+ model_dir, torch_dtype='auto', device_map='auto', trust_remote_code=True)
9
+ model = PeftModel.from_pretrained(model, adapter_dir)
10
+
11
+ tokenizer = AutoTokenizer.from_pretrained(model_dir, trust_remote_code=True)
12
+
13
+ messages = [{
14
+ 'role': 'system',
15
+ 'content': 'You are a helpful assistant.'
16
+ }, {
17
+ 'role': 'user',
18
+ 'content': 'who are you?'
19
+ }]
20
+ text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
21
+ model_inputs = tokenizer([text], return_tensors='pt', add_special_tokens=False).to(model.device)
22
+
23
+ generated_ids = model.generate(**model_inputs, max_new_tokens=512, do_sample=False)
24
+ generated_ids = [
25
+ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
26
+ ]
27
+
28
+ response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
29
+ print(f'response: {response}')
30
+ return response
31
+
32
+
33
+ def infer_swift():
34
+ from swift.llm import get_model_tokenizer, get_template, InferRequest, RequestConfig, PtEngine
35
+ from modelscope import snapshot_download
36
+ from swift.tuners import Swift
37
+ model_dir = snapshot_download('Qwen/Qwen2.5-7B-Instruct')
38
+ adapter_dir = snapshot_download('swift/test_lora')
39
+ model, tokenizer = get_model_tokenizer(model_dir, device_map='auto')
40
+ model = Swift.from_pretrained(model, adapter_dir)
41
+ template = get_template(model.model_meta.template, tokenizer)
42
+ engine = PtEngine.from_model_template(model, template)
43
+
44
+ messages = [{
45
+ 'role': 'system',
46
+ 'content': 'You are a helpful assistant.'
47
+ }, {
48
+ 'role': 'user',
49
+ 'content': 'who are you?'
50
+ }]
51
+ request_config = RequestConfig(max_tokens=512, temperature=0)
52
+ resp_list = engine.infer([InferRequest(messages=messages)], request_config=request_config)
53
+ response = resp_list[0].choices[0].message.content
54
+ print(f'response: {response}')
55
+ return response
56
+
57
+
58
+ if __name__ == '__main__':
59
+ response = infer_hf()
60
+ response2 = infer_swift()
61
+ assert response == response2
ms-swift/examples/infer/demo_lora.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from typing import Literal
3
+
4
+ os.environ['CUDA_VISIBLE_DEVICES'] = '0'
5
+
6
+
7
+ def infer_multilora(infer_request: 'InferRequest', infer_backend: Literal['vllm', 'pt']):
8
+ # Dynamic LoRA
9
+ adapter_path = safe_snapshot_download('swift/test_lora')
10
+ adapter_path2 = safe_snapshot_download('swift/test_lora2')
11
+ args = BaseArguments.from_pretrained(adapter_path)
12
+ if infer_backend == 'pt':
13
+ engine = PtEngine(args.model)
14
+ elif infer_backend == 'vllm':
15
+ from swift.llm import VllmEngine
16
+ engine = VllmEngine(args.model, enable_lora=True, max_loras=1, max_lora_rank=16)
17
+ template = get_template(args.template, engine.processor, args.system)
18
+ request_config = RequestConfig(max_tokens=512, temperature=0)
19
+ adapter_request = AdapterRequest('lora1', adapter_path)
20
+ adapter_request2 = AdapterRequest('lora2', adapter_path2)
21
+
22
+ # use lora
23
+ resp_list = engine.infer([infer_request], request_config, template=template, adapter_request=adapter_request)
24
+ response = resp_list[0].choices[0].message.content
25
+ print(f'lora1-response: {response}')
26
+ # origin model
27
+ resp_list = engine.infer([infer_request], request_config)
28
+ response = resp_list[0].choices[0].message.content
29
+ print(f'response: {response}')
30
+ # use lora
31
+ resp_list = engine.infer([infer_request], request_config, template=template, adapter_request=adapter_request2)
32
+ response = resp_list[0].choices[0].message.content
33
+ print(f'lora2-response: {response}')
34
+
35
+
36
+ def infer_lora(infer_request: 'InferRequest'):
37
+ request_config = RequestConfig(max_tokens=512, temperature=0)
38
+ adapter_path = safe_snapshot_download('swift/test_lora')
39
+ args = BaseArguments.from_pretrained(adapter_path)
40
+ # method1
41
+ # engine = PtEngine(args.model, adapters=[adapter_path])
42
+ # template = get_template(args.template, engine.tokenizer, args.system)
43
+ # engine.default_template = template
44
+
45
+ # method2
46
+ # model, processor = args.get_model_processor()
47
+ # model = Swift.from_pretrained(model, adapter_path)
48
+ # template = args.get_template(processor)
49
+ # engine = PtEngine.from_model_template(model, template)
50
+
51
+ # method3
52
+ model, tokenizer = get_model_tokenizer(args.model)
53
+ model = Swift.from_pretrained(model, adapter_path)
54
+ template = get_template(args.template, tokenizer, args.system)
55
+ engine = PtEngine.from_model_template(model, template)
56
+
57
+ resp_list = engine.infer([infer_request], request_config)
58
+ response = resp_list[0].choices[0].message.content
59
+ print(f'lora-response: {response}')
60
+
61
+
62
+ if __name__ == '__main__':
63
+ from swift.llm import (PtEngine, RequestConfig, AdapterRequest, get_template, BaseArguments, InferRequest,
64
+ safe_snapshot_download, get_model_tokenizer)
65
+ from swift.tuners import Swift
66
+ infer_request = InferRequest(messages=[{'role': 'user', 'content': 'who are you?'}])
67
+ # infer_lora(infer_request)
68
+ infer_multilora(infer_request, 'pt')
ms-swift/examples/infer/demo_mllm.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Alibaba, Inc. and its affiliates.
2
+ import os
3
+ from typing import List, Literal
4
+
5
+ os.environ['CUDA_VISIBLE_DEVICES'] = '0'
6
+
7
+
8
+ def infer_batch(engine: 'InferEngine', infer_requests: List['InferRequest']):
9
+ request_config = RequestConfig(max_tokens=512, temperature=0)
10
+ metric = InferStats()
11
+ resp_list = engine.infer(infer_requests, request_config, metrics=[metric])
12
+ query0 = infer_requests[0].messages[0]['content']
13
+ print(f'query0: {query0}')
14
+ print(f'response0: {resp_list[0].choices[0].message.content}')
15
+ print(f'metric: {metric.compute()}')
16
+ # metric.reset() # reuse
17
+
18
+
19
+ def infer_stream(engine: 'InferEngine', infer_request: 'InferRequest'):
20
+ request_config = RequestConfig(max_tokens=512, temperature=0, stream=True)
21
+ metric = InferStats()
22
+ gen_list = engine.infer([infer_request], request_config, metrics=[metric])
23
+ query = infer_request.messages[0]['content']
24
+ print(f'query: {query}\nresponse: ', end='')
25
+ for resp in gen_list[0]:
26
+ if resp is None:
27
+ continue
28
+ print(resp.choices[0].delta.content, end='', flush=True)
29
+ print()
30
+ print(f'metric: {metric.compute()}')
31
+
32
+
33
+ def get_message(mm_type: Literal['text', 'image', 'video', 'audio']):
34
+ if mm_type == 'text':
35
+ message = {'role': 'user', 'content': 'who are you?'}
36
+ elif mm_type == 'image':
37
+ message = {
38
+ 'role':
39
+ 'user',
40
+ 'content': [
41
+ {
42
+ 'type': 'image',
43
+ # url or local_path or PIL.Image or base64
44
+ 'image': 'http://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/animal.png'
45
+ },
46
+ {
47
+ 'type': 'text',
48
+ 'text': 'How many sheep are there in the picture?'
49
+ }
50
+ ]
51
+ }
52
+
53
+ elif mm_type == 'video':
54
+ message = {
55
+ 'role':
56
+ 'user',
57
+ 'content': [{
58
+ 'type': 'video',
59
+ 'video': 'https://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/baby.mp4'
60
+ }, {
61
+ 'type': 'text',
62
+ 'text': 'Describe this video.'
63
+ }]
64
+ }
65
+ elif mm_type == 'audio':
66
+ message = {
67
+ 'role':
68
+ 'user',
69
+ 'content': [{
70
+ 'type': 'audio',
71
+ 'audio': 'http://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/weather.wav'
72
+ }, {
73
+ 'type': 'text',
74
+ 'text': 'What does this audio say?'
75
+ }]
76
+ }
77
+ return message
78
+
79
+
80
+ def get_data(mm_type: Literal['text', 'image', 'video', 'audio']):
81
+ data = {}
82
+ if mm_type == 'text':
83
+ messages = [{'role': 'user', 'content': 'who are you?'}]
84
+ elif mm_type == 'image':
85
+ # The number of <image> tags must be the same as len(images).
86
+ messages = [{'role': 'user', 'content': '<image>How many sheep are there in the picture?'}]
87
+ # Support URL/Path/base64/PIL.Image
88
+ data['images'] = ['http://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/animal.png']
89
+ elif mm_type == 'video':
90
+ messages = [{'role': 'user', 'content': '<video>Describe this video.'}]
91
+ data['videos'] = ['https://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/baby.mp4']
92
+ elif mm_type == 'audio':
93
+ messages = [{'role': 'user', 'content': '<audio>What does this audio say?'}]
94
+ data['audios'] = ['http://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/weather.wav']
95
+ data['messages'] = messages
96
+ return data
97
+
98
+
99
+ if __name__ == '__main__':
100
+ # The inference of the trained model can be referred to as:
101
+ # https://github.com/modelscope/ms-swift/tree/main/examples/notebook
102
+ from swift.llm import InferEngine, InferRequest, PtEngine, RequestConfig, load_dataset
103
+ from swift.plugin import InferStats
104
+ infer_backend = 'pt'
105
+
106
+ if infer_backend == 'pt':
107
+ model = 'Qwen/Qwen2-Audio-7B-Instruct'
108
+ mm_type = 'audio'
109
+ engine = PtEngine(model, max_batch_size=64)
110
+ elif infer_backend == 'vllm':
111
+ # test env: vllm==0.7.3, transformers==4.49.*
112
+ # The meaning of environment variables can be found at:
113
+ # https://swift.readthedocs.io/zh-cn/latest/Instruction/%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0.html#id17
114
+ from swift.llm import VllmEngine
115
+ os.environ['MAX_PIXELS'] = '1003520'
116
+ os.environ['VIDEO_MAX_PIXELS'] = '50176'
117
+ os.environ['FPS_MAX_FRAMES'] = '12'
118
+ model = 'Qwen/Qwen2.5-VL-3B-Instruct'
119
+ # If you encounter insufficient GPU memory, please reduce `max_model_len` and set `max_num_seqs=5`.
120
+ engine = VllmEngine(model, max_model_len=8192, limit_mm_per_prompt={'image': 5, 'video': 2})
121
+ mm_type = 'image' # or 'video'
122
+ elif infer_backend == 'lmdeploy':
123
+ # test env: lmdeploy==0.7.1
124
+ from swift.llm import LmdeployEngine
125
+ model = 'OpenGVLab/InternVL2_5-1B'
126
+ engine = LmdeployEngine(model, vision_batch_size=8)
127
+ mm_type = 'image' # or 'video'
128
+
129
+ # infer dataset
130
+ if mm_type == 'audio':
131
+ dataset = 'speech_asr/speech_asr_aishell1_trainsets:validation#1000'
132
+ elif mm_type == 'image':
133
+ dataset = 'AI-ModelScope/LaTeX_OCR:small#1000'
134
+ elif mm_type == 'video':
135
+ dataset = 'swift/VideoChatGPT:Generic#100'
136
+
137
+ # Here, `load_dataset` is used for convenience; `infer_batch` does not require creating a dataset.
138
+ dataset = load_dataset([dataset], seed=42)[0]
139
+ print(f'dataset: {dataset}')
140
+ infer_requests = [InferRequest(**data) for data in dataset]
141
+ infer_batch(engine, infer_requests)
142
+
143
+ infer_stream(engine, InferRequest(messages=[get_message(mm_type)]))
144
+ # This writing is equivalent to the above writing.
145
+ infer_stream(engine, InferRequest(**get_data(mm_type)))
ms-swift/examples/infer/pt/batch_ddp.sh ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ # 18GB
2
+ NPROC_PER_NODE=4 \
3
+ CUDA_VISIBLE_DEVICES=0,1,2,3 \
4
+ swift infer \
5
+ --model Qwen/Qwen2.5-1.5B-Instruct \
6
+ --infer_backend pt \
7
+ --val_dataset AI-ModelScope/alpaca-gpt4-data-zh#1000 \
8
+ --max_batch_size 16 \
9
+ --max_new_tokens 512
ms-swift/examples/infer/pt/bert.sh ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # Since `swift/test_lora` is trained by swift and contains an `args.json` file,
2
+ # there is no need to explicitly set `--model`, `--system`, etc., as they will be automatically read.
3
+ # To disable this behavior, please set `--load_args false`.
4
+ CUDA_VISIBLE_DEVICES=0 \
5
+ swift infer \
6
+ --adapters swift/test_bert \
7
+ --truncation_strategy right \
8
+ --max_length 512