feat(practice): server-owned realtime personas with knowledge tool calling

- AihrRealtimePersonaRegistry whitelist: owner-calm (default), owner-impatient,
  digital-mentor (search_knowledge); persona binds default voice
- /realtime/session assembles session.update server-side (instructions/tools);
  browser forwards payload verbatim; Redis session record 30min with sliding renewal
- /realtime/tools/invoke validates login identity + Redis session ownership +
  persona tool whitelist, then read-only searchAuthorized; per-account rate limits
- source=realtime skips sop review and knowledge-gap persistence (Beta no-persist)
- frontend: persona cards replace 56-voice picker; serialized tool-call chain with
  soft-landing fallback
This commit is contained in:
2026-07-25 11:13:04 +08:00
parent 3a19b475a8
commit 35b37b07f7
17 changed files with 1180 additions and 214 deletions
+1
View File
@@ -64,6 +64,7 @@
- 候选面试复用 `/api/recruit/interview/**`;补充资料走认证的移动端接口,先写 `sys_oss`/MinIO,再写 `aihr_candidate_material`,状态仅为 `待审核/已通过/已驳回`,由管理端 `/recruit/interview` 审核。上传接口不得放入 class-level `@SaIgnore`。
- 后端 API 对接先看 `docs/API_INTEGRATION.md`。三角色对练 `/turn`/`/finish` 使用 `AihrPracticeLlmService`,必须保留“未配置/失败回退 seed”的降级链。
- 对练语音复用 `/api/ai/asr` 与 `/api/ai/tts`,TTS 保持旧 `voice` 兼容并支持角色音色。浏览器录音不可用或权限失败时,用 `audio/*` file input 继续走同一 ASR,不退回纯文字;新增 multipart 外发同样清洗 filename/contentType 的 CRLF。
- 实时对练 Beta(WebRTC)的人设与工具声明只由服务端 `AihrRealtimePersonaRegistry` 白名单组装,浏览器原样转发 session.update,不得恢复前端自组 instructions 或音色 picker;工具执行按登录态 + Redis 会话归属 + 人设白名单三重校验,仅只读知识检索且 `source=realtime` 不落 SOP 评审/知识缺口表;实时 Beta 不计分、不持久化、仅 H5、需 APP 登录态,接口契约见 `docs/API_INTEGRATION.md`。
- 后端业务代码不要塞进上游 `ruoyi-demo`;自有 API 放在 `backend/ruoyi-modules/ruoyi-aihr`,再接入 `ruoyi-admin`。
- AI 面试、三角色对练、案例、SOP 和三端首页保持真实 API/模型优先与既有降级。知识检索以 MySQL 为事实源,Qdrant/vector/rerank 是可选增强;向量维度不一致必须经状态与重建入口处理,不得静默换成本地向量。
- 批量资料和所有视频只走 `/api/knowledge/doc/upload-async` 异步队列;同步 `/api/knowledge/doc/upload` 仅供 SOP 单文件即时预览,禁止把重加工塞回请求线程。格式、大小、超时、OCR/视频解析和重试契约以 `docs/API_INTEGRATION.md` 为准;图片无可用视觉结果时保持「待处理」,视频关键帧不得退回纯 OCR。