diff --git a/app/schemas/customize_resume.py b/app/schemas/customize_resume.py new file mode 100644 index 0000000..85203c5 --- /dev/null +++ b/app/schemas/customize_resume.py @@ -0,0 +1,87 @@ +"""定制简历 Schema + +定制简历的 Pydantic 模型,用于 Redis 缓存、AI 优化结果、前端交互。 +字段命名使用 camelCase alias,与前端 JSON 对齐。 +""" + +from pydantic import BaseModel, Field + + +class _AliasModel(BaseModel): + """带 alias 的基类,允许同时用 alias 和字段名赋值""" + model_config = {"populate_by_name": True} + + +class Paragraph(_AliasModel): + id: str = Field(...) + text: str = Field(default="") + + +class ResumeProfile(_AliasModel): + avatar_url: str = Field(default="", alias="avatarUrl") + name: str = Field(default="") + email: str = Field(default="") + mobile_number: str = Field(default="", alias="mobileNumber") + city: str = Field(default="") + wechat_number: str = Field(default="", alias="wechatNumber") + portfolio_url: str = Field(default="", alias="portfolioUrl") + skills: list[str] = Field(default_factory=list) + certificates: list[str] = Field(default_factory=list) + summary: str = Field(default="") + + +class Education(_AliasModel): + id: str = Field(default="") + school: str = Field(default="") + major: str = Field(default="") + degree: str = Field(default="") + study_type: str = Field(default="", alias="studyType") + start_date: str = Field(default="", alias="startDate") + end_date: str = Field(default="", alias="endDate") + description: list[Paragraph] = Field(default_factory=list) + + +class Work(_AliasModel): + id: str = Field(default="") + company_name: str = Field(default="", alias="companyName") + position: str = Field(default="") + start_date: str = Field(default="", alias="startDate") + end_date: str = Field(default="", alias="endDate") + description: list[Paragraph] = Field(default_factory=list) + + +class Internship(_AliasModel): + id: str = Field(default="") + company_name: str = Field(default="", alias="companyName") + position: str = Field(default="") + start_date: str = Field(default="", alias="startDate") + end_date: str = Field(default="", alias="endDate") + description: list[Paragraph] = Field(default_factory=list) + + +class Project(_AliasModel): + id: str = Field(default="") + company_name: str = Field(default="", alias="companyName") + project_name: str = Field(default="", alias="projectName") + role: str = Field(default="") + start_date: str = Field(default="", alias="startDate") + end_date: str = Field(default="", alias="endDate") + description: list[Paragraph] = Field(default_factory=list) + + +class Competition(_AliasModel): + id: str = Field(default="") + competition_name: str = Field(default="", alias="competitionName") + award: str = Field(default="") + award_date: str = Field(default="", alias="awardDate") + description: list[Paragraph] = Field(default_factory=list) + + +class CustomizeResume(_AliasModel): + """定制简历结构""" + resume: ResumeProfile = Field(default_factory=ResumeProfile) + education: list[Education] = Field(default_factory=list) + work: list[Work] = Field(default_factory=list) + internship: list[Internship] = Field(default_factory=list) + project: list[Project] = Field(default_factory=list) + competition: list[Competition] = Field(default_factory=list) diff --git a/app/schemas/skill_gap.py b/app/schemas/skill_gap.py index 04b40a8..0aceba9 100644 --- a/app/schemas/skill_gap.py +++ b/app/schemas/skill_gap.py @@ -1,6 +1,6 @@ -"""技能差距分析 + 定制简历 Schema +"""技能差距分析 Schema -请求参数 Param、响应 Dto、Redis 缓存模型。 +请求参数 Param。定制简历模型已抽到 customize_resume.py。 字段命名使用 camelCase alias,与前端 JSON 对齐。 """ @@ -37,85 +37,3 @@ class AiEditParam(BaseModel): job_id: int = Field(..., alias="jobId") instruction: str = Field(...) chat_history: list[ChatMessage] = Field(default_factory=list, alias="chatHistory") - - -# ===== Redis 缓存子模型 ===== - -class _AliasModel(BaseModel): - """带 alias 的基类,允许同时用 alias 和字段名赋值""" - model_config = {"populate_by_name": True} - - -class Paragraph(_AliasModel): - id: str = Field(...) - text: str = Field(default="") - - -class ResumeProfile(_AliasModel): - avatar_url: str = Field(default="", alias="avatarUrl") - name: str = Field(default="") - email: str = Field(default="") - mobile_number: str = Field(default="", alias="mobileNumber") - city: str = Field(default="") - wechat_number: str = Field(default="", alias="wechatNumber") - portfolio_url: str = Field(default="", alias="portfolioUrl") - skills: list[str] = Field(default_factory=list) - certificates: list[str] = Field(default_factory=list) - summary: str = Field(default="") - - -class Education(_AliasModel): - id: str = Field(default="") - school: str = Field(default="") - major: str = Field(default="") - degree: str = Field(default="") - study_type: str = Field(default="", alias="studyType") - start_date: str = Field(default="", alias="startDate") - end_date: str = Field(default="", alias="endDate") - description: list[Paragraph] = Field(default_factory=list) - - -class Work(_AliasModel): - id: str = Field(default="") - company_name: str = Field(default="", alias="companyName") - position: str = Field(default="") - start_date: str = Field(default="", alias="startDate") - end_date: str = Field(default="", alias="endDate") - description: list[Paragraph] = Field(default_factory=list) - - -class Internship(_AliasModel): - id: str = Field(default="") - company_name: str = Field(default="", alias="companyName") - position: str = Field(default="") - start_date: str = Field(default="", alias="startDate") - end_date: str = Field(default="", alias="endDate") - description: list[Paragraph] = Field(default_factory=list) - - -class Project(_AliasModel): - id: str = Field(default="") - company_name: str = Field(default="", alias="companyName") - project_name: str = Field(default="", alias="projectName") - role: str = Field(default="") - start_date: str = Field(default="", alias="startDate") - end_date: str = Field(default="", alias="endDate") - description: list[Paragraph] = Field(default_factory=list) - - -class Competition(_AliasModel): - id: str = Field(default="") - competition_name: str = Field(default="", alias="competitionName") - award: str = Field(default="") - award_date: str = Field(default="", alias="awardDate") - description: list[Paragraph] = Field(default_factory=list) - - -class CustomizeResume(_AliasModel): - """定制简历 Redis 缓存结构""" - resume: ResumeProfile = Field(default_factory=ResumeProfile) - education: list[Education] = Field(default_factory=list) - work: list[Work] = Field(default_factory=list) - internship: list[Internship] = Field(default_factory=list) - project: list[Project] = Field(default_factory=list) - competition: list[Competition] = Field(default_factory=list) diff --git a/app/services/skill_gap_service.py b/app/services/skill_gap_service.py index 08c9d54..37b2032 100644 --- a/app/services/skill_gap_service.py +++ b/app/services/skill_gap_service.py @@ -20,7 +20,7 @@ from app.ai.skill_gap_analyzer.analyzer import ( ) from app.ai.skill_gap_analyzer.prompts import MODULE_SCHEMAS from app.core.logger import log -from app.schemas.skill_gap import ( +from app.schemas.customize_resume import ( CustomizeResume, ResumeProfile, Education, Work, Internship, Project, Competition, Paragraph, ) from app.models.job import Job