feat: 增强规则资产管理与审计页面运行时调试

后端新增规则资产版本管理和规则文件 CRUD 接口,优化风险
规则生成模板执行和员工数据模型字段,知识库 RAG 增强本
地回退和文档提取能力,清理旧风险规则文件统一由生成引擎
管理,前端审计页面增加运行时调试面板和规则资产编辑交互,
补充单元测试覆盖。
This commit is contained in:
caoxiaozhu
2026-05-24 21:44:17 +08:00
parent 575f093c74
commit 50b1c3f9a9
113 changed files with 13896 additions and 5044 deletions

View File

@@ -0,0 +1,41 @@
# Hermes 后台智能体架构总览
## 1. 定位与愿景
Hermes 是 X-Financial 系统中的**后台自动巡检与数据洞察中枢**。与处理实时对话的 UserAgent 不同Hermes 专注于异步、长周期、大批量的任务,核心价值在于提供事前的**深度风险挖掘**和定期的**业财洞察报告**。
## 2. 系统拓扑图
```mermaid
graph TD
subgraph 调度层
A[Cron Scheduler] -->|定时触发| B[Task Queue]
end
subgraph Hermes Agent 层
B -->|消费任务| C(Hermes Worker)
C --> D[Task Skills Router]
D --> E{RiskScanner Skill}
D --> F{ExpenseReport Skill}
D --> G{KnowledgeCheck Skill}
end
subgraph X-Financial 核心服务
E <--> H[(Expense DB)]
F <--> H
G <--> I[(LightRAG Graph/Vector)]
C <--> J[LLM Gateway / OpenAI]
C --> K[Notification Service / 企业微信]
end
```
## 3. 核心设计原则
1. **防抖与限流**:后台全量扫表时,必须分片执行,防止对主数据库造成 I/O 拥堵。
2. **幂等性保障**:每一个扫描任务和报告生成任务都应该具备唯一幂等键,避免因进程重启导致的重复发信或重复扣减信用分。
3. **隔离性**Hermes 的进程应与对外提供 API 服务的 Web Server 物理/逻辑隔离大模型限流策略Token Rate Limit应配置相互独立的账单通道。
## 4. 核心执行链路(示例:夜间风控巡检)
1. 凌晨 02:00Cron 触发 `trigger_risk_scan` 任务。
2. Worker 拉取状态为 `draft``submitted``risk_scanned=False` 的单据。
3. 将近三个月的相关人员单据聚类,构建 Context。
4. 调用大模型,寻找“拆单”、“合谋”、“时间/地点异常”等隐蔽风险。
5. 将发现的风险写入 `hermes_risk_report` 表,并标记对应单据。
6. 任务结束,更新执行日志,等待早晨财务主管查阅。

View File

@@ -0,0 +1,46 @@
# Hermes 数据库表结构设计
为了支持后台异步任务的执行和长期记忆(风险标记、执行结果归档),我们需要在数据库中增加(或扩充)以下表结构。
## 1. 任务调度与执行表
### `hermes_task_config` (定时任务配置表)
用于管理所有的后台巡检和推送任务,支持动态调整频率与开关。
- `id`: string (UUID)
- `task_type`: string (enum: `global_risk_scan`, `weekly_expense_report`, `kb_validation`...)
- `cron_expression`: string (e.g., `0 2 * * *`)
- `is_enabled`: boolean (默认 True)
- `payload_template`: jsonb (预留参数,如扫描的时间窗口、特定部门过滤条件等)
- `updated_at`: datetime
### `hermes_task_execution_log` (任务执行日志表)
记录每次任务的执行状态,便于排错与溯源。
- `id`: string (UUID)
- `config_id`: string (外键,关联 `hermes_task_config`)
- `started_at`: datetime
- `completed_at`: datetime
- `status`: string (enum: `running`, `success`, `failed`)
- `result_summary`: string (执行结果的简要说明,如“扫描了 1500 条单据,发现 12 条高危”)
- `error_trace`: text (如果失败,存储错误堆栈)
## 2. 深度分析结果表
### `hermes_risk_report` (深度风险报告表)
用于存储 LLM 找出的深层逻辑风险。
- `id`: string (UUID)
- `claim_id`: string (外键,关联存疑的主单据 `expense_claim`)
- `execution_log_id`: string (外键,由哪次扫描任务产生的)
- `risk_level`: string (enum: `low`, `medium`, `high`, `critical`)
- `risk_type`: string (enum: `split_billing` 拆单, `collusion` 合谋, `policy_violation` 违规...)
- `risk_description`: text (大模型生成的自然语言报告,如“该单据与前天提交的单据存在拆分可能...”)
- `related_claim_ids`: jsonb (存储关联的同谋/相关单据 ID 列表,提供上下文线索)
- `status`: string (enum: `pending_review` 待人工复核, `confirmed` 已确认为风险, `dismissed` 已忽略)
## 3. 现有表的平滑改造
### 修改 `employee` 表 (员工信用分预留)
- **新增字段** `compliance_score`: int (默认 100由 Hermes 动态扣减或恢复,用于风控引擎调节对该员工的抽查率和宽容度)
### 修改 `expense_claim` 表 (风控标记)
- **新增字段** `hermes_scanned_at`: datetime (记录该单据上次被 Hermes 扫描的时间,防止重复扫描)
- **新增字段** `hermes_risk_flag`: boolean (快速判断该单子是否被挂载了 `hermes_risk_report`)

View File

@@ -0,0 +1,32 @@
# 深度风险扫描模块设计 (Risk Scan Module)
## 1. 业务目标
将单点硬规则风控(如:发票大于 500 元是否合规)升级为**图谱式全局风控**。Hermes 将利用大语言模型LLM的逻辑推理能力在海量历史数据中寻找隐藏的违规模式。
## 2. 核心扫描链路
本模块将作为一个独立的 Skill 被定时任务触发。
### 第一步:数据快照聚合
- **提取目标**:拉取状态为 `draft``submitted` 且最近 30 天内活跃的报销单,同时带出相关的发票明细。
- **降维处理**:为避免超出大模型的 Token 上下文限制,必须对单据信息进行降维。仅提取:`申请人、时间、地点、商户名、金额、报销类型` 形成精简的 CSV 或 JSON Lines 格式。
### 第二步:大模型批量推理 (LLM Batch Inference)
- **风险定义植入**:通过 System Prompt 将目前财务最头疼的几类风险定义给模型(如拆单、套现、虚假连号发票)。
- **执行方式**:将数据按“同部门”或“同地域”分块 (Chunking) 喂给大模型。
- **Prompt 示例**
```markdown
你是一个内控审计 Agent。以下是某部门近半个月的报销流水清单。
请找出其中是否存在:
1. 拆单行为(同人、同地点、连日、小额累加)
2. 聚众套现行为(不同人、同偏僻餐馆、同日极高额)
如果发现风险,请输出对应的单号集合以及你的推理过程。
```
### 第三步:风险标记与处置
- 解析大模型返回的结构化 JSON。
- 对被判定的高危单据,在主库中插入 `hermes_risk_report` 记录。
- **动作反馈**:如果该单据正处于 `submitted` 状态,并且得分极高(如虚假连号发票),可以通过 X-Financial 原有接口自动注入“退回”动作,并附加大模型的分析日志。
## 3. 防抖与自我迭代
- **扫描去重**:利用 `expense_claim.hermes_scanned_at` 防止已经出具过报告的单据被重复投入分析队列。
- **人工纠偏 (Human-in-the-loop)**:当财务在前端驳回 Hermes 的风险提示即认为没问题事件将被记录。Hermes 可通过夜间的反思任务优化下一次 Prompt 中的判定容忍度。

View File

@@ -0,0 +1,34 @@
# 动态费控与洞察报告模块设计 (Expense Report Module)
## 1. 业务目标
基于海量的流水账单,定期(周/月)由 Hermes Agent 为部门管理者或财务总监自动生成具有**业务洞察力**的归因分析报告,将冷冰冰的数字转化为具有指导意义的自然语言建议。
## 2. 核心分析链路
### 第一步BI 数据聚合 (Data Aggregation)
- 借助 ORM 或底层 Data Warehouse (如有)Hermes 执行预置的聚合查询。
- **采集核心指标**
- 本期各部门总花费及环比/同比变动率。
- 各类目(如打车、机票、住宿、招待)的占比变化。
- Top 10 花费最多的商户(如特定几家酒店或订票平台)。
- 各类目超额/退回率最高的人员画像。
### 第二步:大模型归因分析 (LLM Attribution Analysis)
将硬性的聚合数据转化为结构化 Prompt让 LLM 充当“财务分析师”。
- **Prompt 示例**
```markdown
你是企业的财务总监助理,请阅读以下【本月报销聚合数据】。
请帮我撰写一份 300 字以内的执行摘要报告。
重点指出:
1. 哪个部门/哪类费用增长最快?原因可能是什么?
2. 我们的长尾开销集中在哪些商户?是否存在能够跟商户谈“协议价”的谈判空间?
```
### 第三步:多渠道报告分发 (Report Delivery)
- **生成制品**Hermes 利用代码解释器 (如有) 或 Markdown 引擎,将图表与文本融合成正式的 PDF 或长图。
- **触达渠道**
- **推送机制**:调用企微/钉钉机器人 API直接向管理者的工作台推送“上周费控简报”。
- **交互追问**:管理者收到简报卡片后,可以在对话框里直接@Hermes 追问:“详细列一下研发部上周在北京住宿的那 5 万块钱是怎么花的”Hermes 将调取缓存的报告上下文立即答复。
## 3. 商业价值落地
这项功能极大地解放了财务部的报表处理时间。通过提供前置的谈判线索(如发现某经济型酒店的高频住客其实都可以导流到协议酒店),可以给公司带来直接的差旅成本节约。

View File

@@ -0,0 +1,63 @@
# 部署与任务调度架构方案 (Deployment & Cron)
## 1. 业务诉求分析
Hermes 作为纯后台的智能体,它的执行过程长达几分钟甚至几小时。它绝不能与提供给前台 HTTP 请求的主 Web 服务混合在同一个事件循环Event Loop或同步进程中否则会导致 API 严重堵塞和超时崩溃。
因此Hermes 的部署需要进行**进程级解耦**。
## 2. 选型对比与推荐方案
### 方案 ACelery + Redis (重型/工业级标准)
- **优势**:业界最成熟的 Python 异步任务队列,支持极其复杂的 Cron 配置,原生支持任务重试、失败回调以及分布式扩展。
- **劣势**:增加系统组件(必须额外部署 Redis / RabbitMQ 容器),运维成本相对较高。
- **结论**:如果 X-Financial 后续要承载上千人的企业报销,这是**首选必经之路**。
### 方案 BAPScheduler + Background Worker (中型/轻量级)
- **优势**:直接在 Python 进程内运行,无需额外的消息队列组件。可以用一个单独的 Docker 容器运行 `python run_hermes_scheduler.py`
- **劣势**:多节点部署时难以控制并发(可能会多个节点同时执行同样的任务),需要引入基于数据库表或 Redis 的分布式锁。
- **结论**:适合初期快速跑通 MVP 的方案。
## 3. 推荐架构:基于 Redis 分布式锁的独立容器方案
结合当前现状,建议采用 **方案B 叠加 分布式锁** 的轻量微服务架构。
### 部署拓扑:
```yaml
# docker-compose.yml 示例切片
services:
x-financial-api:
build: .
command: uvicorn main:app
ports:
- "8000:8000"
x-financial-hermes:
build: .
command: python scripts/start_hermes_daemon.py
# 这个容器不暴露外部端口,纯粹在后台运行定时任务和消费队列
```
### 执行伪代码 (`start_hermes_daemon.py`)
```python
from apscheduler.schedulers.blocking import BlockingScheduler
from app.services.system_hermes import SystemHermesService
scheduler = BlockingScheduler()
hermes = SystemHermesService()
# 每天凌晨 3 点执行深度风控扫表
@scheduler.scheduled_job('cron', hour=3, minute=0)
def job_risk_scan():
# 获取分布式锁防止集群脑裂重复执行
if acquire_redis_lock("hermes:lock:risk_scan"):
try:
hermes.run_query("执行全局风控扫描技能...", skills=["global_risk_scan"])
finally:
release_redis_lock("hermes:lock:risk_scan")
if __name__ == "__main__":
scheduler.start()
```
## 4. 容灾与可观测性保障
- **日志采集**:确保 `hermes.run_query` 及其后台生成的 stdout/stderr 日志能够写入 ELK 或文件系统中,方便第二天的运维排查。
- **告警链路**:如果调度系统挂掉或者大模型连续多次返回失败状态码,必须通过 Webhook 飞书/钉钉及时告警系统管理员。