generated from kgod/ai-review-template
自内部仓库剥离深度优化与 RAG 知识库后的交付版本: - Builder 对话式简历生成(FSM + 意图路由 LLM 兜底增强) - 条目级轻度优化:事实覆盖门禁 + STAR/bullet 修复链,功能/简介/成果与技术栈同级保护 - 简历导入:DOCX/PDF 解析、结构归一、手机号脱敏 - PostgreSQL 运行时 + Alembic 迁移链 Co-Authored-By: Claude <noreply@anthropic.com>
112 lines
4.3 KiB
Python
112 lines
4.3 KiB
Python
"""Candidate rewrite guards for the Builder light optimization (截图1/截图2 回归)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from app.builder_conversation import _candidate_rewrite
|
|
|
|
|
|
class _StaticExpander:
|
|
def __init__(self, optimized: str) -> None:
|
|
self.optimized = optimized
|
|
|
|
def expand(self, entry: dict[str, Any], *, context: dict[str, Any]) -> dict[str, Any]:
|
|
return {"optimized_description": self.optimized, "source": "test"}
|
|
|
|
|
|
class _Agent:
|
|
def __init__(self, optimized: str) -> None:
|
|
self.expander = _StaticExpander(optimized)
|
|
|
|
|
|
def test_candidate_rewrite_does_not_inject_identity_into_education_description() -> None:
|
|
"""Identity fields have their own card slots; never merge them into the narrative (截图2)."""
|
|
proposal = _candidate_rewrite(
|
|
_Agent("在学校中学习数据结构、计算机视觉等课程。"),
|
|
{"job_type": "campus"},
|
|
{
|
|
"school": "东莞城市学院",
|
|
"major": "软件工程",
|
|
"degree": "本科",
|
|
"description": "在学校中学习数据结构、计算机视觉等课程。",
|
|
},
|
|
"education",
|
|
)
|
|
|
|
assert proposal["optimized_description"] == "在学校中学习数据结构、计算机视觉等课程。"
|
|
assert "东莞城市学院" not in proposal["optimized_description"]
|
|
|
|
|
|
def test_candidate_rewrite_reports_uncovered_facts_without_appending() -> None:
|
|
"""Uncovered user facts are reported, not stitched onto the candidate (截图1 关键词尾巴)."""
|
|
proposal = _candidate_rewrite(
|
|
_Agent("完成数据库课程项目并参与实验室实践。"),
|
|
{"job_type": "campus", "target_position": "backend engineer"},
|
|
{"description": "完成数据库课程项目。GPA: 4.3/5.0,排名前百分之10。"},
|
|
"education",
|
|
)
|
|
|
|
assert proposal["optimized_description"] == "完成数据库课程项目并参与实验室实践。"
|
|
assert proposal["uncovered_facts"] == ["GPA: 4.3/5.0", "排名前百分之10"]
|
|
|
|
|
|
def test_candidate_rewrite_reports_other_uncovered_user_facts() -> None:
|
|
original = (
|
|
"完成数据库课程项目,使用 Python 和 SQL 实现信息查询。"
|
|
"获得校级一等奖学金,服务 300 名学生。"
|
|
)
|
|
proposal = _candidate_rewrite(
|
|
_Agent("参与学习与实践活动。"),
|
|
{"job_type": "campus"},
|
|
{"description": original},
|
|
"education",
|
|
)
|
|
|
|
assert proposal["optimized_description"] == "参与学习与实践活动。"
|
|
for fact in ("完成数据库课程项目", "Python", "SQL", "获得校级一等奖学金", "服务 300 名学生"):
|
|
assert fact in proposal["uncovered_facts"]
|
|
|
|
|
|
def test_candidate_rewrite_reports_no_uncovered_facts_when_candidate_covers_all() -> None:
|
|
proposal = _candidate_rewrite(
|
|
_Agent("完成数据库课程项目。GPA: 4.3/5.0。"),
|
|
{"job_type": "campus"},
|
|
{"description": "完成数据库课程项目。GPA: 4.3/5.0。"},
|
|
"education",
|
|
)
|
|
|
|
assert proposal["uncovered_facts"] == []
|
|
|
|
|
|
def test_candidate_rewrite_reports_dropped_function_modules() -> None:
|
|
"""功能模块/平台简介被吞时必须进入未覆盖报告(只保留技术栈不算覆盖)。"""
|
|
original = (
|
|
"全栈 AI 求职助手平台,包含 5 大功能模块:\n"
|
|
"1. AI 对话式简历生成助手\n"
|
|
"2. 简历导入 (PDF/DOCX 智能解析)\n"
|
|
"技术栈: Next.js + React"
|
|
)
|
|
proposal = _candidate_rewrite(
|
|
_Agent("• 前端采用 Next.js 与 React 实现响应式界面。"),
|
|
{"job_type": "campus"},
|
|
{"description": original},
|
|
"project_experience",
|
|
)
|
|
|
|
assert any("AI 对话式简历生成助手" in fact for fact in proposal["uncovered_facts"])
|
|
assert any("简历导入" in fact for fact in proposal["uncovered_facts"])
|
|
assert not any("Next.js" in fact for fact in proposal["uncovered_facts"])
|
|
|
|
|
|
def test_candidate_rewrite_tolerates_covered_fragments_without_false_positives() -> None:
|
|
original = "1. AI 对话式简历生成助手\n2. 简历导入智能解析"
|
|
proposal = _candidate_rewrite(
|
|
_Agent("负责 AI 对话式简历生成助手与简历导入智能解析两大模块。"),
|
|
{"job_type": "campus"},
|
|
{"description": original},
|
|
"project_experience",
|
|
)
|
|
|
|
assert proposal["uncovered_facts"] == []
|