feat(personal-assistant): add confirmed project memory

This commit is contained in:
2026-07-19 08:19:24 +08:00
parent 151cc26caf
commit 24da833fa6
31 changed files with 4037 additions and 60 deletions
+20 -16
View File
@@ -70,7 +70,7 @@
| 全文检索 | 使用个人片段表 MySQL Fulltext | 查询必须包含 `tenant_id + owner_user_id` |
| 向量检索 | 新建 `aihr_personal_knowledge` collection | Qdrant filter 必须包含 `tenant_id + owner_user_id` |
| 企业知识检索 | 调用现有企业 RAG 服务 | 继续执行企业知识密级、项目和角色权限 |
| 项目业务记忆 | 独立 `aihr_service_memory` 关系表与同名 Qdrant collection | 查询必须包含 `tenant_id + project_id`,不得写入个人或企业知识表 |
| 项目业务记忆 | 独立 `aihr_service_memory` 关系表;关系库检索为 2026-07-19 最小切片,Qdrant 仅列为后续增强 | 查询必须包含 `tenant_id + project_code`,不得写入个人或企业知识表 |
禁止将个人资料写入:
@@ -87,7 +87,7 @@
→ AUTO: 意图路由只在三个内部授权域中选择;MANUAL: 校验用户指定的内部范围
→ 校验日期、itemIds、知识范围和配额
→ personal: 个人 Fulltext + 个人 Qdrant(强制 owner filter)
→ project_service: 项目业务记忆 Fulltext + 独立 Qdrant(强制 project filter)
→ project_service: 首批用关系库检索并强制 project_code filter;后续再叠加独立 Qdrant
→ enterprise: 企业 Fulltext + 企业 Qdrant(强制企业权限)
→ mixed: 所选域分别检索并授权后融合,不做跨域原始结果直连
→ Rerank
@@ -197,8 +197,8 @@ org.dromara.aihr.knowledge.parse
### 3.4 项目业务记忆权限
1. `project_id` 必须由当前登录员工的有效项目任职解析,客户端不得指定越权项目。
2. 项目业务记忆的列表、详情、修改和召回必须同时过滤 `tenant_id + project_id`,创建人不因“本人记录”获得跨项目访问权。
1. `project_code` 必须由当前登录员工的有效项目任职解析,沿用 `aihr_org_snapshot.project_code` 和现有知识授权口径;客户端不得指定越权项目。
2. 项目业务记忆的列表、详情、修改和召回必须同时过滤 `tenant_id + project_code`,创建人不因“本人记录”获得跨项目访问权。
3. 住户姓名、电话、身份证件和健康信息不作为自由文本检索字段;首批优先保存房屋定位、需求摘要、跟进状态和必要说明。
4. 发送外部模型前先由服务端提取并令牌化可识别信息;模型输出不得覆盖服务端保存的主体定位。
5. 员工修改已确认记录必须携带 `expectedVersion`,成功后新增版本快照,不原地抹除历史。
@@ -305,8 +305,8 @@ Message 保存:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint PK | 候选 ID |
| tenant_id/owner_user_id/project_id | varchar/bigint | 当前身份与候选项目范围 |
| source_session_id/source_message_id | bigint | 来源会话与消息 |
| 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) | PERSONAL_NOTE / WORK_IDEA / RESIDENT_NEED / FOLLOW_UP |
| target_domain | varchar(30) | PERSONAL / PROJECT_SERVICE |
@@ -314,11 +314,13 @@ Message 保存:
| 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_message_id, candidate_hash)`;DRAFT 默认 24 小时过期,DISMISSED/EXPIRED 的 `draft_json` 在 24 小时内物理清理。
约束:`UNIQUE(tenant_id, owner_user_id, source_request_id, candidate_hash)`;DRAFT 默认 24 小时过期,DISMISSED/EXPIRED 的 `draft_json` 在 24 小时内物理清理。
### 4.8 `aihr_service_memory`
@@ -327,7 +329,7 @@ Message 保存:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint PK | 业务记忆 ID |
| tenant_id/project_id | varchar/bigint | 租户与项目数据范围 |
| tenant_id/project_code | varchar | 租户与现有项目授权键 |
| subject_type | varchar(20) | RESIDENT / LOCATION |
| resident_external_id | varchar(100) null | 仅权威住户主数据接入后保存;不得自行生成 |
| building_name/unit_name/room_no | varchar | 员工确认的结构化房屋定位 |
@@ -336,12 +338,12 @@ Message 保存:
| status | varchar(20) | OPEN / IN_PROGRESS / RESOLVED / VOID |
| occurred_at | datetime | 事件发生或获知时间 |
| follow_up_at | datetime null | 用户单独确认的跟进时间;空值不产生提醒 |
| source_session_id/source_message_id | bigint | 可追溯来源 |
| source_conversation_id/source_request_id | varchar(64) | 可追溯来源 |
| created_by/confirmed_by | bigint | 记录人与确认人 |
| version | int | 乐观锁版本,从 1 开始 |
| version | int | 当前乐观锁版本,从 1 开始 |
| create_time/update_time | datetime | 审计时间 |
索引至少包含 `(tenant_id, project_id, status, follow_up_at)`、`(tenant_id, project_id, building_name, unit_name, room_no)`;全文检索只覆盖 `title/summary/detail`,向量 payload 强制包含 `tenant_id + project_id + memory_id + status`。
索引至少包含 `(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.9 `aihr_service_memory_version`
@@ -351,11 +353,12 @@ Message 保存:
### 5.1 Qdrant
- collections:个人资料使用 `aihr_personal_knowledge`;项目业务记忆使用 `aihr_service_memory`,两者不混 collection。
- 完整阶段目标:个人资料使用 `aihr_personal_knowledge` collection;项目业务记忆使用独立 `aihr_service_memory` collection,两者不混 collection。
- 2026-07-19 项目服务记忆最小切片只使用 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_id`、`memory_id`、`status`、`occurred_at`、`updated_at`;必建 index 为 `tenant_id`、`project_id`、`memory_id`、`status`。
- 个人查询无 owner filter、项目业务查询无 project filter 时,检索服务直接拒绝执行并记录安全日志。
- 项目业务记忆后续 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
@@ -508,7 +511,7 @@ Message 保存:
"targetDomain": "PROJECT_SERVICE",
"memoryType": "RESIDENT_NEED",
"subject": {
"projectId": 88,
"projectCode": "YC-RESIDENTIAL-03",
"buildingName": "3栋",
"unitName": "2单元",
"roomNo": "1201"
@@ -520,7 +523,7 @@ Message 保存:
}
```
服务端必须忽略请求中的 `projectId` 作为授权依据,仅用它与当前登录态可访问项目做一致性校验。确认成功返回 `targetDomain/targetId/version`;同一 `idempotencyKey` 重放必须返回同一结果,不重复创建记录。
服务端必须忽略请求中的 `projectCode` 作为授权依据,仅用它与当前登录态可访问项目做一致性校验;客户端可省略该字段。确认成功返回 `targetDomain/targetId/version`;同一 `idempotencyKey` 重放必须返回同一结果,不重复创建记录,同一键配不同请求体必须拒绝。
## 7. 网页采集安全
@@ -759,6 +762,7 @@ src/services/personal-assistant.ts API 客户端
- `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/**`