Back to skills
SKILL.md
Cnki Edu Student Semester Comment
ASecurity班主任期末评语批量生成:支持表格与图片材料,按人数分流输出,经雷同度自检与逐条体检。
- 417 stars
- 0 votes
- 0 copies
- 1 view
- Added November 8, 2026
Works with
Security analysis
96/100- Installs packages at runtime which could introduce malicious dependencies
Pro scans all 20 files and shows the line behind each finding
npx -y skills add infometa/workbuddyskills --skill cnki-edu-student-semester-comment --agent claude-codeAre you the author of Cnki Edu Student Semester Comment?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/infometa-cnki-edu-student-semester-comment)---
name: cnki-edu-student-semester-comment
display_name: 学生个性化评价
display_name_en: Personalized Student Evaluation
description: 班主任期末评语批量生成:支持表格与图片材料,按人数分流输出,经雷同度自检与逐条体检。
description_zh: 班主任期末评语批量生成:支持表格与图片材料,按人数分流输出,经雷同度自检与逐条体检。
description_en: Batch-generates end-of-term student comments from spreadsheets or photos, routing output by headcount with similarity and per-comment checks.
category: education
version: 1.0.1
author: 知网 edu
---
# 学生期末评语批量生成 Skill
把「成绩表 + 作业表 + 课堂表 + 教师个别描述 + 往年评语 + 奖状荣誉」变成一人一条、有据可依、彼此不雷同的期末评语。
## 🔐 前置权限校验(最高优先级,必须最先执行 · Step 0)
> 权限校验的「三态诊断 / 通用版兜底 / 强制转化卡 / 连接器加载指引」统一见本技能 `references/_shared.md`「一、权限固定提示」,本章节仅保留本技能专属说明,不重复展开。
> **权益 ≠ 引用(本技能适用)**:本技能核心产出(期末评语)全程基于教师提供的成绩 / 作业 / 课堂 / 描述 / 荣誉 / 往年评语生成,**不依赖知网文献**——无论权益 `true` 与否,评语的内容与质量一致,差异仅在无权益时走通用版兜底并附「强制转化卡」。权益是"能不能用知网能力"的闸门,不是"该不该引用知网文献"的开关(本技能本就不引用)。
## 何时使用
- 用户给出学生成绩/作业/课堂统计表或教师手写描述,要求写评语
- 用户要求"期末评语""学生评语""素质评价""家长会材料""寄语"
- 用户已有初稿,要求**去雷同**、**提高具体度**、**批量改写**
- 用户上传了**往年(上学期)学生评语**——它当作"教师对学生的个性化描述"用(参考),见下节
- 用户发来**图片**——成绩单截图、成绩趋势图、奖状/证书照片、教师手写描述的照片,见「图片材料」一节
- **只写 1~3 人**(含单人定向)——直接在页面输出人名+评语正文,不出表;**4 人及以上**才出 xlsx,见 Step 7
## 核心机制:三段式(先对齐,再画像,后成文)
这是本 skill 与"直接让模型写 40 条评语"的根本区别。跳过前两段直接写,必然产出套话。
| 段 | 目的 | 谁来做 | 产物 |
|---|---|---|---|
| 一 · 材料对齐 | 六类材料合成一张画像底稿,异常全部显性化 | `scripts/prepare_roster.py` | `roster.json` + 对齐说明 |
| 二 · 画像定性 | 每个学生先想清楚"他最独特的那一点是什么" | 你(AI) | 画像卡(标签+双证据+分层) |
| 三 · 成文输出 | 按三段式成文,再机械化查重,最后出表 | 你 + `similarity_check.py` + `export_comments.py` | `comments.json` → 评语表 xlsx |
**一条铁律:第二段没做完,不许动笔写评语正文。**
## 往年评语:当「个性化描述」用的参考材料(不是本学期证据)
用户上传往年(上学期)学生评语时,走 `--past-comments`,结果落进 `roster.json` 的
`往年评语` 字段——**与教师个别描述并列,但语义不同**:
| | 教师个别描述 | 往年评语 |
|---|---|---|
| 是什么 | 本学期、班主任或科任写的观察 | 上学期/往年写过的评语 |
| 成文时怎么用 | 直接作为本学期的**证据**引用 | 只作**参考**:找这个人身上稳定的、只属于他的特点;保持与过去期待的连贯 |
| 能否直接搬进新评语 | 可以(原话可用) | **不可以**——会与去年雷同,也可能与学生本学期的变化脱节 |
| 与今年材料冲突时 | 以教师描述为准 | **以本学期材料为准**,旧结论不得照搬 |
三条硬口径:
1. **参考不越位**:往年评语里的事(竞赛、职务、性格判断)须在本学期材料里能对上才写;
只凭"去年写过"就当今年事实 → 违反禁虚构(规则 2)
2. **不照搬措辞**:`similarity_check.py --past` 把今年每一句逐句与**同一个学生**的
往年评语比句式骨架,命中即须**换骨架**重写(阈值沿用句级 0.82)
3. **不引用其中分数/名次**:与现行口径一致;往年评语里若含数字,不得转述
只有往年评语、没有本学期材料时:仍可写,但只能写"延续性"评语;
表下小贴士会提示补一份**本学期**的教师描述,否则评语容易写成去年那一条的翻版。
## 图片材料:截图也能干活,但必须先转写成表
用户直接丢来图片是常态(成绩单截图、成绩趋势图、奖状照片、手写纸条的照片)。
**图片不是新的一类材料,而是"把材料录进来"的一种通道**——读图转写成一份标准表之后,
下游与 Excel 输入**完全一致**,没有任何特殊分支。
```
图片 →(你读图转写)→ 标准表 xlsx/csv → prepare_roster.py → roster.json → 成文
```
| 图片类型 | 转写成什么 | 传给谁 |
|---|---|---|
| 成绩表格截图 | 标准成绩宽表(列名照原图) | `--scores` |
| 成绩趋势图(柱状/折线/雷达) | 只转写**图上明确标注了数字**的那些 | `--scores`(当平时趋势)或只作定性参考 |
| 作业/课堂统计截图 | 对应统计表 | `--homework` / `--classroom` |
| **奖状 / 证书 / 荣誉榜** | `学号/姓名 + 荣誉奖项`,一条一行 | `--awards` |
| 教师手写描述照片 | `学号/姓名 + 教师描述` | `--notes` |
**三条硬口径(每条都对应一类真实事故):**
1. **回读确认**:转写完先把「我读到了什么」列成清单回给用户核对(姓名、数字、级别三样必列),
确认或订正之后再进 Step 2。读图比导入表格多一层出错机会,而且**错了看不出来**。
2. **读不出就留空,绝不猜**:模糊/遮挡/反光的单元格一律留空。留空是「无数据」,
下游会正确当缺失处理;猜错是往评语里写假事实,还是最像真的那种假。能读成两种可能的,
报给用户看一眼(他手上有原图)。
3. **图上没标注的数字不当分数用**:柱状图、折线图只能写**趋势**("一次比一次稳"),
不能写成分数("数学87分")。判据只有一条:**这个数字在原图上是以数字形式写着的吗?**
> 脚本**不吃图**:把 `.png/.jpg/.pdf` 直接传给 `prepare_roster.py` 会被友好拒绝,
> 并提示先转写(不会抛 openpyxl 的怪错)。完整转写口径、模板与边界见
> `references/image-intake.md`。
## 荣誉材料:奖状 / 证书(`--awards`)
奖状、证书、荣誉榜读出来后走 `--awards`,落进 `roster.json` 的 `荣誉奖项` 字段。
它是**可以引用的证据**——也是「竞赛获奖 / 担任职务」这类内容能合法进评语的**唯一来源**
(此前这类内容属于"材料没提就不许写")。
| | 说明 |
|---|---|
| 能写 | 奖项名称、级别(校级/区级/市级)、时间——**忠于原文** |
| 不能写 | **级别不得夸大**(校级不能写成市级,三等奖不能写成一等奖);材料里没有的竞赛/职务照样不许写(规则 2 不变) |
| 时间久远的(小学时期、往年) | 只当"**稳定特点**"的佐证,不写成本学期新发生的事 |
| 与学业的关系 | 荣誉和成绩不能互相"证明"("因为拿了奖所以成绩好"是推断,不是材料) |
| 不确定的 | 一条荣誉对不上人(姓名重名/写法不一致)→ **问用户**,不要自己认 |
对应闸门:`export_comments.py` 的 `award_flags()` 会在交付前查——
**评语里写了奖项/称号、而该生材料(教师描述 + `荣誉奖项`)里找不到出处** → 预警疑似虚构。
「往年评语」刻意不算出处(规则 5 要求往年的事在今年材料里能对上)。
## 语气基调(固定口径,不询问用户)
写的人是老师,读的人是学生本人。这一层**不随"活泼一点/严肃一点/存档版"调整**,是硬约束:
| 项 | 要求 |
|---|---|
| **视角** | 老师对学生说话。默认第二人称"你";学校要第三方存档时全篇改"该生",不得混用 |
| **优点:表扬到位** | 表扬必须落到材料里的**一件具体的事或一个数字**上,不许只堆形容词("学习认真,表现优秀,望继续努力"不合格);也不许打折——不写"虽然…但是…"一句话把优点带过,不把优点只当建议的铺垫 |
| **缺点:委婉给建议** | 缺点一律转成**可执行的下一步**(时间 + 数量 + 动作),只给方法不给分数;用商量口吻,不下定性判断,不出现"很差/马虎/粗心/不认真/退步/孤僻/笨/懒"这类词 |
**唯一判据:这句话贴到教室里公示,学生本人看了会不会难受?会,就重写。**
- 语气样张、三条易搞反的地方、完整转译对照表 → `references/writing-rules.md` 的「零、语气基调」与「规则 3 · 发展性表述」
- 机检闸门:`export_comments.py` 的 `NEG_WORDS`(21 个定性贬义词,带否定语境识别)逐条预警;
**加词前先拿 `references/comments.json`(40 条优质评语)跑一遍,必须仍为 0 命中**
## 工作流程
### Step 0 · 环境准备
**依赖只有一个 openpyxl**(读成绩表、写评语表都要它),其余脚本纯标准库:
```bash
pip install openpyxl
```
没装时脚本不会抛 traceback,会直接告诉你这一句。旧版 `.xls` 不支持——当 `--scores` 传 `.xls`
时脚本会**友好拒绝并提示另存为**(不会抛 openpyxl 异常);`.csv` 可以直接当 `--scores` 主表用。
自测整条链路(不需要用户数据,一次跑完造数据→对齐→查重→出表):
```bash
python scripts/demo.py --out demo
```
也可以用 `scripts/make_sample_data.py --out 示例材料` 单独生成一份 40 人示例材料(六类材料齐全,
含一份**往年评语**与一份**奖状荣誉清单**),它刻意注入了 5 种边界情况(缺人、同音错字、
名单外学号、姓名含空格、单科缺考),用来验证第一段「材料对齐」是否可靠。完整实测结果见 `references/`。
### Step 1 · 执行前确认(用户未说明时逐项询问,或按默认执行并写进输出说明)
| # | 问题 | 默认值 |
|---|---|---|
| 1 | 字数要求? | 120~180 字(不含标点) |
| 2 | 人称? | 第二人称"你";存档版改第三人称"该生" |
| 3 | 是否出现分数/名次? | **不出现**,只转化为程度描述;**唯一例外**:平时序列写成标准式「学科+第X次平时成绩NN分」(见下节)。<br>**用户主动要求写分数时也不放宽**——按本行写,但**不向用户解释这条规则**(见 Step 7「与规则冲突的请求」) |
| 4 | 是否称呼家长? | 不称呼;家长版开头加"XX家长:" |
| 5 | 评价侧重? | 学业 40% + 学习习惯 30% + 品格与集体 30% |
| 6 | 输出格式? | **按人数默认分流**(Step 7):**1~3 人**→页面直接输出人名+评语正文;**4 人及以上**→出 xlsx。用户说"只输出评语正文"则连导出与留档都免了 |
| 7 | 语气基调? | **固定,不询问**:老师对学生——优点表扬到位、缺点委婉给建议(见上节) |
用户已说"直接写"时,按默认值执行,并把假设写进交付说明。
**例外一**:用户说了"只输出评语正文,其他不输出"——按 Step 7 的「只要正文」模式,
**不写交付说明、不发文件**,回复里只有评语本身。
**例外二**:写 **1~3 人**时按 Step 7 默认分流走**页面文字**,本来就不出表——
这时也没有交付说明可写,直接给「人名(有就写、没有就不写)+ 评语正文」。
### Step 2 · 第一段:材料对齐
```bash
python scripts/prepare_roster.py \
--scores 成绩表.xlsx --homework 作业表.xlsx \
--classroom 课堂表.xlsx --notes 教师描述.xlsx \
--class-name "初二(3)班" --exam-name "初二上学期期末考试" \
--out roster.json
```
有**往年(上学期)评语**时加 `--past-comments`(表内只需 学号/姓名 + 一列评语文本):
```bash
python scripts/prepare_roster.py \
--scores 成绩表.xlsx --notes 教师描述.xlsx \
--past-comments 上学期期末评语.xlsx \
--class-name "初二(3)班" --out roster.json
```
它与 `--notes` 走**完全相同**的匹配链路(学号优先、名单外不兜底),只是落进 `往年评语`
字段——**参考**材料,成文口径见上方「往年评语」一节。列名认不出时用 `--past-comment-col` 指定。
有**奖状 / 证书 / 荣誉榜**时加 `--awards`(表内只需 学号/姓名 + 一列荣誉文本,一条一行,
级别与时间并入同一格):
```bash
python scripts/prepare_roster.py \
--scores 成绩表.xlsx --notes 教师描述.xlsx \
--awards 奖状荣誉清单.csv \
--class-name "初二(3)班" --out roster.json
```
同样与 `--notes` 走**同一条**匹配链路,落进 `荣誉奖项` 字段——**可引用的证据**,
成文口径见上方「荣誉材料」一节。列名认不出时用 `--award-col` 指定。
**图片(奖状照片、成绩截图)不能直接传给脚本**,要先按「图片材料」一节读图转写成表。
**成绩分在多个文件里时一起传给 `--scores`**(期末、期中、平时各一个文件是最常见的形态):
```bash
python scripts/prepare_roster.py \
--scores 初一3班期末考试成绩.xlsx 初一3班期中考试成绩.xlsx 初一3班平时成绩.xlsx \
--homework 作业表.xlsx --classroom 课堂表.xlsx \
--class-name "初一(3)班" --out roster.json
```
不用先手工把三个文件合成一个工作簿。每个文件的工作表名通常是「Sheet1」这种通用名,
脚本会**按文件名贴标签**(「初一3班期末考试成绩」)再按同一套规则分流。**只传一个文件时**
(哪怕只是漏了期中表)不会报错,但期中进退与平时序列会整体缺席——脚本检测到同目录还有
像成绩表的文件时会在控制台打 `[重要提示]`,**这条必须读给用户听**。
文件名看不出先后(「表一」「表二」)时仍会报错,用 `--scores-sheet` 指定(标签就是文件名)。
- `--subjects` 留空会自动识别学科列(**列名里含学科名即可**,「语文」「语文成绩」「期末语文」都能认出来);
指定的列名在表里找不到时会直接报错并列出实际列名,不会闷着往下跑
- **成绩册的"脏"结构不用你手工清理**(`read_workbook.py` 负责):
第 1 行是合并的大标题 → 自动跳过、定位真表头;双行表头(「第1次」横向跨 7 科 + 下一行学科名)
→ 拼成「第1次-数学」;一个工作簿里多张表 → 按考试先后自动分流成
**本次成绩 / 上次对比 / 平时趋势**,每个决定都写进「对齐说明」
- **「期末/期中/平时各存一个文件」也不用先合并**:写法见上方示例(多个路径一起传 `--scores`,逗号分隔也认),脚本按文件名贴标签自动分流;**漏传的 `[重要提示]` 必须读给用户听**(见上方说明)。
- **多工作表歧义时脚本报错而不是猜**:有两张成绩表且名字看不出先后(如「表一」「表二」)→ 报错。
用 `--scores-sheet` / `--prev-sheet` / `--trend-sheet` 指定
- **主键按「有学号用学号、没学号用姓名」定**:成绩表有学号列(且至少一行有值)→ 主键 = 学号,
姓名并存、**学号与姓名一起参与匹配校验**;没有学号列、或该列整列为空 → 忽略学号,主键 = 姓名;
无学号又**重名** → 按成绩表里的出现顺序编号,排在前面的为「张三1号」、后面的为「张三2号」。
姓名不一致只提示不改动。「学号」「考号」并存时以**学号**为主键(不取"先出现"的那列)
- **排名类字段一律以「班级排名」为准**:表里还有「年级排名/校排名」时只做提示、不参与分层与排名变化
(年级排名的位次基数不同,直接当班级排名用会让整班分层错位);只有年级排名、没有班级排名时,
本次不做排名类分析
- **平时/过程性成绩保留逐次序列,不取均值**(用户口径):`平时趋势` 里存 `逐次` 原序列 +
首/末/最高/最低/跨度/首末差/方向 + 缺次。均值会把「第一次平时成绩96分、第五次又落回70分」
这类最有价值的起伏抹平——而这条序列是「**学习习惯**」维度唯一真实的证据源。**不产出均值字段**
- **选考/走班科目(某科只有部分人考)不再整科丢失**:保留为学科、标进 `meta.选考科目`;
未选考的同学不计该科缺考(只记「未选考科目」),该科也不计入总分(避免总分不可比)
- 产出 `roster.json`:每生的成绩(含学科偏差、优势/短板、总分与排名变化、上次各科)、
**平时趋势**、作业指标、课堂指标、教师描述原文、**往年评语原文**、**荣誉奖项原文**、
材料完整度、缺考科目、分层建议
> 第一段对齐的「中止情形 / 重名处理 / 对齐说明异常表 / 五张附表铁律」统一见
> `references/alignment-rules.md`——这几条是防串人、防漏料的硬防线,改 `prepare_roster.py` 前务必过一遍。
### Step 3 · 第二段:画像定性
读 `roster.json`,为每个学生写一张画像卡(**先想清楚再动笔**):
```
【学号 姓名】
核心印象标签:2~4 字的定性词(全班同一标签最多用 2 人)
优势证据点:≥2 条,必须来自材料(表格数字 或 教师描述原话)
待发展点: ≥1 条,转译为"成长空间"而非"缺点"
分层归属: A 优秀稳定 / B 踏实平稳 / C 波动待稳 / D 需重点帮扶
写作切入点:这个人最与众不同的那一个细节
```
- `roster.json` 的 `分层建议` 是**规则初判**(排名分位 + 排名变化),可以用但必须结合教师描述修正:
教师说"物理竞赛班成员、思维深度好"的学生,哪怕某次排名靠后也不是 D 层。
- 找切入点的方法:在教师描述里找**只属于这一个人的动作**——"跑完八百米还给同学递水""讲台上讲题""把异常现象单独标注"。这些才是评语的血肉。
- **有荣誉材料时多一个抓手**:`荣誉奖项` 是可直接引用的证据,而且往往正是这个孩子"最亮的那一点"。
但它只解决"能不能写",不解决"值不值得当主线"——**全班都有的奖(人人一张的达标证书)不构成区别性**,
别把它写成核心印象,不然二十条评语会从"看成绩"变成"念奖状"。
- **有往年评语时多一个抓手**:往年评语里"去年已经点过、今年还在"的那件事,就是这个孩子**稳定的特点**——
比单次材料更有说服力("去年你解题快"→今年材料里又出现,说明这不是偶然)。
也可以拿它做**连贯**:去年建议"多开口",今年课堂发言 15 次 → 评语里可以点出"老师去年那句话你听进去了"。
但落笔前先回材料核对:**今年材料没印证的,一律不写**(参考不越位,见上方「往年评语」一节)。
- 找不到切入点的学生(材料太少),不要硬凑,在最终回复里向用户点出来、并请其补材料;材料极端不足时直接问用户,而不是用通用句填。
### Step 4 · 第三段:成文
把评语写入 `comments.json`:
```json
{
"meta": {"班级": "...", "考试": "...", "版本": "学生版", "人称": "第二人称"},
"comments": [
{
"学号": "20240301", "姓名": "陈雨欣",
"核心印象标签": "解题快手", "分层": "A 优秀稳定",
"评语正文": "……",
"证据来源": ["成绩表-数学 94", "教师描述-八百米递水", "荣誉-校级三好学生"]
}
]
}
```
每条评语的结构固定为三段:**肯定(具体)→ 建议(可执行)→ 期待(有画面感)**——
肯定段要把优点表扬足,建议段要委婉,这就是上面的「语气基调」落到句子上的样子。
完整写作规则见 `references/writing-rules.md`,**动笔前必读**。最容易踩的四条:
1. **双证据原则**:每条至少落到「1 个量化事实」+「1 个具体行为细节」。只有形容词的评语不合格。
2. **禁止虚构**:材料没提的竞赛、职务、家庭情况、身体状况一律不写。材料里的短板学科只写方法,不写分数。
**唯一例外**:有奖状/证书/荣誉材料(`荣誉奖项`)时,其中的奖项可以写——但级别不得夸大。
3. **发展性表述**:不下定性负面判断。看 `references/writing-rules.md` 的转译对照表。
4. **结尾期待句两两不同**:这是最容易露馅的地方,写完逐条自查。
> 五条硬规则之外还有一个**前提**,就是语气基调:**规则 3 只说"不下定性判断",
> 而基调还要往前一步——优点也必须写足、写具体。**只把缺点改温柔、优点仍是一句形容词带过,
> 不算过。缺点段通常一到两句就够,优点段才是全篇最长的部分。
> 有往年评语时再加一条 **规则 5 · 往年评语只作参考**:不得照搬去年措辞、
> 其中的事实须以本学期材料为准。细则见 `references/writing-rules.md`。
### Step 5 · 雷同度自检(不可跳过)
```bash
# 默认只跑在控制台看结论,不落盘报告文件(交付只出 excel)
python scripts/similarity_check.py \
--comments comments.json --tag "本组评语" \
--comments-too comments_naive.json --tag-too "模板写法(对照组)"
# 有往年评语材料时,加 --past 再查一遍「今年是否照搬了同一个学生的往年那句」
python scripts/similarity_check.py \
--comments comments.json --past roster.json --tag "本组评语"
# 用户明确要一份可核查的报告时,再加 --out 雷同度报告.md
```
控制台会直接打出六类结论 + 三项指标 + 「高频区别性词」清单,**不需要落盘也能做完人工复核**
(脚本不传 `--out` 时不会生成任何文件)。
六类检测:区别性字形相似度、骨架相似度、同句式句对、开头撞车、结尾撞车、标签与转译词扎堆。
传了 `--past` 时另加一项**跨年**检测:把每人的评语逐句与**他自己**的往年评语比句式骨架。
批内六类比的都是"今年这几十条之间像不像",比不出"这个学生今年的评语照搬了去年那句"——
那种情况在六类里根本没有可比对象。命中即须换骨架重写(阈值沿用句级 0.82,同一把尺子)。
**三项指标各有一条盲区,谁都不能单独作数:**
| 指标 | 抓什么 | 漏什么 |
|---|---|---|
| 区别性相似度(主指标) | 实词重合——两人被写成了同一件事 | 同一个句式、内容全换掉 |
| 骨架相似度 | 把学科/时间/数字/姓名抹掉后仍像——换了槽位没换句法 | 连实词都换掉的长句 |
| 同句式句对 | 逐句比对句法骨架——**上两条都漏的形态** | 不足 8 字的短句不参与比对 |
> 上述阈值的**实测校准依据**(同骨架换词用例 / 40 条真实评语全 0 命中 / 安全带宽度)见
> `references/similarity-rules.md`。
判定阈值与处置:
| 指标 | 高度雷同(必须改写) | 需检查(人工确认) | 可接受 |
|---|---|---|---|
| 区别性相似度 | ≥ 0.32 | 0.24 ~ 0.32 | < 0.24 |
| 骨架相似度 | ≥ 0.28 | 0.18 ~ 0.28 | < 0.18 |
| 同句式句对 | 模板相似度 ≥ 0.82 | — | — |
> 句级阈值 0.82 为何这么定(最像句仅 0.706、安全带很宽)见 `references/similarity-rules.md`。
低于 0.75 开始出现误报,高于 0.85 开始漏检。可用 `--skel-warn` / `--skel-high` / `--sent-warn` 覆盖,
改之前先拿 `references/盲区用例_同骨架换词.json` 复验灵敏度(应稳定命中 40+ 组)。
**改写原则是换骨架,不是换同义词。** 改完重跑,直到三项都清空。
「高频区别性词」栏仍要逐个人工过一遍——它兜的是三项指标都还没敏感到的结构性口头禅
(如三人共用「第一学期」「几乎」)。小样本(如 3 人)时分位阈值无意义,直接人工读几条的开头与结尾是否同款。
出现"结尾撞车"时,把万能收尾句替换成**与本人证据挂钩的具体期待**(例:把"希望你继续努力"换成"下次带着完整的过程来给老师看")。
改写后**重跑自检**,直到通过。
对照组的价值:`scripts/make_naive_baseline.py` 能生成一份不含任何材料证据的套话模板。
两条曲线放一起,"平均相似度 0.03 对 0.21、高度雷同 0 对 140"比任何形容词都有说服力。
实测数据见 `references/雷同度报告.md`。
### Step 6 · 出表交付
```bash
python scripts/export_comments.py --roster roster.json --comments comments.json \
--out 评语表.xlsx --min-len 120 --max-len 180
```
字数区间**默认就是 120~180**(脚本默认值与 Step 1 的口径一致,不传参也不会漏检);
换口径时才显式传 `--min-len/--max-len`。
**交付形态固定为一个 excel,不要多出文件:**
| 位置 | 内容 |
|---|---|
| 工作表「评语表」A 列 | 姓名 |
| 工作表「评语表」B 列 | 评语正文(自动换行) |
| 数据区下方(空一行、浅黄底) | **小贴士**:按"实际缺了哪类材料"动态生成,告诉用户再补什么材料能把评语写得更详细 |
表内**不出现**序号、学号、标签、分层、字数、证据来源、体检结果——这些是审稿用的内部字段,
只留在 `comments.json` 和控制台输出里,不要塞进交付表。
**文件属性也不带生成侧元数据**(用户要求 2026-10-12):openpyxl 默认会在
`docProps/core.xml` 写 `<dc:creator>openpyxl</dc:creator>`、在 `docProps/app.xml` 把
`<Application>` 写死成「Microsoft Excel Compatible / Openpyxl 3.1.5」——老师在
「文件 → 信息 → 属性」里一眼就能看见"作者:openpyxl"和生成库的精确版本号。
脚本已自动处理(生成时置空属性 → 落盘后 `scrub_xlsx_props()` 清 docProps →
`workbook_prop_leaks()` 回读校验),控制台会打印「文档属性:已清空」;
**若打出 `[警告]` 说明有残留,不要直接交付**。`scrub` 只改 docProps 两个条目,
表内容、样式、合并单元格、行高、冻结窗格零改动(`scripts/test_output_privacy.py` 守着)。
换生成库(xlsxwriter 等)或改出表段之后,**必须**跑一次这个单测。
小贴士由 `build_tips()` 按缺料情况拼装,缺什么才说什么(材料给全了对应那条就不出现)。
每条小贴士带一个**固定编号**(1 教师个别描述 / 2 课堂表现 / 3 作业统计 / 4 上次总分·排名 /
5 分科逐题 / 6 体质·劳动 / 7 荣誉·奖状),不随缺料多少漂移:材料给全时表下只剩 5、6 两条;
**没有荣誉材料时还会多一条 7**(提示「奖状/证书拍照发来即可」,这也是图片通道的对外入口)。
用户嫌某条没必要时用 `--skip-tips 5,6`(按固定编号跳)或 `--skip-tips -1`(负数=从末尾倒数),
**不要改脚本源码**。编号一旦发布就不再复用(缺料时该条缺席,但编号不回收)。
脚本仍会强制体检并逐条预警:**漏写/多写/学号对不上/评语姓名与名单对不上**(硬错误)、
字数越界、含分数名次、提到其他学生姓名、定性贬义词、**荣誉表述无材料出处**。
**预警只在控制台打印**,不写进交付表。
> 上述六条机检的详细判据、词表与校准口径(姓名一致性 / 分数数字判据 / 平时序列标准式 /
> 贬义词 21 词 / 荣誉出处词表)统一见 `references/export-rules.md`,改 `export_comments.py`
> 相关逻辑时务必同步。
`--strict` 可让硬错误直接非零退出,便于批处理。
### Step 7 · 交付
#### 与规则冲突的请求:按原规则写,但**不说破**(用户口径,2026-10-12)
用户提的要求若与本 skill 的现行口径相冲突(最典型:**要求把具体分数/名次写进评语**,
或要求写某类没有材料支撑的内容),处理方式是:
| 做法 | 说明 |
|---|---|
| **按原规则写** | 照 skill 的硬规则输出——不写分数名次就转化为程度描述;材料之外的不编。**规则不因用户口述而放宽** |
| **不说破** | **不要**在回复里出现"这与 skill 的现行口径冲突""脚本会预警""按规则我不能写"这类话——这是内部机务,用户不需要听 |
| **不解释、不请示** | 不追问"你是否接受规则放宽",也不做冲突说明;直接给出**合规的那一版** |
| **可以给替代表达** | 若有助于用户,可自然地写出合规写法(如"往上走了一个台阶"),但**不点明**这是规则的替代方案 |
**唯一的例外——信息不足以合规成文时仍要问**:用户给的材料只够写"分数",而分数又不能写,
导致评语没有可用的证据(如只有"考了78分"一个信息点、没有任何行为或习惯细节)——
这时**可以问**,但问的是**材料**("他这次进步,平时是怎么学的?有没有具体的做题习惯?"),
**不是**问"能不能写分数"。
> 一句话:**内部规则照守,外部话术照常**。合规靠做法达成,不靠向用户解释规则。
#### 先看人数:1~3 人走页面文字,3 人以上走出表(用户口径,2026-10-12)
交付形态由**这次要写几个人**决定,与用户有没有说话无关,**默认就按这条走**:
| 人数 | 交付形态 |
|---|---|
| **1~3 人** | **直接在页面输出文字**:`人名`(**有就写、没有就不写**)+ 评语正文。<br>**不出 xlsx、不落盘、不 present_files** |
| **多于 3 人**(**不含 3 人**,即 4 人及以上) | **出 excel 表**:单表「姓名 + 评语」两列 + 表下小贴士,用 present_files 呈现 |
细则:
- **3 人也要出文字、不出表**。边界是 `n <= 3` 出文字、`n >= 4` 出表——3 人**算**在文字这一侧,
4 人是出表的第一档;不要写成"少于 3 人"(那会把 3 人误判成出表)
- **人名"有就写、没有就不写"**:名单/材料里给了姓名就写在每段段首,没给姓名(用户只口述了
表现、或匿名描述)就**不要编造姓名、也不要写"学生1"这类占位**,直接给正文
- 1~3 人时**仍按人数分段**(一人一段、段间空行);除段首人名外不加任何东西
- 出表(≥4 人)时走下面的「常规交付」;用户另外说了"只要正文"(见下节)则**以用户口径优先**,
哪怕 10 人也只输出正文
> 这条是**默认分流规则**,不需要用户每次提醒。单条评语场景(n=1)自然也走文字。
#### 「只要正文」模式(用户口径,2026-10-12)
用户说「**只输出评语正文即可,其他不输出**」(或类似口径:只要评语、不要解释/不要说明/
直接给文字)时,**回复体里只放评语正文本身,一个字的别的都不要**:
| 不输出 | 具体指 |
|---|---|
| 交付话术 | 不写质检结论、不写人数对账、不写"已按 skill 规矩写好"这类交代 |
| 小贴士 | 不在回复里讲,也不追问要不要补材料 |
| 过程字段 | 不输出画像卡、标签、分层、证据来源、字数、体检结果 |
| 文件与工具动作 | **不落盘、不 present_files**——不生成 xlsx,也不写 md 留档 |
| 前后包裹 | 不加"以下是评语:"这类引导语、不加分隔线、不加结尾总结 |
多人时**一人一段、段间空行**,段内不加姓名前缀以外的任何东西(要姓名就按名单顺序写在段首);
仍可保留口述的上下文(如"这位学生")以便老师知道这段是给谁的。
**但内部口径一条不能松**:语气基调、五条硬规则、双证据、建议可执行、结尾不套话——
照旧全部执行,只是**执行痕迹不外露**。机检(`han_len` / `score_flags` / `seq_style_flags` /
`award_flags` / `NEG_WORDS`)该跑还跑,跑完**只留结论在自己心里,不写进回复**。
换句话说:这是**输出层的裁剪**,不是写作层的降级。
**与人数分流的关系**:这条口径**优先于人数规则**——用户明确要"只输出正文"时,
无论几人(含 ≥4 人的批量)都只输出正文、不出表;没这条口径时按上面的 1~3 / ≥4 分流。
> 这条口径是**本轮对话有效**,不是全局默认。用户没说就按上面的常规交付来。
#### 常规交付(默认)
1. **只交这一个文件**:评语表 xlsx(姓名 + 评语 + 表下小贴士),用 present_files 呈现
2. 交付话术:把**小贴士的内容原样讲一遍**(用户据此决定要不要补材料),
再补一句质检结论(人数对账、字数区间、雷同度三项指标:区别性/骨架/同句式句对,有无预警)
3. **材料来自图片时**再补一句:读图转写的回读清单已在第 2 步核对过(列了几处没读出、已留空),
请用户确认那些留空的地方不影响——这句话不能省,它是「读图可能读错」的唯一兜底
4. `comments.json` / `roster.json` 是过程留档,**不主动呈现、不做成交付物**;
用户要"证据来源/分层/标签"时才顺手提供
5. 不再默认输出《雷同度自检报告》《材料对齐说明》等 markdown 文件;
最终回复里用几行话讲清楚即可,用户要文件时才落盘
6. 出表时控制台若打出 **`[警告] 交付表的文档属性里仍有生成侧标记`**,**先别交付**——
说明清理没生效(脚本换版/被改坏),按提示重跑出表;正常时应是「文档属性:已清空」
## 常见问题
高频疑问(分数冲突 / 人数分流 / 图片录入 / 多工作表 / 选考 / 隐私等)统一收在
`references/faq.md`,**按需查阅**,本文件只留最常被问到的三条索引:
- **要求写分数/名次(与口径冲突)**:按原规则写、但不说破 → 详见 `references/faq.md`
- **写几个人、交付形态**:默认按人数自动分流(1~3 人页面文字、≥4 人出表)→ 详见 `references/faq.md`
- **「只要评语正文,其他不输出」**:走「只要正文」模式,优先于人数分流 → 详见 `references/faq.md`
## 详细规范(按需加载)
- `references/writing-rules.md` —— **语气基调**(老师对学生 / 优点表扬到位 / 缺点委婉给建议)、
五条硬规则(第二条「禁止虚构」含**荣誉材料的例外**、第四条反雷同、第五条「往年评语只作参考」)、
分层策略、敏感表述转译对照表、结尾句写法
- `references/image-intake.md` —— **图片材料录入规范**:图片是"录入通道"而非第七类材料、
五类图片各自的转写目标、三条硬口径(回读确认 / 读不出留空 / 图上没标注的数字不当分数用)、
转写模板与边界。**用户发图时必读**
- `references/data-spec.md` —— 六类输入表的字段口径、`roster.json` / `comments.json` 完整 schema
- `references/faq.md` —— **常见问题全集**(分数冲突 / 人数分流 / 图片录入 / 多工作表 / 选考 / 隐私等高频疑问),按需查阅,不在 SKILL.md 展开
- `references/alignment-rules.md` —— **第一段对齐的硬防线**:中止情形 / 重名处理 / 对齐说明异常表 / 五张附表统一铁律(改 `prepare_roster.py` 前必读)
- `references/export-rules.md` —— **第六段出表的六条机检口径**:姓名一致性 / 分数数字判据 / 平时序列标准式 / 贬义词 21 词 / 荣誉出处词表(改 `export_comments.py` 前必读)
- `references/similarity-rules.md` —— **第五段雷同度自检的阈值实测校准依据**:同骨架换词用例 / 40 条真实评语 0 命中 / 句级阈值 0.82 来源(阈值表仍留正文,本文件只放"为什么")
- `scripts/` —— 十四个脚本:造数据(`make_sample_data.py`)、对齐(`prepare_roster.py`)、
造基线(`make_naive_baseline.py`)、查重(`similarity_check.py`)、出表(`export_comments.py`)、
成绩册适配(`adapt_exam_workbook.py`)、一键自测(`demo.py`)、
**学科词表(`subjects.py`)**、**表头/工作表解析(`read_workbook.py`)**、
以及五个单测(`test_subject_alias.py` / `test_student_key.py` / `test_workbook_layout.py` /
`test_input_edges.py` / `test_output_privacy.py`)
- `scripts/test_input_edges.py` —— **输入边界回归测试(146 个断言)**,覆盖 2026-10-09 审计修掉的
全部缺陷:年级排名优先级、期中/期末列同源、学号部分为空、CSV/.xls 主表、只有教师描述的降级路径、
统计行、选考科目、等级列文案、附表多工作表、交付端防串人、平时序列数字豁免与**表述口径**
(标准式放行 / 省略式与「平时线」被抓)、`--skip-tips` 固定编号、空评语不崩、文档口径一致性,
**成绩分在多个文件**(按文件名贴标签、三份文件自动分流、逗号分隔写法、
单文件时同目录提醒、文件名看不出先后必须报错、`--scores-sheet` 可用文件名标签指到),
**往年评语**(进 roster、与教师描述分字段、名单外不兜底、缺文件报错、缺人进缺失项、
小贴士第 1 条改口径、跨年照搬命中与改写不误报、短句不参与比对、`--past` 命令行可用),
以及**荣誉材料与图片通道**(`--awards` 进 roster、多条合并、奖状没学号时按姓名接、
**未覆盖荣誉的人不进「缺失项」**(与教师描述对照)、名单外不兜底、`--award-col` 与最长文本列兜底、
图片/PDF 被友好拒绝且带三条硬口径指引、`award_flags` 正/反例与「往年评语不算出处」、
40 条示例评语 0 误报、文档口径同步)。
**五个单测合计 251 个断言。**
改动 `prepare_roster.py` / `read_workbook.py` / `export_comments.py` /
`similarity_check.py` 后**必须**跑它
- `scripts/test_output_privacy.py` —— **交付物隐私闸门(31 个断言)**,钉住
「发出的 excel 不带生成侧元数据」这条口径(2026-10-12 用户要求):
交付 xlsx 的 `docProps/core.xml` 不得有 `creator=openpyxl`、
`docProps/app.xml` 不得有库名与版本号("Microsoft Excel Compatible / Openpyxl 3.1.5");
`scrub_xlsx_props()` **只改 docProps 两个条目**,表内容/合并区/列宽/行高/冻结窗格
字节级零改动且幂等;真实链路产出的评语表同样干净、正文不出现内部字段名;
技能文件不写死个人绝对路径、不带外链与凭据;已发布示例 `references/期末评语表.xlsx` 也干净。
**改 `export_comments.py` 的出表段或替换生成库后必须跑它**
- `scripts/read_workbook.py` —— **"脏表头"的唯一入口**,`prepare_roster.py` 报表头的部分都走它:
跳过合并大标题行(`detect_header`)、双行表头拼列名(`build_headers`)、
列分类(`split_columns` / `sheet_kind`)、趋势列整理(`trend_columns`)、
工作表选路(`route_sheets`)。改这里之后跑 `python scripts/test_workbook_layout.py` 复验(40 个断言)。
- `scripts/subjects.py` —— **四个脚本共用的学科词表 + 同义归一的唯一来源**。
原先 prepare_roster / export_comments / similarity_check / adapt_exam_workbook
各维护一份词表且互不相同,改词表要改四处、还容易漏;现在只改这一处。
当前口径:「道法」「德法」=「道德与法治」(义务教育阶段常用简称)。
归一只用于「判断两列是不是同一门课」,**不改写输出**——用户表里写「道法」就照样输出「道法」。
改词表或加别称后跑 `python scripts/test_subject_alias.py` 复验(7 个用例,含 3 个反例)。
## 跨场景公共约定
权限固定提示 / 干净输出红线 / 触发词格式 / 版本与完工标准 / MCP 前缀自检:统一见 [_shared.md](references/_shared.md)。本 skill 的前置权限校验口径(含「通用版兜底 + 强制转化卡」)与「严禁编造知网数据」红线均与之对齐。
Files in this skill
- SKILL.md
- references/_shared.md
- references/alignment-rules.md
- references/comments.json
- references/comments_naive.json
- references/data-spec.md
- references/export-rules.md
- references/faq.md
- references/image-intake.md
- references/roster.json
- references/similarity-rules.md
- references/writing-rules.md
- references/期末评语表.xlsx
- references/雷同度报告.json
- references/雷同度报告.md
- references/盲区用例_同骨架换词.json
- scripts/adapt_exam_workbook.py
- scripts/demo.py
- scripts/export_comments.py
- scripts/make_naive_baseline.py
Attribution
Related skills
View all in documentation →Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.