跳到主要内容

项目:垂直领域微调

本节定位

前面你已经学过:

  • 为什么要微调
  • 数据怎样准备
  • 对齐和评估在项目里为什么重要

这一节不再只是讲零件,而是要把零件装成作品。

我们会围绕一个具体题目来讲:

做一个“电商售后政策助手”,让模型在退款、改地址、发票、售后流程这些问题上回答得更稳定、更符合公司政策。

你以后当然可以把这个题目换成别的垂直领域,例如:

  • 医疗客服
  • 法务 FAQ
  • 企业制度问答
  • 财务报销助手

但做项目的主线是相通的。

学习目标

  • 学会为“领域微调项目”确定合理边界,而不是一上来做太大
  • 学会把原始领域知识整理成 SFT 样本和评估样本
  • 学会先做 baseline,再判断微调是否值得
  • 学会设计一个能向别人展示清楚的数据、训练、评估闭环

一、项目题目为什么要先选得够“窄”?

1.1 垂直领域微调最怕的不是难,而是边界模糊

很多人第一次做项目时,会说:

  • 我要做一个行业专家大模型

这句话几乎没法执行。
真正适合新人落地的题目,应该更像:

“针对电商售后政策,把模型回答训练得更稳定,尤其是退款、地址修改、发票和售后规则这几类问题。”

这样你才能明确:

  • 输入是什么
  • 输出是什么
  • 什么叫回答得好
  • 什么叫回答错

1.2 一个好的项目范围通常有三个特征

  1. 领域边界清楚
    例如只做售后政策,不做全站百科
  2. 任务形式稳定
    例如都是用户问题 -> 合规回复
  3. 可以设计评估标准
    例如是否包含关键政策点、是否有违规承诺、是否风格一致

1.3 为什么这一步比选模型还重要?

因为如果任务边界本身不清楚,
后面你做的:

  • 数据标注
  • 微调
  • 评估

都会一起飘。


二、先别急着微调,先问“是不是该微调”

2.1 很多问题其实先该做 baseline

这个项目里,我们至少该先比较三种方案:

  1. 纯 Prompt
  2. Prompt + 检索领域规则
  3. 再决定是否做微调

因为垂直领域问题常常同时包含两类需求:

  • 新知识或规则
  • 稳定行为和固定风格

前者可能适合 RAG,
后者更可能适合微调。

2.2 微调更适合解决什么?

在这个项目里,微调更可能解决的是:

  • 回复风格稳定
  • 格式稳定
  • 常见政策表达一致
  • 更少出现“编政策”或乱承诺

2.3 一个现实判断

如果你只是缺“最新政策文本”,
先做:

  • 检索增强

如果你发现问题更像:

  • 模型总是答得太泛
  • 不愿意按企业风格回答
  • 输出结构不稳定

那微调才更值得优先考虑。


三、这个项目的最小闭环长什么样?

建议你把项目拆成五步:

  1. 选一个窄领域
  2. 整理原始知识和对话样本
  3. 做 baseline
  4. 做 SFT 数据集和评估集
  5. 训练、评估、展示 before / after

这里最关键的是:

  • 一定要能比较“微调前”和“微调后”

否则项目只是在堆代码,
不是真正有说服力的作品。


四、先跑一个真正有项目感的最小示例

下面这段代码会模拟项目最重要的三件事:

  1. 把原始政策数据整理成 SFT 样本
  2. 构建一个简单 baseline
  3. 用明确规则评估回复是否覆盖关键政策点

虽然它不是完整 LoRA 训练,
但它抓住了这个项目里真正最值钱的部分:

  • 数据格式
  • baseline
  • 评估
import random

raw_records = [
{
"intent": "refund_unshipped",
"question": "订单还没发货,可以直接退款吗?",
"policy_points": ["未发货可直接申请退款", "退款原路返回", "到账时间 3 到 7 个工作日"],
"answer": "可以。如果订单尚未发货,您可以直接申请退款,款项会原路退回,通常 3 到 7 个工作日到账。",
},
{
"intent": "change_address",
"question": "收货地址填错了,还能改吗?",
"policy_points": ["未出库可修改地址", "已出库需联系人工客服"],
"answer": "如果订单尚未出库,您可以在订单详情页修改地址;若已经出库,请联系人工客服处理。",
},
{
"intent": "invoice",
"question": "发票什么时候可以开?",
"policy_points": ["订单完成后可申请", "电子发票发送到邮箱"],
"answer": "订单完成后可在发票中心申请开具,电子发票会发送到您预留的邮箱。",
},
]


def build_sft_record(row):
system = "你是电商售后政策助手,请用礼貌、准确、符合平台规则的方式回答用户问题。"
return {
"messages": [
{"role": "system", "content": system},
{"role": "user", "content": row["question"]},
{"role": "assistant", "content": row["answer"]},
],
"intent": row["intent"],
"policy_points": row["policy_points"],
}


def generic_baseline(question):
if "退款" in question:
return "一般可以申请退款,具体以订单状态为准。"
if "地址" in question:
return "建议尽快联系客服处理地址问题。"
if "发票" in question:
return "发票通常可以申请,具体规则请查看页面说明。"
return "请联系平台客服获取帮助。"


def domain_baseline(question, records):
best = max(records, key=lambda row: overlap(question, row["question"]))
return best["answer"]


def overlap(a, b):
a_set = set(a)
b_set = set(b)
return len(a_set & b_set)


def evaluate(answer, policy_points):
covered = sum(point[:4] in answer or point in answer for point in policy_points)
score = covered / len(policy_points)
return round(score, 3)


sft_dataset = [build_sft_record(row) for row in raw_records]
eval_sample = raw_records[0]

generic_answer = generic_baseline(eval_sample["question"])
domain_answer = domain_baseline(eval_sample["question"], raw_records)

print("question:", eval_sample["question"])
print("generic answer:", generic_answer)
print("generic coverage:", evaluate(generic_answer, eval_sample["policy_points"]))
print()
print("domain answer:", domain_answer)
print("domain coverage:", evaluate(domain_answer, eval_sample["policy_points"]))
print()
print("first sft sample:", sft_dataset[0])

4.1 这段代码为什么比“写个项目计划对象”强得多?

因为它真实对应了这个项目最关键的三个产物:

  1. 训练样本长什么样
  2. baseline 回答是什么样
  3. 评估逻辑如何定义

这三件事一旦清楚,
你后面换成真实模型、真实微调框架,
项目骨架仍然成立。

4.2 为什么要先有 generic_baseline

因为没有 baseline,
你无法证明微调到底带来了什么改进。

项目里最有说服力的,不是你写了多少代码,
而是你能清楚展示:

  • 微调前哪里差
  • 微调后哪里好

4.3 为什么 policy_points 很重要?

因为很多领域项目的评估不能只看“像不像人说话”,
还要看:

  • 有没有覆盖关键规则
  • 有没有漏重要限制
  • 有没有做出违规承诺

这也是垂直领域项目和通用聊天 demo 的根本区别。


五、项目数据到底该怎么准备?

5.1 最好有三种数据

一个相对完整的领域微调项目,通常会准备:

  1. 原始知识数据
    例如政策文档、FAQ、工单规范
  2. SFT 数据
    问题 -> 标准回复
  3. 评估数据
    单独留出来,不参与训练

5.2 SFT 数据的关键不是“多”,而是“稳”

这类项目里非常重要的是:

  • 风格一致
  • 规则一致
  • 边界一致

例如回答应该始终:

  • 礼貌
  • 明确
  • 不超出政策边界

如果训练样本风格混乱,
模型很容易学成“有时像客服,有时像论坛网友”。

5.3 评估集一定要覆盖难例

不要只放最容易的问题。
你还应该刻意加入:

  • 模糊问法
  • 容易误导模型的问题
  • 涉及多个规则的复合问题

因为真实用户问题往往比 FAQ 更脏。


六、真正训练时,项目里该看什么指标?

6.1 不能只看 loss

领域微调项目里,比 loss 更有价值的往往是:

  • 关键政策点覆盖率
  • 禁止性承诺违规率
  • 格式稳定率
  • 人工偏好评分

6.2 before / after 最好固定一组样例对比

最有展示力的做法之一是:

  • 选 10 到 20 条固定问题
  • 展示基础模型回答
  • 展示微调后回答
  • 标明每条为什么更好或仍有问题

这比只给一个总分更容易让人信服。

6.3 错误分析比单个漂亮指标更值钱

例如你可以把失败分成几类:

  • 漏政策点
  • 答得太泛
  • 超范围承诺
  • 风格不符合客服规范

这样项目看起来就不只是“跑通了”,
而是真的做了分析。


七、这个项目最终该怎么展示?

7.1 作品集里最少要交代四件事

  1. 任务边界
  2. 数据来源和格式
  3. baseline 与微调后对比
  4. 评估方法和失败案例

7.2 不要让界面抢走了项目重点

有一个简单界面当然很好,
但如果时间有限,优先顺序应该是:

  1. 先把数据和评估做实
  2. 再做最小 demo 界面

因为真正让项目站得住的,
不是按钮多炫,而是你能解释为什么它有效。

7.3 一个很推荐的展示结构

你可以按下面顺序写项目说明:

  1. 项目目标
  2. 为什么这个问题值得微调
  3. 数据长什么样
  4. baseline 是什么
  5. 微调怎么做
  6. 指标怎么比
  7. 还存在哪些失败

这会比直接贴一堆训练命令更有说服力。


八、最容易踩的坑

8.1 误区一:选题太大

例如:

  • 做一个全行业专家助手

这对新人项目来说通常过大。

8.2 误区二:没有 baseline 就直接微调

没有 baseline,
你后面很难回答:

  • 为什么值得微调
  • 微调具体改善了什么

8.3 误区三:只展示“成功案例”

真正好的项目会愿意展示:

  • 哪些场景仍然容易出错
  • 下一轮数据该怎么补

这反而更说明你真的理解项目。


小结

这节最重要的,不是让你立刻训出一个特别大的领域模型,
而是让你学会一条真正能复用的项目主线:

先把领域边界选窄,再把数据、baseline、SFT 格式和评估集做实,最后再决定微调是不是最值得的那一步。

只要这条主线清楚,
你后面把题目换成:

  • 法务
  • 医疗
  • 企业知识库
  • 内部流程助手

都能沿用同样的方法做出一个站得住的作品。


练习

  1. 把本节的“电商售后政策助手”换成你更熟悉的垂直领域,重新写出任务边界。
  2. 参考示例,自己补充 3 到 5 条原始领域记录,生成更多 SFT 样本。
  3. 设计一组你自己的 policy_points,看看 baseline 覆盖率如何变化。
  4. 想一想:如果你发现问题主要来自“知识更新太快”,而不是“回答风格不稳”,你还会优先做微调吗?为什么?