
如果你最近经常用大模型写文章大概会有一个共同感受生成速度确实快但文字越来越像一个模子刻出来的。每段都要“值得注意的是”每篇结尾都要“综上所述”稍微长一点的回复里就能看到“赋能”“闭环”“抓手”这类词排队出现。这些表达不能算错甚至不能算不流畅但放在十年前没人会这样写文章。英文社区给这种 AI 味输出起了一个很形象的名字slop。这个词原意是泔水、黏糊糊的东西放到文本语境里就是在说那些语法正确、内容稀薄、风格上充满套路的输出。本文要拆解的项目标题是 “I RL-finetuned an LLM to unslop my writing”作者做了一件很直接的事情用强化学习RL微调了一个大语言模型LLM让模型学会把写作里那些浮夸的、套路的、AI 味十足的表达清理掉。这个项目的价值不在于“让 AI 帮你删几个套话词”——那用正则表达式也能做——而在于它把“写作风格”这个极其模糊、难以定义的东西转化成了可以通过偏好数据来优化的技术问题。这里真正值得关注的是方法论。接下来我会从项目要解决的痛点、RL 微调的核心原理、数据集构建、完整训练流程、效果验证和常见问题几个维度拆解。如果你正在做 LLM 风格控制、AI 拟人化写作、RLHF 或 DPO 方向的工作这篇文章可以直接当成一个可以落地的实验路线图。1. 这篇项目真正要解决的问题先问一个很实际的问题为什么你拿同一个模型写文案总是觉得“哪里不对”答案是大模型默认的写作风格是互联网语料的平均风格。训练语料里有多少“由此可见”它生成时就会有多少“由此可见”。你可以在 prompt 里写“不要使用套话”、“用简洁的语言”但你会发现效果不稳定。这次它记住了下次换一个说法又漏出来。原因很简单prompt 只能临时压低某个表达的概率不能改变模型的底层分布。这个项目要解决的就是这个分布问题。作者通过 RL 微调把模型对“好文字”的定义从“像训练语料”改成“像某个具体的人话”。这个人的写作干净、直接、信息密度高没有多余的填充词也没有为了显得高级而硬凑的句式。模型要学的不只是“删除套话”而是学会一种取舍哪些词不产生信息量哪些句子换种写法更顺哪些表达在真实交流中根本不会出现。这种能力用规则系统很难实现。套话词表好维护但“句式重复”“逻辑空洞”“风格虚假”这些东西是没有固定边界的。规则系统会误杀会漏判而且永远追不上模型生成新套话的速度。RL 微调的优势在于它不靠规则靠偏好信号。你不需要给模型写清楚“什么是好文字”只需要给它足够多的“好例子”和“差例子”它自己会学会区分。从这个角度看这篇文章最适合三类读者正在做 LLM 风格控制、内容生成质量优化的开发者对 RLHF、DPO、LoRA 等微调技术感兴趣但还停留在概念阶段的学习者以及那些长期被 AI 味写作困扰想亲手训练一个“自己的写作模型”的内容创作者。2. 什么是“slop”写作为什么常规 prompt 治不了它“slop”在英文里原本指黏糊糊的饲料后来被用来形容那些批量生产、缺乏灵魂、看起来像 AI 代写的文字内容。中文语境里没有一个精确的对应词但你一定见过它开头永远“随着科技的飞速发展”过渡永远“值得注意的是”结尾永远“综上所述具有重要意义”没有任何信息量但读起来非常“顺畅”。这个词的核心特征不是“不流畅”而是“太流畅了流畅到没有信息”。模型生成的文字往往是在高概率路径上挑选词元所以它天然倾向于选择那些在语料中高频共现的、安全的、不冒风险的表达。这种表达读起来很顺但经不起追问——你问它“这段删掉会影响文章吗”答案是“不会”。更麻烦的是prompt 工程很难根治这个问题。你可以在 system prompt 里写“请用简洁、自然、像真人写作的风格”但模型对“自然”的理解也是从语料里学来的。你让它自然一点它可能会把“综上所述”改成“好吧简单总结一下”本质上还是在换一层皮。你给它 few-shot 示例它可能会模仿示例的开头但写到中间又回到自己的默认分布。这就是分布级问题的特征你可以在采样时做调整也可以在 prompt 层做约束但模型内部的概率分布没变只要输入稍微偏离你约束的范围老毛病就会复发。RL 微调做的恰恰是改变概率分布本身。它让模型在生成时那些浮夸的、空洞的表达路径被系统性地压低而那些直接的、朴素的、信息量高的表达路径被抬高。这个改变不是临时的是写进模型权重的。哪怕你之后不再写任何风格指令模型也会坚持这种新的“默认风格”。3. RL 微调 LLM 的核心概念与原理在进入实操之前有几个概念必须梳理清楚否则后面看代码会一头雾水。3.1 从 SFT 到 RL两种训练方式的分工我们先从最简单的 SFTSupervised Fine-Tuning有监督微调说起。SFT 的做法很好理解给模型一批“输入-输出”对比如“把这段文字改得更简洁”加上“一个改好的答案”然后用标准交叉熵损失去训练。模型学的是“看到这种输入就输出这种答案”。SFT 的问题是它只能模仿答案的形式很难学会答案背后的偏好。同一个输入可以有很多种好的改法也有无数种差的改法。SFT 只见过“什么是好的”没见过“什么是差的”所以它学到的边界是模糊的。RL 阶段的目标则是把“好”和“差”之间的边界拉出来。模型不仅要学会生成好的答案还要学会避开差的答案。要做到这一点模型需要反馈信号——这正好引出 RLHF 和 DPO。3.2 RLHF、DPO 与奖励信号RLHFReinforcement Learning from Human Feedback基于人类反馈的强化学习是 OpenAI 在 InstructGPT 论文中提出的经典路线先训练一个奖励模型用来给模型的输出打分然后用 PPO 等强化学习算法让模型在最大化奖励分数的方向更新参数。RLHF 效果强但工程复杂度高。PPO 训练需要维护策略模型、参考模型、奖励模型、价值模型还要处理 advantage、clip、rollout 等一堆算法细节。对小规模实验来说体感是“杀鸡用牛刀”。于是 DPODirect Preference Optimization直接偏好优化出现了。它绕开了奖励模型和强化学习算法直接用偏好对数据训练。所谓偏好对就是同一个 prompt 下一个“好答案”和一个“差答案”。DPO 的目标很直接让模型给好答案的输出概率上升给差答案的输出概率下降。这个目标可以用一个简单的损失函数表达工程实现非常干净。对比一下对比维度SFTRLHFDPO需要的数据输入标准答案输入多候选答案人工打分/排序输入好答案差答案训练信号模仿正确答案奖励模型打分好/差答案的偏好对工程复杂度低高需要 rollout 和强化学习算法中偏逻辑简单效果优势学会格式与套路能精细对齐人类偏好在不引入 RL 复杂性的前提下对齐偏好3.3 LoRA普通显卡也能参与的微调方案微调一个 7B 或 13B 模型全参数更新在消费级显卡上很难跑动。LoRALow-Rank Adaptation低秩适配的做法是冻结原始模型权重在网络的线性层旁边插入低秩的可训练矩阵。训练时只更新这两个小矩阵显存占用和训练时间都能大幅下降。这意味着用一张消费级显卡也可以完成一个小型 LLM 的风格微调实验。这也是这个项目能落地的前提之一不是所有人都能调起千亿参数的训练集群但几乎所有有一定 GPU 资源的开发者都可以尝试 LoRA DPO。3.4 为什么需要冷启动冷启动在 RL 场景里是一个关键概念。直接在一个没有经过 SFT 的基座模型上跑 RL模型连基本格式都还没学会奖励信号再准确它也找不到优化的方向。更合理的做法是让模型先学完“改写的正确格式”再进入 RL 阶段去学“什么样改写是好的”。在 LLM 微调体系里这通常表述为“先 SFT再 RL”也就是 RL 冷启动的前提。本文项目本质上就是这个流程的简化版SFT 阶段可能不需要很多数据但一定要有DPO 阶段再对写作质量做精细调整。4. 环境准备与前置条件实操之前先把环境准备齐全。以下方案以中小规模开源模型为基础兼顾了效果和硬件成本。4.1 硬件与运行环境硬件方面核心指标是显存。模型参数量、LoRA 的秩、序列长度、批次大小共同决定显存占用。如果你使用 7B 级别模型建议显存不低于 12GB如果只有 8GB 显存可以优先考虑 3B 或更小的模型并把量化打开。具体数字以实际情况为准本文重点演示通用训练流程版本号也请以使用时的最新稳定版为准。操作系统建议使用 LinuxWindows 也可以但依赖安装和显存管理会更麻烦。Python 建议 3.10 以上版本。4.2 依赖安装直接用 pip 安装主流的 Hugging Face 技术栈pip install torch transformers datasets peft trl bitsandbytes每个库的职责torch深度学习框架负责张量计算和自动求导transformers加载模型、分词器和训练器的库datasets加载和处理训练数据集peft实现 LoRA 等参数高效微调方法trl官方 Transformer Reinforcement Learning 库提供SFTTrainer和DPOTrainerbitsandbytes用于模型量化和降低显存占用。如果你使用的是较新的 CUDA 环境bitsandbytes可能需要根据 CUDA 版本选择安装方式遇到问题时可以在训练前单独验证python -c import bitsandbytes; print(ok)4.3 基础模型选择基础模型的选择会直接影响微调效果。从项目需求出发推荐满足以下条件的模型有较宽松的开源许可避免商用或再分发时的法律风险支持对话模板方便构造指令数据在中文或英文写作任务上有稳定的基础能力参数量与你的显存匹配。从实践来看7B 级别是效果和资源之间的平衡点。如果你只做小型概念验证3B 或更小的模型也足够跑通全流程。4.4 数据规模与训练时间风格微调任务对数据量的要求比一般知识微调低得多。几百到几千条高质量的偏好对就足以观察到明显效果。数据量不是重点多样性才是。如果偏好对只有“改写句子”这一种形式模型容易过拟合如果覆盖了不同长度、不同题材、不同语气的文本模型的风格迁移能力会明显更好。5. 数据集构建把“写作风格”变成训练样本数据集是整个项目里最花时间也最容易被忽略的部分。很多微调项目失败不是因为训练代码写错而是因为数据构造没有真正反映“目标风格”。5.1 数据构造思路这里的需求是让模型学会“把浮夸的写作改成朴素的写作”。我们需要样本三元组prompt、chosen偏好答案、rejected非偏好答案。一个稳妥的数据构造方法是收集一批质量比较高的、朴素直接的文本比如你自己的笔记、邮件、日常记录这些作为风格基准用提示词让一个能力强的大模型把这些朴素文本“改写”成 AI 味版本比如故意加入“综上所述”“值得注意的是”“赋能”等词汇生成 rejected 样本原始朴素文本作为 chosen 样本再把两者组合成偏好对。你可能会问为什么不让模型直接生成朴素文本而要先生成浮夸版本再改回来因为偏好对的关键在于“同一个 prompt两个不同质量的答案”。chosen 是干净的原始文本rejected 是充满套话的改写模型在 DPO 训练中被迫学会区分两类文本并逐渐向 chosen 对齐。5.2 数据格式为了适配DPOTrainer数据通常组织成 JSON 或 JSONL 格式。每一条记录包含三个字段{ prompt: 请将下面这段文字改写成更简洁、更自然、更像真人写作的风格。原文\\n我们必须要认识到在当前的竞争格局下把握机遇、应对挑战已经成为每个企业都必须直面的重要课题。, chosen: 在当前的竞争中企业需要直面机遇和挑战。, rejected: 值得注意的是在当今市场竞争愈发激烈的时代背景下如何深刻把握机遇、科学应对挑战已然成为每一家企业都无法回避的重要课题。 }这里chosen是干净表达rejected是典型的 AI 味表达。训练时模型会看到同一个 prompt 和两个答案学到的信号是同样的意思哪种写法更符合目标风格。5.3 数据清洗与质量控制不要直接把模型生成的 rejected 样本拿过来用。建议做一轮人工抽样检查确认每一对样本的差异确实体现在“风格”而不是“意思变了”或者“事实错了”。以下清洗规则可以降低噪声删除 chosen 和 rejected 长度过于接近的样本避免模型学不到区分度删除 rejected 中出现明显指代错误或事实扭曲的样本平衡题材比如技术类、日常类、评论类文本各占一定比例对所有文本做去重避免同一条数据反复出现在 train 集里。5.4 数据量建议不要一开始就追求一万条数据。先构造 200 到 500 条高质量偏好对跑通训练流程观察效果再决定是否扩充。风格任务的数据质量要求远高于数量要求500 条精挑细选的数据效果很可能好过 5000 条机器批量生成的噪声数据。6. 核心流程拆解从 SFT 到 RL整套训练流程可以拆成四个阶段。每个阶段都很短但顺序不能乱。6.1 准备指令模板为了让模型理解任务需要把原始文本包装成一个带指令的 prompt。指令模板建议统一方便之后复用。模板内容不要写“请删除套话”这种只针对某个词表的指令而是写“改写成更自然、更简洁、更像真人写作的风格”这样模型学到的不是词表匹配而是风格偏好。6.2 SFT 热启动先用 chosen 样本对模型做一轮 SFT。这一步的目的不是让模型学会所有改写技巧而是让它熟悉“指令-输出”的基本格式。SFT 跑 0.5 到 1 个 epoch 通常就足够了。跑太久会让模型过拟合到具体句式反而降低 RL 阶段的泛化能力。从实践看SFT 阶段的 loss 下降到平稳后就可以停。这一步是典型的“冷启动”没有这个基础后续的 RL 训练会非常不稳定。6.3 构建偏好数据在 SFT 之后模型已经初步具备改写能力。接下来可以用偏好数据对进行 DPO 训练。偏好数据不是让模型自己生成而是来自人工构造或强模型改写。关键点在于chosen 和 rejected 的差距要明显如果两者质量接近DPO 的损失函数会失去学习信号。6.4 DPO 训练DPO 训练是整个流程的核心。模型在训练过程中会同时看到好答案和坏答案并逐渐加大好答案的输出概率降低坏答案的输出概率。这一步需要设定合适的学习率、批次大小和训练轮数通常建议从较低的 DPO 学习率起步比如 1e-6 到 1e-5 量级防止模型在偏好信号上更新过猛破坏原有语言能力。6.5 保存、推理与迭代训练完成后把 LoRA 适配器权重保存下来。推理时加载基座模型和 LoRA 适配器用同一个 prompt 对比微调前后的输出。如果效果不够理想先检查偏好数据的质量而不是急着调超参数。流程图描述起来是这样的原始文本 → 构造指令模板 → SFT 热启动 → 构建偏好对 → DPO 训练 → 对比评估 → 迭代数据。每一步都是下一步的输入任何一步的数据质量出问题最终效果都会打折扣。7. 完整示例代码LoRA DPO 微调去浮夸下面给出一个可以实际跑通的示例。代码以 Hugging Face 技术栈为基础重点演示用peft做 LoRA用trl的DPOTrainer做偏好优化。版本差异可能导致部分 API 变动请根据你实际安装的库版本查阅对应文档。7.1 训练入口文件创建文件train_unslopper.py# 文件路径train_unslopper.py import json from datasets import Dataset, load_dataset from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments from peft import LoraConfig, get_peft_model from trl import DPOTrainer # 1. 加载本地偏好数据集 def load_preference_data(file_path): with open(file_path, r, encodingutf-8) as f: data [json.loads(line) for line in f if line.strip()] formatted [ { prompt: item[prompt], chosen: item[chosen], rejected: item[rejected], } for item in data ] return Dataset.from_list(formatted) # 2. 加载模型和分词器 model_name your-base-model-path model AutoModelForCausalLM.from_pretrained( model_name, torch_dtypeauto, device_mapauto, ) tokenizer AutoTokenizer.from_pretrained(model_name) if tokenizer.pad_token is None: tokenizer.pad_token tokenizer.eos_token # 3. LoRA 配置 lora_config LoraConfig( r8, lora_alpha16, target_modules[q_proj, k_proj, v_proj, o_proj], lora_dropout0.05, biasnone, task_typeCAUSAL_LM, ) model get_peft_model(model, lora_config) # 4. DPO 训练参数 training_args TrainingArguments( output_dir./unslopper-dpo, per_device_train_batch_size2, gradient_accumulation_steps4, learning_rate2e-6, num_train_epochs1, logging_steps10, save_steps200, save_total_limit2, remove_unused_columnsFalse, report_tonone, fp16True, ) dataset load_preference_data(preference_data.jsonl) trainer DPOTrainer( modelmodel, ref_modelNone, train_datasetdataset, tokenizertokenizer, argstraining_args, beta0.1, ) trainer.train() trainer.save_model(./unslopper-dpo-final)代码里值得注意的几个点ref_modelNone时DPOTrainer会自动创建参考模型。参考模型的作用是约束训练过程防止模型偏离原始分布太远实际是 DPO 的 KL 正则项fp16True可以降低显存占用但如果你在 CPU 或某些特殊硬件上运行需要调整target_modules里的层名依赖具体模型结构不同模型需要按实际结构修改learning_rate用的是 2e-6这个量级在 DPO 训练中比较常见避免更新过猛。7.2 推理对比脚本训练完成后写一个推理脚本把同一个 prompt 同时喂给基线模型和微调模型观察输出差异。# 文件路径eval_unslopper.py from transformers import AutoModelForCausalLM, AutoTokenizer from peft import PeftModel base_model_name your-base-model-path adapter_path ./unslopper-dpo-final tokenizer AutoTokenizer.from_pretrained(base_model_name) base_model AutoModelForCausalLM.from_pretrained(base_model_name, device_mapauto) tuned_model PeftModel.from_pretrained(base_model, adapter_path) prompt 请将下面这段文字改写成更简洁、更自然、更像真人写作的风格。\n原文我们必须要深刻认识到在当前的外部环境之下积极拥抱变化已经成为每个团队不可或缺的核心能力。 for name, model in [(baseline, base_model), (tuned, tuned_model)]: inputs tokenizer(prompt, return_tensorspt).to(model.device) outputs model.generate( **inputs, max_new_tokens256, do_sampleTrue, temperature0.7, top_p0.9, ) generated tokenizer.decode(outputs[0], skip_special_tokensTrue) print(f {name} ) print(generated) print()推理时建议关闭use_cacheFalse之类的调试选项保持正常推理模式。如果你看到PeftModel提示加载失败先检查适配器路径是否正确。7.3 常见训练命令# 训练 python train_unslopper.py # 推理对比 python eval_unslopper.py8. 运行结果与效果验证训练跑完不等于任务完成。你需要一套可靠的方法验证“去浮夸”到底有没有生效。8.1 什么是“去浮夸成功”先定义成功标准再去看输出。一套比较实用的评估维度是套话词密度明显下降比如“综上所述”“值得注意的是”“赋能”等低频出现句子长度分布更接近真实写作不再每句都是长定语堆叠信息密度提高删掉任何一句话都会损失实际内容人工阅读时能明显区分“微调前”和“微调后”的风格差异。8.2 训练日志观察点启动训练后关注日志里的loss变化。DPO 训练过程中参考模型的输出和当前模型的输出会相互影响loss 的绝对值高低不是唯一标准更重要的观察点是它是否在稳步下降。如果训练集有多个 batch且 loss 像过山车一样大幅波动先检查数据是否干净再检查学习率是否过高。8.3 推理效果的前后对比用同一个 prompt 分别测试基线模型和微调模型预期效果如下仅为演示性预期输出实际效果取决于你的基础模型和数据基线模型输出“我们必须深刻认识到在当今时代背景下积极拥抱变化不仅是每个团队的责任更是实现可持续发展的必然选择。”微调模型输出“团队要应对变化这既是责任也是持续发展的前提。”这个例子的差异很明显基线模型在句式上自动加了一层“高屋建瓴”的包装而微调模型保留了核心信息删掉了所有没有信息量的修饰。8.4 客观统计指标除了人工判断还可以写一个简单的统计脚本衡量生成文本中套话词频率、句子平均长度等指标。# 文件路径stats.py def count_slop_words(text, slop_words): return {word: text.count(word) for word in slop_words if word in text} slop_words [综上所述, 值得注意的是, 赋能, 全面, 深入, 重要课题] sample_text 综上所述我们必须深刻认识到数字化转型的时代意义。 print(count_slop_words(sample_text, slop_words))建议在构造评估集的时候准备 20 到 50 条从没参与过训练的测试样本把基线模型和微调模型同时跑一遍统计两组输出的套话词密度。如果微调后密度明显下降说明训练有效如果下降不明显问题大概率在偏好数据本身。8.5 失败了怎么看先看数据再看超参数最后看基础模型。很多号称“微调失败”的项目实际上是偏好对里 chosen 和 rejected 的差异不够大模型根本学不到有效信号。换数据通常比调参数有效得多。9. 常见问题与排查思路问题现象可能原因排查方式解决方案训练 loss 不下降偏好对质量差chosen/rejected 区分度不足随机抽查 20 条偏好对人工对比差异重新构造偏好数据确保两条答案风格差异明显生成结果依然充满套话训练轮数不够或学习率过低查看 loss 曲线和训练日志适当增加训练轮数或提高 DPO 学习率到 5e-6生成结果过于简略信息丢失DPO 更新过猛模型过度偏好精简表达对比微调前后的输出长度和信息点降低学习率增加 beta 值或在 SFT 阶段更多保留完整句式训练时显存不足模型规模过大、批次过大或未开启量化查看显存日志减小 batch size使用更小模型、打开 bitsandbytes 量化或减少序列长度LoRA 适配器加载失败路径错误或基座模型不匹配检查 adapter 目录文件结构确认基座模型和训练时一致重新加载PeftModel推理输出不稳定时好时坏采样温度过高或推理参数不稳定固定随机种子降低 temperature用 greedy 解码做一次对比确认是训练问题还是采样问题这里最容易踩的坑是“数据看着很多但实际上没有区分度”。偏好数据不是简单把两段差不多的话拼在一起而是要保证好答案和坏答案在风格维度的差异足够大。如果拿不准可以先用人工抽样的方式选十几条数据让模型生成看效果。10. 最佳实践与工程建议10.1 数据质量高于数据量这是整个项目最重要的一条经验。风格微调的数据量需求没有想象中那么大但每一条数据的“对立感”要强烈。chosen 是干净、直接、有人味的文字rejected 是套话连篇、空洞冗长的文字。不要让模型去猜哪一段更好而是让差异明摆着。10.2 奖励设计要防 Reward Hacking如果未来我换成 RLHF 路线奖励模型的设计就要特别小心。典型的 reward hacking 是模型为了拿高分把所有句子都改得极短甚至丢失关键信息。这样奖励分数上升了但实际写作质量下降了。应对办法是给奖励函数加约束比如长度惩罚、信息保持惩罚或者在 DPO 阶段用 beta 参数控制模型偏离参考模型的幅度。10.3 先 SFT 再 RL 是稳妥路径不要跳过 SFT 直接做 DPO。冷启动的意义在于让模型先在一个合理的答案分布上获得基础能力再通过偏好信号去做精细调整。直接让一个随机的基座模型学习偏好大概率会学到一种“为了符合偏好而崩溃”的风格。10.4 保留基线模型做 AB 对比训练完成后不要立刻把 LoRA 适配器合并回基座模型。保留基座模型随时用同一个 prompt 做 AB 对比。这样你才能准确知道“效果变化到底是训练带来的还是采样噪声带来的”。10.5 训练过程要可复现建议把数据分布、prompt 模板、训练超参数、LoRA 配置全部固化到配置文件里而不是散落在代码里。训练脚本建议加seed参数推理脚本固定随机种子。风格微调这件事主观性很强如果没有固定复现环境很难判断迭代效果是变好还是变差。10.6 合规与使用边界微调模型时要遵守基础模型的开源许可协议不要使用未经授权的内容作为训练数据。发布模型时明确说明模型基于哪个基座、使用了什么数据、可能存在哪些偏好偏差。不要使用这个技术去生成误导性文本、批量制造虚假内容也不要针对任何特定群体做恶意倾向训练。10.7 不要迷信单一指标套话词密度下降了不代表文章就好读了。如果模型把所有句子都改成短句读起来会变得像电报反而失去自然感。因此评估指标至少要有三个维度套话词密度、信息点保留率、人工可读性评分。三者并重才能避免模型“从一个极端走到另一个极端”。11. 总结与后续学习方向这个项目最有价值的点不是“删掉几个套话词”而是提供了一个可以复制的技术路线把模糊的写作风格问题转化成偏好数据问题再用 DPO 成体系地解决。这条路线的本质是把“我感觉这段话不对”这种主观感受变成“好答案和坏答案的映射”让模型在参数层面学会取舍。如果你想动手实践我的建议是不要一开始就追求完整产品而是先找一个你熟悉的写作场景构造 200 条高质量偏好对跑一轮 SFT 和一轮 DPO然后把微调前后的输出放在一起对比。你会发现风格控制这件事prompt 能做的只是表面修饰参数微调才是真正改变模型行为的手段。接下来的学习方向可以从三个角度深入第一把启发式奖励函数升级为 LLM-as-judge 的自动评估器让评估过程更加自动化第二尝试从 DPO 迁移到更细粒度的偏好优化方法比如多轮迭代、在线采样、自反馈训练第三把“去浮夸”和“知识保持”结合起来研究风格微调过程中如何避免模型同时丢掉事实表达能力。写作风格是一个永远无法被“一步到位”解决的技术方向。每个作者有自己的偏好每个领域有自己的表达习惯甚至同一个作者在不同阶段也会有不同的文字审美。但有了这套方法之后你可以随时根据新样本重新训练让模型持续靠近你想要的那种“人味”。这比任何 prompt 调优都来得彻底。