8.4 KiB
8.4 KiB
后端 API 对接指南
前端四条演示流和演示预检已经稳定。后端 API 按页面逐刀接入,避免一次性铺满四个页面。
第一阶段范围
| 页面 | 后端接口 | 处理 |
|---|---|---|
AI面试 /recruit/interview |
POST /api/recruit/interview/start、/answer、/finish |
已接入 seed API |
三角色对练 /train/practice |
POST /api/train/practice/start、/turn、/finish |
已接入 seed API |
案例沉淀 /knowledge/cases |
POST /api/knowledge/case/upload、/organize、/curate |
已接入 seed API |
SOP知识库 /knowledge/sop |
POST /api/knowledge/search、POST /api/knowledge/doc/upload |
已接入 MySQL Fulltext + Qdrant 混合召回、OSS-first 文档上传、txt/md/PDF/Word/Excel/PPT 解析和 embedding 写入,失败回退 seed |
资料处理 /knowledge/processing |
GET /api/knowledge/processing/overview、POST /api/knowledge/doc/import-local-task、GET /api/knowledge/doc/import-tasks、复用 POST /api/knowledge/doc/upload |
已接入解析任务状态聚合;页面支持多文件/目录选择、服务端后台目录导入和进度轮询,失败回退 seed |
后端落点
- 业务模块:
backend/ruoyi-modules/ruoyi-aihr - 注册模块:
backend/ruoyi-modules/pom.xml - 接入启动包:
backend/ruoyi-admin/pom.xml - 包名建议:
org.dromara.aihr - Controller 返回统一用
org.dromara.common.core.domain.R
当前四条页面流仍保留 seed fallback。知识库、模型能力、文档解析、RAG、chat 按 ruoyi-ai 能力分片迁移计划 逐片引入;知识库 DDL 与住宅类 SOP seed 在 backend/script/sql/aihr_knowledge_mysql8.sql,模型 DDL 在 backend/script/sql/aihr_model_mysql8.sql。
直接打后端 /api/** 需要登录后的 Authorization: Bearer <access_token>;浏览器内通过已登录前端和 /dev-api 代理访问。
SOP 文档上传第三片已经落最小后端边界:
| 能力 | 后端接口 | 处理 |
|---|---|---|
| 文档上传解析 | POST /api/knowledge/doc/upload |
multipart/form-data,字段 file 和 category;支持 .txt/.md/.markdown/.pdf/.doc/.docx/.xls/.xlsx/.ppt/.pptx、100MB 内;先写 sys_oss,再绑定 aihr_knowledge_attach.oss_id 并切分写入 aihr_knowledge_fragment |
| 智能归类与标签 | 同一上传/导入链路 | category=__auto__ 时,解析正文后优先调用已启用的 aihr_model_config.category='chat' 模型生成分类、摘要、标签和归类理由,温度固定为 0;无模型或调用失败时按文件名/正文关键词兜底。最终分类写入 aihr_knowledge_info/attach,摘要和标签写入 sys_oss.ext1 |
| 重复资料处理 | 同一上传/导入链路 | 上传时计算原始文件 aihrFileSha256、解析文本 aihrTextSha256 和 md5 写入 sys_oss.ext1;重复判断优先按文件 SHA-256,其次按文本 SHA-256,最后用同名同大小兼容旧数据。命中重复时复用原附件并迁移到最新分类,删除其他重复附件和旧 fragment |
| 归类稳定性 | 同一上传/导入链路 | 命中重复资料时优先复用已有 sys_oss.ext1 里的分类、摘要和标签;只有旧资料没有存过模型结果时才重新分析,避免同文件因重复上传或更换模型导致标签漂移 |
| 文档替换 | 同一 category + fileName 再上传 |
复用原 doc_id,删除旧 fragment 后重写新 fragment,避免重复文档堆积 |
| 片段向量化 | 同一上传接口内机会性执行 | 若 aihr_model_config.category='vector' 且启用,会调用配置供应商的 OpenAI-compatible /embeddings,把返回向量写入 aihr_knowledge_fragment.embedding_json |
| Qdrant 向量索引 | 同一上传接口内机会性执行 | embedding 写入 MySQL 后尽力 upsert 到 Qdrant;同名文档替换会尽力删除旧 points;Qdrant 不可用不影响上传和 MySQL 检索 |
| 混合检索 | POST /api/knowledge/search |
先跑 MySQL Fulltext,同时在 vector 模型和 Qdrant 可用时生成 query embedding 走 Qdrant,再按 RRF 融合并回 MySQL hydrate 片段 |
| 解析状态聚合 | GET /api/knowledge/processing/overview |
聚合 aihr_knowledge_attach.status、fragment 数、embedding 数、sys_oss.ext1.fileSize,生成资料处理页指标、分类、任务、链路和最近事件 |
| 服务端目录导入 | POST /api/knowledge/doc/import-local |
JSON { directory, category, limit };directory 只能是 AIHR_IMPORT_ROOT / aihr.import.root 下的相对目录,默认根目录为 ./.data/import;逐文件复用上传解析链路,同步执行,保留给小批量/调试 |
| 服务端导入任务 | POST /api/knowledge/doc/import-local-task、GET /api/knowledge/doc/import-tasks |
启动后台目录导入并返回任务;任务写入 aihr_knowledge_import_task,页面轮询查看总数、成功数、失败数、当前文件和进度;重试当前按同目录重新启动一轮 |
模型能力第二片已经落最小后端边界:
| 能力 | 后端接口 | 处理 |
|---|---|---|
| 模型供应商 | GET /api/aihr/model/providers、POST /api/aihr/model/providers、PUT /api/aihr/model/providers/{providerCode}、PATCH /api/aihr/model/providers/{providerCode}/status |
优先返回 aihr_model_provider,支持新增、编辑、启停;缺表或空表时返回 seed 清单 |
| 模型配置 | GET /api/aihr/model/configs、POST /api/aihr/model/configs、PUT /api/aihr/model/configs/{id}、PATCH /api/aihr/model/configs/{id}/enabled |
优先返回 aihr_model_config,支持新增、编辑、启停,并计算是否已具备 URL/Key |
| 模型探针 | POST /api/aihr/model/chat |
数据库配置后走 OpenAI-compatible /chat/completions,否则 seed fallback |
本阶段不修改 .env,也不自动执行模型 SQL。API Key 通过模型配置页面写入数据库:api_key 可放在 aihr_model_provider 作为供应商默认值,也可放在 aihr_model_config 覆盖单个模型;接口响应只返回 configured/apiKeyConfigured,不返回密钥明文。
Qdrant 本地默认值可不配;需要覆盖时用 JVM property 或环境变量:
| 配置 | 默认值 | 用途 |
|---|---|---|
AIHR_QDRANT_URL / -Daihr.qdrant.url |
http://127.0.0.1:6333 |
Qdrant REST 地址 |
AIHR_QDRANT_COLLECTION / -Daihr.qdrant.collection |
aihr_knowledge |
知识库向量 collection |
AIHR_QDRANT_API_KEY / -Daihr.qdrant.apiKey |
空 | 远端 Qdrant API Key,本地不用 |
AIHR_IMPORT_ROOT / -Daihr.import.root |
./.data/import |
服务端资料目录导入根目录 |
前端落点
- AI 面试 API 文件:
frontend/src/api/aihr/interview.ts - AI 面试页面:
frontend/src/views/recruit/interview.vue - 三角色对练 API 文件:
frontend/src/api/aihr/practice.ts - 三角色对练页面:
frontend/src/views/train/practice.vue - 案例沉淀 API 文件:
frontend/src/api/aihr/case.ts - 案例沉淀页面:
frontend/src/views/knowledge/cases.vue - SOP 知识库 API 文件:
frontend/src/api/aihr/sop.ts - SOP 知识库页面:
frontend/src/views/knowledge/sop.vue - 资料处理 API 文件:
frontend/src/api/aihr/processing.ts - 资料处理页面:
frontend/src/views/knowledge/processing.vue - 模型配置 API 文件:
frontend/src/api/aihr/model.ts - 模型配置页面:
frontend/src/views/system/model/index.vue - 保留本地 seed fallback:接口失败时仍能演示,不让现场 Demo 被后端状态拖死。
验收
./scripts/demo-check.sh
npm --prefix frontend run lint:eslint -- src/api/aihr/interview.ts src/views/recruit/interview.vue src/api/aihr/practice.ts src/views/train/practice.vue src/api/aihr/case.ts src/views/knowledge/cases.vue src/api/aihr/sop.ts src/views/knowledge/sop.vue
mvn -f backend/pom.xml -pl ruoyi-admin -am -DskipTests package
模型能力可单独 smoke:
TOKEN=<登录后 access_token>
curl -fsS http://127.0.0.1:8080/api/aihr/model/providers -H "Authorization: Bearer $TOKEN"
curl -fsS http://127.0.0.1:8080/api/aihr/model/configs -H "Authorization: Bearer $TOKEN"
curl -fsS -X POST http://127.0.0.1:8080/api/aihr/model/chat \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"prompt":"物业管家处理漏水投诉第一步是什么?"}'
Qdrant 可单独 smoke:
curl -fsS http://127.0.0.1:6333/
浏览器验收仍按 DEMO_ACCEPTANCE.md 的四条关键路径执行。