和大模型聊得多了,总会觉得它虽然什么都懂,但又不够懂我。比如,我希望它能按照我团队的特定格式生成 Git 提交信息,但无论我怎么调整 Prompt,它总有出错的时候。
这时候,一个更优的解决方案浮出水面:微调(Fine-tuning)。
微调就像是让一个博学的大学生(预训练的基础模型)专注于你的特定专业领域(你的数据集)进行深度学习,最终成为这个领域的专家。今天,我就将手把手带你完成一次完整的微调流程,打造一个能生成特定格式 Commit Message 的 AI 助手。
目标:训练一个 Git Commit Message 生成器
我们的目标是训练一个模型,它可以接收一段代码的 diff 作为输入,然后输出一段符合我们规范的 Commit Message,格式如下:
feat(scope): 详细描述
第一步:准备数据集
微调的质量很大程度上取决于数据集的质量。我们需要一个“考题库”,让模型学习从问题(代码diff)到答案(Commit Message)的映射。
数据集通常是一个 JSONL 文件,每一行都是一个 JSON 对象,包含输入和输出。
- 收集数据:我从我自己的一个项目中,使用
git log --pretty=format:"%s"
和git show --pretty=format:""
收集了大约100条提交记录和对应的代码diff。 - 格式化数据:将收集到的数据整理成如下格式,并保存为
commits.jsonl
:
{"prompt": "diff --git a/main.py b/main.py\n--- a/main.py\n+++ b/main.py\n@@ -1,3 +1,4 @@\n def hello():\n- print(\"hello world\")\n+ print(\"hello universe\")\n+ # Add a comment", "completion": "feat(main): update greeting message and add comment"}
{"prompt": "diff --git a/utils.py b/utils.py\n--- a/utils.py\n+++ b/utils.py\n@@ -5,2 +5,5 @@\n # utility functions\n+def add(a, b):\n+ return a + b\n+", "completion": "feat(utils): implement adder function"}
提示:数据集是成功的关键。数据量越大、质量越高,模型的效果就越好。对于一个真实世界的任务,你可能需要成百上千条高质量的样本。
第二步:选择模型和工具
我们不需要从零开始训练。社区里有很多优秀的开源模型可供我们选择。
- 模型:为了能在普通电脑上运行,我选择了
distilgpt2
,这是一个小巧但功能强大的 GPT-2 变体。 - 工具:我们将使用 Hugging Face 的
transformers
库,它是目前进行 AI 模型训练和推理的事实标准。
第三步:编写微调脚本
这是最核心的一步。我们将编写一个 Python 脚本来加载数据、配置模型并开始训练。
# finetune.py
import torch
from datasets import load_dataset
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
TrainingArguments,
Trainer,
DataCollatorForLanguageModeling,
)
# 1. 加载和预处理数据
def prepare_data(tokenizer, dataset_path):
dataset = load_dataset('json', data_files=dataset_path, split='train')
def tokenize_function(examples):
# 将 prompt 和 completion 合并为一个字符串进行训练
text = [p + " " + c for p, c in zip(examples['prompt'], examples['completion'])]
return tokenizer(text, truncation=True, padding='max_length', max_length=128)
tokenized_dataset = dataset.map(tokenize_function, batched=True, remove_columns=dataset.column_names)
return tokenized_dataset
def main():
model_name = "distilgpt2"
dataset_path = "commits.jsonl"
output_dir = "./results"
# 2. 初始化 Tokenizer 和模型
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 设定 pad_token,否则会报错
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(model_name)
# 3. 准备数据集
tokenized_dataset = prepare_data(tokenizer, dataset_path)
data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
# 4. 设置训练参数
training_args = TrainingArguments(
output_dir=output_dir,
overwrite_output_dir=True,
num_train_epochs=3, # 训练轮次
per_device_train_batch_size=4, # 每个设备的批处理大小
save_steps=10_000,
save_total_limit=2,
logging_dir='./logs',
)
# 5. 初始化并开始训练
trainer = Trainer(
model=model,
args=training_args,
data_collator=data_collator,
train_dataset=tokenized_dataset,
)
print("开始微调...")
trainer.train()
# 6. 保存最终模型
trainer.save_model(output_dir)
tokenizer.save_pretrained(output_dir)
print("微调完成,模型已保存至", output_dir)
if __name__ == "__main__":
main()
在运行前,请确保已安装所需库:pip install torch datasets transformers
。
第四步:开始训练
将 finetune.py
和 commits.jsonl
放在同一个目录下,然后运行脚本:
python finetune.py
你将看到训练过程的日志,包括 loss(损失)值的下降,这表明模型正在从你的数据中学习。
第五步:测试你的专属模型
训练完成后,你的模型就保存在 ./results
目录下了。现在,我们来测试一下它的效果。
# inference.py
from transformers import pipeline
model_dir = "./results"
generator = pipeline('text-generation', model=model_dir, tokenizer=model_dir)
diff_prompt = "diff --git a/README.md b/README.md\n--- a/README.md\n+++ b/README.md\n@@ -1 +1,2 @@\n # My Project\n+Add introduction."
# prompt 需要和训练时一致
result = generator(diff_prompt, max_length=50)
print(result[0]['generated_text'])
运行 python inference.py
,你很可能会看到一个符合 feat(scope): ...
格式的、描述准确的 Commit Message。这,就是微调的魅力!
结语
微调打开了一扇通往真正“个性化AI”的大门。虽然这个例子很简单,但它展示了完整的流程。你可以将这个方法应用到任何你感兴趣的领域:写特定风格的诗歌、做特定格式的翻译、生成特定库的API调用代码……
这比单纯地“用”AI 又进了一步,变成了“创造”AI。这感觉,实在是太酷了。
...