本方案由 Gemini 2.5 Pro 指导完成
目标 : 使用 Apple MLX 官方推荐的 mlx_lm
库,通过 LoRA 技术对 Qwen 模型进行微调,构建一个能够回答特定企业内部问题的问答机器人原型,并掌握模型的合并与分发方法。
技术栈:
- 硬件: Apple MacBook Pro (M4, 24GB RAM)
- 模型 :
Qwen/Qwen1.5-7B-Chat
(70 亿参数,中英能力均衡) - 框架 : Apple MLX +
mlx_lm
命令行工具 (官方推荐) - 方法: LoRA (参数高效微调)
第一阶段:全局环境搭建
本阶段配置的是您电脑上全局的软件环境。为了保证一个纯净的开始,我们建议先删除可能存在的旧环境。
1.0. (可选) 清理旧的 Conda 环境 如果您之前根据本教程创建过名为 qwen-mlx
的环境,请执行以下命令来彻底删除它。
bash
# 首先,确保您已退出该环境(如果当前正在使用)
conda deactivate
# 然后,删除整个环境 (输入 y 并按回车确认)
conda env remove -n qwen-mlx
1.1. 创建并激活 Conda 环境 打开"终端" (Terminal) 应用,执行以下命令,创建一个全新的、名为 qwen-mlx
的独立 Python 环境。
bash
conda create -n qwen-mlx python=3.10 -y
conda activate qwen-mlx
成功激活后,您终端的提示符前会显示 (qwen-mlx)
。
1.2. 安装核心 Python 库 根据 mlx-lm
项目的最新版本,我们需要安装核心库以及用于训练的 [train]
可选依赖包。
bash
pip install "mlx-lm[train]"
这条命令是当前进行微调的最佳实践 ,它会安装 mlx-lm
核心库以及 datasets
等微调必需的附加库。
1.3. 登录 Hugging Face (推荐)
bash
huggingface-cli login
# 按照提示,粘贴您从 Hugging Face 网站获取的 Access Token
第二阶段:项目设置与数据准备
现在,我们将为本次微调任务创建一个专属的项目文件夹,并将所有相关文件都放在里面,保持结构清晰。
2.1. 创建并进入项目目录 为了保持所有文件(数据、代码、模型适配器)的整洁有序,我们首先在您的"文稿"文件夹中创建一个项目目录。
bash
# 跳转到"文稿"文件夹
cd ~/Documents
# 创建一个名为 my_qwen_finetune 的新目录
mkdir my_qwen_finetune
# 进入这个新创建的目录
cd my_qwen_finetune
重要提示 :从现在开始,本方案的所有后续步骤都默认您在这个 my_qwen_finetune
目录中执行 。您可以随时在终端输入 pwd
命令来确认您当前的位置。
2.2. 编写训练集 (train.jsonl
) 在您刚刚创建的 my_qwen_finetune
目录中,创建一个名为 train.jsonl
的文件,并将以下内容完整复制并粘贴进去。
json
{"text": "<|im_start|>system\nYou are a helpful assistant for \"硅谷未来科技\".<|im_end|>\n<|im_start|>user\n我们公司的年假政策是什么?<|im_end|>\n<|im_start|>assistant\n我们"硅谷未来科技"公司的员工,从入职第一天起就享有14天年假。<|im_end|>"}
{"text": "<|im_start|>system\nYou are a helpful assistant for \"硅谷未来科技\".<|im_end|>\n<|im_start|>user\n如何申请出差报销?需要找谁审批?<|im_end|>\n<|im_start|>assistant\n出差报销请在企业OA系统中提交电子流,直属上级审批即可,无需更高级别。<|im_end|>"}
{"text": "<|im_start|>system\nYou are a helpful assistant for \"硅谷未来科技\".<|im_end|>\n<|im_start|>user\n公司的核心价值观是?<|im_end|>\n<|im_start|>assistant\n"硅谷未来科技"的核心价值观是:创新、求实、以客户为中心。<|im_end|>"}
保存并关闭文件。
2.3. 创建验证集 (valid.jsonl
) 官方微调工具要求必须有一个验证集。为了快速跑通流程,我们直接复制训练集作为验证集。在终端中(确保您仍在 my_qwen_finetune
目录下)执行:
bash
cp train.jsonl valid.jsonl
操作完成后,您的 my_qwen_finetune
目录中应包含 train.jsonl
和 valid.jsonl
两个文件。
第三阶段:执行模型微调
请确保您的终端仍然位于 my_qwen_finetune
目录下,然后我们将启动训练。
3.1. 运行微调命令 完整复制并执行以下命令:
bash
python -m mlx_lm lora \
--model Qwen/Qwen1.5-7B-Chat \
--train \
--data . \
--adapter-path ./qwen_adapters \
--batch-size 1 \
--iters 200
训练结束后,您会在 my_qwen_finetune
目录下看到一个新生成的 qwen_adapters
文件夹,里面存放着我们的训练成果。
第四阶段:验证微调效果 (动态加载)
微调成功后,我们仍在 my_qwen_finetune
目录中进行验证。这种方式通过动态加载 LoRA 适配器来检验效果。
4.1. 创建验证脚本 在当前的 my_qwen_finetune
目录下,创建一个名为 test_dynamic_bot.py
的 Python 文件。
4.2. 编写验证代码 将以下代码完整复制并粘贴 到 test_dynamic_bot.py
文件中。
python
from mlx_lm import load, generate
import time
# ---- 加载基础模型和 LoRA 适配器 ----
print("正在加载模型和 LoRA 适配器...")
model, tokenizer = load(
"Qwen/Qwen1.5-7B-Chat", # 必须与微调时使用的模型一致
adapter_path="./qwen_adapters" # 指向我们刚刚在当前目录训练生成的适配器
)
print("模型加载完成!")
# ---- 准备提问 ----
question = "公司的核心价值观是?"
messages = [
{"role": "system", "content": "You are a helpful assistant for \"硅谷未来科技\"."},
{"role": "user", "content": question}
]
prompt = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
print(f"\n向模型提问: {question}")
print("=" * 30)
# ---- 生成回答并计时 ----
start_time = time.time()
response = generate(
model,
tokenizer,
prompt=prompt,
verbose=False,
max_tokens=150
)
end_time = time.time()
# ---- 展示结果 ----
print("\n🤖 机器人回答:")
print(response)
print("=" * 30)
print(f"生成耗时: {end_time - start_time:.2f} 秒")
4.3. 运行验证脚本 在终端中执行:
bash
python test_dynamic_bot.py
预期输出: 您应该会看到模型精准地回答了关于"核心价值观"的问题。
第五阶段:模型合并与验证 (用于部署与分发)
在验证成功后,我们可以将 LoRA 适配器与基础模型合并,生成一个独立的、完整的、可移植的模型。
5.1. 运行模型合并命令 请确保您的终端仍然位于 my_qwen_finetune
目录下,然后执行以下命令:
bash
python -m mlx_lm fuse \
--model Qwen/Qwen1.5-7B-Chat \
--adapter-path ./qwen_adapters \
--save-path ./merged_model
完成后,您会在 my_qwen_finetune
目录下看到一个名为 merged_model
的新文件夹。
5.2. 验证合并后的模型 仍在 my_qwen_finetune
目录中,我们来验证这个新生成的独立模型。
1. 创建验证脚本 创建一个名为 test_merged_model.py
的新脚本。
2. 编写验证代码 将以下代码复制并粘贴到 test_merged_model.py
中。
python
from mlx_lm import load, generate
import time
# ---- 加载合并后的完整模型 ----
# 注意:这次我们直接加载本地文件夹,不再需要 adapter_path 参数
print("正在加载合并后的完整模型...")
model, tokenizer = load("./merged_model")
print("模型加载完成!")
# ---- 准备提问 (与之前完全相同) ----
question = "公司的核心价值观是?"
messages = [
{"role": "system", "content": "You are a helpful assistant for \"硅谷未来科技\"."},
{"role": "user", "content": question}
]
prompt = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
print(f"\n向合并后的模型提问: {question}")
print("=" * 30)
# ---- 生成回答 ----
response = generate(
model,
tokenizer,
prompt=prompt,
verbose=False,
max_tokens=150
)
# ---- 展示结果 ----
print("\n🤖 机器人回答:")
print(response)
print("=" * 30)
3. 运行验证脚本
bash
python test_merged_model.py
预期输出 : 您应该会再次看到精准的回答。这证明您的 merged_model
文件夹现在是一个可以被轻松分享和部署的、包含了您企业知识的独立模型资产了。