--- inclusion: manual --- # OfferPie Python AI 项目结构说明 ## 1️⃣ 项目整体层次 ``` offerpie_python_ai/ │ ├─ .env / .env.test / .env.prod # 环境变量配置(dev/test/prod) ├─ requirements.txt # Python 依赖清单 │ └─ app/ # 应用主目录 ├─ main.py # FastAPI 应用入口(注册异常处理、中间件、CORS、路由) ├─ banner.txt # 启动 Banner │ ├─ config/ # **配置层** │ └─ settings.py # Pydantic Settings 统一配置(环境、数据库、Redis、LLM供应商、JWT、CORS、日志等) │ ├─ core/ # **核心基础设施层** │ ├─ auth.py # 权限校验依赖(require_login、func_permission 装饰器) │ ├─ context.py # 请求上下文变量(RequestContext:request_id、user_id) │ ├─ database.py # SQLAlchemy 异步引擎 + 会话工厂(init_db、close_db、get_db) │ ├─ redis.py # Redis 异步连接池(init_redis、close_redis、get_redis) │ ├─ lifespan.py # FastAPI 生命周期管理(启动初始化 DB/Redis,关闭释放资源) │ ├─ logger.py # Loguru 日志配置(控制台+文件,自动注入 request_id/user_id) │ ├─ middleware.py # 中间件注册(RequestID、JWT鉴权、登录拦截、请求日志、响应统一包装) │ ├─ exceptions.py # 全局异常处理器(HTTP异常、验证异常、断言异常、未知异常) │ └─ schemas/ │ └─ responses.py # 统一响应模型 StandardResponse(code/msg/data/timestamp/uuid) │ ├─ ai/ # **AI 能力层** │ ├─ models.py # LLM 模型枚举(LLM.DOUBAO_PRO_32K、DEEPSEEK_V3、GPT_4O 等),基于 LangChain ChatOpenAI │ ├─ model_config.py # AI 模型场景配置(集中管理各模块的模型选择与参数,业务代码引用此文件而非直接使用 LLM 枚举) │ ├─ resume_extractor/ # 简历 AI 提取模块 │ │ ├─ prompts.py # 5 个提取任务的 System Prompt(个人信息/教育/工作+实习/项目/竞赛) │ │ └─ extractor.py # AI 并行提取(extract_all 入口,asyncio.gather 5 路并行) │ ├─ resume_diagnoser/ # 简历 AI 诊断模块 │ │ ├─ prompts.py # 诊断 Prompt 模板(分模块诊断 + 汇总评价 + 润色优化) │ │ └─ diagnoser.py # AI 并行诊断(diagnose_all 入口 + generate_summary 汇总评价 + polish_content 润色优化) │ ├─ 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 + 解析返回) │ │ └─ resume_optimizer.py # 岗位简历优化 AI 引擎(summary优化 + 经历优化,独立 chain) │ └─ nova_chat/ # Nova 对话助手 AI 模块 │ ├─ prompts.py # Nova 对话 System Prompt(岗位匹配评估 + 简历优化建议 + 通用求职对话) │ └─ chat.py # Nova 对话 AI 引擎(拼 prompt + 调 LLM,返回纯文本) │ ├─ api/ # **路由层**(REST API 接口) │ ├─ health.py # 健康检查接口 GET /health/ │ ├─ resume.py # 简历接口 POST /resume/upload(上传文件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 岗位简历优化) │ └─ nova_chat.py # Nova 对话助手接口(POST /nova-chat/chat 纯对话,支持可选岗位上下文) │ ├─ models/ # **ORM 模型层**(SQLAlchemy 声明式映射) │ ├─ func_permission.py # 功能权限定义表(bg_func_permission) │ ├─ user_func_permission_stock.py # 用户功能权限库存表(bg_user_func_permission_stock) │ ├─ user_func_usage_log.py # 用户功能使用记录表(bg_user_func_usage_log) │ ├─ user_resume.py # 用户简历主表(bg_user_resume) │ ├─ user_resume_education.py # 简历-教育经历表(bg_user_resume_education) │ ├─ user_resume_work.py # 简历-工作经历表(bg_user_resume_work) │ ├─ user_resume_internship.py # 简历-实习经历表(bg_user_resume_internship) │ ├─ user_resume_project.py # 简历-项目经历表(bg_user_resume_project) │ ├─ user_resume_competition.py # 简历-竞赛经历表(bg_user_resume_competition) │ ├─ resume_diagnosis_report.py # 简历诊断报告表(bg_resume_diagnosis_report) │ ├─ resume_diagnosis_issue.py # 简历诊断问题表(bg_resume_diagnosis_issue) │ ├─ job.py # 岗位表(bg_job,只读,用于技能差距分析) │ ├─ job_agent_config.py # 求职助手配置表(bg_job_agent_config) │ └─ user_job_customize_resume.py # 用户岗位定制简历表(bg_user_job_customize_resume) │ ├─ tool/ # **工具层**(无状态、无业务依赖的通用工具) │ ├─ file_parser.py # 文件解析工具(PDF/Word/TXT → 纯文本,parse_to_text 入口方法) │ ├─ json_helper.py # AI 输出 JSON 解析工具(自动去除 markdown 代码块包裹 + json_repair 容错,parse_llm_json 入口方法) │ └─ snowflake.py # 雪花 ID 生成工具(next_id) │ ├─ 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) │ └─ nova_chat.py # Nova 对话助手 Schema(NovaChatParam、NovaChatDto) │ └─ services/ # **业务逻辑层** ├─ func_permission_service.py # 功能权限服务(校验+扣减+回退,逻辑与Java端一致) ├─ resume_parse_service.py # 简历解析服务(文件解析→AI结构化→写入主表+5张子表) ├─ resume_diagnose_service.py # 简历诊断服务(加载简历→AI并行诊断→统计评级→写入报告) ├─ skill_gap_service.py # 技能差距分析服务(差距分析→定制简历生成→AI对话编辑) ├─ resume_loader.py # 简历统一查询模块(按ID查/自动选默认+5张子表,返回 ResumeDetail dataclass) ├─ customize_resume_store.py # 定制简历存取模块(数据库持久化 + Redis回滚备份、按用户+岗位维度存取) ├─ job_agent_chat_service.py # 求职助手对话服务(查简历→序列化→调AI模块完成对话) └─ nova_chat_service.py # Nova 对话助手服务(查简历+查岗位(可选)→调AI,纯对话不持久化) ``` ## 2️⃣ 各层模块职责 | 层级 | 主要职责 | 关键类/文件 | |------|----------|-------------| | **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_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/TXT 文件解析为纯文本)、`json_helper.py`(AI 输出 JSON 解析,去 markdown 代码块 + json_repair 容错)、`snowflake.py`(雪花ID生成) | | **services** | 业务逻辑实现 | `FuncPermissionService`(功能权限校验、扣减、回退)、`ResumeParseService`(简历文件解析→AI结构化→入库)、`ResumeDiagnoseService`(简历诊断→AI并行分析→评级→入库)、`SkillGapService`(技能差距分析→定制简历生成→AI对话编辑)、`resume_loader`(简历统一查询,返回ResumeDetail)、`customize_resume_store`(定制简历数据库存取+数据构建,按用户+岗位维度,Redis回滚备份)、`JobAgentChatService`(求职助手对话+岗位简历优化)、`NovaChatService`(Nova对话助手,查简历+查岗位→调AI) | ## 3️⃣ 技术栈 | 类别 | 技术选型 | 说明 | |------|----------|------| | **Web 框架** | FastAPI + Uvicorn + Gunicorn | 异步 ASGI 框架 | | **ORM** | SQLAlchemy 2.0 (asyncio) + asyncmy | 异步 MySQL 驱动 | | **缓存** | redis-py (asyncio) | 异步 Redis 客户端 | | **AI/LLM** | LangChain + LangChain-OpenAI + LangGraph | AI 编排框架,兼容 OpenAI 协议的多供应商接入 | | **配置** | Pydantic Settings + python-dotenv | 类型安全的环境变量管理 | | **日志** | Loguru | 结构化日志,自动注入请求上下文 | | **鉴权** | PyJWT | JWT 解析,与 Java 端共享同一 jwt_secret | | **数据处理** | Pandas + NumPy | 数据分析与处理 | | **HTTP** | httpx | 异步 HTTP 客户端 | | **文件解析** | pdfplumber + python-docx | PDF 和 Word 文件内容提取 | ## 4️⃣ 中间件执行链(由外到内) | 顺序 | 中间件 | 职责 | |------|--------|------| | 1 | `RequestIDMiddleware` | 生成 ShortUUID 请求ID,写入响应头 X-Request-ID | | 2 | `JwtAuthMiddleware` | 从 Cookie/Header 解析 JWT,校验 Redis 登录信息,续期,写入 RequestContext.user_id | | 3 | `AuthRequiredMiddleware` | 非白名单路径必须有 user_id,否则返回 401 | | 4 | `RequestLogMiddleware` | 记录请求方法、URL、参数、响应状态码和耗时 | | 5 | `ResponseWrapMiddleware` | 将业务路由的 JSON 响应统一包装为 StandardResponse 格式 | ## 5️⃣ 鉴权体系 - 与 Java 端共享同一 JWT Secret 和 Redis 登录信息 - Token 来源:优先 Cookie `Token`,其次 Header `Token` - 白名单路径(`/health/**`、`/docs/**`、`/redoc/**`、`/openapi.json`)跳过鉴权 - 功能权限校验通过 `func_permission(func_code)` 依赖注入实现,逻辑与 Java 端 `FuncPermissionAspect` 完全一致: 1. 校验每日免费额度 2. 查付费库存(时间+次数维度) 3. SQL 原子扣减 4. 业务异常自动回退 ## 6️⃣ AI 模型配置 ### 模型定义(`app/ai/models.py`) | 供应商 | 模型 | 枚举值 | |--------|------|--------| | 火山引擎 | doubao-1-5-pro-32k-250115 | `LLM.DOUBAO_PRO_32K` | | 火山引擎 | doubao-1-5-lite-32k-250115 | `LLM.DOUBAO_LITE_32K` | | 火山引擎 | deepseek-v3-250324 | `LLM.DEEPSEEK_V3` | | 火山引擎 | deepseek-r1-250528 | `LLM.DEEPSEEK_R1` | | 火山引擎 | doubao-seed-2-0-mini-260215 | `LLM.DOUBAO_SEED_MINI` | | 火山引擎 | doubao-seed-2-0-lite-260215 | `LLM.DOUBAO_SEED_LITE` | | 火山引擎 | doubao-seed-2-0-pro-260215 | `LLM.DOUBAO_SEED_PRO` | | 加鱼 | gpt-4o | `LLM.GPT_4O` | | 接口 | gpt-4o-mini | `LLM.GPT_4O_MINI` | | 接口 | gemini-2.5-flash | `LLM.GEMINI_FLASH` | | 加鱼 | claude-sonnet-4.5 | `LLM.JIAYU_CLAUDE_SONNET_4_5` | | 加鱼 | claude-haiku-4.5 | `LLM.JIAYU_CLAUDE_HAIKU_4_5` | | 加鱼 | deepseek-3.2 | `LLM.JIAYU_DEEPSEEK_3_2` | | 加鱼 | glm-5 | `LLM.JIAYU_GLM_5` | | 加鱼 | qwen3-coder-next | `LLM.JIAYU_QWEN3_CODER_NEXT` | | 加鱼 | minimax-m2.5 | `LLM.JIAYU_MINIMAX_M2_5` | | ZM | gpt-5.5 | `LLM.ZM_GPT_5_5` | | ZM | gpt-5.4 | `LLM.ZM_GPT_5_4` | | ZM | gpt-5.4-mini | `LLM.ZM_GPT_5_4_MINI` | | ZM | gpt-5.2 | `LLM.ZM_GPT_5_2` | 所有模型通过 `LLM.XXX.create(**kwargs)` 创建 LangChain `ChatOpenAI` 实例,kwargs 透传 temperature、max_tokens 等参数。 ### 场景模型配置(`app/ai/model_config.py`) 业务代码**不直接使用** `LLM` 枚举,而是通过 `model_config.py` 中的场景配置类引用预创建的模型实例。修改模型或参数只需改此文件。 | 配置类 | 场景 | 说明 | |--------|------|------| | `SkillGapModel` | ANALYSIS / SUMMARY / EXPERIENCE / AGENT_PLAN / AGENT_EDIT / AGENT_ADD | 技能差距分析模块 | | `JobAgentModel` | CHAT / SUMMARY / EXPERIENCE | 求职助手Agent模块 | | `NovaChatModel` | CHAT | Nova智能聊天模块 | | `ResumeExtractorModel` | PARSE | 简历解析模块 | | `DiagnoserModel` | MODULE / SUMMARY / POLISH | 简历诊断模块 | | `BrowserPlugModel` | FORM_FILL | 浏览器插件模块 | 业务代码引用示例:`from app.ai.model_config import SkillGapModel`,然后在 chain 中直接使用 `SkillGapModel.ANALYSIS`。 ## 7️⃣ 与 Java 后端的关系 - **共享数据库**:Python 端与 Java 端(back-end)连接同一 MySQL 数据库(offerpie),ORM 模型对应相同的表 - **共享 Redis**:共享登录态(`login:token:{userId}`),JWT Secret 一致 - **共享权限体系**:功能权限校验逻辑与 Java 端 `FuncPermissionAspect` 完全对齐 - **职责分工**:Java 端负责业务 CRUD(用户、简历、岗位等),Python 端负责 AI 能力(LLM 调用、智能分析等) ## 8️⃣ 构建与运行 - **虚拟环境**:项目使用 `.venv` 目录管理 Python 虚拟环境 - **依赖安装**:`pip install -r requirements.txt` - **开发启动**:`python -m app.main`(默认 ENV=dev,端口由 settings.server_port 控制) - **生产部署**:通过 Gunicorn + Uvicorn Worker 运行 - **环境切换**:通过 `.env` / `.env.test` / `.env.prod` 文件控制环境变量