# 智能公募基金系统(开发计划 Phase 0 骨架) 基于《开发计划.md》搭建的分层架构。当前为 **Phase 0 基础设施**:四库懒连接底座 + 统一响应/异常/日志/链路 + 24 张表 DDL + docker-compose。业务 Agent 与前端按计划后续 Phase 落地。 ## 目录结构 ``` Memory_demo/ ├── main.py # 应用入口:四库生命周期 + 中间件 + 异常 + 路由 ├── api/ # 路由层(health 已就绪,其余模块随 Phase 加入) │ ├── router.py # 路由汇总 │ └── routers/health.py ├── service/ # 业务逻辑层(rag/profile/trade/risk/advisor/memory…) ├── repositories/ # 数据访问层:BaseRepository(CRUD)+ SysConfigRepo(模板),AsyncSession 注入 ├── tool/ # 工具层(文档解析/Embedding/检索/规则/置信度/记忆) ├── model/ # 数据模型层(Base + ORM:sys_config 起步) ├── config/ # 配置文件+四库单例(现有) │ ├── settings.py # pydantic-settings(env 前缀:MYSQL_/REDIS_/NEO4J_/MILVUS_) │ ├── deps.py # FastAPI 依赖注入工厂 │ └── database/ # mysql / redis / neo4j / milvus 惰性单例 ├── utils/ # 基础设施 │ ├── response.py # 统一响应 {code,message,data,trace_id} + 错误码(§6.1) │ ├── exceptions.py # ApiError 体系 + 全局异常处理器 │ ├── logger.py # info/error 分文件日志 + 手机号/身份证脱敏 │ └── request_id.py # trace_id 中间件 ├── sql/schema.sql # 24 张表建表脚本(注释含中文,供 NL2SQL) ├── docker-compose.yml # 四库一键启动 ├── requirements.txt └── .env / .env.example # 连接配置 ``` ## 快速启动 ```bash # 1. 中间件(Milvus 启动较慢,首次约 1-2 分钟) docker compose up -d # 2. 建表 mysql -uroot -p -h 127.0.0.1 memory_demo < sql/schema.sql # 3. 配置 .env(复制 .env.example 填写密码,与 docker-compose 保持一致) # 4. 启动服务 uvicorn main:app --reload --port 8000 # Swagger: http://localhost:8000/docs # 健康检查: http://localhost:8000/api/health/ready (四库全 ok 返回 200,否则 503 + 明细) ``` ## 约定 - **配置**:`config/settings.py` 无任何硬编码,全部从 `.env` 读取(各子配置各自加载 env_file,进程环境变量优先级高于 `.env`);任一生效键缺失启动即报错(fail-fast),新增键记得同步 `.env` 与 `.env.example`。 - **数据库连接(懒创建)**:应用启动不连接任何库,四库会话首次访问才建(`redis.client()`/`neo4j.client()`/`milvus.client()`/`mysql.get_engine()`);需要时可手动预热 `python -c "import asyncio,config.database as d; asyncio.run(d.init_db())"`。手动预热会逐库重试 `DB_CONN_RETRIES` 次(指数退避),`DB_STRICT_STARTUP=true` 时重试耗尽抛错。`/api/health/ready` 按需探测各库 `{status, ms}`。Redis 开启 `retry_on_timeout`/`socket_keepalive`,Milvus 操作超时走 `MILVUS_TIMEOUT`。 - **统一响应**:`{"code":200,"message":"success","data":...,"trace_id":"..."}`;业务错误码见 `utils/response.py` Code(1001 LLM 失败 / 1002 知识库无结果 / 1004 风控拦截 / 1005 适当性不匹配)。 - **异常路由**:业务抛 `ApiError` 子类,全局处理器转统一响应(400/401/403/404 保留 HTTP 状态码,1001+ 业务码返回 HTTP 200)。 - **日志**:`logs/info.log`、`logs/error.log` 按天滚动,自动带 trace_id,身份证/手机号脱敏。 - **四库职责**(开发计划 §1):MySQL 业务 / Milvus 向量 / Neo4j 图谱 / Redis 缓存·会话·事件·锁。 - **LLM 统一客户端**(`tool/llm.py`):`LLM_MODE=auto | ollama | api`,底层均走 OpenAI 兼容 `/v1` 端点,业务只调 `chat(messages)` / `embed(texts)`。`auto`(默认)按 `.env` 填写情况组成后端链:本地 Ollama 优先,`LLM_API_KEY` 配齐则作为兜底。内置:指数退避重试(1s/2s/4s)、主模型失败自动切 `LLM_FALLBACK_CHAT_MODEL`、本地后端耗尽自动切 API 后端(embed 不跨后端,向量空间不兼容)、全部失败抛 `LLMFailError`(§1001)由调用方兜底话术。自检:`python test_llm.py`。 - **数据访问**:service 不直接写 SQL,统一走 `repositories/`(会话经 `config.deps.get_db` 注入);新表照 `repositories/sys_config.py` 复制一个仓储 + 一个 ORM 模型。 - **JWT 鉴权**:`POST /api/auth/login`(username/password)签发 token(仅存 user_id+exp,HS256);任意路由加 `Depends(get_current_user)`(`api/deps.py`)即自动校验 Bearer token → 按 user_id 回查 `sys_user` → 注入用户对象(401 无效/过期/不存在,403 禁用)。密码哈希用 stdlib PBKDF2(`service/auth.py`),SEED 测试用户可看 `test_auth.py`。生产务必替换 `JWT_SECRET`(≥32 字节)。 ## 下一步(按开发计划) 1. Phase 1:官网 + 注册登录 + 知识库(RAG)+ 客服Agent —— 新增 `api/auth.py`、`api/knowledge.py`、`tool/embedding.py`、`service/rag_service.py` 2. Phase 2:客户Web端 + 风评问卷 + 画像/记忆(含 memory_unit) 3. Phase 3:Neo4j 图谱 + 投顾Agent(调仓/深度分析/对比) 4. Phase 4:风控Agent(规则引擎 + 阻断闭环) 5. Phase 5:运营后台 + 审计/脱敏/定时任务 + 集成联调