马自立的博客
PORTFOLIO · 企业 RAG

员工问政策(生产级)

人事政策问答:规则 + RAG + 转人工

员工问人事政策:问题先过人工闸和规则闸,能查表的直接给答案和条款原文,不调模型;其余走 RAG(混合检索 + 重排 + 引用和数字校验),答不准就建工单转人工,工单附上相关条款。每条回答都能评价,Bad 进归因、修复、回归的闭环;HR 工作台看人工介入率和自然通过率。登录演示账户后,按档案里的用工地、参保地和所属公司算出具体天数和金额。手册改版逐条比对、按生效日期切换;内部口径按角色过滤后才检索,每次检索留审计;答过的问题走两级缓存,链路接 LangSmith。演示资料是两份公开的员工手册,修订通知和内部口径是虚构的。

v1.3.0当前版本 · 2026-11-10 更新看更新记录
回作品集
🧾 员工问政策(生产级):能查表的查表,答不准的转人工
3道闸
人工 → 规则 → RAG
7种转人工的情况
工单附相关条款
38/38道自测题路由都对
含 8 道版本和权限题
0道错答
该转人工却答了也是 0
FLOW · 一个问题怎么走

一个问题怎么走

先看要不要交给人,再看能不能查表,最后才交给模型。

① 人工闸

想找人的先找人

  • 只看关键词,不调模型:明说要人工、敏感事项(辞退、赔偿)、查个人数据,直接建工单
  • 「被辞退能赔多少」就算查得到条款也不该让机器答,所以人工闸排第一
  • 身份证、手机号、银行卡在发给模型之前就遮掉,记录和工单里也只存遮过的
② 规则闸

能查表的不交给模型

  • 年假、丧假这类查表题,命中规则直接给答案和条款原文,0 token
  • 缺条件就追问,给按钮选:年假按累计工龄查,先问工龄几年
  • 构建时规则表的每个数字都要在条款原文里找到,对不上就构建失败;规则宁可少命中,漏了只是多走一遍 RAG
③ RAG

校验过了才展示

  • bge-m3 向量 + BM25 混合检索,bge-reranker 重排,DeepSeek 生成,回答带 [1][2] 引用和条款页码
  • 重排分高的直接答;中间的照答,但提示找 HR 核实、给一键转人工;没过门槛就建工单
  • 回答里的天数、金额要在所引条款里找得到才展示,问题里的数字不算,防「婚假是 10 天对吧」这种诱导
DESIGN · 路由设计

一个问题按固定顺序过三道闸

页面右边「这次怎么走的」会实时点亮走到哪一步、为什么走这条路。

路由

text
问题 + 身份(登录了带档案:所属公司、用工地、参保地、角色)
 │  先脱敏:身份证、手机号、银行卡遮掉,后面所有环节只看到遮盖后的文字
 │
 ├─ ① 人工闸(关键词,不调模型)
 │     明说要人工 / 敏感事项 / 查个人数据 ─────────────────────→ 工单
 │
 ├─ ② 规则闸(查表,不调模型)
 │     登录了先按档案匹配:公司制度、属地政策 ──────────────→ 档案直答
 │     命中一条规则 → 缺条件就追问 → 查表 + 条款原文 ────→ 规则直答
 │     没命中,或同时命中多条 ↓
 │
 └─ ③ RAG
       答案缓存:同问题、同身份和角色、同一天、同版本资料 ──→ 直接回答,0 token
       按身份、生效日期、角色圈范围(先过滤,再检索)
       混合检索 → 粗门槛 0.6 → 重排 → 细门槛 0.1 → 生成 → 引用和数字校验
         │                                            │
         │                                            ├─ 重排 ≥ 0.5 高置信 → 回答 + 出处
         │                                            └─ 0.1–0.5 中置信 → 回答 + 出处 + 建议找 HR
         └─ 没过门槛 / 答「手册没写到」/ 校验没过 ────────────→ 工单

为什么这样排

  • 想找人的意愿优先:「被辞退能赔多少」就算查得到条款也不该让机器答,所以人工闸排第一
  • 规则宁可少命中:漏命中只是多走一遍 RAG,错命中会很确定地答错
  • 门槛的取向和个人笔记 RAG 相反:人事答错要赔,宁可多转人工
  • 能查表的不交给模型:规则直答、档案直答都是 0 token,也不进缓存
RULES · 规则

规则是一张表,代码只做匹配和查表

业务能看懂、能维护;每次构建都把规则表的每个数字和条款原文核一遍,对不上就构建失败。

一条规则(rules/rules.json,table 只摆了前 3 行)

json
{
  "id": "annual-leave-days",
  "name": "年假天数(按累计工龄查表)",
  "subject": "fosun",
  "any": ["年假", "年休假", "带薪假"],
  "all": ["几天", "多少天", "天数", "多久", "有多少"],
  "not": ["延期", "没休完", "工资", "折算", "怎么申请", "提前"],
  "clause": "5.16.1",
  "slot": {
    "name": "累计工龄", "kind": "years",
    "ask": "手册按「累计工龄」查表(包括在之前单位的工作年限)。你的累计工龄是几年?",
    "options": ["不满 1 年", "1 年", "3 年", "6 年", "10 年", "20 年"]
  },
  "table": [
    { "lt": 1, "value": "3 天", "src": "累计工龄<1年3天" },
    { "gte": 1, "lt": 2, "value": "5 天", "src": "1年<=累计工龄<2年5天" },
    { "gte": 2, "lt": 3, "value": "6 天", "src": "2年<=累计工龄<3年6天" }
  ]
}

匹配口径

  • any 命中其一、all 命中其一、not 全不命中,才算命中;同时命中多条不猜,交给 RAG
  • 缺条件就追问,给按钮选;手册写「累计工龄」,问「在公司干了 3 年」是司龄,要追问确认
  • 手册只写「难产」,问「剖腹产」不替它推断,追问生育情况

7 种转人工

触发怎么判断调模型吗
用户明说关键词,排除「不用转人工」这类否定否
敏感事项关键词表:辞退、仲裁、工伤赔偿、举报……否
查个人数据「我的 + 工资 / 社保 + 少了 / 查一下」组合否
检索拒答没有候选,或最高余弦 < 粗门槛 0.6只算向量
置信度低重排最高分 < 细门槛 0.1向量 + 重排
生成兜底答「手册没写到」、引用不存在、数字在条款里找不到是
反馈后看完回答点转人工,或打 Bad 并勾「要真人」否

置信度三档(重排分不是概率,只用来排序和切门槛)

档位条件怎么答
高重排 ≥ 0.5回答 + 出处
中0.1 ≤ 重排 < 0.5回答 + 出处 + 建议找 HR 核实,一键转人工
低重排 < 0.1,或余弦 < 0.6不生成,建工单

门槛来自评测:20 道标定题里,该答的题重排最低 0.377,该转人工的最高 0.049,细门槛取 0.1 落在空档里;另外 10 道留出题不参与调门槛。

PRODUCTION · 生产级

真上线要补的四件事,这一版都做了演示

来自一条「生产级 RAG」建议:文件更新、链路监控、权限控制检索、缓存和它的更新策略。

四件事怎么做

问题做法演示里看哪
手册改版修订通知后台异步导入:逐条比对,只给改了的条款重算向量;每条带生效日期,生效前按旧的答并提示;规则表跟着每一版核第 3 题的修订提示;HR 工作台「资料版本」
谁能查什么角色只从档案来;检索之前先按角色过滤,没权限的块进不了提示词;没权限对员工和不存在一样;每次检索留审计登录改角色问「调薪」「试用期转正」;「权限与审计」
链路监控每次提问在 LangSmith 里是一棵 run 树(闸、检索、重排、生成带 token、校验),员工的评价挂成 feedback轨迹最下面「已上报 LangSmith」
缓存两级:进程内存 + 全站共享(Upstash);缓存问题向量、重排结果、答案;键里带问题、身份、角色、日期、资料版本、提示词、模型、门槛,任一变了就重算;被打 Bad 的当场删同一问题问两次:「缓存命中 · 0 token」;看板「问答缓存」

一份修订通知(docs/revisions/,演示虚构)

markdown
---
id: fosun-2026-12
subject: fosun
version: V5.1(演示修订)
effectiveFrom: 2026-12-01
title: 关于修订《员工手册》部分条款的通知(演示虚构)
---
## 修改 5.16.4
5.16.4 ……当年度的年休假可延期使用至次年 6 月 30 日之前。……

## 新增 5.17 远程办公
5.17.1 因个人原因需要远程办公的员工,需至少提前 1 个工作日在系统中申请……
5.17.2 远程办公每月累计不超过 4 天,不可跨月累计……
FEATURES · 它能做什么

它能做什么

按用到的场景分成几类。

按档案匹配

同一个问题,换个人答案就变

  • 登录演示账户,档案里有所属公司、用工地、参保地、累计工龄、工资,能在页面上改
  • 婚假、产假、育儿假按用工地,生育津贴按参保地,两地不一致就提示并给转人工
  • 年假、加班费、病假工资按所属公司的制度,代入档案里的工资算出具体数
HR 工作台

答不准的交人,答错的变回归题

  • 工单带问题、身份、转人工原因、路由轨迹和 3 条相关条款;HR 回复草稿就用这几条起草,改完才能发
  • 每条回答都能打 Good / OK / Bad;Bad 进队列,人工归因 → 修复 → 一键加入回归集 → 跑评测,不自动改答案
  • 看板看人工介入率(拆成四类)和自然通过率,分子分母都摆出来
版本和权限

手册改版、谁能查什么

  • 修订通知后台异步导入:逐条和现行版比对,只给改了的条款重算向量,规则表跟着每一版核,对不上就导入失败
  • 每条条款带生效日期:生效前按旧的答,回答下面提示哪天起有修订;生效后自动切到新版
  • 经理、HR 的内部口径在检索之前按角色过滤,员工查不到就转人工、不知道有这份资料;每次检索留一行审计,链路可接 LangSmith
评测

门槛来自评测,不靠感觉

  • 30 道自己出的题,对照手册原文:20 道用来定门槛,10 道留出不参与调
  • 路由全对,规则误命中 0、该转人工却答了 0、错答 0
  • 重排门槛取 0.1:该答的题最低 0.377,该转人工的最高 0.049,落在中间的空档里
CHANGELOG · 更新记录

从 v1.0.0 到 v1.3.0

每个版本做了什么,新的在上面。

  1. v1.3.0当前版本
    • 问答缓存:两级(进程内存 + 全站共享),缓存问题向量、重排结果和答案;资料、角色、提示词、模型变了自动重算,被打 Bad 的当场删;看板加命中率和省下的调用
    • 权限与审计:加一份《员工关系处理口径》、经理口径补两节;审计页加可见范围、汇总和一组示例记录,改角色也记一笔;「过滤掉的相关资料」只算会进提示词的前几块
    • 项目页加路由设计、规则和「生产级」四件事
  2. v1.2.0
    • 手册改版:修订通知后台异步导入,逐条比对、只给改了的条款重算向量,规则表跟着每一版核;每条条款带生效日期,生效前按旧的答,回答下面提示哪天起有修订
    • 按角色检索:经理、HR 的内部口径在检索之前过滤,员工查不到就转人工、看不出有这份资料;每次检索留审计。HR 工作台加「资料版本」「权限与审计」
    • 接 LangSmith:一次提问一棵 run 树(闸、检索、重排、生成、校验),员工的评价回写成 feedback
    • 作品集里改名「员工问政策(生产级)」;顶栏重新排版,免责声明挪到下面单独一条
  3. v1.1.1
    • 进作品集:页面顶上加「← 项目页」,声明不写公司名
  4. v1.1.0
    • 登录演示账户后按档案回答:婚假、产假按用工地,生育津贴按参保地,年假、加班费、病假工资按所属公司制度,代入工资算出具体数
  5. v1.0.0
    • 上线 matsuri.site:人工闸、规则闸、RAG 三道闸,反馈闭环、HR 工作台和看板,30 道自测题全对
    • 每位访客一份演示数据,7 天不来就过期;手册切块加密放
MORE · 其他项目

其他项目

别的主打项目也各有一页;插件、Skill 和没有在线 Demo 的项目在作品集里。

对哪个项目感兴趣,想提意见,欢迎联系

133 5781 1224