first commit
This commit is contained in:
104
README.md
Normal file
104
README.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# Resume Parse API
|
||||
|
||||
一个简单的 Node.js/Express 接口:上传简历文档(支持 `.docx` / `.pdf`),提取文本后返回结构化信息和面试评估内容。
|
||||
|
||||
## 运行
|
||||
|
||||
1. 安装依赖
|
||||
- `npm install`
|
||||
2. 启动开发模式
|
||||
- `npm run dev`
|
||||
3. 服务启动后默认地址
|
||||
- `http://localhost:3000`
|
||||
|
||||
## 健康检查
|
||||
|
||||
- `GET /health`
|
||||
返回示例:`{ "ok": true, "mysql": { "ok": true, "skipped": false, "database": "Resume" } }`
|
||||
- 未配置 `MYSQL_HOST` 时:`mysql.skipped === true`
|
||||
- 连接失败时:`mysql.ok === false` 且带 `mysql.error`
|
||||
|
||||
## MySQL(远程库 Resume)
|
||||
|
||||
在 `.env` 中配置(勿提交到 Git,仓库已忽略 `.env`):
|
||||
|
||||
- `MYSQL_HOST`:服务器 IP 或域名(必填)
|
||||
- `MYSQL_PORT`:默认 `3306`
|
||||
- `MYSQL_USER`:默认 `root`(按你服务器实际账号修改)
|
||||
- `MYSQL_PASSWORD`
|
||||
- `MYSQL_DATABASE`:默认 `Resume`
|
||||
|
||||
启动时会在控制台打印 `[mysql] 已连接` 或 `[mysql] 连接失败`。代码里通过 `require("./mysql").getMysqlPool()` 获取连接池。
|
||||
|
||||
### 入库说明
|
||||
|
||||
- 连接成功后会自动维护表 **`resume_submissions`**。
|
||||
- **列结构**:与解析结果对齐,**姓名、城市、年龄、期望薪资、教育经历、学历、能力、工作经历、项目经历、技术栈**各占一列(便于查询、统计、以后查重);**不再写入**整段 `extracted_text`。
|
||||
- **JSON 列**:`interview_report`(AI 面试题与整块评估)、`pdf_meta`(PDF/OCR 元信息)、`warnings_json`(解析告警列表)。
|
||||
- 若检测到**旧版表**(曾含 `extracted_text` 列),启动时会 **DROP 后重建**,旧数据会清空,请注意备份。
|
||||
- 接口响应里仍有 **`db`**:`{ "saved": true, "id": 1 }` 等含义不变。
|
||||
|
||||
## 解析接口
|
||||
|
||||
### 推荐流程(前端默认)
|
||||
|
||||
1. **`POST /api/resume/step1`**(`multipart/form-data`,字段 `file`)
|
||||
- 抽取文本、计算 `file_sha256`、与库比对是否重复(同哈希且已有 `interview_report`)。
|
||||
- **不调 AI**。返回 `parsedPreview`(规则)、`text`、`fileSha256`、`uploadId`(非重复时用于第二步)、`isDuplicate` 等。
|
||||
|
||||
2. **`POST /api/resume/consult-ai`**(`application/json`)
|
||||
- Body:`{ "fileSha256": "...", "uploadId": "..." }`(重复时可省略 `uploadId`)。
|
||||
- 若重复:直接返回库内 `interview_report` 与列字段还原的 `parsed`,**不请求模型**。
|
||||
- 若不重复:用 `uploadId` 取内存会话,调用 AI,写入 `resume_submissions`,并清除会话。
|
||||
|
||||
### 兼容接口
|
||||
|
||||
- `POST /api/parse-word`:一步完成「抽取 + AI + 入库」(脚本或旧客户端可用)。
|
||||
- 请求类型:`multipart/form-data`
|
||||
- 文件字段名:`file`
|
||||
|
||||
### curl 示例
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:3000/api/parse-word" ^
|
||||
-F "file=@D:\test\demo.docx"
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:3000/api/parse-word" ^
|
||||
-F "file=@D:\test\demo.pdf"
|
||||
```
|
||||
|
||||
### 返回
|
||||
|
||||
```json
|
||||
{
|
||||
"filename": "demo.pdf",
|
||||
"mimeType": "application/pdf",
|
||||
"sourceType": "pdf",
|
||||
"text": "解析出的内容(纯文本)",
|
||||
"parsed": {
|
||||
"姓名": "张三"
|
||||
},
|
||||
"interviewReport": {
|
||||
"interviewQuestions": []
|
||||
},
|
||||
"warnings": []
|
||||
}
|
||||
```
|
||||
|
||||
## 说明
|
||||
|
||||
- 当前使用 `mammoth` 解析 `.docx`,使用 `pdf-parse` 解析 `.pdf`。
|
||||
- **扫描版 PDF(几乎无文本层)**:当文本层有效字符数低于阈值时,可启用 OCR:使用 `pdfjs-dist` + `@napi-rs/canvas` 将页面渲染为图片,再用 `tesseract.js` 识别文字。
|
||||
- **`PDF_OCR_ENABLED=1` 才会执行 OCR**(默认不开启,避免首次下载模型时请求长时间无响应)。
|
||||
- `PDF_OCR_MIN_CHARS`:低于该有效字符数才尝试 OCR,默认 `80`
|
||||
- `PDF_OCR_MAX_PAGES`:最多 OCR 的页数,默认 `5`
|
||||
- `PDF_OCR_SCALE`:渲染缩放(越大越清晰但更慢),默认 `2`
|
||||
- `PDF_OCR_DISABLED`:设为 `1` 可强制关闭 OCR(优先级高于 `PDF_OCR_ENABLED`)
|
||||
- `PDF_OCR_LANG`:Tesseract 语言,默认 `chi_sim`。可设为 `eng` 或 `chi_sim+eng` 等
|
||||
- `PDF_OCR_INIT_TIMEOUT_MS`:初始化 Tesseract(含首次下载)超时,默认 `120000`
|
||||
- `PDF_OCR_PAGE_TIMEOUT_MS`:单页识别超时,默认 `120000`
|
||||
- 项目将 `pdfjs-dist` 固定为 `5.4.296`,与 `pdf-parse` 内置版本一致,避免 Worker 与 API 版本不一致。
|
||||
- 如果你需要支持 `.doc`(旧版 Word),告诉我你的文档来源/格式,我可以再加转换或抽取方案。
|
||||
|
||||
Reference in New Issue
Block a user