Files
prop-ai-hr/docs/个人AI助理阶段二专项TechSpec.md

839 lines
48 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 员工个人 AI 助理 / 个人知识空间专项 TechSpec
> 版本:v1.5 | 日期:2026-07-22
>
> 归属:《银城员工端 APP 分阶段实施总纲》阶段二
>
> 需求基线:《物业 AI 人力资源系统业务需求文档 BRD》4.8
>
> 实施边界:首批交付个人资料收藏、检索、带引用问答、工作整理,以及“识别候选记忆 → 用户确认 → 分域持久化 → 可追溯召回”闭环;PPT 生成为 P1;北森、考勤等外部数据归阶段三。
>
> v1.1 需求补充:客户明确提出,员工在对话中描述住户需求、待跟进事项或个人经验时,个人助理应识别值得长期保留的信息,返回可编辑确认卡;仅在用户确认后写入对应记忆域,后续问答可按权限召回。模型不得直接修改数据库,提醒必须单独确认。
>
> v1.2 实施收口:显式“记一下 / 帮我记 / 保存一下”统一生成 `ASSISTANT_CAPTURE` 确认卡;楼栋、单元、房号和项目均为可补充信息,不再阻断保存。用户必须选择“仅自己保存 / 提交公司处理”;公司处理首批只可靠写入待流转队列,未配置正式接收接口前不得显示“已送达”。音色不在本次范围。
>
> v1.3 文档收口:v1.2 描述的是 2026-07-20 已部署行为;多项目工作采集按[《工作助手与今日工作成果迭代计划》](工作助手与今日工作成果迭代计划-20260721.md)执行。个人笔记允许项目为空,项目工作记录必须先按名称选择当前项目;项目编码只作内部授权字段,不由用户输入。
>
> v1.4 发布前本地实施快照:项目名称选择、项目化短会话、项目化确认卡、来源快照、业务状态历史、员工今日成果和主管项目成果已完成本地实现、真实 HTTP 与 390×844 验证;该快照记录的是发布前状态,外部线索/工单/考勤投递仍保持 PENDING。
> v1.5 发布与本轮回填:v1.4 所列多项目、项目化确认采集、来源/状态、员工今日成果和主管项目成果已于 2026-07-21 部署;成果历史日期选择、服务端拒绝未来日期,以及主管手机号授权兜底已于 2026-07-22 发布,并完成远端服务、schema 与产物匹配复核。外部线索/工单/考勤投递仍保持 PENDING。
当前代码状态(2026-07-22 复核):已部署版本包含候选检测、可编辑确认、PRIVATE/COMPANY 持久化、项目名称选择、项目化短会话、`ATTENDANCE/INSPECTION` 分类、来源绑定、状态闭环、员工工作成果和主管项目成果,以及成果历史日期查看、未来日期拒绝和手机号授权兼容。个人文件/网页知识空间、PPT 自动生成、外部线索/工单投递 Worker 和正式回执仍是后续工作。开发者不得从 `PENDING` 推断已派单或已送达。
## 0. 交互设计基准
![工作助手语音优先与确认记忆交互基准](prototypes/personal-assistant-work-helper-voice-first-v2.png)
设计资产:[personal-assistant-work-helper-voice-first-v2.png](prototypes/personal-assistant-work-helper-voice-first-v2.png)
多项目与今日成果联合高保真资产:[work-assistant-project-context-v3.png](prototypes/work-assistant-project-context-v3.png),仓库绝对路径为 `/Users/yuanjiantsui/dev/11-project/wygj/docs/prototypes/work-assistant-project-context-v3.png`;逐状态运行截图路径见[迭代计划 §1.5](工作助手与今日工作成果迭代计划-20260721.md#15-本地运行视觉证据390844)。
该图是阶段二「问」页和确认记忆流程的实现参考,不是当前生产截图。后续 Agent 实施 `mobile-uni/src/pages/user/sop/index.vue` 与记忆确认卡时应遵守以下不变量:
1. 页面标题保持“问 · 数字师傅”,一级只区分“工作助手 / 查全网”,不增加“个人助理”一级 Tab。
2. 工作助手自动在已授权的个人资料、项目记录和企业知识中路由;首屏主路径不要求一线员工选择资料域,高级筛选只能放入次级入口。
3. 会话保持语音优先:输入区默认“按住说话”,键盘为切换能力;师傅回复优先显示语音条,正文可通过“转文字”展开。
4. ASR 转写以普通用户消息进入同一会话;候选检测不得绕过当前会话、登录态或项目权限。
5. 确认卡至少展示系统建议类型、对象、事项、可见范围、明确回访日期和“加入跟进提醒”选项;缺少房号等信息只作弱提示。
6. `ASSISTANT_CAPTURE` 卡必须提供“修改 / 暂不保存 / 仅自己保存 / 提交公司处理”四个明确动作;旧项目服务卡继续保留“确认保存”。保存和提醒分别确认。
7. 回答或保存结果只展示实际使用的来源,不得暗示已查询未命中的资料,更不得自动把内部内容转发到全网。
若设计图中的示例文案、间距或字段与本文的数据权限、安全、状态机或 API 约束冲突,以本文约束为准;视觉实现应继续复用现有 `ChatComposer`、女性数字师傅头像和「今日 / 练 / 问 / 我」底栏。
## 1. 目标与非目标
### 1.1 目标
为每名已登录员工提供与企业知识库隔离的个人知识空间,支持:
1. 收藏个人文字、文件、图片和网页链接。
2. 自动解析正文、生成摘要与主题标签。
3. 按日期、主题、来源和关键词检索个人资料。
4. 默认由“工作助手”在个人资料、项目业务记忆和企业知识之间自动路由并展示实际来源;资料范围只作为次级高级筛选。
5. 输出结论、行动项和待确认事项,并逐条展示引用来源。
6. 删除个人资料时同步清理关系库、对象存储和向量索引。
7. 从文字或 ASR 转写中识别服务线索、住户画像、优秀案例、个人想法、待跟进事项和工作记录,返回可编辑确认卡。
8. 用户确认保存范围:`PRIVATE` 仅本人可见;`COMPANY` 进入企业待流转队列。项目服务旧记录继续按项目权限独立保存和检索。
9. 后续问答可召回已确认记忆,并展示来源消息、记录时间、当前状态和可见范围。
10. 对确认后的修改保留版本历史;提醒时间与长期保存分别确认。
### 1.2 非目标
- 阶段二首批不生成 PPT 文件,只生成可编辑汇报提纲。
- 不读取北森、考勤、请假、任职等阶段三外部数据。
- 不做通用网盘、多人协作文档、在线 Office 编辑和自动对外发送。
- 不允许个人资料自动进入企业知识库。
- 不通过“收藏网页”绕过登录、付费墙、企业内网或版权限制。
- 不复用企业知识表增加 `scope_type` 来承载个人数据。
- 不把普通聊天历史自动升级为长期记忆,不在用户确认前写入个人或项目长期记忆表。
- 不允许 LLM 直接执行 SQL、更新业务实体、创建提醒或对外发送消息;模型只生成结构化候选草稿。
- 不把 `COMPANY/PENDING` 描述成已生成工单、已上报或已送达;正式接收端、认证和回执协议确定后才启用投递 Worker。
- 不把住户服务事实只存入员工私人空间;这类记录属于项目业务域,员工调岗后仍按项目权限保留。
- 阶段二首批不替代权威房屋、住户、工单或 CRM 主数据;未接入权威主数据时不得伪造住户身份。
## 2. 核心架构决策
### 2.1 处理能力复用,数据物理分域
| 能力 | 复用方式 | 隔离要求 |
|---|---|---|
| 文件上传与 OSS | 复用 `ISysOssService` | 使用私有前缀 `personal/{tenantId}/{userId}/{itemId}/` |
| 文档解析 | 从 `AihrSopSeedService` 抽取无状态解析组件 | 解析结果只能写个人表 |
| Embedding / Rerank / LLM | 复用现有模型配置与成本闸门 | 调用前按个人资料规则脱敏,不写企业片段表 |
| 全文检索 | 使用个人片段表 MySQL Fulltext | 查询必须包含 `tenant_id + owner_user_id` |
| 向量检索 | 新建 `aihr_personal_knowledge` collection | Qdrant filter 必须包含 `tenant_id + owner_user_id` |
| 企业知识检索 | 调用现有企业 RAG 服务 | 继续执行企业知识密级、项目和角色权限 |
| 项目业务记忆 | 独立 `aihr_service_memory` 关系表;关系库检索为 2026-07-19 最小切片,Qdrant 仅列为后续增强 | 查询必须包含 `tenant_id + project_code`,不得写入个人或企业知识表 |
| 对话统一采集 | `aihr_memory_candidate` 暂存确认卡,确认后写 `aihr_assistant_capture` | `PRIVATE` 仅按 owner 查询;`COMPANY` 以 outbox 状态流转,不允许前端伪造已送达 |
禁止将个人资料写入:
- `aihr_knowledge_info`
- `aihr_knowledge_attach`
- `aihr_knowledge_fragment`
- 企业 Qdrant collection `aihr_knowledge`
### 2.2 检索流程
```text
用户问题 + scopeMode(AUTO / MANUAL) + scope(personal / project_service / enterprise)
→ 从移动端 token 取得 tenantId、userId、extPartyId
→ AUTO: 意图路由只在三个内部授权域中选择;MANUAL: 校验用户指定的内部范围
→ 校验日期、itemIds、知识范围和配额
→ personal: 个人 Fulltext + 个人 Qdrant(强制 owner filter)
→ project_service: 首批用关系库检索并强制 project_code filter;后续再叠加独立 Qdrant
→ enterprise: 企业 Fulltext + 企业 Qdrant(强制企业权限)
→ mixed: 所选域分别检索并授权后融合,不做跨域原始结果直连
→ Rerank
→ LLM 生成答案
→ 返回 citations,每条标记 PERSONAL / PROJECT_SERVICE / ENTERPRISE / WEB
→ 保存会话、答案、引用和 prompt/model 版本
```
`AUTO` 永远不包含公网查询。内部域没有命中时只返回“是否查全网”的用户操作建议,不得把原问题、住户信息或项目数据自动转发到全网 AI。
### 2.3 模块边界
后端新增独立包,避免继续扩大 `AihrSopSeedService`:
```text
org.dromara.aihr.personal
├── controller/PersonalAssistantController.java
├── domain/PersonalAssistantDto.java
├── service/PersonalSpaceService.java
├── service/PersonalIngestionService.java
├── service/PersonalRetrievalService.java
├── service/PersonalAnswerService.java
├── service/PersonalCleanupService.java
├── service/PersonalUrlFetchService.java
├── memory/MemoryCandidateService.java
├── memory/MemoryConfirmationService.java
├── memory/ServiceMemoryService.java
├── memory/ServiceMemoryRetrievalService.java
└── support/PersonalKnowledgeProperties.java
```
解析器抽为共享、无状态能力:
```text
org.dromara.aihr.knowledge.parse
├── KnowledgeDocumentParser.java
├── ParsedDocument.java
└── KnowledgeChunker.java
```
共享解析器只接受文件/字节和解析参数,只返回内存对象,不知道企业表、个人表或 Qdrant collection。
### 2.4 确认式长期记忆
个人助理统一承接三层记忆,但持久化边界不同:
| 记忆层 | 用途 | 生命周期与事实源 |
|---|---|---|
| 对话上下文 | 理解“刚才那位住户”等短期指代 | 仅进入受限上下文窗口;会话历史不自动成为长期记忆 |
| 个人工作记忆 | 员工自己的经验、灵感、工作方法 | 用户确认后写入 `aihr_personal_item`,默认仅本人可见 |
| 项目业务记忆 | 住户需求、服务事实、待跟进事项 | 用户确认后写入 `aihr_service_memory`,按租户 + 项目 + 角色授权共享 |
写入流程固定为:
```text
文字输入 / 语音 ASR 转写
→ 规则预筛(明确“记一下”等意图,或同时出现对象 + 需求/跟进事实)
→ 服务端先提取并令牌化楼栋、单元、房号、姓名、电话等标识
→ 当前 P0 用确定性规则建议类型和分类;后续模型只能输出符合 JSON Schema 的候选建议
→ 服务端校验当前租户、项目、重复记录、权限和敏感字段
→ 显式“记一下”始终持久化 DRAFT;项目/楼栋/单元/房号缺失只列为可选补充项
→ 用户修改并选择 PRIVATE / COMPANY(携带幂等键和 expectedVersion)
→ 确定性 Service 写 `aihr_assistant_capture`;PRIVATE 记为 NOT_REQUIRED,COMPANY 记为 PENDING
→ 正式企业接收端接入后,由独立投递 Worker 消费 PENDING 并记录回执;当前不得假投递
→ 如用户另行确认 followUpAt,则进入“今日安排”;不默认创建提醒
```
约束:
1. 候选检测可自动发生,但任何置信度都不得跳过用户确认。
2. DRAFT 候选只为跨刷新恢复确认卡,不进入检索和回答;忽略或过期后清理草稿内容。
3. 同一来源消息和候选哈希在有效期内只展示一次,避免重复打扰。
4. 当前仓库没有权威房屋/住户主数据。首批允许保存经员工确认的可选项目、楼栋、单元、房号定位;缺少这些字段仍可保存,但不得据此虚构或合并住户身份。
5. 关系数据库是事实源,向量索引只负责召回;索引写入失败不得丢失已确认记录,可重试重建。
## 3. 身份、权限与数据隔离
### 3.1 所有者身份
- `owner_user_id`:本地 `sys_user.user_id`,作为阶段二强制所有权键。
- `owner_ext_party_id`:可空,保存组织快照外部主体 ID,供阶段三身份迁移使用。
- `tenant_id`:沿用 RuoYi 多租户上下文。
- Controller 不接受客户端提供的 `ownerUserId`、`tenantId`。
- Service 每次查询都从当前登录态取得 `tenant_id + user_id`,不得只按主键查询。
### 3.2 访问矩阵
| 操作 | 本人 | 普通主管 | HR/运营 | 系统管理员 |
|---|---:|---:|---:|---:|
| 查看个人资料正文 | ✅ | ❌ | ❌ | ❌(默认) |
| 查看个人资料数量/处理状态 | ✅ | ❌ | 聚合且脱敏 | 聚合且脱敏 |
| 删除本人资料 | ✅ | ❌ | ❌ | ❌(默认) |
| 申请分享/企业入库 | ✅ | ❌ | 审核申请 | 审核申请 |
| 紧急审计查看 | ❌ | ❌ | 需 `aihr:personal:audit`、工单号和原因 | 同左 |
紧急审计必须记录审计人、目标用户、itemId、原因、工单号、时间和结果;正文不写入审计日志。
### 3.3 防越权规则
1. 所有 `/api/aihr/personal-assistant/**` 接口必须登录,不使用 `@SaIgnore`。
2. 单项读取、删除、重试必须使用 `WHERE id=? AND tenant_id=? AND owner_user_id=?`。
3. Qdrant 查询必须同时过滤 `tenant_id` 和 `owner_user_id`。
4. 企业知识结果进入融合前必须经过企业权限过滤;客户端传来的 fragmentId 不能直接作为引用。
5. 个人资料转企业知识必须复制经审核后的脱敏版本,不能把个人 item 直接改成企业 scope。
6. 自动化测试必须使用两个用户交叉访问,验证列表、详情、检索、向量和删除均返回不可见。
### 3.4 项目业务记忆权限
1. 个人笔记允许 `project_code` 为空;晨会、巡检、业主服务、画像、线索等项目工作记录必须先选择当前项目。
2. 客户端展示员工有权限的项目名称下拉列表,不展示或要求手输项目编码;选择结果可携带内部项目标识,服务端必须按当前登录员工的有效项目任职重新解析并校验,不能信任客户端字段。
3. 项目授权沿用 `aihr_org_snapshot.project_code` 和现有知识授权口径;同一员工的多项目成员关系按 `tenant_id + project_code + ext_party_id` 保留,客户端不得指定越权项目。
4. 项目业务记忆的列表、详情、修改和召回必须同时过滤 `tenant_id + project_code`,创建人不因“本人记录”获得跨项目访问权。
5. 住户姓名、电话、身份证件和健康信息不作为自由文本检索字段;首批优先保存房屋定位、需求摘要、跟进状态和必要说明。
6. 发送外部模型前先由服务端提取并令牌化可识别信息;模型输出不得覆盖服务端保存的主体定位。
7. 员工修改已确认记录必须携带 `expectedVersion`,成功后新增版本快照,不原地抹除历史。
8. 项目业务记忆不能通过个人资料删除接口删除;作废使用 `VOID` 状态并保留操作人、原因和版本记录。
## 4. 数据模型
初始化 SQL:`backend/script/sql/aihr_personal_knowledge_mysql8.sql`。
### 4.1 `aihr_personal_space`
每个租户内每名员工一条。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint PK | 主键 |
| tenant_id | varchar(20) | 租户 |
| owner_user_id | bigint | 本地用户 ID |
| owner_ext_party_id | varchar(100) null | 外部主体 ID |
| status | varchar(20) | ACTIVE / FROZEN / DELETING |
| quota_bytes | bigint | 默认 524288000(500MB) |
| used_bytes | bigint | 已用空间,事务内维护 |
| item_count | int | 未删除资料数 |
| create_time/update_time | datetime | 审计时间 |
约束:`UNIQUE(tenant_id, owner_user_id)`。
### 4.2 `aihr_personal_item`
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint PK | 资料 ID |
| tenant_id/space_id/owner_user_id | bigint/varchar | 冗余所有权键,便于强制过滤 |
| source_type | varchar(20) | TEXT / FILE / IMAGE / URL |
| capture_channel | varchar(20) | TEXT / VOICE / UPLOAD / SHARE;语音保存 ASR 文本,不把音频文件冒充正文 |
| title | varchar(500) | 标题 |
| original_url | varchar(2000) null | 原网页地址 |
| oss_id | bigint null | 原文件或网页快照 OSS ID |
| mime_type | varchar(100) | MIME |
| size_bytes | bigint | 原始大小 |
| content_hash | varchar(64) | SHA-256 去重 |
| status | varchar(20) | QUEUED / PARSING / READY / FAILED / DELETING / DELETED |
| error_code/error_message | varchar | 可公开的失败信息,不存堆栈 |
| attempt_count | int | 解析尝试次数,默认 0,每次执行前加 1 |
| summary | text | 自动摘要 |
| tags_json | json | 主题标签数组 |
| captured_at | datetime | 内容产生/网页抓取时间 |
| parsed_at | datetime null | 解析完成时间 |
| deleted_at | datetime null | 逻辑删除时间 |
| create_time/update_time | datetime | 审计时间 |
索引:
- `(tenant_id, owner_user_id, status, create_time)`
- `(tenant_id, owner_user_id, captured_at)`
- `(space_id, content_hash)`
### 4.3 `aihr_personal_fragment`
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint PK | 片段 ID |
| tenant_id/space_id/owner_user_id/item_id | bigint/varchar | 所有权与父项 |
| idx | int | 片段序号 |
| content | text | 正文片段 |
| token_count | int | token 数 |
| embedding_json | longtext null | Qdrant 不可用时的本地兜底 |
| embedding_model | varchar(100) null | 模型 |
| embedding_time | datetime null | 向量时间 |
| create_time | datetime | 创建时间 |
约束:`UNIQUE(item_id, idx)`;Fulltext 索引仅覆盖个人表。
### 4.4 `aihr_personal_chat_session` 与 `aihr_personal_chat_message`
Session 保存 `id/tenant_id/owner_user_id/title/default_scope_mode/default_scope_json/create_time/update_time`;`default_scope_mode` 默认 AUTO。
Message 保存:
- `session_id/owner_user_id/role`
- `content`
- `scope_json`
- `citations_json`
- `model_name/prompt_version`
- `input_tokens/output_tokens/latency_ms`
- `create_time`
个人消息只允许本人读取和删除;运营报表仅统计数量、token 和延迟,不读取 content。
### 4.5 `aihr_personal_publish_request`(P1)
个人资料申请进入团队或企业知识库的审核记录:`item_id/applicant_user_id/target_scope/reason/status/reviewer_user_id/review_comment/review_time/published_knowledge_id`。
状态固定为 `PENDING / APPROVED / REJECTED / CANCELLED`。批准后生成新的企业知识附件和片段,保留来源链,不改变个人 item 所有权。
### 4.6 `aihr_personal_audit_log`
紧急审计专用不可变日志:`tenant_id/auditor_user_id/target_owner_user_id/item_id/action/reason/ticket_no/result/create_time`。日志不保存个人正文、附件 URL、问题或答案内容;业务接口不提供更新和删除操作。
### 4.7 `aihr_memory_candidate`
确认卡草稿表,不属于长期记忆,也不进入全文/向量索引。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint PK | 候选 ID |
| tenant_id/owner_user_id/project_code | varchar | 当前身份与候选项目范围;项目键使用现有组织快照的 `project_code`,不是自造数值 ID |
| source_conversation_id/source_request_id | varchar(64) | 来源短会话与本次问答请求;当前「问」链没有持久化消息 ID |
| candidate_hash | varchar(64) | 来源 + 规范化草稿哈希,用于防重复 |
| memory_type | varchar(30) | SERVICE_LEAD / RESIDENT_PROFILE / CASE / PERSONAL_NOTE / FOLLOW_UP / PROJECT_NOTE |
| target_domain | varchar(30) | 新候选为 ASSISTANT_CAPTURE;确认后记录结果映射为 PERSONAL / COMPANY;旧记录兼容 PROJECT_SERVICE |
| status | varchar(20) | NEEDS_INPUT / DRAFT / CONFIRMED / DISMISSED / EXPIRED |
| draft_json | json | 可编辑结构化草稿;不得包含未脱敏模型原始响应 |
| missing_fields_json | json | 仍需追问的字段 |
| confidence | decimal(5,4) | 只决定是否建议展示,不决定自动保存 |
| version | int | 乐观锁版本,从 1 开始 |
| confirm_idempotency_key/confirm_request_hash | varchar | 确认写入的稳定幂等键及请求内容哈希 |
| target_id | bigint null | 确认后生成的个人 item 或业务记忆 ID |
| expires_at/confirmed_at | datetime null | 草稿过期与确认时间 |
| create_time/update_time | datetime | 审计时间 |
约束:`UNIQUE(tenant_id, owner_user_id, source_request_id, candidate_hash)`;DRAFT 默认 24 小时过期,DISMISSED/EXPIRED 的 `draft_json` 在 24 小时内物理清理。
### 4.8 `aihr_assistant_capture`
用户确认后的统一采集事实源。核心字段为 `tenant_id/owner_user_id/project_code/save_scope/suggested_type/building_name/unit_name/room_no/category/summary/detail/occurred_at/follow_up_at/work_date/business_status/source_snapshot_json/source_conversation_id/source_request_id/delivery_status/delivery_attempts/next_delivery_at/external_record_id/last_error/confirm_idempotency_key/confirm_request_hash/version/create_time/update_time`。
- `save_scope=PRIVATE` 时 `delivery_status=NOT_REQUIRED`,查询必须同时带 `tenant_id + owner_user_id`。
- `save_scope=COMPANY` 时首批写 `delivery_status=PENDING`;`DELIVERED` 只能由拿到外部成功回执的投递 Worker 更新。
- `confirm_idempotency_key` 在租户和 owner 范围唯一,确认事务先写采集记录再关闭候选,任一步失败整体回滚。
- `business_status` 固定为 `RECORDED/PENDING/IN_PROGRESS/COMPLETED/VOID`;状态历史保留原状态、目标状态、操作人、说明和时间,状态幂等键不得跨记录或目标状态复用。
- `source_snapshot_json` 只保存最小必要来源快照和受保护 OSS 引用,源文件通过重新鉴权接口交付,不保存公开 URL。
- 表内不保存原始录音、模型原始输出或伪造的住户主体 ID;音色不属于本表和本次实现。
### 4.9 `aihr_service_memory`
项目共享的住户需求和待跟进事实,不放入个人知识表。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint PK | 业务记忆 ID |
| tenant_id/project_code | varchar | 租户与现有项目授权键 |
| subject_type | varchar(20) | RESIDENT / LOCATION |
| resident_external_id | varchar(100) null | 仅权威住户主数据接入后保存;不得自行生成 |
| building_name/unit_name/room_no | varchar | 员工确认的结构化房屋定位 |
| category | varchar(50) | 需求分类,例如养老咨询、维修、投诉、增值服务 |
| title/summary/detail | varchar/text | 标题、最小必要摘要与说明 |
| status | varchar(20) | OPEN / IN_PROGRESS / RESOLVED / VOID |
| occurred_at | datetime | 事件发生或获知时间 |
| follow_up_at | datetime null | 用户单独确认的跟进时间;空值不产生提醒 |
| source_conversation_id/source_request_id | varchar(64) | 可追溯来源 |
| created_by/confirmed_by | bigint | 记录人与确认人 |
| version | int | 当前乐观锁版本,从 1 开始 |
| create_time/update_time | datetime | 审计时间 |
索引至少包含 `(tenant_id, project_code, status, follow_up_at)`、`(tenant_id, project_code, building_name, unit_name, room_no)`;首批关系库检索覆盖 `title/summary/detail`,后续若启用向量检索,payload 强制包含 `tenant_id + project_code + memory_id + status`。
### 4.10 `aihr_service_memory_version`
每次确认修改、状态变更或作废都追加版本:`memory_id/version/snapshot_json/change_type/change_reason/operator_user_id/create_time`。快照只保存业务字段,不复制姓名、电话等无关标识;`UNIQUE(memory_id, version)`。
## 5. Qdrant 与 OSS 设计
### 5.1 Qdrant
- 完整阶段目标:个人资料使用 `aihr_personal_knowledge` collection;项目业务记忆使用独立 `aihr_service_memory` collection,两者不混 collection。
- 确认式统一采集和兼容项目服务记录只使用 MySQL 关系库,不创建新的 Qdrant collection;不得因未做向量化而回退到无权限过滤的企业 collection。
- 向量维度:跟随当前启用的 vector 模型;模型或维度变化使用独立重建任务。
- 个人 payload:`tenant_id`、`owner_user_id`、`space_id`、`item_id`、`fragment_id`、`source_type`、`captured_at`;必建 index 为 `tenant_id`、`owner_user_id`、`item_id`。
- 项目业务记忆后续 payload:`tenant_id`、`project_code`、`memory_id`、`status`、`occurred_at`、`updated_at`;必建 index 为 `tenant_id`、`project_code`、`memory_id`、`status`。
- 个人查询无 owner filter、项目业务查询无 project_code filter 时,检索服务直接拒绝执行并记录安全日志。
- `aihr_memory_candidate` 的任何状态都不写 Qdrant;只有关系库确认事务提交成功后才异步索引目标记录。
### 5.2 OSS
- 路径:`personal/{tenantId}/{userId}/{itemId}/{safeFileName}`。
- bucket 保持私有;下载只能通过鉴权接口返回短时签名 URL。
- 原文件、网页正文快照和生成导出文件使用不同子目录。
- 文件名、Content-Type 和 multipart header 继续执行 CRLF 清洗。
- `sys_oss.ext1` 只保存解析状态和 personal itemId,不保存个人正文或手机号。
## 6. API 契约
统一前缀:`/api/aihr/personal-assistant`。响应沿用 `R<T>`。
### 6.1 空间与资料
| 方法 | 路径 | 请求/说明 |
|---|---|---|
| GET | `/space` | 当前用户空间、配额、已用量、资料数 |
| GET | `/items` | `pageNum/pageSize/status/sourceType/dateFrom/dateTo/keyword` |
| POST | `/items/text` | `{title, content, capturedAt?, tags?}` |
| POST | `/items/file` | multipart `file`, `title?`, `capturedAt?` |
| POST | `/items/url` | `{url, title?, capturedAt?}`,异步抓取 |
| GET | `/items/{id}` | 详情、解析状态、摘要、标签;所有权校验 |
| POST | `/items/{id}/retry` | 仅 FAILED 可重试 |
| DELETE | `/items/{id}` | 返回 cleanupJobId,进入 DELETING |
| GET | `/items/{id}/download-url` | 返回 5 分钟私有签名 URL |
创建响应:
```json
{
"itemId": 1201,
"status": "QUEUED",
"duplicateOf": null
}
```
### 6.2 搜索与问答
`POST /search`
```json
{
"queryText": "7月1日至7月10日我收藏了哪些保洁管理资料",
"scope": ["PERSONAL"],
"dateFrom": "2026-07-01",
"dateTo": "2026-07-10",
"itemIds": [],
"limit": 10
}
```
`POST /ask`
```json
{
"sessionId": null,
"queryText": "结合我的资料和企业制度,整理本周保洁管理改进建议",
"scopeMode": "AUTO",
"scope": [],
"dateFrom": "2026-07-01",
"dateTo": "2026-07-10",
"itemIds": [],
"outputFormat": "ACTION_PLAN"
}
```
响应:
```json
{
"sessionId": 301,
"answer": "结论……\n行动项……\n待确认事项……",
"resolvedScopes": ["PERSONAL", "ENTERPRISE"],
"citations": [
{
"domain": "PERSONAL",
"sourceId": "item:1201:fragment:3",
"title": "保洁班组周记录.xlsx",
"excerpt": "……",
"capturedAt": "2026-07-08T09:30:00"
},
{
"domain": "ENTERPRISE",
"sourceId": "knowledge:1:fragment:88",
"title": "住宅保洁作业标准",
"excerpt": "……",
"capturedAt": null
}
],
"model": "configured-chat-model",
"promptVersion": "personal_assistant_v1"
}
```
若无可用引用,返回明确的“当前资料中没有足够依据”,不得生成无引用的业务结论。
`scopeMode=AUTO` 时服务端只在 PERSONAL / PROJECT_SERVICE / ENTERPRISE 三个内部域路由,并在响应返回 `resolvedScopes`;`scopeMode=MANUAL` 时 `scope` 至少包含一个内部域。`PROJECT_SERVICE` 结果必须在融合前按当前项目权限过滤;引用额外返回 `status/occurredAt/updatedAt`,使用户能区分历史记录与当前状态。`POST /ask` 可在正常答案外返回一个 `memoryCandidate`,但不能因生成答案成功而自动确认候选。
### 6.3 会话
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `/sessions` | 当前用户会话列表 |
| GET | `/sessions/{id}` | 消息与引用 |
| DELETE | `/sessions/{id}` | 删除本人会话与消息 |
### 6.4 分享与导出(P1)
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | `/items/{id}/publish-requests` | 申请进入团队/企业知识库 |
| GET | `/publish-requests` | 本人申请进度 |
| GET | `/admin/publish-requests` | HR/运营按 PENDING/APPROVED/REJECTED 查询审核列表 |
| POST | `/admin/publish-requests/{id}/review` | HR/运营批准或驳回;批准后生成脱敏企业知识副本 |
| POST | `/exports/outline` | 生成可编辑汇报大纲 |
| POST | `/exports/pptx` | 根据已确认大纲和模板异步生成 PPTX |
| GET | `/exports/{id}` | 生成状态与下载地址 |
### 6.5 运营聚合与紧急审计
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `/admin/metrics` | 仅返回用户数、资料数、状态、容量、失败率等聚合信息,不返回标题和正文 |
| POST | `/admin/items/{id}/audit-view` | 需要 `aihr:personal:audit` 权限、非空工单号和原因;先写审计日志,再返回一次性详情 |
| GET | `/admin/audit-logs` | 按审计人、目标用户、工单号和时间查询不可变日志 |
紧急审计接口与员工接口使用不同 Controller;超级管理员也不能绕过权限、工单号和原因校验。
### 6.6 确认式记忆
候选确认沿用 `/api/aihr/personal-assistant`;项目业务记忆使用独立前缀 `/api/aihr/service-memories`。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `/memory-candidates?status=DRAFT` | 恢复当前用户尚未过期的确认卡 |
| POST | `/memory-candidates/{id}/confirm` | 提交编辑后的草稿、`expectedVersion`、`idempotencyKey`;分域写入 |
| POST | `/memory-candidates/{id}/dismiss` | 明确不保存;同源候选本会话不再提示 |
| GET | `/assistant-captures?saveScope=PRIVATE|COMPANY&limit=50` | 查看本人的已确认记录及公司流转状态 |
| POST | `/assistant-captures/{id}/status` | 带 `businessStatus/note/idempotencyKey` 推进本地处理状态 |
| GET | `/assistant-captures/{id}/status-history` | 查看状态审计历史 |
| GET | `/assistant-captures/{id}/source` | 重新鉴权读取确认记录绑定的原始媒体 |
| POST | `/api/aihr/work-results/mine/generate` | 按员工、项目和自然日幂等生成今日成果 |
| GET | `/api/aihr/work-results/project` | 主管按目标项目权限查看团队当日成果 |
| GET | `/api/aihr/service-memories` | 按当前项目、状态、日期、楼栋/单元/房号查询 |
| GET | `/api/aihr/service-memories/{id}` | 项目权限内查看详情、来源和版本 |
| PATCH | `/api/aihr/service-memories/{id}` | 携带 `expectedVersion` 修改必要字段或状态并生成版本 |
确认请求示例:
```json
{
"idempotencyKey": "01J-memory-confirm-301",
"expectedVersion": 1,
"saveScope": "COMPANY",
"draft": {
"projectCode": "YC-RESIDENTIAL-03",
"buildingName": "3栋",
"unitName": "2单元",
"roomNo": "1201",
"category": "服务线索",
"summary": "住户希望了解社区可提供的养老服务",
"occurredAt": "2026-07-19T14:00:00+08:00",
"workDate": "2026-07-19",
"businessStatus": "PENDING",
"followUpAt": null
},
"enableReminder": false
}
```
服务端必须忽略请求中的 `projectCode` 作为授权依据,仅用它与当前登录态可访问项目做一致性校验;个人笔记可省略该字段,项目工作记录不得省略。确认成功返回 `targetDomain=PERSONAL|COMPANY/targetId/version`;同一 `idempotencyKey` 重放必须返回同一结果,不重复创建记录,同一键配不同请求体必须拒绝。
## 7. 网页采集安全
`PersonalUrlFetchService` 必须执行:
1. 仅允许 `http/https`,拒绝用户名密码 URL、`file:`、`ftp:`、`data:`。
2. DNS 解析后拒绝 loopback、private、link-local、multicast、保留地址和云元数据地址。
3. 最多 3 次重定向,每次重定向重新解析和校验目标 IP。
4. 连接超时 5 秒、总超时 15 秒、响应正文上限 10MB。
5. 只接收 HTML、纯文本及明确允许的文档 MIME;下载文件仍走文件校验链。
6. 不携带用户浏览器 Cookie、Authorization、Referer 或企业内部代理凭证。
7. HTML 清洗脚本、样式、iframe、表单和隐藏元素,只保留正文与可追溯链接。
8. 记录最终 URL、HTTP 状态、抓取时间、内容哈希和 robots/版权提示;失败可重试但不绕过限制。
## 8. 解析、模型与提示词
### 8.1 解析
- 支持格式与现有知识库一致:txt/md/PDF/Word/Excel/PPT、常用图片。
- 视频、音频文件首批不作为个人资料上传;会话语音复用现有 `/api/ai/asr`,ASR 文本可进入候选记忆检测。原始录音仍按现有受保护音频规则处理,不自动复制进长期记忆。
- item 状态由 `QUEUED → PARSING → READY/FAILED` 单向推进;重试将状态恢复为 QUEUED、增加 `attempt_count`,并覆盖 `error_code/error_message`。
- 文本块默认 800 字、重叠 120 字;参数由 `PersonalKnowledgeProperties` 管理。
### 8.2 提示词模板
新增模板代码:
- `personal_assistant_answer_v1`
- `personal_assistant_summary_v1`
- `personal_assistant_action_plan_v1`
- `personal_assistant_memory_candidate_v1`
- `personal_assistant_memory_recall_v1`
- `personal_assistant_outline_v1`
- `personal_assistant_ppt_v1`(P1)
系统提示词必须包含:只基于授权片段回答、区分来源域、忽略资料中的指令注入、没有依据时拒答、不得代表用户对外作决定。
候选记忆模板只允许输出受控 JSON Schema,不能输出 SQL、表名、owner、tenant、project 授权结论或工具调用。楼栋、单元、房号、姓名、电话等标识由服务端预处理和恢复;模型只判断语义类型、摘要、缺失字段与是否值得建议保存。
### 8.3 成本闸门
- 复用 `AIHR_AI_RUNTIME_ENABLED`、chat/vector/rerank 开关。
- 解析和向量化按内容哈希去重。
- 摘要按需生成;首屏列表不批量触发 LLM。
- 保存 token、模型和延迟,不保存供应商原始请求日志中的个人正文。
## 9. 删除、配额与生命周期
### 9.1 配额默认值
| 配置 | 默认值 |
|---|---:|
| `aihr.personal.max-file-size-mb` | 20 |
| `aihr.personal.max-url-body-mb` | 10 |
| `aihr.personal.max-space-mb` | 500 |
| `aihr.personal.max-items` | 1000 |
| `aihr.personal.download-url-minutes` | 5 |
### 9.2 删除流程
1. API 将 item 标记为 DELETING,立即从列表和检索隐藏。
2. 清理任务删除 Qdrant points。
3. 删除个人 fragment。
4. 删除或解绑 `sys_oss` 对象。
5. 将 item 标记为 DELETED,仅保留无正文的审计元数据。
6. 清理任务幂等重试,24 小时内完成物理内容清理。
用户账号冻结后禁止访问个人空间;阶段三接入权威离职状态后,默认冻结 30 天,允许用户或经授权管理员导出,期满清理。该天数必须可配置。
### 9.3 候选与业务记忆生命周期
- DRAFT 候选默认 24 小时过期,不进入任何检索索引;NEEDS_INPUT 仅兼容旧候选。
- DISMISSED/EXPIRED 候选的结构化草稿在 24 小时内清理,只保留候选 ID、状态、来源消息 ID 和时间戳用于防重复。
- 个人记忆沿用个人 item 删除链路。
- 项目业务记忆不因创建员工离职而删除;按项目业务保留策略管理,首批只允许 `VOID` 作废并保留版本。
- `follow_up_at` 到期只进入员工端“今日安排”查询;推送通知、短信或自动派单不在首批范围。
- 统一采集 `PRIVATE` 记录只按 owner 保存;`COMPANY/PENDING` 保留到企业流转成功或人工关闭,失败只更新重试状态,不丢记录。
## 10. 前端设计
本节视觉与交互基准见:[工作助手语音优先与确认记忆设计图](prototypes/personal-assistant-work-helper-voice-first-v2.png)。该图对应现有微信式会话的升级目标,不代表另建页面。
### 10.1 页面与入口
`mobile-uni` 新增:
```text
src/pages/user/sop/index.vue 既有微信式会话,升级为工作助手主入口
src/pages/user/assistant/library.vue 个人资料列表
src/pages/user/assistant/item.vue 资料详情与解析状态
src/pages/user/assistant/capture.vue 文字、文件、链接收藏
src/pages/user/assistant/sessions.vue 历史会话
src/pages/user/assistant/memories.vue 待确认、个人记忆与项目跟进记录
src/services/personal-assistant.ts API 客户端
```
入口策略:一级只提供用户任务导向的“工作助手 / 查全网”。“工作助手”复用员工端「问」页现有微信式会话,在个人资料、项目记录和企业知识之间自动路由;回答以引用徽标说明实际使用范围。输入区仅提供次级“资料范围:自动”入口,专业用户需要时才切换为手动筛选。不新增个人助理 Tab 或第五个底部 Tab;“我”页提供“我的资料与记忆”管理入口。
### 10.2 关键交互
- 上传后立即返回列表并显示解析状态,不阻塞页面等待解析。
- 每条答案引用显示域徽标:我的资料、项目记录、企业 SOP;外部网页只在独立“查全网”入口展示。
- 工作助手默认 `scopeMode=AUTO`,自动路由仅限本人和当前项目可访问的内部域;界面展示 `依据:企业 SOP · 项目记录 · 我的资料` 等实际命中来源。
- “资料范围”是次级设置而非一级 Tab;手动模式才允许选择个人资料、项目记录或企业知识。
- “查全网”保持独立入口和接口。内部资料无命中时只显示“是否查全网”,必须由用户点击后才进入外部查询;包含住户或项目内部信息时不得自动带入原问题。
- 每条用户文字或 ASR 转写完成后可触发候选检测;普通问答不得频繁弹卡,同源候选被忽略后本会话不再提示。
- 统一采集确认卡必须展示系统建议类型、对象定位、摘要、保存范围、记录时间和可选跟进时间,并提供“修改 / 暂不保存 / 仅自己保存 / 提交公司处理”。
- 项目、楼栋、单元或房号不足时只显示“可继续补充”,不阻断保存;未接入权威住户主数据时不得把模糊描述保存成确定身份。
- 保存与提醒是两个独立选择;未填写 `followUpAt` 不创建提醒或今日任务。
- 项目业务记忆引用必须展示来源时间、当前状态和最后更新时间;历史状态不能冒充当前事实。
- 删除前明确提示会删除附件、解析正文和搜索索引。
- 资料详情允许修正标题、时间和标签,不允许直接编辑解析正文。
- P1 PPT 生成必须先展示可编辑大纲和模板选择,再提交异步任务。
## 11. 错误码与降级
| 业务码 | 含义 | 前端动作 |
|---|---|---|
| `PERSONAL_SPACE_QUOTA_EXCEEDED` | 空间或条目配额超限 | 显示用量并引导删除 |
| `PERSONAL_ITEM_NOT_FOUND` | 不存在或无权访问 | 统一显示不存在,不泄露归属 |
| `PERSONAL_ITEM_NOT_READY` | 仍在解析 | 展示状态并允许刷新 |
| `PERSONAL_PARSE_FAILED` | 解析失败 | 展示可公开原因和重试 |
| `PERSONAL_URL_BLOCKED` | URL 被安全策略拦截 | 明确不能访问该地址 |
| `PERSONAL_NO_CITATION` | 无足够资料支撑 | 不生成业务结论 |
| `ENTERPRISE_SCOPE_FORBIDDEN` | 无企业知识范围权限 | 保留个人结果,提示企业范围不可用 |
| `PERSONAL_AI_DISABLED` | AI 成本闸门关闭 | 仍允许收藏和关键词检索,暂停摘要/问答 |
| `MEMORY_CANDIDATE_NEEDS_INPUT` | 旧候选对象或必要字段不完整 | 兼容展示为可编辑卡;统一采集的新 DRAFT 不以位置缺失阻断保存 |
| `MEMORY_CANDIDATE_EXPIRED` | 确认草稿已过期 | 基于原消息重新识别,不直接写入 |
| `MEMORY_CONFIRM_CONFLICT` | 版本冲突或幂等键对应不同内容 | 刷新确认卡,禁止覆盖 |
| `SERVICE_MEMORY_PROJECT_FORBIDDEN` | 当前用户无项目访问权 | 统一显示不可访问,不泄露记录存在性 |
| `SERVICE_MEMORY_SUBJECT_AMBIGUOUS` | 住户/房屋定位不足或冲突 | 要求补充房号或选择权威主体 |
企业检索失败时,mixed 查询可返回仍然可用且已授权的个人/项目业务结果并标记降级;任一域权限校验失败时不得用其他域结果掩盖越权错误。
## 12. 测试策略
### 12.1 单元测试
- owner/tenant 条件生成与空 owner 拒绝。
- URL IP 分类、重定向二次校验、正文上限。
- 文件哈希去重与配额计算。
- 引用域序列化和无引用拒答。
- 删除任务幂等性。
- prompt injection 文本不得改变系统指令。
- 规则预筛不会把普通问答误判为候选;明确“记一下”必定进入候选检测。
- 模型候选输出不能覆盖服务端解析的 tenant、project、楼栋、单元和房号。
- DRAFT、CONFIRMED、DISMISSED、EXPIRED 状态转换只允许规定方向;NEEDS_INPUT 仅兼容旧候选。
- 同一确认幂等键只生成一个目标记录;版本冲突不覆盖较新业务记忆。
- 裸房号只在楼栋/单元上下文后识别,年份、时长、金额不能误判为房号。
- 相同会话中重复表达同一显式记录更新原卡;“另外记 / 再记一条 / 新的一条”生成新卡。
### 12.2 集成测试
- MySQL:两个用户创建、列表、详情、搜索、删除互不可见。
- Qdrant:未带 owner filter 的调用被拒绝;用户 A 不返回用户 B point。
- OSS:签名 URL 只能由本人生成;删除后对象不可访问。
- mixed:个人和企业结果分别授权、融合、引用域正确。
- confirmed memory:未确认不写个人 item、业务记忆或向量;确认后按目标域写入并返回可追溯来源。
- project service:两个项目交叉读取、修改和召回均不可见;创建人调岗后不保留越权访问。
- version:每次修改和作废均追加版本,旧版本可审计但不参与当前状态回答。
- PII:外部模型请求只含令牌化定位,姓名、电话和房号原值不出现在供应商请求体。
- 成本闸门关闭:收藏与关键词检索可用,LLM 能力明确降级。
### 12.3 浏览器 E2E
1. 手机号登录并确认岗位。
2. 收藏一段文字、一个 PDF 和一个公开网页。
3. 查看 QUEUED/PARSING/READY 状态变化。
4. 按日期查询资料。
5. 分别执行个人、企业、混合问答。
6. 检查引用徽标和原始来源。
7. 删除资料并确认列表、问答和下载均不可再访问。
8. 切换另一手机号,确认看不到前一用户的资料、标题和会话。
9. 语音说“帮我记一下三栋 3203 需要保洁服务”,检查缺少单元时仍出现可确认卡且只作可选提示。
10. 分别执行“暂不保存 / 仅自己保存 / 提交公司处理”,验证前者不落长期表、私有记录仅本人可见、公司记录显示 PENDING 而非已送达。
11. 确认时不设置跟进日期,验证不会生成今日任务;另建一条带 `followUpAt` 的记录,验证只出现一次。
12. 双击确认或重放请求,验证只创建一条记录;修改后验证版本递增且旧状态不被当作当前答案。
## 13. 非功能指标
| 指标 | 验收线 |
|---|---|
| 跨用户数据泄漏 | 0;自动越权矩阵 100% 通过 |
| 支持样本解析成功率 | ≥95%(排除加密/损坏文件) |
| 关键词/向量检索 P95 | ≤2.5 秒 |
| AI 回答 P95 | ≤8 秒;超时明确提示可重试 |
| 引用可访问率 | 100%,且当前用户有权访问 |
| 删除可见性 | API 成功后立即隐藏 |
| 物理内容清理 | 24 小时内完成 |
| URL 私网/元数据地址拦截 | 100% |
| 未确认候选进入长期存储/检索 | 0 |
| 确认接口重复创建 | 0;幂等测试 100% 通过 |
| 跨项目业务记忆泄漏 | 0;项目越权矩阵 100% 通过 |
| 当前状态回答可追溯 | 100% 返回来源时间、状态和最后更新时间 |
## 14. 里程碑与发布闸门
### M0:安全与数据地基
- 独立表、独立 Qdrant collection、私有 OSS 前缀。
- 两用户越权测试、URL SSRF 测试、删除测试先行。
### M1:资料收藏与解析
- 文字、文件、图片、网页链接收藏。
- 异步解析状态、失败重试、配额和列表。
### M2:个人检索与问答
- 日期/主题/来源检索。
- 个人问答、引用、会话和成本统计。
### M3:确认式长期记忆
- 文字/ASR 候选识别、信息补充、确认卡、忽略和过期。
- 个人记忆与项目业务记忆分域写入、幂等确认、版本和受控召回。
- `followUpAt` 经单独确认进入“今日安排”,不做推送或自动派单。
### M4:企业知识授权融合
- 企业知识权限过滤。
- 个人/项目业务/企业三域分别授权后融合和引用域标记。
### M5:移动端闭环与试点
- 员工端页面、真实浏览器 E2E、20 名试点员工。
- 试点期间不开放分享/企业入库和 PPT 文件生成。
### M6:P1 增强
- 分享/企业入库审核。
- 周报月报、汇报提纲、PPTX 异步生成。
发布硬闸门:跨用户越权测试、SSRF 测试、删除链路、引用权限和真实浏览器闭环任一未通过,不得进入试点。
## 15. 实施文件清单
预计新增:
- `backend/script/sql/aihr_personal_knowledge_mysql8.sql`
- `backend/script/sql/aihr_service_memory_mysql8.sql`
- `backend/script/sql/update/aihr_20260719_service_memory_mysql8.sql`(确认候选、统一采集和兼容项目服务记录的生产增量)
- `backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/personal/**`
- `backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/memory/**`(候选识别、确认编排与项目业务记忆)
- `backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/personal/**`
- `backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/memory/**`
- `mobile-uni/src/pages/user/assistant/*.vue`
- `mobile-uni/src/services/personal-assistant.ts`
- `mobile-uni/tests/personal-assistant.test.mjs`
预计修改:
- `backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java`(仅抽取解析能力,不加入个人业务)
- `backend/script/sql/aihr_knowledge_mysql8.sql`(仅共享解析迁移兼容时调整)
- `mobile-uni/src/pages.json`
- `mobile-uni/src/pages/user/sop/index.vue`
- `mobile-uni/src/types/api.ts`
- `scripts/reset-dev-db.sh`
- `docs/API_INTEGRATION.md`
- `docs/DEV_SETUP.md`
- `docs/DEMO_ACCEPTANCE.md`
## 16. 决策摘要
1. 个人知识和企业知识物理分域,不采用共享表 `scope_type`。
2. 文件解析、模型和成本闸门复用,存储和检索索引不复用。
3. 本地 `user_id` 是阶段二所有权键,`ext_party_id` 只作阶段三迁移锚点。
4. Mixed 检索先分域授权,再融合结果。
5. 个人资料默认私有,分享和企业入库走 P1 审核链。
6. PPT 是 P1,不阻塞阶段二首批。
7. 北森、考勤等外部个人数据属于阶段三。
8. 对话历史不是长期记忆;只有用户确认的候选才能进入统一采集或兼容项目业务记忆。
9. 统一采集由用户选择 PRIVATE / COMPANY;COMPANY 先进入可靠待流转状态,不能用前端成功提示代替外部回执。
10. 模型只生成结构化草稿,主体解析、授权、幂等、版本和数据库写入全部由确定性服务完成。
11. 保存和提醒分别确认;未设置 `followUpAt` 不产生今日任务、推送或自动派单。
12. 当前没有权威住户主数据时不伪造主体 ID;无法唯一定位不阻断记录一般事项,但不得将其解释为确定住户档案。
13. 用户界面不暴露系统的三域架构作为一级选择;一级只保留“工作助手 / 查全网”,内部来源默认自动路由并以引用透明展示。
14. 公网查询永不由 AUTO 触发;必须由用户明确进入“查全网”,且不得自动携带住户或项目内部信息。