Files
obsidian/study/courses/pm/report.md

16 KiB
Raw Permalink Blame History

基于手机的招聘代理平台系统设计说明书

1 引言

1.1 项目背景

在互联网招聘场景中,企业普遍面临以下问题:

  • 试题缺乏针对性,无法准确考察岗位所需能力;
  • 试题缺乏时效性,不能反映最新项目技术栈或业务需求;
  • 试题的录入与维护成本高,复用性差,题库质量难以持续优化。

为此,设计并实现一个招聘试题代理定制服务平台(下称“本平台”),以“岗位需求 + 项目场景 + 应聘者背景”为驱动,自动生成个性化试题并持续优化题库质量,为多家招聘企业提供 SaaS 级服务。

1.2 设计目标

  • 提供多角色协同的在线招聘试题定制与考试平台;
  • 支持岗位级别的试卷自动生成与个性化定制;
  • 支持在线答题、自动评分、结果分析
  • 通过统计与反馈驱动的算法持续优化题库质量;
  • 面向多租户企业,以云端部署形式提供服务。

2 业务概述与角色

2.1 业务角色

  1. 招聘企业 HR

    • 维护岗位信息与能力要求;
    • 配置试题策略(题量、题型比例、难度分布);
    • 发布考试、查看统计报表;
    • 对试题效果给出评价与反馈。
  2. 应聘者 Candidate

    • 注册/登录平台;
    • 选择目标岗位,领取并完成在线试卷;
    • 查看成绩与解析;
    • 对题目给出主观评价(难度、贴合度、清晰度等)。
  3. 平台管理员 Admin

    • 审核企业接入与企业题库;
    • 管理系统题库、试题标签、难度标注;
    • 监控题目质量与淘汰策略执行;
    • 管理模型训练与推荐策略。
  4. 内部系统模块(逻辑角色)

    • Question Service:题库管理、题目 CRUD
    • Exam Service:考试流程管理、会话控制;
    • Scoring Service:自动评分与统计;
    • ML / Recommendation Service:试题生成与质量评估。

3 UML 视图

3.1 用例图Use Case Diagram

3.2 核心业务活动图Activity Diagram

3.3 时序图Sequence Diagram

3.4 类图Class Diagram

3.5 ER 图(实体–关系图)

4 数据结构与数据库设计

4.1 主要数据表概述

user

字段名 类型 说明
id (PK) INT 用户 ID
company_id INT (FK company.id) 所属公司(应聘者可为空)
name VARCHAR 姓名
email VARCHAR (UNIQUE) 登录邮箱
role ENUM HR / CANDIDATE / ADMIN
password_hash VARCHAR 加密后的密码
created_at DATETIME 注册时间

company

字段名 类型 说明
id (PK) INT 公司 ID
name VARCHAR 公司名称
industry VARCHAR 所属行业
size VARCHAR 规模(人数区间)

candidate_profile

字段名 类型 说明
id (PK) INT 主键
user_id (FK) INT 对应 user.id
degree VARCHAR 学历
years_experience INT 工作年限
skill_tags JSON/VARCHAR 技能标签集合
resume_url VARCHAR 简历文件存储地址

job_position

字段名 类型 说明
id (PK) INT 岗位 ID
company_id (FK) INT 所属公司
title VARCHAR 岗位名称
level VARCHAR 岗位级别
required_skills JSON/VARCHAR 要求技能标签
description TEXT 岗位详细说明
exam_policy_id VARCHAR(FK) 对应考试策略 ID

exam_policy

字段名 类型 说明
id (PK) VARCHAR 策略 ID
total_questions INT 总题量
easy_ratio FLOAT 容易题比例
medium_ratio FLOAT 中等题比例
hard_ratio FLOAT 困难题比例
type_ratio JSON 题型比例(单选/多选/编程等)

question

字段名 类型 说明
id (PK) INT 题目 ID
content TEXT 题干
type VARCHAR 题目类型
skill_tag VARCHAR 技能标签
difficulty INT 难度等级 15
source VARCHAR 来源(企业题/通用题等)
is_active BOOLEAN 是否在用

question_stats

字段名 类型 说明
question_id(PK) INT 对应 question.id
used_count INT 被使用次数
avg_score FLOAT 平均得分
correct_rate FLOAT 正确率
discrimination FLOAT 区分度
feedback_score FLOAT 反馈评分均值
last_used_at DATETIME 最近使用时间

exam_template

字段名 类型 说明
id (PK) INT 试卷模板 ID
job_id (FK) INT 对应岗位
policy_id (FK) VARCHAR 对应策略
question_slots JSON 题目占位或题目列表

exam_session

字段名 类型 说明
id (PK) INT 考试会话 ID
candidate_id INT 应聘者(user.id
job_id INT 岗位 ID
template_id INT 使用的模板 ID
start_time DATETIME 开始时间
submit_time DATETIME 提交时间
total_score FLOAT 总分
status VARCHAR ONGOING / DONE

answer

字段名 类型 说明
id (PK) INT 答案 ID
session_id INT 所属考试会话
question_id INT 对应题目
content TEXT 作答内容
score FLOAT 得分
time_taken FLOAT 作答耗时(秒)

question_feedback

字段名 类型 说明
id (PK) INT 反馈 ID
question_id INT 对应题目
from_user_id INT 反馈人用户 ID
session_id INT 所在考试会话
rating INT 评分15
comment TEXT 文本评价
created_at DATETIME 创建时间

5 系统架构与部署设计

5.1 分层架构说明

  1. 客户端层Clients

    • HR Web 前端Vue/React SPA
    • 应聘者 Web/H5/APP
    • 通过 HTTPS 调用后端 REST API。
  2. 接入层Gateway

    • Nginx 作为统一入口;
    • 实现 HTTPS 终止、静态资源分发、反向代理和负载均衡。
  3. 应用服务层Services

    • Auth Service登录、鉴权、Token 管理;
    • Job & Company Service:企业与岗位管理;
    • Question Service:题库管理、统计指标计算;
    • Exam Service:考试流程、会话管理;
    • Scoring Service:客观题 & 主观题自动评分;
    • ML / Recommend Service:试题生成、质量打分、模糊定制;
    • Admin Console:运营后台接口。
  4. 数据层Data Layer

    • 关系型数据库MySQL/PostgreSQL
    • Redis 缓存热点题目、会话状态;
    • 对象存储存放题目附件、解析文档;
    • 日志分析存储ELK/ClickHouse 等)。

5.2 部署/组件图

6 核心算法设计

6.1 自适应试题生成算法

6.1.1 目标

在满足岗位需求与考试策略(题量、题型、难度分布)的前提下,为特定岗位与候选人生成一套“技能匹配度高、区分度好、不过时”的个性化试卷。

6.1.2 关键输入

  • job:岗位信息(required_skillslevel 等)
  • policy:试题策略(题量、难度比例、题型比例)
  • candidate_profile:候选人画像(技能标签、经验)
  • question_bank:题库(含 QuestionStats 统计信息)

6.1.3 题目综合评分函数

对题目 q 计算综合得分 score(q)

  • skill_match:技能匹配度;
  • difficulty_fit:难度适配度;
  • freshness:新鲜度;
  • discrimination:区分度;
  • bad_feedback:负反馈惩罚。

线性组合示意:

score(q) = w1 * skill_match
         + w2 * difficulty_fit
         + w3 * freshness
         + w4 * discrimination
         - w5 * bad_feedback

6.1.4 伪代码示例

def generate_exam_paper(job, policy, candidate_profile, question_bank):
    # 1. 抽取岗位 & 候选人技能标签
    job_skills = extract_skill_tags(job.required_skills)
    cand_skills = extract_skill_tags(candidate_profile.skill_tags)

    # 2. 候选题集合:技能相关 & 在用
    candidates = [
        q for q in question_bank
        if q.is_active and overlap(q.skill_tag, job_skills | cand_skills)
    ]

    scored_questions = []
    for q in candidates:
        stats = q.stats  # QuestionStats

        skill_match = jaccard(q.skill_tag, job_skills | cand_skills)
        difficulty_fit = 1.0 - abs(q.difficulty - target_difficulty(job)) / 4.0
        freshness = time_decay(now() - stats.last_used_at)
        discrimination = stats.discrimination
        bad_feedback = max(0, 1 - stats.feedback_score)

        score = (
            0.30 * skill_match +
            0.25 * difficulty_fit +
            0.15 * freshness +
            0.25 * discrimination -
            0.05 * bad_feedback
        )
        scored_questions.append((q, score))

    # 3. 按得分排序
    scored_questions.sort(key=lambda x: x[1], reverse=True)

    # 4. 按策略约束(题型 + 难度 + 数量)筛选
    selected = []
    counters = init_counters(policy)

    for q, s in scored_questions:
        if not satisfy_policy(q, counters, policy):
            continue
        selected.append(q)
        update_counters(q, counters)

        if len(selected) >= policy.total_questions:
            break

    # 5. 生成试卷模板对象
    return build_exam_paper_template(job.id, policy.id, selected)

6.2 自动评分算法

拆分为客观题与主观题评分。

6.2.1 客观题评分

  • 单选/判断:完全匹配得满分;
  • 多选:集合比对,可支持“部分正确部分得分”;
  • 填空:字符串归一化后精确匹配。
def score_objective_question(question, candidate_answer):
    correct = question.standard_answer

    if question.type in ("single_choice", "true_false"):
        return question.full_score if candidate_answer == correct else 0.0

    if question.type == "multi_choice":
        cand_set = set(candidate_answer)
        corr_set = set(correct)
        if cand_set == corr_set:
            return question.full_score
        if cand_set.issubset(corr_set):
            return question.full_score * len(cand_set) / len(corr_set)
        # 选错选项则记 0 分
        return 0.0

    if question.type == "blank":
        return question.full_score if normalize(candidate_answer) == normalize(correct) else 0.0

    return 0.0

6.2.2 主观题评分(规则 + 关键词覆盖率)

简化实现:基于关键词覆盖率进行线性赋分。

def score_subjective_question(question, candidate_answer):
    tokens = tokenize(candidate_answer)  # 分词+规范化
    key_points = question.key_points     # 关键点列表

    hit = sum(1 for k in key_points if k in tokens)
    coverage = hit / len(key_points) if key_points else 0.0

    return question.full_score * coverage

6.2.3 会话总分计算

def score_exam_session(session):
    total = 0.0
    for answer in session.answers:
        q = load_question(answer.question_id)
        if q.type in ("single_choice", "multi_choice", "true_false", "blank"):
            s = score_objective_question(q, answer.content)
        else:
            s = score_subjective_question(q, answer.content)

        answer.score = s
        total += s

    session.total_score = total
    persist_scores(session)
    return total

6.3 试题质量评估与淘汰算法

6.3.1 目标

根据题目使用情况、得分表现与主观反馈,动态计算题目质量分 quality_score。当样本量充足且质量分低于阈值时,将题目标记为淘汰候选。

6.3.2 伪代码示例

def update_question_statistics(question_id):
    # 1. 从数据库汇总最新统计信息
    stats = aggregate_stats_from_answers_and_feedback(question_id)
    # 包含used_count, avg_score, correct_rate,
    #       discrimination, feedback_score, last_used_at

    # 2. 计算质量分
    quality = (
        0.25 * stats.correct_rate +
        0.35 * stats.discrimination +
        0.25 * stats.feedback_score +
        0.15 * freshness_factor(stats.last_used_at)
    )

    # 3. 更新统计表
    save_question_stats(question_id, stats, quality)

    # 4. 判定是否进入淘汰池
    MIN_USED = 30
    THRESHOLD = 0.4

    if stats.used_count >= MIN_USED and quality < THRESHOLD:
        mark_question_as_candidate_for_deprecation(question_id)

6.4 模糊定制题目推荐算法

6.4.1 场景

HR 只输入自然语言岗位描述(如“做高并发订单系统的 Java 后端工程师”),系统自动推荐若干候选题目供其选择。

6.4.2 思路

  1. 使用文本向量化TF-IDF 或预训练 Embedding对岗位描述和题目文本编码
  2. 计算岗位向量与题目向量间的余弦相似度;
  3. 返回相似度最高的 Top-K 题目。

6.4.3 伪代码

def fuzzy_recommend_questions(job_free_text, question_bank, top_k=50):
    job_vec = encode_text(job_free_text)  # 向量化岗位描述

    scored = []
    for q in question_bank:
        q_text = q.content + " " + q.skill_tag
        q_vec = encode_text(q_text)
        sim = cosine_similarity(job_vec, q_vec)
        scored.append((q, sim))

    scored.sort(key=lambda x: x[1], reverse=True)
    return [q for q, _ in scored[:top_k]]

7 总结

本报告从业务角色与流程出发,给出了招聘试题定制平台的完整系统设计方案:

  • 业务层面:明确 HR、应聘者、平台管理员等角色及其用例
  • 模型层面:通过 UML 用例图、活动图、时序图、类图与 ER 图,刻画系统的结构与行为;
  • 数据层面:设计了围绕“岗位–试卷–试题–作答–反馈”的关系型数据库模型;
  • 架构层面:采用客户端–接入层–服务层–数据层的分层部署方案,便于扩展与运维;
  • 算法层面:给出自适应试题生成、自动评分、试题质量评估与模糊定制等核心算法的伪代码。