diff --git a/.kiro/specs/job-agent-chat/design.md b/.kiro/specs/job-agent-chat/design.md deleted file mode 100644 index c9ea6d3..0000000 --- a/.kiro/specs/job-agent-chat/design.md +++ /dev/null @@ -1,118 +0,0 @@ -# 求职助手 Agent 对话接口设计方案 - -## 1. 接口概述 - -`POST /job-agent/chat` — 求职助手对话接口,Python 端实现。 - -用户通过对话与求职助手交互,AI 根据用户简历和求职意向提供求职建议,识别用户意图后触发前端工具调用(岗位推荐 / 调整偏好)。 - -## 2. 入参 Schema - -```python -class ChatMessage(BaseModel): - role: Literal["user", "assistant"] - content: str - -class JobAgentChatParam(BaseModel): - message: str = Field(..., description="用户输入的消息") - resume_id: int = Field(..., alias="resumeId", description="简历ID") - history: list[ChatMessage] = Field(default_factory=list, description="对话历史") - job_categories: list[str] = Field(default_factory=list, alias="jobCategories", description="意向岗位类型名称") - regions: list[str] = Field(default_factory=list, alias="regions", description="意向城市名称") - industries: list[str] = Field(default_factory=list, alias="industries", description="意向行业名称") -``` - -## 3. 出参 Schema - -```python -class ToolParams(BaseModel): - preference: str = Field(default="", description="用户岗位偏好描述,仅tool=recommend时有值") - -class JobAgentChatDto(BaseModel): - message: str = Field(..., description="AI回复文本,不超过200字") - tool: str | None = Field(default=None, description="前端需执行的工具:recommend / editPreference / null") - tool_params: ToolParams | None = Field(default=None, alias="toolParams", description="工具参数") -``` - -## 4. AI 上下文构造 - -每次对话请求,后端自动查询以下数据拼入 system prompt: - -1. **简历信息**:根据 resumeId 查 bg_user_resume 主表 + 5张子表(教育/工作/实习/项目/竞赛),序列化为文本 -2. **求职意向**:直接使用前端传入的 jobCategories / regions / industries(中文名称) - -## 5. System Prompt 设计 - -``` -你是 OfferPie 求职助手,帮助用户找到合适的工作。 - -【用户简历】 -{resume_text} - -【求职意向】 -意向岗位:{job_categories} -意向城市:{regions} -意向行业:{industries} - -【你的能力】 -1. 回答求职相关问题(面试技巧、简历建议、行业分析等),回复不超过200字 -2. 当用户想看岗位推荐时,提取用户的偏好描述,调用岗位推荐工具 -3. 当用户想修改求职偏好/设置时,调用偏好设置工具 - -【输出格式】 -严格返回 JSON,不要其他内容: -{"message":"回复内容","tool":null,"toolParams":null} - -tool 可选值: -- null:普通对话,不触发工具 -- "recommend":岗位推荐,toolParams 必须包含 {"preference":"用户偏好描述"} -- "editPreference":调整偏好,toolParams 为 null - -【规则】 -1. 只聊求职相关话题,其他话题礼貌拒绝 -2. 回复简洁,不超过200字 -3. 用户表达想看岗位、推荐岗位、帮我找工作等意图时,从对话中提取偏好描述,返回 recommend -4. 用户表达想改设置、调整偏好、修改意向等意图时,返回 editPreference -5. 偏好描述要准确概括用户的岗位偏好,如"更偏技术方向的产品岗"、"大厂优先" -``` - -## 6. 处理流程 - -1. 校验登录态,获取 user_id -2. 根据 resume_id 查简历主表 + 5张子表,序列化为文本 -3. 构造 system prompt(简历 + 求职意向 + 规则) -4. 构造 messages 列表:system prompt + history + 当前 message -5. 调用 LLM(使用 LLM.DEEPSEEK_V3 或配置的模型) -6. 用 parse_llm_json 解析 AI 返回的 JSON -7. 构造 JobAgentChatDto 返回 - -## 7. 前端交互流程 - -1. 前端发消息 → 调 `POST /job-agent/chat` -2. 拿到返回后判断 tool 字段: - - `tool=null` → 直接展示 message - - `tool="recommend"` → 展示 message + 用 toolParams.preference 调 Java 端 `POST /job/agent/recommend` 拿岗位列表展示 - - `tool="editPreference"` → 展示 message + 打开偏好设置页面 - -## 8. 涉及文件 - -| 文件 | 位置 | 说明 | -|------|------|------| -| `job_agent_chat.py` | app/schemas/ | Pydantic 请求/响应 Schema | -| `job_agent_chat.py` | app/api/ | 路由定义 | -| `job_agent_chat_service.py` | app/services/ | Service:查简历 + 构造 prompt + 调 LLM | -| `prompts.py` | app/ai/job_agent/ | System Prompt 模板 | -| `main.py` | app/ | 注册新路由 | - -## 9. 依赖的现有模块 - -- `app/models/user_resume.py` + 5张子表 ORM — 查简历数据 -- `app/ai/models.py` — LLM 枚举,创建模型实例 -- `app/tool/json_helper.py` — parse_llm_json 解析 AI 输出 -- `app/core/context.py` — RequestContext 获取 user_id -- `app/core/database.py` — get_db 获取数据库会话 - -## 10. 不需要新增的 ORM 模型 - -- 求职意向由前端传入中文名称,不查 bg_user_job_intention 表 -- 简历相关 ORM 模型已全部存在 diff --git a/.kiro/steering/代码开发风格文档.md b/.kiro/steering/代码开发风格文档.md index 43ccbc4..2403389 100644 --- a/.kiro/steering/代码开发风格文档.md +++ b/.kiro/steering/代码开发风格文档.md @@ -143,7 +143,7 @@ inclusion: manual ### 模型引用示例 ```python -from app.ai.model_config import SkillGapModel +from app.ai.model_config import SkillGapModel, NovaChatModel # chain 中直接使用配置类属性(已经是 ChatOpenAI 实例) _plan_chain = ( @@ -153,7 +153,7 @@ _plan_chain = ( ) # 非 chain 场景直接 await 调用 -result = await JobAgentModel.CHAT.ainvoke(messages) +result = await NovaChatModel.CHAT.ainvoke(messages) ``` ### 新增 AI 场景步骤 diff --git a/.kiro/steering/项目结构说明.md b/.kiro/steering/项目结构说明.md index 60ffd02..688f8d6 100644 --- a/.kiro/steering/项目结构说明.md +++ b/.kiro/steering/项目结构说明.md @@ -45,9 +45,8 @@ offerpie_python_ai/ │ ├─ skill_gap_analyzer/ # 技能差距分析 + 定制简历 AI 模块 │ │ ├─ prompts.py # 差距分析 + 简历优化 + Agent 规划(原子化操作)/ 单条记录修改 / 新增记录 Prompt 模板 + MODULE_SCHEMAS │ │ └─ analyzer.py # AI 调用逻辑(差距分析 + summary优化 + 经历优化 + Agent规划 + 单条记录修改 + 新增记录) - │ ├─ job_agent/ # 求职助手 Agent AI 模块 - │ │ ├─ prompts.py # 对话 System Prompt + 岗位简历优化 Prompt 模板 - │ │ ├─ chat.py # AI 对话引擎(构造 prompt + 拼 messages + 调 LLM + 解析返回) + │ ├─ job_agent/ # 求职助手 Agent AI 模块(岗位简历优化) + │ │ ├─ prompts.py # 岗位简历优化 Prompt 模板 │ │ └─ resume_optimizer.py # 岗位简历优化 AI 引擎(summary优化 + 经历优化,独立 chain) │ └─ nova_chat/ # Nova 对话助手 AI 模块 │ ├─ prompts.py # Nova 对话 System Prompt(岗位匹配评估 + 简历优化建议 + 通用求职对话) @@ -59,7 +58,7 @@ offerpie_python_ai/ │ ├─ resume_diagnose.py # 简历诊断接口(POST 触发诊断 / GET 查询报告 / PUT 标记处理+用户评价 / POST 润色优化) │ ├─ skill_gap.py # 技能差距分析接口(差距分析 / 生成定制简历 / AI对话编辑) │ ├─ customize_resume.py # 定制简历接口(查询 / 修改 / 回滚) - │ ├─ job_agent_chat.py # 求职助手接口(POST /job-agent/chat 对话、POST /job-agent/optimize-resume 岗位简历优化) + │ ├─ job_agent_chat.py # 求职助手接口(POST /job-agent/optimize-resume 岗位简历优化) │ └─ nova_chat.py # Nova 对话助手接口(POST /nova-chat/chat 纯对话,支持可选岗位上下文) │ ├─ models/ # **ORM 模型层**(SQLAlchemy 声明式映射) @@ -86,7 +85,7 @@ offerpie_python_ai/ ├─ schemas/ # **Schema 层**(Pydantic 请求/响应/缓存模型) │ ├─ skill_gap.py # 技能差距分析 Schema(SkillGapParam、CustomizeResumeParam、AiEditParam) │ ├─ customize_resume.py # 定制简历 Schema(CustomizeResume、ResumeProfile、Education、Work、Internship、Project、Competition、Paragraph) - │ ├─ job_agent_chat.py # 求职助手对话 Schema(JobAgentChatParam、JobAgentChatDto、ToolParams) + │ ├─ job_agent_chat.py # 求职助手岗位简历优化 Schema(OptimizeResumeParam) │ └─ nova_chat.py # Nova 对话助手 Schema(NovaChatParam、NovaChatDto) │ └─ services/ # **业务逻辑层** @@ -96,7 +95,7 @@ offerpie_python_ai/ ├─ skill_gap_service.py # 技能差距分析服务(差距分析→定制简历生成→AI对话编辑) ├─ resume_loader.py # 简历统一查询模块(按ID查/自动选默认+5张子表,返回 ResumeDetail dataclass) ├─ customize_resume_store.py # 定制简历存取模块(数据库持久化 + Redis回滚备份、按用户+岗位维度存取) - ├─ job_agent_chat_service.py # 求职助手对话服务(查简历→序列化→调AI模块完成对话) + ├─ job_agent_chat_service.py # 求职助手服务(查简历+岗位→并发AI优化简历→存库) └─ nova_chat_service.py # Nova 对话助手服务(查简历+查岗位(可选)→调AI,纯对话不持久化) ``` @@ -105,11 +104,11 @@ offerpie_python_ai/ |------|----------|-------------| | **config** | 统一配置管理,基于 Pydantic Settings,支持 .env 文件加载 | `Settings`(数据库、Redis、LLM供应商、JWT、CORS、日志等全部配置项) | | **core** | 核心基础设施:数据库连接、Redis连接、鉴权、日志、中间件、异常处理、统一响应 | `database.py`、`redis.py`、`auth.py`、`middleware.py`、`exceptions.py`、`logger.py`、`StandardResponse` | -| **ai** | AI 模型管理 + 业务 AI 能力 | `LLM` 枚举(models.py)、`model_config.py`(场景模型配置)、`resume_extractor/`(简历并行提取)、`resume_polisher/`(简历段落润色)、`resume_diagnoser/`(简历诊断)、`skill_gap_analyzer/`(技能差距分析 + 定制简历优化 + Agent 原子化规划 + 单条记录修改/新增)、`job_agent/`(求职助手对话 + 岗位简历优化)、`nova_chat/`(Nova 对话助手,纯对话) | -| **api** | REST API 路由定义 | `health.py`(健康检查)、`resume.py`(简历上传解析 + 段落润色)、`resume_diagnose.py`(简历诊断)、`skill_gap.py`(技能差距分析 + 生成定制简历 + AI对话编辑)、`customize_resume.py`(定制简历查询/修改/回滚)、`job_agent_chat.py`(求职助手对话 + 岗位简历优化)、`nova_chat.py`(Nova 对话助手) | +| **ai** | AI 模型管理 + 业务 AI 能力 | `LLM` 枚举(models.py)、`model_config.py`(场景模型配置)、`resume_extractor/`(简历并行提取)、`resume_polisher/`(简历段落润色)、`resume_diagnoser/`(简历诊断)、`skill_gap_analyzer/`(技能差距分析 + 定制简历优化 + Agent 原子化规划 + 单条记录修改/新增)、`job_agent/`(求职助手岗位简历优化)、`nova_chat/`(Nova 对话助手,纯对话) | +| **api** | REST API 路由定义 | `health.py`(健康检查)、`resume.py`(简历上传解析 + 段落润色)、`resume_diagnose.py`(简历诊断)、`skill_gap.py`(技能差距分析 + 生成定制简历 + AI对话编辑)、`customize_resume.py`(定制简历查询/修改/回滚)、`job_agent_chat.py`(求职助手岗位简历优化)、`nova_chat.py`(Nova 对话助手) | | **models** | SQLAlchemy ORM 模型,与 Java 端共享同一数据库 | `FuncPermission`、`UserFuncPermissionStock`、`UserFuncUsageLog`、`UserResume`、`UserResumeEducation`/`Work`/`Internship`/`Project`/`Competition`、`ResumeDiagnosisReport`、`ResumeDiagnosisIssue`、`Job`(只读)、`JobAgentConfig`、`UserJobCustomizeResume` | | **tool** | 无状态通用工具,不依赖数据库/Redis/用户上下文 | `file_parser.py`(PDF/Word(.docx)/TXT/Markdown 文件解析为文本单元数组)、`json_helper.py`(AI 输出 JSON 解析,去 markdown 代码块 + json_repair 容错)、`snowflake.py`(雪花ID生成) | -| **services** | 业务逻辑实现 | `FuncPermissionService`(功能权限校验、扣减、回退)、`ResumeService`(简历文件解析→AI结构化→入库 + 段落润色)、`ResumeDiagnoseService`(简历诊断→AI并行分析→评级→入库)、`SkillGapService`(技能差距分析→定制简历生成→AI对话编辑)、`resume_loader`(简历统一查询,返回ResumeDetail)、`customize_resume_store`(定制简历数据库存取+数据构建,按用户+岗位维度,Redis回滚备份)、`JobAgentChatService`(求职助手对话+岗位简历优化)、`NovaChatService`(Nova对话助手,查简历+查岗位→调AI) | +| **services** | 业务逻辑实现 | `FuncPermissionService`(功能权限校验、扣减、回退)、`ResumeService`(简历文件解析→AI结构化→入库 + 段落润色)、`ResumeDiagnoseService`(简历诊断→AI并行分析→评级→入库)、`SkillGapService`(技能差距分析→定制简历生成→AI对话编辑)、`resume_loader`(简历统一查询,返回ResumeDetail)、`customize_resume_store`(定制简历数据库存取+数据构建,按用户+岗位维度,Redis回滚备份)、`JobAgentChatService`(求职助手岗位简历优化)、`NovaChatService`(Nova对话助手,查简历+查岗位→调AI) | ## 3️⃣ 技术栈 | 类别 | 技术选型 | 说明 | @@ -179,7 +178,7 @@ offerpie_python_ai/ | 配置类 | 场景 | 说明 | |--------|------|------| | `SkillGapModel` | ANALYSIS / SUMMARY / EXPERIENCE / AGENT_PLAN / AGENT_EDIT / AGENT_ADD | 技能差距分析模块 | -| `JobAgentModel` | CHAT / SUMMARY / EXPERIENCE | 求职助手Agent模块 | +| `JobAgentModel` | SUMMARY / EXPERIENCE | 求职助手Agent模块 | | `NovaChatModel` | CHAT | Nova智能聊天模块 | | `ResumeExtractorModel` | PARSE | 简历解析模块 | | `DiagnoserModel` | MODULE / SUMMARY / POLISH | 简历诊断模块 | diff --git a/app/ai/job_agent/chat.py b/app/ai/job_agent/chat.py deleted file mode 100644 index 0cfcd84..0000000 --- a/app/ai/job_agent/chat.py +++ /dev/null @@ -1,51 +0,0 @@ -"""求职助手 Agent 对话 AI 引擎 - -构造 prompt + 调 LLM + 解析返回。 -依赖:LLM 枚举、job_agent/prompts、parse_llm_json -""" - -from app.ai.job_agent.prompts import SYSTEM_PROMPT -from app.ai.model_config import JobAgentModel -from app.core.logger import log -from app.tool.json_helper import parse_llm_json - - -async def agent_chat(resume_text: str, message: str, history: list[dict], - job_categories: list[str], regions: list[str], - industries: list[str]) -> dict: - """求职助手对话 - 1. 构造 system prompt 2. 拼 messages 3. 调 LLM 4. 解析返回 - """ - # 1. 构造 system prompt - system_content = SYSTEM_PROMPT.format( - resume_text=resume_text, - job_categories="、".join(job_categories) if job_categories else "未设置", - regions="、".join(regions) if regions else "未设置", - industries="、".join(industries) if industries else "未设置", - ) - - # 2. 拼 messages - messages = [("system", system_content)] - for msg in history: - messages.append((msg["role"], msg["content"])) - messages.append(("human", message)) - - # 3. 调 LLM - try: - result = await JobAgentModel.CHAT.ainvoke(messages) - raw = result.content - except Exception as e: - log.error(f"求职助手AI调用失败: {e}") - return {"message": "抱歉,我暂时无法回复,请稍后再试。", "tool": None, "toolParams": None} - - # 4. 解析返回 - try: - parsed = parse_llm_json(raw) - return { - "message": parsed.get("message", ""), - "tool": parsed.get("tool"), - "toolParams": parsed.get("toolParams"), - } - except Exception as e: - log.warning(f"求职助手AI返回解析失败, raw={raw}, error={e}") - return {"message": raw.strip() if raw else "抱歉,我暂时无法回复。", "tool": None, "toolParams": None} diff --git a/app/ai/job_agent/prompts.py b/app/ai/job_agent/prompts.py index fa2bc9a..ea06066 100644 --- a/app/ai/job_agent/prompts.py +++ b/app/ai/job_agent/prompts.py @@ -1,41 +1,4 @@ -"""求职助手 Agent 对话 Prompt 模板 + 岗位简历优化 Prompt""" - -SYSTEM_PROMPT = """你是 OfferPie 求职助手,帮助用户找到合适的工作。 - -【用户简历】 -{resume_text} - -【求职意向】 -意向岗位:{job_categories} -意向城市:{regions} -意向行业:{industries} - -【你的能力】 -1. 回答求职相关问题(面试技巧、简历建议、行业分析等),回复不超过200字 -2. 当用户想看岗位推荐时,提取用户的偏好描述,调用岗位推荐工具 -3. 当用户想修改求职偏好/设置时,调用偏好设置工具 - -【输出格式】 -严格返回 JSON,不要其他内容: -{{"message":"回复内容","tool":null,"toolParams":null}} - -tool 可选值: -- null:普通对话,不触发工具 -- "recommend":岗位推荐,toolParams 必须包含 {{"preference":"用户偏好描述"}} -- "editPreference":调整偏好,toolParams 为 null - -【规则】 -1. 只聊求职相关话题,其他话题礼貌拒绝 -2. 回复简洁,不超过200字 -3. 用户表达想看岗位、推荐岗位、帮我找工作等意图时,从对话中提取偏好描述,返回 recommend -4. 用户表达想改设置、调整偏好、修改意向等意图时,返回 editPreference -5. 偏好描述要准确概括用户的岗位偏好,如"更偏技术方向的产品岗"、"大厂优先" -6. 如果用户没有明确偏好,preference 填"无特殊偏好" -7. 触发工具时(tool 非 null),前端会在消息展示后再打开对应面板/列表,message 只做一句简短的"即将..."提示,不要追问"想怎么调整"、"有什么偏好"等引导用户在对话里继续输入的话 - - 注意工具调用是置后的:message 先展示给用户,面板/列表随后打开,所以用将来时态,不要用"已为你..."这种完成时 - - recommend 示例:"好的,正在为你匹配合适的岗位" - - editPreference 示例:"好的,为你打开偏好设置" -""" +"""求职助手 Agent 岗位简历优化 Prompt""" # ===== 岗位简历优化 Prompt ===== diff --git a/app/ai/model_config.py b/app/ai/model_config.py index 83cbb7c..a7ed515 100644 --- a/app/ai/model_config.py +++ b/app/ai/model_config.py @@ -24,8 +24,6 @@ class SkillGapModel: class JobAgentModel: """求职助手Agent模块""" - # 多轮对话:理解用户求职意图,返回结构化回复(message+tool调用) - CHAT = LLM.DOUBAO_PRO_32K.create(temperature=0.7) # 岗位简历-summary优化:针对具体岗位JD优化个人概述 SUMMARY = LLM.DEEPSEEK_V4_FLASH.create(temperature=0.3) # 岗位简历-经历优化:针对具体岗位JD优化单条经历描述 diff --git a/app/api/job_agent_chat.py b/app/api/job_agent_chat.py index 6788ec5..8e07ee1 100644 --- a/app/api/job_agent_chat.py +++ b/app/api/job_agent_chat.py @@ -1,30 +1,16 @@ -"""求职助手 Agent 对话接口""" +"""求职助手 Agent 岗位简历优化接口""" from fastapi import APIRouter, Depends from app.core.auth import func_permission from app.core.context import RequestContext from app.core.database import get_db -from app.schemas.job_agent_chat import JobAgentChatParam, OptimizeResumeParam +from app.schemas.job_agent_chat import OptimizeResumeParam from app.services.job_agent_chat_service import JobAgentChatService router = APIRouter(prefix="/job-agent", tags=["求职助手agent"]) -@router.post("/chat", summary="求职助手对话") -async def chat(param: JobAgentChatParam): - """求职助手对话,根据用户简历和意向提供求职建议、触发岗位推荐或偏好调整""" - user_id = RequestContext.user_id.get() - async for session in get_db(): - service = JobAgentChatService(session) - result = await service.chat( - user_id, param.resume_id, param.message, - [msg.model_dump() for msg in param.history], - param.job_categories, param.regions, param.industries, - ) - return result - - @router.post("/optimize-resume", summary="针对岗位优化简历") async def optimize_resume(param: OptimizeResumeParam, _: None = Depends(func_permission("resume_custom"))): """根据目标岗位,AI并发优化简历(summary + 5张子表经历),存Redis并返回""" diff --git a/app/schemas/job_agent_chat.py b/app/schemas/job_agent_chat.py index be84dd3..f96ed88 100644 --- a/app/schemas/job_agent_chat.py +++ b/app/schemas/job_agent_chat.py @@ -1,41 +1,11 @@ -"""求职助手 Agent 对话 Schema +"""求职助手 Agent 岗位简历优化 Schema -请求参数 Param、响应 Dto。 +请求参数 Param。 字段命名使用 camelCase alias,与前端 JSON 对齐。 """ -from typing import Literal - from pydantic import BaseModel, Field -ChatRole = Literal["user", "assistant"] - - -class ChatMessage(BaseModel): - role: ChatRole - content: str - - -class JobAgentChatParam(BaseModel): - message: str = Field(..., description="用户输入的消息") - resume_id: int = Field(..., alias="resumeId", description="简历ID") - history: list[ChatMessage] = Field(default_factory=list, description="对话历史") - job_categories: list[str] = Field(default_factory=list, alias="jobCategories", description="意向岗位类型名称") - regions: list[str] = Field(default_factory=list, alias="regions", description="意向城市名称") - industries: list[str] = Field(default_factory=list, alias="industries", description="意向行业名称") - - -class ToolParams(BaseModel): - preference: str = Field(default="", description="用户岗位偏好描述") - - -class JobAgentChatDto(BaseModel): - message: str = Field(..., description="AI回复文本,不超过200字") - tool: str | None = Field(default=None, description="前端需执行的工具:recommend / editPreference / null") - tool_params: ToolParams | None = Field(default=None, alias="toolParams", description="工具参数") - - model_config = {"populate_by_name": True} - class OptimizeResumeParam(BaseModel): resume_id: int = Field(..., alias="resumeId", description="简历ID") diff --git a/app/services/job_agent_chat_service.py b/app/services/job_agent_chat_service.py index 9768b20..21c98d3 100644 --- a/app/services/job_agent_chat_service.py +++ b/app/services/job_agent_chat_service.py @@ -1,7 +1,7 @@ -"""求职助手 Agent 对话 + 岗位简历优化 Service +"""求职助手 Agent 岗位简历优化 Service -主要功能:查询简历数据,调用 AI 模块完成对话;针对岗位并发优化简历。 -依赖:resume_loader(简历统一查询)、customize_resume_store(定制简历存取+构建)、job_agent.chat AI 模块、job_agent.resume_optimizer(岗位简历优化) +主要功能:针对岗位并发优化简历。 +依赖:resume_loader(简历统一查询)、customize_resume_store(定制简历存取+构建)、job_agent.resume_optimizer(岗位简历优化) 使用表:bg_user_resume + 5张子表(通过 resume_loader 查询)、bg_job(查岗位) """ @@ -12,12 +12,11 @@ import time from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession -from app.ai.job_agent.chat import agent_chat from app.ai.job_agent.resume_optimizer import optimize_summary, optimize_experience_record from app.core.logger import log from app.models.job import Job from app.schemas.customize_resume import CustomizeResume, Education, Work, Internship, Project, Competition -from app.services.resume_loader import ResumeDetail, load_resume_detail +from app.services.resume_loader import load_resume_detail from app.services import customize_resume_store @@ -26,51 +25,6 @@ class JobAgentChatService: def __init__(self, session: AsyncSession): self.session = session - async def chat(self, user_id: int, resume_id: int, message: str, - history: list[dict], job_categories: list[str], - regions: list[str], industries: list[str]) -> dict: - """求职助手对话:查简历 → 序列化 → 调 AI 模块""" - detail = await load_resume_detail(self.session, resume_id, user_id) - resume_text = self._build_resume_text(detail) - return await agent_chat(resume_text, message, history, job_categories, regions, industries) - - @staticmethod - def _build_resume_text(detail: ResumeDetail) -> str: - """将简历数据序列化为文本供 AI 使用""" - resume = detail.resume - parts = [] - if resume.name: - parts.append(f"姓名:{resume.name}") - if resume.target_position: - parts.append(f"目标岗位:{resume.target_position}") - if resume.skills: - parts.append(f"技能:{'、'.join(resume.skills)}") - if resume.certificates: - parts.append(f"证书:{'、'.join(resume.certificates)}") - if resume.summary: - parts.append(f"个人概述:{resume.summary}") - if detail.education: - parts.append("教育经历:") - for r in detail.education: - parts.append(f" - {r.school or ''} {r.major or ''} {r.degree or ''}") - if detail.work: - parts.append("工作经历:") - for r in detail.work: - parts.append(f" - {r.company_name or ''} {r.position or ''}") - if detail.internship: - parts.append("实习经历:") - for r in detail.internship: - parts.append(f" - {r.company_name or ''} {r.position or ''}") - if detail.project: - parts.append("项目经历:") - for r in detail.project: - parts.append(f" - {r.project_name or ''} {r.role or ''}") - if detail.competition: - parts.append("竞赛经历:") - for r in detail.competition: - parts.append(f" - {r.competition_name or ''} {r.award or ''}") - return "\n".join(parts) if parts else "暂无简历信息" - async def optimize_resume(self, user_id: int, resume_id: int, job_id: int) -> dict: """针对岗位优化简历:查简历+岗位 → 构建定制简历 → 按单条记录并发AI优化 → 存数据库 → 返回""" # 1. 查简历 + 岗位