缺漏查 · 名单缺漏核对技能(点名 / 作业 / 签到 / 资料回收通用)
这个技能做什么
本质是一个通用的「缺漏核对」引擎:只要你有「应到/应交名单」和「实到/实交名单」两份清单,就能找出谁缺席、谁漏交。典型需求包括:
1. 班级:收上来一摞作业,不知道全班还差谁没交;语音/拍照点名,清点缺席的人
2. 团体/组织:社团活动签到、部门会议考勤、培训出勤,谁没来
3. 资料回收:回收作业本/报表/合同回执/上报材料,核对谁还没交
4. 任何两份名单比对:婚礼宾客、考试入场、物资签收同理
这个技能的核心不是"识别"本身(识别交给下面提到的官方技能去做),而是"识别结果 → 花名册核对 → 缺交/缺席名单 → 填入指定表格"这套业务逻辑,尤其是手写体、口语化姓名的模糊纠错。
调用的官方技能(识别层,不要自己重新实现)
重要:涉及图片里的文字识别(尤其手写体),必须调用专门的OCR技能,禁止直接用通用视觉/多模态模型(如 GLM-5v-Turbo 等)"看图猜字"作为识别手段。
原因:通用多模态大模型做OCR是靠"理解图片+推理文字"的综合能力顺带完成的,本质是"看个大概、连蒙带猜";而专门的OCR技能是针对文字识别单独训练的专精模型,对手写体、连笔字这种需要精细笔画级别判断的任务明显更稳。实测中 GLM-5v-Turbo 直接识别手写姓名出现过"向峻辉"认成"何峻辉"、"程桢皓"认成"程筱喆"这类字形相近但完全认错的情况,专门OCR技能的识别准确率明显更高,这是两类技术路线的天然差异,不是简单换个模型版本能解决的。
- 花名册是图片/照片 → 调用「通用印刷体识别(高精度版)」或「文档抽取(多模态版)」技能,提取文字后再交给本技能做结构化解析。字迹潦草/连笔的手写花名册,优先用「通用印刷体识别(高精度版)」,不要退化成用视觉模型直接读图
- 花名册/名单是表格文件(xlsx/csv) → 调用「表格识别」技能,或直接用 Excel 处理能力读取
- 已交作业照片(一摞作业本封面,通常是手写姓名/学号) → 必须走「通用印刷体识别(高精度版)」这类专门OCR技能,这是手写体误识别率最高的环节,也是本技能准确率的关键瓶颈,不能图省事让视觉模型顺手识别
- 点名录音(一段音频) → 调用「音频转写」相关技能,得到文字转写稿后再交给本技能提取姓名/学号
- 实时语音输入 / 第三方软件语音转写的文字 → 无论这段姓名文字是用 WorkBuddy 实时语音、还是用其他 App(讯飞/微信/Otter 等)先把人声转成文字再粘贴进来的,只要源头是人声,统一标记
source="voice",走拼音匹配。不要因为收到的是纯文本就误标成image(拍照/OCR 才用字形)。匹配方法看的是"错误模式"(语音→同音、图像→形近),不看哪个软件做的转写 - 结果需要写入 Excel → 调用 Excel 读写技能,把本技能算出的"已交/缺交"或"已到/缺席"结果填入用户指定的工作表和列
本技能自身不做OCR、不做语音转写,只负责解析识别结果、和花名册做匹配、生成结构化的核对结果。如果当前环境确实没有可用的专门OCR技能、只能退化成用视觉模型直接识别,必须在结果里明确提示用户"本次识别未使用专门OCR技能,准确率可能低于预期,手写体请务必逐条核对",不要悄悄降级却不说明。
工作流程
步骤 1:确定花名册
优先级:用户本轮对话直接提供的名单 > 之前保存过的班级花名册文件(如果用户提到"沿用上次的花名册",去 references/ 或用户指定的路径找)。
花名册解析规则(无论来源是文本、表格识别结果还是图片OCR结果,统一走这一步):
- 每条记录尽量拆出 学号(数字)和 姓名(中文,2-4字为主)两个字段
- 允许只有姓名或只有学号
- 忽略"姓名""学号""序号""班级"这类表头字样
步骤 2:解析"已交/已到"识别结果
对 OCR 或语音转写返回的原始文字,提取出候选名单,每条候选记录包含:
- raw_text:识别到的原始文字(保留,用于人工核对时展示)
- name:猜测的姓名(找不到填 null)
- student_id:猜测的学号(找不到填 null)
- source:这条记录的识别来源,image(拍照/OCR)或 voice(语音转写/实时语音输入),下一步匹配时按这个字段选用不同的模糊匹配方式。此字段必须准确标注:语音来源(不论 WorkBuddy 实时语音还是第三方软件转写后粘贴的文字)一律 voice;拍照/OCR 一律 image。标错来源会导致匹配方法用错(语音数据误用字形、或反之),是常见翻车点
步骤 3:和花名册匹配(核心容错逻辑——必须调用脚本,禁止自己现编逻辑)
这一步不允许临时手写匹配代码或凭感觉判断,必须实际执行 scripts/match_roster.py 这个脚本来完成匹配。
原因:曾经实测发现,即使不调用脚本、让模型自己现场写一段匹配逻辑,结果也可能"看起来是对的"(比如手动列出几个同音字对照表,这一次刚好蒙对了)——但这种临时现编的逻辑没有真正走一致的规则,换一批新姓名大概率不会一直蒙对,而且没经过测试验证。scripts/match_roster.py 里的字形编辑距离阈值、拼音编辑距离阈值,都是拿真实翻车案例("向峻辉/何峻辉""程桢皓/陈真浩""王芳/黄芳"等)反复测试调出来的,不是随手定的数字,靠现场发挥重新实现,等于把已经验证过的结果又推倒重来。
具体执行方式:
- 把步骤 1 得到的花名册,整理成 JSON 数组写入临时文件(格式:
[{"id": "...", "name": "..."}, ...]) - 把步骤 2 得到的候选识别结果,整理成 JSON 数组写入临时文件(格式:
[{"raw_text": "...", "name": "...", "student_id": "...", "confidence": "...", "source": "image或voice"}, ...],source 字段必须准确标注这批数据到底是拍照识别还是语音转写得到的,脚本会根据这个字段自动切换字形匹配还是拼音匹配,不需要调用者自己判断用哪种模糊匹配方式) - 执行:
python scripts/match_roster.py --roster <花名册临时文件> --candidates <候选临时文件> --output <结果临时文件> - 读取输出的 JSON(
matched/missing/review/warnings四个字段),基于这份脚本算出的结果组织最终回复给用户的内容,不要在脚本结果之外自己再额外做一遍匹配判断 - 务必检查
warnings字段:从 v1.1.0 起,脚本在「pypinyin 缺失 + 存在语音候选」时会把告警写进warnings并在 stderr 打印。若warnings非空,如实转告用户(例如"本次语音同音匹配未生效,缺 pypinyin 依赖"),不要因为脚本"正常结束"就以为语音容错已经生效
如果执行脚本时报错(比如环境里没装 pypinyin 导致拼音匹配跳过),如实告诉用户"这次语音场景的同音字匹配可能不完整,因为缺少依赖库",不要假装正常运行、也不要退回自己现编逻辑硬撑。
(以下是脚本内部匹配规则的说明,帮助理解结果,不是要求你自己重新实现一遍):
- 图片/OCR来源:错误模式是"字形相近"(比如"向"认成"何"),脚本用字面编辑距离≤1做模糊匹配
- 语音/转写来源:错误模式是"读音相近"(比如"程桢皓"听成"陈真浩",拼音编辑距离≤1),脚本用拼音相似度做模糊匹配
- 不管哪种来源,模糊匹配命中不止一个候选人时,脚本会自动把它归入"待人工核对",不会替用户瞎猜
步骤 4:输出结果
默认只在对话里直接给出三段文字清单:已交/已到、缺交/缺席、待人工核对(附原始识别文字),不要默认生成Excel文件。 生成Excel涉及额外的文件读写和排版步骤,会明显拖慢单次核对的耗时,用户平时高频用的是"快速看一眼谁没交/谁没到",不是每次都要一份正式表格。
只有在用户明确提出导出要求时(比如"导出Excel""生成表格""存成文件""填到XX表里"这类字眼),才调用 Excel 读写技能生成文件。如果用户提供了目标 Excel 工作表并给出具体指令(比如"把已交名单填到考勤表的C列"),按用户指定的表格、列、格式把结果写进去——不要自己臆造表格结构,用户没说清楚写在哪一列/哪个表时,先问清楚再动手改文件。
所有本技能过程中产生的文件(临时JSON、生成的Excel等),一律存放在当前工作间目录下(用户在WorkBuddy里指定的那个工作空间文件夹,不是C盘默认路径,也不是桌面),不允许自行选择桌面或其他路径存放。 这一条和工作间根目录下的 AGENTS.md 全局规则一致,即使这次没有读取到 AGENTS.md,本技能自身也必须遵守这条规则。真实翻车过的反例:曾经在自己写脚本处理时,把中间文件和最终Excel都硬编码存到了 C:/Users/Administrator/Desktop/,用户完全没有被告知、也没有选择过这个位置,属于不该发生的行为。
注意事项
- 手写体/口语化姓名识别不可能100%准,"待人工核对"这一步不是可选项,是必须保留的兜底环节,不要为了"结果好看"擅自把模糊匹配的结果直接归为已交/已到
- 语音点名场景下,同一个学生可能被喊到两次、或者名字被连续误识别成两条记录,匹配后需要按花名册记录去重,不要重复计数
- 花名册一旦确认过,建议持久化保存(写入
references/roster.json或用户指定的位置),避免每次都要重新输入/重新识别 - 真实翻车案例(供参考,不要在没有阈值支撑的情况下凭感觉做匹配):语音点名把"程桢皓"听成了"陈真浩"——字形上"陈/程""真浩/桢皓"完全不像,但拼音都是 zhen hao,属于典型的语音同音误差,应该靠拼音相似度匹配上,而不是字形编辑距离
- 依赖说明(发布/跨环境必读):语音点名场景依赖
pypinyin。执行脚本前若发现未安装,先尝试pip install pypinyin安装(本机/连接电脑模式通常可成功);云端/沙箱执行环境可能禁止pip install,此时 pypinyin 装不上,语音路会自动降级——拼音匹配跳过、相关候选进review。脚本会显式告警(stderr + 结果warnings字段),请在回复里如实告知用户,而不是假装语音容错正常。图片/OCR 场景不依赖 pypinyin,任何环境都能跑满
参考脚本
scripts/match_roster.py 提供了花名册解析、模糊匹配、结果分类的实现——这不是"参考代码",是步骤3必须实际执行的脚本,不是给你抄一遍逻辑用的样板。执行前如发现环境未安装 pypinyin,先尝试 pip install pypinyin 安装依赖,不要绕开脚本自己实现。注意:云端/沙箱执行环境可能禁止 pip install,此时 pypinyin 装不上,语音路会自动降级(拼音匹配跳过、相关候选进 review),脚本会显式告警——请在回复里如实告知用户,而不是假装语音容错正常。