# 南方基金智能业务平台 本项目是一个基于 FastAPI 和 MVC+S 架构的金融业务 Agent 平台,当前包含以下三项核心业务: 1. 场外基金申购/赎回运营流程 2. 产品推介材料与宣传海报生成 3. 金融自然语言转 SQL(NL2SQL)查询 项目中的场外基金运营、产品推介材料与场内基金模拟交易相互隔离。场外业务使用独立的 `offsite_fund_*` 数据表和接口,不写入场内交易表。 ## 一、技术栈 - Python `3.13` - FastAPI、Uvicorn - SQLAlchemy 2.x、Alembic - MySQL、Redis - Pydantic v2 - JWT + RBAC - `python-pptx`、OpenPyXL、Pillow、Matplotlib - 可选:阿里云 DocMind/OCR、DeepSeek、SMTP、Milvus、Neo4j ## 二、项目结构 ```text group_fqcd_jr/ ├── app/ │ ├── api/controllers/ # HTTP 路由和请求参数校验 │ ├── api/schemas/ # 请求/响应模型 │ ├── core/ # 业务契约、配置和公共规则 │ ├── model/ # SQLAlchemy 数据模型 │ ├── service/ # 业务编排、规则和数据访问 │ ├── infrastructure/ # 数据库、缓存和外部基础设施适配 │ └── worker/ # 异步 Worker ├── data/ # 测试与演示数据集 ├── docs/ # 架构、接口、数据库和业务说明 ├── tests/ # 单元、契约、集成和环境测试 ├── tools/ # 迁移、种子、检查和测试工具 ├── alembic/ # 数据库迁移 ├── hq.py # 南方基金行情数据适配模块 ├── nl2sql_yc.py # 金融 NL2SQL 兼容入口和查询逻辑 ├── .env.example # 环境变量模板 └── README.md ``` ## 三、环境准备 项目要求 Python `>=3.13,<3.14`。建议使用独立虚拟环境: ```powershell conda create -n jr_py313 python=3.13 conda activate jr_py313 pip install -r requirements.txt ``` 复制配置文件: ```powershell Copy-Item .env.example .env ``` 然后根据本机环境修改 `.env`,至少配置: ```text MYSQL_DSN JWT_PRIVATE_KEY_PATH JWT_PUBLIC_KEY_PATH ``` `.env`、JWT 私钥、模型密钥和真实外部服务凭据禁止提交到 Git。 ## 四、启动服务 ### 4.1 数据库迁移 请确保 MySQL 已启动,并且 `.env` 中的数据库连接可用: ```powershell alembic upgrade head python tools/audit_schema.py ``` ### 4.2 启动 HTTP 服务 ```powershell python -m uvicorn app.main:app --host 127.0.0.1 --port 8099 ``` 服务地址: ```text http://127.0.0.1:8099 ``` OpenAPI 文档: ```text http://127.0.0.1:8099/docs ``` ### 4.3 启动 Worker 需要异步处理 Agent 运行或场外邮件时,另开终端: ```powershell python -m app.worker ``` Worker 是否启用场外收信,取决于: ```text OFFSITE_MAIL_WORKER_ENABLED OFFSITE_IMAP_ENABLED OFFSITE_WORKER_USER_ID ``` ## 五、功能一:场外基金申购/赎回 ### 5.1 功能说明 场外流程面向运营人员,主要处理: ```text 邮件接收 → 附件保存 → OCR/文档识别 → 结构化字段提取 → 申购/赎回规则计算 → NL2SQL 查询资金和持仓数据 → 运营人员确认 → 创建通知 → 发送或 dry-run → 审计和统计 ``` 支持的单据类型: - `subscription`:申购 - `redemption`:赎回 - `summary`:汇总材料 - `other`:其他材料 系统保留原始邮件、附件、识别结果、查询记录、规则结果、人工修正记录和审计记录。 人工修正不会覆盖 Agent 原始识别值。 ### 5.2 主要接口 基础路径: ```text /api/v1/offsite-fund ``` | 方法 | 路径 | 用途 | |---|---|---| | `GET` | `/mails` | 分页查询场外邮件 | | `GET` | `/mails/{mail_id}` | 查看邮件详情 | | `POST` | `/mails/{mail_id}/deletions` | 软删除邮件 | | `GET` | `/mails/{mail_id}/recognition-fields` | 查看 OCR 识别字段 | | `PUT` | `/mails/{mail_id}/recognition-fields` | 保存 OCR 字段人工修正 | | `GET` | `/documents/{task_id}/nl2sql-fields` | 查看 NL2SQL 返回字段 | | `PUT` | `/documents/{task_id}/nl2sql-fields` | 保存 NL2SQL 字段人工修正 | | `GET` | `/documents/{task_id}/rule-results` | 查看规则判定结果 | | `POST` | `/documents/{task_id}/rule-results/recalculations` | 使用已有结果重新判定 | | `GET` | `/mailbox-status` | 查看收件游标状态 | | `POST` | `/mailbox-status/recoveries` | 恢复被阻塞的收件游标 | | `GET` | `/attachments/{attachment_id}/file` | 预览或下载原始附件 | | `POST` | `/documents/{task_id}/confirmations` | 运营人员确认单据 | | `POST` | `/documents/{task_id}/recognition-retries` | 重试识别异常单据 | | `POST` | `/documents/{task_id}/notifications` | 创建运营通知 | | `POST` | `/notifications/{notification_id}/send` | 发送通知 | | `POST` | `/settlement-statistics/recalculate` | 重算结算统计 | 触发场外单据 NL2SQL 核对的接口为: ```text POST /api/tasks/{task_id}/trigger-agent-nl2sql ``` ### 5.3 权限与安全 - 读取权限:`offsite:read` - 写入权限:`offsite:write` - 确认权限:`offsite:confirm` - NL2SQL 权限:`offsite:nl2sql` - 通知权限:`offsite:notify` - 请求中的 `operator_id` 必须与 JWT 身份一致 - 所有写操作都进行权限校验、操作人校验、审计和状态流转校验 - 通知发送支持幂等,SMTP 默认关闭并使用 dry-run ## 六、功能二:产品推介材料与宣传海报生成 ### 6.1 功能说明 该模块用于新产品的结构化资料整理和宣传材料生成。当前生成链路为: ```text 创建任务 → 填写产品、经理、团队、策略、费用、业绩和风险资料 → 上传经理照片、业绩数据、来源证据或模板 → 合规检查 → 生成 PPTX、宣传海报和可选 PDF → 审核 → 发送给指定投顾 ``` 支持的输入附件: - `manager_photo`:基金经理照片 - `performance_data`:CSV/XLSX 业绩数据 - `source_evidence`:来源证据 - `template_file`:材料模板 支持的输出格式: - `pptx` - `poster` - `pdf`,需要配置 LibreOffice/`soffice` 等转换器 模块会执行风险披露、费用结构、业绩数据、输入完整性和生成文本合规检查。 合规阻断时返回具体 findings 和补齐建议,不继续生成材料。 ### 6.2 主要接口 基础路径: ```text /api/v1/fund-promotion-materials ``` | 方法 | 路径 | 用途 | |---|---|---| | `POST` | `/` | 创建推介材料任务 | | `PUT` | `/{task_no}/inputs` | 保存结构化输入资料 | | `POST` | `/{task_no}/attachments` | 上传照片、业绩文件或证据 | | `POST` | `/{task_no}/generations` | 生成推介材料 | | `GET` | `/{task_no}/compliance-checks` | 查看合规检查结果 | | `GET` | `/{task_no}` | 查询任务和已审核材料 | | `POST` | `/{task_no}/reviews` | 审核、驳回或要求修改 | | `POST` | `/{task_no}/deliveries` | 发送给投顾 | 创建任务和写入操作必须提供请求头: ```text Idempotency-Key: <唯一请求键> ``` ### 6.3 权限与状态 主要权限: - `promotion:write` - `promotion:read` - `promotion:review` - `promotion:deliver` 材料任务状态包括: ```text draft → input_ready → generating → generated → pending_review → approved → sent ``` 异常状态包括: ```text compliance_failed rejected failed ``` 生成的文件默认保存到: ```text data/promotion_materials/ ``` ## 七、功能三:金融 NL2SQL ### 7.1 功能说明 NL2SQL 将自然语言问题转换为经过权限、业务域、表白名单和只读校验的 SQL。 业务 Agent 不直接连接数据库,而是通过公共只读工具调用: ```text 业务 Agent → BaseAgent.call_tool → ToolExecutor → query_financial_data → 只读金融数据表 ``` 工具名称: ```text query_financial_data ``` 权限码: ```text financial:nl2sql:read ``` ### 7.2 支持范围 当前纳入查询范围的主要表: ```text sys_customer_assignment fin_customer_profile fin_risk_assessment fin_product fin_fee_rule fin_market_price fin_nav_history fin_holding fin_transaction fin_sim_order fin_sim_account fin_cash_ledger client_facing_content ``` 支持: - 基金净值、行情和历史收益查询 - 费率和费用查询 - 客户风险测评和画像查询 - 持仓、交易、订单、账户和资金流水查询 - 历史范围查询 - 最多跨三个业务域查询 - 结果行数限制,默认 50,最大 200 - SQL dry-run 不支持或会被拒绝: - 非白名单表 - 非 `SELECT` 查询 - 未通过客户数据范围校验的查询 - 当前快照表的历史时点查询 - 模糊且未确认查询范围、指标口径或时间条件的问题 ### 7.3 调用示例 ```python result = await self.call_tool( "query_financial_data", { "question": "查询基金代码 000001 最近 30 天的净值", "dry_run": False, "limit": 50, }, intent="financial_query", context=context, ) ``` 模糊问题会返回: ```json { "status": "need_confirmation", "message": "请确认查询范围、指标口径和时间条件。" } ``` 工具结果包含查询计划、SQL、参数、权限检查和执行摘要,并进入统一审计和运行持久化链路。 ## 八、测试数据集 测试数据位于: ```text data/ ``` 当前数据集概况: | 类型 | 数量 | 用途 | |---|---:|---| | `.eml` | 13 | 场外邮件及附件识别 | | `.csv` / `.xlsx` | 8 | 推介材料业绩数据 | | `.png` / `.jpg` | 35 | 经理照片、宣传图和测试图片 | | `.pptx` | 10 | 推介材料结构检查 | | `.pdf` | 9 | PDF 文件有效性检查 | 测试数据只用于本地测试和演示,不应直接作为生产业务数据导入。 ## 九、测试与代码检查 ### 9.1 运行完整测试 普通单元和契约测试: ```powershell python -m pytest tests/unit tests/contract -q -p no:cacheprovider ``` 使用独立 MySQL 测试库并执行测试数据隔离: ```powershell python -m tools.run_tests_on_test_db tests -p no:cacheprovider ``` ### 9.2 运行三项功能定向测试 ```powershell python -m pytest ` tests/integration/test_offsite_fund_api.py ` tests/integration/test_offsite_nl2sql_fields.py ` tests/integration/test_offsite_notification_send.py ` tests/integration/test_promotion_material_api.py ` tests/unit/service/test_suitability_service.py ` tests/contract/test_financial_nl2sql_tool_contract.py ` -q -p no:cacheprovider ``` ### 9.3 代码质量检查 ```powershell python -m ruff check app tests tools alembic python -m mypy app git diff --check ``` ### 9.4 测试基线 最近一次项目回归记录: ```text 关键三项功能定向测试:85 passed 全量自动化测试:559 passed, 1 skipped ``` Redis、真实 IMAP/OCR/DeepSeek/SMTP、Neo4j、Milvus 和浏览器 E2E 是否能执行, 取决于本机服务和凭据配置。外部服务关闭或不可用时,测试使用本地数据集、Mock 或 dry-run。 ## 十、配置开关 场外邮件和外部识别: ```text OFFSITE_IMAP_ENABLED=false OFFSITE_MAIL_WORKER_ENABLED=false OFFSITE_OCR_ENABLED=false OFFSITE_DEEPSEEK_ENABLED=false OFFSITE_SMTP_ENABLED=false OFFSITE_SMTP_DRY_RUN=true ``` 产品推介材料: ```text PROMOTION_MATERIAL_STORAGE_DIR=data/promotion_materials PROMOTION_PDF_ENABLED=false PROMOTION_PDF_CONVERTER_PATH= ``` 启用真实服务前,请先完成网络、凭据、权限、数据脱敏和回滚方案确认。 ## 十一、安全与开发约束 - 所有业务请求都应经过统一 JWT、RBAC、客户范围和审计链路。 - 不在业务 Agent 中自行读取密钥、直接连接数据库或绕过 `ToolExecutor`。 - 场外业务不能写入场内交易表。 - 数据库结构只能通过 Alembic 迁移修改。 - 不删除、重命名或复用已有表和字段;历史结构不足时新增字段、新表或兼容读写。 - 所有写接口应设计幂等键、状态机和重复提交保护。 - 真实外部服务默认关闭,测试优先使用本地数据、Mock 和 dry-run。 ## 十二、相关文档 - `docs/MVC/MVC架构.md`:项目架构和目录职责 - `docs/00-新数据库基线设计.md`:数据库业务基线 - `docs/05-接口文档.md`:接口权威说明 - `docs/14-Agent组员统一接入说明书.md`:Agent 接入规范 - `docs/15-金融NL2SQL工具接入说明.md`:NL2SQL 工具规范 - `product_promotion_to_do_list.md`:推介材料模块开发记录 - `测试报告/2026-09-12.md`:三项功能数据集测试报告