166 lines
6.0 KiB
Python
166 lines
6.0 KiB
Python
"""技能差距分析 AI 引擎
|
|
|
|
差距分析 + 定制简历优化 + Agent 规划/执行。
|
|
依赖:LLM 枚举、skill_gap_analyzer/prompts
|
|
"""
|
|
|
|
import asyncio
|
|
import time
|
|
|
|
from langchain_core.output_parsers import StrOutputParser
|
|
from langchain_core.prompts import ChatPromptTemplate
|
|
|
|
from app.ai.models import LLM
|
|
from app.ai.skill_gap_analyzer.prompts import (
|
|
SKILL_GAP_PROMPT, SUMMARY_OPTIMIZE_PROMPT, EXPERIENCE_OPTIMIZE_PROMPT,
|
|
AGENT_PLAN_PROMPT, AGENT_MODULE_EDIT_PROMPT, AGENT_MODULE_ADD_PROMPT, MODULE_SCHEMAS,
|
|
)
|
|
from app.core.logger import log
|
|
from app.tool.json_helper import parse_llm_json
|
|
|
|
|
|
# ===== 差距分析 =====
|
|
|
|
_skill_gap_chain = (
|
|
ChatPromptTemplate.from_messages([("system", SKILL_GAP_PROMPT), ("human", "请开始分析。")])
|
|
| LLM.DOUBAO_LITE_32K.create(temperature=0)
|
|
| StrOutputParser()
|
|
)
|
|
|
|
|
|
async def analyze_skill_gap(skill_tags: list[str], resume_json: str) -> list[str]:
|
|
"""分析技能差距,返回缺失技能列表"""
|
|
try:
|
|
raw = await _skill_gap_chain.ainvoke({"skill_tags": str(skill_tags), "resume_json": resume_json})
|
|
result = parse_llm_json(raw)
|
|
if isinstance(result, list):
|
|
return [s for s in result if isinstance(s, str) and s in skill_tags]
|
|
return skill_tags # 解析异常降级:全部标记缺失
|
|
except Exception as e:
|
|
log.warning(f"AI技能差距分析失败: {e}")
|
|
return skill_tags # 降级:全部标记缺失
|
|
|
|
|
|
# ===== 定制简历 - summary 优化 =====
|
|
|
|
_summary_optimize_chain = (
|
|
ChatPromptTemplate.from_messages([("system", SUMMARY_OPTIMIZE_PROMPT), ("human", "请开始优化。")])
|
|
| LLM.DOUBAO_LITE_32K.create(temperature=0.3)
|
|
| StrOutputParser()
|
|
)
|
|
|
|
|
|
async def optimize_summary(job_title: str, add_skills: list[str], original_summary: str) -> str:
|
|
"""优化个人概述,融入技能关键词"""
|
|
t0 = time.monotonic()
|
|
try:
|
|
result = await _summary_optimize_chain.ainvoke({
|
|
"job_title": job_title, "add_skills": "、".join(add_skills) if add_skills else "无",
|
|
"original_summary": original_summary or "暂无",
|
|
})
|
|
log.info(f"AI优化summary完成 ({round(time.monotonic() - t0, 2)}s)")
|
|
return result
|
|
except Exception as e:
|
|
log.warning(f"AI优化summary失败: {e} ({round(time.monotonic() - t0, 2)}s)")
|
|
return original_summary
|
|
|
|
|
|
# ===== 定制简历 - experience 优化 =====
|
|
|
|
_experience_optimize_chain = (
|
|
ChatPromptTemplate.from_messages([("system", EXPERIENCE_OPTIMIZE_PROMPT), ("human", "请开始优化。")])
|
|
| LLM.DOUBAO_LITE_32K.create(temperature=0.3)
|
|
| StrOutputParser()
|
|
)
|
|
|
|
|
|
async def optimize_module(job_title: str, job_description: str, module_data: str) -> list | dict | None:
|
|
"""优化单条经历描述,返回修改后的记录数据"""
|
|
t0 = time.monotonic()
|
|
try:
|
|
raw = await _experience_optimize_chain.ainvoke({
|
|
"job_title": job_title, "job_description": job_description or "",
|
|
"original_module_data": module_data,
|
|
})
|
|
result = parse_llm_json(raw)
|
|
log.info(f"AI优化经历模块完成 ({round(time.monotonic() - t0, 2)}s)")
|
|
return result
|
|
except Exception as e:
|
|
log.warning(f"AI优化经历模块失败: {e} ({round(time.monotonic() - t0, 2)}s)")
|
|
return None
|
|
|
|
|
|
# ===== Agent - 规划 =====
|
|
|
|
_plan_chain = (
|
|
ChatPromptTemplate.from_messages([("system", AGENT_PLAN_PROMPT), ("human", "请分析用户指令。")])
|
|
| LLM.DOUBAO_PRO_32K.create(temperature=0)
|
|
| StrOutputParser()
|
|
)
|
|
|
|
|
|
async def plan_edit(job_title: str, job_description: str, resume_json: str,
|
|
chat_history: str, instruction: str) -> dict | None:
|
|
"""Agent 规划:分析用户指令,返回原子操作列表或对话回复"""
|
|
try:
|
|
raw = await _plan_chain.ainvoke({
|
|
"job_title": job_title, "job_description": job_description,
|
|
"resume_json": resume_json,
|
|
"chat_history": chat_history, "instruction": instruction,
|
|
})
|
|
result = parse_llm_json(raw)
|
|
return result if isinstance(result, dict) else None
|
|
except Exception as e:
|
|
log.warning(f"AI规划失败: {e}")
|
|
return None
|
|
|
|
|
|
# ===== Agent - 单条记录修改 =====
|
|
|
|
_record_edit_chain = (
|
|
ChatPromptTemplate.from_messages([("system", AGENT_MODULE_EDIT_PROMPT), ("human", "请执行修改。")])
|
|
| LLM.DOUBAO_PRO_32K.create(temperature=0.3)
|
|
| StrOutputParser()
|
|
)
|
|
|
|
|
|
async def execute_record_edit(job_title: str, job_description: str, instruction: str,
|
|
chat_history: str, module_schema: str,
|
|
record_data: str) -> dict | list | None:
|
|
"""修改单条记录:根据指令修改指定记录数据"""
|
|
try:
|
|
raw = await _record_edit_chain.ainvoke({
|
|
"job_title": job_title, "job_description": job_description,
|
|
"instruction": instruction, "chat_history": chat_history,
|
|
"module_schema": module_schema, "record_data": record_data,
|
|
})
|
|
return parse_llm_json(raw)
|
|
except Exception as e:
|
|
log.warning(f"AI单条记录修改失败: {e}")
|
|
return None
|
|
|
|
|
|
# ===== Agent - 新增记录 =====
|
|
|
|
_record_add_chain = (
|
|
ChatPromptTemplate.from_messages([("system", AGENT_MODULE_ADD_PROMPT), ("human", "请生成新记录。")])
|
|
| LLM.DOUBAO_PRO_32K.create(temperature=0.3)
|
|
| StrOutputParser()
|
|
)
|
|
|
|
|
|
async def execute_record_add(job_title: str, job_description: str, instruction: str,
|
|
chat_history: str, module_schema: str) -> dict | None:
|
|
"""新增一条记录:根据指令生成新记录"""
|
|
try:
|
|
raw = await _record_add_chain.ainvoke({
|
|
"job_title": job_title, "job_description": job_description,
|
|
"instruction": instruction, "chat_history": chat_history,
|
|
"module_schema": module_schema,
|
|
})
|
|
result = parse_llm_json(raw)
|
|
return result if isinstance(result, dict) else None
|
|
except Exception as e:
|
|
log.warning(f"AI新增记录失败: {e}")
|
|
return None
|