generated from kgod/ai-review-template
feat: initialize resume agent with OfferPai sync
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
"""Deterministic display categories for confirmed resume skills."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterable, Mapping
|
||||
|
||||
_EXACT_CATEGORY_RULES: dict[str, str] = {
|
||||
"sql analysis": "产品、设计与分析",
|
||||
"data analysis": "产品、设计与分析",
|
||||
"user research": "产品、设计与分析",
|
||||
"数据分析": "产品、设计与分析",
|
||||
"用户研究": "产品、设计与分析",
|
||||
}
|
||||
|
||||
_CATEGORY_RULES: tuple[tuple[str, tuple[str, ...]], ...] = (
|
||||
("编程语言与框架", (
|
||||
"python", "java", "javascript", "typescript", "go", "golang", "c++", "c#",
|
||||
"fastapi", "django", "flask", "spring", "spring boot", "node.js", "nodejs",
|
||||
"react native", "pytorch", "tensorflow", "编程语言", "软件工程",
|
||||
)),
|
||||
("前端", (
|
||||
"vue", "react", "angular", "html", "css", "sass", "tailwind", "webpack", "vite",
|
||||
"前端", "小程序",
|
||||
)),
|
||||
("后端与数据存储", (
|
||||
"postgresql", "postgres", "mysql", "sqlite", "redis", "mongodb", "elasticsearch",
|
||||
"kafka", "rabbitmq", "sql", "clickhouse", "后端", "数据库", "缓存", "消息队列",
|
||||
)),
|
||||
("AI 与数据智能", (
|
||||
"langgraph", "langchain", "llamaindex", "rag", "pgvector", "bge-m3", "bge", "tei",
|
||||
"机器学习", "深度学习", "人工智能", "计算机视觉", "自然语言处理", "pandas", "numpy",
|
||||
)),
|
||||
("云、DevOps 与工具", (
|
||||
"docker", "kubernetes", "k8s", "git", "github actions", "gitlab ci", "jenkins",
|
||||
"linux", "terraform", "aws", "azure", "aliyun", "云原生", "容器",
|
||||
)),
|
||||
("产品、设计与分析", (
|
||||
"figma", "axure", "tableau", "power bi", "excel", "data analysis", "sql analysis",
|
||||
"product", "user research", "产品", "原型", "需求分析", "项目管理",
|
||||
)),
|
||||
)
|
||||
|
||||
|
||||
def classify_skills(
|
||||
skills: Iterable[object], preferred: Mapping[str, str] | None = None
|
||||
) -> list[dict[str, list[str] | str]]:
|
||||
"""Group confirmed user skills without changing their display order.
|
||||
|
||||
`preferred` maps skill -> category assigned by the recommender (LLM); it wins
|
||||
over the keyword rules, which remain the fallback for manual edits.
|
||||
"""
|
||||
preferred_normalized = {
|
||||
" ".join(str(skill).casefold().split()): str(category).strip()
|
||||
for skill, category in (preferred or {}).items()
|
||||
if str(category).strip()
|
||||
}
|
||||
grouped: dict[str, list[str]] = {category: [] for category, _ in _CATEGORY_RULES}
|
||||
grouped["其他技能"] = []
|
||||
seen: set[str] = set()
|
||||
for value in skills:
|
||||
skill = str(value or "").strip()
|
||||
normalized = " ".join(skill.casefold().split())
|
||||
if not normalized or normalized in seen:
|
||||
continue
|
||||
seen.add(normalized)
|
||||
category = preferred_normalized.get(normalized) or _EXACT_CATEGORY_RULES.get(normalized) or next(
|
||||
(name for name, keywords in _CATEGORY_RULES if any(keyword in normalized for keyword in keywords)),
|
||||
"其他技能",
|
||||
)
|
||||
grouped.setdefault(category, []).append(skill)
|
||||
return [
|
||||
{"category": category, "skills": values}
|
||||
for category, values in grouped.items()
|
||||
if values
|
||||
]
|
||||
Reference in New Issue
Block a user