Resume AgentOfferπ 简历生成 Agent

对话式简历生成服务:引导用户分段填写经历,AI 将用户确认过的事实整理为优化稿,支持导入既有简历继续编辑。本仓库为 MVP 交付范围:

  • 简历生成(Builder:分板块对话采集(教育/实习/项目/校园/竞赛等),事实→候选稿→确认写入
  • 轻度优化:基于条目已有事实的一键 STAR 优化稿(纯 LLM 改写 + 声明校验,不追加追问)
  • 简历导入:docx/pdf/图片解析为结构化草稿,确认后并入在线简历
  • 个人总结生成/再生成、技能推荐、目标岗位设置、条目级编辑/撤销

当前不包含:深度优化(多轮追问式)与 RAG 知识库。两者将随深度优化架构重构后单独集成;轻度优化自始不依赖知识库(优化稿仅基于用户已确认事实 + 声明校验)。

目录结构

backend/    FastAPI 后端(Python 3.11+),SQLite(试点)或 PostgreSQL(生产)
frontend/   Vue 3 + Vite 前端(构建产物为静态文件)

快速开始

后端

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

前端

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 的 地址进入:

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 端简历接口:

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/listupdateTime 检查远端是否变化, 变化后再读取主表和五个经历分区,并把 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;远端已不存在按 幂等成功处理。

测试

cd backend
python -m pytest tests -q        # 需要 .env 中配置 RESUME_AGENT_TEST_DATABASE_URLPostgres 测试库)
cd frontend
npm run typecheck && npm run build

部署与安全基线

docs/DEPLOY.md。要点:试点期单进程 + 单 Postgres 即可,无需容器编排; 所有 session、简历编辑、SSE 和导入接口都会逐请求校验 OfferPai Token 及 session 所属用户; 仍建议部署在 HTTPS 网关之后。不要在环境变量中设置 RESUME_AGENT_DEFAULT_TIER=vip(会把全量会话提权)。

S
Description
ai创建简历的agnet
Readme
650 KiB
Languages
Python 79%
Vue 15.8%
TypeScript 4.2%
CSS 0.8%
JavaScript 0.1%