轻松聘AI开发
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

14 KiB

N02 候选评分规则解释与合理性:详细设计

状态:N02 独立代码复验与真实 MySQL/Docker 黑盒验收通过,待 Git 检查点。

文档类型:解释。目标读者为产品负责人、后端开发、独立验收人员和前端联调人员。本设计说明现有候选评分实际上计算了什么、一期应如何向学生解释,以及哪些结论不得从这些分数推出。

1. 背景与目标

当前候选评分由 CandidateScoringCalculator 计算八个维度,并由 CandidateScoringEngineService 写入或读取 candidate_dimension_scores。学生单维接口已有 subScores、reasons 和 dataSources,但这些信息由各计算方法临时拼装,缺少稳定的规则编码、解释版本、适用范围和限制说明。

N02 的一期目标是让学生能够回答以下问题:

  1. 这个分数使用了哪些数据;
  2. 哪些确定性规则实际命中;
  3. 每条规则对当前结果产生了什么影响;
  4. 哪些数据缺失、过期或仍未接入;
  5. 用户可以通过哪些真实、合理的方式完善资料;
  6. 该分数不能代表什么。

N02 同时要求企业端继续只查看聚合分与状态,不获得学生的私人明细、行为次数、测评细分或改进建议。

2. 非目标

一期不做:

  • SHAP、机器学习特征贡献或 AI 生成解释;
  • 人口属性公平性推断;
  • 宣称规则已具备心理测量效度或预测效度;
  • 自动修改评分权重、排名或推荐逻辑;
  • 新增评分事实表、解释历史表或规则配置后台;
  • 向企业暴露学生的细分评分证据;
  • 将行为频次解释为人格、诚信、成长潜力或职业能力;
  • 用解释功能引导用户刷投递、刷消息、刷简历版本。

3. 当前真实实现

3.1 代码入口

  • 计算:mydreamjob-server/src/main/java/com/mydreamjob/candidatescore/CandidateScoringCalculator.java
  • 服务:CandidateScoringEngineService.java
  • 学生与企业接口:CandidateScoringController.java
  • 快照:CandidateDimensionScore.java、CandidateDimensionScoreRepository.java
  • 能力映射:AbilityAssessmentScoreSource.java、AbilityScoreMapper.java
  • 申诉与回滚:candidatescore/governance/
  • 排名:competition/CompetitionRankingCalculator.java

3.2 综合分

当前八维默认展示权重均为 12.50。只有状态为 OK 或 ESTIMATED 且分数非空的维度参与综合分:

overallScore = sum(可计算维度分数) / 可计算维度数量

最终保留两位小数,HALF_UP。PENDING 和 INSUFFICIENT_DATA 被排除后重新归一化,因此两个相同综合分可能来自不同的维度集合。解释必须展示参与维度数量与排除维度,禁止把综合分描述为完整、统一口径的能力总分。

3.3 规则版本

  • 能力测评开关关闭:candidate-scoring-v0.1;
  • 能力测评开关开启:candidate-scoring-v0.2;
  • ABILITY 映射规则:ability-assessment-scoring-v0.1;
  • 历史趋势优先使用快照自身 rulesVersion。

N02 只增加解释契约时不升级候选评分规则版本,建议新增独立的 explanationVersion=candidate-scoring-explanation-v1。只有公式、阈值、参与维度或排名输入发生变化时才升级评分规则版本。

4. 设计原则

4.1 解释必须与计算同源

每个计分分支在计算贡献值的同时生成内部 RuleContribution,不能在 Controller、DTO mapper 或另一套公式中根据最终分数反推解释。

建议内部结构:

RuleContribution
- ruleCode             稳定规则编码
- outcome              APPLIED / NOT_APPLIED / MISSING / EXPIRED / UNAVAILABLE
- contribution         实际加减分;不适用时为 null
- maxContribution      该规则可能贡献的绝对上限
- publicLabel          面向学生的中性名称
- publicObservation    安全的区间或状态,不输出内部数据库字段
- explanationKey       固定解释模板编码

规则元数据由 CandidateScoringExplanationCatalog 按 ruleCode 提供名称、限制、建议和证据等级。计算器产生“事实和贡献”,目录提供“稳定语义”,Assembler 只组合,不重复计算。

当逐项贡献按两位小数展示而整体分数采用 HALF_UP 产生舍入差时,使用 SCORE_ROUNDING_ADJUSTMENT 显式记录对账差;它只解释展示精度,不改变任何评分公式。

4.2 不把解释做成刷分指南

学生可以看到区间和缺失项,例如“近 90 天存在投递记录”“求职偏好尚未完整”,但默认不暴露风控阈值组合、审计动作名称、原始消息数量或内部 SQL 字段。已经在界面契约中公开的固定能力权重可继续展示。

4.3 区分事实、推断与限制

每个维度必须有:

  • whatItMeasures:规则直接使用的数据;
  • interpretation:可谨慎解释的含义;
  • limitations:不能据此得出的结论;
  • evidenceLevel:DIRECT_RULE、SELF_REPORTED、BEHAVIOR_PROXY、UNVALIDATED_PROXY;
  • improvementActions:只给可合理完成的操作,不鼓励刷行为。

5. 一期响应方案

5.1 路径范围

保持现有 4 个路径,不新增 operation:

  • GET /profile/me/candidate-scoring
  • GET /profile/me/candidate-scoring/dimensions/{dimension}
  • GET /profile/me/candidate-scoring/trend
  • GET /company/candidates/{applicationId}/scoring

OpenAPI 路径/操作数保持当前基线 172/210。

5.2 学生综合卡兼容扩展

建议新增:

  • explanationVersion;
  • coverage.computableDimensions;
  • coverage.totalDimensions=8;
  • coverage.includedDimensions;
  • coverage.excludedDimensions[]{dimension,status,reason};
  • comparabilityNotice,固定说明不同参与维度集合的综合分不宜直接比较。

不得返回内部快照 ID、测评结果 ID、题目、答案、审计详情、消息正文或数据库字段名。

5.3 学生单维详情兼容扩展

保留现有 subScores/reasons/dataSources,新增:

  • displayName;
  • whatItMeasures;
  • interpretation;
  • limitations[];
  • evidenceLevel;
  • ruleContributions[];
  • improvementActions[];
  • explanationVersion;
  • validity:仅在存在明确有效期时返回,例如 ABILITY;
  • calculatedAt:本次真实计算基准时间。

ruleContributions 只面向学生本人。旧字段在一期保留,避免前端破坏性升级;文档标记旧 reasons/dataSources 后续逐步由结构化字段替代。

5.4 企业端

企业端保持现有字段:applicationId/overallScore/status/dimensions/generatedAt/rulesVersion。不新增 ruleContributions、limitations、行为次数、学校分档、资料缺失项、四维能力细分或有效期。

企业页面可增加平台级固定说明,但不得把学生解释 DTO 直接复用到企业响应。

6. 时间一致性

computeAll 应在入口生成一次 capturedNow,并传递给所有时间敏感查询与规则:

  • 90 天投递;
  • 30 天登录和活跃操作;
  • 账号月龄;
  • 简历 90 天更新;
  • ABILITY 有效期;
  • calculatedAt 和数据源时间说明。

不得在同一次计算中多次调用 LocalDateTime.now() 形成不同边界。建议注入 Clock,生产使用系统时钟,测试使用固定时钟。

7. 八维解释口径

维度 一期允许的名称 允许解释 禁止解释
EDUCATION 教育背景信息 已填写学历与学校分类规则的确定性结果 智力、能力上限、人才质量
INTERNSHIP 实习经历信息 当前数据源尚未接入 无实习能力、经验不足
ABILITY 四维能力测评 最新有效自研测评的规则化聚合 确定性职业能力、招聘结论
COMPLIANCE 求职偏好完整度 五类偏好字段填写情况 合规意识、服从性
STABILITY 平台求职行为稳定信号 账号时长、撤回与登录形成的行为代理 人格稳定、忠诚度
GROWTH 简历维护与技能展示信号 简历维护和技能标签状态 成长潜力、学习速度
INTEGRITY 履约与资料一致性信号 Offer 响应、反馈与资料完整度的行为代理 道德、诚信人格、信用评级
ACTIVITY 平台求职活跃度 近期投递、平台操作和沟通信号 工作积极性、职业投入度

维度代码为兼容字段,本版不改数据库枚举。产品展示名称采用上述中性名称。

8. 合理性整改分级

8.1 仅解释整改即可上线

  • ABILITY:保留现有公式和有效期,补自评/情境测验限制;
  • INTERNSHIP:保持 PENDING,明确“未接入”不是低分;
  • 综合分:补参与维度和不可横向比较提示。

8.2 需要改名但暂不改公式

  • COMPLIANCE → 求职偏好完整度;
  • STABILITY → 平台求职行为稳定信号;
  • GROWTH → 简历维护与技能展示信号;
  • INTEGRITY → 履约与资料一致性信号;
  • ACTIVITY → 平台求职活跃度。

这里只修改展示语义,不改变维度代码、快照或历史接口。

8.3 需要后续规则版本评审

  • EDUCATION 的学校名单及 45% 权重;
  • STABILITY 的账号时长奖励和撤回惩罚;
  • GROWTH 的简历版本数量奖励;
  • INTEGRITY 的 Offer 接受奖励、过期惩罚和反馈评分;
  • ACTIVITY 的投递、审计和消息计数可操纵性;
  • 缺失维度重新归一化后仍进入企业评分与排名。

任何一项改变分数都必须升级评分版本、完成新旧结果对账和 V32 排名回归,不能混入纯解释提交。

9. 权限与隐私

学生本人可以查看自身安全聚合解释。企业只能查看现有聚合评分卡。ADMIN 沿用治理接口,不因 N02 获得新的个人解释查询入口。

所有 HTTP 响应禁止新增:

  • 原始审计动作、IP、User-Agent;
  • 消息正文或对话对象;
  • Offer 具体企业、岗位或时间线;
  • 评价正文与评价人身份;
  • assessment/ability 的题目、答案、答案键、评分规则和结果 ID;
  • 内部 SQL、表名、快照 ID、用户 ID;
  • 密码、Token、密钥。

学生响应中的数据来源改为产品语义名称,如“个人教育资料”“求职偏好”“平台求职活动”,不直接返回 student_profiles.education/school 等物理字段名。

10. 实现建议

建议新增内部类:

  • CandidateScoringExplanationCatalog:规则元数据白名单;
  • CandidateScoringExplanationAssembler:将 DimensionResult 与规则元数据组装为学生 DTO;
  • RuleContribution、ScoreCoverage 等内部/DTO 类型。

修改:

  • CandidateScoringCalculator:统一 capturedNow/Clock,每个实际分支同步生成贡献;
  • CandidateScoringEngineService:组装覆盖率与学生解释;
  • 学生 DTO:兼容新增字段;
  • OpenAPI、校验脚本、API 和联调文档。

原则上无新 Flyway、无新 ErrorCode、无新公网路径。解释元数据先随代码版本发布,不引入可在线修改规则的后台。

11. 测试与验收

11.1 规则同源

  • 每个阈值边界独立手算;
  • contribution 之和与真实维度分形成可证明关系;
  • 未命中、缺失、过期和不可用规则不能伪造成 0 分命中;
  • 固定 Clock 验证 30/90 天和有效期边界;
  • 不允许修改解释而改变分数,或修改分支后遗漏解释。

11.2 综合分

  • 0、1、2、8 个可计算维度;
  • OK/ESTIMATED 参与,其他状态排除;
  • coverage 与实际参与集合完全一致;
  • 学生综合卡、趋势、企业评分和 V32 排名与既有纯函数对账。

11.3 权限与脱敏

  • STUDENT 仅查看本人;
  • COMPANY 只见聚合字段;
  • ADMIN 不获得新增学生详情入口;
  • 匿名 401,角色越权 403/2002;
  • 对完整 JSON 递归扫描禁止字段;
  • ABILITY 不泄露题目、答案或来源结果 ID。

11.4 防刷与边界评审

用固定样例证明重复投递、发消息、制造简历版本可能改变哪些分数,并在本版明确标为未验证代理信号。若决定保留其排名影响,必须形成书面产品决策和监测指标。

11.5 发布验证

  • N02 专项、候选评分、治理、V32、V38、V39、V41、V42、V43 回归;
  • mvn clean verify;
  • 静态与运行时 OpenAPI 对账;
  • 真实 MySQL 主链路和响应脱敏;
  • 查询前后快照写入行为保持既有语义;
  • 无新增 RabbitMQ 消息。

12. 编码前决策表

编号 决策项 建议方案 状态
D01 N02 是否只做解释,不改任何现有分数、权重和排名 是;规则合理性问题记录为后续独立评分版本 已确认
D02 是否保持现有 4 个接口、0 个新增 path/operation 是 已确认
D03 是否无新 Flyway、无规则配置后台 是 已确认
D04 是否增加独立 explanationVersion,不升级评分 rulesVersion 是,值为 candidate-scoring-explanation-v1 已确认
D05 是否兼容扩展学生综合卡,展示参与/排除维度和可比性提示 是 已确认
D06 是否兼容扩展学生单维详情,增加结构化规则贡献、限制和建议 是 已确认
D07 企业端是否保持现有 schema,不展示任何规则贡献与私人细分 是 已确认
D08 是否采用中性展示名,但保持八个维度代码不变 是 已确认
D09 是否明确 INTEGRITY 不能解释为人格诚信或信用评级 是 已确认
D10 是否明确 GROWTH/STABILITY/COMPLIANCE/ACTIVITY 仅为平台数据代理 是 已确认
D11 是否用单次 capturedNow 并注入 Clock 修复解释时间一致性 是,不改变阈值与公式 已确认
D12 学生是否只看安全区间/状态,不显示可用于刷分的内部计数与审计动作 是 已确认
D13 EDUCATION 学校分档是否暂时保留计算,但增加未验证与公平性警示 暂留,另开评分版本评审决定移除/降权 已确认
D14 缺失维度重新归一化是否暂时保留 暂留,明确可比性限制并在规则评审中决定 已确认
D15 是否安排题库和规则证据验证,不将当前确定性规则称为已验证模型 是 已确认

D01–D15 已全部确认并按本设计实现。若未来 D01、D13 或 D14 的产品决策改变计分,本模块必须另行升级评分规则版本,不能通过解释增强提交混入。