03
数据准备
考勤数据准备
attendance-data-prep
把某客户某月的原始考勤源数据,整理成「按员工分文件夹」的结构化目录,并产出标准化员工清单
reference_roster.xlsx,供 attendance-remarks 等下游直接消费。本 skill 只回答「数据从哪来、有哪些人、文件归谁」—— 只做归档与员工清单,不做备注计算。⚡
TRIGGERS
触发场景▸拿到一个月原始考勤源目录,
.msg / Excel / PDF / 图片混杂待整理▸需要先抽附件、AI 视觉预处理、确定员工范围、按人归档
▸下游 attendance-remarks 需要
reference_roster.xlsx 作为输入▸触发词:准备考勤数据 / 考勤归档 / 整理考勤 / 考勤分文件夹
⛔
SESSION GATE
会话入口与前置门禁- G1用户必须先提供目录名GATE目录名指
data/raw/下的子目录名(如202604_客户A),不是脚本自动猜出的路径。用户未提供时暂停询问,不要自动选「最新目录」或看似最匹配的目录。 - G2
SOURCE_DIR不存在则停下重确认GATE由用户提供的DATASET_NAME派生SOURCE_DIR=data/raw/${DATASET_NAME}、OUTPUT_DIR=outputs/${DATASET_NAME}。若SOURCE_DIR不存在,先列出可选目录请用户重新确认,不要继续运行。
↹
INPUT & OUTPUT
输入 / 产出↘ INPUT · 输入
data/raw/<目录名>月度源目录(用户指定)- 可选底表:账单 / 工资 / 人员清单 / 汇总 Excel
.msg邮件及其附件、邮件正文- 考勤 Excel、扫描 PDF、审批截图、签到明细图片
↗ OUTPUT · 产出
- 给人看:
reference_roster.xlsx等 5 个 Excel - 给脚本/LLM:
_prep_summary.json等 JSON / JSONL employees/<姓名>/按人归档 +_sources.json_email_texts.jsonl邮件正文(供 remarks 消费)
📤
ARTIFACTS
产物清单 · 人类件 vs 机器件reference_roster.xlsx · 人类件
标准化员工清单:姓名、身份证号、来源、文件夹、底表行号。下游核心输入。
数据收集汇总.xlsx · 人类件
员工覆盖、问题概览、视觉概览的人类可读汇总。
人工复核清单.xlsx · 人类件
待处理问题与视觉待识别清单。非「附件列表」式交付,是当前未闭环项的索引。
姓名候选复核.xlsx · 人类件
无底表模式专用:列为 候选姓名 / 复核结论 / 来源 / 复核理由,结论填 确认纳入 / 剔除 / 待确认。人工确认入口。
视觉提取结果.xlsx · 人类件
vision_extracted_records.jsonl 的人类可读审阅版,列用中文状态(高/中/低、是/否)。_prep_summary.json · 机器件 / 门禁
员工数、文件数、视觉待处理数等机器汇总,数字须自洽。
_prep_questions.json · 机器件 / 门禁
待追问:
missing_attendance_data / extra_attendance_employee / unmatched_file / uncertain_employee_candidate。对应人工复核清单.xlsx。_vision_manifest.json · 机器件 / 门禁
需 LLM 视觉处理的图片与 PDF 逐页 PNG 清单;含
status: pending/processed 与 needs_pdf_preprocess。_pdf_preprocess.json · 机器件
PDF 逐页预渲染结果索引;预渲染失败时先看其
errors。vision_extracted_records.jsonl · 机器件
AI / 人工视觉中间结果,下游脚本消费。每条须有
source_file 与 page_or_image。vision_extracted_records.reviewed.jsonl · 机器件
人工在视觉复核清单填「人工结论」后,
apply_vision_review.py 回填生成的下游输入;确认/剔除写回 confidence / needs_review / record_status。vision_review_apply_report.xlsx · 人类件
回填汇总/明细;「是否可继续下游」须为「是」(无未匹配结论、无待追问)才把 reviewed JSONL 作为
--vision-records 传回。_email_texts.jsonl · 机器件
邮件正文(按员工归属),remarks 的
--email-texts 消费。employees/<姓名>/_sources.json · 机器件
每个员工目录归档依据:
original_path / match_reason / match_confidence。config_draft.json · 机器件
配置草稿:
attendance_start/end、候选法定假日等。pdf_pages/<pdf标识>/page-NNN.png · 中间件
PDF 逐页 PNG,步骤 2 生成,供视觉逐页识别。
🪜
STEPS
处理流程 · 6 步- 1抽取 .msg 附件
extract_msg_attachments.py把邮件附件解到attachments/,并写_msg_meta.json(含 subject)。 - 2PDF 逐页渲染 PNG
preprocess_pdfs_for_vision.py把所有 PDF 逐页渲染成 PNG。考勤不能依赖 PDF 文本层,即使看似文字型 PDF 也交给视觉逐页识别。加密加--password,字小调--dpi(180–220)。 - 3AI 视觉结构化预处理逐图、逐页 PNG 读取,产出
vision_extracted_records.jsonl+视觉提取结果.xlsx。保留来源定位,不猜身份证 / 小时数 / 日期 / 姓名;看不清写空并needs_review=true。无视觉能力时走 PDF 文本层 fallback。 - 4确定底表GATE扫描源目录 Excel 识别底表候选(文件名含 底表/账单/工资/人员/汇总,表头含 姓名/身份证号/考勤备注/计薪周期)。单候选可继续但须写明依据;多候选必须暂停问用户;无候选进无底表模式。
- 5确定目标员工范围GATE有底表以底表人员为准;无底表先视觉 + 文件名/主题候选,再由 LLM 语义复核,人工确认前不生成 roster、不归档(详见下两节)。
- 6按员工归档
prepare_attendance_data.py按 5 级优先级把文件归入employees/<姓名>/,无法归属进_unmatched/,并产出 roster 与全部汇总文件。
⑃
ROSTER BRANCH
底表分支与姓名候选复核有有底表
以底表人员为目标范围,姓名 / 身份证号优先取自底表,考勤附件仅作交叉校验。底表有人但无考勤 → 标
missing_attendance_data;考勤有人但底表无 → 标 extra_attendance_employee,不可静默丢弃。无无底表
先用结构化考勤 Excel 建清单(须先做完视觉预处理避免漏人),再从文件名 / 邮件主题抽候选 —— 但仅作候选,不能凭正则直接确认。
- ✓LLM 语义复核(仅候选集内)只在代码抽出的候选集合内做 确认 / 剔除 / 存疑,不从邮件正文泛抽姓名(防止「中控」「主题」「个小时」被误识别)。公司名 / 表单名标
rejected,如英伟达、科锐国际、科之锐考勤表。 - ⏸人工确认门禁GATE先输出
姓名候选复核.xlsx并暂停等待人工确认。仅confirmed进 roster;rejected剔除;uncertain不写 roster、写_prep_questions.json(uncertain_employee_candidate)。确认前不得生成 roster 或归档。
👁
VISION RULES
视觉抽取规则与字段字段
source_file · page_or_image · record_type(attendance_detail / approval / summary / special_note / unknown)· confidence · needs_review · review_reason 及姓名/身份证/休假/加班/计薪天等。▸
不猜身份证号 / 小时数 / 日期 / 姓名;看不清、遮挡、手写不确定 → 写空值并
needs_review=true。▸
一图多员工拆成多条;多页 PDF 逐页处理并保留页码来源;一页含多类(年假 + 法定加班 + 周末加班)拆成多条。
▸
钉钉 / 打卡 / 签到明细记为
attendance_detail,不要误当成已审批加班;审批只有「加班到几点」无起算口径,不自行算小时数,写 待追问。▸
小 logo / 二维码 / 签名图等无信息图片也写入并标
unknown,从待识别清单闭环移除。▸
PDF 文本层 fallback:无批量视觉 / OCR 时不能只停在渲染 + pending,须用 PyMuPDF 按页提文本层兜底(
confidence=high,review_reason=pdf_text_layer_fallback)。▸
复核清单不是终点:可处理附件须被打开 / 读取 / 提取并回写
视觉提取结果.xlsx + vision_extracted_records.jsonl,再带 --vision-records 重跑刷新状态。▸
人工结论回填:在
视觉复核清单.xlsx 填「人工结论」(确认 / 剔除 / 需追问)后,用 apply_vision_review.py 回填为 vision_extracted_records.reviewed.jsonl;逐页结论按「来源文件 + 页码」精确匹配,不串到同文件其它页。🗃
FILING
文件归档规则 · 5 级优先级- 1结构化 Excel 内部员工姓名打开
.xlsx,在表头附近读员工姓名字段并归档到对应员工文件夹。 - 2文件名包含员工姓名遍历目标员工清单,文件名命中某员工则归档。
- 3邮件主题包含员工姓名从
_msg_meta.json的subject匹配。 - 4AI 视觉识别结果从
vision_extracted_records.jsonl的employee_name匹配。 - 5无法归属 → _unmatched/放入
_unmatched/,并在_prep_questions.json写对应unmatched_file。 - +多员工共享文件一个文件关联多员工(多人扫描件)时复制到每个员工目录,并在
_sources.json标shared_with。
⇄
PIPELINE
与其他 skill 衔接→
归档结果与
reference_roster.xlsx 喂给 attendance-remarks 按配置计算备注、输出审核报告。若源数据已按员工归档好,可跳过本 skill 直接用 remarks。⤳
底层 PDF 逐页渲染复用
pdf-llm-preprocess skill 的 PyMuPDF 能力,考勤流程用 --all-pages-image 等价全页出图策略。⤳
人类件 vs 机器件边界:给人看 Excel(中文列名、可读状态),给脚本 / LLM 看 JSON / JSONL,默认引用 Excel 说明结果。
⌘
RUN
运行命令 · 三脚本DATASET_NAME="<用户提供的目录名>" # 如 202604_客户A
SOURCE_DIR="data/raw/${DATASET_NAME}"
OUTPUT_DIR="outputs/${DATASET_NAME}"
ATTACHMENTS_DIR="${OUTPUT_DIR}/attachments"
# 1. 抽取 .msg 附件
uv run python skills/attendance/attendance-data-prep/scripts/extract_msg_attachments.py \
"$SOURCE_DIR" "$ATTACHMENTS_DIR"
# 2. PDF 逐页渲染 PNG(加密加 --password,字小调 --dpi 180-220)
uv run python skills/attendance/attendance-data-prep/scripts/preprocess_pdfs_for_vision.py \
"$OUTPUT_DIR" --source-dir "$SOURCE_DIR" --source-dir "$ATTACHMENTS_DIR"
# 3. 按员工归档
uv run python skills/attendance/attendance-data-prep/scripts/prepare_attendance_data.py \
"$SOURCE_DIR" "$OUTPUT_DIR" \
--attachments-dir "$ATTACHMENTS_DIR" \
--base-table "$SOURCE_DIR/<底表文件名>" \ # 有底表时
--vision-records "${OUTPUT_DIR}/vision_extracted_records.jsonl" \ # 有视觉结果时
--name-candidate-review "${OUTPUT_DIR}/姓名候选复核.xlsx" # 无底表且用了候选复核时必传
# 可选:人工在视觉复核清单填「人工结论」后回填为 reviewed JSONL,再带 --vision-records 重跑
uv run python skills/attendance/attendance-data-prep/scripts/apply_vision_review.py \
--records "${OUTPUT_DIR}/vision_extracted_records.jsonl" \
--review-workbook "${OUTPUT_DIR}/视觉复核清单.xlsx" \
--output-records "${OUTPUT_DIR}/vision_extracted_records.reviewed.jsonl" \
--report "${OUTPUT_DIR}/vision_review_apply_report.xlsx"✓
ACCEPTANCE
闭环验收 · 6 条门禁- ✓
reference_roster.xlsx、数据收集汇总.xlsx、人工复核清单.xlsx、_prep_summary.json、_prep_questions.json、_vision_manifest.json均已生成。 - ✓有底表时底表目标员工全部进 roster;无底表时结构化 Excel + 已确认视觉 + 已确认文件名/主题候选均被覆盖。
- ✓
_prep_summary.json数字自洽:员工数 = 有文件员工 + 缺数据员工;未归属文件数与unmatched_file条目一致。 - ✓每个员工文件夹都有
_sources.json,能说明归档来源和匹配原因。 - ✓仍需人工处理的问题进入
人工复核清单.xlsx,并同步保留在_prep_questions.json,不能只写在对话里。 - ✓复核清单中可处理附件已被打开 / 读取 / 提取并回写视觉结果,再重跑归档刷新状态。
- ✓视觉低置信记录已人工复核并经
apply_vision_review.py回填,vision_review_apply_report.xlsx显示可继续下游。
⊘
ANTI-PATTERNS
反例检查✗
文件名 / 邮件主题里的客户名、公司名、部门名、月份标签被误识别成人名。
✗
_vision_manifest.json 仍有 needs_pdf_preprocess=true,却继续把 PDF 当已处理。✗
视觉记录缺
source_file / page_or_image,下游无法追溯。✗
复核清单里还有可打开的附件 / 页面,却没尝试视觉读取或写入
视觉提取结果.xlsx。✗
把签到明细 / 打卡截图直接当成已审批加班,未区分
attendance_detail 与 approval。✗
加班类型 / 结算去向不清楚却强行归类为法定 / 周末 / 工作日加班,未标
needs_review=true。✗
_unmatched/ 有文件但 _prep_questions.json 无对应 unmatched_file。✗
同名员工只靠姓名归档,未用身份证号或待追问区分。
↻
RETRY & LESSONS
失败重试与复盘沉淀⏸
必须暂停询问的条件:
SOURCE_DIR 不存在、底表多候选、无底表且姓名候选未人工确认。↺
PDF 预渲染失败时先看
_pdf_preprocess.json 的 errors,加 --password / 调高 --dpi / 补文件后重跑步骤 2。视觉不可用先做 PDF 文本层 fallback。⤳
限制:只做归档与员工清单,不做备注计算;同名员工需身份证号区分,无法区分进
_prep_questions.json。→
复盘沉淀:新误识别 / 漏归档先写
LESSONS.md,重复后再补 SKILL.md 反例 / 校验 / pytest。已沉淀(复宏汉霖-202605):小 logo / 二维码过滤 + .msg 反向归属员工。