00
前期准备
练习材料
下载材料包| 材料 | 用途 | 文件 |
|---|---|---|
| 脱敏群聊 | 保留九问、消息时间及缺失图片标记 | 群聊_已脱敏.txt |
| 三份制度 | 按正文生效、废止说明和问题时间核对适用版本 | 制度/ |
| 引用核对脚本 | 核文件、条款和数字,输出需解释的提示 | scripts/check_citations.py |
查看练习材料5份材料
员工群聊(脱敏副本)群聊_已脱敏.txt
【教学虚构示例数据:人名、工号、手机号均为编造,非真实员工】 企业微信 聊天记录导出 群聊:青梧科技-HR制度答疑群(52人) 导出时间:2026-10-16 09:12 2026-10-15 09:41:07 员工A @HR 请问我司龄刚满3年,今年除了法定年假还有福利年假吗?有几天? 2026-10-15 09:43:52 员工B(HR) 收到,我统一整理后回复大家 2026-10-15 10:02:15 员工C 去年的年假我还剩2天没休,现在10月了还能用吗 2026-10-15 10:05:40 员工D 工作日加班到晚上11点,可以换调休吗?我记得以前是可以1:1调休的 2026-10-15 10:06:03 员工D [图片] 2026-10-15 11:20:33 员工E 福利年假没休完能折现吗?手机[手机号] 方便的话电话说下 2026-10-15 14:08:19 员工F 上周出差去上海住了680一晚,超标的部分能报吗? 2026-10-15 14:10:02 员工F 另外 发票我只有截图可以吗 2026-10-15 15:33:47 员工G 我们组实习生[同事]问能不能请病假,实习生适用这个考勤制度吗 2026-10-15 16:47:10 员工A 还有,我下个月结婚,婚假一共几天?@员工G 你上次休了几天来着 2026-10-15 17:02:55 员工H 公司明年会不会涨薪啊 哈哈
差旅报销 v1.4差旅与费用报销制度_v1.4.pdf
青梧科技 差旅与费用报销制度(v1.4) 文号 QW-FIN-003 生效日期 2026-03-01 【教学虚构示例,非真实制度】 第一章 总则 第一条 本制度适用于公司全体员工因公发生的差旅及费用。 第二章 差旅标准 第六条 住宿标准:一线城市每晚不超过 600 元,其他城市每晚不超过 400 元。 第七条 出差补贴每天 100 元,含餐费与市内交通。 第八条 高铁二等座、飞机经济舱可直接报销;其他舱位须事前经部门负责人审批。 第三章 报销流程 第十二条 费用须在发生后 30 天内提交报销,逾期须附情况说明并经财务负责人批准。 第十三条 电子发票须上传原始 PDF/OFD 文件,截图不予受理。
考勤休假 v3.0考勤与休假管理制度_v3.0.pdf
青梧科技 考勤与休假管理制度(v3.0) 文号 QW-HR-007 生效日期 2026-07-01 本版生效后 v2.2 同时废止 【教学虚构示例,非真实制度】 第一章 总则 第一条 本制度适用于与公司签订劳动合同的全体员工。实习生另行约定。 第二条 考勤以企业微信打卡记录为准。 第二章 工作时间与打卡 第五条 标准工作时间为 9:30—18:30,午休 1 小时。 第六条 迟到 30 分钟以内且当月累计不超过 3 次的,不扣薪;超过的按事假半天计。 第七条 漏打卡每月可补卡 3 次,须在 3 个工作日内于企业微信提交补卡申请。 第三章 休假 第十一条 年休假按国家规定执行:累计工作满 1 年不满 10 年的 5 天,满 10 年不满 20 年的 10 天,满 20 年的 15 天。 第十二条 公司另给予司龄满 3 年的员工每年 2 天福利年假,福利年假当年有效,不跨年、不折现。 第十三条 法定年休假当年未休完的,可顺延至次年 3 月 31 日前休完。 第十四条 病假须提供二级及以上医院诊断证明;连续病假 3 天以内可事后 2 个工作日内补交。 第十五条 婚假 3 天;在公司工作期间登记结婚的,另给予 7 天福利婚假,须在登记之日起 1 年内一次休完。 第四章 加班与调休 第十八条 工作日加班不再安排调休,按审批后的加班时长发放加班费;休息日加班优先安排 6 个月内调休。
考勤休假 v2.2(旧版)考勤休假制度(最终版).pdf
青梧科技 考勤与休假管理制度(v2.2) 文号 QW-HR-007 生效日期 2024-01-01 【已于 2026-07-01 废止,被 v3.0 替代】 【教学虚构示例,非真实制度】 第一章 总则 第一条 本制度适用于全体员工及实习生。 第二章 工作时间与打卡 第五条 标准工作时间为 9:00—18:00。 第六条 迟到 15 分钟以内每月不超过 2 次的不扣薪。 第七条 漏打卡每月可补卡 2 次。 第三章 休假 第十一条 年休假按国家规定执行。 第十二条 司龄满 2 年的员工每年额外享有 3 天福利年假,未休部分可按日工资折现。 第十三条 当年未休完的年休假可顺延至次年 6 月 30 日。 第十五条 婚假 3 天,另给予 10 天福利婚假。 第四章 加班与调休 第十八条 工作日加班可按 1:1 申请调休,调休须在 3 个月内使用。 第十九条 调休未使用完的,年底统一折算为加班费。
引用核对脚本scripts/check_citations.py
#!/usr/bin/env python3
"""用 pdftotext 抽条款,核对 AI 答复草稿里的引用(v3)。
用法: python3 check_citations.py <制度目录> <答复草稿.md> [--questions 群聊_已脱敏.txt]
逐条检查:
① 引用的文件 + 条款号是否存在
② 是否把已废止版本当依据
③ 答复里的数字能否在所引现行条款原文里找到(找不到 = 推算/编造/引错,需人工看)
每段答复的结论只会是以下之一:
已核 至少一条引用被脚本核到
需人工 有实际答复文字,且依据里明说“无制度依据/转人工”,脚本无可核的条款,交人判断(合法情形)
未完成核对 认不出答复、答复正文为空(只有标签/提问/依据)、认不出依据字段、或依据里有条款号却认不出文件 —— 不等于没问题
退出码:0 = 全部已核/需人工且无问题;1 = 核到了问题;2 = 未完成核对(含识别到 0 段、段数少于问题数、空输入)
"""
import re, subprocess, sys, pathlib, argparse
CN = "零一二三四五六七八九十百"
CLAUSE = rf"第[{CN}]+条"
ap = argparse.ArgumentParser()
ap.add_argument("pdf_dir"); ap.add_argument("draft"); ap.add_argument("--questions")
a = ap.parse_args()
# ---- 1. 抽条款 ----
clauses, deprecated, ver2file = {}, {}, {}
for pdf in sorted(pathlib.Path(a.pdf_dir).glob("*.pdf")):
txt = subprocess.run(["pdftotext", "-layout", str(pdf), "-"], capture_output=True, text=True, check=True).stdout
v = re.search(r"[((]v(\d+\.\d+)[))]", txt[:300])
if v: ver2file["v" + v.group(1)] = pdf.name # 让「考勤 v3.0」这类简称也能对上文件
deprecated[pdf.name] = bool(re.search(r"已.{0,20}废止", txt[:400]))
parts = re.split(f"({CLAUSE})", txt)
clauses[pdf.name] = {parts[i]: re.sub(r"\s+", "", parts[i+1].split("第")[0]) for i in range(1, len(parts)-1, 2)}
print(f"[抽取] {pdf.name}: {len(clauses[pdf.name])} 条{' ⚠已废止' if deprecated[pdf.name] else ''}")
if not clauses:
print("✗ 未完成核对:制度目录里没有可抽取的 PDF"); sys.exit(2)
# ---- 2. 输入问题数(可选)----
n_questions = None
if a.questions:
chat = open(a.questions, encoding="utf-8").read()
msgs = re.findall(r"^\d{4}-\d\d-\d\d \d\d:\d\d:\d\d (.+)\n(.+)$", chat, re.M)
n_questions = sum(1 for who, body in msgs if "(HR)" not in who and body.strip() != "[图片]")
print(f"[问题] 群聊里员工文字消息 {n_questions} 条(不含 HR 发言和纯图片)")
# ---- 3. 切分答复段:任意级别 Markdown 标题,或「数字. / 问题N」开头的行 ----
draft = open(a.draft, encoding="utf-8").read()
head_re = re.compile(r"^(?:#{2,6}\s*(?:Q|问题)?\s*\d+|\*\*(?:Q|问题)?\s*\d+[.、.]|(?:Q|问题)\s*\d+[.、.::])", re.M)
starts = [m.start() for m in head_re.finditer(draft)]
sections = [draft[s:e] for s, e in zip(starts, starts[1:] + [len(draft)])]
# 去掉文末的汇总表段(标题里没有数字的不会进来;带数字但没有任何字段的,算未识别)
BASIS_RE = re.compile(r"^\s*(?:[-*>]\s*)?(?:\*\*)?(?:依据|出处|来源)(?:\*\*)?\s*[::]", re.M)
# 非答复正文的行:答复类空标签、提问/原问题、备注、分隔线
ANS_LABEL = re.compile(r"^\s*(?:[-*>]\s*)?(?:\*\*)?(?:答复草稿|答复|回复|建议答复|拟答复)(?:\*\*)?\s*[::]\s*(?:\*\*)?")
NON_ANSWER = re.compile(r"^\s*(?:[-*>]\s*)?(?:\*\*)?(?:提问|原问题|员工原问|问题|备注|HR\s*内部)[^::]{0,12}(?:\*\*)?\s*[::]|^\s*(?:-{3,}|\*{3,}|_{3,})\s*$")
def extract_answer(body_lines):
"""从段落正文(已去掉标题、依据行)里取真正的答复文字;空标签、提问、备注、分隔线都不算。"""
quoted = [l for l in body_lines if re.match(r"^\s*>", l)]
if quoted and _collect(quoted): return _collect(quoted) # 有引用块答复时只认引用块(与 v2 一致)
return _collect(body_lines)
def _collect(body_lines):
out = []
for l in body_lines:
if NON_ANSWER.match(l): continue
l = ANS_LABEL.sub("", l) # 「**答复草稿**:xxx」只保留 xxx
l = re.sub(r"^\s*>\s?", "", l) # 引用块符号
if re.search(r"[\u4e00-\u9fa5A-Za-z0-9]", l): out.append(l.strip())
text = "".join(out)
return text if len(re.findall(r"[\u4e00-\u9fa5A-Za-z]", text)) >= 4 else "" # 少于 4 个字不算有答复
problems = unfinished = manual = checked = 0
for sec in sections:
lines = sec.splitlines(); title = lines[0].lstrip("#* ").strip()
for i, l in enumerate(lines[1:], 1): # 段内遇到不带编号的新标题(如「### 汇总」)就截断
if re.match(r"^#{1,6}\s", l): lines = lines[:i]; break
print(f"\n== {title}")
basis_lines = [l for l in lines if BASIS_RE.match(l)]
if not basis_lines:
print(" ✗ 未完成核对:没找到「依据/出处/来源:」字段"); unfinished += 1; continue
basis = "\n".join(basis_lines)
answer = extract_answer([l for l in lines[1:] if l not in basis_lines])
if not answer:
print(" ✗ 未完成核对:没有实际答复文字(只有标题/标签/提问/依据/分隔线)"); unfinished += 1; continue
cites, cur = [], None
for tok in re.finditer(rf"([^\s/《》【】\[\]]+?\.pdf)|(v\d+\.\d+)|({CLAUSE})", basis):
if tok.group(1): cur = tok.group(1)
elif tok.group(2): cur = ver2file.get(tok.group(2), cur)
elif cur: cites.append((cur, tok.group(3)))
if not cites:
if re.search(CLAUSE, basis):
print(" ✗ 未完成核对:依据里有条款号,但认不出是哪个文件"); unfinished += 1
elif re.search(r"[::]\s*(\*\*)?无|无.{0,12}(依据|条款|规定)|没有.{0,8}(依据|条款|规定)|未涉及|转人工|负责人确认", basis):
print(" · 需人工:依据写明无制度条款,交人判断"); manual += 1
else:
print(" ✗ 未完成核对:依据字段里认不出任何条款"); unfinished += 1
continue
used_text, sec_ok = "", False
for f, c in cites:
if f not in clauses: print(f" ✗ 文件不存在: {f}"); problems += 1; continue
if c not in clauses[f]: print(f" ✗ 条款不存在: {f} {c}"); problems += 1; continue
sec_ok = True
i = basis.find(f); ctx = basis[max(0, i-30):i+len(f)+15] if i >= 0 else basis
if deprecated[f]:
if re.search(r"对照|旧|废止|当时有效", ctx): print(f" · 引了废止版 {f} {c},标明为对照/当时有效(人工确认措辞)")
else: print(f" ✗ 以废止版为依据: {f} {c}"); problems += 1; continue
else: used_text += clauses[f][c]
print(f" ✓ {f} {c}: {clauses[f][c][:40]}")
checked += sec_ok
clean = re.sub(r"v\d+\.\d+|20\d\d[-年./]\s*\d{1,2}\s*[-月./]\s*\d{1,2}\s*日?|20\d\d\s*年\s*\d{1,2}\s*月|\d{1,2}\s*月\s*\d{1,2}\s*日|20\d\d\s*年?", "", answer) # 去掉日期,避免把 7 月 1 日 当成可疑数字
for n in sorted(set(re.findall(r"\d+(?:\.\d+)?", clean))):
if used_text and n not in used_text:
print(f" ? 答复里的数字 {n} 不在所引现行条款原文中(推算/编造/引错,需人工核)"); problems += 1
n = len(sections)
print("\n---- 汇总 ----")
print(f"识别答复段 {n}" + (f" / 输入问题 {n_questions}" if n_questions is not None else "(未给 --questions,无法核对是否每个问题都有答复)"))
print(f"已核 {checked} 段;需人工 {manual} 段;未完成核对 {unfinished} 段;需处理问题 {problems} 处")
if n == 0:
print("✗ 未完成核对:一段答复都没认出来(格式变了或文件为空),这不代表没有问题"); sys.exit(2)
if n_questions is not None and n < n_questions:
print(f"✗ 未完成核对:答复段 {n} 少于问题 {n_questions},有问题没答或没认出"); sys.exit(2)
if unfinished:
print("✗ 未完成核对:上面标「未完成核对」的段落脚本没核,请人工看或调整格式后重跑"); sys.exit(2)
sys.exit(1 if problems else 0)
01
处理自己的群聊原件
查看可选处理方法与完整历史回放
命令(复制后在练习目录执行)
mkdir -p 私密 答疑工作目录/制度 && cp 材料/*.pdf 答疑工作目录/制度/ && python3 scripts/redact_chat.py 材料/企业微信聊天记录_HR答疑群_20261015.txt 答疑工作目录/群聊_已脱敏.txt 私密/对照表.csv
02
起草九问答复
发给智能体的完整输入
制度 文件夹里是公司制度 PDF,群聊_已脱敏.txt 是员工在答疑群里的提问。帮我给每个问题写一条答复草稿,存成 答复草稿.md,每条注明出自哪个文件第几条。
03
04
先改已确认的问题
发给智能体的完整输入
核对结果.txt 是我用脚本查答复草稿.md 的结果。第5条超标部分怎么处理、第4条企业微信查余额,制度里都没写,改成请员工找对应负责人确认;第2条去年年假要按当时有效的版本说。其余你对照核对结果自查一遍,改好后直接覆盖答复草稿.md。
05
补齐条件,形成完整终稿
发给智能体的续修请求
请回原群聊和制度再核九问:去年年假先分清类型及过渡安排,上海适用档次未确认,婚假保留在职登记条件;缺图属于加班消息,别挂到发票。统一版本说明、短答、出处和待确认项,不替负责人作结论。运行材料里的核对脚本并解释提示,另存完整的 答复终稿.md 和核对日志,前稿保留。
发给智能体的续修请求
再改两处:去年年假别在分支中先说“无法再休”,类型、记录和过渡安排未核定。680高于制度列出的400、600两档上限,不能写“无法判断是否超标”;待确认的是具体档次及处理。登记日期是未提供,不是未定。把条款已核与个案待确认分开标,精简重复说明,同步短答、版本说明和汇总,另存完整修正版并重跑日志。
发给智能体的续修请求
通查并删去材料没写的“加班前审批”和“企微加班审批”等要求;缺图请补回,审批方式待确认。“条款已核”仅说明脚本和AI回源核对,不称人工审核。终稿删制作轮次和重复改动说明,九问、出处与待确认条件保留,另存 答复终稿-修正版2.md 并重跑日志。
发给智能体的续修请求
第8问的登记日期未知,只能说“材料未提供”;“非已排定”仍是在猜,删去,也别写已定或未定。只修这类未知状态的表述,九问、条款、汇总和待确认项保留,另存完整的 答复终稿-修正版3.md 并重跑核对日志。
发给智能体的续修请求
汇总表第8问的“一年内休完”请明确对应福利婚假,与该问短答一致,别让读者理解成全部10天的期限。其他内容保留,另存完整的 答复终稿-修正版4.md,并同步重跑核对日志。
发给智能体的续修请求
第二问中,旧版第十三条未分法定或福利,别把顺延只放法定分支;福利假能否同样顺延也待负责人确认。各问状态括注改为“见A…”或与待确认表补齐,避免漏项。其他内容保留,另存完整的 答复终稿-修正版5.md,并重跑核对日志。
发给智能体的续修请求
第2问的现行对照补清:v3.0仅法定年假顺延至次年3月31日,福利年假不跨年;旧版十三条仍未分类。其余内容保留,另存完整的 答复终稿-修正版6.md,并重跑核对日志。日志和聊天回复只描述文件里实际改动。
06