diff --git a/document/development/AI意图规划器/CONCEPT.md b/document/development/AI意图规划器/CONCEPT.md deleted file mode 100644 index 6c11a16..0000000 --- a/document/development/AI意图规划器/CONCEPT.md +++ /dev/null @@ -1,146 +0,0 @@ -# AI 意图规划器 - -## 功能一句话 - -把用户一句自然语言先交给大模型识别成“动作和步骤”的结构化计划,再由前端/后端确定性执行器逐步校验和执行;规则只作为模型不可用或结构非法时的兜底。 - -## 背景 - -用户真实表达往往不是一个简单关键词,而是一个目标: - -```text -去上海出差,辅助国网仿生产服务器部署,交通火车,直接提交 -``` - -这句话包含至少四层语义: - -- 业务对象:差旅费用申请。 -- 已给字段:地点、事由、交通方式。 -- 用户动作:直接提交,不只是生成草稿。 -- 执行步骤:生成申请核对表、校验必填字段、查重、提交审批。 - -如果继续用前端规则直接判断,会越来越像关键词路由;正确方向是让大模型先拆成结构化计划,系统只执行经过白名单校验的步骤。 - -## 目标 - -- 大模型作为复杂意图的主识别器,输出结构化 `intent plan`。 -- `intent plan` 明确描述用户要执行的动作、业务字段、缺失字段和步骤列表。 -- 执行器只认计划中的白名单步骤,不直接相信模型文本。 -- 字段齐全且用户明确“直接提交”时,系统自动走完整链路。 -- 字段缺失、风险阻断、重复申请或低置信度时,系统停在核对表或风险提示。 -- 本地规则只作为 `rule_fallback`,不得伪装成模型判断。 - -## 非目标 - -- 不让大模型直接写数据库、提交审批或绑定附件。 -- 不引入 LangChain 高层 Agent 来替代现有业务服务。 -- 不让 LangGraph 直接接管模型供应商密钥、数据库写入或审批副作用。 -- 不绕过已有申请预览、规则测算、重复申请核查和提交接口。 -- 不把所有财务场景一次性改完;第一阶段先覆盖个人工作台 AI 模式里的差旅申请链路。 - -## 结构化计划契约 - -前端执行器消费统一结构: - -```json -{ - "source": "llm_function_call", - "intent": "create_travel_application", - "requestedAction": "submit", - "confidence": 0.91, - "sourceText": "去上海出差,辅助国网仿生产服务器部署,交通火车,直接提交", - "slots": { - "location": "上海", - "reason": "辅助国网仿生产服务器部署", - "transportMode": "火车" - }, - "missingFields": [], - "steps": [ - "build_application_preview", - "validate_required_fields", - "run_duplicate_precheck", - "submit_application" - ] -} -``` - -## 步骤白名单 - -- `build_application_preview`:生成申请核对表,复用现有申请预览能力。 -- `validate_required_fields`:用确定性代码校验必填字段和字段格式。 -- `run_duplicate_precheck`:提交前查询同日期或重叠申请单。 -- `submit_application`:调用现有申请提交动作;只有用户明确要求提交且前置校验通过才执行。 -- `save_application_draft`:调用现有申请草稿保存能力。 -- `create_reimbursement_draft`:调用现有报销草稿创建能力。 -- `associate_attachments`:调用现有附件关联 runner;缺少 `receipt_ids` 或匹配不唯一时阻断,不能假成功。 -- `link_existing_application`:调用现有报销草稿创建链路并写入申请关联 flag;申请单不存在、未审批或已被报销时阻断。 - -## 数据流 - -```text -用户输入 - ↓ -steward LLM function calling - ↓ -模型计划归一化与白名单校验 - ↓ -可执行 intent plan - ↓ -申请/报销/附件等确定性执行器 - ↓ -核对表、风险提示、草稿或提交结果 -``` - -当模型不可用、超时或返回不可执行结构时: - -```text -模型失败 - ↓ -本地 rule_fallback 生成保守计划 - ↓ -同一个执行器继续处理 -``` - -## 安全边界 - -- 模型只负责“理解”和“拆步骤”,不拥有副作用权限。 -- 执行器必须校验 `intent` 和 `steps` 是否在白名单内;未知 action 必须阻断,不能调用业务服务。 -- 提交前必须走 `readyToSubmit` 和重复申请 precheck。 -- 提交类副作用必须带用户确认和 precheck 通过证据。 -- 地点、日期、事由等字段仍由现有申请预览和规则校验模块判断。 -- 模型置信度低、流程冲突或必填字段缺失时,不自动提交。 - -## 第一阶段落地 - -- 新增前端 planner model,把后端 `StewardPlanResponse` 映射成前端 `intent plan`。 -- 个人工作台 AI 模式在命中差旅申请候选时,优先调用现有 `/steward/plans` 获取模型计划。 -- 模型计划可执行时,按 `steps` 生成申请核对表并在条件满足时自动提交。 -- 模型不可用或计划不可执行时,使用本地 `rule_fallback` 保持体验不倒退。 -- 保留既有普通小财管家路径,用来处理无法直接执行或更复杂的多任务场景。 - -## LangGraph 迁移方向 - -后端小财管家的规划入口、槽位决策入口和运行时动作决策入口已经开始迁入 LangGraph。 -后续不再继续把感知、规划、补字段、运行时动作判断堆进自研 `if/else` 编排,而是按 node 拆分: - -- `model_intent_node`:模型 function calling 规划。 -- `slot_tool_decision_node`:字段缺口与追问判断,失败时进入规则兜底。 -- `runtime_memory_context_node`:合并前端运行时状态和持久化 `steward_state`。 -- `runtime_tool_decision_node`:用户补充、确认、取消、继续执行等运行时判断。 -- `runtime_action_decision_node`:已选流程确认等不需要模型的确定性行动路由。 -- `action_plan_node`:生成白名单 `StewardActionStep`,当前已覆盖申请预览、保存草稿、直接提交和报销草稿。 -- `human_review_node`:保存草稿、提交审批、关联申请单前的确认点。 -- `action_execute_node`:调用现有确定性业务服务;当前已由 `/steward/actions/execute`、`StewardGraphActionRuntime` 和 `StewardActionExecutor` 提供 checkpoint、pending interrupt 和幂等重放。 -- `persist_state_node`:合并 conversation state 和 steward state。 - -当前 `plans` 已返回服务端 `action_steps`,`slot-decisions` / `runtime-decisions` 已默认走 `StewardGraphRuntime`。 -如果 LangGraph 图节点异常,服务端会退回原有 Agent 和规则兜底,避免框架层故障影响用户会话。 - -详细迁移计划见 `LANGGRAPH_RUNTIME_MIGRATION.md`。 - -## 测试策略 - -- planner model 单元测试:模型计划归一化、rule fallback、政策咨询排除。 -- 前端静态接线测试:主流程必须先请求 steward plan,再 fallback。 -- 申请预览回归测试:`直接提交` 不得污染事由;缺日期不得伪造字段。 -- 构建验证:`npm --prefix web run build`。 diff --git a/document/development/AI意图规划器/LANGGRAPH_RUNTIME_MIGRATION.md b/document/development/AI意图规划器/LANGGRAPH_RUNTIME_MIGRATION.md deleted file mode 100644 index 4837f8b..0000000 --- a/document/development/AI意图规划器/LANGGRAPH_RUNTIME_MIGRATION.md +++ /dev/null @@ -1,420 +0,0 @@ -# 小财管家 LangGraph Runtime 迁移计划 - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** 把小财管家的感知、规划、记忆、确认和行动逐步迁到 LangGraph runtime,减少自研流程编排里的隐藏状态和分支 bug。 - -**Architecture:** 保留现有 FastAPI API、Pydantic schema、`RuntimeChatService` 模型供应商抽象和业务服务;LangGraph 只接管 agent 编排。副作用动作必须通过白名单 action node 调用现有业务服务,保存草稿、提交和关联单据都不能由模型文本直接触发。 - -**Tech Stack:** Python 3.11、FastAPI、Pydantic、LangGraph 1.x、SQLAlchemy、现有 `AgentConversationService` / `StewardFlowStateService`。 - ---- - -## 当前状态 - -已经完成第一阶段接入: - -- `server/src/app/services/steward_graph_planner.py` - - 已新增 `StewardGraphPlannerService`。 - - 已用 LangGraph `StateGraph` 编排 `prepare_context -> detect_model_intent -> done/off_topic/rule_fallback`。 -- `server/src/app/services/steward_graph_runtime.py` - - 已新增 `StewardGraphRuntime`。 - - 槽位决策已编排为 `slot_prepare_context -> slot_tool_decision -> done/rule_fallback`。 - - 运行时决策已编排为 `runtime_memory_context -> runtime_action_decision/runtime_tool_decision -> done/rule_fallback`。 - - 图内失败会降级到原有规则兜底;端点层图运行异常会回退旧 Agent。 -- `server/src/app/services/steward_action_contracts.py` - - 已新增 `StewardActionPlanBuilder`。 - - 已把申请、报销、保存草稿、直接提交规划成 `StewardActionStep` 白名单动作。 - - `StewardGraphPlannerService` 已增加 `attach_action_steps` 节点,计划返回前统一补全动作列表。 -- `server/src/app/services/steward_action_executor.py` - - 已新增 `StewardActionExecutor`。 - - 已接入 `/steward/actions/execute`,支持未知动作拒绝、缺字段阻断、提交确认门禁、重复申请 precheck、申请/报销草稿真实执行、关联申请单和附件关联。 - - 申请动作复用 `UserAgentService` 的申请保存/提交能力,报销草稿复用 `ExpenseClaimService.save_or_submit_from_ontology()`。 -- `server/src/app/services/steward_graph_action_runtime.py` - - 已新增 `StewardGraphActionRuntime`。 - - 已用 LangGraph `StateGraph` 编排 `action_checkpoint_load -> action_execute_node -> action_checkpoint_persist`。 - - 已通过 `conversation_id + client_trace_id` 在 `AgentConversation.state_json` 中记录 checkpoint、pending interrupt 和幂等重放结果。 -- `web/src/services/steward.js` / `web/src/views/scripts/stewardPlanModel.js` - - 前端已新增 `executeStewardAction()` 服务方法。 - - steward suggested action 已携带服务端可执行 action step,旧申请预览流仍保留兜底。 -- `web/src/composables/workbenchAiMode/useWorkbenchAiActionRouter.js` - - AI 工作台点击 `steward_execute_action` 时会调用 `/steward/actions/execute`。 - - 直接提交会先执行 `run_duplicate_precheck`,precheck 通过后再提交申请。 -- `server/src/app/api/v1/endpoints/steward.py` - - `/steward/plans` 和 `/steward/plans/stream` 默认使用 `StewardGraphPlannerService`。 - - `/steward/slot-decisions` 和 `/steward/runtime-decisions` 默认使用 `StewardGraphRuntime`。 - - `STEWARD_AGENT_RUNTIME=legacy` 可回退旧 `StewardPlannerService`。 -- `server/pyproject.toml` / `server/uv.lock` - - 已加入 `langgraph>=1.2.0,<2.0.0`。 -- `server/tests/test_steward_graph_planner.py` - - 已覆盖默认 LangGraph、显式 LangGraph、legacy 回退、模型成功计划和模型失败后规则兜底。 -- `server/tests/test_steward_graph_runtime.py` - - 已覆盖槽位工具节点、图内规则兜底、运行时记忆合并、确定性行动选择和端点级 legacy 兜底。 -- `server/tests/test_application_fact_resolver.py` - - 已覆盖 `交通火车` 不污染申请事由,以及 `高铁往返` 这类业务描述仍保留。 - -当前已完成规划入口、slot decision、runtime decision、基础 action contract、第一版 action executor、前端点击执行闭环,以及 action runtime 的 checkpoint / interrupt / 幂等重放。 -真实外部模型连通性仍需要用当前 MiniMax / backup 配置再回放确认。 - -## 官方能力边界 - -LangGraph 官方文档强调它是低层 agent orchestration runtime,重点能力是 durable execution、streaming、human-in-the-loop 和 persistence。 - -本项目只采用这些底层编排能力: - -- Graph API:用 state、node、edge 表达流程,node 可以是 LLM 调用,也可以是普通业务代码。 -- Persistence:用 checkpointer 保存 thread scoped state,用 store 保存跨线程长期信息。 -- Interrupt:在需要用户确认时暂停 graph,等待外部输入后恢复。 - -参考: - -- -- -- -- - -## 总体目标架构 - -```text -用户输入 / 前端上下文 / 附件 - ↓ -StewardGraphRuntime - ├── prepare_context_node - ├── model_intent_node - ├── slot_decision_node - ├── flow_guard_node - ├── action_plan_node - ├── human_review_node - ├── action_execute_node - ├── persist_state_node - └── response_adapter_node - ↓ -现有前端协议:StewardPlanResponse / StewardRuntimeDecisionResponse / StewardSlotDecisionResponse -``` - -关键原则: - -- API 响应协议稳定,前端不因为 runtime 替换被迫大改。 -- 模型只负责理解、拆步骤、给候选 action,不直接写库。 -- 所有副作用节点必须调用现有业务服务,并保留确认和审计。 -- `RuntimeChatService` 继续是唯一模型调用入口,LangGraph 不直接管理供应商密钥。 -- `StewardFlowStateService` 和 `AgentConversationService` 是 checkpoint 落库的第一候选,不另起一套状态源。 - -## Runtime State 草案 - -第一版 graph state 用 `TypedDict`,后续需要持久化时再评估 Pydantic schema。 - -```python -class StewardGraphState(TypedDict, total=False): - request: StewardPlanRequest - conversation_id: str - thread_id: str - message: str - base_date: date - steward_state: dict[str, Any] - model_call_traces: list[dict[str, Any]] - intent_result: StewardIntentAgentResult | None - slot_decision: StewardSlotDecisionResponse | None - runtime_decision: StewardRuntimeDecisionResponse | None - action_plan: list[StewardActionStep] - pending_interrupt: dict[str, Any] - action_result: dict[str, Any] - response: StewardPlanResponse | StewardRuntimeDecisionResponse | StewardSlotDecisionResponse - fallback_reason: str -``` - -`thread_id` 推荐使用现有 `conversation_id`,这样 LangGraph checkpoint、业务会话和前端会话能对齐。 - -## 节点边界 - -### 感知节点 - -- `prepare_context_node` - - 输入:`StewardPlanRequest` 或 runtime decision request。 - - 输出:清洗后的消息、base date、当前 conversation state。 - - 禁止:模型调用、数据库写入。 - -- `model_intent_node` - - 调用:`StewardIntentAgent.detect()`。 - - 约束:保留 `timeout_seconds=10`、`max_attempts=3`、`use_failure_cooldown=False`。 - - 失败:只写入 `fallback_reason` 和 `model_call_traces`,不吞掉错误上下文。 - -### 决策节点 - -- `slot_decision_node` - - 迁移对象:`StewardSlotDecisionAgent.decide()`。 - - 目标:让字段缺口判断进入同一个 graph state,不再由前端和后端多个入口各自推断。 - -- `runtime_decision_node` - - 迁移对象:`StewardRuntimeDecisionAgent.decide()`。 - - 目标:用户补字段、确认流程、取消当前动作、继续下一任务都走 graph routing。 - -- `flow_guard_node` - - 负责申请/报销歧义、重复单据、时间重叠、低置信度、off-topic。 - - 低置信度或强冲突必须进入确认或阻断,不允许继续 action 执行。 - -### 行动节点 - -- `action_plan_node` - - 输出白名单步骤,例如 `build_application_preview`、`save_application_draft`、`submit_application`。 - - 禁止输出自由文本 action。 - -- `human_review_node` - - 对保存草稿、提交审批、关联申请单等副作用动作生成 interrupt payload。 - - 第一阶段可继续返回前端确认动作;第二阶段再接 LangGraph `interrupt()`。 - -- `action_execute_node` - - 只能调用现有业务服务。 - - 必须幂等,或在执行前检查动作是否已完成。 - - 提交类动作必须检查 `confirmation_required` 和用户确认来源。 - -- `persist_state_node` - - 合并 `StewardFlowStateService.merge_plan()` / `merge_state()`。 - - 后续接入 LangGraph checkpointer 后,这里负责业务状态与 checkpoint 的一致性。 - -### 响应节点 - -- `response_adapter_node` - - 输出现有 Pydantic response。 - - 必须保留 `model_call_traces`、`planning_source`、`steward_state`。 - -## 分阶段计划 - -### Phase 0:规划入口接入 LangGraph - -状态:已完成。 - -完成标准: - -- [x] 默认 runtime 为 `langgraph`。 -- [x] `STEWARD_AGENT_RUNTIME=legacy` 可回退。 -- [x] `/steward/plans` 真实接口仍返回兼容的 `StewardPlanResponse`。 -- [x] 模型失败后仍按 10s * 3 次再规则降级。 - -### Phase 1:修通模型成功路径 - -目标:让真实保存草稿话术至少能走一次 `llm_function_call` 成功路径。 - -文件: - -- 修改:`server/src/app/services/runtime_chat.py` -- 修改:`server/src/app/services/settings.py` -- 修改:`server/tests/test_runtime_chat_service.py` -- 测试:`server/tests/test_steward_intent_agent.py` - -步骤: - -- [x] 写失败测试:模拟 main provider 超时但 backup provider 可用时,`complete_with_tool_call()` 返回 backup 的 tool call。 -- [x] 确认 backup function calling 会在 main 失败后返回 tool call,不等待 main 重试结束。 -- [ ] 写失败测试:MiniMax 返回非 OpenAI tool call 兼容格式时,服务端能记录清晰 trace 并降级。 -- [x] 容器内运行: - -```bash -docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-local-linux \ - timeout 60s /tmp/x-financial-server-venv/bin/pytest -q \ - server/tests/test_runtime_chat_service.py \ - server/tests/test_steward_intent_agent.py -``` - -验收: - -- [ ] 真实 `/api/v1/steward/plans` 对保存草稿原句返回 `planning_source=llm_function_call`。 -- [x] `model_call_traces` 能区分 main 失败、backup 成功或全失败。 - -### Phase 2:slot/runtime decision 迁入 graph - -目标:把字段缺口和运行时动作判断从独立 agent 类迁进同一个 graph runtime。 - -状态:已完成。 - -文件: - -- 已创建:`server/src/app/services/steward_graph_runtime.py` -- 已修改:`server/src/app/api/v1/endpoints/steward.py` -- 已测试:`server/tests/test_steward_graph_runtime.py` -- 保留测试:`server/tests/test_steward_slot_decision_agent.py` -- 保留测试:`server/tests/test_steward_runtime_decision_agent.py` - -步骤: - -- [x] 写失败测试:`StewardGraphRuntime.decide_slot()` 调用 slot node 后返回与现有 `StewardSlotDecisionAgent.decide()` 等价的 response。 -- [x] 写失败测试:`StewardGraphRuntime.decide_runtime()` 在用户补充字段时合并 `steward_state`。 -- [x] 把 `StewardSlotDecisionAgent` 包成 `slot_tool_decision` 节点。 -- [x] 把 `StewardRuntimeDecisionAgent` 包成 `runtime_tool_decision` 节点。 -- [x] 把已选流程确认和当前运行时记忆归一化拆成 `runtime_memory_context` / `runtime_action_decision` 节点。 -- [x] endpoint 在 `STEWARD_AGENT_RUNTIME=langgraph` 时使用 graph runtime。 -- [x] endpoint 在 graph runtime 异常时回退旧 Agent,避免框架层失效影响会话。 - -验收: - -- [x] `slot-decisions`、`runtime-decisions` 和 `plans` 三个入口都由 LangGraph runtime 路由。 -- [x] legacy 回退仍可用。 -- [x] 图内工具节点失败时仍有可执行规则兜底。 - -### Phase 3:action node 标准化 - -目标:把保存草稿、提交审批、关联申请单这些副作用动作变成显式 action node。 - -状态:基础 action contract、第一版 action executor、前端点击执行闭环、LangGraph action node、checkpoint、pending interrupt 和幂等重放已完成;后续只剩 durable checkpointer 抽象与更完整 trace UI。 - -文件: - -- 已创建:`server/src/app/services/steward_action_executor.py` -- 已创建:`server/src/app/services/steward_action_contracts.py` -- 已创建:`server/src/app/services/steward_graph_action_runtime.py` -- 已修改:`server/src/app/api/v1/endpoints/steward.py` -- 已修改:`server/src/app/services/steward_graph_planner.py` -- 已修改:`server/src/app/schemas/steward.py` -- 已修改:`web/src/services/steward.js` -- 已修改:`web/src/views/scripts/stewardPlanModel.js` -- 已修改:`web/src/composables/workbenchAiMode/useWorkbenchAiActionRouter.js` -- 已修改:`web/src/composables/workbenchAiMode/usePersonalWorkbenchAiMode.js` -- 已测试:`server/tests/test_steward_action_executor.py` -- 已测试:`server/tests/test_steward_graph_planner.py` -- 已测试:`server/tests/test_steward_planner.py` -- 已测试:`web/tests/workbench-ai-intent-planner-model.test.mjs` -- 已测试:`web/tests/steward-actions-service.test.mjs` -- 已测试:`web/tests/steward-plan-message-copy.test.mjs` -- 已测试:`web/tests/workbench-ai-action-router.test.mjs` - -白名单 action: - -- `build_application_preview` -- `save_application_draft` -- `submit_application` -- `link_existing_application` -- `create_reimbursement_draft` -- `associate_attachments` - -步骤: - -- [x] 写失败测试:申请直接提交计划必须输出 `fill_application_fields -> build_application_preview -> validate_required_fields -> run_duplicate_precheck -> submit_application`。 -- [x] 写失败测试:保存草稿计划必须输出 `save_application_draft`,并在字段缺失时阻断后续副作用。 -- [x] 写失败测试:报销计划必须输出 `fill_reimbursement_fields -> build_reimbursement_preview -> validate_required_fields -> create_reimbursement_draft`。 -- [x] 在 `StewardTask` 和 `StewardPlanResponse` 中增加 `action_steps`。 -- [x] 实现 `StewardActionPlanBuilder`,由服务端确定性生成白名单 action step。 -- [x] 在 LangGraph planner 中新增 `attach_action_steps` 节点。 -- [x] 前端 planner model 优先消费服务端 `task.action_steps`,旧响应才回退本地推导。 -- [x] 写失败测试:未知 action step 被拒绝,不调用任何业务服务。 -- [x] 写失败测试:`submit_application` 缺少确认来源时返回 `needs_confirmation`。 -- [x] 写失败测试:`submit_application` 必须看到 precheck 通过后才允许真实提交。 -- [x] 实现 action registry,只允许白名单 action。 -- [x] 接入现有申请保存草稿、申请提交和报销草稿服务。 -- [x] 前端新增 `executeStewardAction()` 并让 suggested action 携带服务端 action step。 -- [x] AI 工作台点击 suggested action 时调用 `StewardActionExecutor`;直接提交先串行执行 precheck,再把结果交给 submit。 -- [x] 接入 `link_existing_application` 和附件关联的真实执行。 -- [x] 把 action executor 包成 LangGraph `action_execute_node`,并接入 checkpoint / interrupt 恢复。 - -验收: - -- [x] 模型不能通过自由文本触发数据库写入,服务端只输出白名单 `StewardActionStep`。 -- [x] 申请提交动作没有确认时返回 `needs_confirmation`,不会写库。 -- [x] 申请提交动作没有 precheck 通过证据时被阻断。 -- [x] 保存申请草稿和创建报销草稿通过现有业务服务真实入库,测试覆盖。 -- [x] 前端点击可执行 steward action 会真实调用 executor,并把结果回写到会话消息。 -- [x] 基础副作用动作有 `client_trace_id` 幂等键、conversation checkpoint 和 pending interrupt 记录。 - -### Phase 4:checkpoint 与 human-in-the-loop - -目标:让 LangGraph 负责暂停、恢复和跨轮状态,而不是只靠前端消息状态。 - -文件: - -- 已创建:`server/src/app/services/steward_graph_action_runtime.py` -- 已复用:`server/src/app/models/agent_conversation.py` -- 已测试:`server/tests/test_steward_action_executor.py` - -步骤: - -- [x] 设计 `conversation_id -> thread_id` 映射,当前直接以 `conversation_id` 作为 graph action thread。 -- [x] 实现基于数据库的 checkpoint,先复用 `AgentConversation.state_json`。 -- [x] 在提交审批缺确认时生成 pending interrupt payload。 -- [x] 用户确认后用同一 `client_trace_id` / `conversation_id` 继续执行;终态请求会幂等重放。 - -验收: - -- [x] 刷新页面后,后端仍保留当前等待确认的 action checkpoint。 -- [x] 同一个 action 不会因为重复点击或重试重复写库。 -- [ ] 前端完整恢复 UI 仍需继续把 checkpoint 状态展示为可恢复按钮。 - -### Phase 5:可观测性与 legacy 收敛 - -目标:让 agent 规划过程可解释、可测试、可回放,并逐步删除重复手写编排。 - -文件: - -- 修改:`server/src/app/services/agent_traces.py` -- 修改:`server/src/app/models/agent_run.py` -- 修改:`document/development/Agent链路追踪中心/CONCEPT.md` -- 测试:`server/tests/test_agent_traces.py` - -步骤: - -- [ ] 每个 graph node 写入 trace event:输入摘要、输出摘要、耗时、错误。 -- [ ] 前端显示“模型规划中 / 字段判断中 / 等待确认 / 执行动作”阶段。 -- [ ] 对 legacy planner 增加废弃标记和删除条件。 -- [ ] 删除重复的手写分支前,先保留至少一轮灰度开关。 - -验收: - -- 任何一次用户请求都能从 trace 看出走过哪些 node。 -- 删除 legacy 前,LangGraph 路径覆盖当前核心申请/报销链路测试。 - -## 回退策略 - -- 环境变量: - -```bash -STEWARD_AGENT_RUNTIME=legacy -``` - -- 回退后: - - `/steward/plans` 使用旧 `StewardPlannerService`。 - - 新 action node 和 checkpoint 不应影响 legacy。 - - 回退原因必须写入当天工作日志。 - -## 验证矩阵 - -每个阶段至少跑: - -```bash -docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-local-linux \ - timeout 60s /tmp/x-financial-server-venv/bin/pytest -q \ - server/tests/test_steward_graph_planner.py \ - server/tests/test_steward_planner.py \ - server/tests/test_steward_intent_agent.py \ - server/tests/test_runtime_chat_service.py -``` - -涉及前端执行器时补跑: - -```bash -node --test web/tests/workbench-ai-intent-planner-model.test.mjs \ - web/tests/workbench-ai-application-gate-model.test.mjs \ - web/tests/steward-actions-service.test.mjs \ - web/tests/steward-plan-message-copy.test.mjs -npm --prefix web run build -``` - -每次完成后执行: - -```bash -git diff --check -docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-local-linux \ - /tmp/x-financial-server-venv/bin/python -m pip check -``` - -## 不做的事 - -- 不引入 LangChain 高层 Agent 来替代现有业务服务。 -- 不让模型直接调用数据库写入、提交审批或绑定附件。 -- 不为了接框架重写申请、报销、OCR、票据夹、审批规则。 -- 不在没有测试覆盖时删除 legacy planner。 - -## 风险与处理 - -- 模型连通性不稳定:先修 provider 和 backup,再扩大 graph 节点。 -- checkpoint 与业务 state 双写不一致:先复用 `AgentConversation.state_json`,不要新增第二个业务状态源。 -- action node 副作用重复执行:每个 action 必须有幂等键和执行前状态检查。 -- LangGraph 传递依赖影响 WebSocket:当前 `pip check` 通过;后续若流式接口异常,先核对 `websockets` 版本。 -- 节点内继续堆大块逻辑:每个 node 只做一类事,超过 300 行先拆文件。 diff --git a/document/development/AI意图规划器/TODO.md b/document/development/AI意图规划器/TODO.md deleted file mode 100644 index b5ebbd4..0000000 --- a/document/development/AI意图规划器/TODO.md +++ /dev/null @@ -1,32 +0,0 @@ -# AI 意图规划器 TODO - -## 第一阶段 - -- [x] 落地 AI 意图规划器概念文档,明确大模型负责拆计划、业务代码负责执行。 -- [x] 新增前端 planner model,统一模型计划和本地 fallback 的输出结构。 -- [x] 个人工作台 AI 模式先请求 steward 模型计划,再使用本地 fallback。 -- [x] 差旅申请直提链路改为消费 `intent plan.steps`,不再直接消费正则识别结果。 -- [x] 补齐 planner model 与主流程接线回归测试。 -- [x] 跑前端构建和定向测试。 -- [x] 后端 `/steward/plans` 增加 `requested_action` 输出,减少前端从原句推断“提交/保存”的比例。 -- [x] 引入 LangGraph,并默认用 `StewardGraphPlannerService` 接管 `/steward/plans` 规划编排。 -- [x] 落地 LangGraph runtime 迁移计划文档:`LANGGRAPH_RUNTIME_MIGRATION.md`。 -- [x] 新增 `StewardGraphRuntime`,接管 `slot-decisions` 和 `runtime-decisions` 的 LangGraph 路由。 -- [x] 为 LangGraph runtime 增加图内规则兜底和端点级 legacy Agent 兜底。 -- [x] 为 `/steward/plans` 增加服务端白名单 `action_steps`,覆盖申请、报销、保存草稿和直接提交的基础动作规划。 -- [x] 前端 planner model 优先消费服务端 `task.action_steps`,旧响应才回退本地步骤推导。 -- [x] 新增 `/steward/actions/execute` 和 `StewardActionExecutor`,把未知 action 拒绝、提交确认门禁、precheck 阻断、申请草稿保存、申请提交和报销草稿创建接到现有业务服务。 -- [x] 前端新增 `executeStewardAction()` 服务方法,并让 steward suggested action 携带服务端可执行 action step。 -- [x] AI 工作台点击可执行 steward action 时调用 `/steward/actions/execute`;申请直接提交会先跑 `run_duplicate_precheck`,通过后再提交。 -- [x] `complete_with_tool_call()` 增加 main 失败后 backup tool-call 成功路径测试,保证模型成功路径能从 backup 返回 `llm_function_call`。 -- [x] 新增 `StewardGraphActionRuntime`,把 action executor 包成 LangGraph `action_execute_node`,并用 `conversation_id + client_trace_id` 在 `AgentConversation.state_json` 中持久化 checkpoint。 -- [x] 对提交确认生成 pending interrupt;重复 client trace 直接重放 checkpoint,避免重复保存草稿或重复提交。 -- [x] `link_existing_application` 接入现有报销草稿创建链路并写入申请关联 flag。 -- [x] `associate_attachments` 接入现有附件关联 runner,按 receipt_ids 归集到可匹配报销草稿。 - -## 后续阶段 - -- [ ] 用真实 MiniMax / backup 配置再回放 `/steward/plans`,确认真实环境返回 `planning_source=llm_function_call`,不是规则兜底。 -- [ ] 将当前 `AgentConversation.state_json` checkpoint 抽象为可替换的 durable checkpointer,并补恢复/清理策略。 -- [ ] 为每个 LangGraph node 写入可追溯 trace,展示模型调用、规则降级、等待确认和动作执行结果。 -- [ ] 在 LangGraph 路径覆盖申请/报销核心链路后,再逐步删除旧 `StewardPlannerService` 的重复编排。 diff --git a/document/development/Agent链路追踪中心/CONCEPT.md b/document/development/Agent链路追踪中心/CONCEPT.md deleted file mode 100644 index b482240..0000000 --- a/document/development/Agent链路追踪中心/CONCEPT.md +++ /dev/null @@ -1,132 +0,0 @@ -# Agent链路追踪中心 概念文档 - -## 功能一句话 - -为 Orchestrator 全链路运行提供统一 trace 采集、查询和前端回放入口,让管理员能按 `run_id` 或 `conversation_id` 还原一次 Agent 对话从意图识别到最终回复的全过程。 - -## 背景与问题 - -- 当前现状:系统已有 `agent_runs`、`agent_tool_calls`、`semantic_parse_logs` 和对话消息,但它们分散在运行记录、工具调用、语义解析与系统日志中。 -- 用户痛点:线上 Agent 回答异常时,只能看局部日志或 Hermes 工作记录,难以判断问题出在意图路由、知识检索、规则引擎、数字员工任务还是回复生成。 -- 业务影响:Agent 链路越长,排障成本越高;没有可重放视图会影响交付、演示和运维可信度。 - -## 目标与非目标 - -### 目标 - -- [G1] 后端沉淀统一的 Agent trace 事件模型,按运行顺序记录关键阶段输入、输出、状态、耗时和错误。 -- [G2] 提供 trace 查询接口,支持按 `run_id` 查看单次运行,按 `conversation_id` 查看多轮会话链路。 -- [G3] 前端新增 Agent Trace Center 入口,展示运行时间线、工具调用、语义解析、路由上下文和最终回复。 -- [G4] 保留现有 Agent Run / ToolCall 数据结构,避免破坏数字员工工作记录和系统日志页面。 - -### 非目标 - -- [NG1] 本轮不做重新执行真实业务动作的“调试重跑”,只做历史重放。 -- [NG2] 本轮不接入 OpenTelemetry、Jaeger 等外部分布式追踪系统。 -- [NG3] 本轮不改造总账、预算、报销审批等业务语义。 -- [NG4] 本轮不做跨服务链路采样策略和海量归档策略。 - -## 用户与场景 - -- 目标用户:系统管理员、财务系统运维、Agent 能力开发者、实施顾问。 -- 使用入口:系统日志详情、数字员工工作记录、报销助手消息中的 `run_id`、新增 Trace Center 页面。 -- 核心场景: - - 管理员打开某次异常回复,查看每一步输入输出和耗时。 - - 实施人员按会话查看多轮上下文,判断上下文是否被错误继承。 - - 开发者定位工具调用失败、语义识别降级或路由选错 Agent 的原因。 -- 异常场景: - - 运行失败但没有工具调用时,仍展示已记录的 orchestration 阶段。 - - 旧数据没有 trace event 时,接口回退展示 `agent_runs`、`semantic_parse`、`tool_calls`。 - -## 功能能力 - -- [C1] 输入能力:接收 `run_id`、`conversation_id`、Agent、状态、来源、关键字等查询条件。 -- [C2] 采集能力:记录 `received`、`context_hydrated`、`semantic_parsed`、`agent_selected`、`capability_selected`、`tool_invoked`、`response_built`、`conversation_updated`、`failed` 等事件。 -- [C3] 输出能力:返回 trace 摘要、事件时间线、工具调用、语义解析、路由 JSON、最终回复和关联会话消息。 -- [C4] 状态与权限:复用现有登录与页面权限,管理员/可访问设置页用户可查看全量 trace。 -- [C5] 边界与降级:旧运行没有 trace events 时,按现有 run/tool/semantic 数据合成最小时间线。 - -## 方案设计 - -### 前端 - -- 页面/组件: - - 新增 `AgentTraceCenterView` 或设置页内 Trace Center 分区。 - - 新增 trace 详情组件,复用现有日志详情的直角企业级视觉。 - - 从日志详情、数字员工工作记录、报销助手操作反馈中可跳转到 trace 详情。 -- 交互状态: - - 列表支持关键字、状态、Agent、来源筛选。 - - 详情展示左侧时间线、右侧输入输出 JSON、顶部摘要。 - - 支持加载、空态、错误态和刷新。 -- 展示规则: - - 事件按 `started_at`、`sequence` 升序展示。 - - 失败事件突出错误信息。 - - 大 JSON 使用可滚动代码块,避免撑破页面。 - -### 后端 - -- 接口/服务: - - `GET /api/v1/agent-traces`:查询 trace 列表。 - - `GET /api/v1/agent-traces/{run_id}`:读取单次运行 trace。 - - `GET /api/v1/agent-traces/conversations/{conversation_id}`:读取会话 trace。 -- 权限与校验: - - 复用当前 API 依赖和系统登录态。 - - 不允许通过 trace 接口修改业务数据。 -- 持久化: - - 新增 `agent_trace_events` 表。 - - 通过 `AgentTraceService` 封装记录、查询、合成旧数据时间线。 - -### 算法与规则 - -- 规则输入:Agent 运行阶段、工具调用结果、语义解析结果和会话消息。 -- 规则流程: - - 采集阶段按固定事件名记录。 - - 查询阶段按事件序列合并 run、semantic、tool、conversation。 - - 无事件时从历史 run 数据合成 fallback timeline。 -- 结果解释: - - 每个事件输出 `title`、`summary`、`status`、`duration_ms`、`input_json`、`output_json`、`error_message`。 - -## 算法与公式 - -当前功能不涉及评分、预算或风控公式,只涉及耗时统计: - -$$ -duration\_ms = finished\_at - started\_at -$$ - -变量说明: - -- $duration\_ms$:阶段耗时,单位毫秒。 -- $finished\_at$:阶段结束时间。 -- $started\_at$:阶段开始时间。 - -## 测试方案 - -- 单元测试:覆盖 `AgentTraceService` 记录事件、查询详情、旧 run fallback 时间线。 -- 接口测试:覆盖 trace 列表、单 run 详情、会话详情。 -- 前端交互测试:覆盖 trace 数据归一化、状态文案、空态和错误态。 -- 端到端测试:通过一次 Orchestrator 用户消息生成 `run_id`,验证详情接口能返回语义解析、路由和至少一个事件。 -- 回归测试:确认原 `agent-runs` 接口、数字员工工作记录、系统日志详情不破坏。 -- 手工验证:在浏览器打开 Trace Center,检查列表、详情和 JSON 展示。 - -## 指标与验收 - -- [A1] 功能验收:一次 Orchestrator 调用后,能通过 `run_id` 查询到完整 trace 详情。 -- [A2] 性能指标:单次 trace 详情查询在常规数据量下不引入明显慢查询;默认列表限制数量。 -- [A3] 质量指标:后端定向测试在 Docker `x-financial-main` 容器内 60s 超时内通过。 -- [A4] 安全/权限指标:trace 接口只读,不触发业务动作或副作用。 -- [A5] 可观测性:失败运行也能看到最后成功事件和失败事件。 - -## 风险与开放问题 - -- 风险:当前工作树已有大量未提交改动,本轮实现必须避免覆盖既有业务改动。 -- 已处理依赖:新增 trace 模型已纳入 `Base` 导入,`AgentTraceService.ensure_storage_ready()` 会按需创建 trace 事件表。 -- 待确认:后续是否需要接 OpenTelemetry、跨容器 trace 或长期归档策略。 -- 降级策略:没有 trace event 的旧 run 通过 `semantic_parse`、`tool_calls` 和 `route_json` 合成只读时间线。 - -## 本轮实现记录 - -- 后端已完成 `AgentTraceEvent`、`AgentTraceService` 和 `/api/v1/agent-traces` 只读接口。 -- Orchestrator 已在接收请求、会话补全、语义识别、路由、工具调用、会话写回、最终回复和失败路径写入 trace event。 -- 前端已在系统设置中新增 Agent Trace Center,并从日志详情、数字员工工作记录跳转到指定 `run_id`。 -- 本轮保持非目标不变:不做真实业务重跑、不接 OpenTelemetry、不处理 GL/总账体系和前端统一状态管理。 diff --git a/document/development/Agent链路追踪中心/TODO.md b/document/development/Agent链路追踪中心/TODO.md deleted file mode 100644 index df0b24b..0000000 --- a/document/development/Agent链路追踪中心/TODO.md +++ /dev/null @@ -1,55 +0,0 @@ -# Agent链路追踪中心 开发 TODO - -## 使用规则 - -- 每个 TODO 必须对应 `CONCEPT.md` 中的目标、能力或验收点。 -- 只有完成并验证后,才能把 `[ ]` 改成 `[x]`。 -- 勾选时在任务后补充简短证据,例如文件、接口、命令或验证结果。 -- 如果需求发生变化,先更新 `CONCEPT.md`,再调整本 TODO。 - -## 1. 调研与边界 - -- [x] [CONCEPT: 背景与问题] 阅读相关页面、接口、服务、测试和历史文档,记录当前实现事实。证据:已确认 `agent_runs`、`agent_tool_calls`、`semantic_parse_logs`、`LogDetailView`、`DigitalEmployeeWorkRecords` 现状。 -- [x] [CONCEPT: 目标与非目标] 确认本轮开发范围,写清楚不做项。证据:`CONCEPT.md` 明确只做历史重放,不做调试重跑和 OpenTelemetry。 -- [x] [CONCEPT: 风险与开放问题] 标记无法立即确认的依赖、风险和假设。证据:`CONCEPT.md` 风险章节记录脏工作树和数据库初始化依赖。 - -## 2. 契约与设计 - -- [x] [CONCEPT: 功能能力] 定义输入、输出、状态、权限和边界条件。证据:`CONCEPT.md` 功能能力章节。 -- [x] [CONCEPT: 方案设计] 明确前端、后端、算法、数据的职责边界。证据:`CONCEPT.md` 方案设计章节。 -- [x] [CONCEPT: 算法与公式] 补全耗时公式和变量解释。证据:`CONCEPT.md` 算法与公式章节。 -- [x] [CONCEPT: 指标与验收] 把验收标准转成可验证的检查点。证据:`CONCEPT.md` 指标与验收章节。 - -## 3. 后端实现 - -- [x] [CONCEPT: 后端] 新增 trace 事件模型、schema、repository/service。证据:`AgentTraceEvent`、`agent_trace.py`、`AgentTraceService`。 -- [x] [CONCEPT: 后端] 新增 `agent-traces` 只读接口和路由注册。证据:`agent_traces.py` endpoint 与 `router.py` 注册。 -- [x] [CONCEPT: 后端] 在 Orchestrator 关键节点写入 trace event。证据:`orchestrator.py` 记录接收、会话、语义、路由、回复、失败事件;`orchestrator_execution.py` 记录工具调用事件。 -- [x] [CONCEPT: 数据] 实现旧 run fallback 时间线,避免旧数据详情为空。证据:`AgentTraceService.get_trace()` 在无事件时由 `AgentRun`、`SemanticParseLog`、`AgentToolCall` 合成只读时间线。 - -## 4. 算法/规则实现 - -- [x] [CONCEPT: 算法与规则] 实现 trace 事件排序、耗时计算和状态归一化。证据:`AgentTraceService._next_sequence()`、`_resolve_duration_ms()`、`agentTraceViewModel.js`。 -- [x] [CONCEPT: 结果解释] 输出可读事件标题、摘要、输入输出和错误信息。证据:Trace event schema 与 `AgentTraceCenterView.vue` 详情面板。 - -## 5. 前端实现 - -- [x] [CONCEPT: 前端] 新增 trace 服务 API 和数据归一化工具。证据:`agentTraces.js`、`agentTraceViewModel.js`。 -- [x] [CONCEPT: 前端] 新增 Trace Center 列表与详情视图。证据:`AgentTraceCenterView.vue`。 -- [x] [CONCEPT: 前端] 从现有日志详情和工作记录补充 trace 跳转入口。证据:`LogDetailView.vue`、`DigitalEmployeeWorkRecords.vue`。 -- [x] [CONCEPT: 前端] 实现加载、空态、错误态和刷新。证据:`AgentTraceCenterView.vue` 列表/详情状态与刷新按钮。 -- [x] [CONCEPT: 前端] 对齐现有企业级直角、低饱和、密集信息风格。证据:`agent-trace-center-view.css` 使用面板、表格、状态徽标和紧凑信息布局。 - -## 6. 测试与验证 - -- [x] [CONCEPT: 测试方案] 补充后端 service/API 定向测试。证据:`test_agent_trace_service.py` 覆盖事件记录、fallback、接口列表和详情。 -- [x] [CONCEPT: 测试方案] 补充前端数据归一化测试或可构建验证。证据:`npm.cmd --prefix web run build` 通过。 -- [x] [CONCEPT: 测试方案] 在 60s 超时内运行 Docker 后端定向验证。证据:`docker exec ... pytest -q server/tests/test_agent_trace_service.py server/tests/test_agent_runs_service.py`,7 passed。 -- [x] [CONCEPT: 测试方案] 运行 `npm.cmd --prefix web run build`。证据:Vite build 成功。 -- [x] [CONCEPT: 指标与验收] 记录验证命令、结果和未覆盖风险。证据:后端测试 7 passed、Vite build 成功、重启后 `/api/v1/agent-traces/{run_id}` live 返回 8 个 fallback 事件;浏览器插件后续不可用,未完成最终截图巡检。 - -## 7. 文档收尾 - -- [x] [CONCEPT: 指标与验收] 回看所有验收点,确认均有实现或验证证据。证据:后端 service/API 测试、前端构建、入口接入均已完成。 -- [x] [CONCEPT: 风险与开放问题] 更新剩余风险、后续任务和明确不做项。证据:`CONCEPT.md` 保留 OpenTelemetry、跨容器 trace、长期归档为后续待定。 -- [x] [CONCEPT: 功能一句话] 确认最终实现没有偏离原始目标。证据:本轮只做 Agent Trace Center,未处理 GL/前端状态管理两项待定问题。 diff --git a/document/development/attachment-association-background-job/CONCEPT.md b/document/development/attachment-association-background-job/CONCEPT.md deleted file mode 100644 index 2f6dde1..0000000 --- a/document/development/attachment-association-background-job/CONCEPT.md +++ /dev/null @@ -1,144 +0,0 @@ -# 附件自动关联后台任务方案 - -## 背景 - -小财管家 AI 模式里,用户上传票据后会先做 OCR。当前附件自动关联报销草稿的后半段仍依赖前端会话内存: - -- 前端保留浏览器里的 `File` 对象。 -- 前端在当前会话里完成草稿匹配。 -- 用户点击“确认自动关联”后,再用这些 `File` 上传到报销单明细。 - -这会带来一个核心问题:用户发送消息后,如果刷新页面、切换会话或退出当前会话,浏览器内存里的附件原件会丢失,历史消息中的关联动作就无法继续执行。 - -票据夹已经能持久化 OCR 结果和源文件,并且 OCR 返回里已经带有 `receipt_id`。所以正式方案应该把“附件关联”从前端内存任务调整为后端可查询任务。 - -## 目标 - -1. 用户一上传附件即触发 OCR,附件卡片显示“识别中”,识别完成后显示“当前附件已识别”。 -2. 用户点击发送后,前端不再依赖 `File` 原件做后续归集,而是把 OCR 产生的 `receipt_id` 提交给后端。 -3. 后端创建附件关联任务,并在后台继续匹配、复制票据夹源文件、关联报销单明细。 -4. 用户退出或刷新当前会话后,前端可通过保存下来的 `job_id` 查询任务状态并更新消息。 -5. 如果匹配失败、置信度不足或找不到可编辑草稿,系统给出清晰提示,引导用户补充说明、上传附件或新建草稿。 - -## 非目标 - -第一版不承诺后端服务进程重启后任务状态仍可恢复。 - -本次实现使用轻量内存任务池,解决“用户离开前端会话导致连接断开”的问题。后续如果要做到服务重启、横向扩容、任务审计都可恢复,再新增数据库任务表。 - -## 核心流程 - -```text -用户上传票据 - → 前端立即调用 OCR - → OCR 写入票据夹并返回 receipt_id - → 附件卡片显示“当前附件已识别” - → 用户点击发送 - → 前端 POST 创建附件关联任务 - → 后端后台任务继续运行 - → 前端轮询 job_id - → 成功:消息显示已关联,并刷新报销单详情 - → 失败:消息显示失败原因和下一步动作 -``` - -## 后端设计 - -### API - -新增接口: - -- `POST /api/v1/reimbursements/attachment-association-jobs` -- `GET /api/v1/reimbursements/attachment-association-jobs/{job_id}` - -创建任务请求只传持久化引用,不传浏览器文件: - -```json -{ - "receipt_ids": ["receipt-1", "receipt-2"], - "prompt": "请帮我处理已上传的附件。", - "conversation_id": "inline-xxx" -} -``` - -状态返回: - -```json -{ - "job_id": "job-xxx", - "status": "running", - "message": "正在匹配可关联的报销草稿...", - "receipt_ids": ["receipt-1", "receipt-2"], - "claim_id": "", - "claim_no": "", - "uploaded_count": 0, - "skipped_count": 0, - "error": "" -} -``` - -状态枚举: - -- `queued`:任务已创建,等待后台执行。 -- `running`:正在匹配和归集。 -- `succeeded`:已完成自动归集。 -- `failed`:无法自动完成,返回可读错误。 - -### 任务执行 - -后端任务执行步骤: - -1. 按 `receipt_ids` 读取票据夹明细和源文件。 -2. 从票据 OCR 文本、结构化字段、日期、城市提取匹配信号。 -3. 查询当前用户可见且可编辑的报销草稿,排除申请单和已归档单据。 -4. 对候选草稿按日期、城市、事由、草稿状态评分。 -5. 置信度足够时选择目标草稿。 -6. 为每份票据找到可用费用明细,没有合适明细时创建空明细。 -7. 从票据夹源文件复制到报销单附件目录,并沿用 `source_receipt_id` 回填 OCR 信息。 -8. 更新票据夹状态为 `linked`。 -9. 写入任务最终状态。 - -## 前端设计 - -### 会话消息 - -AI 消息需要持久化 `attachmentAssociationJob`: - -```json -{ - "jobId": "job-xxx", - "status": "running", - "receiptIds": ["receipt-1", "receipt-2"] -} -``` - -这样历史会话恢复后,不再需要浏览器里的 `File` 对象,只要消息里仍有 `jobId`,就可以继续查询后端状态。 - -### 发送行为 - -当用户上传附件并点击发送: - -1. 前端确认 OCR 已完成。 -2. 从 OCR 结果里提取 `receipt_id`。 -3. 创建后端任务。 -4. 立即持久化带 `job_id` 的 pending 消息。 -5. 页面仍打开时轮询任务状态。 -6. 页面恢复或打开历史会话时,对未完成任务继续轮询。 - -## 异常处理 - -- 未完成 OCR:禁止发送,提示“附件 OCR 识别中,请稍等,识别完成后再继续对话。” -- OCR 失败:禁止发送,提示“请先移除识别失败的附件或重新上传。” -- 没有 `receipt_id`:提示“当前附件没有持久化票据记录,请重新上传后再试。” -- 没有可编辑草稿:任务失败,提示用户先新建或选择草稿。 -- 多个候选置信度接近:第一版不自动归集,提示补充说明或手动选择。 -- 服务重启导致内存任务丢失:返回任务不存在,前端提示“后台任务状态已失效,请重新发送附件关联请求。” - -## 验收标准 - -1. 上传附件后必须先进入 OCR 识别中状态,识别完成前不能发送对话。 -2. 发送附件关联请求后,前端能收到并保存 `job_id`。 -3. 用户离开当前会话后,后端任务仍会继续执行。 -4. 用户回到历史会话后,前端可以根据 `job_id` 查询并更新最终状态。 -5. 成功后报销单明细出现附件,票据夹状态变为已关联。 -6. 找不到草稿、低置信度、源文件缺失时,消息能给出明确原因。 - diff --git a/document/development/attachment-association-background-job/TODO.md b/document/development/attachment-association-background-job/TODO.md deleted file mode 100644 index 2a7470f..0000000 --- a/document/development/attachment-association-background-job/TODO.md +++ /dev/null @@ -1,22 +0,0 @@ -# 附件自动关联后台任务 TODO - -- [x] 梳理当前前端内存任务断链原因。 -- [x] 明确第一版边界:页面/会话退出可恢复,服务进程重启暂不承诺恢复。 -- [x] 新增后端任务 schema。 -- [x] 新增后端后台任务服务。 -- [x] 新增任务创建和查询接口。 -- [x] 补后端任务测试。 -- [x] 新增前端任务 service。 -- [x] 调整 AI 模式附件关联流程为创建后端任务。 -- [x] 持久化消息里的 `attachmentAssociationJob`。 -- [x] 历史会话恢复时继续轮询未完成任务。 -- [x] 更新前端源码断言测试。 -- [x] 容器内运行后端定向测试。 -- [x] 运行前端定向测试和构建。 - -## 验证记录 - -- `docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-local-linux /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_attachment_association_jobs.py server/tests/test_ocr_endpoints.py server/tests/test_reimbursement_endpoints.py::test_claim_item_attachment_upload_preview_and_delete server/tests/test_openapi_schema.py` -- `node --test web/tests/workbench-ai-mode-switch.test.mjs web/tests/ai-attachment-association-model.test.mjs` -- `npm --prefix web run build` -- 已重启 `x-financial-local-linux`,并确认 `/api/v1/reimbursements/attachment-association-jobs/not-exist` 返回自定义任务失效提示。 diff --git a/document/development/budget-expense-control-model-plan/employee_behavior_profile_model.md b/document/development/budget-expense-control-model-plan/employee_behavior_profile_model.md deleted file mode 100644 index bf18f27..0000000 --- a/document/development/budget-expense-control-model-plan/employee_behavior_profile_model.md +++ /dev/null @@ -1,515 +0,0 @@ -# 员工业务行为画像模型方案 - -## 目标 - -员工业务行为画像用于把费用申请、审批流转、AI 协作和数字员工巡检中产生的行为数据沉淀为可解释的统计画像。 - -它不是给员工贴负面标签,也不是替代审批人做最终判断,而是为以下场景提供结构化依据: - -- 费用审批详情页展示申请人近期费用节奏和材料质量。 -- Hermes 数字员工定期巡检高频费用、异常预算占用和流程质量问题。 -- 运营看板观察 AI 使用、Token 消耗、流程耗时和审核效率。 -- 后续规则中心根据真实覆盖率和人工覆盖情况优化规则阈值。 - -## 设计原则 - -1. 不把不同性质的数据混成一个总分。 -2. 费用风险、流程质量、AI 使用、审批行为必须分维度计算。 -3. 画像结果必须能追溯到指标、窗口期、同组基准和计算时间。 -4. Hermes 负责调度和沉淀快照,确定性算法负责计算,LLM 只可用于解释和报告。 -5. 画像用于审批参考和运营治理,不直接作为惩罚或自动降标依据。 - -## 画像分层 - -```text -员工业务行为画像 -├── 费用支出画像 -├── 流程质量画像 -├── AI 协作画像 -└── 审批行为画像 -``` - -### 费用支出画像 - -用于判断申请人的费用节奏是否显著高于同组基准。 - -核心指标: - -- 近 30 / 90 / 180 天申请次数。 -- 近 30 / 90 / 180 天申请金额。 -- 差旅申请次数、出差天数、日均费用。 -- 招待申请次数、人均招待金额、同客户重复招待次数。 -- 个人费用占部门预算比例。 -- 个人费用占项目预算比例。 -- 同部门、同岗位、同费用类型分位数。 -- 历史调减、退回、复核次数。 - -审批用途: - -- 识别高频费用申请人。 -- 提醒审核者复核出差天数和费用标准。 -- 推荐补充业务必要性、拆分费用或升级审批。 - -### 流程质量画像 - -用于判断申请人提交材料和流程配合质量。 - -核心指标: - -- 草稿到提交平均耗时。 -- 退回到重新提交平均耗时。 -- 退单次数。 -- 补充材料次数。 -- 附件缺失次数。 -- 发票金额不一致次数。 -- 申请事由缺失次数。 -- 业务地点缺失次数。 -- 项目编号缺失次数。 -- 同一申请多次修改次数。 - -审批用途: - -- 提示“近期材料质量偏低,需要重点核对附件和事由”。 -- 对高频退单申请人提高材料完整性检查权重。 -- 对低质量申请触发补充材料建议,而不是直接判定费用风险。 - -### AI 协作画像 - -用于观察员工和系统的 AI 协作行为,不直接判定费用风险。 - -核心指标: - -- AI 调用次数。 -- AI 辅助生成申请次数。 -- AI 解析票据次数。 -- AI 预审次数。 -- 语义解析次数。 -- 输入 Token。 -- 输出 Token。 -- 总 Token。 -- 估算调用成本。 -- AI 建议被采纳次数。 -- AI 建议被人工覆盖次数。 -- AI 生成后人工修改次数。 - -运营用途: - -- 观察哪些流程高度依赖 AI。 -- 识别高成本用户、部门或功能入口。 -- 衡量 AI 建议采纳率和被覆盖率。 -- 为模型配置、成本控制和产品优化提供依据。 - -审批边界: - -AI 使用多不等于风险高。Token 消耗、AI 调用次数不应直接推高费用审批风险,只能作为运营和辅助说明。 - -### 审批行为画像 - -用于分析审批人的审核效率和审核风格。 - -核心指标: - -- 平均审核时长。 -- 中位审核时长。 -- 超 SLA 次数。 -- 直接通过率。 -- 退回率。 -- 调减率。 -- 高风险单据通过率。 -- 系统建议采纳率。 -- 系统建议覆盖率。 -- 审批意见完整度。 -- 审批积压数量。 - -治理用途: - -- 识别审批积压。 -- 识别过度宽松或过度退回的审批模式。 -- 评估规则建议是否被人工持续覆盖。 -- 为流程优化和审批授权调整提供依据。 - -## 计算窗口 - -第一版建议支持三个窗口: - -```text -30 天:识别近期异常波动 -90 天:作为审批详情页默认画像 -180 天:用于稳定趋势和年度预算节奏 -``` - -审批详情页默认读取 `90 天` 画像。运营看板可以切换 30 / 90 / 180 天。 - -## 同组基准 - -费用支出画像必须和可比人群比较,不能全公司一刀切。 - -建议同组口径: - -```text -peer_group = - department_id -+ position -+ grade -+ expense_type_scope -+ city_tier -+ project_type -+ window_days -``` - -当某个同组样本量不足时,逐级回退: - -```text -部门 + 岗位 + 费用类型 -→ 部门 + 费用类型 -→ 岗位 + 费用类型 -→ 公司 + 费用类型 -``` - -回退必须写入 `peer_group_fallback_level`,避免审核者误以为基准非常精确。 - -## 分值模型 - -### 不建议使用一个大总分 - -不要这样计算: - -```text -综合风险分 = 费用金额 + Token 消耗 + 操作时长 + 审核时长 + 退单次数 -``` - -原因: - -- Token 高可能代表高频使用 AI,不代表费用风险。 -- 审核时长是审批人的行为,不是申请人的费用风险。 -- 退单次数可能代表材料质量问题,不一定代表费用不合理。 -- 一个总分会掩盖到底是哪一类风险触发。 - -### 建议使用多维分 - -```text -employee_behavior_profile = - expense_profile_score - process_quality_score - ai_usage_score - approval_behavior_score -``` - -每个分值都有自己的等级: - -```text -0-39 normal -40-59 watch -60-79 review -80-100 escalation -``` - -审批详情页只展示与当前场景相关的分值: - -```text -费用申请审批: - 展示 expense_profile_score - 展示 process_quality_score - 隐藏或弱化 ai_usage_score - 不展示 approval_behavior_score - -运营看板: - 展示四类分值和趋势 -``` - -## 指标权重建议 - -### 费用支出画像分 - -```text -expense_profile_score = - frequency_score * 20% -+ amount_occupancy_score * 25% -+ peer_deviation_score * 25% -+ adjustment_history_score * 15% -+ current_claim_deviation_score * 15% -``` - -### 流程质量画像分 - -```text -process_quality_score = - return_count_score * 25% -+ missing_attachment_score * 20% -+ invoice_mismatch_score * 20% -+ resubmit_duration_score * 15% -+ missing_business_context_score * 20% -``` - -### AI 协作画像分 - -AI 协作分不命名为风险分,建议叫 `ai_usage_intensity_score`。 - -```text -ai_usage_intensity_score = - ai_call_count_score * 25% -+ token_cost_score * 25% -+ ai_generated_claim_ratio_score * 20% -+ ai_suggestion_override_score * 20% -+ failed_ai_call_score * 10% -``` - -含义: - -- 分数高代表 AI 使用强度高或成本高。 -- 不代表员工费用风险高。 -- 主要用于成本治理、流程优化和模型配置。 - -### 审批行为画像分 - -审批行为分不命名为风险分,建议叫 `approval_behavior_score`。 - -```text -approval_behavior_score = - avg_review_duration_score * 20% -+ sla_overdue_score * 20% -+ direct_approve_ratio_score * 20% -+ high_risk_approve_score * 20% -+ system_advice_override_score * 20% -``` - -含义: - -- 分数高代表审批行为需要运营关注。 -- 不直接代表审批人存在问题。 -- 必须结合审批量、单据复杂度和部门业务特性解释。 - -## 数据来源 - -### 费用与流程数据 - -主要来源: - -- `expense_claims` -- `expense_claim_items` -- 审批流转记录 -- 退回 / 调减 / 补充材料记录 -- 预算池和预算交易记录 - -需要补齐或确认的数据: - -- 审批开始时间。 -- 审批完成时间。 -- 退回原因结构化字段。 -- 调减前后金额。 -- 补充材料事件。 -- 审批意见是否为空。 - -### AI 与工具调用数据 - -主要来源: - -- `AgentRun` -- `AgentToolCall` -- `SemanticParseLog` -- `runtime_chat.py` -- `ontology.py` -- `user_agent.py` -- `ocr.py` - -需要注意: - -不是所有模型入口都已经完整持久化 Token。第一版必须区分: - -```text -exact_token_count:真实记录的 Token -estimated_token_count:按文本长度估算 -unavailable:当前不可用 -``` - -不能把估算值包装成真实计费数据。 - -## 存储设计 - -建议第一版使用通用画像快照表: - -```text -employee_behavior_profile_snapshots -``` - -字段建议: - -```text -id -subject_type applicant / approver / employee -subject_id employee_id -subject_name -department_id -department_name -position -grade - -profile_type expense / process_quality / ai_usage / approval -window_days 30 / 90 / 180 -expense_type_scope overall / travel / entertainment / ... -peer_group_key -peer_group_fallback_level - -profile_score -profile_level -metrics_json -basis_codes_json -source_task_type -source_task_log_id -calculated_at -created_at -``` - -### 为什么用快照表 - -不要把画像直接写入员工表: - -```text -employee.profile_score = 80 -``` - -原因: - -- 员工表是主数据,画像是动态计算结果。 -- 审批审计需要知道当时为什么是这个分。 -- 算法规则调整后,历史依据不能被覆盖。 -- 快照可以支持趋势分析。 - -### 是否每个员工都存 - -不建议全员每天存。 - -第一版只存: - -- 近 90 / 180 天有费用申请记录的员工。 -- 当前存在待审批申请的员工。 -- 上一期画像等级为 `watch`、`review`、`escalation` 的员工。 -- AI 使用或审批行为达到运营关注阈值的员工。 - -无行为员工不生成画像快照。 - -## Hermes 调度策略 - -不重新写调度器,复用 Hermes 现有 cron 调度体系。 - -建议新增任务类型: - -```text -employee_behavior_profile_scan -``` - -任务职责: - -```text -1. 识别本次需要刷新画像的员工集合。 -2. 聚合费用、流程、AI、审批行为指标。 -3. 调用各画像子算法。 -4. 写入 employee_behavior_profile_snapshots。 -5. 在 HermesTaskExecutionLog 写入执行摘要。 -``` - -建议频率: - -```text -事件触发:申请提交、审批完成、退回、调减、AI 任务完成后,刷新相关员工。 -每日轻量:只扫描昨日新增行为和上一期高关注员工。 -每周全量:刷新同组基准、分位数和活跃员工画像。 -每月复盘:分析阈值、规则覆盖率和人工覆盖率。 -``` - -## 审批详情展示 - -费用审批详情页建议展示: - -```text -申请人费用画像 -流程材料质量 -本次申请实时偏离 -``` - -不建议在普通审批详情页直接展示: - -```text -Token 消耗 -AI 调用成本 -审批人行为分 -``` - -这些更适合管理员运营看板。 - -示例展示: - -```text -申请人费用画像 -近 90 天 · 销售部 / 客户经理 / 差旅费 -状态:重点复核 - -触发依据: -- 近 90 天差旅金额处于同组 P88。 -- 本次出差天数为同类 P75 的 1.67 倍。 -- 最近 180 天存在 3 次调减或退回记录。 - -审核建议: -- 建议确认本次 5 天行程是否可压缩至 4 天。 -- 如确属关键客户推进,请补充客户拜访安排和预期产出。 -``` - -## 运营看板展示 - -管理员或运营人员可以看到更完整的画像: - -```text -员工画像总览 -├── 费用支出关注榜 -├── 流程质量待优化榜 -├── AI 使用强度榜 -├── Token 成本趋势 -├── 审批效率与积压 -└── 系统建议采纳率 -``` - -运营看板要标明: - -- 哪些指标是真实采集。 -- 哪些指标是估算。 -- 哪些指标当前不可用。 - -## 第一版落地边界 - -第一版建议先做: - -1. 费用支出画像。 -2. 流程质量画像。 -3. AI 协作画像的数据口径定义。 -4. 通用快照表。 -5. Hermes 画像扫描任务。 - -暂不做: - -- 自动处罚或自动降标。 -- 将 AI Token 消耗纳入费用风险分。 -- 用 LLM 直接判断员工是否异常。 -- 全员每日全量画像。 - -## 后续演进 - -### 第二阶段 - -- 接入审批详情页“申请人费用画像”卡片。 -- 接入 Hermes 数字员工日志。 -- 支持画像快照趋势对比。 -- 支持规则中心根据高频触发指标生成规则草稿。 - -### 第三阶段 - -- 引入更稳定的同组基准缓存。 -- 引入审批建议采纳率。 -- 对 AI 使用成本做部门和功能维度分摊。 -- 将画像结果接入运营看板。 - -### 第四阶段 - -- 根据真实历史数据调整权重。 -- 对高覆盖、高误报规则做自动复盘。 -- 让 Hermes 输出月度费用治理建议,但仍不直接改线上规则。 - diff --git a/document/development/budget-expense-control-model-plan/index.html b/document/development/budget-expense-control-model-plan/index.html deleted file mode 100644 index 8fbbb63..0000000 --- a/document/development/budget-expense-control-model-plan/index.html +++ /dev/null @@ -1,1472 +0,0 @@ - - - - - - X-Financial 预算费用规划推荐模型方案 - - - -
- - -
-
-
-
X-Financial Model Proposal
-

预算费用规划推荐模型方案

-

- 这个模型不只是给审批页打一个分,而是把“预算是否够、费用是否合理、是否影响预算节奏、下一步该怎么处理”整理成可解释、可审计、可持续迭代的推荐结果。 -

-
- 规则模型优先 - 硬约束可审计 - LLM 只做解释层 - 审批反馈可回流 -
-
- -
-
-
- 模型主目标 - 帮预算管理者快速判断是否可承接 -
-
Recommend
-
-
-
- 第一版边界 - 不替代人工审批,不让 LLM 直接做硬判断 -
-
Guarded
-
-
-
- 核心口径 - 扣除当前申请已预占,避免重复计算 -
-
Traceable
-
-
-
- 迭代方向 - 规则评分 + 历史基准 + 解释生成 -
-
V1 → V3
-
-
-
- -
-
-
-

方案结论

-

建议把模型定位为“预算审批辅助决策引擎”,输出结构化推荐和解释依据,而不是单纯的页面分数。

-
-
Executive Summary
-
- -
-
-
推荐动作
-
4 类
-
建议通过、谨慎通过、需要复核、不建议直接通过。
-
-
-
核心评分
-
100 分
-
预算安全优先,费用必要性与信息完整度共同影响。
-
-
-
硬性约束
-
3 条
-
超预算、强阻断控制、预算池无法匹配必须显式处理。
-
-
-
上线策略
-
分阶段
-
先确定性规则,再接入历史基准和解释层。
-
-
- -
-
- 推荐采用的产品口径: - 分数不是结论本身,结论应由“推荐动作 + 风险等级 + 触发依据 + 可执行建议”共同表达。 -
-
- 需要避免的方向: - 不要让 LLM 直接判断是否通过,也不要只用一个综合分覆盖预算、业务必要性、历史异常等不同原因。 -
-
-
- -
-
-
-

业务闭环

-

模型要服务完整预算链路:预算池建立、申请预占、审批推荐、报销核销、结果反馈。

-
-
Business Loop
-
- -
-
- 1 - 预算计划建立 - 按部门、项目、科目、成本中心形成预算池和预警线。 -
-
- 2 - 费用申请预占 - 申请提交后先占用预算,避免后续审批期间额度被重复使用。 -
-
- 3 - 预算审批推荐 - 预算管理者看到风险等级、计算依据、建议动作和补充要求。 -
-
- 4 - 报销与核销 - 申请通过后生成报销草稿,实际报销后转为已核销金额。 -
-
- 5 - 结果反馈回流 - 记录审批采纳、驳回原因、实际报销差异,反哺后续规则。 -
-
-
- -
-
-
-

模型架构

-

采用“上下文构建 → 特征计算 → 硬约束判定 → 综合评分 → 推荐解释 → 反馈沉淀”的分层结构。

-
-
Model Layers
-
- -
-
-

上下文层

-
-

统一组装申请单、预算池、历史费用、项目计划和审批身份,形成模型输入快照。

-
    -
  • 复用 build_claim_budget_context() 的预算上下文。
  • -
  • 补充申请事由、地点、费用类型、项目编号、附件摘要。
  • -
  • 保留计算时刻的预算快照,方便事后审计。
  • -
-
-
- -
-

特征层

-
-

把业务数据转换成可解释特征,而不是直接把原始字段丢给模型。

-
    -
  • 预算容量:审批前可用、审批后使用率、超预算金额。
  • -
  • 单笔影响:本次金额占预算比例、是否突破预算节奏。
  • -
  • 必要性证据:事由、项目、地点、附件、业务场景是否完整。
  • -
  • 历史基准:同部门、同项目、同费用类型的历史均值和波动。
  • -
-
-
- -
-

决策层

-
-

先执行硬规则,再计算综合分,确保强管控场景不会被其他维度“平均掉”。

-
    -
  • 硬规则:超预算、预算池阻断、预算无法匹配、关键字段缺失。
  • -
  • 综合评分:预算安全、费用影响、规划匹配、历史异常、信息完整。
  • -
  • 分档输出:recommended、caution、review、block、reference。
  • -
-
-
- -
-

解释层

-
-

第一版直接用模板解释;后续允许 LLM 改写语气,但不能改写分数、等级和硬性结论。

-
    -
  • 解释必须引用结构化依据,不允许凭空补充原因。
  • -
  • 建议要能变成审批动作,例如补充材料、拆分费用、调整预算。
  • -
  • 所有展示文案保留对应的 basis_code,方便追踪。
  • -
-
-
-
-
- -
-
-
-

数据与特征

-

模型输入需要覆盖“预算是否够”和“费用是否该花”两条线,避免只看额度、不看业务必要性。

-
-
Feature Design
-
- -
-
-

预算上下文

-
    -
  • budget_applicable:是否纳入预算管控。
  • -
  • matched:是否匹配到预算池。
  • -
  • total_amountreserved_amountconsumed_amount
  • -
  • current_reserved_amount:当前申请已预占金额。
  • -
  • warning_thresholdcontrol_action
  • -
-
- -
-

申请单主数据

-
    -
  • 申请金额、费用类型、申请事由。
  • -
  • 业务地点、项目编号、成本中心。
  • -
  • 直属领导意见、附件摘要。
  • -
  • 申请时间、期望发生时间、是否紧急。
  • -
-
- -
-

增强特征

-
    -
  • 同类费用历史均值与分位数。
  • -
  • 部门剩余预算消耗速度。
  • -
  • 项目里程碑与预算计划匹配度。
  • -
  • 申请人近期预算占用频次。
  • -
-
-
- -
- 预算容量 - 单笔影响 - 预算节奏 - 业务必要性 - 历史异常 - 信息完整度 - 审批反馈 -
-
- -
-
-
-

计算口径

-

申请提交时已经发生预算预占,所以审批分析必须扣除当前申请已预占金额,避免重复计算。

-
-
Calculation
-
- -
-
已使用基数 = 已预占金额 + 已核销金额 - 当前申请已预占金额
-审批前可用预算 = 预算总额度 - 已使用基数
-审批后占用 = 已使用基数 + 本次申请金额
-此次费用占预算 = 本次申请金额 / 预算总额度
-审批后使用率 = 审批后占用 / 预算总额度
-超预算金额 = max(本次申请金额 - 审批前可用预算, 0)
- -
- 关键原则 - 如果当前申请在提交阶段已经进入 reserved_amount,审批页就不能再把它当成新增占用直接叠加。否则预算管理者看到的风险会被放大,尤其是大额申请会明显失真。 -
-
-
- -
-
-
-

评分推荐

-

建议采用“硬规则优先 + 加权评分”的组合。硬规则决定是否必须复核或阻断,评分用于排序和解释风险程度。

-
-
Decision Strategy
-
- -
-
-

建议权重

-
    -
  • 预算安全:40 分,覆盖可用额度、审批后使用率、超预算金额。
  • -
  • 单笔影响:18 分,判断本次费用对预算池的冲击。
  • -
  • 规划匹配:16 分,比较项目计划、预算周期和费用发生时间。
  • -
  • 历史基准:14 分,识别同类费用异常偏高或频繁占用。
  • -
  • 信息完整:12 分,衡量事由、项目、地点、附件是否足够。
  • -
-
- -
- -
- caution -
70-84
- 预算可承接但影响较明显,建议谨慎通过并关注后续节奏。 -
-
- review -
50-69
- 存在信息缺口、历史异常或接近预警线,需要复核。 -
-
- block -
0-49
- 超预算或触发强管控动作,不建议直接通过。 -
-
-
- -
-
- 硬规则示例: - control_action = block 且超预算时,直接进入 block;预算池未匹配时输出 reference,不能伪装成低风险。 -
-
- 推荐动作要具体: - 不只写“需关注”,而要给出“补充业务必要性、拆分费用、调整预算池、发起预算调剂”等可执行动作。 -
-
-
- -
-
-
-

申请人费用画像公式

-

画像只用于调整复核强度和审核建议,不能直接把申请人定义为“异常人员”。核心是用同组基准解释个人费用节奏是否偏离。

-
-
Applicant Profile
-
- -
-
申请人画像风险分 =
-  高频申请分 * 20%
-+ 高金额占用分 * 25%
-+ 同组偏离分 * 25%
-+ 历史调减退回分 * 15%
-+ 本次申请偏离分 * 15%
-
-等级:
-0-39   正常
-40-59  需关注
-60-79  重点复核
-80-100 强复核 / 升级审批
- -
- 同组基准口径 - 同组不按全公司粗暴比较,而应按 部门 + 岗位 + 费用类型 + 城市等级 + 项目类型 + 近 90/180 天 聚合。销售、项目经理和研发不能混在一个基准池里比较。 -
-
- -
-
-

出差天数建议

-
同类基准天数 = peer_group.travel_days_p75
-天数偏离率 = 本次出差天数 / 同类基准天数
-建议天数 = min(
-  本次出差天数,
-  同类基准天数 + 业务缓冲天数
-)
-

当偏离率超过 1.5 时,建议补充行程安排或压缩天数;超过 2.0 时进入重点复核。

-
- -
-

出差费用建议

-
本次日均费用 = 本次申请金额 / 本次出差天数
-日均费用偏离率 =
-  本次日均费用 / 同城市同职级日均基准
-建议金额上限 =
-  建议天数 * 日均基准 * 容忍系数
-

容忍系数第一版建议使用 1.15 到 1.20,避免模型因为小幅波动给出过硬建议。

-
- -
-

招待费用建议

-
人均招待金额 = 本次招待金额 / 参与人数
-人均偏离率 = 人均招待金额 / 招待标准上限
-同客户招待频率 = 近 90 天同客户招待次数
-个人招待分位 = 个人近 90 天招待金额在同组分位
-

人均偏离率超过 1.2 时建议调低标准;同客户 90 天内多次招待时要求补充客户推进阶段。

-
-
- -
-
- 建议生成公式: - 审核建议强度 = max(画像风险等级, 本次偏离等级, 硬规则等级)。展示时必须说明是哪一类指标触发,而不是只给一个结论。 -
-
- 审核建议示例: - “该申请人近 90 天费用占用处于同组 P88,本次出差天数为同类 P75 的 1.67 倍。建议将 5 天调整为 4 天,或补充客户拜访安排和项目阶段说明。” -
-
-
- -
-
-
-

输出协议

-

接口输出需要同时服务审批页展示、看板统计和后续审计,因此自然语言必须和结构化字段分开。

-
-
API Contract
-
- -
{
-  "score": 82,
-  "rating": "caution",
-  "risk_level": "medium",
-  "recommendation": "cautious_approve",
-  "summary": "预算整体可承接,但本次费用对预算池已有明显影响。",
-  "metrics": {
-    "claim_amount": "12000.00",
-    "total_amount": "50000.00",
-    "available_before_approval": "38000.00",
-    "claim_amount_ratio": "24.00",
-    "after_usage_rate": "72.00",
-    "over_budget_amount": "0.00"
-  },
-  "applicant_profile": {
-    "profile_score": 66,
-    "profile_level": "review",
-    "peer_percentile": 88,
-    "travel_days_ratio": "1.67",
-    "daily_cost_ratio": "1.34",
-    "suggested_days": 4,
-    "suggested_amount_cap": "6800.00"
-  },
-  "evidence": [
-    {
-      "basis_code": "budget.after_usage_rate.warning_near",
-      "text": "审批后预算使用率为 72.00%,接近预警区间。"
-    }
-  ],
-  "suggested_actions": [
-    {
-      "action": "approve_with_note",
-      "text": "可继续审批,但建议备注本次费用对应的项目阶段和后续预算节奏。"
-    }
-  ],
-  "explainable_snapshot": {
-    "budget_no": "BUD-TEST",
-    "control_action": "warn",
-    "warning_threshold": "80.00"
-  }
-}
-
- -
-
-
-

审批展示

-

预算管理者最需要看到的是“为什么是这个建议”和“如果要通过,还要补什么”。页面不应只展示一个分数。

-
-
Approval UX
-
- -
-
- 顶部结论条 - 展示推荐动作、风险等级、综合分和一句话摘要,例如“谨慎通过:预算可承接,但审批后使用率接近预警线”。 -
-
- 关键指标 - 本次金额、预算总额、审批前可用、审批后使用率、超预算金额。 -
-
- 触发依据 - 逐条展示规则依据,保留 basis_code,方便定位到模型逻辑。 -
-
- 建议动作 - 通过、谨慎通过、补充材料、拆分费用、预算调剂、退回修改。 -
-
- 申请人费用画像 - 展示近 90 天频率、金额分位、天数偏离率和建议压缩区间,只作为审批参考。 -
-
- 审批反馈 - 记录预算管理者是否采纳建议,以及不采纳时的原因。 -
-
-
- -
-
-
-

落地路线

-

先把确定性口径做稳,再逐步接入历史基准和解释层,避免第一版就变成难以审计的黑盒。

-
-
Implementation
-
- -
-
-

P0:口径对齐

-

确认预算预占、审批前可用、审批后占用的计算口径。

-
    -
  • 梳理预算上下文字段。
  • -
  • 固化不重复计算规则。
  • -
  • 定义输出协议。
  • -
-
-
-

P1:规则评分

-

上线可审计的确定性模型,覆盖预算审批主流程。

-
    -
  • 实现特征计算。
  • -
  • 实现硬规则和分档。
  • -
  • 补齐单元测试。
  • -
-
-
-

P2:历史基准

-

引入同类费用历史均值、部门消耗速度和预算节奏。

-
    -
  • 沉淀历史统计任务。
  • -
  • 增加异常检测特征。
  • -
  • 看板展示采纳率。
  • -
-
-
-

P3:解释增强

-

在结构化依据上增加 LLM 文案层,提升可读性。

-
    -
  • LLM 不改分数和等级。
  • -
  • 解释引用 basis_code。
  • -
  • 增加人工反馈闭环。
  • -
-
-
-
- -
-
-
-

验收清单

-

下面的清单会保存在当前浏览器本地,方便后续评审和开发跟踪。

-
-
Checklist
-
- -
- - - - - - - -
-
- - -
-
- - - - diff --git a/document/development/employee-behavior-profile/CONCEPT.md b/document/development/employee-behavior-profile/CONCEPT.md deleted file mode 100644 index fdac8b0..0000000 --- a/document/development/employee-behavior-profile/CONCEPT.md +++ /dev/null @@ -1,681 +0,0 @@ -# 员工业务行为画像功能概念文档 - -## 1. 功能一句话 - -员工业务行为画像通过确定性算法把费用申请、流程质量、AI 协作和审批行为沉淀为可追溯的画像快照,并在审批详情、Hermes 数字员工巡检和运营看板中提供可解释的审核依据。 - -## 2. 背景与问题 - -预算费用规划推荐模型需要解释“为什么某个申请应该被重点审核”。仅看当前单据金额不够,因为同样的金额在不同员工、部门、岗位、城市和费用类型下含义不同。 - -当前讨论中已经明确几个问题: - -- 出差天数、出差金额、业务招待频次和招待标准需要和申请人挂钩,否则审核者看不到长期费用节奏。 -- 用户操作时长、AI 使用次数、Token 消耗、审核时长、退单次数等指标也有价值,但它们性质不同,不能混成一个“坏人分”。 -- 审批详情需要一个直观入口展示画像,例如“风险审核画像”卡片,但卡片必须展示证据、口径和建议,避免给员工贴不可解释标签。 -- Hermes 已有数字员工和调度入口,画像检测应该接入现有 Hermes 任务体系,而不是另写一套调度器。 - -代码现状可作为第一版基础: - -- `AgentRun`、`AgentToolCall`、`SemanticParseLog` 已记录 Agent 运行、工具调用耗时和语义解析日志。 -- `ExpenseClaim`、`ExpenseClaimItem` 已承载费用申请和明细。 -- `HermesTaskConfig`、`HermesTaskExecutionLog` 已承载 Hermes 任务配置和执行日志。 -- 现有 Hermes 调度器会轮询启用任务,并按 `task_type` 分发到具体服务。 -- 当前前端 Hermes 设置仅暴露 `global_risk_scan` 和 `weekly_expense_report` 两类任务,画像任务需要补齐配置入口。 - -## 3. 目标与非目标 - -### 3.1 目标 - -- 建立员工维度的多层画像:费用支出画像、流程质量画像、AI 协作画像、审批行为画像。 -- 建立可审计的快照存储,不把动态画像直接写进员工主表。 -- 形成可解释的量化公式,支持 30 / 90 / 180 天窗口。 -- 接入 Hermes 数字员工任务,定期生成画像快照和汇总日志。 -- 在审批详情中展示“风险审核画像”卡片,默认突出费用支出和流程质量。 -- 保留指标来源、同组基准、计算窗口、任务日志和算法版本,便于复核。 -- 明确 Token 统计口径:真实值、估算值和不可用值必须区分。 - -### 3.2 非目标 - -- 不用画像自动处罚员工,也不自动降低费用标准或缩短出差天数。 -- 不把 AI 使用次数、Token 消耗直接当作费用风险。 -- 不做全员每日全量画像快照,避免频率过高和无意义存储。 -- 不重写 Hermes 调度器;如频率能力不足,优先增强现有 Hermes 调度体系。 -- 不用 LLM 直接判定风险等级;LLM 仅可用于解释、摘要和报告生成。 - -## 4. 用户与场景 - -### 4.1 费用审核者 - -在费用申请详情页查看“风险审核画像”卡片。审核者需要知道: - -- 申请人近期是否频繁申请大额出差或招待。 -- 当前申请是否显著高于同组基准或个人历史。 -- 申请人的材料质量是否经常导致退单、补充材料或复核。 -- 系统建议是“重点复核”“建议补充说明”还是“建议升级审批”。 - -### 4.2 财务和预算管理员 - -在运营看板或 Hermes 报告中查看部门、项目、费用类型下的画像趋势。管理员需要识别: - -- 哪些部门或项目存在持续预算占用压力。 -- 哪些费用类型的人均标准偏离明显。 -- 哪些流程环节反复出现退单或材料缺失。 - -### 4.3 AI 运营人员 - -观察 AI 调用、Token 消耗、建议采纳率和覆盖率。AI 运营人员需要知道: - -- 哪些入口消耗高但采纳率低。 -- 哪些业务流程高度依赖 AI。 -- 哪些模型调用需要限额、优化或替换。 - -### 4.4 Hermes 数字员工 - -Hermes 作为调度入口,负责在设定周期内触发画像计算、写入快照、记录执行日志,并输出可读摘要。 - -## 5. 功能能力 - -### 5.1 输入 - -- 费用申请:申请人、部门、岗位、费用类型、申请金额、审批金额、出差天数、招待客户、业务地点、项目编号。 -- 费用明细:明细金额、票据金额、费用类型、发生日期、供应商或客户线索。 -- 审批流转:提交时间、审核开始时间、审核完成时间、退单、调减、复核、审批意见。 -- Agent 数据:Agent 运行记录、工具调用次数、工具耗时、语义解析、AI 建议、AI 建议采纳或覆盖。 -- Token 数据:输入 Token、输出 Token、总 Token、估算 Token、不可用状态。 -- Hermes 数据:任务配置、任务执行日志、报告或风险巡检结果。 -- 组织基准:部门、岗位、职级、城市等级、项目类型、费用类型和预算池。 - -### 5.2 输出 - -- 员工画像快照:每个员工、每个窗口、每个画像类型一条或多条快照。 -- 最新画像查询:给审批详情、运营看板和 Hermes 报告读取。 -- 画像证据:指标值、同组基准、贡献项、命中原因、数据质量标记。 -- 画像标签:把复杂指标转成可读标签,例如“费用之王”“长差达人”“材料补丁户”“急速审核员”,每个标签必须有触发公式、置信度和证据。 -- 行为雷达图:把费用、差旅招待、流程质量、AI 协作和审批行为压缩成 6 到 8 个维度,用于分析者快速理解员工行为结构。 -- 审核建议:复核天数、复核金额、补充材料、升级审批、关注预算占用等建议。 -- Hermes 执行摘要:本次计算人数、生成快照数、高关注人数、失败原因。 - -### 5.3 审批详情卡片 - -审批详情中建议新增卡片:`风险审核画像`。 - -卡片默认展示: - -- 总览:画像等级、计算时间、窗口期、同组基准口径。 -- 特征标签:展示 3 到 6 个置信度最高、与当前场景相关的标签;风险型标签优先,但必须保留证据入口。 -- 雷达图:展示行为维度得分,帮助审核者一眼判断该员工是“费用强度高”“材料质量弱”还是“审批节奏快”。 -- 费用支出:频次、金额占用、同组偏离、历史调减、当前单据偏离。 -- 流程质量:退单、附件缺失、发票不一致、补充材料、重提耗时。 -- 当前单据建议:是否建议复核出差天数、招待人均金额、业务必要性或预算占用。 -- 证据展开:展示贡献最高的 3 到 5 个指标和原始口径。 - -审批详情默认不突出 AI 协作画像和审批人行为画像。AI 指标主要服务运营治理,审批人画像只在管理员或流程治理场景展示。 - -### 5.4 权限和边界 - -- 普通审核者只能看到与当前单据审核有关的申请人费用画像和流程质量画像。 -- 财务管理员可查看部门、项目和费用类型维度的汇总趋势。 -- AI 运营人员可查看 AI 协作画像,但不把它用于单据费用风险裁决。 -- 审批行为画像只面向管理员和流程治理角色展示。 -- 所有画像结论必须展示数据窗口和计算时间,避免被误读为永久标签。 - -## 6. 方案设计 - -### 6.1 数据模型 - -第一版建议新增通用快照表: - -```text -employee_behavior_profile_snapshots -``` - -核心字段: - -```text -id -subject_type applicant / approver / employee -subject_id employee_id 或 user_id -subject_name -department_id -department_name -position -grade - -profile_type expense / process_quality / ai_usage / approval -window_days 30 / 90 / 180 -expense_type_scope overall / travel / entertainment / ... -peer_group_key -peer_group_fallback_level - -profile_score 0-100 -profile_level normal / watch / review / escalation -metrics_json 原始指标、分位数、样本量、Token 口径 -basis_codes_json 贡献项和解释编码 -profile_tags_json 标签、触发分、置信度、证据和展示优先级 -radar_json 雷达图维度、维度分、维度等级和主导标签 -source_task_type employee_behavior_profile_scan -source_task_log_id HermesTaskExecutionLog.id -algorithm_version -calculated_at -created_at -``` - -不建议把画像直接写入员工主表,例如 `employee.profile_score = 80`。画像是动态计算结果,需要保留算法版本、窗口期和历史依据。 - -### 6.2 后端服务 - -建议拆成三个职责: - -- 数据抽取服务:从费用、审批、Agent、Hermes 记录中抽取指标。 -- 算法服务:在 `server/src/app/algorithem` 下维护评分公式、等级判定和解释贡献项。 -- 应用服务:负责员工集合筛选、快照写入、最新画像查询和 Hermes 执行结果汇总。 - -候选模块: - -```text -server/src/app/algorithem/employee_behavior_profile.py -server/src/app/services/employee_behavior_profile_service.py -server/src/app/services/hermes_employee_profile_scanner.py -server/src/app/models/employee_behavior_profile.py -``` - -### 6.3 Hermes 接入 - -新增任务类型: - -```text -employee_behavior_profile_scan -``` - -接入原则: - -- 复用现有 `HermesTaskConfig` 和 `HermesTaskExecutionLog`。 -- 在现有 `HermesScheduler._execute_task()` 中增加任务分发。 -- 在 `start_hermes_daemon.py` 中初始化画像任务配置。 -- 在 `hermesEmployeeSettingsModel.js` 中补充任务展示和默认开关。 -- 不创建第二个后台调度器。 - -频率建议: - -- 第一版不做全员每日全量。 -- 推荐每周一次全量画像,工作日对存在待审单据的员工做轻量增量。 -- 如果现有 Hermes 调度只支持近似每日触发,应先把画像任务默认关闭或仅启用轻量扫描;后续在现有调度器内补齐 frequency / weekday / time 判断。 - -### 6.4 API 契约 - -审批详情读取最新画像: - -```text -GET /api/v1/employee-profiles/{employee_id}/latest -``` - -建议查询参数: - -```text -scene=approval -claim_id= -window_days=90 -expense_type_scope=travel|entertainment|overall -``` - -响应结构建议: - -```json -{ - "employee_id": "EMP001", - "window_days": 90, - "calculated_at": "2026-05-28T10:30:00+08:00", - "peer_group": { - "key": "FINANCE|M2|travel|tier1", - "fallback_level": 1, - "sample_size": 42 - }, - "profiles": [ - { - "profile_type": "expense", - "score": 72, - "level": "review", - "top_contributors": [ - { - "code": "peer_deviation_high", - "label": "差旅日均费用高于同组 P90", - "value": 1.18, - "unit": "ratio" - } - ] - } - ], - "profile_tags": [ - { - "code": "expense_king", - "label": "费用之王", - "display_label": "费用集中度高", - "category": "expense", - "polarity": "risk", - "score": 86, - "confidence": 0.82, - "reason": "近90天费用总额达到同组P90,且部门费用占比为34%", - "metrics": { - "amount_total": 128000, - "peer_amount_p90": 76000, - "amount_share": 0.34 - } - } - ], - "radar": { - "dimensions": [ - { - "code": "expense_intensity", - "label": "费用强度", - "score": 78, - "level": "review", - "top_tags": ["expense_king", "large_amount_deviation"] - } - ] - }, - "review_suggestions": [ - { - "type": "review_travel_days", - "severity": "medium", - "message": "建议复核出差天数和业务必要性" - } - ] -} -``` - -### 6.5 前端展示 - -审批详情页新增 `风险审核画像` 卡片,建议分成三层: - -- 顶部摘要:等级、窗口期、同组基准、更新时间。 -- 中部指标:费用支出和流程质量两个分组。 -- 底部建议:系统建议和证据展开。 - -文案边界: - -- 使用“关注”“复核”“建议”而不是“惩罚”“违规”“头号人物”。 -- 展示“该结论来自 90 天窗口和同组对比”,避免变成员工永久标签。 -- AI 协作强度只作为运营指标,不在费用审批默认卡片中强调。 - -## 7. 算法与公式 - -### 7.1 通用归一化 - -对越大越需要关注的指标,使用同组分位数归一化: - -$$ -score(x) = clip\left(100 \times \frac{x - P_{50}}{P_{90} - P_{50}}, 0, 100\right) -$$ - -其中: - -- \(x\):员工在窗口期内的指标值。 -- \(P_{50}\):同组中位数。 -- \(P_{90}\):同组 90 分位数。 -- \(clip(v, 0, 100)\):把结果限制在 0 到 100。 - -当同组样本不足时,按以下顺序降级: - -```text -部门 + 岗位 + 费用类型 -→ 部门 + 费用类型 -→ 岗位 + 费用类型 -→ 公司 + 费用类型 -``` - -降级层级必须写入 `peer_group_fallback_level`。 - -### 7.2 费用支出画像 - -$$ -expense\_profile\_score = -0.20F + 0.25B + 0.25D + 0.15H + 0.15C -$$ - -变量定义: - -- \(F\):费用申请频次分,包含出差、招待等申请次数。 -- \(B\):预算占用分,包含个人费用占部门或项目预算比例。 -- \(D\):同组偏离分,包含金额、天数、人均招待金额等分位数偏离。 -- \(H\):历史调减和复核分,包含历史调减、退回、复核次数。 -- \(C\):当前单据偏离分,衡量当前申请相对个人历史和同组基准的偏离。 - -### 7.3 流程质量画像 - -$$ -process\_quality\_score = -0.25R + 0.20A + 0.20I + 0.15T + 0.20M -$$ - -变量定义: - -- \(R\):退单次数分。 -- \(A\):附件缺失分。 -- \(I\):发票金额或票据一致性问题分。 -- \(T\):退回后重新提交耗时分。 -- \(M\):业务上下文缺失分,包含事由、地点、项目编号、客户信息等。 - -### 7.4 AI 协作画像 - -AI 协作画像命名为强度分,不命名为风险分。 - -$$ -ai\_usage\_intensity\_score = -0.25N + 0.25K + 0.20G + 0.20O + 0.10E -$$ - -变量定义: - -- \(N\):AI 调用次数分。 -- \(K\):Token 或估算成本分。 -- \(G\):AI 辅助生成申请比例分。 -- \(O\):AI 建议被人工覆盖分。 -- \(E\):AI 调用失败或低置信度分。 - -Token 口径必须进入 `metrics_json`: - -```text -exact_token_count 真实记录 -estimated_token_count 按文本长度估算 -unavailable 当前入口不可用 -``` - -### 7.5 审批行为画像 - -审批行为画像用于流程治理,不用于评价申请人的费用合理性。 - -$$ -approval\_behavior\_score = -0.20L + 0.20S + 0.20P + 0.20Q + 0.20V -$$ - -变量定义: - -- \(L\):平均审核时长分。 -- \(S\):SLA 超时分。 -- \(P\):直接通过率异常分。 -- \(Q\):高风险单据通过率分。 -- \(V\):系统建议被覆盖分。 - -### 7.6 审批优先级分 - -审批详情只使用费用支出和流程质量形成优先级,不引入 AI 协作强度。 - -$$ -review\_priority\_score = -clip(0.70 \times expense\_profile\_score + -0.30 \times process\_quality\_score, 0, 100) -$$ - -等级映射: - -$$ -level(s)= -\begin{cases} -normal, & 0 \le s < 40 \\ -watch, & 40 \le s < 60 \\ -review, & 60 \le s < 80 \\ -escalation, & 80 \le s \le 100 -\end{cases} -$$ - -### 7.7 审核建议公式 - -系统建议只能作为复核提示,不自动改写申请单。 - -差旅天数建议上限: - -$$ -recommended\_days\_upper = -min(requested\_days,\ P_{75}^{peer\_days} \times factor(level)) -$$ - -业务招待人均金额建议上限: - -$$ -recommended\_entertainment\_unit\_upper = -min(policy\_limit,\ P_{75}^{peer\_unit\_amount} \times factor(level)) -$$ - -其中: - -$$ -factor(level)= -\begin{cases} -1.20, & normal \\ -1.10, & watch \\ -1.00, & review \\ -0.90, & escalation -\end{cases} -$$ - -如果当前申请本身有充分业务依据,审核者可以覆盖系统建议。覆盖原因应进入后续流程治理指标。 - -### 7.8 目标员工集合 - -第一版不计算全员。每次 Hermes 扫描目标集合为: - -$$ -target\_employees = -E_{claims180} \cup E_{pending} \cup E_{previous\_attention} \cup E_{ops\_threshold} -$$ - -变量定义: - -- \(E_{claims180}\):近 180 天有费用申请的员工。 -- \(E_{pending}\):当前有待审费用申请的员工。 -- \(E_{previous\_attention}\):上一期画像等级为 watch、review 或 escalation 的员工。 -- \(E_{ops\_threshold}\):AI 使用或审批行为达到运营关注阈值的员工。 - -### 7.9 用户画像标签体系 - -标签用于把复杂指标转成直观特征。标签不是永久评价,也不是处罚依据;它只表示员工在某个时间窗口、某个同组基准下呈现出的行为特征。 - -前端可以展示两层文案: - -- `label`:内部或分析侧标签,例如“费用之王”“急速审核员”。 -- `display_label`:审批详情默认展示文案,例如“费用集中度高”“快速审核型”。 - -标签输出结构建议: - -```json -{ - "code": "expense_king", - "label": "费用之王", - "display_label": "费用集中度高", - "category": "expense", - "polarity": "risk", - "score": 86, - "confidence": 0.82, - "window_days": 90, - "reason": "近90天费用总额达到同组P90,且部门费用占比为34%", - "evidence": [ - {"metric": "amount_total", "value": 128000, "peer_p90": 76000, "unit": "元"}, - {"metric": "amount_share", "value": 0.34, "threshold": 0.30, "unit": "比例"} - ], - "radar_dimensions": ["expense_intensity"] -} -``` - -#### 7.9.1 通用标签打分 - -标签触发后仍然需要计算强度和置信度,避免一个边界值把员工直接贴成强标签。 - -$$ -tag\_score = -clip(100 \times (0.55S + 0.25C + 0.20R), 0, 100) -$$ - -$$ -confidence = -clip(DQ \times (0.65S + 0.20SR + 0.15C), 0, 1) -$$ - -变量定义: - -- \(S\):指标强度,表示当前指标超过阈值或同组分位数的程度。 -- \(C\):持续性,30 / 90 / 180 天三个窗口中命中的窗口比例。 -- \(R\):近期性,最近一次命中距今天数越近分越高。 -- \(DQ\):数据质量,字段完整、样本充足、无估算时更高。 -- \(SR\):样本可靠性,同组样本量越大越可靠。 - -标签展示阈值: - -$$ -active(tag)= -\begin{cases} -true, & tag\_score \ge 60 \land confidence \ge 0.55 \\ -false, & otherwise -\end{cases} -$$ - -强标签阈值: - -$$ -strong(tag)=tag\_score \ge 80 \land confidence \ge 0.75 -$$ - -常用强度函数: - -$$ -peerHigh(x)=clip\left(\frac{x-P_{75}}{P_{90}-P_{75}}, 0, 1\right) -$$ - -$$ -band(x,t_{low},t_{high})=clip\left(\frac{x-t_{low}}{t_{high}-t_{low}}, 0, 1\right) -$$ - -$$ -recent(days)=clip\left(1-\frac{days}{90}, 0, 1\right) -$$ - -#### 7.9.2 第一版候选标签清单 - -以下标签均需要写入触发依据、窗口期、同组样本量和 fallback 层级。审批详情默认只展示与当前单据相关的前 3 到 6 个标签;运营看板可展示完整标签。 - -| 类别 | code / 标签 | 默认展示文案 | 量化触发条件 | 雷达维度 | -| --- | --- | --- | --- | --- | -| 费用支出 | `expense_king` / 费用之王 | 费用集中度高 | \(amount\_total_{90} \ge P90(amount\_total)\) 且 \(amount\_share_{90} \ge 0.30\)。强度 \(S=max(peerHigh(amount\_total), band(amount\_share,0.15,0.45))\)。 | 费用强度 | -| 费用支出 | `high_frequency_applicant` / 高频申请人 | 申请频次高 | \(claim\_count_{90} \ge P90(claim\_count)\),且申请次数不少于 3 次。强度 \(S=peerHigh(claim\_count)\)。 | 申请节奏 | -| 费用支出 | `micro_high_frequency` / 小额高频 | 小额高频 | \(claim\_count_{90} \ge P90(claim\_count)\) 且 \(avg\_amount_{90} \le P50(avg\_amount)\)。 | 申请节奏 | -| 费用支出 | `large_amount_deviation` / 大额偏离者 | 当前金额偏高 | \(current\_amount \ge P90(claim\_amount)\) 或 \(amount\_total_{90} \ge P90(amount\_total)\)。 | 费用强度 | -| 费用支出 | `budget_sprint` / 预算冲刺型 | 近期费用集中 | \(amount_{30}/amount_{90} \ge 0.55\) 且 \(amount_{30} \ge P75(amount_{30})\)。 | 费用强度 | -| 费用支出 | `cost_controlled` / 成本克制型 | 成本克制 | \(amount\_total_{90} \le P50(amount\_total)\),\(claim\_count_{90} \ge P50(claim\_count)\),且退单次数为 0。该标签为正向标签。 | 费用强度 | -| 费用支出 | `adjustment_frequent` / 调减高发 | 历史调减较多 | \(adjustment\_count_{90} \ge P90(adjustment\_count)\) 或 \(adjusted\_amount/claimed\_amount \ge 0.20\)。 | 流程压力 | -| 费用支出 | `expense_type_wide` / 费用类型跨度大 | 费用类型分散 | \(distinct\_expense\_types_{90} \ge P75(distinct\_expense\_types)\) 且费用类型熵 \(entropy \ge 0.60\)。 | 申请节奏 | -| 差旅招待 | `long_trip_master` / 长差达人 | 出差天数偏长 | \(current\_travel\_days \ge 1.5 \times P75(peer\_days)\) 或 \(travel\_days_{90} \ge P90(travel\_days)\)。 | 差旅招待 | -| 差旅招待 | `travel_frequent` / 出差高频客 | 出差频次高 | \(travel\_claim\_count_{90} \ge P90(travel\_claim\_count)\)。 | 差旅招待 | -| 差旅招待 | `travel_daily_high` / 差旅日均偏高 | 差旅日均偏高 | \(travel\_amount_{90}/max(travel\_days_{90},1) \ge P90(travel\_daily\_amount)\)。 | 差旅招待 | -| 差旅招待 | `hotel_high_standard` / 住宿标准偏高 | 住宿单价偏高 | \(hotel\_amount/max(hotel\_nights,1) \ge P90(peer\_hotel\_nightly)\) 或超过制度住宿标准。 | 差旅招待 | -| 差旅招待 | `transport_high_cost` / 交通成本偏高 | 交通成本偏高 | \((flight+train+ride)_{90}/max(travel\_days_{90},1) \ge P90(peer\_transport\_daily)\)。 | 差旅招待 | -| 差旅招待 | `entertainment_active` / 招待活跃户 | 招待频次高 | \(entertainment\_count_{90} \ge P90(entertainment\_count)\) 或 \(entertainment\_amount_{90} \ge P90(entertainment\_amount)\)。 | 差旅招待 | -| 差旅招待 | `entertainment_unit_high` / 人均招待偏高 | 人均招待偏高 | \(unit\_amount \ge P75(peer\_unit\_amount)\),且 \(unit\_amount\) 超过制度标准或同组 P90。 | 差旅招待 | -| 差旅招待 | `repeat_client_host` / 重复客户招待高 | 同客户招待集中 | \(max(client\_entertainment\_count_{90}) \ge 3\) 或达到同组 P90。客户无法结构化时降级为“客户线索不足”。 | 差旅招待 | -| 差旅招待 | `holiday_expense_active` / 节假日费用活跃 | 节假日费用活跃 | \(holiday\_claim\_ratio_{90} \ge P75(holiday\_claim\_ratio)\),且节假日申请不少于 2 次。 | 申请节奏 | -| 流程质量 | `return_frequent` / 退单常客 | 退单频次高 | \(return\_count_{90} \ge 2\) 或 \(return\_rate_{90} \ge 0.30\),且达到同组 P75。 | 流程压力 | -| 流程质量 | `material_patch` / 材料补丁户 | 材料补充较多 | \(missing\_attachment + missing\_context \ge 3\) 或达到同组 P90。 | 材料完整度 | -| 流程质量 | `invoice_unstable` / 票据不稳 | 票据一致性弱 | \(invoice\_mismatch\_count_{90} \ge 1\) 或票据异常次数达到同组 P75。 | 材料完整度 | -| 流程质量 | `reason_thin` / 事由空心化 | 事由说明偏弱 | 空事由、模板化事由或少于最小字数的事由占比 \(\ge 0.40\)。 | 材料完整度 | -| 流程质量 | `resubmit_slow` / 补充材料慢 | 补充响应偏慢 | \(avg\_resubmit\_hours_{90} \ge P75(avg\_resubmit\_hours)\) 或超过 SLA。 | 流程压力 | -| 流程质量 | `repeat_issue` / 重复问题未改善 | 同类问题反复 | 同一问题编码在 90 天内出现 \(\ge 2\) 次,且 30 天内仍出现。 | 流程压力 | -| 流程质量 | `clean_first_pass` / 材料清爽 | 一次通过质量好 | \(first\_pass\_rate_{90} \ge 0.90\),附件缺失为 0,票据不一致为 0。该标签为正向标签。 | 材料完整度 | -| 流程质量 | `large_return_amount` / 高额退回 | 退回金额偏高 | \(returned\_amount_{90} \ge P90(returned\_amount)\) 或 \(returned\_amount/claimed\_amount \ge 0.20\)。 | 流程压力 | -| AI 协作 | `ai_heavy` / AI 重度用户 | AI 使用频繁 | \(ai\_run\_count_{90} \ge P90(ai\_run\_count)\)。 | AI 协作 | -| AI 协作 | `token_high` / Token 高耗用户 | Token 消耗较高 | \(token\_count_{90} \ge P90(token\_count)\)。估算 Token 必须标记 `estimated`,不得当作真实成本。 | AI 协作 | -| AI 协作 | `ai_effective` / AI 高效协作者 | AI 协作有效 | \(ai\_run\_count_{90} \ge P75(ai\_run\_count)\),且 \(first\_pass\_rate_{90} \ge 0.85\),流程质量分低于 40。该标签为正向标签。 | AI 协作 | -| AI 协作 | `ai_dependency_unimproved` / AI 依赖未改善 | AI 使用高但质量未改善 | \(ai\_run\_count_{90} \ge P75(ai\_run\_count)\),且流程质量分 \(\ge 60\) 或退单率未下降。 | AI 协作 | -| AI 协作 | `ai_failure_cluster` / AI 调用失败集中 | AI 调用失败偏多 | \(failed\_tool\_call\_rate_{90} \ge 0.20\) 或失败次数达到同组 P90。 | AI 协作 | -| AI 协作 | `ai_override_frequent` / AI 建议常被覆盖 | AI 建议覆盖较多 | \(override\_rate_{90} \ge 0.40\) 或覆盖次数达到同组 P75。无结构化覆盖字段时不触发。 | AI 协作 | -| 审批行为 | `speed_reviewer` / 急速审核员 | 快速审核型 | \(avg\_review\_duration \le P10(avg\_review\_duration)\),且直接通过率 \(\ge 0.90\)。该标签为行为型,不默认视为风险。 | 审批效率 | -| 审批行为 | `cautious_reviewer` / 谨慎审核员 | 谨慎审核型 | \(avg\_review\_duration \ge P75(avg\_review\_duration)\),且退回率达到同组 P75。 | 审批把关 | -| 审批行为 | `gatekeeper` / 退回把关型 | 退回把关强 | \(return\_rate \ge P75(return\_rate)\),且高风险单据退回率达到同组 P75。 | 审批把关 | -| 审批行为 | `high_risk_fast_pass` / 高风险快通过 | 高风险快通过 | 高风险单据直接通过次数 \(\ge 1\),且该类单据平均审核时长 \(\le P25\)。 | 审批效率 | -| 审批行为 | `sla_delayer` / SLA 拖延型 | 审批超时偏多 | \(sla\_overdue\_count_{90} \ge P75(sla\_overdue\_count)\) 或 SLA 超时率 \(\ge 0.25\)。 | 审批效率 | -| 审批行为 | `steady_reviewer` / 稳健审核员 | 稳健审核型 | 审核时长在 P25 到 P75,退回率在 P25 到 P75,高风险快通过为 0。该标签为正向标签。 | 审批把关 | - -### 7.10 行为雷达图 - -雷达图用于表达“行为结构”,不是单一风险分。第一版建议 8 个维度,每个维度 0 到 100 分。 - -$$ -radarScore_d = clip\left(\frac{\sum_{i=1}^{n}w_i component_i}{\sum_{i=1}^{n}w_i}, 0, 100\right) -$$ - -维度定义: - -| 维度 code | 展示名称 | 计算来源 | 含义 | -| --- | --- | --- | --- | -| `expense_intensity` | 费用强度 | 预算占用、同组金额偏离、当前单据偏离、费用之王、大额偏离者 | 分数越高,费用金额和预算占用越突出。 | -| `application_rhythm` | 申请节奏 | 申请频次、小额高频、费用类型跨度、近期费用集中 | 分数越高,申请节奏越密集或集中。 | -| `travel_entertainment` | 差旅招待 | 出差天数、差旅日均、住宿单价、交通成本、招待频次、人均招待 | 分数越高,差旅或招待行为越活跃。 | -| `material_completeness` | 材料完整度压力 | 附件缺失、票据不一致、事由空心化、重复问题 | 分数越高,材料质量越需要关注。 | -| `process_pressure` | 流程压力 | 退单、调减、高额退回、补充材料耗时 | 分数越高,流程返工和沟通成本越高。 | -| `ai_collaboration` | AI 协作强度 | AI 调用、Token、失败率、覆盖率、AI 高效或未改善标签 | 分数越高,AI 参与度越高;不等同费用风险。 | -| `approval_efficiency` | 审批效率特征 | 平均审核时长、急速审核、SLA 超时、高风险快通过 | 分数越高,表示审批速度或时效特征越明显。 | -| `approval_control` | 审批把关特征 | 退回率、高风险退回率、谨慎审核、稳健审核 | 分数越高,表示审批把关或复核行为越明显。 | - -审批详情默认雷达图建议展示前 5 个维度: - -```text -费用强度 / 申请节奏 / 差旅招待 / 材料完整度压力 / 流程压力 -``` - -AI 协作、审批效率和审批把关默认放在运营视图或管理员视图中展示。审批详情如需展示,必须明确标注“不参与费用风险裁决”。 - -个人工作台的用户画像详情允许在行为雷达右上角提供视角切换,避免把不同性质的指标混成单一结论: - -- `financial_risk` / 财务风险视角:默认面向普通员工画像,展示费用强度、申请节奏、差旅招待、材料完整度压力、流程压力。 -- `collaboration_governance` / 协作治理视角:展示 AI 协作强度、审批效率特征、审批把关特征,用于管理员或运营人员查看系统协作和流程治理行为。 -- `all_behavior` / 全部行为视角:展示全部雷达维度,满足用户查看完整操作和行为细节的需求。 - -切换只改变雷达图可视维度和雷达下方的行为标签过滤结果,不改变后端画像快照、上方画像标签总列表、标签证据和审批优先级分。审批详情的“风险审核画像”仍默认只展示费用审核相关维度。 - -## 8. 测试方案 - -- 单元测试:覆盖归一化、同组降级、四类画像评分、等级映射、审核建议生成。 -- 标签算法测试:覆盖 36 个候选标签的触发、未触发、强标签、置信度和数据质量降级。 -- 雷达图测试:覆盖 8 个雷达维度的维度分、等级映射和 top tags 关联。 -- 数据服务测试:覆盖费用、审批、Agent、Hermes 数据缺失时的降级逻辑。 -- API 测试:覆盖审批场景读取最新画像、权限过滤、无画像时的空态。 -- Hermes 测试:覆盖任务配置初始化、任务分发、执行日志成功和失败状态。 -- 前端测试:覆盖“风险审核画像”卡片的正常态、空态、标签展示、雷达图展示、证据展开和权限隐藏。 -- 回归测试:确保 AI 协作强度不进入审批优先级分。 -- 手工验证:用包含差旅、招待、退单、AI 调用的样例员工验证卡片展示是否可解释。 - -后端测试优先在 Docker 容器中执行: - -```bash -docker exec x-financial-main bash -lc "cd /app && timeout 60s /tmp/x-financial-server-venv/bin/python -m pytest server/tests/test_employee_behavior_profile_algorithm.py -q" -``` - -## 9. 指标与验收 - -- 能为目标员工生成 30 / 90 / 180 天窗口画像快照。 -- 快照包含 `profile_type`、`profile_score`、`profile_level`、`metrics_json`、`basis_codes_json`、`source_task_log_id` 和 `algorithm_version`。 -- 快照或最新画像响应包含 `profile_tags`,每个标签必须包含 `code`、`label`、`display_label`、`score`、`confidence`、`reason` 和 `evidence`。 -- 最新画像响应包含 `radar.dimensions`,每个维度必须包含 `code`、`label`、`score`、`level` 和 `top_tags`。 -- 每个标签都有实际量化触发条件,不能只靠文字描述或 LLM 判断。 -- 审批详情默认展示不超过 6 个标签,优先展示与当前单据相关且置信度最高的标签。 -- 雷达图默认展示费用审核相关维度,AI 和审批人行为维度不参与申请人费用风险裁决。 -- 同一输入和同一算法版本下,评分结果可重复。 -- 同组样本不足时有明确 fallback 记录。 -- Token 统计明确区分真实、估算和不可用,不把估算值包装成真实计费数据。 -- 审批详情卡片只默认展示申请人费用画像和流程质量画像。 -- AI 协作强度不进入 `review_priority_score`。 -- Hermes 任务执行后能写入执行日志、结果摘要和失败堆栈。 -- 后端定向单元测试在 60 秒内通过。 -- 前端构建或相关测试通过,且卡片在无画像时有稳定空态。 - -## 10. 风险与开放问题 - -- Token 采集可能并不完整,需要先确认各 AI 入口是否真实记录 Token。 -- 审批开始时间、完成时间、退单原因、补充材料事件可能还不够结构化。 -- 当前 Hermes 调度器对频率的执行能力需要核对;如只支持近似每日触发,需要在现有调度器内增强。 -- 同组样本量不足时,分位数容易失真,需要展示样本量和 fallback 层级。 -- 审批详情中的画像语言要克制,避免把治理建议变成员工标签。 -- 标签名称需要区分内部分析文案和前端默认展示文案,避免“费用之王”等趣味标签在审批场景造成压迫感。 -- 雷达图维度不能混淆“行为强度”和“风险结论”;AI 使用强度、审批速度特征必须单独解释。 -- 正向标签和风险标签需要同时存在,否则画像容易变成单向负面评价。 -- 画像快照可能增长较快,需要后续定义保留周期和归档策略。 -- 业务招待中的客户、用户或项目标识需要数据标准化,否则重复招待次数难以准确统计。 diff --git a/document/development/employee-behavior-profile/TODO.md b/document/development/employee-behavior-profile/TODO.md deleted file mode 100644 index dbf6762..0000000 --- a/document/development/employee-behavior-profile/TODO.md +++ /dev/null @@ -1,153 +0,0 @@ -# 员工业务行为画像开发 TODO - -## 使用规则 - -- 每个 TODO 完成并经过对应验证后,才允许把 `[ ]` 改为 `[x]`。 -- 勾选时需要在任务后补一句证据,例如文件、接口、测试命令或验证结果。 -- 如果实现过程中发现需求变化,先更新 `CONCEPT.md`,再调整本文件。 -- 后端验证优先在 Docker 容器 `x-financial-main` 的 `/app` 下执行,并为测试设置 60 秒超时。 - -## 阶段 1:调研与边界 - -- [x] 确认文档技能要求,产物拆为 `CONCEPT.md` 与 `TODO.md`。[CONCEPT: 全文] 证据:已使用 `feature-development-docs` 技能建立本目录文档。 -- [x] 初步确认现有 Agent 指标来源。[CONCEPT: 背景与问题] 证据:`server/src/app/models/agent_run.py` 已有 `AgentRun`、`AgentToolCall`、`SemanticParseLog`。 -- [x] 初步确认现有 Hermes 任务基础。[CONCEPT: 方案设计] 证据:`HermesTaskConfig`、`HermesTaskExecutionLog`、`HermesScheduler` 已存在。 -- [x] 盘点费用申请、费用明细、审批记录中可直接用于画像的字段。[CONCEPT: 功能能力] 证据:`employee_behavior_profile_service.py` 聚合 `ExpenseClaim`、`ExpenseClaimItem`、`ApprovalRecord`。 -- [x] 盘点当前所有 AI 入口的 Token 记录情况,标记真实、估算和不可用。[CONCEPT: 算法与公式] 证据:`employee_behavior_profile_service.py` 在 AI 画像中写入 `token_count_mode`、`estimated_token_count`、`exact_token_count`。 -- [x] 确认审批详情页当前组件入口和数据加载方式。[CONCEPT: 前端展示] 证据:`TravelRequestDetailView.js` 读取画像 API,`TravelRequestDetailView.vue` 挂载画像卡片。 -- [x] 确认 Hermes 设置页是否需要展示“员工画像巡检”任务。[CONCEPT: Hermes 接入] 证据:`hermesEmployeeSettingsModel.js` 新增 `employee_behavior_profile_scan`。 - -## 阶段 2:契约设计 - -- [x] 定义画像快照模型字段和 JSON 结构。[CONCEPT: 数据模型] 证据:`employee_behavior_profile.py` ORM 模型。 -- [x] 定义 `GET /api/v1/employee-profiles/{employee_id}/latest` 响应契约。[CONCEPT: API 契约] 证据:`employee_profile.py` 和 `employee_profiles.py`。 -- [x] 定义审批详情场景下的权限过滤规则。[CONCEPT: 权限和边界] 证据:审批场景 API 仅返回 `expense` 与 `process_quality`。 -- [x] 定义 Hermes 任务结果摘要结构。[CONCEPT: Hermes 接入] 证据:`hermes_scheduler.py` 写入画像巡检摘要。 -- [x] 定义 `basis_codes_json` 的贡献项编码和展示文案。[CONCEPT: 审批详情卡片] 证据:算法 `ProfileComponent` 与服务写入 top contributors。 -- [x] 定义无画像、样本不足、指标缺失时的空态协议。[CONCEPT: 指标与验收] 证据:`EmployeeProfileLatestRead.empty_reason` 和卡片空态。 - -## 阶段 3:数据与持久化 - -- [x] 新增 `employee_behavior_profile_snapshots` ORM 模型。[CONCEPT: 数据模型] 证据:`server/src/app/models/employee_behavior_profile.py`。 -- [x] 将新模型加入 `server/src/app/models/__init__.py` 和 `db/base.py`。[CONCEPT: 数据模型] 证据:两个入口已导入 `EmployeeBehaviorProfileSnapshot`。 -- [x] 补充数据库迁移或项目当前等价建表流程。[CONCEPT: 数据模型] 证据:`EmployeeBehaviorProfileService.ensure_storage_ready()` 使用 `Base.metadata.create_all` 创建快照表。 -- [x] 为 `metrics_json` 写入 Token 口径字段。[CONCEPT: AI 协作画像] 证据:AI 画像 metrics 写入 `token_count_mode`。 -- [x] 为快照写入 `algorithm_version`、`source_task_type`、`source_task_log_id`。[CONCEPT: 数据模型] 证据:快照模型和服务写入三项字段。 -- [x] 增加最新画像查询索引,至少覆盖员工、画像类型、窗口期和计算时间。[CONCEPT: 指标与验收] 证据:`ix_employee_behavior_profile_latest`。 - -## 阶段 4:算法实现 - -- [x] 在 `server/src/app/algorithem` 新增员工画像算法模块。[CONCEPT: 后端服务] 证据:`employee_behavior_profile.py`。 -- [x] 实现同组分位数归一化函数。[CONCEPT: 通用归一化] 证据:`normalize_by_peer_percentiles()`。 -- [x] 实现同组样本不足 fallback 逻辑。[CONCEPT: 通用归一化] 证据:`_resolve_peer_claims()` 写入 fallback level。 -- [x] 实现费用支出画像评分。[CONCEPT: 费用支出画像] 证据:`_calculate_expense_profile()`。 -- [x] 实现流程质量画像评分。[CONCEPT: 流程质量画像] 证据:`_calculate_process_quality_profile()`。 -- [x] 实现 AI 协作强度评分。[CONCEPT: AI 协作画像] 证据:`_calculate_ai_usage_profile()`。 -- [x] 实现审批行为画像评分。[CONCEPT: 审批行为画像] 证据:`_calculate_approval_behavior_profile()`。 -- [x] 实现审批优先级分,确保不引入 AI 协作强度。[CONCEPT: 审批优先级分] 证据:`calculate_review_priority_score()` 测试通过。 -- [x] 实现差旅天数和招待人均金额的建议上限计算。[CONCEPT: 审核建议公式] 证据:`build_review_suggestions()` 测试通过。 -- [x] 实现 top contributors 贡献项提取。[CONCEPT: 审批详情卡片] 证据:`ProfileScoreResult.top_contributors()`。 - -## 阶段 5:后端服务 - -- [x] 新增画像数据抽取服务,聚合费用、审批、Agent 和 Hermes 指标。[CONCEPT: 后端服务] 证据:`employee_behavior_profile_service.py`。 -- [x] 新增画像应用服务,负责目标员工筛选、算法调用和快照写入。[CONCEPT: 目标员工集合] 证据:`scan_profiles()` 和 `refresh_employee_profiles()`。 -- [x] 实现最新画像查询服务。[CONCEPT: API 契约] 证据:`get_latest_profile()`。 -- [x] 实现审批场景画像 DTO,过滤 AI 和审批人治理指标。[CONCEPT: 权限和边界] 证据:审批场景响应只包含两类画像。 -- [x] 实现无画像时的空态响应。[CONCEPT: API 契约] 证据:`empty_reason`。 -- [x] 增加 API 路由并接入权限依赖。[CONCEPT: API 契约] 证据:`employee_profiles.py` 使用 `get_current_user`。 - -## 阶段 6:Hermes 接入 - -- [x] 新增 `employee_behavior_profile_scan` 任务类型常量或分发分支。[CONCEPT: Hermes 接入] 证据:`hermes_scheduler.py` 分发分支。 -- [x] 在现有 `HermesScheduler._execute_task()` 中接入画像扫描服务。[CONCEPT: Hermes 接入] 证据:`HermesEmployeeProfileScannerService`。 -- [x] 在 `start_hermes_daemon.py` 初始化画像任务配置。[CONCEPT: Hermes 接入] 证据:默认 cron `0 8 * * 1` 且默认关闭。 -- [x] 在设置服务中补齐画像任务的 capabilities 和 schedules 读写。[CONCEPT: Hermes 接入] 证据:`settings.py` 按周任务写入 cron。 -- [x] 在 `hermesEmployeeSettingsModel.js` 增加“员工画像巡检”配置项。[CONCEPT: Hermes 接入] 证据:前端设置项已新增。 -- [x] 核对现有调度器的 frequency / weekday / time 是否真实生效;如不足,在现有调度器内增强,不新增调度器。[CONCEPT: Hermes 接入] 证据:`HermesScheduler._parse_simple_cron()` 与 `_resolve_last_scheduled_at()`,测试覆盖周任务解析。 -- [x] 确认画像任务默认频率,推荐每周全量,待审员工轻量增量。[CONCEPT: Hermes 接入] 证据:默认配置为每周一 08:00,任务默认关闭,扫描目标集非全员。 - -## 阶段 7:前端展示 - -- [x] 定位费用审批详情页的数据加载和卡片布局入口。[CONCEPT: 前端展示] 证据:`TravelRequestDetailView.js` 与 `TravelRequestDetailView.vue`。 -- [x] 新增“风险审核画像”卡片组件。[CONCEPT: 审批详情卡片] 证据:`EmployeeProfileRiskCard.vue`。 -- [x] 展示画像等级、窗口期、同组基准和更新时间。[CONCEPT: 审批详情卡片] 证据:卡片 summary 区域。 -- [x] 展示费用支出和流程质量指标分组。[CONCEPT: 审批详情卡片] 证据:审批场景 API 和卡片 profile list。 -- [x] 展示审核建议和证据展开。[CONCEPT: 审批详情卡片] 证据:卡片 contributors 与 suggestions 区域。 -- [x] 实现无画像、样本不足、计算中和接口失败状态。[CONCEPT: 指标与验收] 证据:卡片 loading、error、empty state。 -- [x] 按权限隐藏 AI 协作画像和审批行为画像。[CONCEPT: 权限和边界] 证据:审批场景后端只返回费用支出与流程质量。 -- [x] 保持企业费用审核界面密度,避免卡片过高或营销式视觉。[CONCEPT: 前端展示] 证据:`EmployeeProfileRiskCard.vue` 使用紧凑指标格与证据列表。 - -## 阶段 8:测试 - -- [x] 新增算法单元测试:归一化、fallback、评分和等级映射。[CONCEPT: 测试方案] 证据:`test_employee_behavior_profile_algorithm.py`。 -- [x] 新增审核建议单元测试:差旅天数和招待人均金额建议上限。[CONCEPT: 审核建议公式] 证据:`test_review_suggestions_generate_caps_without_auto_penalty`。 -- [x] 新增回归测试:AI 协作强度不得进入审批优先级分。[CONCEPT: 审批优先级分] 证据:`test_review_priority_excludes_ai_usage_score`。 -- [x] 新增服务测试:目标员工集合和快照写入。[CONCEPT: 目标员工集合] 证据:`test_service_scans_snapshots_and_filters_approval_scene`。 -- [x] 新增 API 测试:最新画像查询、权限过滤和空态。[CONCEPT: API 契约] 证据:`test_latest_profile_endpoint_returns_approval_payload`。 -- [x] 新增 Hermes 测试:任务分发、成功日志和失败日志。[CONCEPT: Hermes 接入] 证据:Hermes 扫描服务测试覆盖快照写入,调度 cron 解析测试覆盖周任务。 -- [x] 新增前端测试或构建验证:画像卡片正常渲染。[CONCEPT: 前端展示] 证据:`npm --prefix web run build` 通过。 - -建议后端定向验证命令: - -```bash -docker exec x-financial-main bash -lc "cd /app && timeout 60s /tmp/x-financial-server-venv/bin/python -m pytest server/tests/test_employee_behavior_profile_algorithm.py -q" -``` - -建议 Hermes 定向验证命令: - -```bash -docker exec x-financial-main bash -lc "cd /app && timeout 60s /tmp/x-financial-server-venv/bin/python -m pytest server/tests/test_hermes_employee_profile_scanner.py -q" -``` - -建议前端构建验证命令: - -```bash -docker exec x-financial-main bash -lc "cd /app && timeout 60s npm --prefix web run build" -``` - -## 阶段 9:文档 - -- [x] 建立员工业务行为画像概念文档。[CONCEPT: 全文] 证据:`document/development/employee-behavior-profile/CONCEPT.md`。 -- [x] 建立员工业务行为画像开发 TODO。[CONCEPT: 全文] 证据:`document/development/employee-behavior-profile/TODO.md`。 -- [x] 开发完成后回填已实现 API、模型和测试命令。[CONCEPT: 指标与验收] 证据:后端 pytest 7 passed,ruff passed,前端 build passed。 -- [ ] 开发完成后补充前端截图或交互验证说明。[CONCEPT: 指标与验收] - -## 阶段 10:验收 - -- [x] 验收时确认画像用于审核建议,不用于自动处罚或自动降标。[CONCEPT: 非目标] 证据:API 仅返回 `review_suggestions`,不改写费用单。 -- [x] 验收时确认 Token 估算值有明确标识。[CONCEPT: 指标与验收] 证据:AI 画像写入 `token_count_mode=estimated_token_count/unavailable`。 -- [x] 验收时确认 Hermes 没有新增独立调度器。[CONCEPT: Hermes 接入] 证据:仅改造 `HermesScheduler` 分发和 cron 判断。 - -## 阶段 11:画像标签与雷达图扩展 - -- [x] 在原概念文档中增补标签体系、量化规则和雷达图设计,不新建独立功能目录。[CONCEPT: 用户画像标签体系] 证据:`CONCEPT.md` 新增 7.9 和 7.10。 -- [x] 定义后端标签 DTO 和雷达图 DTO,字段包含 `code`、`label`、`display_label`、`score`、`confidence`、`reason`、`evidence`、`radar_dimensions`。[CONCEPT: 用户画像标签体系] 证据:`employee_profile.py` 新增 `EmployeeProfileTagRead`、`EmployeeProfileRadarRead`。 -- [x] 在算法层新增标签计算模块,建议拆为 `employee_behavior_profile_tags.py`,避免继续扩大主画像算法模块。[CONCEPT: 用户画像标签体系] 证据:新增 `employee_behavior_profile_tags.py` 与 `employee_behavior_profile_tag_rules.py`,单文件均小于 800 行。 -- [x] 实现标签通用强度、持续性、近期性、数据质量和样本可靠性计算函数。[CONCEPT: 通用标签打分] 证据:`employee_behavior_profile_tag_rules.py` 中 `add_tag()`、`data_quality()`、`band()`。 -- [x] 实现费用支出类标签:费用之王、高频申请人、小额高频、大额偏离者、预算冲刺型、成本克制型、调减高发、费用类型跨度大。[CONCEPT: 第一版候选标签清单] 证据:`append_expense_tags()`。 -- [x] 实现差旅招待类标签:长差达人、出差高频客、差旅日均偏高、住宿标准偏高、交通成本偏高、招待活跃户、人均招待偏高、重复客户招待高、节假日费用活跃。[CONCEPT: 第一版候选标签清单] 证据:`append_travel_entertainment_tags()`。 -- [x] 实现流程质量类标签:退单常客、材料补丁户、票据不稳、事由空心化、补充材料慢、重复问题未改善、材料清爽、高额退回。[CONCEPT: 第一版候选标签清单] 证据:`append_process_tags()`。 -- [x] 实现 AI 协作类标签:AI 重度用户、Token 高耗用户、AI 高效协作者、AI 依赖未改善、AI 调用失败集中、AI 建议常被覆盖。[CONCEPT: 第一版候选标签清单] 证据:`append_ai_tags()`。 -- [x] 实现审批行为类标签:急速审核员、谨慎审核员、退回把关型、高风险快通过、SLA 拖延型、稳健审核员。[CONCEPT: 第一版候选标签清单] 证据:`append_approval_tags()`。 -- [x] 实现雷达图 8 个维度计算,并把 top tags 关联到对应维度。[CONCEPT: 行为雷达图] 证据:`build_profile_radar()`。 -- [x] 将标签和雷达图写入快照或最新画像响应;若不改表,第一版可落入 `metrics_json`,但 API 必须输出结构化字段。[CONCEPT: 数据模型] 证据:第一版不改表,由 `EmployeeBehaviorProfileService._serialize_latest_profile()` 输出结构化 `profile_tags` 与 `radar`。 -- [x] 更新 `GET /api/v1/employee-profiles/{employee_id}/latest` 响应 schema,返回 `profile_tags` 和 `radar`。[CONCEPT: API 契约] 证据:`EmployeeProfileLatestRead` 已新增字段。 -- [x] 审批详情“风险审核画像”卡片增加标签区,默认展示 3 到 6 个与当前单据相关的高置信标签。[CONCEPT: 审批详情卡片] 证据:`EmployeeProfileRiskCard.vue` 新增 `employee-risk-tags` 区域。 -- [x] 审批详情卡片增加雷达图展示,默认展示费用强度、申请节奏、差旅招待、材料完整度压力、流程压力。[CONCEPT: 行为雷达图] 证据:`EmployeeProfileRiskCard.vue` 新增 SVG 雷达图。 -- [ ] 管理员或运营视图再展示 AI 协作、审批效率、审批把关维度,审批详情不把它们混入费用风险裁决。[CONCEPT: 权限和边界] -- [x] 新增标签算法单元测试,覆盖每类标签的触发、未触发、强标签和置信度降级。[CONCEPT: 测试方案] 证据:`test_profile_tags_and_approval_radar_use_quantified_evidence`、`test_profile_tags_include_ai_and_approval_traits_outside_approval_scene`。 -- [x] 新增雷达图算法单元测试,覆盖 8 个维度、维度等级和 top tags 关联。[CONCEPT: 测试方案] 证据:算法测试断言审批场景 5 维、运营场景 8 维。 -- [x] 新增 API 测试,确认最新画像响应包含标签和雷达图,且审批场景权限过滤正确。[CONCEPT: API 契约] 证据:`test_latest_profile_endpoint_returns_approval_payload` 已断言 `profile_tags` 与 `radar`。 -- [x] 新增前端构建或组件测试,确认标签和雷达图在正常态、空态、低样本态下展示稳定。[CONCEPT: 前端展示] 证据:`npm --prefix web run build` 通过。 -- [x] 后端验证在 Docker 容器执行,命令设置 60s 超时。[CONCEPT: 测试方案] 证据:`pytest ... -q` 结果 `9 passed in 6.20s`,Ruff `All checks passed!`。 -- [ ] 前端验证通过后补充截图或交互验证说明,并回勾阶段 9 未完成项。[CONCEPT: 指标与验收] - -## 阶段 12:个人画像雷达视角切换 - -- [x] 在 `CONCEPT.md` 补充个人画像详情的雷达视角切换契约,明确财务风险、协作治理、全部行为三档。[CONCEPT: 行为雷达图] 证据:`CONCEPT.md` 7.10 已补充三档视角和边界。 -- [x] 在个人工作台画像 view model 中定义雷达视角分组和默认视角规则,普通员工默认财务风险,admin/仅 AI 账号默认协作治理。[CONCEPT: 行为雷达图] 证据:`employeeProfileViewModel.js` 新增 `USER_PROFILE_RADAR_VIEW_OPTIONS`、`resolveUserProfileDefaultRadarView()`。 -- [x] 在 `ExpenseProfileDetailModal.vue` 的行为雷达标题右上角增加小型下拉切换,复用 Element Plus 控件。[CONCEPT: 前端展示] 证据:弹窗使用 `ElSelect` / `ElOption` 渲染雷达视角下拉。 -- [x] 切换雷达视角时过滤展示维度和雷达下方行为标签,不改变上方画像标签、核心指标和最近操作列表。[CONCEPT: 权限和边界] 证据:`filterUserProfileRadarDimensions()` 与 `filterUserProfileTagsByRadarView()` 仅作用于雷达区入参。 -- [x] 保持审批详情 `EmployeeProfileRiskCard.vue` 不混入协作治理维度。[CONCEPT: 审批详情卡片] 证据:本次未修改审批详情风险卡片。 -- [x] 运行前端构建,并用浏览器确认个人画像详情的三档切换可用、空态稳定。[CONCEPT: 测试方案] 证据:`npm --prefix web run build` 通过;浏览器验证默认财务风险,可切换协作治理和全部行为,图表高度 360px,底部行为标签随视角过滤。 diff --git a/document/development/expense-control-demo-data/01_finance-rules.md b/document/development/expense-control-demo-data/01_finance-rules.md deleted file mode 100644 index e41f38a..0000000 --- a/document/development/expense-control-demo-data/01_finance-rules.md +++ /dev/null @@ -1,41 +0,0 @@ -# 财务规则表补齐开发记录 - -## 2026-06-05 口径调整 - -用户明确要求业务招待费超过 500 元、大额办公用品以及金额超过 2000 元的费用申请审批要求进入财务规则中心。因此新增《公司费用申请审批规则》作为申请前置和审批阈值的财务规则依据;风险规则负责引用该财务规则并执行命中判断。 - -本次调整不恢复旧的单项《业务招待费报销规则》或《办公用品费报销规则》,而是使用统一规则表维护申请审批阈值,避免规则中心再次出现多个口径型规则表。 - -## 目标 - -财务规则中心只维护真正具备制度标准、且需要按职级/职务或明确人均标准执行的规则表。没有实际金额分档的费用类型,不在财务规则中心单独生成 Excel 表;其额度控制进入预算中心,申请前置和材料完整性进入风险规则。 - -## 本次范围调整 - -- 保留《公司差旅费报销规则》。 -- 保留《公司通信费报销规则》。 -- 删除独立《公司交通住宿费细分规则》,交通/住宿标准统一并入差旅规则。 -- 删除业务招待费、市场推广费、会务费、办公用品费、培训费、软件服务费、福利费这 7 张口径型规则表。 -- 不再为“申请、附件、合同/验收、预算归集口径”单独创建财务规则表。 -- 规则中心中如已存在上述口径型资产,统一标记为废弃规则,不再作为财务规则展示。 - -## 字段口径 - -- 金额标准:只在真实制度表中维护。 -- 职级/职务分档:没有实际标准时不造字段、不造表。 -- 预算额度:进入预算中心和预算执行规则。 -- 申请前置:进入风险规则的申请前置类。 -- 附件/合同/验收:进入风险规则的材料完整性类。 -- 费用类型归类:进入风险规则或本体费用类型映射,不通过财务规则表承载。 - -## 当前交付物 - -- `server/rules/finance-rules/公司差旅费报销规则.xlsx` -- `server/rules/finance-rules/公司通信费报销规则.xlsx` - -## 验证方式 - -- 规则中心只展示真实财务标准表。 -- 被删除的口径型规则资产不会被重新创建。 -- 历史口径型规则资产如已存在,会被同步为 `废弃规则`。 -- 风险规则不再引用已删除的口径型财务规则表 code。 diff --git a/document/development/expense-control-demo-data/02_risk-rules.md b/document/development/expense-control-demo-data/02_risk-rules.md deleted file mode 100644 index fe4644d..0000000 --- a/document/development/expense-control-demo-data/02_risk-rules.md +++ /dev/null @@ -1,43 +0,0 @@ -# 风险规则补齐开发记录 - -## 2026-06-05 口径调整 - -业务招待费超过 500 元、办公用品超过 2000 元、通用费用超过 2000 元的申请前置要求,制度依据统一改为财务规则《公司费用申请审批规则》。风险规则继续承担执行判断,但 `finance_rule_code` 统一指向 `expense.preapproval.policy`。 - -## 目标 - -补齐预算、申请前置、报销偏差、费用标准、材料完整性类风险规则,让后续 demo 数据可以形成“预算-申请-报销-风控”的闭环。 - -## 本次范围 - -- 第一批新增 30 条左右平台 JSON 风险规则。 -- 风险规则必须能通过现有 `risk-rules` JSON 规则库同步到规则中心。 -- 规则中保留口径引用字段;只有存在真实职级/职务金额分档的费用才引用财务规则表。 -- 没有独立财务标准表的费用,引用申请制度、材料完整性、预算执行或费用归类口径。 -- 规则中心的适用场景必须来自 `expense_types`,展示为具体费用类型,而不是统一显示通用。 -- 预算类规则先预留预算字段和口径,不在本阶段新增预算流水表。 - -## 规则分类 - -- 预算类:预算不足、80% 预警、100% 超预算、冻结预算、跨部门预算、跨季度预算。 -- 申请前置类:大额费用无申请,推广/培训/会务/软件/办公采购/招待无事前申请。 -- 申请报销偏差类:金额超申请、超 10%、科目不一致、部门不一致、周期不一致、重复报销。 -- 费用标准类:差旅、通信等真实标准;其他费用不伪造职级限额。 -- 费用归类类:固定资产伪装为办公用品等科目错配风险。 -- 材料完整性类:合同、方案、验收、签到、参与人、客户说明等材料缺失。 - -## 风险规则扩展字段 - -- `finance_rule_code`:可指向真实财务规则表,也可指向申请/预算/材料/归类制度口径。 -- `finance_rule_sheet`:真实表时记录工作表名称,制度口径时记录口径名称。 -- `business_stage` -- `expense_types`:用于意图识别后的费用类型匹配,也是规则中心适用场景的来源。 -- `budget_required` - -## 验证方式 - -- `AgentFoundationRiskRuleMixin` 能同步新增 JSON 规则。 -- 新增规则不被识别为自然语言生成草稿并跳过。 -- 规则资产的 `config_json` 能保留口径引用字段,且不指向已删除的口径型财务规则表。 -- 规则资产的 `scenario_json` 能从 `expense_types` 生成具体费用场景。 -- 至少验证预算类、申请前置类、费用标准类、材料完整性类各有规则同步成功。 diff --git a/document/development/expense-control-demo-data/TODO.md b/document/development/expense-control-demo-data/TODO.md deleted file mode 100644 index 0872a70..0000000 --- a/document/development/expense-control-demo-data/TODO.md +++ /dev/null @@ -1,20 +0,0 @@ -# 费用管控 Demo 数据规则补齐 TODO - -## 2026-05-26 - -- [x] 建立开发记录目录。 -- [x] 编写财务规则表开发记录。 -- [x] 编写风险规则开发记录。 -- [x] 设计费用类型财务规则定义。 -- [x] 生成第一版财务规则 Excel 文件。 -- [x] 让第一版财务规则表进入规则中心资产同步。 -- [x] 补充规则中心同步测试。 -- [x] 新增预算/申请/报销风险 JSON 规则。 -- [x] 补充风险规则同步测试。 -- [x] 补充财务规则资产同步脚本并同步演示库。 -- [x] 纠正财务规则表口径:删除独立交通住宿细分表,非制度标准费用不再维护限额表。 -- [x] 按真实职务金额分档口径二次纠正:删除 7 张没有实际金额分档的口径型财务规则表。 -- [x] 调整风险规则引用,避免指向已删除的口径型财务规则表。 -- [x] 修正规则中心适用场景:按 `expense_types` 展示具体费用类型,不再统一落为通用。 -- [x] 运行后端定向测试。 -- [x] 核对交付物和 TODO。 diff --git a/document/development/hermes-risk-graph-algorithm/CONCEPT.md b/document/development/hermes-risk-graph-algorithm/CONCEPT.md deleted file mode 100644 index ce2d90e..0000000 --- a/document/development/hermes-risk-graph-algorithm/CONCEPT.md +++ /dev/null @@ -1,1021 +0,0 @@ -# 数字员工财务行为图谱风险算法方案 - -更新日期:2026-05-29 - -## 1. 功能一句话 - -以数字员工为后台分析入口,持续把财务业务数据转成行为画像、制度语义和风险观察,再通过图谱证据链、单据详情和风险看板提供可解释的风险判断。 - -规则中心、审批和报销主流程仍由外层智能体流程负责调度;数字员工只消费事实、规则命中和反馈结果,生成后台分析、报告、知识库材料和待复核线索。 - -## 2. 背景与问题 - -X-Financial 已经具备费用申请、报销、审批、规则中心、知识制度归集、Agent 运行记录和数字员工任务入口。当前系统的风险能力主要来自规则命中、人工审核和局部页面展示,后续如果只继续增加单点技能,会出现几个问题: - -- 风险判断缺少统一载体,不同页面、规则和数字员工各自输出,难以汇总为算法资产。 -- 知识制度、员工画像、票据、审批链和历史反馈之间没有形成稳定关联。 -- 单据详情能看到风险描述,但很难直观看到“为什么异常”和“和谁相比异常”。 -- 分析看板如果只从散表拼统计图,会成为展示型页面,不能反映算法效果。 -- 数字员工如果只做定时任务,会变成调度工具,不能形成核心壁垒。 - -本方案把核心能力定义为“财务行为图谱风险引擎”。它不是单一模型,而是一套闭环:事件沉淀、实体建图、画像基线、风险推理、人工反馈、待复核线索归集。 - -## 3. 核心判断 - -数字员工可以做后台数据分析、画像分析和风险分析,但壁垒不在“多几个技能”,而在: - -- 公司制度的结构化能力。 -- 报销、预算、票据、审批、供应商、员工和部门之间的业务图谱。 -- 员工、部门、供应商和费用类型的长期行为基线。 -- 审批结果、退回原因、人工复核结论和误报反馈。 -- 可解释的风险观察模型和持续反馈闭环。 - -最终目标是让系统回答六个问题: - -- 谁异常。 -- 哪个业务环节异常。 -- 和什么基线相比异常。 -- 关联哪条制度或规则。 -- 历史相似情况怎么处理。 -- 当前应该怎么处置。 - -### 3.1 不可复制壁垒设计 - -别人可以复制页面、规则名称、图谱展示甚至部分算法论文,但很难复制 X-Financial 长期沉淀的业务语义、过程数据、人工反馈和证据闭环。系统壁垒必须设计在这些不可外购、不可快速补齐的资产上。 - -第一层壁垒:专有财务语义本体。 - -```text -公司制度条款 - -> 费用类型本体 - -> 风险信号本体 - -> 审批场景本体 - -> 预算科目本体 - -> 票据与附件要求本体 -``` - -该本体不是通用词典,而是由公司制度、历史审批、费用类型、预算口径、组织结构和管理员修订持续训练出来。外部系统即使知道字段名,也缺少本体版本、别名映射、风险信号口径和制度条款绑定关系。 - -第二层壁垒:对象中心财务事件日志。 - -```text -申请 -> 预算占用 -> 票据上传 -> 审批 -> 退回 -> 修改 -> 付款 -> 归档 -> 复盘 -``` - -每个事件同时绑定员工、部门、费用类型、供应商、审批人、票据、制度条款和 AgentRun。长期积累后,系统知道“正常流程是什么”“异常流程如何出现”“哪些异常最终被确认”,这是单纯规则库无法复制的。 - -第三层壁垒:风险观察反馈池。 - -每条 `RiskObservation` 都沉淀: - -```text -风险信号 -证据路径 -本体解析 -规则命中 -画像偏离 -图谱异常 -人工处理结果 -误报/确认反馈 -算法版本 -``` - -这会形成自有训练集、评测集和规则执行校准样本。竞品能复制算法框架,但复制不了这些被真实审批和财务人员校准过的样本。 - -第四层壁垒:人机共审行为数据。 - -系统不仅记录“AI 判断什么”,还记录“人如何处理 AI 的判断”: - -```text -采纳 -驳回 -改写 -退回 -补件 -升级审批 -标记误报 -归集待复核线索 -``` - -这些反馈会反向影响规则质量、抽审比例、自动化门控和数字员工能力考核。越使用越贴近企业自己的财务控制风格。 - -第五层壁垒:可回放评测资产。 - -每个风险版本都必须能离线回放: - -```text -同一批历史单据 -同一本体版本 -同一规则版本 -同一算法版本 -同一反馈标签 -``` - -这样系统不是“调参数看感觉”,而是可以证明新算法是否降低误报、提高确认率、减少人工审核量。长期回放集会成为核心资产。 - -因此,本项目的算法壁垒不是某一个模型,而是: - -```text -专有本体 -+ 对象中心事件日志 -+ 风险观察反馈池 -+ 人机共审行为数据 -+ 可回放评测资产 -+ 规则/图谱/画像/制度的版本化证据链 -``` - -这些资产必须在产品和数据库设计阶段就开始沉淀,否则后续即使接入复杂模型,也只会是可复制的通用能力。 - -## 4. 目标与非目标 - -### 4.1 目标 - -- 建立统一的 `RiskObservation` 风险观察模型,承接规则中心、数字员工、单据审核和图谱分析结果。 -- 建立财务行为图谱,关联员工、部门、供应商、票据、费用类型、单据、审批人、制度条款和风险规则。 -- 建立员工、部门、供应商、费用类型画像,提供同类基线和异常偏离度。 -- 在单据详情中展示风险证据链,解决单个风险解释问题。 -- 在数字员工工作记录详情中展示本次分析结果和图谱构建结果,解决数字员工“做了什么”的解释问题。 -- 在分析看板中增加风险看板,解决整体风险态势、算法效果和待处理风险管理问题。 -- 把人工反馈、审批处理结果和误报标记写回风险闭环。 - -### 4.2 非目标 - -- 第一版不做独立“大图谱中心”,避免做成展示型页面。 -- 不让大模型直接决定风险等级,大模型只参与语义抽取、解释生成和事实线索整理;不参与规则生成、改写或发布。 -- 不用画像自动惩罚员工,不给员工永久贴标签。 -- 不在员工技能详情中展示知识归集图谱;图谱结果只进入工作记录详情、单据风险详情或画像详情。 -- 不让数字员工生成、改写或自动上线规则;规则变更只能由管理员在规则中心维护。 - -## 5. 用户与场景 - -### 5.1 审批人 - -入口:单据详情。 - -关注点: - -- 当前单据为什么被标为风险。 -- 和本人历史、同部门同级别、同费用类型相比是否异常。 -- 命中了哪条制度或规则。 -- 历史相似单据是通过、退回还是调整金额。 -- 当前建议动作是什么。 - -### 5.2 财务与审计人员 - -入口:风险看板、风险详情、数字员工工作记录。 - -关注点: - -- 哪些部门、费用类型、供应商、员工风险集中。 -- 哪些风险重复出现。 -- 哪些规则误报率高。 -- 图谱发现了哪些异常关系。 -- 哪些风险需要优先复核。 - -### 5.3 管理员 - -入口:数字员工、规则中心、系统设置。 - -关注点: - -- 数字员工运行是否成功。 -- 本次分析处理了多少数据、产出多少风险观察。 -- 待复核风险线索是否有足够事实和证据。 -- 是否需要调整技能、规则、制度知识或调度配置。 - -### 5.4 管理层 - -入口:分析看板中的风险看板。 - -关注点: - -- 整体风险态势是否恶化。 -- 涉及金额和高风险待处理量。 -- 部门、费用类型和供应商风险分布。 -- 风险处理效率和算法确认率。 - -## 6. 功能能力 - -### 6.1 数字员工能力分层 - -第一版建议保留四类核心数字员工: - -- 制度整理员工:把公司财务制度整理成条款、适用范围、费用类型、触发条件和引用关系。 -- 风险扫描员工:定期扫描新增单据、票据、供应商、审批链和画像偏离,生成风险观察。 -- 画像更新员工:定期更新员工、部门、供应商、费用类型画像和同类基线。 -- 风险线索归集员工:从申请、报销、规则命中和人工反馈中归集待复核线索,不生成规则。 - -### 6.2 图谱体现方式 - -图谱不应该默认展示成全量关系网。第一版按业务场景拆成四种可读形态: - -- 单据详情:风险证据链。 -- 风险详情:小范围关系穿透图。 -- 工作记录详情:本次分析图谱和产出摘要。 -- 风险看板:风险地图、分布、趋势和算法效果。 - -### 6.3 单据详情风险证据链 - -建议在现有风险说明或审核建议附近增加“风险证据链”区块: - -```text -员工张三 - -> 提交差旅报销 4,860 元 - -> 命中住宿费用异常 - -> 同部门同级别平均 680 元/晚,本单 1,260 元/晚 - -> 关联制度:差旅住宿标准第 3 条 - -> 历史相似单据 12 笔,其中 8 笔被退回 - -> 建议:补充说明或人工复核 -``` - -显示内容: - -- 风险结论。 -- 证据链节点。 -- 同类基线对比。 -- 命中制度条款。 -- 历史相似案例。 -- 建议动作。 - -### 6.4 数字员工工作记录详情 - -工作记录详情展示数字员工本次任务结果,不展示员工技能定义。 - -建议展示: - -- 本次扫描范围。 -- 处理实体数量。 -- 生成风险观察数量。 -- 关键异常关系。 -- 失败原因和跳过数据。 -- 可点击的风险观察列表。 -- 对知识制度整理类任务,展示知识制度记录图谱。 - -### 6.5 分析看板风险看板 - -风险看板放在分析看板中作为独立页签,定位是风险算法驾驶舱。 - -第一版模块: - -- 风险总览:今日新增风险数、高风险待处理数、涉及金额、已确认风险数、误报数量。 -- 风险分布:按部门、费用类型、风险类型、供应商、员工职级分布。 -- 风险趋势:7 天 / 30 天风险走势、高风险占比、重复触发趋势、处理完成率。 -- 异常排行:风险最多部门、偏离基线最大员工、高频异常供应商、高频触发规则。 -- 算法效果:规则命中数、图谱异常命中数、人工确认率、误报率、待复核线索数。 - -风险看板必须从 `RiskObservation` 聚合,不直接从散表临时拼图表。 - -### 6.6 画像详情 - -画像详情作为第二阶段,不抢第一版主线。 - -可支持: - -- 员工画像:费用结构、历史风险、同级对比、供应商关联、退回率。 -- 部门画像:预算压力、费用结构、风险热力、审批效率。 -- 供应商画像:关联员工、关联部门、重复票据、金额集中度。 -- 费用类型画像:周期性、异常波动、制度命中频率。 - -## 7. 方案设计 - -### 7.1 总体架构 - -```text -业务数据 - -> 财务事件层 - -> 实体图谱层 - -> 画像基线层 - -> 风险推理层 - -> RiskObservation 风险观察池 - -> 单据详情 / 工作记录详情 / 风险看板 / 规则候选 - -> 人工反馈 - -> 画像、规则、制度知识持续优化 -``` - -### 7.2 事件层 - -统一沉淀业务事件,避免不同模块重复解释业务动作。 - -候选事件: - -```text -claim_created -claim_submitted -invoice_uploaded -approval_passed -approval_returned -amount_adjusted -budget_reserved -payment_completed -policy_document_ingested -risk_rule_triggered -digital_employee_run_completed -manual_feedback_submitted -``` - -### 7.3 实体图谱层 - -节点类型: - -```text -employee -department -position -vendor -invoice -expense_claim -expense_item -expense_type -approval_user -policy_clause -risk_rule -risk_observation -digital_employee_run -``` - -边类型: - -```text -belongs_to -submitted -contains_item -uses_invoice -paid_to_vendor -approved_by -matches_policy_clause -triggered_rule -similar_to -generated_by_run -confirmed_by_feedback -``` - -第一版不要求必须引入图数据库。可以先在关系型数据库中存储节点、边和 `path_json`,等查询复杂度上升后再接入专用图数据库。 - -### 7.4 本体与风险图谱桥接 - -本体层是风险图谱的语义骨架,不是图谱的替代品。图谱负责记录“谁和谁有关”,本体负责定义“这个关系在财务语义上是什么”。风险图谱中的节点、边、风险信号、规则匹配和看板聚合都必须引用本体标准化结果。 - -现有系统已有 `/api/v1/ontology/parse`、`SemanticParseLog`、`scenario`、`intent`、`entities`、`risk_flags`、`missing_slots` 等基础能力。风险图谱不应另建解析器,而应复用本体解析结果,并在必要时扩展本体词典和风险信号。 - -本体输出进入风险图谱的最小协议: - -```text -ontology_parse_id -ontology_version -domain -scenario -intent -entities -constraints -risk_signals -missing_slots -confidence -``` - -本体实体映射到图谱节点: - -```text -ontology entity graph node -employee employee -department department -expense_type expense_type -document_type invoice / expense_claim / contract / payment_record -vendor vendor -policy_clause policy_clause -risk_signal risk_observation / risk_signal -budget_subject budget_subject -project project -location location -``` - -图谱节点必须保留本体标准键: - -```text -node_type employee / claim / invoice / vendor / policy_clause / ... -ontology_type expense_type / document_type / risk_signal / organization / ... -canonical_key hotel / travel / duplicate_invoice / over_standard / ... -canonical_id 标准实体 ID,可为空但必须记录 canonical_key -source_object_type expense_claim / invoice / policy_document / agent_run / ... -source_object_id -ontology_parse_id -ontology_version -``` - -图谱边必须来自白名单,不能让数字员工自由创造运行时边类型: - -```text -submitted 员工提交单据 -belongs_to 员工归属部门 -contains_item 单据包含费用明细 -uses_invoice 费用明细使用票据 -paid_to_vendor 付款或票据关联供应商 -approved_by 单据由某审批人审批 -matches_policy_clause 单据或风险观察关联制度条款 -triggered_risk_signal 单据触发本体风险信号 -triggered_rule 单据命中规则 -similar_to 与历史对象相似 -generated_by_run 由数字员工运行生成 -confirmed_by_feedback 由人工反馈确认 -``` - -风险信号必须本体化。不同文本说法要映射到同一标准风险信号,例如: - -```text -住宿超标 / 酒店超标 / 差旅住宿异常 - -> risk_signal = accommodation_standard_deviation - -> scenario = travel_reimbursement - -> expense_type = hotel - -重复发票 / 发票重复 / 票据重复报销 - -> risk_signal = duplicate_invoice - -> scenario = invoice_validation - -> document_type = invoice -``` - -规则中心、图谱引擎和风险看板必须按同一套本体口径聚合: - -```text -规则中心:scenario + expense_type + risk_signal 决定规则适用范围 -图谱引擎:canonical node + whitelisted edge 构造证据路径 -风险观察:ontology fields + evidence path 输出可解释结论 -风险看板:按 ontology scenario / expense_type / risk_signal 聚合 -数字员工:只能产出本体可识别的事实、规则命中、待复核风险线索和证据引用 -``` - -当本体置信度不足时,风险图谱必须降级: - -```text -confidence >= 0.85 可进入自动规则匹配和图谱证据构建 -0.60 <= confidence < 0.85 进入人工复核或半自动模式 -confidence < 0.60 只记录候选观察,不触发强拦截 -``` - -### 7.5 统一风险观察模型 - -核心结构: - -```text -RiskObservation -- id -- subject_type employee / department / vendor / claim / invoice / expense_type -- subject_id -- risk_type -- severity low / medium / high / critical -- score 0-100 -- status open / confirmed / false_positive / resolved / ignored -- evidence_items_json -- evidence_path_json -- related_policy_clauses_json -- related_entities_json -- comparable_baseline_json -- suggested_actions_json -- source_type rule / graph / profile / policy / digital_employee -- source_id -- ontology_parse_id -- ontology_version -- domain -- scenario -- intent -- ontology_entities_json -- ontology_constraints_json -- risk_signals_json -- canonical_subject_key -- algorithm_version -- feedback_status -- created_at -- updated_at -``` - -### 7.6 API 契约建议 - -单据详情读取风险证据链: - -```text -GET /api/v1/risk-observations/by-claim/{claim_id} -``` - -风险观察详情: - -```text -GET /api/v1/risk-observations/{observation_id} -``` - -风险看板聚合: - -```text -GET /api/v1/risk-observations/analytics/summary -``` - -数字员工工作记录关联风险观察: - -```text -GET /api/v1/agent-runs/{run_id}/risk-observations -``` - -人工反馈: - -```text -POST /api/v1/risk-observations/{observation_id}/feedback -``` - -本体图谱映射调试接口建议只面向管理员: - -```text -GET /api/v1/risk-graph/ontology-mapping/{object_type}/{object_id} -``` - -返回当前对象关联的本体解析、标准实体、图谱节点、图谱边和降级原因,用于排查风险解释是否来自正确语义。 - -### 7.7 前端入口关系 - -```text -分析看板 - -> 风险看板:整体态势和算法效果 - -单据详情 - -> 风险证据链:解释单个单据风险 - -数字员工 - -> 员工技能:配置技能和 Markdown 源文件 - -> 工作记录详情:展示本次任务结果和图谱结果 - -规则中心 - -> 风险规则详情:展示规则定义、条件、执行逻辑 - -画像详情 - -> 员工 / 部门 / 供应商长期画像 -``` - -## 8. 算法与公式 - -### 8.1 风险总分 - -第一版使用可解释加权模型,不直接使用黑盒模型给最终分。 - -$$ -risk\_score = -clip(0.35S_{rule} + 0.25S_{anomaly} + 0.20S_{graph} + 0.15S_{policy} + 0.05S_{history}, 0, 100) -$$ - -变量定义: - -- \(S_{rule}\):确定性规则命中分,来自规则中心或制度规则。 -- \(S_{anomaly}\):画像和同类基线偏离分。 -- \(S_{graph}\):图谱关系异常分,例如重复票据、供应商集中、审批链异常。 -- \(S_{policy}\):制度语义相关分,例如说明、票据和制度条款不一致。 -- \(S_{history}\):历史反馈分,例如相似案例退回率、确认风险率。 - -### 8.2 同类基线偏离 - -对金额、频次、天数、退回率等数值型指标,优先使用稳健统计: - -$$ -deviation = \frac{x - median(peer)}{max(IQR(peer), \epsilon)} -$$ - -$$ -S_{anomaly} = 100 \times sigmoid(k(deviation - \tau)) -$$ - -变量定义: - -- \(x\):当前员工、部门、供应商或单据指标。 -- \(peer\):同部门、同职级、同费用类型、同城市级别等同类样本。 -- \(IQR\):四分位距。 -- \(\epsilon\):防止分母为零的最小值。 -- \(\tau\):异常阈值。 -- \(k\):放大系数。 - -### 8.3 图谱异常分 - -第一版图谱异常分可以采用可解释信号累加: - -$$ -S_{graph} = min(100, \sum_{i=1}^{n} w_i g_i) -$$ - -候选信号: - -- 重复票据:同一票据号、金额、供应商或影像指纹重复。 -- 供应商集中:某员工或部门在窗口期内高度集中到少数供应商。 -- 审批链异常:审批人和申请人关系异常、审批路径绕行或过短。 -- 时间地点异常:业务地点、票据地点、行程地点不一致。 -- 相似单据异常:与历史退回或调整金额单据高度相似。 - -### 8.4 人工反馈校准 - -人工反馈不直接覆盖算法,但会影响后续权重和待复核线索优先级: - -$$ -confirmed\_rate = \frac{confirmed}{confirmed + false\_positive + ignored} -$$ - -$$ -rule\_quality = 0.6 \times confirmed\_rate + 0.4 \times coverage -$$ - -其中 `coverage` 表示该规则或风险类型在目标场景中的有效覆盖率。 - -## 9. 公开竞品资料借鉴 - -### 9.1 资料边界 - -本节只基于公开资料提炼可借鉴的算法模式,不假设能够获得用友费用或合思费控的内部算法实现。公开资料能证明的是产品能力、架构方向、典型场景和治理方法;工程实现仍需要结合 X-Financial 的本体、规则中心、数字员工、AgentRun 和业务数据重新设计。 - -参考资料: - -- [用友 YonBIP 财务云智能费控服务白皮书](https://mks.yybip.com/group1/M00/07/EB/CgoRC2JVTMGAPdWmAEdtt5GGOf0756.pdf) -- [用友数智化财务资料:商旅费控、事项法会计与 AI 能力](https://mks.yybip.com/group1/M00/0A/29/CgoRC2XvFQuAKvNtACX8GJS9Zgo009.pdf) -- [合思 AI 官网:7 大 Agent、700+ skills、财务审核专家](https://www.ekuaibao.com/hoseai.html) -- [合思 AI 财务审核专家](https://www.ekuaibao.com/aifinancialapproval.html) -- [合思企业内控解决方案](https://www.ekuaibao.com/solutionsr/control.html) -- [合思 AI 审核风控升级文章](https://www.ekuaibao.com/blog/620731.html) - -### 9.2 用友费用可借鉴模式 - -公开资料中,用友费控的重点不是单点审核,而是“事前规划、事中控制、事后分析”的端到端费控链路。可借鉴点如下: - -- 流程前置:在出差申请、商旅预订、报销、稽核、核算、结算、归档全流程内嵌管控,而不是只在报销提交后审核。 -- 规则模板库:公开资料提到“超级差规”基于规则引擎,并预置大量差旅规则模板。X-Financial 应建设按本体场景绑定的规则模板族,而不是只存自由文本规则。 -- 商旅比价与推荐:根据出行时间、目的地、企业标准和供应商价格推荐合规方案。X-Financial 可将其抽象为“候选行为合规推荐”,服务事前控制。 -- 多服务连接:连接商旅、用车、餐饮、采购、电子发票等外部服务,交易数据自动同步。X-Financial 可把这些数据统一成图谱事件,而不是只做附件。 -- 预算刚柔控制:预算规则支持事前、事中、刚性、柔性控制。X-Financial 的风险观察应记录 `control_stage` 和 `control_mode`,区分禁止、预警、复核、提示。 -- 信用与抽审:公开架构中出现信用管理、指标管理、评价管理、抽审规则和抽审单据。X-Financial 可借鉴为“风险分层抽审”,不是所有单据都同等审核。 - -落地到 X-Financial,建议新增三个算法组件: - -```text -PolicyTemplateLibrary - -> 按 ontology scenario / expense_type / risk_signal 绑定规则模板 - -PreControlRecommender - -> 在申请和预订阶段给出合规选项、预算影响和风险提示 - -RiskSamplingPlanner - -> 根据风险分、历史误报率、员工画像和规则质量决定抽审比例 -``` - -### 9.3 合思费控可借鉴模式 - -公开资料中,合思更强调 AI 审核、人机共审、专属规则、跨材料校验和持续反馈。可借鉴点如下: - -- AI 数字员工治理:官网强调类似新员工管理的“培训、授权、监督、考核”。X-Financial 的数字员工也应该有能力边界、授权范围、低置信度转人工和运行质量考核。 -- 结构化信息提取:公开资料强调从单据、发票、流水、合同、票据等材料提取结构化信息。X-Financial 应把 OCR、附件解析和本体实体统一进证据模型。 -- 跨材料交叉验证:公开资料提到单据、发票、支付水单、事前申请事项的比对,以及单据、发票、流水一致性校验。X-Financial 应把它抽象为“多凭证一致性图谱”。 -- 时空推理:公开资料提到结合时空推理还原真实轨迹。X-Financial 可在差旅、用车、住宿、餐饮场景中引入时间、地点、行程、票据地点一致性信号。 -- 自然语言规则配置:公开资料提到财务可用日常语言编辑规则、制度导入导出、离线测试调优。X-Financial 应让制度整理员工产出规则候选,但上线必须走模板、测试和审核。 -- 三种自动化模式:辅助审批、半自动、全自动。X-Financial 应将其产品化为风险自动化等级,而不是一开始追求全自动。 -- 正负样本与对抗样本:公开资料提到正负向样本、反事实、噪声干扰、低置信度转人工。X-Financial 的反馈闭环应明确样本池和模型评测集。 -- 结果可追溯:合思公开页面强调风险点、依据、建议、分级可溯和看板下钻。X-Financial 的 `RiskObservation` 必须保留证据、来源、算法版本和反馈状态。 - -落地到 X-Financial,建议新增四个算法组件: - -```text -MultiEvidenceReconciler - -> 单据、发票、流水、合同、行程、申请之间的一致性校验 - -SpatioTemporalRiskEngine - -> 时间、地点、行程、消费、开票之间的时空一致性检查 - -HumanInLoopAutomationGate - -> 按置信度、风险等级、证据覆盖、历史误报率决定辅助/半自动/自动 - -RiskEvaluationDataset - -> 正样本、负样本、反事实样本、噪声样本和历史误报样本 -``` - -### 9.4 对当前方案的补强 - -结合公开资料,本方案需要补强五点: - -1. 从“事后风险识别”扩展为“事前申请、事中消费、事后审核”的分阶段风险控制。 -2. 从“规则命中”扩展为“本体模板 + 多凭证一致性 + 时空推理 + 行为画像”的组合判断。 -3. 从“统一风险分”扩展为“风险分 + 自动化等级 + 抽审策略”。 -4. 从“单次数字员工任务”扩展为“训练、授权、监督、考核”的数字员工治理。 -5. 从“人工反馈记录”扩展为“样本池、离线回放、规则质量、模型质量”的持续评测体系。 - -建议在 `RiskObservation` 增加字段: - -```text -control_stage pre_application / booking / submission / approval / payment / archive -control_mode block / warn / require_review / suggest / observe -automation_mode assist / semi_auto / auto -confidence_score 0-1 -evidence_coverage_count -sampling_strategy full_review / risk_sampling / random_sampling / exempt -evaluation_case_id -``` - -自动化等级建议使用可审计门控: - -$$ -automation = -\begin{cases} -auto, & confidence \ge \theta_{auto} \land severity \le medium \land evidence\_coverage \ge 2 \land false\_positive\_rate \le \alpha \\ -semi\_auto, & confidence \ge \theta_{semi} \land evidence\_coverage \ge 1 \\ -assist, & otherwise -\end{cases} -$$ - -这个门控比“AI 直接通过/驳回”更适合企业费控,因为它把自动化建立在置信度、风险等级、证据覆盖和历史误报率之上。 - -### 9.5 可集成的外部算法技术栈 - -除友商公开能力外,还可以引入一组成熟的公开技术,形成更深的算法壁垒。核心原则是:先把技术映射到 X-Financial 的本体、图谱、风险观察和反馈闭环,不为了复杂而复杂。 - -参考资料: - -- [OCEL 2.0 Object-Centric Event Log](https://www.ocel-standard.org/) -- [IEEE Task Force Process Mining Manifesto](https://www.tf-pm.org/resources/manifesto) -- [Temporal Graph Networks](https://arxiv.org/abs/2006.10637) -- [GraphSAGE](https://papers.neurips.cc/paper/6703-inductive-representation-learning-on-large-graphs) -- [metapath2vec](https://www.kdd.org/kdd2017/papers/view/metapath2vec-scalable-representation-learning-for-heterogeneous-networks) -- [Heterogeneous Graph Attention Network](https://arxiv.org/abs/1903.07293) -- [Isolation Forest](https://cs.nju.edu.cn/zhouzh/zhouzh.files/publication/icdm08b.pdf) -- [Fellegi-Sunter record linkage](https://pmc.ncbi.nlm.nih.gov/articles/PMC9336505/) -- [SHAP](https://arxiv.org/abs/1705.07874) -- [Decision Model and Notation](https://www.omg.org/dmn/) -- [Open Policy Agent](https://www.openpolicyagent.org/docs/latest) -- [DoWhy causal inference](https://www.pywhy.org/dowhy/v0.9.1/user_guide/effect_inference/index.html) -- [OpenLineage](https://openlineage.io/) -- [Great Expectations](https://docs.greatexpectations.io/docs/guides/validation/validate_data_overview/) - -#### 9.5.1 对象中心过程挖掘 - -传统流程分析通常按单一 case 展开,例如一张报销单。但财务真实流程是多对象交织:申请、报销、票据、合同、付款、供应商、预算、审批人同时参与。OCEL 2.0 的对象中心事件日志适合承载这种复杂关系。 - -建议新增 `FinancialObjectEventLog`: - -```text -event_id -activity claim_submitted / invoice_uploaded / approval_returned / payment_completed -timestamp -actor_id -object_refs_json claim / invoice / vendor / budget / payment / policy_clause -attributes_json -ontology_parse_id -source_run_id -``` - -可形成的风险能力: - -- 流程偏离:实际审批路径和标准流程不一致。 -- 返工循环:反复退回、补件、重提。 -- 跳步审批:缺少关键节点或审批路径过短。 -- 付款前异常:付款早于必要审批或票据校验。 -- 供应商集中流程:同一供应商相关单据绕过常规节点。 - -对应算法组件: - -```text -ObjectCentricProcessMiner - -> 从业务表和 AgentRun 构造对象中心事件日志 - -ConformanceRiskDetector - -> 对比标准流程模型和实际事件路径,输出流程偏离风险 -``` - -#### 9.5.2 实体解析与主数据归一 - -风险图谱的质量取决于实体是否归一。供应商、商户、酒店、员工姓名、发票销售方、银行户名经常存在别名、错别字、简称和大小写差异。Fellegi-Sunter 记录链接、主动学习实体去重和人工确认机制都可以借鉴。 - -建议新增 `EntityResolutionService`: - -```text -entity_type vendor / merchant / hotel / employee / bank_account -raw_name -canonical_key -canonical_id -match_score -match_method exact / rule / probabilistic / embedding / human -evidence_json -review_status -``` - -可形成的风险能力: - -- 同一供应商多名称拆分识别。 -- 发票销售方和付款户名疑似同一主体识别。 -- 酒店、商户、供应商别名归一。 -- 员工、审批人、外部联系人身份消歧。 - -对应算法组件: - -```text -FinancialEntityResolver - -> 字符串相似度 + 频率权重 + 业务字段校验 + 人工确认 - -CanonicalEntityRegistry - -> 维护财务图谱中的标准主体 ID -``` - -#### 9.5.3 异构图与时序图学习 - -X-Financial 的图谱天然是异构图:员工、部门、供应商、票据、单据、制度条款和规则都不是同一种节点。metapath2vec、HAN、GraphSAGE、Temporal Graph Networks 等技术可以用于发现人工规则难以覆盖的结构风险。 - -第一版不建议直接上深度 GNN 作为主判定。建议先用可解释图特征,再把图嵌入作为候选信号: - -```text -metapath features: -employee -> claim -> vendor -employee -> claim -> invoice -> vendor -department -> employee -> claim -> vendor -claim -> expense_type -> policy_clause -approver -> claim -> employee -> department - -temporal features: -最近 7 / 30 / 90 天边新增速度 -供应商集中度变化 -审批链长度变化 -同类风险信号传播路径 -``` - -对应算法组件: - -```text -HeterogeneousRiskGraphFeatureBuilder - -> 构造元路径、中心性、团簇、邻域风险密度等可解释图特征 - -TemporalRiskGraphMonitor - -> 监控关系在时间上的突增、消失、迁移和异常传播 -``` - -#### 9.5.4 多模型异常检测组合 - -单一异常检测模型不适合作为最终风控结论,但可以作为风险观察的候选信号。建议组合稳健统计、Isolation Forest、局部离群、时间序列突变和规则命中。 - -候选信号: - -```text -robust_z_score 同类分位偏离 -isolation_score 多维行为孤立度 -local_outlier_score 邻域异常 -change_point_score 时间序列突变 -seasonality_score 周期偏离 -``` - -组合方式: - -$$ -S_{anomaly\_ensemble} = -0.35S_{robust} + 0.20S_{isolation} + 0.15S_{local} + 0.20S_{change} + 0.10S_{seasonality} -$$ - -该分数只作为 `RiskObservation` 的一类证据,不能单独触发强拦截。 - -#### 9.5.5 决策建模与策略即代码 - -规则中心适合承载确定性规则,但复杂审批策略需要拆成“业务决策表 + 策略执行 + 审计日志”。DMN 和 Open Policy Agent 的思路可以借鉴。 - -建议拆分: - -```text -DecisionTable - -> 业务可读决策表,例如不同职级、城市、费用类型的标准 - -PolicyRuntime - -> 执行策略、权限、自动化门控、抽审策略 - -DecisionTrace - -> 记录输入、命中行、输出、版本、解释 -``` - -这样规则中心负责版本和发布,风险图谱引擎消费 `DecisionTrace` 作为证据。 - -#### 9.5.6 可解释与不确定性控制 - -企业费控不能只输出分数,需要输出证据贡献、置信度、低置信度原因和人工复核建议。SHAP 类解释方法、置信区间、保守门控和人工反馈可以组合使用。 - -建议每条风险观察保存: - -```text -feature_contributions_json -confidence_score -uncertainty_reasons_json -required_human_review -explanation_template_key -``` - -门控原则: - -- 强制度规则命中:优先使用规则解释。 -- 多证据一致:允许进入半自动。 -- 只有模型异常:只进入候选观察或抽审池。 -- 低置信度本体解析:不触发强拦截。 - -#### 9.5.7 因果分析与反事实建议 - -风险看板不应只回答“哪里风险多”,还要回答“哪些控制动作真的降低风险”。DoWhy 类因果推断框架可以用于后续分析,但第一版先做可回放的反事实建议。 - -示例: - -```text -如果补充酒店水单,当前风险分从 76 降到 48 -如果选择协议酒店,住宿标准异常消失 -如果审批链增加预算负责人复核,付款前风险等级降为中 -``` - -对应组件: - -```text -CounterfactualRiskAdvisor - -> 给出降低风险分的可执行补救动作 - -ControlEffectAnalyzer - -> 评估某条规则、抽审策略或数字员工上线前后的风险变化 -``` - -#### 9.5.8 数据血缘与质量门禁 - -复杂风险算法的前提是数据可信。OpenLineage 和 Great Expectations 的思路可以用于记录数据来源、校验质量和阻止低质量数据进入强风控。 - -建议新增: - -```text -RiskDataLineage - -> 记录风险观察使用了哪些表、文档、OCR、AgentRun、规则版本和本体版本 - -RiskDataQualityGate - -> 校验金额、日期、供应商、费用类型、票据号、审批状态等字段完整性 -``` - -质量门禁策略: - -- 缺少关键金额或票据号:不生成强结论。 -- 本体费用类型低置信度:只生成候选观察。 -- OCR 关键字段冲突:进入多凭证一致性复核。 -- 来源数据过旧:风险观察标记为 stale。 - -## 10. 测试方案 - -### 10.1 后端测试 - -- 风险观察模型序列化测试。 -- 单据风险观察查询接口测试。 -- 风险看板聚合接口测试。 -- 画像基线计算单元测试。 -- 图谱路径构建单元测试。 -- 人工反馈状态流转测试。 -- 自动化门控模式测试。 -- 多凭证一致性校验测试。 -- 风险抽审策略测试。 - -后端验证优先在 Docker 容器中执行: - -```bash -docker exec x-financial-main sh -lc "cd /app && pytest -q" -``` - -单元测试超时建议设置 60s,避免任务卡死。 - -### 10.2 前端测试 - -- 单据详情存在风险观察时展示证据链。 -- 单据详情无风险观察时不占用主流程。 -- 工作记录详情只展示本次任务相关图谱,不污染员工技能详情。 -- 风险看板筛选、趋势、排行和卡片数据一致。 -- 风险观察点击后能回到单据、规则或工作记录。 - -### 10.3 回归测试 - -- 规则中心风险规则详情不被图谱展示污染。 -- 数字员工员工技能详情不显示知识归集图谱。 -- 系统日志和数字员工工作记录边界保持清晰。 -- 分析看板原有指标不受风险看板影响。 - -## 11. 指标与验收 - -### 11.1 业务验收 - -- 审批人能在单据详情看到风险结论、证据链、基线对比、制度条款和建议动作。 -- 财务人员能在风险看板看到整体风险态势、分布、趋势、排行和算法效果。 -- 管理员能在数字员工工作记录详情看到本次任务产出的风险观察和异常关系。 -- 规则候选必须带证据、来源、置信度和人工审核状态。 - -### 11.2 技术验收 - -- 所有风险输出统一落到 `RiskObservation` 或兼容结构。 -- 风险看板只读取风险观察聚合接口,不直接拼接业务散表。 -- 风险观察详情接口返回结构化证据链。 -- 每条风险观察保留算法版本、来源、时间和反馈状态。 -- 关键接口有单元测试或接口测试覆盖。 -- 自动化模式必须有门控原因,不允许只记录 AI 判断结果。 -- 风险抽审策略必须可回放,保留当时的分数、阈值和样本策略。 - -### 11.3 算法验收 - -- 风险观察证据覆盖率不低于 95%。 -- 高风险观察必须至少包含 2 类证据:规则、画像、图谱、制度、历史中的任意两类。 -- 人工确认率、误报率、忽略率可统计。 -- 同类基线样本不足时必须记录降级口径。 -- 自动化放行单据的抽检误报/漏报结果可统计。 -- 评测集必须包含正样本、负样本、反事实样本、噪声样本和历史误报样本。 - -## 12. 风险与开放问题 - -- 是否需要引入图数据库:第一版建议先用关系表和 JSON 路径,后续根据查询复杂度评估。 -- 历史数据质量不足会影响画像基线,需要记录样本量和降级口径。 -- 制度条款结构化质量会直接影响语义风险,需要把制度整理员工作为基础能力持续完善。 -- 风险看板如果没有 `RiskObservation` 统一模型,会退化为普通统计页面。 -- 图谱展示必须小范围、场景化,避免全量关系图降低可读性。 -- 公开竞品资料只能提供产品能力和方法论参考,不能直接证明其内部算法实现;X-Financial 必须以自有数据和可审计实现为准。 diff --git a/document/development/hermes-risk-graph-algorithm/PUBLIC_COMPETITOR_REFERENCE.md b/document/development/hermes-risk-graph-algorithm/PUBLIC_COMPETITOR_REFERENCE.md deleted file mode 100644 index 08b874f..0000000 --- a/document/development/hermes-risk-graph-algorithm/PUBLIC_COMPETITOR_REFERENCE.md +++ /dev/null @@ -1,91 +0,0 @@ -# 公开竞品资料校准与自有算法映射 - -更新日期:2026-05-30 - -## 资料边界 - -本文件只使用公开资料做产品能力和方法论校准,不推断竞品内部算法实现。 -X-Financial 的落地实现必须以自有数据、本体、规则中心、风险观察池、反馈池、 -决策追踪和可回放测试为准。 - -公开资料来源: - -- [用友 YonBIP 财务云智能费控服务白皮书](https://mks.yybip.com/group1/M00/07/EB/CgoRC2JVTMGAPdWmAEdtt5GGOf0756.pdf) -- [用友数智化财务资料:商旅费控、事项法会计与 AI 能力](https://mks.yybip.com/group1/M00/0A/29/CgoRC2XvFQuAKvNtACX8GJS9Zgo009.pdf) -- [合思 AI 财务审核专家](https://www.ekuaibao.com/aifinancialapproval.html) -- [合思 AI 审核解决方案](https://www.ekuaibao.com/solutionsr/check.html) -- [合思企业内控解决方案](https://www.ekuaibao.com/solutionsr/control.html) - -## 用友公开资料校准 - -### 端到端费控链路 - -公开资料覆盖事前申请、商旅预订、智能识票、自动报账、移动审批、智能收单、 -智能审核、自动核算、结算、分析、电子归档等环节。 - -X-Financial 映射: - -- 用 `ObjectCentricEvent` 建立申请、预订、报销、审批、付款、归档、复盘事件。 -- 用 `RiskObservation` 承接每个阶段产生的风险结论。 -- 用 `RiskDataLineage` 记录每条结论引用的单据、票据、规则、本体和 AgentRun。 - -### 规则模板、预算刚柔控制、信用抽审、商旅推荐 - -公开资料中可借鉴的能力包括规则引擎/规则模板、预算事前事中控制、刚性/柔性 -控制、信用管理与抽审规则,以及基于出发时间、目的地、差旅标准和多供应商比价 -的商旅推荐。 - -X-Financial 映射: - -- `PolicyTemplateLibrary`:把制度条款沉淀为按场景、本体实体、费用类型和角色 - 绑定的规则模板族。 -- `PreControlRecommender`:在提交前给出预算、差标、商旅供应商、住宿和交通 - 标准建议。 -- `RiskSamplingPlanner`:结合风险分、员工画像、信用等级、历史误报率和反馈 - 标签,生成抽审策略、阈值和回放桶。 -- `ProfileBaselineUpdater`:定期更新员工、部门、供应商、费用类型基线,为信用 - 抽审和预算柔性控制提供自有画像数据。 - -## 合思公开资料校准 - -### AI 审核与人机共审 - -公开资料强调 AI 先完成规则型检查、风险标记和建议输出,再由财务处理异常、 -灰区和制度优化。X-Financial 不应让 AI 直接替代规则中心,而应把 AI 产出转成 -可解释、可审计、可回放的风险观察。 - -X-Financial 映射: - -- `HumanInLoopAutomationGate`:按置信度、风险等级、证据来源数、历史误报率和 - 数据质量决定自动放行、辅助、人工复核或候选观察。 -- `DecisionTrace`:保留输入、命中行、贡献项、不确定性原因和解释模板。 -- `RiskObservationFeedback`:把确认、误报、忽略、补件、升级、候选规则来源 - 转为闭环样本。 - -### 多凭证校验与时空推理 - -公开资料中,多凭证校验覆盖报销单、发票、水单、订单、小票、合同、行程等材料; -时空校验覆盖消费时间、地点、轨迹、行程逻辑和异常地点。 - -X-Financial 映射: - -- `MultiEvidenceReconciler`:把单据、发票、附件、流水、合同、行程和事前申请 - 统一成证据项,输出字段一致性和缺失项。 -- `SpatioTemporalRiskEngine`:基于发生时间、提交时间、明细时间、地点、行程、 - 开票地点和供应商地点构造时空一致性信号。 -- `RiskDataQualityGate`:证据不足或字段缺失时封顶风险分,避免低质量数据触发 - 强结论。 - -## 转成 X-Financial 自有壁垒 - -竞品资料只作为能力校准。真正不可复制的部分必须沉淀在以下资产中: - -1. 自有财务本体:场景、意图、实体、约束、风险信号、权限、置信度。 -2. 自有对象中心事件日志:每个报销和风控过程可回放。 -3. 自有画像基线:员工、部门、供应商、费用类型、规则、制度条款长期演化。 -4. 自有反馈池:人工确认、误报、补件、升级和候选规则来源。 -5. 自有回放集:正样本、负样本、反事实样本、噪声样本和历史误报样本。 -6. 自有解释资产:证据链、制度条款、相似案例、贡献项、决策追踪和数据血缘。 - -因此,后续实现原则是:不复制竞品页面、术语和流程包装;只吸收公开资料中可验证 -的能力方向,并转译为 X-Financial 的结构化数据、确定性算法、人工反馈和回放测试。 diff --git a/document/development/hermes-risk-graph-algorithm/RISK_SOURCE_AND_MOAT.md b/document/development/hermes-risk-graph-algorithm/RISK_SOURCE_AND_MOAT.md deleted file mode 100644 index 1d317f5..0000000 --- a/document/development/hermes-risk-graph-algorithm/RISK_SOURCE_AND_MOAT.md +++ /dev/null @@ -1,112 +0,0 @@ -# 风险图谱数据来源与壁垒资产清单 - -更新日期:2026-05-30 - -## 风险相关数据来源 - -1. 报销单主表:`ExpenseClaim` - - 关键字段:`id`、`claim_no`、`employee_id`、`employee_name`、`department_id`、`department_name`、`expense_type`、`amount`、`currency`、`invoice_count`、`occurred_at`、`submitted_at`、`status`、`approval_stage`、`risk_flags_json`。 - - 用途:风险主体、金额基线、流程阶段、规则命中、图谱 claim 节点。 - -2. 报销明细:`ExpenseClaimItem` - - 关键字段:`item_id`、`item_type`、`item_amount`、`item_location`、`item_date`、`invoice_id`。 - - 用途:多凭证一致性、时空一致性、票据关系、图谱 item / invoice 节点。 - -3. 风险规则命中:`risk_flags_json` 与规则中心结果 - - 来源:报销单已有风险标记、`RiskObservationService.upsert_platform_risk_flags()`。 - - 用途:`S_rule`、规则版本追溯、候选规则闭环。 - -4. 风险观察池:`RiskObservation` - - 关键字段:主体、单据、风险类型、风险信号、分数、等级、证据、图谱节点、图谱边、制度引用、相似案例、本体 JSON、决策追踪。 - - 用途:统一风险结论、看板、详情、反馈、回放。 - -5. 风险观察反馈:`RiskObservationFeedback` - - 关键字段:反馈类型、动作、处理人、备注、扩展 payload。 - - 用途:人工采纳、误报、忽略、处理完成、候选规则来源、回放标签。 - -6. 数字员工任务记录:`HermesTaskExecutionLog` - - 关键字段:任务配置、状态、开始结束时间、错误信息、执行摘要。 - - 用途:风险扫描任务追溯、数字员工工作记录详情、失败原因。 - -7. Agent 运行记录:`AgentRun` - - 关键字段:`run_id`、`agent`、`source`、`task_id`、`ontology_json`、`route_json`、权限、状态、摘要、错误、起止时间。 - - 用途:数字员工运行上下文、数据血缘、回放输入。 - -8. 工具调用记录:`AgentToolCall` - - 关键字段:工具类型、工具名称、请求、响应、状态、耗时、错误。 - - 用途:OCR、知识检索、规则执行、外部工具证据链。 - -9. 语义解析日志:`SemanticParseLog` - - 关键字段:原始查询、场景、意图、实体、时间范围、指标、约束、风险信号、权限、置信度。 - - 用途:本体到风险图谱桥接、低置信度降级、语义血缘。 - -10. 财务制度知识库 - - 来源:知识库文档、制度归集任务、知识检索证据。 - - 用途:制度条款引用、`S_policy`、风险解释、制度缺口识别。 - -## `/api/v1/ontology/parse` 字段与落库方式 - -接口请求:`OntologyParseRequest` - -- `query`:自然语言问题。 -- `user_id`:当前用户。 -- `context_json`:角色、部门、权限上下文。 - -接口响应:`OntologyParseResult` - -- `scenario`:业务场景。 -- `intent`:用户意图。 -- `entities`:实体列表,包含类型、原值、标准值、角色、置信度。 -- `time_range`:时间范围。 -- `metrics`:指标列表。 -- `constraints`:字段约束。 -- `risk_flags`:风险信号列表。 -- `permission`:权限结果。 -- `confidence`:整体置信度。 -- `missing_slots`:缺失槽位。 -- `ambiguity`:歧义说明。 -- `parse_strategy`:解析策略。 -- `clarification_required` / `clarification_question`:是否需要追问。 -- `run_id`:关联 `AgentRun.run_id`。 -- `field_errors`:字段级错误。 - -落库方式: - -- `AgentRun.ontology_json` 保存本次解析概要。 -- `SemanticParseLog.entities_json` 保存实体。 -- `SemanticParseLog.time_range_json` 保存时间。 -- `SemanticParseLog.metrics_json` 保存指标。 -- `SemanticParseLog.constraints_json` 保存约束。 -- `SemanticParseLog.risk_flags_json` 保存风险信号。 -- `SemanticParseLog.permission_json` 保存权限。 -- `SemanticParseLog.confidence` 保存整体置信度。 - -## 不可复制壁垒资产 - -1. 专有财务本体 - - 由场景、意图、实体、约束、风险信号、权限和置信度构成。 - - 价值:把自然语言、规则中心和风险图谱统一到同一业务语义。 - -2. 对象中心财务事件日志 - - 由 `ObjectCentricEvent` 承载,统一申请、报销、票据、审批、退回、付款、归档、复盘。 - - 价值:形成可回放过程挖掘资产。 - -3. 风险观察反馈池 - - 由 `RiskObservationFeedback` 承载,记录确认、误报、忽略、改写、补件、升级和候选规则来源。 - - 价值:把人工判断变成模型和规则迭代样本。 - -4. 人机共审行为数据 - - 来源:AgentRun、ToolCall、反馈、数字员工执行日志。 - - 价值:记录谁在何时基于什么证据做了什么判断。 - -5. 可回放评测资产 - - 由 `AlgorithmReplaySet` 与 `RiskEvaluationCase` 承载。 - - 价值:每次规则、本体或算法升级后都能复跑历史样本,防止误报率失控。 - -6. 实体标准化资产 - - 由 `FinancialEntityResolver` 和 `CanonicalEntityRegistry` 承载。 - - 价值:沉淀供应商、商户、酒店、银行户名、员工姓名等标准主体。 - -7. 可解释决策资产 - - 由 `DecisionTrace`、贡献项、不确定性原因、数据血缘承载。 - - 价值:让每个风险结论都能被审计、复核和反事实推演。 diff --git a/document/development/hermes-risk-graph-algorithm/TODO.md b/document/development/hermes-risk-graph-algorithm/TODO.md deleted file mode 100644 index 4ca6197..0000000 --- a/document/development/hermes-risk-graph-algorithm/TODO.md +++ /dev/null @@ -1,158 +0,0 @@ -# 数字员工财务行为图谱风险算法开发 TODO - -更新日期:2026-05-30 - -## 1. 调研与契约 - -- [x] 梳理现有风险相关数据来源:报销单、费用明细、票据、审批记录、规则命中、AgentRun、ToolCall、语义解析日志。[CONCEPT: 背景与问题] 证据:`RISK_SOURCE_AND_MOAT.md` 已记录 `ExpenseClaim`、`ExpenseClaimItem`、`RiskObservation`、`RiskObservationFeedback`、`HermesTaskExecutionLog`、`AgentRun`、`AgentToolCall`、`SemanticParseLog` 和知识库来源。 -- [x] 梳理现有数字员工技能和工作记录模型,确认员工技能详情、工作记录详情、知识制度记录详情的边界。[CONCEPT: 非目标] 证据:`DigitalEmployeesView.vue` 保持员工技能/工作记录页签,`DigitalEmployeeWorkRecords.vue` 负责完整详情页,`AuditDigitalEmployeeDetail.vue` 不引入知识图谱组件。 -- [x] 梳理分析看板现有数据来源和页面结构,确认风险看板作为独立页签的接入方式。[CONCEPT: 分析看板风险看板] 证据:`TopBar.vue` 的分析看板下拉已新增 `risk`,`OverviewView.vue` 已按 `dashboard=risk` 渲染独立风险看板。 -- [x] 定义 `RiskObservation` 后端字段、状态枚举、来源枚举和 JSON 字段结构。[CONCEPT: 统一风险观察模型] 证据:`server/src/app/models/risk_observation.py` 与 `server/src/app/schemas/risk_observation.py` 已实现。 -- [x] 定义图谱节点和边的最小字段,不急于引入图数据库。[CONCEPT: 实体图谱层] 证据:`RiskGraphNode.as_dict()` 输出 `canonical_key/canonical_id/ontology_parse_id/ontology_version`,`RiskGraphEdge.as_dict()` 输出 `source/evidence/metadata`,后端算法测试已覆盖。 -- [x] 定义单据详情风险证据链响应结构。[CONCEPT: API 契约建议] 证据:`riskObservations.js` 已归一单据风险观察字段,详情组件读取 `/risk-observations/claim/{claim_id}`。 -- [x] 定义风险看板聚合响应结构。[CONCEPT: API 契约建议] 证据:`RiskObservationDashboardRead` 已输出总览、分布、确认率、误报率和近期高风险记录。 -- [x] 定义数字员工工作记录关联风险观察响应结构。[CONCEPT: API 契约建议] 证据:`/api/v1/risk-observations/execution-log/{execution_log_id}` 已按执行日志返回观察列表。 -- [x] 明确不可复制壁垒资产清单:专有本体、对象中心事件日志、风险观察反馈池、人机共审行为数据、可回放评测资产。[CONCEPT: 不可复制壁垒设计] 证据:`RISK_SOURCE_AND_MOAT.md` 已明确专有本体、对象中心事件日志、风险观察反馈池、人机共审行为、可回放评测、实体标准化和可解释决策资产。 - -### 1.1 公开竞品资料校准 - -- [x] 复核用友公开资料中的端到端费控链路,确认 X-Financial 是否需要覆盖事前申请、商旅预订、报销提交、审批、付款、归档各阶段。[CONCEPT: 公开竞品资料借鉴] 证据:`PUBLIC_COMPETITOR_REFERENCE.md` 已记录用友公开资料中的事前申请、商旅预订、报销、审批、结算、分析和归档链路,并映射到 `ObjectCentricEvent`、`RiskObservation`、`RiskDataLineage`。 -- [x] 复核用友公开资料中的规则模板、预算刚柔控制、信用抽审和商旅推荐能力,映射为 `PolicyTemplateLibrary`、`PreControlRecommender`、`RiskSamplingPlanner`。[CONCEPT: 用友费用可借鉴模式] 证据:`PUBLIC_COMPETITOR_REFERENCE.md` 已将规则模板、预算刚柔控制、信用抽审和商旅推荐映射为 `PolicyTemplateLibrary`、`PreControlRecommender`、`RiskSamplingPlanner`、`ProfileBaselineUpdater`。 -- [x] 复核合思公开资料中的 AI 审核、人机共审、多凭证校验、时空推理和低置信度转人工能力,映射为 `MultiEvidenceReconciler`、`SpatioTemporalRiskEngine`、`HumanInLoopAutomationGate`。[CONCEPT: 合思费控可借鉴模式] 证据:`PUBLIC_COMPETITOR_REFERENCE.md` 已将合思公开资料中的 AI 审核、人机共审、多凭证和时空校验映射为 `HumanInLoopAutomationGate`、`DecisionTrace`、`MultiEvidenceReconciler`、`SpatioTemporalRiskEngine`、`RiskDataQualityGate`。 -- [x] 明确竞品资料只作为产品能力和方法论参考,不能作为内部算法实现依据。[CONCEPT: 资料边界] 证据:`PUBLIC_COMPETITOR_REFERENCE.md` 已写明只使用公开资料做产品能力和方法论校准,不推断竞品内部算法实现。 -- [x] 把竞品借鉴项转成 X-Financial 自有数据、可解释算法、可审计证据和可回放测试,不直接复制竞品页面或术语。[CONCEPT: 对当前方案的补强] 证据:`PUBLIC_COMPETITOR_REFERENCE.md` 已把竞品能力转译为自有财务本体、对象中心事件日志、画像基线、反馈池、回放集和解释资产。 - -### 1.2 本体与风险图谱桥接 - -- [x] 梳理现有 `/api/v1/ontology/parse`、`SemanticParseLog`、`scenario`、`intent`、`entities`、`risk_flags`、`missing_slots` 的当前字段和落库方式。[CONCEPT: 本体与风险图谱桥接] 证据:`RISK_SOURCE_AND_MOAT.md` 已记录 `OntologyParseRequest/OntologyParseResult` 字段,以及 `AgentRun.ontology_json` 与 `SemanticParseLog.*_json` 落库方式。 -- [x] 定义本体输出进入风险图谱的最小协议:`ontology_parse_id`、`ontology_version`、`domain`、`scenario`、`intent`、`entities`、`constraints`、`risk_signals`、`confidence`。[CONCEPT: 本体与风险图谱桥接] 证据:`OntologyRiskGraphMapping` 保留协议字段,`map_ontology_to_risk_graph()` 将本体结果转为图谱节点、边和标准风险信号。 -- [x] 定义本体实体到图谱节点的映射表,例如 `expense_type -> expense_type`、`document_type -> invoice / expense_claim`、`risk_signal -> risk_observation / risk_signal`。[CONCEPT: 本体与风险图谱桥接] 证据:`ONTOLOGY_NODE_TYPE_MAP` 已归一本体实体类型,测试断言 `employee` 进入 `employee:e001` 标准节点。 -- [x] 定义图谱边白名单,禁止数字员工自由创造运行时边类型。[CONCEPT: 本体与风险图谱桥接] 证据:`ALLOWED_EDGE_TYPES` 与 `ALLOWED_ONTOLOGY_EDGE_TYPES` 双层白名单已生效,测试断言本体边类型只来自白名单。 -- [x] 定义风险信号标准词典,把“住宿超标 / 酒店超标 / 差旅住宿异常”等近义说法归一到同一个 `risk_signal`。[CONCEPT: 本体与风险图谱桥接] 证据:`SIGNAL_ALIASES` 和 `normalize_risk_signals()` 已归一规则、本体、图谱信号,测试断言 `city_mismatch` 归一为 `location_mismatch`。 -- [x] 定义本体置信度降级策略,决定自动规则匹配、半自动复核和候选观察的边界。[CONCEPT: 本体与风险图谱桥接] 证据:`_gate_from_confidence()` 输出 `automatic/review/candidate_only`,低置信度测试断言 `gate == "candidate_only"`。 - -## 2. 数据模型 - -- [x] 新增风险观察模型和迁移脚本,包含主体、分数、等级、证据、来源、算法版本和反馈状态。[CONCEPT: 统一风险观察模型] 证据:`RiskObservationService.ensure_storage_ready()` 按当前项目模式运行时建表,模型包含主体、分数、证据、来源、版本和反馈状态。 -- [x] 新增图谱节点存储模型或兼容结构,第一版支持员工、部门、供应商、票据、单据、制度条款、规则、风险观察。[CONCEPT: 实体图谱层] 证据:`RiskObservation.graph_node_keys_json` 已保存观察关联节点键,算法结果保留完整节点契约。 -- [x] 新增图谱边存储模型或兼容结构,支持提交、包含、使用票据、关联供应商、命中规则、关联制度、相似案例等关系。[CONCEPT: 实体图谱层] 证据:`RiskObservation.graph_edge_keys_json` 已保存观察关联边键,算法图谱边包含白名单边类型。 -- [x] 为图谱节点补充 `ontology_type`、`canonical_key`、`canonical_id`、`ontology_parse_id`、`ontology_version` 字段。[CONCEPT: 本体与风险图谱桥接] 证据:`RiskGraphNode` 已补齐字段,算法测试断言所有节点序列化包含 `canonical_id/ontology_parse_id/ontology_version`。 -- [x] 为图谱边增加白名单校验和来源字段,记录边由规则、数字员工、本体解析还是人工反馈生成。[CONCEPT: 本体与风险图谱桥接] 证据:算法图谱边通过 `ALLOWED_EDGE_TYPES` 校验,本体边通过 `ALLOWED_ONTOLOGY_EDGE_TYPES` 校验,测试断言边序列化包含非空 `source`。 -- [x] 新增人工反馈模型或扩展现有反馈表,支持确认、误报、忽略、已处理等状态。[CONCEPT: 人工反馈校准] 证据:`RiskObservationFeedback` 与反馈接口已支持确认、误报、忽略、已处理和备注。 -- [x] 为风险观察补充 `control_stage`、`control_mode`、`automation_mode`、`confidence_score`、`sampling_strategy` 和 `evaluation_case_id`。[CONCEPT: 对当前方案的补强] 证据:`RiskObservation` 已通过兼容属性暴露 `sampling_strategy/evaluation_case_id`,API schema 已补字段,服务测试覆盖字段读取。 -- [x] 为风险观察补充 `ontology_parse_id`、`ontology_version`、`domain`、`scenario`、`intent`、`ontology_entities_json`、`risk_signals_json` 和 `canonical_subject_key`。[CONCEPT: 统一风险观察模型] 证据:`RiskObservation` 已从 `ontology_json` 暴露本体字段,`RiskObservationRead` 已输出,服务测试覆盖字段读取。 -- [x] 为风险观察增加必要索引:主体、单据、风险类型、等级、状态、来源、创建时间。[CONCEPT: 技术验收] 证据:`RiskObservation.__table_args__` 与字段索引覆盖主体、单据、等级、状态、信号、来源和时间。 -- [x] 设计对象中心财务事件日志模型,把申请、预算占用、票据上传、审批、退回、付款、归档、复盘统一为可回放事件。[CONCEPT: 不可复制壁垒设计] 证据:`process_mining.py` 已定义 `ObjectCentricEvent`,统一保存事件类型、发生时间、对象引用、来源、参与人和元数据,测试覆盖从报销单生成可回放事件。 -- [x] 设计风险观察反馈池字段,记录人工采纳、驳回、改写、退回、补件、升级审批、误报和线索来源。[CONCEPT: 不可复制壁垒设计] 证据:`RiskObservationFeedback` 已通过兼容属性暴露 `decision/candidate_rule_source/confidence_score/escalation_target/supplement_required`,测试覆盖反馈来源元数据。 -- [x] 设计算法回放集模型,绑定历史单据、本体版本、规则版本、算法版本和反馈标签。[CONCEPT: 不可复制壁垒设计] 证据:`replay.py` 已定义 `AlgorithmReplayCase/AlgorithmReplaySet/AlgorithmReplaySetBuilder`,测试覆盖从风险观察构建回放集。 - -## 3. 后端服务 - -- [x] 实现风险观察写入服务,统一接收规则、图谱、画像、数字员工产出。[CONCEPT: 总体架构] 证据:`RiskObservationService.upsert_observation()` 已接收 `RiskObservationDraft` 或 dict。 -- [x] 实现单据维度风险观察查询服务。[CONCEPT: 单据详情风险证据链] 证据:`list_claim_observations()` 与 `/api/v1/risk-observations/claim/{claim_id}` 已实现。 -- [x] 实现风险观察详情查询服务,返回证据链、基线、制度条款、相似案例和建议动作。[CONCEPT: API 契约建议] 证据:`get_observation()` 与详情接口返回 evidence、baseline、policy_refs、similar_case_claim_ids 和 decision_trace。 -- [x] 实现风险看板聚合服务,输出总览、分布、趋势、排行和算法效果。[CONCEPT: 分析看板风险看板] 证据:`summarize_dashboard()` 与 `/api/v1/risk-observations/dashboard` 已返回总览、分布、确认率、误报率和近期高风险。 -- [x] 实现数字员工运行记录关联风险观察查询服务。[CONCEPT: 数字员工工作记录详情] 证据:`list_execution_log_observations()` 与 `/execution-log/{execution_log_id}` 已实现。 -- [x] 实现人工反馈写入和状态流转服务。[CONCEPT: 人工反馈校准] 证据:`create_feedback()` 已同步更新 `status` 与 `feedback_status`。 -- [x] 在服务层保留算法版本和来源信息,避免风险结论不可追溯。[CONCEPT: 技术验收] 证据:`RiskObservationService.upsert_observation()` 保留 `source/algorithm_version`,规则中心写入保留 `rule_version`,服务测试已断言。 - -## 4. 算法与图谱 - -- [x] 实现同类基线计算方法,支持部门、职级、费用类型、城市等级等口径。[CONCEPT: 同类基线偏离] 证据:`server/src/app/algorithem/risk_graph/engine.py`,`pytest --ignore=.venv-ocr312 tests\test_financial_risk_graph_algorithm.py -q` 通过。 -- [x] 实现同类样本不足时的降级口径记录。[CONCEPT: 算法验收] 证据:`PeerBaseline(scope="insufficient_sample")` 与空风险测试覆盖。 -- [x] 实现确定性规则命中分 `S_rule` 的映射逻辑。[CONCEPT: 风险总分] 证据:`server/src/app/algorithem/risk_graph/signals.py` 与算法测试覆盖。 -- [x] 实现画像偏离分 `S_anomaly` 的计算逻辑。[CONCEPT: 同类基线偏离] 证据:金额偏离基线测试断言 `S_anomaly >= 90`。 -- [x] 实现图谱异常分 `S_graph` 的第一版信号累加逻辑。[CONCEPT: 图谱异常分] 证据:重复发票、拆单、频次、地点不一致、跨部门聚集信号已进入 `engine.py`。 -- [x] 实现制度语义相关分 `S_policy` 的占位契约,第一版可先接制度条款命中结果。[CONCEPT: 风险总分] 证据:`policy_refs_for_signal()` 已把制度约束型信号映射为 `policy.*`。 -- [x] 实现历史反馈分 `S_history`,基于相似案例退回率、确认率和误报率。[CONCEPT: 人工反馈校准] 证据:`RiskObservationService.build_history_stats()` 汇总确认/误报/退回反馈,Hermes 扫描已把历史统计注入 `S_history`。 -- [x] 实现风险总分和等级计算,保证输出可解释贡献项。[CONCEPT: 风险总分] 证据:`RiskObservationDraft.contribution_scores` 输出 `S_rule/S_anomaly/S_graph/S_policy/S_history`。 -- [x] 实现本体到图谱的映射服务,输入本体解析结果,输出标准图谱节点和白名单边。[CONCEPT: 本体与风险图谱桥接] 证据:`server/src/app/algorithem/risk_graph/ontology.py` 与白名单边测试覆盖。 -- [x] 实现风险信号归一化服务,保证规则中心、图谱引擎、风险看板使用同一 `risk_signal` 口径。[CONCEPT: 本体与风险图谱桥接] 证据:`normalize_risk_signals()` 已归一规则、本体和图谱信号。 -- [x] 实现本体置信度门控,低置信度只生成候选观察,不触发强拦截。[CONCEPT: 本体与风险图谱桥接] 证据:低置信度本体映射测试断言 `gate == "candidate_only"`。 -- [x] 实现多凭证一致性校验,覆盖单据、发票、流水、合同、行程、事前申请之间的字段一致性。[CONCEPT: 合思费控可借鉴模式] 证据:第一版已覆盖报销单金额、费用明细金额合计、声明票据数量和实际票据数量一致性,输出 `multi_evidence` 证据源,算法测试已覆盖金额和票据数量不一致。 -- [x] 实现时空一致性风险信号,覆盖时间、地点、行程、消费和开票关系。[CONCEPT: 合思费控可借鉴模式] 证据:第一版已覆盖报销发生日期、明细日期、报销地点和明细地点一致性,输出 `spatiotemporal` 证据源,算法测试已覆盖跨日期和跨地点异常。 -- [x] 实现自动化门控逻辑,按置信度、风险等级、证据覆盖和历史误报率决定辅助、半自动、自动模式。[CONCEPT: 对当前方案的补强] 证据:`_resolve_automation_mode()` 输出 `assist/manual_review/semi_auto_review/auto_hold`,测试覆盖半自动模式。 -- [x] 实现风险分层抽审策略,记录抽审口径、阈值和回放数据。[CONCEPT: 用友费用可借鉴模式] 证据:`sampling.py` 已实现 `RiskSamplingPlanner`,算法输出在 `decision_trace.sampling_strategy` 中保留策略、阈值、回放桶和原因,测试覆盖高风险进入 `focused_review/high_risk`。 -- [x] 建立风险评测样本集,包含正样本、负样本、反事实样本、噪声样本和历史误报样本。[CONCEPT: 合思费控可借鉴模式] 证据:`evaluation_cases.py` 已提供第一版可回放评测样本清单,覆盖 `positive/negative/counterfactual/noise/historical_false_positive`,算法测试断言分类完整。 - -### 4.1 深度算法壁垒模块 - -- [x] 实现对象中心事件日志构建器 `ObjectCentricProcessMiner`,把申请、报销、票据、付款、供应商、审批人等多对象事件统一沉淀。[CONCEPT: 对象中心过程挖掘] 证据:`ObjectCentricProcessMiner.build_from_claims()` 和 `build_from_dicts()` 已支持报销单快照与通用事件输入,测试覆盖 `claim_submitted/invoice_attached/risk_flagged` 等事件。 -- [x] 实现流程一致性检测 `ConformanceRiskDetector`,识别跳步审批、返工循环、付款前异常和流程绕行。[CONCEPT: 对象中心过程挖掘] 证据:`ConformanceRiskDetector.detect()` 已输出 `payment_before_approval/approval_bypass/rework_loop/process_bypass`,测试覆盖四类流程异常。 -- [x] 实现金融实体解析服务 `FinancialEntityResolver`,归一供应商、商户、酒店、银行户名和员工姓名。[CONCEPT: 实体解析与主数据归一] 证据:`entity_resolution.py` 已实现实体类型别名和标准主键归一,测试覆盖供应商/商户别名归一到同一 `vendor` 主体。 -- [x] 实现标准实体注册表 `CanonicalEntityRegistry`,维护图谱标准主体 ID 和人工确认记录。[CONCEPT: 实体解析与主数据归一] 证据:`CanonicalEntityRegistry` 支持标准主体 upsert、别名合并和人工确认记录,算法测试覆盖别名合并与 `confirmed_by`。 -- [x] 实现异构图特征构建器 `HeterogeneousRiskGraphFeatureBuilder`,输出元路径、中心性、团簇、邻域风险密度等特征。[CONCEPT: 异构图与时序图学习] 证据:`features.py` 已输出节点类型、边类型、元路径、度中心性、连通簇和邻域风险密度,算法测试覆盖重复发票图谱特征。 -- [x] 实现时序图监控 `TemporalRiskGraphMonitor`,监控关系突增、消失、迁移和异常传播。[CONCEPT: 异构图与时序图学习] 证据:`temporal.py` 已比较前后图谱快照,输出关系新增、删除、突增、目标迁移和风险传播,算法测试覆盖边变化检测。 -- [x] 实现多模型异常检测集成,组合稳健统计、孤立森林、局部离群、时间突变和周期偏离。[CONCEPT: 多模型异常检测组合] 证据:`anomaly_models.py` 已实现 `MultiModelAnomalyDetector`,组合 `robust_statistics/isolation_forest_proxy/local_outlier_factor_proxy/temporal_jump/periodic_deviation`,测试已覆盖五类信号。 -- [x] 实现决策追踪 `DecisionTrace`,记录决策表输入、命中行、输出、版本和解释。[CONCEPT: 决策建模与策略即代码] 证据:`decisioning.py` 已定义 `DecisionTrace` 与 `DecisionTraceBuilder`,算法输出保留公式、算法版本、输入分、输出分、命中行和元数据,测试已断言。 -- [x] 实现风险解释贡献字段 `feature_contributions_json`、`uncertainty_reasons_json` 和 `explanation_template_key`。[CONCEPT: 可解释与不确定性控制] 证据:`DecisionTraceBuilder` 已输出贡献项、不确定性原因和解释模板键,测试覆盖高风险贡献项与低质量封顶原因。 -- [x] 实现反事实风险建议 `CounterfactualRiskAdvisor`,输出降低风险分的可执行补救动作。[CONCEPT: 因果分析与反事实建议] 证据:`counterfactual.py` 已根据规则、基线、图谱和数据质量贡献输出可执行降分动作,测试覆盖四类建议。 -- [x] 实现控制效果分析 `ControlEffectAnalyzer`,评估规则、抽审策略或数字员工上线前后的风险变化。[CONCEPT: 因果分析与反事实建议] 证据:`control_effect.py` 已比较上线前后风险数量、均分、高风险率、确认率和误报率变化,测试已覆盖。 -- [x] 实现风险数据血缘 `RiskDataLineage`,记录风险观察使用的数据表、文档、OCR、AgentRun、规则版本和本体版本。[CONCEPT: 数据血缘与质量门禁] 证据:`lineage.py` 已定义 `RiskDataLineage` 和构建器,支持数据表、文档、OCR、AgentRun、ToolCall、规则版本、本体版本、算法版本和事件来源,测试已覆盖。 -- [x] 实现风险数据质量门禁 `RiskDataQualityGate`,阻止低质量数据触发强风控结论。[CONCEPT: 数据血缘与质量门禁] 证据:`quality.py` 已实现必填字段和上下文质量门禁,低质量单据高分结论会封顶为 69,算法测试覆盖缺失员工信息时禁止输出高风险。 - -## 5. 数字员工 - -- [x] 补充制度整理员工输出契约,确保制度条款可被风险观察引用。[CONCEPT: 数字员工能力分层] 证据:`policy_knowledge_contract.py` 已定义制度整理报告、知识条目、来源引用和 `risk_policy_refs`,技能文件已补输出要求,测试覆盖风险条款引用。 -- [x] 新增或扩展风险扫描员工,扫描新增单据和异常关系并写入风险观察。[CONCEPT: 数字员工能力分层] 证据:`HermesRiskScannerService` 已接入 `evaluate_financial_risk_graph()`,并写入现有 `HermesRiskReport` 与单据风险标记。 -- [x] 将风险扫描和员工画像巡检注册到数字员工的员工技能列表。[CONCEPT: 数字员工能力分层] 证据:新增 `financial-risk-graph-scanner`、`employee-behavior-profile-scanner` 技能包,并通过任务资产种子和补齐逻辑进入员工技能列表。 -- [x] 员工技能详情的立即运行按技能类型调用真实后端任务。[CONCEPT: 数字员工能力分层] 证据:`OrchestratorExecutionEngine` 已按 `global_risk_scan`、`employee_behavior_profile_scan`、`finance_policy_knowledge_organize` 分发到真实服务。 -- [x] 新增或扩展画像更新员工,定期更新员工、部门、供应商、费用类型基线。[CONCEPT: 数字员工能力分层] 证据:`ProfileBaselineUpdater` 已生成员工、部门、供应商、费用类型四类画像基线,`HermesEmployeeProfileScannerService.scan_employee_profiles()` 已返回 `baseline_summary`;`pytest --ignore=.venv-ocr312 tests/test_risk_graph_profile_baselines.py tests/test_hermes_employee_profile_baselines.py -q` 通过。 -- [x] 新增风险线索归集员工输出,线索必须带事实、规则命中、证据来源和人工复核标记。[CONCEPT: 数字员工能力分层] 证据:数字员工任务与技能已注册为“风险线索归集”,`test_digital_employee_skill_catalog.py` 已锁定不输出候选规则或自动发布语义。 -- [x] 数字员工运行完成后写入处理范围、处理数量、风险观察数量和失败原因。[CONCEPT: 数字员工工作记录详情] 证据:`HermesScheduler` 已写入风险图谱巡检摘要,失败仍沿用执行日志 `error_trace`。 -- [x] 确认 UI 上继续使用“数字员工 / 员工技能 / 工作记录”等业务命名,不在普通用户界面暴露内部实现名。[CONCEPT: 用户与场景] 证据:`DigitalEmployeesView.vue` 页签文案为“员工技能 / 工作记录”,普通界面未展示内部 Hermes 名称。 - -## 6. 前端:单据详情 - -- [x] 在单据详情风险说明附近新增风险证据链区块。[CONCEPT: 单据详情风险证据链] 证据:`RiskObservationEvidenceCard.vue` 已接入 `TravelRequestDetailView.vue`,按单据 `claimId` 拉取风险观察。 -- [x] 展示风险结论、证据链节点、基线对比、制度条款、历史相似案例和建议动作。[CONCEPT: 单据详情风险证据链] 证据:详情证据链已展示风险分、贡献分、证据、图谱关系、基线、建议、制度引用和相似案例。 -- [x] 支持点击风险观察进入风险观察详情或展开详情。[CONCEPT: 前端入口关系] 证据:`RiskObservationEvidenceCard.vue` 已支持多条风险观察点击切换当前详情,详情区包含贡献分、证据、图谱关系、基线建议、制度案例和反馈历史。 -- [x] 无风险观察时不占用主流程空间。[CONCEPT: 前端测试] 证据:`RiskObservationEvidenceCard.vue` 在非加载、无错误且无观察记录时不渲染卡片。 -- [x] 普通审批人只能看到当前单据相关证据,不展示无关员工长期敏感画像。[CONCEPT: 用户与场景] 证据:`RiskObservationEvidenceCard.vue` 只调用 `fetchClaimRiskObservations(claimId)`,`risk-observation-evidence-card.test.mjs` 断言不引入员工画像和知识图谱组件。 - -## 7. 前端:数字员工工作记录详情 - -- [x] 工作记录列表维持通用列表样式,详情点击进入完整详情页。[CONCEPT: 数字员工工作记录详情] 证据:`DigitalEmployeeWorkRecords.vue` 继续使用 `EnterpriseListPage`,点击行进入非侧栏完整详情。 -- [x] 工作记录详情展示本次扫描范围、处理实体数量、风险观察数量和失败原因。[CONCEPT: 数字员工工作记录详情] 证据:`DigitalEmployeeRunProducts.vue` 展示扫描单据、风险观察、图谱节点/关系、画像快照和失败摘要。 -- [x] 工作记录详情展示本次任务产出的风险观察列表。[CONCEPT: 数字员工工作记录详情] 证据:`DigitalEmployeeRunProducts.vue` 通过 `fetchRunRiskObservations()` 读取本次 Run 生成的风险观察并渲染列表。 -- [x] 知识制度整理类记录展示知识制度记录图谱,员工技能详情不展示该图谱。[CONCEPT: 非目标] 证据:`node --test web/tests/risk-observation-evidence-card.test.mjs web/tests/digital-employee-work-record-products.test.mjs` 通过,覆盖员工技能详情不渲染 `KnowledgeIngestGraphView`、工作记录详情按任务类型解析产物和局部展开风险观察。 -- [x] 风险扫描类记录展示小范围异常关系,不展示全量图谱。[CONCEPT: 图谱体现方式] 证据:`DigitalEmployeeRunProducts.vue` 点击风险观察后只展开当前观察的图谱节点、关系、证据和制度建议。 - -## 8. 前端:风险看板 - -- [x] 在分析看板中增加“风险看板”页签。[CONCEPT: 分析看板风险看板] 证据:分析看板下拉新增“风险看板”,并渲染 `RiskObservationDashboard.vue`。 -- [x] 增加风险总览卡片:新增风险数、高风险待处理数、涉及金额、已确认风险数、误报数量。[CONCEPT: 分析看板风险看板] 证据:`riskKpiMetrics` 已改为新增风险数、高风险待处理、涉及金额、已确认风险、误报数量和待复核,接口补充 `total_amount`。 -- [x] 增加风险分布图:部门、费用类型、风险类型、供应商、员工职级。[CONCEPT: 分析看板风险看板] 证据:`RiskObservationDashboard.vue` 新增业务维度分布区,统一读取 `department/expense_type/risk_type/supplier/employee_grade` 分布字段。 -- [x] 增加风险趋势图:7 天 / 30 天走势、高风险占比、处理完成率。[CONCEPT: 分析看板风险看板] 证据:`RiskDailyTrendChart.vue` 已展示风险观察与高风险趋势;风险看板时间窗口支持 7/30/90 天切换,处理完成率由闭环效果区承接。 -- [x] 增加异常排行:部门、员工、供应商、规则、费用类型。[CONCEPT: 分析看板风险看板] 证据:风险观察聚合接口输出 `top_departments/top_employees/top_suppliers/top_rules/top_expense_types`,前端异常排行区已展示。 -- [x] 增加算法效果:规则命中数、图谱异常命中数、人工确认率、误报率、待复核线索数。[CONCEPT: 分析看板风险看板] 证据:风险看板已展示平均风险分、人工确认数、误报样本和待复核线索口径,规则/图谱来源通过来源分布体现。 -- [x] 风险看板所有数据通过风险观察聚合接口读取,不直接拼接业务散表。[CONCEPT: 技术验收] 证据:后端已提供 `/api/v1/risk-observations/dashboard` 作为统一聚合源。 - -## 9. 规则与反馈闭环 - -- [x] 规则中心执行结果写入风险观察池或与风险观察建立关联。[CONCEPT: 统一风险观察模型] 证据:`RiskObservationService.upsert_platform_risk_flags()` 已接收规则中心风险命中,报销提交预审会同步写入风险观察池。 -- [x] 风险观察支持人工确认、误报、忽略、已处理等反馈。[CONCEPT: 人工反馈校准] 证据:反馈接口支持 `confirm/false_positive/ignore/resolve/comment`。 -- [x] 风险线索归集员工根据反馈整理待复核线索,不生成、不改写、不上线规则。[CONCEPT: 非目标] 证据:技能配置统一写入 `writes_rules=false`、`role_boundary` 和 `allowed_outputs`,目录测试覆盖不再注册候选规则技能名或规则优化输出格式。 -- [x] 风险观察详情展示反馈历史和当前处理状态。[CONCEPT: 技术验收] 证据:详情模型保留 `status`、`feedback_status`,反馈历史由 `RiskObservationFeedback` 存储。 -- [x] 风险看板展示人工确认率、误报率和待复核线索数量。[CONCEPT: 分析看板风险看板] 证据:聚合接口已输出 `confirmation_rate` 和 `false_positive_rate`;待复核线索口径由风险观察与人工复核状态聚合。 - -## 10. 测试与验证 - -- [x] 后端模型测试:风险观察序列化、状态流转、JSON 字段兼容。[CONCEPT: 后端测试] 证据:`server/tests/test_risk_observations_service.py` 覆盖 upsert、dashboard、feedback 状态流转。 -- [x] 后端算法测试:同类基线、降级口径、风险总分、图谱异常分。[CONCEPT: 算法与公式] 证据:`server/tests/test_financial_risk_graph_algorithm.py`,`pytest --ignore=.venv-ocr312 tests\test_financial_risk_graph_algorithm.py -q` 通过。 -- [x] 后端接口测试:单据风险观察、风险观察详情、风险看板聚合、工作记录关联风险观察。[CONCEPT: API 契约建议] 证据:`pytest --ignore=.venv-ocr312 tests\test_financial_risk_graph_algorithm.py tests\test_risk_observations_service.py -q` 本地与 Docker 均 7 passed。 -- [x] 前端测试:单据详情证据链展示和空状态。[CONCEPT: 前端测试] 证据:`node --test web/tests/risk-observation-evidence-card.test.mjs` 通过 3 项断言。 -- [x] 前端测试:员工技能详情不显示知识制度图谱。[CONCEPT: 回归测试] 证据:`web/tests/digital-employee-work-record-products.test.mjs` 断言员工技能详情不渲染 `KnowledgeIngestGraphView`。 -- [x] 前端测试:工作记录详情只展示对应任务的图谱和风险观察。[CONCEPT: 回归测试] 证据:`web/tests/digital-employee-work-record-products.test.mjs` 覆盖任务类型识别、产物类型解析和风险观察局部展开。 -- [x] 前端测试:风险看板筛选、趋势、排行和卡片数据一致。[CONCEPT: 前端测试] 证据:`node --test web/tests/risk-observation-dashboard.test.mjs` 通过 3 项断言,覆盖窗口筛选、趋势、排行和 KPI 数据源联动。 -- [x] 在 Docker 容器中执行后端定向测试,命令形态为 `docker exec x-financial-main sh -lc "cd /app && pytest -q"`,测试超时控制在 60s 内。[CONCEPT: 后端测试] 证据:`docker exec x-financial-main sh -lc "cd /app/server && python -m pytest --ignore=.venv-ocr312 tests/test_financial_risk_graph_algorithm.py tests/test_risk_observations_service.py -q"` 已通过 7 passed。 -- [x] 执行前端构建验证,确认风险看板和详情变更不破坏现有页面。[CONCEPT: 前端测试] 证据:`npm.cmd run build` 已通过;`/app/overview` 与 `/api/v1/risk-observations/dashboard` 本地 HTTP 检查返回 200。 - -## 11. 验收 - -- [x] 单据详情能解释单个风险:结论、证据链、基线、制度条款、历史案例、建议动作齐全。[CONCEPT: 业务验收] 证据:`RiskObservationEvidenceCard.vue` 展示风险结论、贡献分、证据、图谱关系、基线建议、制度引用、相似案例和反馈历史;`node --test web/tests/risk-observation-evidence-card.test.mjs` 通过 3 项断言。 -- [x] 数字员工工作记录能解释一次任务:范围、数量、产出、失败、风险观察齐全。[CONCEPT: 业务验收] 证据:`DigitalEmployeeRunProducts.vue` 展示扫描范围、处理数量、任务产物、失败摘要和本次风险观察;`node --test web/tests/digital-employee-work-record-products.test.mjs` 通过 4 项断言。 -- [x] 风险看板能解释整体态势:总览、分布、趋势、排行、算法效果齐全。[CONCEPT: 业务验收] 证据:`RiskObservationDashboard.vue` 已包含总览 KPI、业务维度分布、趋势、信号排行、异常排行、算法闭环效果,`npm.cmd run build` 通过。 -- [x] 所有风险输出统一进入风险观察模型或兼容结构。[CONCEPT: 技术验收] 证据:Hermes 风险扫描已调用 `RiskObservationService.upsert_observation()`。 -- [x] 高风险观察至少包含两类证据来源。[CONCEPT: 算法验收] 证据:`_apply_evidence_source_gate()` 对单一证据源高风险封顶为 69,算法测试覆盖单源封顶和多源高风险通过。 -- [x] 风险观察保留算法版本、来源、时间、反馈状态。[CONCEPT: 技术验收] 证据:`RiskObservation` 模型包含 `algorithm_version`、`source`、`created_at`、`updated_at`、`feedback_status`。 diff --git a/document/development/hermes-risk-graph-algorithm/index.html b/document/development/hermes-risk-graph-algorithm/index.html deleted file mode 100644 index 0c544e9..0000000 --- a/document/development/hermes-risk-graph-algorithm/index.html +++ /dev/null @@ -1,1483 +0,0 @@ - - - - - - X-Financial 财务行为图谱风险引擎核心算法说明 - - - -
- - -
-
-
-
核心中的核心算法
-

财务行为图谱风险引擎

-

- 这套算法不是单一模型,而是把专有本体、对象中心事件日志、财务行为图谱、画像基线、规则命中、人工反馈和可回放评测集组合成一套持续进化的风险控制系统。它的目标不是“给一个风险分”,而是解释清楚谁异常、哪里异常、依据是什么、历史如何处理、现在应该怎么做。 -

-
-
-
5
-
不可复制资产
-
专有本体、事件日志、反馈池、人机共审、回放评测。
-
-
-
8
-
第一版风险信号
-
重复票据、超标准、预算超额、附件缺失等。
-
-
-
10+
-
算法模块
-
本体、实体解析、过程挖掘、图特征、异常检测。
-
-
-
1
-
统一产物
-
所有风险最终沉淀为 `RiskObservation`。
-
-
-
-
- -
-
-
-
-

不可复制壁垒

-
- 复杂算法本身可以被模仿,真正难复制的是长期运行中积累的语义、过程、反馈和评测资产。 -
-
- Core Barrier -
- -
-
- 1 -

专有财务语义本体

-

把制度条款、费用类型、风险信号、审批场景、预算科目和票据要求归一为公司自己的语义协议。

-
-
- 2 -

对象中心事件日志

-

把申请、预算、票据、审批、付款、归档、复盘统一沉淀为可回放事件。

-
-
- 3 -

风险观察反馈池

-

每条风险都有证据路径、规则命中、画像偏离、图谱异常、人工结果和算法版本。

-
-
- 4 -

人机共审行为数据

-

记录采纳、驳回、补件、退回、升级审批、标记误报和候选规则生成。

-
-
- 5 -

可回放评测资产

-

用同一批历史单据、本体版本、规则版本、算法版本和反馈标签评估新算法。

-
-
- -
- 结论:别人可以复制页面、名词和公开算法,但复制不了真实审批过程、公司制度语义、历史处理结果和长期回放集。算法壁垒必须从第一天开始沉淀这些资产。 -
-
-
- -
-
-
-
-

总体架构

-
- 整体架构分为语义、事件、图谱、画像、推理、观察、反馈七层。每层只解决一个问题,避免规则中心、图谱引擎和数字员工职责混乱。 -
-
- Seven Layers -
- -
-
-
语义层
-
-

本体解析

识别场景、意图、费用类型、风险信号、约束条件。

-

制度条款

把制度转成可引用、可版本化、可匹配的条款。

-

标准词典

统一供应商、费用类型、票据类型和风险信号。

-
-
-
-
事件层
-
-

业务事件

申请、提交、上传票据、审批、退回、付款、归档。

-

多对象日志

一个事件同时绑定单据、票据、员工、供应商和预算。

-

运行追踪

关联 AgentRun、数字员工任务和工具调用结果。

-
-
-
-
图谱层
-
-

节点

员工、部门、供应商、票据、单据、制度条款、规则。

-

提交、包含、使用票据、关联供应商、命中规则。

-

证据路径

形成可展示、可审计、可回放的风险解释链。

-
-
-
-
推理层
-
-

规则命中

确定性规则提供强证据,仍由规则中心治理。

-

画像偏离

员工、部门、供应商和费用类型的同类基线。

-

图谱异常

供应商集中、重复票据、审批链异常、时空冲突。

-
-
-
-
反馈层
-
-

人工确认

采纳、误报、忽略、退回、补件、升级审批。

-

离线回放

用历史样本评估规则和算法版本。

-

候选优化

生成规则候选、制度更新候选和抽审策略调整。

-
-
-
-
-
- -
-
-
-
-

本体与风险图谱桥接

-
- 本体不是一个辅助字段,而是风险图谱的语义骨架。它决定节点类型、边类型、规则适用范围、风险信号口径和看板聚合维度。 -
-
- Ontology First -
- -
-
-

本体输出最小协议

-
ontology_parse_id
-ontology_version
-domain
-scenario
-intent
-entities
-constraints
-risk_signals
-confidence
-
-
-

图谱节点标准字段

-
node_type
-ontology_type
-canonical_key
-canonical_id
-source_object_type
-source_object_id
-ontology_parse_id
-ontology_version
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
本体实体图谱节点作用示例
expense_type费用类型节点统一规则范围、画像基线和风险看板聚合。hotel, travel, entertainment
risk_signal风险信号节点 / 风险观察把“住宿超标”“酒店超标”等近义说法合并。accommodation_standard_deviation
document_type单据、票据、合同、流水支撑多凭证一致性校验。invoice, payment_record
policy_clause制度条款节点让风险结论能引用制度依据。差旅住宿标准第 3 条
vendor供应商 / 商户节点支撑供应商集中、别名归一、关联交易识别。上海某酒店管理有限公司
-
- -
- 关键约束:图谱边必须来自白名单,例如 submitteduses_invoicepaid_to_vendormatches_policy_clausetriggered_rule。数字员工不能自由创造运行时边类型。 -
-
-
- -
-
-
-
-

RiskObservation 是唯一风险产物

-
- 规则命中、画像偏离、图谱异常、制度条款和人工反馈最终都必须合成风险观察。它是单据详情、工作记录、风险看板和算法回放的统一事实表。 -
-
- Single Output -
- -
-
-

输入

-
    -
  • 本体解析结果
  • -
  • 规则命中结果
  • -
  • 画像基线偏离
  • -
  • 图谱关系异常
  • -
  • 历史反馈和相似案例
  • -
-
-
-

输出

-
    -
  • 风险分和风险等级
  • -
  • 证据链和制度依据
  • -
  • 建议动作和自动化模式
  • -
  • 算法版本和置信度
  • -
  • 人工反馈状态
  • -
-
-
-

用途

-
    -
  • 单据详情解释风险
  • -
  • 工作记录展示任务产出
  • -
  • 风险看板聚合态势
  • -
  • 规则优化和误报分析
  • -
  • 离线回放和算法评测
  • -
-
-
- -
-

核心结构

-
RiskObservation
-  subject_type / subject_id
-  risk_type / risk_signals_json
-  severity / score / confidence_score
-  ontology_parse_id / ontology_version
-  domain / scenario / intent
-  evidence_items_json / evidence_path_json
-  related_policy_clauses_json
-  comparable_baseline_json
-  suggested_actions_json
-  source_type / source_id
-  automation_mode / control_stage / control_mode
-  algorithm_version / feedback_status
-
-
-
- -
-
-
-
-

风险评分模型

-
- 第一版采用可解释加权模型,不用黑盒模型直接给最终结论。复杂模型只提供候选证据,强结论必须能解释。 -
-
- Explainable Score -
- -
-
-risk_score = clip( - 0.35 * S_rule -+ 0.25 * S_anomaly -+ 0.20 * S_graph -+ 0.15 * S_policy -+ 0.05 * S_history, - 0, 100 -) -
-
- S_rule 来自规则中心命中,S_anomaly 来自画像基线偏离,S_graph 来自图谱关系异常,S_policy 来自制度语义,S_history 来自历史反馈。 -
-
- -
-
-

同类基线偏离

-
deviation = (x - median(peer)) / max(IQR(peer), epsilon) -S_anomaly = 100 * sigmoid(k * (deviation - tau))
-
用于金额、频次、天数、退回率等指标。样本不足时必须记录降级口径。
-
-
-

图谱异常分

-
S_graph = min(100, sum(w_i * g_i))
-
候选信号包括重复票据、供应商集中、审批链异常、时空冲突和相似单据异常。
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
分数项证据来源可解释依据是否可单独强拦截
S_rule规则中心 / 决策表规则版本、命中条件、输入快照。强制度规则可拦截。
S_anomaly画像基线同部门、同职级、同费用类型分位偏离。不可单独拦截。
S_graph图谱路径供应商集中、重复票据、异常审批路径。高证据覆盖时可复核拦截。
S_policy制度条款费用说明、票据、制度条款是否一致。需结合规则和证据。
S_history人工反馈相似单据退回率、确认率、误报率。不单独拦截,影响权重和门控。
-
-
-
- -
-
-
-
-

证据链如何展示

-
- 图谱不要默认展示成全量关系网。产品上要展示小范围、场景化、可解释的证据链。 -
-
- Evidence Path -
- -
-
员工张三,P8,研发中心
-
单据差旅报销 4,860 元
-
票据酒店发票,1,260 元/晚
-
供应商上海某酒店
-
基线同级别 P90 为 760 元/晚
-
制度住宿标准第 3 条
-
历史相似 12 笔,8 笔退回
-
- -
-
-

单据详情

-

面向审批人,解释当前单据为什么异常、应该怎么处理。

-
-
-

工作记录详情

-

面向管理员,解释数字员工本次任务处理了哪些实体、发现了哪些风险。

-
-
-

风险看板

-

面向财务和管理层,展示整体风险态势、算法效果和抽审结果。

-
-
-
-
- -
-
-
-
-

深度算法层

-
- 这些模块构成算法复杂度,但必须全部回到可解释证据和 `RiskObservation`,不能变成不可审计黑盒。 -
-
- Algorithm Stack -
- -
-
-

对象中心过程挖掘

-

把申请、票据、预算、审批、付款、供应商放入多对象事件日志,识别跳步审批、流程绕行、返工循环和付款前异常。

-
-
-

实体解析与主数据归一

-

归一供应商、商户、酒店、银行户名、员工姓名,避免同一主体被拆成多个节点。

-
-
-

异构图与时序图特征

-

计算员工、部门、供应商、票据、规则、制度之间的元路径、中心性、邻域风险密度和关系突增。

-
-
-

多模型异常检测组合

-

组合稳健统计、孤立森林、局部离群、时间突变和周期偏离,但只作为候选风险证据。

-
-
-

决策建模与策略即代码

-

把规则中心的确定性规则拆成决策表、策略运行和决策追踪,保证版本化和可审计。

-
-
-

反事实风险建议

-

给出降低风险分的可执行补救动作,例如补充酒店水单、选择协议酒店或增加预算负责人复核。

-
-
-

数据血缘与质量门禁

-

记录风险观察使用了哪些表、文档、OCR、AgentRun、规则版本和本体版本;低质量数据不触发强风控。

-
-
-

可解释与不确定性控制

-

保存特征贡献、置信度、低置信度原因和人工复核要求,让每个结论都能被复查。

-
-
-
-
- -
-
-
-
-

人机共审门控

-
- 系统不应让 AI 直接通过或驳回单据。自动化必须由置信度、风险等级、证据覆盖、历史误报率和金额影响共同决定。 -
-
- Human in the Loop -
- -
-
-if confidence >= theta_auto - and severity <= medium - and evidence_coverage >= 2 - and false_positive_rate <= alpha: - automation_mode = "auto" -elif confidence >= theta_semi - and evidence_coverage >= 1: - automation_mode = "semi_auto" -else: - automation_mode = "assist" -
-
- `assist` 只给建议,`semi_auto` 可半自动但保留抽审,`auto` 只允许低风险、高置信、证据充分、历史误报低的场景。 -
-
- -
-

高风险

全量复核,必须展示完整证据链和制度依据。

-

中风险

按风险类型、金额和历史误报率进入抽审。

-

低风险

可进入小比例随机抽审,用于监控漏报。

-

低置信

只生成候选观察,不触发强拦截。

-
-
-
- -
-
-
-
-

产品体现

-
- 核心算法不能只存在后端。它必须在用户能理解的地方体现:详情解释单点风险,看板解释整体态势,工作记录解释数字员工产出。 -
-
- Product Surface -
- -
-
-
单据详情风险证据链、基线对比、制度条款、建议动作。
-
工作记录详情任务范围、处理数量、风险观察、异常关系。
-
风险看板总览、分布、趋势、排行、算法效果。
-
规则中心规则定义、版本、测试、发布、候选规则审核。
-
画像详情员工、部门、供应商和费用类型长期基线。
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
页面用户回答的问题数据来源
单据详情审批人这张单为什么异常,应该怎么处理。RiskObservation + evidence_path
数字员工工作记录管理员这次任务处理了什么,产出了什么风险。AgentRun + RiskObservation
风险看板财务 / 管理层整体风险态势、确认率、误报率、抽审效率。RiskObservation 聚合
规则中心管理员规则如何定义、测试、发布和回滚。risk_rules + rule_runs
-
-
-
- -
-
-
-
-

实施路线

-
- 第一版不要一次引入全部复杂算法。先打通最小闭环,然后逐步增强图谱、过程挖掘和评测体系。 -
-
- Execution Plan -
- -
-
-
- 建立本体桥接和 RiskObservation -

把本体解析、规则命中、画像偏离、图谱路径和人工反馈统一进风险观察模型。

-
-
-
-
- 实现第一批 8 个高价值风险信号 -

重复票据、金额超标准、预算超额、附件缺失、报销发票金额不一致、申请报销不一致、时间地点不一致、供应商集中异常。

-
-
-
-
- 落地三个产品入口 -

单据详情风险证据链、数字员工工作记录详情、分析看板风险看板。

-
-
-
-
- 沉淀反馈与回放集 -

记录人工采纳、误报、退回、补件和升级审批;建立历史样本回放能力。

-
-
-
-
- 引入深度算法模块 -

逐步加入实体解析、对象中心过程挖掘、异构图特征、异常检测组合和反事实建议。

-
-
-
-
-
- -
- -
-
- - -
- - diff --git a/document/development/intelligent-expense-control-platform/index.html b/document/development/intelligent-expense-control-platform/index.html deleted file mode 100644 index dbec979..0000000 --- a/document/development/intelligent-expense-control-platform/index.html +++ /dev/null @@ -1,2294 +0,0 @@ - - - - - - X-Financial 智能费控平台核心说明文档 - - - -
- - -
-
-
-
-
X-Financial / Intelligent Expense Control
-

从报销工具,到企业费用智能操作系统

-

- 智能费控平台的核心价值,不是把传统审批流程搬到线上, - 而是把费用、预算、组织、制度、票据、行为画像和智能体能力 - 连接成一套可解释、可追溯、可持续进化的企业财务风控中枢。 -

-
- 面向管理层 - 面向财务共享 - 面向研发评审 - HTML 单页文档 -
-
- -
-
-
2 层
-
双智能体循环
-
User Agent 处理用户操作;Hermes 在后台持续巡检数据与流转风险。
-
-
-
10+
-
业务模块
-
覆盖总览、单据、预算、规则、数字员工、知识库、日志和设置。
-
-
-
8 字段
-
本体协议核心
-
domain、scenario、intent、entities、time_range、constraints、risk_signals、next_step。
-
-
-
4 类
-
画像与风控算法
-
申请人费用画像、员工行为画像、预算费用模型、规则/本体/RAG 分析。
-
-
-
-
- -
-
-
01 / WHY
-

为什么要做智能费控平台

-

- 智能费控不是把报销审批电子化,而是把企业每一笔支出变成可理解、可预测、可解释的经营信号。 - 当前,在金税四期深化、数电发票单轨制全面普及的政策背景下,传统的“后置流程型”费控已被逼入死胡同,企业必须构建全链路智能费控平台。 -

-
- -
-

- 第一,数电票时代倒逼全链路数字化。随着全国数电发票的单轨制落地,发票的真伪验重、多系统抵扣、合规归档以及全生命周期的追踪已无法通过传统人工肉眼或零散的OCR识别来解决。系统必须具备在发票导入瞬间进行结构化解析、关联交易比对、业务事由交叉匹配的自动化能力,实现“开票即采集、采集即验真、入账即归档”。 -

-

- 第二,企业从“事后核销”向“事前控制”的主动性跨越。传统ERP与报销系统核心是“记账与流程审批”,当员工提交报销单时,费用早已产生。智能费控利用 RAG 知识检索、预算实时联动,在费用申请阶段甚至消费发生的瞬间(如因公商旅预订)就进行预算额度校验与制度约束,使费控前置到决策端。 -

-

- 第三,费用舞弊与异常的隐性化、复杂化。根据 ACFE 2024 年《全球职业舞弊与滥用报告》显示,全球企业中约有 15% 的舞弊案件与费用报销直接相关,且平均潜伏期长达 18 个月。传统的强硬制度配置只能拦截“超标准”、“无附件”等显性异常,但对于拆单报销、异地多点异常消费、同组偏离度过高、长期合作供应商异常开票等隐性风控,需要基于大数据画像和语义关系的图谱检测。 -

-
- -
-
- 59% - Gartner 2025 年调研显示,财务 AI 采用率已达到约六成,知识管理、应付自动化和异常检测是高频用例。 -
-
- 85% - McKinsey CFO Pulse 提到,多数 CFO 期待 AI 生成洞察、减少手工分析,把财务人员释放到更高价值工作。 -
-
- 25% - Salesforce 2025 年 CFO 调研显示,CFO 平均把约四分之一 AI 预算投向 AI Agent,数字劳动力进入预算层。 -
-
- -
-
- 1. 从事后核销,变成事前控制 -

- 传统系统往往在报销单提交后才发现问题,智能费控可以在申请阶段就识别预算余量、 - 费用类型、地点、票据要求和制度约束。这样报销不是最后一关,而是从费用发生前就开始的控制链路。 -

-
-
- 2. 从人找规则,变成规则找风险 -

- 制度、Excel 规则、风险 JSON、知识库和历史记录被统一纳入规则中心与本体语义层, - 系统可以自动给出命中原因、制度依据和补正建议,减少审批人凭经验反复判断。 -

-
-
- 3. 从部门口径,变成企业费用画像 -

- 部门、岗位、职级、费用类型、预算池、审批质量和 AI 协作记录共同构成画像, - 让财务看到“为什么这个单据值得关注”,也让部门负责人知道费用结构是否偏离经营节奏。 -

-
-
- 4. 从流程系统,变成智能运营中枢 -

- Hermes 数字员工可以按计划巡检风险、生成报告、汇总异常、沉淀优化候选, - 让财务团队从重复检查转向规则治理、预算策略、风险决策和经营分析。 -

-
-
- -
-
一句话定位
-

- 智能费控平台不是“更漂亮的报销页面”,而是企业经营数据进入财务风控体系的语义入口, - 也是未来 AI 财务中台最容易落地、最容易证明价值的入口之一。 -

-
-
- -
-
-
02 / COMPANY POSITION
-

费控在未来公司的地位

-

- 未来公司的费控,会从“报销审批工具”变成“企业费用智能操作系统”(Expense OS)。 - 它一端连接员工和部门的真实业务动作,另一端连接预算、现金流、成本、风险、制度和管理决策。 -

-
- -
-

- 从组织分工与决策支持来看,CFO 的角色正加速从“合规记录者”转变为“战略业务伙伴(HR/IT/业务协同的中心)”。Deloitte 2025 年未来财务展望报告指出,财务部门未来的工作精力将有 70% 倾斜于数据分析和未来预测。智能费控则是这一变革的第一步——通过把一线经营活动(如差旅、招待、项目交付)产生的每一笔资金流动转化为语义数据,为 CFO 的“战略驾驶舱”提供实时的一手信号。 -

-

- 从预算与资源控制来看,未来的预算管控不再是“年初编预算,月底对账单”的静态割裂状态。智能费控通过建立动态预算池与资金控制链,使预算能够在秒级发生响应。这保证了业务部门在项目推进过程中,能实时感知每一笔花费对项目整体毛利空间、部门现金流余量的动态影响,促使人人关注经营效果。 -

-

- 从业务运营与体验来看,智能费控是消除部门隔阂、降低一线行政摩擦的“润滑剂”。当平台实现高度数字化与免报销消费结算时,员工不再需要贴票垫资,管理者不再需要在审批页面盲目点“同意”,财务不再需要枯燥审单,整个公司的运营效率将得到数量级提升。 -

-
- -
-
-
    -
  • 经营支出中枢 (Expense OS): 将多系统的零散流程、差旅出行、第三方消费直接通过本体层收归统一。
  • -
  • 预算守护雷达: 在业务动作发生时实现“秒级预算占用与测算”,而不是事后核销时的“超支警告”。
  • -
  • 合规内控防火墙: 结合发票验真、合同信息、行程轨迹和行为偏差等多模态数据对风险自动拦截。
  • -
  • 战略决策沙盘: 支持 CFO 和高管直接询问“各项目利润健康度”、“政策变动预算消耗预测”等深度命题。
  • -
  • 自进化规则工厂: 依据历史人工审批意见和申诉结果,系统能自动推荐规则优化方案,实现制度灰度升级。
  • -
-
-
-
-
-
-
业务场景
-
差旅、招待、采购、项目外包、会务支出
-
-
-
费用智能操作系统
-
本体语义 · 实时预算 · 智能体 · 仿真沙盘
-
-
-
经营结果
-
成本优化、合规账套、税务风险减免、现金流稳健
-
-
-
-
-
CFO 战略看板
-
业财融合数据、动态毛利预警、资金利用率
-
-
-
数字孪生仿真
-
制度变动测算、预算优化预测、行为偏差度
-
-
-
协同平台
-
免贴票、即时审批、智能助手交互
-
-
-
-
- 智能费控平台向上承接公司战略与预算规则,向下沉入业务一线动作,最终演化为企业支出的全局操作系统。 -
-
-
-
- -
-
-
03 / BLUE OCEAN
-

智能分析费控平台的蓝海

-

- 传统的报销系统、OA 工作流和财务共享软件已是一片红海,产品竞争停留在表单设计与流程配置层面。而真正能为企业带来颠覆性价值的“智能费控蓝海”,则存在于从流程处理到智能化决策预测的跃迁中。 -

-
- -
-

- 根据全球著名调研机构 Grand View Research 2025 发布的市场预测报告,全球差旅与费用管理(T&E)软件市场规模在 2030 年将达到 106.9 亿美元,2024 至 2030 年的复合年增长率(CAGR)高达 16.9%。报告中特别强调,市场增长的核心引擎已不再是单纯的“线上化审批”,而是引入 AI Agent 进行决策自动化、基于 OCR/LLM 的隐性欺诈检测、以及基于企业历史支出行为的可持续 ESG 碳足迹追踪。这表明,“费用智能化与经营沙盘仿真”是蕴含巨大商业溢价的崭新蓝海。 -

-
- -
-
- 1. 认知与决策型 AI Agent -

从“机械填表和固定规则校验”跨越到“能基于上下文自主决策、异常判定、并提供人机协同解释”的财务数字员工。

-
-
- 2. 财务数字孪生与政策仿真 -

基于公司历史发票、人员组织、预算规则建立仿真模型,模拟差旅标准或预算政策调整后,对企业资金流与利润的实际影响。

-
-
- 3. 多源异构数据语义对齐 -

打破各子系统(CRM、ERP、OA、商旅聚合商)接口壁垒,利用 Semantic Ontology 本体语义层实现业务数据的天然降维对齐。

-
-
- 4. 行为偏离与隐性欺诈识别 -

基于知识图谱与图机器学习技术,识别跨期拆单、虚假报销、同组偏离异常、跨部门关联交易等人工难以察觉的系统性风险。

-
-
- 5. 自进化规则治理闭环 -

支持自然语言输入制度,由 LLM 自动翻译成系统执行规则,并通过人工申诉与退回反馈,在后台自动完成规则库的校准 and 修正。

-
-
- 6. 绿色财务与 ESG 碳足迹 -

在费控和商旅端自动提取交通工具、酒店的排放系数,帮助企业在进行费用管控的同时,同步测算并生成企业 ESG 碳足迹报告。

-
-
-
- -
-
-
03.1 / COMPETITORS
-

主流费控系统竞品分析

-

- 要实现上述蓝海构想,必须客观分析当前市场上主流的费控软件。各大软件定位明确,但普遍在“智能化决策”、“跨系统语义融合”及“政策仿真”方面存在显著痛点。 -

-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
竞品名称核心定位与主要优势核心痛点与局限性X-Financial 的创新解决与差异化
SAP Concur -
    -
  • 全球化费控天花板,支持多币种、多税制、全球财税合规。
  • -
  • 商旅生态极其成熟,能够与 SAP ERP 体系深度咬合。
  • -
-
-
    -
  • 本土化体验被国内用户诟病(如数电发票处理缓慢)。
  • -
  • 系统界面臃肿,配置与二次开发极为繁琐。
  • -
  • 实施周期漫长,运维与实施费用极其高昂。
  • -
-
-
    -
  • 原生适配数电发票单轨制,具备开箱即用的 AI 智能验真归档。
  • -
  • 基于本地化轻量级大模型架构,大幅降低实施门槛和部署成本。
  • -
-
分贝通 -
    -
  • 以商旅消费支付为切入点,打造“商旅+支付+费控”模式。
  • -
  • 倡导“无需报销”体验,员工体验极佳。
  • -
-
-
    -
  • 强依赖平台内置的消费商城生态,在面对大量零星线下费用、外包采购时灵活性不足。
  • -
  • 对于复杂的多级跨账簿预算、动态共享额度的精细化管控能力相对偏弱。
  • -
-
-
    -
  • 提供基于本体层屏蔽异构商城壁垒的通用解析能力,线下报销补件与线上免报销消费实现语义对齐。
  • -
  • 支持复杂层级的预算池(部门/项目/成本中心)秒级动态关联管控。
  • -
-
合思 (易快报) -
    -
  • 一站式业财收支管理,国内市占率居前。
  • -
  • 生态系统对接广泛,能与国内主流 ERP 无缝打通,配置灵活。
  • -
-
-
    -
  • 系统逻辑依然以“传统工作流表单”为主,交互较为传统,缺乏智能助理的深度参与。
  • -
  • 缺乏中长周期的员工行为偏差分析、规则误报自适应纠偏机制。
  • -
-
-
    -
  • 前台 User Agent 支持自然语言直接进行报销提问、草稿生成、异常核对与智能交互。
  • -
  • 通过共享本体与规则中心,让财务人员可以用自然语言配置和灰度升级风控规则。
  • -
-
每刻报销 -
    -
  • 专注于大中型企业的智能财务共享,规则引擎非常强大。
  • -
  • AI 智能审单能力强,支持复杂的集团化多层级架构。
  • -
-
-
    -
  • 系统的学习曲线陡峭,对业务人员和普通员工的交互不够平滑。
  • -
  • 侧重于既定流程的合规审计,对于预算和费控政策调整带来的前瞻性影响缺乏模拟仿真能力。
  • -
-
-
    -
  • 前台大模型辅助,降低普通用户填单学习曲线。
  • -
  • 核心差异化:首创“财务数字孪生与仿真沙盘”,在系统级测试和决策前对费控变动进行量化分析预测。
  • -
-
-
-
- -
-
-
03.2 / SOLUTIONS
-

X-Financial 痛点解决方案

-

- 针对以上竞品普遍面临的系统孤岛、缺乏智能决策、政策调整靠经验等痛点,X-Financial 提出了以 **“AI + 数字化 + 财务数字孪生”** 为核心的下一代费控解决方案。 -

-
- -
-
- 一、 解决多系统孤岛:Semantic Ontology 本体语义层 -

- 传统软件通过 API 强行硬编码对接 CRM、ERP 和商旅系统,一旦系统升级,接口极易断裂,导致业财数据“语义断层”。 -

-

- X-Financial 方案: 我们设计了包含 8 个关键因子的本体语义协议(domain, scenario, intent 等)。无论是口语化描述、页面动作还是三方消费接口,都先被解析为统一的“本体状态”,再分发至下层服务。这实现了跨系统的语义级天然对齐,让数据真正融为一体。 -

-
- -
- 二、 解决财务假智能:User Agent & Hermes 双智能体闭环 -

- 市面软件仅使用 OCR 识别将文字填入表单,人工审核工作量并没有显著降低,也无法识别隐性舞弊。 -

-

- X-Financial 方案: 我们构建了双 Agent 循环。前台 User Agent 帮员工和财务进行友好交互,自动查漏补正,解释退回原因;后台 Hermes 数字员工 定时在数据底座扫描,分析员工近90/180天的费用画像和行为画像,依据同组偏差算法自动判定隐性风险,出具报告。 -

-
- -
- 三、 解决规则配置难:LLM 驱动的规则与知识工厂 -

- 传统系统的规则引擎配置需要 IT 人员编写繁杂的条件表达式,难以响应公司制度的频繁变动。 -

-

- X-Financial 方案: 支持财务直接上传自然语言描述的制度文档。系统通过大模型将文本转化为可测试、可执行的规则库资产;当发生审批争议或误报时,支持财务通过“反馈池”对规则 and 知识库进行一键校正,进入自进化闭环。 -

-
- -
- 首创蓝海技术 - 四、 解决政策盲目调整:财务数字孪生与仿真沙盘(Financial Digital Twin) -

- 很多企业在遇到经营波动时,会盲目调低差旅标准(如酒店降低20%),这容易导致员工满意度下降、灰色报销增多或合规偏离率升高,甚至因行政摩擦上升造成更大的隐性成本。目前市场没有任何一款软件能评估规则调整带来的实际后果。 -

-

- X-Financial 方案: 我们通过融合组织架构树、员工费用画像、预算控制规则与历史发票数据库,为企业构建了一个“财务数字孪生体”。当管理层想要修改政策(如“下调销售部酒店标准 15%”)时,可在系统仿真沙盘(Simulation Sandbox)中运行模拟。沙盘会模拟历史真实或合成出的数万个出差场景进行回归测算,量化预测此次政策调整对“未来费用降幅(预估降低11%)”、“员工合规偏离率(预估提升8%)”、“预计审批流程摩擦时间(预估提升12%)”的多维影响,为企业提供真正科学的决策辅助。 -

-
-
-
- -
-
-
04 / PROJECT GOAL
-

开发这个平台的目的

-

- 当前项目的目标是做一套可演示、可扩展、可继续工程化的智能费控底座。 - 它既要能承载真实报销、审批、预算和知识库流程,也要能承载智能体调用和后续自进化闭环。 -

-
- -
-
-
01
-
-
让用户用自然语言完成费用流程
-
用户可以描述出差、招待、补件、审批问题,系统通过本体解析成结构化字段,再交给编排器和对应服务处理。
-
-
-
-
02
-
-
让财务看到预算和风险的真实原因
-
预算中心计算预算占用、剩余额度、审批后使用率;规则中心解释风险规则命中;画像算法给出同组基准。
-
-
-
-
03
-
-
让 Hermes 自动发现隐藏问题
-
后台数字员工读取单据、聚类上下文、识别拆单和异常频次等隐性风险,再形成报告和工单候选。
-
-
-
-
04
-
-
让知识、规则和反馈持续进化
-
人工反馈、OCR 修正、规则误报漏报、审批意见改写和知识问答反馈进入候选池,经人工审核后更新规则或知识。
-
-
-
-
- -
-
-
05 / ALGORITHMS
-

相关算法与智能分析能力

-

- 项目中已经沉淀了独立算法目录和多个业务模型。核心原则是: - 先有可解释公式,再进入服务;算法输出“依据 + 建议动作”,不直接替代人工审批。 -

-
- -
-
- 申请人费用画像 -

- 根据近 90/180 天申请频次、金额占用、同组偏离、历史退回调减、本次申请偏离等指标, - 计算画像风险分和审批建议强度。 -

- applicant_expense_profile.py / applicant_expense_profile_formula.md -
-
- 员工行为画像 -

- 覆盖费用支出画像、流程质量画像、AI 协作强度、审批行为画像, - 支持按照部门、岗位、职级和费用类型建立同组基准。 -

- employee_behavior_profile.py / employee_behavior_profile_service.py -
-
- 预算费用管控模型 -

- 结合预算总额、已占用、已核销、本次申请金额、审批后使用率、预警线和超预算金额, - 输出 recommended、caution、review、block 等建议。 -

- budget_expense_control.py / budget.py -
-
- 风险规则与本体桥接 -

- 风险信号会映射到具体规则编码,例如重复发票、地点不一致、附件不匹配、事由过短, - 使自然语言风险问题能落到可执行规则。 -

- risk_ontology_bridge.py / risk_rule_template_executor.py -
-
- -
profile_score = - frequency_score * 0.20 -+ amount_occupancy_score * 0.25 -+ peer_deviation_score * 0.25 -+ adjustment_history_score * 0.15 -+ current_claim_deviation_score * 0.15 - -budget_control = - claim_amount_ratio -+ after_usage_rate -+ over_budget_amount -+ missing_business_context -+ control_action
-
- -
-
-
06 / MODULES
-

当前项目模块与核心能力

-

- 前端提供业务操作入口,后端提供领域服务、智能体编排、本体解析、规则资产、知识检索和审计追踪。 - 其中最核心的是:本体语义层、Orchestrator、User Agent、Hermes、预算/单据服务、规则中心和画像算法。 -

-
- -
-
-
前端应用层
-

- 总览、个人工作台、单据中心、预算中心、规则中心、数字员工、员工管理、制度知识、日志管理、系统设置。 -

-
- OverviewView - BudgetCenterView - AuditView - DigitalEmployeesView - DocumentsCenterView -
-
- -
-
单据与报销服务
-

- 支持申请单、报销单、附件、票据分析、审批、退回、归档、预算联动和 AI 结构化核对。 -

-
- ExpenseClaimService - expense_claim_budget_flow - expense_claim_risk_review -
-
- -
-
预算中心
-

- 管理预算额度、部门/项目/成本中心维度、预算占用、核销、可用余额、预警线和超预算控制。 -

-
- BudgetService - BudgetAllocation - BudgetReservation -
-
- -
-
规则中心
-

- 管理财务规则、风险规则、规则测试、规则等级、业务场景、费用类型范围和规则资产版本。 -

-
- AgentAssetService - AgentFoundationRiskRuleMixin - risk-rules -
-
- -
-
本体语义层
-

- 把自然语言、页面动作、附件上下文和定时任务解析成统一协议,供 Agent 和工具调用使用。 -

-
- SemanticOntologyService - ontology_detection - ontology_extraction - ontology_validation -
-
- -
-
Agent 编排与追踪
-

- Orchestrator 决定进入 User Agent 或 Hermes,记录本体解析、工具调用、降级结果和审计轨迹。 -

-
- OrchestratorService - OrchestratorExecutionEngine - AgentRunService -
-
- -
-
知识库与 RAG
-

- 对制度、FAQ、Excel、PDF、DOCX 进行检索和结构化回答,支持本地文本块与 LightRAG 运行时融合。 -

-
- KnowledgeRagService - knowledge_document_extractors - knowledge_ingest_log -
-
- -
-
Hermes 数字员工
-

- 后台执行风险扫描、费用报告、员工画像刷新、任务日志记录和风险报告沉淀。 -

-
- HermesRiskScannerService - hermes_scheduler - HermesRiskReport -
-
-
-
- -
-
-
07 / ARCHITECTURE
-

双智能体循环架构

-

- 外层 User Agent 负责用户操作、问答、草稿和确认;内层 Hermes 负责后台巡检、隐性风险、任务报告和候选优化。 - 两者不争夺职责,而是共享本体、规则、知识、数据和审计。 -

-
- -
-
-
- 外层循环:User Agent 面向用户操作 - 处理用户自然语言、页面动作、草稿生成、审批解释和确认后的流程写入 -
-
-
-
用户输入
-
自然语言、页面按钮、附件上下文
-
-
-
本体解析
-
场景、意图、实体、缺槽位
-
-
-
Orchestrator
-
路由、权限、审计、降级
-
-
-
工具执行
-
DB、规则、RAG、OCR、预算
-
-
-
回答/草稿
-
解释、核对、确认、提交
-
-
-
- 用户确认、补充字段或修改核对结果后,继续回到同一个会话上下文。 -
-
- 共享中台 - 语义本体 · 规则资产 · 知识库 · 业务数据库 · AgentRun Trace · 权限审计 -
-
- 内层循环:Hermes 数字员工监控核心数据与流转风险 - 面向系统事件和定时任务,负责长期巡检、隐性风险、报告与优化候选 -
-
-
-
定时触发
-
schedule、system event、手动触发
-
-
-
数据快照
-
预算、单据、员工、日志
-
-
-
风险分析
-
规则、LLM、画像、同组基准
-
-
-
报告/工单
-
risk_report、work_items、snapshot
-
-
-
反馈候选
-
规则、知识、OCR、Prompt
-
-
-
- Hermes 只生成候选和报告;规则上线、知识发布、审批和付款仍需要权限、确认和人工审核。 -
-
-
- 双循环的关键不是“两个聊天机器人”,而是把用户主动流程和后台系统巡检拆开, - 再通过统一语义协议、规则资产、业务数据和审计日志连接起来。 -
-
-
- -
-
-
08 / ONTOLOGY
-

本体语义层的优势

-

- 当前项目已经接入本体语义层。它的价值在于把“用户怎么说”和“系统怎么执行”隔开, - 让自然语言、页面动作、定时任务、规则中心和数据库查询都走同一套协议。 -

-
- -
-
-
- 减少关键词误判 -

- 用户说“我今天去客户现场,招待客户”,不能因为出现“客户”就误路由到应收查询。 - 本体会综合场景、意图、缺槽位和上下文判断。 -

-
-
- 让 Agent 调用可审计 -

- 每次调用都能保留 scenario、intent、entities、risk_flags、next_step, - 便于回放、追责和优化。 -

-
-
- 让规则与预算复用同一语义 -

- 费用类型、部门、预算期间、预算科目、风险信号都可以被统一解析, - 减少前后端重复写规则。 -

-
-
- -
-
-
-
-
自然语言 / 页面动作
-
用户提问、发起申请、编辑核对、上传附件
-
-
-
定时任务 / 系统事件
-
风险巡检、知识同步、MCP 健康检查
-
-
-
- Semantic Ontology - domain · scenario · intent · entities · time_range · constraints · risk_signals · next_step -
-
-
-
数据库查询
-
预算、单据、员工、部门、应收应付
-
-
-
规则 / MCP
-
风险规则、票据校验、外部服务
-
-
-
知识 / RAG
-
制度条款、FAQ、历史解释、证据来源
-
-
-
-
- 本体层不直接给最终答案,它输出可执行协议,让后续工具和 Agent 按相同语义工作。 -
-
-
- -
{ - "domain": "reimbursement", - "scenario": "travel_reimbursement", - "intent": "risk_check", - "entities": ["employee", "department", "expense_type", "budget_period"], - "time_range": {}, - "constraints": {}, - "risk_signals": ["duplicate_invoice", "over_budget"], - "next_step": "run_rule" -}
-
- -
-
-
09 / PRODUCT SCREENS
-

关键页面截图

-

- 下列截图来自当前项目 `web/UI` 目录,用来展示平台已经覆盖的核心操作面: - 管理总览、预算、单据、智能助手、知识库、日志和设置。 -

-
- - -
- -
-
-
10 / EVOLUTION
-

建议演进路线

-

- 当前项目已经具备智能费控雏形。后续重点不是堆更多页面,而是把本体、预算、画像、规则、 - Hermes 和反馈闭环做深,让平台从“能演示”走向“可运营”。 -

-
- -
-
-
阶段一
-
- 完成本体协议、单据中心、预算中心、规则中心、知识库和 Agent Run 追踪的稳定联动。 -
-
-
-
阶段二
-
- 加强费用画像、部门预算占比、审批建议、风险解释和单据详情页的业务可读性。 -
-
-
-
阶段三
-
- 将 Hermes 的风险扫描、费用报告、员工画像刷新和规则质量复盘变成可配置任务。 -
-
-
-
阶段四
-
- 建立人工反馈池,让 OCR 修正、规则误报漏报、审批意见改写和知识问答反馈形成候选优化项。 -
-
-
- -
-
关键原则
-

- 自进化不等于自动改线上规则。Hermes 负责发现、聚类、建议和生成候选; - 最终规则、知识、审批和付款仍然必须经过权限、确认和人工审核。 -

-
-
- -
-
-
11 / SOURCES
-

趋势依据与引用来源

-

- 本文档中的市场趋势、CFO 角色变化、AI Agent 预算、异常检测和费控市场空间,参考了以下公开资料。 -

-
- - -
- -
- 结论 -

- X-Financial 的智能费控方向已经具备清晰技术骨架: - 本体语义层负责理解,Orchestrator 负责调度,User Agent 负责用户流程, - Hermes 负责后台内循环,预算、规则、画像和知识库负责提供可解释依据。 - 继续沿着这条线做深,平台会从“报销工具”成长为企业费用经营与财务风控的智能中台。 -

-
-
- - -
- - diff --git a/document/development/ontology-field-governance/CONCEPT.md b/document/development/ontology-field-governance/CONCEPT.md deleted file mode 100644 index 65e4db5..0000000 --- a/document/development/ontology-field-governance/CONCEPT.md +++ /dev/null @@ -1,78 +0,0 @@ -# 本体字段治理 - -## 背景 - -当前费用申请、报销助手、单据详情、风险规则和预算控制中存在字段口径不一致的问题。例如同一语义在不同环节被命名为 `transport_type`、`transport_mode`、`application_transport_mode`,或 `occurred_date`、`business_time`、`time_range`。这些字段如果不先进入本体层,会导致语义识别、规则判断、草稿保存和前端展示各自解释同一业务事实。 - -## 原则 - -所有业务字段必须先设计为本体字段,再下放到业务模块使用。 - -- 本体字段注册表是唯一字段源。 -- 业务层只允许消费本体 canonical 字段。 -- 非本体字段只能作为输入别名,必须在语义入口归一。 -- 页面控件字段、兼容字段、后端历史字段不能直接进入业务判断。 -- 新增业务字段时,必须先更新本体字段设计,再更新表单、助手上下文、持久化、风险规则和测试。 - -## 当前第一阶段范围 - -第一阶段先治理费用申请和报销链路: - -- 个人工作台意图识别。 -- 费用申请预览和提交。 -- 报销助手快速发起报销。 -- 关联申请单生成报销草稿。 -- 报销详情智能录入和附件归集。 -- AI 预审、风险规则、审批流和预算流。 - -## 字段分层 - -本体 canonical 字段: - -- `expense_type` -- `time_range` -- `location` -- `reason` -- `amount` -- `transport_mode` -- `attachments` -- `customer_name` -- `merchant_name` -- `participants` -- `application_claim_id` -- `application_claim_no` -- `application_days` -- `application_date` -- `application_lodging_daily_cap` -- `application_subsidy_daily_cap` -- `application_transport_policy` -- `application_policy_estimate` - -输入兼容别名: - -- `transport_type`、`transportMode`、`application_transport_mode` -> `transport_mode` -- `occurred_date`、`business_time`、`application_business_time` -> `time_range` -- `business_location`、`application_location` -> `location` -- `reason_value`、`business_reason`、`application_reason` -> `reason` -- `attachment_names` -> `attachments` -- `reimbursement_type`、`scene_label` -> `expense_type` - -## 非合规判断 - -以下情况视为字段不合规: - -- 新业务流程直接新增 `context_json` 字段但没有进入本体注册表。 -- 风险规则读取未注册字段。 -- 前端 `review_form_values` 输出页面控件字段。 -- 后端服务用别名字段做业务判断,而不是先归一成本体字段。 -- 同一业务事实在申请、报销、审批、预算中使用不同字段名。 - -## 验收口径 - -完成后应满足: - -- 语义层能从上下文中生成统一本体实体。 -- 报销助手关联申请单后不再因为字段别名丢失追问出行方式。 -- `review_form_values` 对外输出本体字段,不输出页面别名字段。 -- 后端测试覆盖别名归一到本体字段。 -- 前端测试覆盖快速报销和核对抽屉只输出本体字段。 diff --git a/document/development/ontology-field-governance/FIELD_AUDIT.md b/document/development/ontology-field-governance/FIELD_AUDIT.md deleted file mode 100644 index 755fd5d..0000000 --- a/document/development/ontology-field-governance/FIELD_AUDIT.md +++ /dev/null @@ -1,40 +0,0 @@ -# 本体字段纠察记录 - -## 纠察口径 - -所有会参与意图识别、申请/报销草稿、费用明细、风险规则、审批或预算判断的字段,必须先进入本体字段注册表。 - -字段分为三类: - -- 本体业务字段:可被业务逻辑、规则、页面表单直接消费。 -- 输入兼容别名:只允许在语义入口归一,不允许在业务判断中继续直接读取。 -- 上下文元数据:只表达会话、上传、编辑态、权限和执行链路,不作为业务事实。 - -## 已注册的业务字段 - -- 费用事实:`expense_type`、`time_range`、`location`、`reason`、`amount`、`transport_mode`、`attachments` -- 对象事实:`customer_name`、`merchant_name`、`participants` -- 员工事实:`employee_name`、`employee_no`、`department_name`、`employee_position`、`employee_grade`、`manager_name` -- 预算事实:`budget_period`、`budget_subject`、`budget_amount`、`cost_center`、`warning_threshold`、`control_action` -- 申请关联事实:`application_claim_id`、`application_claim_no`、`application_days`、`application_date`、`application_policy_estimate` - -## 已登记为元数据的字段 - -- 会话与流程:`conversation_id`、`conversation_history`、`conversation_scenario`、`conversation_intent`、`session_type`、`entry_source` -- 编辑与动作:`review_action`、`draft_claim_id`、`application_edit_mode`、`application_edit_claim_id` -- 上传与 OCR:`attachment_count`、`attachment_names`、`ocr_documents`、`ocr_summary`、`review_document_form_values` -- 客户端运行态:`client_now_iso`、`client_timezone_offset_minutes` -- 权限与调试:`role_codes`、`is_admin`、`simulate_tool_failure`、`simulate_orchestrator_exception` - -## 当前审计结论 - -- 未注册字段:已清零。 -- 历史别名直接读取:主要集中在员工上下文顶层字段,例如 `name`、`grade`、`department`、`position`。 -- 第一轮已把申请/报销关键链路的表单字段统一到 `expense_type`、`time_range`、`location`、`reason`、`amount`、`transport_mode`。 - -## 后续清理策略 - -1. 新增业务字段前,先更新 `ontology_field_registry.py`。 -2. 旧字段只作为输入别名保留,入口归一到 canonical 字段。 -3. 业务模块逐步停止直接读取旧别名。 -4. 使用 `server/scripts/audit_ontology_context_fields.py --strict` 作为收口质量闸。 diff --git a/document/development/ontology-field-governance/TODO.md b/document/development/ontology-field-governance/TODO.md deleted file mode 100644 index a78221f..0000000 --- a/document/development/ontology-field-governance/TODO.md +++ /dev/null @@ -1,15 +0,0 @@ -# 本体字段治理 TODO - -- [x] 建立本体字段注册表,集中维护 canonical 字段和输入别名。[CONCEPT: 字段分层] -- [x] 在语义解析入口归一 `context_json.review_form_values`。[CONCEPT: 原则] -- [x] 在本体实体抽取中把上下文字段桥接为 `transport_mode`、`reason`、`location` 等实体。[CONCEPT: 当前第一阶段范围] -- [x] 报销助手 review 入口复用本体字段注册表,不再自己维护字段别名。[CONCEPT: 原则] -- [x] 快速报销关联申请单上下文去除 `business_time`、`business_location`、`reason_value`、`reimbursement_type` 等非本体输出字段。[CONCEPT: 非合规判断] -- [x] 核对抽屉提交上下文归一为本体字段。[CONCEPT: 验收口径] -- [x] 补充本体层和前端字段归一回归测试。[CONCEPT: 验收口径] -- [ ] 清查申请助手字段:`application_preview`、`application_fields`、`business_time_context` 是否都已归一本体。 -- [ ] 清查报销详情字段:智能录入、附件归集、费用明细、异常说明是否仍有非本体字段直传。 -- [ ] 清查风险规则字段:规则中心、Hermes 归一字段、OCR pipeline 字段是否有未注册业务字段。 -- [ ] 清查预算字段:预算控制、预算复核、预算操作上下文是否全部使用本体字段。 -- [ ] 清查审批字段:审批意见、退回原因、流程节点字段是否需要纳入本体或定义为流程元数据。 -- [ ] 增加字段合规扫描脚本,对新增 `review_form_values` / `context_json` 字段进行检查。 diff --git a/document/development/receipt-folder/CONCEPT.md b/document/development/receipt-folder/CONCEPT.md deleted file mode 100644 index 6e2054d..0000000 --- a/document/development/receipt-folder/CONCEPT.md +++ /dev/null @@ -1,266 +0,0 @@ -# 票据夹功能概念文档 - -更新时间:2026-05-29 - -## 功能一句话 - -票据夹用于归集用户已上传并经过 OCR 识别的原始票据文件,避免票据已识别但忘记关联报销单后无法找回。 - -## 背景与问题 - -当前系统有两条票据路径: - -- 报销明细附件路径:票据上传到某个草稿费用明细后,会存入 `expense_claims` 附件目录,并写入附件元数据。 -- 独立 OCR 识别路径:报销对话里先上传票据识别时,`/ocr/recognize` 只返回识别结果,源文件使用临时目录,识别结束后会清理。 - -这会导致一个业务缺口:用户可能已经上传票据并完成 OCR,但还没有把票据关联到报销草稿。只要用户关闭会话、切走页面或忘记继续操作,原始票据就没有一个稳定入口可追溯。 - -票据夹要补齐这个缺口:凡是系统对用户上传文件做过 OCR 并持久化源文件,就应进入票据夹列表;后续用户可以查看、修正票据信息、删除无效票据,或一键把未关联票据带入报销对话。 - -## 目标与非目标 - -目标: - -- 在左侧侧边栏的“单据中心”下面新增“票据夹”入口。 -- 建立票据源文件持久化能力,OCR 后保留原始文件、预览文件和识别元数据。 -- 提供票据夹列表,复用单据中心的紧凑列表视觉语言。 -- 支持“未关联票据 / 已关联票据”两个状态切换。 -- 支持票据详情:基本票据信息可编辑、原始文件可预览、底部返回列表和删除票据。 -- 支持“一键关联票据”:选择未关联票据,选择未提交草稿或新建报销单,再跳转到报销对话继续填写和关联。 - -非目标: - -- 本轮不引入 `document_assets` 等数据库结构变更;先用文件资产和元数据 JSON 完成产品闭环。 -- 本轮不替换现有报销明细附件接口。 -- 本轮不把票据夹做成财务共享的全公司档案库;默认只展示当前登录用户自己的票据。 -- 本轮不在列表页直接完成报销单提交,提交仍回到现有对话核对流程。 - -## 用户与场景 - -涉及角色: - -- 普通员工:上传票据后稍后再归集到草稿。 -- 经理或财务用户:在自己名下上传票据时同样需要留存和追溯。 - -典型场景: - -1. 用户在个人工作台上传 3 张票据,OCR 成功后暂时没有保存草稿。 -2. 用户第二天打开票据夹,看到这 3 张票据仍在“未关联票据”。 -3. 用户进入详情,修正票据类型、金额或日期。 -4. 用户点击“一键关联票据”,多选未关联票据。 -5. 用户选择已有草稿,或选择新建报销单。 -6. 系统打开报销对话,把票据源文件和 OCR 信息带入现有核对流程。 - -## 功能能力 - -### 票据持久化 - -- OCR 入口接收文件后,在识别完成阶段保存源文件。 -- 保存位置建议为 `storage/receipt_folder///`。 -- 每个票据目录包含: - - 原始文件:`source.` - - 预览文件:`preview.`,可为空 - - 元数据:`meta.json` -- 元数据记录: - - `id` - - `owner_key` - - `file_name` - - `media_type` - - `size_bytes` - - `uploaded_at` - - `status`: `unlinked` / `linked` - - `linked_claim_id` - - `linked_claim_no` - - `linked_item_id` - - `linked_at` - - OCR 引擎、模型、文本、摘要、置信度、票据类型、场景、结构化字段、提示信息 - -### 列表 - -- 页签: - - 未关联票据 - - 已关联票据 -- 表格字段建议: - - 票据文件 - - 识别类型 - - 费用场景 - - 金额 - - 票据日期 - - OCR 置信度 - - 关联状态 - - 上传时间 -- 交互: - - 搜索文件名、摘要、字段值、关联单号 - - 按状态切换 - - 点击行进入详情 - - 未关联页显示“一键关联票据” - -### 详情 - -- 基本票据信息: - - 文件名只读 - - 票据类型可编辑 - - 费用场景可编辑 - - 票据日期可编辑 - - 金额可编辑 - - 商户 / 出发地 / 到达地 / 票据号码等 OCR 字段可编辑 -- 原始文件展示: - - 图片直接预览 - - PDF 用浏览器内嵌预览 - - 不可预览类型提供下载入口 -- 底部动作: - - 返回列表 - - 删除票据 - -### 一键关联票据 - -流程: - -1. 打开关联弹窗,展示未关联票据多选列表。 -2. 下一步展示当前用户未提交草稿报销单,也提供“新建报销单”选项。 -3. 确认后打开现有报销对话。 -4. 如果选择已有草稿: - - 对话以 `link_to_existing_draft` 语义继续。 - - 携带 `draft_claim_id` 和票据文件。 -5. 如果选择新建报销单: - - 对话以 `create_new_claim_from_documents` 语义继续。 - - 携带票据文件和 OCR 元数据。 - -## 方案设计 - -### 后端 - -新增模块: - -- `schemas/receipt_folder.py` -- `services/receipt_folder.py` -- `api/v1/endpoints/receipt_folder.py` - -接口建议: - -- `GET /api/v1/receipt-folder?status=unlinked|linked|all` -- `GET /api/v1/receipt-folder/{receipt_id}` -- `PATCH /api/v1/receipt-folder/{receipt_id}` -- `DELETE /api/v1/receipt-folder/{receipt_id}` -- `GET /api/v1/receipt-folder/{receipt_id}/preview` -- `GET /api/v1/receipt-folder/{receipt_id}/source` - -OCR 改造: - -- `/api/v1/ocr/recognize` 保持现有响应结构兼容。 -- 在识别后调用票据夹服务保存源文件和识别结果。 -- 给每个返回的 OCR 文档补充可选 `receipt_id`、`receipt_preview_url`、`receipt_source_url` 字段。 - -### 前端 - -新增模块: - -- `services/receiptFolder.js` -- `views/ReceiptFolderView.vue` -- `assets/styles/views/receipt-folder-view.css` - -导航改造: - -- `useNavigation.js` 新增 `receiptFolder`,放在 `documents` 后面。 -- `accessControl.js` 将 `receiptFolder` 作为默认可见视图。 -- `router/index.js` 自动生成 `/app/receiptFolder` 路由。 -- `AppShellRouteView.vue` 渲染新页面,并允许页面触发 `openSmartEntry`。 - -对话衔接: - -- 票据夹确认关联时,前端从 `source` 接口取回 Blob,构造 `File` 对象传给 `openSmartEntry`。 -- 同时把已编辑 OCR 元数据转为 `initialReceiptDocuments` 或直接通过 `prompt` / `extraContext` 进入对话。 -- 本轮优先用现有 `initial-files` 和 `initial-prompt` 打开对话,确保用户可以继续核对和保存。 - -## 算法与公式 - -当前功能不涉及显式数学公式。 - -列表排序使用上传时间倒序: - -$$ -sortKey(receipt) = uploadedAt(receipt) -$$ - -状态归类: - -$$ -status(receipt) = -\begin{cases} -linked, & linkedClaimId \neq \emptyset \\ -unlinked, & linkedClaimId = \emptyset -\end{cases} -$$ - -## 测试方案 - -后端: - -- OCR 识别后会保存源文件和 `meta.json`。 -- 列表只返回当前用户票据。 -- `status=unlinked` 只返回未关联票据。 -- 详情可读取 OCR 字段。 -- PATCH 后字段持久化。 -- 预览接口能返回图片或 PDF。 -- DELETE 只删除票据夹根目录下的目标票据。 - -前端: - -- 导航中“票据夹”位于“单据中心”下面。 -- 列表空态、加载态、错误态可用。 -- 未关联和已关联两个页签计数正确。 -- 点击行进入详情。 -- 详情可保存字段、返回列表、删除票据。 -- 一键关联弹窗能完成票据选择和草稿选择。 - -集成: - -- 上传票据触发 OCR 后,票据出现在票据夹。 -- 从票据夹选择未关联票据,可打开报销对话。 -- 选择已有草稿时,对话带入草稿单号。 -- 选择新建报销单时,对话提示基于票据新建。 - -## 指标与验收 - -- OCR 成功返回后,票据夹列表能查到对应源文件。 -- 票据源文件和预览文件在重启后仍可访问。 -- 未关联票据和已关联票据状态切换正确。 -- 票据详情字段修改后刷新仍保留。 -- 删除票据后列表不再显示,预览接口返回 404。 -- 侧边栏位置符合要求:票据夹在单据中心下面。 -- 单个新增核心前端和后端模块不超过 800 行。 - -## 风险与开放问题 - -- 当前报销草稿流主要持久化 OCR 文本和文件名,真实文件复制到报销明细附件目录仍需要进一步打通。 -- 本轮采用文件元数据而非数据库,适合先完成闭环;后续若需要审计、权限、跨用户协作和全文检索,应升级到资产表。 -- 已关联状态如何自动回写,需要在后续把票据夹 ID 与报销明细 `invoice_id` 建立更强绑定。 -- 多票据关联时,如果用户中途取消对话,本轮仍保留为未关联,避免误标。 - -## 2026-06-03 详情页与上传治理补充 - -本轮根据新的验收要求收敛为三块核心内容: - -- 左侧为票据预览,使用共享详情页主区域承载,图片和 PDF 都以完整票据可见为优先目标,不再提供“打开源文件”按钮。 -- 右侧为识别票据详情,展示当前票据所有 OCR 字段和基础字段;用户点击“编辑”后可直接修改识别内容,保存后写回票据夹元数据。 -- 底部为关联信息;左侧预览卡底部同时展示用户编辑操作记录,用于后续财务判断人工修改痕迹。 - -编辑记录治理: - -- `PATCH /receipt-folder/{receipt_id}` 在保存前后对可编辑票据信息做字段级 diff。 -- 每条编辑日志记录操作者、操作时间、字段名称、修改前值、修改后值。 -- 前端详情页只展示真实 `edit_logs`,不再用模拟操作日志替代。 - -重复上传治理: - -- OCR 持久化票据时计算源文件 `sha256`。 -- 同一用户再次上传相同源文件时,不新建票据目录,返回已有 `receipt_id`,并在 OCR 文档 warnings 中提示“已上传过同样的单据,请不要重复上传。” - -报销助手联动: - -- 用户在报销助手上传新附件前,如果票据夹中存在未关联票据,先提示用户是否进入票据夹关联。 -- 用户可以选择“去票据夹关联”,也可以选择“继续上传新附件”;继续上传时只跳过本次未关联提醒,不影响后续重复附件校验。 - -删除级联: - -- 已关联票据对应的报销单被删除时,票据夹中关联该报销单的票据源文件、预览文件和元数据一并删除。 diff --git a/document/development/receipt-folder/TODO.md b/document/development/receipt-folder/TODO.md deleted file mode 100644 index fbb2a38..0000000 --- a/document/development/receipt-folder/TODO.md +++ /dev/null @@ -1,114 +0,0 @@ -# 票据夹功能 TODO - -更新时间:2026-05-29 - -## 阶段一:调研与契约 - -- [x] 梳理现有单据中心导航、列表样式和详情入口。[CONCEPT: 方案设计] - 证据:已确认 `DocumentsCenterView.vue`、`useNavigation.js`、`AppShellRouteView.vue` 是前端入口。 - -- [x] 梳理现有 OCR 和报销附件存储链路。[CONCEPT: 背景与问题] - 证据:已确认 `/ocr/recognize` 只临时识别;报销明细附件由 `expense_claim_attachment_*` 写入 `expense_claims` 存储。 - -- [x] 确定本轮不做数据库结构变更,先用票据文件资产和元数据 JSON 完成闭环。[CONCEPT: 目标与非目标] - 证据:避免新增迁移,降低本轮开发风险。 - -## 阶段二:文档 - -- [x] 创建 `document/development/receipt-folder/CONCEPT.md`。[CONCEPT: 全文] - 证据:本文档已落地。 - -- [x] 创建 `document/development/receipt-folder/TODO.md`。[CONCEPT: 测试方案] - 证据:本文档已落地。 - -## 阶段三:后端票据资产层 - -- [x] 新增 `schemas/receipt_folder.py`,定义列表项、详情、字段更新和删除响应。[CONCEPT: 后端] - 证据:已新增 `ReceiptFolderItemRead`、`ReceiptFolderDetailRead`、`ReceiptFolderUpdate`、`ReceiptFolderDeleteResponse`。 - -- [x] 新增 `services/receipt_folder.py`,负责源文件保存、元数据读写、预览解析、列表过滤和安全路径校验。[CONCEPT: 票据持久化] - 证据:`ReceiptFolderService` 已覆盖 OCR 批量持久化、已关联附件同步、详情更新、预览/源文件解析与目录安全校验。 - -- [x] 新增 `api/v1/endpoints/receipt_folder.py`,暴露列表、详情、更新、删除、预览和源文件接口。[CONCEPT: 后端] - 证据:已提供 `GET/PATCH/DELETE /receipt-folder/{receipt_id}` 及 `preview/source` 文件接口。 - -- [x] 在 `api/v1/router.py` 注册票据夹接口。[CONCEPT: 后端] - 证据:已 include `receipt_folder_router`。 - -- [x] 改造 `/ocr/recognize`,OCR 后保存源文件并把 `receipt_id` 等可选字段带回前端。[CONCEPT: OCR 改造] - 证据:`OcrRecognizeDocumentRead` 已补充 `receipt_id`、`receipt_status`、`receipt_preview_url`、`receipt_source_url`;来源于票据夹的 `receipt_ids` 会复用原票据,避免重复入库。 - -## 阶段四:前端票据夹页面 - -- [x] 新增 `services/receiptFolder.js`,封装票据夹接口和 Blob 文件读取。[CONCEPT: 前端] - 证据:已封装列表、详情、更新、删除、文件读取和 `buildReceiptFile`。 - -- [x] 新增 `ReceiptFolderView.vue`,实现列表、状态页签、搜索、一键关联入口和详情切换。[CONCEPT: 列表] - 证据:页面已包含未关联/已关联页签、搜索、表格、详情、编辑、预览和删除动作。 - -- [x] 新增 `receipt-folder-view.css`,复用单据中心紧凑企业级视觉,避免继续拉大现有 `DocumentsCenterView.vue`。[CONCEPT: 列表] - 证据:票据夹样式独立落在 `assets/styles/views/receipt-folder-view.css`,核心文件均未超过 800 行。 - -- [x] 在 `useNavigation.js` 增加 `receiptFolder`,并放在 `documents` 后面。[CONCEPT: 前端] - 证据:`appViews` 与 `navItems` 中 `receiptFolder` 均紧跟 `documents`。 - -- [x] 在 `accessControl.js` 增加默认可见权限和默认路由顺序。[CONCEPT: 前端] - 证据:已加入 `DEFAULT_APP_VIEW_ORDER` 与 `ALWAYS_VISIBLE_VIEWS`。 - -- [x] 在 `AppShellRouteView.vue` 渲染票据夹页面,并让页面可打开报销对话。[CONCEPT: 一键关联票据] - 证据:已接入 `ReceiptFolderView` 并转发 `open-assistant` 到 `openSmartEntry`。 - -## 阶段五:一键关联流程 - -- [x] 实现未关联票据多选弹窗第一步。[CONCEPT: 一键关联票据] - 证据:`ElDialog` 第一阶段使用 `ElCheckboxGroup` 多选未关联票据。 - -- [x] 实现未提交草稿选择和“新建报销单”选择第二步。[CONCEPT: 一键关联票据] - 证据:第二阶段读取草稿报销单,并保留 `新建报销单` 选项。 - -- [x] 从票据源文件接口取回 Blob 并构造 `File` 对象传给报销对话。[CONCEPT: 对话衔接] - 证据:`buildReceiptFile` 从 `source_url` 读取 Blob 并生成带 `receiptId` 的 `File`。 - -- [x] 选择已有草稿时,打开对话并带入草稿单号和关联提示。[CONCEPT: 一键关联票据] - 证据:选择草稿后以 `source: 'detail'`、`request` 和关联 prompt 打开报销对话;附件上传会携带 `receipt_id` 并回写原票据为已关联。 - -- [x] 选择新建报销单时,打开对话并带入基于票据新建的提示。[CONCEPT: 一键关联票据] - 证据:新建路径以 `source: 'receipt-folder'` 携带票据文件和新建 prompt。 - -## 阶段六:测试与验证 - -- [x] 补充后端票据夹服务和接口测试,超时时间控制在 60s 内。[CONCEPT: 测试方案] - 证据:`docker exec x-financial-main ... pytest server/tests/test_ocr_endpoints.py server/tests/test_reimbursement_endpoints.py -q` 通过,8 passed,耗时 11.41s。 - -- [x] 补充前端导航和票据夹视图模型测试。[CONCEPT: 测试方案] - 证据:`navigation-route-resolution.test.mjs` 已覆盖路由顺序,新增 `receipt-folder-view.test.mjs` 覆盖视图关键能力。 - -- [x] 运行前端构建或定向测试。[CONCEPT: 指标与验收] - 证据:`node web/tests/navigation-route-resolution.test.mjs`、`node web/tests/receipt-folder-view.test.mjs`、`npm.cmd run build` 均通过。 - -- [x] 在 Docker `x-financial-main` 的 `/app` 内运行后端定向测试。[CONCEPT: 测试方案] - 证据:`pytest server/tests/test_ocr_endpoints.py server/tests/test_reimbursement_endpoints.py -q` 在容器内通过,8 passed。 - -- [x] 手动核对侧边栏位置、列表密度、详情预览和关联弹窗。[CONCEPT: 指标与验收] - 证据:内置浏览器打开 `http://localhost:5173/app/receiptFolder`,侧边栏中“票据夹”位于“单据中心”下方,未关联/已关联页签与空态渲染正常,控制台无相关错误。 - -## 阶段七:收口 - -- [x] 回看 `CONCEPT.md` 验收标准,确认已实现项均有证据。[CONCEPT: 指标与验收] - 证据:OCR 持久化、列表/详情/预览、侧边栏位置、一键关联入口和文件行数约束均已覆盖。 - -- [x] 更新本 TODO 的完成状态和验证记录。[CONCEPT: 测试方案] - 证据:本文件已补充完成勾选和验证命令记录。 - -## 阶段八:2026-06-03 详情页与上传治理收口 - -- [x] 将票据夹详情页收敛为共享详情布局下的三块内容:左侧完整预览、右侧识别票据详情、底部关联信息。[CONCEPT: 2026-06-03 详情页与上传治理补充] - 证据:`node web/tests/receipt-folder-view.test.mjs`、`npm.cmd run build`、容器内 `cd /app/web && npm run build` 均通过。 -- [x] 支持识别票据详情编辑,并在后端保存字段级编辑日志。[CONCEPT: 编辑记录治理] - 证据:容器内 `pytest -q server/tests/test_ocr_endpoints.py server/tests/test_receipt_folder_service.py` 通过,3 passed。 -- [x] OCR 持久化时识别同一用户重复上传的相同源文件,返回已有票据并提示不要重复上传。[CONCEPT: 重复上传治理] - 证据:`test_ocr_endpoints.py` 已覆盖重复上传返回原 `receipt_id` 和 warnings。 -- [x] 报销助手上传附件前提示票据夹中存在未关联票据,并提供进入票据夹关联或继续上传的建议动作。[CONCEPT: 报销助手联动] - 证据:`receipt-folder-view.test.mjs` 覆盖 `fetchReceiptFolderItems('unlinked')`、`open_receipt_folder` 和 `continue_upload_with_unlinked_receipts`。 -- [x] 删除已关联报销单时,同步删除票据夹中关联该报销单的票据文件。[CONCEPT: 删除级联] - 证据:`test_receipt_folder_service.py` 已覆盖 `delete_receipts_for_claim` 删除后不可再读取票据。 diff --git a/document/development/reimbursement-draft-action-branching/CONCEPT.md b/document/development/reimbursement-draft-action-branching/CONCEPT.md deleted file mode 100644 index 117d490..0000000 --- a/document/development/reimbursement-draft-action-branching/CONCEPT.md +++ /dev/null @@ -1,137 +0,0 @@ -# 报销草稿分支动作收口 概念文档 - -更新时间:2026-06-23 - -## 功能一句话 - -当用户发起报销且系统命中可继续的报销草稿时,只提供“查看草稿、继续关联草稿、独立新建报销单”三个明确入口,让用户能看详情、补附件/说明,或确认另起一张新草稿。 - -## 背景与问题 - -- 当前现状:AI 工作台和报销助手在“我要报销”后会先查询可继续报销草稿;命中草稿时,当前按钮把“继续草稿”和“打开详情”混在一起,并把跳过草稿描述成“关联申请单新建报销单”。 -- 用户痛点:按钮语义不清,用户无法判断点击“继续草稿”是打开详情、继续补附件,还是进入申请单关联。 -- 业务影响:报销草稿与新建报销单的路径混杂,容易造成重复草稿、附件归集错误或用户误以为已继续处理。 -- 为什么现在需要做:截图中的草稿分支是报销入口的第一屏决策,需要先把按钮数量、文案和后续状态固定下来,再继续开发。 - -## 目标与非目标 - -### 目标 - -- [G1] 命中可继续报销草稿时,快捷按钮固定为三个:查看草稿、继续关联草稿、独立新建报销单。 -- [G2] “查看草稿”只负责跳转详情页,不承担继续上传或新建逻辑。 -- [G3] “继续关联草稿”只负责把当前会话切到“等待上传附件或补充说明”的状态,并锁定目标草稿。 -- [G4] “独立新建报销单”先提示用户确认是否新建草稿单据,再进入新草稿创建流程。 - -### 非目标 - -- [NG1] 本轮不改后端草稿保存、附件 OCR、风险审核和审批流规则。 -- [NG2] 本轮不改变申请单关联命中时的“选择申请单 / 单独新建报销单”逻辑。 -- [NG3] 本轮不重做报销助手整体 UI,只收口草稿命中态的按钮和动作流。 - -## 用户与场景 - -- 目标用户:普通员工在个人工作台 AI 模式或报销助手中发起报销。 -- 使用入口:快捷操作“发起报销”、输入“我要报销 / 发起报销 / 新建报销”。 -- 核心场景: - 1. 系统查到可继续报销草稿,展示草稿卡片和三个按钮。 - 2. 用户点击“查看草稿”,打开对应单据详情页。 - 3. 用户点击“继续关联草稿”,系统提示上传相关附件或补充说明。 - 4. 用户点击“独立新建报销单”,系统询问是否新建草稿单据。 -- 异常场景: - - 草稿缺少 `claim_id` 时,“查看草稿”和“继续关联草稿”不能提交无目标动作。 - - 历史会话里的旧动作仍可兼容处理,不影响新生成提示。 - -## 功能能力 - -- [C1] 输入能力:读取报销草稿候选单据,识别 `claim_id`、`claim_no`、状态、金额、时间和事由。 -- [C2] 处理能力:将草稿命中态动作拆成查看、继续关联、独立新建三条互斥分支。 -- [C3] 输出能力:输出固定三按钮,并在点击后生成明确的用户回显和助手提示。 -- [C4] 状态与权限:继续关联时记录目标草稿,后续上传附件或补充说明应围绕该草稿继续。 -- [C5] 边界与降级:保留旧 `skip_reimbursement_draft_check` 动作兼容,避免历史会话按钮失效。 - -## 方案设计 - -### 前端 - -- 页面/组件: - - `travelReimbursementAssociationGateModel.js` 负责生成草稿命中态文案和三个动作。 - - `useWorkbenchAiActionRouter.js` 负责个人工作台 AI 模式的动作分流。 - - `useWorkbenchAiExpenseFlow.js` 负责个人工作台中的继续关联提示和独立新建确认提示。 - - `useTravelReimbursementSuggestedActions.js` 负责报销助手页面中的相同动作分流。 -- 交互状态: - - 查看草稿:沿用 `open_application_detail`,只跳转详情。 - - 继续关联草稿:新增动作类型,点击后提示“请上传相关附件,或补充说明”,并记录目标草稿。 - - 独立新建报销单:新增动作类型,点击后提示“是否新建草稿单据”,确认后进入现有单独新建流程。 -- 展示规则: - - 草稿命中态只显示三个按钮,不再出现“继续草稿”或“不用草稿,关联申请单新建报销单”。 - - 按钮文案携带草稿编号,方便用户辨认目标。 -- 降级处理: - - 历史旧动作仍走原有分支。 - - 缺少草稿 ID 时给出 toast,不继续进入无目标关联。 - -### 后端 - -- 接口/服务:当前不新增接口。 -- 权限与校验:沿用现有详情页与草稿操作权限。 -- 持久化:当前不改后端持久化结构。 -- 降级处理:后续上传附件或保存草稿仍使用现有 orchestrator 与附件归集能力。 - -### 算法与规则 - -- 输入:已筛选出的报销草稿候选。 -- 流程:按更新时间排序后取首个草稿作为三按钮默认目标;草稿卡片仍展示候选详情。 -- 输出:三个动作对象及后续提示文案。 -- 解释:本轮不是匹配算法改造,只是草稿命中后的动作语义收口。 - -### 数据与契约 - -- 核心字段:`claim_id`、`claim_no`、`original_message`、`draft_claim_id`、`selected_claim_no`。 -- 状态枚举:新增前端动作类型 `continue_reimbursement_draft_association`、`create_standalone_reimbursement_draft`、`cancel_standalone_reimbursement_draft`。 -- 兼容策略:保留 `open_application_detail` 和旧跳过动作分支。 -- 版本/审计:通过前端测试锁定动作数量、文案和路由行为。 - -## 算法与公式 - -当前功能不涉及显式数学公式。 - -## 测试方案 - -后端: - -- 当前不新增后端测试;本轮没有修改后端服务或接口。 - -前端: - -- 扩展 `workbench-ai-reimbursement-association-gate.test.mjs`,验证草稿命中态只输出三个动作和新文案。 -- 扩展 `workbench-ai-action-router.test.mjs`,验证继续关联、独立新建确认的路由行为。 -- 扩展 `travel-reimbursement-guided-flow.test.mjs` 或既有报销助手动作测试,验证旧报销助手使用相同动作语义。 - -集成: - -- 运行相关 Node 测试,确认 AI 工作台和报销助手入口没有回退到旧按钮。 - -手工验证: - -- 在个人工作台 AI 模式输入“我要报销”,命中草稿后检查按钮数量和点击行为。 - -## 指标与验收 - -- [A1] 功能验收:草稿命中态固定显示三个按钮,且第一个按钮跳详情,第二个按钮提示上传附件/说明,第三个按钮提示是否新建草稿单据。 -- [A2] 性能指标:不增加额外接口查询;仍复用一次单据列表查询。 -- [A3] 质量指标:定向前端测试通过,旧动作兼容测试不失效。 -- [A4] 安全/权限指标:不绕过详情页和草稿操作原有权限。 -- [A5] 可观测性:对话消息中能看到用户选择了哪个分支。 - -## 风险与开放问题 - -- 风险:多个草稿同时命中时,三个按钮默认指向最新草稿;用户如需其他草稿,可先通过卡片查看信息后进入详情页处理。 -- 风险:全量 `code-size-limits` 当前仍会被既有 `TopBar.vue:824` 阻断;本轮新增和修改的文件均已控制在 800 行内。 -- 已处理依赖:复用现有详情页跳转、报销场景选择和草稿保存链路。 -- 待确认:后续是否要在草稿卡片内为每张草稿提供独立按钮;本轮先按截图中的三按钮入口收口。 -- 降级策略:旧历史会话按钮保持可点击,不强制迁移旧消息。 - -## 本轮实现记录 - -- 2026-06-23:先落本文档和 TODO,再按测试驱动修改前端草稿分支动作。 -- 2026-06-23:新增 `travelReimbursementDraftBranchModel.js` 承载草稿三分支动作,避免继续放大 `travelReimbursementAssociationGateModel.js`。 -- 2026-06-23:个人工作台和报销助手页面均已接入“继续关联草稿”和“独立新建报销单”的后续提示。 diff --git a/document/development/reimbursement-draft-action-branching/TODO.md b/document/development/reimbursement-draft-action-branching/TODO.md deleted file mode 100644 index 235989b..0000000 --- a/document/development/reimbursement-draft-action-branching/TODO.md +++ /dev/null @@ -1,73 +0,0 @@ -# 报销草稿分支动作收口 开发 TODO - -更新时间:2026-06-23 - -## 使用规则 - -- 每个 TODO 必须对应 `CONCEPT.md` 中的目标、能力、方案或验收点。 -- 只有完成并验证后,才能把 `[ ]` 改成 `[x]`。 -- 勾选时在任务后补充简短证据,例如文件、接口、命令或验证结果。 -- 如果需求发生变化,先更新 `CONCEPT.md`,再调整本 TODO。 - -## 1. 调研与边界 - -- [x] [CONCEPT: 背景与问题] 阅读相关页面、动作模型和测试,确认当前“继续草稿”实际走详情打开,“不用草稿”走申请单关联。 - 证据:`travelReimbursementAssociationGateModel.js`、`useWorkbenchAiActionRouter.js`、`useWorkbenchAiExpenseFlow.js`、`workbench-ai-reimbursement-association-gate.test.mjs`。 -- [x] [CONCEPT: 目标与非目标] 确认本轮只改草稿命中态按钮与点击流,不改后端草稿保存和风险审核。 - 证据:`CONCEPT.md` 的目标与非目标章节。 -- [x] [CONCEPT: 风险与开放问题] 标记多草稿命中时默认指向最新草稿,历史旧动作保留兼容。 - 证据:`CONCEPT.md` 的风险与开放问题章节。 - -## 2. 契约与设计 - -- [x] [CONCEPT: 功能能力] 定义三个动作分支:查看草稿、继续关联草稿、独立新建报销单。 - 证据:`CONCEPT.md` 的功能能力和方案设计章节。 -- [x] [CONCEPT: 方案设计] 明确个人工作台 AI 模式与报销助手页面共用动作模型,但分别在各自 action router 中处理点击。 - 证据:`CONCEPT.md` 的前端方案设计章节。 -- [x] [CONCEPT: 算法与公式] 明确本轮不涉及显式数学公式。 - 证据:`CONCEPT.md` 的算法与公式章节。 -- [x] [CONCEPT: 指标与验收] 把验收标准拆成按钮数量、按钮文案、点击后提示和旧动作兼容。 - 证据:`CONCEPT.md` 的指标与验收章节。 - -## 3. 后端实现 - -- [x] [CONCEPT: 后端] 本轮不新增后端 schema、service、endpoint、权限和持久化逻辑。 - 证据:`CONCEPT.md` 明确当前不新增接口。 -- [x] [CONCEPT: 数据与契约] 后端响应结构不变,新增内容仅为前端动作类型。 - 证据:`CONCEPT.md` 的数据与契约章节。 - -## 4. 算法/规则实现 - -- [x] [CONCEPT: 算法与规则] 本轮不改候选单据筛选算法,只改命中后的动作分支。 - 证据:`CONCEPT.md` 的算法与规则章节。 -- [x] [CONCEPT: 功能能力] 明确旧动作保留兼容,不删除历史会话能力。 - 证据:`CONCEPT.md` 的边界与降级说明。 - -## 5. 前端实现 - -- [x] [CONCEPT: 前端] 在草稿分支模型中新增动作类型和三按钮生成逻辑。 - 证据:`travelReimbursementDraftBranchModel.js` 定义 `CONTINUE_REIMBURSEMENT_DRAFT_ACTION`、`CREATE_STANDALONE_REIMBURSEMENT_DRAFT_ACTION` 和三按钮构造;`travelReimbursementAssociationGateModel.js` re-export 保持兼容。 -- [x] [CONCEPT: 前端] 在个人工作台 AI 模式中处理继续关联草稿、独立新建确认和取消新建。 - 证据:`useWorkbenchAiActionRouter.js` 分流新动作;`useWorkbenchAiExpenseFlow.js` 追加上传附件/说明提示和新建草稿确认提示。 -- [x] [CONCEPT: 前端] 在报销助手页面中处理同一批新动作,保持与工作台一致。 - 证据:`useTravelReimbursementSuggestedActions.js` 接入继续关联、独立新建确认和取消新建;`TravelReimbursementCreateView.js` 传入 `draftClaimId` 与 `composerUploadIntent`。 -- [x] [CONCEPT: 前端] 保留旧动作兼容,不破坏历史会话按钮。 - 证据:`SKIP_REIMBURSEMENT_DRAFT_CHECK_ACTION` 和 `SKIP_REQUIRED_APPLICATION_LINK_ACTION` 仍由原路径处理;相关旧链路测试通过。 - -## 6. 测试与验证 - -- [x] [CONCEPT: 测试方案] 先补充失败的前端单元测试,覆盖三按钮生成和路由行为。 - 证据:RED 阶段 `workbench-ai-reimbursement-association-gate.test.mjs` 和 `workbench-ai-action-router.test.mjs` 因缺少 `CONTINUE_REIMBURSEMENT_DRAFT_ACTION` 导出失败。 -- [x] [CONCEPT: 测试方案] 实现后运行定向前端测试,记录通过结果。 - 证据:`node --test web/tests/workbench-ai-reimbursement-association-gate.test.mjs`、`node --test web/tests/workbench-ai-action-router.test.mjs`、`node --test web/tests/travel-reimbursement-guided-flow.test.mjs`、`node --test web/tests/travel-reimbursement-review-drawer-switch.test.mjs`、`node --test web/tests/expense-attachment-draft-selection.test.mjs`、`node --test web/tests/attachment-association-confirmation.test.mjs` 均通过。 -- [x] [CONCEPT: 指标与验收] 回看验收点,确认没有旧文案继续出现在新草稿命中态。 - 证据:`workbench-ai-reimbursement-association-gate.test.mjs` 断言新草稿命中态有且仅有三个动作,并不再出现“跳过草稿后再关联申请单”。 - -## 7. 文档收尾 - -- [x] [CONCEPT: 指标与验收] 实现完成后更新本 TODO 的证据。 - 证据:本 TODO 已回填实现文件和测试命令。 -- [x] [CONCEPT: 风险与开放问题] 根据实现结果更新剩余风险。 - 证据:`CONCEPT.md` 已记录全量 `code-size-limits` 仍被既有 `TopBar.vue:824` 阻断;本轮文件行数为 `travelReimbursementAssociationGateModel.js:714`、`travelReimbursementDraftBranchModel.js:143`。 -- [x] [CONCEPT: 功能一句话] 确认最终实现没有偏离原始目标。 - 证据:新草稿命中态固定为查看草稿、继续关联草稿、独立新建报销单三个入口。 diff --git a/document/development/risk-rule-explainable-flow/CONCEPT.md b/document/development/risk-rule-explainable-flow/CONCEPT.md deleted file mode 100644 index 1b7f28f..0000000 --- a/document/development/risk-rule-explainable-flow/CONCEPT.md +++ /dev/null @@ -1,581 +0,0 @@ -# 风险规则可解释流程判断改造方案 - -## 功能一句话 - -把风险规则从“自然语言生成一段 JSON”升级为“自然语言、字段本体、可执行 JSON DSL、流程判断图、测试命中路径、版本修改”一致闭环,让业务用户能看懂规则怎么判断,让系统按同一套逻辑执行。 - -## 背景与问题 - -当前风险规则已经具备自然语言创建、JSON 风险规则、风险评分、详情页流程图、仿真测试和上线启用能力,但仍有几个关键缺口: - -- 规则解释不够稳定。用户输入复杂业务规则后,系统可能把“城市是否一致、日期是否越界、是否存在合理说明”解释成“是否出现关键词”,这会导致业务语义失真。 -- 流程图容易变成展示装饰。如果流程图不严格从可执行 JSON DSL 派生,就会出现“页面看起来是 A,后端实际执行是 B”的问题。 -- 测试结果缺少路径解释。用户上传票据和输入意图后,需要知道系统识别到了哪些字段、走过哪些判断节点、为什么命中或未命中。 -- 规则修改缺少版本化闭环。已上线规则不能直接覆盖,应创建修订版本,旧版本继续生效,新版本测试通过后再替换。 -- 常见费控规则需要模板化扩展。预算、票据、差旅、招待、采购/AP、企业卡等规则应进入规则模板库,但仍必须走同一套解释和执行链路。 - -## 目标与非目标 - -### 目标 - -- [G1] 自然语言规则经过 Hermes 语义理解后,生成结构稳定、可校验、可执行的 JSON DSL。 -- [G2] 流程判断图必须由 JSON DSL 派生,不能直接由自然语言单独生成。 -- [G3] 详情页展示“文字流程解释 + 流程图 + 使用字段 + 风险分数 + 规则状态”,让业务用户能确认系统理解是否正确。 -- [G4] 测试规则时展示本次样例或票据仿真的字段识别结果、判断路径、命中节点和最终结论。 -- [G5] 用户觉得规则不合理时,通过“创建修订版本”修改,线上版本保持稳定。 -- [G6] 常见费控规则模板库可以复用同一套 DSL、流程图和测试机制。 - -### 非目标 - -- [NG1] 本期不做流程图编辑器,不允许拖拽、改节点、缩放编辑或在线画图。 -- [NG2] 本期不让大模型作为风险命中裁判。Hermes 只负责理解、生成、解释和辅助解析,最终命中由规则执行器决定。 -- [NG3] 本期不把所有复杂政策一次性建成完整专家系统,先保证规则表达、解释和执行一致。 -- [NG4] 本期不直接覆盖已上线规则,所有线上修改都走修订版本。 - -## 用户与场景 - -- 财务规则制定者:创建风险规则,查看系统理解是否正确,修改草稿规则。 -- 高级财务人员 / admin:审核、上线、下线、启用、停用、删除未发布规则。 -- 普通报销用户:在真实业务命中风险时看到简明原因,可反馈误判或漏判。 -- 系统执行链路:报销、费用申请、预算占用、票据识别、采购/AP 等场景只加载已上线且已启用的规则。 - -核心场景: - -1. 新建规则:输入规则标题、费用业务环节、费用领域、是否需要附件、自然语言规则。 -2. 生成规则:Hermes 结合字段本体输出 JSON DSL、业务说明、风险评分、流程模型和 SVG。 -3. 查看详情:用户确认“系统理解的字段、判断条件、例外说明、命中动作”是否正确。 -4. 仿真测试:用户上传附件并输入测试意图,系统统一识别字段,再由执行器判断当前规则。 -5. 修改规则:未上线规则直接编辑;已上线规则创建修订版本,测试通过后发布替换。 - -## 功能能力 - -### C1. 自然语言输入能力 - -新建风险规则表单应包含: - -- 规则标题。 -- 业务环节:费用申请、报销、预算控制、付款/采购等。 -- 费用领域:差旅、住宿、交通、招待、办公、培训、会议、软件服务、通讯、福利、预算、发票、采购/AP、通用。 -- 是否需要附件:需要时测试弹窗开放附件上传;不需要时隐藏上传入口。 -- 自然语言规则描述。 - -风险等级不允许用户手动选择,由评分模型输出风险分数和等级。 - -### C2. 语义理解与字段本体映射 - -Hermes 需要输出一份中间语义计划,而不是直接写死 JSON: - -- 规则意图:判断什么业务风险。 -- 适用范围:业务环节、费用领域、费用科目、单据类型。 -- 所需字段:中文解释、英文字段名、来源、是否必填。 -- 票据字段:OCR 或文档智能识别得到的城市、日期、金额、销售方、发票号等。 -- 判断步骤:按顺序表达条件、分支、例外说明和命中动作。 -- 例外条件:例如延期、改签、跨城办事、临时任务等说明。 -- 风险动作:提醒、人工复核、要求补充说明、退回修改、禁止提交。 - -字段展示统一为: - -```text -申报目的地[claim.destination_city] -明细发生地点[item.location_city] -交通票行程城市[receipt.transport_route_cities] -住宿发票城市[receipt.hotel_city] -出差开始日期[trip.start_date] -出差结束日期[trip.end_date] -报销事由[claim.reason] -``` - -### C3. 可执行 JSON DSL - -JSON DSL 应表达规则执行逻辑,而不是保存自然语言摘要。建议基本结构: - -```json -{ - "rule_id": "risk.travel.city_mismatch", - "version": "v1", - "scope": { - "business_stage": "reimbursement", - "expense_types": ["travel", "lodging"] - }, - "required_fields": [ - { - "label": "申报目的地", - "field": "claim.destination_city", - "source": "claim", - "required": true - } - ], - "conditions": { - "all": [ - { - "op": "in_scope", - "field": "expense.type", - "values": ["travel", "lodging"] - }, - { - "op": "any_present", - "fields": [ - "receipt.transport_route_cities", - "receipt.hotel_city", - "item.location_city" - ] - }, - { - "op": "none_match", - "left_fields": [ - "receipt.transport_route_cities", - "receipt.hotel_city" - ], - "right_fields": [ - "claim.destination_city", - "item.location_city", - "trip.route_cities" - ], - "matcher": "city_equivalent" - }, - { - "op": "not_contains_any", - "field": "claim.reason", - "values": ["延期", "改签", "跨城办事", "临时任务", "绕行"] - } - ] - }, - "action": { - "risk_level": "high", - "risk_score": 76, - "decision": "review_required", - "message": "票据城市与申报目的地或行程城市不一致,且未说明合理原因。" - } -} -``` - -核心要求: - -- 城市、日期、金额、人员、供应商等字段必须使用专门比较算子,不能退化成“关键词出现”。 -- 复杂规则允许多层条件组合:`all`、`any`、`not`、`branch`、`exists`、`range`、`compare`、`semantic_contains`。 -- 例外说明可以使用语义包含,但只能影响“是否进入复核/降级/豁免”,不能替代结构化字段判断。 -- DSL 生成后必须通过 schema 校验和执行器 dry-run。 - -### C4. 流程判断图 - -流程图不是编辑器,也不是自然语言插图。流程图必须由 JSON DSL 转换成 `flow_model`,再生成 SVG。 - -建议 `flow_model`: - -```json -{ - "nodes": [ - { - "id": "start", - "type": "start", - "title": "开始", - "description": "进入差旅住宿报销风险检查" - }, - { - "id": "scope", - "type": "decision", - "title": "是否属于差旅住宿报销", - "fields": ["expense.type", "claim.business_stage"] - }, - { - "id": "city_match", - "type": "decision", - "title": "票据城市是否匹配申报或行程城市", - "fields": [ - "receipt.hotel_city", - "receipt.transport_route_cities", - "claim.destination_city", - "trip.route_cities" - ] - }, - { - "id": "hit", - "type": "risk", - "title": "命中高风险", - "description": "要求补充行程说明或退回修改" - } - ], - "edges": [ - { "from": "start", "to": "scope", "label": "开始检查" }, - { "from": "scope", "to": "end_pass", "label": "否" }, - { "from": "scope", "to": "city_match", "label": "是" }, - { "from": "city_match", "to": "end_pass", "label": "是" }, - { "from": "city_match", "to": "hit", "label": "否" } - ] -} -``` - -流程图展示要求: - -- 详情页左侧为文字流程解释,右侧为“流程图”。 -- 判断分支用“是 / 否 / 通过 / 不通过 / 缺失 / 存在”等明确标签。 -- 风险命中框使用风险等级颜色:低风险蓝色,中风险橙色,高风险红色,极高风险深红色。 -- 普通节点保持 SaaS 白底、细边框、低饱和样式,不能整张图都染成风险色。 -- 图只做展示,不响应拖拽、编辑、缩放和节点点击。 -- 节点数量超过 8 个时,需要自动压缩文字、合并说明节点或分页展示,避免图过大。 - -### C5. 测试命中路径 - -测试规则弹窗应展示三类信息: - -1. 输入与识别结果 - - 用户自然语言测试意图。 - - 上传附件清单。 - - OCR / 文档智能识别字段。 - - Hermes 辅助规范化后的结构化字段。 - -2. 规则执行结果 - - 是否进入适用范围。 - - 每个判断节点的输入值、比较方式、判断结果。 - - 命中的风险动作。 - - 未命中的原因。 - -3. 流程图路径高亮 - - 使用同一个 `flow_model`。 - - 本次执行走过的节点和边由执行器输出 `trace`。 - - 前端按 `trace` 高亮路径。 - -执行 trace 示例: - -```json -{ - "trace_id": "run_001", - "matched": true, - "risk_level": "high", - "risk_score": 76, - "steps": [ - { - "node_id": "scope", - "result": true, - "inputs": { - "expense.type": "住宿费", - "claim.business_stage": "reimbursement" - } - }, - { - "node_id": "city_match", - "result": false, - "inputs": { - "receipt.hotel_city": "北京", - "claim.destination_city": "上海", - "trip.route_cities": ["武汉", "上海"] - } - } - ] -} -``` - -### C6. 规则修改与版本化 - -规则修改分三种: - -- 未上线规则:允许创建者或 admin 直接编辑,保存后重新生成 DSL、流程图、评分和说明。 -- 已上线规则:不允许直接覆盖,必须点击“创建修订版本”。 -- 业务用户反馈:只能提交误判/漏判反馈,由管理员决定是否创建修订版本。 - -已上线规则修改流程: - -```text -线上版本 active - ↓ -创建修订版本 draft_revision - ↓ -编辑自然语言 / 参数 / 附件要求 - ↓ -重新生成 JSON DSL + 流程图 + 评分 - ↓ -仿真测试通过 - ↓ -发布新版本 - ↓ -旧版本归档,新版本 active -``` - -版本记录必须包含: - -- 修改人。 -- 修改原因。 -- 修改前后自然语言差异。 -- 修改前后 DSL 差异。 -- 测试报告。 -- 发布时间。 -- 是否替换线上版本。 - -## 方案设计 - -### 总体链路 - -```text -自然语言规则 - ↓ -字段本体召回与业务域约束 - ↓ -Hermes 生成语义计划 semantic_plan - ↓ -语义计划校验与补全 - ↓ -生成 JSON DSL - ↓ -Schema 校验 + 执行器 dry-run - ↓ -风险评分 risk_score / risk_level - ↓ -DSL 转 flow_model - ↓ -flow_model 转 flow_diagram_svg - ↓ -详情展示 + 仿真测试 + 上线执行 -``` - -### 前端设计 - -涉及入口: - -- `AuditRuleDialogs.vue`:新建风险规则表单,后续增加修订版本编辑入口。 -- `AuditJsonRiskRuleDetail.vue`:详情页展示基本信息、测试状态、流程解释、流程图、操作按钮。 -- `RiskRuleFlowDiagram.vue`:只负责展示 SVG 或由 `flow_model` 派生的静态图,不做编辑。 -- `RiskRuleTestDialog.vue`:仿真测试窗口,展示输入识别、执行路径、测试报告。 -- `auditViewRiskRuleModel.js` / `auditViewModel.js`:规则详情视图模型、列表字段和状态映射。 - -详情页建议结构: - -```text -Topbar:规则标题、状态、风险分数、风险等级、上线/启用状态 - -基本信息:费用领域、业务环节、附件要求、创建人、上线时间、最后操作、测试状态 - -判断流程: - 左侧:文字流程解释 - 右侧:流程图 - -测试与版本: - 最近测试报告 - 修订版本 / 历史版本 - 操作按钮 -``` - -修改规则界面建议采用左右布局: - -- 左侧:自然语言规则编辑、规则标题、费用领域、附件要求。 -- 右侧:系统解释预览,包括字段、本体映射、流程解释、风险分数。 -- 底部:重新生成、保存草稿、测试规则、提交上线。 - -### 后端设计 - -已有相关模块应优先复用: - -- `risk_rule_generation.py`:规则生成主流程。 -- `risk_rule_generation_prompt.py`:Hermes 提示词。 -- `risk_rule_generation_ontology.py`:字段本体和费用领域约束。 -- `risk_rule_generation_semantics.py`:自然语言语义解释。 -- `risk_rule_generation_interpreter.py`:解释结果到 DSL。 -- `risk_rule_scoring.py`:风险评分。 -- `risk_rule_flow_diagram.py`:流程图 SVG 生成。 -- `risk_rule_manifest_normalizer.py`:规则 manifest 规范化。 -- `risk_rule_template_executor.py`:规则执行器。 -- `agent_asset_risk_rule_testing.py`:规则测试、删除、发布、启用。 -- `agent_asset_risk_rule_simulation.py`:仿真测试对话。 - -后端需要补齐的能力: - -- 生成 `semantic_plan` 并持久化到 `config_json` 或版本内容中。 -- 生成并持久化 `flow_model`,再生成 `flow_diagram_svg`。 -- 执行器输出 `trace`,用于测试解释和流程图高亮。 -- 支持创建修订版本,避免直接覆盖 active 版本。 -- 支持从常见模板创建规则,模板也走同一套生成和校验链路。 - -### 接口设计 - -建议新增或调整: - -```text -POST /agent-assets/risk-rules/generate - 根据自然语言创建生成任务,返回生成中资产。 - -POST /agent-assets/{asset_id}/risk-rules/regenerate - 对草稿或修订版本重新生成 DSL、评分和流程图。 - -POST /agent-assets/{asset_id}/risk-rules/revisions - 基于已上线规则创建修订版本。 - -PATCH /agent-assets/{asset_id}/risk-rules/draft - 保存未上线规则或修订版本的编辑内容。 - -POST /agent-assets/{asset_id}/risk-rule-tests/simulate - 独立仿真测试,返回字段识别、执行结果、trace。 - -GET /agent-assets/{asset_id}/risk-rule-tests/latest - 返回最近测试摘要。 - -POST /agent-assets/{asset_id}/publish - 发布通过测试的规则版本。 -``` - -### 数据设计 - -建议在风险规则版本内容或 `config_json` 中保留: - -```json -{ - "source_text": "用户输入的自然语言规则", - "semantic_plan": {}, - "dsl": {}, - "flow_model": {}, - "flow_diagram_svg": "...", - "flow_explanation": [], - "risk_score": 76, - "risk_level": "high", - "required_attachment": true, - "required_fields": [], - "last_operation": { - "action": "publish", - "actor": "admin", - "at": "2026-05-30T10:00:00+08:00" - } -} -``` - -测试记录保留: - -```json -{ - "test_type": "simulation", - "input_text": "我去北京出差 3 天,上传武汉到上海车票", - "attachments": [], - "recognized_fields": {}, - "normalized_fields": {}, - "execution_result": {}, - "trace": {}, - "passed": true, - "tester": "admin", - "tested_at": "2026-05-30T10:10:00+08:00" -} -``` - -## 算法与公式 - -### 风险评分 - -风险评分由模型辅助判断,但必须结构化输出。建议使用可解释加权模型: - -$$ -score = \min(100, base + \sum_{i=1}^{n} w_i x_i + c + e) -$$ - -变量说明: - -- $base$:业务领域基础风险分。预算、发票、付款类通常高于普通提示类。 -- $x_i$:风险因子是否存在或强度,例如金额影响、附件缺失、字段冲突、越权、历史重复。 -- $w_i$:风险因子权重。 -- $c$:复杂度修正,例如多字段交叉、跨单据、跨时间窗口、跨附件识别。 -- $e$:例外说明修正。存在合理说明时可降低,但不能直接清零。 - -等级映射: - -- 0-30:低风险。 -- 31-60:中风险。 -- 61-80:高风险。 -- 81-100:极高风险。 - -### 流程复杂度控制 - -为了避免流程图过大,建议定义流程复杂度: - -$$ -complexity = node_count + 0.5 \times edge_count + branch_count -$$ - -处理规则: - -- `complexity <= 12`:单图展示。 -- `12 < complexity <= 20`:合并说明节点,保留关键判断。 -- `complexity > 20`:详情页展示主流程,测试弹窗展示完整 trace。 - -## 测试方案 - -### 单元测试 - -- 语义计划生成:复杂差旅城市规则不能退化为关键词判断。 -- DSL schema 校验:缺字段、非法算子、空 action 必须失败。 -- 执行器:城市匹配、日期范围、金额阈值、附件缺失、例外说明。 -- 流程转换:同一 DSL 生成稳定的 `flow_model` 和 SVG。 -- 风险评分:低/中/高/极高边界分数。 - -### 接口测试 - -- 新建规则返回生成中资产。 -- 生成完成后包含 `dsl`、`flow_model`、`flow_diagram_svg`、`risk_score`。 -- 仿真测试返回 `recognized_fields`、`normalized_fields`、`trace`。 -- 未测试通过的规则不能发布。 -- 已上线规则创建修订版本,不覆盖线上版本。 - -### 前端测试 - -- 新建弹窗不再选择风险等级。 -- 详情页展示风险分数、流程解释、流程图。 -- 流程图不可点击、不可拖拽、无工具栏。 -- 测试弹窗显示字段识别结果和判断路径。 -- 已上线规则只能创建修订版本修改。 - -### 容器验证 - -后续开发验证默认在 Docker 容器内执行: - -```bash -docker exec x-financial-main sh -lc "cd /app/server && pytest --timeout=60" -docker exec x-financial-main sh -lc "cd /app/web && npm run build" -``` - -### 本轮落地结果 - -已落地接口: - -- `GET /agent-assets/risk-rules/templates`:返回预算、票据、差旅、招待、采购/AP、企业卡、通用模板分组,包含默认自然语言、字段清单、附件要求和 DSL 样例。 -- `PATCH /agent-assets/{asset_id}/risk-rules/draft`:编辑未上线风险规则草稿。 -- `POST /agent-assets/{asset_id}/risk-rules/revisions`:为已上线规则创建修订草稿。 -- `POST /agent-assets/{asset_id}/risk-rules/regenerate`:重新生成 DSL、流程图、风险评分和业务说明。 -- `POST /agent-assets/{asset_id}/risk-rules/feedback`、`GET /agent-assets/{asset_id}/risk-rules/feedback`:记录和查看误判/漏判反馈。 - -关键文件: - -- 后端模板库与契约:`risk_rule_template_catalog.py`、`agent_asset.py`、`agent_asset_risk_rules.py`。 -- 后端生成、修订、发布、反馈、仿真:`risk_rule_generation*`、`agent_asset_risk_rule_revision.py`、`agent_asset_risk_rule_regeneration.py`、`agent_asset_risk_rule_publish.py`、`agent_asset_risk_rule_feedback.py`、`agent_asset_risk_rule_simulation.py`。 -- 前端新建、详情、测试:`AuditRuleDialogs.vue`、`AuditJsonRiskRuleDetail.vue`、`RiskRuleFlowDiagram.vue`、`RiskRuleTestDialog.vue`、`auditViewDetailTopBar.js`、`useAuditRiskRuleActions.js`、`useAuditAssetData.js`。 -- 测试:`test_risk_rule_template_catalog.py`、`test_risk_rule_feedback.py`、`test_risk_rule_revision_endpoints.py`、`test_risk_rule_explainability.py`、`risk-rule-detail-experience.test.mjs`。 - -已执行验证命令: - -```bash -docker exec x-financial-main bash -lc "cd /app/server && timeout 60 /tmp/x-financial-server-venv/bin/python -m pytest tests/test_risk_rule_template_catalog.py tests/test_openapi_schema.py -q" -docker exec x-financial-main bash -lc "cd /app/server && timeout 60 /tmp/x-financial-server-venv/bin/python -m pytest tests/test_risk_rule_feedback.py tests/test_risk_rule_revision_endpoints.py tests/test_openapi_schema.py -q" -docker exec x-financial-main bash -lc "cd /app/web && timeout 60 node --test tests/risk-rule-detail-experience.test.mjs" -docker exec x-financial-main bash -lc "cd /app/web && timeout 60 npm run build" -``` - -## 指标与验收 - -- [A1] 新建复杂差旅规则后,详情页流程解释不能出现“检查是否包含风险关键词”这类错误表达。 -- [A2] 详情页流程图与 JSON DSL 条件数量、分支方向、命中动作一致。 -- [A3] 仿真测试能显示票据识别字段,并说明为什么命中或未命中。 -- [A4] 同一条测试样例的执行 trace 可以高亮流程图路径。 -- [A5] 已上线规则修改时不会改变当前线上执行结果,只有发布修订版本后才替换。 -- [A6] 低、中、高、极高风险都能由评分模型产出,不应默认集中在中高风险。 -- [A7] 前端构建通过,后端定向测试 60s 内完成。 - -## 风险与开放问题 - -- LLM 语义理解仍可能出错,因此必须有 schema 校验、执行器 dry-run、详情解释和仿真测试兜底。 -- 字段本体不完整会限制规则表达,需要持续扩展费用、票据、预算、采购/AP 字段。 -- 复杂规则可能产生过大的流程图,需要主流程和完整 trace 分层展示。 -- 老规则没有 `semantic_plan` 或 `flow_model`,需要兼容展示并允许重新生成。 -- 常见规则模板要避免写成定制逻辑。模板只能提供默认文本、字段和 DSL 样例,最终仍走通用生成链路。 - -当前仍需持续演进的点: - -- 企业卡、采购/AP、预算场景的字段本体还偏少,后续应补充企业卡交易流水、供应商、采购订单、合同、预算期间等字段。 -- 复杂规则的准确性仍依赖 Hermes 语义计划质量,执行前必须继续保留 DSL validator、执行器 dry-run 和仿真测试。 -- 模板库只作为规则编写入口的业务参考,不作为规则执行捷径;新增模板时必须同时提供 DSL 样例和 validator 测试。 - -## 实现确认 - -当前实现仍围绕“解释图和执行逻辑一致”推进:自然语言先经字段本体和语义计划形成受控 JSON DSL,详情页流程图、文字流程解释、测试 trace、上线版本均围绕同一份 DSL 展示和执行,没有新增流程图编辑器或绕过规则执行器的判断链路。 diff --git a/document/development/risk-rule-explainable-flow/TODO.md b/document/development/risk-rule-explainable-flow/TODO.md deleted file mode 100644 index a1cbe43..0000000 --- a/document/development/risk-rule-explainable-flow/TODO.md +++ /dev/null @@ -1,96 +0,0 @@ -# 风险规则可解释流程判断改造 TODO - -## 使用规则 - -- 每个 TODO 对应 `CONCEPT.md` 的目标、能力或验收点。 -- 只有真实完成并通过相应验证后,才能把 `[ ]` 改成 `[x]`。 -- 如果实现中发现需求变化,先更新 `CONCEPT.md`,再调整本 TODO。 -- 后端和构建验证默认在 Docker 容器 `x-financial-main` 的 `/app` 下执行。 - -## 1. 调研与边界 - -- [x] [CONCEPT: 背景与问题] 梳理当前风险规则生成链路,记录 `risk_rule_generation.py` 到 `risk_rule_template_executor.py` 的真实调用关系。证据:`CONCEPT.md` 后端设计与本轮落地结果记录生成、DSL validator、执行器、流程图、仿真测试链路。 -- [x] [CONCEPT: 前端设计] 梳理详情页、新建弹窗、测试弹窗当前字段来源,记录 `AuditRuleDialogs.vue`、`AuditJsonRiskRuleDetail.vue`、`RiskRuleTestDialog.vue` 的改造点。证据:`CONCEPT.md` 本轮落地结果列出三个组件及对应职责,`risk-rule-detail-experience.test.mjs` 覆盖关键接线。 -- [x] [CONCEPT: 数据设计] 确认 `AgentAssetRead`、版本内容、`config_json` 中已有字段,确定 `semantic_plan`、`flow_model`、`flow_diagram_svg` 的落点。证据:`AgentAssetRead` 返回 `latest_test_summary`,版本 JSON metadata 保存 `semantic_plan`/`flow_model`/`flow_diagram_svg`,生成测试覆盖。 -- [x] [CONCEPT: 非目标] 明确本期不做流程图编辑器,不增加拖拽、缩放、节点编辑能力。证据:`RiskRuleFlowDiagram.vue` 只渲染静态 SVG/文字说明,无编辑、拖拽、缩放入口;前端回归测试断言不存在 zoom 按钮。 - -## 2. 语义计划与 DSL 契约 - -- [x] [CONCEPT: C2] 定义 `semantic_plan` schema,包含规则意图、适用范围、字段本体映射、判断步骤、例外条件和风险动作。证据:`risk_rule_explainability.py` 产出 `semantic_plan`,`test_risk_rule_explainability.py` 已验证。 -- [x] [CONCEPT: C3] 定义 JSON DSL schema,补齐城市、日期、金额、附件、语义说明等通用算子。证据:`risk_rule_dsl_validator.py` 定义受控 DSL 校验,`risk_rule_generation_interpreter.py` 补充 `numeric_compare`,`risk_rule_template_executor.py` 支持日期、字段集合、附件存在性、文本例外和数值比较算子。 -- [x] [CONCEPT: C3] 增加 DSL validator,禁止复杂字段判断退化为“风险关键词匹配”。证据:`validate_risk_rule_draft` 会将城市一致性关键词规则改写为结构化比较,将预算金额关键词规则改写为 `composite_rule_v1`,`test_risk_rule_dsl_validator.py` 覆盖。 -- [x] [CONCEPT: C3] 为差旅城市不一致、住宿日期越界、预算阈值、重复发票各准备一条 DSL 样例。证据:新增 `risk_rule_dsl_examples.py`,并通过 `test_risk_rule_dsl_examples.py` 覆盖四类样例的 validator 与执行器命中/未命中回归。 -- [x] [CONCEPT: C2] 字段展示统一为 `中文[英文]` 格式,并复用字段本体解释。证据:`risk_rule_explainability.py` 的 `semantic_plan.required_fields.display` 使用字段本体生成 `label[key]`。 - -## 3. Hermes 生成链路 - -- [x] [CONCEPT: 总体链路] 调整 `risk_rule_generation_prompt.py`,要求 Hermes 先输出 `semantic_plan`,再输出 DSL。证据:提示词 `required_json_shape` 改为 `{ semantic_plan, dsl }`,`test_prompt_requires_semantic_plan_then_dsl` 验证。 -- [x] [CONCEPT: C2] 在提示词中明确:城市、日期、金额、票据关系必须用结构化比较,不允许用关键词替代。证据:`risk_rule_generation_prompt.py` 补充 `numeric_compare` 和预算金额不得关键词匹配的 guardrail。 -- [x] [CONCEPT: 后端设计] 在 `risk_rule_generation_semantics.py` 或解释层补齐语义计划解析与错误返回。证据:`risk_rule_generation_semantic_plan.py` 解析 `{ semantic_plan, dsl }` 包装并保留 `metadata.model_semantic_plan`;后台生成失败写入 `generation_error` 和 `last_operation=generation_failed`,容器内 `test_risk_rule_generation_failure.py` 与语义计划测试通过。 -- [x] [CONCEPT: 后端设计] 在 `risk_rule_generation_interpreter.py` 中从 `semantic_plan` 生成标准 DSL。证据:新增 `build_dsl_from_semantic_plan`,当 Hermes 仅返回 `semantic_plan` 时生成 `composite_rule_v1` 草稿,再由 DSL validator 基于字段本体规范成受控条件;`test_semantic_plan_only_response_can_generate_standard_dsl` 通过。 -- [x] [CONCEPT: 指标与验收] 增加复杂差旅规则生成测试,确认判断依据不是关键词匹配。证据:`test_generate_complex_travel_route_rule_uses_formula_not_keyword_match` 验证复杂差旅规则生成后为结构化城市一致性规则,且 `condition_summary` 不含“风险关键词”;容器内 `test_risk_rule_generation.py` 通过。 - -## 4. 流程模型与 SVG - -- [x] [CONCEPT: C4] 定义 `flow_model` schema,包含 nodes、edges、字段引用、分支标签和风险节点。证据:`risk_rule_explainability.py` 产出 `flow_model`,生成测试验证 nodes/source/metadata 同步。 -- [x] [CONCEPT: C4] 修改 `risk_rule_flow_diagram.py`,改为从 DSL 或 `flow_model` 生成 SVG。证据:新增 `build_risk_rule_flow_diagram_spec`,优先从 `flow_model.nodes` 生成图形 spec,缺失时回退 `params.conditions`;`test_flow_diagram_spec_prefers_flow_model_nodes` 通过。 -- [x] [CONCEPT: C4] 保持 Style 7 / OpenAI Official 风格:白底、细边框、低饱和、风险节点单点强调。证据:`RiskRuleFlowDiagramRenderer` 输出白底、细边框、低饱和风险色,既有 `test_risk_rule_generation.py` 校验高风险红色、无旧绿色和无阴影滤镜。 -- [x] [CONCEPT: 算法与公式] 实现流程复杂度控制,节点过多时压缩主流程。证据:`_condition_lines_from_flow_nodes` 将超过 4 个判断节点压缩为摘要,`test_flow_diagram_spec_compresses_too_many_decision_nodes` 覆盖。 -- [x] [CONCEPT: C4] 为老规则缺少 `flow_model` 的情况保留默认静态图兜底。证据:`build_risk_rule_flow_diagram_spec` 在 `flow_model` 缺失时使用 DSL/metadata 生成 spec,`test_flow_diagram_spec_falls_back_to_dsl_when_flow_model_missing` 通过。 - -## 5. 执行器 trace 与仿真测试 - -- [x] [CONCEPT: C5] 修改 `RiskRuleTemplateExecutor`,输出每个判断节点的 trace。证据:新增 `evaluate_with_trace`,仿真测试返回 `trace.steps` 和 `path_node_ids`。 -- [x] [CONCEPT: C5] 仿真测试统一在“用户点击运行”后处理附件和文本,不允许上传后立即判断。证据:`RiskRuleTestDialog.vue` 的 `handleFileChange` 只把附件加入待发送列表,`sendMessage` 才调用 `recognizeTemporaryFiles` 与 `simulateRiskRuleTest`;容器内 `npm run build` 通过。 -- [x] [CONCEPT: C5] 测试结果中展示 OCR 原始字段、Hermes 规范化字段、执行器实际输入字段。证据:`AgentAssetRiskRuleSimulationRead` 新增 `ocr_raw_fields`、`hermes_normalized_fields`、`executor_input_fields`,`RiskRuleTestDialog.vue` 展示字段流水线;容器内 `test_risk_rule_explainability.py` 与 `test_risk_rule_generation.py` 通过。 -- [x] [CONCEPT: C5] 测试弹窗展示命中路径、未命中原因和最终风险动作。证据:`RiskRuleTestDialog.vue` 展示“执行路径”,`riskRuleTestDialogDisplay.js` 格式化 trace。 -- [x] [CONCEPT: C5] trace 中的 `node_id` 必须能映射到流程图节点。证据:`flow_model` 使用条件 id 作为节点 id,`risk_rule_execution_trace.py` 输出同名 `node_id`。 - -## 6. 规则修改与版本化 - -- [x] [CONCEPT: C6] 未上线规则支持编辑标题、费用领域、附件要求和自然语言描述。证据:新增 `AgentAssetRiskRuleRevisionService.update_unpublished_draft` 与 `PATCH /agent-assets/{asset_id}/risk-rules/draft`,容器内 `test_risk_rule_revision_endpoints.py` 覆盖返回字段。 -- [x] [CONCEPT: C6] 已上线规则新增“创建修订版本”,不直接覆盖 active 版本。证据:新增 `AgentAssetRiskRuleRevisionService.create_revision_draft` 与 `POST /agent-assets/{asset_id}/risk-rules/revisions`,测试验证 `published_version` 保持不变且 `working_version` 进入修订版本。 -- [x] [CONCEPT: C6] 修订版本保存后重新生成 DSL、流程图、风险评分和业务说明。证据:新增 `AgentAssetRiskRuleRegenerationService` 与 `POST /agent-assets/{asset_id}/risk-rules/regenerate`,草稿/修订草稿都会重新生成 JSON DSL、`flow_diagram_svg`、风险评分和版本 Markdown;容器内 `test_regenerate_revision_draft_keeps_active_document_unchanged` 通过。 -- [x] [CONCEPT: C6] 发布修订版本时归档旧版本,并记录修改人、修改原因和测试报告。证据:新增 `AgentAssetRiskRulePublishMixin`,发布修订时将旧 `rule_document` 写入 `revision_history.previous_rule_document`,切换新 JSON 文件并写入 `last_operation=publish_revision`;容器内 `test_publish_regenerated_revision_replaces_online_document` 通过。 -- [x] [CONCEPT: C6] 普通用户误判/漏判反馈进入规则反馈记录,不直接修改规则。证据:新增 `agent_asset_rule_feedback` 模型、`POST/GET /agent-assets/{asset_id}/risk-rules/feedback`、前端服务方法;容器内 `test_risk_rule_feedback.py`、规则回归和 `npm run build` 通过。 - -## 7. 常见费控规则模板库 - -- [x] [CONCEPT: C1] 增加“从常见规则模板创建”入口。证据:`AuditRuleDialogs.vue` 新建风险规则弹窗新增常见规则模板选择,选择后预填标题、附件要求、业务环节、费用领域和自然语言。 -- [x] [CONCEPT: C1] 模板按预算、票据、差旅、招待、采购/AP、企业卡、通用分组。证据:新增 `risk_rule_template_catalog.py`,`GET /agent-assets/risk-rules/templates` 返回 7 个分组;容器内 `test_risk_rule_template_catalog.py` 通过。 -- [x] [CONCEPT: C3] 每个模板提供默认自然语言、字段清单、附件要求和 DSL 样例。证据:模板接口返回 `natural_language`、`fields`、`requires_attachment`、`dsl_example`;容器内测试逐个调用 DSL validator 验证通过。 -- [x] [CONCEPT: 非目标] 模板不得绕过通用生成链路,不写定制校准器。证据:前端模板只预填 `riskRuleCreateForm`,提交仍走 `generateRiskRuleAsset`;无新增定制校准器,容器内 `npm run build` 通过。 - -## 8. 前端详情与交互 - -- [x] [CONCEPT: 前端设计] 详情页 topbar 展示规则标题、状态、风险分数、风险等级、上线/启用状态。证据:`auditViewDetailTopBar.js` 为风险规则详情输出风险分、风险等级、规则状态、上线状态、启用状态 KPI;容器内 `npm run build` 通过。 -- [x] [CONCEPT: C4] 判断流程区域改成左侧文字流程解释、右侧流程图。证据:`RiskRuleFlowDiagram.vue` 使用左侧 `risk-rule-flow-explainer` 和右侧 `risk-rule-flow-visual` 的两栏布局;容器内 `npm run build` 通过。 -- [x] [CONCEPT: C4] 流程图标题固定为“流程图”,高度与“流程解释”标题对齐。证据:`RiskRuleFlowDiagram.vue` 使用统一 `risk-rule-section-title`,右侧标题固定为“流程图”;容器内 `npm run build` 通过。 -- [x] [CONCEPT: C5] 测试弹窗展示字段识别结果、规范化字段、判断路径和测试报告。证据:`RiskRuleTestDialog.vue` 展示字段流水线、执行路径和右侧测试报告摘要;容器内 `cd /app/web && npm run build` 通过。 -- [x] [CONCEPT: C6] 已上线规则详情展示“创建修订版本”,草稿规则展示“编辑规则”。证据:`AuditView.vue` 底部动作区按规则状态展示按钮,`AuditRuleDialogs.vue` 提供编辑/修订弹窗,`useAuditRiskRuleActions.js` 调用草稿编辑与修订接口;容器内 `cd /app/web && npm run build` 通过。 -- [x] [CONCEPT: 指标与验收] 列表和详情状态刷新不能造成页面闪烁。证据:`useAuditAssetData.loadSelectedAssetDetail` 增加 `{ silent: true }` 静默刷新,规则保存、送审、审核、上线、回退和版本操作均改为静默刷新;容器内 `npm run build` 通过。 - -## 9. 后端接口与权限 - -- [x] [CONCEPT: 接口设计] 实现或调整 `POST /agent-assets/{asset_id}/risk-rules/revisions`。证据:新增独立路由 `agent_asset_risk_rules.py`,容器内 `test_create_risk_rule_revision_endpoint_keeps_active_version` 通过。 -- [x] [CONCEPT: 接口设计] 实现或调整 `PATCH /agent-assets/{asset_id}/risk-rules/draft`。证据:新增独立路由 `agent_asset_risk_rules.py`,容器内 `test_update_risk_rule_draft_endpoint_updates_unpublished_rule` 与已上线阻断用例通过。 -- [x] [CONCEPT: 接口设计] `POST /agent-assets/{asset_id}/risk-rules/regenerate` 返回生成状态和错误详情。证据:独立路由 `agent_asset_risk_rules.py` 已接入重生成接口,成功返回 `AgentAssetRead.config_json.generation_status`/`revision_draft.generation_status`,接口用例 `test_regenerate_risk_rule_endpoint_returns_updated_detail` 通过。 -- [x] [CONCEPT: 接口设计] 仿真测试接口返回 `recognized_fields`、`normalized_fields`、`execution_result`、`trace`。证据:`AgentAssetRiskRuleSimulationRead` 新增 `normalized_fields` 和 `trace`,仿真测试覆盖返回值。 -- [x] [CONCEPT: 用户与场景] 普通财务人员只能编辑未上线/修订草稿,admin 才能删除和测试,管理员按现有权限上线/下线。证据:路由依赖使用 `RuleEditorUser`、`RuleReviewerUser`、`PlatformAdminUser` 分层,`test_risk_rule_revision_endpoints.py` 覆盖 finance 新建/测试阻断、manager 删除阻断和 manager 启停入口。 -- [x] [CONCEPT: 数据设计] 所有操作写入 `last_operation`,用于详情页“最后操作”展示。证据:生成、后台生成、草稿编辑、创建修订、重新生成、发布/下线、测试确认等风险规则服务均写入 `config_json.last_operation`,前端 `AuditJsonRiskRuleDetail.vue` 展示 `lastOperationLabel`。 - -## 10. 测试与验证 - -- [x] [CONCEPT: 测试方案] 后端补充语义计划、DSL validator、执行器 trace、流程图转换单元测试。证据:`test_risk_rule_explainability.py` 覆盖语义计划、flow_model、trace;`test_risk_rule_dsl_validator.py` 覆盖 DSL validator 与 `numeric_compare` 执行;容器内相关测试通过。 -- [x] [CONCEPT: 测试方案] 后端补充修订版本接口和发布替换接口测试。证据:`test_risk_rule_revision_service.py` 覆盖草稿编辑、创建修订、修订重生成和发布替换;`test_risk_rule_revision_endpoints.py` 覆盖草稿编辑、创建修订和重生成接口;容器内相关测试通过。 -- [x] [CONCEPT: 测试方案] 前端补充详情页流程展示、测试弹窗字段展示、修订版本按钮状态测试。证据:新增 `risk-rule-detail-experience.test.mjs` 覆盖 topbar KPI、左文右图流程、字段流水线和修订按钮;容器内 `node --test tests/risk-rule-detail-experience.test.mjs` 通过。 -- [x] [CONCEPT: 容器验证] 在容器执行后端定向测试,单个命令设置 60s 超时。证据:`/tmp/x-financial-server-venv/bin/python -m pytest tests/test_risk_rule_explainability.py -q`、`test_risk_rule_composite_generation.py -q`、`test_risk_rule_generation.py -q` 均通过。 -- [x] [CONCEPT: 容器验证] 在容器执行 `cd /app/web && npm run build`。证据:容器 `/app/web` 构建通过。 -- [x] [CONCEPT: 指标与验收] 用“武汉到上海票据 + 北京出差 3 天”样例验证城市不一致规则必须命中或给出明确不命中原因。证据:`test_simulation_returns_execution_trace_for_ticket_city_mismatch` 验证命中并返回 trace。 -- [x] [CONCEPT: 指标与验收] 用预算阈值、重复发票、住宿日期越界、招待人均超标样例做回归。证据:`risk_rule_dsl_examples.py` 已包含预算阈值、重复发票、住宿日期越界、招待人均超标样例,`test_risk_rule_dsl_examples.py` 在容器内 7 passed。 - -## 11. 文档收尾 - -- [x] [CONCEPT: 指标与验收] 开发完成后补充实际接口、文件和测试命令结果。证据:`CONCEPT.md` 新增“本轮落地结果”,列出接口、关键文件和容器验证命令。 -- [x] [CONCEPT: 风险与开放问题] 记录暂未解决的字段本体缺口和复杂规则降级策略。证据:`CONCEPT.md` 风险与开放问题补充企业卡、采购/AP、预算字段本体缺口和 DSL validator/dry-run/仿真兜底策略。 -- [x] [CONCEPT: 功能一句话] 确认最终实现没有偏离“解释图和执行逻辑一致”的核心目标。证据:`CONCEPT.md` 新增“实现确认”,明确自然语言、字段本体、JSON DSL、流程图、测试 trace 和上线版本围绕同一 DSL。 diff --git a/document/development/travel-application-planning-nudge/CONCEPT.md b/document/development/travel-application-planning-nudge/CONCEPT.md deleted file mode 100644 index 9020da9..0000000 --- a/document/development/travel-application-planning-nudge/CONCEPT.md +++ /dev/null @@ -1,27 +0,0 @@ -# 差旅申请后行程规划推荐 - -## 背景 - -用户完成差旅申请后,当前流程直接结束,交互偏机械。差旅申请本身已经包含地点、行程时间、出行方式、天数等信息,系统可以在申请提交成功后继续以对话形式询问是否需要行程规划。 - -## 目标 - -- 仅在差旅费用申请提交成功后追加一条对话式推荐。 -- 推荐内容应基于本次申请的已知字段,不要求用户重新输入地点和时间。 -- 用户同意后,在当前申请助手对话中生成规划建议。 -- 规划建议只提供交通时间窗口、酒店区域、待确认事项,不创建订单、不保存草稿、不调用真实订票接口。 - -## 非目标 - -- 不接入真实火车、机票、酒店预订。 -- 不改变申请单提交和审批状态。 -- 不强制用户继续规划。 - -## 交互 - -1. 用户确认提交差旅申请。 -2. 系统返回申请提交成功结果。 -3. 系统追加一条轻量对话:询问是否需要行程规划。 -4. 用户点击“生成行程规划”后,系统在对话中给出推荐。 -5. 用户点击“暂不需要”后,系统简短确认,不再继续追问。 - diff --git a/document/development/travel-application-planning-nudge/TODO.md b/document/development/travel-application-planning-nudge/TODO.md deleted file mode 100644 index 5b28300..0000000 --- a/document/development/travel-application-planning-nudge/TODO.md +++ /dev/null @@ -1,8 +0,0 @@ -# 差旅申请后行程规划推荐 TODO - -- [x] 新增差旅规划推荐工具,按申请预览字段生成提示、动作和规划正文。 -- [x] 申请提交成功后追加规划推荐对话。 -- [x] 支持“生成行程规划”和“暂不需要”两个对话动作。 -- [x] 增加前端静态测试覆盖,防止回退成死板结束流程。 -- [x] 运行定向测试和前端构建验证。 - diff --git a/document/development/半年报销模拟数据/CONCEPT.md b/document/development/半年报销模拟数据/CONCEPT.md deleted file mode 100644 index bc10d70..0000000 --- a/document/development/半年报销模拟数据/CONCEPT.md +++ /dev/null @@ -1,154 +0,0 @@ -# 半年报销模拟数据概念文档 - -## 功能一句话 - -为本地演示环境生成 2026 年上半年公司报销、预算和员工组织样本,让财务看板与预算中心能直接呈现半年经营分析效果。 - -## 背景与问题 - -当前容器数据库已有员工与预算基础表,但报销样本很少,无法观察半年维度的费用趋势、部门支出结构、预算使用率和风险预警效果。用户希望把公司人数扩充到 100 人,并模拟半年报销数据,用于查看整体分析和预算管控效果。 - -现状只读检查结果: - -- `employees=82` -- `expense_claims=3` -- `budget_allocations=240` -- `budget_transactions=241` -- `risk_observations=0` -- 尚无 `SIM2026` 员工、`SIM-EXP-2026` 报销单和 `SIM-BUD-2026` 预算数据。 - -## 目标与非目标 - -目标: - -- 把本地演示公司员工补齐到 100 人,不删除已有员工。 -- 生成 2026 年 1 月到 6 月的报销单、报销明细和风险观察样本。 -- 生成或复用预算额度,并写入预算核销台账,让预算中心能看到真实使用率、预警和超支。 -- 保证脚本默认 dry-run,只有显式 `--apply` 才写数据库。 -- 生成完成后能用容器内 DB 统计和真实 API 返回值验证。 - -非目标: - -- 不接入真实生产 API,不导入真实个人敏感数据。 -- 不删除或重置用户已有数据;如未来需要清理模拟数据,应另走显式确认。 -- 不改造预算中心、财务看板和报销审批页面结构。 -- 不把模拟数据写入启动流程,避免每次启动自动膨胀数据。 - -## 用户与场景 - -- 财务负责人:查看半年费用趋势、待审批金额、风险数量和 SLA。 -- 预算管理者:查看部门和费用科目的预算使用率、预警线和剩余额度。 -- 产品演示者:用 100 人组织规模演示智能费控、预算中心和分析看板的联动。 - -## 功能能力 - -### 输入 - -- 目标员工数:默认 100。 -- 模拟窗口:默认 `2026-01-01` 到 `2026-06-30`。 -- 随机种子:固定值,确保样本可复现。 -- 执行模式:默认 dry-run,`--apply` 写入数据库。 - -### 输出 - -- 新增员工:只补齐缺口,员工编号前缀 `SIM2026`。 -- 新增报销单:编号前缀 `SIM-EXP-2026`。 -- 新增明细:按报销单生成 1 到 3 条费用明细。 -- 新增预算额度:编号前缀 `SIM-BUD-2026`,按部门、季度、费用科目覆盖差旅、招待、办公和通信。 -- 新增预算交易:编号前缀 `SIM-BTX-2026`,对已通过、待付款、已付款和完成状态写入 `consume` 台账,对待审批状态写入 `reserve` 台账。 -- 新增风险观察:编号前缀 `SIM-RISK-2026`,用于财务看板风险混合和异常数统计。 - -### 边界 - -- 如果员工数已经大于等于 100,只新增 0 人,不删除已有员工。 -- 如果同编号模拟数据已存在,脚本跳过,保证重复执行不重复膨胀。 -- 预算使用率通过交易台账计算,不直接改写预算余额字段。 -- 预算超支样本允许存在,用于展示预算效果和预警,但需要控制比例,避免所有部门都显示异常。 - -## 方案设计 - -### 后端脚本 - -新增独立服务模块: - -- `demo_company_simulation_seed.py`:封装模拟数据规划、dry-run 统计和 apply 写入。 - -新增命令脚本: - -- `seed_half_year_expense_demo.py`:解析参数并调用服务模块。 - -### 数据策略 - -- 组织:复用现有 `OrganizationUnit`,优先使用部门节点和成本中心。 -- 员工:补齐到 100 人,按部门规模权重分配,职级覆盖 P3-P8。 -- 报销单:按员工、月份、费用类型生成,低频员工 1-2 单,高频角色 4-8 单。 -- 风险:约 12%-18% 的报销单带风险标记和 `RiskObservation`。 -- 预算:按部门、季度、科目创建模拟预算额度,Q2 相比 Q1 有 8%-18% 增长,部分市场、技术部门科目接近 80% 预警线。 - -### 运行命令 - -```bash -docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main \ - /tmp/x-financial-server-venv/bin/python server/scripts/seed_half_year_expense_demo.py -``` - -写入时使用: - -```bash -docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main \ - /tmp/x-financial-server-venv/bin/python server/scripts/seed_half_year_expense_demo.py --apply -``` - -## 算法与公式 - -### 员工缺口 - -$$ -new\_employees = \max(target\_employees - current\_employees,\ 0) -$$ - -### 报销金额 - -每类费用按基础金额、部门系数、职级系数和月度季节系数生成: - -$$ -claim\_amount = base\_amount(type) \times dept\_factor \times grade\_factor \times month\_factor \times noise -$$ - -### 预算使用率 - -预算中心沿用现有计算口径: - -$$ -usage\_rate = \frac{reserved\_amount + consumed\_amount}{original\_amount + adjusted\_amount} \times 100 -$$ - -### 风险样本概率 - -风险概率按金额分位和预算压力提升: - -$$ -risk\_probability = base\_risk + amount\_boost + budget\_pressure\_boost -$$ - -## 测试方案 - -- 单元测试:在 SQLite 内存库里验证 dry-run、员工补齐、幂等写入和预算交易统计。 -- 容器验证:在 `x-financial-main` 内运行定向测试,单次不超过 60s。 -- 运行时验证:执行 dry-run 后检查计划数量;执行 apply 前必须人工确认。 -- API 验证:写入后请求财务看板和预算汇总接口,确认 JSON 中员工、报销、预算使用率和风险指标有数据。 - -## 指标与验收 - -- 员工总数达到 100。 -- `SIM-EXP-2026` 半年报销单不少于 300 单。 -- 预算汇总接口返回 Q1、Q2 趋势,且至少有 1 条预算预警。 -- 财务看板 `has_real_data=true`,风险数、费用分类、部门排行和预算摘要均非空。 -- 重复执行脚本不会新增重复模拟数据。 - -## 风险与开放问题 - -- 批量写入数据库属于高风险操作,执行 `--apply` 前必须获得用户明确确认。 -- 如果当前数据库已有大量非模拟员工,脚本不会删除员工来凑精确 100 人,只保证不少于目标数。 -- 财务看板趋势接口当前最多按 90 天标签解析;半年分析主要依赖预算中心 Q1/Q2 趋势和自定义日期范围。 -- 如果后续要支持页面一键生成,需要另行设计权限、审计和清理机制。 diff --git a/document/development/半年报销模拟数据/TODO.md b/document/development/半年报销模拟数据/TODO.md deleted file mode 100644 index e8b2771..0000000 --- a/document/development/半年报销模拟数据/TODO.md +++ /dev/null @@ -1,23 +0,0 @@ -# 半年报销模拟数据 TODO - -## 调研与契约 - -- [x] [CONCEPT: 背景与问题] 读取员工、报销、预算和财务看板现有模型,确认模拟数据要写入 `employees`、`expense_claims`、`expense_claim_items`、`budget_allocations`、`budget_transactions`、`budget_reservations` 和 `risk_observations`。 -- [x] [CONCEPT: 背景与问题] 在 `x-financial-main` 容器内完成只读规模检查,当前员工 82 人、报销单 3 单、模拟前缀数据为 0。 -- [x] [CONCEPT: 方案设计] 明确脚本默认 dry-run,批量写入必须使用 `--apply` 并先得到用户确认。 - -## 数据生成 - -- [x] [CONCEPT: 数据策略] 新增模拟数据服务模块,封装员工、预算、报销、明细、风险观察的生成逻辑。证据:`demo_company_simulation_seed.py` 与 `demo_company_simulation_catalog.py`。 -- [x] [CONCEPT: 输入] 新增命令脚本,支持 `--target-employees`、`--start-date`、`--months`、`--seed`、`--apply`。证据:`seed_half_year_expense_demo.py`。 -- [x] [CONCEPT: 边界] 实现幂等逻辑:已存在的 `SIM2026`、`SIM-EXP-2026` 和 `SIM-BUD-2026` 数据不重复创建。证据:`test_half_year_simulation_preview_and_apply_are_idempotent`。 -- [x] [CONCEPT: 预算使用率] 通过 `BudgetTransaction` 和 `BudgetReservation` 形成预算使用效果,不直接改余额。证据:`test_half_year_simulation_feeds_budget_summary`。 - -## 验证 - -- [x] [CONCEPT: 测试方案] 新增定向单元测试,覆盖 dry-run、apply、员工补齐和幂等性。证据:`server/tests/test_demo_company_simulation_seed.py`。 -- [x] [CONCEPT: 测试方案] 在容器中以 60s 超时运行定向测试。证据:`pytest -q server/tests/test_demo_company_simulation_seed.py` 通过,2 passed。 -- [x] [CONCEPT: 运行命令] 执行 dry-run,输出计划写入规模。证据:dry-run 计划新增 18 名员工、495 张报销单、855 条明细、34 个预算池、459 条预算交易、83 条预占、55 条风险观察。 -- [x] [CONCEPT: 风险与开放问题] 获得用户确认后执行 `--apply` 写入本地数据库。证据:`seed_half_year_expense_demo.py --apply` 成功写入。 -- [x] [CONCEPT: 指标与验收] 用容器内 DB 统计确认员工数、模拟报销单、预算交易和风险观察。证据:员工 100 人,模拟报销 495 单、预算交易 459 条、风险观察 55 条。 -- [x] [CONCEPT: 指标与验收] 用真实 API 验证财务看板与预算汇总 JSON 已出现半年模拟数据效果。证据:预算汇总 API 返回 `warning_count=10`、`over_budget_count=3`;财务看板 API 返回 `has_real_data=true`、`riskCount=57`。 diff --git a/document/development/小财管家/CONCEPT.md b/document/development/小财管家/CONCEPT.md deleted file mode 100644 index 223670c..0000000 --- a/document/development/小财管家/CONCEPT.md +++ /dev/null @@ -1,424 +0,0 @@ -# 小财管家 - -## 功能一句话 - -小财管家是首页统一财务任务入口,负责把用户的自然语言和附件拆解为多个可确认、可追踪、可分派的申请与报销任务,再调用现有申请助手和报销助手完成执行闭环。 - -## 背景与问题 - -当前个人工作台已经提供首页输入框,并能通过本体解析把一句话路由到申请、报销、预算或知识等单一会话。这个能力适合单意图,但用户真实表达经常是多任务组合,例如同时包含出差申请、昨日交通费报销、历史出差费用报销以及多张附件。 - -现有问题: - -- 首页输入框当前会收敛为一个 `sessionType`,无法保留多任务计划。 -- 申请助手和报销助手已经具备单任务核对能力,但缺少上层任务拆解、归集和跨助手分派。 -- 附件上传后主要进入当前会话,缺少面向多任务的自动归集建议。 -- 财务动作需要确认后才能入库、绑定或提交,不能让大模型直接执行高风险动作。 -- 新增字段必须尊重本体字段,不能因为小财管家新增一套业务字段。 - -## 目标与非目标 - -### 目标 - -- 首页输入框定位为“小财管家”,作为用户默认财务任务入口。 -- 用户提交自然语言和附件后,先展示小财管家的任务识别与附件归集过程。 -- 支持把一句话拆成多个任务,第一版只验证费用申请和费用报销。 -- 支持多附件按费用场景、时间、地点、任务线索形成归集建议。 -- 遇到创建申请单、创建报销草稿、附件绑定、提交审批等动作时必须等待用户确认。 -- 保留现有申请助手和报销助手能力,小财管家只做上层编排和分派。 -- 外层意图识别必须优先使用大模型 function calling 输出结构化任务计划,规则逻辑只作为模型不可用或结构不合法时的兜底。 -- 前端展示“意图识别智能体”过程气泡,并用流式状态逐步呈现,不暴露模型内部推理链。 -- 所有业务字段先进入本体字段归一化,再进入下游助手、草稿、风险规则和持久化。 - -### 非目标 - -- 第一版不做万能智能体,不覆盖预算、审批、知识问答等全部场景。 -- 第一版不引入 LangChain 或 LangGraph,先复用项目内运行时模型配置和 OpenAI-compatible function calling 契约。 -- 第一版不自动提交审批,不绕过用户确认。 -- 第一版不新增业务语义字段;只新增任务编排态字段。 -- 第一版不重写申请助手、报销助手和现有 Orchestrator。 - -## 用户与场景 - -### 目标用户 - -- 普通员工:在首页一次性描述申请、报销和附件处理诉求。 -- 财务人员:查看任务拆解、附件归集和用户确认链路是否可追溯。 -- 审批/管理角色:后续可扩展为审批待办和预算提醒编排,但不进入第一版。 - -### 核心场景 - -用户在首页输入: - -```text -我想要申请7月2日去北京出差,辅助北京供电局的税务审核任务,并且我要报销昨天的交通费,还需要报销6月3日出差去上海的费用 -``` - -系统处理: - -1. 小财管家识别到三条候选任务。 -2. 将“昨天”按客户端日期解析为明确日期,例如 2026-06-03。 -3. 将“7月2日去北京出差”归为费用申请任务。 -4. 将“昨天的交通费”和“6月3日去上海出差费用”归为费用报销任务。 -5. 如果用户同时上传附件,系统先识别附件场景,再建议归集到对应任务。 -6. 需要创建申请单或报销草稿时,向用户展示核对摘要和确认动作。 - -## 功能能力 - -### 1. 任务识别与拆分 - -任务识别主链路是“小财管家意图识别智能体”: - -1. 后端读取系统设置中的主模型/备模型运行时配置。 -2. 将用户话术、客户端日期、附件元信息、上下文和 canonical ontology field 列表传入模型。 -3. 通过强制 function calling 调用 `submit_steward_intent_plan`。 -4. 模型只能返回结构化参数:`thinking_events`、`tasks`、`attachment_groups`。 -5. 服务端再次校验:任务类型只能是 `expense_application` / `reimbursement`,业务字段只能是 canonical ontology fields,附件名必须来自本次上传。 -6. 如果模型未配置、调用失败、未返回工具调用或结构不合法,才切换到规则兜底,并在过程摘要中标记兜底原因。 - -输入: - -- 用户自然语言 `message` -- 附件元信息 `attachments` -- 当前用户、部门、角色、客户端时间 -- 已有会话上下文,可选 - -输出: - -- `plan_id`:本次小财管家计划 ID -- `tasks`:多个任务条目 -- `thinking_events`:面向用户展示的过程摘要 -- `confirmation_groups`:需要用户确认的动作集合 -- `attachment_groups`:附件归集建议 - -任务条目包含: - -- `task_id`:编排态任务 ID -- `task_type`:`expense_application` 或 `reimbursement` -- `assigned_agent`:`application_assistant` 或 `reimbursement_assistant` -- `title`:任务标题 -- `summary`:任务摘要 -- `status`:`planned`、`needs_confirmation`、`ready_to_delegate`、`delegated`、`completed`、`blocked` -- `confidence`:识别置信度 -- `ontology_fields`:归一化后的本体字段 -- `missing_fields`:缺失字段 -- `confirmation_required`:是否需要确认后执行 - -### 2. 附件归集 - -附件归集基于以下信号: - -- 附件类型:发票、火车票、机票、酒店票、付款截图、招待票据等。 -- 费用场景:差旅、交通、招待、住宿、其他。 -- 日期:票据日期是否匹配任务时间。 -- 地点:票据地点是否匹配任务地点。 -- 金额:是否能参与报销草稿。 -- 置信度:低置信度必须提示用户核对。 - -输出示例: - -```json -{ - "group_id": "ag_travel_001", - "target_task_id": "task_reim_002", - "scene": "travel", - "scene_label": "差旅费用", - "attachment_names": ["上海高铁票.jpg", "上海酒店发票.pdf", "出租车票.png"], - "excluded_attachment_names": ["客户招待发票.jpg"], - "confidence": 0.86, - "confirmation_required": true -} -``` - -### 3. 用户确认 - -必须确认的动作: - -- 创建费用申请单。 -- 创建报销草稿。 -- 将附件归集并绑定到某一任务。 -- 将附件关联到已有报销草稿。 -- 提交审批。 -- 修改已有草稿字段。 - -小财管家的确认动作采用“下一步优先”策略: - -- 同一个计划里同时存在申请和报销时,前端只展示当前下一步主动作,不一次性摊开全部确认按钮。 -- 下一步优先级为:费用申请单创建 > 报销单填写 > 附件归集确认。 -- 小财管家先思考和分析,说明下一步将要做的行为;用户输入“确定”或点击确认后,才进入行动。 -- 行动完成后重新检查剩余任务队列,继续进入“思考 -> 分析 -> 等待确认 -> 行动”的循环。 -- 申请任务完成后,再把剩余报销任务作为后续任务引导到报销助手。 -- 附件归集不作为第一屏主动作抢占申请流程;当进入报销任务时,相关附件随报销上下文带入。 - -小财管家必须维护运行时任务上下文,而不是把每次用户输入都当成新的独立意图。上下文至少包含: - -- 当前任务:正在处理的申请或报销任务。 -- 剩余任务:已拆解但尚未处理的任务队列。 -- 已完成任务:已经形成申请单、报销草稿、附件归集或提交动作的任务。 -- 等待动作:当前正在等待用户补字段、确认核对表、确认提交审批或继续下一项。 -- 最近结构化结果:当前申请核对表、报销核对结果、附件归集建议等。 - -用户输入“确认”“无误”“可以提交”等文本时,小财管家必须先匹配当前等待动作;如果当前等待的是申请单提交确认,就提交当前申请单;如果当前等待的是继续下一项,就进入剩余任务队列中的下一项;如果当前核对表仍有缺字段,则提示补字段。只有没有可匹配上下文时,才重新进入任务规划。 - -上述匹配不应主要依赖前端关键词规则。第一版应新增“小财管家运行时决策智能体”,由后端 function calling 接收 `runtime_state` 和用户当前输入,返回结构化 `next_action`: - -- `submit_current_application`:确认当前申请核对表并提交至审批。 -- `continue_next_task`:当前任务已完成,继续剩余任务队列中的下一项。 -- `fill_current_slot`:用户补充了当前等待字段。 -- `ask_user`:当前信息不足,需要继续追问。 -- `plan_new_tasks`:当前没有可匹配上下文,重新进入任务规划。 -- `cancel_current_action` / `no_op`:取消或不执行当前动作。 - -前端只执行模型返回的结构化动作,并做安全校验:例如申请核对表必须 `readyToSubmit` 才能提交,已提交消息必须标记避免重复提交,缺字段时必须追问。本地规则只允许作为模型失败后的保守兜底,不作为主判断来源。 - -可以自动执行的动作: - -- 任务拆解。 -- 本体字段归一化。 -- 附件分类。 -- 缺失字段检查。 -- 风险和规则预审。 -- 生成确认摘要。 - -### 4. 流式过程摘要 - -前端展示的是“意图识别智能体”的过程摘要,不是模型内部推理链;过程摘要必须独立于最终回复正文展示。过程摘要必须围绕业务理解展开,例如用户说了什么、被拆成哪些申请/报销任务、已识别哪些业务要素、还缺少哪些关键条件、为什么需要向用户追问。不能只展示“接收确认、协调能力、准备输出”等系统执行日志。 - -示例: - -```text -正在识别用户输入中的财务事项... -已识别到 3 个候选任务。 -正在按时间、地点和费用场景核对附件... -发现 3 张附件疑似属于差旅费用,1 张附件需要单独处理。 -等待你确认后,我再创建申请单或报销草稿。 -``` - -第一版通过 `POST /steward/plans/stream` 返回 `application/x-ndjson` 流式事件: - -- `thinking`:逐条追加到系统回复气泡上方的独立“意图识别智能体”折叠气泡。 -- `plan`:返回完整任务计划后,再渲染最终正文、任务卡片、附件归集和确认动作。 - -流式接口必须在模型 function calling 完成前先返回首个 `thinking` 事件,告知用户“意图识别智能体接管”。后续模型返回后再追加结构化拆解、字段映射、附件归集等过程摘要。 - -前端收到 `thinking` 事件后,也必须以 typewriter 方式逐字展示过程摘要,不能把一条完整思考事件一次性塞进折叠气泡。多条 `thinking` 事件应排队顺序输出,上一条内容打完后再输出下一条。 - -前端流式超时必须区分“首包等待”和“流式空闲等待”:首包应快速返回,收到首包后不能再用固定总时长中断仍在思考的模型调用,只能在长时间没有任何新事件时判定空闲超时。 - -流式过程中正文区域不输出任务结论;计划完成后意图识别气泡默认折叠,正文只保留用户需要确认和执行的信息。 - -计划完成后的最终正文也必须流式输出。前端不能把完整正文一次性替换到消息气泡里,而应进入 `typing` 状态按字符逐步追加正文;正文输出完成后,再把状态改为“等待用户确认”并展示确认按钮。 - -用户确认当前步骤后,小财管家隐式委派给申请能力或报销能力时,也必须保持同一套流式体验:先在系统气泡上方的小财管家思考折叠气泡中逐字展示当前业务任务、已识别信息、待补充条件和下一步动作;拿到申请核对表或报销核对结果后,再逐字输出正文。结构化表格、核对卡片、确认按钮可以在正文输出完成后一次性展示,但正文不能一次性替换进消息气泡。 - -小财管家委派期间不得打开右侧单助手执行流程面板,也不得把“申请助手 / 报销助手”的执行步骤显示成独立助手思考框。用户可见身份保持“小财管家”,具体调用哪个能力只作为小财管家自己的过程摘要,不切换为“财务助手”或单独助手会话。 - -### 5. 用户可见结果展示 - -小财管家的第一屏最终正文必须采用适中信息量的分段结构:让用户看懂系统理解了哪些财务事项、先后顺序是什么、每一步会交给哪个助手做什么;但不要把任务摘要、置信度、字段缺口和附件判断提前摊开。 - -第一屏推荐结构: - -1. `我会这样推进`:说明识别到几个财务事项,以及会逐步处理。 -2. 顺序列表:说明先做什么、后做什么,每步附一句负责助手和动作边界。 -3. 确认提示:请用户回复“确定”后开始第一步,并说明具体缺口会在对应步骤里再判断。 - -最终正文必须使用 Markdown 块结构渲染,至少包含标题、段落和顺序列表;标题与段落之间必须保留空行,并通过 `steward-plan-markdown` 专属样式拉开块间距。不能只依赖普通换行拼接文本,因为普通换行在对话气泡里会显得拥挤。 - -第一屏不展示任务详情卡片里的“还需要补充”,也不展示字段缺口说明。用户确认开始后,进入当前步骤的申请助手或报销助手,再由具体助手基于当前任务判断需要补充什么。 - -后续步骤如果需要展示“还需要补充”,必须是结构化列表,每个待补充项独立成行,包含字段业务名称和填写说明;不得把多个待补充项拼接成一行连续文本。 - -当后续步骤发现关键条件缺失时,小财管家不能只展示“模型复核不稳定”或“下方表格待补充”。它必须把缺口转成下一轮对话问题,并优先给出可直接选择的业务选项。例如差旅申请缺少 `transport_mode` 时,用户界面展示为“请问你打算怎么出行?火车、飞机或轮船”,不得先展示申请核对表,也不得默认补成火车;用户选择后再生成申请核对表、写回出行方式、重新测算费用,并继续判断是否可以提交申请。这是“思考 -> 行动 -> 再思考 -> 再行动”循环的一部分。 - -用户补齐关键字段也不是终态动作。以“出行方式”为例,用户选择火车后,小财管家必须先进入下一轮业务思考,基于已识别的时间、地点、事由和出行方式模拟查询交通票据或票价口径,完成系统预估金额测算,再流式输出正文并展示申请核对表;不能在用户点击选项后直接把旧核对表补字段后闪现出来。 - -费用申请核对表阶段不得把系统档案字段或非阻塞归档字段当作用户待补充项。`employee_no`、`employee_name`、`department_name` 应从当前登录用户档案和组织上下文读取;`attachments` 在差旅申请阶段不阻塞核对表生成,可在后续报销、归档或审批材料补充阶段处理;`amount` 在申请阶段由系统规则估算。字段决策模型即使返回这些字段为缺失,服务端也必须过滤,不能向用户展示“附件/凭证和员工编号为合规必需字段”这类错误追问。 - -任务卡片和正文不得直接暴露本体字段名,例如 `transport_mode`、`amount`、`attachments`。本体字段只允许作为内部结构化数据进入后端、助手委派和持久化链路;用户界面必须翻译为业务中文,并提供可理解的填写说明: - -- `transport_mode` 展示为“出行方式”,说明可填写高铁、飞机、自驾、出租车等。 -- `amount` 在申请任务中展示为“预计金额”,在报销任务中展示为“报销金额”。 -- `attachments` 展示为“附件/凭证”,说明可上传发票、行程单、付款截图或其他证明材料。 -- `merchant_name` 展示为“商户/开票方”。 -- `customer_name` 展示为“客户或项目对象”。 - -## 本体字段约束 - -业务字段必须使用本体 canonical field: - -- `expense_type` -- `time_range` -- `location` -- `reason` -- `amount` -- `transport_mode` -- `attachments` -- `customer_name` -- `merchant_name` -- `department_name` -- `employee_name` -- `employee_no` - -兼容字段只能作为输入别名,例如: - -- `occurred_date` -> `time_range` -- `business_time` -> `time_range` -- `reason_value` -> `reason` -- `transport_type` -> `transport_mode` -- `application_transport_mode` -> `transport_mode` - -小财管家的编排态字段不进入业务语义本体: - -- `plan_id` -- `task_id` -- `planning_source` -- `model_call_traces` -- `task_status` -- `assigned_agent` -- `confirmation_status` -- `attachment_group_id` -- `thinking_event_id` - -这些字段只用于编排、展示和审计,不参与费用规则判断。 - -## 方案设计 - -### 后端 - -新增小财管家规划服务: - -- `schemas/steward.py`:定义请求、任务计划、附件归集、确认动作等契约。 -- `services/runtime_chat.py`:新增 `complete_with_tool_call`,复用主/备模型配置发送 `tools` 与 `tool_choice`。 -- `services/steward_intent_agent.py`:负责构造 `submit_steward_intent_plan` function schema 与模型调用。 -- `services/steward_model_plan_builder.py`:负责把模型工具参数转换为服务端可校验计划。 -- `services/steward_planner.py`:负责“大模型 function calling 优先、规则兜底”的编排和本体字段归一化。 -- `api/v1/endpoints/steward.py`:提供 `POST /steward/plans` 和 `POST /steward/plans/stream`。 - -后端第一版不直接落库业务单据,只返回计划和确认动作。确认后的执行仍走现有申请助手、报销助手和 Orchestrator。 - -### 前端 - -新增或改造能力: - -- 首页输入框标题和提示文案改为“小财管家”。 -- 工作台打开时默认使用 `sessionType=steward`。 -- 小财管家模式下隐藏“智能体切换”工具条。 -- 小财管家模式下不展示欢迎界面。 -- 小财管家模式下使用专属底部输入框,仅保留附件、自然语言输入和发送动作。 -- 小财管家模式下先流式渲染独立过程摘要,再渲染任务计划正文。 -- 用户确认当前下一步后,再切换/分派到申请助手或报销助手执行;多任务按顺序推进,不把所有任务动作一次性展示给用户。 - -### 执行流 - -```text -首页输入 - ↓ -小财管家计划接口 - ↓ -意图识别智能体 function calling - ↓ -思考过程流式输出 + 任务分析 + 下一步动作说明 - ↓ -等待用户输入“确定”或点击确认 - ↓ -小财管家隐式调用申请助手创建申请单核对结果 - ↓ -申请动作完成后重新思考剩余队列 - ↓ -继续等待确认并隐式调用报销助手填写报销单 - ↓ -执行结果汇总 -``` - -## 算法与公式 - -第一版主路径不以关键词规则定义“意图”,而是使用大模型 function calling 生成结构化计划。 -模型输出后由服务端做确定性校验、字段归一化和确认动作生成。 - -规则置信度评分仅用于模型不可用或模型返回结构不可用时的兜底路径。 - -任务拆解之后还需要第二层“任务字段决策智能体”。这一步不能由前端关键词或固定 required 字段直接决定,而要把当前任务类型、用户原话、上游任务拆解结果、canonical ontology fields、已抽取字段、缺失字段、附件和申请/报销上下文交给模型,通过 function calling 返回下一步动作: - -- `ask_user`:当前信息不足,必须先把缺口转成业务问题和可选项。 -- `render_preview`:当前信息足够生成可核对结果,但提交、入库、绑定附件前仍需用户确认。 - -字段决策规则只能作为模型不可用或结构化结果非法时的兜底,兜底结果必须标记为 `rule_fallback`,不能伪装成智能体判断。字段名必须来自 ontology registry;UI 只展示中文业务名称,不展示 canonical 字段名。 - -任务置信度: - -$$ -confidence = \min(1, 0.35s_i + 0.25s_t + 0.2s_l + 0.2s_a) -$$ - -变量说明: - -- `s_i`:意图关键词得分,命中申请/报销核心动词。 -- `s_t`:时间得分,识别到明确日期、相对日期或时间范围。 -- `s_l`:地点得分,识别到城市、客户或业务对象。 -- `s_a`:附件/费用场景得分,识别到票据、交通、住宿、招待等费用线索。 - -附件归集置信度: - -$$ -group\_score = 0.4m_s + 0.3m_t + 0.2m_l + 0.1m_n -$$ - -变量说明: - -- `m_s`:附件场景与任务场景匹配度。 -- `m_t`:附件日期与任务日期匹配度。 -- `m_l`:附件地点与任务地点匹配度。 -- `m_n`:附件名称和任务关键词匹配度。 - -## 测试方案 - -### 后端单元测试 - -- function calling 路径能把模型工具参数转换为 `planning_source=llm_function_call` 的任务计划。 -- 模型返回 `occurred_date`、`transport_type`、`reason_value` 等别名时,服务端仍只输出 canonical 字段。 -- 一句话中同时包含申请和报销时,返回多个任务。 -- “昨天”能根据 `client_now_iso` 解析为明确日期。 -- `occurred_date`、`transport_type`、`reason_value` 等兼容字段不会作为业务 canonical 字段输出。 -- 多附件能生成差旅归集建议和排除项。 -- 创建/绑定/提交类动作必须带 `confirmation_required=true`。 - -### 前端测试 - -- 首页输入复杂话术后打开小财管家模式。 -- 小财管家模式标题显示“小财管家”,不展示智能体切换。 -- 过程摘要按步骤渐进展示。 -- 任务计划卡片展示申请任务和报销任务。 -- 附件归集建议展示包含项、排除项和确认按钮。 - -### 容器验证 - -后端测试必须在 `x-financial-main` 容器内执行: - -```bash -docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_steward_planner.py -``` - -前端构建优先使用宿主机 `npm.cmd` 或项目既有脚本,并设置合理超时。 - -## 指标与验收 - -- 输入包含 3 个任务的示例话术时,至少识别出 1 个申请任务和 2 个报销任务。 -- 输入“明天出差北京3天,支撑国网仿生产部署,并且报销昨天业务招待费”时,必须识别出 1 个申请任务和 1 个报销任务。 -- 模型可用时,小财管家计划响应包含 `planning_source=llm_function_call`。 -- 小财管家计划响应中业务字段只出现 canonical ontology fields。 -- 附件场景混合时,能区分差旅相关附件和非差旅附件。 -- 前端弹窗标题为“小财管家”,并隐藏智能体切换。 -- 前端确认区只展示当前下一步主动作;存在申请任务时,第一步必须是“先创建申请单”。 -- 意图识别折叠气泡不得宽于正文气泡,且流式首包必须先于最终计划到达。 -- 用户未确认前,不创建申请单、不创建报销草稿、不绑定附件、不提交审批。 -- 后端定向测试通过。 - -## 风险与开放问题 - -- 模型供应商对 tools/function calling 的兼容度可能不同;第一版保留规则兜底和主备模型 failover。 -- 规则兜底无法覆盖所有自然语言,需要保留人工确认和低置信度提示。 -- 附件真实 OCR 归集依赖现有票据识别质量;第一版先使用附件名称和已有 OCR 摘要做轻量归集。 -- NDJSON 流式输出展示的是过程摘要,不是模型内部推理链。 -- 多任务之间可能共享日期、地点、申请单上下文,需要后续完善任务图依赖。 -- 如果未来接入 LangGraph,应基于当前计划契约迁移,而不是推翻现有申请/报销助手。 diff --git a/document/development/小财管家/TODO.md b/document/development/小财管家/TODO.md deleted file mode 100644 index f6ac99c..0000000 --- a/document/development/小财管家/TODO.md +++ /dev/null @@ -1,66 +0,0 @@ -# 小财管家 TODO - -## 阶段一:调研与契约 - -- [x] 盘点首页输入框、工作台弹窗、会话路由和本体字段注册表。[CONCEPT: 背景与问题] 证据:已确认 `PersonalWorkbench.vue`、`useAppShell.js`、`TravelReimbursementCreateView.vue`、`ontology_field_registry.py`。 -- [x] 定义第一版只覆盖申请助手和报销助手,不引入 LangChain,但外层意图识别使用大模型 function calling。[CONCEPT: 目标与非目标] 证据:`CONCEPT.md` 已明确 MVP 边界和 function calling 主链路。 -- [x] 明确小财管家业务字段必须走 ontology canonical fields,编排字段不得进入业务本体。[CONCEPT: 本体字段约束] 证据:`CONCEPT.md` 已列出 canonical 字段与编排态字段。 - -## 阶段二:后端规划服务 - -- [x] 新增 `schemas/steward.py`,定义计划请求、任务、附件归集、确认动作和响应模型。[CONCEPT: 后端] 证据:`StewardPlanRequest`、`StewardTask`、`StewardAttachmentGroup`、`StewardConfirmationAction` 已新增。 -- [x] 扩展 `services/runtime_chat.py`,支持 OpenAI-compatible / Azure OpenAI 的 `tools` 与 `tool_choice` function calling。[CONCEPT: 后端] 证据:新增 `complete_with_tool_call`、`RuntimeChatToolCall` 和工具调用解析。 -- [x] 新增 `services/steward_intent_agent.py`,定义 `submit_steward_intent_plan` function schema 并调用系统主/备模型。[CONCEPT: 任务识别与拆分] 证据:模型调用入口已从 `StewardPlannerService` 注入。 -- [x] 新增 `services/steward_model_plan_builder.py`,将模型工具参数转换为服务端可校验计划。[CONCEPT: 后端] 证据:模型返回后仍会校验任务类型、canonical 字段和附件名。 -- [x] 改造 `services/steward_planner.py`,实现大模型 function calling 优先、规则规划兜底。[CONCEPT: 任务识别与拆分] 证据:`planning_source` 区分 `llm_function_call` 与 `rule_fallback`。 -- [x] 新增 `api/v1/endpoints/steward.py`,提供 `POST /steward/plans`。[CONCEPT: 后端] 证据:容器内接口 smoke 返回 `task_count=3`。 -- [x] 新增 `POST /steward/plans/stream`,以 NDJSON 返回 `thinking` 和最终 `plan` 事件。[CONCEPT: 流式过程摘要] 证据:真实接口 smoke 返回事件序列 `thinking,thinking,thinking,thinking,plan`。 -- [x] 调整 `POST /steward/plans/stream`,确保模型 function calling 完成前先返回首个 `thinking` 事件。[CONCEPT: 流式过程摘要] 证据:live smoke 首个事件为 `thinking/stream_start`。 -- [x] 在 `api/v1/router.py` 注册小财管家接口。[CONCEPT: 后端] 证据:运行中 `/api/v1/steward/plans` 返回 200。 -- [x] 保证所有输出到 `ontology_fields` 的业务字段只使用 canonical ontology fields。[CONCEPT: 本体字段约束] 证据:测试断言 `occurred_date`、`transport_type`、`reason_value` 不进入输出字段。 -- [x] 强化模型提示词和规则兜底,确保“未来出差/去某地几天/部署支撑”即使未出现“申请”也识别为费用申请。[CONCEPT: 任务识别与拆分] 证据:live smoke 将“明天出差北京3天...”拆为 `expense_application,reimbursement`。 - -## 阶段三:前端入口和弹窗 - -- [x] 将首页输入区主文案调整为“小财管家”,提示语体现可处理多任务。[CONCEPT: 前端] 证据:`PersonalWorkbench.vue` 标题和 placeholder 已更新。 -- [x] 增加 `steward` 会话类型,首页复杂输入默认进入小财管家模式。[CONCEPT: 前端] 证据:`SESSION_TYPE_STEWARD` 与首页 `sessionType` 已接入。 -- [x] 小财管家模式下隐藏“智能体切换”工具条。[CONCEPT: 前端] 证据:`shortcuts` 在 `isStewardSession` 下返回空数组。 -- [x] 小财管家模式下标题显示“小财管家”,副标题说明“统一财务任务编排入口”。[CONCEPT: 前端] 证据:`assistantHeaderTitle` 和 `assistantHeaderDescription` 已按 steward 分支处理。 -- [x] 小财管家模式下不展示欢迎界面。[CONCEPT: 前端] 证据:`useTravelReimbursementSessionState.js` 对 steward 空会话返回空消息,并过滤旧欢迎消息快照。 -- [x] 小财管家模式下使用专属底部输入框,不展示日期选择、差旅计算器和业务时间标签。[CONCEPT: 前端] 证据:`TravelReimbursementCreateView.vue` 按 `isStewardSession` 渲染 `steward-composer-row`。 -- [x] 新增前端小财管家计划服务,调用 `POST /steward/plans`。[CONCEPT: 后端] 证据:`web/src/services/steward.js` 已新增 `fetchStewardPlan`。 -- [x] 新增小财管家视图模型,生成过程摘要、任务计划卡片和附件归集卡片。[CONCEPT: 流式过程摘要] 证据:`stewardPlanModel.js` 和 `TravelReimbursementMessageItem.vue` 已接入 `stewardPlan`。 -- [x] 支持后端 `thinking` 事件真流式呈现为折叠式意图识别气泡。[CONCEPT: 流式过程摘要] 证据:`useStewardPlanFlow.js` 通过 `fetchStewardPlanStream` 接收 thinking 事件,并用 `typeStewardThinkingEvent` 将每条过程摘要逐字输出到折叠气泡。 -- [x] 支持小财管家最终正文逐字流式输出,正文完成前不展示确认按钮。[CONCEPT: 流式过程摘要] 证据:`useStewardPlanFlow.js` 新增 `typeStewardPlanText`,计划完成后进入 `typing` 状态逐字追加正文,完成后再注入 `suggestedActions`。 -- [x] 意图识别过程放在系统回复气泡上方,作为不同颜色的独立折叠气泡,完成后默认折叠。[CONCEPT: 流式过程摘要] 证据:`TravelReimbursementMessageItem.vue` 将 `steward-intent-bubble` 放在 `message-bubble` 上方,`steward-plan-block` 只渲染任务和附件结果。 -- [x] 统一小财管家思考折叠气泡与正文气泡宽度,避免思考气泡长于正文框。[CONCEPT: 流式过程摘要] 证据:`has-steward-plan` 消息栈统一为 760px,思考气泡和正文气泡同宽。 -- [x] 优化小财管家最终正文和任务卡片层次,用户可见内容不直接展示本体字段名。[CONCEPT: 用户可见结果展示] 证据:`stewardPlanModel.js` 第一屏使用 Markdown 标题、段落和顺序列表说明“先做什么、后做什么、交给哪个助手做什么”,但不展示置信度和字段缺口;`useStewardPlanFlow.js` 将第一屏标记为 `initialSummaryOnly`,`TravelReimbursementMessageItem.vue` 不再渲染第一屏任务详情卡片;后续步骤如需展示待补充项,再按独立列表行展示业务名称和填写说明。 - -## 阶段四:确认与分派 - -- [x] 为每个创建/绑定/提交类动作生成确认按钮,不确认不执行。[CONCEPT: 用户确认] 证据:接口返回 `confirmation_count=4`,前端转为 suggested actions。 -- [x] 将小财管家确认区改为“只展示当前下一步主动作”,存在申请任务时优先进入申请助手。[CONCEPT: 用户确认] 证据:`buildStewardSuggestedActions` 只返回下一步动作,优先 `confirm_create_application`。 -- [x] 支持用户输入“确定”触发小财管家的下一步动作,而不是重新生成计划。[CONCEPT: 用户确认] 证据:`useStewardPlanFlow` 会查找待确认的小财管家动作并执行。 -- [x] 支持小财管家隐藏委派申请/报销能力,执行后保留小财管家会话并继续引导剩余任务。[CONCEPT: 执行流] 证据:`sessionTypeOverride` 和 `stewardContinuation` 已接入前端提交流程。 -- [x] 支持小财管家确认后的隐式委派继续流式输出,正文完成后再展示申请核对表、报销核对卡片和确认按钮。[CONCEPT: 流式过程摘要] 证据:`useTravelReimbursementSubmitComposer.js` 新增 `typeStewardDelegatedMessage`,申请预览与 orchestrator 结果均先流式思考、再逐字正文、最后挂载结构化 payload;`npm.cmd --prefix web run build` 成功。 -- [x] 小财管家委派申请/报销能力期间不打开右侧单助手执行流程面板,用户可见身份保持“小财管家”。[CONCEPT: 流式过程摘要] 证据:`stewardDelegated` 分支跳过 flow step 与 review panel scope,并在最终消息设置 `assistantName: '小财管家'`;`stewardPlanModel.js` 助手标签兜底不再显示“财务助手”。 -- [x] 小财管家在后续步骤发现关键缺口时,主动转成可回答的问题和选项,而不是只展示待补充表格。[CONCEPT: 用户可见结果展示] 证据:`useTravelReimbursementSubmitComposer.js` 在申请核对缺少“出行方式”时只输出主动追问和火车/飞机/轮船选项,不提前挂载 `applicationPreview`;`stewardPlanModel.js` 的内部 `carry_text` 不再把“高铁、飞机”等示例写进缺字段提示,避免本地抽取误当成用户已选择;`TravelReimbursementCreateView.js` 在用户选择后不再直接补旧表格,而是重新进入小财管家的委派流;`web/tests/expense-application-fast-preview.test.mjs` 覆盖该回归。 -- [x] 用户补齐出行方式后,小财管家必须先思考、模拟查询票据和测算金额,再展示申请核对表。[CONCEPT: 用户可见结果展示] 证据:`stewardFieldCompletionModel.js` 将补齐字段后的当前任务、本体字段和旧预览重组为续跑输入;`TravelReimbursementCreateView.js` 的 `continueStewardApplicationFieldCompletion` 调用 `submitComposerInternal` 触发流式思考、申请复核和费用测算,不再调用 `commitApplicationPreviewEditor` 直接闪现表格。 -- [x] 防止残留预算上下文抢占小财管家的申请续跑链路。[CONCEPT: 执行流] 证据:`budgetAssistantReportModel.js` 不再因存在 `initialBudgetContext` 就无条件进入预算编制报告;`useTravelReimbursementSubmitComposer.js` 对 `stewardDelegated` 显式跳过预算编制分支;`expense-application-fast-preview.test.mjs` 覆盖“申请续跑 + 残留预算上下文”不得进入预算编制。 -- [x] 支持用户直接输入“确认/无误/可以提交”命中当前申请核对表提交动作,而不是重新规划。[CONCEPT: 用户确认] 证据:`TravelReimbursementCreateView.js` 通过 `handleStewardRuntimeDecision` 优先请求运行时决策智能体;模型返回 `submit_current_application` 后复用 `confirmApplicationSubmit`;本地 `handleApplicationSubmitConfirmationText` 仅作为模型不可用时的兜底;提交成功后标记 `applicationSubmitConfirmed`,避免后续重复提交;测试 `text confirmation submits pending application preview before replanning steward task` 覆盖该优先级。 -- [x] 增加小财管家运行时决策智能体,把“确认、继续下一项、补字段、重新规划”的上下文判断迁到后端 function calling。[CONCEPT: 用户确认] 证据:`POST /steward/runtime-decisions` 调用 `StewardRuntimeDecisionAgent`,通过 `submit_steward_runtime_decision` 返回 `submit_current_application`、`continue_next_task`、`fill_current_slot`、`plan_new_tasks` 等动作;前端 `handleStewardRuntimeDecision` 先提交 `runtime_state`,再执行模型返回的结构化动作,本地规则仅兜底。 -- [x] 增加第二层任务字段决策智能体,动态判断当前任务应追问用户还是展示核对结果。[CONCEPT: 算法与公式] 证据:`POST /steward/slot-decisions` 调用 `StewardSlotDecisionAgent`,通过 `submit_steward_slot_decision` function calling 输出 `ask_user` / `render_preview`、canonical 缺失字段、问题和选项;前端 `useTravelReimbursementSubmitComposer.js` 在小财管家委派申请时消费该决策。 -- [x] 防止字段决策模型把申请阶段非阻塞字段误判为用户必填项。[CONCEPT: 用户可见结果展示] 证据:`StewardSlotDecisionAgent` 过滤 `amount`、`attachments`、`employee_no`、`department_name`、`employee_name`,模型误返 `ask_user` 且过滤后无缺口时改为 `render_preview`;前端 `APPLICATION_NON_BLOCKING_ONTOLOGY_FIELDS` 同步过滤兜底缺口和选项;测试覆盖附件/员工编号误判。 -- [x] 小财管家思考气泡必须体现业务意图和关键缺口,不能退化为系统执行日志。[CONCEPT: 流式过程摘要] 证据:`steward_planner.py` 将差旅申请缺少“出行方式”纳入计划缺口并追加业务缺口思考事件;`useTravelReimbursementSubmitComposer.js` 和 `TravelReimbursementCreateView.js` 的确认后思考改为读取任务摘要、已识别信息和待补充项。 -- [x] 确认申请任务后,将任务摘要分派到现有申请助手会话。[CONCEPT: 执行流] 证据:确认动作携带 `session_type=application` 和 `auto_submit=true`。 -- [x] 确认报销任务后,将任务摘要和附件带入现有报销助手会话。[CONCEPT: 执行流] 证据:确认动作携带 `session_type=expense`、`carry_files=true` 和 `auto_submit=true`。 -- [x] 附件归集建议确认后,将选中附件作为报销助手上下文继续处理。[CONCEPT: 附件归集] 证据:附件归集确认动作携带归集附件名称和排除附件名称。 - -## 阶段五:测试与验证 - -- [x] 新增 `server/tests/test_steward_planner.py`,覆盖多任务拆解、相对日期、附件归集、确认动作和流式事件。[CONCEPT: 测试方案] 证据:新增 4 个后端定向测试。 -- [x] 补充 function calling 定向测试,覆盖模型工具参数、canonical 字段清洗、附件归集和规则兜底。[CONCEPT: 后端单元测试] 证据:`test_steward_planner.py` 新增 fake function calling 路径,`test_runtime_chat_service.py` 新增 tools payload 用例。 -- [x] 后端测试在 Docker `x-financial-main:/app` 内执行,超时控制在 60s 内。[CONCEPT: 容器验证] 证据:`pytest -q server/tests/test_steward_planner.py server/tests/test_runtime_chat_service.py` 结果 `13 passed`。 -- [ ] 新增或更新前端定向测试,覆盖小财管家标题、隐藏智能体切换和计划展示。[CONCEPT: 前端测试] -- [x] 运行前端构建或定向测试,确认 UI 编译通过。[CONCEPT: 测试方案] 证据:`npm.cmd run build` 成功。 -- [x] 通过接口或页面可见结果证明用户最终看到小财管家计划和确认点。[CONCEPT: 指标与验收] 证据:容器接口返回 3 个任务、3 份归集附件、1 份排除附件和 4 个确认动作。 diff --git a/document/development/小财管家本体JSON流程/CONCEPT.md b/document/development/小财管家本体JSON流程/CONCEPT.md deleted file mode 100644 index cbe2f9e..0000000 --- a/document/development/小财管家本体JSON流程/CONCEPT.md +++ /dev/null @@ -1,273 +0,0 @@ -# 小财管家本体 JSON 流程 - -## 功能一句话 - -用大模型作为小财管家的主意图识别器,将用户连续对话转换为受本体字段约束的业务 JSON,并在申请和报销意图不确定时先进入用户确认,而不是用固定规则直接判定。 - -## 背景与问题 - -当前小财管家已经具备任务规划、部分运行时状态和申请/报销委派能力,但仍有两个关键缺口: - -- 意图识别仍带有较强规则假设。例如“2月20-23日去上海出差辅助国网仿生产环境部署”这类话术,在没有“申请”或“报销”动词时,系统不能仅凭规则直接判定为申请。 -- 跨轮对话需要一个贯穿流程的结构化 JSON。该 JSON 必须只承载本体 canonical field,不能由前端、规则或大模型临时发明业务字段。 - -因此,本轮目标不是重写整个小财管家,而是在现有 `steward` 体系上补齐“LLM 主识别 + 本体 JSON 模板 + 待确认流程 + 上下文记忆”的闭环。 - -## 目标与非目标 - -### 目标 - -- 用大模型 function calling 作为主路径识别用户意图。 -- 模型输出必须落到统一业务 JSON 模板,字段来源必须来自本体字段注册表。 -- 支持 `travel_application` 和 `travel_reimbursement` 两个业务流程。 -- 当用户话术无法确定是申请还是报销时,返回 `pending_flow_confirmation`,由前端展示两个明确选项。 -- 跨轮对话持续携带并合并 `steward_state`,直到用户完成、取消或切换业务。 -- 规则只做兜底,且响应必须标记 `rule_fallback`,不能伪装成模型判断。 -- 用户可见回复使用 Markdown 块结构,重点信息加粗,避免密集换行。 - -### 非目标 - -- 本轮不引入 LangChain 或 LangGraph。 -- 本轮不迁移申请助手、报销助手和 Orchestrator 的既有核心逻辑。 -- 本轮不让大模型直接创建申请单、保存草稿、绑定附件或提交审批。 -- 本轮不新增脱离本体字段体系的新业务字段。 -- 本轮不改造所有财务场景,只先覆盖出差申请和差旅/费用报销。 - -## 用户与场景 - -- 普通员工:在首页或小财管家对话框中说“2月20-23日去上海出差辅助国网仿生产环境部署”。 -- 小财管家:先判断该话术包含出差、时间、地点和事由,但缺少“申请还是报销”的明确动作。 -- 用户:点击“补办出差申请”或“发起费用报销”。 -- 系统:将用户选择写入同一个业务 JSON,并继续用对应流程追问缺字段、生成核对结果或委派现有助手。 - -示例预期: - -```markdown -我识别到你描述的是一次 **上海出差事项**,时间为 **2月20日至2月23日**,事由是 **辅助国网仿生产环境部署**。 - -但当前还不能确定你要做哪一件事: - -1. **补办出差申请** -2. **发起费用报销** - -请先选择一个方向,我会继续整理对应材料。 -``` - -## 功能能力 - -### 输入 - -- 用户自然语言 `message`。 -- 当前时间 `client_now_iso`,用于解析相对日期。 -- 附件元信息和 OCR 摘要。 -- 当前 `conversation_id`。 -- 已持久化 `steward_state`。 -- ontology canonical fields 列表。 - -### 输出 - -- `steward_state`:贯穿对话的业务 JSON。 -- `intent_result`:本轮模型或兜底规则的识别结果。 -- `candidate_flows`:存在歧义时的候选流程。 -- `next_action`:下一步动作,例如追问、确认流程、渲染申请预览、渲染报销预审。 -- `markdown_reply`:面向用户的 Markdown 回复。 - -### 状态边界 - -业务 JSON 必须区分业务字段和编排字段: - -- 业务字段只允许出现在 `flows..fields`。 -- 业务字段 key 必须是 canonical ontology field。 -- 编排字段只能出现在 `active_flow`、`pending_flow_confirmation`、`events`、`status` 等结构里。 -- 规则或模型返回的别名字段必须先归一化,例如 `occurred_date -> time_range`、`transport_type -> transport_mode`、`reason_value -> reason`。 - -### 安全边界 - -- 保存草稿、创建申请单、提交审批、删除或绑定附件必须等待用户确认。 -- LLM 只能产出结构化建议,不直接执行副作用操作。 -- 如果模型返回非法字段、非法流程或非法动作,服务端丢弃非法部分并进入保守兜底。 - -## 业务 JSON 模板 - -目标模板如下: - -```json -{ - "version": "steward.flow_state.v2", - "active_flow": "", - "pending_flow_confirmation": { - "status": "none", - "source_message": "", - "reason": "", - "candidate_flows": [] - }, - "flows": { - "travel_application": { - "flow_id": "travel_application", - "intent": "travel_application_create", - "status": "idle", - "fields": {}, - "missing_fields": [], - "confidence": 0, - "evidence": [] - }, - "travel_reimbursement": { - "flow_id": "travel_reimbursement", - "intent": "travel_reimbursement_draft", - "status": "idle", - "fields": {}, - "missing_fields": [], - "linked_application_claim_id": "", - "attachments": [], - "confidence": 0, - "evidence": [] - } - }, - "events": [] -} -``` - -候选流程结构: - -```json -{ - "flow_id": "travel_application", - "label": "补办出差申请", - "confidence": 0.52, - "reason": "用户描述了出差时间、地点和事由,但没有明确要求报销或提交申请。" -} -``` - -## 方案设计 - -### 后端 - -新增或扩展以下职责: - -- `schemas/steward.py`:增加 v2 JSON 状态、候选流程、待确认流程和意图识别响应模型。 -- `services/steward_intent_agent.py`:扩展 function schema,允许模型返回 `pending_flow_confirmation` 和 `candidate_flows`。 -- `services/steward_model_plan_builder.py`:校验模型输出,只保留合法 flow、合法 action 和 canonical ontology fields。 -- `services/steward_flow_state.py`:支持 v1 到 v2 状态兼容、字段 patch 合并、候选流程落态和事件追踪。 -- `services/steward_runtime_decision_agent.py`:识别用户点击或输入的流程选择,并把选择写回 `active_flow`。 -- `api/v1/endpoints/steward.py`:在 `/steward/plans`、`/steward/plans/stream`、`/steward/runtime-decisions` 中统一返回最新 `steward_state`。 - -### 前端 - -- `stewardPlanModel.js`:将 `pending_flow_confirmation` 转为可点击操作。 -- `TravelReimbursementCreateView.js`:用户点击候选流程后,优先走 runtime decision,不重新把原句当新任务规划。 -- `useStewardPlanFlow.js`:渲染 Markdown 回复和候选流程操作。 -- `useTravelReimbursementSessionState.js`:持续保存并传回 `conversation_id` 和 `steward_state`。 - -### 数据与持久化 - -- 复用 `AgentConversation.state_json` 持久化 `steward_state`。 -- 不新增数据库表。 -- 不改变申请单、报销单现有表结构。 - -### 接口契约 - -`POST /steward/plans` 和流式计划接口返回: - -```json -{ - "planning_source": "llm_function_call", - "conversation_id": "conv_xxx", - "steward_state": {}, - "next_action": "confirm_flow", - "candidate_flows": [], - "summary": "Markdown 文本" -} -``` - -运行时确认接口返回: - -```json -{ - "decision_source": "llm_function_call", - "next_action": "continue_selected_flow", - "steward_state": {}, - "response_text": "Markdown 文本" -} -``` - -## 算法与公式 - -主路径不使用关键词打分决定最终意图,而是由 LLM function calling 返回结构化候选结果。 - -规则兜底仅在模型不可用、超时或结构非法时使用。兜底置信度用于决定是否直接进入候选确认: - -$$ -confidence(flow) = 0.35t + 0.25l + 0.25v + 0.15a -$$ - -变量定义: - -- `t`:时间线索得分,出现明确日期、日期区间或相对日期时取 1,否则取 0。 -- `l`:地点线索得分,出现城市、客户地点或项目地点时取 1,否则取 0。 -- `v`:动作线索得分,出现申请、报销、提交、保存草稿等动作词时取 1,否则取 0。 -- `a`:附件线索得分,存在票据、发票、行程单、OCR 金额等附件证据时取 1,否则取 0。 - -当最高候选流程与第二候选流程差值小于阈值时进入确认: - -$$ -\Delta = confidence(flow_1) - confidence(flow_2) < 0.20 -$$ - -该公式只用于兜底路径,不能覆盖模型主判断。 - -## 测试方案 - -### 后端单元测试 - -- `test_steward_intent_agent.py`:覆盖 function schema 包含 `candidate_flows`、`pending_flow_confirmation`。 -- `test_steward_model_plan_builder.py`:覆盖非法字段过滤、别名归一、非法 flow 丢弃。 -- `test_steward_flow_state.py`:覆盖 v2 状态合并、候选流程落态、用户选择后 active flow 切换。 -- `test_steward_runtime_decision_agent.py`:覆盖用户选择“补办出差申请 / 发起费用报销”。 - -### 接口测试 - -- `/steward/plans` 输入“2月20-23日去上海出差辅助国网仿生产环境部署”,返回 `next_action=confirm_flow`。 -- `/steward/runtime-decisions` 选择“补办出差申请”后,`active_flow=travel_application`。 -- `/steward/runtime-decisions` 选择“发起费用报销”后,`active_flow=travel_reimbursement`。 - -### 前端测试 - -- 候选流程按钮只在 `pending_flow_confirmation.status=pending` 时展示。 -- 用户点击候选流程后不重复触发新计划。 -- Markdown 回复中标题、段落、列表和重点加粗能正确渲染。 - -### 容器验证 - -后端测试必须在 Docker 容器内执行: - -```bash -docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_steward_intent_agent.py server/tests/test_steward_model_plan_builder.py server/tests/test_steward_flow_state.py server/tests/test_steward_runtime_decision_agent.py -``` - -前端构建必须在容器内执行: - -```bash -docker exec -w /app/web x-financial-main npm run build -``` - -单次测试命令最长等待 60 秒,避免任务卡死。 - -## 指标与验收 - -- 对“2月20-23日去上海出差辅助国网仿生产环境部署”,系统不再直接判定为申请,而是返回两个候选流程并要求用户确认。 -- 用户选择“补办出差申请”后,同一 `conversation_id` 的 `steward_state.active_flow=travel_application`。 -- 用户选择“发起费用报销”后,同一 `conversation_id` 的 `steward_state.active_flow=travel_reimbursement`。 -- `flows.*.fields` 中不出现非本体字段。 -- 模型返回别名字段时,服务端输出仍为 canonical ontology field。 -- 模型不可用时,规则兜底结果明确标记 `rule_fallback`。 -- 用户未确认前,不创建申请单、不保存报销草稿、不提交审批、不绑定附件。 -- 前端候选流程按钮点击后不产生重复消息、不重复规划、不丢失上下文。 -- 后端定向测试和前端构建在 `x-financial-main:/app` 通过。 - -## 风险与开放问题 - -- 模型供应商对 function calling 的兼容程度不同,需要保留严格的服务端结构校验。 -- 旧版 `steward_state.v1` 已有数据需要兼容升级到 v2。 -- 用户输入可能同时包含“补申请”和“报销”,这种情况不应进入歧义确认,而应拆成两个任务。 -- 过去日期不等于报销,未来日期也不绝对等于申请;最终应由 LLM 主识别,并用候选确认处理低确定性场景。 -- 后续如果要支持更多流程,例如审批、制度问答或预算查询,需要先扩展本体业务契约,再扩展本 JSON 模板。 diff --git a/document/development/小财管家本体JSON流程/TODO.md b/document/development/小财管家本体JSON流程/TODO.md deleted file mode 100644 index a006a00..0000000 --- a/document/development/小财管家本体JSON流程/TODO.md +++ /dev/null @@ -1,75 +0,0 @@ -# 小财管家本体 JSON 流程 TODO - -> 开发时必须先更新本 TODO,再按小步执行。只有真实完成并通过对应验证后,才能把 `[ ]` 改成 `[x]` 并补充证据。 - -## 阶段一:调研与契约确认 - -- [x] 盘点 `schemas/steward.py`、`steward_intent_agent.py`、`steward_model_plan_builder.py`、`steward_flow_state.py` 的当前状态模型。[CONCEPT: 方案设计] 证据:已在实现前读取并确认现有 `steward_state`、planner、runtime decision 入口。 -- [x] 盘点 `ontology_field_registry.py` 中申请和报销可使用的 canonical ontology fields。[CONCEPT: 业务 JSON 模板] 证据:实现复用 `BUSINESS_CANONICAL_FIELDS` 与 `normalize_ontology_form_values`。 -- [x] 确认 `AgentConversation.state_json` 中已有 `steward_state.v1` 数据的兼容方式。[CONCEPT: 数据与持久化] 证据:`StewardFlowStateService._normalize_state` 兼容旧 state 并升级默认版本为 `steward.flow_state.v2`。 -- [x] 复核前端 `stewardPlanModel.js`、`useStewardPlanFlow.js`、`TravelReimbursementCreateView.js` 中候选动作和状态携带入口。[CONCEPT: 前端] 证据:前端子智能体只读检查确认建议动作入口可复用。 - -## 阶段二:后端 Schema 与 JSON 模板 - -- [x] 在 `schemas/steward.py` 增加 `StewardCandidateFlow`、`StewardPendingFlowConfirmation`、v2 `steward_state` 相关模型。[CONCEPT: 业务 JSON 模板] 证据:新增模型与 `StewardPlanResponse.pending_flow_confirmation`。 -- [x] 在 `StewardPlanResponse` 和 runtime response 中补充 `next_action`、`candidate_flows` 或等价结构,保持旧字段兼容。[CONCEPT: 接口契约] 证据:`StewardPlanResponse.next_action/candidate_flows` 与 `continue_selected_flow` 已接入。 -- [x] 编写 schema 单元测试,验证候选流程只允许 `travel_application` 和 `travel_reimbursement`。[CONCEPT: 安全边界] 证据:`test_steward_intent_agent.py` 覆盖 function schema 枚举。 - -## 阶段三:LLM 意图识别主路径 - -- [x] 扩展 `steward_intent_agent.py` 的 function schema,要求模型输出 `pending_flow_confirmation` 和 `candidate_flows`。[CONCEPT: 后端] 证据:`test_steward_intent_agent.py` 通过。 -- [x] 更新系统提示词:不能把无明确动作的出差描述直接判定为申请;应结合语义、上下文和候选置信度决定是否确认。[CONCEPT: 背景与问题] 证据:`steward_intent_agent.py` system prompt 已要求低确定性返回 pending flow。 -- [x] 增加 fake LLM 测试:输入“2月20-23日去上海出差辅助国网仿生产环境部署”时,模型路径返回 `confirm_flow`。[CONCEPT: 指标与验收] 证据:`test_steward_planner_returns_pending_flow_confirmation_from_llm`。 -- [ ] 增加模型非法输出测试:非法字段、非法 flow、空候选项必须被服务端过滤或降级。[CONCEPT: 安全边界] - -## 阶段四:状态合并与上下文记忆 - -- [x] 扩展 `steward_flow_state.py`,支持 `steward.flow_state.v1` 到 `steward.flow_state.v2` 的兼容升级。[CONCEPT: 风险与开放问题] 证据:`_normalize_state` 默认 v2 并保留 v1 核心结构。 -- [x] 支持将 `pending_flow_confirmation` 写入 state,并记录 source message、候选 flow 和确认原因。[CONCEPT: 业务 JSON 模板] 证据:`test_state_merge_plan_keeps_pending_flow_confirmation`。 -- [x] 支持用户选择候选 flow 后切换 `active_flow`,并把已识别字段合并到对应流程。[CONCEPT: 功能能力] 证据:`StewardFlowStateService.confirm_flow` 与 runtime 测试覆盖。 -- [x] 增加状态测试:多轮合并后 `flows.*.fields` 不出现非本体字段。[CONCEPT: 指标与验收] 证据:既有 `test_state_merge_filters_non_ontology_fields` 继续通过。 -- [ ] 增加状态测试:同一 `conversation_id` 下选择申请或报销不会丢失前一轮字段和证据。[CONCEPT: 数据与持久化] - -## 阶段五:运行时决策 - -- [x] 扩展 `steward_runtime_decision_agent.py`,识别用户点击或输入“补办出差申请”“发起费用报销”。[CONCEPT: 后端] 证据:`_build_selected_flow_decision` 前置处理候选 flow。 -- [x] Runtime decision 输入为空时,从 `context_json.conversation_state.steward_state` 恢复状态。[CONCEPT: 输入] 证据:既有 `test_steward_runtime_decision_fallback_reads_persisted_steward_state` 继续通过。 -- [x] 用户选择申请后返回 `continue_selected_flow`,并设置 `active_flow=travel_application`。[CONCEPT: 指标与验收] 证据:`test_steward_runtime_decision_fallback_confirms_selected_flow`。 -- [x] 用户选择报销后返回 `continue_selected_flow`,并设置 `active_flow=travel_reimbursement`。[CONCEPT: 指标与验收] 证据:`test_steward_runtime_decision_fallback_confirms_reimbursement_flow`。 -- [x] 增加 runtime 测试,覆盖点击按钮和用户直接输入两种方式。[CONCEPT: 测试方案] 证据:runtime 单测覆盖申请/报销选择,接口 smoke 覆盖用户选择。 - -## 阶段六:前端候选流程展示 - -- [x] 在 `stewardPlanModel.js` 中把 `pending_flow_confirmation` 转成两个可点击建议动作。[CONCEPT: 前端] 证据:`steward-plan-model-pending-flow.test.mjs`。 -- [x] 在 `useStewardPlanFlow.js` 中渲染 Markdown 回复,确保标题、列表和重点加粗间距正常。[CONCEPT: 用户与场景] 证据:`buildStewardPlanMessageText` 对 `confirm_flow` 生成 Markdown 标题、列表和加粗内容。 -- [x] 在 `TravelReimbursementCreateView.js` 中处理候选流程点击:优先调用 runtime decision,不重新规划原始输入。[CONCEPT: 前端] 证据:`steward_confirm_flow` 分支调用 `handleStewardRuntimeDecision`。 -- [x] 在 `useTravelReimbursementSessionState.js` 中确认 `conversation_id` 和 `steward_state` 后续请求持续携带。[CONCEPT: 输入] 证据:现有 session state 与 `buildStewardPlanRequest` 已持续携带,无需新增改动。 -- [x] 增加或补充前端定向测试,覆盖候选按钮展示、点击后状态更新和不重复规划。[CONCEPT: 前端测试] 证据:新增 `steward-plan-model-pending-flow.test.mjs` 覆盖候选按钮,接口 smoke 覆盖选择后状态更新。 - -## 阶段七:接口与回归验证 - -- [x] 在容器中运行后端定向测试,单次命令超时控制在 60 秒内。[CONCEPT: 容器验证] 证据:`24 passed in 25.14s`。 - -```bash -docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_steward_intent_agent.py server/tests/test_steward_model_plan_builder.py server/tests/test_steward_flow_state.py server/tests/test_steward_runtime_decision_agent.py -``` - -- [x] 在容器中运行已有小财管家回归测试,确认旧的申请/报销拆分不退化。[CONCEPT: 测试方案] 证据:`test_steward_planner.py`、`test_steward_slot_decision_agent.py` 包含在后端定向测试中并通过。 - -```bash -docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_steward_planner.py server/tests/test_steward_slot_decision_agent.py -``` - -- [x] 在容器中运行前端构建。[CONCEPT: 容器验证] 证据:`docker exec -w /app/web x-financial-main npm run build` 成功。 - -```bash -docker exec -w /app/web x-financial-main npm run build -``` - -- [x] 手工验证小财管家输入“2月20-23日去上海出差辅助国网仿生产环境部署”,页面展示两个候选流程,未确认前不创建申请单或报销草稿。[CONCEPT: 指标与验收] 证据:接口 smoke 返回 `next_action=confirm_flow`、候选 `travel_application/travel_reimbursement`、`state_pending=pending`。 - -## 阶段八:文档同步 - -- [x] 实现过程中如调整 JSON 字段或接口契约,先更新 `CONCEPT.md`,再修改代码。[CONCEPT: 方案设计] 证据:已先新增 `CONCEPT.md` 与 `TODO.md`。 -- [x] 每完成一个阶段,在本 TODO 中勾选并补充证据,例如测试命令、文件名或接口返回要点。[CONCEPT: 测试方案] 证据:本文件已补充阶段证据。 -- [ ] 最终汇报工作区状态,不自动 commit/push,除非用户明确要求。[CONCEPT: 风险与开放问题] diff --git a/document/development/工作台费用统计详情弹窗/CONCEPT.md b/document/development/工作台费用统计详情弹窗/CONCEPT.md deleted file mode 100644 index 0d90f1f..0000000 --- a/document/development/工作台费用统计详情弹窗/CONCEPT.md +++ /dev/null @@ -1,111 +0,0 @@ -# 工作台费用统计详情弹窗概念文档 - -## 功能一句话 - -在个人工作台的“费用统计”卡片中提供本地弹窗详情,让用户直接查看历史费用分布、单据处理时间和系统操作明细。 - -## 背景与问题 - -当前“费用统计”右上角的“查看详情”会进入助手问答,不符合用户期望的“像用户画像一样直接看详情”的操作方式。费用进度区域也存在两个可见性问题:右上角“全部进度”按钮没有实际承载完整列表能力,10 日以上分割标识靠左且不醒目。 - -本次调整需要让工作台成为个人费用操作的直接入口:用户不离开首页即可理解自己的费用结构、单据流转时间和近期系统动作。 - -## 目标与非目标 - -目标: - -- 移除“费用进度”右上角的“全部进度”按钮,减少无效操作。 -- 将“10日以上”分割标识放在分割线中间,并使用更醒目的主题强调色。 -- 将“费用统计”的“查看详情”改为打开详情弹窗。 -- 弹窗展示历史报销费用分布、单据处理时间和系统操作详情。 -- 数据优先来自 `buildWorkbenchSummary` 已有的当前用户单据汇总,不新增后端接口。 - -非目标: - -- 不新增后端 API。 -- 不改变报销单据审批状态计算规则。 -- 不替代用户画像详情弹窗。 -- 不做复杂图表库接入,避免为了一个工作台弹窗扩大依赖和维护面。 - -## 用户与场景 - -主要用户是个人员工和经常处理报销的业务人员。典型场景: - -- 在首页查看本月报销情况后,想进一步确认自己的历史费用主要花在哪些类别。 -- 想知道近期单据从创建到当前状态大概处理了多久。 -- 想复盘系统里最近需要处理或已提醒的费用相关动作。 - -## 功能能力 - -### 费用分布 - -按单据标题、场景或备注归类费用类型,统计每类金额、单据数量和金额占比。详情区使用项目现有 `DonutChart` 饼图展示费用分布,并通过图例保留金额与占比信息。若数据不足,展示空状态。 - -### 处理时间 - -按单据创建、提交、更新或进度步骤时间推断处理耗时,输出可读的耗时文案,并展示当前状态和节点数量。 - -### 操作详情 - -基于待办、通知和进度项生成系统操作明细,帮助用户理解最近有哪些费用动作需要关注。 - -## 方案设计 - -前端实现: - -- 在 `workbenchSummary.js` 中新增 `expenseStatsDetail` 汇总结构。 -- 新增 `ExpenseStatsDetailModal.vue`,复用 Element Plus `ElDialog`、`ElButton`、`ElTag` 的企业后台弹窗体验。 -- 费用分布展示复用现有 `DonutChart`,不手写临时 SVG、Canvas 或 CSS 饼图。 -- 在 `PersonalWorkbench.vue` 中接入弹窗状态,费用统计“查看详情”只打开弹窗。 -- 调整 `personal-workbench.css` 中长时间分割标识的居中与强调样式。 - -数据结构: - -```js -expenseStatsDetail: { - distributionRows: [], - processingRows: [], - operationRows: [] -} -``` - -## 算法与公式 - -费用类型金额占比: - -$$ -percent_i = \frac{amount_i}{\sum_{k=1}^{n} amount_k} \times 100 -$$ - -单据处理耗时: - -$$ -duration = latestTime - firstTime -$$ - -其中 `firstTime` 优先取单据创建时间、提交时间或最早进度步骤时间,`latestTime` 优先取更新时间或最新进度步骤时间。 - -## 测试方案 - -- 源码测试确认费用进度不再渲染“全部进度”按钮。 -- 源码测试确认“费用统计”的“查看详情”打开弹窗而不是进入助手。 -- 单元测试确认 `buildWorkbenchSummary` 能生成费用分布、处理时间和操作明细。 -- 源码测试确认弹窗包含费用分布饼图、处理时间和系统操作详情区块。 -- 运行前端构建验证组件编译通过。 - -## 指标与验收 - -- “10日以上”标识位于分割线中间,且使用主题强调色。 -- “费用进度”卡片右上角不再出现“全部进度”。 -- 点击“费用统计”的“查看详情”打开详情弹窗。 -- 弹窗至少包含费用分布饼图、处理时间、系统操作详情三个信息区。 -- 相关测试与前端构建通过。 - -## 风险与开放问题 - -- 当前数据来自工作台前端汇总,历史维度受首页已加载单据范围影响;若后续需要跨年或分页全量统计,应补后端专用接口。 -- 单据类型归类依赖标题、场景和备注,属于前端轻量归类;后续可与 ontology 费用类别字段打通。 - -## 2026-06-03 饼图呈现修正 - -费用分布仍复用项目已有 `DonutChart`,但在费用统计详情弹窗内关闭组件自带图例,只保留一个环形饼图入口。费用类型、金额、笔数和占比改为右侧文字明细列表,避免环图主体和双列图例在同一卡片内被误认为出现两个饼图。 diff --git a/document/development/工作台费用统计详情弹窗/TODO.md b/document/development/工作台费用统计详情弹窗/TODO.md deleted file mode 100644 index 42ac62a..0000000 --- a/document/development/工作台费用统计详情弹窗/TODO.md +++ /dev/null @@ -1,31 +0,0 @@ -# 工作台费用统计详情弹窗 TODO - -## 调研与契约 - -- [x] 核对 `PersonalWorkbench.vue`、工作台样式和现有用户画像弹窗结构。[CONCEPT: 方案设计] 证据:已确认工作台入口、`ExpenseProfileDetailModal.vue` 弹窗模式和 `personal-workbench.css` 分割样式。 -- [x] 明确费用详情弹窗的数据结构,并限制为前端工作台汇总数据。[CONCEPT: 功能能力] 证据:采用 `expenseStatsDetail`,由 `buildWorkbenchSummary` 基于当前用户单据生成。 - -## 前端实现 - -- [x] 移除费用进度卡片右上角“全部进度”按钮。[CONCEPT: 目标与非目标] 证据:`PersonalWorkbench.vue` 的费用进度标题区已移除该按钮。 -- [x] 调整“10日以上”分割标识为居中、醒目主题色样式。[CONCEPT: 指标与验收] 证据:`personal-workbench.css` 使用 `left: 50%`、`transform: translateX(-50%)` 和主题强调色。 -- [x] 在 `workbenchSummary.js` 生成费用分布、处理时间、系统操作详情数据。[CONCEPT: 算法与公式] 证据:新增 `expenseStatsDetail` 汇总结构。 -- [x] 新增费用统计详情弹窗组件,展示三个详情区块和空状态。[CONCEPT: 功能能力] 证据:新增 `ExpenseStatsDetailModal.vue`。 -- [x] 在 `PersonalWorkbench.vue` 接入弹窗状态与费用统计“查看详情”按钮。[CONCEPT: 方案设计] 证据:新增 `expenseStatsModalOpen` 与 `openExpenseStatsModal`。 -- [x] 将费用分布区从条形列表改为 `DonutChart` 饼图展示。[CONCEPT: 功能能力] 证据:`ExpenseStatsDetailModal.vue` 已接入 `DonutChart` 和 `distributionChartItems`。 -- [x] 关闭费用详情内 `DonutChart` 自带图例,改为单饼图加右侧文字明细。[CONCEPT: 2026-06-03 饼图呈现修正] 证据:`ExpenseStatsDetailModal.vue` 传入 `:show-legend="false"` 并新增 `expense-distribution-summary-list`。 -- [x] 为通用 `DonutChart` 增加可隐藏内置图例的开关,默认保持其它页面不变。[CONCEPT: 2026-06-03 饼图呈现修正] 证据:`DonutChart.vue` 新增 `showLegend` 默认值和 `donut-chart--legendless` 状态。 - -## 测试与验证 - -- [x] 补充工作台源码测试,覆盖按钮移除、弹窗接入和分割标识样式。[CONCEPT: 测试方案] 证据:`node web/tests/personal-workbench-assistant.test.mjs` 通过。 -- [x] 补充工作台汇总单元测试,覆盖详情数据生成。[CONCEPT: 测试方案] 证据:`node web/tests/workbench-summary.test.mjs` 通过。 -- [x] 补充弹窗源码测试,覆盖费用分布、处理时间、系统操作详情区块。[CONCEPT: 测试方案] 证据:`node web/tests/expense-stats-detail-modal.test.mjs` 通过。 -- [x] 运行前端定向测试和构建验证。[CONCEPT: 指标与验收] 证据:以上定向测试和 `npm.cmd --prefix web run build` 均通过。 -- [x] 更新弹窗源码测试,确认费用分布使用饼图组件。[CONCEPT: 测试方案] 证据:`node web/tests/expense-stats-detail-modal.test.mjs` 通过,`npm.cmd --prefix web run build` 通过。 -- [x] 更新弹窗与环图源码测试,确认详情弹窗只使用一个饼图入口且关闭内置图例。[CONCEPT: 2026-06-03 饼图呈现修正] 证据:`node web/tests/expense-stats-detail-modal.test.mjs` 与 `node web/tests/donut-chart.test.mjs` 通过。 - -## 交付 - -- [x] 复查本次暂存范围,避免纳入无关工作区改动。[CONCEPT: 风险与开放问题] 证据:`git diff --cached --name-only` 仅包含本次工作台弹窗、样式、汇总测试和开发文档。 -- [x] 提交并 push 本次功能分支。[CONCEPT: 指标与验收] 证据:本次单饼图修复完成后提交并推送当前分支。 diff --git a/document/development/工作台费用进度详情返回与类型列/CONCEPT.md b/document/development/工作台费用进度详情返回与类型列/CONCEPT.md deleted file mode 100644 index f028dc1..0000000 --- a/document/development/工作台费用进度详情返回与类型列/CONCEPT.md +++ /dev/null @@ -1,75 +0,0 @@ -# 工作台费用进度详情返回与类型列概念文档 - -## 功能一句话 - -让用户从首页费用进度进入单据详情后能返回首页,并在费用进度列表中直接看到每笔单据的费用类型。 - -## 背景与问题 - -当前首页费用进度点击单据后进入详情页,但详情页返回按钮默认回到单据中心,破坏了用户从首页查看进度的上下文。同时费用进度行只展示单号、标题、流程、状态和金额,用户需要点进详情才知道单据属于差旅、招待、办公等哪类费用。 - -## 目标与非目标 - -目标: - -- 从首页费用进度进入详情时,详情页返回按钮回到个人工作台。 -- 从单据中心进入详情时,原有返回单据中心逻辑不变。 -- 在首页费用进度行新增“费用类型”列。 -- 费用类型优先使用单据已有类型字段,缺失时按标题、场景和备注轻量归类。 - -非目标: - -- 不修改详情页主体内容。 -- 不新增后端接口。 -- 不改变单据中心列表、审批详情和其他来源的返回逻辑。 - -## 用户与场景 - -个人员工在首页查看最近费用进度,点击某笔单据进入详情核对处理情况。查看完后点击返回,应回到刚才的首页工作台继续看其他进度项,而不是跳到单据中心列表。 - -## 功能能力 - -- 首页打开详情时带入 `returnTo=workbench` 来源标记。 -- 详情页根据来源标记动态显示返回按钮文案并执行返回首页。 -- 费用进度数据新增 `expenseTypeLabel`。 -- 费用类型列在桌面端作为独立列展示,窄屏下按移动端布局折行展示。 - -## 方案设计 - -前端实现: - -- `PersonalWorkbench.vue` 在 `open-document` 事件 payload 中补 `source: 'workbench'` 和 `returnTo: 'workbench'`。 -- `AppShellRouteView.vue` 接收工作台来源并传给 `openRequestDetail`。 -- `useAppShell.js` 在打开详情时写入查询参数,在关闭详情时根据查询参数返回工作台或单据中心。 -- `workbenchSummary.js` 在 `progressItems` 中补费用类型字段。 -- `personal-workbench.css` 与响应式样式新增费用类型列。 - -## 算法与公式 - -当前功能不涉及复杂数学公式。 - -费用类型归类优先级: - -1. 单据显式字段:`expenseCategory`、`expense_type`、`category` 等。 -2. 文本规则:从场景、标题、备注和描述中匹配差旅、招待、办公、培训、市场等关键词。 -3. 兜底为“其他费用”。 - -## 测试方案 - -- 源码测试确认首页费用进度打开详情时带 `returnTo=workbench`。 -- 源码测试确认详情返回文案和关闭逻辑支持工作台来源。 -- 单元测试确认 `progressItems` 输出费用类型字段。 -- 源码测试确认费用进度模板和样式包含费用类型列。 -- 运行前端定向测试与构建。 - -## 指标与验收 - -- 从首页费用进度进入详情后,返回按钮回到个人工作台。 -- 从单据中心进入详情后,返回按钮仍回到单据中心。 -- 首页费用进度行可直接看到费用类型。 -- 相关定向测试与前端构建通过。 - -## 风险与开放问题 - -- 当前费用类型归类仍是前端轻量归类。后续若后端已有稳定 ontology 类型字段,应优先接入 canonical 字段。 -- 路由查询参数只用于详情返回来源,不应影响单据筛选和详情数据加载。 diff --git a/document/development/工作台费用进度详情返回与类型列/TODO.md b/document/development/工作台费用进度详情返回与类型列/TODO.md deleted file mode 100644 index b31ddde..0000000 --- a/document/development/工作台费用进度详情返回与类型列/TODO.md +++ /dev/null @@ -1,25 +0,0 @@ -# 工作台费用进度详情返回与类型列 TODO - -## 调研与契约 - -- [x] 核对首页费用进度点击链路、详情页返回逻辑和当前进度行样式。[CONCEPT: 方案设计] 证据:已确认 `PersonalWorkbench.vue` 发出 `open-document`,`AppShellRouteView.vue` 转入详情,`useAppShell.js` 默认返回单据中心。 -- [x] 明确来源标记与费用类型字段的前端契约。[CONCEPT: 功能能力] 证据:采用 `returnTo: 'workbench'` 与 `expenseTypeLabel`。 - -## 前端实现 - -- [x] 首页费用进度打开详情时带入工作台返回来源。[CONCEPT: 方案设计] 证据:`PersonalWorkbench.vue` 的 `open-document` payload 已包含 `source` 与 `returnTo`。 -- [x] 详情页关闭逻辑按来源返回工作台或单据中心。[CONCEPT: 功能能力] 证据:`useAppShell.js` 根据 `route.query.returnTo` 选择 `app-workbench` 或 `app-documents`。 -- [x] 工作台进度汇总新增费用类型字段。[CONCEPT: 功能能力] 证据:`workbenchSummary.js` 的 `progressItems` 输出 `expenseTypeLabel`。 -- [x] 首页费用进度行新增费用类型列及响应式样式。[CONCEPT: 指标与验收] 证据:`PersonalWorkbench.vue` 新增 `progress-type`,样式和响应式布局已更新。 - -## 测试与验证 - -- [x] 补充详情返回来源源码测试。[CONCEPT: 测试方案] 证据:`node web/tests/workbench-detail-return.test.mjs` 通过。 -- [x] 补充费用进度类型列源码测试。[CONCEPT: 测试方案] 证据:`node web/tests/personal-workbench-assistant.test.mjs` 通过。 -- [x] 补充工作台汇总单元测试,覆盖费用类型字段。[CONCEPT: 测试方案] 证据:`node web/tests/workbench-summary.test.mjs` 通过。 -- [x] 运行定向测试和前端构建。[CONCEPT: 指标与验收] 证据:以上定向测试和 `npm.cmd --prefix web run build` 均通过。 - -## 交付 - -- [x] 复查暂存范围,避免纳入无关工作区改动。[CONCEPT: 风险与开放问题] 证据:`git diff --cached --name-only` 仅包含本次工作台进度、返回来源、测试和开发文档。 -- [ ] 提交并 push 本次功能分支。[CONCEPT: 指标与验收] diff --git a/document/development/数字员工工作看板/CONCEPT.md b/document/development/数字员工工作看板/CONCEPT.md deleted file mode 100644 index 88acf86..0000000 --- a/document/development/数字员工工作看板/CONCEPT.md +++ /dev/null @@ -1,151 +0,0 @@ -# 数字员工工作看板概念文档 - -## 功能一句话 - -在分析看板中新增“数字员工看板”,让用户用一个统一视角看到数字员工每天执行了哪些后台分析、整理、积累和评估工作,以及这些工作产生了什么业务结果。 - -## 背景与问题 - -当前数字员工已经有“员工技能”和“工作记录”页面,但工作记录偏运行明细,适合追溯单次任务。管理者在分析看板中缺少一个汇总视角,无法快速回答: - -- 今天数字员工是否真的在工作。 -- 哪些技能执行最多。 -- 成功、失败、运行中的任务分别是多少。 -- 风险图谱、风险线索、员工画像和知识整理分别产出了什么。 -- 最近失败或异常的后台任务是否需要处理。 - -新增看板后,分析看板承担“经营和运行洞察”入口,数字员工页面继续承担“技能配置、工作记录详情和人工操作”入口。 - -## 目标与非目标 - -### 目标 - -- 在分析看板顶部切换项中新增“数字员工看板”。 -- 用真实 `AgentRun` 和 `AgentToolCall` 数据聚合数字员工工作,不使用演示数据伪装真实结果。 -- 展示最近 N 天的工作总数、成功数、失败数、运行中数量、产出量和日趋势。 -- 区分技能类型:积累、升级、整理、评估。 -- 展示最近工作记录,用户能直观看到每天做了什么和产出了什么。 - -### 非目标 - -- 不替代数字员工页面的“员工技能”和“工作记录”详情。 -- 不让数字员工执行规则中心主流程,也不让数字员工定义、发布或确认风险规则。 -- 不展示内部实现名称或技术代号,页面文案统一使用“数字员工”。 -- 不在本期新增新的算法执行器,只消费已有执行结果做分析看板聚合。 - -## 用户与场景 - -- 财务负责人:查看数字员工每天是否持续产出知识整理、风险观察、画像快照和线索。 -- 风控与审计人员:查看评估、升级类任务的失败与产出情况,判断是否需要复核。 -- 系统管理员:观察后台任务是否运行稳定,识别失败任务和数据异常。 - -## 功能能力 - -### 输入 - -- `agent_runs`:数字员工运行记录。 -- `agent_tool_calls`:每次运行中的工具调用与响应摘要。 -- `route_json` / `request_json` / `response_json`:用于识别任务类型、任务编码、报告类型和产出指标。 - -### 输出 - -- KPI 指标:工作总数、成功数量、失败数量、运行中数量、业务产出、成功率。 -- 每日工作趋势:按日期聚合总数、成功、失败和主要产出量。 -- 技能类型分布:积累、升级、整理、评估。 -- 工作模块排行:财务风险图谱巡检、员工行为画像巡检、风险线索归集、知识制度整理等。 -- 最近工作记录:任务名称、状态、开始时间、耗时、摘要和关键指标。 - -### 状态 - -- 成功:`succeeded`、`success`、`completed`、`done`。 -- 失败:`failed`、`failure`、`error`、`errored`。 -- 运行中:`running`、`pending`。 -- 其他状态统一归入“其他”,但不丢弃记录。 - -### 权限与边界 - -- 本期沿用分析看板已有访问控制,不新增独立权限。 -- 看板只读,不提供运行、定时、编辑技能等操作。 -- 单次运行详情仍在数字员工工作记录页面处理。 - -## 方案设计 - -### 后端 - -新增 `DigitalEmployeeDashboardService`: - -- 从 `AgentRun` 查询最近 `days` 天数据,最多取 `limit` 条。 -- 通过 `agent == "hermes"`、`source == "schedule"`、`route_json` 任务字段、工具名 `digital_employee.*` 和知识整理任务类型识别数字员工工作。 -- 从工具响应中提取业务产出指标,例如风险观察数、风险线索数、画像快照数、知识文档数。 -- 返回稳定结构,前端只负责展示,不重复推断核心聚合逻辑。 - -新增接口: - -```http -GET /api/v1/analytics/digital-employee-dashboard?days=7&limit=300 -``` - -### 前端 - -新增 `DigitalEmployeeDashboard.vue`: - -- 复用现有 `OverviewView` 的 KPI 卡片、`dashboard-card`、`BarChart` 和企业级直角视觉。 -- 使用两列到多列的看板网格,避免新增营销化卡片风格。 -- 状态、空数据和加载错误保持与风险看板一致。 - -接入点: - -- `TopBar.vue` 增加“数字员工看板”切换项。 -- `OverviewView.vue` 新增 `activeDashboard === "digitalEmployee"` 分支。 -- `useOverviewView.js` 新增数据加载、KPI 映射、趋势行和排行行。 -- `analytics.js` 新增接口调用和字段归一化。 - -## 算法与公式 - -### 成功率 - -$$ -success\_rate = \frac{success\_runs}{max(total\_runs, 1)} -$$ - -### 失败率 - -$$ -failure\_rate = \frac{failed\_runs}{max(total\_runs, 1)} -$$ - -### 业务产出量 - -$$ -business\_outputs = risk\_observations + risk\_clues + profile\_snapshots + knowledge\_documents -$$ - -### 日工作负载 - -$$ -daily\_workload_d = total\_runs_d + business\_outputs_d -$$ - -以上公式只用于看板展示和排序,不参与规则中心决策。 - -## 测试方案 - -- 后端单元测试:构造数字员工运行、普通智能体运行、失败运行和工具响应,验证聚合结果。 -- 接口测试:验证 `/analytics/digital-employee-dashboard` 返回字段结构和空数据行为。 -- 前端静态测试:验证切换项、接口地址、组件分支和核心文案存在。 -- 构建验证:运行前端构建,确保新增 Vue 组件可编译。 -- 容器验证:在 `x-financial-main` 中运行后端定向测试,并调用真实接口确认返回 JSON。 - -## 指标与验收 - -- 分析看板切换中出现“数字员工看板”。 -- 选择该看板后页面显示 KPI、每日工作、技能类型分布、任务排行和最近工作。 -- 没有真实数据时显示空状态,不使用伪造业务数。 -- 接口返回 `has_real_data`,前端可据此判断真实数据状态。 -- 后端定向测试和前端定向测试通过。 - -## 风险与开放问题 - -- 旧版 `hermes_task_execution_logs` 中的日志没有完整工具响应,本期优先以 `AgentRun` 为准;如需兼容旧日志,可后续做补充。 -- 部分新增技能当前可能只有定义,未必已有真实执行结果,看板会显示为 0 或不出现。 -- 如果后续新增数字员工技能,需要同步更新任务类型映射,避免看板归类为“其他”。 diff --git a/document/development/数字员工工作看板/TODO.md b/document/development/数字员工工作看板/TODO.md deleted file mode 100644 index 11c2396..0000000 --- a/document/development/数字员工工作看板/TODO.md +++ /dev/null @@ -1,29 +0,0 @@ -# 数字员工工作看板 TODO - -## 调研与边界 - -- [x] 梳理分析看板切换入口和现有数据流。[CONCEPT: 方案设计] 证据:`TopBar.vue`、`OverviewView.vue`、`useOverviewView.js`。 -- [x] 梳理数字员工工作记录数据来源。[CONCEPT: 功能能力] 证据:`AgentRun`、`AgentToolCall`、`digitalEmployeeWorkRecordsModel.js`。 -- [x] 明确本期非目标:不替代数字员工详情、不执行规则中心主流程、不使用演示数据。[CONCEPT: 目标与非目标] - -## 契约与后端 - -- [x] 新增数字员工看板响应 schema。[CONCEPT: 后端] 证据:`DigitalEmployeeDashboardRead`。 -- [x] 新增 `DigitalEmployeeDashboardService` 聚合运行记录、任务分布、日趋势和最近工作。[CONCEPT: 后端] 证据:`digital_employee_dashboard.py`。 -- [x] 新增 `/analytics/digital-employee-dashboard` 接口。[CONCEPT: 后端] 证据:`analytics.py` 路由和容器接口返回。 -- [x] 补后端定向测试覆盖成功、失败、非数字员工过滤和业务产出统计。[CONCEPT: 测试方案] 证据:`server/tests/test_digital_employee_dashboard_service.py`,2 passed。 - -## 前端 - -- [x] 在分析看板切换项中增加“数字员工看板”。[CONCEPT: 前端] 证据:`TopBar.vue`。 -- [x] 在 `analytics.js` 新增接口调用和字段归一化。[CONCEPT: 前端] 证据:`fetchDigitalEmployeeDashboard` 和 `normalizeDigitalEmployeeDashboardPayload`。 -- [x] 在 `useOverviewView.js` 接入加载状态、KPI、趋势和排行数据。[CONCEPT: 前端] 证据:`useOverviewView.js` 与 `overviewDigitalEmployeeDashboardModel.js`。 -- [x] 新增 `DigitalEmployeeDashboard.vue`,复用现有企业看板风格。[CONCEPT: 前端] 证据:看板组件和 ECharts 日趋势组件。 -- [x] 在 `OverviewView.vue` 增加数字员工看板分支。[CONCEPT: 前端] 证据:`activeDashboard === "digitalEmployee"`。 - -## 验证与验收 - -- [x] 运行后端定向测试,超时不超过 60s。[CONCEPT: 测试方案] 证据:`timeout 60s ... pytest server/tests/test_digital_employee_dashboard_service.py -q`,2 passed。 -- [x] 运行前端定向测试或构建验证。[CONCEPT: 测试方案] 证据:`node --test web/tests/digital-employee-dashboard.test.mjs`,3 passed;`npm.cmd --prefix web run build` 通过。 -- [x] 在 Docker 容器中调用真实接口验证 JSON 返回。[CONCEPT: 指标与验收] 证据:`GET /api/v1/analytics/digital-employee-dashboard?days=7&limit=300` 返回 `True 1 1 知识制度整理`。 -- [x] 更新本 TODO 的完成证据。[CONCEPT: 指标与验收] 证据:本文档已更新。 diff --git a/document/development/数字员工能力库扩展/CONCEPT.md b/document/development/数字员工能力库扩展/CONCEPT.md deleted file mode 100644 index 8635940..0000000 --- a/document/development/数字员工能力库扩展/CONCEPT.md +++ /dev/null @@ -1,133 +0,0 @@ -# 数字员工能力库扩展概念文档 - -更新日期:2026-05-31 - -## 功能一句话 - -把数字员工从少量后台任务扩展为覆盖事实抽取、规则命中分析、资产积累、报告生成和人工复核辅助的企业级后台分析能力库。 - -## 背景与问题 - -当前员工技能数量偏少,只有制度整理、风险图谱巡检、员工画像巡检和少量复核辅助能力。页面观感更像技术演示,不像完整的财务数字员工能力矩阵。 - -需要把已有风险图谱、制度知识、画像基线、反馈池、回放评测等算法资产拆成用户能理解的员工技能,让列表规模、分类结构和详情内容都更完整。 - -同时必须收敛数字员工边界:数字员工不是风险专家,也不是规则制定者。风险口径、规则内容、制度解释和最终判断由人负责;规则中心执行归属外层智能体流程,数字员工只负责读取事实、规则命中和反馈结果,生成后台分析、报告、知识库材料和待人工复核线索。 - -## 目标 - -- 员工技能数量扩展到不少于 16 个。 -- 保持四类技能:积累、升级、整理、评估。 -- 每个技能都有名称、描述、技能包、分类、执行场景、输入、输出、是否定时、是否写入工作记录。 -- 新增技能进入资产种子和运行时补齐逻辑,已有数据库启动后也能自动补齐。 -- 新增技能包落在 `server/src/app/skills/domain`,便于后续同步到数字员工运行侧。 -- 明确技能边界:输出事实、规则命中和待人工确认线索,不输出正式规则结论或规则变更裁判。 - -## 非目标 - -- 本轮不引入新的数据库结构变更。 -- 本轮不要求所有新增技能都接入真实执行器。 -- 本轮不复制竞品术语或页面包装,只做 X-Financial 自有能力命名。 -- 本轮不让数字员工总结风险规则、发明新规则、修改规则中心或替代人工确认风险。 - -## 用户与场景 - -- 风控管理员:查看评估类和升级类技能,理解规则命中分析、异常线索、人工复核样本和回放评测能力。 -- 财务制度管理员:查看整理类技能,维护制度条款、政策口径和规则命中样本。 -- 数据治理人员:查看积累类技能,理解员工、部门、供应商和反馈样本如何沉淀。 -- 系统管理员:配置定时计划、查看工作记录和执行结果。 - -## 功能能力 - -完整员工技能库按四类组织: - -- 整理:财务制度、制度条款、政策口径、规则命中样本。 -- 积累:员工画像、部门基线、供应商画像、误报样本、反馈样本。 -- 评估:风险图谱、多凭证一致性、时空一致性、预算超标、供应商异常关系。 -- 升级:风险线索归集、算法回放、制度引用缺口提示和人工复核材料整理。 - -每个技能需要提供: - -- `skill_name`:技能包目录名。 -- `skill_category`:积累、升级、整理、评估之一。 -- `task_type`:由任务 code 派生。 -- `schedule` / `cron_expression`:默认定时计划。 -- `input_sources`:输入来源。 -- `output_format`:产出格式。 -- `writes_work_record`:是否产出工作记录。 -- `execution_strategy`:真实执行、复用现有扫描器或定义先行。 -- `role_boundary`:规则由人定义、风险由人确认、主流程由外层智能体执行,数字员工只做后台分析、报告生成和知识沉淀。 -- `allowed_outputs`:只允许输出 `facts`、`rule_hits`、`risk_clues`、`evidence_refs`、`human_review_required` 等受控字段。 - -## 数字员工边界 - -数字员工允许做三件事: - -- 事实抽取:从申请单、报销单、票据、附件、审批记录中抽取金额、时间、地点、人员、供应商、票据号、申请关系等事实。 -- 规则命中分析:读取外层智能体流程已经产生的规则命中结果、字段依据和原始证据,用于后台报告与复核材料整理。 -- 线索归集:基于事实和规则命中输出“待人工复核”的潜在线索,不能把线索升级为正式风险结论。 - -数字员工禁止做四件事: - -- 不总结或发明风险规则。 -- 不修改、发布、删除规则中心规则。 -- 不把潜在线索判定为最终违规结论。 -- 不替代财务、风控或管理员进行制度解释和风险确认。 - -## 方案设计 - -### 后端 - -- 在 `agent_foundation_constants.py` 增加新增任务 code 和分类映射。 -- 在 `agent_foundation_digital_employee_tasks.py` 增加运行时任务规格。 -- 在初始种子流程完成基础任务 flush 后,调用运行时补齐逻辑,保证新库完整落库。 -- 新增技能包目录和 `SKILL.md`,内容包含功能说明、执行时机、输入输出和边界。 -- 将容易越权的“规则发现、规则模板整理、制度缺口优化”收敛为“风险线索归集、规则命中样本整理、制度引用缺口提示”。 - -### 前端 - -前端列表已按资产接口读取任务类资产,不需要新增页面结构。新增任务落库后会自动进入员工技能列表,并使用已有筛选、分类和详情展示。 - -### 算法与公式 - -本轮主要扩展能力目录和角色边界,不新增评分公式。后续每个技能接入真实算法时,再在对应算法文档中补充公式。 - -数字员工输出的线索置信度只能作为排序依据,不能作为最终风险裁判: - -$$ -risk\_clue = f(facts, rule\_hits, evidence\_quality) -$$ - -其中 `facts` 来自申请与报销事实,`rule_hits` 来自外层智能体流程或规则中心已经产生的命中结果,`evidence_quality` 表示证据完整度。数字员工不触发规则主流程,最终是否构成风险由人工复核或规则中心既有处置流程决定。 - -### 后台分析闭环 - -风险线索归集不是规则生产流程,而是后台分析闭环的一环: - -- 工作记录详情展示本次归集的事实、规则命中、待复核线索和近期反馈样本。 -- 风险看板展示待复核线索数和反馈样本数,用于观察后台分析是否形成可复盘资产。 -- 人工反馈仍写入风险观察反馈池,数字员工只读取反馈池做线索排序、复核材料整理和后续报告生成。 - -## 测试方案 - -- 单元测试:校验数字员工运行时任务规格数量、分类覆盖、技能包目录存在、任务 code 唯一。 -- 配置测试:校验每个任务配置都包含 `skill_name`、`output_format`、`skill_category_options`。 -- 容器验证:在 `x-financial-main:/app/server` 运行定向测试。 -- 手工验收:进入数字员工员工技能列表,确认技能数量和分类明显完整。 -- 接口验收:风险看板接口返回 `risk_clue_count` 和 `feedback_sample_count`,工作记录详情能展示风险线索归集的反馈样本摘要。 - -## 指标与验收 - -- 员工技能总数不少于 17 个。 -- 四类分类都有技能。 -- 新增技能包全部存在 `SKILL.md`。 -- 定向测试通过。 -- 风险看板不再展示候选规则指标,改为待复核线索和反馈样本。 -- 不引入数据库迁移和破坏性变更。 - -## 风险与开放问题 - -- 新增技能中部分为“定义先行”,立即运行时需要后续逐步接入真实执行器。 -- 如果用户希望每个技能都能立即产出真实结果,需要继续拆分执行服务和工作记录产物。 -- 已接入风险线索归集真实执行器,后续应继续把多凭证、时空、预算、供应商异常从风险图谱主引擎中拆成独立算法模块。 -- 若技能命名或说明再次出现“数字员工承担规则主流程、规则发现、规则优化、自动总结风险”等表述,应优先改为读取规则命中结果、事实、线索、复核材料等受控表述。 diff --git a/document/development/数字员工能力库扩展/TODO.md b/document/development/数字员工能力库扩展/TODO.md deleted file mode 100644 index 007b335..0000000 --- a/document/development/数字员工能力库扩展/TODO.md +++ /dev/null @@ -1,56 +0,0 @@ -# 数字员工能力库扩展 TODO - -更新日期:2026-05-31 - -## 1. 调研与契约 - -- [x] 复核当前员工技能数量、分类和技能包目录。[CONCEPT: 背景与问题] 证据:当前已有基础技能包:制度整理、风险图谱巡检、员工画像巡检、风险线索归集。 -- [x] 定义完整能力矩阵,覆盖积累、升级、整理、评估四类。[CONCEPT: 功能能力] 证据:`CONCEPT.md` 已列出 17 个目标技能。 - -## 2. 后端资产 - -- [x] 增加新增数字员工任务 code 和分类映射。[CONCEPT: 后端] 证据:`agent_foundation_constants.py` 已新增 13 个任务 code,`DIGITAL_EMPLOYEE_TASK_CATEGORY_MAP` 覆盖四类分类。 -- [x] 增加运行时任务规格,保证已有数据库可自动补齐新增员工技能。[CONCEPT: 后端] 证据:`agent_foundation_digital_employee_tasks.py` 已扩展到 16 个运行时任务规格,新增技能均包含 `skill_name/input_sources/output_format/execution_strategy`。 -- [x] 调整初始种子流程,保证空库初始化时也能落齐完整员工技能库。[CONCEPT: 后端] 证据:`agent_foundation_asset_seed.py` 在基础资产 `flush` 后调用 `_upsert_runtime_digital_employee_tasks()`,空库初始化会补齐完整运行时技能。 - -## 3. 技能包 - -- [x] 新增制度条款、政策口径、规则命中样本等整理类技能包。[CONCEPT: 功能能力] 证据:已新增 `finance-policy-clause-extractor`、`expense-policy-alignment`、`rule-execution-case-organizer` 技能包。 -- [x] 新增部门基线、供应商画像、误报样本、反馈样本等积累类技能包。[CONCEPT: 功能能力] 证据:已新增 `department-expense-baseline-accumulator`、`supplier-risk-profile-accumulator`、`false-positive-sample-accumulator`、`risk-feedback-sample-accumulator` 技能包。 -- [x] 新增多凭证、时空、预算、供应商关系等评估类技能包。[CONCEPT: 功能能力] 证据:已新增 `multi-evidence-consistency-evaluator`、`travel-spatiotemporal-consistency-evaluator`、`budget-overrun-precontrol-evaluator`、`supplier-abnormal-relation-evaluator` 技能包。 -- [x] 新增回放评测、制度引用缺口提示等升级类技能包。[CONCEPT: 功能能力] 证据:已新增 `risk-algorithm-replay-evaluator`、`policy-reference-gap-hinter` 技能包。 - -## 4. 测试与验收 - -- [x] 增加数字员工技能目录测试,校验任务 code 唯一、分类覆盖、技能包存在。[CONCEPT: 测试方案] 证据:新增 `tests/test_digital_employee_skill_catalog.py` 覆盖任务数量、分类、配置和技能包。 -- [x] 在 Docker 容器 `x-financial-main:/app` 运行定向测试,60s 内完成。[CONCEPT: 测试方案] 证据:`docker exec x-financial-main bash -lc "cd /app && timeout 60s /tmp/x-financial-server-venv/bin/python -m pytest server/tests/test_digital_employee_skill_catalog.py -q"` 通过,3 个测试通过。 -- [x] 确认最终员工技能总数不少于 17 个,四类分类都有技能。[CONCEPT: 指标与验收] 证据:测试断言运行时 16 个技能加 `整理公司财务知识制度` 共 17 个,分类覆盖积累、升级、整理、评估。 - -## 5. 边界收敛 - -- [x] 调整概念文档,明确数字员工不总结风险规则、不发明规则、不替代人工确认风险。[CONCEPT: 数字员工边界] 证据:`CONCEPT.md` 和 `hermes-risk-graph-algorithm/CONCEPT.md` 已把数字员工边界收敛为事实抽取、规则命中结果读取、后台分析和待复核线索归集。 -- [x] 将“风险规则候选发现、风险规则模板整理、制度缺口与规则变更建议”收敛为事实、规则命中和人工复核辅助类技能。[CONCEPT: 功能能力] 证据:运行时技能已改为 `risk-clue-collector`、`rule-execution-case-organizer`、`policy-reference-gap-hinter`。 -- [x] 在技能配置中增加 `role_boundary` 和 `allowed_outputs`,约束输出只能是事实、规则命中、线索和证据引用。[CONCEPT: 数字员工边界] 证据:`agent_foundation_digital_employee_tasks.py` 为运行时技能配置写入 `role_boundary`、`allowed_outputs` 和 `writes_rules=false`。 -- [x] 更新技能包 Markdown,禁止数字员工发布、改写、总结规则,风险线索必须待人工复核。[CONCEPT: 后端] 证据:`risk-clue-collector`、`rule-execution-case-organizer`、`policy-reference-gap-hinter` 及兼容别名技能包均已声明禁止生成、改写或发布规则。 -- [x] 增加目录测试,防止数字员工技能重新出现自动发布、规则变更、候选规则生成等越权语义。[CONCEPT: 测试方案] 证据:`test_digital_employee_skills_do_not_cross_rule_governance_boundary` 已断言旧技能名和危险输出格式不再进入数字员工目录。 - -## 7. 流程边界收敛 - -- [x] 明确规则中心命中结果归属外层智能体流程,数字员工只消费规则命中结果。[CONCEPT: 数字员工边界] 证据:`CONCEPT.md` 已改为“规则命中分析”,并声明数字员工不触发规则主流程。 -- [x] 更新技能与配置文案,禁止数字员工被描述为规则主流程处理器。[CONCEPT: 后端] 证据:`agent_foundation_digital_employee_tasks.py`、`risk-clue-collector`、`rule-execution-case-organizer` 及兼容别名技能包均已改为后台分析和复核材料口径。 -- [x] 增加测试,防止 `role_boundary` 再次出现规则主流程越界表述。[CONCEPT: 测试方案] 证据:`test_digital_employee_runtime_specs_build_display_ready_config` 已覆盖主流程归属和禁止数字员工承担规则主流程职责。 - -## 6. 风险线索归集真实执行器 - -- [x] 新增 `HermesRiskClueCollectorService`,读取申请/报销事实、规则命中、风险观察和人工反馈,输出 `risk_clue_review_packet`。[CONCEPT: 算法与公式] 证据:`hermes_risk_clue_collector.py` 输出 `facts/rule_hits/risk_clues/evidence_refs/human_review_required`。 -- [x] 将 `risk_clue_collect` 接入数字员工立即运行分发。[CONCEPT: 后端] 证据:`orchestrator_execution.py` 已新增 `digital_employee.risk_clue.collect` 工具调用,`test_schedule_digital_employee_task_runs_real_service` 覆盖分发。 -- [x] 将 `risk_clue_collect` 接入 Hermes 定时调度。[CONCEPT: 后端] 证据:`hermes_scheduler.py` 已新增 `risk_clue_collect` 分支并写入执行摘要。 -- [x] 工作记录详情识别风险线索归集产物,展示事实、规则命中、待复核线索和证据引用计数。[CONCEPT: 前端] 证据:`digitalEmployeeWorkRecordsModel.js` 和 `DigitalEmployeeRunProducts.vue` 已支持 `risk_clue` 产物,前端测试覆盖。 -- [x] 增加执行器测试,验证不写规则、不输出候选规则、线索必须待人工复核。[CONCEPT: 测试方案] 证据:`test_hermes_risk_clue_collector.py` 通过,断言 `writes_rules=false`、`human_review_required=true` 和无 `candidate_risk_rules/auto_publish`。 - -## 8. 后台分析闭环 - -- [x] 风险线索归集产物补充观察键、反馈状态和近期反馈样本摘要,方便工作记录详情定位复核上下文。[CONCEPT: 后台分析闭环] 证据:`hermes_risk_clue_collector.py` 输出 `observation_key/feedback_status/next_action/feedback_summary`,`DigitalEmployeeRunProducts.vue` 展示反馈样本。 -- [x] 风险看板聚合接口补充 `risk_clue_count` 与 `feedback_sample_count`,把数字员工后台分析结果接入看板指标。[CONCEPT: 后台分析闭环] 证据:`RiskObservationDashboardRead` 与 `RiskObservationService.summarize_dashboard()` 已输出线索数和反馈样本数。 -- [x] 风险看板前端移除“候选规则”指标,改为“待复核线索”和“反馈样本”。[CONCEPT: 指标与验收] 证据:`RiskObservationDashboard.vue` 的算法闭环效果区已展示 `待复核线索/反馈样本`,前端测试断言不再出现候选规则。 -- [x] 增加后端与前端定向测试,并在 Docker 容器内验证核心后端测试通过。[CONCEPT: 测试方案] 证据:`pytest` 定向测试 8 个通过,`node --test` 前端定向测试 8 个通过。 diff --git a/document/development/数字员工财务报告体系/CONCEPT.md b/document/development/数字员工财务报告体系/CONCEPT.md deleted file mode 100644 index 563a78a..0000000 --- a/document/development/数字员工财务报告体系/CONCEPT.md +++ /dev/null @@ -1,328 +0,0 @@ -# 数字员工财务报告体系概念文档 - -更新日期:2026-06-02 - -## 功能一句话 - -让数字员工每周、每季、每年自动汇总企业费用、预算、流程、画像和风险经验,生成图文并茂的 PDF 报告,并按计划投递给财务管理人员。 - -## 背景与问题 - -当前系统已经具备财务看板快照、员工行为画像、风险观察、预算数据、定时提醒和 SMTP 配置入口,但这些能力仍是分散的: - -- 财务看板展示的是即时指标,不能替代周期复盘。 -- 数字员工已有运行记录,但缺少能给管理层阅读的正式 PDF 报告。 -- 员工画像、预算偏差、风险线索和提醒效果没有被串成企业经验。 -- 周报、季报、年报关注重点不同,不能只用一套普通表格。 -- 邮件投递需要可追踪:生成了什么、发给谁、是否成功、附件是什么。 - -因此本功能新增“财务报告编排员工”,负责把现有沉淀结果组织成管理层报告。 - -## 目标与非目标 - -### 目标 - -- 设计三类周期报告: - - 周报:每周一上午投递上周财务经营与流程待办。 - - 季报:每季度首周投递上季度预算执行、结构变化和风险复盘。 - - 年报:每年一月投递上一年度费用经营、预算质量、制度经验和改进建议。 -- 报告输出为 PDF,包含图表、重点结论、异常解释和行动建议。 -- 邮件投递给财务管理人员,收件人来自系统设置、角色或配置名单。 -- 报告生成、PDF 渲染、邮件投递都写入数字员工工作记录。 -- 模板可版本化,后续可以调整样式和章节,不影响历史报告。 - -### 非目标 - -- 第一阶段不接入真实外部 BI 平台。 -- 第一阶段不要求复杂拖拽式模板编辑器。 -- 第一阶段不让数字员工自动修改预算、规则或审批结论。 -- 第一阶段不对外发送生产邮件,除非 SMTP 配置和测试收件人已确认。 -- 第一阶段不生成面向普通员工的个人账单报告,先聚焦财务管理层。 - -## 用户与场景 - -- **财务负责人**:阅读周报,知道本周费用规模、预算压力、异常单据和流程卡点。 -- **财务经理**:阅读季报,复盘部门费用结构、预算执行质量和高频风险。 -- **预算管理员**:从报告中看到预算使用率、超支预测、闲置预算和编制提醒。 -- **风控/审计人员**:从报告中看到风险观察、误报样本、制度缺口和重点复核对象。 -- **系统管理员**:查看报告任务是否按计划生成、渲染和发送。 - -## 报告周期与核心用途 - -### 周报 - -定位:经营驾驶舱 + 本周行动清单。 - -适合回答: - -- 上周花了多少钱,多少单,环比是否异常。 -- 哪些部门、人员、费用类型最突出。 -- 本周有哪些待付款、待补材料、待审批和预算压力。 -- 数字员工发现了哪些风险线索,需要谁处理。 - -### 季报 - -定位:预算执行复盘 + 管理改进。 - -适合回答: - -- 本季度预算使用是否健康。 -- 哪些部门长期超预算或预算闲置。 -- 哪些费用类型增长过快。 -- 员工画像和供应商画像中出现了什么稳定趋势。 -- 风险规则和制度条款哪里需要人工优化。 - -### 年报 - -定位:年度经营经验沉淀 + 下一年度管理建议。 - -适合回答: - -- 全年费用结构和预算质量如何。 -- 哪些制度执行效果好,哪些制度经常缺引用或被反馈误报。 -- 哪些部门、岗位、费用类型需要来年重点管理。 -- 数字员工全年沉淀了哪些企业财务经验。 -- 下一年度预算编制、制度修订和风险模型优化建议是什么。 - -## PDF 模板设计 - -整体视觉采用 X-Financial 企业 SaaS 风格:低饱和蓝灰、直角卡片、清晰分隔、少装饰、图表优先。PDF 以 A4 纵向为主,关键图表允许横向宽图。 - -### 统一样式 - -- 字体:中文使用系统黑体或 Noto Sans CJK,数字使用等宽或 Inter 风格数字。 -- 主色:深蓝灰用于标题,财务蓝用于主指标,绿色表示健康,橙色表示预警,红色表示高风险。 -- 页眉:报告名称、周期、生成时间、数字员工名称。 -- 页脚:页码、数据窗口、保密提示。 -- 图表:柱状图、折线图、堆叠条、矩阵热力图、Top N 排行。 -- 每页结构:结论区在上,图表在中,解释和建议在下。 - -### 周报模板 - -建议 8-10 页: - -1. 封面:报告周期、收件部门、生成时间。 -2. 管理摘要:3-5 条关键结论,突出金额、预算、风险和待办。 -3. 费用总览:报销金额、单数、人均费用、环比变化。 -4. 每日费用趋势:每日金额折线 + 每日单数柱状。 -5. 部门费用排行:Top 部门金额、单数、人均费用。 -6. 预算执行:预算使用率、预警预算池、待释放预占。 -7. 高额单据与个人排行:金额最高单据、金额最高个人、待付款金额。 -8. 流程待办:待审批、待补材料、待付款、待归档。 -9. 风险线索:高风险单据、材料异常、预算压力、重复票据。 -10. 本周行动清单:责任人、事项、建议动作、截止时间。 - -### 季报模板 - -建议 12-16 页: - -1. 封面。 -2. 季度管理摘要。 -3. 季度费用结构:费用类型占比和季度变化。 -4. 部门预算执行矩阵:部门 x 费用类型预算使用率热力图。 -5. 预算偏差分析:超支、闲置、预占未释放、预测偏差。 -6. 部门经营画像:部门费用强度、流程质量、风险密度。 -7. 员工行为画像:高频报销、退回率、补材料率、异常波动。 -8. 供应商/商户画像:高频商户、集中度、异常关系。 -9. 风险观察复盘:确认率、误报率、高频风险信号。 -10. 制度执行复盘:制度条款命中、缺引用、冲突或过期条款。 -11. 数字员工工作成效:扫描次数、沉淀快照、提醒数量、关闭事项。 -12. 下季度管理建议:预算、制度、流程、风控四类建议。 - -### 年报模板 - -建议 18-24 页: - -1. 封面。 -2. 年度管理摘要。 -3. 全年费用规模与趋势。 -4. 部门费用结构年度变化。 -5. 预算编制质量:预算准确率、调整频率、超支/闲置分布。 -6. 费用类型策略复盘:差旅、招待、办公、通信等。 -7. 流程效率年度复盘:提交、审批、付款、归档耗时。 -8. 员工画像年度沉淀:费用行为群组和变化。 -9. 供应商画像年度沉淀。 -10. 风险图谱年度复盘。 -11. 制度与规则效果:命中、误报、人工反馈和制度缺口。 -12. 数字员工年度工作记录:任务覆盖、报告、提醒、快照、风险线索。 -13. 下一年度预算编制建议。 -14. 下一年度制度优化建议。 -15. 下一年度风险治理建议。 -16. 附录:指标口径、数据窗口、样本限制。 - -## 邮件投递设计 - -### 收件人 - -收件人优先级: - -1. 报告任务配置中的固定收件人。 -2. 系统设置中的 `default_receiver`、`notice_email` 或 `admin_email`。 -3. 具有财务管理、预算管理、风控审计角色的员工邮箱。 - -### 邮件内容 - -- 标题:`X-Financial 财务周报 | 2026-05-25 至 2026-05-31` -- 正文: - - 报告摘要 3 条。 - - 关键指标 4 个。 - - 待处理行动数量。 - - PDF 附件。 - - 系统内报告详情链接。 - -### 投递追踪 - -每次投递写入数字员工运行记录: - -- 报告类型:weekly / quarterly / annual。 -- 报告周期。 -- PDF 文件路径或存储 key。 -- 收件人列表。 -- 邮件发送状态。 -- 失败原因。 -- 重试次数。 - -## 后端方案 - -### 新增服务 - -- `finance_report_context.py`:聚合财务看板、预算、风险、画像、提醒、数字员工运行记录。 -- `finance_report_template.py`:定义周报、季报、年报章节和图表配置。 -- `finance_report_renderer.py`:将报告上下文渲染为 HTML,再生成 PDF。 -- `finance_report_mailer.py`:读取 SMTP 配置并发送邮件。 -- `finance_report_scheduler.py`:按周、季、年触发报告生成。 -- `digital_employee_finance_report_task.py`:数字员工任务编排入口。 - -### 数据来源 - -- `expense_claims`、`expense_claim_items`:费用、单据、部门、状态。 -- `budget_allocations`、`budget_transactions`、`budget_reservations`:预算执行。 -- `risk_observations`:风险观察和复核结果。 -- `employee_behavior_profile_snapshots`:员工画像。 -- `agent_runs`、`agent_tool_calls`:数字员工工作记录、提醒扫描、看板快照。 -- `settings`:SMTP 和默认收件人配置。 - -### 存储方式 - -第一阶段建议不新增大表,先使用: - -- PDF 文件:`server/storage/finance_reports///report.pdf` -- 元数据:写入 `agent_runs.route_json.report_delivery` - -如果后续需要报告列表、重发、下载和归档,再新增 `finance_reports` 表。 - -## 前端方案 - -第一阶段只做必要入口: - -- 数字员工工作记录中显示“财务周报/季报/年报生成”。 -- 报告运行详情显示摘要、收件人、PDF 路径和发送状态。 -- 系统设置保留 SMTP 配置,不新增复杂模板编辑器。 - -第二阶段新增报告中心: - -- 报告列表:类型、周期、生成时间、发送状态。 -- 报告详情:PDF 预览、摘要、指标、收件人。 -- 手动生成:选择周期和收件人后触发数字员工。 -- 重发邮件:仅对已有 PDF 重发,不重复计算。 - -## 数字员工新增能力 - -### 必做技能 - -1. **财务报告编排** - - 把看板、预算、风险、画像和提醒整合为报告上下文。 - - 输出 PDF 和邮件摘要。 - -2. **预算偏差解释** - - 对预算超支、闲置、预占未释放做原因归因。 - - 输出部门、费用类型和责任人视角建议。 - -3. **流程效率复盘** - - 沉淀审批、付款、归档耗时。 - - 找出长期卡点和责任角色。 - -4. **制度缺口复盘** - - 汇总风险观察中缺少制度依据的情况。 - - 提示制度管理员补齐条款,不自动改规则。 - -5. **报告投递与回执跟踪** - - 记录邮件是否发出、是否失败、是否需要重试。 - -### 可逐步挖掘的高价值技能 - -- **费用结构漂移检测**:发现某部门费用类型占比突然变化。 -- **预算预测与预警**:基于当前消耗预测季度末是否超支。 -- **重复报销关系挖掘**:从员工、商户、发票、地点关系中找重复模式。 -- **供应商集中度监控**:识别费用过度集中到少数商户或供应商。 -- **部门横向对标**:同规模部门人均费用、退回率、补材料率对比。 -- **制度执行热力图**:哪些制度条款最常命中,哪些最常被人工否定。 -- **数字员工建议命中率复盘**:数字员工提醒、风险线索和人工处理结果之间的闭环。 -- **异常趋势早期信号**:在风险尚未形成前发现金额、频次、提交时间的异常变化。 - -## 算法与公式 - -### 周报异常评分 - -$$ -weekly\_alert\_score = 0.35 \times spend\_change + 0.25 \times budget\_pressure + 0.25 \times risk\_density + 0.15 \times process\_delay -$$ - -其中: - -- `spend_change`:本周费用环比变化归一化值。 -- `budget_pressure`:预算使用率或预测超支风险。 -- `risk_density`:风险单据金额 / 报销总金额。 -- `process_delay`:逾期待处理事项占比。 - -### 预算预测 - -$$ -predicted\_usage = current\_usage + \frac{current\_usage}{elapsed\_days} \times remaining\_days -$$ - -当 `predicted_usage > budget_limit` 时,报告标记为预算超支预测。 - -### 流程效率 - -$$ -avg\_cycle\_hours = \frac{\sum_{i=1}^{n}(finished\_at_i - submitted\_at_i)}{n} -$$ - -按部门、审批人、费用类型拆分,识别长期高于 P90 的卡点。 - -### 报告优先级 - -$$ -section\_priority = 0.4 \times amount\_impact + 0.3 \times risk\_impact + 0.2 \times recurrence + 0.1 \times management\_urgency -$$ - -用于决定管理摘要中展示哪些结论。 - -## 测试方案 - -- 后端单元测试:报告上下文聚合、模板章节生成、指标计算。 -- PDF 渲染测试:生成 HTML 和 PDF,检查页数、标题、图表占位和附件存在。 -- 邮件测试:使用 mock SMTP,验证标题、收件人、正文和附件。 -- 调度测试:周报、季报、年报触发时间和重复执行保护。 -- 数字员工运行记录测试:确认报告生成和邮件投递写入 `agent_runs`。 -- 容器验证:在 `x-financial-main:/app` 内运行定向 pytest,60s 超时。 -- 手工验证:生成一份周报 PDF,检查图文布局、中文显示、金额格式和页码。 - -## 指标与验收 - -- 可以生成一份周报 PDF,包含摘要、趋势图、部门排行、预算、风险和行动清单。 -- PDF 文件路径写入数字员工运行记录。 -- 邮件 mock 测试能验证附件发送。 -- SMTP 未配置时任务不失败,降级为“生成成功、投递待配置”。 -- 周报、季报、年报模板均有独立章节定义。 -- 报告中的单号、部门、金额、状态来自真实数据库聚合。 -- 数字员工看板能看到报告生成任务和结果摘要。 - -## 风险与开放问题 - -- PDF 渲染依赖中文字体和浏览器/渲染库环境,必须在容器内验证。 -- 真实 SMTP 投递涉及外部邮件服务器,需要先用测试收件人验证。 -- 若后续要求报告下载、重发、审阅状态和历史归档,建议新增 `finance_reports` 表。 -- 季报和年报需要更稳定的画像和风险反馈数据,否则前期只能展示模拟或有限结论。 -- 图表渲染要避免依赖前端 ECharts 截图,优先后端生成可控 SVG/HTML 图表。 diff --git a/document/development/数字员工财务报告体系/TODO.md b/document/development/数字员工财务报告体系/TODO.md deleted file mode 100644 index ff09e32..0000000 --- a/document/development/数字员工财务报告体系/TODO.md +++ /dev/null @@ -1,80 +0,0 @@ -# 数字员工财务报告体系 TODO - -更新日期:2026-06-02 - -## 阶段一:调研与契约 - -- [x] 梳理现有财务看板、预算、风险、画像、提醒扫描和数字员工运行记录接口字段。[CONCEPT: 数据来源] 证据:`finance_report_context.py` 已聚合 `FinanceDashboardService`、`RiskObservation`、`EmployeeBehaviorProfileSnapshot`、`AgentRun`。 -- [x] 梳理系统设置中的 SMTP 配置字段和默认收件人来源。[CONCEPT: 邮件投递设计] 证据:`finance_report_mailer.py` 已读取 `SystemSetting` 和 `SystemSettingSecret`。 -- [x] 定义报告任务类型:`weekly_finance_report`、`quarterly_finance_report`、`annual_finance_report`。[CONCEPT: 后端方案] 证据:当前实现采用 `weekly/quarterly/annual` 类型并写入 `finance_report_orchestration` 任务。 -- [x] 定义数字员工任务 code、技能名称、输出格式和调度周期。[CONCEPT: 数字员工新增能力] 证据:`task.hermes.finance_report_orchestration`、`finance-report-orchestrator`、`finance_report_pdf_delivery` 已注册。 -- [x] 定义报告上下文 schema,覆盖摘要、指标、图表、行动清单、投递结果。[CONCEPT: 后端方案] 证据:`DigitalEmployeeFinanceReportTaskService._result_payload()` 已输出 `summary/insights/action_items/pdf/delivery`。 - -## 阶段二:模板与样式 - -- [x] 新增周报模板章节配置,包含摘要、费用趋势、部门排行、预算、高额单据、流程待办、风险线索和行动清单。[CONCEPT: 周报模板] 证据:`finance_report_renderer.py` 已输出周报 HTML/PDF 章节。 -- [ ] 新增季报模板章节配置,包含预算执行矩阵、员工画像、供应商画像、风险复盘和下季度建议。[CONCEPT: 季报模板] -- [ ] 新增年报模板章节配置,包含年度费用、预算质量、流程效率、制度效果和下一年度建议。[CONCEPT: 年报模板] -- [x] 设计统一 PDF 主题变量:字体、颜色、页眉、页脚、图表色板、金额格式。[CONCEPT: 统一样式] 证据:`FinanceReportRenderer.render_html()` 与 `SimpleFinancePdfWriter` 已定义报告样式和图表表现。 -- [x] 准备 HTML 到 PDF 的最小渲染样例,验证中文字体、页码、分页和图表展示。[CONCEPT: PDF 模板设计] 证据:真实生成 `server/storage/finance_reports/weekly/2026-05-25_至_2026-05-31/report.pdf`,PDF 头为 `%PDF`。 - -## 阶段三:后端报告上下文 - -- [x] 新增 `finance_report_context.py`,聚合财务看板、预算、风险、画像、提醒和数字员工运行记录。[CONCEPT: 后端方案] 证据:服务文件已新增并通过测试。 -- [x] 实现周报上下文计算,输出上周金额、单数、环比、预算压力、风险线索和行动清单。[CONCEPT: 周报] 证据:脚本生成周报摘要 `30 单 / ¥135,058 / 5 项行动`。 -- [ ] 实现季报上下文计算,输出季度预算偏差、部门矩阵、画像复盘和风险反馈。[CONCEPT: 季报] -- [ ] 实现年报上下文计算,输出年度趋势、预算质量、制度执行和数字员工沉淀成果。[CONCEPT: 年报] -- [ ] 实现异常评分、预算预测、流程效率和章节优先级公式。[CONCEPT: 算法与公式] - -## 阶段四:PDF 渲染 - -- [x] 新增 `finance_report_template.py`,把上下文映射为章节、图表和建议文本。[CONCEPT: 后端方案] 证据:第一版模板逻辑内聚在 `finance_report_renderer.py`,后续如需复杂模板再拆文件。 -- [x] 新增 `finance_report_renderer.py`,把模板渲染为 HTML。[CONCEPT: 后端方案] 证据:已生成 `report.html`。 -- [x] 接入 PDF 渲染方案,输出到 `server/storage/finance_reports///report.pdf`。[CONCEPT: 存储方式] 证据:已生成 `finance_reports/weekly/2026-05-25_至_2026-05-31/report.pdf`。 -- [x] 生成周报 PDF 样例,手工检查封面、摘要、图表、行动清单和页脚。[CONCEPT: 指标与验收] 证据:容器内确认 PDF 文件存在且以 `%PDF` 开头。 -- [ ] 渲染失败时保留 HTML 和错误信息,写入数字员工运行记录。[CONCEPT: 风险与开放问题] - -## 阶段五:邮件投递 - -- [x] 新增 `finance_report_mailer.py`,读取 SMTP 配置和默认收件人。[CONCEPT: 邮件投递设计] 证据:已联动系统设置 SMTP 字段和加密密码。 -- [x] SMTP 未配置时降级为“报告生成成功、投递待配置”。[CONCEPT: 指标与验收] 证据:真实脚本返回 `pending_configuration`,原因 `smtp_password` 缺失。 -- [ ] 使用 mock SMTP 测试邮件标题、正文、收件人和 PDF 附件。[CONCEPT: 测试方案] -- [x] 记录邮件投递状态、失败原因、重试次数和收件人列表。[CONCEPT: 投递追踪] 证据:`agent_runs.route_json.report_delivery.delivery` 已记录收件人、主题、状态和失败原因。 -- [ ] 支持手动重发已有 PDF,不重复计算报告上下文。[CONCEPT: 前端方案] - -## 阶段六:数字员工任务与调度 - -- [x] 新增 `digital_employee_finance_report_task.py`,作为报告编排员工入口。[CONCEPT: 后端方案] 证据:服务已生成报告、PDF 和投递结果。 -- [x] 新增或扩展报告调度器,支持每周、每季、每年执行。[CONCEPT: 报告周期与核心用途] 证据:`finance_report_scheduler.py` 已按周、季、年触发并做当天去重。 -- [x] 将报告生成写入 `agent_runs` 和 `agent_tool_calls`。[CONCEPT: 邮件投递设计] 证据:`run_f137ec8112cd44eb` 成功记录报告结果。 -- [x] 在数字员工技能列表中新增“财务报告编排”技能。[CONCEPT: 数字员工新增能力] 证据:技能中心同步后查询到 `task.hermes.finance_report_orchestration`。 -- [x] 在数字员工工作记录中展示报告生成、PDF 路径、投递状态和摘要。[CONCEPT: 前端方案] 证据:当前通过 `agent_runs.route_json.report_delivery` 暴露,前端详情可读取。 - -## 阶段七:报告中心增强 - -- [ ] 评估是否新增 `finance_reports` 表,用于报告列表、下载、重发、审阅状态和历史归档。[CONCEPT: 存储方式] -- [ ] 新增报告列表接口,按类型、周期、生成状态筛选。[CONCEPT: 前端方案] -- [ ] 新增报告详情接口,返回摘要、收件人、PDF 下载地址和投递记录。[CONCEPT: 前端方案] -- [ ] 前端新增报告中心页面或数字员工详情页入口。[CONCEPT: 前端方案] -- [ ] 支持手动生成报告,选择周期和测试收件人。[CONCEPT: 前端方案] - -## 阶段八:高价值挖掘技能 - -- [ ] 费用结构漂移检测:识别部门费用类型占比突变。[CONCEPT: 可逐步挖掘的高价值技能] -- [ ] 预算预测与预警:预测季度末超支风险。[CONCEPT: 可逐步挖掘的高价值技能] -- [ ] 重复报销关系挖掘:识别员工、商户、发票、地点的重复模式。[CONCEPT: 可逐步挖掘的高价值技能] -- [ ] 供应商集中度监控:识别费用过度集中到少数商户或供应商。[CONCEPT: 可逐步挖掘的高价值技能] -- [ ] 部门横向对标:同规模部门人均费用、退回率、补材料率对比。[CONCEPT: 可逐步挖掘的高价值技能] -- [ ] 制度执行热力图:统计条款命中、缺引用和人工否定。[CONCEPT: 可逐步挖掘的高价值技能] -- [ ] 数字员工建议命中率复盘:把提醒、风险线索和人工处理结果闭环。[CONCEPT: 可逐步挖掘的高价值技能] -- [ ] 异常趋势早期信号:发现未形成风险前的金额、频次和提交时间异常。[CONCEPT: 可逐步挖掘的高价值技能] - -## 阶段九:测试与验收 - -- [x] 后端单元测试覆盖报告上下文聚合、模板章节生成和指标公式。[CONCEPT: 测试方案] 证据:`test_finance_report_task.py` 覆盖报告生成和摘要。 -- [x] PDF 渲染测试覆盖中文字体、页数、标题、图表占位和文件存在。[CONCEPT: 测试方案] 证据:测试确认 PDF 文件存在且以 `%PDF` 开头。 -- [ ] 邮件 mock 测试覆盖标题、正文、收件人和附件。[CONCEPT: 测试方案] -- [ ] 调度测试覆盖周报、季报、年报触发时间和重复执行保护。[CONCEPT: 测试方案] -- [x] 容器内运行定向测试,命令使用 `docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main ...`,60s 超时。[CONCEPT: 测试方案] 证据:`pytest -q server/tests/test_finance_report_task.py server/tests/test_digital_employee_skill_catalog.py` 4 passed。 -- [x] 生成真实周报 PDF 并检查最终用户可见效果。[CONCEPT: 指标与验收] 证据:`server/scripts/generate_finance_report.py --type weekly --dry-run-email` 生成真实周报。 -- [x] 验证数字员工看板能看到报告任务和投递结果。[CONCEPT: 指标与验收] 证据:运行记录中已有 `finance_report_orchestration` 和 `report_delivery`。 diff --git a/document/development/数字员工财务经验沉淀与定时提醒/CONCEPT.md b/document/development/数字员工财务经验沉淀与定时提醒/CONCEPT.md deleted file mode 100644 index a956b62..0000000 --- a/document/development/数字员工财务经验沉淀与定时提醒/CONCEPT.md +++ /dev/null @@ -1,227 +0,0 @@ -# 数字员工财务经验沉淀与定时提醒概念文档 - -更新日期:2026-06-02 - -## 功能一句话 - -把数字员工定位为后台财务数据分析员:定时沉淀企业财务经验,周期性生成分析报告,并在审批、预算、出差申请和报销流程中生成可追踪的提醒建议。 - -## 背景与问题 - -当前数字员工已经具备技能目录、财务看板快照和员工行为画像扫描能力,但业务价值仍偏弱: - -- 技能列表数量多,但多数只是能力定义,缺少持续沉淀和行动产出。 -- 员工画像已有数据,但如果不持续沉淀,系统不会随企业数据变多而变聪明。 -- 财务流程中存在大量需要定时推动的事项,例如领导审批、预算编制、出差申请到期、报销补材料和归档。 -- 现在缺少统一的后台提醒扫描结果,无法证明数字员工每天发现了哪些待处理事项、提醒了谁、为什么提醒。 - -因此本功能把数字员工拆成三条主线: - -- **行为沉淀技能**:每天小颗粒沉淀费用、预算、单据、流程、画像经验。 -- **定时提醒技能**:按时间窗口扫描待办事项,生成面向责任人的提醒清单。 -- **周期报告技能**:读取沉淀结果和提醒效果,形成企业财务经验报告。 - -## 目标与非目标 - -### 目标 - -- 建立数字员工“后台分析员”定位,不再把全部技能包装成前台执行能力。 -- 收敛技能体系为行为沉淀、定时提醒、周期报告三类。 -- 第一阶段落地一个真实可运行的 **定时提醒扫描任务**。 -- 提醒扫描使用现有业务数据,不新增数据库结构,结果写入 `agent_runs` 和 `agent_tool_calls`。 -- 提醒扫描至少覆盖: - - 待审批单据提醒。 - - 预算编制/预算缺口提醒。 - - 出差申请到期后待报销提醒。 - - 报销逾期、补材料、付款/归档提醒。 -- 数字员工看板能够看到提醒扫描的运行记录和提醒产出数量。 - -### 非目标 - -- 第一阶段不做站内信、邮件、短信或企业微信真实投递。 -- 第一阶段不新增提醒表、已读表、重复提醒去重表等数据库结构。 -- 第一阶段不替代审批、付款、预算编制和报销操作,只生成提醒建议。 -- 第一阶段不让数字员工自动修改单据状态、预算状态或审批结果。 -- 第一阶段不做完整报告页面,只把提醒报告结构化写入运行记录。 - -## 用户与场景 - -- **部门领导**:每天收到待审批单据汇总,知道待审数量、最高金额、最长等待时间。 -- **预算管理员**:在预算周期临近或预算池缺失时收到编制/补齐提醒。 -- **出差员工**:出差申请结束后未报销时收到报销或延长申请提醒。 -- **财务人员**:看到报销逾期、补材料、付款、归档等流程卡点。 -- **财务负责人**:周期性查看提醒扫描报告,判断哪些流程经常阻塞。 -- **系统管理员**:在数字员工看板查看提醒任务是否稳定运行。 - -## 功能能力 - -### 行为沉淀技能 - -后续应逐步沉淀以下经验快照: - -- 费用结构基线:部门、费用类型、月份、单数、金额、均值、P90。 -- 预算执行偏差:使用率、闲置率、超支风险、预测偏差。 -- 报销行为画像:员工/部门报销频率、金额区间、退回率、补材料率。 -- 单据质量经验:缺附件、发票异常、金额不一致、退回原因。 -- 流程效率经验:提交到审批、审批到付款、付款到归档的耗时。 -- 制度执行经验:制度条款命中频率、人工否定频率、制度缺口。 - -### 定时提醒技能 - -第一阶段实现 `digital_employee_reminder_scan`,生成统一提醒报告: - -- `approval_pending`:待审批提醒。 -- `budget_compilation`:预算编制/预算池缺口提醒。 -- `travel_application_expiry`:出差申请已结束但未报销提醒。 -- `reimbursement_overdue`:报销逾期、补材料、待付款、待归档提醒。 - -提醒报告只写入数字员工运行记录,结构包含: - -- 扫描时间和窗口。 -- 每类提醒数量。 -- 每个收件人的提醒摘要。 -- 关联单据、金额、最长等待时间、建议动作。 -- 是否需要人工处理。 - -### 周期报告技能 - -后续在沉淀和提醒任务稳定后生成: - -- 每日财务经营摘要。 -- 周度流程效率复盘。 -- 月度预算执行复盘。 -- 半年度企业财务经验报告。 - -## 方案设计 - -### 后端 - -第一阶段新增三个后端模块: - -- `digital_employee_reminder_task.py`:执行提醒扫描,写入 `AgentRun`。 -- `digital_employee_reminder_scheduler.py`:后台调度器,默认每天 02:00 扫描,可配置首次延迟用于开发验证。 -- `digital_employee_dashboard.py`:扩展任务类型和指标,让看板统计提醒产出。 - -提醒扫描复用现有表: - -- `expense_claims`:报销单和费用申请单。 -- `employees`:员工、直属领导、角色。 -- `budget_allocations`:预算池。 -- `agent_runs` / `agent_tool_calls`:数字员工运行记录。 - -### 数据输出结构 - -运行记录中的 `route_json.report` 使用如下结构: - -```json -{ - "title": "数字员工定时提醒扫描报告", - "generatedAt": "2026-06-02T02:00:00+08:00", - "windowDays": 14, - "totals": { - "recipientCount": 8, - "reminderCount": 23, - "approvalPendingCount": 7, - "budgetReminderCount": 4, - "travelApplicationReminderCount": 5, - "reimbursementOverdueCount": 7 - }, - "recipients": [ - { - "recipientId": "emp-001", - "recipientName": "张三", - "recipientRole": "manager", - "reminders": [ - { - "type": "approval_pending", - "priority": "high", - "title": "你有 3 笔报销单待审批", - "action": "请在今日处理审批待办", - "relatedDocuments": [] - } - ] - } - ] -} -``` - -### 前端 - -第一阶段不新增独立页面。数字员工看板通过已有最近运行记录展示: - -- 任务名称:定时提醒扫描。 -- 产出数量:提醒数量。 -- 最近摘要:提醒了多少人、多少条事项。 - -后续可在数字员工工作记录详情中扩展“提醒报告详情”。 - -## 算法与公式 - -### 提醒优先级 - -提醒优先级由等待天数、金额和业务类型决定: - -$$ -priority\_score = 0.45 \times wait\_score + 0.35 \times amount\_score + 0.20 \times type\_score -$$ - -其中: - -- `wait_score = min(wait_days / threshold_days, 1)` -- `amount_score = min(amount / high_amount_threshold, 1)` -- `type_score`:审批、预算、出差、报销流程分别给定基础分。 - -优先级映射: - -$$ -priority = -\begin{cases} -high, & priority\_score \ge 0.75 \\ -medium, & 0.45 \le priority\_score < 0.75 \\ -low, & priority\_score < 0.45 -\end{cases} -$$ - -### 待审批等待天数 - -$$ -wait\_days = floor((now - submitted\_at) / 86400) -$$ - -如果 `submitted_at` 为空,则使用 `updated_at` 或 `created_at` 降级计算。 - -### 预算缺口识别 - -当前阶段使用预算池存在性和周期作为提醒依据: - -$$ -budget\_gap = active\_allocation\_count = 0 -$$ - -当当前年度/期间没有有效预算池,或预算池处于非 active/published 状态时,生成预算编制提醒。 - -## 测试方案 - -- 后端单元测试:构造员工、领导、报销单、申请单和预算池,验证提醒报告数量与收件人。 -- 看板聚合测试:构造 `digital_employee_reminder_scan` 运行记录,验证 `reminders` 指标被统计。 -- 调度器测试:验证 scheduler 能调用任务服务,不重复启动。 -- 容器验证:在 `x-financial-main:/app` 内运行定向 pytest,60s 超时。 -- 运行时验证:重启容器后查询 `agent_runs`,确认提醒扫描记录成功生成。 -- HTTP 验证:调用 `/api/v1/analytics/digital-employee-dashboard`,确认任务分布包含定时提醒扫描。 - -## 指标与验收 - -- `agent_runs` 中出现 `task_type=digital_employee_reminder_scan` 的成功运行。 -- 工具响应包含 `recipient_count`、`reminder_count` 和四类提醒计数。 -- 数字员工看板 `businessOutputs` 计入提醒数量。 -- 最近运行记录展示“定时提醒扫描”。 -- 定向测试通过。 -- 不新增数据库结构,不改变现有单据状态。 - -## 风险与开放问题 - -- 第一阶段只生成提醒报告,不做真实消息投递;后续需要站内信/邮件/企业微信时再新增消息模型。 -- 当前预算编制状态模型还不完整,第一阶段只能基于预算池缺口和期间判断。 -- 出差申请到期依赖申请单中的 `application_detail.time`,如果历史数据缺失,只能降级使用 `occurred_at`。 -- 审批责任人目前主要通过员工直属领导推断,复杂动态审批流需要后续对接审批路由结果。 -- 如果后续需要“已读/已处理/重复提醒抑制”,必须新增提醒表或消息表,并进行数据库迁移确认。 diff --git a/document/development/数字员工财务经验沉淀与定时提醒/TODO.md b/document/development/数字员工财务经验沉淀与定时提醒/TODO.md deleted file mode 100644 index 2f4ddfa..0000000 --- a/document/development/数字员工财务经验沉淀与定时提醒/TODO.md +++ /dev/null @@ -1,39 +0,0 @@ -# 数字员工财务经验沉淀与定时提醒开发 TODO - -## 阶段一:调研与文档 - -- [x] 梳理现有数字员工技能、画像扫描、财务看板快照和看板聚合链路。[CONCEPT: 背景与问题] 证据:已核对 `agent_foundation_digital_employee_tasks.py`、`digital_employee_dashboard.py`、`employee_profile_scan_task.py`。 -- [x] 梳理审批、预算、出差申请和报销单模型字段。[CONCEPT: 方案设计] 证据:已核对 `approval.py`、`budget.py`、`financial_record.py`、`user_agent_application.py`。 -- [x] 明确第一阶段不新增数据库结构,只用 `agent_runs` 和 `agent_tool_calls` 保存提醒扫描报告。[CONCEPT: 目标与非目标] 证据:`CONCEPT.md` 已写明。 -- [x] 创建概念文档和开发 TODO。[CONCEPT: 全文] 证据:本目录 `CONCEPT.md` 与 `TODO.md`。 - -## 阶段二:后端提醒扫描任务 - -- [x] 新增 `digital_employee_reminder_task.py`,定义 `DigitalEmployeeReminderTaskService`。[CONCEPT: 后端] 证据:新增服务文件并通过 ruff。 -- [x] 实现待审批提醒扫描,按直属领导聚合待审批单据。[CONCEPT: 定时提醒技能] 证据:`test_digital_employee_reminder_task.py` 覆盖 `approval_pending`。 -- [x] 实现预算编制/预算缺口提醒,按当前年度和期间识别预算池缺口。[CONCEPT: 定时提醒技能] 证据:`test_digital_employee_reminder_task.py` 覆盖 `budget_compilation`。 -- [x] 实现出差申请到期提醒,识别已结束但未报销或未关闭的申请单。[CONCEPT: 定时提醒技能] 证据:`test_digital_employee_reminder_task.py` 覆盖 `travel_application_expiry`。 -- [x] 实现报销逾期/补材料/付款/归档提醒,识别流程卡点。[CONCEPT: 定时提醒技能] 证据:`test_digital_employee_reminder_task.py` 覆盖 `reimbursement_overdue`。 -- [x] 将提醒报告写入 `AgentRun` 和 `AgentToolCall`,包含 `recipient_count`、`reminder_count` 和分类计数。[CONCEPT: 数据输出结构] 证据:任务服务测试读取返回 summary 与 report。 - -## 阶段三:调度与看板 - -- [x] 新增 `digital_employee_reminder_scheduler.py`,默认每天 02:00 扫描,支持开发环境首次延迟运行。[CONCEPT: 后端] 证据:新增调度器并通过 ruff。 -- [x] 在 `main.py` 生命周期中启动和关闭提醒调度器。[CONCEPT: 后端] 证据:`main.py` 已接入 scheduler start/shutdown。 -- [x] 扩展 `DigitalEmployeeDashboardService`,识别 `digital_employee_reminder_scan`。[CONCEPT: 前端] 证据:看板聚合测试覆盖 task type。 -- [x] 看板指标增加提醒产出计数,最近运行记录显示“定时提醒扫描”。[CONCEPT: 指标与验收] 证据:`test_digital_employee_dashboard_service.py` 覆盖 `reminders` 和 `businessOutputs`。 - -## 阶段四:测试与验证 - -- [x] 新增后端单元测试,验证四类提醒的收件人、数量和摘要。[CONCEPT: 测试方案] 证据:`server/tests/test_digital_employee_reminder_task.py`。 -- [x] 新增数字员工看板聚合测试,验证提醒数量进入 `businessOutputs`。[CONCEPT: 测试方案] 证据:`server/tests/test_digital_employee_dashboard_service.py`。 -- [x] 在容器内运行 ruff:`docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/python -m ruff check `。[CONCEPT: 测试方案] 证据:All checks passed。 -- [x] 在容器内运行定向 pytest,超时 60s,验证提醒任务和看板聚合。[CONCEPT: 测试方案] 证据:`5 passed in 3.39s`。 -- [x] 重启 `x-financial-main`,查询 `agent_runs` 确认提醒扫描运行记录成功生成。[CONCEPT: 指标与验收] 证据:`run_4c3a2b847fae4ada` succeeded,提醒 47 人,生成 403 条事项。 -- [x] 调用 `/api/v1/analytics/digital-employee-dashboard`,确认任务分布包含定时提醒扫描。[CONCEPT: 指标与验收] 证据:HTTP 200,`reminders=403`,任务分布包含 `digital_employee_reminder_scan`。 - -## 后续阶段:消息投递闭环 - -- [ ] 评估是否新增提醒消息表、已读状态和重复提醒抑制策略。[CONCEPT: 风险与开放问题] -- [ ] 设计站内信、邮件或企业微信投递通道。[CONCEPT: 非目标] -- [ ] 设计提醒处理结果回流,用于沉淀“哪些提醒真正有效”。[CONCEPT: 行为沉淀技能] diff --git a/document/development/申请交通费用自动预估/CONCEPT.md b/document/development/申请交通费用自动预估/CONCEPT.md deleted file mode 100644 index ab1508a..0000000 --- a/document/development/申请交通费用自动预估/CONCEPT.md +++ /dev/null @@ -1,127 +0,0 @@ -# 申请交通费用自动预估概念文档 - -## 功能一句话 - -在费用申请预览阶段,系统自动生成交通票价 mock 估算,并叠加现有住宿与补助标准,形成申请预估总费用,替代用户手动填写预估金额。 - -## 背景与问题 - -当前申请流程要求用户补充“用户预估费用”。对差旅申请来说,用户在申请阶段往往只能确认出行方式、目的地和天数,交通票价又暂时缺少正式票务接口支持,因此让用户手填金额会降低流程顺畅度。 - -本期先用系统估算补齐申请金额: - -- 交通费用:按火车、飞机、轮船三类 mock 票价生成稳定估算。 -- 住宿与补助:前端申请预览继续调用现有差旅规则测算,复用住宿上限和补助标准。 -- 后端对话:当没有前端预览上下文时,用同口径的兜底估算生成金额,避免选择交通方式后继续追问金额。 - -## 目标与非目标 - -目标: - -- 申请预览不再要求用户手动填写预估费用。 -- 用户选择火车、飞机或轮船后,系统能生成交通费用估算。 -- 预估总费用 = mock 交通费 + 住宿标准小计 + 补助标准小计。 -- 预览、提交文本和后端对话统一展示“系统预估费用”。 -- 保留用户明确输入金额时的兼容能力,不破坏历史提交链路。 - -非目标: - -- 本期不接入真实机票、火车票、船票接口。 -- 本期不做票价实时波动、余票、舱等、席别、折扣和路线中转算法。 -- 本期不把 mock 估算作为最终报销金额,报销阶段仍应结合真实票据复核。 - -## 用户与场景 - -主要用户: - -- 员工:在“申请/事前审批”环节快速发起差旅费用申请。 -- 财务/审批人:查看申请金额是否由系统按标准测算生成。 - -典型场景: - -1. 用户输入“去上海出差 3 天,火车”。 -2. 系统识别地点、天数、出行方式。 -3. 系统 mock 生成火车往返票价。 -4. 系统调用现有差旅测算拿到住宿与补助小计。 -5. 系统在申请预览中展示系统预估费用,并允许进入确认提交。 - -## 功能能力 - -输入: - -- 地点:用于差旅规则匹配和交通 mock 城市层级判断。 -- 天数:用于住宿与补助小计。 -- 出行方式:火车、飞机、轮船。 -- 职级:沿用现有差旅测算接口的标准匹配入参。 - -输出: - -- 交通费用口径:说明当前是 mock 票价估算,报销阶段按真实票据复核。 -- 规则测算参考:展示交通、住宿、补助拆分与合计。 -- 系统预估费用:写入申请金额字段,用于后续申请提交。 -- 估算来源字段:记录 mock 交通估算和规则测算结果,便于后续审计解释。 - -边界: - -- 缺少地点或天数时,仍不能完成住宿与补助测算,需要继续补齐基础字段。 -- 缺少出行方式时,仍需用户选择火车、飞机或轮船。 -- 后端纯对话流程没有前端规则测算结果时,使用保守的 mock 住宿/补助兜底。 - -## 方案设计 - -前端: - -- 新增申请估算工具模块,集中维护交通 mock 票价、金额格式化和总额合成。 -- `expenseApplicationPreview` 在差旅规则测算返回后,将交通 mock 金额叠加到住宿与补助小计。 -- 将 `amount` 字段改为“系统预估费用”,并设为非手动必填字段。 -- 申请提交文本使用系统生成的金额。 - -后端: - -- 新增申请系统预估服务模块,避免继续向已经超过 800 行的 `user_agent_application.py` 堆业务算法。 -- 后端对话在基础字段和出行方式齐全时自动补 `amount`、`transport_policy`、`policy_estimate`。 -- 缺失字段追问只保留基础字段和出行方式,不再追问预估金额。 - -数据与接口: - -- 不新增数据库字段。 -- 不新增外部接口。 -- 申请详情仍通过现有 `risk_flags_json.application_detail` 保存展示字段。 - -## 算法与公式 - -交通费用采用稳定 mock: - -$$ -transport\_amount = round\_10(base(mode, location) \times 2) -$$ - -其中 `mode` 为火车、飞机、轮船,`location` 用于判断一线/远途/沿海等粗粒度场景,默认按往返估算。 - -总费用: - -$$ -estimated\_total = transport\_amount + lodging\_amount + allowance\_amount -$$ - -前端的 `lodging_amount` 和 `allowance_amount` 来自现有差旅规则测算结果;后端兜底时按 mock 标准生成。 - -## 测试方案 - -- 前端单测:验证交通 mock、规则测算合计、行标签和提交文本。 -- 后端单测:验证选择交通方式后不再追问金额,而是直接生成预览。 -- 编排流测试:验证申请会话从补充出行方式直接进入确认,再提交成功。 -- 回归测试:用户明确输入金额时仍能提交,并保留兼容链路。 - -## 指标与验收 - -- 用户选择出行方式后,系统不再提示“用户预估费用”缺失。 -- 申请预览中出现“系统预估费用”。 -- 规则测算参考包含交通、住宿、补助三项拆分。 -- 前端定向测试和后端申请流程测试通过。 - -## 风险与开放问题 - -- mock 票价不代表真实票价,只适合作为申请阶段预算参考。 -- 后端兜底住宿/补助不能完全替代规则中心,前端有规则测算结果时应优先使用规则中心。 -- 后续接入真实票务接口后,应替换交通 mock 模块,不改变申请预览和提交的数据契约。 diff --git a/document/development/申请交通费用自动预估/TODO.md b/document/development/申请交通费用自动预估/TODO.md deleted file mode 100644 index 1181702..0000000 --- a/document/development/申请交通费用自动预估/TODO.md +++ /dev/null @@ -1,34 +0,0 @@ -# 申请交通费用自动预估开发 TODO - -## 调研与契约 - -- [x] 确认申请预览当前金额字段仍为用户手填。证据:`expenseApplicationPreview.js` 中 `amount` 标签为“用户预估费用”。 -- [x] 确认住宿与补助已有规则测算入口。证据:前端申请预览调用 `calculateTravelReimbursement` 并读取 `hotel_amount`、`allowance_amount`。 -- [x] 确认后端对话仍追问金额。证据:`user_agent_application.py` 的缺失字段包含 `amount`。 - -## 算法 - -- [x] 新增前端申请估算工具模块,提供火车、飞机、轮船 mock 交通费。证据:`expenseApplicationEstimate.js`。 -- [x] 将前端规则测算结果合成为交通 + 住宿 + 补助总额。证据:`expenseApplicationPreview.js` 的规则测算合成逻辑和前端定向测试。 -- [x] 新增后端申请估算工具模块,提供无前端上下文时的兜底估算。证据:`application_system_estimate.py`。 - -## 前端 - -- [x] 将申请预览金额标签改为“系统预估费用”。证据:`expenseApplicationPreview.js` 字段定义。 -- [x] 将 `amount` 改为系统估算字段,不再作为用户必填项阻塞。证据:`amount` 字段 `required: false` 且 `editable: false`。 -- [x] 更新交通费用口径文案,明确是模拟票价估算。证据:`buildTransportPolicyText` 输出模拟票价口径。 -- [x] 在规则测算成功后写入系统预估总费用。证据:前端测试 `application preview merges rule center travel estimate into highlighted rows`。 - -## 后端 - -- [x] 选择出行方式后自动生成系统预估费用。证据:后端测试 `test_user_agent_application_builds_system_estimate_after_transport_choice`。 -- [x] 缺失字段追问不再包含 `amount`。证据:后端申请流程定向测试。 -- [x] 后端预览和提交摘要统一展示“系统预估费用”。证据:`user_agent_application.py` 摘要表字段。 - -## 测试与验证 - -- [x] 更新前端申请预览定向测试。证据:`expense-application-fast-preview.test.mjs`。 -- [x] 更新后端用户 Agent 申请流程测试。证据:`test_user_agent_service.py`。 -- [x] 更新编排流申请提交测试。证据:`test_orchestrator_review_flow.py`。 -- [x] 运行前端定向测试,记录结果。证据:`node --test web/tests/expense-application-fast-preview.test.mjs`,14 passed。 -- [x] 在 `x-financial-main` 容器内运行后端定向测试,记录结果。证据:申请相关 7 个 UserAgent 用例通过、2 个 Orchestrator 用例通过;整包定向存在无关查询动作测试失败。 diff --git a/document/development/申请单关联归档状态/CONCEPT.md b/document/development/申请单关联归档状态/CONCEPT.md deleted file mode 100644 index 845b8c5..0000000 --- a/document/development/申请单关联归档状态/CONCEPT.md +++ /dev/null @@ -1,88 +0,0 @@ -# 申请单关联归档状态概念文档 - -## 功能一句话 - -申请单审批完成后先进入关联单据状态,只有关联的报销单完成付款归档后,申请单才同步归档。 - -## 背景与问题 - -当前费用申请单审批完成后,部分列表和进度展示会把申请单视为归档;但业务上申请单只是完成了事前审批,还需要等待后续报销单关联、报销审批、付款完成后,申请单生命周期才真正闭环。 - -这会导致用户看到报销单仍在处理、申请单却已归档,或者报销单已完成但申请单还停留在进行中的割裂状态。 - -## 目标 - -1. 申请单审批完成不直接进入归档中心。 -2. 申请单进度在归档前增加“关联单据状态”节点。 -3. 已有关联报销单但未付款完成时,该节点显示“关联中”。 -4. 没有关联报销单时,该节点显示“未关联”。 -5. 关联报销单付款完成后,申请单同步进入“申请归档”。 - -## 非目标 - -1. 不新增数据库表。 -2. 不改变报销单本身的审批、付款权限。 -3. 不改变申请单审批通过自动生成报销草稿的现有能力。 - -## 用户与场景 - -涉及角色: - -- 申请人:查看申请单是否已经关联后续报销单。 -- 审批人:审批申请单后不再误以为该申请已经归档。 -- 财务人员:付款完成报销单时,同步闭环关联申请单。 - -关键场景: - -1. 申请单审批通过,但未生成或未关联报销单:显示“关联单据状态 / 未关联”。 -2. 申请单审批通过,并已生成报销草稿或报销单仍在流程中:显示“关联单据状态 / 关联中”。 -3. 关联报销单已付款:报销单进入已付款,申请单进入“申请归档”。 - -## 方案设计 - -后端: - -- 申请单 `approved + 审批完成` 不再被归档查询命中。 -- 申请单只有 `approved + 申请归档` 才属于归档。 -- 报销单付款完成时,从 `application_handoff` 或 `application_link` 风险事件中读取关联申请单。 -- 找到关联申请单后,追加同步归档事件,并将申请单阶段置为“申请归档”。 - -前端: - -- 申请单进度增加“关联单据状态”和“已归档”节点。 -- 审批完成但未归档的申请单,当前节点停留在“关联单据状态”。 -- 根据申请单自身的 `generated_draft_claim_no` 或报销单侧关联事件显示“关联中 / 未关联”。 -- 只有“申请归档”阶段才展示归档完成。 - -## 算法与公式 - -当前功能不涉及显式数学公式。 - -关联状态判断: - -```text -has_linked_reimbursement = exists(application.generated_draft_claim_no) - or exists(reimbursement.risk_flags.application_claim_id/no == application.id/no) - -application_archived = application.status in {approved, completed} - and application.approval_stage == "申请归档" -``` - -## 测试方案 - -1. 后端状态测试:审批完成申请单不归档,申请归档才归档。 -2. 后端付款测试:关联报销单付款后,申请单同步进入“申请归档”。 -3. 前端进度测试:审批完成申请单显示“关联单据状态”和“已归档”。 -4. 前端归档判断测试:`审批完成` 申请单不算归档,`申请归档` 才算归档。 - -## 验收标准 - -1. 单据中心普通视图仍能看到审批完成但未归档的申请单。 -2. 归档中心不会提前出现仅审批完成的申请单。 -3. 申请单进度在审批完成后能看到“关联单据状态”。 -4. 报销单付款完成后,关联申请单同步显示为归档。 - -## 风险与开放问题 - -- 旧数据中可能存在已经把申请单审批完成当作归档的数据,本次按新业务规则修正展示与查询口径。 -- 如果历史申请单缺少关联报销事件,只能展示“未关联”,不做自动猜测。 diff --git a/document/development/申请单关联归档状态/TODO.md b/document/development/申请单关联归档状态/TODO.md deleted file mode 100644 index aa3d72f..0000000 --- a/document/development/申请单关联归档状态/TODO.md +++ /dev/null @@ -1,8 +0,0 @@ -# 申请单关联归档状态开发 TODO - -- [x] 梳理申请单审批完成、报销单关联、报销单付款、归档查询的现有链路。[CONCEPT: 背景与问题] 证据:已确认 `expense_claim_status_registry.py`、`expense_claim_access_policy.py`、`expense_claim_approval_flow.py`、`useRequests.js` 的当前行为。 -- [x] 调整后端归档查询口径:申请单 `审批完成` 不再视为归档,仅 `申请归档` 才归档。[CONCEPT: 方案设计] 证据:`ExpenseClaimAccessPolicy.build_archived_claim_condition()` 仅将 `APPLICATION_ARCHIVE_STAGE` 视为申请归档。 -- [x] 调整报销单付款完成逻辑:根据关联事件同步推进申请单到 `申请归档`。[CONCEPT: 方案设计] 证据:`mark_claim_paid()` 调用 `_archive_linked_applications_after_reimbursement_paid()`,新增付款同步测试通过。 -- [x] 调整前端申请单进度:增加 `关联单据状态` 与 `已归档` 节点,并显示 `关联中/未关联`。[CONCEPT: 方案设计] 证据:`useRequests.js` 新增申请单进度节点和关联状态计算。 -- [x] 补充前后端回归测试,覆盖未关联、关联中、已归档三类申请单状态。[CONCEPT: 测试方案] 证据:`requestProgressSteps.test.mjs`、`document-center-archived-scope.test.mjs`、`expense-claim-archive.test.mjs`、`test_expense_claim_service.py` 已覆盖。 -- [x] 在容器或前端定向测试中完成验证,并记录命令结果。[CONCEPT: 验收标准] 证据:前端 Node 定向测试、容器内 py_compile、状态/路由/归档/付款同步 pytest、`npm.cmd --prefix web run build` 均通过。 diff --git a/document/development/移动端适配/CONCEPT.md b/document/development/移动端适配/CONCEPT.md deleted file mode 100644 index de25f22..0000000 --- a/document/development/移动端适配/CONCEPT.md +++ /dev/null @@ -1,137 +0,0 @@ -# 移动端适配概念文档 - -## 功能一句话 - -让手机浏览器打开 X-Financial Web 时具备可导航、可对话、控件完整可点的移动端体验。 - -## 背景与问题 - -本轮目标是 Web 在手机浏览器中的适配,不是 `mobile/app` 原生应用。 - -当前 Web 已经有部分移动端样式,例如侧边栏抽屉、移动遮罩和报销助手工作台的弹层基础样式,但仍有两个直接影响手机使用的问题: - -- 应用壳层已有 `mobileSidebarOpen` 状态和 `.mobile-hamburger-btn` 样式,却缺少真正可见的手机导航按钮。 -- 报销智能体使用 Element Plus `el-dialog` 打开全屏工作台,但手机宽度下仍保留弹窗式留边和双栏工作台逻辑,底部输入区把附件、日期、计算器、输入框和发送按钮挤在一行,容易展示不全。 - -## 目标与非目标 - -### 目标 - -- 手机浏览器下提供明确的 Web 导航入口。 -- 智能体对话在手机视口下以全屏工作台呈现,不保留弹窗留边。 -- 对话主区、洞察侧栏、底部输入区在手机上不互相挤压。 -- 附件、日期、差旅计算器和发送控件在窄屏下完整展示。 -- 侧栏洞察在手机上转为覆盖式面板,不占用主对话宽度。 -- 保持 X-Financial 企业 SaaS 风格:白底、细边框、低饱和、直角控件。 - -### 非目标 - -- 本轮不改 `mobile/app` 原生应用。 -- 本轮不重写所有 Web 业务页面为移动端卡片流。 -- 本轮不调整后端接口、数据库和智能体业务协议。 -- 本轮不改变报销助手的会话、附件、日期和差旅计算器业务逻辑。 - -## 用户与场景 - -- 员工、财务或审批人员在手机浏览器中临时打开 Web 工作台。 -- 用户通过侧边栏进入单据、预算、票据夹或智能体助手。 -- 用户在报销智能体中上传附件、选择业务日期、打开差旅计算器并发送问题。 - -## 功能能力 - -### 手机导航入口 - -输入: - -- 手机浏览器打开 Web。 -- 视口宽度小于等于 `760px`。 - -输出: - -- 页面右上角显示移动端导航按钮。 -- 点击按钮打开侧边栏抽屉。 -- 点击遮罩或导航项关闭侧边栏。 - -### 智能体全屏工作台 - -输入: - -- 用户从工作台、单据、票据夹或预算中心打开报销智能体。 -- 当前视口为手机宽度。 - -输出: - -- `el-dialog` 使用 100dvh 全屏,占满手机浏览器可视区域。 -- 工作台不再保留外边距和圆角弹窗感。 -- 对话主面板独占宽度。 -- 右侧洞察面板在打开时覆盖主对话,不挤压主对话宽度。 - -### 底部输入控件 - -输入: - -- 用户添加附件、选择日期、打开差旅计算器或输入文本。 - -输出: - -- 工具按钮在手机上独占一行,固定三列展示。 -- 输入框和发送按钮在下一行展示。 -- 日期与差旅计算器浮层改为固定底部浮层,宽度适配手机视口。 -- 附件区域可滚动,避免把输入区挤出屏幕。 - -## 方案设计 - -### Web 壳层 - -- 在 `AppShellRouteView.vue` 增加 `.mobile-hamburger-btn` 模板节点。 -- 复用现有 `mobileSidebarOpen` 状态和遮罩关闭逻辑。 -- 在 `app.css` 中补齐按钮默认隐藏,手机媒体查询内显示。 - -### 报销智能体 - -- 保持 `TravelReimbursementCreateView.vue` 的业务结构不变。 -- 在 `travel-reimbursement-create-view-part4.css` 的手机断点中覆盖 Element Plus 弹层、工作台、布局和输入区样式。 -- 手机断点下: - - overlay padding 设为 `0`。 - - 工作台 `height/min-height` 使用 `100dvh`。 - - `assistant-layout` 改为单列。 - - `insight-panel-shell` 改为绝对定位覆盖面板。 - - `composer-row` 改为两行网格布局。 - -## 算法与公式 - -当前功能不涉及显式数学公式。 - -核心断点规则: - -```css -@media (max-width: 760px) { - /* phone browser layout */ -} -``` - -## 测试方案 - -- 静态回归测试:`node --test web/tests/app-shell-mobile-browser.test.mjs`。 -- Web 构建:`npm.cmd --prefix web run build`。 -- 手机视口浏览器验证: - - 以 390x844 或相近视口打开 Web。 - - 验证导航按钮可见且侧栏可打开。 - - 打开报销智能体,验证工作台占满手机视口。 - - 验证底部附件、日期、差旅计算器、输入框和发送按钮完整展示。 - - 打开洞察面板,验证其覆盖展示而不是挤压主对话。 - -## 指标与验收 - -- `mobile/app` 无本轮改动。 -- 手机浏览器下 Web 存在可点击导航入口。 -- 报销智能体不再呈现带留边的弹窗效果。 -- 底部输入工具控件不被挤出屏幕。 -- 定向静态测试通过。 -- Web 构建通过。 - -## 风险与开放问题 - -- 其他业务页面仍可能存在表格密度过高的问题,需要按页面继续做字段折叠或卡片化。 -- 一些二级确认弹窗、票据预览和日期控件需要后续逐页检查。 -- 手机浏览器地址栏收起/展开会改变视口高度,后续应继续用真实设备补充验证。 diff --git a/document/development/移动端适配/TODO.md b/document/development/移动端适配/TODO.md deleted file mode 100644 index 280e060..0000000 --- a/document/development/移动端适配/TODO.md +++ /dev/null @@ -1,27 +0,0 @@ -# 移动端适配 TODO - -## 调研与边界 - -- [x] 确认本轮范围是手机浏览器打开 Web,不是 `mobile/app` 原生应用。证据:`CONCEPT.md` 已明确目标与非目标。[CONCEPT: 目标与非目标] -- [x] 梳理 Web 应用壳层移动端状态。证据:`AppShellRouteView.vue` 已有 `mobileSidebarOpen` 和遮罩,但缺少按钮节点。[CONCEPT: 手机导航入口] -- [x] 梳理报销智能体弹层结构。证据:`TravelReimbursementCreateView.vue` 使用 `el-dialog`、`assistant-layout`、`composer-row` 和洞察侧栏。[CONCEPT: 背景与问题] - -## Web 实现 - -- [x] 在 Web 壳层补充手机导航按钮。证据:`AppShellRouteView.vue` 新增 `.mobile-hamburger-btn`,点击打开 `mobileSidebarOpen`。[CONCEPT: Web 壳层] -- [x] 补齐手机导航按钮默认隐藏与手机断点显示。证据:`app.css` 新增默认隐藏,`760px` 断点内显示按钮。[CONCEPT: Web 壳层] -- [x] 将报销智能体手机视口改为真正全屏。证据:`travel-reimbursement-create-view-part4.css` 覆盖 overlay padding、dialog 圆角和工作台 `100dvh`。[CONCEPT: 智能体全屏工作台] -- [x] 将手机端洞察侧栏改为覆盖式面板。证据:`insight-panel-shell` 在手机断点下使用绝对定位和 `translateX` 切换。[CONCEPT: 智能体全屏工作台] -- [x] 重排手机端底部输入区。证据:`composer-row` 改为两行网格,工具按钮独占一行,输入框和发送按钮在下一行。[CONCEPT: 底部输入控件] -- [x] 调整日期和差旅计算器浮层。证据:手机断点下浮层使用固定底部定位并限制最大高度。[CONCEPT: 底部输入控件] - -## 测试与验证 - -- [x] 运行 `node --test web/tests/app-shell-mobile-browser.test.mjs`。证据:2 个测试通过。[CONCEPT: 测试方案] -- [x] 运行 `npm.cmd --prefix web run build`。证据:构建通过,保留既有 VueUse 注释和 chunk 体积 warning。[CONCEPT: 测试方案] -- [ ] 使用手机视口打开 Web,验证导航、智能体全屏、底部控件完整展示和洞察覆盖面板。[CONCEPT: 测试方案] - -## 后续增强 - -- [ ] 继续盘点高频表格页面的手机浏览器阅读体验。[CONCEPT: 风险与开放问题] -- [ ] 逐页检查二级确认弹窗、票据预览、日期选择和复杂筛选在手机浏览器里的表现。[CONCEPT: 风险与开放问题] diff --git a/document/development/自我进化学习闭环/CONCEPT.md b/document/development/自我进化学习闭环/CONCEPT.md deleted file mode 100644 index 970d2f7..0000000 --- a/document/development/自我进化学习闭环/CONCEPT.md +++ /dev/null @@ -1,490 +0,0 @@ -# X-Financial 自我进化学习闭环方案 - -更新日期:2026-06-23 - -## 功能一句话 - -把 X-Financial 从“规则 + 图谱 + Agent 的智能费控系统”升级为“可持续学习的费控智能体平台”:先通过反馈、回放和影子运行让分析能力变强,再把稳定结论沉淀为可审核、可测试、可回滚的规则、参数和知识资产。 - -## 背景与问题 - -当前系统已经具备费用申请、报销、审批、规则中心、知识库、小财管家、数字员工、风险观察、员工画像和财务行为图谱。现有能力已经不是单一算法,而是由多类算法共同形成判断: - -- 规则引擎负责执行已上线的制度口径和风险 DSL。 -- 风控图谱负责识别重复票据、拆单、高频、跨部门聚集、同组偏离等风险信号。 -- 员工画像和申请人画像负责建立同组基线、流程质量和历史行为特征。 -- 知识库负责制度检索、引用和政策解释。 -- Agent 编排负责意图识别、流程确认、工具调用和可视化交互。 - -但如果这些模块只各自运行,系统仍然只是“更自动化的费控工具”。要变成自我进化系统,必须解决几个核心问题: - -- 每次命中风险后,系统是否知道人工最终确认、驳回、误报还是漏报。 -- 新规则、新阈值、新权重上线前,是否能用历史样本回放验证。 -- 系统是否能从反复出现的人工反馈中形成候选规则或候选参数。 -- 知识库制度变更后,是否能定位受影响的规则、流程和问答。 -- Agent 回答错误或流程误判后,是否能沉淀为可复盘样本,而不是只改一处文案。 - -因此,自我进化不是让大模型直接改生产代码或发布规则,而是建立一条受控学习链路: - -```text -运行数据 - -> 人工反馈 / 审批结果 / 用户纠错 - -> 标签样本与回放集 - -> 分析能力校准 - -> 候选规则 / 候选参数 / 候选知识修订 - -> 影子运行与历史回放 - -> 人审发布 - -> 上线后持续监控 -``` - -## 核心判断 - -学习闭环同时让两类能力变强,但顺序不同。 - -第一层是分析变强。 - -分析变强指系统越来越知道: - -- 哪些风险信号真的值得阻断。 -- 哪些风险只适合提醒或补充说明。 -- 哪些规则在某些部门、费用类型、职级或场景下误报率高。 -- 哪些历史相似单据最终被退回、确认或通过。 -- 哪些同组基线更适合当前单据,而不是简单使用全局均值。 - -这一层优先影响风险分、置信度、推荐动作、抽检策略、自动化模式和解释质量。 - -第二层是规则变强。 - -规则变强指当某类分析结论被足够多的反馈和回放证明稳定后,再沉淀为正式规则、规则修订、例外条件或阈值配置。规则变强必须经过测试和审核,不能由模型直接上线。 - -推荐顺序是: - -```text -分析先学习 - -> 形成候选结论 - -> 回放证明有效 - -> 人审沉淀为规则或参数 - -> 规则上线后继续接受反馈 -``` - -这样可以避免系统过早把偶然反馈固化为生产规则。 - -## 目标与非目标 - -### 目标 - -- 建立统一的学习闭环总纲,串联风险观察、规则反馈、Agent 反馈、审批结果、回放评测和规则中心。 -- 明确“分析进化”和“规则进化”的边界。 -- 让风险分、置信度、推荐动作、抽检策略和自动化模式具备反馈校准依据。 -- 让候选规则、候选参数和候选知识修订进入待审核流程,而不是自动生效。 -- 通过历史回放、影子运行和灰度发布降低自我进化风险。 -- 为后续实现算法评估中心、反馈样本池和候选规则工厂提供架构依据。 - -### 非目标 - -- 不让大模型直接修改生产规则、生产数据或核心代码。 -- 不让系统绕过财务、风控或管理员审核自动发布规则。 -- 不把员工画像作为惩罚标签;画像只服务于风险解释、排序和复核辅助。 -- 不把所有学习结果都固化为规则;低置信反馈只进入分析校准和样本池。 -- 不在第一阶段引入复杂机器学习训练平台,优先把样本、标签、回放和门控做稳。 - -## 现有基础 - -### 风控图谱 - -`evaluate_financial_risk_graph()` 已经把单据、员工、部门、费用类型、地点、票据和本体解析合成风险图谱,并输出贡献分、证据、风险等级、置信度、采样策略和决策 trace。 - -当前贡献分包括: - -- `S_rule`:规则信号。 -- `S_anomaly`:同组金额异常。 -- `S_graph`:图谱异常。 -- `S_policy`:制度关联。 -- `S_history`:历史反馈。 - -这说明系统已经具备“分析可解释”和“反馈可进入评分”的基础。 - -### 规则中心 - -风险规则已经支持自然语言生成 JSON 风险规则、DSL 校验、风险评分、样例测试、真实场景试运行、测试报告确认、审核发布、反馈记录和修订版本。 - -这说明系统已经具备“规则可生成、可测试、可审核、可发布”的基础。 - -### 风险观察反馈池 - -`RiskObservation` 和 `RiskObservationFeedback` 已经能记录风险观察、反馈状态、反馈历史、算法版本和证据数据。 - -这说明系统已经有学习闭环的核心样本载体。 - -### 回放评测雏形 - -`AlgorithmReplayCase` 和 `AlgorithmReplaySet` 已经定义了历史单据、本体版本、规则版本、算法版本和反馈标签的回放契约。 - -这说明系统已经具备把历史风险观察转为评测样本的基础。 - -### 数字员工 - -数字员工已有风险图谱巡检、员工画像扫描、反馈样本积累、算法回放评估等任务概念。 - -这说明后台定时分析能力可以成为学习闭环的执行入口。 - -## 学习对象分层 - -### L1. 交互与意图学习 - -学习对象: - -- 用户是否选择了正确流程。 -- 小财管家是否误判申请 / 报销。 -- 直接提交、保存草稿、附件关联、关联申请单等动作是否被用户纠正。 - -可进化内容: - -- 意图识别提示词。 -- 澄清问题策略。 -- 流程确认门控。 -- 推荐动作排序。 -- 前端快捷动作默认项。 - -禁止直接进化内容: - -- 不根据单次对话自动修改规则中心。 -- 不把用户一句话纠错直接变成生产规则。 - -### L2. 风险分析学习 - -学习对象: - -- 风险观察是否被人工确认。 -- 命中后是否被退回、补件、通过、忽略。 -- 哪些风险信号误报率高。 -- 哪些风险在相似场景下总是漏报。 - -可进化内容: - -- 风险分权重。 -- 置信度计算。 -- 自动化模式门槛。 -- 抽检和回放采样策略。 -- 同组基线选择策略。 -- 风险解释优先级。 - -禁止直接进化内容: - -- 不让系统自动把高风险改成阻断。 -- 不让模型直接替代人工确认违规。 - -### L3. 规则学习 - -学习对象: - -- 多次确认的风险观察。 -- 反复出现的漏判反馈。 -- 规则测试中的真实场景命中差异。 -- 制度变更引起的规则失配。 - -可进化内容: - -- 候选规则。 -- 规则修订草稿。 -- 例外条件。 -- 阈值建议。 -- 规则适用范围。 - -必须经过: - -- 样例测试。 -- 真实场景试运行。 -- 回放评测。 -- 人工审核。 -- 灰度或发布确认。 - -### L4. 知识学习 - -学习对象: - -- 知识库问答命中错误。 -- 制度引用缺口。 -- 规则和制度条款不一致。 -- 用户追问中反复出现的政策盲点。 - -可进化内容: - -- 知识文档结构化摘要。 -- 制度条款引用。 -- 问答检索关键词。 -- 规则与制度条款绑定。 - -禁止直接进化内容: - -- 不让模型编造制度。 -- 不让模型用未审核知识覆盖正式制度。 - -## 闭环架构 - -### 1. 事件采集层 - -统一采集以下事件: - -- 风险观察生成。 -- 规则命中和未命中。 -- 审批通过、退回、驳回、补件。 -- 风控人员反馈确认、误报、漏报、不清楚。 -- 用户对 Agent 回答的低分反馈。 -- 规则测试、试运行和发布结果。 -- 知识库检索命中和无结果。 - -每个事件都应绑定: - -- 业务对象:申请单、报销单、票据、员工、部门、规则。 -- 版本信息:算法版本、规则版本、本体版本、知识版本。 -- 执行上下文:run_id、conversation_id、task_id。 -- 处理结果:人工动作、审批状态、反馈标签。 - -### 2. 标签与样本层 - -将原始事件转为标准标签: - -- `confirmed`:风险被确认。 -- `false_positive`:误报。 -- `false_negative`:漏报。 -- `unclear`:证据不足。 -- `over_blocked`:阻断过度。 -- `manual_override`:人工覆盖系统建议。 -- `policy_changed`:制度变化导致旧判断失效。 - -同时形成三类样本池: - -- 分析校准样本:用于调整风险分、置信度和推荐动作。 -- 回放评测样本:用于新算法、新规则、新权重上线前验证。 -- 规则候选样本:用于生成或修订规则草稿。 - -### 3. 离线评估层 - -定期对候选算法、候选规则、候选参数运行回放。 - -关键指标: - -- 确认率:命中后被人工确认的比例。 -- 误报率:命中后被标记误报的比例。 -- 漏报率:人工发现风险但系统未命中的比例。 -- 阻断准确率:阻断动作最终被确认合理的比例。 -- 人工负担:进入人工复核的单据比例。 -- 解释完整率:风险观察是否包含规则、证据、基线和相似案例。 -- 数据质量通过率:字段完整性、票据 OCR、申请关联等基础数据质量。 - -### 4. 候选生成层 - -系统只能生成候选,不直接生效。 - -候选类型: - -- 候选规则:来自反复确认的风险观察或漏判样本。 -- 候选规则修订:来自误报较高的规则反馈。 -- 候选参数:来自权重、阈值、置信度、自动化门槛的评估结果。 -- 候选知识修订:来自制度引用缺口或知识问答低分反馈。 - -每个候选必须包含: - -- 来源样本。 -- 触发原因。 -- 预期改善指标。 -- 可能副作用。 -- 回放结果。 -- 推荐发布方式。 - -### 5. 发布门控层 - -发布顺序: - -```text -候选 - -> 样例测试 - -> 历史回放 - -> 影子运行 - -> 人工审核 - -> 灰度启用 - -> 全量发布 - -> 上线后监控 -``` - -影子运行期间,新规则或新参数只记录“如果启用会发生什么”,不影响真实审批。 - -灰度启用期间,只对指定部门、费用类型或测试公司生效。 - -全量发布后,必须持续监控误报、漏报、阻断和人工覆盖。 - -## 数据与版本要求 - -每条学习样本至少保留: - -- `sample_id` -- `sample_type` -- `subject_type` -- `subject_id` -- `business_stage` -- `risk_signal` -- `rule_code` -- `algorithm_version` -- `rule_version` -- `ontology_version` -- `knowledge_version` -- `input_snapshot` -- `decision_trace` -- `expected_label` -- `actual_label` -- `feedback_source` -- `feedback_actor` -- `created_at` - -每次算法或规则评估至少保留: - -- `evaluation_id` -- `candidate_type` -- `candidate_version` -- `baseline_version` -- `replay_set_id` -- `sample_count` -- `metrics_before` -- `metrics_after` -- `regression_cases` -- `approval_status` - -## 推荐实施路径 - -### 第一阶段:补齐评估地基 - -目标是让系统知道自己判断得好不好。 - -- 统一风险观察反馈标签。 -- 把审批结果、退回原因、补件动作写入风险样本池。 -- 将 Agent 低分反馈归因到意图识别、流程路由、知识问答、规则解释、附件处理等类别。 -- 建立回放集生成任务,把风险观察和反馈状态转成评测样本。 -- 在数字员工工作记录中展示反馈样本摘要和回放评估摘要。 - -### 第二阶段:分析进化 - -目标是先让判断更稳。 - -- 将风险图谱权重、置信度门槛、自动化模式门槛迁移到版本化配置。 -- 基于反馈样本计算规则、风险信号、费用类型、部门维度的误报率和确认率。 -- 对高误报规则降低默认动作等级,对高确认规则提高抽检优先级。 -- 增强同组基线选择,优先使用部门、职级、费用类型、供应商等可解释维度。 -- 引入影子参数评估,只记录差异,不直接影响生产。 - -### 第三阶段:规则进化 - -目标是把稳定结论沉淀为规则资产。 - -- 从 confirmed 和 false_negative 样本中生成候选规则。 -- 从 false_positive 样本中生成候选例外条件或适用范围收缩建议。 -- 候选规则自动进入规则中心草稿,不自动发布。 -- 草稿必须完成样例测试、真实场景试运行和测试报告确认。 -- 已上线规则只能通过修订版本替换。 - -### 第四阶段:知识进化 - -目标是让制度、规则和问答保持一致。 - -- 对知识库无结果、低分反馈和制度引用缺口做聚类。 -- 自动生成知识修订建议或制度引用补充建议。 -- 标记受影响规则和问答范围。 -- 由制度管理员确认后再更新知识库或规则引用。 - -### 第五阶段:灰度自进化 - -目标是在受控范围内逐步提高自动化程度。 - -- 为低风险、高置信、高证据完整度场景开放自动提醒或自动补件建议。 -- 为高风险场景继续保持人工复核或阻断确认。 -- 每个自动化动作都必须可解释、可撤回、可追踪。 -- 自动化范围随反馈质量逐步扩大。 - -## 产品边界 - -自我进化系统里,人和系统的职责要明确。 - -系统负责: - -- 发现模式。 -- 聚合证据。 -- 生成候选。 -- 运行回放。 -- 计算指标。 -- 提醒风险。 -- 记录全链路证据。 - -人负责: - -- 确认制度口径。 -- 审核规则发布。 -- 判断复杂业务例外。 -- 决定阻断、退回或放行。 -- 对候选改进做最终确认。 - -大模型负责: - -- 语义理解。 -- 候选规则草稿。 -- 解释生成。 -- 知识摘要。 -- 反馈归因辅助。 - -大模型不负责: - -- 最终违规判定。 -- 自动发布规则。 -- 自动修改生产代码。 -- 绕过审核执行高风险动作。 - -## 验收指标 - -第一阶段验收: - -- 风险观察反馈、规则反馈、Agent 反馈能统一进入样本池。 -- 回放集能按算法版本、规则版本、本体版本构建。 -- 风险看板能展示确认率、误报率、反馈样本数和待回放样本数。 - -第二阶段验收: - -- 风险分、置信度和自动化动作的调整都有反馈证据。 -- 新参数可以影子运行并产生差异报告。 -- 高误报规则能被识别并生成修订建议。 - -第三阶段验收: - -- 系统能从反馈样本生成候选规则或候选修订。 -- 候选规则能进入规则中心草稿。 -- 候选规则必须通过测试报告确认后才允许发布。 - -第四阶段验收: - -- 知识问答低分反馈能定位到知识缺口。 -- 制度变更能提示受影响规则和问答范围。 -- 知识修订必须保留来源和审核记录。 - -## 风险与防护 - -- 反馈噪音:单次反馈不能直接改规则或参数,必须聚合后进入候选。 -- 误报固化:规则上线前必须跑历史回放和影子运行。 -- 模型幻觉:所有制度、规则和风险结论必须绑定来源证据。 -- 自动化越权:阻断、退回、发布规则等高风险动作必须人工确认。 -- 数据漂移:长期监控样本量、字段缺失率、费用分布和 OCR 质量。 -- 版本混乱:算法、规则、本体、知识和回放集必须带版本号。 - -## 与现有文档关系 - -- `document/development/hermes-risk-graph-algorithm/CONCEPT.md`:负责风险图谱算法和风险观察模型。 -- `document/development/risk-rule-explainable-flow/CONCEPT.md`:负责风险规则 DSL、解释、测试和发布流程。 -- `document/development/数字员工能力库扩展/CONCEPT.md`:负责数字员工技能边界和后台分析任务。 -- 本文档负责把上述能力串成“自我进化学习闭环”的总体路线。 - -## 结论 - -X-Financial 的自我进化应先让分析变强,再让规则变强。 - -分析变强是低风险、高收益的第一步:它通过反馈、回放和影子运行持续校准风险分、置信度、动作建议和解释质量。 - -规则变强是第二步:只有当分析结论经过足够样本验证后,才沉淀为正式规则、规则修订或参数版本,并通过测试、人审和灰度发布进入生产。 - -最终目标不是“系统自己随便改规则”,而是形成一条可审计、可回放、可控发布的学习链路,让系统越用越懂企业自己的财务控制口径。 diff --git a/document/development/财务与风险看板卡片重组/CONCEPT.md b/document/development/财务与风险看板卡片重组/CONCEPT.md deleted file mode 100644 index 491d071..0000000 --- a/document/development/财务与风险看板卡片重组/CONCEPT.md +++ /dev/null @@ -1,115 +0,0 @@ -# 财务与风险看板卡片重组 - -## 功能一句话 - -将财务看板的预算执行率合并进预算指标卡片,并重组风险看板尾部卡片,让异常排行和风险占比成为主要分析信息。 - -## 背景与问题 - -当前分析看板存在两个体验问题: - -- 财务看板底部同时有“预算指标”和“预算执行率(本月)”两个预算卡片,信息相近但占用两块空间。 -- 风险看板中“算法闭环效果”和“近期高风险观察”对当前看板判断价值较低;“来源分布”展示 `unknown` 时会让用户误以为数据异常,实际用户想看每类风险占比。 - -## 目标与非目标 - -目标: - -- 将预算执行率仪表图整合进“预算指标”卡片,取消单独的预算执行率卡片,并把整合后的预算指标卡放在“高额单据”右侧空白位。 -- 风险看板把“来源分布”改为“风险占比”,展示风险信号或风险类型占比。 -- 风险看板移除“算法闭环效果”和“近期高风险观察”卡片。 -- 异常排行重新设计为占满整张卡片的图表化内容,减少碎片列表感。 - -非目标: - -- 不改后端接口,不新增风险或预算接口。 -- 不改顶部 KPI 和风险趋势图数据口径。 -- 不引入新的图表库,继续复用现有 `DonutChart`、`BarChart` 和 `GaugeChart`。 - -## 用户与场景 - -用户: - -- 财务分析人员、风险复核人员、管理员。 - -场景: - -- 财务人员查看预算指标时,一眼看到预算执行率、预算总额、已用和剩余额度。 -- 风险人员查看风险看板时,优先看到风险类型占比和异常维度排行,而不是来源未知或低价值尾部卡片。 - -## 功能能力 - -财务看板: - -- “预算指标”卡片包含预算执行率仪表图和预算指标列表,桌面端与“高额单据”同处底部半宽行,避免预算信息独占新行造成留白。 -- `budgetSummary` 仍作为仪表图数据源。 -- `budgetMetrics` 仍作为指标列表数据源。 -- 单独 `budget-panel` 不再渲染。 - -风险看板: - -- “来源分布”改为“风险占比”,数据来自 `signalDistribution` 或 `topRiskSignals`。 -- 异常排行卡片横跨整行,主图表填满卡片,下面只保留紧凑排行明细。 -- 删除算法闭环效果和近期高风险观察两个卡片。 - -## 方案设计 - -前端: - -- `OverviewView.vue` - - 删除独立预算执行率卡片。 - - 在预算指标卡片内部增加 `GaugeChart` 区域,与指标列表左右布局。 - -- `overview-view.css` - - 调整 `budget-metrics-panel` 的布局宽度和内部栅格,桌面端占 6 栅格贴合“高额单据”右侧。 - - 新增预算整合布局样式,移动端自动单列。 - -- `useOverviewView.js` - - 将 `riskSourceLegend` 改为风险占比 legend,优先使用风险信号分布。 - -- `RiskObservationDashboard.vue` - - 风险占比卡片标题改为“风险占比”。 - - 异常排行卡片改为整行大卡。 - - 移除算法闭环效果和近期高风险观察模板与样式。 - -## 算法与公式 - -本次不改变后端算法,只改变前端展示。 - -风险占比: - -$$ -share_i = \frac{count_i}{\sum_{j=1}^{n} count_j} -$$ - -预算执行率沿用已有 `budgetSummary.ratio`: - -$$ -budgetUsageRate = \frac{usedBudget}{totalBudget} -$$ - -## 测试方案 - -- 前端源码测试: - - 财务看板不再渲染独立 `budget-panel`。 - - 预算指标卡片包含 `GaugeChart`。 - - 风险看板标题为“风险占比”,不再使用“来源分布”。 - - 风险看板不再渲染算法闭环效果和近期高风险观察。 - - 异常排行卡片使用整行样式和图表填充样式。 -- 构建验证: - - `node web/tests/risk-observation-dashboard.test.mjs` - - 如有财务看板测试则补充运行。 - - `npm.cmd --prefix web run build` - -## 指标与验收 - -- 财务看板底部不再多出单独“预算执行率(本月)”卡片。 -- 预算指标卡片内部能看到预算执行率和预算指标,并在桌面端填充“高额单据”右侧空白位。 -- 风险看板不再显示“算法闭环效果”和“近期高风险观察”。 -- 风险占比不再显示来源未知,而是展示具体风险占比。 -- 异常排行卡片占满整行,图表区域明显成为主内容。 - -## 风险与开放问题 - -- 当前工作区已有未提交改动,提交时必须只纳入本次相关文件。 -- 本次只改前端展示,如果后端风险信号为空,则仍需要显示“暂无数据”兜底。 diff --git a/document/development/财务与风险看板卡片重组/TODO.md b/document/development/财务与风险看板卡片重组/TODO.md deleted file mode 100644 index 44724e2..0000000 --- a/document/development/财务与风险看板卡片重组/TODO.md +++ /dev/null @@ -1,30 +0,0 @@ -# 财务与风险看板卡片重组 TODO - -## 调研 - -- [x] 盘点财务预算卡片和风险看板卡片现状。[CONCEPT: 背景与问题] 证据:已检查 `OverviewView.vue`、`overview-view.css`、`RiskObservationDashboard.vue`、`useOverviewView.js` 和风险看板测试。 - -## 契约 - -- [x] 确认本次不改后端接口,只调整前端展示和数据映射。[CONCEPT: 目标与非目标] 证据:现有 `budgetSummary`、`budgetMetrics`、`signalDistribution` 和 `topRiskSignals` 足够支撑改动。 - -## 前端 - -- [x] 将预算执行率整合到预算指标卡片,移除独立预算执行率卡片。[CONCEPT: 财务看板] 证据:`OverviewView.vue` 中预算指标卡片内新增 `GaugeChart`,并保留在“高额单据”右侧的底部栅格位置;独立 `budget-panel` 已移除。 -- [x] 将风险“来源分布”改成“风险占比”,使用风险信号分布数据。[CONCEPT: 风险看板] 证据:`riskCompositionLegend` 优先读取 `signalDistribution`,标题显示“风险占比”。 -- [x] 移除风险看板“算法闭环效果”和“近期高风险观察”卡片。[CONCEPT: 风险看板] 证据:模板、计算属性和样式中的 `risk-effect-*`、`risk-recent-*` 已删除。 -- [x] 重设异常排行卡片为整行大图表布局。[CONCEPT: 风险看板] 证据:`.risk-ranking-panel` 改为 `grid-column: span 12`,并新增 `risk-ranking-chart-block`。 - -## 测试 - -- [x] 更新风险看板源码测试。[CONCEPT: 测试方案] 证据:`risk-observation-dashboard.test.mjs` 覆盖删卡、异常排行图表化、风险映射中文化和顶部时间范围驱动。 -- [x] 补充或更新财务看板源码测试。[CONCEPT: 测试方案] 证据:新增 `finance-dashboard-budget-card.test.mjs`,校验预算指标卡位于高额单据之后且桌面端 `grid-column: span 6`。 -- [x] 运行定向前端测试。[CONCEPT: 测试方案] 证据:`node web/tests/risk-observation-dashboard.test.mjs`、`node web/tests/finance-dashboard-ranking.test.mjs`、`node web/tests/finance-dashboard-budget-card.test.mjs` 通过。 -- [x] 运行前端构建验证。[CONCEPT: 测试方案] 证据:`npm.cmd --prefix web run build` 通过,仅保留 Vite 大 chunk 与第三方 PURE 注释警告。 - -## 验收 - -- [x] 确认财务看板只有一个预算卡片且含预算执行率。[CONCEPT: 指标与验收] 证据:源码测试确认 `budget-metrics-panel` 包含 `GaugeChart`、没有旧 `budget-panel`,并在桌面端填充“高额单据”右侧空白位。 -- [x] 确认风险占比展示具体风险类型,不再展示来源未知。[CONCEPT: 指标与验收] 证据:源码测试确认使用 `riskCompositionLegend` 和 `signalDistribution`,并补充 `budget_pressure`、`missing_material`、`simulation` 中文映射。 -- [x] 确认风险看板尾部仅保留重设计后的异常排行核心信息。[CONCEPT: 指标与验收] 证据:源码测试确认 `risk-ranking-visual`、`rankingChartItems` 生效,且 `risk-effect-panel`、`risk-recent-panel` 不再渲染。 -- [x] 提交并推送本次改动,避免纳入无关脏工作区文件。[CONCEPT: 风险与开放问题] 证据:本次看板相关文件将随 `feat(dashboard): reorganize budget and risk cards` 提交并推送到当前分支。 diff --git a/document/development/财务看板口径重构与画像模拟/CONCEPT.md b/document/development/财务看板口径重构与画像模拟/CONCEPT.md deleted file mode 100644 index 7a35125..0000000 --- a/document/development/财务看板口径重构与画像模拟/CONCEPT.md +++ /dev/null @@ -1,167 +0,0 @@ -# 财务看板口径重构与画像模拟概念文档 - -## 功能一句话 - -把财务看板从“审批过程展示”调整为“财务费用经营分析”,并让半年模拟数据自然形成部门、预算、风险和员工画像。 - -## 背景与问题 - -当前财务看板存在三类偏差: - -- 费用结构里直接展示 `travel_application` 等技术枚举,业务用户无法理解,且申请类口径不应混入报销费用结构。 -- 风险异常分布缺少完整中文映射,`missing_material`、`budget_pressure` 等风险信号以英文或半翻译方式泄露到页面。 -- 趋势图和底部卡片仍围绕审批量、审批时长展开,不符合财务看板的核心诉求。 - -半年模拟数据也需要服务于看板分析,不能只堆单据。它必须能支撑多部门费用排行、预算消耗、风险分布和员工画像。 - -## 目标 - -- 费用结构只展示费用科目中文名称,申请类技术值不裸露。 -- 风险异常分布统一中文化,并覆盖预算压力、材料缺失、预算超支等常见信号。 -- 趋势图改为每日报销数量和每日报销金额。 -- “审批瓶颈”改为财务关注项,展示预算、待付款、材料待补、风险金额等财务指标。 -- 部门排行按费用金额统计,而不是只看待处理审批金额。 -- 模拟数据在写入后可生成员工行为画像快照,画像与报销单据、预算压力和风险观察一致。 - -## 非目标 - -- 不重做财务看板整体视觉框架。 -- 不新增一套独立画像算法。 -- 不修改生产环境数据;所有批量修复只作用于 `SIM2026`、`SIM-EXP-2026`、`SIM-BUD-2026` 等模拟前缀数据。 - -## 用户与场景 - -- 财务经理:查看半年费用趋势、部门费用结构、预算执行和风险异常。 -- 部门负责人:理解本部门费用消耗和预算压力。 -- 审批人:查看员工画像时,能看到基于半年模拟数据形成的费用和流程质量画像。 -- 系统演示人员:用 100 人规模的模拟数据演示端到端效果。 - -## 功能能力 - -### 费用结构 - -输入为当前时间范围内有效报销单。 - -输出为费用科目金额占比: - -- 排除草稿、退回、驳回、删除等非有效支出状态。 -- `travel_application` 等申请类值不直接展示;若历史数据仍存在,则归一为“差旅费”或从费用结构中排除申请类虚拟项。 -- 所有展示名称必须是中文。 - -### 风险异常分布 - -输入为风险观察和报销单风险标记。 - -输出为中文风险类型分布: - -- `missing_material`:材料不完整 -- `budget_pressure`:预算压力偏高 -- `budget_overrun`:预算超支 -- `duplicate_invoice`:重复发票 -- `split_billing`:拆分报销 -- `amount_outlier`:金额异常 - -未知枚举用“风险观察”兜底,不能把英文下划线文案直接展示给用户。 - -### 每日报销趋势 - -趋势图按天返回: - -- `claimCount`:每日有效报销单数量 -- `claimAmount`:每日有效报销金额 - -前端使用柱线组合图展示,左轴为单量,右轴为金额。 - -### 财务关注项 - -替代原“审批瓶颈”: - -- 预算超支:超支预算池数量和金额。 -- 预算预警:预算使用率接近上限的池数量。 -- 材料待补:材料不完整风险数量。 -- 风险金额:当前范围内风险单据金额。 -- 待付款:已审批待付款金额。 - -### 员工画像 - -模拟数据写入后触发现有 `EmployeeBehaviorProfileService`: - -- 生成 30、90、180 天画像快照。 -- 画像类型沿用费用支出、流程质量、AI 使用和审批行为。 -- 不伪造画像结果,只用模拟报销单、审批记录和风险数据驱动算法。 - -## 方案设计 - -### 后端 - -- 在 `FinanceDashboardService` 中新增费用类型与风险信号归一化方法。 -- 将 `_trend` 改为统计每日有效报销数量和金额,同时保留旧字段兼容前端灰度。 -- 将 `_department_ranking` 改为按有效费用金额统计。 -- 将 `_bottlenecks` 的返回语义改为财务关注项,字段名暂保留,降低接口破坏面。 -- 模拟数据脚本增加画像刷新入口,调用现有画像服务生成快照。 - -### 前端 - -- `TrendChart` 文案改为“报销单量”和“报销金额”。 -- `OverviewView` 标题改为: - - 报销数量与金额趋势 - - 部门报销排行(费用金额) - - 财务关注项 -- 底部列表继续复用现有紧凑卡片样式,不引入新视觉体系。 - -### 数据 - -- 部门分布按业务权重分配,避免只有市场部或技术部。 -- 近 10 日和本月窗口保证各核心部门都有可见费用。 -- 风险样本覆盖材料缺失、预算压力、重复发票、金额异常等类型。 -- 预算台账与报销单金额一致,能体现预警和超支。 - -## 算法与公式 - -费用金额: - -$$ -amount_d = \sum_{c \in C_d} claimAmount(c) -$$ - -其中 \(C_d\) 为某日有效状态报销单集合。 - -部门费用排行: - -$$ -deptSpend_i = \sum_{c \in C_i} claimAmount(c) -$$ - -预算使用率: - -$$ -usageRate = \frac{reservedAmount + consumedAmount}{totalAmount} \times 100\% -$$ - -风险金额: - -$$ -riskAmount = \sum_{c \in C, hasRisk(c)=true} claimAmount(c) -$$ - -## 测试方案 - -- 后端单元测试:验证费用类型中文化、风险信号中文化、趋势字段、部门排行和财务关注项。 -- 容器接口测试:在 `x-financial-main:/app` 调用 `/api/v1/analytics/finance-dashboard`。 -- 前端构建:使用项目现有 `npm.cmd` 构建路径。 -- 数据脚本 dry-run:确认模拟修复仅作用于 `SIM` 前缀数据。 -- 画像验证:确认 `employee_behavior_profile_snapshots` 生成模拟员工的快照。 - -## 指标与验收 - -- 财务看板接口不再返回 `travel_application`、`missing material`、`budget pressure` 等裸英文展示名。 -- 趋势字段包含 `claimCount` 和 `claimAmount`,前端标题不再出现“审批趋势”。 -- 部门排行至少覆盖 6 个核心部门的有效费用金额。 -- 财务关注项不再显示审批节点或平均处理时长。 -- 半年模拟数据可生成 100 人规模下的员工画像快照。 - -## 风险与开放问题 - -- 历史非模拟数据可能仍有 `待补充` 部门,当前方案只保证模拟数据合理,不强行修复历史数据。 -- 批量修复模拟数据涉及数据库更新和重建模拟预算台账,执行 `--apply` 前需要用户明确确认。 -- 前端浏览器验证若环境不稳定,可降级为接口 JSON、构建和容器内测试证据。 diff --git a/document/development/财务看板口径重构与画像模拟/STATUS_AUDIT.md b/document/development/财务看板口径重构与画像模拟/STATUS_AUDIT.md deleted file mode 100644 index 336ee03..0000000 --- a/document/development/财务看板口径重构与画像模拟/STATUS_AUDIT.md +++ /dev/null @@ -1,99 +0,0 @@ -# 数据库状态字段审查 - -## 审查范围 - -- 容器:`x-financial-main` -- 数据库:当前运行时 PostgreSQL -- 字段范围:所有 `status`、`stage`、`approval`、`state` 相关列 -- 审查方式:只读查询 `information_schema` 与各表状态值分布 - -## 总体结论 - -- 当前数据库没有 `status_code`、`state_code`、`stage_code` 这类数字状态码字段。 -- 所有匹配到的状态字段类型都是 `character varying`。 -- 非业务运行态表,例如 agent 运行、工具调用、预算池、风险观察,主要使用英文机器码。 -- 报销主表 `expense_claims` 是当前最需要修复的表:`status` 使用英文码,`approval_stage` 同时混入英文码和中文节点名。 - -## 报销主表现状 - -`expense_claims` 当前共 498 条。 - -按单据类型拆分: - -- 申请类单据:2 条,阶段为 `审批完成`、`直属领导审批`。 -- 普通报销单:1 条,阶段为 `待提交`。 -- 半年模拟报销单:495 条,主要问题都集中在这里。 - -`expense_claims.status` 当前值: - -- `paid`:212 -- `approved`:98 -- `pending_payment`:67 -- `finance_review`:43 -- `submitted`:41 -- `returned`:17 -- `rejected`:13 -- `draft`:7 - -`expense_claims.approval_stage` 当前值: - -- `payment`:279 -- `completed`:97 -- `finance_review`:43 -- `manager_review`:40 -- `supplement`:17 -- `rejected`:13 -- `draft`:6 -- `审批完成`:1 -- `待提交`:1 -- `直属领导审批`:1 - -## 问题判断 - -现在不是单纯中文显示问题,而是字段职责混乱: - -- `status` 被当作流程机器状态使用。 -- `approval_stage` 既被当作流程节点,也被历史模拟数据写成英文状态码。 -- 单据中心和审批权限逻辑依赖 `submitted + 中文审批阶段`。 -- 旧模拟数据中的 `finance_review/manager_review/payment/completed` 会导致审核、归档、报销单分类偏差。 - -## 建议契约 - -短期先采用当前代码最接近的契约: - -- `status`:稳定机器码,继续使用英文枚举。 -- `approval_stage`:当前流程节点,统一使用中文节点名。 -- 前端和接口展示层:只展示中文标签,不直接暴露机器码。 - -中期如要数字状态码,需要单独迁移: - -- 增加 `status_code`、`approval_stage_code` 或独立状态字典表。 -- 保留现有字符串字段作为兼容层,避免一次性改动所有查询、权限、看板和智能体逻辑。 -- 完成迁移后再逐步让业务代码改读数字码。 - -## 报销主表修复映射 - -建议先只修 `expense_claims` 的模拟数据和历史异常阶段: - -- `status=finance_review` → `status=submitted`,`approval_stage=财务审批` -- `approval_stage=manager_review` → `直属领导审批` -- `approval_stage=budget_review` → `预算管理者审批` -- `approval_stage=finance_review` → `财务审批` -- `status=pending_payment` → `approval_stage=待付款` -- `status=paid` → `approval_stage=已付款` -- `status=approved` 且为报销单 → `approval_stage=归档入账` -- `status=approved` 且为申请单 → `approval_stage=审批完成` -- `status=returned` → `approval_stage=待补充` -- `status=rejected` → `approval_stage=已驳回` -- `status=draft` → `approval_stage=待提交` - -## 后续动作 - -- 已完成:只读审查数据库状态字段。 -- 已完成:模拟数据修复脚本支持 dry-run 和中文阶段归一化。 -- 已完成:新增报销状态注册表,统一状态码、标签、阶段别名与历史值归一化。 -- 已完成:新增只读审计脚本 `audit_expense_claim_statuses.py`,用于修复前后核对状态一致性。 -- 已验证:当前 498 张单据中 495 张模拟报销单需要归一化,集中在 `payment`、`completed`、`finance_review`、`manager_review` 等历史阶段值。 -- 待确认:执行模拟数据修复脚本 `--apply --refresh-profiles`。 -- 待确认:执行 mock 附件脚本 `--apply`。 -- 待开发:如确认要数字状态码,新增状态字典/状态码迁移方案。 diff --git a/document/development/财务看板口径重构与画像模拟/TODO.md b/document/development/财务看板口径重构与画像模拟/TODO.md deleted file mode 100644 index a03b95e..0000000 --- a/document/development/财务看板口径重构与画像模拟/TODO.md +++ /dev/null @@ -1,47 +0,0 @@ -# 财务看板口径重构与画像模拟开发 TODO - -## 调研 - -- [x] 核对财务看板接口字段和页面消费位置。[CONCEPT: 背景与问题] 证据:`FinanceDashboardService`、`TrendChart`、`OverviewView` 已确认。 -- [x] 核对员工画像现有服务是否可复用。[CONCEPT: 员工画像] 证据:`EmployeeBehaviorProfileService` 已支持批量扫描和按员工刷新。 - -## 契约 - -- [x] 将趋势字段调整为 `claimCount`、`claimAmount`,并保留旧字段兼容。[CONCEPT: 每日报销趋势] 证据:`FinanceDashboardService._trend` 已返回新字段,定向测试通过。 -- [x] 将底部 `bottlenecks` 展示替换为预算指标。[CONCEPT: 财务关注项] 证据:页面展示预算池数量、总预算、已用预算、预占预算、可用预算、预警预算池。 -- [x] 补齐费用类型和风险类型中文归一化规则。[CONCEPT: 费用结构] 证据:接口 JSON 不再包含 `travel_application`、`missing_material`、`budget_pressure`。 -- [x] 建立报销状态注册表,集中管理状态码、中文标签、阶段别名和历史值归一化。[CONCEPT: 数据] 证据:`expense_claim_status_registry.py` 已新增。 -- [x] 将财务看板主指标改为财务口径,移除风险异常展示。[CONCEPT: 指标与验收] 证据:KPI 改为本期报销金额、报销单数、待付款金额、单均金额、预算使用率、付款完成率。 - -## 后端 - -- [x] 修改 `FinanceDashboardService` 的费用结构、趋势、部门排行、个人排行、高额单据和预算指标计算。[CONCEPT: 方案设计] 证据:`server/src/app/services/finance_dashboard.py` 已更新。 -- [x] 补充后端定向测试,覆盖英文枚举不外露和趋势字段。[CONCEPT: 测试方案] 证据:`test_finance_dashboard_uses_financial_terms_instead_of_approval_terms` 已新增。 - -## 前端 - -- [x] 修改 `TrendChart` 为报销单量和报销金额图。[CONCEPT: 前端] 证据:`TrendChart.vue` 已改为双轴单量/金额。 -- [x] 修改财务看板标题和底部列表文案。[CONCEPT: 前端] 证据:`OverviewView.vue` 标题已更新。 -- [x] 确认页面不再出现审批趋势、审批瓶颈文案。[CONCEPT: 指标与验收] 证据:`rg` 检查财务看板相关文案已清理。 -- [x] 将趋势拆为“每日报销金额”和“每日报销数量”两个单指标图。[CONCEPT: 每日报销趋势] 证据:`OverviewView.vue` 和 `TrendChart.vue` 已更新。 -- [x] 新增个人报销排行和本月高额单据列表。[CONCEPT: 指标与验收] 证据:财务看板模板已新增 `个人报销排行(本月)`、`本月高额单据`。 -- [x] 移除财务页“财务关注项”卡片,新增预算指标网格。[CONCEPT: 指标与验收] 证据:财务页模板已展示 `预算指标`,不再展示 `财务关注项`。 - -## 数据与画像 - -- [x] 修复半年模拟数据部门分布脚本,保持 dry-run 可审计。[CONCEPT: 数据] 证据:`repair_half_year_expense_demo_distribution.py` dry-run 返回六部门重分布计划。 -- [x] 为模拟数据写入脚本增加画像刷新入口。[CONCEPT: 员工画像] 证据:seed 与 repair 脚本均支持 `--refresh-profiles`。 -- [x] 将模拟数据修复脚本中的审批阶段规范为中文业务阶段。[CONCEPT: 数据] 证据:待审单统一为 `submitted + 财务审批/直属领导审批`,归档/付款阶段写入中文阶段。 -- [x] 增加报销状态只读审计脚本。[CONCEPT: 指标与验收] 证据:`audit_expense_claim_statuses.py` 可输出需要归一化的状态组合。 -- [x] 提高半年模拟数据单据密度。[CONCEPT: 数据] 证据:seed dry-run 计划在现有 495 单基础上新增 690 单,总量约 1185 单。 -- [ ] 在用户确认后执行模拟数据修复 `--apply`。[CONCEPT: 风险与开放问题] -- [ ] 验证模拟员工画像快照已形成。[CONCEPT: 指标与验收] - -## 验证 - -- [x] 在 `x-financial-main` 容器内运行后端定向测试,超时不超过 60s。[CONCEPT: 测试方案] 证据:`pytest -q server/tests/test_finance_dashboard_service.py server/tests/test_demo_company_simulation_seed.py`,4 passed。 -- [x] 运行前端构建或等价静态验证。[CONCEPT: 测试方案] 证据:`npm.cmd run build` 成功。 -- [x] 调用财务看板 API,确认 JSON 中不再泄露英文枚举并包含新指标。[CONCEPT: 指标与验收] 证据:容器内服务调用返回 `claimCount`、`claimAmount`,英文枚举检查为 false。 -- [x] 验证单据中心财务角色可以看到公司报销单与归档单。[CONCEPT: 测试方案] 证据:`test_list_claims_returns_company_reimbursements_for_finance_document_center` 与归档测试通过。 -- [x] 验证财务看板真实 payload 不含风险展示文案,部门排行不含“待补充”。[CONCEPT: 指标与验收] 证据:容器内服务调用 `contains_risk_text=false`、`contains_pending_fill_department=false`。 -- [x] 验证预算指标真实 payload。[CONCEPT: 指标与验收] 证据:容器内服务调用返回 6 个 `budget_metrics`,且 `contains_focus_label=false`。 diff --git a/document/development/财务看板排行口径与部门人员占比/CONCEPT.md b/document/development/财务看板排行口径与部门人员占比/CONCEPT.md deleted file mode 100644 index 4f1361e..0000000 --- a/document/development/财务看板排行口径与部门人员占比/CONCEPT.md +++ /dev/null @@ -1,153 +0,0 @@ -# 财务看板排行口径与部门人员占比 - -## 功能一句话 - -在分析看板的财务看板中补齐部门人员报销占比,并让部门、个人、高额单据使用统一的排行时间筛选口径。 - -## 背景与问题 - -当前财务看板已有部门报销排行、个人报销排行和本月高额单据,但存在三个问题: - -- 部门排行的时间筛选只有本周、本月、本季度,缺少本年和全部。 -- 个人报销排行标题固定为“本月”,实际无法由用户切换本月、本季度、本年和全部。 -- 高额单据旁缺少部门内人员报销构成,财务人员难以判断高额单据是否集中在少数人员或单一部门。 - -## 目标与非目标 - -目标: - -- 新增“部门人员报销占比”饼图,放在“本月高额单据”左侧,并与排行时间筛选口径联动。 -- 部门报销排行增加参与人员数量,卡片空间完整展示排行内容。 -- 个人报销排行增加报销笔数和所属部门信息,卡片空间完整展示排行内容。 -- 部门排行、个人排行、高额单据、部门人员占比统一支持:本月、本季度、本年、全部。 - -非目标: - -- 不新增独立页面。 -- 不重做顶部 KPI、趋势图、预算指标和系统/风险/数字员工看板。 -- 不引入新的图表库,继续复用现有 ECharts 封装组件。 - -## 用户与场景 - -用户: - -- 高级财务人员、预算监控员、管理员。 - -场景: - -- 财务人员进入分析看板后,查看不同时间口径下的部门费用集中度。 -- 财务人员切换本季度、本年或全部后,对比部门排行、个人排行、高额单据和人员占比。 -- 财务人员判断某部门报销金额高,是因为多人正常报销,还是少数人集中报销。 - -## 功能能力 - -输入: - -- `department_range` 查询参数,取值:`本月`、`本季度`、`本年`、`全部`。 - -输出: - -- `department_ranking`:部门报销排行,新增 `employeeCount`。 -- `employee_ranking`:个人报销排行,保留金额、笔数、部门,并随筛选口径变化。 -- `top_claims`:高额单据,随筛选口径变化,标题不再固定为本月。 -- `department_employee_mix`:部门人员报销占比饼图数据。 - -状态与边界: - -- 没有真实数据时返回空数组或“暂无数据”占位。 -- 草稿、删除等非支出口径状态不参与金额排行。 -- 缺失部门或人员名称的数据不进入排行和占比图。 -- `全部` 表示所有可用报销单据,不按日期裁剪。 - -## 方案设计 - -后端: - -- 在 `FinanceDashboardService` 中扩展排行时间范围解析。 -- 将 `department_range` 作为排行分析窗口,统一供部门排行、个人排行、高额单据和部门人员占比使用。 -- 部门排行按部门聚合金额、单据数、待付款金额和人员数量。 -- 部门人员占比按“部门 + 人员”聚合金额,展示排名靠前的人员构成,名称格式为 `部门 · 人员`。 - -接口: - -- `GET /api/v1/analytics/finance-dashboard` 保持原路径。 -- `department_range` 支持 `本月`、`本季度`、`本年`、`全部`。 -- 响应体新增 `department_employee_mix`。 - -前端: - -- `analytics.js` 增加 `departmentEmployeeMix` 归一化。 -- `metrics.js` 将 `departmentRangeOptions` 改为 `本月 / 本季度 / 本年 / 全部`。 -- `useOverviewView.js` 新增部门人员占比 legend,并让部门/个人排行读取新增字段。 -- `OverviewView.vue` 调整财务看板底部布局: - - 部门排行占更宽区域,并保留筛选器。 - - 个人排行占更宽区域,并增加相同筛选器。 - - 高额单据卡片左侧放部门人员报销占比饼图,右侧放高额单据列表。 -- 样式继续沿用企业 SaaS 直角、低饱和、Element Plus 控件和已有 `DonutChart` / `BarChart`。 - -## 算法与公式 - -支出金额: - -$$ -amount_i = claim_i.amount -$$ - -部门金额: - -$$ -departmentAmount_d = \sum_{i \in claims(d)} amount_i -$$ - -部门人员数: - -$$ -employeeCount_d = \left| distinct(employeeName_i), i \in claims(d) \right| -$$ - -个人金额: - -$$ -employeeAmount_e = \sum_{i \in claims(e)} amount_i -$$ - -部门人员报销占比: - -$$ -share_{d,e} = \frac{\sum_{i \in claims(d,e)} amount_i}{\sum_{i \in rankingClaims} amount_i} -$$ - -其中 `rankingClaims` 为当前 `department_range` 时间口径下过滤后的有效报销单据。 - -## 测试方案 - -- 后端单元测试: - - 覆盖 `department_range=本年` 和 `department_range=全部`。 - - 验证部门排行返回 `employeeCount`。 - - 验证个人排行随口径变化。 - - 验证 `department_employee_mix` 返回正确人员占比数据。 -- 前端源码测试: - - 验证筛选选项包含本月、本季度、本年、全部。 - - 验证个人排行和部门排行都有筛选器。 - - 验证高额单据卡片包含部门人员报销占比图。 - - 验证服务层归一化新增字段。 -- 构建验证: - - `npm.cmd --prefix web run build`。 -- 容器验证: - - 后端测试在 `x-financial-main:/app` 中运行,超时不超过 60s。 - - 可用时通过接口检查 `department_employee_mix`、`employeeCount` 和 `department_range=全部`。 - -## 指标与验收 - -- 财务看板接口返回 `department_employee_mix`。 -- 部门排行每项返回 `employeeCount`。 -- 部门排行和个人排行都可选择本月、本季度、本年、全部。 -- 个人排行标题不再固定“本月”。 -- 高额单据卡片左侧显示部门人员报销占比饼图。 -- 定向后端测试和前端构建通过。 - -## 风险与开放问题 - -- 当前工作区存在大量未提交变更,提交时必须只纳入本次相关文件。 -- 如果浏览器自动化不可用,前端以源码测试、构建和接口验证为主要证据。 -- `全部` 口径数据量可能更大,当前实现继续沿用内存聚合;后续数据量过大时再考虑 SQL 聚合优化。 diff --git a/document/development/财务看板排行口径与部门人员占比/TODO.md b/document/development/财务看板排行口径与部门人员占比/TODO.md deleted file mode 100644 index 0e33a6d..0000000 --- a/document/development/财务看板排行口径与部门人员占比/TODO.md +++ /dev/null @@ -1,35 +0,0 @@ -# 财务看板排行口径与部门人员占比 TODO - -## 调研 - -- [x] 盘点财务看板后端聚合、前端服务、页面布局和测试现状。[CONCEPT: 背景与问题] 证据:已检查 `FinanceDashboardService`、`analytics.js`、`useOverviewView.js`、`OverviewView.vue`、`test_finance_dashboard_service.py`。 - -## 契约 - -- [x] 扩展 `department_range` 支持 `本月 / 本季度 / 本年 / 全部`。[CONCEPT: 功能能力] 证据:`FinanceDashboardService._resolve_ranking_scope` 和 `departmentRangeOptions` 已更新。 -- [x] 响应体新增 `department_employee_mix`,部门排行新增 `employeeCount`。[CONCEPT: 方案设计] 证据:`FinanceDashboardRead`、`_department_ranking`、`_department_employee_mix` 已更新。 - -## 后端 - -- [x] 修改财务看板服务的排行时间范围解析,统一驱动部门排行、个人排行、高额单据和人员占比。[CONCEPT: 方案设计] 证据:`ranking_claims` 同时供四类排行/图表使用。 -- [x] 新增部门人员报销占比聚合逻辑。[CONCEPT: 算法与公式] 证据:新增 `_department_employee_mix`,按部门和人员聚合金额并返回饼图数据。 -- [x] 更新快照缓存兼容新增字段。[CONCEPT: 接口] 证据:`SNAPSHOT_SCHEMA_VERSION = "finance-dashboard-ranking-v2"` 已加入快照缓存 key。 - -## 前端 - -- [x] 更新前端服务归一化和筛选选项。[CONCEPT: 前端] 证据:`analytics.js` 支持 `departmentEmployeeMix`,`metrics.js` 选项为本月/本季度/本年/全部。 -- [x] 调整财务看板底部布局,新增部门人员报销占比饼图。[CONCEPT: 前端] 证据:`OverviewView.vue` 的 `top-claim-split` 左侧接入 `DonutChart`。 -- [x] 部门排行和个人排行展示人员数、单据数等辅助信息,并占满卡片空间。[CONCEPT: 前端] 证据:`BarChart.vue` 支持 `meta`,排行卡片跨度改为 6 栅格。 - -## 测试 - -- [x] 补充后端定向测试,覆盖排行时间口径、人员数和部门人员占比。[CONCEPT: 测试方案] 证据:`test_finance_dashboard_ranking_range_supports_year_and_all_scope` 已新增。 -- [x] 补充前端源码测试,覆盖筛选器和新增图表字段。[CONCEPT: 测试方案] 证据:新增 `web/tests/finance-dashboard-ranking.test.mjs`。 -- [x] 在 `x-financial-main` 容器内运行后端定向测试,超时不超过 60s。[CONCEPT: 测试方案] 证据:`pytest -q server/tests/test_finance_dashboard_service.py`,4 passed。 -- [x] 运行前端定向测试或构建验证。[CONCEPT: 测试方案] 证据:`node web/tests/finance-dashboard-ranking.test.mjs`,3 passed;`npm.cmd --prefix web run build` 通过。 - -## 验收 - -- [x] 调用财务看板接口验证 `department_range=全部` 返回新增字段。[CONCEPT: 指标与验收] 证据:接口返回 `has_department_employee_mix=true`、`department_employee_mix_count=6`、部门排行含 `employeeCount=67`。 -- [x] 更新本 TODO 的完成证据。[CONCEPT: 指标与验收] 证据:本文件已补充每项完成证据。 -- [ ] 提交并推送本次功能改动,避免纳入无关脏工作区变更。[CONCEPT: 风险与开放问题] 阻塞:工作区已有大量未提交改动,且本次相关后端文件依赖未跟踪的财务看板快照/常量文件,直接提交会混入既有改动,单独提交又可能缺依赖。 diff --git a/document/development/费用审批动态路由/CONCEPT.md b/document/development/费用审批动态路由/CONCEPT.md deleted file mode 100644 index 7482e7d..0000000 --- a/document/development/费用审批动态路由/CONCEPT.md +++ /dev/null @@ -1,106 +0,0 @@ -# 费用审批动态路由概念文档 - -## 功能一句话 - -让费用申请和报账在直属领导审批后,按预算风险、规则风险和员工历史风险动态决定是否进入预算管理者复核。 - -## 背景与问题 - -当前申请单默认进入预算管理者审批,报账单默认进入财务审批,审批路径偏固定。业务上更合理的方式是:预算充足、当前无风险、历史画像正常的单据减少审批层级;存在超预算、规则命中、超标或历史风险异常的单据交给预算管理者做二次确认。 - -## 目标与非目标 - -目标: - -- 申请环节:低风险且预算充足时,直属领导审批后直接完成申请并生成报销草稿。 -- 申请环节:超预算、预算预警、当前风险或历史风险异常时,进入预算管理者审批。 -- 报账环节:低风险且预算充足时,直属领导审批后进入财务审批。 -- 报账环节:超预算、超标、当前风险或历史风险异常时,先进入预算管理者审批,再进入财务审批。 -- 审批记录中保留路由决策依据,便于追溯。 - -非目标: - -- 不改预算占用、释放、核销的资金动作语义。 -- 不引入新的审批流配置页面。 -- 不让大模型参与最终审批路由裁判。 - -## 用户与场景 - -- 普通员工:提交费用申请或报账。 -- 直属领导:确认业务必要性。 -- 预算管理者:只复核有预算或风险关注项的单据。 -- 财务人员:处理报账财务终审和付款前流程。 - -## 功能能力 - -路由决策输入: - -- 单据基本信息:金额、费用类型、发生时间、部门、项目、申请人。 -- 预算测算:预算池匹配、可用余额、预算使用率、预警阈值、超预算金额。 -- 当前风险:预算标记、规则中心风险、提交预审风险、票据/附件风险、超标风险。 -- 历史风险:同一员工近一段时间内的实质风险记录。 - -路由决策输出: - -- `requires_budget_review`:是否需要预算管理者复核。 -- `route`:下一环节建议。 -- `reasons`:触发预算复核或跳过的原因。 -- `budget_result`:预算模型摘要。 -- `current_risk_count`、`historical_risk_count`:当前和历史风险计数。 - -## 方案设计 - -后端新增独立审批路由决策模块,避免在审批主流程中堆条件。 - -直属领导审批时: - -1. 调用预算服务计算当前单据预算影响。 -2. 读取当前单据风险标记,过滤审批记录等非风险事件。 -3. 查询同一员工近期历史单据,统计实质风险记录。 -4. 生成路由决策标记并写入 `risk_flags_json`。 -5. 根据结果决定下一环节: - - 申请单:预算复核或审批完成。 - - 报账单:预算复核或财务审批。 - -预算管理者审批时: - -- 申请单进入审批完成,并生成报销草稿。 -- 报账单进入财务审批。 - -## 算法与公式 - -路由决策不是单一分数,而是规则化闸口: - -$$ -requires\_budget\_review = -budget\_risk \lor current\_risk \lor historical\_risk -$$ - -其中: - -- `budget_risk = rating in {block, review, caution} or risk_level in {medium, high, critical}` -- `current_risk = 当前单据存在 medium/high/critical 实质风险标记` -- `historical_risk = 同一员工近期存在实质风险记录` - -实质风险标记排除审批通过、退回、付款、路由说明等流程记录,只保留预算、规则、AI 预审、附件、政策超标等风险来源。 - -## 测试方案 - -- 单元测试:低风险申请跳过预算管理者并生成报销草稿。 -- 单元测试:高风险报账进入预算管理者审批,预算审批后进入财务审批。 -- 回归测试:原有风险规则生成、申请提交、阶段化风险规则执行继续通过。 -- 容器验证:在 `x-financial-main:/app/server` 内运行定向 pytest。 - -## 指标与验收 - -- 低风险申请不会固定进入预算管理者审批。 -- 风险报账会进入预算管理者审批。 -- 报账经过预算管理者审批后仍需进入财务终审。 -- 每次动态路由都有可追溯的 `approval_routing` 标记。 -- 预算资金动作仍由原有提交、退回、财务终审链路处理。 - -## 风险与开放问题 - -- 历史风险的口径会影响预算管理者工作量,当前一期采用“存在实质风险即复核”的严格口径。 -- 缺失预算池时是否全部进入预算复核,当前按预算风险处理。 -- 后续如要支持可配置路由阈值,应新增配置表或策略服务,而不是继续改审批流分支。 diff --git a/document/development/费用审批动态路由/TODO.md b/document/development/费用审批动态路由/TODO.md deleted file mode 100644 index ef3a12d..0000000 --- a/document/development/费用审批动态路由/TODO.md +++ /dev/null @@ -1,9 +0,0 @@ -# 费用审批动态路由 TODO - -- [x] 调研现有审批流、预算模型和风险标记结构。[CONCEPT: 方案设计] 证据:已梳理 `expense_claim_approval_flow.py`、`budget.py`、`budget_expense_control.py`、`expense_claim_risk_review.py`。 -- [x] 新增审批路由决策模块,统一输出是否需要预算复核。[CONCEPT: 功能能力] 证据:新增 `expense_claim_approval_routing.py`。 -- [x] 接入申请单直属领导审批后的动态路由。[CONCEPT: 方案设计] 证据:`ExpenseClaimApprovalFlowMixin.approve_claim` 根据路由结果完成或进入预算审批。 -- [x] 接入报账单直属领导审批后的动态路由,并允许报账经过预算管理者后进入财务审批。[CONCEPT: 方案设计] 证据:报账单预算审批后进入 `FINANCE_APPROVAL_STAGE`。 -- [x] 审批记录写入 `approval_routing` 决策标记。[CONCEPT: 指标与验收] 证据:审批通过时同时写入路由标记和 `route_decision` 摘要。 -- [x] 补充低风险申请跳过预算、高风险报账进入预算的测试。[CONCEPT: 测试方案] 证据:新增 `test_expense_claim_approval_routing.py`。 -- [x] 在 `x-financial-main:/app/server` 运行 60s 内定向验证。[CONCEPT: 测试方案] 证据:`uv run --with pytest python -m pytest ... -q`,6 passed。 diff --git a/document/development/费用申请审批财务规则/CONCEPT.md b/document/development/费用申请审批财务规则/CONCEPT.md deleted file mode 100644 index 0821a39..0000000 --- a/document/development/费用申请审批财务规则/CONCEPT.md +++ /dev/null @@ -1,131 +0,0 @@ -# 费用申请审批财务规则概念文档 - -## 功能一句话 - -在财务规则中心新增《公司费用申请审批规则》,统一维护业务招待、办公用品和通用大额费用的事前申请与审批阈值,并让报销风险规则引用该规则执行。 - -## 背景与问题 - -现有系统已经有“业务招待无申请”“办公采购无申请”“大额费用无申请”等风险规则,但制度依据主要以风险规则 JSON 的口径字段存在,财务规则中心缺少一张可被制度管理员查看、编辑和追溯的规则表。 - -用户明确要求: - -- 业务招待费超过 500 元需要申请。 -- 大额办公用品需要申请。 -- 金额超过 2000 元的费用都需要走审批。 -- 这些要求最好形成财务规则,而不是散落在代码或前端提示中。 - -## 目标与非目标 - -目标: - -- 新增一张财务规则资产《公司费用申请审批规则》。 -- 规则资产以 Excel 形式进入 `finance-rules` 规则库,并在规则中心按“财务规则”展示。 -- 风险规则引用统一的 `finance_rule_code`,不再使用零散口径 code。 -- 报销阶段按结构化金额规则判断,而不是只靠关键词命中。 -- 关联有效申请单后不触发“缺少申请”风险。 - -非目标: - -- 本轮不新增数据库字段。 -- 本轮不新增非本体业务字段。 -- 本轮不改造完整审批流节点,只补充申请前置与风险执行依据。 - -## 用户与场景 - -- 报销人:上传或录入业务招待、办公用品、大额费用报销时,系统自动识别是否缺少事前申请。 -- 直属领导和财务审核人:审核单据时能看到风险来自财务规则。 -- 财务制度管理员:能在规则中心看到并维护《公司费用申请审批规则》。 - -## 功能能力 - -### 财务规则表 - -规则表包含以下行: - -- 业务招待费:单次费用金额大于 500 元时,必须先提交费用申请单。 -- 办公用品费:单次或批量采购金额大于 2000 元时,必须先提交办公采购或费用申请单。 -- 通用大额费用:任意费用金额大于 2000 元时,必须进入审批流程。 - -### 风险规则执行 - -- `meal` 与 `entertainment` 都视为业务招待费。 -- `office` 视为办公用品费。 -- `all` 视为通用大额费用。 -- 报销阶段没有关联有效申请单时,超过阈值命中高风险。 -- 已有关联申请单时,不命中缺少申请风险。 - -## 方案设计 - -### 后端 - -- 在 `agent_asset_spreadsheet.py` 中新增费用申请审批规则 code 与文件名常量。 -- 在财务规则同步中新增该资产的 metadata、Excel 工作簿生成和版本快照。 -- 在初始化和补齐逻辑中创建该财务规则资产,确保老库和新库都能看到。 -- 将三条风险规则改为 `composite_rule_v1`,使用金额阈值和申请单存在性执行。 -- 在 `risk_rule_template_executor.py` 中补齐 `application.*` 字段解析,桥接现有 `application_link` / `application_handoff` / `application_detail` 风险上下文。 - -### 前端 - -本轮不新增前端页面。规则中心已有财务规则和 JSON 风险规则展示能力,后端资产同步后前端可直接展示。 - -### 数据与本体 - -本轮只使用现有本体字段: - -- `expense_type` -- `amount` -- `reason` -- `application_claim_id` -- `application_claim_no` -- `application_detail` - -不新增非本体字段。 - -## 算法与公式 - -业务招待费规则: - -$$ -hit = expenseType \in \{meal, entertainment\} \land amount > 500 \land \neg hasApplication -$$ - -办公用品规则: - -$$ -hit = expenseType = office \land amount > 2000 \land \neg hasApplication -$$ - -通用大额规则: - -$$ -hit = amount > 2000 \land \neg hasApplication -$$ - -其中: - -- `amount` 来自 `claim.amount`。 -- `hasApplication` 来自 `application.id`、`application.claim_no` 或等价申请单上下文。 - -## 测试方案 - -- 单元测试:验证 `application.*` 字段能从已有申请关联上下文解析。 -- 规则执行测试:超过 500 元业务招待费且无申请命中风险。 -- 规则执行测试:超过 2000 元办公用品费且无申请命中风险。 -- 规则执行测试:超过 2000 元通用费用且无申请命中风险。 -- 规则执行测试:已关联申请单的超额费用不命中缺少申请风险。 -- 资产测试:规则中心种子数据包含《公司费用申请审批规则》,且 `config_json.tag` 为“财务规则”。 - -## 指标与验收 - -- 财务规则中心能看到新增规则资产。 -- 新增资产 `finance_rule_code` 统一为 `expense.preapproval.policy`。 -- 三条风险规则均引用该财务规则 code。 -- 容器内后端定向测试通过。 -- 不新增非本体业务字段。 - -## 风险与开放问题 - -- “大额办公用品”的金额阈值按用户同句“大额/超过 2000 都需要审批”落为 2000 元。 -- 当前申请单上下文主要存在 `risk_flags_json` 的申请关联 flag 中,本轮先补执行器解析,不新增外键字段。 -- 后续如果要支持不同部门或不同职级阈值,可以在同一张财务规则表中扩展分档行。 diff --git a/document/development/费用申请审批财务规则/TODO.md b/document/development/费用申请审批财务规则/TODO.md deleted file mode 100644 index f67788e..0000000 --- a/document/development/费用申请审批财务规则/TODO.md +++ /dev/null @@ -1,23 +0,0 @@ -# 费用申请审批财务规则 TODO - -## 调研与契约 - -- [x] 盘点现有财务规则资产、风险规则 JSON 与规则同步链路。[CONCEPT: 背景与问题] 证据:确认现有 `finance-rules` 仅差旅和通信两张核心规则表,前置申请规则当前在 `risk-rules` 中。 -- [x] 明确本轮不新增非本体业务字段。[CONCEPT: 数据与本体] 证据:规则只使用 `expense_type`、`amount`、`reason` 和申请单上下文。 - -## 后端实现 - -- [x] 新增《公司费用申请审批规则》财务规则资产常量与 Excel 工作簿内容。[CONCEPT: 财务规则表] 证据:`COMPANY_PREAPPROVAL_RULE_CODE`、`COMPANY_PREAPPROVAL_RULE_FILENAME` 和 `_ensure_company_preapproval_rule_spreadsheet_seed()` 已实现。 -- [x] 初始化种子和老库补齐逻辑都能创建该财务规则资产。[CONCEPT: 方案设计] 证据:`agent_foundation_asset_seed.py` 和 `agent_foundation_asset_topup.py` 均接入该资产。 -- [x] 将大额费用、业务招待、办公用品三条前置申请风险规则改为结构化金额判断。[CONCEPT: 风险规则执行] 证据:三条 `risk.application.*without_preapproval.json` 已改为 `composite_rule_v1`。 -- [x] 补齐 `application.*` 字段解析,支持从现有关联申请上下文判断是否已有申请。[CONCEPT: 后端] 证据:`risk_rule_template_executor.py` 新增 `_resolve_application_values()`。 - -## 测试与验证 - -- [x] 新增执行器测试:申请单上下文存在时 `application.id` 可解析。[CONCEPT: 测试方案] 证据:`test_application_context_values_are_available_to_composite_rules` 通过。 -- [x] 新增风险规则执行测试:业务招待费超过 500 元且无申请命中。[CONCEPT: 测试方案] 证据:`test_preapproval_amount_rules_hit_without_linked_application` 覆盖 meal。 -- [x] 新增风险规则执行测试:办公用品超过 2000 元且无申请命中。[CONCEPT: 测试方案] 证据:`test_preapproval_amount_rules_hit_without_linked_application` 覆盖 office。 -- [x] 新增风险规则执行测试:通用费用超过 2000 元且无申请命中。[CONCEPT: 测试方案] 证据:`test_preapproval_amount_rules_hit_without_linked_application` 覆盖 software。 -- [x] 新增资产同步测试:财务规则中心包含新增规则资产。[CONCEPT: 指标与验收] 证据:`test_finance_rules_use_risk_rule_scenario_categories` 断言新增财务规则资产和规则文档。 -- [x] Docker `x-financial-main` 容器内定向测试通过。[CONCEPT: 指标与验收] 证据:新增与相邻回归共 15 个后端测试通过。 -- [x] 重启后端并验证运行时健康状态。[CONCEPT: 指标与验收] 证据:`x-financial-main` 已重启并进入 healthy;真实库可查到 `rule.expense.company_preapproval_requirement`。 diff --git a/document/development/通知中心状态持久化/CONCEPT.md b/document/development/通知中心状态持久化/CONCEPT.md deleted file mode 100644 index 9ffb242..0000000 --- a/document/development/通知中心状态持久化/CONCEPT.md +++ /dev/null @@ -1,111 +0,0 @@ -# 通知中心状态持久化概念文档 - -## 功能一句话 - -为首页小铃铛通知中心补齐服务端状态接口,让同一用户在不同电脑登录时看到一致的已读、清空和隐藏状态,并优化笔记本等小屏幕下的通知弹窗可读性。 - -## 背景与问题 - -当前小铃铛通知由前端从单据中心、个人工作台摘要等数据源即时生成,但已读与清空状态主要写入浏览器 `localStorage`。这会导致同一账号在 A 电脑清空通知后,换到 B 电脑仍然看到通知。 - -同时,通知条数较多或屏幕高度较小时,列表内容容易挤压头部操作区,通知标题与描述也容易在窄宽度下互相挤压。 - -## 目标与非目标 - -目标: - -- 提供当前用户维度的通知状态接口。 -- 支持批量同步通知状态,至少覆盖已读与隐藏。 -- 前端优先使用服务端状态,接口不可用时保留本地降级能力。 -- 优化小屏幕通知弹窗,列表多时使用内部滚动,标题、描述与操作按钮不互相挤压。 - -非目标: - -- 不做独立消息投递系统。 -- 不新增推送、WebSocket 或邮件通知能力。 -- 不改变通知来源生成逻辑,当前仍由单据中心和工作台摘要生成。 - -## 用户与场景 - -- 普通员工:在个人工作台查看待办、单据新消息,跨电脑登录后已读状态一致。 -- 审批人:处理待审批单据后,通知中心不因换电脑重新显示已清空内容。 -- 管理员:仍可看到系统内已有通知入口,但 admin 是否展示工作台由现有逻辑决定。 - -## 功能能力 - -- `GET /notification-states`:读取当前登录用户的通知状态集合。 -- `POST /notification-states`:批量保存当前登录用户的通知状态。 -- 状态字段: - - `notification_id`:前端生成的稳定通知 ID。 - - `read_at`:已读时间。 - - `hidden_at`:隐藏或清空时间。 - - `context_json`:保留通知来源、类型等低风险上下文,便于排查。 -- 前端能力: - - 打开工作台或弹窗时读取服务端状态。 - - 点击通知写入已读。 - - 清空通知写入隐藏。 - - 接口失败时仍写入本地缓存,避免用户操作失效。 - -## 方案设计 - -后端: - -- 新增 `NotificationState` SQLAlchemy 模型。 -- 新增 `NotificationStateService`,负责按 `CurrentUserContext.username` 读写状态。 -- 新增 `notification_states` endpoint,并挂到 API v1 router。 -- 服务初始化时使用项目现有 `Base.metadata.create_all(..., tables=[...])` 模式确保表存在。 - -前端: - -- 新增 `web/src/services/notificationStates.js` 封装接口。 -- `TopBar.vue` 将 `localStorage` 状态作为初始兜底,服务端状态返回后合并覆盖。 -- `markNotificationRead` 与 `clearAllNotifications` 做乐观更新,再异步同步服务端。 -- 对单据通知仍调用现有 `markDocumentInboxRowRead`,同时写入通知状态接口,保证跨设备一致。 - -小屏幕布局: - -- 弹窗宽度使用 `clamp` 与 `100vw` 约束。 -- 弹窗最大高度使用 `min(..., calc(100vh - ...))`。 -- 列表作为唯一滚动区域,头部和 tab 固定在弹窗网格内。 -- 通知描述允许两行截断,避免窄屏时横向挤压。 - -## 算法与公式 - -当前功能不涉及显式数学公式。状态合并规则为: - -$$ -visible = notification\_id \notin hiddenIds -$$ - -$$ -unread = sourceUnread \land notification\_id \notin readIds \land notification\_id \notin hiddenIds -$$ - -服务端状态优先,前端本地状态仅作为接口失败或首次加载前的兜底。 - -## 测试方案 - -- 后端单元测试: - - 当前用户只能读取自己的通知状态。 - - 批量 upsert 后可读取 `read_at`、`hidden_at`。 - - 清空通知写入 hidden 状态。 -- 前端静态测试: - - `TopBar` 引用通知状态服务。 - - 已读、清空操作会同步服务端。 - - 小屏 CSS 使用弹窗 max-height、内部滚动和移动端约束。 -- 构建验证: - - 运行前端构建确认 Vue 与服务导入无误。 - - 在容器内运行后端定向 pytest。 - -## 指标与验收 - -- 同一用户跨电脑登录后,已读和清空状态由服务端保持一致。 -- 接口失败时用户仍可本地清空,不阻断主要流程。 -- 通知弹窗在笔记本高度下不会挤压头部按钮,列表内部滚动。 -- 通知标题、描述、时间在窄屏下不横向溢出。 - -## 风险与开放问题 - -- 当前通知本身仍由前端即时生成,服务端只保存状态,不保存完整通知正文。 -- 通知 ID 需要保持稳定,否则服务端状态无法命中;本次沿用现有 `document:` 和 `workbench:` 前缀。 -- 历史 localStorage 状态会作为首次迁移兜底,后续服务端会逐步成为主状态源。 diff --git a/document/development/通知中心状态持久化/TODO.md b/document/development/通知中心状态持久化/TODO.md deleted file mode 100644 index 53c9568..0000000 --- a/document/development/通知中心状态持久化/TODO.md +++ /dev/null @@ -1,10 +0,0 @@ -# 通知中心状态持久化 TODO - -- [x] 调研现有小铃铛通知来源、localStorage 键和单据中心已读逻辑。[CONCEPT: 背景与问题] 证据:`TopBar.vue`、`useDocumentCenterInbox.js`、`documentCenterNewState.js` 已确认。 -- [x] 新增后端通知状态模型、Schema、Service 与 API endpoint。[CONCEPT: 方案设计] 证据:`notification_states` 支持按用户保存已读与隐藏状态。 -- [x] 将通知状态接口挂载到 API v1 router,并保持当前用户隔离。[CONCEPT: 功能能力] 证据:`GET /notification-states` 与 `POST /notification-states` 已接入。 -- [x] 新增前端 `notificationStates` 服务封装读取与批量保存。[CONCEPT: 前端] 证据:服务层统一请求 `/notification-states`。 -- [x] 改造 `TopBar` 已读、清空逻辑,优先同步服务端,保留本地降级。[CONCEPT: 前端] 证据:小铃铛点击已读、清空通知都会写入状态接口。 -- [x] 优化通知弹窗笔记本与窄屏布局,避免条数多时挤压。[CONCEPT: 小屏幕布局] 证据:弹窗限制视口高度,列表滚动,描述两行截断,420px 下隐藏行箭头。 -- [x] 补充后端和前端回归测试。[CONCEPT: 测试方案] 证据:`server/tests/test_notification_states.py`、`web/tests/sidebar-document-unread-dot.test.mjs`。 -- [x] 运行容器后端定向 pytest、前端 Node 测试与前端 build。[CONCEPT: 指标与验收] 证据:pytest 2 passed;Node 4 passed;Vite build passed。 diff --git a/document/development/附件上传风险前置复核/CONCEPT.md b/document/development/附件上传风险前置复核/CONCEPT.md deleted file mode 100644 index 793a339..0000000 --- a/document/development/附件上传风险前置复核/CONCEPT.md +++ /dev/null @@ -1,86 +0,0 @@ -# 附件上传风险前置复核 - -## 功能一句话 - -报销附件上传并完成 OCR 识别后立即执行完整风险复核,提交审批时只做轻量最终校验、预算占用和流程流转。 - -## 背景与问题 - -当前报销单提交阶段会同步执行较重的风险检查,包括附件风险汇总、差旅规则、场景规则、规则中心风险、历史行为统计和风险观测写入。用户在点击提交后会等待较长时间,容易误认为页面卡住。 - -风险的主要依据来自已上传票据、OCR 识别结果、费用明细、关联申请单和员工历史行为。这些数据在附件上传完成后已经基本具备,因此完整风险复核应前移到上传完成阶段。 - -## 目标与非目标 - -目标: - -- 附件上传成功后自动刷新费用明细、附件风险、差旅/场景/规则中心风险和 AI 预审标识。 -- 风险复核结果写回 `claim.risk_flags_json`,并持久化规则中心风险观测。 -- 提交阶段不再重复跑完整 `_run_ai_submission_review()`。 -- 提交阶段只保留草稿完整性校验、预算占用、未处理阻断风险判断、状态流转、审计日志和助手会话清理。 - -非目标: - -- 不新增业务字段。 -- 不改变现有风险规则语义。 -- 不把提交改成真正的后端异步任务队列。 - -## 用户与场景 - -- 报销申请人:上传票据后立即看到风险建议和需补充说明,不必等到提交时才发现问题。 -- 直属领导和财务人员:收到单据时可看到提交前已生成的风险提示和用户处理结果。 -- 系统管理员:风险观测仍可进入后台统计。 - -## 功能能力 - -上传完成后: - -- 根据 OCR 结果回填费用明细类型、日期、金额、事由等已有字段。 -- 刷新附件级 `attachment_analysis` 风险。 -- 执行报销级风险复核,并生成 `ai_pre_review` 状态。 -- 对规则中心命中的风险写入 `risk_observations`。 - -提交审批时: - -- 如果存在高风险且用户未处理,继续阻止提交或要求说明/按职级测算。 -- 如果风险已处理,只做预算和流程流转。 -- 不再重复生成一套提交阶段风险。 - -## 方案设计 - -后端: - -- 在 `ExpenseClaimService.upload_claim_item_attachment()` 中,OCR、附件分析和 `_sync_claim_from_items()` 完成后,调用上传后风险复核 helper。 -- 新增 helper 复用现有 `_run_ai_submission_review()` 与 `_replace_ai_pre_review_flag()`,但保持单据状态为草稿。 -- 提交阶段读取既有风险结果,只做最终阻断风险判断,不重复调用 `_run_ai_submission_review()`。 - -前端: - -- 继续使用当前附件识别中的状态条。 -- 上传完成后通过接口返回的 `claim_risk_flags` 更新 AI 建议区和风险标识。 -- 提交时只显示轻量后台提交流程提示。 - -## 算法与公式 - -当前功能不涉及新的显式数学公式。风险评分和风险等级沿用现有规则中心、附件分析、差旅政策和风险观测逻辑。 - -## 测试方案 - -- 后端单元测试:附件上传后写入 `ai_pre_review` 和 `submission_review` 风险。 -- 后端单元测试:提交阶段不再调用完整 `_run_ai_submission_review()`。 -- 后端单元测试:上传后规则中心风险可写入 `risk_observations`。 -- 前端静态回归:提交确认仍为后台提交,不恢复阻塞弹窗。 -- 构建验证:`npm.cmd --prefix web run build`。 - -## 指标与验收 - -- 上传附件后,接口响应的 `claim_risk_flags` 包含最新复核结果。 -- 提交接口耗时不再包含完整风险复核耗时。 -- 提交后审批人仍能看到已前置生成的风险提示。 -- 后端和前端相关回归测试通过。 - -## 风险与开放问题 - -- 如果用户上传后又修改费用明细,现有 `update_claim_item()` 需要继续刷新附件风险和报销级风险。 -- 如果用户没有上传附件直接提交,提交阶段仍需要保留兜底风险复核或阻断提示。 -- 未来可进一步把上传后复核做成真正后台任务,但本次先保持同步接口返回最新风险结果。 diff --git a/document/development/附件上传风险前置复核/TODO.md b/document/development/附件上传风险前置复核/TODO.md deleted file mode 100644 index 18e4bcc..0000000 --- a/document/development/附件上传风险前置复核/TODO.md +++ /dev/null @@ -1,28 +0,0 @@ -# 附件上传风险前置复核 TODO - -## 调研与契约 - -- [x] 盘点附件上传、预审、提交链路,确认完整风险复核当前在提交阶段重复执行。[CONCEPT: 背景与问题] -- [x] 明确上传后复核 helper 的输入输出契约,不新增业务字段。[CONCEPT: 方案设计] 证据:新增 `_refresh_claim_pre_review_flags()` 复用现有风险字段。 - -## 后端实现 - -- [x] 在附件上传完成后触发报销级风险复核,并保持单据状态为草稿。[CONCEPT: 功能能力] 证据:`upload_claim_item_attachment()` 调用 `_refresh_claim_pre_review_flags()`。 -- [x] 上传后风险复核写回 `ai_pre_review` 和 `submission_review` 风险结果。[CONCEPT: 功能能力] 证据:`test_upload_attachment_refreshes_claim_pre_review` 通过。 -- [x] 规则中心风险在上传后写入 `risk_observations`,避免提交阶段集中写入。[CONCEPT: 方案设计] 证据:上传后复核复用 `_run_ai_submission_review()`,平台风险仍调用 `RiskObservationService.upsert_platform_risk_flags()`。 -- [x] 提交阶段改为读取既有风险结果,只做最终校验、预算占用和流转。[CONCEPT: 目标与非目标] 证据:`submit_claim()` 仅在缺少 `ai_pre_review` 时兜底复核。 -- [x] 保留“无附件直接提交”的兜底检查,避免绕过风险复核。[CONCEPT: 风险与开放问题] 证据:`test_submit_claim_runs_ai_review_and_routes_to_direct_manager` 通过。 - -## 前端实现 - -- [x] 确认上传完成后 UI 使用接口返回的 `claim_risk_flags` 刷新 AI 建议与行风险标识。[CONCEPT: 前端] 证据:`travel-request-detail-risk-advice.test.mjs` 通过。 -- [x] 确认提交阶段不恢复阻塞弹窗,只显示轻量后台提交提示。[CONCEPT: 前端] 证据:`travel-request-detail-submit-confirm.test.mjs` 通过。 - -## 测试与验证 - -- [x] 后端测试:附件上传后自动生成预审风险结果。[CONCEPT: 测试方案] 证据:`test_upload_attachment_refreshes_claim_pre_review` 通过。 -- [x] 后端测试:提交阶段不重复调用完整风险复核。[CONCEPT: 测试方案] 证据:`test_submit_claim_reuses_upload_pre_review_without_rerunning_review` 通过。 -- [x] 后端测试:风险观测仍被持久化。[CONCEPT: 测试方案] 证据:`test_risk_observation_storage_ready_is_cached_per_bind` 通过。 -- [x] 前端回归测试通过。[CONCEPT: 测试方案] 证据:54 个详情页风险/提交测试通过。 -- [x] `npm.cmd --prefix web run build` 通过。[CONCEPT: 测试方案] 证据:前端生产构建通过,仅保留既有 Rollup 注释与 chunk size 警告。 -- [x] Docker `x-financial-main` 容器内后端定向测试通过。[CONCEPT: 测试方案] 证据:核心上传前置复核、提交复用预审、申请/报销风险回归测试通过。 diff --git a/document/development/预算中心列表化改造/CONCEPT.md b/document/development/预算中心列表化改造/CONCEPT.md deleted file mode 100644 index 041c631..0000000 --- a/document/development/预算中心列表化改造/CONCEPT.md +++ /dev/null @@ -1,188 +0,0 @@ -# 预算中心列表化改造概念文档 - -## 功能一句话 - -将预算中心从看板式监控页改造成单据中心式预算列表,让预算的正式额度、待审核草案和历史归档有清晰入口。 - -## 背景与问题 - -当前预算中心以预算概览、部门切换、预算明细表和图表为主,适合查看执行情况,但不适合承载预算编制后的审核流程。预算从 AI 分析、部门编制、提交审核、高级财务审核、发布生效到归档,天然是对象生命周期,不应该把审核入口硬塞进看板区域。 - -本次改造采用类似单据中心的列表结构,把预算对象按状态域分成三个入口: - -- 全部预算:查看已发布并生效的部门预算。 -- 预算审核:查看各部门提交的预算草案,由高级财务人员审核。 -- 归档预算:查看历史版本、已驳回、已失效或被新版本替换的预算。 - -## 目标与非目标 - -### 目标 - -- 将预算中心主界面改为列表形态。 -- 提供三个 switch/tab:全部预算、预算审核、归档预算。 -- 全部预算按部门展示正式预算,并在详情中展示年度、季度、月度预算。 -- 预算审核按部门展示已提交预算草案,并提供进入审核助手的入口。 -- 归档预算展示历史预算版本和审核痕迹。 -- 保留预算监控员、高级财务人员、admin 的预算可见性边界。 -- 前端 demo 阶段仅覆盖差旅、通信、招待费、办公用品四类预算。 - -### 非目标 - -- 本阶段不直接完成后端预算草案表、审核表和发布接口。 -- 本阶段不实现真实审核通过或驳回的数据库写入。 -- 本阶段不改变报销单据的预算占用和核销逻辑。 -- 本阶段不扩大普通员工的预算可见范围。 - -## 用户与场景 - -- 预算监控员:查看本部门正式预算、提交草案状态和历史归档。 -- 高级财务人员:查看所有部门预算、审核各部门提交的预算草案。 -- admin:查看所有预算数据并兜底处理异常。 -- 普通员工:不进入预算中心,不需要关注预算。 - -## 功能能力 - -### 全部预算 - -输入: - -- 年度 -- 季度 -- 状态 -- 关键词 - -输出: - -- 预算编号 -- 部门 -- 预算周期 -- 年度预算 -- 季度预算 -- 月度预算 -- 已发生 -- 已占用 -- 剩余可用 -- 风险状态 -- 更新时间 - -点击行进入预算详情,详情展示: - -- 年度预算、季度预算、月度预算 -- 四类费用预算明细:差旅、通信、招待费、办公用品 -- 已发生、已占用、剩余可用和使用率 -- 提醒阈值、告警阈值、风险阈值 - -### 预算审核 - -输入: - -- 年度 -- 季度 -- 审核状态 -- 关键词 - -输出: - -- 草案编号 -- 提交部门 -- 编制人 -- 提交时间 -- 预算周期 -- 申请预算 -- 较上一版变化 -- AI 分析分 -- 风险状态 -- 审核状态 - -高级财务人员和 admin 可以通过“进入审核”打开预算编制助手,带入当前部门草案上下文。 - -### 归档预算 - -输入: - -- 年度 -- 季度 -- 归档状态 -- 关键词 - -输出: - -- 归档编号 -- 部门 -- 预算周期 -- 版本 -- 归档类型 -- 原预算额 -- 审核人 -- 归档时间 -- 状态 - -## 方案设计 - -### 前端 - -- `BudgetCenterView.vue` 改成列表页结构。 -- 复用单据中心的 `status-tabs`、`table-wrap`、`list-foot` 视觉结构。 -- 保留 `EnterpriseSelect` 作为年度、季度、状态和分页大小控件。 -- 使用通用详情页承载预算详情,和票据夹等列表详情页保持同一交互结构。 -- 使用预算助手入口处理编制和审核上下文。 -- 抽出预算列表 demo 数据和转换逻辑到 `budgetCenterListModel.js`,避免主脚本继续变大。 - -### 后端 - -本阶段不改后端。后续应新增预算草案、预算审核和预算发布接口,并将已发布预算写入正式预算池。 - -### 权限 - -- 预算监控员:只能看到本部门预算和本部门提交记录。 -- 高级财务人员:可以看到全部部门预算,并审核预算草案。 -- admin:可以看到全部预算并兜底处理。 - -## 算法与公式 - -预算使用率: - -$$ -usageRate = \frac{usedAmount + occupiedAmount}{budgetAmount} \times 100 -$$ - -剩余可用预算: - -$$ -availableAmount = budgetAmount - usedAmount - occupiedAmount -$$ - -风险分层: - -$$ -risk = -\begin{cases} -风险, & usageRate \ge riskThreshold \\ -告警, & usageRate \ge alertThreshold \\ -提醒, & usageRate \ge reminderThreshold \\ -正常, & usageRate < reminderThreshold -\end{cases} -$$ - -## 测试方案 - -- 静态检查:预算中心脚本 `node --check`。 -- 前端构建:`npm.cmd --prefix web run build`。 -- 交互验证:切换全部预算、预算审核、归档预算,检查筛选、分页、通用详情页和预算助手入口。 -- 权限验证:使用 admin、高级财务人员、预算监控员分别检查可见范围。 -- 响应式验证:检查笔记本宽度下列表横向滚动、通用详情页和按钮尺寸。 - -## 指标与验收 - -- 预算中心首屏为列表,而不是原看板。 -- 三个 switch/tab 可切换:全部预算、预算审核、归档预算。 -- 全部预算详情能看到年度、季度、月度预算。 -- 预算审核列表有进入审核入口。 -- 预算监控员不出现跨部门审核能力。 -- 构建通过,无新增运行时引用错误。 - -## 风险与开放问题 - -- 后端预算草案和审核表尚未落库,本阶段使用前端 demo 数据表达流程。 -- 后续需要明确“审核通过”是自动发布,还是高级财务人员审核后再点击发布。 -- 归档预算的触发条件需要后续和预算发布版本模型一起设计。 diff --git a/document/development/预算中心列表化改造/TODO.md b/document/development/预算中心列表化改造/TODO.md deleted file mode 100644 index 16b7de5..0000000 --- a/document/development/预算中心列表化改造/TODO.md +++ /dev/null @@ -1,37 +0,0 @@ -# 预算中心列表化改造 TODO - -## 调研 - -- [x] 阅读预算中心现有页面结构和脚本。证据:`BudgetCenterView.vue`、`BudgetCenterView.js`。 -- [x] 阅读单据中心列表结构。证据:`DocumentsCenterView.vue`、`document-list-shared.css`。 -- [x] 确认预算中心 UI 规范。证据:`x-financial-enterprise-ui-style` 技能。 - -## 契约与数据 - -- [x] 定义预算中心三个页签:全部预算、预算审核、归档预算。证据:`CONCEPT.md` 功能能力。 -- [x] 定义前端 demo 阶段的预算列表字段。证据:`CONCEPT.md` 功能能力。 -- [x] 抽出预算列表数据模型与格式化逻辑到独立脚本。证据:`budgetCenterListModel.js`。`[CONCEPT: 方案设计]` - -## 前端实现 - -- [x] 将预算中心主界面改成单据中心式列表结构。证据:`BudgetCenterView.vue` 使用 `status-tabs`、`table-wrap`、`list-foot`。`[CONCEPT: 前端]` -- [x] 增加全部预算、预算审核、归档预算三个 switch/tab。证据:Playwright 验证 `全部预算6 / 预算审核6 / 归档预算6`。`[CONCEPT: 功能能力]` -- [x] 增加关键词、年度、季度、状态筛选。证据:`BudgetCenterView.vue` 工具栏筛选控件。`[CONCEPT: 全部预算]` -- [x] 增加分页和空状态。证据:`BudgetCenterView.vue` 分页脚与 `TableEmptyState`。`[CONCEPT: 测试方案]` -- [x] 增加预算通用详情页,展示年度、季度、月度预算。证据:Playwright 验证详情含年度预算、季度预算、月度预算。`[CONCEPT: 全部预算]` -- [x] 增加预算审核入口,带上下文进入预算助手。证据:预算审核列表操作列显示“进入审核”。`[CONCEPT: 预算审核]` -- [x] 按权限限制预算监控员和高级财务人员可见范围。证据:Playwright 验证预算监控员仅 1 条技术部记录,审核操作为“查看进度”。`[CONCEPT: 权限]` -- [x] 将预算工作区纳入单据中心同一外层触底布局。证据:`app.css` 增加 `budget-main` 与 `budget-workarea` 高度规则。`[CONCEPT: 前端]` - -## 验证 - -- [x] 运行 `node --check web/src/views/scripts/BudgetCenterView.js`。证据:命令通过。`[CONCEPT: 测试方案]` -- [x] 运行 `node --check web/src/views/scripts/budgetCenterListModel.js`。证据:命令通过。`[CONCEPT: 测试方案]` -- [x] 运行 `npm.cmd --prefix web run build`。证据:构建通过,仅剩既有 VueUse 注释和 chunk 体积 warning。`[CONCEPT: 验收]` -- [x] 做预算页基础渲染验证,确认三个页签、通用详情页、审核入口可用。证据:浏览器验证预算列表 1366×768 视口下触底,详情页无 `ElDrawer`,详情四类费用和图表渲染,console 无新增错误。`[CONCEPT: 验收]` - -## 后续阶段 - -- [ ] 设计后端预算草案表、预算审核表和发布接口。`[CONCEPT: 后端]` -- [ ] 将审核通过后的预算发布到正式预算池。`[CONCEPT: 后端]` -- [ ] 将报销预算占用、费用控制和预算发布版本打通。`[CONCEPT: 风险与开放问题]` diff --git a/document/development/风险与数字员工看板视觉优化/CONCEPT.md b/document/development/风险与数字员工看板视觉优化/CONCEPT.md deleted file mode 100644 index dd76d9d..0000000 --- a/document/development/风险与数字员工看板视觉优化/CONCEPT.md +++ /dev/null @@ -1,95 +0,0 @@ -# 风险与数字员工看板视觉优化 - -## 功能一句话 - -修正分析看板中风险看板的英文指标展示,将异常排行改成图表化表达,并优化数字员工看板的卡片布局和图表填充。 - -## 背景与问题 - -当前分析看板已经接入风险观察和数字员工数据,但存在三个影响个人操作体验的问题: - -- 风险看板仍会把 `duplicate_invoice`、`rule_center`、`unknown` 等后端 key 直接展示给用户。 -- 异常排行以多列文字列表呈现,分类多、层级碎,难以快速判断哪个异常维度最突出。 -- 数字员工看板部分卡片高度没有被内容充分利用,图表固定高度偏小,视觉上留下较多空白。 - -## 目标与非目标 - -目标: - -- 风险看板可见指标全部中文化,常见风险信号、来源、状态、规则名和未知占位都不再直接显示英文 key。 -- 异常排行聚合成一张图表化总览,保留部门、员工、供应商、规则和费用类型五个维度,并展示数量与金额。 -- 数字员工看板减少无效空白,让趋势图、技能分布、模块排行和业务产出更充分占满卡片。 -- 保持企业 SaaS 风格,继续复用现有 ECharts 封装组件和直角低饱和视觉体系。 - -非目标: - -- 不新增接口,不改变后端数据契约。 -- 不引入新的图表库。 -- 不重做分析看板顶部导航、财务看板、系统看板和页面路由。 - -## 用户与场景 - -用户: - -- 财务人员、风险复核人员、管理员。 - -场景: - -- 用户进入风险看板,快速识别最近周期的风险来源、风险等级和主要异常维度。 -- 用户查看异常排行时,优先通过图形长度和金额标签判断高发异常。 -- 用户进入数字员工看板,查看后台任务趋势、技能类型、工作模块和产出,不需要在大面积空白里寻找信息。 - -## 功能能力 - -风险看板: - -- 对风险信号 key、风险来源 key、状态 key、英文规则名和未知值做前端中文化。 -- 异常排行从五列小列表改为组合图表: - - 每个维度取排名第一项作为主条形图。 - - 展示维度名称、异常项名称、数量和金额。 - - 保留各维度的次级排行,作为图表下方的紧凑明细。 - -数字员工看板: - -- 主趋势卡片与每日摘要组成同一行,趋势图高度随卡片拉伸。 -- 技能分布、工作模块排行和业务产出统一为等高卡片。 -- 最近工作记录独占整行,减少右侧空白和表格压缩。 - -## 前端方案 - -- `RiskObservationDashboard.vue` - - 扩展 `formatSignal`、`formatDimensionName`、`formatRiskLevel` 等映射。 - - 新增异常排行图表数据 `rankingChartItems`,复用 `BarChart` 展示五个维度的头部异常。 - - 将原 `risk-ranking-grid` 改成图表 + 紧凑明细布局。 - -- `DigitalEmployeeDashboard.vue` - - 给卡片设置 flex 纵向结构,让图表区和列表区可拉伸。 - - 调整栅格跨度:趋势 7、每日摘要 5;技能分布、模块排行、业务产出各 4;最近记录 12。 - - 为图表容器增加可填充高度,减少固定高度导致的空白。 - -- `DigitalEmployeeDailyWorkChart.vue` - - 将固定高度改为跟随父容器的 `100%`,用最小高度保证可读性。 - -## 测试方案 - -- 前端源码测试: - - 风险看板不再暴露常见英文风险 key。 - - 异常排行包含 `rankingChartItems` 并复用 `BarChart`。 - - 数字员工看板包含布局填充类名和可拉伸图表区域。 -- 构建验证: - - `node web/tests/risk-observation-dashboard.test.mjs` - - `node web/tests/digital-employee-dashboard.test.mjs` - - `npm.cmd --prefix web run build` - -## 验收标准 - -- 风险看板常见英文 key 在用户可见位置被中文文案替代。 -- 异常排行以图表作为主视觉,不再只是五列文字列表。 -- 数字员工看板主要图表能够跟随卡片高度填充,卡片间高度更均衡。 -- 定向测试和前端构建通过。 - -## 风险与开放问题 - -- 当前工作区有大量既有未提交和未跟踪文件,本次提交需要严格隔离目标文件。 -- 若现有测试文件中保留了旧版乱码断言,需要同步更新为 UTF-8 中文断言。 -- 本次不改后端,如果后端后续新增新的风险 key,需要前端映射表继续补充。 diff --git a/document/development/风险与数字员工看板视觉优化/TODO.md b/document/development/风险与数字员工看板视觉优化/TODO.md deleted file mode 100644 index e410415..0000000 --- a/document/development/风险与数字员工看板视觉优化/TODO.md +++ /dev/null @@ -1,31 +0,0 @@ -# 风险与数字员工看板视觉优化 TODO - -## 调研 - -- [x] 盘点风险看板英文指标、异常排行和数字员工布局现状。[CONCEPT: 背景与问题] 证据:已检查 `RiskObservationDashboard.vue`、`DigitalEmployeeDashboard.vue`、`DigitalEmployeeDailyWorkChart.vue`、`BarChart.vue` 和相关测试。 - -## 契约 - -- [x] 确认本次不改后端接口,只做前端展示归一化和布局优化。[CONCEPT: 目标与非目标] 证据:风险看板和数字员工看板已有所需数据字段。 - -## 前端 - -- [x] 扩展风险看板中文化映射,覆盖风险信号、来源、状态、未知值和规则名。[CONCEPT: 功能能力] 证据:新增 `riskLabels.js`,`RiskObservationDashboard.vue` 和 `useOverviewView.js` 已接入统一中文化函数。 -- [x] 将异常排行改为图表化主视觉,并保留紧凑明细。[CONCEPT: 前端方案] 证据:`RiskObservationDashboard.vue` 新增 `rankingChartItems`、`rankingDetailGroups` 和 `risk-ranking-visual`。 -- [x] 优化数字员工看板卡片跨度、等高布局和图表填充。[CONCEPT: 前端方案] 证据:`DigitalEmployeeDashboard.vue` 调整趋势/摘要/最近记录栅格,并新增 `digital-chart-fill`、`digital-card-fill`。 -- [x] 调整数字员工趋势图高度,使其跟随父容器填充。[CONCEPT: 前端方案] 证据:`DigitalEmployeeDailyWorkChart.vue` 高度改为 `100%` 并保留 `min-height`。 - -## 测试 - -- [x] 更新风险看板源码测试,覆盖中文化和图表化异常排行。[CONCEPT: 测试方案] 证据:`risk-observation-dashboard.test.mjs` 新增中文化 helper 和排行图表断言。 -- [x] 更新数字员工看板源码测试,覆盖布局填充类名和图表高度策略。[CONCEPT: 测试方案] 证据:`digital-employee-dashboard.test.mjs` 新增填充布局断言。 -- [x] 运行风险看板定向测试。[CONCEPT: 测试方案] 证据:`node web/tests/risk-observation-dashboard.test.mjs`,7 passed。 -- [x] 运行数字员工看板定向测试。[CONCEPT: 测试方案] 证据:`node web/tests/digital-employee-dashboard.test.mjs`,4 passed。 -- [x] 运行前端构建验证。[CONCEPT: 测试方案] 证据:`npm.cmd --prefix web run build` 通过,仍有既有 Rollup 注释和大 chunk 警告。 - -## 验收 - -- [x] 确认风险看板可见文案不再暴露常见英文 key。[CONCEPT: 验收标准] 证据:测试覆盖 `duplicate_invoice`、`policy.duplicate_invoice`、`travel`、`rule_center`、`financial_risk_graph` 中文化。 -- [x] 确认异常排行主视觉为图表形式。[CONCEPT: 验收标准] 证据:组件中异常排行由 `BarChart` 的 `rankingChartItems` 驱动。 -- [x] 确认数字员工看板主要图表和卡片减少无效空白。[CONCEPT: 验收标准] 证据:趋势图、饼图、条形图和业务产出卡片均接入可填充容器。 -- [x] 评估提交和推送范围,避免纳入无关脏工作区变更。[CONCEPT: 风险与开放问题] 证据:暂存区限定为分析看板前端、风险标签工具、定向测试和本开发文档,未纳入 `server/storage`、日志、临时截图等无关文件。 diff --git a/document/work-log/2026-06-24.md b/document/work-log/2026-06-24.md index 832c7de..ad577eb 100644 --- a/document/work-log/2026-06-24.md +++ b/document/work-log/2026-06-24.md @@ -445,8 +445,39 @@ - 验证:`node --test web/tests/ai-document-query-model.test.mjs` 通过 17/17;`node --test web/tests/ai-document-query-model.test.mjs web/tests/workbench-intent-frame-model.test.mjs web/tests/workbench-ai-command-intent-model.test.mjs web/tests/workbench-ai-action-router.test.mjs web/tests/workbench-ai-intent-planner-model.test.mjs` 通过 46/46;`npm --prefix web run build` 通过;`git diff --check -- ...` 无输出;`curl -I http://127.0.0.1:5173/app/workbench` 返回 200。 - 影响:用户输入“删除申请单草稿”后,结果标题下方会恢复高风险说明、候选单据卡片和“进入详情确认删除”快捷按钮;系统仍不会直接删除单据,而是要求进入详情核对后再操作。 +- 23:02:我补上了 AI 历史会话里旧详情入口的点击前校验,避免单据已删除后重新进入会话再点“进入详情确认删除/查看详情”跳到坏详情页。 + - Git 提交检查:`git fetch --all --prune` 成功;当前 upstream 为 `origin/main`,`HEAD..@{u}` 与 `@{u}..HEAD` 均未输出新提交;当前工作区还有一个非本轮修改的规则 Excel 文件变更,本轮只修改 AI 工作台点击防护。 + - 根因:历史会话里保存的是静态详情链接,用户删除单据后再重进会话点击,原逻辑会直接 `emit('open-document')` 跳详情页,没有先确认单据是否仍存在;如果后端返回 404,就会在详情页暴露异常状态。 + - 修改:`usePersonalWorkbenchAiMode.js` 将详情链接点击处理改为异步校验;对带 `claim_id` 的 AI 历史详情入口先调用 `fetchExpenseClaimDetail()`,当返回 not found / 不存在 / 已删除 / 不可访问 / 无权时,不再跳转详情。 + - 修改:失效时调用既有 `markAiWorkbenchConversationDocumentDeleted()` 把当前会话里的 `#ai-open-document-detail` 写回 `#ai-deleted-document-detail`,刷新历史列表,并 toast 提示“该单据已经删除或不可访问,已将这条历史入口标记为不可查看。” + - 验证:`node --test --test-name-pattern "deleted document|validates document detail" web/tests/ai-conversation-html-renderer.test.mjs web/tests/assistant-session-draft-delete.test.mjs` 通过 3/3;相关主链路 `node --test web/tests/ai-document-query-model.test.mjs web/tests/workbench-intent-frame-model.test.mjs web/tests/workbench-ai-command-intent-model.test.mjs web/tests/workbench-ai-action-router.test.mjs web/tests/workbench-ai-intent-planner-model.test.mjs` 通过 46/46;`npm --prefix web run build` 通过;`git diff --check -- ...` 无输出;5173 工作台路由返回 200。 + - 影响:用户重新进入历史会话后,如果之前的候选单据已被删除,再点旧快捷入口会在会话内变成“单据已删除/不可查看”,不会进入坏详情页;后端临时网络错误则不会错误失效化链接,会继续按原流程跳转。 + +- 23:10:我修复了 AI 工作台“直接提交”自然语言意图被自动提交的问题,让它先进入申请核对表,用户再次确认后才提交。 + - Git 提交检查:`git fetch --all --prune` 成功;当前 upstream 为 `origin/main`,`HEAD..@{u}` 与 `@{u}..HEAD` 均未输出新提交;工作区仍有一个非本轮修改的通讯费规则 Excel 变更,本轮没有触碰该文件。 + - 根因:`resolveExecutableTravelApplicationPlan()` 原来把包含 `submit_application` step 的计划直接映射为 `autoSubmit: true`;`startAiApplicationPreview()` 又在核对表 ready 时用 `confirmed: true` 调用提交动作,等于把“用户说直接提交”误当成“已核对并确认提交”。 + - 修改:`workbenchAiApplicationGateModel.js` 保留 `requestedSubmit` 语义,但不再给紧凑差旅申请返回 `autoSubmit: true`;`workbenchAiIntentPlannerModel.js` 仍识别 `requestedAction=submit` 和提交步骤,但 executable payload 固定 `autoSubmit: false`,并输出 `requestedSubmit` / `submitRequiresConfirmation`。 + - 修改:`usePersonalWorkbenchAiMode.js` 将确认标志传入申请预览流;`useWorkbenchAiApplicationPreviewFlow.js` 删除预览生成后的自动 `confirmed: true` 提交分支,改为在核对表 footer 提醒“系统不会自动提交申请,请先核对申请核对表”;`workbenchAiMessageModel.js` 持久化这两个确认标志,避免刷新或重进会话后提示丢失。 + - 修改:同步更新 `AI意图规划器` 相关文档,把“直接提交自动走完整链路”改成“先展示核对表,用户确认后进入提交链路”。 + - 验证:先用改过的测试跑出红灯;修复后 `node --test --test-name-pattern "direct-submit|direct submit|requires confirmation|confirmation metadata|intent planner|application gate" ...` 通过 14/14;相关主链路 `node --test web/tests/workbench-ai-application-gate-model.test.mjs web/tests/workbench-ai-intent-planner-model.test.mjs web/tests/ai-document-query-model.test.mjs web/tests/workbench-intent-frame-model.test.mjs web/tests/workbench-ai-command-intent-model.test.mjs web/tests/workbench-ai-action-router.test.mjs` 通过 51/51;`node --test --test-name-pattern "direct-submit|direct submit|direct-submit command" web/tests/expense-application-fast-preview.test.mjs` 通过 2/2;`npm --prefix web run build` 通过;`git diff --check` 无输出;`curl -I --max-time 5 http://127.0.0.1:5173/app/workbench` 返回 200。 + - 影响:用户输入“2026-02-20 至 2026-02-23,去上海出差,辅助国网仿生产服务器部署,交通火车,直接提交”时,系统仍能识别提交目标,但只会生成申请核对表/确认入口,不会直接提交给领导审批。 + +- 23:22:我把统一意图框架里的规则职责进一步收口为“安全策略字段”,避免规则继续承担复杂语义识别。 + - Git 提交检查:`git fetch --all --prune` 成功;当前 upstream 为 `origin/main`,`HEAD..@{u}` 与 `@{u}..HEAD` 均未输出新提交;工作区仍有一个非本轮修改的通讯费规则 Excel 变更,本轮没有触碰该文件。 + - 修改:`workbenchIntentFrameModel.js` 新增 `riskLevel`、`requiresCandidateSearch`、`requiresSelection`、`requiresConfirmation`、`executionMode`、`policyDecision`,让删除、审核、驳回等高风险动作稳定落到候选筛选或确认,而不是从规则里直接推执行。 + - 修改:`workbenchIntentActionPolicy.js` 改为优先消费 `policyDecision`,并把 `riskLevel`、`requiresSelection`、`requiresConfirmation` 透传到 route,方便后续 UI 和 action executor 统一读取。 + - 修改:调整 `resolveAction()` 顺序,让“查 3 天前的申请单”先命中查询动词,不再被裸 `申请` 误判为创建申请;这也是本轮红灯测试暴露出的规则误伤点。 + - 文档:`AI意图规划器/CONCEPT.md` 新增“规则兜底边界”,明确规则只输出安全策略,不拥有副作用授权;同时把第一阶段落地里的自动提交旧描述改为等待核对和二次确认。 + - 测试:先给 `workbench-intent-frame-model.test.mjs` 增加红灯断言,覆盖上下文删除、筛选删除、无风险审核、政策咨询和只读查询的策略字段;修复后该文件通过 8/8。 + - 验证:`node --test web/tests/workbench-intent-frame-model.test.mjs web/tests/ai-document-query-model.test.mjs web/tests/workbench-ai-command-intent-model.test.mjs web/tests/workbench-ai-action-router.test.mjs web/tests/workbench-ai-application-gate-model.test.mjs web/tests/workbench-ai-intent-planner-model.test.mjs` 通过 52/52;`npm --prefix web run build` 通过;`git diff --check` 无输出;`curl -I --max-time 5 http://127.0.0.1:5173/app/workbench` 返回 200。 + - 影响:后续规则层更像 guardrail,而不是继续堆关键词猜测;模型可以负责语义理解,规则负责高风险动作、候选筛选、选择和确认这些稳定边界。 + ## 遗留问题 +- 23:22:本轮只是把现有前端 IntentFrame 的策略字段收口,尚未把后端 LLM 返回的结构化 intent frame 与该策略字段完全统一。建议下一步让 `/steward/plans` 或 runtime decision 输出同名字段,再由前端只做展示和兜底。 +- 23:10:本轮尚未在真实 5173 页面输入完整“直接提交”句子做点击级回放;当前证据来自模型/静态/构建和路由烟测。建议后续真页确认只出现申请核对表和二次确认入口,没有直接生成提交结果。 +- 23:10:`expense-application-fast-preview.test.mjs` 整文件仍有 13 个既有旧静态断言失败,失败点包括旧 assistantName 断言、旧申请 session 静态结构、表格样式和已拆分 composable 的旧代码片段匹配;本轮只验证了 direct-submit 相关子集通过。建议后续单独清理该测试文件,避免继续掩盖真实回归。 +- 23:02:本轮用单元/静态回归覆盖了旧详情入口失效逻辑,但还没有在真实 5173 页面完成“删除单据 -> 重新进入历史会话 -> 点击旧入口”的点击级回放。建议后续用真实草稿跑一次闭环,确认 toast、禁用按钮和历史会话刷新都符合预期。 - 22:49:本轮用渲染级回归测试确认 trusted HTML 已恢复,但还没有做真实浏览器点击级回放和截图复核。建议后续在 5173 输入“删除申请单草稿”,确认真实主题下提示块、候选卡片和按钮没有拥挤或错位。 - 22:42:本轮仍未做真实浏览器点击级回放确认高风险提示在 AI 工作台卡片里的视觉效果。建议后续在 5173 输入“删除申请单草稿”,截图确认提示块、候选卡片和“进入详情确认删除”按钮在当前主题下没有拥挤或错位。 - 22:36:本轮仍未做浏览器点击级回放确认“删除申请单草稿”的实际 thinking 卡片视觉状态。建议后续在真实 5173 工作台输入该句,确认首条 thinking 为删除高风险策略、后续才是查询和筛选候选。 @@ -550,7 +581,13 @@ - [ ] 在真实 5173 AI 工作台输入“删除申请单草稿”,确认首条 thinking 明确显示“删除”高风险策略,且结果只展示申请单草稿候选。(来源:22:36 删除动作 thinking 修复) - [x] ~~为高风险删除/审核候选结果补充用户可见确认边界说明和实体快捷按钮文案。~~(完成于 22:42,证据:`workbench-intent-frame-model.test.mjs` 新增结果提示回归通过,相关前端测试 45/45 通过,前端 build 通过) - [x] ~~修复“删除申请单草稿”高风险提示和候选卡片被 trusted HTML 安全渲染整块丢弃的问题。~~(完成于 22:49,证据:新增渲染级红灯测试后修复,相关前端测试 46/46 通过,前端 build 通过) +- [x] ~~修复 AI 历史会话旧详情入口在单据已删除后仍可跳转坏详情页的问题。~~(完成于 23:02,证据:deleted document / validates document detail 定向测试 3/3 通过,相关主链路测试 46/46 通过,前端 build 通过) +- [x] ~~修复“直接提交”自然语言意图绕过申请核对表并自动提交的问题。~~(完成于 23:10,证据:direct-submit 定向测试 14/14、相关主链路测试 51/51、fast-preview direct-submit 子集 2/2、前端 build 与 `git diff --check` 均通过) +- [x] ~~把前端统一意图框架里的规则职责收口为稳定安全策略字段。~~(完成于 23:22,证据:`workbench-intent-frame-model.test.mjs` 红灯后转绿,相关前端测试 52/52 通过,前端 build 与 `git diff --check` 均通过) - [ ] 在真实 5173 AI 工作台输入“删除申请单草稿”,确认结果卡片上方显示高风险说明,候选单据按钮显示“进入详情确认删除”。(来源:22:42 高风险结果提示补强) +- [ ] 在真实 5173 跑“删除单据 -> 重新进入历史会话 -> 点击旧详情入口”,确认旧入口禁用、toast 提示和历史会话刷新符合预期。(来源:23:02 旧详情入口点击前校验) +- [ ] 在真实 5173 AI 工作台输入“2026-02-20 至 2026-02-23,去上海出差,辅助国网仿生产服务器部署,交通火车,直接提交”,确认系统只生成申请核对表和二次确认入口,不直接提交审批。(来源:23:10 直接提交确认边界修复) +- [ ] 将后端模型计划 / runtime decision 的结构化输出与前端 IntentFrame 策略字段对齐,统一 `riskLevel`、`requiresCandidateSearch`、`requiresSelection`、`requiresConfirmation`、`executionMode`、`policyDecision` 命名。(来源:23:22 规则职责收口) - [ ] 单独修复或重写 `workbench-ai-mode-switch.test.mjs` 的旧静态结构断言,使它适配 `WorkbenchAiFileStrip` 和 OCR composable 拆分后的真实代码。(来源:17:26 额外测试发现) - [ ] 单独修复或重写 `workbench-ai-mode-expense-scene-action.test.mjs` 与 `expense-application-fast-preview.test.mjs` 中继续扫描旧 Vue 单文件的静态断言,改为覆盖 composable/model 的行为测试。(来源:17:40 上下文提交验证) - [ ] 在真实 5173 AI 工作台回放“2026-02-20 至 2026-02-23,去上海出差,辅助国网仿生产服务器部署,交通火车”,确认唯一申请候选流直接生成申请核对表。(来源:17:48 无动作话术直进申请预览修复) diff --git a/document/work-log/2026-06-25.md b/document/work-log/2026-06-25.md index 472cccb..7ff2ac0 100644 --- a/document/work-log/2026-06-25.md +++ b/document/work-log/2026-06-25.md @@ -18,11 +18,25 @@ - 验证:两个 `SKILL.md` frontmatter 分别校验通过,路径规则检索命中,两个技能副本的模板和 UI 元数据 diff 一致,`git diff --check -- .codex/skills/write-development-docs hermes/skills/domain/write-development-docs` 通过。 - 影响:后续新功能落文档会先按日期建目录,再进入 `feature`,最后按具体功能点独立建目录,便于按天回溯和按功能点拆分。 +- 21:30:我针对 AI 工作台意图门控做了三处加固,守住高风险动作的确认底线、补齐缺失的兜底与预筛逻辑。 + - Git 提交检查:`git fetch --all --prune` 后 origin/main 落后本地 0、领先本地 0;本地 ahead 3 个提交(`6b0756a5`/`4d8a606c`/`23f7de6c`),均与本任务无关;工作区有大量未提交改动,本次只动 `web/src/composables/workbenchAiMode` 与对应测试。 + - 背景:先通读门控全链路(`workbenchAiApplicationGateModel` / `workbenchIntentFrameModel` / `workbenchIntentActionPolicy` / `workbenchAiIntentPlannerModel` / `useWorkbenchAiCommandIntents` / `useWorkbenchAiActionRouter` / `usePersonalWorkbenchAiMode`),确认高风险动作(删除/审核/驳回)一律 `requiresConfirmation` 且执行出口无 `execute_allowed`、政策类问题被挡在执行链路外、直接提交需二次确认——安全底线稳。 + - 修改①(低置信度反问):`workbenchAiIntentPlannerModel.js` 新增 `WORKBENCH_AI_INTENT_CONFIDENCE_THRESHOLD=0.6` 与 `isLowConfidenceTravelApplicationPlan`;规则兜底(rule_fallback)与显式 submit/save_draft 不计为低置信。`usePersonalWorkbenchAiMode.js` 在可执行 travel 计划前插入低置信分支,新增 `startModelPlannedTravelApplicationConfirmation` 与 `buildLowConfidenceTravelApplicationConfirmationText`,反问消息携带 `ai_application_confirm_intent` 动作。`useWorkbenchAiActionRouter.js` 新增 `ai_application_confirm_intent` 分支,还原 ontologyFields/提交标记后调用 `startAiApplicationPreview`。 + - 修改②(闲聊预筛):`shouldRequestWorkbenchAiIntentPlan` 增加业务关键词正则,「你好/谢谢/嗯/ok」等闲聊不再发起 35s 的模型规划请求,直接落到通用 steward 回复。 + - 修改③(报销兜底核查):复查确认 `executeModelPlannedWorkbenchIntent` 的 catch 分支不 return 时,`isReimbursementCreationIntent(cleanPrompt)` 在后续 823 行仍会被求值,报销兜底天然可达,无需新增重复分支,本次未改动。 + - 验证:`workbench-ai-intent-planner-model.test.mjs`(20/20,含新增 3 个用例)、`workbench-ai-application-gate-model.test.mjs`(5/5)、`workbench-intent-frame-model.test.mjs`(8/8)全绿;`expense-application-fast-preview.test.mjs` 既有 12 个失败(「小财管家」文案/表格渲染问题,与本次无关),本次改动额外使 `not ok 2 - AI workbench routes compact travel direct-submit planner` 由失败转通过,无新增失败。 + - 影响:模型给出低置信度差旅申请意图时不再直接建预览,先反问确认;闲聊类输入不再误触发模型规划,响应更快、减轻后端压力。 + - 局限:`agent-change-log` Skill 在当前环境不可调用,已按 AGENTS.md 规范手动增量更新本日志。 + ## 遗留问题 - 09:18:官方 `quick_validate.py` 仍因当前 Python 环境缺少 `PyYAML` 无法运行,已用 frontmatter、必需文件、占位符和 diff check 做人工兜底。建议后续统一为 skill 校验脚本补齐依赖或增加无 PyYAML 的轻量校验路径。 - 09:23:当前环境没有找到 Skill Creator 的 `quick_validate.py` 脚本文件本体,因此本次继续采用人工兜底校验。建议后续恢复系统 Skill Creator 脚本路径,或把轻量校验脚本纳入仓库级工具。 +- 21:30:`expense-application-fast-preview.test.mjs` 仍有 12 个既有失败(文案「小财管家」「此意图系统不支持」与 markdown 表格整块渲染相关),与本次意图门控改动无关,建议单独排查。 +- 21:30:本次未纳入范围的三项已记录:时间过滤维度扩展(仅支持 N天前/昨天/今天)、排除词两处重复维护、`handleInlineDraftDeletionIntent` 命名与职责不符,建议后续分批处理。 ## TODO - [ ] 为 `quick_validate.py` 准备稳定运行环境,避免后续新增 Skill 时继续依赖人工兜底。(来源:09:18 技能校验) +- [ ] 排查 `expense-application-fast-preview.test.mjs` 的 12 个既有失败(小财管家文案 / 表格整块渲染)。(来源:21:30 意图门控加固) +- [ ] 评估意图门控剩余三项:时间过滤维度扩展、排除词常量抽取、`handleInlineDraftDeletionIntent` 重命名。(来源:21:30 意图门控加固) diff --git a/server/rules/finance-rules/公司通信费报销规则.xlsx b/server/rules/finance-rules/公司通信费报销规则.xlsx index 948de19..2107e72 100644 Binary files a/server/rules/finance-rules/公司通信费报销规则.xlsx and b/server/rules/finance-rules/公司通信费报销规则.xlsx differ