# 衡审 · AI-Agent 财务审计系统 基于用户提供的 18 份技术课件实现的完整本地系统:员工报销与发票、四节点 LangGraph 审核、独立人工反馈、多级审批、Agent 与规则版本配置、政策检索、审计日志、告警和报表。界面、业务注释及接口说明均为中文。 本项目选择 **Vue 3 + TypeScript + Element Plus + Pinia + FastAPI + SQLAlchemy async + SQLite**。前后端真实访问数据库和接口;没有外部模型服务时也能完成用户填报、规则审核与人工审批,并明确显示降级原因。课件阅读结论见 [文档阅读清单](docs/文档阅读清单.md),实现对照见 [设计与实现说明](docs/设计与实现说明.md)。 ## 架构 ```mermaid flowchart LR UI[Vue / Element Plus] -->|Bearer / JSON / 文件 / SSE| API[FastAPI /api/v1] API --> AUTH[身份、角色、所有权与版本护栏] AUTH --> APP[应用服务 / 短写事务] APP --> DB[(SQLite WAL)] APP --> FILE[本地发票文件] APP --> EVENT[(持久 outbox)] EVENT --> WORKER[单实例异步消费者] WORKER --> GRAPH[LangGraph] GRAPH --> E[extract / 发票提取] E --> R[rule_check / 七类规则] R --> K[risk_detect / 双引擎] K --> D[make_decision / 确定性路由] E --> AI[真实外部 VLM / LLM] R --> POL[政策分块 / Embedding / COSINE / Rerank] D --> APPROVE[冻结审批链 / 人工签署] APPROVE --> FEEDBACK[独立 feedback / 不执行训练] WORKER --> ALERT[站内持久告警] APP --> LOG[操作与变更日志] ``` 完整文件树见 [项目目录结构](docs/项目目录结构.md)。`backend/app/api` 放接口,`application` 放编排、审批和队列,`domain` 放模型与规则,`infrastructure` 放数据库、真实 AI、文件和密码,`shared` 放配置、金额与请求契约;`frontend/src/views` 包含全部业务页面。 ## 环境准备 - Python **3.11+**;实测 Python **3.12.14**。建议在虚拟环境中安装。 - Node.js **24+**;实测 Node **24.15.0**、npm **11.12.1**。 - Windows PowerShell;需要首次下载 pip/npm 依赖的网络连接。无须 Docker、GPU、Redis、PostgreSQL、Milvus 或 MinIO。 - 默认后端 `127.0.0.1:8000`,前端 `127.0.0.1:5173`,端口必须空闲。仅启动一个后端实例,不使用多 worker。 所有项目内路径都根据项目本身解析。代码可放在指定的 `D:\HuaweiMoveData\Users\HUAWEI\Desktop\agent\docs\docs\course_html\code`,也可把整个 `code` 文件夹复制到其他可写位置。交付包不包含本机数据库、访问凭据、上传文件、node_modules 或虚拟环境。 ## 安装、初始化与启动 ### 1. 后端环境与依赖 进入 `code/backend` 后执行: ```powershell python -m venv .venv .\.venv\Scripts\python.exe -m pip install -r requirements.txt Copy-Item .env.example .env ``` 无需激活 PowerShell 脚本就能使用虚拟环境,避免为启动项目修改执行策略。`requirements.txt` 固定直接运行依赖,`requirements-lock.txt` 记录本次完整安装版本;如需完全复现,可用后者安装。已验证 `pip check` 没有依赖冲突。 ### 2. 初始化数据库 ```powershell .\.venv\Scripts\python.exe scripts\migrate.py upgrade .\.venv\Scripts\python.exe scripts\init_db.py ``` `migrate.py` 以 UTF-8 读取配置并调用 Alembic,兼容默认 GBK 的 Windows;请使用此入口,避免 Alembic 直接以系统 locale 解码中文 INI。首次直接启动 `main.py` 也会建初始表、登记 `0001_initial` 并初始化基础数据。重复初始化不会重置账户密码或规则。以后升级数据库结构须提供明确增量迁移;`create_all` 不会自动修改旧表。 默认 `SEED_DEMO=true` 创建一组本地测试账户,共用初始密码 **Demo@2026!**: | 登录名 | 角色 | 可以体验的主要功能 | |---|---|---| | alice | 员工 | 自己的报销、上传、审核、政策阅读 | | bob | 主管 | 同部门查看、本人审批待办、告警 | | carol | 财务审计员 | 全局审计证据、Agent/规则查看与测试、政策管理、日志 | | dave | 经理 | 以上查看能力、审批链配置、报表导出、用户名单 | | erin | 管理员 | 用户/部门、Agent/规则版本配置;不能代签或自审 | 示例主管链指派 bob,财务/人工链指派 carol。没有企业政策、真实发票或法定税率种子。更改 `DEMO_PASSWORD` 只影响首次创建,已有账户不会被覆盖。 ### 3. 启动后端 ```powershell .\.venv\Scripts\python.exe main.py ``` 访问 [健康检查](http://127.0.0.1:8000/api/v1/health) 与 [交互接口文档](http://127.0.0.1:8000/docs)。健康检查应显示数据库 `ok` 和消费者 `running`。`configured` 只表示已配置模型,不表示已验证服务质量。 ### 4. 启动前端(新终端) 进入 `code/frontend`: ```powershell Copy-Item .env.example .env npm install npm run dev ``` 打开 [前端登录页](http://127.0.0.1:5173)。复现锁文件推荐 `npm ci`;生产构建执行 `npm run build`。前端使用 Vite 原生配置加载与 dayjs ESM 别名,避免受限 Windows 环境依赖预打包扫描盘符根目录。首次页面加载可能稍慢,随后浏览器缓存会复用模块。 生产部署应由 Web 服务器提供 `frontend/dist`,对 `/api/v1` 做反向代理,对 Vue 路由做 SPA 回退;`npm run preview` 仅检查构建,不是生产服务器。 ### 用户指定的简化自检命令 以下命令在已选择正确 Python 环境、Node 24+ 且终端支持 `&&` 时可直接执行;PowerShell 7 和 Git Bash 支持: ```bash # 后端:首次启动自动初始化初始数据库 cd code/backend && pip install -r requirements.txt && python main.py # 前端:另开终端 cd code/frontend && npm install && npm run dev ``` Windows PowerShell 5.1 请分行执行,不使用 `&&`。若 npm 默认缓存目录没有写权限,可临时使用 `npm install --cache ./npm-cache`,或复用工作区已获授权的缓存目录。 ## 完整体验流程 1. alice 登录,新建申请,填写含税金额;上传真实 PNG/JPEG/PDF。默认每张 10MB、每批 20 张、PDF 最多 5 页;不同发票应拆分上传。 2. 未配置 VLM 时通过“补录”表单填写原票日期、金额、税额、购方、销方和其他已知字段;未知留空。税率填小数,如原票明确为 6% 时填 `0.06`,不得推测。 3. 提交后跳转审核结果,查看真实节点执行、耗时、提取来源、每条规则和风险依据。缺少关键证据转人工;中风险/部分合规转主管;高风险/失败转财务;明确低风险且全部所需检查通过才自动批准。 4. 退出后用指定审批人登录,在“审批待办”查看审核证据并签署。可通过、驳回或退回草稿;所有动作必须填写依据。签署后“已处理 / 历史”可提交反馈,反馈不覆盖原证据、不执行训练。 5. 审计员在告警中心确认再解决异常;规则或模型降级产生的原始结果仍保留。经理可导出 Excel/PDF,审计员可导出日志 CSV。 无外部 AI 时,完整填报发票通常形成中风险、政策未完成检查,并进入主管审批。缺少金额或日期则转人工。这是明确的降级路径,不能理解为模型已识别成功。 ## 配置与真实模型接入 全部后端设置见 `.env.example` 和 `app/shared/config.py`;前端设置见 `.env.example` 和 `vite.config.ts`。 | 配置 | 影响 | |---|---| | PORT / FRONTEND_PORT / BACKEND_URL | 后端端口、前端端口、开发代理目标;修改要同步 | | CORS_ORIGINS / VITE_API_BASE | 允许的前端来源与 API 前缀;默认 `/api/v1` | | DATA_DIR / DATABASE_URL | 本地运行目录与 SQLite async URL;本版数据库实现仅验证 SQLite | | JWT_SECRET / ACCESS_MINUTES / REFRESH_DAYS | 服务端密钥、访问令牌时效、轮换刷新会话时效 | | BUSINESS_TIMEZONE | 单号及开票日期审核业务时区;数据库和接口时间为 UTC | | SEED_DEMO / DEMO_PASSWORD | 本地示例账户开关及首次创建密码 | | LLM_BASE_URL / LLM_MODEL / VLM_BASE_URL / VLM_MODEL | 兼容 `/chat/completions` 的服务根地址和准确模型名称 | | AI_API_KEY | 外部 AI 统一 Bearer 凭据,只存后端,不注入 VITE 变量 | | EMBEDDING_BASE_URL / EMBEDDING_MODEL / EMBEDDING_DIMENSION | 真实文本向量服务、同模型回退标识、维度,默认 1024 | | RERANK_BASE_URL | 可选精排服务;故障保留基础排序并标记 | | AI_TIMEOUT / AI_CONCURRENCY / AI_FAILURE_THRESHOLD / AI_RECOVERY_SECONDS | 超时、全局并发、熔断阈值、半开恢复冷却 | | WORKER_ENABLED / OUTBOX_ATTEMPTS / WORKER_INTERVAL | 消费者开关、持久任务尝试上限和轮询间隔 | | APPROVAL_TIMEOUT_HOURS / TIMEOUT_SCAN_SECONDS | 审批逾期阈值和告警扫描频率 | | MAX_UPLOAD_MB / MAX_BATCH_FILES / MAX_PDF_PAGES | 上传内容限制,以服务端校验为准 | | PDF_FONT_PATH | 可选中文 TTF 文件;默认 PDF 使用 STSong-Light CID 字体 | LLM/VLM 地址通常包含服务的 `/v1` 前缀;客户端追加 `/chat/completions`,需要服务支持 JSON Schema `response_format`。没有 VLM 专用配置时复用 LLM 地址/模型,复用模型必须真实支持视觉输入。返回内容可为 JSON 或包裹 JSON 的文本,但最终必须通过 Pydantic 字段校验。 Embedding 自定义协议:POST `{EMBEDDING_BASE_URL}/embeddings`,请求 `{"texts":["原文"]}`,响应 `{"vectors":[[1024个真实数值]]}`。协议失败时可向 LLM 根地址的 `/embeddings` 发送 `{"model":"配置的同一模型","input":["原文"]}`;维度/数量/有限数值/非零向量均校验,不生成随机向量。Rerank POST `/rerank`:`query` 和 `documents`,响应 `results` 数组,每项包含 `index`、`relevance_score`,必须覆盖全部候选。详细协议见 [AI 与接口文档](docs/接口文档.md)。 政策正文可录入或导入 UTF-8 txt/md,先生成中文分块;配置真实 Embedding 后点击“重建索引”。“关键词检索”本地可用且明确标识;“语义检索”要求已建真实向量。政策审核引用冻结快照中的片段 ID、原文、标题和版本;没有真实依据时记录未完成,不默认通过。 ## 接口文档 统一前缀 `/api/v1`。除登录、刷新、健康外需要 `Authorization: Bearer `;认证后的角色和资源所有权在服务端校验。 成功 JSON 为 `{"data":业务值,"message":"操作成功","request_id":"请求追踪编号"}`;失败 JSON 为 `{"error":{"code":"稳定错误码","message":"原因","details":附加信息},"request_id":"请求追踪编号"}`。分页 `data` 为 `items/total/page/page_size`。金额以十进制字符串返回,UTC 时间带 `Z`。上传/进度为 SSE,下载和导出为文件字节,不能按普通 JSON 解析。 | 模块 | 主要接口(相对统一前缀) | |---|---| | 身份 | POST `/auth/login`、`/auth/refresh`、`/auth/logout`;GET `/auth/me` | | 用户与部门 | GET/POST `/users`、`/departments`;PATCH 各自 `/{id}` | | Agent | GET `/agents`、`/agents/{node}`;PATCH 配置;POST `/{node}/test` | | 规则 | GET `/rules`、`/rules/{code}`;PATCH 新版本;POST `/{code}/test` | | 报销 | GET/POST `/reimbursements`;GET/PATCH `/{id}`;POST `/{id}/submit`、`/{id}/withdraw` | | 发票 | POST `/reimbursements/{id}/invoices` multipart SSE;PATCH/DELETE `/invoices/{id}`;GET `/{id}/file` | | 审核 | GET `/audit`、`/audit/{id}`、`/{id}/events` SSE;POST `/{id}/rerun`、`/{id}/feedback` | | 审批 | GET `/approvals`;POST `/{id}/decide`;GET/POST `/approvals/chains`、PATCH 链 `/{id}` | | 政策 | GET/POST `/knowledge/documents`;POST `/import`、`/{id}/reindex`;PATCH `/{id}`;POST `/knowledge/search` | | 日志与告警 | GET `/logs`、`/logs/export`、`/alerts`;POST `/alerts/{id}/acknowledge`、`/resolve` | | 统计与健康 | GET `/stats/overview`、`/stats/export?format=xlsx或pdf`、`/health` | 完整 **52 个方法 / 43 条路径**、请求字段、错误语义及 SSE 示例见 [接口文档](docs/接口文档.md) 和 [OpenAPI 快照](docs/openapi.json)。运行中的 `/docs` 提供可直接填写参数的交互文档。 ## 自检与已验证范围 ```powershell # backend 目录 .\.venv\Scripts\python.exe -m pip install -r requirements-dev.txt .\.venv\Scripts\python.exe -m pytest -q .\.venv\Scripts\python.exe -m pip check .\.venv\Scripts\python.exe -m compileall -q app main.py scripts migrations .\.venv\Scripts\python.exe scripts\migrate.py current # frontend 目录 npm ci npm test npm run build ``` 测试使用临时独立数据库,不能把测试设置应用到实际业务库。结果和浏览器截图见 [自检报告](docs/自检报告.md)。真实外部模型、生产负载和公网部署未提供环境,不能据测试声明零缺陷或真实识别精度达标。 本版适合单实例本地/小规模使用:SQLite 单写事务、进程内并发限制、持久 outbox 至少一次消费、副作用幂等。向量为应用内 COSINE 扫描;缓存是精确输入哈希缓存,不是近似语义缓存;日志为应用操作与请求追踪,不宣称具备签名防篡改存储。要扩为多实例,需要真实部署的 PostgreSQL、分布式队列、集中存储/限流等改造。课程中的税号格式不是法律验真,系统结论需要企业提供的政策和人工授权闭环。 生产配置至少设 `APP_ENV=production`、`SEED_DEMO=false`、足够长的 `JWT_SECRET`,再用 `python scripts/create_admin.py --username 管理员英文登录名 --name 姓名 --department 部门名称` 交互创建管理员。备份需覆盖 SQLite 数据库与上传目录;修改数据目录或数据库 URL 前要迁移文件,单独复制数据库无法还原原票。