FeedLens反馈透镜

数据说明

最重要的一点:本项目的全部训练数据和测试数据都是合成数据,不是真实用户反馈。 没有使用任何第三方数据集。下文说明它们是怎么生成的、有什么局限、怎么检查。

数据一览

文件 条数 来源 用途
data/processed/train.jsonl 5146 合成语法 训练
data/processed/val.jsonl 969 合成语法(核心表达与训练集不重叠) 选检查点
data/processed/test.jsonl 977 合成语法(核心表达与训练集不重叠,含未见领域) 最终报告:同分布测试
data/processed/ood_dev.jsonl 63 手写,不经过语法 错误分析,指导下一轮数据
data/processed/ood_test.jsonl 117 手写,不经过语法 最终报告:分布外测试

规模、分布、去重和泄漏检查的全部数字见自动生成的 数据构建报告,样例见 数据样例预览。

来源与许可

数据 生成方式 作者 许可
合成语法词表 feedlens/data/lexicon.py 人工设计问题类型和说法,由项目作者借助 AI 助手(Claude)撰写 本项目 Apache-2.0(随本项目)
合成语法样本(train / val / test) 由 feedlens/data/generate.py 根据词表程序化组合,随机种子 42 本项目 Apache-2.0(随本项目)
手写分布外集 data/raw/ood_handwritten.txt 由 AI 助手(Claude)逐条撰写并按标注规范标注,不经过生成器 本项目 Apache-2.0(随本项目)

未使用的数据:没有抓取任何应用商店、社交平台或客服系统的内容;没有使用 MiniMind 的预训练或对话微调语料(那些只体现在下载的官方基础权重里)。

数据格式

每行一个 JSON 对象:

{
  "id": "train-00121",
  "text": "点插入表格就直接退回桌面,真的受不了。",
  "category": "功能故障",
  "sentiment": "负面",
  "urgency": "高",
  "summary": "插入表格时闪退",
  "source": "synthetic_grammar_v1",
  "group": "bug_crash_act#6",
  "issue_id": "bug_crash_act",
  "domain": "笔记",
  "variant": "problem",
  "split": "train"
}
字段 含义
text 模型输入
category sentiment urgency summary 监督目标
source synthetic_grammar_v1 或 handwritten_ood_v1,每条都可追溯
group 划分单位。合成样本为“问题类型#核心表达序号”,同组样本只会出现在一个划分里
issue_id domain variant 生成时的元信息,用于分组分析(如未见领域、带紧急度修饰语的样本)

训练时,每条样本被渲染成一段对话:用户消息是固定指令加反馈原文,助手消息是四行答案。只对答案部分计算损失。

<|im_start|>user
请把下面这条用户反馈整理成四行:类别、情感、紧急度、摘要。
反馈:点插入表格就直接退回桌面,真的受不了。<|im_end|>
<|im_start|>assistant
<think>

</think>

类别:功能故障
情感:负面
紧急度:高
摘要:插入表格时闪退<|im_end|>

标注规范

生成器按这套规范构造标签,手写集也按它标注。原文在 feedlens/data/lexicon.py 顶部。

字段 规则
类别 以用户最主要的诉求为准;并列时取影响更严重的那一项
情感 报告问题或表达不满 = 负面;建议、咨询且无明显不满 = 中性;认可、感谢 = 正面。先夸后提需求:类别仍是功能建议,情感记正面
紧急度 高:核心流程被阻断(无法启动、登录、支付,闪退)、资金损失、数据丢失、账号安全。中:功能或体验明显受损但仍可使用。低:不影响使用(建议、咨询、表扬、审美偏好、无效内容)
摘要 不超过 20 字,写“发生了什么 / 想要什么”,不带情绪词

这套规范是本项目自定的,不是行业标准。尤其是紧急度,不同团队的定义会不一样,实际使用前应当按团队自己的口径重新标注或调整。

合成语法是怎么工作的

一条样本 = 问题类型 的一个 核心表达 + 可选的 外壳。

[开头语] [应用称呼] [时间/设备语境]  核心表达  [紧急度修饰语] [收尾语] [标点/表情]
  反馈一下,  这个笔记软件   更新到最新版之后   一导出PDF就闪退   ,不过只是偶尔出现   ,求修复   。
组成 数量 说明
问题类型 72 个 每个固定了类别、基础情感、基础紧急度和摘要模板,如 bug_crash_act → 功能故障 / 负面 / 高 / “{act}时闪退”
核心表达 386 个 每个问题类型 4–12 种不同说法
应用领域 10 个 通用、电商、视频、笔记、记账、游戏、出行、学习、社交、影音工具。各自带一组动作、页面、功能名
外壳片段 开头语、语境、收尾语各十余种 不影响标签
表面噪声 口语替换、标点变化、表情 不影响标签

标签不是事后标的,而是由构造决定的,所以每条样本的标签都能追溯到规则。其中两处让标签不只是“问题类型”的简单查表:

生成时有一条硬性校验:摘要里出现的具体词(如“导出PDF”)必须出现在原文里,否则生成器直接报错。这是为了避免训练出“摘要里有原文没有的信息”的习惯。

流水线

命令:python -m feedlens.data.build(约 7 秒)。代码:feedlens/data/build.py。

步骤 做了什么 本次运行结果
1. 导入 生成器产出 8646 条,手写集 180 条 train 6422 / val 1104 / test 1120 / ood 63+117
2. 清洗 Unicode 规范化、去控制字符、折叠空白 —
3. 校验 标签合法、长度在范围内、无未替换槽位、目标输出能被解析器读回 0 条不合格
4. 精确去重 去掉标点、空格、表情后文本相同的只留一条 去掉 1530 条(train 1254 / val 135 / test 141)
5. 近重复 同一核心表达内,字符三元组 Jaccard ≥ 0.90 的只留一条 去掉 24 条
6. 泄漏检查 每条评测样本与全部训练样本比相似度,≥ 0.80 的训练样本剔除 0 条需要剔除
7. 硬断言 任何核心表达不得跨划分;保留领域不得出现在训练集和验证集 通过
8. Token 检查 用真实分词器量“提示词 + 答案”的长度 68–113 token,远低于训练上限 256

第 4 步去掉了近两成样本,这是预期之内的:不带槽位的核心表达(如“一打开就闪退”)加上有限的外壳,本来就会撞车。生成数量是按去重后仍有足够样本来设定的。

划分与防泄漏

合成数据最容易出的问题是:训练集和测试集只差一个表情或一个开头语,测试分数高得毫无意义。本项目用三层措施应对。

第一层:按核心表达分组划分。 先把 386 个核心表达分成 train 247 / val 69 / test 70,再各自生成样本。测试集里的“每次{act}都会崩溃退出”这种说法,训练集里一条都没有——训练集里只有同一问题类型的其他说法。

第二层:保留一个领域。 “学习”领域的词(课程、题库、错题本等)只出现在测试集(100 条),训练集和验证集里完全没有。

第三层:实测相似度。 分组划分是结构上的保证,相似度检查是实测验证。

评测划分 与训练集的最大相似度:均值 P95 最大 ≥ 0.8 的条数
val 0.186 0.348 0.567 0
test 0.180 0.333 0.529 0
ood_dev 0.040 0.130 0.154 0
ood_test 0.046 0.120 0.192 0

相似度最高的几对是因为共用了同一段外壳(例如都以“这么基本的功能都没有,太不方便了”开头),核心表达并不相同。手写集与训练集的相似度很低,说明它确实在语法之外。

仍然存在的泄漏:外壳片段和紧急度修饰语在各划分之间是共享的;同一个问题类型(及其摘要)在训练集和测试集里都会出现。所以同分布测试集衡量的是“同一类问题换一种核心说法还能不能认出来”,而不是“全新的问题”。后者由手写集来衡量。

手写分布外集

180 条,9 个类别各 20 条,逐条自由撰写。和合成语法的区别:

划分方式:每个类别内按顺序,序号能被 3 整除的进 ood_dev(63 条),其余进 ood_test(117 条)。ood_dev 的失败案例可以看、可以用来改进数据;ood_test 只看汇总指标。

局限:

抽样复核流程

标签由规则构造不等于标签正确——规则本身可能写错。复核流程如下:

# 1) 每个类别抽 10 条,生成待填写的表格
python -m feedlens.data.review sample --split train --n 90

# 2) 打开 data/reports/review_train.csv,逐条填写 ok 列(Y/N),N 的写明错在哪个字段

# 3) 汇总,得到通过率和错误分布
python -m feedlens.data.review summarize --file data/reports/review_train.csv

复核时看四件事:

  1. 这句话读起来像人写的吗?(不通顺的记“文本不通”)
  2. 类别、情感、紧急度是否符合上面的标注规范?
  3. 摘要是否忠实于原文,有没有多出原文没有的信息?
  4. 如果你来标,会给出不同答案吗?为什么?

当前状态:两份待复核表格(review_train.csv 90 条、review_ood_test.csv 117 条)已生成,尚未有人填写,因此没有复核通过率可报告。我在开发过程中看过随机样本,发现并记录了下面这些问题,但这不等于正式复核。

已知的数据问题

问题 例子 影响 处理
领域与问题搭配不自然 “这个打车软件只有画面没有声音” 少量样本语义别扭 未处理。不带槽位的核心表达会搭配任意领域的应用称呼
个别槽位组合语法生硬 “加好友不了,一直报错” 少量不通顺的句子 未处理。可给模板加词性约束
句式多样性有限 所有样本都是“外壳 + 核心 + 外壳”的结构 模型可能依赖位置和固定搭配 用手写集暴露这个问题
情感分布偏斜 训练集负面 71% 反映了反馈的常态,但中性、正面样本偏少 未处理
“其他”类过于简单 多为几个字的短句 稍长的无关内容可能被误判 未处理

第二轮数据:语法 v2

第一轮训练完成后,我看了全参数微调模型 ft-full-v1 在分布外开发集 ood_dev 上的全部失败案例(自动整理的清单),据此扩充了语法,得到 v2 数据,用于训练 v0.2。结果和结论在 评测报告 里,这里只说数据怎么改的。

失败类型 → 数据改动

编号 在 ood_dev 上看到的失败 例子(原文 → 模型给出的摘要或标签) v2 的改动
F1 摘要拼贴:把训练见过的摘要模板碎片和输入里的词拼在一起 “首月1元,第二个月直接扣了30…” → 摘要“首月界面发烫” 增加摘要里带开放槽位的问题类型(“{remind}不响”“咨询{acctopic}”“希望{adj}可调”),让“把原文的主体抄进摘要”成为常见模式
F2 关键词捷径:某些词在 v1 里只出现在投诉中;性能、界面类说法稍变就归错类 “没有开屏广告这一点就值得五星” → 广告骚扰 / 负面 增加对照样本:带“广告”“换”等词的表扬;不带“卡”“慢”字样的性能投诉;抱怨现有交互而非提需求的界面投诉
F3 咨询识别不稳 “买错了规格,想改一下订单,在哪里操作呀” → 其他 增加带开放主题的咨询类型
F4 v1 没有的紧急度修饰语不起作用 “…导航完全不能用” → 紧急度 中 新增 6 种升级说法、3 种降级说法,并让 v1 的问题类型也带上它们再生成一批

代码:feedlens/data/lexicon_v2.py(只含增量)、feedlens/data/build_v2.py。命令:python -m feedlens.data.build_v2。

v2 数据规模

文件 条数 构成
train_v2.jsonl 8408 v1 的 5146 条原样保留 + 新增 3262 条(新问题类型 2859 条、新修饰语 403 条)
val_v2.jsonl 1444 v1 的 969 条 + 新增 475 条
test_v2new.jsonl 381 v2 新增问题类型里留出的核心表达,训练中未出现

新增 44 个问题类型、190 个核心表达。全部数字见 v2 数据构建报告。

保持可比性的三条约束

  1. v1 的文件一个字节都不改。 改动生成器后重新构建 v1,各文件 SHA256 与改动前相同(已核对)。所以 v0.1 和 v0.2 可以在同一份 test、同一份 ood_test 上直接比较。
  2. 训练设置不变。 v0.2 用与 v0.1 相同的配置(方法、轮数、学习率、种子),只换数据,差别就只能来自数据。
  3. 只看 ood_dev,不看 ood_test。 新增内容只依据 ood_dev 的失败类型设计。

一次真实的泄漏,以及怎么发现的

第 3 条约束我第一次没有守住。写完 v2 词表后,我用程序扫描了它与 ood_test 的字面重合(槽位取值整词、三字片段,核心表达四字片段),发现:

处理:删掉这个取值,改写那两处,重新构建。重建后,新增训练样本与 ood_test 的最大相似度为 0.143,没有任何一条超过 0.4。

这件事说明两点:

ood_dev 从此不再独立

v2 的新增语法就是照着 ood_dev 的失败案例写的,新增训练样本与 ood_dev 的最大相似度达到 0.833。因此 v0.2 在 ood_dev 上的成绩不能当作泛化能力的证据,它只说明“针对性的修改生效了”。下一轮迭代需要一份新的开发集。

复现

python -m feedlens.data.build --seed 42

同一种子会生成逐字节相同的文件。各文件的 SHA256 记录在 data/processed/manifest.json,模型说明卡里记录了训练所用训练集的校验和。

本页由 docs/07-data.md 生成。