generated from kgod/ai-review-template
feat: builder 简历生成 + 轻度优化 + 简历导入交付副本
自内部仓库剥离深度优化与 RAG 知识库后的交付版本: - Builder 对话式简历生成(FSM + 意图路由 LLM 兜底增强) - 条目级轻度优化:事实覆盖门禁 + STAR/bullet 修复链,功能/简介/成果与技术栈同级保护 - 简历导入:DOCX/PDF 解析、结构归一、手机号脱敏 - PostgreSQL 运行时 + Alembic 迁移链 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
"""Candidate-only skill recommendations for the resume preview editor."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from .skill_classifier import classify_skills
|
||||
from .skill_suggester import SkillSuggester
|
||||
|
||||
|
||||
def recommend_skill_candidates(
|
||||
profile: dict[str, Any],
|
||||
existing_skills: list[str],
|
||||
question: str,
|
||||
suggester: SkillSuggester,
|
||||
) -> list[dict[str, Any]]:
|
||||
"""Return suggestions only; callers must never write them into the resume automatically."""
|
||||
working_profile = dict(profile)
|
||||
tags = dict(working_profile.get("tags") or {})
|
||||
tags["skills"] = existing_skills
|
||||
working_profile["tags"] = tags
|
||||
suggestions = suggester.suggest(working_profile)
|
||||
source_text = _profile_text(working_profile).casefold()
|
||||
target = str(working_profile.get("target_position") or "目标岗位").strip()
|
||||
candidates: list[dict[str, Any]] = []
|
||||
for skill in suggestions:
|
||||
clean = str(skill).strip()
|
||||
if not clean:
|
||||
continue
|
||||
group = classify_skills([clean])
|
||||
category = str(group[0]["category"]) if group else "其他技能"
|
||||
supported = clean.casefold() in source_text
|
||||
reason = (
|
||||
"已在你填写的经历中出现,可作为已掌握技能确认。"
|
||||
if supported
|
||||
else f"与{target}及你的提问“{question.strip()}”相关,作为待学习或待确认技能建议。"
|
||||
)
|
||||
candidates.append({
|
||||
"skill": clean,
|
||||
"category": category,
|
||||
"reason": reason[:160],
|
||||
"evidence_supported": supported,
|
||||
})
|
||||
return candidates[:12]
|
||||
|
||||
|
||||
def _profile_text(profile: dict[str, Any]) -> str:
|
||||
values: list[str] = []
|
||||
entries: list[Any] = [profile.get("anchor")]
|
||||
entries.extend(profile.get("experiences") or [])
|
||||
for records in (profile.get("records") or {}).values():
|
||||
entries.extend(records or [])
|
||||
for entry in entries:
|
||||
if not isinstance(entry, dict):
|
||||
continue
|
||||
values.append(str(entry.get("description") or ""))
|
||||
values.extend(str(item) for item in entry.get("highlights") or [] if item)
|
||||
return "\n".join(values)
|
||||
Reference in New Issue
Block a user