generated from kgod/ai-review-template
116 lines
6.1 KiB
Markdown
116 lines
6.1 KiB
Markdown
# Resume Agent(Offerπ 简历生成 Agent)
|
||
|
||
对话式简历生成服务:引导用户从新建流程分段填写经历,AI 将用户确认过的事实整理为优化稿。本仓库为 MVP 交付范围:
|
||
|
||
- **简历生成(Builder)**:分板块对话采集(教育/实习/项目/校园/竞赛等),事实→候选稿→确认写入
|
||
- **轻度优化**:基于条目已有事实的一键 STAR 优化稿(纯 LLM 改写 + 声明校验,不追加追问)
|
||
- 个人总结生成/再生成、技能推荐、目标岗位设置、条目级编辑/撤销
|
||
|
||
**当前不包含**:深度优化(多轮追问式)与 RAG 知识库。两者将随深度优化架构重构后单独集成;轻度优化自始不依赖知识库(优化稿仅基于用户已确认事实 + 声明校验)。
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
backend/ FastAPI 后端(Python 3.11+),SQLite(试点)或 PostgreSQL(生产)
|
||
frontend/ Vue 3 + Vite 前端(构建产物为静态文件)
|
||
```
|
||
|
||
## 快速开始
|
||
|
||
### 后端
|
||
|
||
```bash
|
||
cd backend
|
||
python -m pip install -r requirements.txt
|
||
cp .env.example .env # 配置 OPENAI_API_KEY / DATABASE_URL 等
|
||
python -m uvicorn app.asgi:application --port 8000
|
||
```
|
||
|
||
- `OPENAI_API_KEY` 留空时走规则兜底(可演示流程,无 AI 改写)。
|
||
- 生产使用 PostgreSQL:在 `.env` 配置 `DATABASE_URL`,表结构由 Alembic 迁移管理
|
||
(`alembic upgrade head`;存量 SQLite 数据可用 `scripts/migrate_sqlite_to_postgres.py` 迁移)。
|
||
- API 文档默认关闭;仅在开发环境设置 `RESUME_AGENT_API_DOCS=1` 开启 `/docs`。
|
||
|
||
### 前端
|
||
|
||
```bash
|
||
cd frontend
|
||
npm ci
|
||
npm run build # 产物在 frontend/dist,任意静态服务器/Nginx 托管
|
||
npm run dev # 开发模式(默认代理到本机 8000)
|
||
```
|
||
|
||
前端通过 `VITE_API_BASE_URL` 指定后端地址(默认同源 `/ai-api/resume-agent`)。
|
||
|
||
### OfferPai 账号入口
|
||
|
||
后端在 `.env` 保持 `OFFERPAI_AUTH_REQUIRED=true`,前端必须通过以下带 Token 的
|
||
地址进入:
|
||
|
||
```text
|
||
http://localhost:5173/?token=<OfferPai Token>
|
||
```
|
||
|
||
前端会立即从地址栏移除 `token`,将它只保存在当前页面内存中,并通过
|
||
`Authorization: Bearer` 附加到后续每个 API 请求。后端先调用 OfferPai 的
|
||
`checkLogin` 和用户信息接口,并校验当前账号拥有对应 session;鉴权成功后才创建、恢复
|
||
或修改会话。前端工作台也只会在取得受认证的 session 后挂载;缺少 Token 时返回
|
||
`401 external_auth_required`,鉴权失败时不会进入服务。
|
||
同一 OfferPai 用户再次从带 Token 的入口进入时会恢复其最近会话。
|
||
|
||
后端的账号资料只保存外部用户 ID、昵称和默认手机号,不保存原始 Token;另外会保存不含
|
||
Token 的 C 端同步元数据(远端简历 ID、同步状态、revision、内容 hash 和错误码)。默认
|
||
手机号会在手机号选择卡中自动选中,用户仍可改填其他手机号。页面每次完整重新加载都必须
|
||
重新携带 `?token=`。
|
||
|
||
### OfferPai C 端简历镜像
|
||
|
||
后端通过以下配置调用 OfferPai C 端简历接口:
|
||
|
||
```dotenv
|
||
OFFERPAI_RESUME_API_BASE_URL=https://test.offerpai.com.cn/api
|
||
OFFERPAI_RESUME_TIMEOUT_SECONDS=8
|
||
```
|
||
|
||
手动创建流程进入 `MINIMUM_READY`(完成姓名、邮箱、手机号、求职类型和目标岗位)时,
|
||
系统会自动创建本地工作文档与 OfferPai C 端简历,不再等待用户额外点击“创建简历”。
|
||
之后已确认的主表信息及教育、工作、实习、项目、竞赛五类经历会继续同步到 C 端;导入
|
||
简历确认后也会执行相同同步。候选优化稿、待确认个人总结等 Agent 中间结果不会作为正式
|
||
简历同步。local DB 仍保留会话 FSM、对话与组件生命周期、导入和优化任务状态,以及
|
||
简历 revision 缓存,用于并发校验、恢复会话和失败重试。
|
||
|
||
简历同步是双向的:时间线读取会先用 `/resume/list` 的 `updateTime` 检查远端是否变化,
|
||
变化后再读取主表和五个经历分区,并把 OfferPai 支持的字段拉回当前简历;教育、工作、
|
||
实习、项目、竞赛条目的段落 ID 用于保留本地条目 ID,不支持的本地分区继续留在本地。
|
||
本地编辑则使用“上次共同版本 B / 当前本地投影 L / 当前远端快照 R”判断:只远端变化时
|
||
拉取,只本地变化时推送,两边都变化时返回冲突(409),不会静默覆盖另一侧。前端工作台
|
||
会每 20 秒轮询时间线,并在窗口重新聚焦或恢复可见时立即检查。
|
||
|
||
暂时不能用 C 端接口完全替代 local DB:远程 HTTP 写入无法与本地会话事务原子提交,
|
||
且 Agent 仍依赖稳定的 section/entry/bullet ID、乐观 revision、pending proposal、撤销版本
|
||
和优化运行状态。只有在 C 端接口支持幂等写入、条件版本更新、稳定子项 ID,并完成远程
|
||
写入与本地状态的补偿/对账机制后,才适合进一步缩减本地简历缓存。
|
||
|
||
写操作会在同一 session 锁内完成远端预检查、本地修改和条件推送;远程 HTTP 仍无法与
|
||
本地数据库事务组成真正的跨系统原子提交,因此 C 端超时或拒绝时,本地 revision 可能
|
||
已经更新,失败状态会记录在 `profile.external_resume`,后续进入或读取会话时会按基线
|
||
继续补偿。远端被删除时读取不会自动重建或覆盖未知内容;需要先处理冲突/删除状态后再
|
||
重新开始。“重新开始”会先删除已绑定的 C 端镜像,再删除本地 session;远端已不存在按
|
||
幂等成功处理。
|
||
|
||
## 测试
|
||
|
||
```bash
|
||
cd backend
|
||
python -m pytest tests -q # 需要 .env 中配置 RESUME_AGENT_TEST_DATABASE_URL(Postgres 测试库)
|
||
cd frontend
|
||
npm run typecheck && npm run build
|
||
```
|
||
|
||
## 部署与安全基线
|
||
|
||
见 [docs/DEPLOY.md](docs/DEPLOY.md)。要点:试点期单进程 + 单 Postgres 即可,无需容器编排;
|
||
所有 session、简历编辑、SSE 和导入接口都会逐请求校验 OfferPai Token 及 session 所属用户;
|
||
仍建议部署在 HTTPS 网关之后。不要在环境变量中设置
|
||
`RESUME_AGENT_DEFAULT_TIER=vip`(会把全量会话提权)。
|