| import re |
|
|
|
|
| SKILL_CATALOG = [ |
| |
| "LLM", "RAG", "Agent", "Embedding", "Faiss", "LangChain", "Prompt", |
| "BERT", "GPT", "T5", "Llama", "Qwen", "ChatGLM", "DeepSeek", |
| "文本分类", "命名实体识别", "NER", "Seq2Seq", "Attention", "Beam Search", |
| "自然语言处理", "NLP", "文本生成", "摘要生成", "信息抽取", |
| |
| "推荐系统", "召回", "排序", "重排", "NDCG", "A/B Test", "CTR", |
| "搜索", "Query 理解", "意图识别", "向量检索", "多兴趣", "Semantic ID", |
| "Wide&Deep", "DeepFM", "DIN", "DIEN", "MIND", |
| |
| "TensorFlow", "PyTorch", "OpenCV", "YOLO", "图像分类", "目标检测", |
| "计算机视觉", "CV", "分割", "Transformer", "ViT", |
| |
| "Python", "Java", "Go", "Golang", "C++", "Rust", |
| "Docker", "Kubernetes", "K8s", "微服务", "gRPC", "Thrift", "RPC", |
| "MySQL", "Redis", "Kafka", "消息队列", "Consul", "etcd", |
| "FastAPI", "Flask", "Spring", "Django", "Gin", |
| |
| "SQL", "Hadoop", "Spark", "Flink", "Hive", "Pandas", "NumPy", "Matplotlib", |
| "数据分析", "数据可视化", "指标体系", "漏斗分析", "AUC", "ROC", |
| |
| "机器学习", "深度学习", "强化学习", "scikit-learn", "XGBoost", "LightGBM", |
| "模型训练", "模型评估", "特征工程", |
| |
| "多轮对话", "Function Calling", "Tool Use", "思维链", "CoT", |
| "混合检索", "Hybrid Search", "Reranker", "重排序", |
| "Prompt Engineering", "Few-shot", "RLHF", "SFT", |
| |
| "产品设计", "可视化", "多模态", "CLIP", "Stable Diffusion", |
| ] |
|
|
|
|
| PROJECT_SIGNAL_CATALOG = [ |
| "Semantic ID", "rerank", "MIND", "简历", "JD", "岗位", |
| "检索", "评估", "Demo", "用户兴趣", "多兴趣", "生成式推荐", |
| ] |
|
|
|
|
| def contains(text: str, term: str) -> bool: |
| return term.lower() in text.lower() |
|
|
|
|
| def parse_resume(resume_text: str) -> dict: |
| """Rule-based parser used as the stable fallback for Resume Parser Agent.""" |
| resume_text = resume_text or "" |
| skills = [skill for skill in SKILL_CATALOG if contains(resume_text, skill)] |
| project_signals = [ |
| signal for signal in PROJECT_SIGNAL_CATALOG if contains(resume_text, signal) |
| ] |
| project_signals = list(dict.fromkeys(project_signals + skills)) |
|
|
| has_metrics = bool( |
| re.search(r"ndcg|hitrate|auc|准确率|召回率|提升|%|topk", resume_text, re.I) |
| ) |
| has_llm_project = bool( |
| re.search(r"llm|rag|agent|prompt|deepseek|openai|通义|混元", resume_text, re.I) |
| ) |
| has_rec_project = bool( |
| re.search(r"推荐|召回|排序|mind|semantic id|rerank|用户兴趣", resume_text, re.I) |
| ) |
|
|
| return { |
| "skills": skills, |
| "project_signals": project_signals, |
| "has_metrics": has_metrics, |
| "has_llm_project": has_llm_project, |
| "has_rec_project": has_rec_project, |
| "raw_text": resume_text, |
| } |
|
|
|
|
| |
| |
| |
|
|
| RESUME_LLM_SCHEMA = """{ |
| "skills": ["技能列表"], |
| "project_signals": ["项目信号词"], |
| "has_metrics": true/false, |
| "has_llm_project": true/false, |
| "has_rec_project": true/false |
| }""" |
|
|
| RESUME_LLM_PROMPT = """你是一个简历解析器。请从以下简历文本中提取结构化信息,严格按 JSON Schema 输出。 |
| |
| Schema: |
| {schema} |
| |
| 要求: |
| 1. 只输出 JSON,不要输出任何其他文字 |
| 2. skills 提取所有明确提到的技术名称 |
| 3. has_metrics 判断是否有量化指标(NDCG、准确率、提升 x%、TopK 等) |
| 4. has_llm_project 判断是否有 LLM/RAG/Agent/Prompt 相关项目 |
| 5. has_rec_project 判断是否有推荐/召回/排序相关项目 |
| 6. project_signals 提取项目相关关键词 |
| |
| 简历文本: |
| {resume_text}""" |
|
|
|
|
| def parse_resume_with_llm(resume_text: str, llm_client=None) -> dict: |
| """LLM 增强简历解析,失败自动 fallback 到 parse_resume。""" |
| if llm_client is None: |
| return parse_resume(resume_text) |
| try: |
| from src.llm_client import LLMClient |
| if not isinstance(llm_client, LLMClient) or not llm_client.available: |
| return parse_resume(resume_text) |
| except ImportError: |
| return parse_resume(resume_text) |
|
|
| prompt = RESUME_LLM_PROMPT.format(schema=RESUME_LLM_SCHEMA, resume_text=resume_text[:3000]) |
| result = llm_client.chat_json("你是精确的简历解析器。", prompt) |
| if result is None: |
| return parse_resume(resume_text) |
|
|
| |
| for key in ["skills", "project_signals"]: |
| if key not in result or not isinstance(result.get(key), list): |
| result[key] = [] |
| for key in ["has_metrics", "has_llm_project", "has_rec_project"]: |
| if key not in result: |
| result[key] = False |
| result["raw_text"] = resume_text |
| return result |
|
|